@madh-io/alfred-ai 0.13.1 → 0.13.2
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.
- package/bundle/index.js +61 -61
- package/package.json +1 -1
package/bundle/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var hc=Object.defineProperty;var u=(l,e)=>hc(l,"name",{value:e,configurable:!0}),fc=(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 _=(l,e)=>()=>(l&&(e=l(l=0)),e);var pe=(l,e)=>{for(var t in e)hc(l,t,{get:e[t],enumerable:!0})};import{z as T}from"zod";var yc,Tc,wc,_c,kc,Ec,bc,Sc,vt,_m,km,Em,gc,bm,Sm,vm,$m,Im,Am,Rm,xm,Cm,Nm,Lm,Dm,Mm,Om,Um,Pm,Fm,jm,Hm,Bm,Wm,zm,qm,Gm,Xm,Vm,Km,Ym,Jm,ni,oi=_(()=>{"use strict";yc=T.object({token:T.string().optional(),enabled:T.boolean()}),Tc=T.object({token:T.string().optional(),enabled:T.boolean()}),wc=T.object({enabled:T.boolean(),dataPath:T.string()}),_c=T.object({homeserverUrl:T.string(),accessToken:T.string().optional(),userId:T.string().optional(),enabled:T.boolean()}),kc=T.object({apiUrl:T.string(),phoneNumber:T.string().optional(),enabled:T.boolean()}),Ec=T.object({path:T.string()}),bc=T.object({level:T.enum(["trace","debug","info","warn","error","fatal"]),pretty:T.boolean(),auditLogPath:T.string().optional()}),Sc=T.object({rulesPath:T.string(),defaultEffect:T.enum(["allow","deny"]),ownerUserId:T.string().optional()}),vt=T.object({provider:T.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:T.string().optional(),baseUrl:T.string().optional(),model:T.string(),temperature:T.number().optional(),maxTokens:T.number().optional()}),_m=T.object({default:vt,strong:vt.optional(),fast:vt.optional(),embeddings:vt.optional(),local:vt.optional()}).passthrough(),km=T.union([vt,_m]),Em=T.object({provider:T.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:T.string().optional(),baseUrl:T.string().optional()}),gc=T.object({name:T.string().optional(),provider:T.enum(["imap-smtp","microsoft"]).optional(),imap:T.object({host:T.string(),port:T.number(),secure:T.boolean()}).optional(),smtp:T.object({host:T.string(),port:T.number(),secure:T.boolean()}).optional(),auth:T.object({user:T.string(),pass:T.string()}).optional(),microsoft:T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}).optional()}),bm=T.union([T.object({accounts:T.array(gc)}),gc]),Sm=T.object({provider:T.enum(["openai","groq","google"]),apiKey:T.string(),baseUrl:T.string().optional(),ttsEnabled:T.boolean().optional(),ttsModel:T.string().optional(),ttsVoice:T.string().optional()}),vm=T.object({serverUrl:T.string(),username:T.string(),password:T.string()}),$m=T.object({clientId:T.string(),clientSecret:T.string(),refreshToken:T.string()}),Im=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),Am=T.object({provider:T.enum(["caldav","google","microsoft"]),caldav:vm.optional(),google:$m.optional(),microsoft:Im.optional(),vorlauf:T.object({enabled:T.boolean(),minutesBefore:T.coerce.number().min(1).max(120).default(15),enrichWithRoute:T.boolean().optional(),enrichWithMemories:T.boolean().optional()}).optional()}),Rm=T.object({name:T.string(),command:T.string().optional(),args:T.array(T.string()).optional(),env:T.record(T.string()).optional(),url:T.string().optional()}),xm=T.object({servers:T.array(Rm)}),Cm=T.object({enabled:T.boolean(),allowedLanguages:T.array(T.enum(["javascript","python"])).optional(),maxTimeoutMs:T.number().optional(),allowNetwork:T.boolean().optional()}),Nm=T.object({enabled:T.boolean().optional(),minMessageLength:T.number().optional(),minConfidence:T.number().min(0).max(1).optional(),maxExtractionsPerMinute:T.number().optional()}),Lm=T.object({enabled:T.boolean(),port:T.coerce.number().int().min(1).max(65535),host:T.string(),token:T.string().optional(),corsOrigin:T.string().optional()}),Dm=T.object({name:T.string(),command:T.string(),argsTemplate:T.array(T.string()),promptVia:T.enum(["arg","stdin"]).default("arg"),env:T.record(T.string()).optional(),cwd:T.string().optional(),timeoutMs:T.number().max(9e5).optional()}),Mm=T.object({token:T.string(),baseUrl:T.string().optional()}),Om=T.object({token:T.string(),baseUrl:T.string().optional()}),Um=T.object({provider:T.enum(["github","gitlab"]),baseBranch:T.string().optional(),github:Mm.optional(),gitlab:Om.optional()}),Pm=T.object({enabled:T.boolean(),agents:T.array(Dm),forge:Um.optional()}),Fm=T.object({baseUrl:T.string(),tokenId:T.string(),tokenSecret:T.string(),verifyTls:T.boolean().optional(),defaultNode:T.string().optional()}),jm=T.object({baseUrl:T.string(),apiKey:T.string().optional(),username:T.string().optional(),password:T.string().optional(),site:T.string().optional(),verifyTls:T.boolean().optional()}),Hm=T.object({baseUrl:T.string(),accessToken:T.string(),verifyTls:T.boolean().optional()}),Bm=T.object({serverUrl:T.string(),username:T.string(),password:T.string(),addressBookPath:T.string().optional()}),Wm=T.object({clientId:T.string(),clientSecret:T.string(),refreshToken:T.string()}),zm=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),qm=T.object({provider:T.enum(["carddav","google","microsoft"]),carddav:Bm.optional(),google:Wm.optional(),microsoft:zm.optional()}),Gm=T.object({socketPath:T.string().optional(),host:T.string().optional(),verifyTls:T.boolean().optional()}),Xm=T.object({clientId:T.string()}),Vm=T.object({apiKey:T.string()}),Km=T.object({gridName:T.string().optional(),gridUsageCt:T.coerce.number().optional(),gridLossCt:T.coerce.number().optional(),gridCapacityFee:T.coerce.number().optional(),gridMeterFee:T.coerce.number().optional()}),Ym=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),Jm=T.object({maxHistoryMessages:T.number().min(10).max(500).optional()}).optional(),ni=T.object({name:T.string(),telegram:yc,discord:Tc.optional(),whatsapp:wc.optional(),matrix:_c.optional(),signal:kc.optional(),llm:km,storage:Ec,logger:bc,security:Sc,search:Em.optional(),email:bm.optional(),speech:Sm.optional(),calendar:Am.optional(),mcp:xm.optional(),codeSandbox:Cm.optional(),activeLearning:Nm.optional(),api:Lm.optional(),codeAgents:Pm.optional(),proxmox:Fm.optional(),unifi:jm.optional(),homeassistant:Hm.optional(),contacts:qm.optional(),docker:Gm.optional(),bmw:Xm.optional(),routing:Vm.optional(),todo:Ym.optional(),energy:Km.optional(),conversation:Jm})});var ii,ai=_(()=>{"use strict";ii={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 vc from"node:fs";import $c from"node:path";import{config as Ic}from"dotenv";import Zm from"js-yaml";function Ac(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]=Ac(n,r):t[s]=r}return t}function ep(l){let e=l.toLowerCase();return e==="true"?!0:e==="false"?!1:l}function tp(l){let e={...l};for(let[t,s]of Object.entries(Qm)){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]]=ep(r)}return e}function ci(){Ic({override:!0})}function sp(l){let e=$c.resolve(l),t=["/etc","/bin","/proc","/sys","/dev","/boot"];for(let s of t)if(e.startsWith(s+"/")||e===s)throw new Error(`Storage path "${e}" is in forbidden directory ${s}`)}var Qm,ue,Rc=_(()=>{"use strict";oi();ai();u(Ac,"deepMerge");Qm={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_PROXMOX_VERIFY_TLS:["proxmox","verifyTls"],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_UNIFI_VERIFY_TLS:["unifi","verifyTls"],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"],ALFRED_REASONING_ENABLED:["reasoning","enabled"],ALFRED_REASONING_SCHEDULE:["reasoning","schedule"],ALFRED_REASONING_TIER:["reasoning","tier"]};u(ep,"coerceEnvValue");u(tp,"applyEnvOverrides");u(ci,"reloadDotenv");ue=class{static{u(this,"ConfigLoader")}loadConfig(e){Ic();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=$c.resolve(t);if(vc.existsSync(r)){let g=vc.readFileSync(r,"utf-8"),h=Zm.load(g);h&&typeof h=="object"&&(s=h)}let n=Ac(ii,s),o=tp(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(h=>a[h]&&typeof a[h]=="object")){let h={};for(let[k,S]of Object.entries(a))!i.includes(k)&&k!=="default"&&(h[k]=S);let y={default:h};for(let k of i)a[k]&&(y[k]=a[k]);o.llm=y}let c=ni.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let m=c.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let h of["default","strong","fast","embeddings","local"]){let y=m[h];y&&!y.apiKey&&(y.apiKey=g)}}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 g=p.microsoft;if(g){let y=p.accounts.find(k=>k.provider==="microsoft");if(y){let k=y.microsoft??{};y.microsoft={...k,...g}}delete p.microsoft}}let f=c.storage;return f?.path&&typeof f.path=="string"&&sp(f.path),c}};u(sp,"validateStoragePath")});var et=_(()=>{"use strict";oi();ai();Rc()});import li from"pino";function Vs(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=li.transport({target:"pino-pretty",options:{colorize:!0}});return li({name:l,level:t,redact:xc},r)}return li({name:l,level:t,redact:xc})}var xc,Cc=_(()=>{"use strict";xc={paths:["**.apiKey","**.token","**.password","**.secret","**.accessToken","**.refreshToken","**.clientSecret","**.Authorization","**.authorization"],censor:"[REDACTED]"};u(Vs,"createLogger")});import Ag from"pino";var Nc=_(()=>{"use strict"});var di=_(()=>{"use strict";Cc();Nc()});var Gt,xn=_(()=>{"use strict";Gt=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
|
|
2
|
+
var hc=Object.defineProperty;var u=(l,e)=>hc(l,"name",{value:e,configurable:!0}),fc=(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 _=(l,e)=>()=>(l&&(e=l(l=0)),e);var he=(l,e)=>{for(var t in e)hc(l,t,{get:e[t],enumerable:!0})};import{z as T}from"zod";var yc,Tc,wc,_c,kc,Ec,bc,Sc,vt,_m,km,Em,gc,bm,Sm,vm,$m,Im,Am,Rm,xm,Cm,Nm,Lm,Dm,Mm,Om,Um,Pm,Fm,jm,Hm,Bm,Wm,zm,qm,Gm,Xm,Vm,Km,Ym,Jm,ni,oi=_(()=>{"use strict";yc=T.object({token:T.string().optional(),enabled:T.boolean()}),Tc=T.object({token:T.string().optional(),enabled:T.boolean()}),wc=T.object({enabled:T.boolean(),dataPath:T.string()}),_c=T.object({homeserverUrl:T.string(),accessToken:T.string().optional(),userId:T.string().optional(),enabled:T.boolean()}),kc=T.object({apiUrl:T.string(),phoneNumber:T.string().optional(),enabled:T.boolean()}),Ec=T.object({path:T.string()}),bc=T.object({level:T.enum(["trace","debug","info","warn","error","fatal"]),pretty:T.boolean(),auditLogPath:T.string().optional()}),Sc=T.object({rulesPath:T.string(),defaultEffect:T.enum(["allow","deny"]),ownerUserId:T.string().optional()}),vt=T.object({provider:T.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:T.string().optional(),baseUrl:T.string().optional(),model:T.string(),temperature:T.number().optional(),maxTokens:T.number().optional()}),_m=T.object({default:vt,strong:vt.optional(),fast:vt.optional(),embeddings:vt.optional(),local:vt.optional()}).passthrough(),km=T.union([vt,_m]),Em=T.object({provider:T.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:T.string().optional(),baseUrl:T.string().optional()}),gc=T.object({name:T.string().optional(),provider:T.enum(["imap-smtp","microsoft"]).optional(),imap:T.object({host:T.string(),port:T.number(),secure:T.boolean()}).optional(),smtp:T.object({host:T.string(),port:T.number(),secure:T.boolean()}).optional(),auth:T.object({user:T.string(),pass:T.string()}).optional(),microsoft:T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}).optional()}),bm=T.union([T.object({accounts:T.array(gc)}),gc]),Sm=T.object({provider:T.enum(["openai","groq","google"]),apiKey:T.string(),baseUrl:T.string().optional(),ttsEnabled:T.boolean().optional(),ttsModel:T.string().optional(),ttsVoice:T.string().optional()}),vm=T.object({serverUrl:T.string(),username:T.string(),password:T.string()}),$m=T.object({clientId:T.string(),clientSecret:T.string(),refreshToken:T.string()}),Im=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),Am=T.object({provider:T.enum(["caldav","google","microsoft"]),caldav:vm.optional(),google:$m.optional(),microsoft:Im.optional(),vorlauf:T.object({enabled:T.boolean(),minutesBefore:T.coerce.number().min(1).max(120).default(15),enrichWithRoute:T.boolean().optional(),enrichWithMemories:T.boolean().optional()}).optional()}),Rm=T.object({name:T.string(),command:T.string().optional(),args:T.array(T.string()).optional(),env:T.record(T.string()).optional(),url:T.string().optional()}),xm=T.object({servers:T.array(Rm)}),Cm=T.object({enabled:T.boolean(),allowedLanguages:T.array(T.enum(["javascript","python"])).optional(),maxTimeoutMs:T.number().optional(),allowNetwork:T.boolean().optional()}),Nm=T.object({enabled:T.boolean().optional(),minMessageLength:T.number().optional(),minConfidence:T.number().min(0).max(1).optional(),maxExtractionsPerMinute:T.number().optional()}),Lm=T.object({enabled:T.boolean(),port:T.coerce.number().int().min(1).max(65535),host:T.string(),token:T.string().optional(),corsOrigin:T.string().optional()}),Dm=T.object({name:T.string(),command:T.string(),argsTemplate:T.array(T.string()),promptVia:T.enum(["arg","stdin"]).default("arg"),env:T.record(T.string()).optional(),cwd:T.string().optional(),timeoutMs:T.number().max(9e5).optional()}),Mm=T.object({token:T.string(),baseUrl:T.string().optional()}),Om=T.object({token:T.string(),baseUrl:T.string().optional()}),Um=T.object({provider:T.enum(["github","gitlab"]),baseBranch:T.string().optional(),github:Mm.optional(),gitlab:Om.optional()}),Pm=T.object({enabled:T.boolean(),agents:T.array(Dm),forge:Um.optional()}),Fm=T.object({baseUrl:T.string(),tokenId:T.string(),tokenSecret:T.string(),verifyTls:T.boolean().optional(),defaultNode:T.string().optional()}),jm=T.object({baseUrl:T.string(),apiKey:T.string().optional(),username:T.string().optional(),password:T.string().optional(),site:T.string().optional(),verifyTls:T.boolean().optional()}),Hm=T.object({baseUrl:T.string(),accessToken:T.string(),verifyTls:T.boolean().optional()}),Bm=T.object({serverUrl:T.string(),username:T.string(),password:T.string(),addressBookPath:T.string().optional()}),Wm=T.object({clientId:T.string(),clientSecret:T.string(),refreshToken:T.string()}),zm=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),qm=T.object({provider:T.enum(["carddav","google","microsoft"]),carddav:Bm.optional(),google:Wm.optional(),microsoft:zm.optional()}),Gm=T.object({socketPath:T.string().optional(),host:T.string().optional(),verifyTls:T.boolean().optional()}),Xm=T.object({clientId:T.string()}),Vm=T.object({apiKey:T.string()}),Km=T.object({gridName:T.string().optional(),gridUsageCt:T.coerce.number().optional(),gridLossCt:T.coerce.number().optional(),gridCapacityFee:T.coerce.number().optional(),gridMeterFee:T.coerce.number().optional()}),Ym=T.object({clientId:T.string(),clientSecret:T.string(),tenantId:T.string(),refreshToken:T.string()}),Jm=T.object({maxHistoryMessages:T.number().min(10).max(500).optional()}).optional(),ni=T.object({name:T.string(),telegram:yc,discord:Tc.optional(),whatsapp:wc.optional(),matrix:_c.optional(),signal:kc.optional(),llm:km,storage:Ec,logger:bc,security:Sc,search:Em.optional(),email:bm.optional(),speech:Sm.optional(),calendar:Am.optional(),mcp:xm.optional(),codeSandbox:Cm.optional(),activeLearning:Nm.optional(),api:Lm.optional(),codeAgents:Pm.optional(),proxmox:Fm.optional(),unifi:jm.optional(),homeassistant:Hm.optional(),contacts:qm.optional(),docker:Gm.optional(),bmw:Xm.optional(),routing:Vm.optional(),todo:Ym.optional(),energy:Km.optional(),conversation:Jm})});var ii,ai=_(()=>{"use strict";ii={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 vc from"node:fs";import $c from"node:path";import{config as Ic}from"dotenv";import Zm from"js-yaml";function Ac(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]=Ac(n,r):t[s]=r}return t}function ep(l){let e=l.toLowerCase();return e==="true"?!0:e==="false"?!1:l}function tp(l){let e={...l};for(let[t,s]of Object.entries(Qm)){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]]=ep(r)}return e}function ci(){Ic({override:!0})}function sp(l){let e=$c.resolve(l),t=["/etc","/bin","/proc","/sys","/dev","/boot"];for(let s of t)if(e.startsWith(s+"/")||e===s)throw new Error(`Storage path "${e}" is in forbidden directory ${s}`)}var Qm,ue,Rc=_(()=>{"use strict";oi();ai();u(Ac,"deepMerge");Qm={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_PROXMOX_VERIFY_TLS:["proxmox","verifyTls"],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_UNIFI_VERIFY_TLS:["unifi","verifyTls"],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"],ALFRED_REASONING_ENABLED:["reasoning","enabled"],ALFRED_REASONING_SCHEDULE:["reasoning","schedule"],ALFRED_REASONING_TIER:["reasoning","tier"]};u(ep,"coerceEnvValue");u(tp,"applyEnvOverrides");u(ci,"reloadDotenv");ue=class{static{u(this,"ConfigLoader")}loadConfig(e){Ic();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=$c.resolve(t);if(vc.existsSync(r)){let g=vc.readFileSync(r,"utf-8"),h=Zm.load(g);h&&typeof h=="object"&&(s=h)}let n=Ac(ii,s),o=tp(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(h=>a[h]&&typeof a[h]=="object")){let h={};for(let[k,S]of Object.entries(a))!i.includes(k)&&k!=="default"&&(h[k]=S);let y={default:h};for(let k of i)a[k]&&(y[k]=a[k]);o.llm=y}let c=ni.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let m=c.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let h of["default","strong","fast","embeddings","local"]){let y=m[h];y&&!y.apiKey&&(y.apiKey=g)}}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 g=p.microsoft;if(g){let y=p.accounts.find(k=>k.provider==="microsoft");if(y){let k=y.microsoft??{};y.microsoft={...k,...g}}delete p.microsoft}}let f=c.storage;return f?.path&&typeof f.path=="string"&&sp(f.path),c}};u(sp,"validateStoragePath")});var et=_(()=>{"use strict";oi();ai();Rc()});import li from"pino";function Vs(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=li.transport({target:"pino-pretty",options:{colorize:!0}});return li({name:l,level:t,redact:xc},r)}return li({name:l,level:t,redact:xc})}var xc,Cc=_(()=>{"use strict";xc={paths:["**.apiKey","**.token","**.password","**.secret","**.accessToken","**.refreshToken","**.clientSecret","**.Authorization","**.authorization"],censor:"[REDACTED]"};u(Vs,"createLogger")});import Ag from"pino";var Nc=_(()=>{"use strict"});var di=_(()=>{"use strict";Cc();Nc()});var Gt,xn=_(()=>{"use strict";Gt=class{static{u(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,
|
|
@@ -584,9 +584,9 @@ var hc=Object.defineProperty;var u=(l,e)=>hc(l,"name",{value:e,configurable:!0})
|
|
|
584
584
|
`).run(t,e.name,e.userId,e.chatId,e.platform,JSON.stringify(e.steps),e.triggerType,e.triggerConfig?JSON.stringify(e.triggerConfig):null,e.enabled?1:0,s),{...e,id:t,createdAt:s}}getById(e){let t=this.db.prepare("SELECT * FROM workflow_chains WHERE id = ?").get(e);return t?this.mapChain(t):void 0}findByUser(e){return this.db.prepare("SELECT * FROM workflow_chains WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapChain(s))}findByChatId(e,t){return this.db.prepare("SELECT * FROM workflow_chains WHERE chat_id = ? AND platform = ? ORDER BY created_at DESC").all(e,t).map(r=>this.mapChain(r))}delete(e){return this.db.prepare("DELETE FROM workflow_chains WHERE id = ?").run(e).changes>0}toggle(e,t){this.db.prepare("UPDATE workflow_chains SET enabled = ? WHERE id = ?").run(t?1:0,e)}createExecution(e,t){let s=sl(),r=new Date().toISOString();return this.db.prepare(`
|
|
585
585
|
INSERT INTO workflow_executions (id, chain_id, status, steps_completed, total_steps, started_at)
|
|
586
586
|
VALUES (?, ?, 'running', 0, ?, ?)
|
|
587
|
-
`).run(s,e,t,r),{id:s,chainId:e,status:"running",stepsCompleted:0,totalSteps:t,startedAt:r}}updateExecution(e,t){let s=[],r=[];t.status!==void 0&&(s.push("status = ?"),r.push(t.status)),t.stepsCompleted!==void 0&&(s.push("steps_completed = ?"),r.push(t.stepsCompleted)),t.stepResults!==void 0&&(s.push("step_results = ?"),r.push(t.stepResults)),t.error!==void 0&&(s.push("error = ?"),r.push(t.error)),t.completedAt!==void 0&&(s.push("completed_at = ?"),r.push(t.completedAt)),s.length!==0&&(r.push(e),this.db.prepare(`UPDATE workflow_executions SET ${s.join(", ")} WHERE id = ?`).run(...r))}getExecution(e){let t=this.db.prepare("SELECT * FROM workflow_executions WHERE id = ?").get(e);return t?this.mapExecution(t):void 0}getRecentExecutions(e,t=10){return this.db.prepare("SELECT * FROM workflow_executions WHERE chain_id = ? ORDER BY started_at DESC LIMIT ?").all(e,t).map(r=>this.mapExecution(r))}mapChain(e){return{id:e.id,name:e.name,userId:e.user_id,chatId:e.chat_id,platform:e.platform,steps:JSON.parse(e.steps),triggerType:e.trigger_type,triggerConfig:e.trigger_config?JSON.parse(e.trigger_config):void 0,enabled:e.enabled===1,createdAt:e.created_at}}mapExecution(e){return{id:e.id,chainId:e.chain_id,status:e.status,stepsCompleted:e.steps_completed,totalSteps:e.total_steps,stepResults:e.step_results,error:e.error,startedAt:e.started_at,completedAt:e.completed_at}}}});var pi=_(()=>{"use strict";Dc();Oc();Uc();Pc();Fc();xn();mi();jc();Hc();Bc();Wc();zc();qc();Xc();Vc();Kc();Yc();Jc();Zc();Qc();el();tl();rl()});function tt(l){if(hi[l])return hi[l];let e=Object.entries(hi).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var hi,fp,xe,xt=_(()=>{"use strict";hi={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-opus-4-5-20251101":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-sonnet-4-5-20250929":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-3-5-sonnet-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-sonnet-20240620":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-haiku-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-4-5-20251001":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-opus-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-sonnet-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-haiku-20240307":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-":{maxInputTokens:2e5,maxOutputTokens:16e3},"gpt-4.1":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-mini":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-nano":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o3:{maxInputTokens:2e5,maxOutputTokens:1e5},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"o4-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"gpt-5.4":{maxInputTokens:105e4,maxOutputTokens:128e3},"gpt-5":{maxInputTokens:4e5,maxOutputTokens:128e3},"gemini-3.1-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3.1-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"mistral-large":{maxInputTokens:262144,maxOutputTokens:262144},"mistral-medium":{maxInputTokens:128e3,maxOutputTokens:128e3},"mistral-small":{maxInputTokens:128e3,maxOutputTokens:128e3},codestral:{maxInputTokens:262144,maxOutputTokens:262144},"magistral-medium":{maxInputTokens:128e3,maxOutputTokens:131072},"magistral-small":{maxInputTokens:128e3,maxOutputTokens:131072},ministral:{maxInputTokens:128e3,maxOutputTokens:128e3},llama4:{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},gemma3:{maxInputTokens:128e3,maxOutputTokens:8192},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},qwen3:{maxInputTokens:128e3,maxOutputTokens:8192},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},phi4:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-v3":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-chat":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"command-r-plus":{maxInputTokens:128e3,maxOutputTokens:4096}},fp={maxInputTokens:128e3,maxOutputTokens:8192};u(tt,"lookupContextWindow");xe=class{static{u(this,"LLMProvider")}config;contextWindow=fp;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import gp from"@anthropic-ai/sdk";var pr,fi=_(()=>{"use strict";xt();pr=class extends xe{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new gp({apiKey:this.config.apiKey,maxRetries:5});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,messages:t,tools:s},n=await this.client.messages.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=this.client.messages.stream({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,messages:t,tools:s});for await(let n of r)if(n.type==="content_block_delta")n.delta.type==="text_delta"?yield{type:"text_delta",text:n.delta.text}:n.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:n.delta.partial_json}});else if(n.type==="content_block_start")n.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:n.content_block.id,name:n.content_block.name}});else if(n.type==="message_stop"){let o=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(o)}}}isAvailable(){return!!this.config.apiKey}mapMessages(e){return e.map(t=>{if(typeof t.content=="string")return{role:t.role,content:t.content};let s=t.content.map(r=>{switch(r.type){case"text":return{type:"text",text:r.text};case"image":return{type:"image",source:{type:"base64",media_type:r.source.media_type,data:r.source.data}};case"tool_use":return{type:"tool_use",id:r.id,name:r.name,input:r.input};case"tool_result":return{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content,is_error:r.is_error};default:return{type:"text",text:"[Unsupported block type]"}}}).filter(r=>r!==void 0);return{role:t.role,content:s}})}mapTools(e){let t=e.map(s=>({name:s.name,description:s.description,input_schema:s.inputSchema}));return t.length>0&&(t[t.length-1].cache_control={type:"ephemeral"}),t}mapResponse(e){let t="",s=[];for(let r of e.content)r.type==="text"?t+=r.text:r.type==="tool_use"&&s.push({id:r.id,name:r.name,input:r.input});return{content:t,model:e.model??this.config.model,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens,cacheCreationTokens:e.usage.cache_creation_input_tokens??0,cacheReadTokens:e.usage.cache_read_input_tokens??0},stopReason:e.stop_reason}}}});import yp from"openai";var Fe,Xt=_(()=>{"use strict";xt();Fe=class extends xe{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new yp({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",c=[],d=null,m=0,p=0;for await(let f of r){let g=f.choices[0];if(!g)continue;let h=g.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let y of h.tool_calls)if(y.id){if(n){let k;try{k=JSON.parse(i||"{}")}catch{k={}}c.push({id:n,name:o,input:k})}n=y.id,o=y.function?.name,i=y.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else y.function?.arguments&&(i+=y.function.arguments,yield{type:"tool_use_delta",toolCall:{input:y.function.arguments}});g.finish_reason&&(d=g.finish_reason),f.usage&&(m=f.usage.prompt_tokens,p=f.usage.completion_tokens)}if(n){let f;try{f=JSON.parse(i||"{}")}catch{f={}}c.push({id:n,name:o,input:f})}yield{type:"message_complete",response:{content:a,model:this.config.model,toolCalls:c.length>0?c:void 0,usage:{inputTokens:m,outputTokens:p},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}isReasoningModel(){return/^(o[1-9]|gpt-5($|[.-][01]))/.test(this.config.model)}tokenLimitParam(e){let t=e??this.config.maxTokens??4096;return/^(gpt-5|o[1-9])/.test(this.config.model)?{max_completion_tokens:t}:{max_tokens:t}}safeTemperature(e){if(!this.isReasoningModel())return e??this.config.temperature}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(c=>c.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,model:e.model??this.config.model,toolCalls:n&&n.length>0?n:void 0,usage:{inputTokens:e.usage?.prompt_tokens??0,outputTokens:e.usage?.completion_tokens??0},stopReason:this.mapStopReason(t?.finish_reason??null)}}mapStopReason(e){switch(e){case"stop":return"end_turn";case"tool_calls":return"tool_use";case"length":return"max_tokens";default:return"end_turn"}}}});var hr,gi=_(()=>{"use strict";Xt();hr=class extends Fe{static{u(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var fr,yi=_(()=>{"use strict";xt();fr=class extends xe{static{u(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=tt(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let f=await n.text();throw new Error(`Ollama API error (${n.status}): ${f}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",d=0,m=0,p=[];try{for(;;){let{done:f,value:g}=await o.read();if(f)break;a+=i.decode(g,{stream:!0});let h=a.split(`
|
|
587
|
+
`).run(s,e,t,r),{id:s,chainId:e,status:"running",stepsCompleted:0,totalSteps:t,startedAt:r}}updateExecution(e,t){let s=[],r=[];t.status!==void 0&&(s.push("status = ?"),r.push(t.status)),t.stepsCompleted!==void 0&&(s.push("steps_completed = ?"),r.push(t.stepsCompleted)),t.stepResults!==void 0&&(s.push("step_results = ?"),r.push(t.stepResults)),t.error!==void 0&&(s.push("error = ?"),r.push(t.error)),t.completedAt!==void 0&&(s.push("completed_at = ?"),r.push(t.completedAt)),s.length!==0&&(r.push(e),this.db.prepare(`UPDATE workflow_executions SET ${s.join(", ")} WHERE id = ?`).run(...r))}getExecution(e){let t=this.db.prepare("SELECT * FROM workflow_executions WHERE id = ?").get(e);return t?this.mapExecution(t):void 0}getRecentExecutions(e,t=10){return this.db.prepare("SELECT * FROM workflow_executions WHERE chain_id = ? ORDER BY started_at DESC LIMIT ?").all(e,t).map(r=>this.mapExecution(r))}mapChain(e){return{id:e.id,name:e.name,userId:e.user_id,chatId:e.chat_id,platform:e.platform,steps:JSON.parse(e.steps),triggerType:e.trigger_type,triggerConfig:e.trigger_config?JSON.parse(e.trigger_config):void 0,enabled:e.enabled===1,createdAt:e.created_at}}mapExecution(e){return{id:e.id,chainId:e.chain_id,status:e.status,stepsCompleted:e.steps_completed,totalSteps:e.total_steps,stepResults:e.step_results,error:e.error,startedAt:e.started_at,completedAt:e.completed_at}}}});var pi=_(()=>{"use strict";Dc();Oc();Uc();Pc();Fc();xn();mi();jc();Hc();Bc();Wc();zc();qc();Xc();Vc();Kc();Yc();Jc();Zc();Qc();el();tl();rl()});function tt(l){if(hi[l])return hi[l];let e=Object.entries(hi).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var hi,fp,Ce,xt=_(()=>{"use strict";hi={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-opus-4-5-20251101":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-sonnet-4-5-20250929":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-3-5-sonnet-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-sonnet-20240620":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-haiku-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-4-5-20251001":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-opus-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-sonnet-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-haiku-20240307":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-":{maxInputTokens:2e5,maxOutputTokens:16e3},"gpt-4.1":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-mini":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-nano":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o3:{maxInputTokens:2e5,maxOutputTokens:1e5},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"o4-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"gpt-5.4":{maxInputTokens:105e4,maxOutputTokens:128e3},"gpt-5":{maxInputTokens:4e5,maxOutputTokens:128e3},"gemini-3.1-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3.1-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"mistral-large":{maxInputTokens:262144,maxOutputTokens:262144},"mistral-medium":{maxInputTokens:128e3,maxOutputTokens:128e3},"mistral-small":{maxInputTokens:128e3,maxOutputTokens:128e3},codestral:{maxInputTokens:262144,maxOutputTokens:262144},"magistral-medium":{maxInputTokens:128e3,maxOutputTokens:131072},"magistral-small":{maxInputTokens:128e3,maxOutputTokens:131072},ministral:{maxInputTokens:128e3,maxOutputTokens:128e3},llama4:{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},gemma3:{maxInputTokens:128e3,maxOutputTokens:8192},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},qwen3:{maxInputTokens:128e3,maxOutputTokens:8192},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},phi4:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-v3":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-chat":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"command-r-plus":{maxInputTokens:128e3,maxOutputTokens:4096}},fp={maxInputTokens:128e3,maxOutputTokens:8192};u(tt,"lookupContextWindow");Ce=class{static{u(this,"LLMProvider")}config;contextWindow=fp;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import gp from"@anthropic-ai/sdk";var pr,fi=_(()=>{"use strict";xt();pr=class extends Ce{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new gp({apiKey:this.config.apiKey,maxRetries:5});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,messages:t,tools:s},n=await this.client.messages.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=this.client.messages.stream({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,messages:t,tools:s});for await(let n of r)if(n.type==="content_block_delta")n.delta.type==="text_delta"?yield{type:"text_delta",text:n.delta.text}:n.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:n.delta.partial_json}});else if(n.type==="content_block_start")n.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:n.content_block.id,name:n.content_block.name}});else if(n.type==="message_stop"){let o=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(o)}}}isAvailable(){return!!this.config.apiKey}mapMessages(e){return e.map(t=>{if(typeof t.content=="string")return{role:t.role,content:t.content};let s=t.content.map(r=>{switch(r.type){case"text":return{type:"text",text:r.text};case"image":return{type:"image",source:{type:"base64",media_type:r.source.media_type,data:r.source.data}};case"tool_use":return{type:"tool_use",id:r.id,name:r.name,input:r.input};case"tool_result":return{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content,is_error:r.is_error};default:return{type:"text",text:"[Unsupported block type]"}}}).filter(r=>r!==void 0);return{role:t.role,content:s}})}mapTools(e){let t=e.map(s=>({name:s.name,description:s.description,input_schema:s.inputSchema}));return t.length>0&&(t[t.length-1].cache_control={type:"ephemeral"}),t}mapResponse(e){let t="",s=[];for(let r of e.content)r.type==="text"?t+=r.text:r.type==="tool_use"&&s.push({id:r.id,name:r.name,input:r.input});return{content:t,model:e.model??this.config.model,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens,cacheCreationTokens:e.usage.cache_creation_input_tokens??0,cacheReadTokens:e.usage.cache_read_input_tokens??0},stopReason:e.stop_reason}}}});import yp from"openai";var Fe,Xt=_(()=>{"use strict";xt();Fe=class extends Ce{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new yp({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",c=[],d=null,m=0,p=0;for await(let f of r){let g=f.choices[0];if(!g)continue;let h=g.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let y of h.tool_calls)if(y.id){if(n){let k;try{k=JSON.parse(i||"{}")}catch{k={}}c.push({id:n,name:o,input:k})}n=y.id,o=y.function?.name,i=y.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else y.function?.arguments&&(i+=y.function.arguments,yield{type:"tool_use_delta",toolCall:{input:y.function.arguments}});g.finish_reason&&(d=g.finish_reason),f.usage&&(m=f.usage.prompt_tokens,p=f.usage.completion_tokens)}if(n){let f;try{f=JSON.parse(i||"{}")}catch{f={}}c.push({id:n,name:o,input:f})}yield{type:"message_complete",response:{content:a,model:this.config.model,toolCalls:c.length>0?c:void 0,usage:{inputTokens:m,outputTokens:p},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}isReasoningModel(){return/^(o[1-9]|gpt-5($|[.-][01]))/.test(this.config.model)}tokenLimitParam(e){let t=e??this.config.maxTokens??4096;return/^(gpt-5|o[1-9])/.test(this.config.model)?{max_completion_tokens:t}:{max_tokens:t}}safeTemperature(e){if(!this.isReasoningModel())return e??this.config.temperature}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(c=>c.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,model:e.model??this.config.model,toolCalls:n&&n.length>0?n:void 0,usage:{inputTokens:e.usage?.prompt_tokens??0,outputTokens:e.usage?.completion_tokens??0},stopReason:this.mapStopReason(t?.finish_reason??null)}}mapStopReason(e){switch(e){case"stop":return"end_turn";case"tool_calls":return"tool_use";case"length":return"max_tokens";default:return"end_turn"}}}});var hr,gi=_(()=>{"use strict";Xt();hr=class extends Fe{static{u(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var fr,yi=_(()=>{"use strict";xt();fr=class extends Ce{static{u(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=tt(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let f=await n.text();throw new Error(`Ollama API error (${n.status}): ${f}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",d=0,m=0,p=[];try{for(;;){let{done:f,value:g}=await o.read();if(f)break;a+=i.decode(g,{stream:!0});let h=a.split(`
|
|
588
588
|
`);a=h.pop()??"";for(let y of h){let k=y.trim();if(!k)continue;let S;try{S=JSON.parse(k)}catch{continue}if(S.message?.content&&(c+=S.message.content,yield{type:"text_delta",text:S.message.content}),S.message?.tool_calls)for(let b of S.message.tool_calls){let C={id:`ollama_tool_${p.length}`,name:b.function.name,input:b.function.arguments};p.push(C),yield{type:"tool_use_start",toolCall:{id:C.id,name:C.name}},yield{type:"tool_use_delta",toolCall:{input:C.input}}}S.done&&(d=S.prompt_eval_count??0,m=S.eval_count??0,yield{type:"message_complete",response:{content:c,model:this.config.model,toolCalls:p.length>0?p:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let f;try{f=JSON.parse(a.trim())}catch{return}if(f.message?.content&&(c+=f.message.content,yield{type:"text_delta",text:f.message.content}),f.message?.tool_calls)for(let g of f.message.tool_calls){let h={id:`ollama_tool_${p.length}`,name:g.function.name,input:g.function.arguments};p.push(h),yield{type:"tool_use_start",toolCall:{id:h.id,name:h.name}},yield{type:"tool_use_delta",toolCall:{input:h.input}}}f.done&&(d=f.prompt_eval_count??0,m=f.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
|
|
589
|
-
`)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,model:this.config.model,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var gr,Ti=_(()=>{"use strict";Xt();gr=class extends Fe{static{u(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});import{GoogleGenAI as Tp}from"@google/genai";var yr,wi=_(()=>{"use strict";xt();yr=class extends xe{static{u(this,"GoogleProvider")}client;rawContentCache=new Map;constructor(e){super(e)}async initialize(){this.client=new Tp({apiKey:this.config.apiKey});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContent({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}});return this.cacheRawContent(r),this.mapResponse(r)}async*stream(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContentStream({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}}),n="",o=[],i=0,a=0,c;for await(let d of r){c=d;let m=d.text;if(m&&(n+=m,yield{type:"text_delta",text:m}),d.functionCalls)for(let p of d.functionCalls){let f={id:p.id??`google_tool_${o.length}`,name:p.name,input:p.args??{}};o.push(f),yield{type:"tool_use_start",toolCall:{id:f.id,name:f.name}}}d.usageMetadata&&(i=d.usageMetadata.promptTokenCount??0,a=d.usageMetadata.candidatesTokenCount??0)}c&&this.cacheRawContent(c),yield{type:"message_complete",response:{content:n,model:this.config.model,toolCalls:o.length>0?o:void 0,usage:{inputTokens:i,outputTokens:a},stopReason:o.length>0?"tool_use":"end_turn"}}}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}cacheRawContent(e){let t=e.candidates?.[0]?.content;if(!t?.parts)return;let s=t.parts.filter(n=>n.functionCall);if(s.length===0)return;let r=this.buildCacheKey(s);if(this.rawContentCache.set(r,t),this.rawContentCache.size>20){let n=this.rawContentCache.keys().next().value;n&&this.rawContentCache.delete(n)}}buildCacheKey(e){return e.map(t=>`${t.functionCall.id??""}:${t.functionCall.name}`).sort().join("|")}buildCacheKeyFromBlocks(e){return e.map(t=>`${t.id}:${t.name}`).sort().join("|")}mapContents(e){let t=new Map;for(let r of e)if(!(r.role!=="assistant"||typeof r.content=="string"))for(let n of r.content)n.type==="tool_use"&&t.set(n.id,n.name);let s=[];for(let r of e){let n=r.role==="assistant"?"model":"user";if(typeof r.content=="string"){s.push({role:n,parts:[{text:r.content}]});continue}let o=[],i=[],a=[];for(let c of r.content)switch(c.type){case"text":i.push({text:c.text});break;case"image":i.push({inlineData:{mimeType:c.source.media_type,data:c.source.data}});break;case"tool_use":o.push({id:c.id,name:c.name,input:c.input});break;case"tool_result":{let d=t.get(c.tool_use_id)??c.tool_use_id,m;try{let p=JSON.parse(c.content);m=typeof p=="object"&&p!==null?p:{result:p}}catch{m={result:c.content}}a.push({functionResponse:{id:c.tool_use_id,name:d,response:m}});break}}if(r.role==="assistant"&&o.length>0){let c=this.buildCacheKeyFromBlocks(o),d=this.rawContentCache.get(c);if(d)s.push(d);else{let m=[...i];for(let p=0;p<o.length;p++){let f=o[p];m.push({functionCall:{id:f.id,name:f.name,args:f.input},...p===0?{thoughtSignature:"skip_thought_signature_validator"}:{}})}s.push({role:"model",parts:m})}}else i.length>0&&s.push({role:n,parts:i});a.length>0&&s.push({role:"user",parts:a})}return this.sanitizeContents(s)}sanitizeContents(e){let t=new Set,s=[];for(let i of e)if(i.role==="model"){for(let a of i.parts??[])if(a.functionCall){let c=a.functionCall.id??a.functionCall.name??"";c&&t.add(c)}s.push(i)}else{let a=(i.parts??[]).filter(c=>{if(c.functionResponse){let d=c.functionResponse.id??c.functionResponse.name??"";return d?t.has(d):!1}return!0});a.length>0&&s.push({role:i.role,parts:a})}let r=new Set;for(let i of s)if(i.role!=="model"){for(let a of i.parts??[])if(a.functionResponse){let c=a.functionResponse.id??a.functionResponse.name??"";c&&r.add(c)}}let n=[];for(let i of s)if(i.role==="model"){let a=(i.parts??[]).filter(c=>{if(c.functionCall){let d=c.functionCall.id??c.functionCall.name??"";return d?r.has(d):!1}return!0});a.length>0&&n.push({role:i.role,parts:a})}else n.push(i);if(n.length<=1)return n;let o=[n[0]];for(let i=1;i<n.length;i++){let a=o[o.length-1],c=n[i];a.role===c.role?a.parts=[...a.parts??[],...c.parts??[]]:o.push(c)}return o}mapTools(e){return e.map(t=>({name:t.name,description:t.description,parameters:t.inputSchema}))}mapResponse(e){let t=e.text??"",r=e.functionCalls?.map((n,o)=>({id:n.id??`google_tool_${o}`,name:n.name,input:n.args??{}}));return{content:t,model:this.config.model,toolCalls:r&&r.length>0?r:void 0,usage:{inputTokens:e.usageMetadata?.promptTokenCount??0,outputTokens:e.usageMetadata?.candidatesTokenCount??0},stopReason:r&&r.length>0?"tool_use":"end_turn"}}}});var Tr,_i=_(()=>{"use strict";Xt();Tr=class extends Fe{static{u(this,"MistralProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://api.mistral.ai/v1/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});function ki(l){switch(l.provider){case"anthropic":return new pr(l);case"openai":return new Fe(l);case"openrouter":return new hr(l);case"ollama":return new fr(l);case"openwebui":return new gr(l);case"google":return new yr(l);case"mistral":return new Tr(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var Ei=_(()=>{"use strict";fi();Xt();gi();yi();Ti();wi();_i();u(ki,"createLLMProvider")});function nl(l){let e=l.toLowerCase();for(let[t,s]of wp)if(e.startsWith(t.toLowerCase()))return s}function Nn(l,e){let t=nl(l);if(!t)return 0;let s=1e6,r=0,n=e.cacheReadTokens??0,o=e.cacheCreationTokens??0,i=e.inputTokens-n;return r+=i/s*t.input,r+=e.outputTokens/s*t.output,n>0&&t.cacheRead&&(r+=n/s*t.cacheRead),o>0&&t.cacheWrite&&(r+=o/s*t.cacheWrite),r}var wp,wr,bi=_(()=>{"use strict";wp=[["gpt-5.4",{input:2.5,output:15,cacheRead:1.25}],["gpt-5",{input:2,output:8,cacheRead:.5}],["gpt-4.1-nano",{input:.1,output:.4,cacheRead:.025}],["gpt-4.1-mini",{input:.4,output:1.6,cacheRead:.1}],["gpt-4.1",{input:2,output:8,cacheRead:.5}],["gpt-4o-mini",{input:.15,output:.6,cacheRead:.075}],["gpt-4o",{input:2.5,output:10,cacheRead:1.25}],["o4-mini",{input:1.1,output:4.4,cacheRead:.275}],["o3-mini",{input:1.1,output:4.4,cacheRead:.55}],["o3",{input:2,output:8,cacheRead:.5}],["claude-opus-4",{input:5,output:25,cacheRead:.5,cacheWrite:6.25}],["claude-sonnet-4",{input:3,output:15,cacheRead:.3,cacheWrite:3.75}],["claude-haiku-4",{input:1,output:5,cacheRead:.1,cacheWrite:1.25}],["claude-3.5-sonnet",{input:3,output:15,cacheRead:.3,cacheWrite:3.75}],["claude-3-haiku",{input:.25,output:1.25,cacheRead:.03}],["gemini-3.1-pro",{input:2,output:12,cacheRead:.2}],["gemini-3.0-pro",{input:2,output:12,cacheRead:.2}],["gemini-3.1-flash-lite",{input:.25,output:1.5,cacheRead:.025}],["gemini-3.0-flash",{input:.5,output:3,cacheRead:.05}],["gemini-2.5-pro",{input:1.25,output:10,cacheRead:.125}],["gemini-2.5-flash",{input:.3,output:2.5,cacheRead:.03}],["gemini-2.0-flash",{input:.1,output:.4,cacheRead:.025}],["mistral-large",{input:2,output:6}],["mistral-small",{input:.2,output:.6}]];u(nl,"getModelPricing");u(Nn,"calculateCost");wr=class{static{u(this,"TokenCostTracker")}data={totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheWriteTokens:0,totalCostUsd:0,byModel:{}};persistFn;setPersist(e){this.persistFn=e}record(e,t){let s=Nn(e,t),r=t.cacheReadTokens??0,n=t.cacheCreationTokens??0;this.data.totalInputTokens+=t.inputTokens,this.data.totalOutputTokens+=t.outputTokens,this.data.totalCacheReadTokens+=r,this.data.totalCacheWriteTokens+=n,this.data.totalCostUsd+=s;let o=this.data.byModel[e];o||(o={calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,costUsd:0},this.data.byModel[e]=o),o.calls++,o.inputTokens+=t.inputTokens,o.outputTokens+=t.outputTokens,o.cacheReadTokens+=r,o.cacheWriteTokens+=n,o.costUsd+=s;try{this.persistFn?.(e,t.inputTokens,t.outputTokens,r,n,s)}catch{}return s}getSummary(){return{...this.data,totalCostUsd:Math.round(this.data.totalCostUsd*1e6)/1e6,byModel:Object.fromEntries(Object.entries(this.data.byModel).map(([e,t])=>[e,{...t,costUsd:Math.round(t.costUsd*1e6)/1e6}]))}}}});function Si(l,e){return new Ln(l,e)}var _p,Ln,ol=_(()=>{"use strict";xt();Ei();bi();_p=["default","strong","fast","embeddings","local"],Ln=class extends xe{static{u(this,"ModelRouter")}providers=new Map;multiConfig;logger;costTracker=new wr;constructor(e,t){super(e.default),this.multiConfig=e,this.logger=t}async initialize(){for(let e of _p){let t=this.multiConfig[e];if(t){let s=ki(t);await s.initialize(),this.providers.set(e,s),this.logger?.info({tier:e,provider:t.provider,model:t.model},"LLM tier initialized")}}if(!this.providers.has("default"))throw new Error(`ModelRouter: no "default" tier configured. Available tiers: [${[...this.providers.keys()].join(", ")}]`)}resolve(e){if(e&&this.providers.has(e))return{provider:this.providers.get(e),resolvedTier:e};let t=this.providers.get("default");if(!t)throw new Error('ModelRouter: no "default" tier available. Was initialize() called?');return{provider:t,resolvedTier:"default"}}async complete(e){let{provider:t,resolvedTier:s}=this.resolve(e.tier),r=this.multiConfig[s];this.logger?.debug({requestedTier:e.tier??"default",resolvedTier:s,model:r?.model},"LLM routing request");let n=await t.complete(e),o=n.model??r?.model??"unknown";n.model||(n.model=o);let i=this.costTracker.record(o,n.usage);return this.logger?.info({tier:s,model:o,costUsd:Math.round(i*1e6)/1e6,inputTokens:n.usage?.inputTokens,outputTokens:n.usage?.outputTokens,cacheReadTokens:n.usage?.cacheReadTokens,cacheWriteTokens:n.usage?.cacheCreationTokens},"LLM call completed"),n}async*stream(e){let{provider:t}=this.resolve(e.tier);yield*t.stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve().provider).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve().provider).supportsEmbeddings()}isAvailable(){return this.resolve().provider.isAvailable()}getContextWindow(){return this.resolve().provider.getContextWindow()}getCostSummary(){return this.costTracker.getSummary()}setPersist(e){this.costTracker.setPersist(e)}};u(Si,"createModelRouter")});function je(l){return Math.ceil(l.length/3.5)}function Ct(l){if(typeof l.content=="string")return je(l.content)+4;let e=4;for(let t of l.content)switch(t.type){case"text":e+=je(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=je(t.name)+je(JSON.stringify(t.input));break;case"tool_result":e+=je(t.content);break}return e}function vi(l,e){let t=e?.keepRecentPairs??3,s=e?.maxTrimmedLength??120,r=e?.minContentLength??300,n=new Map;for(let a of l)if(a.role==="assistant"&&Array.isArray(a.content))for(let c of a.content)c.type==="tool_use"&&n.set(c.id,c.name);let o=[];for(let a=0;a<l.length;a++){let c=l[a];c.role==="user"&&Array.isArray(c.content)&&c.content.some(d=>d.type==="tool_result")&&o.push(a)}let i=new Set(o.slice(-t));return l.map((a,c)=>{if(i.has(c)||a.role!=="user"||!Array.isArray(a.content))return a;let d=!1,m=a.content.map(p=>{if(p.type!=="tool_result")return p;let f=p.content;if(typeof f!="string"||f.length<r)return p;d=!0;let g=n.get(p.tool_use_id)||"unknown",h=f.split(`
|
|
589
|
+
`)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,model:this.config.model,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var gr,Ti=_(()=>{"use strict";Xt();gr=class extends Fe{static{u(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});import{GoogleGenAI as Tp}from"@google/genai";var yr,wi=_(()=>{"use strict";xt();yr=class extends Ce{static{u(this,"GoogleProvider")}client;rawContentCache=new Map;constructor(e){super(e)}async initialize(){this.client=new Tp({apiKey:this.config.apiKey});let e=tt(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContent({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}});return this.cacheRawContent(r),this.mapResponse(r)}async*stream(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContentStream({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}}),n="",o=[],i=0,a=0,c;for await(let d of r){c=d;let m=d.text;if(m&&(n+=m,yield{type:"text_delta",text:m}),d.functionCalls)for(let p of d.functionCalls){let f={id:p.id??`google_tool_${o.length}`,name:p.name,input:p.args??{}};o.push(f),yield{type:"tool_use_start",toolCall:{id:f.id,name:f.name}}}d.usageMetadata&&(i=d.usageMetadata.promptTokenCount??0,a=d.usageMetadata.candidatesTokenCount??0)}c&&this.cacheRawContent(c),yield{type:"message_complete",response:{content:n,model:this.config.model,toolCalls:o.length>0?o:void 0,usage:{inputTokens:i,outputTokens:a},stopReason:o.length>0?"tool_use":"end_turn"}}}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}cacheRawContent(e){let t=e.candidates?.[0]?.content;if(!t?.parts)return;let s=t.parts.filter(n=>n.functionCall);if(s.length===0)return;let r=this.buildCacheKey(s);if(this.rawContentCache.set(r,t),this.rawContentCache.size>20){let n=this.rawContentCache.keys().next().value;n&&this.rawContentCache.delete(n)}}buildCacheKey(e){return e.map(t=>`${t.functionCall.id??""}:${t.functionCall.name}`).sort().join("|")}buildCacheKeyFromBlocks(e){return e.map(t=>`${t.id}:${t.name}`).sort().join("|")}mapContents(e){let t=new Map;for(let r of e)if(!(r.role!=="assistant"||typeof r.content=="string"))for(let n of r.content)n.type==="tool_use"&&t.set(n.id,n.name);let s=[];for(let r of e){let n=r.role==="assistant"?"model":"user";if(typeof r.content=="string"){s.push({role:n,parts:[{text:r.content}]});continue}let o=[],i=[],a=[];for(let c of r.content)switch(c.type){case"text":i.push({text:c.text});break;case"image":i.push({inlineData:{mimeType:c.source.media_type,data:c.source.data}});break;case"tool_use":o.push({id:c.id,name:c.name,input:c.input});break;case"tool_result":{let d=t.get(c.tool_use_id)??c.tool_use_id,m;try{let p=JSON.parse(c.content);m=typeof p=="object"&&p!==null?p:{result:p}}catch{m={result:c.content}}a.push({functionResponse:{id:c.tool_use_id,name:d,response:m}});break}}if(r.role==="assistant"&&o.length>0){let c=this.buildCacheKeyFromBlocks(o),d=this.rawContentCache.get(c);if(d)s.push(d);else{let m=[...i];for(let p=0;p<o.length;p++){let f=o[p];m.push({functionCall:{id:f.id,name:f.name,args:f.input},...p===0?{thoughtSignature:"skip_thought_signature_validator"}:{}})}s.push({role:"model",parts:m})}}else i.length>0&&s.push({role:n,parts:i});a.length>0&&s.push({role:"user",parts:a})}return this.sanitizeContents(s)}sanitizeContents(e){let t=new Set,s=[];for(let i of e)if(i.role==="model"){for(let a of i.parts??[])if(a.functionCall){let c=a.functionCall.id??a.functionCall.name??"";c&&t.add(c)}s.push(i)}else{let a=(i.parts??[]).filter(c=>{if(c.functionResponse){let d=c.functionResponse.id??c.functionResponse.name??"";return d?t.has(d):!1}return!0});a.length>0&&s.push({role:i.role,parts:a})}let r=new Set;for(let i of s)if(i.role!=="model"){for(let a of i.parts??[])if(a.functionResponse){let c=a.functionResponse.id??a.functionResponse.name??"";c&&r.add(c)}}let n=[];for(let i of s)if(i.role==="model"){let a=(i.parts??[]).filter(c=>{if(c.functionCall){let d=c.functionCall.id??c.functionCall.name??"";return d?r.has(d):!1}return!0});a.length>0&&n.push({role:i.role,parts:a})}else n.push(i);if(n.length<=1)return n;let o=[n[0]];for(let i=1;i<n.length;i++){let a=o[o.length-1],c=n[i];a.role===c.role?a.parts=[...a.parts??[],...c.parts??[]]:o.push(c)}return o}mapTools(e){return e.map(t=>({name:t.name,description:t.description,parameters:t.inputSchema}))}mapResponse(e){let t=e.text??"",r=e.functionCalls?.map((n,o)=>({id:n.id??`google_tool_${o}`,name:n.name,input:n.args??{}}));return{content:t,model:this.config.model,toolCalls:r&&r.length>0?r:void 0,usage:{inputTokens:e.usageMetadata?.promptTokenCount??0,outputTokens:e.usageMetadata?.candidatesTokenCount??0},stopReason:r&&r.length>0?"tool_use":"end_turn"}}}});var Tr,_i=_(()=>{"use strict";Xt();Tr=class extends Fe{static{u(this,"MistralProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://api.mistral.ai/v1/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});function ki(l){switch(l.provider){case"anthropic":return new pr(l);case"openai":return new Fe(l);case"openrouter":return new hr(l);case"ollama":return new fr(l);case"openwebui":return new gr(l);case"google":return new yr(l);case"mistral":return new Tr(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var Ei=_(()=>{"use strict";fi();Xt();gi();yi();Ti();wi();_i();u(ki,"createLLMProvider")});function nl(l){let e=l.toLowerCase();for(let[t,s]of wp)if(e.startsWith(t.toLowerCase()))return s}function Nn(l,e){let t=nl(l);if(!t)return 0;let s=1e6,r=0,n=e.cacheReadTokens??0,o=e.cacheCreationTokens??0,i=e.inputTokens-n;return r+=i/s*t.input,r+=e.outputTokens/s*t.output,n>0&&t.cacheRead&&(r+=n/s*t.cacheRead),o>0&&t.cacheWrite&&(r+=o/s*t.cacheWrite),r}var wp,wr,bi=_(()=>{"use strict";wp=[["gpt-5.4",{input:2.5,output:15,cacheRead:1.25}],["gpt-5",{input:2,output:8,cacheRead:.5}],["gpt-4.1-nano",{input:.1,output:.4,cacheRead:.025}],["gpt-4.1-mini",{input:.4,output:1.6,cacheRead:.1}],["gpt-4.1",{input:2,output:8,cacheRead:.5}],["gpt-4o-mini",{input:.15,output:.6,cacheRead:.075}],["gpt-4o",{input:2.5,output:10,cacheRead:1.25}],["o4-mini",{input:1.1,output:4.4,cacheRead:.275}],["o3-mini",{input:1.1,output:4.4,cacheRead:.55}],["o3",{input:2,output:8,cacheRead:.5}],["claude-opus-4",{input:5,output:25,cacheRead:.5,cacheWrite:6.25}],["claude-sonnet-4",{input:3,output:15,cacheRead:.3,cacheWrite:3.75}],["claude-haiku-4",{input:1,output:5,cacheRead:.1,cacheWrite:1.25}],["claude-3.5-sonnet",{input:3,output:15,cacheRead:.3,cacheWrite:3.75}],["claude-3-haiku",{input:.25,output:1.25,cacheRead:.03}],["gemini-3.1-pro",{input:2,output:12,cacheRead:.2}],["gemini-3.0-pro",{input:2,output:12,cacheRead:.2}],["gemini-3.1-flash-lite",{input:.25,output:1.5,cacheRead:.025}],["gemini-3.0-flash",{input:.5,output:3,cacheRead:.05}],["gemini-2.5-pro",{input:1.25,output:10,cacheRead:.125}],["gemini-2.5-flash",{input:.3,output:2.5,cacheRead:.03}],["gemini-2.0-flash",{input:.1,output:.4,cacheRead:.025}],["mistral-large",{input:2,output:6}],["mistral-small",{input:.2,output:.6}]];u(nl,"getModelPricing");u(Nn,"calculateCost");wr=class{static{u(this,"TokenCostTracker")}data={totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheWriteTokens:0,totalCostUsd:0,byModel:{}};persistFn;setPersist(e){this.persistFn=e}record(e,t){let s=Nn(e,t),r=t.cacheReadTokens??0,n=t.cacheCreationTokens??0;this.data.totalInputTokens+=t.inputTokens,this.data.totalOutputTokens+=t.outputTokens,this.data.totalCacheReadTokens+=r,this.data.totalCacheWriteTokens+=n,this.data.totalCostUsd+=s;let o=this.data.byModel[e];o||(o={calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,costUsd:0},this.data.byModel[e]=o),o.calls++,o.inputTokens+=t.inputTokens,o.outputTokens+=t.outputTokens,o.cacheReadTokens+=r,o.cacheWriteTokens+=n,o.costUsd+=s;try{this.persistFn?.(e,t.inputTokens,t.outputTokens,r,n,s)}catch{}return s}getSummary(){return{...this.data,totalCostUsd:Math.round(this.data.totalCostUsd*1e6)/1e6,byModel:Object.fromEntries(Object.entries(this.data.byModel).map(([e,t])=>[e,{...t,costUsd:Math.round(t.costUsd*1e6)/1e6}]))}}}});function Si(l,e){return new Ln(l,e)}var _p,Ln,ol=_(()=>{"use strict";xt();Ei();bi();_p=["default","strong","fast","embeddings","local"],Ln=class extends Ce{static{u(this,"ModelRouter")}providers=new Map;multiConfig;logger;costTracker=new wr;constructor(e,t){super(e.default),this.multiConfig=e,this.logger=t}async initialize(){for(let e of _p){let t=this.multiConfig[e];if(t){let s=ki(t);await s.initialize(),this.providers.set(e,s),this.logger?.info({tier:e,provider:t.provider,model:t.model},"LLM tier initialized")}}if(!this.providers.has("default"))throw new Error(`ModelRouter: no "default" tier configured. Available tiers: [${[...this.providers.keys()].join(", ")}]`)}resolve(e){if(e&&this.providers.has(e))return{provider:this.providers.get(e),resolvedTier:e};let t=this.providers.get("default");if(!t)throw new Error('ModelRouter: no "default" tier available. Was initialize() called?');return{provider:t,resolvedTier:"default"}}async complete(e){let{provider:t,resolvedTier:s}=this.resolve(e.tier),r=this.multiConfig[s];this.logger?.debug({requestedTier:e.tier??"default",resolvedTier:s,model:r?.model},"LLM routing request");let n=await t.complete(e),o=n.model??r?.model??"unknown";n.model||(n.model=o);let i=this.costTracker.record(o,n.usage);return this.logger?.info({tier:s,model:o,costUsd:Math.round(i*1e6)/1e6,inputTokens:n.usage?.inputTokens,outputTokens:n.usage?.outputTokens,cacheReadTokens:n.usage?.cacheReadTokens,cacheWriteTokens:n.usage?.cacheCreationTokens},"LLM call completed"),n}async*stream(e){let{provider:t}=this.resolve(e.tier);yield*t.stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve().provider).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve().provider).supportsEmbeddings()}isAvailable(){return this.resolve().provider.isAvailable()}getContextWindow(){return this.resolve().provider.getContextWindow()}getCostSummary(){return this.costTracker.getSummary()}setPersist(e){this.costTracker.setPersist(e)}};u(Si,"createModelRouter")});function je(l){return Math.ceil(l.length/3.5)}function Ct(l){if(typeof l.content=="string")return je(l.content)+4;let e=4;for(let t of l.content)switch(t.type){case"text":e+=je(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=je(t.name)+je(JSON.stringify(t.input));break;case"tool_result":e+=je(t.content);break}return e}function vi(l,e){let t=e?.keepRecentPairs??3,s=e?.maxTrimmedLength??120,r=e?.minContentLength??300,n=new Map;for(let a of l)if(a.role==="assistant"&&Array.isArray(a.content))for(let c of a.content)c.type==="tool_use"&&n.set(c.id,c.name);let o=[];for(let a=0;a<l.length;a++){let c=l[a];c.role==="user"&&Array.isArray(c.content)&&c.content.some(d=>d.type==="tool_result")&&o.push(a)}let i=new Set(o.slice(-t));return l.map((a,c)=>{if(i.has(c)||a.role!=="user"||!Array.isArray(a.content))return a;let d=!1,m=a.content.map(p=>{if(p.type!=="tool_result")return p;let f=p.content;if(typeof f!="string"||f.length<r)return p;d=!0;let g=n.get(p.tool_use_id)||"unknown",h=f.split(`
|
|
590
590
|
`)[0].slice(0,s),y=p.is_error?"Fehler":"Ergebnis";return{...p,content:`[${y}: ${g} \u2014 ${h}]`}});return d?{...a,content:m}:a})}var _r,il=_(()=>{"use strict";u(je,"estimateTokens");u(Ct,"estimateMessageTokens");u(vi,"trimOldToolResults");_r=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n,conversationSummary:o}=e,i=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",a=process.env.HOME||process.env.USERPROFILE||"~",c=`You are Alfred, a personal AI assistant. You run on ${i} (home: ${a}).
|
|
591
591
|
|
|
592
592
|
## Core principles
|
|
@@ -693,12 +693,12 @@ Available JS libraries in code_sandbox (no install needed): exceljs, pdfkit, pdf
|
|
|
693
693
|
|
|
694
694
|
Additional context: ${r}`);let g,h;t.resumeState?.conversationHistory?.length?(g=t.resumeState.conversationHistory,h=t.resumeState.currentIteration):(g=[{role:"user",content:f}],h=0);try{let y=h,k=0,S=0;for(;;){if(t.abortSignal?.aborted)return t.onIteration?.({iteration:y,maxIterations:o,messages:[...g],dataStore:Object.fromEntries(d)}),a.ping("done",{iteration:y,maxIterations:o}),{success:!0,data:{response:"Task paused \u2014 can be resumed later.",iterations:y,paused:!0,usage:{inputTokens:k,outputTokens:S}},display:"Task paused \u2014 can be resumed later."};a.ping("llm_call",{iteration:y,maxIterations:o});let b=await this.llm.complete({messages:g,system:p,tools:c.length>0?c:void 0,maxTokens:8192,tier:"strong"});if(k+=b.usage.inputTokens,S+=b.usage.outputTokens,a.ping("processing",{iteration:y,maxIterations:o}),!b.toolCalls||b.toolCalls.length===0||y>=o)return a.ping("done",{iteration:y,maxIterations:o}),{success:!0,data:{response:b.content,iterations:y,usage:{inputTokens:k,outputTokens:S}},display:b.content};y++;let C=[];b.content&&C.push({type:"text",text:b.content});for(let U of b.toolCalls)C.push({type:"tool_use",id:U.id,name:U.name,input:U.input});g.push({role:"assistant",content:C});let D=[];for(let U of b.toolCalls){a.ping("tool_call",{iteration:y,maxIterations:o,tool:U.name});let Q=U.input;if(U.name==="code_sandbox"&&U.input.data){let z=String(U.input.data);d.has(z)&&(Q={...U.input,data:d.get(z)},Q.action==="run"&&(Q.action="run_with_data"))}let ie=await this.executeSubAgentTool({...U,input:Q},t),j=ie.content;if(!ie.isError&&j.length>500){let z=`result_${++m}`,ae=ie.rawData!=null?JSON.stringify(ie.rawData):j;d.set(z,ae),j+=`
|
|
695
695
|
|
|
696
|
-
[Data stored as "${z}" \u2014 use code_sandbox action "run_with_data" with data="${z}" to process this data. Do NOT copy data into code.]`}D.push({type:"tool_result",tool_use_id:U.id,content:j,is_error:ie.isError})}g.push({role:"user",content:D}),t.onIteration?.({iteration:y,maxIterations:o,messages:[...g],dataStore:Object.fromEntries(d)})}}catch(y){return{success:!1,error:`Sub-agent failed: ${y instanceof Error?y.message:String(y)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var rt,On=_(()=>{"use strict";rt=class{static{u(this,"EmailProvider")}async extractFromSearch(e,t,s,r,n){throw new Error("Extract is not supported by this email provider.")}async createDraft(e){throw new Error("Draft creation is not supported by this email provider.")}async forwardMessage(e,t,s){throw new Error("Email forwarding is not supported by this email provider.")}}});var Rl={};pe(Rl,{MicrosoftGraphEmailProvider:()=>Un});var Un,Ci=_(()=>{"use strict";On();Un=class extends rt{static{u(this,"MicrosoftGraphEmailProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){if(!this.config.refreshToken)throw new Error("Microsoft email: refreshToken is missing from config");let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Microsoft token refresh failed: ${s.status} \u2014 ${n.slice(0,300)}`)}let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let n=await s(this.accessToken);if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return this.parseJsonOrUndefined(n)}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return this.parseJsonOrUndefined(r)}async parseJsonOrUndefined(e){if(e.status===204||e.status===202)return;let t=await e.text();if(!(!t||t.length===0))return JSON.parse(t)}async graphRequestRaw(e){let t=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${n}`}}),"doFetch"),s=await t(this.accessToken);if(s.status===401&&(await this.refreshAccessToken(),s=await t(this.accessToken)),!s.ok)throw new Error(`Graph API error: ${s.status}`);let r=await s.arrayBuffer();return Buffer.from(r)}async fetchInbox(e){let t=new URLSearchParams({$top:String(Math.min(Math.max(1,e),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/inbox/messages?${t}`)).value??[]).map(r=>this.mapMessage(r))}async readMessage(e){let t=new URLSearchParams({$select:"id,from,toRecipients,ccRecipients,bccRecipients,subject,body,receivedDateTime,isRead,hasAttachments"}),s=await this.graphRequest(`/me/messages/${e}?${t}`),r=[];return s.hasAttachments&&(r=((await this.graphRequest(`/me/messages/${e}/attachments?$select=id,name,contentType,size`)).value??[]).map(o=>({id:o.id,name:o.name,contentType:o.contentType,size:o.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(n=>this.formatGraphAddress(n)),subject:s.subject??"(no subject)",date:new Date(s.receivedDateTime),read:s.isRead??!1,body:s.body?.contentType==="html"?this.stripHtml(s.body.content??""):s.body?.content??"",bodyHtml:s.body?.contentType==="html"?s.body.content:void 0,cc:s.ccRecipients?.map(n=>this.formatGraphAddress(n)),bcc:s.bccRecipients?.map(n=>this.formatGraphAddress(n)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=new URLSearchParams({$search:`"${e}"`,$top:String(s),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"}),n=await this.graphRequest(`/me/messages?${r}`),o=(n.value??[]).map(i=>this.mapMessage(i));if(t>50){let i=n["@odata.nextLink"];for(;i&&o.length<t;){let a=await this.graphRequest(i.replace("https://graph.microsoft.com/v1.0","")),c=(a.value??[]).map(d=>this.mapMessage(d));o.push(...c),i=a["@odata.nextLink"]}}return o.slice(0,t)}async extractFromSearch(e,t,s,r,n){let o=await this.searchWithDateFilter(e,t,r,n),i=s.includes("amount"),a=[];if(i)for(let d=0;d<o.length;d+=5){let m=o.slice(d,d+5),p=await Promise.allSettled(m.map(async f=>{let g={id:f.id,from:f.from,subject:f.subject,date:f.date.toISOString().split("T")[0],preview:(f.preview??"").slice(0,200)};try{let h=await this.readMessage(f.id),y=this.extractAmount(h.body);y&&(g.amount=y.amount,g.currency=y.currency)}catch{}return g}));for(let f of p)f.status==="fulfilled"&&a.push(f.value)}else for(let c of o)a.push({id:c.id,from:c.from,subject:c.subject,date:c.date.toISOString().split("T")[0],preview:(c.preview??"").slice(0,200)});return a}async searchWithDateFilter(e,t,s,r){let n=Math.min(Math.max(1,t),50),o=[];if(s||r){let p=s?this.toKqlDate(s):"01/01/2000",f=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${f}`)}e&&o.push(e.includes(" ")?`(${e})`:e);let i=o.join(" AND "),a=new URLSearchParams({$top:String(n),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});i?a.set("$search",`"${i}"`):a.set("$orderby","receivedDateTime desc");let c=await this.graphRequest(`/me/messages?${a}`),d=(c.value??[]).map(p=>this.mapMessage(p)),m=c["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),f=(p.value??[]).map(g=>this.mapMessage(g));d.push(...f),m=p["@odata.nextLink"]}return d.slice(0,t)}toKqlDate(e){let[t,s,r]=e.split("-");return`${s}/${r}/${t}`}extractAmount(e){let t=[{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*€\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*€/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*EUR\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*EUR/i,currency:"EUR"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*\$\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*USD\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*([\d.,]+)\s*USD/i,currency:"USD"},{regex:/€\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\b([\d]+[.,]\d{2})\s*€/,currency:"EUR"},{regex:/EUR\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\$([\d]+[.,]\d{2})\b/,currency:"USD"},{regex:/USD\s*([\d]+[.,]\d{2})\b/,currency:"USD"}];for(let{regex:s,currency:r}of t){let n=e.match(s);if(n?.[1])return{amount:n[1].trim(),currency:r}}return null}async sendMessage(e){if(e.replyTo)return await this.graphRequest(`/me/messages/${e.replyTo}/reply`,{method:"POST",body:JSON.stringify({comment:e.body})}),{messageId:e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(s=>({emailAddress:{address:s.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(s=>({emailAddress:{address:s.trim()}}))),await this.graphRequest("/me/sendMail",{method:"POST",body:JSON.stringify({message:t})}),{messageId:`sent-${Date.now()}`}}async createDraft(e){if(e.replyTo)return{messageId:(await this.graphRequest(`/me/messages/${e.replyTo}/createReply`,{method:"POST",body:JSON.stringify({comment:e.body})}))?.id??e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(r=>({emailAddress:{address:r.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(r=>({emailAddress:{address:r.trim()}}))),{messageId:(await this.graphRequest("/me/messages",{method:"POST",body:JSON.stringify(t)}))?.id??`draft-${Date.now()}`}}async listFolders(){return((await this.graphRequest("/me/mailFolders?$select=displayName&$top=100")).value??[]).map(t=>t.displayName)}async fetchFolder(e,t){let r=((await this.graphRequest("/me/mailFolders?$select=id,displayName&$top=100")).value??[]).find(i=>i.displayName.toLowerCase()===e.toLowerCase());if(!r)throw new Error(`Folder "${e}" not found. Use the 'folders' action to list available folders.`);let n=new URLSearchParams({$top:String(Math.min(Math.max(1,t),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/${r.id}/messages?${n}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}async forwardMessage(e,t,s){return await this.graphRequest(`/me/messages/${e}/forward`,{method:"POST",body:JSON.stringify({comment:s??"",toRecipients:t.split(",").map(r=>({emailAddress:{address:r.trim()}}))})}),{messageId:`fwd-${Date.now()}`}}mapMessage(e){return{id:e.id,from:this.formatGraphAddress(e.from),to:(e.toRecipients??[]).map(t=>this.formatGraphAddress(t)),subject:e.subject??"(no subject)",date:new Date(e.receivedDateTime),read:e.isRead??!1,preview:e.bodyPreview??void 0,hasAttachments:e.hasAttachments??!1}}formatGraphAddress(e){if(!e)return"unknown";let t=e.emailAddress??e;return t?.address?t.name?`${t.name} <${t.address}>`:t.address:"unknown"}stripHtml(e){return e.replace(/<br\s*\/?>/gi,`
|
|
696
|
+
[Data stored as "${z}" \u2014 use code_sandbox action "run_with_data" with data="${z}" to process this data. Do NOT copy data into code.]`}D.push({type:"tool_result",tool_use_id:U.id,content:j,is_error:ie.isError})}g.push({role:"user",content:D}),t.onIteration?.({iteration:y,maxIterations:o,messages:[...g],dataStore:Object.fromEntries(d)})}}catch(y){return{success:!1,error:`Sub-agent failed: ${y instanceof Error?y.message:String(y)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var rt,On=_(()=>{"use strict";rt=class{static{u(this,"EmailProvider")}async extractFromSearch(e,t,s,r,n){throw new Error("Extract is not supported by this email provider.")}async createDraft(e){throw new Error("Draft creation is not supported by this email provider.")}async forwardMessage(e,t,s){throw new Error("Email forwarding is not supported by this email provider.")}}});var Rl={};he(Rl,{MicrosoftGraphEmailProvider:()=>Un});var Un,Ci=_(()=>{"use strict";On();Un=class extends rt{static{u(this,"MicrosoftGraphEmailProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){if(!this.config.refreshToken)throw new Error("Microsoft email: refreshToken is missing from config");let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Microsoft token refresh failed: ${s.status} \u2014 ${n.slice(0,300)}`)}let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let n=await s(this.accessToken);if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return this.parseJsonOrUndefined(n)}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return this.parseJsonOrUndefined(r)}async parseJsonOrUndefined(e){if(e.status===204||e.status===202)return;let t=await e.text();if(!(!t||t.length===0))return JSON.parse(t)}async graphRequestRaw(e){let t=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${n}`}}),"doFetch"),s=await t(this.accessToken);if(s.status===401&&(await this.refreshAccessToken(),s=await t(this.accessToken)),!s.ok)throw new Error(`Graph API error: ${s.status}`);let r=await s.arrayBuffer();return Buffer.from(r)}async fetchInbox(e){let t=new URLSearchParams({$top:String(Math.min(Math.max(1,e),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/inbox/messages?${t}`)).value??[]).map(r=>this.mapMessage(r))}async readMessage(e){let t=new URLSearchParams({$select:"id,from,toRecipients,ccRecipients,bccRecipients,subject,body,receivedDateTime,isRead,hasAttachments"}),s=await this.graphRequest(`/me/messages/${e}?${t}`),r=[];return s.hasAttachments&&(r=((await this.graphRequest(`/me/messages/${e}/attachments?$select=id,name,contentType,size`)).value??[]).map(o=>({id:o.id,name:o.name,contentType:o.contentType,size:o.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(n=>this.formatGraphAddress(n)),subject:s.subject??"(no subject)",date:new Date(s.receivedDateTime),read:s.isRead??!1,body:s.body?.contentType==="html"?this.stripHtml(s.body.content??""):s.body?.content??"",bodyHtml:s.body?.contentType==="html"?s.body.content:void 0,cc:s.ccRecipients?.map(n=>this.formatGraphAddress(n)),bcc:s.bccRecipients?.map(n=>this.formatGraphAddress(n)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=new URLSearchParams({$search:`"${e}"`,$top:String(s),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"}),n=await this.graphRequest(`/me/messages?${r}`),o=(n.value??[]).map(i=>this.mapMessage(i));if(t>50){let i=n["@odata.nextLink"];for(;i&&o.length<t;){let a=await this.graphRequest(i.replace("https://graph.microsoft.com/v1.0","")),c=(a.value??[]).map(d=>this.mapMessage(d));o.push(...c),i=a["@odata.nextLink"]}}return o.slice(0,t)}async extractFromSearch(e,t,s,r,n){let o=await this.searchWithDateFilter(e,t,r,n),i=s.includes("amount"),a=[];if(i)for(let d=0;d<o.length;d+=5){let m=o.slice(d,d+5),p=await Promise.allSettled(m.map(async f=>{let g={id:f.id,from:f.from,subject:f.subject,date:f.date.toISOString().split("T")[0],preview:(f.preview??"").slice(0,200)};try{let h=await this.readMessage(f.id),y=this.extractAmount(h.body);y&&(g.amount=y.amount,g.currency=y.currency)}catch{}return g}));for(let f of p)f.status==="fulfilled"&&a.push(f.value)}else for(let c of o)a.push({id:c.id,from:c.from,subject:c.subject,date:c.date.toISOString().split("T")[0],preview:(c.preview??"").slice(0,200)});return a}async searchWithDateFilter(e,t,s,r){let n=Math.min(Math.max(1,t),50),o=[];if(s||r){let p=s?this.toKqlDate(s):"01/01/2000",f=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${f}`)}e&&o.push(e.includes(" ")?`(${e})`:e);let i=o.join(" AND "),a=new URLSearchParams({$top:String(n),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});i?a.set("$search",`"${i}"`):a.set("$orderby","receivedDateTime desc");let c=await this.graphRequest(`/me/messages?${a}`),d=(c.value??[]).map(p=>this.mapMessage(p)),m=c["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),f=(p.value??[]).map(g=>this.mapMessage(g));d.push(...f),m=p["@odata.nextLink"]}return d.slice(0,t)}toKqlDate(e){let[t,s,r]=e.split("-");return`${s}/${r}/${t}`}extractAmount(e){let t=[{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*€\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*€/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*EUR\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*EUR/i,currency:"EUR"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*\$\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*USD\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*([\d.,]+)\s*USD/i,currency:"USD"},{regex:/€\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\b([\d]+[.,]\d{2})\s*€/,currency:"EUR"},{regex:/EUR\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\$([\d]+[.,]\d{2})\b/,currency:"USD"},{regex:/USD\s*([\d]+[.,]\d{2})\b/,currency:"USD"}];for(let{regex:s,currency:r}of t){let n=e.match(s);if(n?.[1])return{amount:n[1].trim(),currency:r}}return null}async sendMessage(e){if(e.replyTo)return await this.graphRequest(`/me/messages/${e.replyTo}/reply`,{method:"POST",body:JSON.stringify({comment:e.body})}),{messageId:e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(s=>({emailAddress:{address:s.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(s=>({emailAddress:{address:s.trim()}}))),await this.graphRequest("/me/sendMail",{method:"POST",body:JSON.stringify({message:t})}),{messageId:`sent-${Date.now()}`}}async createDraft(e){if(e.replyTo)return{messageId:(await this.graphRequest(`/me/messages/${e.replyTo}/createReply`,{method:"POST",body:JSON.stringify({comment:e.body})}))?.id??e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(r=>({emailAddress:{address:r.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(r=>({emailAddress:{address:r.trim()}}))),{messageId:(await this.graphRequest("/me/messages",{method:"POST",body:JSON.stringify(t)}))?.id??`draft-${Date.now()}`}}async listFolders(){return((await this.graphRequest("/me/mailFolders?$select=displayName&$top=100")).value??[]).map(t=>t.displayName)}async fetchFolder(e,t){let r=((await this.graphRequest("/me/mailFolders?$select=id,displayName&$top=100")).value??[]).find(i=>i.displayName.toLowerCase()===e.toLowerCase());if(!r)throw new Error(`Folder "${e}" not found. Use the 'folders' action to list available folders.`);let n=new URLSearchParams({$top:String(Math.min(Math.max(1,t),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/${r.id}/messages?${n}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}async forwardMessage(e,t,s){return await this.graphRequest(`/me/messages/${e}/forward`,{method:"POST",body:JSON.stringify({comment:s??"",toRecipients:t.split(",").map(r=>({emailAddress:{address:r.trim()}}))})}),{messageId:`fwd-${Date.now()}`}}mapMessage(e){return{id:e.id,from:this.formatGraphAddress(e.from),to:(e.toRecipients??[]).map(t=>this.formatGraphAddress(t)),subject:e.subject??"(no subject)",date:new Date(e.receivedDateTime),read:e.isRead??!1,preview:e.bodyPreview??void 0,hasAttachments:e.hasAttachments??!1}}formatGraphAddress(e){if(!e)return"unknown";let t=e.emailAddress??e;return t?.address?t.name?`${t.name} <${t.address}>`:t.address:"unknown"}stripHtml(e){return e.replace(/<br\s*\/?>/gi,`
|
|
697
697
|
`).replace(/<\/p>/gi,`
|
|
698
698
|
|
|
699
699
|
`).replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/\n{3,}/g,`
|
|
700
700
|
|
|
701
|
-
`).trim()}}});var xl={};
|
|
701
|
+
`).trim()}}});var xl={};he(xl,{StandardEmailProvider:()=>Pn});var Pn,Ni=_(()=>{"use strict";On();Pn=class extends rt{static{u(this,"StandardEmailProvider")}config;constructor(e){super(),this.config=e}async initialize(){}createImapClient(){return import("imapflow").then(({ImapFlow:e})=>new e({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1}))}formatAddress(e){return e?e.name?`${e.name} <${e.address}>`:e.address??"unknown":"unknown"}async fetchInbox(e){return this.fetchFolder("INBOX",e)}async readMessage(e){let t=parseInt(e,10);if(isNaN(t)||t<1)throw new Error("messageId must be a positive number (sequence number).");let s=await this.createImapClient();try{await s.connect();let r=await s.getMailboxLock("INBOX");try{let n=await s.fetchOne(String(t),{envelope:!0,source:!0,bodyStructure:!0});if(!n)throw new Error(`Message #${t} not found.`);let o=this.formatAddress(n.envelope?.from?.[0]),i=n.envelope?.to?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??"")??[],a=n.envelope?.cc?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??""),c=n.source?.toString()??"",d=this.extractTextBody(c),m=this.extractAttachmentInfo(n.bodyStructure);return{id:String(t),from:o,to:i,subject:n.envelope?.subject??"(no subject)",date:n.envelope?.date??new Date,read:n.flags?.has("\\Seen")??!1,body:d,cc:a,attachments:m}}finally{r.release()}}finally{await s.logout()}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=await r.search({or:[{subject:e},{from:e},{body:e}]}),i=Array.isArray(o)?o:[];if(i.length===0)return[];let a=i.slice(-s),c=[];for await(let d of r.fetch(a,{envelope:!0,flags:!0}))c.push({id:String(d.seq),from:this.formatAddress(d.envelope?.from?.[0]),to:d.envelope?.to?.map(m=>m.name?`${m.name} <${m.address}>`:m.address??"")??[],subject:d.envelope?.subject??"(no subject)",date:d.envelope?.date??new Date,read:d.flags?.has("\\Seen")??!1});return c.reverse(),c}finally{n.release()}}finally{await r.logout()}}async sendMessage(e){let s=(await import("nodemailer")).createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure,auth:this.config.auth}),r={from:this.config.auth.user,to:e.to,subject:e.subject};return e.cc&&(r.cc=e.cc),e.isHtml?r.html=e.body:r.text=e.body,e.replyTo&&(r.inReplyTo=e.replyTo,r.references=e.replyTo),{messageId:(await s.sendMail(r)).messageId}}async listFolders(){let e=await this.createImapClient();try{await e.connect();let t=await e.list(),s=[];for(let r of t)s.push(r.path);return s}finally{await e.logout()}}async fetchFolder(e,t){let s=Math.min(Math.max(1,t),50),r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock(e);try{let o=[],i=r.mailbox,a=i&&typeof i=="object"?i.exists??0:0;if(a===0)return[];let d=`${Math.max(1,a-s+1)}:*`;for await(let m of r.fetch(d,{envelope:!0,flags:!0})){let p=this.formatAddress(m.envelope?.from?.[0]);o.push({id:String(m.seq),from:p,to:m.envelope?.to?.map(f=>f.name?`${f.name} <${f.address}>`:f.address??"")??[],subject:m.envelope?.subject??"(no subject)",date:m.envelope?.date??new Date,read:m.flags?.has("\\Seen")??!1})}return o.reverse(),o}finally{n.release()}}finally{await r.logout()}}async downloadAttachment(e,t){let s=parseInt(e,10);if(isNaN(s)||s<1)throw new Error("messageId must be a positive number.");let r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let i=(await r.fetchOne(String(s),{bodyParts:[t]}))?.bodyParts?.get(t);if(!i)throw new Error(`Attachment "${t}" not found in message #${s}.`);return Buffer.from(i)}finally{n.release()}}finally{await r.logout()}}extractAttachmentInfo(e){let t=[];if(!e)return t;let s=u((r,n)=>{if(r.childNodes){for(let i=0;i<r.childNodes.length;i++)s(r.childNodes[i],n?`${n}.${i+1}`:String(i+1));return}let o=r.disposition?.toLowerCase();if(o==="attachment"||r.type&&!r.type.startsWith("text/")&&o!=="inline"){let i=r.dispositionParameters?.filename??r.parameters?.name??`part-${n}`;t.push({id:r.part??n,name:i,contentType:r.type??"application/octet-stream",size:r.size??0})}},"walk");return s(e,""),t}extractTextBody(e){let t=e.split(/\r?\n\r?\n/);if(t.length<2)return e;let s=t[0].toLowerCase();if(!s.includes("multipart"))return this.decodeBody(t.slice(1).join(`
|
|
702
702
|
|
|
703
703
|
`));let r=s.match(/boundary="?([^"\s;]+)"?/i)??e.match(/boundary="?([^"\s;]+)"?/i);if(!r)return t.slice(1).join(`
|
|
704
704
|
|
|
@@ -778,7 +778,7 @@ Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.op
|
|
|
778
778
|
|
|
779
779
|
${c}`}}catch(n){return{success:!1,error:`Failed to open "${s}": ${n.message}`}}}async screenshotPage(e,t){try{let s=await this.ensurePage(e),r=t.url;r&&await s.goto(r,{waitUntil:"networkidle2",timeout:3e4});let n=s.url();if(n==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let o=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||Lp.join(Dp.homedir(),"Desktop",`browser-${o}.png`);return await s.screenshot({path:i,fullPage:!1}),{success:!0,data:{path:i,url:n},display:`Screenshot saved to ${i}`}}catch(s){return{success:!1,error:`Screenshot failed: ${s.message}`}}}async clickElement(e){let t=e.selector;if(!t)return{success:!1,error:'Missing "selector" for click action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t);try{await this.page.waitForNavigation({timeout:3e3})}catch{}let s=await this.page.title();return{success:!0,data:{selector:t,url:this.page.url(),title:s},display:`Clicked "${t}" \u2014 now on: ${s} (${this.page.url()})`}}catch(s){return{success:!1,error:`Click failed on "${t}": ${s.message}`}}}async typeText(e){let t=e.selector,s=e.text;if(!t)return{success:!1,error:'Missing "selector" for type action'};if(!s)return{success:!1,error:'Missing "text" for type action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{return await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t),await this.page.type(t,s,{delay:50}),{success:!0,data:{selector:t,textLength:s.length},display:`Typed ${s.length} characters into "${t}"`}}catch(r){return{success:!1,error:`Type failed on "${t}": ${r.message}`}}}async evaluateScript(e){let t=e.script;if(!t)return{success:!1,error:'Missing "script" for evaluate action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{let s=await this.page.evaluate(t),r=typeof s=="string"?s:JSON.stringify(s,null,2);return{success:!0,data:{result:s},display:r?.slice(0,1e4)??"(no output)"}}catch(s){return{success:!1,error:`Evaluate failed: ${s.message}`}}}validateUrl(e){let t;try{t=new URL(e)}catch{return`Invalid URL: "${e}"`}if(["file:","chrome:","about:","data:","javascript:"].includes(t.protocol))return`Blocked URL protocol "${t.protocol}". Only http: and https: are allowed.`;if(t.protocol!=="http:"&&t.protocol!=="https:")return`Unsupported URL protocol "${t.protocol}". Only http: and https: are allowed.`;let r=t.hostname;return this.isPrivateHost(r)?`Access to private/internal network address "${r}" is blocked.`:null}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;if(e.startsWith("[")||e.toLowerCase().startsWith("fc")||e.toLowerCase().startsWith("fd")){let s=e.replace(/[\[\]]/g,"").toLowerCase();if(s.startsWith("fc")||s.startsWith("fd")||s==="::1")return!0}let t=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(t){let[,s,r]=t.map(Number);if(s===10||s===172&&r>=16&&r<=31||s===192&&r===168||s===127||s===169&&r===254||s===0)return!0}return!1}async closeBrowser(){try{return this.page=null,this.browser&&(await this.browser.close(),this.browser=null),{success:!0,display:"Browser closed."}}catch(e){return this.browser=null,this.page=null,{success:!1,error:`Close failed: ${e.message}`}}}}});var us,Bl=_(()=>{"use strict";B();Me();us=class extends x{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",category:"core",description:"Manage user profile settings including timezone, language, and bio. Use this to personalize Alfred for each user.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set_timezone","set_language","set_bio","set_preference"],description:"The profile action to perform"},value:{type:"string",description:"The value to set (for set_* actions)"},preference_key:{type:"string",description:"The preference key (for set_preference)"},preference_value:{type:"string",description:"The preference value (for set_preference)"}},required:["action"]}};constructor(e){super(),this.userRepo=e}async execute(e,t){let s=e.action,r=ce(t);switch(s){case"get":return this.getProfile(r);case"set_timezone":return this.setField(r,"timezone",e.value);case"set_language":return this.setField(r,"language",e.value);case"set_bio":return this.setField(r,"bio",e.value);case"set_preference":return this.setPreference(r,e.preference_key,e.preference_value);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}getProfile(e){let t=this.userRepo.getProfile(e);if(!t)return{success:!0,data:null,display:"No profile found. Set your timezone, language, or bio to create one."};let s=[];if(t.displayName&&s.push(`Name: ${t.displayName}`),t.timezone&&s.push(`Timezone: ${t.timezone}`),t.language&&s.push(`Language: ${t.language}`),t.bio&&s.push(`Bio: ${t.bio}`),t.preferences)for(let[r,n]of Object.entries(t.preferences))s.push(`${r}: ${String(n)}`);return{success:!0,data:t,display:s.length>0?`Profile:
|
|
780
780
|
${s.map(r=>`- ${r}`).join(`
|
|
781
|
-
`)}`:"Profile is empty."}}setField(e,t,s){return!s||typeof s!="string"?{success:!1,error:`Missing required "value" for ${t}`}:(this.userRepo.updateProfile(e,{[t]:s}),{success:!0,data:{[t]:s},display:`${t} set to "${s}"`})}setPreference(e,t,s){if(!t||typeof t!="string")return{success:!1,error:'Missing required "preference_key"'};let n=this.userRepo.getProfile(e)?.preferences??{};return n[t]=s,this.userRepo.updateProfile(e,{preferences:n}),{success:!0,data:{key:t,value:s},display:`Preference "${t}" set to "${s}"`}}}});var He,$r=_(()=>{"use strict";He=class{static{u(this,"CalendarProvider")}timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}});var Wl={};
|
|
781
|
+
`)}`:"Profile is empty."}}setField(e,t,s){return!s||typeof s!="string"?{success:!1,error:`Missing required "value" for ${t}`}:(this.userRepo.updateProfile(e,{[t]:s}),{success:!0,data:{[t]:s},display:`${t} set to "${s}"`})}setPreference(e,t,s){if(!t||typeof t!="string")return{success:!1,error:'Missing required "preference_key"'};let n=this.userRepo.getProfile(e)?.preferences??{};return n[t]=s,this.userRepo.updateProfile(e,{preferences:n}),{success:!0,data:{key:t,value:s},display:`Preference "${t}" set to "${s}"`}}}});var He,$r=_(()=>{"use strict";He=class{static{u(this,"CalendarProvider")}timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}});var Wl={};he(Wl,{CalDAVProvider:()=>Fn});var Fn,Di=_(()=>{"use strict";$r();Fn=class extends He{static{u(this,"CalDAVProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"caldav"})}catch(e){throw new Error(`CalDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){let s=await this.client.fetchCalendars();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchCalendarObjects({calendar:n,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of o){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.start.getTime()-o.start.getTime())}async createEvent(e){let t=await this.client.fetchCalendars();if(!t||t.length===0)throw new Error("No calendars found");let s=`alfred-${Date.now()}@alfred`,r=this.buildICalEvent(s,e);return await this.client.createCalendarObject({calendar:t[0],filename:`${s}.ics`,iCalString:r}),{id:s,title:e.title,start:e.start,end:e.end,location:e.location,description:e.description,allDay:e.allDay}}async updateEvent(e,t){let s=await this.client.fetchCalendars();for(let r of s){let n=await this.client.fetchCalendarObjects({calendar:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseICalEvent(o.data,o.url);if(!i)continue;let a={title:t.title??i.title,start:t.start??i.start,end:t.end??i.end,location:t.location??i.location,description:t.description??i.description,allDay:t.allDay??i.allDay},c=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:c}}),{id:e,...a}}}throw new Error(`Event ${e} not found`)}async deleteEvent(e){let t=await this.client.fetchCalendars();for(let s of t){let r=await this.client.fetchCalendarObjects({calendar:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:n});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
|
|
782
782
|
`).map(p=>p.trim()),r=u(p=>s.find(f=>f.startsWith(p+":"))?.slice(p.length+1),"get"),n=r("SUMMARY"),o=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),c=r("DESCRIPTION"),d=r("UID")??t;if(!n||!o)return;let m=o.length===8;return{id:d,title:n,start:this.parseICalDate(o),end:i?this.parseICalDate(i):this.parseICalDate(o),location:a||void 0,description:c||void 0,allDay:m}}catch(s){console.error("[caldav] Failed to parse iCal event",s);return}}parseICalDate(e){if(e.length===8)return new Date(`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`);let t=e.replace(/[^0-9TZ]/g,"");return t.length>=15?new Date(`${t.slice(0,4)}-${t.slice(4,6)}-${t.slice(6,8)}T${t.slice(9,11)}:${t.slice(11,13)}:${t.slice(13,15)}Z`):new Date(e)}buildICalEvent(e,t){let s=u((n,o)=>o?n.toISOString().slice(0,10).replace(/-/g,""):n.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
|
|
783
783
|
VERSION:2.0\r
|
|
784
784
|
PRODID:-//Alfred//EN\r
|
|
@@ -794,7 +794,7 @@ BEGIN:VEVENT\r
|
|
|
794
794
|
`),r+=`DTSTAMP:${s(new Date)}\r
|
|
795
795
|
`,r+=`END:VEVENT\r
|
|
796
796
|
END:VCALENDAR\r
|
|
797
|
-
`,r}}});var zl={};
|
|
797
|
+
`,r}}});var zl={};he(zl,{GoogleCalendarProvider:()=>jn});var jn,Mi=_(()=>{"use strict";$r();jn=class extends He{static{u(this,"GoogleCalendarProvider")}config;calendar;constructor(e){super(),this.config=e}async initialize(){try{let{google:e}=await import("googleapis"),t=new e.auth.OAuth2(this.config.clientId,this.config.clientSecret);t.setCredentials({refresh_token:this.config.refreshToken}),this.calendar=e.calendar({version:"v3",auth:t})}catch(e){throw new Error(`Google Calendar initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){return((await this.calendar.events.list({calendarId:"primary",timeMin:e.toISOString(),timeMax:t.toISOString(),singleEvents:!0,orderBy:"startTime"})).data.items??[]).map(r=>this.mapEvent(r))}async createEvent(e){let t={summary:e.title,location:e.location,description:e.description};e.allDay?(t.start={date:e.start.toISOString().slice(0,10)},t.end={date:e.end.toISOString().slice(0,10)}):(t.start={dateTime:e.start.toISOString()},t.end={dateTime:e.end.toISOString()});let s=await this.calendar.events.insert({calendarId:"primary",requestBody:t});return this.mapEvent(s.data)}async updateEvent(e,t){let s={};t.title&&(s.summary=t.title),t.location&&(s.location=t.location),t.description&&(s.description=t.description),t.start&&(s.start=t.allDay?{date:t.start.toISOString().slice(0,10)}:{dateTime:t.start.toISOString()}),t.end&&(s.end=t.allDay?{date:t.end.toISOString().slice(0,10)}:{dateTime:t.end.toISOString()});let r=await this.calendar.events.patch({calendarId:"primary",eventId:e,requestBody:s});return this.mapEvent(r.data)}async deleteEvent(e){await this.calendar.events.delete({calendarId:"primary",eventId:e})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){let t=!!e.start?.date;return{id:e.id,title:e.summary??"(No title)",start:new Date(e.start?.dateTime??e.start?.date),end:new Date(e.end?.dateTime??e.end?.date),location:e.location??void 0,description:e.description??void 0,allDay:t}}}});var ql={};he(ql,{MicrosoftCalendarProvider:()=>Hn});var Hn,Oi=_(()=>{"use strict";$r();Hn=class extends He{static{u(this,"MicrosoftCalendarProvider")}config;client;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Calendars.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s={Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",Prefer:'outlook.timezone="UTC"',...t.headers??{}},r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:s});if(r.status===401){await this.refreshAccessToken(),s.Authorization=`Bearer ${this.accessToken}`;let n=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:s});if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return n.json()}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);if(r.status!==204)return r.json()}async listEvents(e,t){let s=new URLSearchParams({startDateTime:e.toISOString(),endDateTime:t.toISOString(),$orderby:"start/dateTime",$top:"50"});return((await this.graphRequest(`/me/calendarView?${s}`)).value??[]).map(n=>this.mapEvent(n))}async createEvent(e){let t=this.timezone,s={subject:e.title,body:e.description?{contentType:"text",content:e.description}:void 0,location:e.location?{displayName:e.location}:void 0,isAllDay:e.allDay??!1};e.allDay?(s.start={dateTime:this.formatDateInTz(e.start,t).slice(0,10)+"T00:00:00",timeZone:t},s.end={dateTime:this.formatDateInTz(e.end,t).slice(0,10)+"T00:00:00",timeZone:t}):(s.start={dateTime:this.formatDateInTz(e.start,t),timeZone:t},s.end={dateTime:this.formatDateInTz(e.end,t),timeZone:t});let r=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(s)});return this.mapEvent(r)}async updateEvent(e,t){let s={};t.title&&(s.subject=t.title),t.description&&(s.body={contentType:"text",content:t.description}),t.location&&(s.location={displayName:t.location}),t.start&&(s.start={dateTime:this.formatDateInTz(t.start,this.timezone),timeZone:this.timezone}),t.end&&(s.end={dateTime:this.formatDateInTz(t.end,this.timezone),timeZone:this.timezone});let r=await this.graphRequest(`/me/events/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapEvent(r)}async deleteEvent(e){await this.graphRequest(`/me/events/${e}`,{method:"DELETE"})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}formatDateInTz(e,t){let s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),r=u(n=>s.find(o=>o.type===n)?.value??"00","g");return`${r("year")}-${r("month")}-${r("day")}T${r("hour")}:${r("minute")}:${r("second")}`}mapEvent(e){return{id:e.id,title:e.subject??"(No title)",start:this.parseGraphDateTime(e.start),end:this.parseGraphDateTime(e.end),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}parseGraphDateTime(e){if(!e?.dateTime)return new Date;let t=e.dateTime.replace(/(\.\d{3})\d*$/,"$1"),s=e.timeZone;return!s||s==="UTC"||s.includes("Utc")?new Date(t+"Z"):this.parseDateInTimezone(t,s)}parseDateInTimezone(e,t){let s=new Date(e+"Z"),r=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(s),n=u(a=>r.find(c=>c.type===a)?.value??"00","g"),i=new Date(`${n("year")}-${n("month")}-${n("day")}T${n("hour")}:${n("minute")}:${n("second")}Z`).getTime()-s.getTime();return new Date(s.getTime()-i)}}});async function Ir(l){switch(l.provider){case"caldav":{if(!l.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Di(),Wl)),t=new e(l.caldav);return await t.initialize(),t}case"google":{if(!l.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(Mi(),zl)),t=new e(l.google);return await t.initialize(),t}case"microsoft":{if(!l.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(Oi(),ql)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${l.provider}`)}}var Gl=_(()=>{"use strict";u(Ir,"createCalendarProvider")});var Lt,Xl=_(()=>{"use strict";B();Lt=class extends x{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",category:"productivity",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:`Start date/time in ISO 8601 format WITHOUT timezone suffix (e.g. "2026-03-09T14:00:00", NOT "2026-03-09T14:00:00Z"). Times are interpreted in the user's local timezone.`},end:{type:"string",description:`End date/time in ISO 8601 format WITHOUT timezone suffix (e.g. "2026-03-09T14:30:00"). Times are interpreted in the user's local timezone.`},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){t.timezone&&(this.calendarProvider.timezone=t.timezone);let s=e.action;switch(s){case"list_events":return this.listEvents(e);case"create_event":return this.createEvent(e);case"update_event":return this.updateEvent(e);case"delete_event":return this.deleteEvent(e);case"check_availability":return this.checkAvailability(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async getTodayEvents(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()),s=new Date(e.getFullYear(),e.getMonth(),e.getDate()+1);try{return await this.calendarProvider.listEvents(t,s)}catch(r){return console.error("[calendar] Failed to fetch today events",r),[]}}async listEvents(e){let t=e.start?new Date(e.start):new Date,s=e.end?new Date(e.end):new Date(t.getTime()+7*24*60*60*1e3);try{let r=await this.calendarProvider.listEvents(t,s);if(r.length===0)return{success:!0,data:[],display:"No events found in this time range."};let n=r.map(o=>this.formatEvent(o)).join(`
|
|
798
798
|
`);return{success:!0,data:r,display:`${r.length} event(s):
|
|
799
799
|
${n}`}}catch(r){return{success:!1,error:`Failed to list events: ${r instanceof Error?r.message:String(r)}`}}}parseLocalTime(e){return new Date(e.replace(/Z$/i,""))}async createEvent(e){let t=e.title,s=e.start,r=e.end;if(!t)return{success:!1,error:'Missing required field "title"'};if(!s)return{success:!1,error:'Missing required field "start"'};if(!r)return{success:!1,error:'Missing required field "end"'};try{let n=await this.calendarProvider.createEvent({title:t,start:this.parseLocalTime(s),end:this.parseLocalTime(r),location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:n,display:`Event created: ${this.formatEvent(n)}`}}catch(n){return{success:!1,error:`Failed to create event: ${n instanceof Error?n.message:String(n)}`}}}async updateEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{let s=await this.calendarProvider.updateEvent(t,{title:e.title,start:e.start?this.parseLocalTime(e.start):void 0,end:e.end?this.parseLocalTime(e.end):void 0,location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:s,display:`Event updated: ${this.formatEvent(s)}`}}catch(s){return{success:!1,error:`Failed to update event: ${s instanceof Error?s.message:String(s)}`}}}async deleteEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{return await this.calendarProvider.deleteEvent(t),{success:!0,data:{deleted:t},display:`Event "${t}" deleted.`}}catch(s){return{success:!1,error:`Failed to delete event: ${s instanceof Error?s.message:String(s)}`}}}async checkAvailability(e){let t=e.start,s=e.end;if(!t||!s)return{success:!1,error:'Missing required fields "start" and "end"'};try{let r=await this.calendarProvider.checkAvailability(new Date(t),new Date(s)),n=r.available?"Time slot is available.":`Time slot has ${r.conflicts.length} conflict(s):
|
|
800
800
|
${r.conflicts.map(o=>this.formatEvent(o)).join(`
|
|
@@ -832,13 +832,13 @@ ${c}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success
|
|
|
832
832
|
|
|
833
833
|
${a}`}}list(e,t){let s=e.limit||50,r=G(t),n=new Set,o=[];for(let c of r)for(let d of this.docRepo.listByUser(c))n.has(d.id)||(n.add(d.id),o.push(d));let i=o.slice(0,s);if(i.length===0)return{success:!0,data:[],display:"No documents found."};let a=i.map(c=>`- **${c.filename}** [id=${c.id}] \u2014 ${c.mimeType}, ${c.chunkCount} chunks, ${c.sizeBytes} bytes`).join(`
|
|
834
834
|
`);return{success:!0,data:i,display:`${i.length} document(s):
|
|
835
|
-
${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for delete action'};let s=this.docRepo.getDocument(t);return s?(this.docRepo.deleteDocument(t),{success:!0,data:{documentId:t},display:`Document "${s.filename}" deleted.`}):{success:!1,error:`Document "${t}" not found`}}}});var gs,rd=_(()=>{"use strict";B();gs=class extends x{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",category:"media",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});var ys,nd=_(()=>{"use strict";B();ys=class extends x{static{u(this,"ImageGenerateSkill")}generator;metadata={name:"image_generate",category:"media",description:"Generate an image from a text description. Use this tool when the user asks you to create, generate, draw, or design an image or picture. Returns the generated image that will be sent to the user.",riskLevel:"read",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{prompt:{type:"string",description:"Detailed description of the image to generate. Be specific about style, composition, colors, and subject matter."},model:{type:"string",description:"Optional model to use (e.g. gpt-image-1, gpt-image-1-mini, gemini-2.0-flash-exp). Uses provider default if omitted."},size:{type:"string",enum:["1024x1024","1536x1024","1024x1536"],description:"Image dimensions. 1024x1024 (square, default), 1536x1024 (landscape), 1024x1536 (portrait)."},quality:{type:"string",enum:["low","medium","high"],description:"Image quality level. Higher quality takes longer and costs more."}},required:["prompt"]}};constructor(e){super(),this.generator=e}async execute(e,t){let s=e.prompt;if(!s)return{success:!1,error:"No prompt provided for image generation."};try{let r=await this.generator.generate(s,{model:e.model,size:e.size,quality:e.quality});return{success:!0,display:"Image generated.",attachments:[{fileName:"image.png",data:r.data,mimeType:r.mimeType}]}}catch(r){return{success:!1,error:`Image generation failed: ${r instanceof Error?r.message:String(r)}`}}}}});function
|
|
836
|
-
`)}}async listNodes(){let e=await this.get("/nodes"),t=["## Nodes","","| Node | Status | CPU | RAM Used / Total | Uptime |"];t.push("|------|--------|-----|------------------|--------|");for(let s of e){let r=typeof s.cpu=="number"?xr(s.cpu):"-",n=
|
|
837
|
-
`)}}async nodeStats(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/status`),r=s.cpu,n=s.memory,o=s.rootfs,i=s.swap,a=[`## Node: ${t}`,"",`**Uptime:** ${Bn(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${xr(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${
|
|
838
|
-
`)}}async listVms(e,t){let s;if(e){if(s=[],!t||t==="qemu"){let n=await this.get(`/nodes/${e}/qemu`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"qemu"})}if(!t||t==="lxc"){let n=await this.get(`/nodes/${e}/lxc`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"lxc"})}}else s=await this.getAllVms(),t&&(s=s.filter(n=>n.type===t));s.sort((n,o)=>n.vmid-o.vmid);let r=["## Virtual Machines & Containers","","| VMID | Name | Type | Node | Status | CPU | RAM Used / Max | Uptime |","|------|------|------|------|--------|-----|----------------|--------|"];for(let n of s)r.push(`| ${n.vmid} | ${n.name??"-"} | ${n.type} | ${n.node} | ${n.status??"-"} | ${xr(n.cpu)} | ${
|
|
839
|
-
`)}}async vmStatus(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/status/current`),n=[`## VM ${e} (${s.type}) on ${s.node}`,"",`**Name:** ${r.name??"-"}`,`**Status:** ${r.status}`,`**CPU:** ${xr(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${
|
|
835
|
+
${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for delete action'};let s=this.docRepo.getDocument(t);return s?(this.docRepo.deleteDocument(t),{success:!0,data:{documentId:t},display:`Document "${s.filename}" deleted.`}):{success:!1,error:`Document "${t}" not found`}}}});var gs,rd=_(()=>{"use strict";B();gs=class extends x{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",category:"media",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});var ys,nd=_(()=>{"use strict";B();ys=class extends x{static{u(this,"ImageGenerateSkill")}generator;metadata={name:"image_generate",category:"media",description:"Generate an image from a text description. Use this tool when the user asks you to create, generate, draw, or design an image or picture. Returns the generated image that will be sent to the user.",riskLevel:"read",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{prompt:{type:"string",description:"Detailed description of the image to generate. Be specific about style, composition, colors, and subject matter."},model:{type:"string",description:"Optional model to use (e.g. gpt-image-1, gpt-image-1-mini, gemini-2.0-flash-exp). Uses provider default if omitted."},size:{type:"string",enum:["1024x1024","1536x1024","1024x1536"],description:"Image dimensions. 1024x1024 (square, default), 1536x1024 (landscape), 1024x1536 (portrait)."},quality:{type:"string",enum:["low","medium","high"],description:"Image quality level. Higher quality takes longer and costs more."}},required:["prompt"]}};constructor(e){super(),this.generator=e}async execute(e,t){let s=e.prompt;if(!s)return{success:!1,error:"No prompt provided for image generation."};try{let r=await this.generator.generate(s,{model:e.model,size:e.size,quality:e.quality});return{success:!0,display:"Image generated.",attachments:[{fileName:"image.png",data:r.data,mimeType:r.mimeType}]}}catch(r){return{success:!1,error:`Image generation failed: ${r instanceof Error?r.message:String(r)}`}}}}});function fe(l){return l==null?"-":l<1024?`${l} B`:l<1024**2?`${(l/1024).toFixed(1)} KiB`:l<1024**3?`${(l/1024**2).toFixed(1)} MiB`:`${(l/1024**3).toFixed(2)} GiB`}function xr(l){return l==null?"-":`${(l*100).toFixed(1)}%`}function Bn(l){if(!l)return"-";let e=Math.floor(l/86400),t=Math.floor(l%86400/3600),s=Math.floor(l%3600/60),r=[];return e&&r.push(`${e}d`),t&&r.push(`${t}h`),r.push(`${s}m`),r.join(" ")}var Wn,od=_(()=>{"use strict";B();u(fe,"bytes");u(xr,"pct");u(Bn,"uptimeStr");Wn=class l extends x{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",category:"infrastructure",description:'Manage Proxmox VE virtual machines, containers, and cluster. Use action "list_vms" to see VMs, "start_vm"/"shutdown_vm" to control them, "cluster_status" for health, "create_snapshot" for backups.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["cluster_status","list_nodes","node_stats","list_vms","vm_status","list_snapshots","list_storage","list_tasks","task_status","start_vm","shutdown_vm","reboot_vm","suspend_vm","resume_vm","create_snapshot","backup_vm","migrate_vm","stop_vm","delete_snapshot","rollback_snapshot"],description:"The Proxmox action to perform"},vmid:{type:"number",description:"Virtual machine / container ID"},node:{type:"string",description:"Proxmox node name (optional \u2014 resolved automatically when omitted)"},type:{type:"string",enum:["qemu","lxc"],description:"VM type filter for list_vms (default: both)"},name:{type:"string",description:"Snapshot name (for create/delete/rollback_snapshot)"},description:{type:"string",description:"Snapshot description (optional)"},target:{type:"string",description:"Target node for migration"},storage:{type:"string",description:"Storage target for backup_vm"},upid:{type:"string",description:"Task UPID for task_status"}},required:["action"]}};config;vmCache=null;static VM_CACHE_TTL=3e4;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"cluster_status":return await this.clusterStatus();case"list_nodes":return await this.listNodes();case"node_stats":return await this.nodeStats(e.node);case"list_vms":return await this.listVms(e.node,e.type);case"vm_status":return await this.vmStatus(e.vmid,e.node);case"list_snapshots":return await this.listSnapshots(e.vmid,e.node);case"list_storage":return await this.listStorage(e.node);case"list_tasks":return await this.listTasks(e.node);case"task_status":return await this.taskStatus(e.upid);case"start_vm":return await this.vmPowerAction("start",e);case"shutdown_vm":return await this.vmPowerAction("shutdown",e);case"reboot_vm":return await this.vmPowerAction("reboot",e);case"suspend_vm":return await this.vmPowerAction("suspend",e);case"resume_vm":return await this.vmPowerAction("resume",e);case"stop_vm":return await this.vmPowerAction("stop",e);case"create_snapshot":return await this.createSnapshot(e);case"backup_vm":return await this.backupVm(e);case"migrate_vm":return await this.migrateVm(e);case"delete_snapshot":return await this.deleteSnapshot(e);case"rollback_snapshot":return await this.rollbackSnapshot(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Proxmox API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl}/api2/json${t}`,n={Authorization:`PVEAPIToken=${this.config.tokenId}=${this.config.tokenSecret}`},o={method:e,headers:n};s&&e!=="GET"&&(n["Content-Type"]="application/json",o.body=JSON.stringify(s));let i=this.config.verifyTls===!1,a=process.env.NODE_TLS_REJECT_UNAUTHORIZED;i&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let c;try{c=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!c.ok){let m="";try{m=(await c.text()).slice(0,500)}catch{}throw new Error(`HTTP ${c.status} ${c.statusText} \u2014 ${m}`)}return(await c.json()).data}async get(e){return this.api("GET",e)}async post(e,t){return this.api("POST",e,t)}async del(e){return this.api("DELETE",e)}async resolveVm(e,t){if(t)try{return await this.get(`/nodes/${t}/qemu/${e}/status/current`),{node:t,type:"qemu"}}catch{try{return await this.get(`/nodes/${t}/lxc/${e}/status/current`),{node:t,type:"lxc"}}catch{throw new Error(`VM ${e} not found on node "${t}"`)}}let r=(await this.getAllVms()).find(n=>n.vmid===e);if(!r)throw new Error(`VM ${e} not found on any node. Use "list_vms" to see available VMs.`);return{node:r.node,type:r.type}}async getAllVms(){let e=Date.now();if(this.vmCache&&e-this.vmCache.ts<l.VM_CACHE_TTL)return this.vmCache.entries;let t=await this.get("/nodes"),s=[];for(let r of t){let[n,o]=await Promise.all([this.get(`/nodes/${r.node}/qemu`).catch(()=>[]),this.get(`/nodes/${r.node}/lxc`).catch(()=>[])]);for(let i of n)s.push({...i,node:r.node,type:"qemu"});for(let i of o)s.push({...i,node:r.node,type:"lxc"})}return this.vmCache={entries:s,ts:e},s}async clusterStatus(){let e=await this.get("/cluster/status"),t=["## Cluster Status",""],s=e.find(n=>n.type==="cluster");s&&(t.push(`**Cluster:** ${s.name}`),t.push(`**Quorum:** ${s.quorate?"Yes":"No"}`),t.push(`**Nodes:** ${s.nodes??"-"}`),t.push(`**Version:** ${s.version??"-"}`),t.push(""));let r=e.filter(n=>n.type==="node");if(r.length){t.push("| Node | Online | Level | ID |"),t.push("|------|--------|-------|----|");for(let n of r)t.push(`| ${n.name} | ${n.online?"Yes":"**No**"} | ${n.level??"-"} | ${n.nodeid??"-"} |`)}return{success:!0,data:e,display:t.join(`
|
|
836
|
+
`)}}async listNodes(){let e=await this.get("/nodes"),t=["## Nodes","","| Node | Status | CPU | RAM Used / Total | Uptime |"];t.push("|------|--------|-----|------------------|--------|");for(let s of e){let r=typeof s.cpu=="number"?xr(s.cpu):"-",n=fe(s.mem),o=fe(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${Bn(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
|
|
837
|
+
`)}}async nodeStats(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/status`),r=s.cpu,n=s.memory,o=s.rootfs,i=s.swap,a=[`## Node: ${t}`,"",`**Uptime:** ${Bn(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${xr(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${fe(n.used)} / ${fe(n.total)} (${xr(n.used/n.total)})`),i&&a.push(`**Swap:** ${fe(i.used)} / ${fe(i.total)}`),o&&a.push(`**Root FS:** ${fe(o.used)} / ${fe(o.total)}`),{success:!0,data:s,display:a.join(`
|
|
838
|
+
`)}}async listVms(e,t){let s;if(e){if(s=[],!t||t==="qemu"){let n=await this.get(`/nodes/${e}/qemu`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"qemu"})}if(!t||t==="lxc"){let n=await this.get(`/nodes/${e}/lxc`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"lxc"})}}else s=await this.getAllVms(),t&&(s=s.filter(n=>n.type===t));s.sort((n,o)=>n.vmid-o.vmid);let r=["## Virtual Machines & Containers","","| VMID | Name | Type | Node | Status | CPU | RAM Used / Max | Uptime |","|------|------|------|------|--------|-----|----------------|--------|"];for(let n of s)r.push(`| ${n.vmid} | ${n.name??"-"} | ${n.type} | ${n.node} | ${n.status??"-"} | ${xr(n.cpu)} | ${fe(n.mem)} / ${fe(n.maxmem)} | ${Bn(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
|
|
839
|
+
`)}}async vmStatus(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/status/current`),n=[`## VM ${e} (${s.type}) on ${s.node}`,"",`**Name:** ${r.name??"-"}`,`**Status:** ${r.status}`,`**CPU:** ${xr(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${fe(r.mem)} / ${fe(r.maxmem)}`,`**Disk:** ${fe(r.disk)} / ${fe(r.maxdisk)}`,`**Uptime:** ${Bn(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${fe(r.netin)} / ${fe(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
|
|
840
840
|
`)}}async listSnapshots(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/snapshot`),n=[`## Snapshots for VM ${e}`,"","| Name | Description | Date | Parent |","|------|-------------|------|--------|"];for(let o of r){let i=o.snaptime?new Date(o.snaptime*1e3).toISOString():"-";n.push(`| ${o.name} | ${o.description??"-"} | ${i} | ${o.parent??"-"} |`)}return{success:!0,data:r,display:n.join(`
|
|
841
|
-
`)}}async listStorage(e){let t=e??this.config.defaultNode,s=t?`/nodes/${t}/storage`:"/storage",r=await this.get(s),n=[`## Storage${t?` (Node: ${t})`:""}`,"","| Storage | Type | Content | Used / Total | Status |","|---------|------|---------|--------------|--------|"];for(let o of r){let i=
|
|
841
|
+
`)}}async listStorage(e){let t=e??this.config.defaultNode,s=t?`/nodes/${t}/storage`:"/storage",r=await this.get(s),n=[`## Storage${t?` (Node: ${t})`:""}`,"","| Storage | Type | Content | Used / Total | Status |","|---------|------|---------|--------------|--------|"];for(let o of r){let i=fe(o.used),a=fe(o.total);n.push(`| ${o.storage} | ${o.type} | ${o.content??"-"} | ${i} / ${a} | ${o.active?"active":o.enabled?"enabled":"disabled"} |`)}return{success:!0,data:r,display:n.join(`
|
|
842
842
|
`)}}async listTasks(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/tasks?limit=20`),r=[`## Recent Tasks (Node: ${t})`,"","| UPID | Type | Status | Start | User |","|------|------|--------|-------|------|"];for(let n of s){let o=n.starttime?new Date(n.starttime*1e3).toISOString():"-";r.push(`| \`${n.upid?.slice(-16)??"-"}\` | ${n.type??"-"} | ${n.status??"running"} | ${o} | ${n.user??"-"} |`)}return{success:!0,data:s,display:r.join(`
|
|
843
843
|
`)}}async taskStatus(e){if(!e)return{success:!1,error:'Missing required "upid" parameter'};let t=e.split(":")[1];if(!t)return{success:!1,error:"Invalid UPID format \u2014 cannot extract node"};let s=await this.get(`/nodes/${t}/tasks/${encodeURIComponent(e)}/status`),r=["## Task Status","",`**UPID:** \`${e}\``,`**Status:** ${s.status}`,`**Type:** ${s.type??"-"}`,`**Exit Status:** ${s.exitstatus??"running"}`,`**Node:** ${t}`];return{success:!0,data:s,display:r.join(`
|
|
844
844
|
`)}}async vmPowerAction(e,t){let s=t.vmid;if(s==null)return{success:!1,error:'Missing required "vmid" parameter'};let r=await this.resolveVm(s,t.node),n=await this.post(`/nodes/${r.node}/${r.type}/${s}/status/${e}`);return{success:!0,data:{vmid:s,node:r.node,type:r.type,action:e,upid:n},display:[`**${e.charAt(0).toUpperCase()+e.slice(1)}** sent to VM ${s} (${r.type}) on **${r.node}**.`,"",`UPID: \`${n}\``,"","Use `task_status` with this UPID to check progress."].join(`
|
|
@@ -893,7 +893,7 @@ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this
|
|
|
893
893
|
`)}}async getEnergyStatsViaTemplate(e,t,s,r){let n=[`## Energie-Sensoren: ${r}`,"","*Hinweis: F\xFCr diesen Zeitraum sind keine History-Daten verf\xFCgbar. Zeige aktuelle Z\xE4hlerst\xE4nde.*","","| Sensor | Aktueller Stand | Einheit |","|--------|----------------|---------|"];for(let o of e)try{let i=await this.api("GET",`/api/states/${o}`),a=i.attributes?.friendly_name??o,c=i.attributes?.unit_of_measurement??"",d=i.state;n.push(`| ${a} | ${d} | ${c} |`)}catch{n.push(`| ${o} | Fehler | - |`)}return{success:!0,data:[],display:n.join(`
|
|
894
894
|
`)}}parseEnergyPeriod(e){let t=new Date;switch(e.toLowerCase().replace(/\s+/g,"_")){case"today":case"heute":return{start:new Date(t.getFullYear(),t.getMonth(),t.getDate()).toISOString(),end:t.toISOString(),label:"Heute"};case"yesterday":case"gestern":{let s=new Date(t.getFullYear(),t.getMonth(),t.getDate()-1),r=new Date(t.getFullYear(),t.getMonth(),t.getDate());return{start:s.toISOString(),end:r.toISOString(),label:"Gestern"}}case"this_week":case"diese_woche":{let s=t.getDay(),r=s===0?-6:1-s;return{start:new Date(t.getFullYear(),t.getMonth(),t.getDate()+r).toISOString(),end:t.toISOString(),label:"Diese Woche"}}case"last_week":case"letzte_woche":{let s=t.getDay(),r=s===0?-6:1-s,n=new Date(t.getFullYear(),t.getMonth(),t.getDate()+r);return{start:new Date(n.getTime()-7*864e5).toISOString(),end:n.toISOString(),label:"Letzte Woche"}}case"this_month":case"dieser_monat":return{start:new Date(t.getFullYear(),t.getMonth(),1).toISOString(),end:t.toISOString(),label:"Dieser Monat"};case"last_month":case"letzter_monat":{let s=new Date(t.getFullYear(),t.getMonth()-1,1),r=new Date(t.getFullYear(),t.getMonth(),1);return{start:s.toISOString(),end:r.toISOString(),label:"Letzter Monat"}}default:return{start:ji(e),end:t.toISOString(),label:e}}}async createConfig(e,t,s){if(!t)return{success:!1,error:`Missing required "configId" for create_${e}`};if(!s)return{success:!1,error:`Missing required "configData" for create_${e}`};let r;try{r=JSON.parse(s)}catch{return{success:!1,error:'Invalid "configData" \u2014 must be valid JSON'}}return{success:!0,data:await this.apiPost(`/api/config/${e}/config/${t}`,r),display:`**${e} created:** \`${t}\`
|
|
895
895
|
|
|
896
|
-
${r.alias??r.name??t}`}}async deleteConfig(e,t){return t?(await this.apiDelete(`/api/config/${e}/config/${t}`),{success:!0,data:{deleted:t},display:`**${e} deleted:** \`${t}\``}):{success:!1,error:`Missing required "configId" for delete_${e}`}}async apiPost(e,t){let s=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,r={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n=this.config.verifyTls===!1,o=process.env.NODE_TLS_REJECT_UNAUTHORIZED;n&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let i;try{i=await fetch(s,{method:"POST",headers:r,body:JSON.stringify(t),signal:AbortSignal.timeout(15e3)})}finally{n&&(o===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}if(!i.ok){let a="";try{a=(await i.text()).slice(0,500)}catch{}throw new Error(`HTTP ${i.status} ${i.statusText} \u2014 ${a}`)}return await i.json()}async apiDelete(e){let t=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,s={Authorization:`Bearer ${this.config.accessToken}`},r=this.config.verifyTls===!1,n=process.env.NODE_TLS_REJECT_UNAUTHORIZED;r&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let o;try{o=await fetch(t,{method:"DELETE",headers:s,signal:AbortSignal.timeout(15e3)})}finally{r&&(n===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=n)}if(!o.ok){let i="";try{i=(await o.text()).slice(0,500)}catch{}throw new Error(`HTTP ${o.status} ${o.statusText} \u2014 ${i}`)}}}});var ze,Cr=_(()=>{"use strict";ze=class{static{u(this,"ContactsProvider")}}});var cd={};
|
|
896
|
+
${r.alias??r.name??t}`}}async deleteConfig(e,t){return t?(await this.apiDelete(`/api/config/${e}/config/${t}`),{success:!0,data:{deleted:t},display:`**${e} deleted:** \`${t}\``}):{success:!1,error:`Missing required "configId" for delete_${e}`}}async apiPost(e,t){let s=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,r={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n=this.config.verifyTls===!1,o=process.env.NODE_TLS_REJECT_UNAUTHORIZED;n&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let i;try{i=await fetch(s,{method:"POST",headers:r,body:JSON.stringify(t),signal:AbortSignal.timeout(15e3)})}finally{n&&(o===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}if(!i.ok){let a="";try{a=(await i.text()).slice(0,500)}catch{}throw new Error(`HTTP ${i.status} ${i.statusText} \u2014 ${a}`)}return await i.json()}async apiDelete(e){let t=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,s={Authorization:`Bearer ${this.config.accessToken}`},r=this.config.verifyTls===!1,n=process.env.NODE_TLS_REJECT_UNAUTHORIZED;r&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let o;try{o=await fetch(t,{method:"DELETE",headers:s,signal:AbortSignal.timeout(15e3)})}finally{r&&(n===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=n)}if(!o.ok){let i="";try{i=(await o.text()).slice(0,500)}catch{}throw new Error(`HTTP ${o.status} ${o.statusText} \u2014 ${i}`)}}}});var ze,Cr=_(()=>{"use strict";ze=class{static{u(this,"ContactsProvider")}}});var cd={};he(cd,{CardDAVContactsProvider:()=>Gn});var Gn,Hi=_(()=>{"use strict";Cr();Gn=class extends ze{static{u(this,"CardDAVContactsProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"carddav"})}catch(e){throw new Error(`CardDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async list(e,t){let s=await this.client.fetchAddressBooks();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchVCards({addressBook:n});for(let i of o){let a=this.parseVCard(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.displayName.localeCompare(o.displayName)),e?r.slice(0,e):r}async search(e){let t=await this.list(),s=e.toLowerCase();return t.filter(r=>r.displayName.toLowerCase().includes(s)||r.emails.some(n=>n.address.toLowerCase().includes(s))||r.phones.some(n=>n.number.includes(s)))}async get(e){return(await this.list()).find(s=>s.id===e)}async create(e){let t=await this.client.fetchAddressBooks();if(!t||t.length===0)throw new Error("No address books found");let s=`alfred-${Date.now()}@alfred`,r=this.buildVCard(s,e);await this.client.createVCard({addressBook:t[0],filename:`${s}.vcf`,vCardString:r});let n=e.displayName??([e.firstName,e.lastName].filter(Boolean).join(" ")||"Unknown");return{id:s,displayName:n,firstName:e.firstName,lastName:e.lastName,emails:e.emails??[],phones:e.phones??[],addresses:e.addresses??[],organization:e.organization,birthday:e.birthday,notes:e.notes}}async update(e,t){let s=await this.client.fetchAddressBooks();for(let r of s){let n=await this.client.fetchVCards({addressBook:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseVCard(o.data,o.url);if(!i)continue;let a={firstName:t.firstName??i.firstName,lastName:t.lastName??i.lastName,displayName:t.displayName??i.displayName,emails:t.emails??i.emails,phones:t.phones??i.phones,addresses:t.addresses??i.addresses,organization:t.organization??i.organization,birthday:t.birthday??i.birthday,notes:t.notes??i.notes},c=this.buildVCard(e,a);await this.client.updateVCard({vCard:{...o,data:c}});let d=a.displayName??([a.firstName,a.lastName].filter(Boolean).join(" ")||"Unknown");return{id:e,displayName:d,firstName:a.firstName,lastName:a.lastName,emails:a.emails??[],phones:a.phones??[],addresses:a.addresses??[],organization:a.organization,birthday:a.birthday,notes:a.notes}}}throw new Error(`Contact ${e} not found`)}async delete(e){let t=await this.client.fetchAddressBooks();for(let s of t){let r=await this.client.fetchVCards({addressBook:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteVCard({vCard:n});return}}throw new Error(`Contact ${e} not found`)}parseVCard(e,t){let s=u(h=>e.match(new RegExp(`^${h}[;:](.*)$`,"mi"))?.[1]?.trim(),"get"),r=s("FN");if(!r)return;let n=s("N"),[o,i]=n?n.split(";"):[void 0,void 0],a=[];for(let h of e.matchAll(/^EMAIL[^:]*:(.+)$/gmi)){let y=h[0],k=h[1].trim(),S=y.match(/TYPE=([^;:,]+)/i)?.[1],b=/TYPE=pref/i.test(y);a.push({address:k,label:S,primary:b})}let c=[];for(let h of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let y=h[0],k=h[1].trim(),S=y.match(/TYPE=([^;:,]+)/i)?.[1],b=/TYPE=pref/i.test(y);c.push({number:k,label:S,primary:b})}let d=[];for(let h of e.matchAll(/^ADR[^:]*:(.+)$/gmi)){let y=h[1].split(";");d.push({street:y[2]?.trim()||void 0,city:y[3]?.trim()||void 0,region:y[4]?.trim()||void 0,postalCode:y[5]?.trim()||void 0,country:y[6]?.trim()||void 0})}let m=s("ORG")?.replace(/;.*$/,""),p=s("BDAY"),f=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:o,emails:a,phones:c,addresses:d,organization:m,birthday:p,notes:f}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
|
|
897
897
|
VERSION:3.0\r
|
|
898
898
|
`;r+=`UID:${e}\r
|
|
899
899
|
`,r+=`FN:${s}\r
|
|
@@ -905,7 +905,7 @@ VERSION:3.0\r
|
|
|
905
905
|
`),t.birthday&&(r+=`BDAY:${t.birthday}\r
|
|
906
906
|
`),t.notes&&(r+=`NOTE:${t.notes}\r
|
|
907
907
|
`),r+=`END:VCARD\r
|
|
908
|
-
`,r}}});var ld={};pe(ld,{GoogleContactsProvider:()=>Vn});var Xn,Ut,Vn,Bi=_(()=>{"use strict";Cr();Xn="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",Ut="https://people.googleapis.com/v1",Vn=class extends ze{static{u(this,"GoogleContactsProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token"}),t=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()});if(!t.ok)throw new Error(`Google token refresh failed: ${t.status}`);let s=await t.json();this.accessToken=s.access_token}async apiRequest(e,t,s){let r={method:e,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}};s&&(r.body=JSON.stringify(s));let n=await fetch(t,r);if(n.status===401){await this.refreshAccessToken();let o=await fetch(t,{...r,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}});if(!o.ok)throw new Error(`People API error: ${o.status}`);return o.status===204?void 0:o.json()}if(!n.ok)throw new Error(`People API error: ${n.status}`);if(n.status!==204)return n.json()}async list(e=50){let t=`${Ut}/people/me/connections?personFields=${Xn}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${Ut}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${Xn}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${Ut}/${e}?personFields=${Xn}`,s=await this.apiRequest("GET",t);return this.mapPerson(s)}catch{return}}async create(e){let t=this.buildPersonBody(e),s=await this.apiRequest("POST",`${Ut}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${Ut}/${e}?personFields=${Xn}`),r=this.buildPersonBody(t);r.etag=s.etag;let o=`${Ut}/${e}:updateContact?updatePersonFields=names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies`,i=await this.apiRequest("PATCH",o,r);return this.mapPerson(i)}async delete(e){await this.apiRequest("DELETE",`${Ut}/${e}:deleteContact`)}mapPerson(e){let t=e.names?.[0],s=(e.emailAddresses??[]).map(c=>({address:c.value,label:c.type,primary:c.metadata?.primary??!1})),r=(e.phoneNumbers??[]).map(c=>({number:c.value,label:c.type,primary:c.metadata?.primary??!1})),n=(e.addresses??[]).map(c=>({street:c.streetAddress??void 0,city:c.city??void 0,region:c.region??void 0,postalCode:c.postalCode??void 0,country:c.country??void 0,label:c.type??void 0})),o=e.organizations?.[0]?.name,i=e.birthdays?.[0]?.date?`${e.birthdays[0].date.year??"????"}-${String(e.birthdays[0].date.month).padStart(2,"0")}-${String(e.birthdays[0].date.day).padStart(2,"0")}`:void 0,a=e.biographies?.[0]?.value;return{id:e.resourceName??e.etag??"",displayName:t?.displayName??"(No name)",firstName:t?.givenName,lastName:t?.familyName,emails:s,phones:r,addresses:n,organization:o,birthday:i,notes:a}}buildPersonBody(e){let t={};if((e.firstName!==void 0||e.lastName!==void 0||e.displayName!==void 0)&&(t.names=[{givenName:e.firstName,familyName:e.lastName,displayName:e.displayName}]),e.emails&&(t.emailAddresses=e.emails.map(s=>({value:s.address,type:s.label??"home"}))),e.phones&&(t.phoneNumbers=e.phones.map(s=>({value:s.number,type:s.label??"mobile"}))),e.addresses&&(t.addresses=e.addresses.map(s=>({streetAddress:s.street,city:s.city,region:s.region,postalCode:s.postalCode,country:s.country,type:s.label??"home"}))),e.organization&&(t.organizations=[{name:e.organization}]),e.birthday){let s=e.birthday.split("-");t.birthdays=[{date:{year:s[0]!=="????"?parseInt(s[0],10):void 0,month:parseInt(s[1],10),day:parseInt(s[2],10)}}]}return e.notes&&(t.biographies=[{value:e.notes,contentType:"TEXT_PLAIN"}]),t}}});var dd={};pe(dd,{MicrosoftContactsProvider:()=>Kn});var Kn,Wi=_(()=>{"use strict";Cr();Kn=class extends ze{static{u(this,"MicrosoftContactsProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Contacts.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.status===204?void 0:r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async list(e=50){return((await this.graphRequest(`/me/contacts?$top=${e}&$orderby=displayName`)).value??[]).map(s=>this.mapContact(s))}async search(e){try{return((await this.graphRequest(`/me/contacts?$search="${encodeURIComponent(e)}"`,{headers:{ConsistencyLevel:"eventual"}})).value??[]).map(s=>this.mapContact(s))}catch{return((await this.graphRequest(`/me/contacts?$filter=contains(displayName, '${encodeURIComponent(e)}')`)).value??[]).map(s=>this.mapContact(s))}}async get(e){try{let t=await this.graphRequest(`/me/contacts/${e}`);return this.mapContact(t)}catch{return}}async create(e){let t=this.buildContactBody(e),s=await this.graphRequest("/me/contacts",{method:"POST",body:JSON.stringify(t)});return this.mapContact(s)}async update(e,t){let s=this.buildContactBody(t),r=await this.graphRequest(`/me/contacts/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapContact(r)}async delete(e){await this.graphRequest(`/me/contacts/${e}`,{method:"DELETE"})}mapContact(e){let t=(e.emailAddresses??[]).map(o=>({address:o.address,label:o.name??void 0,primary:!1})),s=[];if(e.mobilePhone&&s.push({number:e.mobilePhone,label:"mobile"}),e.businessPhones)for(let o of e.businessPhones)s.push({number:o,label:"work"});if(e.homePhones)for(let o of e.homePhones)s.push({number:o,label:"home"});let r=[];e.homeAddress&&Object.values(e.homeAddress).some(Boolean)&&r.push({street:e.homeAddress.street??void 0,city:e.homeAddress.city??void 0,region:e.homeAddress.state??void 0,postalCode:e.homeAddress.postalCode??void 0,country:e.homeAddress.countryOrRegion??void 0,label:"home"}),e.businessAddress&&Object.values(e.businessAddress).some(Boolean)&&r.push({street:e.businessAddress.street??void 0,city:e.businessAddress.city??void 0,region:e.businessAddress.state??void 0,postalCode:e.businessAddress.postalCode??void 0,country:e.businessAddress.countryOrRegion??void 0,label:"work"});let n=e.birthday?e.birthday.slice(0,10):void 0;return{id:e.id,displayName:e.displayName??"(No name)",firstName:e.givenName??void 0,lastName:e.surname??void 0,emails:t,phones:s,addresses:r,organization:e.companyName??void 0,birthday:n,notes:e.personalNotes??void 0}}buildContactBody(e){let t={};if(e.firstName!==void 0&&(t.givenName=e.firstName),e.lastName!==void 0&&(t.surname=e.lastName),e.displayName!==void 0&&(t.displayName=e.displayName),e.emails&&(t.emailAddresses=e.emails.map(s=>({address:s.address,name:s.label??s.address}))),e.phones){let s=e.phones.find(i=>i.label==="mobile"),r=e.phones.filter(i=>i.label==="work"),n=e.phones.filter(i=>i.label==="home"),o=e.phones.filter(i=>!["mobile","work","home"].includes(i.label??""));s&&(t.mobilePhone=s.number),r.length>0&&(t.businessPhones=r.map(i=>i.number)),n.length>0&&(t.homePhones=n.map(i=>i.number)),o.length>0&&!r.length&&(t.businessPhones=o.map(i=>i.number))}if(e.addresses)for(let s of e.addresses){let r={street:s.street,city:s.city,state:s.region,postalCode:s.postalCode,countryOrRegion:s.country};s.label==="work"?t.businessAddress=r:t.homeAddress=r}return e.organization!==void 0&&(t.companyName=e.organization),e.birthday!==void 0&&(t.birthday=e.birthday),e.notes!==void 0&&(t.personalNotes=e.notes),t}}});async function zi(l){switch(l.provider){case"carddav":{if(!l.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(Hi(),cd)),t=new e(l.carddav);return await t.initialize(),t}case"google":{if(!l.google)throw new Error("Google contacts config missing");let{GoogleContactsProvider:e}=await Promise.resolve().then(()=>(Bi(),ld)),t=new e(l.google);return await t.initialize(),t}case"microsoft":{if(!l.microsoft)throw new Error("Microsoft contacts config missing");let{MicrosoftContactsProvider:e}=await Promise.resolve().then(()=>(Wi(),dd)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${l.provider}`)}}var ud=_(()=>{"use strict";u(zi,"createContactsProvider")});var Nr,md=_(()=>{"use strict";B();Nr=class extends x{static{u(this,"ContactsSkill")}contactsProvider;metadata={name:"contacts",category:"productivity",description:"Manage contacts. Search, view, create, update, or delete contacts.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["search","get","list","create","update","delete"],description:"The contacts action to perform"},query:{type:"string",description:"Search query (for search action)"},contactId:{type:"string",description:"Contact ID (for get/update/delete)"},firstName:{type:"string",description:"First name (for create/update)"},lastName:{type:"string",description:"Last name (for create/update)"},displayName:{type:"string",description:"Display name (for create/update)"},email:{type:"string",description:"Single email address (for create/update, shorthand)"},phone:{type:"string",description:"Single phone number (for create/update, shorthand)"},organization:{type:"string",description:"Organization / company (for create/update)"},birthday:{type:"string",description:"Birthday in YYYY-MM-DD format (for create/update)"},notes:{type:"string",description:"Notes (for create/update)"},emailAddresses:{type:"string",description:"JSON array of {address, label?, primary?} for multiple emails"},phoneNumbers:{type:"string",description:"JSON array of {number, label?, primary?} for multiple phones"},addresses:{type:"string",description:"JSON array of {street?, city?, region?, postalCode?, country?, label?}"},limit:{type:"number",description:"Maximum number of contacts to return (for list, default 50)"}},required:["action"]}};constructor(e){super(),this.contactsProvider=e}async execute(e,t){let s=e.action;switch(s){case"search":return this.searchContacts(e);case"get":return this.getContact(e);case"list":return this.listContacts(e);case"create":return this.createContact(e);case"update":return this.updateContact(e);case"delete":return this.deleteContact(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async searchContacts(e){let t=e.query;if(!t)return{success:!1,error:'Missing required field "query"'};try{let s=await this.contactsProvider.search(t);if(s.length===0)return{success:!0,data:[],display:`No contacts found for "${t}".`};let r=this.formatTable(s);return{success:!0,data:s,display:`${s.length} contact(s) found:
|
|
908
|
+
`,r}}});var ld={};he(ld,{GoogleContactsProvider:()=>Vn});var Xn,Ut,Vn,Bi=_(()=>{"use strict";Cr();Xn="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",Ut="https://people.googleapis.com/v1",Vn=class extends ze{static{u(this,"GoogleContactsProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token"}),t=await fetch("https://oauth2.googleapis.com/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()});if(!t.ok)throw new Error(`Google token refresh failed: ${t.status}`);let s=await t.json();this.accessToken=s.access_token}async apiRequest(e,t,s){let r={method:e,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}};s&&(r.body=JSON.stringify(s));let n=await fetch(t,r);if(n.status===401){await this.refreshAccessToken();let o=await fetch(t,{...r,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}});if(!o.ok)throw new Error(`People API error: ${o.status}`);return o.status===204?void 0:o.json()}if(!n.ok)throw new Error(`People API error: ${n.status}`);if(n.status!==204)return n.json()}async list(e=50){let t=`${Ut}/people/me/connections?personFields=${Xn}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${Ut}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${Xn}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${Ut}/${e}?personFields=${Xn}`,s=await this.apiRequest("GET",t);return this.mapPerson(s)}catch{return}}async create(e){let t=this.buildPersonBody(e),s=await this.apiRequest("POST",`${Ut}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${Ut}/${e}?personFields=${Xn}`),r=this.buildPersonBody(t);r.etag=s.etag;let o=`${Ut}/${e}:updateContact?updatePersonFields=names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies`,i=await this.apiRequest("PATCH",o,r);return this.mapPerson(i)}async delete(e){await this.apiRequest("DELETE",`${Ut}/${e}:deleteContact`)}mapPerson(e){let t=e.names?.[0],s=(e.emailAddresses??[]).map(c=>({address:c.value,label:c.type,primary:c.metadata?.primary??!1})),r=(e.phoneNumbers??[]).map(c=>({number:c.value,label:c.type,primary:c.metadata?.primary??!1})),n=(e.addresses??[]).map(c=>({street:c.streetAddress??void 0,city:c.city??void 0,region:c.region??void 0,postalCode:c.postalCode??void 0,country:c.country??void 0,label:c.type??void 0})),o=e.organizations?.[0]?.name,i=e.birthdays?.[0]?.date?`${e.birthdays[0].date.year??"????"}-${String(e.birthdays[0].date.month).padStart(2,"0")}-${String(e.birthdays[0].date.day).padStart(2,"0")}`:void 0,a=e.biographies?.[0]?.value;return{id:e.resourceName??e.etag??"",displayName:t?.displayName??"(No name)",firstName:t?.givenName,lastName:t?.familyName,emails:s,phones:r,addresses:n,organization:o,birthday:i,notes:a}}buildPersonBody(e){let t={};if((e.firstName!==void 0||e.lastName!==void 0||e.displayName!==void 0)&&(t.names=[{givenName:e.firstName,familyName:e.lastName,displayName:e.displayName}]),e.emails&&(t.emailAddresses=e.emails.map(s=>({value:s.address,type:s.label??"home"}))),e.phones&&(t.phoneNumbers=e.phones.map(s=>({value:s.number,type:s.label??"mobile"}))),e.addresses&&(t.addresses=e.addresses.map(s=>({streetAddress:s.street,city:s.city,region:s.region,postalCode:s.postalCode,country:s.country,type:s.label??"home"}))),e.organization&&(t.organizations=[{name:e.organization}]),e.birthday){let s=e.birthday.split("-");t.birthdays=[{date:{year:s[0]!=="????"?parseInt(s[0],10):void 0,month:parseInt(s[1],10),day:parseInt(s[2],10)}}]}return e.notes&&(t.biographies=[{value:e.notes,contentType:"TEXT_PLAIN"}]),t}}});var dd={};he(dd,{MicrosoftContactsProvider:()=>Kn});var Kn,Wi=_(()=>{"use strict";Cr();Kn=class extends ze{static{u(this,"MicrosoftContactsProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Contacts.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.status===204?void 0:r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async list(e=50){return((await this.graphRequest(`/me/contacts?$top=${e}&$orderby=displayName`)).value??[]).map(s=>this.mapContact(s))}async search(e){try{return((await this.graphRequest(`/me/contacts?$search="${encodeURIComponent(e)}"`,{headers:{ConsistencyLevel:"eventual"}})).value??[]).map(s=>this.mapContact(s))}catch{return((await this.graphRequest(`/me/contacts?$filter=contains(displayName, '${encodeURIComponent(e)}')`)).value??[]).map(s=>this.mapContact(s))}}async get(e){try{let t=await this.graphRequest(`/me/contacts/${e}`);return this.mapContact(t)}catch{return}}async create(e){let t=this.buildContactBody(e),s=await this.graphRequest("/me/contacts",{method:"POST",body:JSON.stringify(t)});return this.mapContact(s)}async update(e,t){let s=this.buildContactBody(t),r=await this.graphRequest(`/me/contacts/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapContact(r)}async delete(e){await this.graphRequest(`/me/contacts/${e}`,{method:"DELETE"})}mapContact(e){let t=(e.emailAddresses??[]).map(o=>({address:o.address,label:o.name??void 0,primary:!1})),s=[];if(e.mobilePhone&&s.push({number:e.mobilePhone,label:"mobile"}),e.businessPhones)for(let o of e.businessPhones)s.push({number:o,label:"work"});if(e.homePhones)for(let o of e.homePhones)s.push({number:o,label:"home"});let r=[];e.homeAddress&&Object.values(e.homeAddress).some(Boolean)&&r.push({street:e.homeAddress.street??void 0,city:e.homeAddress.city??void 0,region:e.homeAddress.state??void 0,postalCode:e.homeAddress.postalCode??void 0,country:e.homeAddress.countryOrRegion??void 0,label:"home"}),e.businessAddress&&Object.values(e.businessAddress).some(Boolean)&&r.push({street:e.businessAddress.street??void 0,city:e.businessAddress.city??void 0,region:e.businessAddress.state??void 0,postalCode:e.businessAddress.postalCode??void 0,country:e.businessAddress.countryOrRegion??void 0,label:"work"});let n=e.birthday?e.birthday.slice(0,10):void 0;return{id:e.id,displayName:e.displayName??"(No name)",firstName:e.givenName??void 0,lastName:e.surname??void 0,emails:t,phones:s,addresses:r,organization:e.companyName??void 0,birthday:n,notes:e.personalNotes??void 0}}buildContactBody(e){let t={};if(e.firstName!==void 0&&(t.givenName=e.firstName),e.lastName!==void 0&&(t.surname=e.lastName),e.displayName!==void 0&&(t.displayName=e.displayName),e.emails&&(t.emailAddresses=e.emails.map(s=>({address:s.address,name:s.label??s.address}))),e.phones){let s=e.phones.find(i=>i.label==="mobile"),r=e.phones.filter(i=>i.label==="work"),n=e.phones.filter(i=>i.label==="home"),o=e.phones.filter(i=>!["mobile","work","home"].includes(i.label??""));s&&(t.mobilePhone=s.number),r.length>0&&(t.businessPhones=r.map(i=>i.number)),n.length>0&&(t.homePhones=n.map(i=>i.number)),o.length>0&&!r.length&&(t.businessPhones=o.map(i=>i.number))}if(e.addresses)for(let s of e.addresses){let r={street:s.street,city:s.city,state:s.region,postalCode:s.postalCode,countryOrRegion:s.country};s.label==="work"?t.businessAddress=r:t.homeAddress=r}return e.organization!==void 0&&(t.companyName=e.organization),e.birthday!==void 0&&(t.birthday=e.birthday),e.notes!==void 0&&(t.personalNotes=e.notes),t}}});async function zi(l){switch(l.provider){case"carddav":{if(!l.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(Hi(),cd)),t=new e(l.carddav);return await t.initialize(),t}case"google":{if(!l.google)throw new Error("Google contacts config missing");let{GoogleContactsProvider:e}=await Promise.resolve().then(()=>(Bi(),ld)),t=new e(l.google);return await t.initialize(),t}case"microsoft":{if(!l.microsoft)throw new Error("Microsoft contacts config missing");let{MicrosoftContactsProvider:e}=await Promise.resolve().then(()=>(Wi(),dd)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${l.provider}`)}}var ud=_(()=>{"use strict";u(zi,"createContactsProvider")});var Nr,md=_(()=>{"use strict";B();Nr=class extends x{static{u(this,"ContactsSkill")}contactsProvider;metadata={name:"contacts",category:"productivity",description:"Manage contacts. Search, view, create, update, or delete contacts.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["search","get","list","create","update","delete"],description:"The contacts action to perform"},query:{type:"string",description:"Search query (for search action)"},contactId:{type:"string",description:"Contact ID (for get/update/delete)"},firstName:{type:"string",description:"First name (for create/update)"},lastName:{type:"string",description:"Last name (for create/update)"},displayName:{type:"string",description:"Display name (for create/update)"},email:{type:"string",description:"Single email address (for create/update, shorthand)"},phone:{type:"string",description:"Single phone number (for create/update, shorthand)"},organization:{type:"string",description:"Organization / company (for create/update)"},birthday:{type:"string",description:"Birthday in YYYY-MM-DD format (for create/update)"},notes:{type:"string",description:"Notes (for create/update)"},emailAddresses:{type:"string",description:"JSON array of {address, label?, primary?} for multiple emails"},phoneNumbers:{type:"string",description:"JSON array of {number, label?, primary?} for multiple phones"},addresses:{type:"string",description:"JSON array of {street?, city?, region?, postalCode?, country?, label?}"},limit:{type:"number",description:"Maximum number of contacts to return (for list, default 50)"}},required:["action"]}};constructor(e){super(),this.contactsProvider=e}async execute(e,t){let s=e.action;switch(s){case"search":return this.searchContacts(e);case"get":return this.getContact(e);case"list":return this.listContacts(e);case"create":return this.createContact(e);case"update":return this.updateContact(e);case"delete":return this.deleteContact(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async searchContacts(e){let t=e.query;if(!t)return{success:!1,error:'Missing required field "query"'};try{let s=await this.contactsProvider.search(t);if(s.length===0)return{success:!0,data:[],display:`No contacts found for "${t}".`};let r=this.formatTable(s);return{success:!0,data:s,display:`${s.length} contact(s) found:
|
|
909
909
|
${r}`}}catch(s){return{success:!1,error:`Failed to search contacts: ${s instanceof Error?s.message:String(s)}`}}}async getContact(e){let t=e.contactId;if(!t)return{success:!1,error:'Missing required field "contactId"'};try{let s=await this.contactsProvider.get(t);if(!s)return{success:!1,error:`Contact "${t}" not found.`};let r=this.formatDetail(s);return{success:!0,data:s,display:r}}catch(s){return{success:!1,error:`Failed to get contact: ${s instanceof Error?s.message:String(s)}`}}}async listContacts(e){let t=e.limit??50;try{let s=await this.contactsProvider.list(t);if(s.length===0)return{success:!0,data:[],display:"No contacts found."};let r=this.formatTable(s);return{success:!0,data:s,display:`${s.length} contact(s):
|
|
910
910
|
${r}`}}catch(s){return{success:!1,error:`Failed to list contacts: ${s instanceof Error?s.message:String(s)}`}}}async createContact(e){try{let t=this.buildContactInput(e),s=await this.contactsProvider.create(t);return{success:!0,data:s,display:`Contact created: ${s.displayName}`}}catch(t){return{success:!1,error:`Failed to create contact: ${t instanceof Error?t.message:String(t)}`}}}async updateContact(e){let t=e.contactId;if(!t)return{success:!1,error:'Missing required field "contactId"'};try{let s=this.buildContactInput(e),r=await this.contactsProvider.update(t,s);return{success:!0,data:r,display:`Contact updated: ${r.displayName}`}}catch(s){return{success:!1,error:`Failed to update contact: ${s instanceof Error?s.message:String(s)}`}}}async deleteContact(e){let t=e.contactId;if(!t)return{success:!1,error:'Missing required field "contactId"'};try{return await this.contactsProvider.delete(t),{success:!0,data:{deleted:t},display:`Contact "${t}" deleted.`}}catch(s){return{success:!1,error:`Failed to delete contact: ${s instanceof Error?s.message:String(s)}`}}}buildContactInput(e){let t={};if(e.firstName&&(t.firstName=e.firstName),e.lastName&&(t.lastName=e.lastName),e.displayName&&(t.displayName=e.displayName),e.organization&&(t.organization=e.organization),e.birthday&&(t.birthday=e.birthday),e.notes&&(t.notes=e.notes),e.emailAddresses)try{t.emails=JSON.parse(e.emailAddresses)}catch{t.emails=[{address:e.emailAddresses}]}else e.email&&(t.emails=[{address:e.email,primary:!0}]);if(e.phoneNumbers)try{t.phones=JSON.parse(e.phoneNumbers)}catch{t.phones=[{number:e.phoneNumbers}]}else e.phone&&(t.phones=[{number:e.phone,primary:!0}]);if(e.addresses)try{t.addresses=JSON.parse(e.addresses)}catch{}return t}formatTable(e){let t=`| Name | Email | Phone |
|
|
911
911
|
|------|-------|-------|`,s=e.map(r=>{let n=r.emails[0]?.address??"-",o=r.phones[0]?.number??"-";return`| ${r.displayName} | ${n} | ${o} |`});return`${t}
|
|
@@ -936,12 +936,12 @@ ${n}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(ce(t),s);
|
|
|
936
936
|
`+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose up:** \`${e}\``,"","```",r,"```"].join(`
|
|
937
937
|
`)}}async composeDown(e){if(!e)return{success:!1,error:'Missing required "project" parameter'};let{stdout:t,stderr:s}=await yd("docker",["compose","-p",e,"down"],{timeout:12e4}),r=(t+`
|
|
938
938
|
`+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose down:** \`${e}\``,"","```",r,"```"].join(`
|
|
939
|
-
`)}}}});import{readFile as _d,writeFile as kd,mkdir as Ed}from"node:fs/promises";import{homedir as Xi}from"node:os";import{join as Vi}from"node:path";import vd from"node:crypto";function Vp(){let l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",e=vd.randomBytes(86);return Array.from(e).map(t=>l[t%l.length]).join("")}function Kp(l){return vd.createHash("sha256").update(l).digest("base64url")}function
|
|
939
|
+
`)}}}});import{readFile as _d,writeFile as kd,mkdir as Ed}from"node:fs/promises";import{homedir as Xi}from"node:os";import{join as Vi}from"node:path";import vd from"node:crypto";function Vp(){let l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",e=vd.randomBytes(86);return Array.from(e).map(t=>l[t%l.length]).join("")}function Kp(l){return vd.createHash("sha256").update(l).digest("base64url")}function Te(l,e){return l[e]?.value??"?"}var zp,bd,Jn,qp,Gp,Xp,Sd,Zn,Yp,Qn,$d=_(()=>{"use strict";B();zp="https://customer.bmwgroup.com/gcdm/oauth/device/code",bd="https://customer.bmwgroup.com/gcdm/oauth/token",Jn="https://api-cardata.bmwgroup.com",qp="v1",Gp="authenticate_user openid cardata:api:read cardata:streaming:read",Xp=5*6e4,Sd="Alfred",Zn=Vi(Xi(),".alfred","bmw-tokens.json");u(Vp,"generateCodeVerifier");u(Kp,"generateCodeChallenge");Yp=["vehicle.drivetrain.batteryManagement.header","vehicle.drivetrain.batteryManagement.maxEnergy","vehicle.drivetrain.batteryManagement.batterySizeMax","vehicle.powertrain.electric.battery.stateOfHealth.displayed","vehicle.powertrain.electric.battery.stateOfCharge.target","vehicle.drivetrain.electricEngine.remainingElectricRange","vehicle.drivetrain.electricEngine.charging.status","vehicle.drivetrain.electricEngine.charging.level","vehicle.drivetrain.electricEngine.charging.timeRemaining","vehicle.drivetrain.electricEngine.charging.timeToFullyCharged","vehicle.drivetrain.electricEngine.charging.hvStatus","vehicle.drivetrain.electricEngine.charging.method","vehicle.drivetrain.electricEngine.charging.phaseNumber","vehicle.drivetrain.electricEngine.charging.lastChargingReason","vehicle.drivetrain.electricEngine.charging.lastChargingResult","vehicle.drivetrain.electricEngine.charging.reasonChargingEnd","vehicle.powertrain.electric.battery.charging.power","vehicle.drivetrain.electricEngine.charging.acVoltage","vehicle.drivetrain.electricEngine.charging.acAmpere","vehicle.powertrain.electric.battery.charging.acLimit.selected","vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged","vehicle.powertrain.tractionBattery.charging.port.anyPosition.flap.isOpen","vehicle.body.chargingPort.lockedStatus","vehicle.body.chargingPort.plugEventId","vehicle.powertrain.electric.battery.preconditioning.automaticMode.statusFeedback","vehicle.powertrain.electric.battery.preconditioning.manualMode.statusFeedback","vehicle.vehicle.avgAuxPower","vehicle.trip.segment.end.drivetrain.batteryManagement.hvSoc","vehicle.trip.segment.accumulated.drivetrain.electricEngine.recuperationTotal","vehicle.vehicleIdentification.basicVehicleData"];u(Te,"tv");Qn=class extends x{static{u(this,"BMWSkill")}metadata={name:"bmw",category:"infrastructure",description:'BMW CarData \u2014 Fahrzeugdaten abrufen. "authorize" startet den Device-Auth-Flow (einmalig). WICHTIG: authorize ist ein 2-Schritt-Prozess. Schritt 1 (ohne device_code) liefert einen User-Code + URL. Schritt 2: Nachdem der User im Browser best\xE4tigt hat, rufe authorize ERNEUT auf \u2014 entweder mit dem device_code aus Schritt 1, oder einfach ohne Parameter (auto-resume). NIEMALS Schritt 1 wiederholen wenn bereits ein Code ausgegeben wurde! "status" zeigt SoC, Reichweite, Modell, Batterie-Gesundheit. "charging" zeigt Ladestatus, Leistung, Restzeit, Ziel-SoC, Stecker. "charging_sessions" listet Lade-Sessions (from/to Zeitraum). "consumption" berechnet Durchschnittsverbrauch (kWh/100km) aus Lade-Sessions \u2014 optional mit period: "last" (letzte Fahrt), "week", "month", "year", "all" (default: month).',riskLevel:"read",version:"2.2.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["authorize","status","charging","charging_sessions","consumption"],description:"BMW CarData action"},vin:{type:"string",description:"Vehicle Identification Number (optional \u2014 uses stored VIN if omitted)"},device_code:{type:"string",description:"Device code from authorize step 1 (optional \u2014 if omitted, auto-resumes pending authorization)"},from:{type:"string",description:"ISO date-time start for charging_sessions (required for that action)"},to:{type:"string",description:"ISO date-time end for charging_sessions (required for that action)"},period:{type:"string",enum:["last","week","month","year","all"],description:"Zeitraum f\xFCr consumption: last (letzte Fahrt), week, month, year, all (default: month)"}},required:["action"]}};config;tokens=null;cache=new Map;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"authorize":return await this.authorize(e.device_code);case"status":return await this.getStatus(e.vin);case"charging":return await this.getCharging(e.vin);case"charging_sessions":return await this.getChargingSessions(e.vin,e.from,e.to);case"consumption":return await this.getConsumption(e.vin,e.period);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`BMW API error: ${r instanceof Error?r.message:String(r)}`}}}async authorize(e){if(e)return await this.pollToken(e);let t=await this.loadTokensFromDisk();if(t?.deviceCode&&t?.codeVerifier)try{return await this.pollToken(t.deviceCode)}catch{}let s=Vp(),r=Kp(s),n=await fetch(zp,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,response_type:"device_code",code_challenge:r,code_challenge_method:"S256",scope:Gp}),signal:AbortSignal.timeout(15e3)});if(!n.ok){let a=await n.text().catch(()=>"");throw new Error(`Device code request failed: HTTP ${n.status} \u2014 ${a.slice(0,300)}`)}let o=await n.json(),i={codeVerifier:s,deviceCode:o.device_code};return await this.savePartialTokens(i),this.tokens=null,{success:!0,data:o,display:["## BMW Autorisierung","",`1. \xD6ffne: **${o.verification_uri_complete??o.verification_uri}**`,`2. Gib diesen Code ein: **${o.user_code}**`,"","Danach rufe einfach `authorize` erneut auf (ohne Parameter) \u2014 der Token wird automatisch abgeholt."].join(`
|
|
940
940
|
`)}}async pollToken(e){let s=(await this.loadTokens())?.codeVerifier;if(!s)throw new Error('Kein code_verifier gefunden. Bitte zuerst "authorize" ohne device_code aufrufen.');let r=await fetch(bd,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,device_code:e,grant_type:"urn:ietf:params:oauth:grant-type:device_code",code_verifier:s}),signal:AbortSignal.timeout(15e3)});if(!r.ok){let p=await r.text().catch(()=>"");if(p.includes("authorization_pending"))return{success:!0,data:{status:"pending"},display:"Autorisierung noch ausstehend \u2014 bitte zuerst im Browser best\xE4tigen, dann erneut versuchen."};throw new Error(`Token poll failed: HTTP ${r.status} \u2014 ${p.slice(0,300)}`)}let n=await r.json(),o=n.access_token,i={accessToken:o,refreshToken:n.refresh_token,idToken:n.id_token,expiresAt:Date.now()+(n.expires_in??3600)*1e3,vin:"",containerId:""},a=await this.fetchVin(o);i.vin=a,await this.saveTokens(i);let c="",d="";try{c=await this.ensureContainer(o),i.containerId=c,await this.saveTokens(i)}catch(p){d=p instanceof Error?p.message:String(p)}this.tokens=i;let m=["## BMW Autorisierung erfolgreich","",`**VIN:** ${a}`];return c?(m.push(`**Container:** ${c}`),m.push("Tokens gespeichert. Du kannst jetzt Fahrzeugdaten abrufen.")):(m.push(`**Container-Fehler:** ${d}`),m.push("Tokens + VIN gespeichert, aber Container konnte nicht erstellt werden."),m.push("Erstelle den Container manuell im BMW CarData Portal oder versuche es erneut.")),{success:c!=="",data:{vin:a,containerId:c,containerError:d||void 0},display:m.join(`
|
|
941
|
-
`)}}async fetchVin(e){let t=await fetch(`${Jn}/customers/vehicles/mappings`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw new Error(`Failed to fetch vehicles: HTTP ${t.status}`);let s=await t.json();if(typeof s.vin=="string")return s.vin;if(Array.isArray(s)){let r=s;return r.find(o=>o.mappingType==="PRIMARY")?.vin??r[0]?.vin??(()=>{throw new Error("No vehicles found")})()}throw new Error(`No vehicles found in account (response: ${JSON.stringify(s).slice(0,200)})`)}async ensureContainer(e){let t=await fetch(`${Jn}/customers/containers`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(t.ok){let n=await t.json(),i=(Array.isArray(n)?n:Array.isArray(n.containers)?n.containers:[]).find(a=>a.name===Sd);if(i)return i.containerId}let s=await fetch(`${Jn}/customers/containers`,{method:"POST",headers:{...this.apiHeaders(e),"Content-Type":"application/json"},body:JSON.stringify({name:Sd,purpose:"Alfred AI Assistant",technicalDescriptors:Yp}),signal:AbortSignal.timeout(15e3)});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Container creation failed: HTTP ${s.status} \u2014 ${n.slice(0,300)}`)}return(await s.json()).containerId}apiHeaders(e){return{Authorization:`Bearer ${e}`,"x-version":qp,Accept:"application/json"}}async apiGet(e){let t=e,s=this.cache.get(t);if(s&&Date.now()-s.ts<Xp)return s.data;let r=await this.ensureToken(),n=`${Jn}${e}`,o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)});if(o.status===401){let a=await this.loadTokens();a&&(r=await this.refreshAccessToken(a),o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)}))}if(!o.ok){let a=await o.text().catch(()=>"");throw new Error(`HTTP ${o.status} \u2014 ${a.slice(0,300)}`)}let i=await o.json();return this.cache.set(t,{data:i,ts:Date.now()}),i}async loadTokens(){return this.tokens?this.tokens:await this.loadTokensFromDisk()}async loadTokensFromDisk(){try{let e=await _d(Zn,"utf-8"),t=JSON.parse(e);return this.tokens=t,t}catch{return null}}async saveTokens(e){await Ed(Vi(Xi(),".alfred"),{recursive:!0}),await kd(Zn,JSON.stringify(e,null,2),"utf-8")}async savePartialTokens(e){await Ed(Vi(Xi(),".alfred"),{recursive:!0});let t={};try{let s=await _d(Zn,"utf-8");t=JSON.parse(s)}catch{}await kd(Zn,JSON.stringify({...t,...e},null,2),"utf-8")}async ensureToken(){let e=await this.loadTokens();if(!e?.accessToken)throw new Error('Nicht autorisiert. Bitte zuerst die "authorize"-Action aufrufen, um den BMW-Account zu verbinden.');return Date.now()>e.expiresAt-6e4?await this.refreshAccessToken(e):e.accessToken}async refreshAccessToken(e){let t=await fetch(bd,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,grant_type:"refresh_token",refresh_token:e.refreshToken}),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw this.tokens=null,new Error('Token-Refresh fehlgeschlagen. Bitte erneut "authorize" aufrufen.');let s=await t.json(),r={...e,accessToken:s.access_token,refreshToken:s.refresh_token??e.refreshToken,idToken:s.id_token??e.idToken,expiresAt:Date.now()+(s.expires_in??3600)*1e3};return delete r.codeVerifier,delete r.deviceCode,await this.saveTokens(r),this.tokens=r,r.accessToken}async resolveVin(e){if(e)return e;let t=await this.loadTokens();if(t?.vin)return t.vin;throw new Error('Keine VIN angegeben und keine gespeicherte VIN gefunden. Bitte zuerst "authorize" aufrufen.')}async resolveContainerId(){let e=await this.loadTokens();if(e?.containerId)return e.containerId;throw new Error('Kein Container gefunden. Bitte zuerst "authorize" aufrufen.')}async getStatus(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),[r,n]=await Promise.all([this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`),this.apiGet(`/customers/vehicles/${t}/basicData`)]),o=r.telematicData??{},i=
|
|
942
|
-
`)}}async getCharging(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),n=(await this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`)).telematicData??{},o=
|
|
941
|
+
`)}}async fetchVin(e){let t=await fetch(`${Jn}/customers/vehicles/mappings`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw new Error(`Failed to fetch vehicles: HTTP ${t.status}`);let s=await t.json();if(typeof s.vin=="string")return s.vin;if(Array.isArray(s)){let r=s;return r.find(o=>o.mappingType==="PRIMARY")?.vin??r[0]?.vin??(()=>{throw new Error("No vehicles found")})()}throw new Error(`No vehicles found in account (response: ${JSON.stringify(s).slice(0,200)})`)}async ensureContainer(e){let t=await fetch(`${Jn}/customers/containers`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(t.ok){let n=await t.json(),i=(Array.isArray(n)?n:Array.isArray(n.containers)?n.containers:[]).find(a=>a.name===Sd);if(i)return i.containerId}let s=await fetch(`${Jn}/customers/containers`,{method:"POST",headers:{...this.apiHeaders(e),"Content-Type":"application/json"},body:JSON.stringify({name:Sd,purpose:"Alfred AI Assistant",technicalDescriptors:Yp}),signal:AbortSignal.timeout(15e3)});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Container creation failed: HTTP ${s.status} \u2014 ${n.slice(0,300)}`)}return(await s.json()).containerId}apiHeaders(e){return{Authorization:`Bearer ${e}`,"x-version":qp,Accept:"application/json"}}async apiGet(e){let t=e,s=this.cache.get(t);if(s&&Date.now()-s.ts<Xp)return s.data;let r=await this.ensureToken(),n=`${Jn}${e}`,o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)});if(o.status===401){let a=await this.loadTokens();a&&(r=await this.refreshAccessToken(a),o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)}))}if(!o.ok){let a=await o.text().catch(()=>"");throw new Error(`HTTP ${o.status} \u2014 ${a.slice(0,300)}`)}let i=await o.json();return this.cache.set(t,{data:i,ts:Date.now()}),i}async loadTokens(){return this.tokens?this.tokens:await this.loadTokensFromDisk()}async loadTokensFromDisk(){try{let e=await _d(Zn,"utf-8"),t=JSON.parse(e);return this.tokens=t,t}catch{return null}}async saveTokens(e){await Ed(Vi(Xi(),".alfred"),{recursive:!0}),await kd(Zn,JSON.stringify(e,null,2),"utf-8")}async savePartialTokens(e){await Ed(Vi(Xi(),".alfred"),{recursive:!0});let t={};try{let s=await _d(Zn,"utf-8");t=JSON.parse(s)}catch{}await kd(Zn,JSON.stringify({...t,...e},null,2),"utf-8")}async ensureToken(){let e=await this.loadTokens();if(!e?.accessToken)throw new Error('Nicht autorisiert. Bitte zuerst die "authorize"-Action aufrufen, um den BMW-Account zu verbinden.');return Date.now()>e.expiresAt-6e4?await this.refreshAccessToken(e):e.accessToken}async refreshAccessToken(e){let t=await fetch(bd,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,grant_type:"refresh_token",refresh_token:e.refreshToken}),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw this.tokens=null,new Error('Token-Refresh fehlgeschlagen. Bitte erneut "authorize" aufrufen.');let s=await t.json(),r={...e,accessToken:s.access_token,refreshToken:s.refresh_token??e.refreshToken,idToken:s.id_token??e.idToken,expiresAt:Date.now()+(s.expires_in??3600)*1e3};return delete r.codeVerifier,delete r.deviceCode,await this.saveTokens(r),this.tokens=r,r.accessToken}async resolveVin(e){if(e)return e;let t=await this.loadTokens();if(t?.vin)return t.vin;throw new Error('Keine VIN angegeben und keine gespeicherte VIN gefunden. Bitte zuerst "authorize" aufrufen.')}async resolveContainerId(){let e=await this.loadTokens();if(e?.containerId)return e.containerId;throw new Error('Kein Container gefunden. Bitte zuerst "authorize" aufrufen.')}async getStatus(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),[r,n]=await Promise.all([this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`),this.apiGet(`/customers/vehicles/${t}/basicData`)]),o=r.telematicData??{},i=Te(o,"vehicle.drivetrain.batteryManagement.header"),a=Te(o,"vehicle.drivetrain.electricEngine.remainingElectricRange"),c=Te(o,"vehicle.drivetrain.batteryManagement.maxEnergy"),d=Te(o,"vehicle.powertrain.electric.battery.stateOfHealth.displayed"),p=["## BMW Fahrzeugstatus","",`**Modell:** ${n.modelName??n.model??"?"}`,`**VIN:** ${t}`,`**Ladestand (SoC):** ${i} %`,`**Elektrische Reichweite:** ${a} km`,`**Batteriekapazit\xE4t:** ${c} kWh`,`**Batterie-Gesundheit (SoH):** ${d} %`];return{success:!0,data:{telematic:o,basic:n},display:p.join(`
|
|
942
|
+
`)}}async getCharging(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),n=(await this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`)).telematicData??{},o=Te(n,"vehicle.drivetrain.electricEngine.charging.status"),i=Te(n,"vehicle.drivetrain.batteryManagement.header"),a=Te(n,"vehicle.drivetrain.electricEngine.charging.level"),c=Te(n,"vehicle.drivetrain.electricEngine.charging.timeRemaining"),d=Te(n,"vehicle.powertrain.electric.battery.charging.power"),m=Te(n,"vehicle.drivetrain.electricEngine.charging.hvStatus"),p=Te(n,"vehicle.powertrain.electric.battery.stateOfCharge.target"),f=Te(n,"vehicle.drivetrain.electricEngine.charging.acVoltage"),g=Te(n,"vehicle.drivetrain.electricEngine.charging.acAmpere"),h=Te(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged"),y=Te(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.flap.isOpen"),k=Te(n,"vehicle.body.chargingPort.lockedStatus"),S=["## BMW Ladestatus","",`**Status:** ${o}`,`**Ladestand:** ${i} %`,`**Ladelevel:** ${a}`,`**Ladeleistung:** ${d} kW`,`**Restzeit:** ${c} min`,`**Ziel-SoC:** ${p} %`,`**HV-Batterie:** ${m}`,`**AC Spannung:** ${f} V`,`**AC Strom:** ${g} A`,`**Stecker eingesteckt:** ${h}`,`**Ladeklappe offen:** ${y}`,`**Ladeport-Schloss:** ${k}`];return{success:!0,data:n,display:S.join(`
|
|
943
943
|
`)}}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 m of c.slice(0,20)){let p=m.startTime,f=m.endTime,g=u(j=>new Date(j*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):"-",k=m.totalChargingDurationSec,S=k!=null?Math.round(k/60):"-",b=m.energyConsumedFromPowerGridKwh??"-",C=m.displayedStartSoc??"-",D=m.displayedSoc??"-",U=m.mileage!=null?`${m.mileage}`:"-",Q=m.chargingLocation,ie=Q?.formattedAddress??Q?.streetAddress??"-";d.push(`| ${h} | ${y} | ${S} min | ${b} kWh | ${C}% | ${D}% | ${U} | ${ie} |`)}return c.length===0&&d.push("| - | - | Keine Sessions gefunden | - | - | - | - | - |"),{success:!0,data:a,display:d.join(`
|
|
944
|
-
`)}}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,m]=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(
|
|
944
|
+
`)}}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,m]=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(Te(m.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(j=>typeof j.mileage=="number"&&typeof j.displayedStartSoc=="number"&&typeof j.displayedSoc=="number").sort((j,z)=>j.mileage-z.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 j=1;j<g.length;j++){let z=g[j-1],ae=g[j],L=z.mileage,se=ae.mileage,K=se-L;if(K<=0)continue;let P=z.displayedSoc,me=ae.displayedStartSoc,De=P-me;if(De<=0)continue;let Ae=De/100*f,ee=Ae/K*100,Ee=ae.startTime,de=Ee?new Date(Ee*1e3).toLocaleDateString("de-AT"):"-";h.push({fromKm:L,toKm:se,distance:K,socUsed:De,kWhUsed:Ae,consumption:ee,date:de})}if(h.length===0)return{success:!0,data:{},display:"Keine auswertbaren Fahrtabschnitte gefunden."};if(t==="last"){let j=h[h.length-1];return{success:!0,data:j,display:["## Letzte Fahrt (gesch\xE4tzt)","",`**Datum:** ${j.date}`,`**Strecke:** ${j.distance} km`,`**Verbrauch:** ${j.consumption.toFixed(1)} kWh/100km`,`**Energie:** ${j.kWhUsed.toFixed(1)} kWh (${j.socUsed}% SoC)`,`**km-Stand:** ${j.fromKm} \u2192 ${j.toKm}`].join(`
|
|
945
945
|
`)}}let y=h.reduce((j,z)=>j+z.distance,0),k=h.reduce((j,z)=>j+z.kWhUsed,0),S=k/y*100,b=h.map(j=>j.consumption).sort((j,z)=>j-z),C=b[0],D=b[b.length-1],U=b[Math.floor(b.length/2)],ie=[`## 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:** ${k.toFixed(1)} kWh`,"",`**Durchschnitt:** ${S.toFixed(1)} kWh/100km`,`**Min:** ${C.toFixed(1)} kWh/100km`,`**Max:** ${D.toFixed(1)} kWh/100km`,`**Median:** ${U.toFixed(1)} kWh/100km`,"","### Einzelne Fahrten","","| Datum | Strecke | Verbrauch | Energie |","|-------|---------|-----------|---------|"];for(let j of h)ie.push(`| ${j.date} | ${j.distance} km | ${j.consumption.toFixed(1)} kWh/100km | ${j.kWhUsed.toFixed(1)} kWh |`);return{success:!0,data:{avgConsumption:S,totalDistance:y,totalKwh:k,segments:h},display:ie.join(`
|
|
946
946
|
`)}}}});var Jp,eo,Id=_(()=>{"use strict";B();Jp="https://routes.googleapis.com/directions/v2:computeRoutes",eo=class extends x{static{u(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),m=c-d,p=["## Route","",`**${e}** \u2192 **${t}**`,"",`**Distanz:** ${a} km`,`**Fahrzeit (aktuell):** ${this.formatMinutes(c)}`,`**Fahrzeit (ohne Verkehr):** ${this.formatMinutes(d)}`];if(m>1&&p.push(`**Verkehrsverz\xF6gerung:** +${this.formatMinutes(m)}`),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(`
|
|
947
947
|
`)}}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),m=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:** ${m.toLocaleString("de-AT")}`];return{success:!0,data:{departureTime:m.toISOString(),durationMinutes:a,bufferMinutes:c},display:p.join(`
|
|
@@ -1080,7 +1080,7 @@ ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
|
|
|
1080
1080
|
|
|
1081
1081
|
**Git:**
|
|
1082
1082
|
${s.join(`
|
|
1083
|
-
`)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var eu=_(()=>{"use strict";Qd();lo();ma();aa();da()});var oe={};
|
|
1083
|
+
`)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var eu=_(()=>{"use strict";Qd();lo();ma();aa();da()});var oe={};he(oe,{ActivityTracker:()=>Nt,BMWSkill:()=>Qn,BackgroundTaskSkill:()=>ps,BriefingSkill:()=>ao,BrowserSkill:()=>ds,CalculatorSkill:()=>Yt,CalendarProvider:()=>He,CalendarSkill:()=>Lt,ClipboardSkill:()=>cs,CodeAgentSkill:()=>jr,CodeExecutionSkill:()=>Rr,CodeExecutor:()=>Ot,ConfigureSkill:()=>Es,ContactsProvider:()=>ze,ContactsSkill:()=>Nr,CrossPlatformSkill:()=>ms,DelegateSkill:()=>ns,DockerSkill:()=>Yn,DocumentSkill:()=>fs,EmailProvider:()=>rt,EmailSkill:()=>lt,EnergyPriceSkill:()=>to,FileSkill:()=>is,ForgeClient:()=>Ft,HomeAssistantSkill:()=>qn,HttpSkill:()=>os,ImageGenerateSkill:()=>ys,MCPClient:()=>Dt,MCPManager:()=>Ar,MCPSkillAdapter:()=>Mt,MarketplaceSkill:()=>Mr,MemorySkill:()=>rs,MicrosoftTodoSkill:()=>ro,MonitorSkill:()=>so,NoteSkill:()=>es,PluginLoader:()=>Mn,ProfileSkill:()=>us,ProxmoxSkill:()=>Wn,ReminderSkill:()=>Qt,RoutingSkill:()=>eo,ScheduledTaskSkill:()=>hs,ScreenshotSkill:()=>ls,ShellSkill:()=>ss,Skill:()=>x,SkillRegistry:()=>Vt,SkillSandbox:()=>Kt,SystemInfoSkill:()=>Jt,TTSSkill:()=>gs,TodoSkill:()=>Ts,TransitSkill:()=>_s,UniFiSkill:()=>zn,WatchSkill:()=>bs,WeatherSkill:()=>ts,WebSearchSkill:()=>Zt,WorkflowSkill:()=>Ss,allUserIds:()=>G,createCalendarProvider:()=>Ir,createContactsProvider:()=>zi,createEmailProvider:()=>Sr,createForgeClient:()=>Is,effectiveUserId:()=>ce,gitAddRemote:()=>Pr,gitGetRemoteUrl:()=>vs,gitInitRepo:()=>Ur,orchestrate:()=>jt,orchestrateWithGit:()=>Fr,parseRemoteUrl:()=>$s});var ne=_(()=>{"use strict";B();Me();pl();hl();Ai();fl();Tl();wl();_l();kl();El();bl();$l();Il();Al();Nl();Dl();Ol();Ul();Fl();Hl();Bl();Vl();Kl();Yl();Jl();Ql();td();sd();rd();nd();od();id();ad();pd();hd();wd();$d();Id();Dd();Md();Pd();Fd();jd();Hd();Bd();qd();Gd();eu()});var Hr,pa=_(()=>{"use strict";Hr=class{static{u(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}pruneMessages(e,t){return this.conversations.pruneMessages(e,t)}}});function $e(l,e){let t;if(e.platformUserId)t=l.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=l.findById(e.userId)??l.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in l?l.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in l&&(r=l.getLinkedUsers(s).map(a=>a.platformUserId));let n;try{"getProfile"in l?n=l.getProfile(s)?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone:n=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{n=Intl.DateTimeFormat().resolvedOptions().timeZone}return{context:{userId:t.platformUserId,masterUserId:s,linkedPlatformUserIds:r,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:e.conversationId??"",timezone:n},user:t,masterUserId:s,linkedPlatformUserIds:r}}var ut=_(()=>{"use strict";u($e,"buildSkillContext")});function tu(l,e){let t=new Set(["core"]),s=!1;for(let[r,n]of Object.entries(bh))e.has(r)&&n.test(l)&&(t.add(r),s=!0);if(!s){let r=["productivity","information","media","automation","files"];for(let n of r)e.has(n)&&t.add(n)}return t}function su(l,e){return l.filter(t=>e.has(t.category??"core"))}var bh,ru=_(()=>{"use strict";bh={productivity:/\b(todo|note|notiz|remind|erinner|calendar|kalender|termin|event|email|e-mail|mail|contact|kontakt|briefing|morgenbriefing|tagesbriefing)\b/i,information:/\b(search|such|weather|wetter|calculat|rechn|time|date|zeit|datum|uhrzeit|system.?info|transit|bahn|zug|bus|tram|u.?bahn|s.?bahn|abfahrt|verbindung|haltestelle|öffi|fahrplan|strom|energy|preis|price|kwh|awattar|marktpreis|spot|günstig|cheapest|netzentgelt)\b/i,media:/\b(voice|stimme|tts|speak|sprech|sprich|screenshot|clipboard|zwischenablage|brows|bild|image|generier|photo|foto)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat|watch|alert|benachrichtig|bescheid|meld|überwach|monitor|script|skript|befehl|kommando|tägliche?r?s?|stündliche?r?s?|wöchentliche?r?s?|monatliche?r?s?|jeden\s+(tag|morgen|abend|montag|dienstag|mittwoch|donnerstag|freitag|samstag|sonntag)|um\s+\d{1,2}\s*(uhr|:|h)|alle\s+\d+\s*(min|stund|sekund)|in\s+\d+\s*(minuten?|stunden?|sekunden?|hours?|minutes?|seconds?|min)|daily|hourly|weekly|every\s+(day|hour|morning|evening|night|\d+\s*min)|führ.{0,5}aus|execut|ausführ)\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload|herunterlad|hochlad|anhang|attachment)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|netzwerk|network|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch|solar|photovoltaik|pv|wechselrichter|inverter|batterie.?speicher|wallbox|energieverbrauch|stromverbrauch|verbrauch.{0,5}kwh|einspeis|netzeinspeis|autarkie|eigenverbrauch|bmw|auto|fahrzeug|ladestand|reichweite|laden(?!e)|charging|vehicle|soc|ladehistorie|ladesession|ladevorgang|ladezyklus|ladekurve|km|kilometer|kilometerstand|mileage|tachostand)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(tu,"selectCategories");u(su,"filterSkills")});import ha from"node:fs";import nu from"node:path";function Ah(l,e){if(l.length<=e)return l;let t=l.split(`
|
|
1084
1084
|
`);if(t.length<=10)return l.slice(0,e)+`
|
|
1085
1085
|
|
|
1086
1086
|
[... truncated, total `+l.length+" chars]";let s=Math.floor(t.length*.7),r=Math.max(Math.floor(t.length*.2),5),n=t.length-s-r,o=t.slice(0,s),i=t.slice(t.length-r),a=`
|
|
@@ -1091,9 +1091,9 @@ ${s.join(`
|
|
|
1091
1091
|
|
|
1092
1092
|
[... truncated, total `+l.length+` chars]
|
|
1093
1093
|
|
|
1094
|
-
`+l.slice(l.length-Math.floor(e*.2))}return c}var Sh,ou,vh,$h,Ih,iu,Rh,xh,Ch,au,Nh,Br,fa=_(()=>{"use strict";$i();ut();ru();Sh=15*60*1e3,ou=50,vh=2,$h=12e3,Ih=3,iu=.85;u(Ah,"truncateToolResult");Rh=1e5,xh=2e3,Ch=.1,au=3,Nh=10,Br=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;documentProcessor;conversationSummarizer;confirmationQueue;activityLogger;skillHealthTracker;activeAgents=new Map;agentIdCounter=0;metrics={requestsTotal:0,requestsSuccess:0,requestsFailed:0,avgDurationMs:0,totalInputTokens:0,totalOutputTokens:0,totalCostUsd:0};getMetrics(){return{...this.metrics}}setConfirmationQueue(e){this.confirmationQueue=e}setActivityLogger(e){this.activityLogger=e}setSkillHealthTracker(e){this.skillHealthTracker=e}recordMetric(e,t,s){this.metrics.requestsTotal++,e?this.metrics.requestsSuccess++:this.metrics.requestsFailed++,this.metrics.avgDurationMs=Math.round(this.metrics.avgDurationMs+(t-this.metrics.avgDurationMs)/this.metrics.requestsTotal),this.metrics.lastRequestAt=new Date().toISOString(),s&&(this.metrics.totalInputTokens+=s.input,this.metrics.totalOutputTokens+=s.output,this.metrics.totalCostUsd+=s.costUsd)}constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.maxHistoryMessages=e.maxHistoryMessages??30,this.documentProcessor=e.documentProcessor,this.conversationSummarizer=e.conversationSummarizer,this.promptBuilder=new _r}async process(e,t){let s=Date.now();if(this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message"),this.confirmationQueue&&e.text){let{context:r}
|
|
1094
|
+
`+l.slice(l.length-Math.floor(e*.2))}return c}var Sh,ou,vh,$h,Ih,iu,Rh,xh,Ch,au,Nh,Br,fa=_(()=>{"use strict";$i();ut();ru();Sh=15*60*1e3,ou=50,vh=2,$h=12e3,Ih=3,iu=.85;u(Ah,"truncateToolResult");Rh=1e5,xh=2e3,Ch=.1,au=3,Nh=10,Br=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;documentProcessor;conversationSummarizer;confirmationQueue;activityLogger;skillHealthTracker;activeAgents=new Map;agentIdCounter=0;metrics={requestsTotal:0,requestsSuccess:0,requestsFailed:0,avgDurationMs:0,totalInputTokens:0,totalOutputTokens:0,totalCostUsd:0};getMetrics(){return{...this.metrics}}setConfirmationQueue(e){this.confirmationQueue=e}setActivityLogger(e){this.activityLogger=e}setSkillHealthTracker(e){this.skillHealthTracker=e}recordMetric(e,t,s){this.metrics.requestsTotal++,e?this.metrics.requestsSuccess++:this.metrics.requestsFailed++,this.metrics.avgDurationMs=Math.round(this.metrics.avgDurationMs+(t-this.metrics.avgDurationMs)/this.metrics.requestsTotal),this.metrics.lastRequestAt=new Date().toISOString(),s&&(this.metrics.totalInputTokens+=s.input,this.metrics.totalOutputTokens+=s.output,this.metrics.totalCostUsd+=s.costUsd)}constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.maxHistoryMessages=e.maxHistoryMessages??30,this.documentProcessor=e.documentProcessor,this.conversationSummarizer=e.conversationSummarizer,this.promptBuilder=new _r}async process(e,t){let s=Date.now();if(this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message"),this.confirmationQueue&&e.text){let{context:r}=$e(this.users,{platformUserId:e.userId,platform:e.platform,chatId:e.chatId,chatType:e.chatType,userName:e.userName,displayName:e.displayName});if(await this.confirmationQueue.checkForConfirmation(e.chatId,e.platform,e.text,r))return{text:""}}try{let{user:r,masterUserId:n,linkedPlatformUserIds:o,context:i}=$e(this.users,{platformUserId:e.userId,platform:e.platform,chatId:e.chatId,chatType:e.chatType,userName:e.userName,displayName:e.displayName}),a=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),c=!e.metadata?.skipHistory&&this.conversationSummarizer?this.conversationSummarizer.getSummary(a.id):void 0,d=c?Nh:this.maxHistoryMessages,m=e.metadata?.skipHistory?[]:this.conversationManager.getHistory(a.id,d);this.conversationManager.addMessage(a.id,"user",e.text);let p,f=this.isSyntheticLabel(e.text),g=e.attachments?.some(X=>X.type==="audio")??!1,h=f&&!g;if(this.memoryRetriever&&e.text&&!h)try{p=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(X){this.logger.debug({err:X},"Hybrid memory retrieval failed")}if(!p&&this.memoryRepo&&!h)try{let X=[n,...(o??[]).filter(v=>v!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let v=new Set;p=[];for(let O of X)for(let Y of await this.embeddingService.semanticSearch(O,e.text,10))v.has(Y.key)||(v.add(Y.key),p.push(Y));for(let O of X)for(let Y of this.memoryRepo.getRecentForPrompt(O,5))v.has(Y.key)||(v.add(Y.key),p.push(Y))}else{let v=new Set;p=[];for(let O of X)for(let Y of this.memoryRepo.getRecentForPrompt(O,20))v.has(Y.key)||(v.add(Y.key),p.push(Y))}}catch(X){this.logger.debug({err:X},"Memory loading failed")}p&&p.length>0&&(p=this.applyMemoryBudget(p));let y;try{"getProfile"in this.users&&(y=this.users.getProfile(n),y&&!y.displayName&&(y.displayName=r.displayName??r.username))}catch(X){this.logger.debug({err:X},"Profile loading failed")}let k=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,S=this.skillRegistry?this.skillRegistry.getAll().map(X=>X.metadata):void 0,b=S;if(S&&e.text){let X=new Set(S.map(pe=>pe.category??"core")),v=m.filter(pe=>pe.role==="user").slice(-3).map(pe=>pe.content).join(" "),O=v?`${e.text} ${v}`:e.text,Y=tu(O,X);b=su(S,Y)}let C=b?this.promptBuilder.buildTools(b):void 0,D=this.promptBuilder.buildSystemPrompt({memories:p,skills:b,userProfile:y,conversationSummary:c?.summary}),U=this.buildActiveAgentStatus();U&&(D+=`
|
|
1095
1095
|
|
|
1096
|
-
`+U);let Q=this.promptBuilder.buildMessages(m),ie=this.collapseRepeatedToolErrors(Q),j=vi(ie),z=ie.reduce((X,v)=>X+Ct(v),0)-j.reduce((X,v)=>X+Ct(v),0);z>100&&this.logger.debug(`Tool result trimming saved ~${z} tokens`);let ae=await this.buildUserContent(e,t);j.push({role:"user",content:ae});let L=C?je(JSON.stringify(C)):0,se=1,K=this.trimToContextWindow(D,j,L,se),P,me=0,
|
|
1096
|
+
`+U);let Q=this.promptBuilder.buildMessages(m),ie=this.collapseRepeatedToolErrors(Q),j=vi(ie),z=ie.reduce((X,v)=>X+Ct(v),0)-j.reduce((X,v)=>X+Ct(v),0);z>100&&this.logger.debug(`Tool result trimming saved ~${z} tokens`);let ae=await this.buildUserContent(e,t);j.push({role:"user",content:ae});let L=C?je(JSON.stringify(C)):0,se=1,K=this.trimToContextWindow(D,j,L,se),P,me=0,De=Date.now(),Ae="",ee=0,Ee=0,de=0,Ve=[],Ke=[],Ye=[];for(t?.("Thinking...");;){me>0&&this.compressToolLoop(K,D,L);try{P=await this.llm.complete({messages:K,system:D,tools:C&&C.length>0?C:void 0,tier:e.metadata?.tier}),Ee+=P.usage?.inputTokens??0,de+=P.usage?.outputTokens??0}catch(le){if((le instanceof Error?le.message:String(le)).includes("prompt is too long")&&se>.3){se*=.5,this.logger.warn({budgetMultiplier:se},"Prompt too long, retrimming with reduced budget"),K=this.trimToContextWindow(D,j,L,se);continue}throw le}if(P.stopReason==="max_tokens"&&P.toolCalls?.length&&(this.logger.warn({toolCallCount:P.toolCalls.length},"Discarding truncated tool calls due to max_tokens"),P={...P,toolCalls:[]}),!P.toolCalls||P.toolCalls.length===0){if(P.stopReason==="max_tokens"){let le=0,Ge=P.content??"";for(;P.stopReason==="max_tokens"&&le<Ih;){le++,this.logger.info({continuationRounds:le,textLength:Ge.length},"Output truncated, requesting continuation"),Ge?(K.push({role:"assistant",content:Ge}),K.push({role:"user",content:"Fahre exakt dort fort wo du aufgeh\xF6rt hast. Keine Wiederholung, nur der Rest."})):K.push({role:"user",content:"Deine Antwort war zu lang und wurde abgeschnitten. Bitte antworte k\xFCrzer und kompakter. Fasse zusammen statt alles aufzulisten."});try{P=await this.llm.complete({messages:K,system:D,tools:C&&C.length>0?C:void 0,tier:e.metadata?.tier}),Ee+=P.usage?.inputTokens??0,de+=P.usage?.outputTokens??0,P.content&&(Ge+=P.content)}catch{break}}P={...P,content:Ge,stopReason:"end_turn"}}break}let X=Date.now()-De;if(X>=Sh){let le=Math.round(X/6e4);this.logger.warn({iteration:me,elapsedMin:le,pendingToolCalls:P.toolCalls.length},"Tool loop timeout reached"),P=await this.abortToolLoop(K,P,a.id,D,`Das Zeitlimit von ${le} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`,!1,e.metadata?.tier);break}if(me>=ou){this.logger.warn({iteration:me,pendingToolCalls:P.toolCalls.length},"Tool loop iteration cap reached"),P=await this.abortToolLoop(K,P,a.id,D,`Das Iterationslimit von ${ou} Tool-Aufrufen wurde erreicht.`,!1,e.metadata?.tier);break}me++,this.logger.info({iteration:me,toolCalls:P.toolCalls.length},"Processing tool calls");let v=[];P.content&&v.push({type:"text",text:P.content});for(let le of P.toolCalls)v.push({type:"tool_use",id:le.id,name:le.name,input:le.input});K.push({role:"assistant",content:v});let O=await this.executeToolCallsParallel(P.toolCalls,{...i,conversationId:a.id,timezone:k},t),Y=O.blocks;O.attachments.length>0&&Ve.push(...O.attachments),Ke.push(...P.toolCalls),Ye.push(...Y);let pe=this.buildErrorSignature(Y);if(pe){if(pe===Ae?ee++:(ee=1,Ae=pe),ee>=vh){this.logger.warn({iteration:me,consecutiveErrors:ee,errorSignature:pe},"Tool loop aborted: same error repeated consecutively"),P=await this.abortToolLoop(K,P,a.id,D,`Der gleiche Tool-Fehler ist ${ee}x hintereinander aufgetreten: "${Ae.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0,e.metadata?.tier);break}}else ee=0,Ae="";K.push({role:"user",content:Y}),t?.("Thinking...")}let ve=P.content;if(!ve)for(let X=K.length-1;X>=0;X--){let v=K[X];if(v.role==="assistant"&&Array.isArray(v.content)){let O=v.content.find(Y=>Y.type==="text");if(O&&"text"in O&&O.text){ve=O.text;break}}}if(ve||(ve="(no response)"),Ke.length>0&&(this.conversationManager.addMessage(a.id,"assistant","",JSON.stringify(Ke)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(Ye))),this.conversationManager.addMessage(a.id,"assistant",ve),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,ve),this.conversationSummarizer&&!e.metadata?.skipHistory){let X=m.slice(-8).map(v=>({role:v.role,content:v.content}));this.conversationSummarizer.onMessageProcessed(a.id,m.length+2,e.text,ve,X)}let xs=Date.now()-s,it=P.model??"unknown",ft=Nn(it,{inputTokens:Ee,outputTokens:de});return this.logger.info({duration:xs,model:it,tokens:P.usage,totalTokens:{inputTokens:Ee,outputTokens:de},costUsd:Math.round(ft*1e6)/1e6,stopReason:P.stopReason,toolIterations:me},"Message processed"),this.recordMetric(!0,Date.now()-s,{input:Ee,output:de,costUsd:ft}),{text:ve,attachments:Ve.length>0?Ve:void 0}}catch(r){throw this.recordMetric(!1,Date.now()-s),this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1,i){if(!o){let d=[];t.content&&d.push({type:"text",text:t.content});for(let m of t.toolCalls)d.push({type:"tool_use",id:m.id,name:m.name,input:m.input});e.push({role:"assistant",content:d})}let a=t.toolCalls.map(d=>({type:"tool_result",tool_use_id:d.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));e.push({role:"user",content:a}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(a));let c=e[e.length-1];return c&&c.role==="user"&&Array.isArray(c.content)?c.content.push({type:"text",text:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}):e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r,tier:i})}buildErrorSignature(e){let t=[];for(let s of e)s.type==="tool_result"&&s.is_error&&t.push(s.content);return t.length>0?t.join("|"):""}collapseRepeatedToolErrors(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=s+1<e.length?e[s+1]:null;if(n&&n.role==="user"&&Array.isArray(n.content)&&n.content.every(o=>o.type==="tool_result"&&o.is_error)){let o=this.toolPairSignature(r,n),i=1,a=s+2;for(;a+1<e.length;){let c=e[a],d=e[a+1];if(c.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(c,d)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"user",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=u((m,p)=>{let f=p.content;if(p.attachments&&p.attachments.length>0){r.push(...p.attachments);let g=p.attachments.map(h=>h.fileName).join(", ");f+=`
|
|
1097
1097
|
|
|
1098
1098
|
[${p.attachments.length} Datei(en) werden dem User gesendet: ${g}]`}return f=Ah(f,$h),{type:"tool_result",tool_use_id:m.id,content:f,is_error:p.isError}},"buildBlock");if(e.length===1){let m=e[0],p=this.getToolLabel(m.name,m.input);s?.(p);let f=await this.executeToolCall(m,t,s);return{blocks:[n(m,f)],attachments:r}}let o=3;s?.(`Running ${e.length} tools...`);let i=new Map;for(let m=0;m<e.length;m++){let p=e[m].name,f=i.get(p);f||(f=[],i.set(p,f)),f.push(m)}let a=[...i.values()].some(m=>m.length>o),c;if(a){c=new Map;let m=[...i.entries()].map(async([p,f])=>{for(let g=0;g<f.length;g+=o){let h=f.slice(g,g+o),y=await Promise.allSettled(h.map(k=>this.executeToolCall(e[k],t,s)));for(let k=0;k<h.length;k++)c.set(h[k],y[k])}});await Promise.all(m)}else{let m=await Promise.allSettled(e.map(p=>this.executeToolCall(p,t,s)));c=new Map(m.map((p,f)=>[f,p]))}return{blocks:e.map((m,p)=>{let f=c.get(p);return f.status==="fulfilled"?n(m,f.value):{type:"tool_result",tool_use_id:m.id,content:`Tool execution failed: ${f.reason}`,is_error:!0}}),attachments:r}}async executeToolCall(e,t,s){let r=this.skillRegistry?.get(e.name);if(!r)return this.logger.warn({tool:e.name},"Unknown skill requested"),{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.skillHealthTracker){let n=this.skillHealthTracker.isDisabled(e.name);if(n){let o=n.disabledUntil?new Date(n.disabledUntil).toISOString():"unknown";return this.logger.warn({tool:e.name,disabledUntil:o,consecutiveFails:n.consecutiveFails},"Skill is auto-disabled due to repeated failures"),{content:`Skill "${e.name}" is temporarily disabled due to repeated failures (${n.consecutiveFails} consecutive). Re-enabled at ${o}.`,isError:!0}}}if(this.securityManager){let n=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!n.allowed)return this.logger.warn({tool:e.name,reason:n.reason,rule:n.matchedRule?.id},"Skill execution denied by security rules"),this.activityLogger?.logSkillExec({userId:t.userId,platform:t.platform,chatId:t.chatId,skillName:e.name,outcome:"denied",error:n.reason}),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:c}=await Promise.resolve().then(()=>(ne(),oe));n=new c(s),o=`agent-${++this.agentIdCounter}`,this.activeAgents.set(o,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:n,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:n,onProgress:s}:s?{...t,onProgress:s}:t,a=Date.now();try{let c=await this.skillSandbox.execute(r,e.input,i,void 0,n);return this.activityLogger?.logSkillExec({userId:t.userId,platform:t.platform,chatId:t.chatId,skillName:e.name,outcome:c.success?"success":"error",durationMs:Date.now()-a,error:c.error}),this.skillHealthTracker&&(c.success?this.skillHealthTracker.recordSuccess(e.name):this.skillHealthTracker.recordFailure(e.name,c.error??"Unknown error")),{content:c.display??(c.success?JSON.stringify(c.data):c.error??"Unknown error"),isError:!c.success,attachments:c.attachments}}catch(c){let d=c instanceof Error?c.message:String(c);throw this.activityLogger?.logSkillExec({userId:t.userId,platform:t.platform,chatId:t.chatId,skillName:e.name,outcome:"error",durationMs:Date.now()-a,error:d}),this.skillHealthTracker?.recordFailure(e.name,d),c}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return n.success?this.skillHealthTracker?.recordSuccess(e.name):this.skillHealthTracker?.recordFailure(e.name,n.error??"Unknown error"),{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){let o=n instanceof Error?n.message:String(n);return this.skillHealthTracker?.recordFailure(e.name,o),{content:`Skill execution failed: ${o}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),n=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${n}s | Last activity ${Math.round(r.idleMs/1e3)}s ago`)}return e.push(""),e.push("If the user asks what you or the agent is doing, describe the above status in natural language."),e.join(`
|
|
1099
1099
|
`)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=Ch));let r=0,n=[];for(let o of s){let i=je(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>xh)break;r+=i,n.push(o)}return n.length<e.length&&this.logger.info({original:e.length,kept:n.length,tokenCount:r,droppedByScore:e.length-s.length},"Memory budget applied"),n}compressToolLoop(e,t,s=0){let r=this.llm.getContextWindow(),n=Math.floor(r.maxInputTokens*iu);if(je(t)+s+e.reduce((h,y)=>h+Ct(y),0)<=n)return;let a=[];for(let h=0;h<e.length-1;h++){let y=e[h],k=e[h+1];y.role==="assistant"&&Array.isArray(y.content)&&y.content.some(S=>S.type==="tool_use")&&k.role==="user"&&Array.isArray(k.content)&&k.content.some(S=>S.type==="tool_result")&&a.push({start:h,end:h+1})}if(a.length<=au)return;let c=a.length-au,d=a.slice(0,c),m=[];for(let h of d){let y=e[h.start],k=[];if(Array.isArray(y.content))for(let C of y.content)C.type==="tool_use"&&k.push(C.name);let S=e[h.end],b="ok";Array.isArray(S.content)&&S.content.some(D=>D.type==="tool_result"&&D.is_error)&&(b="error"),m.push(`- ${k.join(", ")}: ${b}`)}let p=d[0].start,g=d[d.length-1].end-p+1;e.splice(p,g,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
|
|
@@ -1115,20 +1115,20 @@ ${m}`}if(this.documentProcessor&&this.isIngestable(i.mimeType))try{let m=await t
|
|
|
1115
1115
|
|
|
1116
1116
|
`),t}flattenNestedTag(e,t){let s=`<${t}>`,r=`</${t}>`,n=0,o="",i=0;for(;i<e.length;){if(e.slice(i,i+s.length).toLowerCase()===s){n++,n===1&&(o+=s),i+=s.length;continue}if(e.slice(i,i+r.length).toLowerCase()===r){n--,n<=0&&(o+=r,n=0),i+=r.length;continue}o+=e[i],i++}return o}toMarkdown(e){let t=e;return t=t.replace(/<\/?(?:b|strong)>/gi,"**"),t=t.replace(/<\/?(?:i|em)>/gi,"*"),t=t.replace(/<\/?(?:s|del|strike)>/gi,"~~"),t=t.replace(/<code>([^<]*)<\/code>/gi,"`$1`"),t=t.replace(/<pre>([^<]*)<\/pre>/gi,"```\n$1\n```"),t=t.replace(/<a\s+href="([^"]*)"[^>]*>([^<]*)<\/a>/gi,"[$2]($1)"),t=t.replace(/<[^>]+>/g,""),t}toWhatsApp(e){let t=e;return t=t.replace(/<\/?(?:b|strong)>/gi,"**"),t=t.replace(/<\/?(?:i|em)>/gi,"*"),t=t.replace(/<\/?(?:s|del|strike)>/gi,"~~"),t=t.replace(/<[^>]+>/g,""),t=t.replace(/^#{1,6}\s+(.+)$/gm,"*$1*"),t=t.replace(/^[-*_]{3,}\s*$/gm,""),t=t.replace(/\*\*(.+?)\*\*/g,"*$1*"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"_$1_"),t=t.replace(/~~(.+?)~~/g,"~$1~"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}stripFormatting(e){let t=e;return t=t.replace(/<[^>]+>/g,""),t=t.replace(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),t=t.replace(/^#{1,6}\s+/gm,""),t=t.replace(/^[-*_]{3,}\s*$/gm,""),t=t.replace(/\*\*(.+?)\*\*/g,"$1"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"$1"),t=t.replace(/~~(.+?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}escapeHTML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}}});var Kr,Ea=_(()=>{"use strict";Kr=class{static{u(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;let o=this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions});return this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored"),o.id}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content");return}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let c=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:c}});return o.sort((a,c)=>c.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});import{createHash as Lh}from"node:crypto";var Yr,ba=_(()=>{"use strict";Yr=class{static{u(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await import("node:fs"),o=n.readFileSync(t),i=Lh("sha256").update(o).digest("hex"),a=this.docRepo.findByContentHash(e,i);if(a&&a.chunkCount>0)return this.logger.info({documentId:a.id,filename:s,contentHash:i.slice(0,12)},"Document already ingested (duplicate)"),{documentId:a.id,chunkCount:a.chunkCount,existing:!0};a&&a.chunkCount===0&&(this.logger.info({documentId:a.id,filename:s},"Removing failed previous ingest attempt"),this.docRepo.deleteDocument(a.id));let c=await this.extractText(t,r),d=n.statSync(t),m=this.docRepo.createDocument(e,s,r,d.size,i),p=this.chunkText(c,500,50);for(let f=0;f<p.length;f++){let g;try{g=await this.embeddingService.embedAndStore(e,p[f],"document",`${m.id}:${f}`)}catch(h){this.logger.warn({documentId:m.id,chunkIndex:f,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(m.id,f,p[f],g)}return this.docRepo.updateChunkCount(m.id,p.length),this.logger.info({documentId:m.id,filename:s,chunkCount:p.length},"Document ingested"),{documentId:m.id,chunkCount:p.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(c-200,a),m=e.slice(d,c+200),p=m.lastIndexOf(`
|
|
1117
1117
|
|
|
1118
|
-
`);if(p>0)c=d+p;else{let g=m.lastIndexOf(". ");g>0&&(c=d+g+1)}let f=e.slice(a,c).trim();f&&i.push(f),a=c-o}return i.filter(c=>c.length>0)}}});var Jr,Sa=_(()=>{"use strict";ut();Jr=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;activityLogger;skillHealthTracker;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;persistentRunner;constructor(e,t,s,r,n,o,i,a){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o,this.activityLogger=i,this.skillHealthTracker=a}setPersistentRunner(e){this.persistentRunner=e}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started"),this.persistentRunner?.recoverInterrupted().catch(e=>{this.logger.error({err:e},"Failed to recover interrupted persistent tasks")})}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.claimPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){if(e.maxDurationHours&&this.persistentRunner){await this.persistentRunner.runPersistent(e);return}let t=Date.now();try{let s=this.skillRegistry.get(e.skillName);if(!s){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}if(this.skillHealthTracker?.isDisabled(e.skillName)){this.taskRepo.updateStatus(e.id,"failed",void 0,`Skill "${e.skillName}" is temporarily disabled due to repeated failures`);return}let r;try{r=JSON.parse(e.skillInput)}catch(d){this.logger.warn({taskId:e.id,err:d},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:n}
|
|
1118
|
+
`);if(p>0)c=d+p;else{let g=m.lastIndexOf(". ");g>0&&(c=d+g+1)}let f=e.slice(a,c).trim();f&&i.push(f),a=c-o}return i.filter(c=>c.length>0)}}});var Jr,Sa=_(()=>{"use strict";ut();Jr=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;activityLogger;skillHealthTracker;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;persistentRunner;constructor(e,t,s,r,n,o,i,a){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o,this.activityLogger=i,this.skillHealthTracker=a}setPersistentRunner(e){this.persistentRunner=e}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started"),this.persistentRunner?.recoverInterrupted().catch(e=>{this.logger.error({err:e},"Failed to recover interrupted persistent tasks")})}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.claimPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){if(e.maxDurationHours&&this.persistentRunner){await this.persistentRunner.runPersistent(e);return}let t=Date.now();try{let s=this.skillRegistry.get(e.skillName);if(!s){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}if(this.skillHealthTracker?.isDisabled(e.skillName)){this.taskRepo.updateStatus(e.id,"failed",void 0,`Skill "${e.skillName}" is temporarily disabled due to repeated failures`);return}let r;try{r=JSON.parse(e.skillInput)}catch(d){this.logger.warn({taskId:e.id,err:d},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:n}=$e(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),o=new Promise((d,m)=>setTimeout(()=>m(new Error("Background task timed out")),this.taskTimeoutMs)),i=await Promise.race([this.skillSandbox.execute(s,r,n),o]),a=JSON.stringify(i.data??i.display??i.error);this.taskRepo.updateStatus(e.id,i.success?"completed":"failed",a,i.error),this.activityLogger?.logBackgroundTask({taskId:e.id,skillName:e.skillName,platform:e.platform,chatId:e.chatId,userId:e.userId,outcome:i.success?"success":"error",durationMs:Date.now()-t,error:i.error}),this.skillHealthTracker&&(i.success?this.skillHealthTracker.recordSuccess(e.skillName):this.skillHealthTracker.recordFailure(e.skillName,i.error??"Unknown error"));let c=this.adapters.get(e.platform);if(c){let d=i.success?`\u2705 Background task completed: ${e.description}
|
|
1119
1119
|
|
|
1120
1120
|
Result: ${i.display??JSON.stringify(i.data)}`:`\u274C Background task failed: ${e.description}
|
|
1121
1121
|
|
|
1122
1122
|
Error: ${i.error}`;await c.sendMessage(e.chatId,d)}}catch(s){let r=s instanceof Error?s.message:String(s);this.taskRepo.updateStatus(e.id,"failed",void 0,r),this.logger.error({taskId:e.id,err:s},"Background task failed"),this.activityLogger?.logBackgroundTask({taskId:e.id,skillName:e.skillName,platform:e.platform,chatId:e.chatId,userId:e.userId,outcome:"error",durationMs:Date.now()-t,error:r}),this.skillHealthTracker?.recordFailure(e.skillName,r);let n=this.adapters.get(e.platform);n&&await n.sendMessage(e.chatId,`\u274C Background task failed: ${e.description}
|
|
1123
1123
|
|
|
1124
|
-
Error: ${r}`)}}}});var Dh,Zr,va=_(()=>{"use strict";ut();Dh=5,Zr=class{static{u(this,"PersistentAgentRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;activityLogger;activeAbortControllers=new Map;constructor(e,t,s,r,n,o,i){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o,this.activityLogger=i}async recoverInterrupted(){try{let e=this.taskRepo.getInterrupted();for(let t of e)t.agentState?(this.logger.info({taskId:t.id,resumeCount:t.resumeCount},"Recovering interrupted persistent task"),this.resume(t).catch(s=>{this.logger.error({err:s,taskId:t.id},"Failed to recover interrupted task")})):(this.taskRepo.updateStatus(t.id,"failed",void 0,"Process restarted without checkpoint"),this.logger.warn({taskId:t.id},"Interrupted task without checkpoint marked as failed"),this.notifyUser(t,"\u274C Hintergrund-Task abgebrochen (Prozess-Neustart ohne Checkpoint)"))}catch(e){this.logger.error({err:e},"Failed to recover interrupted tasks")}}async runPersistent(e){if(!this.taskRepo.claimTask(e.id)){this.logger.info({taskId:e.id},"Task already claimed by another runner, skipping");return}let t=(e.maxDurationHours??24)*36e5,s=new AbortController;this.activeAbortControllers.set(e.id,s);try{let r=this.skillRegistry.get(e.skillName);if(!r){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let n;try{n=JSON.parse(e.skillInput)}catch{this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:o}
|
|
1124
|
+
Error: ${r}`)}}}});var Dh,Zr,va=_(()=>{"use strict";ut();Dh=5,Zr=class{static{u(this,"PersistentAgentRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;activityLogger;activeAbortControllers=new Map;constructor(e,t,s,r,n,o,i){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o,this.activityLogger=i}async recoverInterrupted(){try{let e=this.taskRepo.getInterrupted();for(let t of e)t.agentState?(this.logger.info({taskId:t.id,resumeCount:t.resumeCount},"Recovering interrupted persistent task"),this.resume(t).catch(s=>{this.logger.error({err:s,taskId:t.id},"Failed to recover interrupted task")})):(this.taskRepo.updateStatus(t.id,"failed",void 0,"Process restarted without checkpoint"),this.logger.warn({taskId:t.id},"Interrupted task without checkpoint marked as failed"),this.notifyUser(t,"\u274C Hintergrund-Task abgebrochen (Prozess-Neustart ohne Checkpoint)"))}catch(e){this.logger.error({err:e},"Failed to recover interrupted tasks")}}async runPersistent(e){if(!this.taskRepo.claimTask(e.id)){this.logger.info({taskId:e.id},"Task already claimed by another runner, skipping");return}let t=(e.maxDurationHours??24)*36e5,s=new AbortController;this.activeAbortControllers.set(e.id,s);try{let r=this.skillRegistry.get(e.skillName);if(!r){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let n;try{n=JSON.parse(e.skillInput)}catch{this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:o}=$e(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),i=Date.now()-new Date(e.createdAt).getTime();if(i>t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Max duration of ${e.maxDurationHours}h exceeded`),this.notifyUser(e,`\u274C Persistenter Task "${e.description}" abgebrochen: maximale Laufzeit \xFCberschritten.`),this.logLifecycle(e,"expired");return}let a;if(e.agentState)try{let h=JSON.parse(e.agentState);h.conversationHistory?.length>0&&(a={conversationHistory:h.conversationHistory,currentIteration:h.currentIteration,totalIterations:h.totalIterations,dataStore:h.dataStore},this.logger.info({taskId:e.id,iteration:h.currentIteration,totalIterations:h.totalIterations},"Resuming persistent task from checkpoint"))}catch(h){this.logger.warn({taskId:e.id,err:h},"Failed to parse checkpoint, starting fresh")}let c=a?.currentIteration??0,d={...o,resumeState:a,abortSignal:s.signal,onIteration:u(h=>{if(h.iteration-c>=Dh||s.signal.aborted){c=h.iteration;let y={conversationHistory:h.messages,partialResults:[],currentIteration:h.iteration,totalIterations:h.maxIterations,startedAt:e.startedAt??e.createdAt,lastActivityAt:new Date().toISOString(),dataStore:h.dataStore};try{this.taskRepo.checkpoint(e.id,JSON.stringify(y)),this.logLifecycle(e,"checkpoint"),this.logger.debug({taskId:e.id,iteration:h.iteration},"Persistent task checkpointed")}catch(k){this.logger.warn({err:k,taskId:e.id},"Failed to write checkpoint, retrying once");try{this.taskRepo.checkpoint(e.id,JSON.stringify(y)),this.logger.info({taskId:e.id},"Checkpoint retry succeeded")}catch(S){this.logger.error({err:S,taskId:e.id},"Checkpoint retry failed, aborting task"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Checkpoint write failed after retry"),s.abort()}}}},"onIteration")},m=t-i,p=new Promise((h,y)=>setTimeout(()=>y(new Error(`Max duration of ${e.maxDurationHours}h exceeded`)),m)),f=await Promise.race([this.skillSandbox.execute(r,n,d),p]);if(this.activeAbortControllers.delete(e.id),s.signal.aborted){this.logger.info({taskId:e.id},"Persistent task paused via abort"),this.notifyUser(e,`\u23F8\uFE0F Persistenter Task pausiert: ${e.description}`);return}let g=JSON.stringify(f.data??f.display??f.error);this.taskRepo.updateStatus(e.id,f.success?"completed":"failed",g,f.error),this.notifyUser(e,f.success?`\u2705 Persistenter Task abgeschlossen: ${e.description}
|
|
1125
1125
|
|
|
1126
1126
|
Ergebnis: ${f.display??JSON.stringify(f.data)}`:`\u274C Persistenter Task fehlgeschlagen: ${e.description}
|
|
1127
1127
|
|
|
1128
1128
|
Fehler: ${f.error}`)}catch(r){this.activeAbortControllers.delete(e.id);let n=r instanceof Error?r.message:String(r);if(s.signal.aborted){this.logger.info({taskId:e.id},"Persistent task paused via abort"),this.notifyUser(e,`\u23F8\uFE0F Persistenter Task pausiert: ${e.description}`);return}this.taskRepo.updateStatus(e.id,"failed",void 0,n),this.logger.error({taskId:e.id,err:r},"Persistent task failed"),this.notifyUser(e,`\u274C Persistenter Task fehlgeschlagen: ${e.description}
|
|
1129
1129
|
|
|
1130
|
-
Fehler: ${n}`)}}async resume(e){this.taskRepo.markResuming(e.id),this.logLifecycle(e,"resume");let t=this.taskRepo.getById(e.id);if(!t){this.logger.warn({taskId:e.id},"Task disappeared during resume");return}await this.runPersistent(t)}async pause(e){this.taskRepo.updateStatus(e,"checkpointed");let t=this.activeAbortControllers.get(e);t&&(t.abort(),this.activeAbortControllers.delete(e)),this.logLifecycle({id:e,skillName:"",platform:"",chatId:"",userId:""},"pause"),this.logger.info({taskId:e},"Persistent task paused")}async cancel(e){let t=this.activeAbortControllers.get(e);t&&(t.abort(),this.activeAbortControllers.delete(e)),this.taskRepo.cancelTask(e),this.logger.info({taskId:e},"Persistent task cancelled")}async notifyUser(e,t){let s=this.adapters.get(e.platform);if(s)try{await s.sendMessage(e.chatId,t)}catch{}}logLifecycle(e,t){this.activityLogger?.logAgentLifecycle({taskId:e.id,skillName:e.skillName,event:t,platform:e.platform,chatId:e.chatId,userId:e.userId})}}});import Mh from"node:crypto";var Qr,$a=_(()=>{"use strict";ut();Qr=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;activityLogger;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,c,d,m){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,this.activityLogger=m}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(),s=Date.now();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let r,n="text";if(e.skillName&&this.skillRegistry.has(e.skillName)){let f=this.skillRegistry.get(e.skillName);try{let g;try{g=JSON.parse(e.skillInput)}catch{g={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:h}
|
|
1131
|
-
${r}`;this.conversationManager.addMessage(g.id,"assistant",h)}}catch(g){this.logger.error({err:g,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let f=`scheduled-${e.id}`,g=this.conversationManager.getOrCreateConversation(e.platform,f,e.userId);this.conversationManager.pruneMessages(g.id,20)}catch{}let p=this.calculateNextRun(e);p?this.actionRepo.updateLastRun(e.id,t,p):(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 As(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 mo(l,e,t,s){let r=Oh(l);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=
|
|
1130
|
+
Fehler: ${n}`)}}async resume(e){this.taskRepo.markResuming(e.id),this.logLifecycle(e,"resume");let t=this.taskRepo.getById(e.id);if(!t){this.logger.warn({taskId:e.id},"Task disappeared during resume");return}await this.runPersistent(t)}async pause(e){this.taskRepo.updateStatus(e,"checkpointed");let t=this.activeAbortControllers.get(e);t&&(t.abort(),this.activeAbortControllers.delete(e)),this.logLifecycle({id:e,skillName:"",platform:"",chatId:"",userId:""},"pause"),this.logger.info({taskId:e},"Persistent task paused")}async cancel(e){let t=this.activeAbortControllers.get(e);t&&(t.abort(),this.activeAbortControllers.delete(e)),this.taskRepo.cancelTask(e),this.logger.info({taskId:e},"Persistent task cancelled")}async notifyUser(e,t){let s=this.adapters.get(e.platform);if(s)try{await s.sendMessage(e.chatId,t)}catch{}}logLifecycle(e,t){this.activityLogger?.logAgentLifecycle({taskId:e.id,skillName:e.skillName,event:t,platform:e.platform,chatId:e.chatId,userId:e.userId})}}});import Mh from"node:crypto";var Qr,$a=_(()=>{"use strict";ut();Qr=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;activityLogger;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,c,d,m){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,this.activityLogger=m}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(),s=Date.now();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let r,n="text";if(e.skillName&&this.skillRegistry.has(e.skillName)){let f=this.skillRegistry.get(e.skillName);try{let g;try{g=JSON.parse(e.skillInput)}catch{g={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:h}=$e(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),y=await this.skillSandbox.execute(f,g,h);if(y.success){let k=y.display??JSON.stringify(y.data);if(this.formatter){let S=this.formatter.format(k,e.platform);r=S.text,n=S.parseMode}else r=k}else r=`\u274C Scheduled action "${e.name}" failed: ${y.error}`}catch(g){let h=g instanceof Error?g.message:String(g);r=`\u274C Scheduled action "${e.name}" failed: ${h}`}}else if(e.promptTemplate&&this.pipeline)try{let f=`scheduled-${e.id}`,g=this.users.findById(e.userId),h=g?.platformUserId??e.userId,y={id:`scheduled-${Mh.randomUUID()}`,platform:e.platform,chatId:f,chatType:"dm",userId:h,userName:g?.username??h,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"}},k=await this.pipeline.process(y),S=this.formatter?this.formatter.format(k.text,e.platform):{text:k.text,parseMode:"text"};r=S.text,n=S.parseMode;let b=this.adapters.get(e.platform);if(b&&k.attachments)for(let C of k.attachments)try{let D=C.mimeType.startsWith("image/"),U=C.mimeType==="audio/ogg"||C.mimeType==="audio/opus";D?await b.sendPhoto(e.chatId,C.data,C.fileName):U?await b.sendVoice(e.chatId,C.data):await b.sendFile(e.chatId,C.data,C.fileName)}catch(D){this.logger.warn({err:D,fileName:C.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(f){let g=f instanceof Error?f.message:String(f);this.logger.error({actionId:e.id,err:f},"Pipeline execution failed for scheduled action"),r=`Scheduled action "${e.name}" failed: ${g}`}else if(e.promptTemplate)try{r=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(f){let g=f instanceof Error?f.message:String(f);this.logger.error({actionId:e.id,err:f},"LLM call failed for scheduled action"),r=`Scheduled action "${e.name}" failed: ${g}`}else this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),r=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;let o=r.startsWith("\u274C");this.activityLogger?.logScheduledExec({actionId:e.id,actionName:e.name,skillName:e.skillName??void 0,platform:e.platform,chatId:e.chatId,userId:e.userId,outcome:o?"error":"success",durationMs:Date.now()-s,error:o?r:void 0});let i=r.trim(),a=(e.promptTemplate??"").toLowerCase(),c=/nichts|silent|no\s*output|don't\s*respond|do\s*not\s*respond/i.test(a),d=/offline|down|fehler|error|warn|critical|alert|fail|nicht\s+(erreichbar|verf[uü]gbar|gefunden|online)|ausgefallen|stopped|unreachable|unavailable|⚠|❌|🚨|🔴/i.test(i)&&!/keine\s+(probleme|fehler|auff[aä]lligkeiten)/i.test(i);if(!i||i.length<3||c&&!d)this.logger.info({actionId:e.id,name:e.name},"Scheduled action produced no actionable output \u2014 skipping notification");else{let f=this.adapters.get(e.platform);if(f)try{if(await f.sendMessage(e.chatId,r,{parseMode:n!=="text"?n:void 0}),e.promptTemplate&&this.conversationManager){let g=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,e.userId),h=`[Automated Scheduled Alert: ${e.name}]
|
|
1131
|
+
${r}`;this.conversationManager.addMessage(g.id,"assistant",h)}}catch(g){this.logger.error({err:g,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let f=`scheduled-${e.id}`,g=this.conversationManager.getOrCreateConversation(e.platform,f,e.userId);this.conversationManager.pruneMessages(g.id,20)}catch{}let p=this.calculateNextRun(e);p?this.actionRepo.updateLastRun(e.id,t,p):(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 As(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 mo(l,e,t,s){let r=Oh(l);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=Ne(l),o=Ne(t);if(n===null||o===null)return{triggered:!1,displayValue:r};if(!(e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o))return{triggered:!1,displayValue:r};let a=Ne(s);return a!==null&&(e==="lt"?a<o:e==="gt"?a>o:e==="lte"?a<=o:a>=o)?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}}case"eq":{let n=Ne(l),o=Ne(t);if(n!==null&&o!==null){if(n!==o)return{triggered:!1,displayValue:r};let c=Ne(s);return c!==null&&c===o?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}}let i=String(l),a=String(t);return i!==a?{triggered:!1,displayValue:r}:String(s)===a?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}}case"neq":{let n=Ne(l),o=Ne(t);if(n!==null&&o!==null){if(n===o)return{triggered:!1,displayValue:r};let c=Ne(s);return c!==null&&c!==o?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}}let i=String(l),a=String(t);return i===a?{triggered:!1,displayValue:r}:String(s)!==a?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}}case"contains":return String(l).includes(String(t??""))?String(s).includes(String(t??""))?{triggered:!1,displayValue:r}:{triggered:!0,displayValue:r}:{triggered:!1,displayValue:r};case"not_contains":return String(l).includes(String(t??""))?{triggered:!1,displayValue:r}:String(s).includes(String(t??""))?{triggered:!0,displayValue:r}:{triggered:!1,displayValue:r};case"changed":return{triggered:JSON.stringify(l)!==JSON.stringify(s),displayValue:r};case"increased":{let n=Ne(l),o=Ne(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=Ne(l),o=Ne(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function Ia(l,e,t){let s={},r={},n=[];for(let i of e.conditions){let a=As(l,i.field),c=t?.[i.field]??null,{triggered:d,displayValue:m}=mo(a,i.operator,i.value,c);n.push(d),s[i.field]=m,r[i.field]=a}return{triggered:e.logic==="and"?n.every(Boolean):n.some(Boolean),displayValues:s,newLastValues:r}}function Ne(l){if(typeof l=="number")return l;let e=parseFloat(String(l));return isNaN(e)?null:e}function Oh(l){return l==null?"null":typeof l=="object"?JSON.stringify(l):String(l)}var po=_(()=>{"use strict";u(As,"extractField");u(mo,"evaluateCondition");u(Ia,"evaluateCompositeCondition");u(Ne,"toNumber");u(Oh,"formatValue")});function en(l,e){return l.replace(/\{\{([^}]+)\}\}/g,(t,s)=>{let r=As(e,s.trim());return r==null?"":typeof r=="object"?JSON.stringify(r):String(r)})}function Ht(l,e){let t={};for(let[s,r]of Object.entries(l))typeof r=="string"?t[s]=en(r,e):r!==null&&typeof r=="object"&&!Array.isArray(r)?t[s]=Ht(r,e):Array.isArray(r)?t[s]=r.map(n=>typeof n=="string"?en(n,e):n!==null&&typeof n=="object"&&!Array.isArray(n)?Ht(n,e):n):t[s]=r;return t}var ho=_(()=>{"use strict";po();u(en,"resolveTemplates");u(Ht,"resolveTemplatesInObject")});var Uh,fo,cu=_(()=>{"use strict";po();ho();ut();Uh={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},fo=class{static{u(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;confirmationQueue;activityLogger;skillHealthTracker;llmProvider;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,c,d){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o,this.confirmationQueue=i,this.activityLogger=a,this.skillHealthTracker=c,this.llmProvider=d}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}if(this.skillHealthTracker?.isDisabled(e.skillName)){this.logger.debug({watchId:e.id,skillName:e.skillName},"Watch poll skill is auto-disabled, skipping"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=$e(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.skillHealthTracker?.recordFailure(e.skillName,n.error??"Watch poll failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}this.skillHealthTracker?.recordSuccess(e.skillName);let o,i,a;if(e.compositeCondition){let c=null;if(e.lastValue!==null)try{let m=JSON.parse(e.lastValue);c=m!==null&&typeof m=="object"&&!Array.isArray(m)?m:null}catch{}let d=Ia(n.data,e.compositeCondition,c);o=d.triggered,a=JSON.stringify(d.newLastValues),i=Object.entries(d.displayValues).map(([m,p])=>`${m}=${p}`).join(", ")}else{let c=As(n.data,e.condition.field),d=e.lastValue!==null?JSON.parse(e.lastValue):null,m=mo(c,e.condition.operator,e.condition.value,d);o=m.triggered,i=m.displayValue,a=JSON.stringify(c)}if(o&&this.isCooldownExpired(e)){let c=e.actionOnTrigger??"alert",d={result:n.data,currentValue:i,watchName:e.name},m=e.actionSkillParams?Ht(e.actionSkillParams,d):{},p=e.messageTemplate?en(e.messageTemplate,d):void 0;if(e.requiresConfirmation&&this.confirmationQueue&&(c==="action_only"||c==="alert_and_action")&&e.actionSkillName){if(await this.confirmationQueue.enqueue({chatId:e.chatId,platform:e.platform,source:"watch",sourceId:e.id,description:`Watch "${e.name}": ${e.actionSkillName} ausf\xFChren`,skillName:e.actionSkillName,skillParams:m}),c==="alert_and_action"){let g=await this.buildAlertText(e,i,n.data,p);g+=`
|
|
1132
1132
|
|
|
1133
1133
|
(Aktion wartet auf Best\xE4tigung)`;let h=this.adapters.get(e.platform);if(h)try{await h.sendMessage(e.chatId,g)}catch{}}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:a,lastTriggeredAt:t});return}let f=null;if((c==="action_only"||c==="alert_and_action")&&e.actionSkillName)if(this.skillHealthTracker?.isDisabled(e.actionSkillName))f=`Action skill "${e.actionSkillName}" is temporarily disabled due to repeated failures`,this.watchRepo.updateActionError(e.id,f),this.logger.warn({watchId:e.id,skillName:e.actionSkillName},"Watch action skill is auto-disabled");else{let g=this.skillRegistry.get(e.actionSkillName);if(g)try{await this.skillSandbox.execute(g,m,r),this.watchRepo.updateActionError(e.id,null),this.skillHealthTracker?.recordSuccess(e.actionSkillName),this.activityLogger?.logWatchAction({watchId:e.id,watchName:e.name,skillName:e.actionSkillName,platform:e.platform,chatId:e.chatId,outcome:"success"})}catch(h){f=h instanceof Error?h.message:String(h),this.watchRepo.updateActionError(e.id,f),this.skillHealthTracker?.recordFailure(e.actionSkillName,f),this.logger.warn({watchId:e.id,err:h},"Watch action failed"),this.activityLogger?.logWatchAction({watchId:e.id,watchName:e.name,skillName:e.actionSkillName,platform:e.platform,chatId:e.chatId,outcome:"error",error:f})}else f=`Action skill "${e.actionSkillName}" not found`,this.watchRepo.updateActionError(e.id,f),this.logger.warn({watchId:e.id,skillName:e.actionSkillName},"Unknown action skill for watch")}if(c==="alert"||c==="alert_and_action"){let g=await this.buildAlertText(e,i,n.data,p);f&&(g+=`
|
|
1134
1134
|
|
|
@@ -1212,7 +1212,7 @@ ${c}`)}let a=this.adapters.get(this.defaultPlatform);if(a)try{await a.sendMessag
|
|
|
1212
1212
|
${a.join(`
|
|
1213
1213
|
|
|
1214
1214
|
`)}`,d=this.adapters.get(this.defaultPlatform);if(d){await d.sendMessage(this.defaultChatId,c);for(let m of a)this.markSent(m);this.logger.info({durationMs:o,insights:a.length},"Reasoning pass: insights sent")}this.activityLogger?.logScheduledExec({actionId:"reasoning-engine",actionName:"Reasoning Engine",platform:this.defaultPlatform,chatId:this.defaultChatId,userId:this.defaultChatId,outcome:"success",durationMs:o})}catch(e){this.logger.error({err:e},"Reasoning pass failed"),this.activityLogger?.logScheduledExec({actionId:"reasoning-engine",actionName:"Reasoning Engine",platform:this.defaultPlatform,chatId:this.defaultChatId,userId:this.defaultChatId,outcome:"error",error:e instanceof Error?e.message:String(e)})}}}async collectContext(){let e=new Date,t=e.toLocaleString("de-AT",{weekday:"long",year:"numeric",month:"long",day:"numeric",hour:"2-digit",minute:"2-digit"}),[s,r,n]=await Promise.all([this.fetchCalendar(e),this.fetchSkillData("weather",{}),this.fetchSkillData("energy_price",{action:"current"})]),o=this.fetchTodos(),i=this.fetchWatches(),a=this.fetchMemories(),c=this.fetchActivity(),d=this.fetchSkillHealth();return{dateTime:t,events:s,todos:o,watches:i,memories:a,activity:c,weather:r,energy:n,skillHealth:d}}async fetchCalendar(e){if(!this.calendarProvider)return"(Kalender nicht konfiguriert)";try{let t=e,s=new Date(e.getTime()+24*60*60*1e3),r=await this.calendarProvider.listEvents(t,s);return r.length===0?"Keine Termine in den n\xE4chsten 24h.":r.map(n=>{let o=n.start instanceof Date?n.start.toLocaleTimeString("de-AT",{hour:"2-digit",minute:"2-digit"}):String(n.start),i=n.location?` (${n.location})`:"";return`- ${o}: ${n.title??"Termin"}${i}`}).join(`
|
|
1215
|
-
`)}catch(t){return this.logger.warn({err:t},"Reasoning: calendar fetch failed"),"(Kalender-Abfrage fehlgeschlagen)"}}async fetchSkillData(e,t){let s=this.skillRegistry.get(e);if(!s)return`(${e} nicht verf\xFCgbar)`;try{let{context:r}
|
|
1215
|
+
`)}catch(t){return this.logger.warn({err:t},"Reasoning: calendar fetch failed"),"(Kalender-Abfrage fehlgeschlagen)"}}async fetchSkillData(e,t){let s=this.skillRegistry.get(e);if(!s)return`(${e} nicht verf\xFCgbar)`;try{let{context:r}=$e(this.userRepo,{userId:this.defaultChatId,platform:this.defaultPlatform,chatId:this.defaultChatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,t,r);return n.success?n.display??JSON.stringify(n.data):`(${e}: ${n.error})`}catch(r){return this.logger.warn({err:r,skillName:e},"Reasoning: skill fetch failed"),`(${e}-Abfrage fehlgeschlagen)`}}fetchTodos(){try{let e=this.todoRepo.getOverdue(),t=new Date(Date.now()+24*60*60*1e3).toISOString(),s=this.todoRepo.getDueInWindow(t),r=this.todoRepo.list(this.defaultChatId),n=[];if(e.length>0){n.push(`\xDCberf\xE4llig (${e.length}):`);for(let o of e.slice(0,10))n.push(` - [${o.priority}] ${o.title} (f\xE4llig: ${o.dueDate})`)}if(s.length>0){n.push(`Bald f\xE4llig (${s.length}):`);for(let o of s.slice(0,10))n.push(` - [${o.priority}] ${o.title} (f\xE4llig: ${o.dueDate})`)}return r.length>0&&n.push(`Gesamt offene Todos: ${r.length}`),n.length>0?n.join(`
|
|
1216
1216
|
`):"Keine offenen Todos."}catch(e){return this.logger.warn({err:e},"Reasoning: todo fetch failed"),"(Todo-Abfrage fehlgeschlagen)"}}fetchWatches(){try{let e=this.watchRepo.getEnabled();return e.length===0?"Keine aktiven Watches.":e.map(t=>{let s=t.lastValue?(()=>{try{let n=JSON.parse(t.lastValue);return typeof n=="object"?JSON.stringify(n).slice(0,200):String(n)}catch{return t.lastValue.slice(0,200)}})():"noch kein Ergebnis",r=t.lastTriggeredAt?`letzter Alert: ${new Date(t.lastTriggeredAt).toLocaleString("de-AT")}`:"noch nie ausgel\xF6st";return`- "${t.name}" (${t.skillName}, alle ${t.intervalMinutes} Min) \u2192 ${r}
|
|
1217
1217
|
Letzter Wert: ${s}`}).join(`
|
|
1218
1218
|
`)}catch(e){return this.logger.warn({err:e},"Reasoning: watch fetch failed"),"(Watch-Abfrage fehlgeschlagen)"}}fetchMemories(){try{let e=this.memoryRepo.getRecentForPrompt(this.defaultChatId,30);return e.length===0?"Keine gespeicherten Erinnerungen.":e.map(t=>`- [${t.type}] ${t.key}: ${t.value}`).join(`
|
|
@@ -1264,19 +1264,19 @@ ${e.weather}
|
|
|
1264
1264
|
${e.energy}
|
|
1265
1265
|
|
|
1266
1266
|
=== Skill-Status ===
|
|
1267
|
-
${e.skillHealth}`}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}insightHash(e){let t=e.slice(0,100).toLowerCase().replace(/\s+/g," ");return Xh.createHash("sha256").update(t).digest("hex").slice(0,16)}wasRecentlySent(e){let s=`reasoning:${this.insightHash(e)}`;return this.notifRepo.wasNotified(s,this.defaultChatId)}markSent(e){let s=`reasoning:${this.insightHash(e)}`,r=new Date(Date.now()+this.deduplicationHours*60*60*1e3).toISOString();this.notifRepo.markNotified(s,this.defaultChatId,this.defaultPlatform,r)}}});import{EventEmitter as Yh}from"node:events";var
|
|
1267
|
+
${e.skillHealth}`}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}insightHash(e){let t=e.slice(0,100).toLowerCase().replace(/\s+/g," ");return Xh.createHash("sha256").update(t).digest("hex").slice(0,16)}wasRecentlySent(e){let s=`reasoning:${this.insightHash(e)}`;return this.notifRepo.wasNotified(s,this.defaultChatId)}markSent(e){let s=`reasoning:${this.insightHash(e)}`,r=new Date(Date.now()+this.deduplicationHours*60*60*1e3).toISOString();this.notifRepo.markNotified(s,this.defaultChatId,this.defaultPlatform,r)}}});import{EventEmitter as Yh}from"node:events";var ge,nt=_(()=>{"use strict";ge=class extends Yh{static{u(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}async sendVoice(e,t,s){}endStream(e){}getStatus(){return this.status}splitText(e,t){if(e.length<=t)return[e];let s=[],r=e;for(;r.length>0;){if(r.length<=t){s.push(r);break}let n=-1,i=r.slice(0,t).lastIndexOf(`
|
|
1268
1268
|
|
|
1269
|
-
`);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as Jh,InputFile as Ha}from"grammy";function lu(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var go,du=_(()=>{"use strict";nt();u(lu,"mapParseMode");go=class extends fe{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new Jh(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:lu(s?.parseMode)});n=String(i.message_id)}return n}async editMessage(e,t,s,r){await this.bot.api.editMessageText(Number(e),Number(t),s,{parse_mode:lu(r?.parseMode)})}async deleteMessage(e,t){await this.bot.api.deleteMessage(Number(e),Number(t))}async sendPhoto(e,t,s){let r=await this.bot.api.sendPhoto(Number(e),new Ha(t,"image.png"),{caption:s});return String(r.message_id)}async sendFile(e,t,s,r){let n=await this.bot.api.sendDocument(Number(e),new Ha(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Ha(t,"voice.ogg"),{caption:s});return String(r.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let c=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:c.length,data:c}}catch(n){console.error("[telegram] Failed to download file",e,n instanceof Error?n.message:"Unknown error");return}}}});import{Client as Zh,GatewayIntentBits as yo,Events as Ba}from"discord.js";var To,uu=_(()=>{"use strict";nt();To=class extends fe{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new Zh({intents:[yo.Guilds,yo.GuildMessages,yo.MessageContent,yo.DirectMessages]}),this.client.on(Ba.MessageCreate,async e=>{if(!e.author.bot)try{let t=await this.downloadAttachments(e),s=e.content||this.inferTextFromAttachments(t),r={id:e.id,platform:"discord",chatId:e.channelId,chatType:e.channel.isDMBased()?"dm":"group",userId:e.author.id,userName:e.author.username,displayName:e.author.displayName,text:s,timestamp:e.createdAt,replyToMessageId:e.reference?.messageId??void 0,attachments:t.length>0?t:void 0};this.emit("message",r)}catch(t){this.emit("error",t instanceof Error?t:new Error(String(t)))}}),this.client.on(Ba.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Ba.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var wo,mu=_(()=>{"use strict";nt();wo=class extends fe{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),c=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of c)try{let m=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(m.status===404)continue;if(!m.ok){console.error(`[matrix] Download failed (${m.status})`,s,d);continue}let p=await m.arrayBuffer(),f=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??f.length,data:f}}catch(m){console.error("[matrix] Download error",s,d,m);continue}console.error("[matrix] All download endpoints failed for",s)}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var _o,pu=_(()=>{"use strict";nt();_o=class extends fe{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let{makeWASocket:e,useMultiFileAuthState:t,DisconnectReason:s,downloadMediaMessage:r}=await import("@whiskeysockets/baileys");this.downloadMedia=r;let{state:n,saveCreds:o}=await t(this.dataPath);this.socket=e({auth:n,printQRInTerminal:!0}),this.socket.ev.on("creds.update",o),this.socket.ev.on("connection.update",i=>{if(i.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),i.connection==="close"){let c=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),c){let d=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),d)}}}),this.socket.ev.on("messages.upsert",({messages:i,type:a})=>{if(a==="notify")for(let c of i)c.message&&(c.key.fromMe||this.processMessage(c).catch(d=>{this.emit("error",d instanceof Error?d:new Error(String(d)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var ko,hu=_(()=>{"use strict";nt();ko=class extends fe{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let d=await c.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let m=await this.downloadAttachment(d);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Wa from"node:readline";var Eo,fu=_(()=>{"use strict";nt();Eo=class extends fe{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Wa.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
|
|
1269
|
+
`);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as Jh,InputFile as Ha}from"grammy";function lu(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var go,du=_(()=>{"use strict";nt();u(lu,"mapParseMode");go=class extends ge{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new Jh(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:lu(s?.parseMode)});n=String(i.message_id)}return n}async editMessage(e,t,s,r){await this.bot.api.editMessageText(Number(e),Number(t),s,{parse_mode:lu(r?.parseMode)})}async deleteMessage(e,t){await this.bot.api.deleteMessage(Number(e),Number(t))}async sendPhoto(e,t,s){let r=await this.bot.api.sendPhoto(Number(e),new Ha(t,"image.png"),{caption:s});return String(r.message_id)}async sendFile(e,t,s,r){let n=await this.bot.api.sendDocument(Number(e),new Ha(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Ha(t,"voice.ogg"),{caption:s});return String(r.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let c=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:c.length,data:c}}catch(n){console.error("[telegram] Failed to download file",e,n instanceof Error?n.message:"Unknown error");return}}}});import{Client as Zh,GatewayIntentBits as yo,Events as Ba}from"discord.js";var To,uu=_(()=>{"use strict";nt();To=class extends ge{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new Zh({intents:[yo.Guilds,yo.GuildMessages,yo.MessageContent,yo.DirectMessages]}),this.client.on(Ba.MessageCreate,async e=>{if(!e.author.bot)try{let t=await this.downloadAttachments(e),s=e.content||this.inferTextFromAttachments(t),r={id:e.id,platform:"discord",chatId:e.channelId,chatType:e.channel.isDMBased()?"dm":"group",userId:e.author.id,userName:e.author.username,displayName:e.author.displayName,text:s,timestamp:e.createdAt,replyToMessageId:e.reference?.messageId??void 0,attachments:t.length>0?t:void 0};this.emit("message",r)}catch(t){this.emit("error",t instanceof Error?t:new Error(String(t)))}}),this.client.on(Ba.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Ba.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var wo,mu=_(()=>{"use strict";nt();wo=class extends ge{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),c=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of c)try{let m=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(m.status===404)continue;if(!m.ok){console.error(`[matrix] Download failed (${m.status})`,s,d);continue}let p=await m.arrayBuffer(),f=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??f.length,data:f}}catch(m){console.error("[matrix] Download error",s,d,m);continue}console.error("[matrix] All download endpoints failed for",s)}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var _o,pu=_(()=>{"use strict";nt();_o=class extends ge{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let{makeWASocket:e,useMultiFileAuthState:t,DisconnectReason:s,downloadMediaMessage:r}=await import("@whiskeysockets/baileys");this.downloadMedia=r;let{state:n,saveCreds:o}=await t(this.dataPath);this.socket=e({auth:n,printQRInTerminal:!0}),this.socket.ev.on("creds.update",o),this.socket.ev.on("connection.update",i=>{if(i.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),i.connection==="close"){let c=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),c){let d=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),d)}}}),this.socket.ev.on("messages.upsert",({messages:i,type:a})=>{if(a==="notify")for(let c of i)c.message&&(c.key.fromMe||this.processMessage(c).catch(d=>{this.emit("error",d instanceof Error?d:new Error(String(d)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var ko,hu=_(()=>{"use strict";nt();ko=class extends ge{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let d=await c.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let m=await this.downloadAttachment(d);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Wa from"node:readline";var Eo,fu=_(()=>{"use strict";nt();Eo=class extends ge{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Wa.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
|
|
1270
1270
|
Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
|
|
1271
1271
|
`),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
|
|
1272
1272
|
Goodbye!
|
|
1273
1273
|
`),this.emit("disconnected");return}this.messageCounter++;let s={id:`cli-${this.messageCounter}`,platform:"cli",chatId:"cli-chat",chatType:"dm",userId:"cli-user",userName:"cli-user",displayName:"You",text:t,timestamp:new Date};this.emit("message",s)}),this.rl.on("close",()=>{this.emit("disconnected")}),this.status="connected",this.emit("connected"),this.prompt()}async disconnect(){this.rl?.close(),this.rl=void 0,this.status="disconnected"}async sendMessage(e,t,s){let r=`cli-resp-${++this.messageCounter}`;return process.stdout.write(`
|
|
1274
1274
|
Alfred: ${t}
|
|
1275
|
-
`),this.prompt(),r}async editMessage(e,t,s,r){Wa.clearLine(process.stdout,0),Wa.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Qh from"node:http";import ef from"node:crypto";var tf,bo,gu=_(()=>{"use strict";nt();tf=1048576,bo=class extends
|
|
1275
|
+
`),this.prompt(),r}async editMessage(e,t,s,r){Wa.clearLine(process.stdout,0),Wa.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Qh from"node:http";import ef from"node:crypto";var tf,bo,gu=_(()=>{"use strict";nt();tf=1048576,bo=class extends ge{static{u(this,"HttpAdapter")}platform="api";server=null;streams=new Map;messageCounter=0;port;host;apiToken;corsOrigin;healthCheckFn;metricsFn;constructor(e,t,s){super(),this.port=e,this.host=t,this.apiToken=s?.apiToken,this.corsOrigin=s?.corsOrigin??"http://localhost:3420",this.healthCheckFn=s?.healthCheck,this.metricsFn=s?.metricsCallback}async connect(){this.status="connecting",this.server=Qh.createServer((e,t)=>{this.handleRequest(e,t)}),await new Promise((e,t)=>{this.server.listen(this.port,this.host,()=>{e()}),this.server.once("error",t)}),this.status="connected",this.emit("connected")}async disconnect(){for(let[e,t]of this.streams)this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e);this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=`api-resp-${++this.messageCounter}`,n=this.streams.get(e);return n&&this.writeSseEvent(n,"response",{type:"response",text:t}),r}async editMessage(e,t,s,r){let n=this.streams.get(e);n&&this.writeSseEvent(n,"status",{type:"status",text:s})}async deleteMessage(e,t){}async sendPhoto(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"image",data:t.toString("base64"),caption:s}),`api-photo-${++this.messageCounter}`}async sendFile(e,t,s,r){let n=this.streams.get(e);return n&&this.writeSseEvent(n,"attachment",{type:"attachment",attachmentType:"file",data:t.toString("base64"),fileName:s,caption:r}),`api-file-${++this.messageCounter}`}async sendVoice(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"voice",data:t.toString("base64"),caption:s}),`api-voice-${++this.messageCounter}`}endStream(e){let t=this.streams.get(e);t&&(this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e))}handleRequest(e,t){if(t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("Access-Control-Allow-Origin",this.corsOrigin),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),e.method==="OPTIONS"){t.writeHead(204),t.end();return}let s=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`);s.pathname==="/api/health"&&e.method==="GET"?this.handleHealth(t):s.pathname==="/api/metrics"&&e.method==="GET"?this.handleMetrics(t):s.pathname==="/api/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}checkAuth(e,t){if(!this.apiToken)return!0;let s=e.headers.authorization;return!s||s!==`Bearer ${this.apiToken}`?(t.writeHead(401,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Unauthorized"})),!1):!0}handleHealth(e){let t=this.healthCheckFn?.()??{},s=t.db!==!1?"ok":"degraded",r=s==="ok"?200:503;e.writeHead(r,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:s,...t,timestamp:new Date().toISOString()}))}handleMetrics(e){this.metricsFn?(e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(this.metricsFn())):this.handleHealth(e)}handleMessage(e,t){if(!this.checkAuth(e,t))return;let s="",r=0,n=!1;e.on("data",o=>{if(!n){if(r+=o.length,r>tf){n=!0,t.writeHead(413,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Payload too large"})),e.destroy();return}s+=o.toString()}}),e.on("end",()=>{if(!n)try{let o=JSON.parse(s),i=o.text;if(!i||typeof i!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let a=o.chatId??`api-chat-${ef.randomUUID()}`,c=o.userId??"api-user",d=this.streams.get(a);d&&(this.writeSseEvent(d,"done",{type:"done"}),d.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(a,t),e.on("close",()=>{this.streams.delete(a)}),this.messageCounter++;let m={id:`api-${this.messageCounter}`,platform:"api",chatId:a,chatType:"dm",userId:c,userName:c,displayName:"API User",text:i,timestamp:new Date};this.emit("message",m)}catch{t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON body"}))}})}writeSseEvent(e,t,s){e.writableEnded||e.write(`event: ${t}
|
|
1276
1276
|
data: ${JSON.stringify(s)}
|
|
1277
1277
|
|
|
1278
|
-
`)}}});var mt={};pe(mt,{CLIAdapter:()=>Eo,DiscordAdapter:()=>To,HttpAdapter:()=>bo,MatrixAdapter:()=>wo,MessagingAdapter:()=>fe,SignalAdapter:()=>ko,TelegramAdapter:()=>go,WhatsAppAdapter:()=>_o});var pt=_(()=>{"use strict";nt();du();uu();mu();pu();hu();fu();gu()});import So from"node:fs";import vo from"node:path";import sf from"js-yaml";var Bt,yu=_(()=>{"use strict";di();pi();et();$i();Dn();ne();pa();fa();ga();ya();Ta();wa();_a();ka();Ea();ba();Sa();va();$a();cu();Aa();Na();La();Da();Ma();Oa();Ua();Pa();Fa();ja();Bt=class{static{u(this,"Alfred")}config;logger;database;pipeline;llmProvider;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;confirmationQueue;adapters=new Map;formatter=new Vr;userRepo;skillRegistry;mcpManager;calendarSkill;calendarWatcher;todoWatcher;reasoningEngine;usageRepo;skillHealthTracker;healthCheckTimer;constructor(e){this.config=e,this.logger=Vs("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new $t(this.config.storage.path);let e=this.database.getDb(),t=new Ys(e),s=new Js(e);this.userRepo=s;let r=new It(e),n=new Zs(e),o=new Qs(e),i=new er(e),a=new tr(e),c=new sr(e),d=new rr(e),m=new nr(e),p=new Rt(e),f=new ln(p,this.logger.child({component:"activity"})),g=new ur(e),h=new dn(g,this.logger.child({component:"skill-health"}),f);this.skillHealthTracker=h,this.logger.info("Storage initialized");let y=new Er,k=this.loadSecurityRules();y.loadRules(k);let S=new br(y,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:k.length},"Security engine initialized");let b=Si(this.config.llm,this.logger.child({component:"llm"}));await b.initialize(),this.llmProvider=b;let C=new dr(e);this.usageRepo=C,b.setPersist((v,O,J,De,le,Ge)=>{C.record(v,O,J,De,le,Ge)});let D=new Kr(b,a,this.logger.child({component:"embeddings"})),U=this.config.activeLearning?.enabled!==!1,Q,ie;U&&(Q=new rn({llm:b,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:D,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),ie=new nn(n,this.logger.child({component:"memory-retriever"}),D),this.logger.info("Active learning & memory retriever initialized"));let j=new lr(e),z=new on(b,j,this.logger.child({component:"summarizer"}));this.logger.info("Conversation summarizer initialized");let ae=new Kt(this.logger.child({component:"sandbox"})),L=this.skillRegistry=new Vt;L.register(new Yt),L.register(new Jt),L.register(new Zt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),L.register(new Qt(o)),L.register(new es(i));let se=new ir(e);if(L.register(new Ts(se)),L.register(new ts),L.register(new ss),L.register(new rs(n,D)),L.register(new ns(b,L,ae,S)),this.config.email?.accounts?.length){let v=new Map;for(let O of this.config.email.accounts)try{O.provider==="microsoft"&&!O.microsoft?.clientId&&this.config.calendar?.microsoft&&(O.microsoft={...this.config.calendar.microsoft});let J=await Sr(O);v.set(O.name,J),this.logger.info({account:O.name,provider:O.provider??"imap-smtp"},"Email account initialized")}catch(J){this.logger.warn({err:J,account:O.name},"Email account initialization failed, skipping")}L.register(v.size>0?new lt(v):new lt)}else L.register(new lt);L.register(new os),L.register(new is);let K=new Es;K.setReloadCallback(v=>this.reloadService(v)),L.register(K),L.register(new cs),L.register(new ls),L.register(new ds),L.register(new us(s)),L.register(new ms(s,c,this.adapters,(v,O)=>t.findByPlatformAndUser(v,O)));let P=new ps(d);L.register(P),L.register(new hs(m));let me=new or(e),Le=new Yr(me,D,this.logger.child({component:"documents"}));L.register(new fs(me,Le,D));let Ie,ee;if(this.config.calendar)try{ee=await Ir(this.config.calendar),Ie=new Lt(ee),L.register(Ie),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(v){this.logger.warn({err:v},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=Ie,ee&&this.config.calendar?.vorlauf?.enabled){let v=new At(e),O=this.config.security?.ownerUserId;O&&(this.calendarWatcher=new an(ee,v,this.adapters,O,"telegram",this.config.calendar.vorlauf,this.logger.child({component:"calendar-watcher"}),f))}{let v=this.config.security?.ownerUserId;if(v){let O=new At(e);this.todoWatcher=new cn(se,O,this.adapters,v,"telegram",{minutesBefore:30},this.logger.child({component:"todo-watcher"}),f)}}if(this.config.mcp?.servers?.length){let{MCPManager:v}=await Promise.resolve().then(()=>(ne(),oe));this.mcpManager=new v(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let O of this.mcpManager.getSkills())L.register(O);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},b)),this.logger.info({agents:this.config.codeAgents.agents.map(O=>O.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:v,createContactsProvider:O}=await Promise.resolve().then(()=>(ne(),oe)),J=await O(this.config.contacts);L.register(new v(J)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(v){this.logger.warn({err:v},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}{let{MarketplaceSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.marketplace)),this.logger.info("Marketplace skill registered")}{let{BriefingSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(L,this.config,n)),this.logger.info("Briefing skill registered")}this.logger.info({skills:L.getAll().map(v=>v.metadata.name)},"Skills registered");let ke;if(this.config.speech?.apiKey&&(ke=new zr(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let v=new qr(this.config.speech,this.logger.child({component:"tts"}));L.register(new gs(v)),this.logger.info("Text-to-speech skill registered")}let de=this.detectImageGenProvider();if(de){let v=new Gr(de,this.logger.child({component:"image-gen"}));L.register(new ys(v)),this.logger.info({provider:de.provider},"Image generation skill registered")}try{let v=new Xr(this.logger.child({component:"transit"}));L.register(new _s(v)),this.logger.info("Public transit skill registered")}catch(v){this.logger.warn({err:v},"Failed to register transit skill")}let Ve=new Hr(t),Ke=vo.resolve(vo.dirname(this.config.storage.path),"inbox");this.pipeline=new Br({llm:b,conversationManager:Ve,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:L,skillSandbox:ae,securityManager:S,memoryRepo:n,speechTranscriber:ke,inboxPath:Ke,embeddingService:D,activeLearning:Q,memoryRetriever:ie,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:Le,conversationSummarizer:z}),this.reminderScheduler=new Wr(o,async(v,O,J)=>{let De=this.adapters.get(v);De?await De.sendMessage(O,J):this.logger.warn({platform:v,chatId:O},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(v=>s.getMasterUserId(v),"getMasterUserId"),getLinkedUsers:u(v=>s.getLinkedUsers(v),"getLinkedUsers"),findConversation:u((v,O)=>t.findByPlatformAndUser(v,O),"findConversation")}),this.backgroundTaskRunner=new Jr(L,ae,d,this.adapters,s,this.logger.child({component:"background-tasks"}),f,h);let Ye=new Zr(L,ae,d,this.adapters,s,this.logger.child({component:"persistent-agents"}),f);this.backgroundTaskRunner.setPersistentRunner(Ye),P.setPersistentRunner(Ye),this.proactiveScheduler=new Qr(m,L,ae,b,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,Ve,f);let Se=new ar(e);L.register(new bs(Se,L));let xs=new cr(e);this.confirmationQueue=new tn(xs,L,ae,this.adapters,this.logger.child({component:"confirmation-queue"}),f),this.watchEngine=new fo(Se,L,ae,this.adapters,s,this.logger.child({component:"watch-engine"}),this.confirmationQueue,f,h,b);let it=new mr(e),ft=new Ss(it);L.register(ft);let X=new un(it,L,ae,this.logger.child({component:"workflow-runner"}),f,h);ft.setRunner(X);{let v=this.config.security?.ownerUserId;if(v&&this.config.reasoning?.enabled!==!1){let O=new At(e);this.reasoningEngine=new mn(ee,se,Se,n,p,g,O,L,ae,b,this.adapters,s,v,"telegram",this.config.reasoning,this.logger.child({component:"reasoning-engine"}),f)}}this.pipeline.setConfirmationQueue(this.confirmationQueue),this.pipeline.setActivityLogger(f),this.pipeline.setSkillHealthTracker(h),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("telegram",new t(e.telegram.token)),this.logger.info("Telegram adapter registered")}if(e.discord?.enabled&&e.discord.token){let{DiscordAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("discord",new t(e.discord.token)),this.logger.info("Discord adapter registered")}if(e.whatsapp?.enabled){let{WhatsAppAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("whatsapp",new t(e.whatsapp.dataPath)),this.logger.info("WhatsApp adapter registered")}if(e.matrix?.enabled&&e.matrix.accessToken){let{MatrixAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("matrix",new t(e.matrix.homeserverUrl,e.matrix.accessToken,e.matrix.userId)),this.logger.info("Matrix adapter registered")}if(e.signal?.enabled&&e.signal.phoneNumber){let{SignalAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}if(e.api?.enabled!==!1){let{HttpAdapter:t}=await Promise.resolve().then(()=>(pt(),mt)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";e.api?.token?this.logger.info("HTTP API authentication enabled"):this.logger.warn("HTTP API has no authentication token configured (api.token). API is open."),this.adapters.set("api",new t(s,r,{apiToken:e.api?.token,corsOrigin:e.api?.corsOrigin,healthCheck:u(()=>({db:!!this.database,uptime:Math.floor(process.uptime()),adapters:Object.fromEntries([...this.adapters].map(([n,o])=>[n,o.getStatus()])),metrics:this.pipeline.getMetrics(),costs:this.llmProvider.getCostSummary(),todayUsage:this.usageRepo?.getDaily(new Date().toISOString().slice(0,10))}),"healthCheck"),metricsCallback:u(()=>this.buildPrometheusMetrics(),"metricsCallback")})),this.logger.info({port:s,host:r},"HTTP API adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.watchEngine?.start(),this.confirmationQueue?.start(),this.calendarWatcher?.start(),this.todoWatcher?.start(),this.reasoningEngine?.start(),this.skillHealthTracker&&(this.healthCheckTimer=setInterval(()=>this.skillHealthTracker.checkReEnables(),5*6e4)),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(pt(),mt)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.watchEngine?.stop(),this.confirmationQueue?.stop(),this.calendarWatcher?.stop(),this.todoWatcher?.stop(),this.reasoningEngine?.stop(),this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=void 0),this.mcpManager&&await this.mcpManager.shutdown();let e=5e3;for(let[t,s]of this.adapters)try{await Promise.race([s.disconnect(),new Promise(r=>setTimeout(r,e))]),this.logger.info({platform:t},"Adapter disconnected")}catch(r){this.logger.error({platform:t,err:r},"Failed to disconnect adapter")}try{this.database.getDb().pragma("wal_checkpoint(TRUNCATE)")}catch{}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{ci();let t=new ue().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.proxmox)),this.config.proxmox=t.proxmox,this.logger.info({baseUrl:t.proxmox.baseUrl},"Proxmox skill hot-reloaded")}if(e==="unifi"&&t.unifi){let{UniFiSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}if(e==="homeassistant"&&t.homeassistant){let{HomeAssistantSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant skill hot-reloaded")}if(e==="contacts"&&t.contacts){let{ContactsSkill:s,createContactsProvider:r}=await Promise.resolve().then(()=>(ne(),oe)),n=await r(t.contacts);this.skillRegistry.register(new s(n)),this.config.contacts=t.contacts,this.logger.info({provider:t.contacts.provider},"Contacts skill hot-reloaded")}if(e==="docker"&&t.docker){let{DockerSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.docker)),this.config.docker=t.docker,this.logger.info("Docker skill hot-reloaded")}if(e==="bmw"&&t.bmw){let{BMWSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.bmw)),this.config.bmw=t.bmw,this.logger.info("BMW CarData skill hot-reloaded")}if(e==="routing"&&t.routing){let{RoutingSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.routing)),this.config.routing=t.routing,this.logger.info("Routing skill hot-reloaded")}if(e==="todo"&&t.todo){let{MicrosoftTodoSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.todo)),this.config.todo=t.todo,this.logger.info("Microsoft To Do skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}buildPrometheusMetrics(){let e=[],t=Math.floor(process.uptime());e.push("# HELP alfred_uptime_seconds Process uptime in seconds"),e.push("# TYPE alfred_uptime_seconds gauge"),e.push(`alfred_uptime_seconds ${t}`);let s=this.pipeline.getMetrics();e.push("# HELP alfred_requests_total Total messages processed"),e.push("# TYPE alfred_requests_total counter"),e.push(`alfred_requests_total ${s.requestsTotal}`),e.push("# HELP alfred_requests_success_total Successful requests"),e.push("# TYPE alfred_requests_success_total counter"),e.push(`alfred_requests_success_total ${s.requestsSuccess}`),e.push("# HELP alfred_requests_failed_total Failed requests"),e.push("# TYPE alfred_requests_failed_total counter"),e.push(`alfred_requests_failed_total ${s.requestsFailed}`),e.push("# HELP alfred_request_duration_avg_ms Average request duration"),e.push("# TYPE alfred_request_duration_avg_ms gauge"),e.push(`alfred_request_duration_avg_ms ${s.avgDurationMs}`);let r=this.llmProvider.getCostSummary();e.push("# HELP alfred_llm_input_tokens_total Total LLM input tokens (session)"),e.push("# TYPE alfred_llm_input_tokens_total counter"),e.push(`alfred_llm_input_tokens_total ${r.totalInputTokens}`),e.push("# HELP alfred_llm_output_tokens_total Total LLM output tokens (session)"),e.push("# TYPE alfred_llm_output_tokens_total counter"),e.push(`alfred_llm_output_tokens_total ${r.totalOutputTokens}`),e.push("# HELP alfred_llm_cost_usd_total Total LLM cost in USD (session)"),e.push("# TYPE alfred_llm_cost_usd_total counter"),e.push(`alfred_llm_cost_usd_total ${r.totalCostUsd}`),e.push("# HELP alfred_llm_calls_total LLM calls by model"),e.push("# TYPE alfred_llm_calls_total counter");for(let[n,o]of Object.entries(r.byModel)){let i=`model="${n}"`;e.push(`alfred_llm_calls_total{${i}} ${o.calls}`)}e.push("# HELP alfred_llm_cost_usd LLM cost by model"),e.push("# TYPE alfred_llm_cost_usd counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_cost_usd{model="${n}"} ${o.costUsd}`);e.push("# HELP alfred_llm_input_tokens LLM input tokens by model"),e.push("# TYPE alfred_llm_input_tokens counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_input_tokens{model="${n}"} ${o.inputTokens}`);e.push("# HELP alfred_llm_output_tokens LLM output tokens by model"),e.push("# TYPE alfred_llm_output_tokens counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_output_tokens{model="${n}"} ${o.outputTokens}`);if(this.usageRepo){let n=new Date().toISOString().slice(0,10),o=this.usageRepo.getDaily(n);e.push("# HELP alfred_llm_today_cost_usd Total LLM cost today (persisted)"),e.push("# TYPE alfred_llm_today_cost_usd gauge"),e.push(`alfred_llm_today_cost_usd ${o.totalCostUsd}`),e.push("# HELP alfred_llm_today_calls Total LLM calls today (persisted)"),e.push("# TYPE alfred_llm_today_calls gauge"),e.push(`alfred_llm_today_calls ${o.totalCalls}`)}return e.push(""),e.join(`
|
|
1279
|
-
`)}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async a=>{if(a!==n){n=a;try{r?await t.editMessage(s.chatId,r,a):r=await t.sendMessage(s.chatId,a)}catch(c){this.logger.debug({err:c,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o);if(i.text){let a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,c)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let m=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,m.text)}}if(i.attachments)for(let a of i.attachments)try{let c=a.mimeType.startsWith("image/"),d=a.mimeType==="audio/ogg"||a.mimeType==="audio/opus";c?await t.sendPhoto(s.chatId,a.data,a.fileName):d?await t.sendVoice(s.chatId,a.data):await t.sendFile(s.chatId,a.data,a.fileName)}catch(c){this.logger.warn({err:c,fileName:a.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}detectImageGenProvider(){let e=["default","strong","fast","embeddings","local"];for(let t of["openai","google"])for(let s of e){let r=this.config.llm[s];if(r?.provider===t&&r.apiKey)return{provider:t,apiKey:r.apiKey,baseUrl:r.baseUrl}}}loadSecurityRules(){let e=vo.resolve(this.config.security.rulesPath),t=[];if(!So.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!So.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=So.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=vo.join(e,n),i=So.readFileSync(o,"utf-8"),a=sf.load(i);if(a?.rules&&Array.isArray(a.rules)){let d=new st().loadFromObject({rules:a.rules});t.push(...d),this.logger.info({file:n,count:d.length},"Loaded security rules")}}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var Tu=_(()=>{"use strict"});var za=_(()=>{"use strict";yu();fa();pa();ga();ya();Ta();ka();Ea();Sa();va();$a();ut();ba();wa();_a();Na();La();Ca();Tu();xa();Da();po();Aa();Ma();Oa();Ua();ho();Pa();Fa();ja()});import $o from"node:fs";import wu from"node:path";import rf from"node:os";function _u(){try{let l=$o.readFileSync(qa,"utf-8"),e=JSON.parse(l);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function ku(l){try{let e=wu.dirname(qa);$o.existsSync(e)||$o.mkdirSync(e,{recursive:!0}),$o.writeFileSync(qa,JSON.stringify(l,null,2),"utf-8")}catch{}}async function Wt(l,e){let t=new AbortController,s=setTimeout(()=>t.abort(),of);try{return await fetch(l,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function Eu(l,e,t){switch(l){case"anthropic":{let s=await Wt("https://api.anthropic.com/v1/models",{headers:{"x-api-key":e??"","anthropic-version":"2023-06-01"}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.display_name})):[]}case"openai":{let s=t?`${t.replace(/\/+$/,"")}/models`:"https://api.openai.com/v1/models",r=await Wt(s,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}case"google":{let s=`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(e??"")}`,r=await Wt(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await Wt("https://api.mistral.ai/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"openrouter":{let s=await Wt("https://openrouter.ai/api/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"ollama":{let s=(t??"http://localhost:11434").replace(/\/+$/,""),r=await Wt(`${s}/api/tags`);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name})):[]}case"openwebui":{let s=(t??"http://localhost:3000/api/v1").replace(/\/+$/,""),r=await Wt(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function Ga(l,e,t){let s=_u(),r=s.providers[l];if(r&&Date.now()-r.fetchedAt<nf)return r.models;try{let n=await Eu(l,e,t);if(n.length>0)return s.providers[l]={fetchedAt:Date.now(),models:n},ku(s),n}catch{}return r?r.models:[]}function Io(l,e,t){Eu(l,e,t).then(s=>{if(s.length>0){let r=_u();r.providers[l]={fetchedAt:Date.now(),models:s},ku(r)}}).catch(()=>{})}function Xa(l,e){let t=new Set,s=[];for(let r of l)if(!t.has(r.id)){t.add(r.id);let n=e.find(o=>o.id===r.id);s.push({id:r.id,name:r.name,desc:n?.desc})}for(let r of e)t.has(r.id)||(t.add(r.id),s.push({id:r.id,desc:r.desc}));return s}var nf,of,qa,Va=_(()=>{"use strict";nf=24*60*60*1e3,of=5e3,qa=wu.join(rf.homedir(),".alfred","model-cache.json");u(_u,"readCache");u(ku,"writeCache");u(Wt,"fetchWithTimeout");u(Eu,"fetchModelsFromAPI");u(Ga,"getModels");u(Io,"refreshCacheInBackground");u(Xa,"mergeModels")});var bu={};
|
|
1278
|
+
`)}}});var mt={};he(mt,{CLIAdapter:()=>Eo,DiscordAdapter:()=>To,HttpAdapter:()=>bo,MatrixAdapter:()=>wo,MessagingAdapter:()=>ge,SignalAdapter:()=>ko,TelegramAdapter:()=>go,WhatsAppAdapter:()=>_o});var pt=_(()=>{"use strict";nt();du();uu();mu();pu();hu();fu();gu()});import So from"node:fs";import vo from"node:path";import sf from"js-yaml";var Bt,yu=_(()=>{"use strict";di();pi();et();$i();Dn();ne();pa();fa();ga();ya();Ta();wa();_a();ka();Ea();ba();Sa();va();$a();cu();Aa();Na();La();Da();Ma();Oa();Ua();Pa();Fa();ja();Bt=class{static{u(this,"Alfred")}config;logger;database;pipeline;llmProvider;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;confirmationQueue;adapters=new Map;formatter=new Vr;userRepo;skillRegistry;mcpManager;calendarSkill;calendarWatcher;todoWatcher;reasoningEngine;usageRepo;skillHealthTracker;healthCheckTimer;constructor(e){this.config=e,this.logger=Vs("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new $t(this.config.storage.path);let e=this.database.getDb(),t=new Ys(e),s=new Js(e);this.userRepo=s;let r=new It(e),n=new Zs(e),o=new Qs(e),i=new er(e),a=new tr(e),c=new sr(e),d=new rr(e),m=new nr(e),p=new Rt(e),f=new ln(p,this.logger.child({component:"activity"})),g=new ur(e),h=new dn(g,this.logger.child({component:"skill-health"}),f);this.skillHealthTracker=h,this.logger.info("Storage initialized");let y=new Er,k=this.loadSecurityRules();y.loadRules(k);let S=new br(y,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:k.length},"Security engine initialized");let b=Si(this.config.llm,this.logger.child({component:"llm"}));await b.initialize(),this.llmProvider=b;let C=new dr(e);this.usageRepo=C,b.setPersist((v,O,Y,pe,le,Ge)=>{C.record(v,O,Y,pe,le,Ge)});let D=new Kr(b,a,this.logger.child({component:"embeddings"})),U=this.config.activeLearning?.enabled!==!1,Q,ie;U&&(Q=new rn({llm:b,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:D,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),ie=new nn(n,this.logger.child({component:"memory-retriever"}),D),this.logger.info("Active learning & memory retriever initialized"));let j=new lr(e),z=new on(b,j,this.logger.child({component:"summarizer"}));this.logger.info("Conversation summarizer initialized");let ae=new Kt(this.logger.child({component:"sandbox"})),L=this.skillRegistry=new Vt;L.register(new Yt),L.register(new Jt),L.register(new Zt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),L.register(new Qt(o)),L.register(new es(i));let se=new ir(e);if(L.register(new Ts(se)),L.register(new ts),L.register(new ss),L.register(new rs(n,D)),L.register(new ns(b,L,ae,S)),this.config.email?.accounts?.length){let v=new Map;for(let O of this.config.email.accounts)try{O.provider==="microsoft"&&!O.microsoft?.clientId&&this.config.calendar?.microsoft&&(O.microsoft={...this.config.calendar.microsoft});let Y=await Sr(O);v.set(O.name,Y),this.logger.info({account:O.name,provider:O.provider??"imap-smtp"},"Email account initialized")}catch(Y){this.logger.warn({err:Y,account:O.name},"Email account initialization failed, skipping")}L.register(v.size>0?new lt(v):new lt)}else L.register(new lt);L.register(new os),L.register(new is);let K=new Es;K.setReloadCallback(v=>this.reloadService(v)),L.register(K),L.register(new cs),L.register(new ls),L.register(new ds),L.register(new us(s)),L.register(new ms(s,c,this.adapters,(v,O)=>t.findByPlatformAndUser(v,O)));let P=new ps(d);L.register(P),L.register(new hs(m));let me=new or(e),De=new Yr(me,D,this.logger.child({component:"documents"}));L.register(new fs(me,De,D));let Ae,ee;if(this.config.calendar)try{ee=await Ir(this.config.calendar),Ae=new Lt(ee),L.register(Ae),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(v){this.logger.warn({err:v},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=Ae,ee&&this.config.calendar?.vorlauf?.enabled){let v=new At(e),O=this.config.security?.ownerUserId;O&&(this.calendarWatcher=new an(ee,v,this.adapters,O,"telegram",this.config.calendar.vorlauf,this.logger.child({component:"calendar-watcher"}),f))}{let v=this.config.security?.ownerUserId;if(v){let O=new At(e);this.todoWatcher=new cn(se,O,this.adapters,v,"telegram",{minutesBefore:30},this.logger.child({component:"todo-watcher"}),f)}}if(this.config.mcp?.servers?.length){let{MCPManager:v}=await Promise.resolve().then(()=>(ne(),oe));this.mcpManager=new v(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let O of this.mcpManager.getSkills())L.register(O);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},b)),this.logger.info({agents:this.config.codeAgents.agents.map(O=>O.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:v,createContactsProvider:O}=await Promise.resolve().then(()=>(ne(),oe)),Y=await O(this.config.contacts);L.register(new v(Y)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(v){this.logger.warn({err:v},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}{let{MarketplaceSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(this.config.marketplace)),this.logger.info("Marketplace skill registered")}{let{BriefingSkill:v}=await Promise.resolve().then(()=>(ne(),oe));L.register(new v(L,this.config,n)),this.logger.info("Briefing skill registered")}this.logger.info({skills:L.getAll().map(v=>v.metadata.name)},"Skills registered");let Ee;if(this.config.speech?.apiKey&&(Ee=new zr(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let v=new qr(this.config.speech,this.logger.child({component:"tts"}));L.register(new gs(v)),this.logger.info("Text-to-speech skill registered")}let de=this.detectImageGenProvider();if(de){let v=new Gr(de,this.logger.child({component:"image-gen"}));L.register(new ys(v)),this.logger.info({provider:de.provider},"Image generation skill registered")}try{let v=new Xr(this.logger.child({component:"transit"}));L.register(new _s(v)),this.logger.info("Public transit skill registered")}catch(v){this.logger.warn({err:v},"Failed to register transit skill")}let Ve=new Hr(t),Ke=vo.resolve(vo.dirname(this.config.storage.path),"inbox");this.pipeline=new Br({llm:b,conversationManager:Ve,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:L,skillSandbox:ae,securityManager:S,memoryRepo:n,speechTranscriber:Ee,inboxPath:Ke,embeddingService:D,activeLearning:Q,memoryRetriever:ie,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:De,conversationSummarizer:z}),this.reminderScheduler=new Wr(o,async(v,O,Y)=>{let pe=this.adapters.get(v);pe?await pe.sendMessage(O,Y):this.logger.warn({platform:v,chatId:O},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(v=>s.getMasterUserId(v),"getMasterUserId"),getLinkedUsers:u(v=>s.getLinkedUsers(v),"getLinkedUsers"),findConversation:u((v,O)=>t.findByPlatformAndUser(v,O),"findConversation")}),this.backgroundTaskRunner=new Jr(L,ae,d,this.adapters,s,this.logger.child({component:"background-tasks"}),f,h);let Ye=new Zr(L,ae,d,this.adapters,s,this.logger.child({component:"persistent-agents"}),f);this.backgroundTaskRunner.setPersistentRunner(Ye),P.setPersistentRunner(Ye),this.proactiveScheduler=new Qr(m,L,ae,b,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,Ve,f);let ve=new ar(e);L.register(new bs(ve,L));let xs=new cr(e);this.confirmationQueue=new tn(xs,L,ae,this.adapters,this.logger.child({component:"confirmation-queue"}),f),this.watchEngine=new fo(ve,L,ae,this.adapters,s,this.logger.child({component:"watch-engine"}),this.confirmationQueue,f,h,b);let it=new mr(e),ft=new Ss(it);L.register(ft);let X=new un(it,L,ae,this.logger.child({component:"workflow-runner"}),f,h);ft.setRunner(X);{let v=this.config.security?.ownerUserId;if(v&&this.config.reasoning?.enabled!==!1){let O=new At(e);this.reasoningEngine=new mn(ee,se,ve,n,p,g,O,L,ae,b,this.adapters,s,v,"telegram",this.config.reasoning,this.logger.child({component:"reasoning-engine"}),f)}}this.pipeline.setConfirmationQueue(this.confirmationQueue),this.pipeline.setActivityLogger(f),this.pipeline.setSkillHealthTracker(h),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("telegram",new t(e.telegram.token)),this.logger.info("Telegram adapter registered")}if(e.discord?.enabled&&e.discord.token){let{DiscordAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("discord",new t(e.discord.token)),this.logger.info("Discord adapter registered")}if(e.whatsapp?.enabled){let{WhatsAppAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("whatsapp",new t(e.whatsapp.dataPath)),this.logger.info("WhatsApp adapter registered")}if(e.matrix?.enabled&&e.matrix.accessToken){let{MatrixAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("matrix",new t(e.matrix.homeserverUrl,e.matrix.accessToken,e.matrix.userId)),this.logger.info("Matrix adapter registered")}if(e.signal?.enabled&&e.signal.phoneNumber){let{SignalAdapter:t}=await Promise.resolve().then(()=>(pt(),mt));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}if(e.api?.enabled!==!1){let{HttpAdapter:t}=await Promise.resolve().then(()=>(pt(),mt)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";e.api?.token?this.logger.info("HTTP API authentication enabled"):this.logger.warn("HTTP API has no authentication token configured (api.token). API is open."),this.adapters.set("api",new t(s,r,{apiToken:e.api?.token,corsOrigin:e.api?.corsOrigin,healthCheck:u(()=>({db:!!this.database,uptime:Math.floor(process.uptime()),adapters:Object.fromEntries([...this.adapters].map(([n,o])=>[n,o.getStatus()])),metrics:this.pipeline.getMetrics(),costs:this.llmProvider.getCostSummary(),todayUsage:this.usageRepo?.getDaily(new Date().toISOString().slice(0,10))}),"healthCheck"),metricsCallback:u(()=>this.buildPrometheusMetrics(),"metricsCallback")})),this.logger.info({port:s,host:r},"HTTP API adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.watchEngine?.start(),this.confirmationQueue?.start(),this.calendarWatcher?.start(),this.todoWatcher?.start(),this.reasoningEngine?.start(),this.skillHealthTracker&&(this.healthCheckTimer=setInterval(()=>this.skillHealthTracker.checkReEnables(),5*6e4)),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(pt(),mt)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.watchEngine?.stop(),this.confirmationQueue?.stop(),this.calendarWatcher?.stop(),this.todoWatcher?.stop(),this.reasoningEngine?.stop(),this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=void 0),this.mcpManager&&await this.mcpManager.shutdown();let e=5e3;for(let[t,s]of this.adapters)try{await Promise.race([s.disconnect(),new Promise(r=>setTimeout(r,e))]),this.logger.info({platform:t},"Adapter disconnected")}catch(r){this.logger.error({platform:t,err:r},"Failed to disconnect adapter")}try{this.database.getDb().pragma("wal_checkpoint(TRUNCATE)")}catch{}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{ci();let t=new ue().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.proxmox)),this.config.proxmox=t.proxmox,this.logger.info({baseUrl:t.proxmox.baseUrl},"Proxmox skill hot-reloaded")}if(e==="unifi"&&t.unifi){let{UniFiSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}if(e==="homeassistant"&&t.homeassistant){let{HomeAssistantSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant skill hot-reloaded")}if(e==="contacts"&&t.contacts){let{ContactsSkill:s,createContactsProvider:r}=await Promise.resolve().then(()=>(ne(),oe)),n=await r(t.contacts);this.skillRegistry.register(new s(n)),this.config.contacts=t.contacts,this.logger.info({provider:t.contacts.provider},"Contacts skill hot-reloaded")}if(e==="docker"&&t.docker){let{DockerSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.docker)),this.config.docker=t.docker,this.logger.info("Docker skill hot-reloaded")}if(e==="bmw"&&t.bmw){let{BMWSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.bmw)),this.config.bmw=t.bmw,this.logger.info("BMW CarData skill hot-reloaded")}if(e==="routing"&&t.routing){let{RoutingSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.routing)),this.config.routing=t.routing,this.logger.info("Routing skill hot-reloaded")}if(e==="todo"&&t.todo){let{MicrosoftTodoSkill:s}=await Promise.resolve().then(()=>(ne(),oe));this.skillRegistry.register(new s(t.todo)),this.config.todo=t.todo,this.logger.info("Microsoft To Do skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}buildPrometheusMetrics(){let e=[],t=Math.floor(process.uptime());e.push("# HELP alfred_uptime_seconds Process uptime in seconds"),e.push("# TYPE alfred_uptime_seconds gauge"),e.push(`alfred_uptime_seconds ${t}`);let s=this.pipeline.getMetrics();e.push("# HELP alfred_requests_total Total messages processed"),e.push("# TYPE alfred_requests_total counter"),e.push(`alfred_requests_total ${s.requestsTotal}`),e.push("# HELP alfred_requests_success_total Successful requests"),e.push("# TYPE alfred_requests_success_total counter"),e.push(`alfred_requests_success_total ${s.requestsSuccess}`),e.push("# HELP alfred_requests_failed_total Failed requests"),e.push("# TYPE alfred_requests_failed_total counter"),e.push(`alfred_requests_failed_total ${s.requestsFailed}`),e.push("# HELP alfred_request_duration_avg_ms Average request duration"),e.push("# TYPE alfred_request_duration_avg_ms gauge"),e.push(`alfred_request_duration_avg_ms ${s.avgDurationMs}`);let r=this.llmProvider.getCostSummary();e.push("# HELP alfred_llm_input_tokens_total Total LLM input tokens (session)"),e.push("# TYPE alfred_llm_input_tokens_total counter"),e.push(`alfred_llm_input_tokens_total ${r.totalInputTokens}`),e.push("# HELP alfred_llm_output_tokens_total Total LLM output tokens (session)"),e.push("# TYPE alfred_llm_output_tokens_total counter"),e.push(`alfred_llm_output_tokens_total ${r.totalOutputTokens}`),e.push("# HELP alfred_llm_cost_usd_total Total LLM cost in USD (session)"),e.push("# TYPE alfred_llm_cost_usd_total counter"),e.push(`alfred_llm_cost_usd_total ${r.totalCostUsd}`),e.push("# HELP alfred_llm_calls_total LLM calls by model"),e.push("# TYPE alfred_llm_calls_total counter");for(let[n,o]of Object.entries(r.byModel)){let i=`model="${n}"`;e.push(`alfred_llm_calls_total{${i}} ${o.calls}`)}e.push("# HELP alfred_llm_cost_usd LLM cost by model"),e.push("# TYPE alfred_llm_cost_usd counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_cost_usd{model="${n}"} ${o.costUsd}`);e.push("# HELP alfred_llm_input_tokens LLM input tokens by model"),e.push("# TYPE alfred_llm_input_tokens counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_input_tokens{model="${n}"} ${o.inputTokens}`);e.push("# HELP alfred_llm_output_tokens LLM output tokens by model"),e.push("# TYPE alfred_llm_output_tokens counter");for(let[n,o]of Object.entries(r.byModel))e.push(`alfred_llm_output_tokens{model="${n}"} ${o.outputTokens}`);if(this.usageRepo){let n=new Date().toISOString().slice(0,10),o=this.usageRepo.getDaily(n);e.push("# HELP alfred_llm_today_cost_usd Total LLM cost today (persisted)"),e.push("# TYPE alfred_llm_today_cost_usd gauge"),e.push(`alfred_llm_today_cost_usd ${o.totalCostUsd}`),e.push("# HELP alfred_llm_today_calls Total LLM calls today (persisted)"),e.push("# TYPE alfred_llm_today_calls gauge"),e.push(`alfred_llm_today_calls ${o.totalCalls}`)}return e.push(""),e.join(`
|
|
1279
|
+
`)}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async a=>{if(a!==n){n=a;try{r?await t.editMessage(s.chatId,r,a):r=await t.sendMessage(s.chatId,a)}catch(c){this.logger.debug({err:c,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o);if(i.text){let a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,c)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let m=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,m.text)}}if(i.attachments)for(let a of i.attachments)try{let c=a.mimeType.startsWith("image/"),d=a.mimeType==="audio/ogg"||a.mimeType==="audio/opus";c?await t.sendPhoto(s.chatId,a.data,a.fileName):d?await t.sendVoice(s.chatId,a.data):await t.sendFile(s.chatId,a.data,a.fileName)}catch(c){this.logger.warn({err:c,fileName:a.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}detectImageGenProvider(){let e=["default","strong","fast","embeddings","local"];for(let t of["openai","google"])for(let s of e){let r=this.config.llm[s];if(r?.provider===t&&r.apiKey)return{provider:t,apiKey:r.apiKey,baseUrl:r.baseUrl}}}loadSecurityRules(){let e=vo.resolve(this.config.security.rulesPath),t=[];if(!So.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!So.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=So.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=vo.join(e,n),i=So.readFileSync(o,"utf-8"),a=sf.load(i);if(a?.rules&&Array.isArray(a.rules)){let d=new st().loadFromObject({rules:a.rules});t.push(...d),this.logger.info({file:n,count:d.length},"Loaded security rules")}}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var Tu=_(()=>{"use strict"});var za=_(()=>{"use strict";yu();fa();pa();ga();ya();Ta();ka();Ea();Sa();va();$a();ut();ba();wa();_a();Na();La();Ca();Tu();xa();Da();po();Aa();Ma();Oa();Ua();ho();Pa();Fa();ja()});import $o from"node:fs";import wu from"node:path";import rf from"node:os";function _u(){try{let l=$o.readFileSync(qa,"utf-8"),e=JSON.parse(l);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function ku(l){try{let e=wu.dirname(qa);$o.existsSync(e)||$o.mkdirSync(e,{recursive:!0}),$o.writeFileSync(qa,JSON.stringify(l,null,2),"utf-8")}catch{}}async function Wt(l,e){let t=new AbortController,s=setTimeout(()=>t.abort(),of);try{return await fetch(l,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function Eu(l,e,t){switch(l){case"anthropic":{let s=await Wt("https://api.anthropic.com/v1/models",{headers:{"x-api-key":e??"","anthropic-version":"2023-06-01"}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.display_name})):[]}case"openai":{let s=t?`${t.replace(/\/+$/,"")}/models`:"https://api.openai.com/v1/models",r=await Wt(s,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}case"google":{let s=`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(e??"")}`,r=await Wt(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await Wt("https://api.mistral.ai/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"openrouter":{let s=await Wt("https://openrouter.ai/api/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"ollama":{let s=(t??"http://localhost:11434").replace(/\/+$/,""),r=await Wt(`${s}/api/tags`);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name})):[]}case"openwebui":{let s=(t??"http://localhost:3000/api/v1").replace(/\/+$/,""),r=await Wt(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function Ga(l,e,t){let s=_u(),r=s.providers[l];if(r&&Date.now()-r.fetchedAt<nf)return r.models;try{let n=await Eu(l,e,t);if(n.length>0)return s.providers[l]={fetchedAt:Date.now(),models:n},ku(s),n}catch{}return r?r.models:[]}function Io(l,e,t){Eu(l,e,t).then(s=>{if(s.length>0){let r=_u();r.providers[l]={fetchedAt:Date.now(),models:s},ku(r)}}).catch(()=>{})}function Xa(l,e){let t=new Set,s=[];for(let r of l)if(!t.has(r.id)){t.add(r.id);let n=e.find(o=>o.id===r.id);s.push({id:r.id,name:r.name,desc:n?.desc})}for(let r of e)t.has(r.id)||(t.add(r.id),s.push({id:r.id,desc:r.desc}));return s}var nf,of,qa,Va=_(()=>{"use strict";nf=24*60*60*1e3,of=5e3,qa=wu.join(rf.homedir(),".alfred","model-cache.json");u(_u,"readCache");u(ku,"writeCache");u(Wt,"fetchWithTimeout");u(Eu,"fetchModelsFromAPI");u(Ga,"getModels");u(Io,"refreshCacheInBackground");u(Xa,"mergeModels")});var bu={};he(bu,{startCommand:()=>af});async function af(){let l=new ue,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Vs("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new Bt(e),r=!1,n=u(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready");let o=e.llm;o?.default?.provider?Io(o.default.provider,o.default.apiKey,o.default.baseUrl):o?.provider&&Io(o.provider,void 0,o.baseUrl);for(let i of["strong","fast"]){let a=o?.[i];a?.provider&&Io(a.provider,a.apiKey,a.baseUrl)}}catch(o){let i=o instanceof Error?o:new Error(String(o));t.fatal({err:i},"Failed to start Alfred"),process.exit(1)}}var Su=_(()=>{"use strict";et();di();za();Va();u(af,"startCommand")});var $u={};he($u,{chatCommand:()=>df});import vu from"node:http";import pn from"node:readline";function cf(l,e){return new Promise(t=>{let s=vu.get(`http://${l}:${e}/api/health`,{timeout:2e3},r=>{let n="";r.on("data",o=>{n+=o.toString()}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function lf(l,e){let t=pn.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
|
|
1280
1280
|
Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
|
|
1281
1281
|
`),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
|
|
1282
1282
|
Goodbye!
|
|
@@ -1291,42 +1291,42 @@ Error: ${f.text??"Unknown error"}
|
|
|
1291
1291
|
`),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let c=a.split(`
|
|
1292
1292
|
`).find(d=>d.startsWith("data: "));if(c)try{let d=JSON.parse(c.slice(6));(d.type==="done"||d.type==="error")&&t.prompt()}catch{}}}),i.on("error",c=>{console.error(`
|
|
1293
1293
|
Connection error: ${c.message}`),t.prompt()})});o.on("error",i=>{console.error(`
|
|
1294
|
-
Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function df(l){let e=new ue,t;try{t=e.loadConfig()}catch(i){console.error("Failed to load configuration:",i.message),process.exit(1)}let s=t.api?.host??"127.0.0.1",r=t.api?.port??3420;if(await cf(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),lf(s,r);return}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let i=t.llm[l.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new Bt(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var Iu=_(()=>{"use strict";et();za();u(cf,"checkHealth");u(lf,"startClientMode");u(df,"chatCommand")});var xu={};
|
|
1295
|
-
`);for(let f of p){let g=f.trim();if(!g||g.startsWith("#"))continue;let h=g.indexOf("=");h>0&&(t[g.slice(0,h)]=g.slice(h+1))}}catch{}let a
|
|
1294
|
+
Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function df(l){let e=new ue,t;try{t=e.loadConfig()}catch(i){console.error("Failed to load configuration:",i.message),process.exit(1)}let s=t.api?.host??"127.0.0.1",r=t.api?.port??3420;if(await cf(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),lf(s,r);return}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let i=t.llm[l.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new Bt(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var Iu=_(()=>{"use strict";et();za();u(cf,"checkHealth");u(lf,"startClientMode");u(df,"chatCommand")});var xu={};he(xu,{setupCommand:()=>kf});import{createInterface as uf}from"node:readline/promises";import{stdin as mf,stdout as pf}from"node:process";import{execFileSync as hf}from"node:child_process";import _e from"node:fs";import ff from"node:os";import Ie from"node:path";import Ka from"js-yaml";function F(l){return`${Ao}${l}${I}`}function Tf(l){return`${H}${l}${I}`}function we(l){return`${Ro}${l}${I}`}function Ru(l){return`${gf}${l}${I}`}function N(l){return`${J}${l}${I}`}function E(l){return`${ht}${l}${I}`}function ke(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function wf(l){let e=process.platform==="win32",t=e?"where":"which";try{let n=hf(t,[l],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=ff.homedir(),r=e?[Ie.join(s,".local","bin",`${l}.exe`),Ie.join(s,"AppData","Roaming","npm",`${l}.cmd`),Ie.join(s,"AppData","Roaming","npm",`${l}`)]:[Ie.join(s,".local","bin",l),"/usr/local/bin/"+l,"/opt/homebrew/bin/"+l,Ie.join(s,".npm-global","bin",l)];for(let n of r)try{return _e.accessSync(n,_e.constants.X_OK),n}catch{}return null}function _f(l){let e={},t={},s=!1,r=!1,n=30,o=Ie.join(l,"config","default.yml");if(_e.existsSync(o))try{let p=Ka.load(_e.readFileSync(o,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=Ie.join(l,".env");if(_e.existsSync(i))try{let p=_e.readFileSync(i,"utf-8").split(`
|
|
1295
|
+
`);for(let f of p){let g=f.trim();if(!g||g.startsWith("#"))continue;let h=g.indexOf("=");h>0&&(t[g.slice(0,h)]=g.slice(h+1))}}catch{}let a=Ie.join(l,"config","rules","default-rules.yml");if(_e.existsSync(a))try{let p=Ka.load(_e.readFileSync(a,"utf-8"));if(p?.rules){s=p.rules.some(h=>h.id==="allow-owner-admin"&&h.effect==="allow"),p.rules.find(h=>h.id==="allow-write-for-dm"||h.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let g=p.rules.find(h=>h.id==="rate-limit-write");g?.rateLimit?.maxInvocations&&(n=g.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled,d=e.llm,m={};if(d){for(let p of["strong","fast","embeddings","local"])d[p]?.provider&&d[p]?.model&&(m[p]=d[p]);d.default?.provider&&(e.llm={...e.llm,provider:d.default.provider,model:d.default.model,baseUrl:d.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c,multiModelTiers:m}}async function kf(){let l=uf({input:mf,output:pf}),e=process.cwd(),t=_f(e),s=Object.keys(t.config).length>0;try{Ef(),console.log(s?`${Ro}Existing configuration found \u2014 press Enter to keep current values.${I}
|
|
1296
1296
|
${ht}Only change what you need to update.${I}
|
|
1297
1297
|
`:`${Ro}Welcome to the Alfred setup wizard!${I}
|
|
1298
1298
|
${ht}This will walk you through configuring your AI assistant.${I}
|
|
1299
1299
|
${ht}Press Enter to accept defaults shown in [brackets].${I}
|
|
1300
1300
|
`);let r=await W(l,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?ot.findIndex(w=>w.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
|
|
1301
|
-
${N("Which LLM provider would you like to use?")}`);for(let w=0;w<ot.length;w++){let $=w===n?` ${E("(current)")}`:"";console.log(` ${
|
|
1301
|
+
${N("Which LLM provider would you like to use?")}`);for(let w=0;w<ot.length;w++){let $=w===n?` ${E("(current)")}`:"";console.log(` ${we(String(w+1)+")")} ${ot[w].label}${$}`)}let i=await hn(l,"> ",1,ot.length,o),a=ot[i-1];console.log(` ${F(">")} Selected: ${N(a.label)}`);let c="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?c=await W(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):c=await Le(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${F(">")} API key set: ${E(ke(c))}`));let m=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let $=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if($){let R={ollama:"Ollama URL (use a remote address if Ollama runs on another machine)",openwebui:"OpenWebUI URL",openai:"OpenAI-compatible API URL (leave default for official API)",openrouter:"OpenRouter API URL",google:"Google Gemini API URL (leave default for official API)"};console.log(""),m=await W(l,R[a.name]??"API Base URL",$.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${F(">")} URL: ${E(m)}`)}}let f=t.config.llm?.model??a.defaultModel;console.log("");let g,h=await Ga(a.name,c,m),y=Xa(h,a.models??[]);if(y.length>0){console.log(`${N("Available models:")}`);for(let R=0;R<y.length;R++){let V=y[R],M=V.desc??V.name??"",q=V.id===f?` ${F("(current)")}`:"";console.log(` ${we(`${R+1})`)} ${V.id}${M?` ${E(`\u2014 ${M}`)}`:""}${q}`)}console.log(` ${we(`${y.length+1})`)} ${E("Other (enter manually)")}`);let w=await W(l,"Choose model","1"),$=parseInt(w,10)-1;$>=0&&$<y.length?g=y[$].id:g=await W(l,"Model ID",f)}else g=await W(l,"Which model?",f);let k=Object.keys(t.multiModelTiers).length>0,S=k?"Y/n":"y/N";console.log(`
|
|
1302
1302
|
${N("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let b=(await l.question(`${H}> ${I}${E(`[${S}] `)}`)).trim().toLowerCase(),C=b===""?k:b==="y"||b==="yes",D={};if(C){let w=[{key:"strong",label:"Strong",hint:"complex reasoning, coding, long documents",defaultModel:"claude-opus-4-20250514"},{key:"fast",label:"Fast",hint:"quick responses, simple tasks",defaultModel:"claude-haiku-4-5-20251001"},{key:"embeddings",label:"Embeddings",hint:"semantic search & memory",defaultModel:"text-embedding-3-small"},{key:"local",label:"Local",hint:"offline fallback via Ollama",defaultModel:"llama3.2"}];for(let $ of w){let R=t.multiModelTiers[$.key],V=!!R?.model;console.log(`
|
|
1303
|
-
${N(`${$.label} model`)} ${E(`(${$.hint})`)}`),V&&console.log(` ${E(`Current: ${R.provider}/${R.model}`)}`);let M=R?.provider??a.name,q=ot.map(
|
|
1303
|
+
${N(`${$.label} model`)} ${E(`(${$.hint})`)}`),V&&console.log(` ${E(`Current: ${R.provider}/${R.model}`)}`);let M=R?.provider??a.name,q=ot.map(xe=>xe.name).join(", ");console.log(` ${E(`Providers: ${q}`)}`);let be=(await l.question(` ${H}Provider: ${I}${E(`[${M}] `)}`)).trim()||M;if(!be&&!V){console.log(` ${E("Skipped.")}`);continue}let Z=be,Se,Pe;if(Z!==a.name){let xe=R?.apiKey??t.env[`ALFRED_LLM_${$.key.toUpperCase()}_API_KEY`]??"";if(xe?Se=await W(l,` API key for ${Z}`,xe):(ot.find(Qe=>Qe.name===Z)?.needsApiKey??!0)&&(Se=await Le(l,` API key for ${Z}`)),["ollama","openwebui"].includes(Z)){let Qe=(R?.baseUrl??"")||ot.find(Rn=>Rn.name===Z)?.baseUrl||"";Qe&&(Pe=await W(l,` ${Z} URL`,Qe))}}let St=Se??(Z===a.name?c:void 0),Xs=Pe??(Z===a.name?m:void 0),si=ot.find(xe=>xe.name===Z),ri=await Ga(Z,St,Xs),ct=Xa(ri,si?.models??[]),Ze;if(ct.length>0){console.log(` ${N("Available models:")}`);for(let qt=0;qt<ct.length;qt++){let Qe=ct[qt],Rn=Qe.desc??Qe.name??"",wm=Qe.id===R?.model?` ${F("(current)")}`:"";console.log(` ${we(`${qt+1})`)} ${Qe.id}${Rn?` ${E(`\u2014 ${Rn}`)}`:""}${wm}`)}console.log(` ${we(`${ct.length+1})`)} ${E("Other (enter manually)")}`),console.log(` ${we("0)")} ${E("Skip this tier")}`);let xe=(await l.question(` ${H}> ${I}${V?E(`[${R.model}] `):""}`)).trim();if(xe==="0"){console.log(` ${E("Skipped.")}`);continue}let An=parseInt(xe,10)-1;An>=0&&An<ct.length?Ze=ct[An].id:!xe&&V?Ze=R.model:Ze=await W(l," Model ID",V?R.model:$.defaultModel)}else if(console.log(` ${E("Press Enter to skip.")}`),Ze=(await l.question(` ${H}Model: ${I}${V?E(`[${R.model}] `):""}`)).trim()||(V?R.model:""),!Ze){console.log(` ${E("Skipped.")}`);continue}D[$.key]={provider:Z,model:Ze,...Se?{apiKey:Se}:{},...Pe?{baseUrl:Pe}:{}},console.log(` ${F(">")} ${$.label}: ${N(Z)}/${N(Ze)}`)}Object.keys(D).length===0&&console.log(`
|
|
1304
1304
|
${E("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${E("Using single model for all tasks.")}`);let U=["brave","tavily","duckduckgo","searxng"],Q=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",ie=U.indexOf(Q),j=ie>=0?ie+1:0;console.log(`
|
|
1305
|
-
${N("Web Search provider (for searching the internet):")}`);let z=["Brave Search \u2014 recommended, free tier (2,000/month)","Tavily \u2014 built for AI agents, free tier (1,000/month)","DuckDuckGo \u2014 free, no API key needed","SearXNG \u2014 self-hosted, no API key needed"],ae=u(w=>ie===w?` ${E("(current)")}`:"","mark");console.log(` ${
|
|
1306
|
-
${N("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<Rs.length;w++){let $=me.includes(w+1)?` ${E("(enabled)")}`:"";console.log(` ${
|
|
1305
|
+
${N("Web Search provider (for searching the internet):")}`);let z=["Brave Search \u2014 recommended, free tier (2,000/month)","Tavily \u2014 built for AI agents, free tier (1,000/month)","DuckDuckGo \u2014 free, no API key needed","SearXNG \u2014 self-hosted, no API key needed"],ae=u(w=>ie===w?` ${E("(current)")}`:"","mark");console.log(` ${we("0)")} None (disable web search)${ie===-1&&Q===""?` ${E("(current)")}`:""}`);for(let w=0;w<z.length;w++)console.log(` ${we(String(w+1)+")")} ${z[w]}${ae(w)}`);let L=await hn(l,"> ",0,U.length,j),se,K="",P="";if(L>=1&&L<=U.length&&(se=U[L-1]),se==="brave"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?K=await W(l," Brave Search API key",w):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),K=await Le(l," Brave Search API key")),console.log(` ${F(">")} Brave Search: ${E(ke(K))}`)}else if(se==="tavily"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?K=await W(l," Tavily API key",w):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),K=await Le(l," Tavily API key")),console.log(` ${F(">")} Tavily: ${E(ke(K))}`)}else if(se==="duckduckgo")console.log(` ${F(">")} DuckDuckGo: ${E("no API key needed")}`);else if(se==="searxng"){let w=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";P=await W(l," SearXNG URL",w),P=P.replace(/\/+$/,""),console.log(` ${F(">")} SearXNG: ${E(P)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let me=[];for(let w=0;w<Rs.length;w++){let $=Rs[w];t.config[$.configKey]?.enabled&&me.push(w+1)}let De=me.length>0?me.join(","):"";console.log(`
|
|
1306
|
+
${N("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<Rs.length;w++){let $=me.includes(w+1)?` ${E("(enabled)")}`:"";console.log(` ${we(String(w+1)+")")} ${Rs[w].label}${$}`)}console.log(` ${we("0)")} None (configure later)`);let Ae=(await l.question(`${H}> ${I}${De?E(`[${De}] `):""}`)).trim(),ee=[],Ee=Ae||De;if(Ee&&Ee!=="0"){let w=Ee.split(",").map($=>parseInt($.trim(),10));for(let $ of w)if($>=1&&$<=Rs.length){let R=Rs[$-1];ee.includes(R)||ee.push(R)}}ee.length>0?console.log(` ${F(">")} Enabling: ${ee.map(w=>N(w.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let de={},Ve={};for(let w of ee){if(w.credentials.length===0){w.name==="whatsapp"&&console.log(`
|
|
1307
1307
|
${Tf("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
|
|
1308
|
-
${N(w.label+" configuration:")}`);let $={};for(let R of w.credentials){let V=t.env[R.envKey]??"",M;V?M=await W(l,` ${R.prompt}`,V):R.defaultValue?M=await W(l,` ${R.prompt}`,R.defaultValue):R.required?M=await
|
|
1309
|
-
${N("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let X=(await l.question(`${H}> ${I}${E(`[${ft}] `)}`)).trim().toLowerCase(),v=X===""?it:X==="y"||X==="yes",O=[],
|
|
1310
|
-
${N("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if(R==="y"||R==="yes"){let M=(await l.question(` ${N("Account name:")} `)).trim()||`account${O.length+1}`,q=Ke.find(te=>te.name===M);O.push(await
|
|
1311
|
-
${N("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let Qa=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${
|
|
1308
|
+
${N(w.label+" configuration:")}`);let $={};for(let R of w.credentials){let V=t.env[R.envKey]??"",M;V?M=await W(l,` ${R.prompt}`,V):R.defaultValue?M=await W(l,` ${R.prompt}`,R.defaultValue):R.required?M=await Le(l,` ${R.prompt}`):(M=(await l.question(` ${R.prompt}: ${H}`)).trim(),process.stdout.write(I)),$[R.configField]=M,Ve[R.envKey]=M,R.configField==="token"||R.configField==="accessToken"?console.log(` ${F(">")} Set: ${E(ke(M))}`):console.log(` ${F(">")} Set: ${E(M)}`)}de[w.configKey]=$}let Ke=t.config.email?.accounts??[],Ye=Ke[0],ve=Ye?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",xs=Ye?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",it=Ke.length>0||!!ve||xs==="microsoft",ft=it?"Y/n":"y/N";console.log(`
|
|
1309
|
+
${N("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let X=(await l.question(`${H}> ${I}${E(`[${ft}] `)}`)).trim().toLowerCase(),v=X===""?it:X==="y"||X==="yes",O=[],Y={"gmail.com":{imap:"imap.gmail.com",smtp:"smtp.gmail.com"},"googlemail.com":{imap:"imap.gmail.com",smtp:"smtp.gmail.com"},"outlook.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"hotmail.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"live.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"yahoo.com":{imap:"imap.mail.yahoo.com",smtp:"smtp.mail.yahoo.com"},"icloud.com":{imap:"imap.mail.me.com",smtp:"smtp.mail.me.com"},"me.com":{imap:"imap.mail.me.com",smtp:"smtp.mail.me.com"},"gmx.de":{imap:"imap.gmx.net",smtp:"mail.gmx.net"},"gmx.net":{imap:"imap.gmx.net",smtp:"mail.gmx.net"},"web.de":{imap:"imap.web.de",smtp:"smtp.web.de"},"posteo.de":{imap:"posteo.de",smtp:"posteo.de"},"mailbox.org":{imap:"imap.mailbox.org",smtp:"smtp.mailbox.org"},"protonmail.com":{imap:"127.0.0.1",smtp:"127.0.0.1"},"proton.me":{imap:"127.0.0.1",smtp:"127.0.0.1"}},pe=u(async(w,$)=>{let R={name:w,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},V=$?.provider??"",M=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],q=V==="microsoft"?1:0;console.log("");for(let Z=0;Z<M.length;Z++){let Se=Z===q?` ${E("(current)")}`:"";console.log(` ${we(`${Z+1})`)} ${M[Z]}${Se}`)}let te=(await l.question(`${H}> ${I}${E(`[${q+1}] `)}`)).trim(),be=te===""?q:parseInt(te,10)-1;if(R.provider=be===1?"microsoft":"imap-smtp",R.provider==="microsoft"){let Z=t.config.calendar?.microsoft,Se=$?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",Pe=$?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",St=$?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(Z&&!Se)console.log(` ${F(">")} Microsoft Calendar already configured \u2014 credentials will be shared.`),console.log(` ${E("The same Azure App Registration will be used for Mail + Calendar.")}`),console.log(` ${E("Ensure the app has Mail.ReadWrite and Mail.Send scopes.")}`);else{console.log(` ${E("Azure Portal \u2192 App Registrations \u2192 your app \u2192 Mail.ReadWrite + Mail.Send scopes")}`),R.msClientId=await W(l," Client ID",Se),R.msClientId||(R.msClientId=await Le(l," Client ID"));let Xs=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";R.msClientSecret=await W(l," Client Secret",Xs),R.msClientSecret||(R.msClientSecret=await Le(l," Client Secret")),R.msTenantId=await W(l," Tenant ID",Pe),R.msTenantId||(R.msTenantId=await Le(l," Tenant ID")),console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),R.msRefreshToken=await W(l," Refresh Token",St),R.msRefreshToken||(R.msRefreshToken=await Le(l," Refresh Token"))}console.log(` ${F(">")} Email [${w}]: Microsoft 365 (Graph API)`)}else{let Z=$?.auth?.user??"";console.log(""),R.user=await W(l," Email address",Z||""),R.user||(R.user=await Le(l," Email address"));let Se=$?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";Se?R.pass=await W(l," Password / App password",Se):(console.log(` ${E("For Gmail: use an App Password (not your regular password)")}`),console.log(` ${E(" \u2192 Google Account \u2192 Security \u2192 2-Step \u2192 App passwords")}`),R.pass=await Le(l," Password / App password"));let Pe=R.user.split("@")[1]?.toLowerCase()??"",St=Y[Pe],Xs=$?.imap?.host??St?.imap??`imap.${Pe}`,si=$?.smtp?.host??St?.smtp??`smtp.${Pe}`,ri=$?.imap?.port??993,ct=$?.smtp?.port??587;St&&console.log(` ${F(">")} Detected ${Pe} \u2014 using preset server settings`),R.imapHost=await W(l," IMAP server",Xs);let Ze=await W(l," IMAP port",String(ri));R.imapPort=parseInt(Ze,10)||993,R.smtpHost=await W(l," SMTP server",si);let xe=await W(l," SMTP port",String(ct));R.smtpPort=parseInt(xe,10)||587,console.log(` ${F(">")} Email [${w}]: ${E(R.user)} via ${E(R.imapHost)}`)}return R},"configureEmailAccount");if(v){let w=Ye??(t.config.email?.auth?{provider:t.config.email.provider,auth:t.config.email.auth,imap:t.config.email.imap,smtp:t.config.email.smtp,microsoft:t.config.email.microsoft}:void 0);O.push(await pe("default",w));let $=!0;for(;$;){let R=(await l.question(`
|
|
1310
|
+
${N("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if(R==="y"||R==="yes"){let M=(await l.question(` ${N("Account name:")} `)).trim()||`account${O.length+1}`,q=Ke.find(te=>te.name===M);O.push(await pe(M,q))}else $=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let le=["openai","groq"],Ge=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",gn=le.indexOf(Ge),Xu=gn>=0?gn+1:0;console.log(`
|
|
1311
|
+
${N("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let Qa=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${we("0)")} None (disable voice transcription)${gn===-1?` ${E("(current)")}`:""}`);for(let w=0;w<Qa.length;w++){let $=gn===w?` ${E("(current)")}`:"";console.log(` ${we(String(w+1)+")")} ${Qa[w]}${$}`)}let Co=await hn(l,"> ",0,le.length,Xu),Xe,at="",Cs="";if(Co>=1&&Co<=le.length&&(Xe=le[Co-1]),Xe==="openai"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?at=await W(l," OpenAI API key (for Whisper)",w):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),at=await Le(l," OpenAI API key")),console.log(` ${F(">")} OpenAI Whisper: ${E(ke(at))}`)}else if(Xe==="groq"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?at=await W(l," Groq API key",w):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),at=await Le(l," Groq API key"));let $=t.env.ALFRED_SPEECH_BASE_URL??"";$&&(Cs=await W(l," Groq API URL",$)),console.log(` ${F(">")} Groq Whisper: ${E(ke(at))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let Ns=!1,Ls="alloy";if(Xe){let w=t.config.speech?.ttsEnabled??!1,$=w?"Y/n":"y/N";console.log(`
|
|
1312
1312
|
${N("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let R=(await l.question(`${H}> ${I}${E(`[${$}] `)}`)).trim().toLowerCase();if(Ns=R===""?w:R==="y"||R==="yes",Ns){let V=["alloy","echo","fable","onyx","nova","shimmer"],M=t.config.speech?.ttsVoice??"alloy",q=V.indexOf(M),te=q>=0?q+1:1;console.log(`
|
|
1313
|
-
${N("Which voice?")}`);for(let Z=0;Z<V.length;Z++){let
|
|
1313
|
+
${N("Which voice?")}`);for(let Z=0;Z<V.length;Z++){let Se=q===Z?` ${E("(current)")}`:"";console.log(` ${we(String(Z+1)+")")} ${V[Z]}${Se}`)}let be=await hn(l," > ",1,V.length,te);Ls=V[be-1],console.log(` ${F(">")} TTS voice: ${N(Ls)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Vu=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
|
|
1314
1314
|
${N("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let No=(await l.question(`${H}> ${I}${E(`[${Vu}] `)}`)).trim().toLowerCase(),Lo=No===""?t.codeSandboxEnabled:No==="y"||No==="yes";console.log(Lo?` ${F(">")} Code Sandbox ${N("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
|
|
1315
1315
|
${N("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let Do=[];for(let w of Au){let $=wf(w.whichCmd);$?(Do.push({...w,resolvedPath:$}),console.log(` ${F("\u2713")} ${N(w.label)} ${E(`(${$})`)}`)):console.log(` ${E("\xB7")} ${E(w.label)} ${E("\u2014 not found")}`)}let Mo=(t.config.codeAgents?.agents??[]).filter(w=>!Au.some($=>$.name===w.name));for(let w of Mo)console.log(` ${F("\u2713")} ${N(w.name)} ${E(`(${w.command}) \u2014 from existing config`)}`);let gt=[];if(Do.length===0&&Mo.length===0)console.log(`
|
|
1316
1316
|
${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let w=[...Do.map(M=>({name:M.name,command:M.resolvedPath??M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia,label:M.label,detected:!0})),...Mo.map(M=>({name:M.name,command:M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia??"arg",label:M.name,detected:!1}))];console.log(`
|
|
1317
1317
|
${N("Which agents should Alfred use?")} ${E("(comma-separated, e.g. 1,2)")}`);let $=new Set((t.config.codeAgents?.agents??[]).map(M=>M.name));for(let M=0;M<w.length;M++){let q=w[M],te=$.has(q.name)?` ${E("(current)")}`:"";console.log(` ${H}${M+1}${I}) ${q.label}${te}`)}console.log(` ${H}0${I}) None`);let R=w.map((M,q)=>$.size>0?$.has(M.name)?String(q+1):null:M.detected?String(q+1):null).filter(Boolean).join(",")||"0",V=(await l.question(` ${H}> ${I}${E(`[${R}] `)}`)).trim()||R;V!=="0"&&(gt=V.split(",").map(q=>parseInt(q.trim(),10)).filter(q=>!isNaN(q)&&q>=1&&q<=w.length).map(q=>{let te=w[q-1];return{name:te.name,command:te.command,argsTemplate:te.argsTemplate,promptVia:te.promptVia}})),gt.length>0?console.log(` ${F(">")} ${N(String(gt.length))} agent(s) selected: ${gt.map(M=>M.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let Oo=t.config.codeAgents?.forge,Uo=Oo?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
|
|
1318
|
-
${N("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${E("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${E("Owner/repo are detected automatically from the git remote at runtime.")}`);let ec=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let w of ec){let $=w.name===Uo?` ${E("(current)")}`:"";console.log(` ${H}${w.num}${I}) ${w.label}${$}`)}let tc=Uo==="github"?"2":Uo==="gitlab"?"3":"1",Ku=(await l.question(`${H}> ${I}${E(`[${tc}] `)}`)).trim()||tc,yt=ec.find(w=>w.num===Ku)?.name??"",Ds="",Ms="";if(yt==="github"){console.log(` ${F(">")} Forge: ${N("GitHub")}`);let w=t.env.ALFRED_GITHUB_TOKEN??Oo?.github?.token??"";w&&console.log(` ${E(`Current token: ${
|
|
1319
|
-
${N("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Os=t.config.proxmox,Po=t.env.ALFRED_PROXMOX_BASE_URL??Os?.baseUrl??"",Yu=Po?"Y/n":"y/N",sc=(await l.question(` ${
|
|
1320
|
-
${
|
|
1321
|
-
${
|
|
1322
|
-
${
|
|
1323
|
-
${
|
|
1324
|
-
${
|
|
1325
|
-
${
|
|
1326
|
-
${
|
|
1327
|
-
${N("Security configuration:")}`);let uc=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",
|
|
1328
|
-
${N("Writing configuration files...")}`);let A=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";A.push(`${w}=${c}`)}if(g!==a.defaultModel&&A.push(`ALFRED_LLM_MODEL=${g}`),m&&A.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(D).length>0){A.push("","# === Additional Model Tiers ===");for(let[w,$]of Object.entries(D)){let R=`ALFRED_LLM_${w.toUpperCase()}`;A.push(""),A.push(`${R}_PROVIDER=${$.provider}`),A.push(`${R}_MODEL=${$.model}`),$.apiKey&&A.push(`${R}_API_KEY=${$.apiKey}`),$.baseUrl&&A.push(`${R}_BASE_URL=${$.baseUrl}`)}}A.push("","# === Messaging Platforms ===","");for(let[w,$]of Object.entries(Ve))A.push(`${w}=${$}`);if(A.push("","# === Web Search ===",""),se?(A.push(`ALFRED_SEARCH_PROVIDER=${se}`),K&&A.push(`ALFRED_SEARCH_API_KEY=${K}`),P&&A.push(`ALFRED_SEARCH_BASE_URL=${P}`)):(A.push("# ALFRED_SEARCH_PROVIDER=brave"),A.push("# ALFRED_SEARCH_API_KEY=")),A.push("","# === Email ===",""),v&&O.length>0){let w=O[0];w.provider==="microsoft"?(A.push("ALFRED_EMAIL_PROVIDER=microsoft"),w.msClientId?(A.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${w.msClientId}`),A.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${w.msClientSecret}`),A.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${w.msTenantId}`),A.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${w.msRefreshToken}`)):A.push("# Microsoft email credentials shared from calendar config")):(A.push(`ALFRED_EMAIL_USER=${w.user}`),A.push(`ALFRED_EMAIL_PASS=${w.pass}`)),O.length>1&&A.push("# Additional email accounts configured in config/default.yml")}else A.push("# ALFRED_EMAIL_USER="),A.push("# ALFRED_EMAIL_PASS=");if(A.push("","# === Speech ===",""),Xe?(A.push(`ALFRED_SPEECH_PROVIDER=${Xe}`),A.push(`ALFRED_SPEECH_API_KEY=${at}`),Cs&&A.push(`ALFRED_SPEECH_BASE_URL=${Cs}`),Ns&&(A.push("ALFRED_TTS_ENABLED=true"),A.push(`ALFRED_TTS_VOICE=${Ls}`))):(A.push("# ALFRED_SPEECH_PROVIDER=groq"),A.push("# ALFRED_SPEECH_API_KEY=")),A.push("","# === Forge (GitHub / GitLab) ===",""),yt==="github"?(A.push("ALFRED_FORGE_PROVIDER=github"),A.push(`ALFRED_GITHUB_TOKEN=${Ds}`)):yt==="gitlab"?(A.push("ALFRED_FORGE_PROVIDER=gitlab"),A.push(`ALFRED_GITLAB_TOKEN=${Ms}`)):(A.push("# ALFRED_FORGE_PROVIDER=github"),A.push("# ALFRED_GITHUB_TOKEN=")),A.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),yn?(A.push(`ALFRED_PROXMOX_BASE_URL=${Us}`),A.push(`ALFRED_PROXMOX_TOKEN_ID=${Fo}`),A.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Ps}`)):(A.push("# ALFRED_PROXMOX_BASE_URL="),A.push("# ALFRED_PROXMOX_TOKEN_ID="),A.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),Fs&&wt?(A.push(`ALFRED_UNIFI_BASE_URL=${zt}`),A.push(`ALFRED_UNIFI_API_KEY=${wt}`)):Fs?(A.push(`ALFRED_UNIFI_BASE_URL=${zt}`),A.push(`ALFRED_UNIFI_USERNAME=${Bo}`),A.push(`ALFRED_UNIFI_PASSWORD=${js}`)):(A.push("# ALFRED_UNIFI_BASE_URL="),A.push("# ALFRED_UNIFI_API_KEY=")),wn?(A.push(`ALFRED_HOMEASSISTANT_URL=${Hs}`),A.push(`ALFRED_HOMEASSISTANT_TOKEN=${Bs}`)):(A.push("# ALFRED_HOMEASSISTANT_URL="),A.push("# ALFRED_HOMEASSISTANT_TOKEN=")),A.push("","# === Contacts ===",""),_n)for(let[w,$]of Object.entries(
|
|
1329
|
-
`),"utf-8"),console.log(` ${F("+")} ${E(".env")} written`);let In
|
|
1318
|
+
${N("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${E("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${E("Owner/repo are detected automatically from the git remote at runtime.")}`);let ec=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let w of ec){let $=w.name===Uo?` ${E("(current)")}`:"";console.log(` ${H}${w.num}${I}) ${w.label}${$}`)}let tc=Uo==="github"?"2":Uo==="gitlab"?"3":"1",Ku=(await l.question(`${H}> ${I}${E(`[${tc}] `)}`)).trim()||tc,yt=ec.find(w=>w.num===Ku)?.name??"",Ds="",Ms="";if(yt==="github"){console.log(` ${F(">")} Forge: ${N("GitHub")}`);let w=t.env.ALFRED_GITHUB_TOKEN??Oo?.github?.token??"";w&&console.log(` ${E(`Current token: ${ke(w)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),Ds=(await l.question(` ${J}GitHub Token${I}: ${H}`)).trim(),process.stdout.write(I),!Ds&&w&&(Ds=w)}else if(yt==="gitlab"){console.log(` ${F(">")} Forge: ${N("GitLab")}`);let w=t.env.ALFRED_GITLAB_TOKEN??Oo?.gitlab?.token??"";w&&console.log(` ${E(`Current token: ${ke(w)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),Ms=(await l.question(` ${J}GitLab Token${I}: ${H}`)).trim(),process.stdout.write(I),!Ms&&w&&(Ms=w)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
|
|
1319
|
+
${N("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Os=t.config.proxmox,Po=t.env.ALFRED_PROXMOX_BASE_URL??Os?.baseUrl??"",Yu=Po?"Y/n":"y/N",sc=(await l.question(` ${J}Enable Proxmox VE?${I} ${E(`[${Yu}]`)}: ${H}`)).trim().toLowerCase()||(Po?"y":"n");process.stdout.write(I);let yn=sc==="y"||sc==="yes",Us="",Fo="",Ps="",jo=!0;if(yn){Us=await W(l," Proxmox URL (e.g. https://pve.local:8006)",Po||"https://pve.local:8006");let w=t.env.ALFRED_PROXMOX_TOKEN_ID??Os?.tokenId??"";w&&console.log(` ${E(`Current token ID: ${w}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),Fo=await W(l," API Token ID (user@realm!name)",w);let $=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Os?.tokenSecret??"";$&&console.log(` ${E(`Current secret: ${ke($)}`)}`),Ps=(await l.question(` ${J}API Token Secret${I}: ${H}`)).trim(),process.stdout.write(I),!Ps&&$&&(Ps=$);let R=Os?.verifyTls===!1?"y/N":"Y/n",V=(await l.question(` ${J}Verify TLS?${I} ${E(`(self-signed? \u2192 no) [${R}]`)}: ${H}`)).trim().toLowerCase()||(Os?.verifyTls===!1?"n":"y");process.stdout.write(I),jo=V==="y"||V==="yes",console.log(` ${F(">")} Proxmox: ${N(Us)} ${E(`(TLS verify: ${jo?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let Tt=t.config.unifi,Ho=t.env.ALFRED_UNIFI_BASE_URL??Tt?.baseUrl??"",Ju=Ho?"Y/n":"y/N",rc=(await l.question(`
|
|
1320
|
+
${J}Enable UniFi Network?${I} ${E(`[${Ju}]`)}: ${H}`)).trim().toLowerCase()||(Ho?"y":"n");process.stdout.write(I);let Fs=rc==="y"||rc==="yes",zt="",wt="",Bo="",js="",Wo=!0;if(Fs){zt=await W(l," UniFi URL (e.g. https://unifi.local)",Ho||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let w=t.env.ALFRED_UNIFI_API_KEY??Tt?.apiKey??"",$=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],R=w?"1":Tt?.username?"2":"1";for(let te of $)console.log(` ${H}${te.num}${I}) ${te.label}`);if(((await l.question(` ${H}> ${I}${E(`[${R}] `)}`)).trim()||R)==="1")w&&console.log(` ${E(`Current key: ${ke(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),wt=(await l.question(` ${J}API Key${I}: ${H}`)).trim(),process.stdout.write(I),!wt&&w&&(wt=w);else{let te=t.env.ALFRED_UNIFI_USERNAME??Tt?.username??"";Bo=await W(l," Username",te||"alfred");let be=t.env.ALFRED_UNIFI_PASSWORD??Tt?.password??"";be&&console.log(` ${E(`Current password: ${ke(be)}`)}`),js=(await l.question(` ${J}Password${I}: ${H}`)).trim(),process.stdout.write(I),!js&&be&&(js=be)}let M=Tt?.verifyTls===!1?"y/N":"Y/n",q=(await l.question(` ${J}Verify TLS?${I} ${E(`(self-signed? \u2192 no) [${M}]`)}: ${H}`)).trim().toLowerCase()||(Tt?.verifyTls===!1?"n":"y");process.stdout.write(I),Wo=q==="y"||q==="yes",console.log(` ${F(">")} UniFi: ${N(zt)} ${E(`(TLS verify: ${Wo?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let Tn=t.config.homeassistant,zo=t.env.ALFRED_HOMEASSISTANT_URL??Tn?.baseUrl??"",Zu=zo?"Y/n":"y/N",nc=(await l.question(`
|
|
1321
|
+
${J}Enable Home Assistant?${I} ${E(`[${Zu}]`)}: ${H}`)).trim().toLowerCase()||(zo?"y":"n");process.stdout.write(I);let wn=nc==="y"||nc==="yes",Hs="",Bs="",qo=!0;if(wn){Hs=await W(l," Home Assistant URL (e.g. http://homeassistant.local:8123)",zo||"http://homeassistant.local:8123");let w=t.env.ALFRED_HOMEASSISTANT_TOKEN??Tn?.accessToken??"";w&&console.log(` ${E(`Current token: ${ke(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),Bs=(await l.question(` ${J}Long-Lived Access Token${I}: ${H}`)).trim(),process.stdout.write(I),!Bs&&w&&(Bs=w);let $=Tn?.verifyTls===!1?"y/N":"Y/n",R=(await l.question(` ${J}Verify TLS?${I} ${E(`(self-signed? \u2192 no) [${$}]`)}: ${H}`)).trim().toLowerCase()||(Tn?.verifyTls===!1?"n":"y");process.stdout.write(I),qo=R==="y"||R==="yes",console.log(` ${F(">")} Home Assistant: ${N(Hs)} ${E(`(TLS verify: ${qo?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let Oe=t.config.contacts,Go=t.env.ALFRED_CONTACTS_PROVIDER??Oe?.provider??"",Qu=Go?"Y/n":"y/N",oc=(await l.question(`
|
|
1322
|
+
${J}Enable Contacts management?${I} ${E(`[${Qu}]`)}: ${H}`)).trim().toLowerCase()||(Go?"y":"n");process.stdout.write(I);let _n=oc==="y"||oc==="yes",Ue="",ye={};if(_n){let w=["carddav","google","microsoft"],$=w.indexOf(Go),R=$>=0?$+1:1;console.log(` ${we("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${we("2)")} Google Contacts`),console.log(` ${we("3)")} Microsoft 365`);let V=await hn(l," > ",1,3,R);if(Ue=w[V-1],ye.ALFRED_CONTACTS_PROVIDER=Ue,Ue==="carddav"){let M=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??Oe?.carddav?.serverUrl??"";ye.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await W(l," CardDAV Server URL",M||"https://cloud.example.com/remote.php/dav");let q=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??Oe?.carddav?.username??"";ye.ALFRED_CARDDAV_CONTACTS_USERNAME=await W(l," Username",q);let te=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??Oe?.carddav?.password??"";te&&console.log(` ${E(`Current password: ${ke(te)}`)}`);let be=(await l.question(` ${J}Password${I}: ${H}`)).trim();process.stdout.write(I),ye.ALFRED_CARDDAV_CONTACTS_PASSWORD=be||te}else if(Ue==="google"){let M=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??Oe?.google?.clientId??"";M&&console.log(` ${E(`Current client ID: ${ke(M)}`)}`),ye.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await l.question(` ${J}Google Client ID${I}: ${H}`)).trim()||M,process.stdout.write(I);let q=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??Oe?.google?.clientSecret??"";ye.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await l.question(` ${J}Google Client Secret${I}: ${H}`)).trim()||q,process.stdout.write(I);let te=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??Oe?.google?.refreshToken??"";ye.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await l.question(` ${J}Refresh Token${I}: ${H}`)).trim()||te,process.stdout.write(I)}else if(Ue==="microsoft"){let M=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??Oe?.microsoft?.clientId??"";M&&console.log(` ${E(`Current client ID: ${ke(M)}`)}`),ye.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await l.question(` ${J}Microsoft Client ID${I}: ${H}`)).trim()||M,process.stdout.write(I);let q=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??Oe?.microsoft?.clientSecret??"";ye.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await l.question(` ${J}Microsoft Client Secret${I}: ${H}`)).trim()||q,process.stdout.write(I);let te=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??Oe?.microsoft?.tenantId??"";ye.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await W(l," Tenant ID",te||"common");let be=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??Oe?.microsoft?.refreshToken??"";console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),ye.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await l.question(` ${J}Refresh Token${I}: ${H}`)).trim()||be,process.stdout.write(I)}console.log(` ${F(">")} Contacts: ${N(Ue)}`)}else console.log(` ${E("Contacts disabled.")}`);let ic=t.config.docker,Xo=t.env.ALFRED_DOCKER_SOCKET_PATH??ic?.socketPath??"",Vo=t.env.ALFRED_DOCKER_HOST??ic?.host??"",em=Xo||Vo?"Y/n":"y/N",ac=(await l.question(`
|
|
1323
|
+
${J}Enable Docker management?${I} ${E(`[${em}]`)}: ${H}`)).trim().toLowerCase()||(Xo||Vo?"y":"n");process.stdout.write(I);let kn=ac==="y"||ac==="yes",_t="",kt="";if(kn){let w=process.platform==="win32"?"//./pipe/docker_engine":"/var/run/docker.sock";console.log(` ${E("Use socket path for local Docker, or host URL for remote.")}`),_t=await W(l," Docker socket path",Xo||w);let $=(await l.question(` ${J}Docker host URL (optional, for remote)${I}: ${H}`)).trim();process.stdout.write(I),kt=$||Vo,console.log(` ${F(">")} Docker: ${N(kt||_t)}`)}else console.log(` ${E("Docker disabled.")}`);let tm=t.config.bmw,Ko=t.env.ALFRED_BMW_CLIENT_ID??tm?.clientId??"",sm=Ko?"Y/n":"y/N",cc=(await l.question(`
|
|
1324
|
+
${J}Enable BMW CarData (vehicle status, charging)?${I} ${E(`[${sm}]`)}: ${H}`)).trim().toLowerCase()||(Ko?"y":"n");process.stdout.write(I);let En=cc==="y"||cc==="yes",Yo="";En?(console.log(` ${E("Setup:")}`),console.log(` ${E(" 1. \xD6ffne https://bmw-cardata.bmwgroup.com/customer")}`),console.log(` ${E(" 2. Login mit deinem MyBMW-Account")}`),console.log(` ${E(" 3. Client-ID generieren")}`),console.log(` ${E(' 4. Scope "CarData API" aktivieren (ca. 60s warten)')}`),Yo=await W(l," BMW CarData Client ID",Ko),console.log(` ${F(">")} BMW CarData: ${N("enabled")}`)):console.log(` ${E("BMW CarData disabled.")}`);let rm=t.config.routing,Jo=t.env.ALFRED_ROUTING_API_KEY??rm?.apiKey??"",nm=Jo?"Y/n":"y/N",lc=(await l.question(`
|
|
1325
|
+
${J}Enable route planning with live traffic (Google Routes)?${I} ${E(`[${nm}]`)}: ${H}`)).trim().toLowerCase()||(Jo?"y":"n");process.stdout.write(I);let bn=lc==="y"||lc==="yes",Zo="";bn?(console.log(` ${E("Setup:")}`),console.log(` ${E(" 1. \xD6ffne https://console.cloud.google.com")}`),console.log(` ${E(" 2. Routes API aktivieren")}`),console.log(` ${E(" 3. API Key erstellen")}`),Zo=await W(l," Google Maps API Key",Jo),console.log(` ${F(">")} Routing: ${N("enabled")}`)):console.log(` ${E("Routing disabled.")}`);let Je=t.config.energy,om=t.env.ALFRED_ENERGY_GRID_NAME??Je?.gridName??"",Qo=t.env.ALFRED_ENERGY_GRID_USAGE_CT??(Je?.gridUsageCt!=null?String(Je.gridUsageCt):""),im=t.env.ALFRED_ENERGY_GRID_LOSS_CT??(Je?.gridLossCt!=null?String(Je.gridLossCt):""),am=t.env.ALFRED_ENERGY_GRID_CAPACITY_FEE??(Je?.gridCapacityFee!=null?String(Je.gridCapacityFee):""),cm=t.env.ALFRED_ENERGY_GRID_METER_FEE??(Je?.gridMeterFee!=null?String(Je.gridMeterFee):""),lm=Qo?"Y/n":"y/N",dc=(await l.question(`
|
|
1326
|
+
${J}Enable energy prices (aWATTar HOURLY / EPEX Spot AT)?${I} ${E(`[${lm}]`)}: ${H}`)).trim().toLowerCase()||(Qo?"y":"n");process.stdout.write(I);let Sn=dc==="y"||dc==="yes",Et="",bt="",vn="",Ws="",zs="";Sn?(console.log(` ${E('Die Werte findest du auf deiner Stromrechnung unter "Netzentgelte".')}`),console.log(` ${E("Marktpreis + aWATTar-Aufschlag + Abgaben werden automatisch berechnet.")}`),console.log(""),Et=await W(l," Netzbetreiber Name (z.B. Netz Nieder\xF6sterreich)",om),bt=await W(l," Netznutzungsentgelt (ct/kWh netto)",Qo),vn=await W(l," Netzverlustentgelt (ct/kWh netto)",im||"0.38"),Ws=await W(l," Leistungspauschale (\u20AC/Monat netto)",am),zs=await W(l," Messentgelt (\u20AC/Monat netto)",cm||"2.22"),console.log(` ${F(">")} Energy: ${N(Et||"enabled")} (${bt} + ${vn} ct/kWh)`)):console.log(` ${E("Energy prices disabled (Marktpreise weiterhin ohne Netzentgelte verf\xFCgbar).")}`),console.log(`
|
|
1327
|
+
${N("Security configuration:")}`);let uc=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",Re;if(uc)Re=await W(l,"Owner user ID (for elevated permissions)",uc);else{let w=(await l.question(`${J}Owner user ID${I} ${E("(optional, for elevated permissions)")}: ${H}`)).trim();process.stdout.write(I),Re=w}let qs=!1;if(Re){let w=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${N("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let $=(await l.question(` ${H}> ${I}${E(`[${w}] `)}`)).trim().toLowerCase();$===""?qs=t.shellEnabled:qs=$==="y"||$==="yes",console.log(qs?` ${F(">")} Shell access ${N("enabled")} for owner ${E(Re)}`:` ${E("Shell access disabled.")}`)}let dm=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${N("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let ei=(await l.question(` ${H}> ${I}${E(`[${dm}] `)}`)).trim().toLowerCase(),Gs;ei===""?Gs=t.writeInGroups:Gs=ei==="y"||ei==="yes",console.log(Gs?` ${F(">")} Write actions ${N("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let um=t.rateLimit??30;console.log("");let mm=await W(l," Rate limit (max write actions per hour per user)",String(um)),$n=Math.max(1,parseInt(mm,10)||30);console.log(` ${F(">")} Rate limit: ${N(String($n))} per hour`),console.log(`
|
|
1328
|
+
${N("Writing configuration files...")}`);let A=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";A.push(`${w}=${c}`)}if(g!==a.defaultModel&&A.push(`ALFRED_LLM_MODEL=${g}`),m&&A.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(D).length>0){A.push("","# === Additional Model Tiers ===");for(let[w,$]of Object.entries(D)){let R=`ALFRED_LLM_${w.toUpperCase()}`;A.push(""),A.push(`${R}_PROVIDER=${$.provider}`),A.push(`${R}_MODEL=${$.model}`),$.apiKey&&A.push(`${R}_API_KEY=${$.apiKey}`),$.baseUrl&&A.push(`${R}_BASE_URL=${$.baseUrl}`)}}A.push("","# === Messaging Platforms ===","");for(let[w,$]of Object.entries(Ve))A.push(`${w}=${$}`);if(A.push("","# === Web Search ===",""),se?(A.push(`ALFRED_SEARCH_PROVIDER=${se}`),K&&A.push(`ALFRED_SEARCH_API_KEY=${K}`),P&&A.push(`ALFRED_SEARCH_BASE_URL=${P}`)):(A.push("# ALFRED_SEARCH_PROVIDER=brave"),A.push("# ALFRED_SEARCH_API_KEY=")),A.push("","# === Email ===",""),v&&O.length>0){let w=O[0];w.provider==="microsoft"?(A.push("ALFRED_EMAIL_PROVIDER=microsoft"),w.msClientId?(A.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${w.msClientId}`),A.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${w.msClientSecret}`),A.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${w.msTenantId}`),A.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${w.msRefreshToken}`)):A.push("# Microsoft email credentials shared from calendar config")):(A.push(`ALFRED_EMAIL_USER=${w.user}`),A.push(`ALFRED_EMAIL_PASS=${w.pass}`)),O.length>1&&A.push("# Additional email accounts configured in config/default.yml")}else A.push("# ALFRED_EMAIL_USER="),A.push("# ALFRED_EMAIL_PASS=");if(A.push("","# === Speech ===",""),Xe?(A.push(`ALFRED_SPEECH_PROVIDER=${Xe}`),A.push(`ALFRED_SPEECH_API_KEY=${at}`),Cs&&A.push(`ALFRED_SPEECH_BASE_URL=${Cs}`),Ns&&(A.push("ALFRED_TTS_ENABLED=true"),A.push(`ALFRED_TTS_VOICE=${Ls}`))):(A.push("# ALFRED_SPEECH_PROVIDER=groq"),A.push("# ALFRED_SPEECH_API_KEY=")),A.push("","# === Forge (GitHub / GitLab) ===",""),yt==="github"?(A.push("ALFRED_FORGE_PROVIDER=github"),A.push(`ALFRED_GITHUB_TOKEN=${Ds}`)):yt==="gitlab"?(A.push("ALFRED_FORGE_PROVIDER=gitlab"),A.push(`ALFRED_GITLAB_TOKEN=${Ms}`)):(A.push("# ALFRED_FORGE_PROVIDER=github"),A.push("# ALFRED_GITHUB_TOKEN=")),A.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),yn?(A.push(`ALFRED_PROXMOX_BASE_URL=${Us}`),A.push(`ALFRED_PROXMOX_TOKEN_ID=${Fo}`),A.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Ps}`)):(A.push("# ALFRED_PROXMOX_BASE_URL="),A.push("# ALFRED_PROXMOX_TOKEN_ID="),A.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),Fs&&wt?(A.push(`ALFRED_UNIFI_BASE_URL=${zt}`),A.push(`ALFRED_UNIFI_API_KEY=${wt}`)):Fs?(A.push(`ALFRED_UNIFI_BASE_URL=${zt}`),A.push(`ALFRED_UNIFI_USERNAME=${Bo}`),A.push(`ALFRED_UNIFI_PASSWORD=${js}`)):(A.push("# ALFRED_UNIFI_BASE_URL="),A.push("# ALFRED_UNIFI_API_KEY=")),wn?(A.push(`ALFRED_HOMEASSISTANT_URL=${Hs}`),A.push(`ALFRED_HOMEASSISTANT_TOKEN=${Bs}`)):(A.push("# ALFRED_HOMEASSISTANT_URL="),A.push("# ALFRED_HOMEASSISTANT_TOKEN=")),A.push("","# === Contacts ===",""),_n)for(let[w,$]of Object.entries(ye))A.push(`${w}=${$}`);else A.push("# ALFRED_CONTACTS_PROVIDER=carddav");A.push("","# === Docker ===",""),kn?(_t&&A.push(`ALFRED_DOCKER_SOCKET_PATH=${_t}`),kt&&A.push(`ALFRED_DOCKER_HOST=${kt}`)):(A.push("# ALFRED_DOCKER_SOCKET_PATH="),A.push("# ALFRED_DOCKER_HOST=")),A.push("","# === BMW CarData ===",""),En?A.push(`ALFRED_BMW_CLIENT_ID=${Yo}`):A.push("# ALFRED_BMW_CLIENT_ID="),A.push("","# === Routing ===",""),bn?A.push(`ALFRED_ROUTING_API_KEY=${Zo}`):A.push("# ALFRED_ROUTING_API_KEY="),A.push("","# === Energy / aWATTar ===",""),Sn&&bt?(Et&&A.push(`ALFRED_ENERGY_GRID_NAME=${Et}`),A.push(`ALFRED_ENERGY_GRID_USAGE_CT=${bt}`),A.push(`ALFRED_ENERGY_GRID_LOSS_CT=${vn}`),Ws&&A.push(`ALFRED_ENERGY_GRID_CAPACITY_FEE=${Ws}`),zs&&A.push(`ALFRED_ENERGY_GRID_METER_FEE=${zs}`)):(A.push("# ALFRED_ENERGY_GRID_NAME="),A.push("# ALFRED_ENERGY_GRID_USAGE_CT="),A.push("# ALFRED_ENERGY_GRID_LOSS_CT="),A.push("# ALFRED_ENERGY_GRID_CAPACITY_FEE="),A.push("# ALFRED_ENERGY_GRID_METER_FEE=")),A.push("","# === Security ===",""),Re?A.push(`ALFRED_OWNER_USER_ID=${Re}`):A.push("# ALFRED_OWNER_USER_ID="),A.push("");let pm=Ie.join(e,".env");_e.writeFileSync(pm,A.join(`
|
|
1329
|
+
`),"utf-8"),console.log(` ${F("+")} ${E(".env")} written`);let In=Ie.join(e,"config");_e.existsSync(In)||_e.mkdirSync(In,{recursive:!0});let mc={name:r,telegram:{token:de.telegram?.token??"",enabled:ee.some(w=>w.name==="telegram")},discord:{token:de.discord?.token??"",enabled:ee.some(w=>w.name==="discord")},whatsapp:{enabled:ee.some(w=>w.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:de.matrix?.homeserverUrl??"https://matrix.org",accessToken:de.matrix?.accessToken??"",userId:de.matrix?.userId??"",enabled:ee.some(w=>w.name==="matrix")},signal:{apiUrl:de.signal?.apiUrl??"http://localhost:8080",phoneNumber:de.signal?.phoneNumber??"",enabled:ee.some(w=>w.name==="signal")},llm:Object.keys(D).length>0?{default:{provider:a.name,model:g,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...D}:{provider:a.name,model:g,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...se?{search:{provider:se,...K?{apiKey:K}:{},...P?{baseUrl:P}:{}}}:{},...v&&O.length>0?{email:{accounts:O.map(w=>w.provider==="microsoft"?{name:w.name,provider:"microsoft",...w.msClientId?{microsoft:{clientId:w.msClientId,clientSecret:w.msClientSecret,tenantId:w.msTenantId,refreshToken:w.msRefreshToken}}:{}}:{name:w.name,imap:{host:w.imapHost,port:w.imapPort,secure:w.imapPort===993},smtp:{host:w.smtpHost,port:w.smtpPort,secure:w.smtpPort===465},auth:{user:w.user,pass:w.pass}})}}:{},...Xe?{speech:{provider:Xe,apiKey:at,...Cs?{baseUrl:Cs}:{},...Ns?{ttsEnabled:!0,ttsVoice:Ls}:{}}}:{},...Lo?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...gt.length>0||yt?{codeAgents:{enabled:gt.length>0,agents:gt,...yt==="github"?{forge:{provider:"github",github:{token:Ds}}}:yt==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:Ms}}}:{}}}:{},...yn?{proxmox:{baseUrl:Us,tokenId:Fo,tokenSecret:Ps,verifyTls:jo}}:{},...Fs?{unifi:{baseUrl:zt,...wt?{apiKey:wt}:{username:Bo,password:js},site:"default",verifyTls:Wo}}:{},...wn?{homeassistant:{baseUrl:Hs,accessToken:Bs,verifyTls:qo}}:{},..._n?{contacts:{provider:Ue,...Ue==="carddav"?{carddav:{serverUrl:ye.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:ye.ALFRED_CARDDAV_CONTACTS_USERNAME}}:Ue==="google"?{google:{clientId:ye.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:Ue==="microsoft"?{microsoft:{clientId:ye.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:ye.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...kn?{docker:{..._t?{socketPath:_t}:{},...kt?{host:kt}:{}}}:{},...En?{bmw:{clientId:Yo}}:{},...bn?{routing:{apiKey:Zo}}:{},...Sn&&bt?{energy:{...Et?{gridName:Et}:{},gridUsageCt:parseFloat(bt),gridLossCt:parseFloat(vn||"0"),...Ws?{gridCapacityFee:parseFloat(Ws)}:{},...zs?{gridMeterFee:parseFloat(zs)}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};Re&&(mc.security.ownerUserId=Re);let hm="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Ka.dump(mc,{lineWidth:120,noRefs:!0,sortKeys:!1}),fm=Ie.join(In,"default.yml");_e.writeFileSync(fm,hm,"utf-8"),console.log(` ${F("+")} ${E("config/default.yml")} written`);let ti=Ie.join(In,"rules");_e.existsSync(ti)||_e.mkdirSync(ti,{recursive:!0});let gm=qs&&Re?`
|
|
1330
1330
|
# Allow admin actions (shell, etc.) for the owner only
|
|
1331
1331
|
- id: allow-owner-admin
|
|
1332
1332
|
effect: allow
|
|
@@ -1335,7 +1335,7 @@ ${N("Writing configuration files...")}`);let A=["# Alfred Environment Variables"
|
|
|
1335
1335
|
actions: ["*"]
|
|
1336
1336
|
riskLevels: [admin, destructive]
|
|
1337
1337
|
conditions:
|
|
1338
|
-
users: ["${
|
|
1338
|
+
users: ["${Re}"]
|
|
1339
1339
|
`:`
|
|
1340
1340
|
# Allow admin actions (shell, etc.) for the owner only
|
|
1341
1341
|
# Uncomment and set your user ID to enable:
|
|
@@ -1346,7 +1346,7 @@ ${N("Writing configuration files...")}`);let A=["# Alfred Environment Variables"
|
|
|
1346
1346
|
# actions: ["*"]
|
|
1347
1347
|
# riskLevels: [admin, destructive]
|
|
1348
1348
|
# conditions:
|
|
1349
|
-
# users: ["${
|
|
1349
|
+
# users: ["${Re||"YOUR_USER_ID_HERE"}"]
|
|
1350
1350
|
`,ym=`# Alfred \u2014 Default Security Rules
|
|
1351
1351
|
# Rules are evaluated in priority order (lower number = higher priority).
|
|
1352
1352
|
# First matching rule wins.
|
|
@@ -1402,14 +1402,14 @@ ${gm}
|
|
|
1402
1402
|
scope: global
|
|
1403
1403
|
actions: ["*"]
|
|
1404
1404
|
riskLevels: [read, write, destructive, admin]
|
|
1405
|
-
`,Tm
|
|
1406
|
-
${yf}${
|
|
1405
|
+
`,Tm=Ie.join(ti,"default-rules.yml");_e.writeFileSync(Tm,ym,"utf-8"),console.log(` ${F("+")} ${E("config/rules/default-rules.yml")} written`);let pc=Ie.join(e,"data");_e.existsSync(pc)||(_e.mkdirSync(pc,{recursive:!0}),console.log(` ${F("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${Ao}${"=".repeat(52)}${I}`),console.log(`${Ao}${J} Setup complete!${I}`),console.log(`${Ao}${"=".repeat(52)}${I}`),console.log(""),console.log(` ${N("Bot name:")} ${r}`),console.log(` ${N("LLM default:")} ${a.name} (${g})`),c&&console.log(` ${N("API key:")} ${ke(c)}`);for(let[w,$]of Object.entries(D)){let R=w.charAt(0).toUpperCase()+w.slice(1);console.log(` ${N(`LLM ${R}:`)}${" ".repeat(Math.max(1,10-R.length))}${$.provider} (${$.model})`)}if(ee.length>0?console.log(` ${N("Platforms:")} ${ee.map(w=>w.label).join(", ")}`):console.log(` ${N("Platforms:")} none (configure later)`),se){let w={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${P})`};console.log(` ${N("Web search:")} ${w[se]}`)}else console.log(` ${N("Web search:")} ${E("disabled")}`);if(v&&O.length>0){let w=O.map($=>$.provider==="microsoft"?`${$.name} (Microsoft 365)${$.msClientId?"":" \u2014 shared from Calendar"}`:`${$.name} (${$.imapHost})`);console.log(` ${N("Email:")} ${w.join(", ")}`)}else console.log(` ${N("Email:")} ${E("disabled")}`);if(Xe){let w={openai:"OpenAI Whisper",groq:"Groq Whisper"},$=Ns?`, TTS: ${Ls}`:"";console.log(` ${N("Voice:")} ${w[Xe]}${$}`)}else console.log(` ${N("Voice:")} ${E("disabled")}`);console.log(` ${N("Code Sandbox:")} ${Lo?F("enabled"):E("disabled")}`),yn&&console.log(` ${N("Proxmox:")} ${F(Us)}`),Fs&&console.log(` ${N("UniFi:")} ${F(zt)}`),wn&&console.log(` ${N("Home Assist.:")} ${F(Hs)}`),_n&&console.log(` ${N("Contacts:")} ${F(Ue)}`),kn&&console.log(` ${N("Docker:")} ${F(kt||_t)}`),En&&console.log(` ${N("BMW CarData:")} ${F("enabled")}`),bn&&console.log(` ${N("Routing:")} ${F("enabled")}`),Sn&&console.log(` ${N("Energy:")} ${F(Et||"enabled")} ${E(`(${bt} ct/kWh)`)}`),Re&&(console.log(` ${N("Owner ID:")} ${Re}`),console.log(` ${N("Shell access:")} ${qs?F("enabled"):E("disabled")}`)),console.log(` ${N("Write scope:")} ${Gs?"DMs + Groups":"DMs only"}`),console.log(` ${N("Rate limit:")} ${$n}/hour per user`),console.log(""),console.log(`${Ro}Next steps:${I}`),console.log(` ${N("alfred start")} Start Alfred`),console.log(` ${N("alfred status")} Check configuration`),console.log(` ${N("alfred --help")} Show all commands`),console.log(""),console.log(`${ht}Edit ${N(".env")}${ht} or ${N("config/default.yml")}${ht} for manual configuration.${I}`),console.log("")}finally{l.close()}}async function W(l,e,t){let s=(await l.question(`${J}${e}${I} ${E(`[${t}]`)}: ${H}`)).trim();return process.stdout.write(I),s||t}async function Le(l,e){for(;;){let t=(await l.question(`${J}${e}${I}: ${H}`)).trim();if(process.stdout.write(I),t)return t;console.log(` ${Ru("!")} This field is required. Please enter a value.`)}}async function hn(l,e,t,s,r){for(;;){let n=(await l.question(`${H}${e}${I}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Ru("!")} Please enter a number between ${t} and ${s}.`)}}function Ef(){console.log(`
|
|
1406
|
+
${yf}${J} _ _ _____ ____ _____ ____
|
|
1407
1407
|
/ \\ | | | ___| _ \\| ____| _ \\
|
|
1408
1408
|
/ _ \\ | | | |_ | |_) | _| | | | |
|
|
1409
1409
|
/ ___ \\| |___| _| | _ <| |___| |_| |
|
|
1410
1410
|
/_/ \\_\\_____|_| |_| \\_\\_____|____/ ${I}
|
|
1411
1411
|
${ht} Personal AI Assistant \u2014 Setup Wizard${I}
|
|
1412
|
-
`)}var I,Y,ht,Ao,H,Ro,gf,yf,ot,Rs,Au,Cu=_(()=>{"use strict";Va();I="\x1B[0m",Y="\x1B[1m",ht="\x1B[2m",Ao="\x1B[32m",H="\x1B[33m",Ro="\x1B[36m",gf="\x1B[31m",yf="\x1B[35m";u(F,"green");u(Tf,"yellow");u(Te,"cyan");u(Ru,"red");u(N,"bold");u(E,"dim");u(_e,"maskKey");ot=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0,models:[{id:"claude-sonnet-4-20250514",desc:"Sonnet 4 \u2014 fast, smart, recommended"},{id:"claude-opus-4-20250514",desc:"Opus 4 \u2014 most capable, slower"},{id:"claude-haiku-4-5-20251001",desc:"Haiku 4.5 \u2014 fastest, cheapest"}]},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0,models:[{id:"gpt-4o",desc:"GPT-4o \u2014 flagship, 128k context"},{id:"gpt-4o-mini",desc:"GPT-4o Mini \u2014 fast, cheap, 128k context"},{id:"o3-mini",desc:"o3-mini \u2014 reasoning, 200k context"}]},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0,models:[{id:"gemini-2.0-flash",desc:"Flash 2.0 \u2014 fast, 1M context"},{id:"gemini-2.0-pro",desc:"Pro 2.0 \u2014 capable, 1M context"},{id:"gemini-1.5-pro",desc:"Pro 1.5 \u2014 2M context"},{id:"gemini-1.5-flash",desc:"Flash 1.5 \u2014 fast, 1M context"}]},{name:"mistral",label:"Mistral AI",defaultModel:"mistral-small-latest",envKeyName:"ALFRED_MISTRAL_API_KEY",needsApiKey:!0,models:[{id:"mistral-small-latest",desc:"Small 3.2 \u2014 fast, 128k context, best value"},{id:"mistral-medium-latest",desc:"Medium 3.1 \u2014 balanced, 128k context"},{id:"mistral-large-latest",desc:"Large 3 \u2014 flagship, 256k context"},{id:"codestral-latest",desc:"Codestral \u2014 code-optimized, 256k context"},{id:"magistral-medium-latest",desc:"Magistral Medium \u2014 reasoning, 40k context"},{id:"magistral-small-latest",desc:"Magistral Small \u2014 reasoning (light), 40k context"},{id:"ministral-8b-latest",desc:"Ministral 8B \u2014 edge/tiny, 128k context"}]}],Rs=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];u(wf,"findCommand");Au=[{name:"claude-code",label:"Claude Code",command:"claude",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"claude"},{name:"codex",label:"OpenAI Codex CLI",command:"codex",argsTemplate:["{{prompt}}"],promptVia:"arg",whichCmd:"codex"},{name:"aider",label:"Aider",command:"aider",argsTemplate:["--message","{{prompt}}"],promptVia:"arg",whichCmd:"aider"},{name:"gemini",label:"Gemini CLI",command:"gemini",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"gemini"}];u(_f,"loadExistingConfig");u(kf,"setupCommand");u(W,"askWithDefault");u(Ne,"askRequired");u(hn,"askNumber");u(Ef,"printBanner")});var Lu={};pe(Lu,{configCommand:()=>$f});function Sf(l){let e=l.toLowerCase();return bf.some(t=>e.includes(t))}function vf(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Nu(l){let e={};for(let[t,s]of Object.entries(l))Sf(t)?e[t]=vf(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Nu(s):e[t]=s;return e}async function $f(){let l=new ue,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Nu(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var bf,Du=_(()=>{"use strict";et();bf=["token","apikey","api_key","accesstoken","secret","password"];u(Sf,"isSensitiveKey");u(vf,"redactValue");u(Nu,"redactObject");u($f,"configCommand")});var Ou={};pe(Ou,{rulesCommand:()=>Af});import xo from"node:fs";import Mu from"node:path";import If from"js-yaml";async function Af(){let l=new ue,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Mu.resolve(e.security.rulesPath);if(!xo.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}xo.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=xo.readdirSync(t).filter(a=>a.endsWith(".yml")||a.endsWith(".yaml"));if(r.length===0){console.log(`No YAML rule files found in: ${t}`);return}let n=new st,o=[],i=[];for(let a of r){let c=Mu.join(t,a);try{let d=xo.readFileSync(c,"utf-8"),m=If.load(d),p=n.loadFromObject(m);o.push(...p)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Uu=_(()=>{"use strict";et();Dn();u(Af,"rulesCommand")});var Pu={};pe(Pu,{statusCommand:()=>xf});import fn from"node:fs";import Ya from"node:path";import Rf from"js-yaml";async function xf(){let l=new ue,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let d=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",m=c.enabled?"+":"-";console.log(` [${m}] ${c.name}: ${d}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let d=e.llm[c];d&&console.log(` ${c}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=Ya.resolve(e.storage.path),n=fn.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Ya.resolve(e.security.rulesPath),i=0,a=0;if(fn.existsSync(o)&&fn.statSync(o).isDirectory()){let c=fn.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=c.length;let d=new st;for(let m of c){let p=Ya.join(o,m);try{let f=fn.readFileSync(p,"utf-8"),g=Rf.load(f),h=d.loadFromObject(g);i+=h.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var Fu=_(()=>{"use strict";et();Dn();u(xf,"statusCommand")});var Bu={};pe(Bu,{authCommand:()=>Gf});import{createServer as Cf}from"node:http";import{exec as Nf}from"node:child_process";import{readFileSync as Lf,writeFileSync as Df,existsSync as Mf}from"node:fs";import{createInterface as Of}from"node:readline";import{resolve as Uf}from"node:path";async function Ja(l){let e=Of({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(l,s=>{e.close(),t(s.trim())})})}function Ff(){let l={};try{let s=new ue().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!l.clientId&&a.clientId&&(l.clientId=a.clientId),!l.clientSecret&&a.clientSecret&&(l.clientSecret=a.clientSecret),!l.tenantId&&a.tenantId&&(l.tenantId=a.tenantId))}let r=s.todo;r&&(!l.clientId&&r.clientId&&(l.clientId=r.clientId),!l.clientSecret&&r.clientSecret&&(l.clientSecret=r.clientSecret),!l.tenantId&&r.tenantId&&(l.tenantId=r.tenantId));let n=s.email;if(n?.accounts&&Array.isArray(n.accounts))for(let o of n.accounts){let i=o.microsoft;i&&(!l.clientId&&i.clientId&&(l.clientId=i.clientId),!l.clientSecret&&i.clientSecret&&(l.clientSecret=i.clientSecret),!l.tenantId&&i.tenantId&&(l.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)l.clientId||(l.clientId=process.env[`${t}_CLIENT_ID`]),l.clientSecret||(l.clientSecret=process.env[`${t}_CLIENT_SECRET`]),l.tenantId||(l.tenantId=process.env[`${t}_TENANT_ID`]);return l}async function jf(){let l=Ff(),e=l.clientId||await Ja(" Client ID: "),t=l.clientSecret||await Ja(" Client Secret: "),s=l.tenantId||await Ja(' Tenant ID (oder "common"): ');return(!e||!t||!s)&&(console.error("Fehler: Client ID, Client Secret und Tenant ID werden ben\xF6tigt."),process.exit(1)),{clientId:e,clientSecret:t,tenantId:s}}function Hf(l){let e=new URLSearchParams({client_id:l.clientId,response_type:"code",redirect_uri:ju,response_mode:"query",scope:Hu,prompt:"consent"});return`https://login.microsoftonline.com/${l.tenantId}/oauth2/v2.0/authorize?${e}`}async function Bf(l,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:l,redirect_uri:ju,grant_type:"authorization_code",scope:Hu}),s=await fetch(`https://login.microsoftonline.com/${e.tenantId}/oauth2/v2.0/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t});if(!s.ok){let n=await s.text();throw new Error(`Token-Austausch fehlgeschlagen (${s.status}): ${n}`)}let r=await s.json();if(!r.refresh_token)throw new Error('Kein Refresh Token in der Antwort. Stelle sicher, dass "offline_access" als Scope erlaubt ist.');return r.refresh_token}function Wf(l){let t={win32:`start "" "${l}"`,darwin:`open "${l}"`,linux:`xdg-open "${l}"`}[process.platform];t&&Nf(t,()=>{})}function zf(l,e){let t=Uf(process.cwd(),".env"),s=[];Mf(t)&&(s=Lf(t,"utf-8").split(`
|
|
1412
|
+
`)}var I,J,ht,Ao,H,Ro,gf,yf,ot,Rs,Au,Cu=_(()=>{"use strict";Va();I="\x1B[0m",J="\x1B[1m",ht="\x1B[2m",Ao="\x1B[32m",H="\x1B[33m",Ro="\x1B[36m",gf="\x1B[31m",yf="\x1B[35m";u(F,"green");u(Tf,"yellow");u(we,"cyan");u(Ru,"red");u(N,"bold");u(E,"dim");u(ke,"maskKey");ot=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0,models:[{id:"claude-sonnet-4-20250514",desc:"Sonnet 4 \u2014 fast, smart, recommended"},{id:"claude-opus-4-20250514",desc:"Opus 4 \u2014 most capable, slower"},{id:"claude-haiku-4-5-20251001",desc:"Haiku 4.5 \u2014 fastest, cheapest"}]},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0,models:[{id:"gpt-4o",desc:"GPT-4o \u2014 flagship, 128k context"},{id:"gpt-4o-mini",desc:"GPT-4o Mini \u2014 fast, cheap, 128k context"},{id:"o3-mini",desc:"o3-mini \u2014 reasoning, 200k context"}]},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0,models:[{id:"gemini-2.0-flash",desc:"Flash 2.0 \u2014 fast, 1M context"},{id:"gemini-2.0-pro",desc:"Pro 2.0 \u2014 capable, 1M context"},{id:"gemini-1.5-pro",desc:"Pro 1.5 \u2014 2M context"},{id:"gemini-1.5-flash",desc:"Flash 1.5 \u2014 fast, 1M context"}]},{name:"mistral",label:"Mistral AI",defaultModel:"mistral-small-latest",envKeyName:"ALFRED_MISTRAL_API_KEY",needsApiKey:!0,models:[{id:"mistral-small-latest",desc:"Small 3.2 \u2014 fast, 128k context, best value"},{id:"mistral-medium-latest",desc:"Medium 3.1 \u2014 balanced, 128k context"},{id:"mistral-large-latest",desc:"Large 3 \u2014 flagship, 256k context"},{id:"codestral-latest",desc:"Codestral \u2014 code-optimized, 256k context"},{id:"magistral-medium-latest",desc:"Magistral Medium \u2014 reasoning, 40k context"},{id:"magistral-small-latest",desc:"Magistral Small \u2014 reasoning (light), 40k context"},{id:"ministral-8b-latest",desc:"Ministral 8B \u2014 edge/tiny, 128k context"}]}],Rs=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];u(wf,"findCommand");Au=[{name:"claude-code",label:"Claude Code",command:"claude",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"claude"},{name:"codex",label:"OpenAI Codex CLI",command:"codex",argsTemplate:["{{prompt}}"],promptVia:"arg",whichCmd:"codex"},{name:"aider",label:"Aider",command:"aider",argsTemplate:["--message","{{prompt}}"],promptVia:"arg",whichCmd:"aider"},{name:"gemini",label:"Gemini CLI",command:"gemini",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"gemini"}];u(_f,"loadExistingConfig");u(kf,"setupCommand");u(W,"askWithDefault");u(Le,"askRequired");u(hn,"askNumber");u(Ef,"printBanner")});var Lu={};he(Lu,{configCommand:()=>$f});function Sf(l){let e=l.toLowerCase();return bf.some(t=>e.includes(t))}function vf(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Nu(l){let e={};for(let[t,s]of Object.entries(l))Sf(t)?e[t]=vf(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Nu(s):e[t]=s;return e}async function $f(){let l=new ue,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Nu(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var bf,Du=_(()=>{"use strict";et();bf=["token","apikey","api_key","accesstoken","secret","password"];u(Sf,"isSensitiveKey");u(vf,"redactValue");u(Nu,"redactObject");u($f,"configCommand")});var Ou={};he(Ou,{rulesCommand:()=>Af});import xo from"node:fs";import Mu from"node:path";import If from"js-yaml";async function Af(){let l=new ue,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Mu.resolve(e.security.rulesPath);if(!xo.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}xo.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=xo.readdirSync(t).filter(a=>a.endsWith(".yml")||a.endsWith(".yaml"));if(r.length===0){console.log(`No YAML rule files found in: ${t}`);return}let n=new st,o=[],i=[];for(let a of r){let c=Mu.join(t,a);try{let d=xo.readFileSync(c,"utf-8"),m=If.load(d),p=n.loadFromObject(m);o.push(...p)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Uu=_(()=>{"use strict";et();Dn();u(Af,"rulesCommand")});var Pu={};he(Pu,{statusCommand:()=>xf});import fn from"node:fs";import Ya from"node:path";import Rf from"js-yaml";async function xf(){let l=new ue,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let d=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",m=c.enabled?"+":"-";console.log(` [${m}] ${c.name}: ${d}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let d=e.llm[c];d&&console.log(` ${c}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=Ya.resolve(e.storage.path),n=fn.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Ya.resolve(e.security.rulesPath),i=0,a=0;if(fn.existsSync(o)&&fn.statSync(o).isDirectory()){let c=fn.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=c.length;let d=new st;for(let m of c){let p=Ya.join(o,m);try{let f=fn.readFileSync(p,"utf-8"),g=Rf.load(f),h=d.loadFromObject(g);i+=h.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var Fu=_(()=>{"use strict";et();Dn();u(xf,"statusCommand")});var Bu={};he(Bu,{authCommand:()=>Gf});import{createServer as Cf}from"node:http";import{exec as Nf}from"node:child_process";import{readFileSync as Lf,writeFileSync as Df,existsSync as Mf}from"node:fs";import{createInterface as Of}from"node:readline";import{resolve as Uf}from"node:path";async function Ja(l){let e=Of({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(l,s=>{e.close(),t(s.trim())})})}function Ff(){let l={};try{let s=new ue().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!l.clientId&&a.clientId&&(l.clientId=a.clientId),!l.clientSecret&&a.clientSecret&&(l.clientSecret=a.clientSecret),!l.tenantId&&a.tenantId&&(l.tenantId=a.tenantId))}let r=s.todo;r&&(!l.clientId&&r.clientId&&(l.clientId=r.clientId),!l.clientSecret&&r.clientSecret&&(l.clientSecret=r.clientSecret),!l.tenantId&&r.tenantId&&(l.tenantId=r.tenantId));let n=s.email;if(n?.accounts&&Array.isArray(n.accounts))for(let o of n.accounts){let i=o.microsoft;i&&(!l.clientId&&i.clientId&&(l.clientId=i.clientId),!l.clientSecret&&i.clientSecret&&(l.clientSecret=i.clientSecret),!l.tenantId&&i.tenantId&&(l.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)l.clientId||(l.clientId=process.env[`${t}_CLIENT_ID`]),l.clientSecret||(l.clientSecret=process.env[`${t}_CLIENT_SECRET`]),l.tenantId||(l.tenantId=process.env[`${t}_TENANT_ID`]);return l}async function jf(){let l=Ff(),e=l.clientId||await Ja(" Client ID: "),t=l.clientSecret||await Ja(" Client Secret: "),s=l.tenantId||await Ja(' Tenant ID (oder "common"): ');return(!e||!t||!s)&&(console.error("Fehler: Client ID, Client Secret und Tenant ID werden ben\xF6tigt."),process.exit(1)),{clientId:e,clientSecret:t,tenantId:s}}function Hf(l){let e=new URLSearchParams({client_id:l.clientId,response_type:"code",redirect_uri:ju,response_mode:"query",scope:Hu,prompt:"consent"});return`https://login.microsoftonline.com/${l.tenantId}/oauth2/v2.0/authorize?${e}`}async function Bf(l,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:l,redirect_uri:ju,grant_type:"authorization_code",scope:Hu}),s=await fetch(`https://login.microsoftonline.com/${e.tenantId}/oauth2/v2.0/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t});if(!s.ok){let n=await s.text();throw new Error(`Token-Austausch fehlgeschlagen (${s.status}): ${n}`)}let r=await s.json();if(!r.refresh_token)throw new Error('Kein Refresh Token in der Antwort. Stelle sicher, dass "offline_access" als Scope erlaubt ist.');return r.refresh_token}function Wf(l){let t={win32:`start "" "${l}"`,darwin:`open "${l}"`,linux:`xdg-open "${l}"`}[process.platform];t&&Nf(t,()=>{})}function zf(l,e){let t=Uf(process.cwd(),".env"),s=[];Mf(t)&&(s=Lf(t,"utf-8").split(`
|
|
1413
1413
|
`));let r={ALFRED_EMAIL_PROVIDER:"microsoft",ALFRED_CALENDAR_PROVIDER:"microsoft",ALFRED_CONTACTS_PROVIDER:"microsoft",ALFRED_MICROSOFT_EMAIL_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_EMAIL_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_CALENDAR_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_CONTACTS_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:e,ALFRED_MICROSOFT_TODO_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_TODO_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_TODO_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:e},n=new Set(Object.keys(r));for(let i=0;i<s.length;i++){let a=s[i].match(/^#?\s*([A-Z_]+)=/);a&&n.has(a[1])&&(s[i]=`${a[1]}=${r[a[1]]}`,n.delete(a[1]))}if(n.size>0){s.length>0&&s[s.length-1]!==""&&s.push("");for(let i of n)s.push(`${i}=${r[i]}`)}let o=s.join(`
|
|
1414
1414
|
`).replace(/\n*$/,`
|
|
1415
1415
|
`);Df(t,o)}function qf(l){return new Promise((e,t)=>{let s=Cf(async(r,n)=>{let o=new URL(r.url??"/","http://localhost:3000");if(o.pathname!=="/callback"){n.writeHead(404),n.end("Not found");return}let i=o.searchParams.get("code"),a=o.searchParams.get("error");if(a){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>Fehler: ${a}</h1><p>${o.searchParams.get("error_description")??""}</p>`),s.close(),t(new Error(`OAuth-Fehler: ${a}`));return}if(!i){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>Fehler: Kein Auth-Code erhalten</h1>");return}try{let c=await Bf(i,l);n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(Pf),s.close(),e(c)}catch(c){n.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>Fehler beim Token-Austausch</h1><p>${c.message}</p>`),s.close(),t(c)}});s.listen(3e3,()=>{console.log(" Callback-Server gestartet auf http://localhost:3000")}),s.on("error",r=>{t(new Error(`Server konnte nicht gestartet werden: ${r.message}`))})})}async function Gf(l){l||(console.error("Usage: alfred auth <provider>"),console.error(" Unterst\xFCtzte Provider: microsoft"),process.exit(1)),l!=="microsoft"&&(console.error(`Unbekannter Provider: ${l}`),console.error(" Unterst\xFCtzte Provider: microsoft"),process.exit(1)),console.log(""),console.log(" Microsoft 365 OAuth \u2014 Automatischer Token-Flow"),console.log(" ================================================"),console.log("");let e=await jf(),t=Hf(e);console.log(""),console.log(" \xD6ffne diese URL im Browser:"),console.log(` ${t}`),console.log(""),Wf(t);try{let s=await qf(e);console.log(""),console.log(" Refresh Token erhalten! Schreibe in .env ..."),zf(e,s),console.log(" .env aktualisiert (Email, Calendar, Contacts, To Do)."),console.log(""),console.log(" Fertig! Du kannst Alfred jetzt mit Microsoft 365 nutzen."),console.log("")}catch(s){console.error(`
|
|
@@ -1418,7 +1418,7 @@ ${ht} Personal AI Assistant \u2014 Setup Wizard${I}
|
|
|
1418
1418
|
<style>body{font-family:system-ui,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0d1117;color:#e6edf3}
|
|
1419
1419
|
.card{text-align:center;padding:2rem;border:1px solid #30363d;border-radius:12px;background:#161b22}
|
|
1420
1420
|
h1{color:#3fb950;margin-bottom:.5rem}p{color:#8b949e}</style></head>
|
|
1421
|
-
<body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(Ja,"askQuestion");u(Ff,"resolveCredentials");u(jf,"ensureCredentials");u(Hf,"buildAuthUrl");u(Bf,"exchangeCode");u(Wf,"openBrowser");u(zf,"updateEnvFile");u(qf,"waitForCallback");u(Gf,"authCommand")});var zu={};
|
|
1421
|
+
<body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(Ja,"askQuestion");u(Ff,"resolveCredentials");u(jf,"ensureCredentials");u(Hf,"buildAuthUrl");u(Bf,"exchangeCode");u(Wf,"openBrowser");u(zf,"updateEnvFile");u(qf,"waitForCallback");u(Gf,"authCommand")});var zu={};he(zu,{logsCommand:()=>Kf});import Xf from"node:fs";import Vf from"node:path";async function Kf(l,e){let t=new ue,s;try{s=t.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let r=Vf.resolve(s.storage.path);if(!Xf.existsSync(r)){console.log(`Database not found at: ${r}`),console.log("No log entries. Alfred has not been run yet, or the database path is incorrect.");return}let n;try{n=new $t(r),e?.activity?Jf(n,l,e):Yf(n,l)}catch(o){console.error("Failed to read log:",o.message),process.exit(1)}finally{n&&n.close()}}function Yf(l,e){let t=new It(l.getDb()),s=t.count({}),r=t.query({limit:e});if(console.log("Alfred \u2014 Audit Log (Security)"),console.log("=============================="),console.log(`Total entries: ${s}`),console.log(`Showing last ${Math.min(e,s)} entries:`),console.log(""),r.length===0){console.log("No audit log entries found.");return}for(let n of r){let o=n.timestamp.toISOString(),i=n.effect==="allow"?"ALLOW":"DENY ";console.log(` ${o} [${i}] ${n.action}`),console.log(` user: ${n.userId} | platform: ${n.platform} | risk: ${n.riskLevel}`),n.ruleId&&console.log(` rule: ${n.ruleId}`),n.chatId&&console.log(` chat: ${n.chatId}`),n.context&&console.log(` context: ${JSON.stringify(n.context)}`),console.log("")}}function Jf(l,e,t){let s=new Rt(l.getDb());if(t.stats){let o=s.stats(t.since);if(console.log("Alfred \u2014 Activity Stats"),console.log("========================"),t.since&&console.log(`Since: ${t.since}`),console.log(""),o.length===0){console.log("No activity entries found.");return}let i=Math.max(...o.map(c=>c.eventType.length),10),a=Math.max(...o.map(c=>c.outcome.length),7);console.log(` ${"EVENT TYPE".padEnd(i)} ${"OUTCOME".padEnd(a)} COUNT`),console.log(` ${"\u2500".repeat(i)} ${"\u2500".repeat(a)} \u2500\u2500\u2500\u2500\u2500`);for(let c of o)console.log(` ${c.eventType.padEnd(i)} ${c.outcome.padEnd(a)} ${c.count}`);return}let r=s.count({eventType:t.type,source:t.source,outcome:t.outcome}),n=s.query({eventType:t.type,source:t.source,outcome:t.outcome,since:t.since,limit:e});if(console.log("Alfred \u2014 Activity Log"),console.log("======================"),console.log(`Total entries: ${r}`),t.type&&console.log(`Filter: type=${t.type}`),t.source&&console.log(`Filter: source=${t.source}`),t.outcome&&console.log(`Filter: outcome=${t.outcome}`),console.log(`Showing last ${Math.min(e,r)} entries:`),console.log(""),n.length===0){console.log("No activity entries found.");return}for(let o of n){let i=Zf(o.outcome),a=o.durationMs?` (${o.durationMs}ms)`:"";console.log(` ${o.timestamp} [${i}] ${o.eventType}: ${o.action}${a}`),console.log(` source: ${o.source}${o.sourceId?` (${o.sourceId.slice(0,8)})`:""} | platform: ${o.platform??"-"}`),o.userId&&console.log(` user: ${o.userId}`),o.errorMessage&&console.log(` error: ${o.errorMessage.slice(0,200)}`),o.details&&console.log(` details: ${JSON.stringify(o.details)}`),console.log("")}}function Zf(l){switch(l){case"success":return"\x1B[32mSUCCESS\x1B[0m";case"error":return"\x1B[31mERROR \x1B[0m";case"denied":return"\x1B[31mDENIED \x1B[0m";case"approved":return"\x1B[32mAPPROVED\x1B[0m";case"rejected":return"\x1B[33mREJECTED\x1B[0m";case"expired":return"\x1B[33mEXPIRED\x1B[0m";case"skipped":return"\x1B[90mSKIPPED\x1B[0m";default:return l.toUpperCase()}}var qu=_(()=>{"use strict";et();pi();u(Kf,"logsCommand");u(Yf,"showAuditLog");u(Jf,"showActivityLog");u(Zf,"formatOutcome")});import{readFileSync as Qf}from"node:fs";import{fileURLToPath as eg}from"node:url";import{dirname as tg,join as sg}from"node:path";function rg(){try{let l=tg(eg(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Qf(sg(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(rg,"getVersion");var Gu=rg(),Za=`
|
|
1422
1422
|
Alfred CLI v${Gu}
|
|
1423
1423
|
Personal AI Assistant
|
|
1424
1424
|
|