@madh-io/alfred-ai 0.10.28 → 0.10.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bundle/index.js +88 -88
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var ma=Object.defineProperty;var u=(c,e)=>ma(c,"name",{value:e,configurable:!0}),pa=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var _=(c,e)=>()=>(c&&(e=c(c=0)),e);var oe=(c,e)=>{for(var t in e)ma(c,t,{get:e[t],enumerable:!0})};import{z as y}from"zod";var fa,ga,ya,wa,Ta,_a,Ea,ba,pt,au,cu,lu,ha,du,uu,mu,pu,hu,fu,gu,yu,wu,Tu,_u,Eu,bu,$u,ku,vu,Su,Au,Iu,xu,Ru,Cu,Nu,Lu,Du,Mu,Ou,Pu,Uu,To,_o=_(()=>{"use strict";fa=y.object({token:y.string().optional(),enabled:y.boolean()}),ga=y.object({token:y.string().optional(),enabled:y.boolean()}),ya=y.object({enabled:y.boolean(),dataPath:y.string()}),wa=y.object({homeserverUrl:y.string(),accessToken:y.string().optional(),userId:y.string().optional(),enabled:y.boolean()}),Ta=y.object({apiUrl:y.string(),phoneNumber:y.string().optional(),enabled:y.boolean()}),_a=y.object({path:y.string()}),Ea=y.object({level:y.enum(["trace","debug","info","warn","error","fatal"]),pretty:y.boolean(),auditLogPath:y.string().optional()}),ba=y.object({rulesPath:y.string(),defaultEffect:y.enum(["allow","deny"]),ownerUserId:y.string().optional()}),pt=y.object({provider:y.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:y.string().optional(),baseUrl:y.string().optional(),model:y.string(),temperature:y.number().optional(),maxTokens:y.number().optional()}),au=y.object({default:pt,strong:pt.optional(),fast:pt.optional(),embeddings:pt.optional(),local:pt.optional()}).passthrough(),cu=y.union([pt,au]),lu=y.object({provider:y.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:y.string().optional(),baseUrl:y.string().optional()}),ha=y.object({name:y.string().optional(),provider:y.enum(["imap-smtp","microsoft"]).optional(),imap:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),smtp:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),auth:y.object({user:y.string(),pass:y.string()}).optional(),microsoft:y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}).optional()}),du=y.union([y.object({accounts:y.array(ha)}),ha]),uu=y.object({provider:y.enum(["openai","groq","google"]),apiKey:y.string(),baseUrl:y.string().optional(),ttsEnabled:y.boolean().optional(),ttsModel:y.string().optional(),ttsVoice:y.string().optional()}),mu=y.object({serverUrl:y.string(),username:y.string(),password:y.string()}),pu=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),hu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),fu=y.object({provider:y.enum(["caldav","google","microsoft"]),caldav:mu.optional(),google:pu.optional(),microsoft:hu.optional()}),gu=y.object({name:y.string(),command:y.string().optional(),args:y.array(y.string()).optional(),env:y.record(y.string()).optional(),url:y.string().optional()}),yu=y.object({servers:y.array(gu)}),wu=y.object({enabled:y.boolean(),allowedLanguages:y.array(y.enum(["javascript","python"])).optional(),maxTimeoutMs:y.number().optional(),allowNetwork:y.boolean().optional()}),Tu=y.object({enabled:y.boolean().optional(),minMessageLength:y.number().optional(),minConfidence:y.number().min(0).max(1).optional(),maxExtractionsPerMinute:y.number().optional()}),_u=y.object({enabled:y.boolean(),port:y.coerce.number().int().min(1).max(65535),host:y.string()}),Eu=y.object({name:y.string(),command:y.string(),argsTemplate:y.array(y.string()),promptVia:y.enum(["arg","stdin"]).default("arg"),env:y.record(y.string()).optional(),cwd:y.string().optional(),timeoutMs:y.number().max(9e5).optional()}),bu=y.object({token:y.string(),baseUrl:y.string().optional()}),$u=y.object({token:y.string(),baseUrl:y.string().optional()}),ku=y.object({provider:y.enum(["github","gitlab"]),baseBranch:y.string().optional(),github:bu.optional(),gitlab:$u.optional()}),vu=y.object({enabled:y.boolean(),agents:y.array(Eu),forge:ku.optional()}),Su=y.object({baseUrl:y.string(),tokenId:y.string(),tokenSecret:y.string(),verifyTls:y.boolean().optional(),defaultNode:y.string().optional()}),Au=y.object({baseUrl:y.string(),apiKey:y.string().optional(),username:y.string().optional(),password:y.string().optional(),site:y.string().optional(),verifyTls:y.boolean().optional()}),Iu=y.object({baseUrl:y.string(),accessToken:y.string(),verifyTls:y.boolean().optional()}),xu=y.object({serverUrl:y.string(),username:y.string(),password:y.string(),addressBookPath:y.string().optional()}),Ru=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),Cu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Nu=y.object({provider:y.enum(["carddav","google","microsoft"]),carddav:xu.optional(),google:Ru.optional(),microsoft:Cu.optional()}),Lu=y.object({socketPath:y.string().optional(),host:y.string().optional(),verifyTls:y.boolean().optional()}),Du=y.object({clientId:y.string()}),Mu=y.object({apiKey:y.string()}),Ou=y.object({gridName:y.string().optional(),gridUsageCt:y.coerce.number().optional(),gridLossCt:y.coerce.number().optional(),gridCapacityFee:y.coerce.number().optional(),gridMeterFee:y.coerce.number().optional()}),Pu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Uu=y.object({maxHistoryMessages:y.number().min(10).max(500).optional()}).optional(),To=y.object({name:y.string(),telegram:fa,discord:ga.optional(),whatsapp:ya.optional(),matrix:wa.optional(),signal:Ta.optional(),llm:cu,storage:_a,logger:Ea,security:ba,search:lu.optional(),email:du.optional(),speech:uu.optional(),calendar:fu.optional(),mcp:yu.optional(),codeSandbox:wu.optional(),activeLearning:Tu.optional(),api:_u.optional(),codeAgents:vu.optional(),proxmox:Su.optional(),unifi:Au.optional(),homeassistant:Iu.optional(),contacts:Nu.optional(),docker:Lu.optional(),bmw:Du.optional(),routing:Mu.optional(),todo:Pu.optional(),energy:Ou.optional(),conversation:Uu})});var Eo,bo=_(()=>{"use strict";Eo={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 $a from"node:fs";import Fu from"node:path";import{config as ka}from"dotenv";import ju from"js-yaml";function va(c,e){let t={...c};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]=va(n,r):t[s]=r}return t}function Hu(c){let e={...c};for(let[t,s]of Object.entries(Bu)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function $o(){ka({override:!0})}var Bu,ne,Sa=_(()=>{"use strict";_o();bo();u(va,"deepMerge");Bu={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"]};u(Hu,"applyEnvOverrides");u($o,"reloadDotenv");ne=class{static{u(this,"ConfigLoader")}loadConfig(e){ka();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Fu.resolve(t);if($a.existsSync(r)){let g=$a.readFileSync(r,"utf-8"),f=ju.load(g);f&&typeof f=="object"&&(s=f)}let n=va(Eo,s),o=Hu(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(f=>a[f]&&typeof a[f]=="object")){let f={};for(let[T,b]of Object.entries(a))!i.includes(T)&&T!=="default"&&(f[T]=b);let h={default:f};for(let T of i)a[T]&&(h[T]=a[T]);o.llm=h}let l=To.parse(o),d=l.llm;d&&"provider"in d&&(l.llm={default:d});let m=l.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let f of["default","strong","fast","embeddings","local"]){let h=m[f];h&&!h.apiKey&&(h.apiKey=g)}}let p=l.email;if(p&&!("accounts"in p))l.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let g=p.microsoft;if(g){let h=p.accounts.find(T=>T.provider==="microsoft");if(h){let T=h.microsoft??{};h.microsoft={...T,...g}}delete p.microsoft}}return l}}});var ze=_(()=>{"use strict";_o();bo();Sa()});import ko from"pino";function Ls(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=ko.transport({target:"pino-pretty",options:{colorize:!0}});return ko({name:c,level:t},r)}return ko({name:c,level:t})}var Aa=_(()=>{"use strict";u(Ls,"createLogger")});import Jh from"pino";var Ia=_(()=>{"use strict"});var vo=_(()=>{"use strict";Aa();Ia()});var Ct,Jr=_(()=>{"use strict";Ct=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var ma=Object.defineProperty;var u=(c,e)=>ma(c,"name",{value:e,configurable:!0}),pa=(c=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(c,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):c)(function(c){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+c+'" is not supported')});var _=(c,e)=>()=>(c&&(e=c(c=0)),e);var ie=(c,e)=>{for(var t in e)ma(c,t,{get:e[t],enumerable:!0})};import{z as y}from"zod";var fa,ga,ya,wa,Ta,_a,Ea,ba,pt,au,cu,lu,ha,du,uu,mu,pu,hu,fu,gu,yu,wu,Tu,_u,Eu,bu,$u,ku,vu,Su,Au,Iu,xu,Ru,Cu,Nu,Du,Lu,Mu,Ou,Pu,Uu,To,_o=_(()=>{"use strict";fa=y.object({token:y.string().optional(),enabled:y.boolean()}),ga=y.object({token:y.string().optional(),enabled:y.boolean()}),ya=y.object({enabled:y.boolean(),dataPath:y.string()}),wa=y.object({homeserverUrl:y.string(),accessToken:y.string().optional(),userId:y.string().optional(),enabled:y.boolean()}),Ta=y.object({apiUrl:y.string(),phoneNumber:y.string().optional(),enabled:y.boolean()}),_a=y.object({path:y.string()}),Ea=y.object({level:y.enum(["trace","debug","info","warn","error","fatal"]),pretty:y.boolean(),auditLogPath:y.string().optional()}),ba=y.object({rulesPath:y.string(),defaultEffect:y.enum(["allow","deny"]),ownerUserId:y.string().optional()}),pt=y.object({provider:y.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:y.string().optional(),baseUrl:y.string().optional(),model:y.string(),temperature:y.number().optional(),maxTokens:y.number().optional()}),au=y.object({default:pt,strong:pt.optional(),fast:pt.optional(),embeddings:pt.optional(),local:pt.optional()}).passthrough(),cu=y.union([pt,au]),lu=y.object({provider:y.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:y.string().optional(),baseUrl:y.string().optional()}),ha=y.object({name:y.string().optional(),provider:y.enum(["imap-smtp","microsoft"]).optional(),imap:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),smtp:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),auth:y.object({user:y.string(),pass:y.string()}).optional(),microsoft:y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}).optional()}),du=y.union([y.object({accounts:y.array(ha)}),ha]),uu=y.object({provider:y.enum(["openai","groq","google"]),apiKey:y.string(),baseUrl:y.string().optional(),ttsEnabled:y.boolean().optional(),ttsModel:y.string().optional(),ttsVoice:y.string().optional()}),mu=y.object({serverUrl:y.string(),username:y.string(),password:y.string()}),pu=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),hu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),fu=y.object({provider:y.enum(["caldav","google","microsoft"]),caldav:mu.optional(),google:pu.optional(),microsoft:hu.optional()}),gu=y.object({name:y.string(),command:y.string().optional(),args:y.array(y.string()).optional(),env:y.record(y.string()).optional(),url:y.string().optional()}),yu=y.object({servers:y.array(gu)}),wu=y.object({enabled:y.boolean(),allowedLanguages:y.array(y.enum(["javascript","python"])).optional(),maxTimeoutMs:y.number().optional(),allowNetwork:y.boolean().optional()}),Tu=y.object({enabled:y.boolean().optional(),minMessageLength:y.number().optional(),minConfidence:y.number().min(0).max(1).optional(),maxExtractionsPerMinute:y.number().optional()}),_u=y.object({enabled:y.boolean(),port:y.coerce.number().int().min(1).max(65535),host:y.string()}),Eu=y.object({name:y.string(),command:y.string(),argsTemplate:y.array(y.string()),promptVia:y.enum(["arg","stdin"]).default("arg"),env:y.record(y.string()).optional(),cwd:y.string().optional(),timeoutMs:y.number().max(9e5).optional()}),bu=y.object({token:y.string(),baseUrl:y.string().optional()}),$u=y.object({token:y.string(),baseUrl:y.string().optional()}),ku=y.object({provider:y.enum(["github","gitlab"]),baseBranch:y.string().optional(),github:bu.optional(),gitlab:$u.optional()}),vu=y.object({enabled:y.boolean(),agents:y.array(Eu),forge:ku.optional()}),Su=y.object({baseUrl:y.string(),tokenId:y.string(),tokenSecret:y.string(),verifyTls:y.boolean().optional(),defaultNode:y.string().optional()}),Au=y.object({baseUrl:y.string(),apiKey:y.string().optional(),username:y.string().optional(),password:y.string().optional(),site:y.string().optional(),verifyTls:y.boolean().optional()}),Iu=y.object({baseUrl:y.string(),accessToken:y.string(),verifyTls:y.boolean().optional()}),xu=y.object({serverUrl:y.string(),username:y.string(),password:y.string(),addressBookPath:y.string().optional()}),Ru=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),Cu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Nu=y.object({provider:y.enum(["carddav","google","microsoft"]),carddav:xu.optional(),google:Ru.optional(),microsoft:Cu.optional()}),Du=y.object({socketPath:y.string().optional(),host:y.string().optional(),verifyTls:y.boolean().optional()}),Lu=y.object({clientId:y.string()}),Mu=y.object({apiKey:y.string()}),Ou=y.object({gridName:y.string().optional(),gridUsageCt:y.coerce.number().optional(),gridLossCt:y.coerce.number().optional(),gridCapacityFee:y.coerce.number().optional(),gridMeterFee:y.coerce.number().optional()}),Pu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Uu=y.object({maxHistoryMessages:y.number().min(10).max(500).optional()}).optional(),To=y.object({name:y.string(),telegram:fa,discord:ga.optional(),whatsapp:ya.optional(),matrix:wa.optional(),signal:Ta.optional(),llm:cu,storage:_a,logger:Ea,security:ba,search:lu.optional(),email:du.optional(),speech:uu.optional(),calendar:fu.optional(),mcp:yu.optional(),codeSandbox:wu.optional(),activeLearning:Tu.optional(),api:_u.optional(),codeAgents:vu.optional(),proxmox:Su.optional(),unifi:Au.optional(),homeassistant:Iu.optional(),contacts:Nu.optional(),docker:Du.optional(),bmw:Lu.optional(),routing:Mu.optional(),todo:Pu.optional(),energy:Ou.optional(),conversation:Uu})});var Eo,bo=_(()=>{"use strict";Eo={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 $a from"node:fs";import Fu from"node:path";import{config as ka}from"dotenv";import ju from"js-yaml";function va(c,e){let t={...c};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]=va(n,r):t[s]=r}return t}function Hu(c){let e={...c};for(let[t,s]of Object.entries(Bu)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function $o(){ka({override:!0})}var Bu,oe,Sa=_(()=>{"use strict";_o();bo();u(va,"deepMerge");Bu={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"]};u(Hu,"applyEnvOverrides");u($o,"reloadDotenv");oe=class{static{u(this,"ConfigLoader")}loadConfig(e){ka();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Fu.resolve(t);if($a.existsSync(r)){let g=$a.readFileSync(r,"utf-8"),f=ju.load(g);f&&typeof f=="object"&&(s=f)}let n=va(Eo,s),o=Hu(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(f=>a[f]&&typeof a[f]=="object")){let f={};for(let[T,b]of Object.entries(a))!i.includes(T)&&T!=="default"&&(f[T]=b);let h={default:f};for(let T of i)a[T]&&(h[T]=a[T]);o.llm=h}let l=To.parse(o),d=l.llm;d&&"provider"in d&&(l.llm={default:d});let m=l.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let f of["default","strong","fast","embeddings","local"]){let h=m[f];h&&!h.apiKey&&(h.apiKey=g)}}let p=l.email;if(p&&!("accounts"in p))l.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let g=p.microsoft;if(g){let h=p.accounts.find(T=>T.provider==="microsoft");if(h){let T=h.microsoft??{};h.microsoft={...T,...g}}delete p.microsoft}}return l}}});var We=_(()=>{"use strict";_o();bo();Sa()});import ko from"pino";function Ds(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=ko.transport({target:"pino-pretty",options:{colorize:!0}});return ko({name:c,level:t},r)}return ko({name:c,level:t})}var Aa=_(()=>{"use strict";u(Ds,"createLogger")});import Jh from"pino";var Ia=_(()=>{"use strict"});var vo=_(()=>{"use strict";Aa();Ia()});var Ct,Jr=_(()=>{"use strict";Ct=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,
@@ -287,7 +287,7 @@ var ma=Object.defineProperty;var u=(c,e)=>ma(c,"name",{value:e,configurable:!0})
287
287
 
288
288
  CREATE UNIQUE INDEX IF NOT EXISTS idx_users_platform
289
289
  ON users(platform, platform_user_id);
290
- `)}runMigrations(){new Ct(this.db).migrate(So)}getDb(){return this.db}close(){this.db.close()}}});import Ra from"node:crypto";var Ds,Ca=_(()=>{"use strict";Ds=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Ra.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
290
+ `)}runMigrations(){new Ct(this.db).migrate(So)}getDb(){return this.db}close(){this.db.close()}}});import Ra from"node:crypto";var Ls,Ca=_(()=>{"use strict";Ls=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Ra.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
291
291
  INSERT INTO conversations (id, platform, chat_id, user_id, created_at, updated_at)
292
292
  VALUES (?, ?, ?, ?, ?, ?)
293
293
  `).run(n.id,n.platform,n.chatId,n.userId,n.createdAt,n.updatedAt),n}findById(e){let t=this.db.prepare("SELECT * FROM conversations WHERE id = ?").get(e);if(t)return this.mapRow(t)}findByPlatformChat(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND chat_id = ?").get(e,t);if(s)return this.mapRow(s)}findByPlatformAndUser(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND user_id = ? ORDER BY updated_at DESC LIMIT 1").get(e,t);if(s)return this.mapRow(s)}addMessage(e,t,s,r){let n={id:Ra.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
@@ -300,10 +300,10 @@ var ma=Object.defineProperty;var u=(c,e)=>ma(c,"name",{value:e,configurable:!0})
300
300
  `).run(e,e,t).changes}mapRow(e){return{id:e.id,platform:e.platform,chatId:e.chat_id,userId:e.user_id,createdAt:e.created_at,updatedAt:e.updated_at}}}});import Gu from"node:crypto";var Ms,Na=_(()=>{"use strict";Ms=class{static{u(this,"UserRepository")}db;constructor(e){this.db=e}findOrCreate(e,t,s,r){let n=this.db.prepare("SELECT * FROM users WHERE platform = ? AND platform_user_id = ?").get(e,t);if(n)return this.mapRow(n);let o=new Date().toISOString(),i={id:Gu.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:o,updatedAt:o};return this.db.prepare(`
301
301
  INSERT INTO users (id, platform, platform_user_id, username, display_name, created_at, updated_at)
302
302
  VALUES (?, ?, ?, ?, ?, ?, ?)
303
- `).run(i.id,i.platform,i.platformUserId,i.username??null,i.displayName??null,i.createdAt,i.updatedAt),i}findById(e){let t=this.db.prepare("SELECT * FROM users WHERE id = ?").get(e);if(t)return this.mapRow(t)}update(e,t){let s=[],r=[];t.username!==void 0&&(s.push("username = ?"),r.push(t.username??null)),t.displayName!==void 0&&(s.push("display_name = ?"),r.push(t.displayName??null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}updateProfile(e,t){let s=[],r=[];t.timezone!==void 0&&(s.push("timezone = ?"),r.push(t.timezone??null)),t.language!==void 0&&(s.push("language = ?"),r.push(t.language??null)),t.bio!==void 0&&(s.push("bio = ?"),r.push(t.bio??null)),t.preferences!==void 0&&(s.push("preferences = ?"),r.push(t.preferences?JSON.stringify(t.preferences):null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}getProfile(e){let t=this.db.prepare("SELECT display_name, timezone, language, bio, preferences FROM users WHERE id = ?").get(e);if(t)return{displayName:t.display_name??void 0,timezone:t.timezone??void 0,language:t.language??void 0,bio:t.bio??void 0,preferences:t.preferences?JSON.parse(t.preferences):void 0}}setMasterUser(e,t){this.db.prepare("UPDATE users SET master_user_id = ?, updated_at = ? WHERE id = ?").run(t,new Date().toISOString(),e)}getLinkedUsers(e){return this.db.prepare("SELECT DISTINCT * FROM users WHERE master_user_id = ? OR id = ?").all(e,e).map(s=>this.mapRow(s))}findFirstByPlatformNotIn(e){let t=e.map(()=>"?").join(", "),s=this.db.prepare(`SELECT * FROM users WHERE platform NOT IN (${t}) LIMIT 1`).get(...e);if(s)return this.mapRow(s)}getMasterUserId(e){return this.db.prepare("SELECT master_user_id FROM users WHERE id = ?").get(e)?.master_user_id??e}mapRow(e){return{id:e.id,platform:e.platform,platformUserId:e.platform_user_id,username:e.username??void 0,displayName:e.display_name??void 0,timezone:e.timezone??void 0,language:e.language??void 0,bio:e.bio??void 0,preferences:e.preferences?JSON.parse(e.preferences):void 0,masterUserId:e.master_user_id??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}}});var ft,La=_(()=>{"use strict";ft=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
303
+ `).run(i.id,i.platform,i.platformUserId,i.username??null,i.displayName??null,i.createdAt,i.updatedAt),i}findById(e){let t=this.db.prepare("SELECT * FROM users WHERE id = ?").get(e);if(t)return this.mapRow(t)}update(e,t){let s=[],r=[];t.username!==void 0&&(s.push("username = ?"),r.push(t.username??null)),t.displayName!==void 0&&(s.push("display_name = ?"),r.push(t.displayName??null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}updateProfile(e,t){let s=[],r=[];t.timezone!==void 0&&(s.push("timezone = ?"),r.push(t.timezone??null)),t.language!==void 0&&(s.push("language = ?"),r.push(t.language??null)),t.bio!==void 0&&(s.push("bio = ?"),r.push(t.bio??null)),t.preferences!==void 0&&(s.push("preferences = ?"),r.push(t.preferences?JSON.stringify(t.preferences):null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}getProfile(e){let t=this.db.prepare("SELECT display_name, timezone, language, bio, preferences FROM users WHERE id = ?").get(e);if(t)return{displayName:t.display_name??void 0,timezone:t.timezone??void 0,language:t.language??void 0,bio:t.bio??void 0,preferences:t.preferences?JSON.parse(t.preferences):void 0}}setMasterUser(e,t){this.db.prepare("UPDATE users SET master_user_id = ?, updated_at = ? WHERE id = ?").run(t,new Date().toISOString(),e)}getLinkedUsers(e){return this.db.prepare("SELECT DISTINCT * FROM users WHERE master_user_id = ? OR id = ?").all(e,e).map(s=>this.mapRow(s))}findFirstByPlatformNotIn(e){let t=e.map(()=>"?").join(", "),s=this.db.prepare(`SELECT * FROM users WHERE platform NOT IN (${t}) LIMIT 1`).get(...e);if(s)return this.mapRow(s)}getMasterUserId(e){return this.db.prepare("SELECT master_user_id FROM users WHERE id = ?").get(e)?.master_user_id??e}mapRow(e){return{id:e.id,platform:e.platform,platformUserId:e.platform_user_id,username:e.username??void 0,displayName:e.display_name??void 0,timezone:e.timezone??void 0,language:e.language??void 0,bio:e.bio??void 0,preferences:e.preferences?JSON.parse(e.preferences):void 0,masterUserId:e.master_user_id??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}}});var ft,Da=_(()=>{"use strict";ft=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
304
304
  INSERT INTO audit_log (id, timestamp, user_id, action, risk_level, rule_id, effect, platform, chat_id, context)
305
305
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
306
- `).run(e.id,e.timestamp.toISOString(),e.userId,e.action,e.riskLevel,e.ruleId??null,e.effect,e.platform,e.chatId??null,e.context?JSON.stringify(e.context):null)}query(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.action&&(t.push("action = ?"),s.push(e.action)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"",n=e.limit??100;return s.push(n),this.db.prepare(`SELECT * FROM audit_log ${r} ORDER BY timestamp DESC LIMIT ?`).all(...s).map(i=>this.mapRow(i))}count(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"";return this.db.prepare(`SELECT COUNT(*) as count FROM audit_log ${r}`).get(...s).count}mapRow(e){return{id:e.id,timestamp:new Date(e.timestamp),userId:e.user_id,action:e.action,riskLevel:e.risk_level,ruleId:e.rule_id??void 0,effect:e.effect,platform:e.platform,chatId:e.chat_id??void 0,context:e.context?JSON.parse(e.context):void 0}}}});import{randomUUID as Vu}from"node:crypto";var Os,Da=_(()=>{"use strict";Os=class{static{u(this,"MemoryRepository")}db;constructor(e){this.db=e}save(e,t,s,r="general"){return this.saveWithMetadata(e,t,s,r,"general",1,"manual")}saveWithMetadata(e,t,s,r,n,o,i){let a=new Date().toISOString(),l=Vu();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
306
+ `).run(e.id,e.timestamp.toISOString(),e.userId,e.action,e.riskLevel,e.ruleId??null,e.effect,e.platform,e.chatId??null,e.context?JSON.stringify(e.context):null)}query(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.action&&(t.push("action = ?"),s.push(e.action)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"",n=e.limit??100;return s.push(n),this.db.prepare(`SELECT * FROM audit_log ${r} ORDER BY timestamp DESC LIMIT ?`).all(...s).map(i=>this.mapRow(i))}count(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"";return this.db.prepare(`SELECT COUNT(*) as count FROM audit_log ${r}`).get(...s).count}mapRow(e){return{id:e.id,timestamp:new Date(e.timestamp),userId:e.user_id,action:e.action,riskLevel:e.risk_level,ruleId:e.rule_id??void 0,effect:e.effect,platform:e.platform,chatId:e.chat_id??void 0,context:e.context?JSON.parse(e.context):void 0}}}});import{randomUUID as Vu}from"node:crypto";var Os,La=_(()=>{"use strict";Os=class{static{u(this,"MemoryRepository")}db;constructor(e){this.db=e}save(e,t,s,r="general"){return this.saveWithMetadata(e,t,s,r,"general",1,"manual")}saveWithMetadata(e,t,s,r,n,o,i){let a=new Date().toISOString(),l=Vu();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
307
307
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
308
308
  ON CONFLICT(user_id, key) DO UPDATE SET
309
309
  value = excluded.value,
@@ -368,9 +368,9 @@ var ma=Object.defineProperty;var u=(c,e)=>ma(c,"name",{value:e,configurable:!0})
368
368
  UPDATE watches
369
369
  SET last_checked_at = ?, last_value = ?
370
370
  WHERE id = ?
371
- `).run(t.lastCheckedAt,t.lastValue,e)}findByChatId(e,t){return this.db.prepare("SELECT * FROM watches WHERE chat_id = ? AND platform = ? ORDER BY created_at DESC").all(e,t).map(r=>this.mapRow(r))}toggle(e,t){return this.db.prepare("UPDATE watches SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM watches WHERE id = ?").run(e).changes>0}getById(e){let t=this.db.prepare("SELECT * FROM watches WHERE id = ?").get(e);return t?this.mapRow(t):void 0}mapRow(e){let t={};try{t=JSON.parse(e.skill_params)}catch{}let s={field:e.condition_field,operator:e.condition_operator};if(e.condition_value!=null){let r=Number(e.condition_value);s.value=isNaN(r)?e.condition_value:r}return{id:e.id,chatId:e.chat_id,platform:e.platform,name:e.name,skillName:e.skill_name,skillParams:t,condition:s,intervalMinutes:e.interval_minutes,cooldownMinutes:e.cooldown_minutes,enabled:e.enabled===1,lastCheckedAt:e.last_checked_at??null,lastTriggeredAt:e.last_triggered_at??null,lastValue:e.last_value??null,createdAt:e.created_at,messageTemplate:e.message_template}}}});var Io=_(()=>{"use strict";xa();Ca();Na();La();Da();Jr();Ao();Ma();Oa();Pa();Ua();Fa();ja();Ha();qa();za()});function We(c){if(xo[c])return xo[c];let e=Object.entries(xo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var xo,sm,Ae,gt=_(()=>{"use strict";xo={"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}},sm={maxInputTokens:128e3,maxOutputTokens:8192};u(We,"lookupContextWindow");Ae=class{static{u(this,"LLMProvider")}config;contextWindow=sm;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import rm from"@anthropic-ai/sdk";var Gs,Ro=_(()=>{"use strict";gt();Gs=class extends Ae{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new rm({apiKey:this.config.apiKey,maxRetries:5});let e=We(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,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,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){return e.map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}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,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens},stopReason:e.stop_reason}}}});import nm from"openai";var Ne,Nt=_(()=>{"use strict";gt();Ne=class extends Ae{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new nm({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=We(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="",l=[],d=null,m=0,p=0;for await(let g of r){let f=g.choices[0];if(!f)continue;let h=f.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let T of h.tool_calls)if(T.id){if(n){let b;try{b=JSON.parse(i||"{}")}catch{b={}}l.push({id:n,name:o,input:b})}n=T.id,o=T.function?.name,i=T.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else T.function?.arguments&&(i+=T.function.arguments,yield{type:"tool_use_delta",toolCall:{input:T.function.arguments}});f.finish_reason&&(d=f.finish_reason),g.usage&&(m=g.usage.prompt_tokens,p=g.usage.completion_tokens)}if(n){let g;try{g=JSON.parse(i||"{}")}catch{g={}}l.push({id:n,name:o,input:g})}yield{type:"message_complete",response:{content:a,toolCalls:l.length>0?l: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(l=>l.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,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 Vs,Co=_(()=>{"use strict";Nt();Vs=class extends Ne{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 Ks,No=_(()=>{"use strict";gt();Ks=class extends Ae{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=We(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 g=await n.text();throw new Error(`Ollama API error (${n.status}): ${g}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",l="",d=0,m=0,p=[];try{for(;;){let{done:g,value:f}=await o.read();if(g)break;a+=i.decode(f,{stream:!0});let h=a.split(`
371
+ `).run(t.lastCheckedAt,t.lastValue,e)}findByChatId(e,t){return this.db.prepare("SELECT * FROM watches WHERE chat_id = ? AND platform = ? ORDER BY created_at DESC").all(e,t).map(r=>this.mapRow(r))}toggle(e,t){return this.db.prepare("UPDATE watches SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM watches WHERE id = ?").run(e).changes>0}getById(e){let t=this.db.prepare("SELECT * FROM watches WHERE id = ?").get(e);return t?this.mapRow(t):void 0}mapRow(e){let t={};try{t=JSON.parse(e.skill_params)}catch{}let s={field:e.condition_field,operator:e.condition_operator};if(e.condition_value!=null){let r=Number(e.condition_value);s.value=isNaN(r)?e.condition_value:r}return{id:e.id,chatId:e.chat_id,platform:e.platform,name:e.name,skillName:e.skill_name,skillParams:t,condition:s,intervalMinutes:e.interval_minutes,cooldownMinutes:e.cooldown_minutes,enabled:e.enabled===1,lastCheckedAt:e.last_checked_at??null,lastTriggeredAt:e.last_triggered_at??null,lastValue:e.last_value??null,createdAt:e.created_at,messageTemplate:e.message_template}}}});var Io=_(()=>{"use strict";xa();Ca();Na();Da();La();Jr();Ao();Ma();Oa();Pa();Ua();Fa();ja();Ha();qa();za()});function Ge(c){if(xo[c])return xo[c];let e=Object.entries(xo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var xo,sm,Ae,gt=_(()=>{"use strict";xo={"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}},sm={maxInputTokens:128e3,maxOutputTokens:8192};u(Ge,"lookupContextWindow");Ae=class{static{u(this,"LLMProvider")}config;contextWindow=sm;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import rm from"@anthropic-ai/sdk";var Gs,Ro=_(()=>{"use strict";gt();Gs=class extends Ae{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new rm({apiKey:this.config.apiKey,maxRetries:5});let e=Ge(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,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,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){return e.map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}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,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens},stopReason:e.stop_reason}}}});import nm from"openai";var Ne,Nt=_(()=>{"use strict";gt();Ne=class extends Ae{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new nm({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=Ge(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="",l=[],d=null,m=0,p=0;for await(let g of r){let f=g.choices[0];if(!f)continue;let h=f.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let T of h.tool_calls)if(T.id){if(n){let b;try{b=JSON.parse(i||"{}")}catch{b={}}l.push({id:n,name:o,input:b})}n=T.id,o=T.function?.name,i=T.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else T.function?.arguments&&(i+=T.function.arguments,yield{type:"tool_use_delta",toolCall:{input:T.function.arguments}});f.finish_reason&&(d=f.finish_reason),g.usage&&(m=g.usage.prompt_tokens,p=g.usage.completion_tokens)}if(n){let g;try{g=JSON.parse(i||"{}")}catch{g={}}l.push({id:n,name:o,input:g})}yield{type:"message_complete",response:{content:a,toolCalls:l.length>0?l: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(l=>l.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,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 Vs,Co=_(()=>{"use strict";Nt();Vs=class extends Ne{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 Ks,No=_(()=>{"use strict";gt();Ks=class extends Ae{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=Ge(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 g=await n.text();throw new Error(`Ollama API error (${n.status}): ${g}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",l="",d=0,m=0,p=[];try{for(;;){let{done:g,value:f}=await o.read();if(g)break;a+=i.decode(f,{stream:!0});let h=a.split(`
372
372
  `);a=h.pop()??"";for(let T of h){let b=T.trim();if(!b)continue;let A;try{A=JSON.parse(b)}catch{continue}if(A.message?.content&&(l+=A.message.content,yield{type:"text_delta",text:A.message.content}),A.message?.tool_calls)for(let C of A.message.tool_calls){let U={id:`ollama_tool_${p.length}`,name:C.function.name,input:C.function.arguments};p.push(U),yield{type:"tool_use_start",toolCall:{id:U.id,name:U.name}},yield{type:"tool_use_delta",toolCall:{input:U.input}}}A.done&&(d=A.prompt_eval_count??0,m=A.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:p.length>0?p:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let g;try{g=JSON.parse(a.trim())}catch{return}if(g.message?.content&&(l+=g.message.content,yield{type:"text_delta",text:g.message.content}),g.message?.tool_calls)for(let f of g.message.tool_calls){let h={id:`ollama_tool_${p.length}`,name:f.function.name,input:f.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}}}g.done&&(d=g.prompt_eval_count??0,m=g.eval_count??0,yield{type:"message_complete",response:{content:l,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(`
373
- `)};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,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 Xs,Lo=_(()=>{"use strict";Nt();Xs=class extends Ne{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 om}from"@google/genai";var Ys,Do=_(()=>{"use strict";gt();Ys=class extends Ae{static{u(this,"GoogleProvider")}client;rawContentCache=new Map;constructor(e){super(e)}async initialize(){this.client=new om({apiKey:this.config.apiKey});let e=We(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,l;for await(let d of r){l=d;let m=d.text;if(m&&(n+=m,yield{type:"text_delta",text:m}),d.functionCalls)for(let p of d.functionCalls){let g={id:p.id??`google_tool_${o.length}`,name:p.name,input:p.args??{}};o.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}}}d.usageMetadata&&(i=d.usageMetadata.promptTokenCount??0,a=d.usageMetadata.candidatesTokenCount??0)}l&&this.cacheRawContent(l),yield{type:"message_complete",response:{content:n,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 l of r.content)switch(l.type){case"text":i.push({text:l.text});break;case"image":i.push({inlineData:{mimeType:l.source.media_type,data:l.source.data}});break;case"tool_use":o.push({id:l.id,name:l.name,input:l.input});break;case"tool_result":{let d=t.get(l.tool_use_id)??l.tool_use_id,m;try{let p=JSON.parse(l.content);m=typeof p=="object"&&p!==null?p:{result:p}}catch{m={result:l.content}}a.push({functionResponse:{id:l.tool_use_id,name:d,response:m}});break}}if(r.role==="assistant"&&o.length>0){let l=this.buildCacheKeyFromBlocks(o),d=this.rawContentCache.get(l);if(d)s.push(d);else{let m=[...i];for(let p=0;p<o.length;p++){let g=o[p];m.push({functionCall:{id:g.id,name:g.name,args:g.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 l=a.functionCall.id??a.functionCall.name??"";l&&t.add(l)}s.push(i)}else{let a=(i.parts??[]).filter(l=>{if(l.functionResponse){let d=l.functionResponse.id??l.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 l=a.functionResponse.id??a.functionResponse.name??"";l&&r.add(l)}}let n=[];for(let i of s)if(i.role==="model"){let a=(i.parts??[]).filter(l=>{if(l.functionCall){let d=l.functionCall.id??l.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],l=n[i];a.role===l.role?a.parts=[...a.parts??[],...l.parts??[]]:o.push(l)}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,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 Js,Mo=_(()=>{"use strict";Nt();Js=class extends Ne{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 Oo(c){switch(c.provider){case"anthropic":return new Gs(c);case"openai":return new Ne(c);case"openrouter":return new Vs(c);case"ollama":return new Ks(c);case"openwebui":return new Xs(c);case"google":return new Ys(c);case"mistral":return new Js(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var Po=_(()=>{"use strict";Ro();Nt();Co();No();Lo();Do();Mo();u(Oo,"createLLMProvider")});function Uo(c,e){return new Zr(c,e)}var im,Zr,Wa=_(()=>{"use strict";gt();Po();im=["default","strong","fast","embeddings","local"],Zr=class extends Ae{static{u(this,"ModelRouter")}providers=new Map;multiConfig;logger;constructor(e,t){super(e.default),this.multiConfig=e,this.logger=t}async initialize(){for(let e of im){let t=this.multiConfig[e];if(t){let s=Oo(t);await s.initialize(),this.providers.set(e,s),this.logger?.info({tier:e,provider:t.provider,model:t.model},"LLM tier initialized")}}}resolve(e){return e&&this.providers.has(e)?{provider:this.providers.get(e),resolvedTier:e}:{provider:this.providers.get("default"),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);return this.logger?.info({tier:s,model:r?.model,inputTokens:n.usage?.inputTokens,outputTokens:n.usage?.outputTokens},"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()}};u(Uo,"createModelRouter")});function Le(c){return Math.ceil(c.length/3.5)}function Qs(c){if(typeof c.content=="string")return Le(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=Le(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=Le(t.name)+Le(JSON.stringify(t.input));break;case"tool_result":e+=Le(t.content);break}return e}var Zs,Ga=_(()=>{"use strict";u(Le,"estimateTokens");u(Qs,"estimateMessageTokens");Zs=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
373
+ `)};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,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 Xs,Do=_(()=>{"use strict";Nt();Xs=class extends Ne{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 om}from"@google/genai";var Ys,Lo=_(()=>{"use strict";gt();Ys=class extends Ae{static{u(this,"GoogleProvider")}client;rawContentCache=new Map;constructor(e){super(e)}async initialize(){this.client=new om({apiKey:this.config.apiKey});let e=Ge(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,l;for await(let d of r){l=d;let m=d.text;if(m&&(n+=m,yield{type:"text_delta",text:m}),d.functionCalls)for(let p of d.functionCalls){let g={id:p.id??`google_tool_${o.length}`,name:p.name,input:p.args??{}};o.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}}}d.usageMetadata&&(i=d.usageMetadata.promptTokenCount??0,a=d.usageMetadata.candidatesTokenCount??0)}l&&this.cacheRawContent(l),yield{type:"message_complete",response:{content:n,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 l of r.content)switch(l.type){case"text":i.push({text:l.text});break;case"image":i.push({inlineData:{mimeType:l.source.media_type,data:l.source.data}});break;case"tool_use":o.push({id:l.id,name:l.name,input:l.input});break;case"tool_result":{let d=t.get(l.tool_use_id)??l.tool_use_id,m;try{let p=JSON.parse(l.content);m=typeof p=="object"&&p!==null?p:{result:p}}catch{m={result:l.content}}a.push({functionResponse:{id:l.tool_use_id,name:d,response:m}});break}}if(r.role==="assistant"&&o.length>0){let l=this.buildCacheKeyFromBlocks(o),d=this.rawContentCache.get(l);if(d)s.push(d);else{let m=[...i];for(let p=0;p<o.length;p++){let g=o[p];m.push({functionCall:{id:g.id,name:g.name,args:g.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 l=a.functionCall.id??a.functionCall.name??"";l&&t.add(l)}s.push(i)}else{let a=(i.parts??[]).filter(l=>{if(l.functionResponse){let d=l.functionResponse.id??l.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 l=a.functionResponse.id??a.functionResponse.name??"";l&&r.add(l)}}let n=[];for(let i of s)if(i.role==="model"){let a=(i.parts??[]).filter(l=>{if(l.functionCall){let d=l.functionCall.id??l.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],l=n[i];a.role===l.role?a.parts=[...a.parts??[],...l.parts??[]]:o.push(l)}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,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 Js,Mo=_(()=>{"use strict";Nt();Js=class extends Ne{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 Oo(c){switch(c.provider){case"anthropic":return new Gs(c);case"openai":return new Ne(c);case"openrouter":return new Vs(c);case"ollama":return new Ks(c);case"openwebui":return new Xs(c);case"google":return new Ys(c);case"mistral":return new Js(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var Po=_(()=>{"use strict";Ro();Nt();Co();No();Do();Lo();Mo();u(Oo,"createLLMProvider")});function Uo(c,e){return new Zr(c,e)}var im,Zr,Wa=_(()=>{"use strict";gt();Po();im=["default","strong","fast","embeddings","local"],Zr=class extends Ae{static{u(this,"ModelRouter")}providers=new Map;multiConfig;logger;constructor(e,t){super(e.default),this.multiConfig=e,this.logger=t}async initialize(){for(let e of im){let t=this.multiConfig[e];if(t){let s=Oo(t);await s.initialize(),this.providers.set(e,s),this.logger?.info({tier:e,provider:t.provider,model:t.model},"LLM tier initialized")}}}resolve(e){return e&&this.providers.has(e)?{provider:this.providers.get(e),resolvedTier:e}:{provider:this.providers.get("default"),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);return this.logger?.info({tier:s,model:r?.model,inputTokens:n.usage?.inputTokens,outputTokens:n.usage?.outputTokens},"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()}};u(Uo,"createModelRouter")});function De(c){return Math.ceil(c.length/3.5)}function Qs(c){if(typeof c.content=="string")return De(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=De(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=De(t.name)+De(JSON.stringify(t.input));break;case"tool_result":e+=De(t.content);break}return e}var Zs,Ga=_(()=>{"use strict";u(De,"estimateTokens");u(Qs,"estimateMessageTokens");Zs=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
374
374
 
375
375
  ## Core principles
376
376
  - **When the user's intent is clear**, ACT immediately using your tools. Don't explain what you'll do \u2014 just do it.
@@ -429,15 +429,15 @@ For complex tasks, work through multiple steps:
429
429
  `;a+=`
430
430
  Use these memories to personalize your responses. When the user tells you new facts or preferences, use the memory tool to save them.`}else a+=`
431
431
 
432
- When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let l of i)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});return a.length===0&&a.push({type:"text",text:""}),{role:"assistant",content:a}}let n=r,o=[];for(let i of n)i.type==="tool_result"&&o.push(i);return o.length>0?{role:"user",content:o}:{role:"user",content:s.content||""}}return{role:s.role,content:s.content}});return this.sanitizeToolMessages(t)}sanitizeToolMessages(e){let t=new Set,s=new Set;for(let a of e)if(a.role==="assistant"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_use"&&t.add(l.id);else if(a.role==="user"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_result"&&t.has(l.tool_use_id)&&s.add(l.tool_use_id);let r=new Set,n=new Set,o=[];for(let a of e){if(!Array.isArray(a.content)){o.push(a);continue}let l=a.content.filter(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);l.length!==0&&o.push({...a,content:l})}let i=[];for(let a of o){let l=i[i.length-1];if(l&&l.role===a.role){let d=typeof l.content=="string"?[{type:"text",text:l.content}]:l.content,m=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...l,content:[...d,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Fo=_(()=>{"use strict";gt();Ro();Nt();Co();No();Lo();Do();Mo();Po();Wa();Ga()});var er,jo=_(()=>{"use strict";er=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var tr,Va=_(()=>{"use strict";jo();tr=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new er;loadRules(e){this.rules=[...e].sort((t,s)=>t.priority-s.priority)}getRules(){return this.rules}evaluate(e){for(let t of this.rules)if(this.ruleMatches(t,e))return t.rateLimit&&t.effect==="allow"&&!this.checkRateLimit(t,e)?{allowed:!1,matchedRule:t,reason:`Rate limit exceeded for rule: ${t.id}`,timestamp:new Date}:{allowed:t.effect==="allow",matchedRule:t,reason:`Matched rule: ${t.id}`,timestamp:new Date};return{allowed:!1,matchedRule:void 0,reason:"No matching rule found \u2014 default deny",timestamp:new Date}}checkRateLimit(e,t){if(!e.rateLimit)return!0;let s=this.getScopeKey(e.scope,t),r=`${e.id}:${s}`;return this.rateLimiter.check(r,e.rateLimit).allowed?(this.rateLimiter.increment(r,e.rateLimit),!0):!1}resetRateLimits(){this.rateLimiter.reset()}getScopeKey(e,t){switch(e){case"global":return"global";case"user":return t.userId;case"conversation":return t.chatId??"unknown";case"platform":return t.platform}}ruleMatches(e,t){return!(!e.actions.includes("*")&&!e.actions.includes(t.action)||!e.riskLevels.includes(t.riskLevel)||e.conditions&&(e.conditions.users&&e.conditions.users.length>0&&!e.conditions.users.includes(t.userId)||e.conditions.platforms&&e.conditions.platforms.length>0&&!e.conditions.platforms.includes(t.platform)||e.conditions.chatType&&t.chatType&&e.conditions.chatType!==t.chatType||e.conditions.timeWindow&&!this.matchesTimeWindow(e.conditions.timeWindow)))}matchesTimeWindow(e){if(!e)return!0;let t=new Date;if(e.daysOfWeek&&e.daysOfWeek.length>0&&!e.daysOfWeek.includes(t.getDay()))return!1;let s=t.getHours();if(e.startHour!==void 0&&e.endHour!==void 0){if(e.startHour<=e.endHour){if(s<e.startHour||s>=e.endHour)return!1}else if(s>=e.endHour&&s<e.startHour)return!1}else if(e.startHour!==void 0){if(s<e.startHour)return!1}else if(e.endHour!==void 0&&s>=e.endHour)return!1;return!0}}});var Ka,Xa,Ya,yt,Ja=_(()=>{"use strict";Ka=["allow","deny"],Xa=["global","user","conversation","platform"],Ya=["read","write","destructive","admin"],yt=class{static{u(this,"RuleLoader")}loadFromObject(e){if(!e||!Array.isArray(e.rules))throw new Error('Invalid data: expected an object with a "rules" array');return e.rules.map((t,s)=>this.validateRule(t,s))}validateRule(e,t){if(typeof e!="object"||e===null)throw new Error(`Rule at index ${t} is not an object`);let s=e;if(typeof s.id!="string"||s.id.length===0)throw new Error(`Rule at index ${t} is missing a valid "id" string`);if(typeof s.effect!="string"||!Ka.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${Ka.join(", ")}`);if(typeof s.priority!="number"||!Number.isFinite(s.priority))throw new Error(`Rule "${s.id}" is missing a valid "priority" number`);if(typeof s.scope!="string"||!Xa.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Xa.join(", ")}`);if(!Array.isArray(s.actions)||s.actions.length===0)throw new Error(`Rule "${s.id}" is missing a valid "actions" array`);for(let n of s.actions)if(typeof n!="string")throw new Error(`Rule "${s.id}" has a non-string entry in "actions"`);if(!Array.isArray(s.riskLevels)||s.riskLevels.length===0)throw new Error(`Rule "${s.id}" is missing a valid "riskLevels" array`);for(let n of s.riskLevels)if(!Ya.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${Ya.join(", ")}`);let r={id:s.id,effect:s.effect,priority:s.priority,scope:s.scope,actions:s.actions,riskLevels:s.riskLevels};if(s.conditions!==void 0){if(typeof s.conditions!="object"||s.conditions===null)throw new Error(`Rule "${s.id}" has invalid "conditions": expected an object`);r.conditions=s.conditions}if(s.rateLimit!==void 0){if(typeof s.rateLimit!="object"||s.rateLimit===null)throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected an object`);let n=s.rateLimit;if(typeof n.maxInvocations!="number"||typeof n.windowSeconds!="number")throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected maxInvocations and windowSeconds numbers`);r.rateLimit=s.rateLimit}return r}}});import am from"node:crypto";var sr,Za=_(()=>{"use strict";sr=class{static{u(this,"SecurityManager")}ruleEngine;auditRepository;logger;constructor(e,t,s){this.ruleEngine=e,this.auditRepository=t,this.logger=s}evaluate(e){let t=this.ruleEngine.evaluate(e),s={id:am.randomUUID(),timestamp:t.timestamp,userId:e.userId,action:e.action,riskLevel:e.riskLevel,ruleId:t.matchedRule?.id,effect:t.allowed?"allow":"deny",platform:e.platform,chatId:e.chatId,context:{chatType:e.chatType,reason:t.reason}};try{this.auditRepository.log(s)}catch(r){this.logger.error({err:r,auditEntry:s},"Failed to write audit log entry")}return this.logger.debug({userId:e.userId,action:e.action,allowed:t.allowed,ruleId:t.matchedRule?.id,reason:t.reason},"Security evaluation completed"),t}}});var Qr=_(()=>{"use strict";Va();jo();Ja();Za()});var I,P=_(()=>{"use strict";I=class{static{u(this,"Skill")}}});function te(c){return c.masterUserId??c.userId}function z(c){let e=new Set;if(e.add(te(c)),e.add(c.userId),c.linkedPlatformUserIds)for(let t of c.linkedPlatformUserIds)e.add(t);return[...e]}var Fe=_(()=>{"use strict";u(te,"effectiveUserId");u(z,"allUserIds")});var Lt,Qa=_(()=>{"use strict";Lt=class{static{u(this,"SkillRegistry")}skills=new Map;register(e){let{name:t}=e.metadata;if(this.skills.has(t))throw new Error(`Skill "${t}" is already registered`);this.skills.set(t,e)}get(e){return this.skills.get(e)}getAll(){return[...this.skills.values()]}has(e){return this.skills.has(e)}unregister(e){return this.skills.delete(e)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Dt,ec=_(()=>{"use strict";Dt=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,l,d,m,p=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),g=u(f=>{a||(a=!0,p(),i(f))},"finish");e.execute(t,s).then(f=>{this.logger.info({skill:r,success:f.success,...f.success?{}:{error:f.error}},"Skill execution completed"),g(f)},f=>{let h=f instanceof Error?f.message:String(f);this.logger.error({skill:r,error:h},"Skill execution failed"),g({success:!1,error:h})}),m=setTimeout(()=>{if(a)return;let f=o.getIdleMs();if(f>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:f,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),g({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(f/1e3)}s (last state: ${T.state})`});return}let h=o.getSnapshot();this.logger.info({skill:r,idleMs:f,state:h.state,iteration:h.iteration,totalMs:h.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){p();return}let T=o.getIdleMs(),b=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:b.state,iteration:b.iteration,totalMs:b.totalElapsedMs},"Agent went inactive \u2014 aborting"),g({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${b.state})`})):this.logger.debug({skill:r,idleMs:T,state:b.state,iteration:b.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let f=o.getSnapshot();this.logger.error({skill:r,totalMs:f.totalElapsedMs,state:f.state,iteration:f.iteration},"Absolute time limit reached \u2014 force killing agent"),g({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success,...o.success?{}:{error:o.error}},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var wt,Bo=_(()=>{"use strict";wt=class{static{u(this,"ActivityTracker")}state="starting";iteration=0;maxIterations=0;currentTool;lastPingAt;startedAt;history=[];onProgress;constructor(e){this.startedAt=Date.now(),this.lastPingAt=Date.now(),this.onProgress=e}ping(e,t){this.state=e,this.lastPingAt=Date.now(),t?.iteration!==void 0&&(this.iteration=t.iteration),t?.maxIterations!==void 0&&(this.maxIterations=t.maxIterations),this.currentTool=t?.tool,this.history.push({state:e,tool:t?.tool,iteration:this.iteration,timestamp:this.lastPingAt}),this.onProgress&&this.onProgress(this.formatStatus())}getIdleMs(){return Date.now()-this.lastPingAt}getTotalElapsedMs(){return Date.now()-this.startedAt}formatStatus(){let e=this.maxIterations>0?` (${this.iteration}/${this.maxIterations})`:"";switch(this.state){case"starting":return"Sub-agent starting...";case"llm_call":return`Sub-agent thinking...${e}`;case"tool_call":return this.currentTool?`Sub-agent using ${this.currentTool}${e}`:`Sub-agent using tool...${e}`;case"processing":return`Sub-agent processing...${e}`;case"done":return`Sub-agent done${e}`;default:return`Sub-agent working...${e}`}}getSnapshot(){return{state:this.state,iteration:this.iteration,maxIterations:this.maxIterations,lastPingAt:this.lastPingAt,idleMs:this.getIdleMs(),currentTool:this.currentTool,totalElapsedMs:this.getTotalElapsedMs(),history:[...this.history]}}}});import cm from"node:fs";import Ho from"node:path";var en,tc=_(()=>{"use strict";P();en=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Ho.resolve(e),s;try{s=await cm.promises.readdir(t)}catch(o){let i=o instanceof Error?o.message:String(o);return console.warn(`PluginLoader: failed to read directory "${t}": ${i}`),[]}let r=s.filter(o=>o.endsWith(".js")),n=[];for(let o of r){let i=Ho.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let l=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${l}`)}}return n}async loadFromFile(e){let t=Ho.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var lm,dm,Mt,sc=_(()=>{"use strict";P();lm=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,dm=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Mt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!dm.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(lm,"");if(/[a-zA-Z]/.test(n))return{success:!1,error:`Invalid expression: "${r}" contains disallowed identifiers`};try{let i=new Function("Math",`"use strict"; return (${r});`)(Math);return typeof i!="number"||!isFinite(i)?{success:!1,error:`Invalid expression: "${r}" did not produce a finite number`}:{success:!0,data:i,display:`${r} = ${i}`}}catch{return{success:!1,error:`Invalid expression: "${r}"`}}}}});var Ot,rc=_(()=>{"use strict";P();Ot=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var Pt,nc=_(()=>{"use strict";P();Pt=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,l)=>`${l+1}. **${a.title}**
432
+ When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let l of i)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});return a.length===0&&a.push({type:"text",text:""}),{role:"assistant",content:a}}let n=r,o=[];for(let i of n)i.type==="tool_result"&&o.push(i);return o.length>0?{role:"user",content:o}:{role:"user",content:s.content||""}}return{role:s.role,content:s.content}});return this.sanitizeToolMessages(t)}sanitizeToolMessages(e){let t=new Set,s=new Set;for(let a of e)if(a.role==="assistant"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_use"&&t.add(l.id);else if(a.role==="user"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_result"&&t.has(l.tool_use_id)&&s.add(l.tool_use_id);let r=new Set,n=new Set,o=[];for(let a of e){if(!Array.isArray(a.content)){o.push(a);continue}let l=a.content.filter(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);l.length!==0&&o.push({...a,content:l})}let i=[];for(let a of o){let l=i[i.length-1];if(l&&l.role===a.role){let d=typeof l.content=="string"?[{type:"text",text:l.content}]:l.content,m=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...l,content:[...d,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Fo=_(()=>{"use strict";gt();Ro();Nt();Co();No();Do();Lo();Mo();Po();Wa();Ga()});var er,jo=_(()=>{"use strict";er=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var tr,Va=_(()=>{"use strict";jo();tr=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new er;loadRules(e){this.rules=[...e].sort((t,s)=>t.priority-s.priority)}getRules(){return this.rules}evaluate(e){for(let t of this.rules)if(this.ruleMatches(t,e))return t.rateLimit&&t.effect==="allow"&&!this.checkRateLimit(t,e)?{allowed:!1,matchedRule:t,reason:`Rate limit exceeded for rule: ${t.id}`,timestamp:new Date}:{allowed:t.effect==="allow",matchedRule:t,reason:`Matched rule: ${t.id}`,timestamp:new Date};return{allowed:!1,matchedRule:void 0,reason:"No matching rule found \u2014 default deny",timestamp:new Date}}checkRateLimit(e,t){if(!e.rateLimit)return!0;let s=this.getScopeKey(e.scope,t),r=`${e.id}:${s}`;return this.rateLimiter.check(r,e.rateLimit).allowed?(this.rateLimiter.increment(r,e.rateLimit),!0):!1}resetRateLimits(){this.rateLimiter.reset()}getScopeKey(e,t){switch(e){case"global":return"global";case"user":return t.userId;case"conversation":return t.chatId??"unknown";case"platform":return t.platform}}ruleMatches(e,t){return!(!e.actions.includes("*")&&!e.actions.includes(t.action)||!e.riskLevels.includes(t.riskLevel)||e.conditions&&(e.conditions.users&&e.conditions.users.length>0&&!e.conditions.users.includes(t.userId)||e.conditions.platforms&&e.conditions.platforms.length>0&&!e.conditions.platforms.includes(t.platform)||e.conditions.chatType&&t.chatType&&e.conditions.chatType!==t.chatType||e.conditions.timeWindow&&!this.matchesTimeWindow(e.conditions.timeWindow)))}matchesTimeWindow(e){if(!e)return!0;let t=new Date;if(e.daysOfWeek&&e.daysOfWeek.length>0&&!e.daysOfWeek.includes(t.getDay()))return!1;let s=t.getHours();if(e.startHour!==void 0&&e.endHour!==void 0){if(e.startHour<=e.endHour){if(s<e.startHour||s>=e.endHour)return!1}else if(s>=e.endHour&&s<e.startHour)return!1}else if(e.startHour!==void 0){if(s<e.startHour)return!1}else if(e.endHour!==void 0&&s>=e.endHour)return!1;return!0}}});var Ka,Xa,Ya,yt,Ja=_(()=>{"use strict";Ka=["allow","deny"],Xa=["global","user","conversation","platform"],Ya=["read","write","destructive","admin"],yt=class{static{u(this,"RuleLoader")}loadFromObject(e){if(!e||!Array.isArray(e.rules))throw new Error('Invalid data: expected an object with a "rules" array');return e.rules.map((t,s)=>this.validateRule(t,s))}validateRule(e,t){if(typeof e!="object"||e===null)throw new Error(`Rule at index ${t} is not an object`);let s=e;if(typeof s.id!="string"||s.id.length===0)throw new Error(`Rule at index ${t} is missing a valid "id" string`);if(typeof s.effect!="string"||!Ka.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${Ka.join(", ")}`);if(typeof s.priority!="number"||!Number.isFinite(s.priority))throw new Error(`Rule "${s.id}" is missing a valid "priority" number`);if(typeof s.scope!="string"||!Xa.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Xa.join(", ")}`);if(!Array.isArray(s.actions)||s.actions.length===0)throw new Error(`Rule "${s.id}" is missing a valid "actions" array`);for(let n of s.actions)if(typeof n!="string")throw new Error(`Rule "${s.id}" has a non-string entry in "actions"`);if(!Array.isArray(s.riskLevels)||s.riskLevels.length===0)throw new Error(`Rule "${s.id}" is missing a valid "riskLevels" array`);for(let n of s.riskLevels)if(!Ya.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${Ya.join(", ")}`);let r={id:s.id,effect:s.effect,priority:s.priority,scope:s.scope,actions:s.actions,riskLevels:s.riskLevels};if(s.conditions!==void 0){if(typeof s.conditions!="object"||s.conditions===null)throw new Error(`Rule "${s.id}" has invalid "conditions": expected an object`);r.conditions=s.conditions}if(s.rateLimit!==void 0){if(typeof s.rateLimit!="object"||s.rateLimit===null)throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected an object`);let n=s.rateLimit;if(typeof n.maxInvocations!="number"||typeof n.windowSeconds!="number")throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected maxInvocations and windowSeconds numbers`);r.rateLimit=s.rateLimit}return r}}});import am from"node:crypto";var sr,Za=_(()=>{"use strict";sr=class{static{u(this,"SecurityManager")}ruleEngine;auditRepository;logger;constructor(e,t,s){this.ruleEngine=e,this.auditRepository=t,this.logger=s}evaluate(e){let t=this.ruleEngine.evaluate(e),s={id:am.randomUUID(),timestamp:t.timestamp,userId:e.userId,action:e.action,riskLevel:e.riskLevel,ruleId:t.matchedRule?.id,effect:t.allowed?"allow":"deny",platform:e.platform,chatId:e.chatId,context:{chatType:e.chatType,reason:t.reason}};try{this.auditRepository.log(s)}catch(r){this.logger.error({err:r,auditEntry:s},"Failed to write audit log entry")}return this.logger.debug({userId:e.userId,action:e.action,allowed:t.allowed,ruleId:t.matchedRule?.id,reason:t.reason},"Security evaluation completed"),t}}});var Qr=_(()=>{"use strict";Va();jo();Ja();Za()});var I,P=_(()=>{"use strict";I=class{static{u(this,"Skill")}}});function te(c){return c.masterUserId??c.userId}function z(c){let e=new Set;if(e.add(te(c)),e.add(c.userId),c.linkedPlatformUserIds)for(let t of c.linkedPlatformUserIds)e.add(t);return[...e]}var Be=_(()=>{"use strict";u(te,"effectiveUserId");u(z,"allUserIds")});var Dt,Qa=_(()=>{"use strict";Dt=class{static{u(this,"SkillRegistry")}skills=new Map;register(e){let{name:t}=e.metadata;if(this.skills.has(t))throw new Error(`Skill "${t}" is already registered`);this.skills.set(t,e)}get(e){return this.skills.get(e)}getAll(){return[...this.skills.values()]}has(e){return this.skills.has(e)}unregister(e){return this.skills.delete(e)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Lt,ec=_(()=>{"use strict";Lt=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,l,d,m,p=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),g=u(f=>{a||(a=!0,p(),i(f))},"finish");e.execute(t,s).then(f=>{this.logger.info({skill:r,success:f.success,...f.success?{}:{error:f.error}},"Skill execution completed"),g(f)},f=>{let h=f instanceof Error?f.message:String(f);this.logger.error({skill:r,error:h},"Skill execution failed"),g({success:!1,error:h})}),m=setTimeout(()=>{if(a)return;let f=o.getIdleMs();if(f>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:f,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),g({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(f/1e3)}s (last state: ${T.state})`});return}let h=o.getSnapshot();this.logger.info({skill:r,idleMs:f,state:h.state,iteration:h.iteration,totalMs:h.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){p();return}let T=o.getIdleMs(),b=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:b.state,iteration:b.iteration,totalMs:b.totalElapsedMs},"Agent went inactive \u2014 aborting"),g({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${b.state})`})):this.logger.debug({skill:r,idleMs:T,state:b.state,iteration:b.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let f=o.getSnapshot();this.logger.error({skill:r,totalMs:f.totalElapsedMs,state:f.state,iteration:f.iteration},"Absolute time limit reached \u2014 force killing agent"),g({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success,...o.success?{}:{error:o.error}},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var wt,Bo=_(()=>{"use strict";wt=class{static{u(this,"ActivityTracker")}state="starting";iteration=0;maxIterations=0;currentTool;lastPingAt;startedAt;history=[];onProgress;constructor(e){this.startedAt=Date.now(),this.lastPingAt=Date.now(),this.onProgress=e}ping(e,t){this.state=e,this.lastPingAt=Date.now(),t?.iteration!==void 0&&(this.iteration=t.iteration),t?.maxIterations!==void 0&&(this.maxIterations=t.maxIterations),this.currentTool=t?.tool,this.history.push({state:e,tool:t?.tool,iteration:this.iteration,timestamp:this.lastPingAt}),this.onProgress&&this.onProgress(this.formatStatus())}getIdleMs(){return Date.now()-this.lastPingAt}getTotalElapsedMs(){return Date.now()-this.startedAt}formatStatus(){let e=this.maxIterations>0?` (${this.iteration}/${this.maxIterations})`:"";switch(this.state){case"starting":return"Sub-agent starting...";case"llm_call":return`Sub-agent thinking...${e}`;case"tool_call":return this.currentTool?`Sub-agent using ${this.currentTool}${e}`:`Sub-agent using tool...${e}`;case"processing":return`Sub-agent processing...${e}`;case"done":return`Sub-agent done${e}`;default:return`Sub-agent working...${e}`}}getSnapshot(){return{state:this.state,iteration:this.iteration,maxIterations:this.maxIterations,lastPingAt:this.lastPingAt,idleMs:this.getIdleMs(),currentTool:this.currentTool,totalElapsedMs:this.getTotalElapsedMs(),history:[...this.history]}}}});import cm from"node:fs";import Ho from"node:path";var en,tc=_(()=>{"use strict";P();en=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Ho.resolve(e),s;try{s=await cm.promises.readdir(t)}catch(o){let i=o instanceof Error?o.message:String(o);return console.warn(`PluginLoader: failed to read directory "${t}": ${i}`),[]}let r=s.filter(o=>o.endsWith(".js")),n=[];for(let o of r){let i=Ho.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let l=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${l}`)}}return n}async loadFromFile(e){let t=Ho.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var lm,dm,Mt,sc=_(()=>{"use strict";P();lm=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,dm=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Mt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!dm.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(lm,"");if(/[a-zA-Z]/.test(n))return{success:!1,error:`Invalid expression: "${r}" contains disallowed identifiers`};try{let i=new Function("Math",`"use strict"; return (${r});`)(Math);return typeof i!="number"||!isFinite(i)?{success:!1,error:`Invalid expression: "${r}" did not produce a finite number`}:{success:!0,data:i,display:`${r} = ${i}`}}catch{return{success:!1,error:`Invalid expression: "${r}"`}}}}});var Ot,rc=_(()=>{"use strict";P();Ot=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var Pt,nc=_(()=>{"use strict";P();Pt=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,l)=>`${l+1}. **${a.title}**
433
433
  ${a.url}
434
434
  ${a.snippet}`).join(`
435
435
 
436
436
  `);return{success:!0,data:{query:s,results:o},display:`Search results for "${s}":
437
437
 
438
- ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let l=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(l);d&&m&&o.push({url:m,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let l=0;l<Math.min(o.length,t);l++)s.push({title:o[l].title,url:o[l].url,snippet:a[l]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var Ut,oc=_(()=>{"use strict";P();Fe();Ut=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let m=this.parseTriggerAt(r,t.timezone);if(!m)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(m.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=m}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(te(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),l=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${l} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),l=parseInt(n[4],10),d=parseInt(n[5],10);return l>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(l,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let g=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||g.setHours(e,t,0,0),g}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let g=i.formatToParts(n),f=parseInt(g.find(V=>V.type==="year").value,10),h=parseInt(g.find(V=>V.type==="month").value,10)-1,T=parseInt(g.find(V=>V.type==="day").value,10),b=new Date(Date.UTC(f,h,T,e,t,0)),A=i.formatToParts(b),C=parseInt(A.find(V=>V.type==="hour").value,10),U=parseInt(A.find(V=>V.type==="minute").value,10),x=(e-C)*60+(t-U);return b=new Date(b.getTime()+x*6e4),b}let a=o,l=i.formatToParts(a),d=parseInt(l.find(g=>g.type==="hour").value,10),m=parseInt(l.find(g=>g.type==="minute").value,10),p=(e-d)*60+(t-m);return a=new Date(a.getTime()+p*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
438
+ ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let l=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(l);d&&m&&o.push({url:m,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let l=0;l<Math.min(o.length,t);l++)s.push({title:o[l].title,url:o[l].url,snippet:a[l]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var Ut,oc=_(()=>{"use strict";P();Be();Ut=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let m=this.parseTriggerAt(r,t.timezone);if(!m)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(m.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=m}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(te(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),l=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${l} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),l=parseInt(n[4],10),d=parseInt(n[5],10);return l>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(l,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let g=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||g.setHours(e,t,0,0),g}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let g=i.formatToParts(n),f=parseInt(g.find(V=>V.type==="year").value,10),h=parseInt(g.find(V=>V.type==="month").value,10)-1,T=parseInt(g.find(V=>V.type==="day").value,10),b=new Date(Date.UTC(f,h,T,e,t,0)),A=i.formatToParts(b),C=parseInt(A.find(V=>V.type==="hour").value,10),U=parseInt(A.find(V=>V.type==="minute").value,10),x=(e-C)*60+(t-U);return b=new Date(b.getTime()+x*6e4),b}let a=o,l=i.formatToParts(a),d=parseInt(l.find(g=>g.type==="hour").value,10),m=parseInt(l.find(g=>g.type==="minute").value,10),p=(e-d)*60+(t-m);return a=new Date(a.getTime()+p*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
439
439
  ${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).join(`
440
- `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var Ft,ic=_(()=>{"use strict";P();Fe();Ft=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",category:"productivity",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(te(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of z(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
440
+ `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var Ft,ic=_(()=>{"use strict";P();Be();Ft=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",category:"productivity",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(te(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of z(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
441
441
  ${n.content.slice(0,100)}${n.content.length>100?"\u2026":""}`).join(`
442
442
  `);return{success:!0,data:s,display:`${s.length} note(s):
443
443
  ${r}`}}searchNotes(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let i of z(t))for(let a of this.noteRepo.search(i,s))r.has(a.id)||(r.add(a.id),n.push(a));if(n.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let o=n.map(i=>`- **${i.title}** (${i.id.slice(0,8)}\u2026)
@@ -449,7 +449,7 @@ Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:l}}catch(r){return{s
449
449
  ${lc(i)}`),a&&d.push(`stderr:
450
450
  ${lc(a)}`),d.length===0&&d.push("(no output)"),d.push(`exit code: ${l}`),{success:l===0,data:{stdout:i,stderr:a,exitCode:l},display:d.join(`
451
451
 
452
- `),...l!==0&&{error:`Command exited with code ${l}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{mm(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var Ht,uc=_(()=>{"use strict";P();Fe();Ht=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",category:"core",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(te(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(te(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r;for(let n of z(t))if(r=this.memoryRepo.recall(n,s),r)break;return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let o of z(t))for(let i of this.memoryRepo.search(o,s))r.has(i.id)||(r.add(i.id),n.push(i));return{success:!0,data:n,display:n.length===0?`No memories matching "${s}".`:`Found ${n.length} memory(ies):
452
+ `),...l!==0&&{error:`Command exited with code ${l}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{mm(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var Ht,uc=_(()=>{"use strict";P();Be();Ht=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",category:"core",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(te(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(te(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r;for(let n of z(t))if(r=this.memoryRepo.recall(n,s),r)break;return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let o of z(t))for(let i of this.memoryRepo.search(o,s))r.has(i.id)||(r.add(i.id),n.push(i));return{success:!0,data:n,display:n.length===0?`No memories matching "${s}".`:`Found ${n.length} memory(ies):
453
453
  ${n.map(o=>`- ${o.key}: "${o.value}"`).join(`
454
454
  `)}`}}listMemories(e,t){let s=e.category,r=new Set,n=[];for(let i of z(t)){let a=s&&typeof s=="string"?this.memoryRepo.listByCategory(i,s):this.memoryRepo.listAll(i);for(let l of a)r.has(l.id)||(r.add(l.id),n.push(l))}let o=s?`in category "${s}"`:"total";return{success:!0,data:n,display:n.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${n.length} memory(ies) ${o}:
455
455
  ${n.map(i=>`- [${i.category}] ${i.key}: "${i.value}"`).join(`
@@ -460,14 +460,14 @@ ${n.map(o=>`- ${o.key}: "${o.value}" (score: ${o.score.toFixed(2)})`).join(`
460
460
  When tool results contain "[Data stored as result_N]", use code_sandbox with action "run_with_data" and data="result_N" to process the data. The data will be injected as INPUT_DATA (parsed array/object). Never hardcode data in code.
461
461
  Available JS libraries in code_sandbox (no install needed): exceljs, pdfkit, pdf-parse.`,g=s;r&&typeof r=="string"&&(g=`${s}
462
462
 
463
- Additional context: ${r}`);let f=[{role:"user",content:g}];try{let h=0,T=0,b=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let A=await this.llm.complete({messages:f,system:p,tools:l.length>0?l:void 0,maxTokens:8192,tier:"strong"});if(T+=A.usage.inputTokens,b+=A.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!A.toolCalls||A.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:A.content,iterations:h,usage:{inputTokens:T,outputTokens:b}},display:A.content};h++;let C=[];A.content&&C.push({type:"text",text:A.content});for(let x of A.toolCalls)C.push({type:"tool_use",id:x.id,name:x.name,input:x.input});f.push({role:"assistant",content:C});let U=[];for(let x of A.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:x.name});let V=x.input;if(x.name==="code_sandbox"&&x.input.data){let ce=String(x.input.data);d.has(ce)&&(V={...x.input,data:d.get(ce)},V.action==="run"&&(V.action="run_with_data"))}let be=await this.executeSubAgentTool({...x,input:V},t),he=be.content;if(!be.isError&&he.length>500){let ce=`result_${++m}`;d.set(ce,he),he+=`
463
+ Additional context: ${r}`);let f=[{role:"user",content:g}];try{let h=0,T=0,b=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let A=await this.llm.complete({messages:f,system:p,tools:l.length>0?l:void 0,maxTokens:8192,tier:"strong"});if(T+=A.usage.inputTokens,b+=A.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!A.toolCalls||A.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:A.content,iterations:h,usage:{inputTokens:T,outputTokens:b}},display:A.content};h++;let C=[];A.content&&C.push({type:"text",text:A.content});for(let x of A.toolCalls)C.push({type:"tool_use",id:x.id,name:x.name,input:x.input});f.push({role:"assistant",content:C});let U=[];for(let x of A.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:x.name});let V=x.input;if(x.name==="code_sandbox"&&x.input.data){let le=String(x.input.data);d.has(le)&&(V={...x.input,data:d.get(le)},V.action==="run"&&(V.action="run_with_data"))}let Te=await this.executeSubAgentTool({...x,input:V},t),he=Te.content;if(!Te.isError&&he.length>500){let le=`result_${++m}`,re=Te.rawData!=null?JSON.stringify(Te.rawData):he;d.set(le,re),he+=`
464
464
 
465
- [Data stored as "${ce}" \u2014 use code_sandbox action "run_with_data" with data="${ce}" to process this data. Do NOT copy data into code.]`}U.push({type:"tool_result",tool_use_id:x.id,content:he,is_error:be.isError})}f.push({role:"user",content:U})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}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}}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}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var Ge,tn=_(()=>{"use strict";Ge=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 pc={};oe(pc,{MicrosoftGraphEmailProvider:()=>sn});var sn,qo=_(()=>{"use strict";tn();sn=class extends Ge{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","")),l=(a.value??[]).map(d=>this.mapMessage(d));o.push(...l),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 g=>{let f={id:g.id,from:g.from,subject:g.subject,date:g.date.toISOString().split("T")[0],preview:(g.preview??"").slice(0,200)};try{let h=await this.readMessage(g.id),T=this.extractAmount(h.body);T&&(f.amount=T.amount,f.currency=T.currency)}catch{}return f}));for(let g of p)g.status==="fulfilled"&&a.push(g.value)}else for(let l of o)a.push({id:l.id,from:l.from,subject:l.subject,date:l.date.toISOString().split("T")[0],preview:(l.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",g=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${g}`)}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 l=await this.graphRequest(`/me/messages?${a}`),d=(l.value??[]).map(p=>this.mapMessage(p)),m=l["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),g=(p.value??[]).map(f=>this.mapMessage(f));d.push(...g),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,`
465
+ [Data stored as "${le}" \u2014 use code_sandbox action "run_with_data" with data="${le}" to process this data. Do NOT copy data into code.]`}U.push({type:"tool_result",tool_use_id:x.id,content:he,is_error:Te.isError})}f.push({role:"user",content:U})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}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 Ve,tn=_(()=>{"use strict";Ve=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 pc={};ie(pc,{MicrosoftGraphEmailProvider:()=>sn});var sn,qo=_(()=>{"use strict";tn();sn=class extends Ve{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","")),l=(a.value??[]).map(d=>this.mapMessage(d));o.push(...l),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 g=>{let f={id:g.id,from:g.from,subject:g.subject,date:g.date.toISOString().split("T")[0],preview:(g.preview??"").slice(0,200)};try{let h=await this.readMessage(g.id),T=this.extractAmount(h.body);T&&(f.amount=T.amount,f.currency=T.currency)}catch{}return f}));for(let g of p)g.status==="fulfilled"&&a.push(g.value)}else for(let l of o)a.push({id:l.id,from:l.from,subject:l.subject,date:l.date.toISOString().split("T")[0],preview:(l.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",g=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${g}`)}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 l=await this.graphRequest(`/me/messages?${a}`),d=(l.value??[]).map(p=>this.mapMessage(p)),m=l["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),g=(p.value??[]).map(f=>this.mapMessage(f));d.push(...g),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,`
466
466
  `).replace(/<\/p>/gi,`
467
467
 
468
468
  `).replace(/<[^>]+>/g,"").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\n{3,}/g,`
469
469
 
470
- `).trim()}}});var hc={};oe(hc,{StandardEmailProvider:()=>rn});var rn,zo=_(()=>{"use strict";tn();rn=class extends Ge{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??""),l=n.source?.toString()??"",d=this.extractTextBody(l),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),l=[];for await(let d of r.fetch(a,{envelope:!0,flags:!0}))l.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 l.reverse(),l}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(g=>g.name?`${g.name} <${g.address}>`:g.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(`
470
+ `).trim()}}});var hc={};ie(hc,{StandardEmailProvider:()=>rn});var rn,zo=_(()=>{"use strict";tn();rn=class extends Ve{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??""),l=n.source?.toString()??"",d=this.extractTextBody(l),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),l=[];for await(let d of r.fetch(a,{envelope:!0,flags:!0}))l.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 l.reverse(),l}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(g=>g.name?`${g.name} <${g.address}>`:g.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(`
471
471
 
472
472
  `));let r=s.match(/boundary="?([^"\s;]+)"?/i)??e.match(/boundary="?([^"\s;]+)"?/i);if(!r)return t.slice(1).join(`
473
473
 
@@ -477,7 +477,7 @@ Additional context: ${r}`);let f=[{role:"user",content:g}];try{let h=0,T=0,b=0;f
477
477
  \r
478
478
  `);if(d>=0)return this.decodeBody(i.slice(d+4))}}return this.decodeBody(t.slice(1).join(`
479
479
 
480
- `).slice(0,5e3))}decodeBody(e){return e.replace(/=\r?\n/g,"").replace(/=([0-9A-Fa-f]{2})/g,(t,s)=>String.fromCharCode(parseInt(s,16))).trim()}}});async function rr(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(qo(),pc)),r=new s(c.microsoft);return await r.initialize(),r}if(!c.imap||!c.smtp||!c.auth)throw new Error("IMAP/SMTP email config missing (imap, smtp, auth required)");let{StandardEmailProvider:e}=await Promise.resolve().then(()=>(zo(),hc)),t=new e(c);return await t.initialize(),t}var fc=_(()=>{"use strict";u(rr,"createEmailProvider")});var Ze,gc=_(()=>{"use strict";tn();fc();zo();qo();P();Ze=class extends I{static{u(this,"EmailSkill")}metadata;providers;accountNames;defaultAccount;multiAccount;constructor(e){super(),e instanceof Map?this.providers=e:e?this.providers=new Map([["default",e]]):this.providers=new Map,this.accountNames=[...this.providers.keys()],this.defaultAccount=this.accountNames[0]??"default",this.multiAccount=this.providers.size>1;let t=this.multiAccount?{account:{type:"string",enum:this.accountNames,description:`Email account to use (available: ${this.accountNames.join(", ")})`}}:{},s=this.multiAccount?`Access the user's email accounts (${this.accountNames.join(", ")}): check inbox, read messages, search emails, send new emails, create drafts, list folders, read from specific folders, reply to messages, forward messages, or download attachments.`:`Access the user's email: check inbox, read messages, search emails, send new emails, create drafts, list folders, read from specific folders, reply to messages, forward messages, or download attachments. Use "draft" instead of "send" when the user asks to prepare/draft an email without sending it.`;this.metadata={name:"email",category:"productivity",description:s,riskLevel:"write",version:"3.1.0",timeoutMs:3e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send","draft","folders","folder","reply","forward","attachment","extract"],description:'The email action to perform. Use "extract" for bulk invoice/receipt extraction from large mailboxes \u2014 it searches with pagination, reads bodies server-side, and returns structured data with amounts.'},...t,count:{type:"number",description:"Number of emails to fetch (for inbox/search/folder, default: 10)"},messageId:{type:"string",description:"Message ID to read or reply to"},query:{type:"string",description:"Search query (for search action)"},to:{type:"string",description:"Recipient email address (for send action)"},subject:{type:"string",description:"Email subject (for send action)"},body:{type:"string",description:"Email body text (for send/reply action)"},cc:{type:"string",description:"CC recipients, comma-separated (for send action)"},folder:{type:"string",description:"Folder name (for folder action)"},attachmentId:{type:"string",description:"Attachment ID or filename (for attachment action)"},save:{type:"string",description:"Directory path to save the attachment to disk instead of reading its content (for attachment action)"},isHtml:{type:"boolean",description:"Whether the body is HTML (for send action)"},maxResults:{type:"number",description:"Maximum number of results for extract action (default: 200, max: 1000)"},fields:{type:"array",items:{type:"string"},description:'Fields to extract (for extract action). Available: "from", "subject", "date", "amount". Include "amount" to read email bodies and extract monetary amounts.'},dateFrom:{type:"string",description:'Start date filter for extract action (YYYY-MM-DD format, e.g. "2026-01-01")'},dateTo:{type:"string",description:'End date filter for extract action (YYYY-MM-DD format, e.g. "2026-12-31")'}},required:["action"]}}}async execute(e,t){if(this.providers.size===0)return{success:!1,error:"Email is not configured. Run `alfred setup` to configure email access."};let s=e.action;try{switch(s){case"inbox":return await this.handleInbox(e);case"read":return await this.handleRead(e);case"search":return await this.handleSearch(e);case"send":return await this.handleSend(e);case"draft":return await this.handleDraft(e);case"folders":return await this.handleFolders(e);case"folder":return await this.handleFolder(e);case"reply":return await this.handleReply(e);case"forward":return await this.handleForward(e);case"attachment":return await this.handleAttachment(e);case"extract":return await this.handleExtract(e);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send, draft, folders, folder, reply, forward, attachment`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}resolveProvider(e){let t=e.account??this.defaultAccount,s=this.providers.get(t);return s?{provider:s,account:t}:{success:!1,error:`Unknown email account "${t}". Available: ${this.accountNames.join(", ")}`}}encodeId(e,t){return this.multiAccount?`${e}::${t}`:t}decodeId(e){if(this.multiAccount){let t=e.indexOf("::");if(t>=0)return{account:e.slice(0,t),rawId:e.slice(t+2)}}return{account:this.defaultAccount,rawId:e}}accountLabel(e,t){return this.multiAccount?`[${e}] ${t}`:t}async handleInbox(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,n=Math.min(Math.max(1,e.count??10),50),o=await s.fetchInbox(n);if(o.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(r,"Inbox is empty.")};let i=o.filter(l=>!l.read).length,a=o.map((l,d)=>{let m=l.read?"":" [UNREAD]",p=l.hasAttachments?" [ATT]":"";return`${d+1}. [${this.encodeId(r,l.id)}]${m}${p} ${l.subject}
480
+ `).slice(0,5e3))}decodeBody(e){return e.replace(/=\r?\n/g,"").replace(/=([0-9A-Fa-f]{2})/g,(t,s)=>String.fromCharCode(parseInt(s,16))).trim()}}});async function rr(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(qo(),pc)),r=new s(c.microsoft);return await r.initialize(),r}if(!c.imap||!c.smtp||!c.auth)throw new Error("IMAP/SMTP email config missing (imap, smtp, auth required)");let{StandardEmailProvider:e}=await Promise.resolve().then(()=>(zo(),hc)),t=new e(c);return await t.initialize(),t}var fc=_(()=>{"use strict";u(rr,"createEmailProvider")});var Qe,gc=_(()=>{"use strict";tn();fc();zo();qo();P();Qe=class extends I{static{u(this,"EmailSkill")}metadata;providers;accountNames;defaultAccount;multiAccount;constructor(e){super(),e instanceof Map?this.providers=e:e?this.providers=new Map([["default",e]]):this.providers=new Map,this.accountNames=[...this.providers.keys()],this.defaultAccount=this.accountNames[0]??"default",this.multiAccount=this.providers.size>1;let t=this.multiAccount?{account:{type:"string",enum:this.accountNames,description:`Email account to use (available: ${this.accountNames.join(", ")})`}}:{},s=this.multiAccount?`Access the user's email accounts (${this.accountNames.join(", ")}): check inbox, read messages, search emails, send new emails, create drafts, list folders, read from specific folders, reply to messages, forward messages, or download attachments.`:`Access the user's email: check inbox, read messages, search emails, send new emails, create drafts, list folders, read from specific folders, reply to messages, forward messages, or download attachments. Use "draft" instead of "send" when the user asks to prepare/draft an email without sending it.`;this.metadata={name:"email",category:"productivity",description:s,riskLevel:"write",version:"3.1.0",timeoutMs:3e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send","draft","folders","folder","reply","forward","attachment","extract"],description:'The email action to perform. Use "extract" for bulk invoice/receipt extraction from large mailboxes \u2014 it searches with pagination, reads bodies server-side, and returns structured data with amounts.'},...t,count:{type:"number",description:"Number of emails to fetch (for inbox/search/folder, default: 10)"},messageId:{type:"string",description:"Message ID to read or reply to"},query:{type:"string",description:"Search query (for search action)"},to:{type:"string",description:"Recipient email address (for send action)"},subject:{type:"string",description:"Email subject (for send action)"},body:{type:"string",description:"Email body text (for send/reply action)"},cc:{type:"string",description:"CC recipients, comma-separated (for send action)"},folder:{type:"string",description:"Folder name (for folder action)"},attachmentId:{type:"string",description:"Attachment ID or filename (for attachment action)"},save:{type:"string",description:"Directory path to save the attachment to disk instead of reading its content (for attachment action)"},isHtml:{type:"boolean",description:"Whether the body is HTML (for send action)"},maxResults:{type:"number",description:"Maximum number of results for extract action (default: 200, max: 1000)"},fields:{type:"array",items:{type:"string"},description:'Fields to extract (for extract action). Available: "from", "subject", "date", "amount". Include "amount" to read email bodies and extract monetary amounts.'},dateFrom:{type:"string",description:'Start date filter for extract action (YYYY-MM-DD format, e.g. "2026-01-01")'},dateTo:{type:"string",description:'End date filter for extract action (YYYY-MM-DD format, e.g. "2026-12-31")'}},required:["action"]}}}async execute(e,t){if(this.providers.size===0)return{success:!1,error:"Email is not configured. Run `alfred setup` to configure email access."};let s=e.action;try{switch(s){case"inbox":return await this.handleInbox(e);case"read":return await this.handleRead(e);case"search":return await this.handleSearch(e);case"send":return await this.handleSend(e);case"draft":return await this.handleDraft(e);case"folders":return await this.handleFolders(e);case"folder":return await this.handleFolder(e);case"reply":return await this.handleReply(e);case"forward":return await this.handleForward(e);case"attachment":return await this.handleAttachment(e);case"extract":return await this.handleExtract(e);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send, draft, folders, folder, reply, forward, attachment`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}resolveProvider(e){let t=e.account??this.defaultAccount,s=this.providers.get(t);return s?{provider:s,account:t}:{success:!1,error:`Unknown email account "${t}". Available: ${this.accountNames.join(", ")}`}}encodeId(e,t){return this.multiAccount?`${e}::${t}`:t}decodeId(e){if(this.multiAccount){let t=e.indexOf("::");if(t>=0)return{account:e.slice(0,t),rawId:e.slice(t+2)}}return{account:this.defaultAccount,rawId:e}}accountLabel(e,t){return this.multiAccount?`[${e}] ${t}`:t}async handleInbox(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,n=Math.min(Math.max(1,e.count??10),50),o=await s.fetchInbox(n);if(o.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(r,"Inbox is empty.")};let i=o.filter(l=>!l.read).length,a=o.map((l,d)=>{let m=l.read?"":" [UNREAD]",p=l.hasAttachments?" [ATT]":"";return`${d+1}. [${this.encodeId(r,l.id)}]${m}${p} ${l.subject}
481
481
  From: ${l.from}
482
482
  Date: ${l.date.toISOString()}`}).join(`
483
483
 
@@ -526,12 +526,12 @@ ${m.join(`
526
526
 
527
527
  ${f.slice(0,5e3)}`}:{success:!0,data:h,display:`HTTP ${l.status} ${l.statusText}
528
528
 
529
- ${f.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import X from"node:fs";import Qe from"node:path";var Wo,Tc,ym,Wt,_c=_(()=>{"use strict";P();Wo=5e5,Tc=5e7,ym={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".rtf":"application/rtf",".epub":"application/epub+zip",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".tsv":"text/tab-separated-values",".html":"text/html",".htm":"text/html",".xml":"application/xml",".yaml":"application/yaml",".yml":"application/yaml",".toml":"application/toml",".ini":"text/plain",".cfg":"text/plain",".log":"text/plain",".json":"application/json",".js":"application/javascript",".ts":"application/typescript",".py":"text/x-python",".sh":"application/x-sh",".sql":"application/sql",".css":"text/css",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".flac":"audio/flac",".aac":"audio/aac",".m4a":"audio/mp4",".mp4":"video/mp4",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".mov":"video/quicktime",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2"},Wt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",category:"files",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. The content is likely too large to include in a tool call. Use the code_sandbox skill instead \u2014 write COMPACT data-driven code: define your data as arrays/objects, then build HTML/text programmatically with .map()/.join(). Example: const data = [{h:8,p:5.2},{h:9,p:4.1}]; const rows = data.map(r => \`<tr><td>\${r.h}</td><td>\${r.p}</td></tr>\`).join(''); fs.writeFileSync('output.html', \`<table>\${rows}</table>\`); \u2014 the sandbox collects output files automatically. Do NOT embed large string literals.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(X.existsSync(i)&&X.lstatSync(i).isSymbolicLink()){let l=X.realpathSync(i);if(this.checkBlocked(l))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return Qe.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=Qe.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=X.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Wo){let r=X.readFileSync(e,"utf-8").slice(0,Wo);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${Wo}):
529
+ ${f.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import X from"node:fs";import et from"node:path";var Wo,Tc,ym,Wt,_c=_(()=>{"use strict";P();Wo=5e5,Tc=5e7,ym={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".rtf":"application/rtf",".epub":"application/epub+zip",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".tsv":"text/tab-separated-values",".html":"text/html",".htm":"text/html",".xml":"application/xml",".yaml":"application/yaml",".yml":"application/yaml",".toml":"application/toml",".ini":"text/plain",".cfg":"text/plain",".log":"text/plain",".json":"application/json",".js":"application/javascript",".ts":"application/typescript",".py":"text/x-python",".sh":"application/x-sh",".sql":"application/sql",".css":"text/css",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".flac":"audio/flac",".aac":"audio/aac",".m4a":"audio/mp4",".mp4":"video/mp4",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".mov":"video/quicktime",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2"},Wt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",category:"files",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. The content is likely too large to include in a tool call. Use the code_sandbox skill instead \u2014 write COMPACT data-driven code: define your data as arrays/objects, then build HTML/text programmatically with .map()/.join(). Example: const data = [{h:8,p:5.2},{h:9,p:4.1}]; const rows = data.map(r => \`<tr><td>\${r.h}</td><td>\${r.p}</td></tr>\`).join(''); fs.writeFileSync('output.html', \`<table>\${rows}</table>\`); \u2014 the sandbox collects output files automatically. Do NOT embed large string literals.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(X.existsSync(i)&&X.lstatSync(i).isSymbolicLink()){let l=X.realpathSync(i);if(this.checkBlocked(l))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return et.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=et.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=X.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Wo){let r=X.readFileSync(e,"utf-8").slice(0,Wo);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${Wo}):
530
530
 
531
- ${r}`}}let s=X.readFileSync(e,"utf-8");return{success:!0,data:{path:e,size:t.size,content:s},display:s}}catch(t){return{success:!1,error:`Cannot read "${e}": ${t.message}`}}}writeFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for write action'};try{let s=Qe.dirname(e);return X.mkdirSync(s,{recursive:!0}),X.writeFileSync(e,t,"utf-8"),{success:!0,data:{path:e,bytes:Buffer.byteLength(t)},display:`Written ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}appendFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for append action'};try{return X.appendFileSync(e,t,"utf-8"),{success:!0,data:{path:e,appendedBytes:Buffer.byteLength(t)},display:`Appended ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot append to "${e}": ${s.message}`}}}listDir(e){try{let s=X.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
531
+ ${r}`}}let s=X.readFileSync(e,"utf-8");return{success:!0,data:{path:e,size:t.size,content:s},display:s}}catch(t){return{success:!1,error:`Cannot read "${e}": ${t.message}`}}}writeFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for write action'};try{let s=et.dirname(e);return X.mkdirSync(s,{recursive:!0}),X.writeFileSync(e,t,"utf-8"),{success:!0,data:{path:e,bytes:Buffer.byteLength(t)},display:`Written ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}appendFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for append action'};try{return X.appendFileSync(e,t,"utf-8"),{success:!0,data:{path:e,appendedBytes:Buffer.byteLength(t)},display:`Appended ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot append to "${e}": ${s.message}`}}}listDir(e){try{let s=X.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
532
532
  `);return{success:!0,data:{path:e,entries:s},display:r}}catch(t){return{success:!1,error:`Cannot list "${e}": ${t.message}`}}}fileInfo(e){try{let t=X.statSync(e),s={path:e,type:t.isDirectory()?"directory":t.isFile()?"file":"other",size:t.size,created:t.birthtime.toISOString(),modified:t.mtime.toISOString(),permissions:t.mode.toString(8)};return{success:!0,data:s,display:`${s.type}: ${e}
533
533
  Size: ${t.size} bytes
534
- Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=X.existsSync(e);return{success:!0,data:{path:e,exists:t},display:t?`Yes, "${e}" exists`:`No, "${e}" does not exist`}}writeBinaryFile(e,t){if(!t)return{success:!1,error:'Missing "content" (base64-encoded) for write_binary action'};try{let s=Qe.dirname(e);X.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return X.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Qe.dirname(s);return X.mkdirSync(n,{recursive:!0}),X.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return X.copyFileSync(e,s),X.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Qe.dirname(s);return X.mkdirSync(n,{recursive:!0}),X.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!X.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=X.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size===0)return{success:!1,error:`"${e}" is empty (0 bytes) \u2014 cannot send an empty file`};if(t.size>Tc)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Tc})`};let s=X.readFileSync(e),r=Qe.basename(e),n=Qe.extname(e).toLowerCase(),o=ym[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return X.existsSync(e)?X.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(X.unlinkSync(e),{success:!0,data:{path:e},display:`Deleted ${e}`}):{success:!1,error:`"${e}" does not exist`}}catch(t){return{success:!1,error:`Cannot delete "${e}": ${t.message}`}}}}});import{execSync as Gt}from"node:child_process";var Vt,Ec=_(()=>{"use strict";P();Vt=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",category:"media",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=Gt("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Gt("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Gt("xclip -selection clipboard -o 2>/dev/null || xsel --clipboard --output",{encoding:"utf-8",timeout:5e3});break}return!e||e.trim().length===0?{success:!0,data:{content:""},display:"Clipboard is empty."}:{success:!0,data:{content:e},display:e.length>2e3?e.slice(0,2e3)+`
534
+ Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=X.existsSync(e);return{success:!0,data:{path:e,exists:t},display:t?`Yes, "${e}" exists`:`No, "${e}" does not exist`}}writeBinaryFile(e,t){if(!t)return{success:!1,error:'Missing "content" (base64-encoded) for write_binary action'};try{let s=et.dirname(e);X.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return X.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=et.dirname(s);return X.mkdirSync(n,{recursive:!0}),X.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return X.copyFileSync(e,s),X.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=et.dirname(s);return X.mkdirSync(n,{recursive:!0}),X.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!X.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=X.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size===0)return{success:!1,error:`"${e}" is empty (0 bytes) \u2014 cannot send an empty file`};if(t.size>Tc)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Tc})`};let s=X.readFileSync(e),r=et.basename(e),n=et.extname(e).toLowerCase(),o=ym[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return X.existsSync(e)?X.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(X.unlinkSync(e),{success:!0,data:{path:e},display:`Deleted ${e}`}):{success:!1,error:`"${e}" does not exist`}}catch(t){return{success:!1,error:`Cannot delete "${e}": ${t.message}`}}}}});import{execSync as Gt}from"node:child_process";var Vt,Ec=_(()=>{"use strict";P();Vt=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",category:"media",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=Gt("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Gt("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Gt("xclip -selection clipboard -o 2>/dev/null || xsel --clipboard --output",{encoding:"utf-8",timeout:5e3});break}return!e||e.trim().length===0?{success:!0,data:{content:""},display:"Clipboard is empty."}:{success:!0,data:{content:e},display:e.length>2e3?e.slice(0,2e3)+`
535
535
 
536
536
  [... truncated]`:e}}catch(e){return{success:!1,error:`Failed to read clipboard: ${e.message}`}}}writeClipboard(e){if(!e||typeof e!="string")return{success:!1,error:'Missing "text" for write action'};try{switch(process.platform){case"darwin":Gt("pbcopy",{input:e,timeout:5e3});break;case"win32":Gt('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Gt("xclip -selection clipboard 2>/dev/null || xsel --clipboard --input",{input:e,timeout:5e3});break}return{success:!0,data:{copiedLength:e.length},display:`Copied ${e.length} characters to clipboard.`}}catch(t){return{success:!1,error:`Failed to write clipboard: ${t.message}`}}}}});import{execSync as nr}from"node:child_process";import bc from"node:path";import wm from"node:os";var Kt,$c=_(()=>{"use strict";P();Kt=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",category:"media",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=bc.join(wm.homedir(),"Desktop"),n=e.path||bc.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":nr(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":nr(`powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height); $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size); $bitmap.Save('${n.replace(/'/g,"''")}'); $graphics.Dispose(); $bitmap.Dispose()"`,{timeout:1e4});break;default:try{nr(`scrot "${n}"`,{timeout:1e4})}catch{try{nr(`import -window root "${n}"`,{timeout:1e4})}catch{nr(`gnome-screenshot -f "${n}"`,{timeout:1e4})}}break}return{success:!0,data:{path:n},display:`Screenshot saved to ${n}`}}catch(o){return{success:!1,error:`Screenshot failed: ${o.message}`}}}}});import Tm from"node:path";import _m from"node:os";var kc,Xt,vc=_(()=>{"use strict";P();kc=5e4,Xt=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",category:"media",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
537
537
  Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.openPage(r,e);case"screenshot":return this.screenshotPage(r,e);case"click":return this.clickElement(e);case"type":return this.typeText(e);case"evaluate":return this.evaluateScript(e);default:return{success:!1,error:`Unknown action "${s}". Valid: open, screenshot, click, type, evaluate, close`}}}async loadPuppeteer(){try{let e=await Function('return import("puppeteer")')();return this.resolvePuppeteerModule(e)}catch{try{let e=await Function('return import("puppeteer-core")')();return this.resolvePuppeteerModule(e)}catch{return null}}}resolvePuppeteerModule(e){let t=e;return typeof t.launch=="function"?t:t.default}async ensureBrowser(e){return this.browser&&this.browser.connected?this.browser:(this.browser=await e.launch({headless:!0,args:["--no-sandbox","--disable-setuid-sandbox","--disable-dev-shm-usage"]}),this.browser)}async ensurePage(e){let t=await this.ensureBrowser(e);return this.page||(this.page=await t.newPage(),await this.page.setViewport({width:1280,height:900})),this.page}async openPage(e,t){let s=t.url;if(!s)return{success:!1,error:'Missing "url" for open action'};let r=this.validateUrl(s);if(r)return{success:!1,error:r};try{let n=await this.ensurePage(e);await n.goto(s,{waitUntil:"networkidle2",timeout:3e4});let o=await n.title(),i=await n.evaluate(`
@@ -545,9 +545,9 @@ Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.op
545
545
 
546
546
  `).trim();return{success:!0,data:{url:n.url(),title:o,length:i.length},display:`**${o}** (${n.url()})
547
547
 
548
- ${l}`}}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||Tm.join(_m.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 Yt,Sc=_(()=>{"use strict";P();Fe();Yt=class extends I{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=te(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:
548
+ ${l}`}}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||Tm.join(_m.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 Yt,Sc=_(()=>{"use strict";P();Be();Yt=class extends I{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=te(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:
549
549
  ${s.map(r=>`- ${r}`).join(`
550
- `)}`:"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 De,or=_(()=>{"use strict";De=class{static{u(this,"CalendarProvider")}timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}});var Ac={};oe(Ac,{CalDAVProvider:()=>nn});var nn,Go=_(()=>{"use strict";or();nn=class extends De{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},l=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:l}}),{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(`
550
+ `)}`:"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 Le,or=_(()=>{"use strict";Le=class{static{u(this,"CalendarProvider")}timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}});var Ac={};ie(Ac,{CalDAVProvider:()=>nn});var nn,Go=_(()=>{"use strict";or();nn=class extends Le{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},l=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:l}}),{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(`
551
551
  `).map(p=>p.trim()),r=u(p=>s.find(g=>g.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"),l=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:l||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
552
552
  VERSION:2.0\r
553
553
  PRODID:-//Alfred//EN\r
@@ -563,11 +563,11 @@ BEGIN:VEVENT\r
563
563
  `),r+=`DTSTAMP:${s(new Date)}\r
564
564
  `,r+=`END:VEVENT\r
565
565
  END:VCALENDAR\r
566
- `,r}}});var Ic={};oe(Ic,{GoogleCalendarProvider:()=>on});var on,Vo=_(()=>{"use strict";or();on=class extends De{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 xc={};oe(xc,{MicrosoftCalendarProvider:()=>an});var an,Ko=_(()=>{"use strict";or();an=class extends De{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=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.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.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:new Date(e.start?.dateTime),end:new Date(e.end?.dateTime),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}}});async function ir(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Go(),Ac)),t=new e(c.caldav);return await t.initialize(),t}case"google":{if(!c.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(Vo(),Ic)),t=new e(c.google);return await t.initialize(),t}case"microsoft":{if(!c.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(Ko(),xc)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var Rc=_(()=>{"use strict";u(ir,"createCalendarProvider")});var Tt,Cc=_(()=>{"use strict";P();Tt=class extends I{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"},end:{type:"string",description:"End date/time in ISO 8601 format"},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(`
566
+ `,r}}});var Ic={};ie(Ic,{GoogleCalendarProvider:()=>on});var on,Vo=_(()=>{"use strict";or();on=class extends Le{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 xc={};ie(xc,{MicrosoftCalendarProvider:()=>an});var an,Ko=_(()=>{"use strict";or();an=class extends Le{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=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.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.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:new Date(e.start?.dateTime),end:new Date(e.end?.dateTime),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}}});async function ir(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Go(),Ac)),t=new e(c.caldav);return await t.initialize(),t}case"google":{if(!c.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(Vo(),Ic)),t=new e(c.google);return await t.initialize(),t}case"microsoft":{if(!c.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(Ko(),xc)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var Rc=_(()=>{"use strict";u(ir,"createCalendarProvider")});var Tt,Cc=_(()=>{"use strict";P();Tt=class extends I{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"},end:{type:"string",description:"End date/time in ISO 8601 format"},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(`
567
567
  `);return{success:!0,data:r,display:`${r.length} event(s):
568
568
  ${n}`}}catch(r){return{success:!1,error:`Failed to list events: ${r instanceof Error?r.message:String(r)}`}}}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:new Date(s),end:new Date(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?new Date(e.start):void 0,end:e.end?new Date(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):
569
569
  ${r.conflicts.map(o=>this.formatEvent(o)).join(`
570
- `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}},s=e.location?` @ ${e.location}`:"",r=e.id?` [id:${e.id}]`:"";if(e.allDay)return`- All day: ${e.title}${s}${r}`;let n=e.start.toLocaleTimeString("en-GB",t),o=e.end.toLocaleTimeString("en-GB",t);return`- ${n}-${o}: ${e.title}${s}${r}`}}});var Nc=_(()=>{"use strict";or();Go();Vo();Ko();Rc();Cc()});var Jt,Lc=_(()=>{"use strict";P();Jt=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",category:"identity",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
570
+ `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}},s=e.location?` @ ${e.location}`:"",r=e.id?` [id:${e.id}]`:"";if(e.allDay)return`- All day: ${e.title}${s}${r}`;let n=e.start.toLocaleTimeString("en-GB",t),o=e.end.toLocaleTimeString("en-GB",t);return`- ${n}-${o}: ${e.title}${s}${r}`}}});var Nc=_(()=>{"use strict";or();Go();Vo();Ko();Rc();Cc()});var Jt,Dc=_(()=>{"use strict";P();Jt=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",category:"identity",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
571
571
 
572
572
  Enter this code on your other platform within 10 minutes using:
573
573
  "Link my account with code ${r.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.resolveInternalId(t),n=this.checkConfirmRateLimit(r);if(n)return{success:!1,error:n};let o=this.linkTokens.findByCode(s.trim());if(!o)return this.recordFailedConfirm(r),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};let i=o.userId;if(i===r)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let a=this.users.getMasterUserId(i),l=this.users.getMasterUserId(r),d;if(a!==i?d=a:l!==r?d=l:d=i,a!==i&&l!==r&&a!==l){let g=this.users.getLinkedUsers(l);for(let f of g)this.users.setMasterUser(f.id,d)}i!==d&&this.users.setMasterUser(i,d),r!==d&&this.users.setMasterUser(r,d),this.linkTokens.consume(o.id);let m=this.users.findById(i),p=o.platform;return{success:!0,data:{masterUserId:d,linkedPlatform:p},display:`Account linked successfully! Your ${p} account (${m?.displayName??m?.username??"unknown"}) is now linked to this ${t.platform} account.
@@ -575,12 +575,12 @@ Enter this code on your other platform within 10 minutes using:
575
575
  Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e,t){let s=e.platform,r=e.chat_id,n=e.message;if(!s)return{success:!1,error:'Missing required field "platform"'};if(!n)return{success:!1,error:'Missing required field "message"'};let o=this.adapters.get(s);if(!o)return{success:!1,error:`Platform "${s}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};if(!r||!/^[!0-9]/.test(r)){let i=this.resolveInternalId(t),a=this.users.getMasterUserId(i),d=this.users.getLinkedUsers(a).find(m=>m.platform===s);if(d&&this.findConversation){let m=this.findConversation(s,d.id);m&&(r=m.chatId)}!r&&d&&(r=d.platformUserId)}if(!r)return{success:!1,error:"Could not resolve chat_id for target platform. No linked account or conversation found."};try{return{success:!0,data:{messageId:await o.sendMessage(r,n),platform:s,chatId:r},display:`Message sent to ${s}.`}}catch(i){return{success:!1,error:`Failed to send message: ${i instanceof Error?i.message:String(i)}`}}}async listIdentities(e){let t=this.resolveInternalId(e),s=this.users.getMasterUserId(t),r=this.users.getLinkedUsers(s);if(r.length<=1)return{success:!0,data:{identities:r},display:`No linked accounts found. To link another platform, use:
576
576
  "Start linking my account" on the platform you want to link from, then enter the code on the other platform.`};let n=r.map(o=>{let i=o.id===t?" (current)":"",a=o.displayName??o.username??o.platformUserId;return`- **${o.platform}**: ${a}${i}`});return{success:!0,data:{identities:r.map(o=>({platform:o.platform,username:o.username,displayName:o.displayName}))},display:`Linked accounts:
577
577
  ${n.join(`
578
- `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),n=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(n).find(a=>a.platform===s&&a.id!==r);return i?(this.users.setMasterUser(i.id,i.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:i.id},display:`Unlinked ${s} account (${i.displayName??i.username??i.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var Zt,Dc=_(()=>{"use strict";P();Fe();Zt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",category:"automation",description:'Schedule, list, or cancel background tasks that run a SINGLE skill call asynchronously. Use "schedule" to queue ONE skill execution in the background (user will be notified when done). NOT for multi-step tasks \u2014 use "delegate" instead when a task needs multiple tool calls (e.g. search + read + process + generate). Use "list" to see active/recent tasks. Use "cancel" to stop a pending or running task.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["schedule","list","cancel"],description:"The background task action to perform"},description:{type:"string",description:"Human-readable description of what the task does (for schedule)"},skill_name:{type:"string",description:"The skill to run in the background (for schedule)"},skill_input:{type:"object",description:"Input to pass to the skill (for schedule)"},task_id:{type:"string",description:"Task ID (for cancel)"}},required:["action"]}};constructor(e){super(),this.taskRepo=e}getAllTasks(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.taskRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"schedule":return this.scheduleTask(e,t);case"list":return this.listTasks(t);case"cancel":return this.cancelTask(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: schedule, list, cancel`}}}scheduleTask(e,t){let s=e.description,r=e.skill_name,n=e.skill_input;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "description" for schedule action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "skill_name" for schedule action'};let o=this.taskRepo.create(te(t),t.platform,t.chatId,s,r,JSON.stringify(n??{}));return{success:!0,data:{taskId:o.id,description:s,skillName:r,status:o.status},display:`Background task scheduled (${o.id}): "${s}" using skill "${r}". You'll be notified when it completes.`}}listTasks(e){let t=this.getAllTasks(e);if(t.length===0)return{success:!0,data:[],display:"No active or recent background tasks."};let s={pending:"\u23F3",running:"\u25B6\uFE0F",completed:"\u2705",failed:"\u274C"},r=t.map(n=>`- ${s[n.status]??"?"} ${n.id}: "${n.description}" [${n.status}] (${n.skillName})`);return{success:!0,data:t.map(n=>({taskId:n.id,description:n.description,status:n.status,skillName:n.skillName,createdAt:n.createdAt,completedAt:n.completedAt})),display:`Background tasks:
578
+ `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),n=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(n).find(a=>a.platform===s&&a.id!==r);return i?(this.users.setMasterUser(i.id,i.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:i.id},display:`Unlinked ${s} account (${i.displayName??i.username??i.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var Zt,Lc=_(()=>{"use strict";P();Be();Zt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",category:"automation",description:'Schedule, list, or cancel background tasks that run a SINGLE skill call asynchronously. Use "schedule" to queue ONE skill execution in the background (user will be notified when done). NOT for multi-step tasks \u2014 use "delegate" instead when a task needs multiple tool calls (e.g. search + read + process + generate). Use "list" to see active/recent tasks. Use "cancel" to stop a pending or running task.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["schedule","list","cancel"],description:"The background task action to perform"},description:{type:"string",description:"Human-readable description of what the task does (for schedule)"},skill_name:{type:"string",description:"The skill to run in the background (for schedule)"},skill_input:{type:"object",description:"Input to pass to the skill (for schedule)"},task_id:{type:"string",description:"Task ID (for cancel)"}},required:["action"]}};constructor(e){super(),this.taskRepo=e}getAllTasks(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.taskRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"schedule":return this.scheduleTask(e,t);case"list":return this.listTasks(t);case"cancel":return this.cancelTask(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: schedule, list, cancel`}}}scheduleTask(e,t){let s=e.description,r=e.skill_name,n=e.skill_input;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "description" for schedule action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "skill_name" for schedule action'};let o=this.taskRepo.create(te(t),t.platform,t.chatId,s,r,JSON.stringify(n??{}));return{success:!0,data:{taskId:o.id,description:s,skillName:r,status:o.status},display:`Background task scheduled (${o.id}): "${s}" using skill "${r}". You'll be notified when it completes.`}}listTasks(e){let t=this.getAllTasks(e);if(t.length===0)return{success:!0,data:[],display:"No active or recent background tasks."};let s={pending:"\u23F3",running:"\u25B6\uFE0F",completed:"\u2705",failed:"\u274C"},r=t.map(n=>`- ${s[n.status]??"?"} ${n.id}: "${n.description}" [${n.status}] (${n.skillName})`);return{success:!0,data:t.map(n=>({taskId:n.id,description:n.description,status:n.status,skillName:n.skillName,createdAt:n.createdAt,completedAt:n.completedAt})),display:`Background tasks:
579
579
  ${r.join(`
580
- `)}`}}cancelTask(e,t){let s=e.task_id;return!s||typeof s!="string"?{success:!1,error:'Missing required field "task_id" for cancel action'}:this.getAllTasks(t).some(i=>i.id===s)?this.taskRepo.cancel(s)?{success:!0,data:{taskId:s},display:`Background task "${s}" cancelled.`}:{success:!1,error:`Task "${s}" not found or already completed`}:{success:!1,error:`Task "${s}" not found or already completed`}}}});var Qt,Mc=_(()=>{"use strict";P();Fe();Qt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",category:"automation",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time. Use this for time-based tasks (reports, periodic checks, reminders). For condition-based alerts ("notify me WHEN X happens"), use the watch tool instead.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}getAllActions(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,l=e.prompt_template;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "name" for create action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "description" for create action'};if(!n||!["cron","interval","once"].includes(n))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!o||typeof o!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if((!i||typeof i!="string")&&!l)return{success:!1,error:'Missing required field "skill_name" (or "prompt_template") for create action'};if(n==="interval"){let p=parseInt(o,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let p=new Date(o);if(isNaN(p.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(p.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let d=this.actionRepo.create({userId:te(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i??"llm_prompt",skillInput:JSON.stringify(a??{}),promptTemplate:l}),m=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${d.id}): "${s}" \u2014 ${m}, running "${i}"${d.nextRunAt?`. Next run: ${d.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
580
+ `)}`}}cancelTask(e,t){let s=e.task_id;return!s||typeof s!="string"?{success:!1,error:'Missing required field "task_id" for cancel action'}:this.getAllTasks(t).some(i=>i.id===s)?this.taskRepo.cancel(s)?{success:!0,data:{taskId:s},display:`Background task "${s}" cancelled.`}:{success:!1,error:`Task "${s}" not found or already completed`}:{success:!1,error:`Task "${s}" not found or already completed`}}}});var Qt,Mc=_(()=>{"use strict";P();Be();Qt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",category:"automation",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time. Use this for time-based tasks (reports, periodic checks, reminders). For condition-based alerts ("notify me WHEN X happens"), use the watch tool instead.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}getAllActions(e){let t=new Set,s=[];for(let r of z(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,l=e.prompt_template;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "name" for create action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "description" for create action'};if(!n||!["cron","interval","once"].includes(n))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!o||typeof o!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if((!i||typeof i!="string")&&!l)return{success:!1,error:'Missing required field "skill_name" (or "prompt_template") for create action'};if(n==="interval"){let p=parseInt(o,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let p=new Date(o);if(isNaN(p.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(p.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let d=this.actionRepo.create({userId:te(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i??"llm_prompt",skillInput:JSON.stringify(a??{}),promptTemplate:l}),m=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${d.id}): "${s}" \u2014 ${m}, running "${i}"${d.nextRunAt?`. Next run: ${d.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
581
581
  ${s.join(`
582
582
  `)}`}}toggleAction(e,t,s){let r=e.action_id;if(!r||typeof r!="string")return{success:!1,error:`Missing required field "action_id" for ${t?"enable":"disable"} action`};let n=this.actionRepo.findById(r),o=z(s);return!n||!o.includes(n.userId)?{success:!1,error:`Scheduled action "${r}" not found`}:this.actionRepo.setEnabled(r,t)?{success:!0,data:{actionId:r,enabled:t},display:`Scheduled action "${r}" ${t?"enabled":"disabled"}.`}:{success:!1,error:`Scheduled action "${r}" not found`}}deleteAction(e,t){let s=e.action_id;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "action_id" for delete action'};let r=this.actionRepo.findById(s),n=z(t);return!r||!n.includes(r.userId)?{success:!1,error:`Scheduled action "${s}" not found`}:this.actionRepo.delete(s)?{success:!0,data:{actionId:s},display:`Scheduled action "${s}" deleted.`}:{success:!1,error:`Scheduled action "${s}" not found`}}}});var _t,Xo=_(()=>{"use strict";_t=class{static{u(this,"MCPClient")}serverName;config;logger;client;transport;connected=!1;constructor(e,t,s){this.serverName=e,this.config=t,this.logger=s}async connect(){try{let{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");if(this.client=new e({name:`alfred-${this.serverName}`,version:"1.0.0"},{capabilities:{}}),this.config.command){let{StdioClientTransport:t}=await import("@modelcontextprotocol/sdk/client/stdio.js"),s={PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:process.env.NODE_ENV??"",SYSTEMROOT:process.env.SYSTEMROOT??""};if(this.config.env)for(let[r,n]of Object.entries(this.config.env))s[r]=n.replace(/\$\{(\w+)\}/g,(o,i)=>process.env[i]??"");this.transport=new t({command:this.config.command,args:this.config.args??[],env:s})}else if(this.config.url){let{SSEClientTransport:t}=await import("@modelcontextprotocol/sdk/client/sse.js");this.transport=new t(new URL(this.config.url))}else throw new Error(`MCP server "${this.serverName}": must specify either command or url`);await this.client.connect(this.transport),this.connected=!0,this.logger.info({server:this.serverName},"MCP server connected")}catch(e){throw this.logger.error({server:this.serverName,err:e},"Failed to connect MCP server"),e}}async listTools(){if(!this.connected||!this.client)return[];try{return((await this.client.listTools()).tools??[]).map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema??{type:"object",properties:{}}}))}catch(e){return this.logger.error({server:this.serverName,err:e},"Failed to list MCP tools"),[]}}async callTool(e,t){if(!this.connected||!this.client)return{content:"MCP server not connected",isError:!0};try{let s=await this.client.callTool({name:e,arguments:t});return{content:(s.content??[]).map(n=>n.text??JSON.stringify(n)).join(`
583
- `),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var Em,Et,Yo=_(()=>{"use strict";P();Em=["read","write","destructive","admin"],Et=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&Em.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var ar,Oc=_(()=>{"use strict";Xo();Yo();ar=class{static{u(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new _t(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new Et(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Pc=_(()=>{"use strict";Xo();Yo();Oc()});import{spawn as bm}from"node:child_process";import et from"node:fs";import je from"node:path";import $m from"node:os";import km from"node:crypto";var bt,Jo=_(()=>{"use strict";bt=class{static{u(this,"CodeExecutor")}resolveNodePath(){let e=new Set;for(let r of["pdf-parse","exceljs","pdfkit"])try{let n=pa.resolve(`${r}/package.json`);e.add(je.dirname(je.dirname(n)))}catch{}let t=je.dirname(process.argv[1]??"");if(t){let r=je.join(t,"node_modules");et.existsSync(r)&&e.add(r)}let s=je.join(process.cwd(),"node_modules");if(et.existsSync(s)&&e.add(s),process.env.NODE_PATH)for(let r of process.env.NODE_PATH.split(je.delimiter))r&&e.add(r);return[...e].join(je.delimiter)}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=je.join($m.tmpdir(),`alfred-sandbox-${km.randomUUID()}`);et.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=je.join(n,`script.${o}`);et.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",l=[i],d=Date.now();return await new Promise(m=>{let p=bm(a,l,{cwd:n,timeout:r,env:{PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n,NODE_PATH:this.resolveNodePath()},stdio:["pipe","pipe","pipe"]}),g="",f="";p.stdout.on("data",h=>{g+=h.toString()}),p.stderr.on("data",h=>{f+=h.toString()}),p.on("close",h=>{let T=Date.now()-d,b=[];try{let A=et.readdirSync(n).filter(C=>!C.startsWith("script."));for(let C of A){let U=je.join(n,C),x=et.statSync(U);if(x.isFile()&&x.size<1e7){let V=et.readFileSync(U),be=C.endsWith(".png")?"image/png":C.endsWith(".jpg")||C.endsWith(".jpeg")?"image/jpeg":C.endsWith(".svg")?"image/svg+xml":C.endsWith(".csv")?"text/csv":C.endsWith(".json")?"application/json":C.endsWith(".html")||C.endsWith(".htm")?"text/html":C.endsWith(".txt")?"text/plain":C.endsWith(".md")?"text/markdown":C.endsWith(".xml")?"application/xml":C.endsWith(".xlsx")?"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":C.endsWith(".xls")?"application/vnd.ms-excel":C.endsWith(".pdf")?"application/pdf":"application/octet-stream";b.push({name:C,data:V,mimeType:be})}}}catch{}m({stdout:g.slice(0,5e4),stderr:f.slice(0,1e4),exitCode:h??1,files:b.length>0?b:void 0,durationMs:T})}),p.on("error",h=>{m({stdout:"",stderr:h.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{et.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var cr,Uc=_(()=>{"use strict";P();Jo();cr=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",category:"automation",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (PDF, HTML, CSV, images, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. Any files written to the working directory are automatically collected and sent to the user as attachments \u2014 do NOT use the file skill to send them afterwards. For PDF generation use pdfkit (Node.js) or reportlab/fpdf (Python). IMPORTANT: When generating large files, write compact data-driven code \u2014 define data as arrays/objects, then build the output programmatically. Never embed large HTML/text as string literals.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data to pass (available as DATA env var or stdin)"},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new bt;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code". IMPORTANT: Do NOT embed large HTML/text as string literals \u2014 write compact code that builds content programmatically from data arrays/objects, e.g. rows.map(r => `<tr><td>${r.time}</td><td>${r.price}</td></tr>`).join(""). Keep the code short and data-driven.'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};if(s==="run"&&r.length>4e3)return{success:!1,error:`Code too large (${r.length} chars, limit 4000 for action "run"). This usually means data is hardcoded in the code. Use action "run_with_data" with the data parameter instead. The data will be available as INPUT_DATA (already parsed). If you received a data reference like "result_1", pass it as the data parameter.`};let a=r;if(s==="run_with_data"&&o){let p=!1;try{JSON.parse(o),p=!0}catch{}n==="javascript"?a=p?`const INPUT_DATA = ${o};
583
+ `),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var Em,Et,Yo=_(()=>{"use strict";P();Em=["read","write","destructive","admin"],Et=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&Em.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var ar,Oc=_(()=>{"use strict";Xo();Yo();ar=class{static{u(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new _t(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new Et(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Pc=_(()=>{"use strict";Xo();Yo();Oc()});import{spawn as bm}from"node:child_process";import Me from"node:fs";import Oe from"node:path";import $m from"node:os";import km from"node:crypto";var bt,Jo=_(()=>{"use strict";bt=class{static{u(this,"CodeExecutor")}resolveNodePath(){let e=new Set;for(let s of["pdf-parse","exceljs","pdfkit"])try{let r=pa.resolve(`${s}/package.json`);e.add(Oe.dirname(Oe.dirname(r)))}catch{}try{let s=Me.realpathSync(process.argv[1]??""),r=Oe.dirname(s),n=Oe.join(r,"node_modules");Me.existsSync(n)&&e.add(n);let o=Oe.join(r,"..","node_modules");Me.existsSync(o)&&e.add(Me.realpathSync(o))}catch{}let t=Oe.join(process.cwd(),"node_modules");if(Me.existsSync(t)&&e.add(t),process.env.NODE_PATH)for(let s of process.env.NODE_PATH.split(Oe.delimiter))s&&e.add(s);return[...e].join(Oe.delimiter)}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=Oe.join($m.tmpdir(),`alfred-sandbox-${km.randomUUID()}`);Me.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=Oe.join(n,`script.${o}`);Me.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",l=[i],d=Date.now();return await new Promise(m=>{let p=bm(a,l,{cwd:n,timeout:r,env:{...process.env,NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n,NODE_PATH:this.resolveNodePath()},stdio:["pipe","pipe","pipe"]}),g="",f="";p.stdout.on("data",h=>{g+=h.toString()}),p.stderr.on("data",h=>{f+=h.toString()}),p.on("close",h=>{let T=Date.now()-d,b=[];try{let A=Me.readdirSync(n).filter(C=>!C.startsWith("script."));for(let C of A){let U=Oe.join(n,C),x=Me.statSync(U);if(x.isFile()&&x.size<1e7){let V=Me.readFileSync(U),Te=C.endsWith(".png")?"image/png":C.endsWith(".jpg")||C.endsWith(".jpeg")?"image/jpeg":C.endsWith(".svg")?"image/svg+xml":C.endsWith(".csv")?"text/csv":C.endsWith(".json")?"application/json":C.endsWith(".html")||C.endsWith(".htm")?"text/html":C.endsWith(".txt")?"text/plain":C.endsWith(".md")?"text/markdown":C.endsWith(".xml")?"application/xml":C.endsWith(".xlsx")?"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":C.endsWith(".xls")?"application/vnd.ms-excel":C.endsWith(".pdf")?"application/pdf":"application/octet-stream";b.push({name:C,data:V,mimeType:Te})}}}catch{}m({stdout:g.slice(0,5e4),stderr:f.slice(0,1e4),exitCode:h??1,files:b.length>0?b:void 0,durationMs:T})}),p.on("error",h=>{m({stdout:"",stderr:h.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{Me.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var cr,Uc=_(()=>{"use strict";P();Jo();cr=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",category:"automation",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (PDF, HTML, CSV, images, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. Any files written to the working directory are automatically collected and sent to the user as attachments \u2014 do NOT use the file skill to send them afterwards. For PDF generation use pdfkit (Node.js) or reportlab/fpdf (Python). IMPORTANT: When generating large files, write compact data-driven code \u2014 define data as arrays/objects, then build the output programmatically. Never embed large HTML/text as string literals.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data (available as variable INPUT_DATA, already parsed if JSON). Do NOT use os.environ or process.env \u2014 use INPUT_DATA directly."},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new bt;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code". IMPORTANT: Do NOT embed large HTML/text as string literals \u2014 write compact code that builds content programmatically from data arrays/objects, e.g. rows.map(r => `<tr><td>${r.time}</td><td>${r.price}</td></tr>`).join(""). Keep the code short and data-driven.'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};if(s==="run"&&r.length>4e3)return{success:!1,error:`Code too large (${r.length} chars, limit 4000 for action "run"). This usually means data is hardcoded in the code. Use action "run_with_data" with the data parameter instead. The data will be available as INPUT_DATA (already parsed). If you received a data reference like "result_1", pass it as the data parameter.`};let a=r;if(s==="run_with_data"&&o){let p=!1;try{JSON.parse(o),p=!0}catch{}n==="javascript"?a=p?`const INPUT_DATA = ${o};
584
584
  ${r}`:`const INPUT_DATA = ${JSON.stringify(o)};
585
585
  ${r}`:a=p?`import json as _json
586
586
  INPUT_DATA = _json.loads(${JSON.stringify(o)})
@@ -589,7 +589,7 @@ ${r}`}let l=await this.executor.execute(a,n,{timeout:i}),d=l.files?.map(p=>({fil
589
589
  ${l.stdout}`:"",l.stderr?`Errors:
590
590
  ${l.stderr}`:"",`Exit code: ${l.exitCode}`,`Duration: ${l.durationMs}ms`,d&&d.length>0?`Files generated: ${d.map(p=>p.fileName).join(", ")}`:""].filter(Boolean).join(`
591
591
 
592
- `);return{success:l.exitCode===0,data:{stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode,durationMs:l.durationMs,fileCount:l.files?.length??0},display:m,error:l.exitCode!==0?`Code execution failed with exit code ${l.exitCode}`:void 0,attachments:d}}}});var Fc=_(()=>{"use strict";Jo();Uc()});var es,jc=_(()=>{"use strict";P();Fe();es=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",category:"files",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,n=e.mime_type;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "file_path" for ingest action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "filename" for ingest action'};if(!n||typeof n!="string")return{success:!1,error:'Missing required field "mime_type" for ingest action'};let o=await import("node:path"),i=o.resolve(s);if(i!==o.normalize(s)&&s.includes(".."))return{success:!1,error:"Invalid file path: path traversal not allowed"};let a=i.toLowerCase();if(a.startsWith("/etc/")||a.startsWith("/proc/")||a.startsWith("/sys/")||a.startsWith("c:\\windows\\")||a.startsWith("/root/"))return{success:!1,error:"Access to system directories is not allowed"};try{let l=await this.processor.ingest(te(t),s,r,n),d=l.existing?`Document "${r}" already ingested (${l.chunkCount} chunks). Ready for search. ID: ${l.documentId.slice(0,8)}...`:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`;return{success:!0,data:l,display:d}}catch(l){return{success:!1,error:`Failed to ingest document: ${l instanceof Error?l.message:String(l)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let n=z(t),o=new Set,i=[];for(let d of n)for(let m of await this.embeddingService.semanticSearch(d,s,r))o.has(m.key)||(o.add(m.key),i.push(m));let a=i.filter(d=>d.category==="document");if(a.length===0)return{success:!0,data:[],display:`No document matches found for "${s}".`};let l=a.map((d,m)=>`${m+1}. (score: ${d.score.toFixed(3)}) ${d.value.slice(0,200)}${d.value.length>200?"...":""}`).join(`
592
+ `);return{success:l.exitCode===0,data:{stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode,durationMs:l.durationMs,fileCount:l.files?.length??0},display:m,error:l.exitCode!==0?`Code execution failed with exit code ${l.exitCode}`:void 0,attachments:d}}}});var Fc=_(()=>{"use strict";Jo();Uc()});var es,jc=_(()=>{"use strict";P();Be();es=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",category:"files",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,n=e.mime_type;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "file_path" for ingest action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "filename" for ingest action'};if(!n||typeof n!="string")return{success:!1,error:'Missing required field "mime_type" for ingest action'};let o=await import("node:path"),i=o.resolve(s);if(i!==o.normalize(s)&&s.includes(".."))return{success:!1,error:"Invalid file path: path traversal not allowed"};let a=i.toLowerCase();if(a.startsWith("/etc/")||a.startsWith("/proc/")||a.startsWith("/sys/")||a.startsWith("c:\\windows\\")||a.startsWith("/root/"))return{success:!1,error:"Access to system directories is not allowed"};try{let l=await this.processor.ingest(te(t),s,r,n),d=l.existing?`Document "${r}" already ingested (${l.chunkCount} chunks). Ready for search. ID: ${l.documentId.slice(0,8)}...`:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`;return{success:!0,data:l,display:d}}catch(l){return{success:!1,error:`Failed to ingest document: ${l instanceof Error?l.message:String(l)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let n=z(t),o=new Set,i=[];for(let d of n)for(let m of await this.embeddingService.semanticSearch(d,s,r))o.has(m.key)||(o.add(m.key),i.push(m));let a=i.filter(d=>d.category==="document");if(a.length===0)return{success:!0,data:[],display:`No document matches found for "${s}".`};let l=a.map((d,m)=>`${m+1}. (score: ${d.score.toFixed(3)}) ${d.value.slice(0,200)}${d.value.length>200?"...":""}`).join(`
593
593
 
594
594
  `);return{success:!0,data:a,display:`Found ${a.length} relevant chunk(s):
595
595
 
@@ -601,13 +601,13 @@ ${l}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success
601
601
 
602
602
  ${a}`}}list(e,t){let s=e.limit||50,r=z(t),n=new Set,o=[];for(let l of r)for(let d of this.docRepo.listByUser(l))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(l=>`- **${l.filename}** [id=${l.id}] \u2014 ${l.mimeType}, ${l.chunkCount} chunks, ${l.sizeBytes} bytes`).join(`
603
603
  `);return{success:!0,data:i,display:`${i.length} document(s):
604
- ${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 ts,Bc=_(()=>{"use strict";P();ts=class extends I{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 ss,Hc=_(()=>{"use strict";P();ss=class extends I{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 ie(c){return c==null?"-":c<1024?`${c} B`:c<1024**2?`${(c/1024).toFixed(1)} KiB`:c<1024**3?`${(c/1024**2).toFixed(1)} MiB`:`${(c/1024**3).toFixed(2)} GiB`}function lr(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function cn(c){if(!c)return"-";let e=Math.floor(c/86400),t=Math.floor(c%86400/3600),s=Math.floor(c%3600/60),r=[];return e&&r.push(`${e}d`),t&&r.push(`${t}h`),r.push(`${s}m`),r.join(" ")}var ln,qc=_(()=>{"use strict";P();u(ie,"bytes");u(lr,"pct");u(cn,"uptimeStr");ln=class c extends I{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 l;try{l=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let m="";try{m=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${m}`)}return(await l.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<c.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(`
605
- `)}}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"?lr(s.cpu):"-",n=ie(s.mem),o=ie(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${cn(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
606
- `)}}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:** ${cn(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${lr(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${ie(n.used)} / ${ie(n.total)} (${lr(n.used/n.total)})`),i&&a.push(`**Swap:** ${ie(i.used)} / ${ie(i.total)}`),o&&a.push(`**Root FS:** ${ie(o.used)} / ${ie(o.total)}`),{success:!0,data:s,display:a.join(`
607
- `)}}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??"-"} | ${lr(n.cpu)} | ${ie(n.mem)} / ${ie(n.maxmem)} | ${cn(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
608
- `)}}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:** ${lr(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${ie(r.mem)} / ${ie(r.maxmem)}`,`**Disk:** ${ie(r.disk)} / ${ie(r.maxdisk)}`,`**Uptime:** ${cn(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${ie(r.netin)} / ${ie(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
604
+ ${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 ts,Bc=_(()=>{"use strict";P();ts=class extends I{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 ss,Hc=_(()=>{"use strict";P();ss=class extends I{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 ae(c){return c==null?"-":c<1024?`${c} B`:c<1024**2?`${(c/1024).toFixed(1)} KiB`:c<1024**3?`${(c/1024**2).toFixed(1)} MiB`:`${(c/1024**3).toFixed(2)} GiB`}function lr(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function cn(c){if(!c)return"-";let e=Math.floor(c/86400),t=Math.floor(c%86400/3600),s=Math.floor(c%3600/60),r=[];return e&&r.push(`${e}d`),t&&r.push(`${t}h`),r.push(`${s}m`),r.join(" ")}var ln,qc=_(()=>{"use strict";P();u(ae,"bytes");u(lr,"pct");u(cn,"uptimeStr");ln=class c extends I{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 l;try{l=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let m="";try{m=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${m}`)}return(await l.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<c.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(`
605
+ `)}}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"?lr(s.cpu):"-",n=ae(s.mem),o=ae(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${cn(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
606
+ `)}}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:** ${cn(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${lr(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${ae(n.used)} / ${ae(n.total)} (${lr(n.used/n.total)})`),i&&a.push(`**Swap:** ${ae(i.used)} / ${ae(i.total)}`),o&&a.push(`**Root FS:** ${ae(o.used)} / ${ae(o.total)}`),{success:!0,data:s,display:a.join(`
607
+ `)}}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??"-"} | ${lr(n.cpu)} | ${ae(n.mem)} / ${ae(n.maxmem)} | ${cn(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
608
+ `)}}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:** ${lr(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${ae(r.mem)} / ${ae(r.maxmem)}`,`**Disk:** ${ae(r.disk)} / ${ae(r.maxdisk)}`,`**Uptime:** ${cn(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${ae(r.netin)} / ${ae(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
609
609
  `)}}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(`
610
- `)}}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=ie(o.used),a=ie(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(`
610
+ `)}}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=ae(o.used),a=ae(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(`
611
611
  `)}}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(`
612
612
  `)}}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(`
613
613
  `)}}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(`
@@ -657,7 +657,7 @@ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this
657
657
  `)}}let s=e.startsWith("script.")?e.slice(7):e,r={};if(t)try{r=JSON.parse(t)}catch{return{success:!1,error:'Invalid "variables" \u2014 must be valid JSON'}}return{success:!0,data:await this.api("POST",`/api/services/script/${s}`,r),display:`**Script executed:** \`script.${s}\``}}async getCalendarEvents(e,t,s){if(!e){let a=await this.api("GET","/api/calendars"),l=["## Calendars","","| Entity ID | Name |","|-----------|------|"];for(let d of a){let m=d.name??d.entity_id??"-";l.push(`| ${d.entity_id} | ${m} |`)}return a.length===0&&l.push("| - | No calendars found |"),{success:!0,data:a,display:l.join(`
658
658
  `)}}let r=t??new Date().toISOString(),n=s??new Date(Date.now()+864e5).toISOString(),o=await this.api("GET",`/api/calendars/${e}?start=${encodeURIComponent(r)}&end=${encodeURIComponent(n)}`),i=[`## Calendar Events: ${e}`,"","| Start | End | Summary | Location |","|-------|-----|---------|----------|"];for(let a of o){let l=a.start?.dateTime?new Date(a.start.dateTime).toLocaleString():a.start?.date??"-",d=a.end?.dateTime?new Date(a.end.dateTime).toLocaleString():a.end?.date??"-";i.push(`| ${l} | ${d} | ${a.summary??"-"} | ${a.location??"-"} |`)}return o.length===0&&i.push("| - | - | No events in range | - |"),{success:!0,data:o,display:i.join(`
659
659
  `)}}async getErrorLog(){let e=await this.apiText("GET","/api/error_log"),t=e.length>3e3?`\u2026${e.slice(-3e3)}`:e;return{success:!0,data:t,display:["## Error Log","","```",t,"```"].join(`
660
- `)}}}});var Me,dr=_(()=>{"use strict";Me=class{static{u(this,"ContactsProvider")}}});var Vc={};oe(Vc,{CardDAVContactsProvider:()=>mn});var mn,Zo=_(()=>{"use strict";dr();mn=class extends Me{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},l=this.buildVCard(e,a);await this.client.updateVCard({vCard:{...o,data:l}});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 T=h[0],b=h[1].trim(),A=T.match(/TYPE=([^;:,]+)/i)?.[1],C=/TYPE=pref/i.test(T);a.push({address:b,label:A,primary:C})}let l=[];for(let h of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let T=h[0],b=h[1].trim(),A=T.match(/TYPE=([^;:,]+)/i)?.[1],C=/TYPE=pref/i.test(T);l.push({number:b,label:A,primary:C})}let d=[];for(let h of e.matchAll(/^ADR[^:]*:(.+)$/gmi)){let T=h[1].split(";");d.push({street:T[2]?.trim()||void 0,city:T[3]?.trim()||void 0,region:T[4]?.trim()||void 0,postalCode:T[5]?.trim()||void 0,country:T[6]?.trim()||void 0})}let m=s("ORG")?.replace(/;.*$/,""),p=s("BDAY"),g=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:o,emails:a,phones:l,addresses:d,organization:m,birthday:p,notes:g}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
660
+ `)}}}});var Pe,dr=_(()=>{"use strict";Pe=class{static{u(this,"ContactsProvider")}}});var Vc={};ie(Vc,{CardDAVContactsProvider:()=>mn});var mn,Zo=_(()=>{"use strict";dr();mn=class extends Pe{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},l=this.buildVCard(e,a);await this.client.updateVCard({vCard:{...o,data:l}});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 T=h[0],b=h[1].trim(),A=T.match(/TYPE=([^;:,]+)/i)?.[1],C=/TYPE=pref/i.test(T);a.push({address:b,label:A,primary:C})}let l=[];for(let h of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let T=h[0],b=h[1].trim(),A=T.match(/TYPE=([^;:,]+)/i)?.[1],C=/TYPE=pref/i.test(T);l.push({number:b,label:A,primary:C})}let d=[];for(let h of e.matchAll(/^ADR[^:]*:(.+)$/gmi)){let T=h[1].split(";");d.push({street:T[2]?.trim()||void 0,city:T[3]?.trim()||void 0,region:T[4]?.trim()||void 0,postalCode:T[5]?.trim()||void 0,country:T[6]?.trim()||void 0})}let m=s("ORG")?.replace(/;.*$/,""),p=s("BDAY"),g=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:o,emails:a,phones:l,addresses:d,organization:m,birthday:p,notes:g}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
661
661
  VERSION:3.0\r
662
662
  `;r+=`UID:${e}\r
663
663
  `,r+=`FN:${s}\r
@@ -669,13 +669,13 @@ VERSION:3.0\r
669
669
  `),t.birthday&&(r+=`BDAY:${t.birthday}\r
670
670
  `),t.notes&&(r+=`NOTE:${t.notes}\r
671
671
  `),r+=`END:VCARD\r
672
- `,r}}});var Kc={};oe(Kc,{GoogleContactsProvider:()=>hn});var pn,$t,hn,Qo=_(()=>{"use strict";dr();pn="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",$t="https://people.googleapis.com/v1",hn=class extends Me{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=`${$t}/people/me/connections?personFields=${pn}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${$t}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${pn}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${$t}/${e}?personFields=${pn}`,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",`${$t}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${$t}/${e}?personFields=${pn}`),r=this.buildPersonBody(t);r.etag=s.etag;let o=`${$t}/${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",`${$t}/${e}:deleteContact`)}mapPerson(e){let t=e.names?.[0],s=(e.emailAddresses??[]).map(l=>({address:l.value,label:l.type,primary:l.metadata?.primary??!1})),r=(e.phoneNumbers??[]).map(l=>({number:l.value,label:l.type,primary:l.metadata?.primary??!1})),n=(e.addresses??[]).map(l=>({street:l.streetAddress??void 0,city:l.city??void 0,region:l.region??void 0,postalCode:l.postalCode??void 0,country:l.country??void 0,label:l.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 Xc={};oe(Xc,{MicrosoftContactsProvider:()=>fn});var fn,ei=_(()=>{"use strict";dr();fn=class extends Me{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 ti(c){switch(c.provider){case"carddav":{if(!c.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(Zo(),Vc)),t=new e(c.carddav);return await t.initialize(),t}case"google":{if(!c.google)throw new Error("Google contacts config missing");let{GoogleContactsProvider:e}=await Promise.resolve().then(()=>(Qo(),Kc)),t=new e(c.google);return await t.initialize(),t}case"microsoft":{if(!c.microsoft)throw new Error("Microsoft contacts config missing");let{MicrosoftContactsProvider:e}=await Promise.resolve().then(()=>(ei(),Xc)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${c.provider}`)}}var Yc=_(()=>{"use strict";u(ti,"createContactsProvider")});var ur,Jc=_(()=>{"use strict";P();ur=class extends I{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:
672
+ `,r}}});var Kc={};ie(Kc,{GoogleContactsProvider:()=>hn});var pn,$t,hn,Qo=_(()=>{"use strict";dr();pn="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",$t="https://people.googleapis.com/v1",hn=class extends Pe{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=`${$t}/people/me/connections?personFields=${pn}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${$t}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${pn}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${$t}/${e}?personFields=${pn}`,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",`${$t}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${$t}/${e}?personFields=${pn}`),r=this.buildPersonBody(t);r.etag=s.etag;let o=`${$t}/${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",`${$t}/${e}:deleteContact`)}mapPerson(e){let t=e.names?.[0],s=(e.emailAddresses??[]).map(l=>({address:l.value,label:l.type,primary:l.metadata?.primary??!1})),r=(e.phoneNumbers??[]).map(l=>({number:l.value,label:l.type,primary:l.metadata?.primary??!1})),n=(e.addresses??[]).map(l=>({street:l.streetAddress??void 0,city:l.city??void 0,region:l.region??void 0,postalCode:l.postalCode??void 0,country:l.country??void 0,label:l.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 Xc={};ie(Xc,{MicrosoftContactsProvider:()=>fn});var fn,ei=_(()=>{"use strict";dr();fn=class extends Pe{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 ti(c){switch(c.provider){case"carddav":{if(!c.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(Zo(),Vc)),t=new e(c.carddav);return await t.initialize(),t}case"google":{if(!c.google)throw new Error("Google contacts config missing");let{GoogleContactsProvider:e}=await Promise.resolve().then(()=>(Qo(),Kc)),t=new e(c.google);return await t.initialize(),t}case"microsoft":{if(!c.microsoft)throw new Error("Microsoft contacts config missing");let{MicrosoftContactsProvider:e}=await Promise.resolve().then(()=>(ei(),Xc)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${c.provider}`)}}var Yc=_(()=>{"use strict";u(ti,"createContactsProvider")});var ur,Jc=_(()=>{"use strict";P();ur=class extends I{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:
673
673
  ${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):
674
674
  ${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 |
675
675
  |------|-------|-------|`,s=e.map(r=>{let n=r.emails[0]?.address??"-",o=r.phones[0]?.number??"-";return`| ${r.displayName} | ${n} | ${o} |`});return`${t}
676
676
  ${s.join(`
677
677
  `)}`}formatDetail(e){let t=[];if(t.push(`**Name:** ${e.displayName}`),e.firstName&&t.push(`**First name:** ${e.firstName}`),e.lastName&&t.push(`**Last name:** ${e.lastName}`),e.emails.length>0&&t.push(`**Email(s):** ${e.emails.map(s=>`${s.address}${s.label?` (${s.label})`:""}`).join(", ")}`),e.phones.length>0&&t.push(`**Phone(s):** ${e.phones.map(s=>`${s.number}${s.label?` (${s.label})`:""}`).join(", ")}`),e.addresses.length>0)for(let s of e.addresses){let r=[s.street,s.city,s.region,s.postalCode,s.country].filter(Boolean);t.push(`**Address${s.label?` (${s.label})`:""}:** ${r.join(", ")}`)}return e.organization&&t.push(`**Organization:** ${e.organization}`),e.birthday&&t.push(`**Birthday:** ${e.birthday}`),e.notes&&t.push(`**Notes:** ${e.notes}`),t.push(`**ID:** ${e.id}`),t.join(`
678
- `)}}});var Zc=_(()=>{"use strict";dr();Zo();Qo();ei();Yc();Jc()});var rs,Qc=_(()=>{"use strict";P();Fe();rs=class extends I{static{u(this,"TodoSkill")}todoRepo;metadata={name:"todo",category:"productivity",description:"Manage todo lists with multiple named lists. Actions: add, list, complete, uncomplete, delete, lists, clear.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["add","list","complete","uncomplete","delete","lists","clear"],description:"The todo action to perform"},title:{type:"string",description:"The todo title (required for add)"},list:{type:"string",description:'The list name (default: "default")'},description:{type:"string",description:"Optional description for the todo"},priority:{type:"string",enum:["low","normal","high","urgent"],description:'Priority level (default: "normal")'},dueDate:{type:"string",description:"Due date for the todo (ISO string)"},todoId:{type:"string",description:"The ID of the todo (required for complete, uncomplete, delete)"},includeCompleted:{type:"boolean",description:"Include completed todos in list output (default: false)"}},required:["action"]}};constructor(e){super(),this.todoRepo=e}async execute(e,t){let s=e.action;switch(s){case"add":return this.addTodo(e,t);case"list":return this.listTodos(e,t);case"complete":return this.completeTodo(e,t);case"uncomplete":return this.uncompleteTodo(e,t);case"delete":return this.deleteTodo(e,t);case"lists":return this.showLists(t);case"clear":return this.clearCompleted(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: add, list, complete, uncomplete, delete, lists, clear`}}}addTodo(e,t){let s=e.title;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for add action'};let r=e.list??"default",n=e.description,o=e.priority,i=e.dueDate,a=this.todoRepo.add(te(t),s,{list:r,description:n,priority:o,dueDate:i});return{success:!0,data:{todoId:a.id,title:a.title,list:a.list},display:`Todo added: "${s}"`}}listTodos(e,t){let s=e.list,r=e.includeCompleted??!1,n=new Set,o=[];for(let l of z(t))for(let d of this.todoRepo.list(l,s,r))n.has(d.id)||(n.add(d.id),o.push(d));if(o.length===0)return{success:!0,data:[],display:"No todos found."};let i=`| | Priority | Title | Due | ID |
678
+ `)}}});var Zc=_(()=>{"use strict";dr();Zo();Qo();ei();Yc();Jc()});var rs,Qc=_(()=>{"use strict";P();Be();rs=class extends I{static{u(this,"TodoSkill")}todoRepo;metadata={name:"todo",category:"productivity",description:"Manage todo lists with multiple named lists. Actions: add, list, complete, uncomplete, delete, lists, clear.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["add","list","complete","uncomplete","delete","lists","clear"],description:"The todo action to perform"},title:{type:"string",description:"The todo title (required for add)"},list:{type:"string",description:'The list name (default: "default")'},description:{type:"string",description:"Optional description for the todo"},priority:{type:"string",enum:["low","normal","high","urgent"],description:'Priority level (default: "normal")'},dueDate:{type:"string",description:"Due date for the todo (ISO string)"},todoId:{type:"string",description:"The ID of the todo (required for complete, uncomplete, delete)"},includeCompleted:{type:"boolean",description:"Include completed todos in list output (default: false)"}},required:["action"]}};constructor(e){super(),this.todoRepo=e}async execute(e,t){let s=e.action;switch(s){case"add":return this.addTodo(e,t);case"list":return this.listTodos(e,t);case"complete":return this.completeTodo(e,t);case"uncomplete":return this.uncompleteTodo(e,t);case"delete":return this.deleteTodo(e,t);case"lists":return this.showLists(t);case"clear":return this.clearCompleted(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: add, list, complete, uncomplete, delete, lists, clear`}}}addTodo(e,t){let s=e.title;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for add action'};let r=e.list??"default",n=e.description,o=e.priority,i=e.dueDate,a=this.todoRepo.add(te(t),s,{list:r,description:n,priority:o,dueDate:i});return{success:!0,data:{todoId:a.id,title:a.title,list:a.list},display:`Todo added: "${s}"`}}listTodos(e,t){let s=e.list,r=e.includeCompleted??!1,n=new Set,o=[];for(let l of z(t))for(let d of this.todoRepo.list(l,s,r))n.has(d.id)||(n.add(d.id),o.push(d));if(o.length===0)return{success:!0,data:[],display:"No todos found."};let i=`| | Priority | Title | Due | ID |
679
679
  |---|---|---|---|---|`,a=o.map(l=>{let d=l.completed?"\u2611":"\u2610",m=l.dueDate??"",p=l.id.slice(0,8);return`| ${d} | ${l.priority} | ${l.title} | ${m} | ${p} |`}).join(`
680
680
  `);return{success:!0,data:o,display:`${o.length} todo(s):
681
681
  ${i}
@@ -700,9 +700,9 @@ ${n}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(te(t),s);
700
700
  `+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose up:** \`${e}\``,"","```",r,"```"].join(`
701
701
  `)}}async composeDown(e){if(!e)return{success:!1,error:'Missing required "project" parameter'};let{stdout:t,stderr:s}=await sl("docker",["compose","-p",e,"down"],{timeout:12e4}),r=(t+`
702
702
  `+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose down:** \`${e}\``,"","```",r,"```"].join(`
703
- `)}}}});import{readFile as ol,writeFile as il,mkdir as al}from"node:fs/promises";import{homedir as ni}from"node:os";import{join as oi}from"node:path";import dl from"node:crypto";function Dm(){let c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",e=dl.randomBytes(86);return Array.from(e).map(t=>c[t%c.length]).join("")}function Mm(c){return dl.createHash("sha256").update(c).digest("base64url")}function ye(c,e){return c[e]?.value??"?"}var Rm,cl,yn,Cm,Nm,Lm,ll,wn,Om,Tn,ul=_(()=>{"use strict";P();Rm="https://customer.bmwgroup.com/gcdm/oauth/device/code",cl="https://customer.bmwgroup.com/gcdm/oauth/token",yn="https://api-cardata.bmwgroup.com",Cm="v1",Nm="authenticate_user openid cardata:api:read cardata:streaming:read",Lm=5*6e4,ll="Alfred",wn=oi(ni(),".alfred","bmw-tokens.json");u(Dm,"generateCodeVerifier");u(Mm,"generateCodeChallenge");Om=["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(ye,"tv");Tn=class extends I{static{u(this,"BMWSkill")}metadata={name:"bmw",category:"infrastructure",description:'BMW CarData \u2014 Fahrzeugdaten abrufen. "authorize" startet den Device-Auth-Flow (einmalig). "status" zeigt SoC, Reichweite, Modell, Batterie-Gesundheit. "charging" zeigt Ladestatus, Leistung, Restzeit, Ziel-SoC, Stecker. "charging_sessions" listet Lade-Sessions (from/to Zeitraum).',riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["authorize","status","charging","charging_sessions"],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 (for polling token in step 2)"},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)"}},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);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=Dm(),s=Mm(t),r=await fetch(Rm,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,response_type:"device_code",code_challenge:s,code_challenge_method:"S256",scope:Nm}),signal:AbortSignal.timeout(15e3)});if(!r.ok){let i=await r.text().catch(()=>"");throw new Error(`Device code request failed: HTTP ${r.status} \u2014 ${i.slice(0,300)}`)}let n=await r.json(),o={codeVerifier:t,deviceCode:n.device_code};return await this.savePartialTokens(o),{success:!0,data:n,display:["## BMW Autorisierung","",`1. \xD6ffne: **${n.verification_uri_complete??n.verification_uri}**`,`2. Gib diesen Code ein: **${n.user_code}**`,"",`Danach ruf diese Action erneut auf mit \`device_code: "${n.device_code}"\` um den Token abzuholen.`].join(`
703
+ `)}}}});import{readFile as ol,writeFile as il,mkdir as al}from"node:fs/promises";import{homedir as ni}from"node:os";import{join as oi}from"node:path";import dl from"node:crypto";function Lm(){let c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",e=dl.randomBytes(86);return Array.from(e).map(t=>c[t%c.length]).join("")}function Mm(c){return dl.createHash("sha256").update(c).digest("base64url")}function ye(c,e){return c[e]?.value??"?"}var Rm,cl,yn,Cm,Nm,Dm,ll,wn,Om,Tn,ul=_(()=>{"use strict";P();Rm="https://customer.bmwgroup.com/gcdm/oauth/device/code",cl="https://customer.bmwgroup.com/gcdm/oauth/token",yn="https://api-cardata.bmwgroup.com",Cm="v1",Nm="authenticate_user openid cardata:api:read cardata:streaming:read",Dm=5*6e4,ll="Alfred",wn=oi(ni(),".alfred","bmw-tokens.json");u(Lm,"generateCodeVerifier");u(Mm,"generateCodeChallenge");Om=["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(ye,"tv");Tn=class extends I{static{u(this,"BMWSkill")}metadata={name:"bmw",category:"infrastructure",description:'BMW CarData \u2014 Fahrzeugdaten abrufen. "authorize" startet den Device-Auth-Flow (einmalig). "status" zeigt SoC, Reichweite, Modell, Batterie-Gesundheit. "charging" zeigt Ladestatus, Leistung, Restzeit, Ziel-SoC, Stecker. "charging_sessions" listet Lade-Sessions (from/to Zeitraum).',riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["authorize","status","charging","charging_sessions"],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 (for polling token in step 2)"},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)"}},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);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=Lm(),s=Mm(t),r=await fetch(Rm,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,response_type:"device_code",code_challenge:s,code_challenge_method:"S256",scope:Nm}),signal:AbortSignal.timeout(15e3)});if(!r.ok){let i=await r.text().catch(()=>"");throw new Error(`Device code request failed: HTTP ${r.status} \u2014 ${i.slice(0,300)}`)}let n=await r.json(),o={codeVerifier:t,deviceCode:n.device_code};return await this.savePartialTokens(o),{success:!0,data:n,display:["## BMW Autorisierung","",`1. \xD6ffne: **${n.verification_uri_complete??n.verification_uri}**`,`2. Gib diesen Code ein: **${n.user_code}**`,"",`Danach ruf diese Action erneut auf mit \`device_code: "${n.device_code}"\` um den Token abzuholen.`].join(`
704
704
  `)}}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(cl,{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 l="",d="";try{l=await this.ensureContainer(o),i.containerId=l,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 l?(m.push(`**Container:** ${l}`),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:l!=="",data:{vin:a,containerId:l,containerError:d||void 0},display:m.join(`
705
- `)}}async fetchVin(e){let t=await fetch(`${yn}/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(`${yn}/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===ll);if(i)return i.containerId}let s=await fetch(`${yn}/customers/containers`,{method:"POST",headers:{...this.apiHeaders(e),"Content-Type":"application/json"},body:JSON.stringify({name:ll,purpose:"Alfred AI Assistant",technicalDescriptors:Om}),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":Cm,Accept:"application/json"}}async apiGet(e){let t=e,s=this.cache.get(t);if(s&&Date.now()-s.ts<Lm)return s.data;let r=await this.ensureToken(),n=`${yn}${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(){if(this.tokens)return this.tokens;try{let e=await ol(wn,"utf-8");return this.tokens=JSON.parse(e),this.tokens}catch{return null}}async saveTokens(e){await al(oi(ni(),".alfred"),{recursive:!0}),await il(wn,JSON.stringify(e,null,2),"utf-8")}async savePartialTokens(e){await al(oi(ni(),".alfred"),{recursive:!0});let t={};try{let s=await ol(wn,"utf-8");t=JSON.parse(s)}catch{}await il(wn,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(cl,{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=ye(o,"vehicle.drivetrain.batteryManagement.header"),a=ye(o,"vehicle.drivetrain.electricEngine.remainingElectricRange"),l=ye(o,"vehicle.drivetrain.batteryManagement.maxEnergy"),d=ye(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:** ${l} kWh`,`**Batterie-Gesundheit (SoH):** ${d} %`];return{success:!0,data:{telematic:o,basic:n},display:p.join(`
705
+ `)}}async fetchVin(e){let t=await fetch(`${yn}/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(`${yn}/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===ll);if(i)return i.containerId}let s=await fetch(`${yn}/customers/containers`,{method:"POST",headers:{...this.apiHeaders(e),"Content-Type":"application/json"},body:JSON.stringify({name:ll,purpose:"Alfred AI Assistant",technicalDescriptors:Om}),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":Cm,Accept:"application/json"}}async apiGet(e){let t=e,s=this.cache.get(t);if(s&&Date.now()-s.ts<Dm)return s.data;let r=await this.ensureToken(),n=`${yn}${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(){if(this.tokens)return this.tokens;try{let e=await ol(wn,"utf-8");return this.tokens=JSON.parse(e),this.tokens}catch{return null}}async saveTokens(e){await al(oi(ni(),".alfred"),{recursive:!0}),await il(wn,JSON.stringify(e,null,2),"utf-8")}async savePartialTokens(e){await al(oi(ni(),".alfred"),{recursive:!0});let t={};try{let s=await ol(wn,"utf-8");t=JSON.parse(s)}catch{}await il(wn,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(cl,{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=ye(o,"vehicle.drivetrain.batteryManagement.header"),a=ye(o,"vehicle.drivetrain.electricEngine.remainingElectricRange"),l=ye(o,"vehicle.drivetrain.batteryManagement.maxEnergy"),d=ye(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:** ${l} kWh`,`**Batterie-Gesundheit (SoH):** ${d} %`];return{success:!0,data:{telematic:o,basic:n},display:p.join(`
706
706
  `)}}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=ye(n,"vehicle.drivetrain.electricEngine.charging.status"),i=ye(n,"vehicle.drivetrain.batteryManagement.header"),a=ye(n,"vehicle.drivetrain.electricEngine.charging.level"),l=ye(n,"vehicle.drivetrain.electricEngine.charging.timeRemaining"),d=ye(n,"vehicle.powertrain.electric.battery.charging.power"),m=ye(n,"vehicle.drivetrain.electricEngine.charging.hvStatus"),p=ye(n,"vehicle.powertrain.electric.battery.stateOfCharge.target"),g=ye(n,"vehicle.drivetrain.electricEngine.charging.acVoltage"),f=ye(n,"vehicle.drivetrain.electricEngine.charging.acAmpere"),h=ye(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged"),T=ye(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.flap.isOpen"),b=ye(n,"vehicle.body.chargingPort.lockedStatus"),A=["## BMW Ladestatus","",`**Status:** ${o}`,`**Ladestand:** ${i} %`,`**Ladelevel:** ${a}`,`**Ladeleistung:** ${d} kW`,`**Restzeit:** ${l} min`,`**Ziel-SoC:** ${p} %`,`**HV-Batterie:** ${m}`,`**AC Spannung:** ${g} V`,`**AC Strom:** ${f} A`,`**Stecker eingesteckt:** ${h}`,`**Ladeklappe offen:** ${T}`,`**Ladeport-Schloss:** ${b}`];return{success:!0,data:n,display:A.join(`
707
707
  `)}}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)}`),l=a.data??a.chargingSessions??[],d=[`## BMW Lade-Sessions (${i.slice(0,10)} \u2013 ${o.slice(0,10)})`,"","| Datum | Dauer | Energie | Start-SoC | End-SoC |","|-------|-------|---------|-----------|---------|"];for(let m of l.slice(0,20)){let p=m.startTime,g=p?new Date(p).toLocaleDateString("de-AT"):"-",f=m.totalChargingDurationSec,h=f!=null?Math.round(f/60):"-",T=m.energyConsumedFromPowerGridKwh??"-",b=m.displayedStartSoc??"-",A=m.displayedSoc??"-";d.push(`| ${g} | ${h} min | ${T} kWh | ${b}% | ${A}% |`)}return l.length===0&&d.push("| - | Keine Sessions gefunden | - | - | - |"),{success:!0,data:a,display:d.join(`
708
708
  `)}}}});var Pm,_n,ml=_(()=>{"use strict";P();Pm="https://routes.googleapis.com/directions/v2:computeRoutes",_n=class extends I{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. Orte als Adresse oder "lat,lng" angeben.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["route","departure_time"],description:"Routing action"},origin:{type:"string",description:'Start-Adresse oder "lat,lng"'},destination:{type:"string",description:'Ziel-Adresse oder "lat,lng"'},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),l=this.parseDuration(i.duration),d=this.parseDuration(i.staticDuration),m=l-d,p=["## Route","",`**${e}** \u2192 **${t}**`,"",`**Distanz:** ${a} km`,`**Fahrzeit (aktuell):** ${this.formatMinutes(l)}`,`**Fahrzeit (ohne Verkehr):** ${this.formatMinutes(d)}`];if(m>1&&p.push(`**Verkehrsverz\xF6gerung:** +${this.formatMinutes(m)}`),s){let g=new Date(new Date(s).getTime()+l*6e4);p.push(`**Gesch\xE4tzte Ankunft:** ${g.toLocaleString("de-AT")}`)}return{success:!0,data:{distanceKm:parseFloat(a),durationMinutes:l,staticDurationMinutes:d},display:p.join(`
@@ -738,14 +738,14 @@ ${s.join(`
738
738
  `)}`}}toggleWatch(e,t){let s=e.watch_id;return s?this.watchRepo.toggle(s,t)?{success:!0,data:{watchId:s,enabled:t},display:`Watch "${s}" ${t?"aktiviert":"deaktiviert"}.`}:{success:!1,error:`Watch "${s}" not found`}:{success:!1,error:`Missing "watch_id" for ${t?"enable":"disable"}`}}deleteWatch(e){let t=e.watch_id;return t?this.watchRepo.delete(t)?{success:!0,data:{watchId:t},display:`Watch "${t}" gel\xF6scht.`}:{success:!1,error:`Watch "${t}" not found`}:{success:!1,error:'Missing "watch_id" for delete'}}}});import{spawn as Hm}from"node:child_process";import Il from"node:fs";import Cl from"node:path";function Gm(c){let e={};for(let[t,s]of Object.entries(c))e[t]=s.replace(/\$\{(\w+)\}/g,(r,n)=>process.env[n]??"");return e}function Vm(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function kn(c){return c.length<=xl?c:`[...truncated...]
739
739
  `+c.slice(-xl)}function Rl(c){let e=new Map;function t(s){let r;try{r=Il.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(Wm.has(n.name))continue;let o=Cl.join(s,n.name);if(n.isDirectory())t(o);else if(n.isFile())try{let i=Il.statSync(o);e.set(o,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function Km(c,e,t){let s=[];for(let[r,n]of e){let o=c.get(r);(o===void 0||n>o)&&s.push(Cl.relative(t,r))}return s.sort()}async function mr(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??qm,n=Math.min(r,zm),o=Vm(c.argsTemplate,e),i={...process.env,...c.env?Gm(c.env):{}},a=process.platform==="win32",l=Rl(s),d=Date.now();return new Promise(m=>{let p=Hm(c.command,o,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),g="",f="",h=!1,T=setTimeout(()=>{h=!0,p.kill("SIGTERM"),setTimeout(()=>p.kill("SIGKILL"),5e3)},n);p.stdout?.on("data",b=>{g+=b.toString()}),p.stderr?.on("data",b=>{let A=b.toString();if(f+=A,t.onProgress){let C=A.trim().split(`
740
740
  `).pop();C&&t.onProgress(`[${c.name}] ${C}`)}}),c.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",b=>{clearTimeout(T);let A=Date.now()-d,C=Rl(s),U=Km(l,C,s);m({stdout:kn(g),stderr:kn(f),exitCode:h?124:b??1,durationMs:A,modifiedFiles:U})}),p.on("error",b=>{clearTimeout(T);let A=Date.now()-d;m({stdout:kn(g),stderr:kn(f+`
741
- `+b.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var qm,zm,xl,Wm,vn=_(()=>{"use strict";qm=3e5,zm=9e5,xl=1e5,Wm=new Set([".git","node_modules",".next","dist",".cache"]);u(Gm,"resolveEnv");u(Vm,"buildArgs");u(kn,"truncateOutput");u(Rl,"snapshotMtimes");u(Km,"detectModifiedFiles");u(mr,"executeAgent")});import{execFile as Xm}from"node:child_process";function Oe(c,e){return new Promise((t,s)=>{Xm("git",c,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,n,o)=>{if(r){let i=o?.trim()||r.message;s(new Error(`git ${c[0]} failed: ${i}`));return}t(n.trim())})})}async function Sn(c){try{let e=await Oe(["rev-parse","--abbrev-ref","HEAD"],c),t=await Oe(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function li(c,e){await Oe(["checkout","-b",c],e)}async function di(c){await Oe(["add","-A"],c)}async function ui(c,e){await Oe(["commit","-m",c],e);let t=await Oe(["rev-parse","--short","HEAD"],e),r=(await Oe(["diff","--stat","HEAD~1","HEAD"],e)).split(`
742
- `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function mi(c,e,t){await Oe(["push","-u",c,e],t)}function pi(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function ls(c,e){try{return await Oe(["remote","get-url",c],e)}catch{return null}}function ds(c){let e=c.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],n=e[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}let t=c.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],n=t[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}return null}async function pr(c){await Oe(["init"],c)}async function hr(c,e,t){await Oe(["remote","add",c,e],t)}var hi=_(()=>{"use strict";u(Oe,"git");u(Sn,"gitStatus");u(li,"gitCreateBranch");u(di,"gitStageAll");u(ui,"gitCommit");u(mi,"gitPush");u(pi,"slugifyBranch");u(ls,"gitGetRemoteUrl");u(ds,"parseRemoteUrl");u(pr,"gitInitRepo");u(hr,"gitAddRemote")});function us(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new fi(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new gi(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var kt,fi,gi,yi=_(()=>{"use strict";kt=class{static{u(this,"ForgeClient")}},fi=class extends kt{static{u(this,"GitHubForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://api.github.com"}async createPullRequest(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/pulls`,r=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({title:t.title,body:t.body,head:t.head,base:t.base})});if(!r.ok){let o=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${o}`)}let n=await r.json();return{id:n.id,url:n.html_url,number:n.number,state:n.state}}async getPipelineStatus(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/commits/${t}/status`,r=await fetch(s,{headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json"}});if(!r.ok)return{state:"unknown"};let o=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[o]??"unknown"}}async createProject(e){let t=`${this.baseUrl}/user/repos`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",private:(e.visibility??"private")==="private"})});if(!s.ok){let n=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},gi=class extends kt{static{u(this,"GitLabForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://gitlab.com"}async createPullRequest(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/merge_requests`,n=await fetch(r,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({title:t.title,description:t.body,source_branch:t.head,target_branch:t.base})});if(!n.ok){let i=await n.text();throw new Error(`GitLab MR creation failed (${n.status}): ${i}`)}let o=await n.json();return{id:o.id,url:o.web_url,number:o.iid,state:o.state}}async getPipelineStatus(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/pipelines?ref=${encodeURIComponent(t)}&per_page=1`,n=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!n.ok)return{state:"unknown"};let o=await n.json();if(o.length===0)return{state:"unknown"};let i=o[0],a=i.status;return{state:{pending:"pending",running:"running",success:"success",failed:"failure",canceled:"failure"}[a]??"unknown",url:i.web_url}}async createProject(e){let t=`${this.baseUrl}/api/v4/projects`,s=await fetch(t,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",visibility:e.visibility??"private"})});if(!s.ok){let n=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(us,"createForgeClient")});function Nl(c,e){return c.length<=e?c:c.slice(0,e)+`
743
- [...truncated]`}function Ll(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function rp(c,e,t){let r=`Available agents:
741
+ `+b.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var qm,zm,xl,Wm,vn=_(()=>{"use strict";qm=3e5,zm=9e5,xl=1e5,Wm=new Set([".git","node_modules",".next","dist",".cache"]);u(Gm,"resolveEnv");u(Vm,"buildArgs");u(kn,"truncateOutput");u(Rl,"snapshotMtimes");u(Km,"detectModifiedFiles");u(mr,"executeAgent")});import{execFile as Xm}from"node:child_process";function Ue(c,e){return new Promise((t,s)=>{Xm("git",c,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,n,o)=>{if(r){let i=o?.trim()||r.message;s(new Error(`git ${c[0]} failed: ${i}`));return}t(n.trim())})})}async function Sn(c){try{let e=await Ue(["rev-parse","--abbrev-ref","HEAD"],c),t=await Ue(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function li(c,e){await Ue(["checkout","-b",c],e)}async function di(c){await Ue(["add","-A"],c)}async function ui(c,e){await Ue(["commit","-m",c],e);let t=await Ue(["rev-parse","--short","HEAD"],e),r=(await Ue(["diff","--stat","HEAD~1","HEAD"],e)).split(`
742
+ `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function mi(c,e,t){await Ue(["push","-u",c,e],t)}function pi(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function ls(c,e){try{return await Ue(["remote","get-url",c],e)}catch{return null}}function ds(c){let e=c.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],n=e[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}let t=c.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],n=t[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}return null}async function pr(c){await Ue(["init"],c)}async function hr(c,e,t){await Ue(["remote","add",c,e],t)}var hi=_(()=>{"use strict";u(Ue,"git");u(Sn,"gitStatus");u(li,"gitCreateBranch");u(di,"gitStageAll");u(ui,"gitCommit");u(mi,"gitPush");u(pi,"slugifyBranch");u(ls,"gitGetRemoteUrl");u(ds,"parseRemoteUrl");u(pr,"gitInitRepo");u(hr,"gitAddRemote")});function us(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new fi(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new gi(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var kt,fi,gi,yi=_(()=>{"use strict";kt=class{static{u(this,"ForgeClient")}},fi=class extends kt{static{u(this,"GitHubForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://api.github.com"}async createPullRequest(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/pulls`,r=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({title:t.title,body:t.body,head:t.head,base:t.base})});if(!r.ok){let o=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${o}`)}let n=await r.json();return{id:n.id,url:n.html_url,number:n.number,state:n.state}}async getPipelineStatus(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/commits/${t}/status`,r=await fetch(s,{headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json"}});if(!r.ok)return{state:"unknown"};let o=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[o]??"unknown"}}async createProject(e){let t=`${this.baseUrl}/user/repos`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",private:(e.visibility??"private")==="private"})});if(!s.ok){let n=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},gi=class extends kt{static{u(this,"GitLabForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://gitlab.com"}async createPullRequest(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/merge_requests`,n=await fetch(r,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({title:t.title,description:t.body,source_branch:t.head,target_branch:t.base})});if(!n.ok){let i=await n.text();throw new Error(`GitLab MR creation failed (${n.status}): ${i}`)}let o=await n.json();return{id:o.id,url:o.web_url,number:o.iid,state:o.state}}async getPipelineStatus(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/pipelines?ref=${encodeURIComponent(t)}&per_page=1`,n=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!n.ok)return{state:"unknown"};let o=await n.json();if(o.length===0)return{state:"unknown"};let i=o[0],a=i.status;return{state:{pending:"pending",running:"running",success:"success",failed:"failure",canceled:"failure"}[a]??"unknown",url:i.web_url}}async createProject(e){let t=`${this.baseUrl}/api/v4/projects`,s=await fetch(t,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",visibility:e.visibility??"private"})});if(!s.ok){let n=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(us,"createForgeClient")});function Nl(c,e){return c.length<=e?c:c.slice(0,e)+`
743
+ [...truncated]`}function Dl(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function rp(c,e,t){let r=`Available agents:
744
744
  ${e.map(a=>`- ${a.name}: command="${a.command}"`).join(`
745
745
  `)}
746
746
 
747
747
  Task:
748
- ${c}`,n=await t.complete({system:tp,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=Ll(n.content);if(!Array.isArray(o.subtasks)||o.subtasks.length===0)throw new Error("LLM returned an empty plan with no subtasks");let i=new Set(e.map(a=>a.name));for(let a of o.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return o}async function np(c,e,t,s){let r=new wi(t),n=[],o=c.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),l=await mr(a,i.prompt,{onProgress:s?m=>s(`[${i.id}] ${m}`):void 0}),d={subtask:i,execution:l};return n.push(d),s?.(`Completed ${i.id}: exit=${l.exitCode}, ${l.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(o),n}async function op(c,e,t){let s=e.map(o=>{let i=Nl(o.execution.stdout,Qm),a=Nl(o.execution.stderr,ep);return[`### ${o.subtask.id} (${o.subtask.description})`,`Agent: ${o.subtask.agent}`,`Exit code: ${o.execution.exitCode}`,`Modified files: ${o.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
748
+ ${c}`,n=await t.complete({system:tp,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=Dl(n.content);if(!Array.isArray(o.subtasks)||o.subtasks.length===0)throw new Error("LLM returned an empty plan with no subtasks");let i=new Set(e.map(a=>a.name));for(let a of o.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return o}async function np(c,e,t,s){let r=new wi(t),n=[],o=c.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),l=await mr(a,i.prompt,{onProgress:s?m=>s(`[${i.id}] ${m}`):void 0}),d={subtask:i,execution:l};return n.push(d),s?.(`Completed ${i.id}: exit=${l.exitCode}, ${l.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(o),n}async function op(c,e,t){let s=e.map(o=>{let i=Nl(o.execution.stdout,Qm),a=Nl(o.execution.stderr,ep);return[`### ${o.subtask.id} (${o.subtask.description})`,`Agent: ${o.subtask.agent}`,`Exit code: ${o.execution.exitCode}`,`Modified files: ${o.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
749
749
  ${i}`:"",a?`stderr:
750
750
  ${a}`:""].filter(Boolean).join(`
751
751
  `)}).join(`
@@ -754,7 +754,7 @@ ${a}`:""].filter(Boolean).join(`
754
754
  ${c}
755
755
 
756
756
  Results:
757
- ${s}`,n=await t.complete({system:sp,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=Ll(n.content);return{approved:o.approved??!0,summary:o.summary??"",fixTasks:Array.isArray(o.fixTasks)?o.fixTasks:[]}}catch{return{approved:!0,summary:n.content,fixTasks:[]}}}async function vt(c,e,t,s={}){let r=Math.min(s.maxIterations??Ym,Jm),n=s.maxConcurrent??Zm,o=s.onProgress,i=Date.now(),a=new Map(e.map(h=>[h.name,h]));o?.("Planning subtasks...");let l=await rp(c,e,t);o?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,p=0,g="";for(;p<r;){p++,o?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let h=await np(m,a,n,o);d=d.concat(h),o?.(`Iteration ${p}: validating results...`);let T=await op(c,d,t);if(g=T.summary,T.approved||T.fixTasks.length===0)break;let b=T.fixTasks.filter(A=>a.has(A.agent)?!0:(o?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if(b.length===0)break;m=b,o?.(`Validation requested ${b.length} fix task(s), iterating...`)}let f=[...new Set(d.flatMap(h=>h.execution.modifiedFiles))].sort();return{plan:l,iterations:p,subtaskResults:d,allModifiedFiles:f,summary:g,totalDurationMs:Date.now()-i}}async function fr(c,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await Sn({cwd:n});if(!i.isRepo)try{await pr({cwd:n}),i=await Sn({cwd:n}),r?.("Initialised new git repository")}catch{return o.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await vt(c,e,t,s),git:o}}let a=null,l=await ls("origin",{cwd:n});if(l){let f=ds(l);f?(a={owner:f.owner,repo:f.repo},r?.(`Detected remote: ${f.owner}/${f.repo} (${f.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let f=us(d),h=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${h}" on forge...`);let T=await f.createProject({name:h,visibility:"private"});await hr("origin",T.cloneUrl,{cwd:n});let b=ds(T.cloneUrl);b&&(a={owner:b.owner,repo:b.repo}),r?.(`Project created: ${T.url} \u2014 remote "origin" set`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`Project creation failed: ${h}`),r?.(`Warning: project creation failed \u2014 ${h}`)}let m=pi(c);try{await li(m,{cwd:n}),o.branch=m,r?.(`Created branch: ${m}`)}catch(f){throw new Error(`Failed to create branch "${m}": ${f instanceof Error?f.message:String(f)}`)}let p=await vt(c,e,t,s);try{await di({cwd:n});let f=`feat: ${c.slice(0,72)}
757
+ ${s}`,n=await t.complete({system:sp,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=Dl(n.content);return{approved:o.approved??!0,summary:o.summary??"",fixTasks:Array.isArray(o.fixTasks)?o.fixTasks:[]}}catch{return{approved:!0,summary:n.content,fixTasks:[]}}}async function vt(c,e,t,s={}){let r=Math.min(s.maxIterations??Ym,Jm),n=s.maxConcurrent??Zm,o=s.onProgress,i=Date.now(),a=new Map(e.map(h=>[h.name,h]));o?.("Planning subtasks...");let l=await rp(c,e,t);o?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,p=0,g="";for(;p<r;){p++,o?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let h=await np(m,a,n,o);d=d.concat(h),o?.(`Iteration ${p}: validating results...`);let T=await op(c,d,t);if(g=T.summary,T.approved||T.fixTasks.length===0)break;let b=T.fixTasks.filter(A=>a.has(A.agent)?!0:(o?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if(b.length===0)break;m=b,o?.(`Validation requested ${b.length} fix task(s), iterating...`)}let f=[...new Set(d.flatMap(h=>h.execution.modifiedFiles))].sort();return{plan:l,iterations:p,subtaskResults:d,allModifiedFiles:f,summary:g,totalDurationMs:Date.now()-i}}async function fr(c,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await Sn({cwd:n});if(!i.isRepo)try{await pr({cwd:n}),i=await Sn({cwd:n}),r?.("Initialised new git repository")}catch{return o.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await vt(c,e,t,s),git:o}}let a=null,l=await ls("origin",{cwd:n});if(l){let f=ds(l);f?(a={owner:f.owner,repo:f.repo},r?.(`Detected remote: ${f.owner}/${f.repo} (${f.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let f=us(d),h=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${h}" on forge...`);let T=await f.createProject({name:h,visibility:"private"});await hr("origin",T.cloneUrl,{cwd:n});let b=ds(T.cloneUrl);b&&(a={owner:b.owner,repo:b.repo}),r?.(`Project created: ${T.url} \u2014 remote "origin" set`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`Project creation failed: ${h}`),r?.(`Warning: project creation failed \u2014 ${h}`)}let m=pi(c);try{await li(m,{cwd:n}),o.branch=m,r?.(`Created branch: ${m}`)}catch(f){throw new Error(`Failed to create branch "${m}": ${f instanceof Error?f.message:String(f)}`)}let p=await vt(c,e,t,s);try{await di({cwd:n});let f=`feat: ${c.slice(0,72)}
758
758
 
759
759
  Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,h=await ui(f,{cwd:n});o.commit=h,r?.(`Committed: ${h.sha} (${h.filesChanged} files changed)`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Commit failed: ${h}`),r?.(`Warning: commit failed \u2014 ${h}`),{...p,git:o}}if(!await ls("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...p,git:o};try{await mi("origin",m,{cwd:n}),r?.(`Pushed branch: ${m}`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Push failed: ${h}`),r?.(`Warning: push failed \u2014 ${h}`),{...p,git:o}}if(d&&a)try{let f=us(d),h=s.baseBranch??d.baseBranch??"main",T=s.prTitle??`feat: ${c.slice(0,72)}`,b=["## Summary",p.summary,"",`**Iterations:** ${p.iterations}`,`**Modified files:** ${p.allModifiedFiles.length}`,p.allModifiedFiles.map(C=>`- \`${C}\``).join(`
760
760
  `),"","_Automated by Alfred_"].join(`
@@ -788,7 +788,7 @@ Respond with ONLY valid JSON (no markdown fences):
788
788
  "fixTasks": [
789
789
  { "id": "fix-1", "agent": "<agent-name>", "prompt": "<detailed fix prompt>", "description": "<short description>" }
790
790
  ]
791
- }`;u(Nl,"truncate");u(Ll,"parseJSON");wi=class{static{u(this,"Semaphore")}max;queue=[];active=0;constructor(e){this.max=e}async acquire(){if(this.active<this.max){this.active++;return}return new Promise(e=>{this.queue.push(()=>{this.active++,e()})})}release(){this.active--;let e=this.queue.shift();e&&e()}};u(rp,"planSubtasks");u(np,"executeSubtasksParallel");u(op,"validateResults");u(vt,"orchestrate");u(fr,"orchestrateWithGit")});var gr,Dl=_(()=>{"use strict";P();vn();Ti();gr=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",category:"automation",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
791
+ }`;u(Nl,"truncate");u(Dl,"parseJSON");wi=class{static{u(this,"Semaphore")}max;queue=[];active=0;constructor(e){this.max=e}async acquire(){if(this.active<this.max){this.active++;return}return new Promise(e=>{this.queue.push(()=>{this.active++,e()})})}release(){this.active--;let e=this.queue.shift();e&&e()}};u(rp,"planSubtasks");u(np,"executeSubtasksParallel");u(op,"validateResults");u(vt,"orchestrate");u(fr,"orchestrateWithGit")});var gr,Ll=_(()=>{"use strict";P();vn();Ti();gr=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",category:"automation",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
792
792
  `);return{success:!0,data:{agents:e},display:`Available code agents:
793
793
  ${t}`}}async runAgent(e,t){let s=e.agent,r=e.prompt;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "agent"'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "prompt"'};let n=this.agents.get(s);if(!n){let d=[...this.agents.keys()].join(", ");return{success:!1,error:`Unknown agent "${s}". Available: ${d}`}}let o=typeof e.cwd=="string"?e.cwd:void 0,i=typeof e.timeout=="number"?e.timeout:void 0,a=await mr(n,r,{cwd:o,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
794
794
  \`\`\`
@@ -809,15 +809,15 @@ ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
809
809
 
810
810
  **Git:**
811
811
  ${s.join(`
812
- `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var Ml=_(()=>{"use strict";Dl();vn();Ti();hi();yi()});var Z={};oe(Z,{ActivityTracker:()=>wt,BMWSkill:()=>Tn,BackgroundTaskSkill:()=>Zt,BrowserSkill:()=>Xt,CalculatorSkill:()=>Mt,CalendarProvider:()=>De,CalendarSkill:()=>Tt,ClipboardSkill:()=>Vt,CodeAgentSkill:()=>gr,CodeExecutionSkill:()=>cr,CodeExecutor:()=>bt,ConfigureSkill:()=>as,ContactsProvider:()=>Me,ContactsSkill:()=>ur,CrossPlatformSkill:()=>Jt,DelegateSkill:()=>qt,DockerSkill:()=>gn,DocumentSkill:()=>es,EmailProvider:()=>Ge,EmailSkill:()=>Ze,EnergyPriceSkill:()=>En,FileSkill:()=>Wt,ForgeClient:()=>kt,HomeAssistantSkill:()=>un,HttpSkill:()=>zt,ImageGenerateSkill:()=>ss,MCPClient:()=>_t,MCPManager:()=>ar,MCPSkillAdapter:()=>Et,MemorySkill:()=>Ht,MicrosoftTodoSkill:()=>$n,MonitorSkill:()=>bn,NoteSkill:()=>Ft,PluginLoader:()=>en,ProfileSkill:()=>Yt,ProxmoxSkill:()=>ln,ReminderSkill:()=>Ut,RoutingSkill:()=>_n,ScheduledTaskSkill:()=>Qt,ScreenshotSkill:()=>Kt,ShellSkill:()=>Bt,Skill:()=>I,SkillRegistry:()=>Lt,SkillSandbox:()=>Dt,SystemInfoSkill:()=>Ot,TTSSkill:()=>ts,TodoSkill:()=>rs,TransitSkill:()=>os,UniFiSkill:()=>dn,WatchSkill:()=>cs,WeatherSkill:()=>jt,WebSearchSkill:()=>Pt,allUserIds:()=>z,createCalendarProvider:()=>ir,createContactsProvider:()=>ti,createEmailProvider:()=>rr,createForgeClient:()=>us,effectiveUserId:()=>te,gitAddRemote:()=>hr,gitGetRemoteUrl:()=>ls,gitInitRepo:()=>pr,orchestrate:()=>vt,orchestrateWithGit:()=>fr,parseRemoteUrl:()=>ds});var Y=_(()=>{"use strict";P();Fe();Qa();ec();Bo();tc();sc();rc();nc();oc();ic();ac();dc();uc();mc();gc();wc();_c();Ec();$c();vc();Sc();Nc();Lc();Dc();Mc();Pc();Fc();jc();Bc();Hc();qc();zc();Gc();Zc();Qc();nl();ul();ml();Tl();_l();$l();kl();vl();Al();Ml()});var yr,_i=_(()=>{"use strict";yr=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 Ve(c,e){let t;if(e.platformUserId)t=c.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=c.findById(e.userId)??c.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in c?c.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in c&&(r=c.getLinkedUsers(s).map(a=>a.platformUserId));let n;try{"getProfile"in c?n=c.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 ms=_(()=>{"use strict";u(Ve,"buildSkillContext")});function Ol(c,e){let t=new Set(["core"]),s=!1;for(let[r,n]of Object.entries(ip))e.has(r)&&n.test(c)&&(t.add(r),s=!0);if(!s)for(let r of e)t.add(r);return t}function Pl(c,e){return c.filter(t=>e.has(t.category??"core"))}var ip,Ul=_(()=>{"use strict";ip={productivity:/\b(todo|note|remind|calendar|termin|event|email|e-mail|mail|contact|kontakt)\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)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat|watch|alert|benachrichtig|bescheid|meld|überwach|monitor|täglich|stündlich|wöchentlich|monatlich|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)|daily|hourly|weekly|every\s+(day|hour|morning|evening|night|\d+\s*min))\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(Ol,"selectCategories");u(Pl,"filterSkills")});import Ei from"node:fs";import Fl from"node:path";var ap,jl,cp,Bl,lp,dp,up,Hl,wr,bi=_(()=>{"use strict";Fo();ms();Ul();ap=15*60*1e3,jl=50,cp=2,Bl=.85,lp=1e5,dp=2e3,up=.1,Hl=3,wr=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;documentProcessor;activeAgents=new Map;agentIdCounter=0;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??100,this.documentProcessor=e.documentProcessor,this.promptBuilder=new Zs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let{user:r,masterUserId:n,linkedPlatformUserIds:o,context:i}=Ve(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),l=this.conversationManager.getHistory(a.id,this.maxHistoryMessages);this.conversationManager.addMessage(a.id,"user",e.text);let d,m=this.isSyntheticLabel(e.text),p=e.attachments?.some(B=>B.type==="audio")??!1,g=m&&!p;if(this.memoryRetriever&&e.text&&!g)try{d=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(B){this.logger.debug({err:B},"Hybrid memory retrieval failed")}if(!d&&this.memoryRepo&&!g)try{let B=[n,...(o??[]).filter(Q=>Q!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let Q=new Set;d=[];for(let se of B)for(let ee of await this.embeddingService.semanticSearch(se,e.text,10))Q.has(ee.key)||(Q.add(ee.key),d.push(ee));for(let se of B)for(let ee of this.memoryRepo.getRecentForPrompt(se,5))Q.has(ee.key)||(Q.add(ee.key),d.push(ee))}else{let Q=new Set;d=[];for(let se of B)for(let ee of this.memoryRepo.getRecentForPrompt(se,20))Q.has(ee.key)||(Q.add(ee.key),d.push(ee))}}catch(B){this.logger.debug({err:B},"Memory loading failed")}d&&d.length>0&&(d=this.applyMemoryBudget(d));let f;try{"getProfile"in this.users&&(f=this.users.getProfile(n),f&&!f.displayName&&(f.displayName=r.displayName??r.username))}catch(B){this.logger.debug({err:B},"Profile loading failed")}let h=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,T=this.skillRegistry?this.skillRegistry.getAll().map(B=>B.metadata):void 0,b=T;if(T&&e.text){let B=new Set(T.map(se=>se.category??"core")),Q=Ol(e.text,B);b=Pl(T,Q)}let A=b?this.promptBuilder.buildTools(b):void 0,C=this.promptBuilder.buildSystemPrompt({memories:d,skills:b,userProfile:f}),U=this.buildActiveAgentStatus();U&&(C+=`
812
+ `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var Ml=_(()=>{"use strict";Ll();vn();Ti();hi();yi()});var Z={};ie(Z,{ActivityTracker:()=>wt,BMWSkill:()=>Tn,BackgroundTaskSkill:()=>Zt,BrowserSkill:()=>Xt,CalculatorSkill:()=>Mt,CalendarProvider:()=>Le,CalendarSkill:()=>Tt,ClipboardSkill:()=>Vt,CodeAgentSkill:()=>gr,CodeExecutionSkill:()=>cr,CodeExecutor:()=>bt,ConfigureSkill:()=>as,ContactsProvider:()=>Pe,ContactsSkill:()=>ur,CrossPlatformSkill:()=>Jt,DelegateSkill:()=>qt,DockerSkill:()=>gn,DocumentSkill:()=>es,EmailProvider:()=>Ve,EmailSkill:()=>Qe,EnergyPriceSkill:()=>En,FileSkill:()=>Wt,ForgeClient:()=>kt,HomeAssistantSkill:()=>un,HttpSkill:()=>zt,ImageGenerateSkill:()=>ss,MCPClient:()=>_t,MCPManager:()=>ar,MCPSkillAdapter:()=>Et,MemorySkill:()=>Ht,MicrosoftTodoSkill:()=>$n,MonitorSkill:()=>bn,NoteSkill:()=>Ft,PluginLoader:()=>en,ProfileSkill:()=>Yt,ProxmoxSkill:()=>ln,ReminderSkill:()=>Ut,RoutingSkill:()=>_n,ScheduledTaskSkill:()=>Qt,ScreenshotSkill:()=>Kt,ShellSkill:()=>Bt,Skill:()=>I,SkillRegistry:()=>Dt,SkillSandbox:()=>Lt,SystemInfoSkill:()=>Ot,TTSSkill:()=>ts,TodoSkill:()=>rs,TransitSkill:()=>os,UniFiSkill:()=>dn,WatchSkill:()=>cs,WeatherSkill:()=>jt,WebSearchSkill:()=>Pt,allUserIds:()=>z,createCalendarProvider:()=>ir,createContactsProvider:()=>ti,createEmailProvider:()=>rr,createForgeClient:()=>us,effectiveUserId:()=>te,gitAddRemote:()=>hr,gitGetRemoteUrl:()=>ls,gitInitRepo:()=>pr,orchestrate:()=>vt,orchestrateWithGit:()=>fr,parseRemoteUrl:()=>ds});var Y=_(()=>{"use strict";P();Be();Qa();ec();Bo();tc();sc();rc();nc();oc();ic();ac();dc();uc();mc();gc();wc();_c();Ec();$c();vc();Sc();Nc();Dc();Lc();Mc();Pc();Fc();jc();Bc();Hc();qc();zc();Gc();Zc();Qc();nl();ul();ml();Tl();_l();$l();kl();vl();Al();Ml()});var yr,_i=_(()=>{"use strict";yr=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 Ke(c,e){let t;if(e.platformUserId)t=c.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=c.findById(e.userId)??c.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in c?c.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in c&&(r=c.getLinkedUsers(s).map(a=>a.platformUserId));let n;try{"getProfile"in c?n=c.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 ms=_(()=>{"use strict";u(Ke,"buildSkillContext")});function Ol(c,e){let t=new Set(["core"]),s=!1;for(let[r,n]of Object.entries(ip))e.has(r)&&n.test(c)&&(t.add(r),s=!0);if(!s)for(let r of e)t.add(r);return t}function Pl(c,e){return c.filter(t=>e.has(t.category??"core"))}var ip,Ul=_(()=>{"use strict";ip={productivity:/\b(todo|note|remind|calendar|termin|event|email|e-mail|mail|contact|kontakt)\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)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat|watch|alert|benachrichtig|bescheid|meld|überwach|monitor|täglich|stündlich|wöchentlich|monatlich|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)|daily|hourly|weekly|every\s+(day|hour|morning|evening|night|\d+\s*min))\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(Ol,"selectCategories");u(Pl,"filterSkills")});import Ei from"node:fs";import Fl from"node:path";var ap,jl,cp,Bl,lp,dp,up,Hl,wr,bi=_(()=>{"use strict";Fo();ms();Ul();ap=15*60*1e3,jl=50,cp=2,Bl=.85,lp=1e5,dp=2e3,up=.1,Hl=3,wr=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;documentProcessor;activeAgents=new Map;agentIdCounter=0;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??100,this.documentProcessor=e.documentProcessor,this.promptBuilder=new Zs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let{user:r,masterUserId:n,linkedPlatformUserIds:o,context:i}=Ke(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),l=this.conversationManager.getHistory(a.id,this.maxHistoryMessages);this.conversationManager.addMessage(a.id,"user",e.text);let d,m=this.isSyntheticLabel(e.text),p=e.attachments?.some(B=>B.type==="audio")??!1,g=m&&!p;if(this.memoryRetriever&&e.text&&!g)try{d=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(B){this.logger.debug({err:B},"Hybrid memory retrieval failed")}if(!d&&this.memoryRepo&&!g)try{let B=[n,...(o??[]).filter(Q=>Q!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let Q=new Set;d=[];for(let se of B)for(let ee of await this.embeddingService.semanticSearch(se,e.text,10))Q.has(ee.key)||(Q.add(ee.key),d.push(ee));for(let se of B)for(let ee of this.memoryRepo.getRecentForPrompt(se,5))Q.has(ee.key)||(Q.add(ee.key),d.push(ee))}else{let Q=new Set;d=[];for(let se of B)for(let ee of this.memoryRepo.getRecentForPrompt(se,20))Q.has(ee.key)||(Q.add(ee.key),d.push(ee))}}catch(B){this.logger.debug({err:B},"Memory loading failed")}d&&d.length>0&&(d=this.applyMemoryBudget(d));let f;try{"getProfile"in this.users&&(f=this.users.getProfile(n),f&&!f.displayName&&(f.displayName=r.displayName??r.username))}catch(B){this.logger.debug({err:B},"Profile loading failed")}let h=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,T=this.skillRegistry?this.skillRegistry.getAll().map(B=>B.metadata):void 0,b=T;if(T&&e.text){let B=new Set(T.map(se=>se.category??"core")),Q=Ol(e.text,B);b=Pl(T,Q)}let A=b?this.promptBuilder.buildTools(b):void 0,C=this.promptBuilder.buildSystemPrompt({memories:d,skills:b,userProfile:f}),U=this.buildActiveAgentStatus();U&&(C+=`
813
813
 
814
- `+U);let x=this.promptBuilder.buildMessages(l),V=this.collapseRepeatedToolErrors(x),be=await this.buildUserContent(e,t);V.push({role:"user",content:be});let he=A?Le(JSON.stringify(A)):0,ce=1,le=this.trimToContextWindow(C,V,he,ce),W,fe=0,ge=Date.now(),de="",re=0,N=0,G=0,$e=[];for(t?.("Thinking...");;){fe>0&&this.compressToolLoop(le,C,he);try{W=await this.llm.complete({messages:le,system:C,tools:A&&A.length>0?A:void 0}),N+=W.usage?.inputTokens??0,G+=W.usage?.outputTokens??0}catch(ke){if((ke instanceof Error?ke.message:String(ke)).includes("prompt is too long")&&ce>.3){ce*=.5,this.logger.warn({budgetMultiplier:ce},"Prompt too long, retrimming with reduced budget"),le=this.trimToContextWindow(C,V,he,ce);continue}throw ke}if(!W.toolCalls||W.toolCalls.length===0)break;let B=Date.now()-ge;if(B>=ap){let ke=Math.round(B/6e4);this.logger.warn({iteration:fe,elapsedMin:ke,pendingToolCalls:W.toolCalls.length},"Tool loop timeout reached"),W=await this.abortToolLoop(le,W,a.id,C,`Das Zeitlimit von ${ke} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(fe>=jl){this.logger.warn({iteration:fe,pendingToolCalls:W.toolCalls.length},"Tool loop iteration cap reached"),W=await this.abortToolLoop(le,W,a.id,C,`Das Iterationslimit von ${jl} Tool-Aufrufen wurde erreicht.`);break}fe++,this.logger.info({iteration:fe,toolCalls:W.toolCalls.length},"Processing tool calls");let Q=[];W.content&&Q.push({type:"text",text:W.content});for(let ke of W.toolCalls)Q.push({type:"tool_use",id:ke.id,name:ke.name,input:ke.input});le.push({role:"assistant",content:Q});let se=await this.executeToolCallsParallel(W.toolCalls,{...i,conversationId:a.id,timezone:h},t),ee=se.blocks;se.attachments.length>0&&$e.push(...se.attachments),this.conversationManager.addMessage(a.id,"assistant",W.content??"",JSON.stringify(W.toolCalls)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(ee));let It=this.buildErrorSignature(ee);if(It){if(It===de?re++:(re=1,de=It),re>=cp){this.logger.warn({iteration:fe,consecutiveErrors:re,errorSignature:It},"Tool loop aborted: same error repeated consecutively"),W=await this.abortToolLoop(le,W,a.id,C,`Der gleiche Tool-Fehler ist ${re}x hintereinander aufgetreten: "${de.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else re=0,de="";le.push({role:"user",content:ee}),t?.("Thinking...")}let J=W.content;if(!J)for(let B=le.length-1;B>=0;B--){let Q=le[B];if(Q.role==="assistant"&&Array.isArray(Q.content)){let se=Q.content.find(ee=>ee.type==="text");if(se&&"text"in se&&se.text){J=se.text;break}}}J||(J="(no response)"),this.conversationManager.addMessage(a.id,"assistant",J),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,J);let fs=Date.now()-s;return this.logger.info({duration:fs,tokens:W.usage,totalTokens:{inputTokens:N,outputTokens:G},stopReason:W.stopReason,toolIterations:fe},"Message processed"),{text:J,attachments:$e.length>0?$e:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let l=[];t.content&&l.push({type:"text",text:t.content});for(let d of t.toolCalls)l.push({type:"tool_use",id:d.id,name:d.name,input:d.input});e.push({role:"assistant",content:l})}let i=t.toolCalls.map(l=>({type:"tool_result",tool_use_id:l.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i));let a=e[e.length-1];return a&&a.role==="user"&&Array.isArray(a.content)?a.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})}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 l=e[a],d=e[a+1];if(l.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(l,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 g=p.content;if(p.attachments&&p.attachments.length>0){r.push(...p.attachments);let f=p.attachments.map(h=>h.fileName).join(", ");g+=`
814
+ `+U);let x=this.promptBuilder.buildMessages(l),V=this.collapseRepeatedToolErrors(x),Te=await this.buildUserContent(e,t);V.push({role:"user",content:Te});let he=A?De(JSON.stringify(A)):0,le=1,re=this.trimToContextWindow(C,V,he,le),W,fe=0,ge=Date.now(),de="",ne=0,N=0,G=0,$e=[];for(t?.("Thinking...");;){fe>0&&this.compressToolLoop(re,C,he);try{W=await this.llm.complete({messages:re,system:C,tools:A&&A.length>0?A:void 0}),N+=W.usage?.inputTokens??0,G+=W.usage?.outputTokens??0}catch(ke){if((ke instanceof Error?ke.message:String(ke)).includes("prompt is too long")&&le>.3){le*=.5,this.logger.warn({budgetMultiplier:le},"Prompt too long, retrimming with reduced budget"),re=this.trimToContextWindow(C,V,he,le);continue}throw ke}if(!W.toolCalls||W.toolCalls.length===0)break;let B=Date.now()-ge;if(B>=ap){let ke=Math.round(B/6e4);this.logger.warn({iteration:fe,elapsedMin:ke,pendingToolCalls:W.toolCalls.length},"Tool loop timeout reached"),W=await this.abortToolLoop(re,W,a.id,C,`Das Zeitlimit von ${ke} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(fe>=jl){this.logger.warn({iteration:fe,pendingToolCalls:W.toolCalls.length},"Tool loop iteration cap reached"),W=await this.abortToolLoop(re,W,a.id,C,`Das Iterationslimit von ${jl} Tool-Aufrufen wurde erreicht.`);break}fe++,this.logger.info({iteration:fe,toolCalls:W.toolCalls.length},"Processing tool calls");let Q=[];W.content&&Q.push({type:"text",text:W.content});for(let ke of W.toolCalls)Q.push({type:"tool_use",id:ke.id,name:ke.name,input:ke.input});re.push({role:"assistant",content:Q});let se=await this.executeToolCallsParallel(W.toolCalls,{...i,conversationId:a.id,timezone:h},t),ee=se.blocks;se.attachments.length>0&&$e.push(...se.attachments),this.conversationManager.addMessage(a.id,"assistant",W.content??"",JSON.stringify(W.toolCalls)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(ee));let It=this.buildErrorSignature(ee);if(It){if(It===de?ne++:(ne=1,de=It),ne>=cp){this.logger.warn({iteration:fe,consecutiveErrors:ne,errorSignature:It},"Tool loop aborted: same error repeated consecutively"),W=await this.abortToolLoop(re,W,a.id,C,`Der gleiche Tool-Fehler ist ${ne}x hintereinander aufgetreten: "${de.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else ne=0,de="";re.push({role:"user",content:ee}),t?.("Thinking...")}let J=W.content;if(!J)for(let B=re.length-1;B>=0;B--){let Q=re[B];if(Q.role==="assistant"&&Array.isArray(Q.content)){let se=Q.content.find(ee=>ee.type==="text");if(se&&"text"in se&&se.text){J=se.text;break}}}J||(J="(no response)"),this.conversationManager.addMessage(a.id,"assistant",J),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,J);let fs=Date.now()-s;return this.logger.info({duration:fs,tokens:W.usage,totalTokens:{inputTokens:N,outputTokens:G},stopReason:W.stopReason,toolIterations:fe},"Message processed"),{text:J,attachments:$e.length>0?$e:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let l=[];t.content&&l.push({type:"text",text:t.content});for(let d of t.toolCalls)l.push({type:"tool_use",id:d.id,name:d.name,input:d.input});e.push({role:"assistant",content:l})}let i=t.toolCalls.map(l=>({type:"tool_result",tool_use_id:l.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i));let a=e[e.length-1];return a&&a.role==="user"&&Array.isArray(a.content)?a.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})}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 l=e[a],d=e[a+1];if(l.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(l,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 g=p.content;if(p.attachments&&p.attachments.length>0){r.push(...p.attachments);let f=p.attachments.map(h=>h.fileName).join(", ");g+=`
815
815
 
816
816
  [${p.attachments.length} Datei(en) werden dem User gesendet: ${f}]`}return{type:"tool_result",tool_use_id:m.id,content:g,is_error:p.isError}},"buildBlock");if(e.length===1){let m=e[0],p=this.getToolLabel(m.name,m.input);s?.(p);let g=await this.executeToolCall(m,t,s);return{blocks:[n(m,g)],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,g=i.get(p);g||(g=[],i.set(p,g)),g.push(m)}let a=[...i.values()].some(m=>m.length>o),l;if(a){l=new Map;let m=[...i.entries()].map(async([p,g])=>{for(let f=0;f<g.length;f+=o){let h=g.slice(f,f+o),T=await Promise.allSettled(h.map(b=>this.executeToolCall(e[b],t,s)));for(let b=0;b<h.length;b++)l.set(h[b],T[b])}});await Promise.all(m)}else{let m=await Promise.allSettled(e.map(p=>this.executeToolCall(p,t,s)));l=new Map(m.map((p,g)=>[g,p]))}return{blocks:e.map((m,p)=>{let g=l.get(p);return g.status==="fulfilled"?n(m,g.value):{type:"tool_result",tool_use_id:m.id,content:`Tool execution failed: ${g.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.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"),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(Y(),Z));n=new a(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;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,n);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){return{content:`Skill execution failed: ${n instanceof Error?n.message:String(n)}`,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(`
817
- `)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=up));let r=0,n=[];for(let o of s){let i=Le(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>dp)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*Bl);if(Le(t)+s+e.reduce((h,T)=>h+Qs(T),0)<=n)return;let a=[];for(let h=0;h<e.length-1;h++){let T=e[h],b=e[h+1];T.role==="assistant"&&Array.isArray(T.content)&&T.content.some(A=>A.type==="tool_use")&&b.role==="user"&&Array.isArray(b.content)&&b.content.some(A=>A.type==="tool_result")&&a.push({start:h,end:h+1})}if(a.length<=Hl)return;let l=a.length-Hl,d=a.slice(0,l),m=[];for(let h of d){let T=e[h.start],b=[];if(Array.isArray(T.content))for(let U of T.content)U.type==="tool_use"&&b.push(U.name);let A=e[h.end],C="ok";Array.isArray(A.content)&&A.content.some(x=>x.type==="tool_result"&&x.is_error)&&(C="error"),m.push(`- ${b.join(", ")}: ${C}`)}let p=d[0].start,f=d[d.length-1].end-p+1;e.splice(p,f,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
817
+ `)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=up));let r=0,n=[];for(let o of s){let i=De(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>dp)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*Bl);if(De(t)+s+e.reduce((h,T)=>h+Qs(T),0)<=n)return;let a=[];for(let h=0;h<e.length-1;h++){let T=e[h],b=e[h+1];T.role==="assistant"&&Array.isArray(T.content)&&T.content.some(A=>A.type==="tool_use")&&b.role==="user"&&Array.isArray(b.content)&&b.content.some(A=>A.type==="tool_result")&&a.push({start:h,end:h+1})}if(a.length<=Hl)return;let l=a.length-Hl,d=a.slice(0,l),m=[];for(let h of d){let T=e[h.start],b=[];if(Array.isArray(T.content))for(let U of T.content)U.type==="tool_use"&&b.push(U.name);let A=e[h.end],C="ok";Array.isArray(A.content)&&A.content.some(x=>x.type==="tool_result"&&x.is_error)&&(C="error"),m.push(`- ${b.join(", ")}: ${C}`)}let p=d[0].start,f=d[d.length-1].end-p+1;e.splice(p,f,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
818
818
  ${m.join(`
819
819
  `)}
820
- ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:f-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let n=this.llm.getContextWindow(),o=Math.floor(n.maxInputTokens*Bl*r),i=Le(e)+s,a=t[t.length-1],l=Qs(a),m=i+l+200+500,p=o-m;if(p<=0)return this.logger.warn({maxInputTokens:o,systemTokens:i,latestTokens:l},"Context window very tight, sending only latest message"),[a];let g=t.slice(0,-1),f=this.groupToolPairs(g),h=[];for(let A=f.length-1;A>=0;A--){let C=f[A].reduce((U,x)=>U+Qs(x),0);if(C>p)break;p-=C,h.unshift(f[A])}let T=h.flat(),b=g.length-T.length;if(b>0){this.logger.info({trimmedCount:b,totalMessages:t.length,maxInputTokens:o},"Trimmed conversation history to fit context window");let A=g.slice(0,g.length-T.length),C=this.summarizeTrimmedMessages(A);T.unshift({role:"user",content:`[Earlier conversation summary \u2014 ${b} messages were trimmed to fit the context window:
820
+ ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:f-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let n=this.llm.getContextWindow(),o=Math.floor(n.maxInputTokens*Bl*r),i=De(e)+s,a=t[t.length-1],l=Qs(a),m=i+l+200+500,p=o-m;if(p<=0)return this.logger.warn({maxInputTokens:o,systemTokens:i,latestTokens:l},"Context window very tight, sending only latest message"),[a];let g=t.slice(0,-1),f=this.groupToolPairs(g),h=[];for(let A=f.length-1;A>=0;A--){let C=f[A].reduce((U,x)=>U+Qs(x),0);if(C>p)break;p-=C,h.unshift(f[A])}let T=h.flat(),b=g.length-T.length;if(b>0){this.logger.info({trimmedCount:b,totalMessages:t.length,maxInputTokens:o},"Trimmed conversation history to fit context window");let A=g.slice(0,g.length-T.length),C=this.summarizeTrimmedMessages(A);T.unshift({role:"user",content:`[Earlier conversation summary \u2014 ${b} messages were trimmed to fit the context window:
821
821
  ${C}
822
822
 
823
823
  The conversation continues below with the most recent messages.]`})}return T.push(a),this.promptBuilder.sanitizeToolMessages(T)}summarizeTrimmedMessages(e){let t=[];for(let r of e){let n=this.extractMessageText(r);if(!n)continue;let o=n.length>150?n.slice(0,150)+"...":n,i=r.role==="user"?"User":"Assistant";if(t.push(`- ${i}: ${o}`),r.role==="assistant"&&Array.isArray(r.content)){for(let a of r.content)if(a.type==="tool_use"){let l=JSON.stringify(a.input).slice(0,80);t.push(` \u2192 Tool: ${a.name}(${l})`)}}}let s=40;if(t.length>s){let r=t.slice(0,s);return r.push(` ... and ${t.length-s} more interactions`),r.join(`
@@ -831,18 +831,18 @@ ${m}`}if(this.documentProcessor&&this.isIngestable(i.mimeType))try{let m=await t
831
831
  [IMPORTANT: This document is already indexed (${m.chunkCount} chunks). To read or answer questions about it, use the "document" skill with action "search" and a relevant query. Do NOT use shell/file tools to read the PDF.]`}else d+=`
832
832
  [IMPORTANT: Document has been indexed (${m.chunkCount} chunks). To read or answer questions about it, use the "document" skill with action "search" and a relevant query. Do NOT use shell/file tools to read the PDF.]`}catch(m){this.logger.warn({err:m,fileName:i.fileName},"Auto-ingest failed")}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");if(r.some(i=>i.type==="image")&&!o)r.push({type:"text",text:"What do you see in this image?"});else if(n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))){let i=r.some(l=>l.type==="text"&&l.text.includes("document is already indexed")),a=r.some(l=>l.type==="text"&&l.text.includes("Document has been indexed"));i||a?r.push({type:"text",text:"The user sent this document. It has been automatically indexed. Acknowledge receipt and tell the user the document is ready \u2014 they can ask questions about its content anytime."}):r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."})}else r.length===0&&r.push({type:"text",text:e.text||"(empty message)"});return r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??Fl.resolve("./data/inbox");try{Ei.mkdirSync(t,{recursive:!0})}catch{this.logger.error({inboxDir:t},"Cannot create inbox directory");return}let s=new Date().toISOString().replace(/[:.]/g,"-"),n=(e.fileName??`file_${s}`).replace(/[<>:"/\\|?*]/g,"_"),o=`${s}_${n}`,i=Fl.join(t,o);try{return Ei.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isIngestable(e){return e?["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/msword","text/plain","text/csv","text/markdown","text/html","application/json","application/xml"].includes(e)||e.startsWith("text/"):!1}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Tr,$i=_(()=>{"use strict";Tr=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,n){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=n,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{let s=`\u23F0 Reminder: ${t.message}`;if(await this.sendMessage(t.platform,t.chatId,s),this.linkedUsers)try{let r=this.linkedUsers.getMasterUserId(t.userId),n=this.linkedUsers.getLinkedUsers(r);for(let o of n){if(o.platform===t.platform)continue;let i=this.linkedUsers.findConversation(o.platform,o.id);i&&await this.sendMessage(o.platform,i.chatId,s)}}catch(r){this.logger.debug({err:r,reminderId:t.id},"Cross-platform reminder delivery failed")}this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var _r,ki=_(()=>{"use strict";_r=class{static{u(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var Er,vi=_(()=>{"use strict";Er=class{static{u(this,"SpeechSynthesizer")}logger;apiKey;baseUrl;model;voice;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,this.baseUrl=e.baseUrl??"https://api.openai.com/v1",this.model=e.ttsModel??"tts-1",this.voice=e.ttsVoice??"alloy"}async synthesize(e){this.logger.info({textLength:e.length,model:this.model,voice:this.voice},"Synthesizing speech");let t=await fetch(`${this.baseUrl}/audio/speech`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:this.model,input:e,voice:this.voice,response_format:"opus"})});if(!t.ok){let r=await t.text();throw new Error(`TTS failed: ${t.status} ${r}`)}let s=Buffer.from(await t.arrayBuffer());return this.logger.info({audioBytes:s.length},"Speech synthesized"),s}}});var br,Si=_(()=>{"use strict";br=class{static{u(this,"ImageGenerator")}config;logger;constructor(e,t){this.config=e,this.logger=t}async generate(e,t={}){return this.logger.info({provider:this.config.provider,model:t.model,size:t.size},"Generating image"),this.config.provider==="openai"?this.generateOpenAI(e,t):this.generateGoogle(e,t)}async generateOpenAI(e,t){let{default:s}=await import("openai"),r=new s({apiKey:this.config.apiKey,...this.config.baseUrl&&{baseURL:this.config.baseUrl}}),n=t.model??"gpt-image-1",i=(await r.images.generate({model:n,prompt:e,n:1,size:t.size??"1024x1024",quality:t.quality??"medium"})).data?.[0]?.b64_json;if(!i)throw new Error("OpenAI image generation returned no data");let a=Buffer.from(i,"base64");return this.logger.info({model:n,bytes:a.length},"Image generated via OpenAI"),{data:a,mimeType:"image/png"}}async generateGoogle(e,t){let{GoogleGenAI:s}=await import("@google/genai"),r=new s({apiKey:this.config.apiKey}),n=t.model??"gemini-2.0-flash-exp",a=(await r.models.generateContent({model:n,contents:[{role:"user",parts:[{text:e}]}],config:{responseModalities:["IMAGE","TEXT"]}})).candidates?.[0]?.content?.parts?.find(m=>m.inlineData?.mimeType?.startsWith("image/"));if(!a?.inlineData)throw new Error("Google image generation returned no image data");let l=Buffer.from(a.inlineData.data,"base64"),d=a.inlineData.mimeType??"image/png";return this.logger.info({model:n,bytes:l.length,mimeType:d},"Image generated via Google"),{data:l,mimeType:d}}}});var $r,Ai=_(()=>{"use strict";$r=class{static{u(this,"TransitClient")}logger;hafasClient;constructor(e){this.logger=e}async getClient(){if(this.hafasClient)return this.hafasClient;let{createClient:e}=await import("hafas-client"),{profile:t}=await import("hafas-client/p/oebb/index.js");return this.hafasClient=e(t,"alfred-ai-assistant"),this.hafasClient}async searchStops(e){return(await(await this.getClient()).locations(e,{results:10})).filter(r=>r.type==="stop"||r.type==="station").map(r=>({id:r.id,name:r.name,location:r.location?{latitude:r.location.latitude,longitude:r.location.longitude}:void 0}))}async journeys(e,t,s){let r=await this.getClient(),n={results:s?.results??3};return s?.departure&&(n.departure=s.departure),s?.arrival&&(n.arrival=s.arrival),((await r.journeys(e,t,n)).journeys||[]).map(i=>{let a=(i.legs||[]).map(f=>({origin:f.origin?.name||f.origin?.id||"Unknown",destination:f.destination?.name||f.destination?.id||"Unknown",departure:f.departure||f.plannedDeparture||"",arrival:f.arrival||f.plannedArrival||"",line:f.line?.name,direction:f.direction,mode:f.line?.mode||(f.walking?"walking":"unknown"),walking:f.walking===!0})),l=a[0]?.departure||"",d=a[a.length-1]?.arrival||"",m=l&&d?Math.round((new Date(d).getTime()-new Date(l).getTime())/6e4):0,p=a.filter(f=>!f.walking),g=Math.max(0,p.length-1);return{legs:a,departure:l,arrival:d,duration:m,transfers:g}})}async departures(e,t){let s=await this.getClient(),r={duration:t?.duration??30};t?.when&&(r.when=t.when);let n=await s.departures(e,r);return(n.departures||n||[]).map(o=>{let i=o.plannedWhen?new Date(o.plannedWhen):null,a=o.when?new Date(o.when):null,l=i&&a?Math.round((a.getTime()-i.getTime())/6e4):o.delay!=null?Math.round(o.delay/60):void 0;return{line:o.line?.name||o.line?.fahrtNr||"Unknown",direction:o.direction||o.destination?.name||"Unknown",when:o.when||o.plannedWhen||"",delay:l&&l>0?l:void 0,platform:o.platform||void 0}})}}});var kr,Ii=_(()=>{"use strict";kr=class{static{u(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t=t.replace(/<(?!\/?(?:b|i|s|u|a|pre|code|tg-spoiler|tg-emoji|blockquote)(?:[\s>\/]|$))/gi,"&lt;"),t}toMatrixHTML(e){return this.toTelegramHTML(e)}toWhatsApp(e){let t=e;return 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(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}});var vr,xi=_(()=>{"use strict";vr=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 l=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:l}});return o.sort((a,l)=>l.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 mp}from"node:crypto";var Sr,Ri=_(()=>{"use strict";Sr=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=mp("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 l=await this.extractText(t,r),d=n.statSync(t),m=this.docRepo.createDocument(e,s,r,d.size,i),p=this.chunkText(l,500,50);for(let g=0;g<p.length;g++){let f;try{f=await this.embeddingService.embedAndStore(e,p[g],"document",`${m.id}:${g}`)}catch(h){this.logger.warn({documentId:m.id,chunkIndex:g,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(m.id,g,p[g],f)}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 l=a+n;if(l>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(l-200,a),m=e.slice(d,l+200),p=m.lastIndexOf(`
833
833
 
834
- `);if(p>0)l=d+p;else{let f=m.lastIndexOf(". ");f>0&&(l=d+f+1)}let g=e.slice(a,l).trim();g&&i.push(g),a=l-o}return i.filter(l=>l.length>0)}}});var Ar,Ci=_(()=>{"use strict";ms();Ar=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n,o){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}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.getPending(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){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(l){this.logger.warn({taskId:e.id,err:l},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:r}=Ve(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=new Promise((l,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let l=o.success?`\u2705 Background task completed: ${e.description}
834
+ `);if(p>0)l=d+p;else{let f=m.lastIndexOf(". ");f>0&&(l=d+f+1)}let g=e.slice(a,l).trim();g&&i.push(g),a=l-o}return i.filter(l=>l.length>0)}}});var Ar,Ci=_(()=>{"use strict";ms();Ar=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n,o){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}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.getPending(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){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(l){this.logger.warn({taskId:e.id,err:l},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let{context:r}=Ke(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=new Promise((l,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let l=o.success?`\u2705 Background task completed: ${e.description}
835
835
 
836
836
  Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${e.description}
837
837
 
838
838
  Error: ${o.error}`;await a.sendMessage(e.chatId,l)}}catch(t){let s=t instanceof Error?t.message:String(t);this.taskRepo.updateStatus(e.id,"failed",void 0,s),this.logger.error({taskId:e.id,err:t},"Background task failed");let r=this.adapters.get(e.platform);r&&await r.sendMessage(e.chatId,`\u274C Background task failed: ${e.description}
839
839
 
840
- Error: ${s}`)}}}});import pp from"node:crypto";var Ir,Ni=_(()=>{"use strict";ms();Ir=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,l,d){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.users=o,this.logger=i,this.pipeline=a,this.formatter=l,this.conversationManager=d}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s;if(e.promptTemplate&&this.pipeline)try{let d=`scheduled-${e.id}`,m={id:`scheduled-${pp.randomUUID()}`,platform:e.platform,chatId:d,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},p=await this.pipeline.process(m);s=(this.formatter?this.formatter.format(p.text,e.platform):{text:p.text,parseMode:"text"}).text;let f=this.adapters.get(e.platform);if(f&&p.attachments)for(let h of p.attachments)try{let T=h.mimeType.startsWith("image/"),b=h.mimeType==="audio/ogg"||h.mimeType==="audio/opus";T?await f.sendPhoto(e.chatId,h.data,h.fileName):b?await f.sendVoice(e.chatId,h.data):await f.sendFile(e.chatId,h.data,h.fileName)}catch(T){this.logger.warn({err:T,fileName:h.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else{let d=this.skillRegistry.get(e.skillName);if(!d)this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;else try{let m;try{m=JSON.parse(e.skillInput)}catch{m={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:p}=Ve(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),g=await this.skillSandbox.execute(d,m,p);s=g.success?`\u{1F514} Scheduled: ${e.name}
840
+ Error: ${s}`)}}}});import pp from"node:crypto";var Ir,Ni=_(()=>{"use strict";ms();Ir=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,l,d){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.users=o,this.logger=i,this.pipeline=a,this.formatter=l,this.conversationManager=d}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s;if(e.promptTemplate&&this.pipeline)try{let d=`scheduled-${e.id}`,m={id:`scheduled-${pp.randomUUID()}`,platform:e.platform,chatId:d,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},p=await this.pipeline.process(m);s=(this.formatter?this.formatter.format(p.text,e.platform):{text:p.text,parseMode:"text"}).text;let f=this.adapters.get(e.platform);if(f&&p.attachments)for(let h of p.attachments)try{let T=h.mimeType.startsWith("image/"),b=h.mimeType==="audio/ogg"||h.mimeType==="audio/opus";T?await f.sendPhoto(e.chatId,h.data,h.fileName):b?await f.sendVoice(e.chatId,h.data):await f.sendFile(e.chatId,h.data,h.fileName)}catch(T){this.logger.warn({err:T,fileName:h.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else{let d=this.skillRegistry.get(e.skillName);if(!d)this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;else try{let m;try{m=JSON.parse(e.skillInput)}catch{m={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:p}=Ke(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),g=await this.skillSandbox.execute(d,m,p);s=g.success?`\u{1F514} Scheduled: ${e.name}
841
841
 
842
842
  ${g.display??JSON.stringify(g.data)}`:`\u274C Scheduled action "${e.name}" failed: ${g.error}`}catch(m){let p=m instanceof Error?m.message:String(m);s=`\u274C Scheduled action "${e.name}" failed: ${p}`}}let r=s.trim(),n=(e.promptTemplate??"").toLowerCase(),o=/nichts|silent|no\s*output|don't\s*respond|do\s*not\s*respond/i.test(n),i=/offline|down|fehler|error|warn|critical|alert|fail|nicht\s+(erreichbar|verf[uü]gbar|gefunden|online)|ausgefallen|stopped|unreachable|unavailable|⚠|❌|🚨|🔴/i.test(r)&&!/keine\s+(probleme|fehler|auff[aä]lligkeiten)/i.test(r);if(!r||r.length<3||o&&!i)this.logger.info({actionId:e.id,name:e.name},"Scheduled action produced no actionable output \u2014 skipping notification");else{let d=this.adapters.get(e.platform);if(d)try{if(await d.sendMessage(e.chatId,s),e.promptTemplate&&this.conversationManager){let m=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,e.userId),p=`[Automated Scheduled Alert: ${e.name}]
843
- ${s}`;this.conversationManager.addMessage(m.id,"assistant",p)}}catch(m){this.logger.error({err:m,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let d=`scheduled-${e.id}`,m=this.conversationManager.getOrCreateConversation(e.platform,d,e.userId);this.conversationManager.pruneMessages(m.id,20)}catch{}let l=this.calculateNextRun(e);l?this.actionRepo.updateLastRun(e.id,t,l):(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 ql(c,e){let t=e.split("."),s=c;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 zl(c,e,t,s){let r=hp(c);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=ps(c),o=ps(t);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o,displayValue:r}}case"eq":return{triggered:String(c)===String(t),displayValue:r};case"neq":return{triggered:String(c)!==String(t),displayValue:r};case"contains":return{triggered:String(c).includes(String(t??"")),displayValue:r};case"not_contains":return{triggered:!String(c).includes(String(t??"")),displayValue:r};case"changed":return{triggered:JSON.stringify(c)!==JSON.stringify(s),displayValue:r};case"increased":{let n=ps(c),o=ps(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=ps(c),o=ps(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function ps(c){if(typeof c=="number")return c;let e=parseFloat(String(c));return isNaN(e)?null:e}function hp(c){return c==null?"null":typeof c=="object"?JSON.stringify(c):String(c)}var Wl=_(()=>{"use strict";u(ql,"extractField");u(zl,"evaluateCondition");u(ps,"toNumber");u(hp,"formatValue")});var fp,An,Gl=_(()=>{"use strict";Wl();ms();fp={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},An=class{static{u(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o}start(){this.timer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Watch engine started")}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.logger.info("Watch engine stopped")}async tick(){try{let e=this.watchRepo.getDue();for(let t of e)try{await this.checkWatch(t)}catch(s){this.logger.error({err:s,watchId:t.id},"Failed to check watch")}}catch(e){this.logger.error({err:e},"Error during watch engine tick")}}async checkWatch(e){let t=new Date().toISOString();this.logger.debug({watchId:e.id,name:e.name,skill:e.skillName},"Checking watch");let s=this.skillRegistry.get(e.skillName);if(!s){this.logger.warn({watchId:e.id,skillName:e.skillName},"Unknown skill for watch"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=Ve(this.users,{platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,e.skillParams,r);if(!n.success){this.logger.warn({watchId:e.id,error:n.error},"Watch skill execution failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let o=ql(n.data,e.condition.field),i=e.lastValue!==null?JSON.parse(e.lastValue):null,{triggered:a,displayValue:l}=zl(o,e.condition.operator,e.condition.value,i),d=JSON.stringify(o);if(a&&this.isCooldownExpired(e)){let m=e.messageTemplate??this.formatAlert(e,l),p=this.adapters.get(e.platform);if(p)try{await p.sendMessage(e.chatId,m),this.logger.info({watchId:e.id,name:e.name,value:l},"Watch alert sent")}catch(g){this.logger.error({err:g,watchId:e.id},"Failed to send watch alert")}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d,lastTriggeredAt:t})}else this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d})}isCooldownExpired(e){if(!e.lastTriggeredAt)return!0;let t=e.cooldownMinutes*6e4;return Date.now()-new Date(e.lastTriggeredAt).getTime()>=t}formatAlert(e,t){let s=fp[e.condition.operator]??e.condition.operator,r=e.condition.value!=null?` ${s} ${e.condition.value}`:` ${s}`;return`\u26A1 Watch Alert: ${e.name}
843
+ ${s}`;this.conversationManager.addMessage(m.id,"assistant",p)}}catch(m){this.logger.error({err:m,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let d=`scheduled-${e.id}`,m=this.conversationManager.getOrCreateConversation(e.platform,d,e.userId);this.conversationManager.pruneMessages(m.id,20)}catch{}let l=this.calculateNextRun(e);l?this.actionRepo.updateLastRun(e.id,t,l):(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 ql(c,e){let t=e.split("."),s=c;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 zl(c,e,t,s){let r=hp(c);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=ps(c),o=ps(t);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o,displayValue:r}}case"eq":return{triggered:String(c)===String(t),displayValue:r};case"neq":return{triggered:String(c)!==String(t),displayValue:r};case"contains":return{triggered:String(c).includes(String(t??"")),displayValue:r};case"not_contains":return{triggered:!String(c).includes(String(t??"")),displayValue:r};case"changed":return{triggered:JSON.stringify(c)!==JSON.stringify(s),displayValue:r};case"increased":{let n=ps(c),o=ps(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=ps(c),o=ps(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function ps(c){if(typeof c=="number")return c;let e=parseFloat(String(c));return isNaN(e)?null:e}function hp(c){return c==null?"null":typeof c=="object"?JSON.stringify(c):String(c)}var Wl=_(()=>{"use strict";u(ql,"extractField");u(zl,"evaluateCondition");u(ps,"toNumber");u(hp,"formatValue")});var fp,An,Gl=_(()=>{"use strict";Wl();ms();fp={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},An=class{static{u(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o}start(){this.timer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Watch engine started")}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.logger.info("Watch engine stopped")}async tick(){try{let e=this.watchRepo.getDue();for(let t of e)try{await this.checkWatch(t)}catch(s){this.logger.error({err:s,watchId:t.id},"Failed to check watch")}}catch(e){this.logger.error({err:e},"Error during watch engine tick")}}async checkWatch(e){let t=new Date().toISOString();this.logger.debug({watchId:e.id,name:e.name,skill:e.skillName},"Checking watch");let s=this.skillRegistry.get(e.skillName);if(!s){this.logger.warn({watchId:e.id,skillName:e.skillName},"Unknown skill for watch"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=Ke(this.users,{platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,e.skillParams,r);if(!n.success){this.logger.warn({watchId:e.id,error:n.error},"Watch skill execution failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let o=ql(n.data,e.condition.field),i=e.lastValue!==null?JSON.parse(e.lastValue):null,{triggered:a,displayValue:l}=zl(o,e.condition.operator,e.condition.value,i),d=JSON.stringify(o);if(a&&this.isCooldownExpired(e)){let m=e.messageTemplate??this.formatAlert(e,l),p=this.adapters.get(e.platform);if(p)try{await p.sendMessage(e.chatId,m),this.logger.info({watchId:e.id,name:e.name,value:l},"Watch alert sent")}catch(g){this.logger.error({err:g,watchId:e.id},"Failed to send watch alert")}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d,lastTriggeredAt:t})}else this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d})}isCooldownExpired(e){if(!e.lastTriggeredAt)return!0;let t=e.cooldownMinutes*6e4;return Date.now()-new Date(e.lastTriggeredAt).getTime()>=t}formatAlert(e,t){let s=fp[e.condition.operator]??e.condition.operator,r=e.condition.value!=null?` ${s} ${e.condition.value}`:` ${s}`;return`\u26A1 Watch Alert: ${e.name}
844
844
  Bedingung erf\xFCllt: ${e.condition.field}${r}
845
- Aktueller Wert: ${t}`}}});function Li(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of gp)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of yp)for(let r of s.patterns)if(r.test(e)){t.push(s.name);break}return t.length>0?{level:"high",matchedPatterns:t}:{level:"low",matchedPatterns:[]}}var gp,yp,Di=_(()=>{"use strict";gp=[/^(what|where|when|who|why|how|which|can you|could you|do you|is there|are there|was |wer |wo |wann |warum |wie |welch|kannst du|könntest du|gibt es)/i,/^(hi|hey|hello|hallo|guten (morgen|tag|abend)|moin|servus|grüß|na\b|yo\b|sup\b|good (morning|evening|night))\b/i,/^(tell me|show me|find|search|help|explain|describe|translate|summarize|zeig|such|hilf|erklär|beschreib|übersetze|fass zusammen)/i,/^(ok|okay|yes|no|ja|nein|danke|thanks|thank you|sure|alright|klar|gut|cool|nice|great|perfect|genau|stimmt|richtig)\b/i],yp=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];u(Li,"scanSignal")});var wp,Tp,xr,Mi=_(()=>{"use strict";wp=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Tp=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
845
+ Aktueller Wert: ${t}`}}});function Di(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of gp)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of yp)for(let r of s.patterns)if(r.test(e)){t.push(s.name);break}return t.length>0?{level:"high",matchedPatterns:t}:{level:"low",matchedPatterns:[]}}var gp,yp,Li=_(()=>{"use strict";gp=[/^(what|where|when|who|why|how|which|can you|could you|do you|is there|are there|was |wer |wo |wann |warum |wie |welch|kannst du|könntest du|gibt es)/i,/^(hi|hey|hello|hallo|guten (morgen|tag|abend)|moin|servus|grüß|na\b|yo\b|sup\b|good (morning|evening|night))\b/i,/^(tell me|show me|find|search|help|explain|describe|translate|summarize|zeig|such|hilf|erklär|beschreib|übersetze|fass zusammen)/i,/^(ok|okay|yes|no|ja|nein|danke|thanks|thank you|sure|alright|klar|gut|cool|nice|great|perfect|genau|stimmt|richtig)\b/i],yp=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];u(Di,"scanSignal")});var wp,Tp,xr,Mi=_(()=>{"use strict";wp=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Tp=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
846
846
 
847
847
  Rules:
848
848
  - Only extract information the user STATES about themselves
@@ -862,18 +862,18 @@ Extract memories from this conversation:
862
862
  User: {USER_MESSAGE}
863
863
  Assistant: {ASSISTANT_RESPONSE}
864
864
 
865
- Return ONLY a valid JSON array, no explanation:`,xr=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=Tp.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),n=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),o=this.parseResponse(n.content);if(o.length===0)return 0;let i=0;for(let a of o)if(!(a.confidence<this.minConfidence))try{let l=this.memoryRepo.saveWithMetadata(e,a.key,a.value,a.category,a.type,a.confidence,"auto");this.embeddingService&&this.embeddingService.embedAndStore(e,`${a.key}: ${a.value}`,"memory",l.id).catch(d=>this.logger.debug({err:d},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(l){this.logger.warn({err:l,key:a.key},"Failed to save extracted memory")}return i}catch(r){return this.logger.error({err:r},"Memory extraction failed"),0}}parseResponse(e){try{let t=e.match(/\[[\s\S]*\]/);if(!t)return[];let s=JSON.parse(t[0]);return Array.isArray(s)?s.filter(r=>typeof r=="object"&&r!==null).map(r=>({key:String(r.key||""),value:String(r.value||""),type:this.validateType(String(r.type||"fact")),confidence:this.clampConfidence(Number(r.confidence)||.5),category:String(r.category||"general")})).filter(r=>r.key&&r.value):[]}catch{return this.logger.debug({content:e.slice(0,200)},"Failed to parse extraction response"),[]}}validateType(e){return wp.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var Rr,Oi=_(()=>{"use strict";Di();Mi();Rr=class{static{u(this,"ActiveLearningService")}extractor;logger;minMessageLength;maxExtractionsPerMinute;extractionTimestamps=new Map;constructor(e){this.logger=e.logger,this.minMessageLength=e.minMessageLength??15,this.maxExtractionsPerMinute=e.maxExtractionsPerMinute??5,this.extractor=new xr(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Li(t);if(r.level==="low"){this.logger.debug({signal:"low"},"Skipping extraction \u2014 low signal");return}if(!this.checkRateLimit(e)){this.logger.debug({userId:e},"Skipping extraction \u2014 rate limit reached");return}this.logger.info({signal:r.level,patterns:r.matchedPatterns},"High signal detected, triggering extraction"),this.extractor.extract(e,t,s).then(n=>{n>0&&this.logger.info({userId:e,extractedCount:n},"Auto-extraction complete")}).catch(n=>{this.logger.error({err:n},"Auto-extraction failed")})}checkRateLimit(e){let t=Date.now(),s=t-6e4,r=this.extractionTimestamps.get(e);r||(r=[],this.extractionTimestamps.set(e,r));let n=r.filter(o=>o>s);return this.extractionTimestamps.set(e,n),n.length>=this.maxExtractionsPerMinute?!1:(n.push(t),!0)}}});var _p,Ep,bp,$p,Cr,Pi=_(()=>{"use strict";_p=Math.LN2,Ep=.3,bp=.7,$p=3,Cr=class{static{u(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let h of n)for(let T of this.memoryRepo.keywordSearch(h,t,30))o.has(T.id)||(o.add(T.id),i.push(T));let a=[],l=!1;if(this.embeddingService)try{let h=new Set;for(let T of n)for(let b of await this.embeddingService.semanticSearch(T,t,30))h.has(b.key)||(h.add(b.key),a.push(b));l=a.length>0}catch(h){this.logger.debug({err:h},"Semantic search failed, falling back to keyword-only")}let d=new Map,m=i.length;for(let h=0;h<i.length;h++){let T=i[h],b=m>0?1-h/m:0,A=l?Ep:1,C=this.applyBoosts(b*A,T);d.set(T.key,{memory:{key:T.key,value:T.value,category:T.category,type:T.type,score:C},score:C}),this.memoryRepo.recordAccess(T.id)}if(l)for(let h of a){let T=h.score*bp,b=d.get(h.key);if(b)b.score+=T,b.memory.score=b.score;else{let A=this.memoryRepo.recall(e,h.key),C=this.applyBoosts(T,A||void 0);d.set(h.key,{memory:{key:h.key,value:h.value,category:h.category,type:A?.type||"general",score:C},score:C}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((h,T)=>T.score-h.score),g=new Map,f=[];for(let{memory:h}of p){let T=g.get(h.type)||0;if(!(T>=$p)&&(g.set(h.type,T+1),f.push(h),f.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:f.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),f}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let l of n)for(let d of this.memoryRepo.getRecentForPrompt(l,s))i.has(d.key)||(i.add(d.key),a.push({key:d.key,value:d.value,category:d.category,type:d.type,score:0}));return a.slice(0,s)}}applyBoosts(e,t){let s=e;if(t){s*=.5+.5*t.confidence;let r=new Date(t.updatedAt).getTime(),n=Date.now()-r,o=Math.exp(-_p*n/2592e6);s*=o}return s}}});import{EventEmitter as kp}from"node:events";var ae,Ke=_(()=>{"use strict";ae=class extends kp{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(`
865
+ Return ONLY a valid JSON array, no explanation:`,xr=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=Tp.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),n=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),o=this.parseResponse(n.content);if(o.length===0)return 0;let i=0;for(let a of o)if(!(a.confidence<this.minConfidence))try{let l=this.memoryRepo.saveWithMetadata(e,a.key,a.value,a.category,a.type,a.confidence,"auto");this.embeddingService&&this.embeddingService.embedAndStore(e,`${a.key}: ${a.value}`,"memory",l.id).catch(d=>this.logger.debug({err:d},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(l){this.logger.warn({err:l,key:a.key},"Failed to save extracted memory")}return i}catch(r){return this.logger.error({err:r},"Memory extraction failed"),0}}parseResponse(e){try{let t=e.match(/\[[\s\S]*\]/);if(!t)return[];let s=JSON.parse(t[0]);return Array.isArray(s)?s.filter(r=>typeof r=="object"&&r!==null).map(r=>({key:String(r.key||""),value:String(r.value||""),type:this.validateType(String(r.type||"fact")),confidence:this.clampConfidence(Number(r.confidence)||.5),category:String(r.category||"general")})).filter(r=>r.key&&r.value):[]}catch{return this.logger.debug({content:e.slice(0,200)},"Failed to parse extraction response"),[]}}validateType(e){return wp.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var Rr,Oi=_(()=>{"use strict";Li();Mi();Rr=class{static{u(this,"ActiveLearningService")}extractor;logger;minMessageLength;maxExtractionsPerMinute;extractionTimestamps=new Map;constructor(e){this.logger=e.logger,this.minMessageLength=e.minMessageLength??15,this.maxExtractionsPerMinute=e.maxExtractionsPerMinute??5,this.extractor=new xr(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Di(t);if(r.level==="low"){this.logger.debug({signal:"low"},"Skipping extraction \u2014 low signal");return}if(!this.checkRateLimit(e)){this.logger.debug({userId:e},"Skipping extraction \u2014 rate limit reached");return}this.logger.info({signal:r.level,patterns:r.matchedPatterns},"High signal detected, triggering extraction"),this.extractor.extract(e,t,s).then(n=>{n>0&&this.logger.info({userId:e,extractedCount:n},"Auto-extraction complete")}).catch(n=>{this.logger.error({err:n},"Auto-extraction failed")})}checkRateLimit(e){let t=Date.now(),s=t-6e4,r=this.extractionTimestamps.get(e);r||(r=[],this.extractionTimestamps.set(e,r));let n=r.filter(o=>o>s);return this.extractionTimestamps.set(e,n),n.length>=this.maxExtractionsPerMinute?!1:(n.push(t),!0)}}});var _p,Ep,bp,$p,Cr,Pi=_(()=>{"use strict";_p=Math.LN2,Ep=.3,bp=.7,$p=3,Cr=class{static{u(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let h of n)for(let T of this.memoryRepo.keywordSearch(h,t,30))o.has(T.id)||(o.add(T.id),i.push(T));let a=[],l=!1;if(this.embeddingService)try{let h=new Set;for(let T of n)for(let b of await this.embeddingService.semanticSearch(T,t,30))h.has(b.key)||(h.add(b.key),a.push(b));l=a.length>0}catch(h){this.logger.debug({err:h},"Semantic search failed, falling back to keyword-only")}let d=new Map,m=i.length;for(let h=0;h<i.length;h++){let T=i[h],b=m>0?1-h/m:0,A=l?Ep:1,C=this.applyBoosts(b*A,T);d.set(T.key,{memory:{key:T.key,value:T.value,category:T.category,type:T.type,score:C},score:C}),this.memoryRepo.recordAccess(T.id)}if(l)for(let h of a){let T=h.score*bp,b=d.get(h.key);if(b)b.score+=T,b.memory.score=b.score;else{let A=this.memoryRepo.recall(e,h.key),C=this.applyBoosts(T,A||void 0);d.set(h.key,{memory:{key:h.key,value:h.value,category:h.category,type:A?.type||"general",score:C},score:C}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((h,T)=>T.score-h.score),g=new Map,f=[];for(let{memory:h}of p){let T=g.get(h.type)||0;if(!(T>=$p)&&(g.set(h.type,T+1),f.push(h),f.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:f.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),f}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let l of n)for(let d of this.memoryRepo.getRecentForPrompt(l,s))i.has(d.key)||(i.add(d.key),a.push({key:d.key,value:d.value,category:d.category,type:d.type,score:0}));return a.slice(0,s)}}applyBoosts(e,t){let s=e;if(t){s*=.5+.5*t.confidence;let r=new Date(t.updatedAt).getTime(),n=Date.now()-r,o=Math.exp(-_p*n/2592e6);s*=o}return s}}});import{EventEmitter as kp}from"node:events";var ce,Xe=_(()=>{"use strict";ce=class extends kp{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(`
866
866
 
867
- `);if(i>0&&(n=i),n<0){let l=r.slice(0,t).match(/.*[.!?]\s/s);l&&(n=l[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as vp,InputFile as Ui}from"grammy";function Vl(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var In,Kl=_(()=>{"use strict";Ke();u(Vl,"mapParseMode");In=class extends ae{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new vp(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:Vl(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:Vl(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 Ui(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 Ui(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Ui(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 l=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:l.length,data:l}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as Sp,GatewayIntentBits as xn,Events as Fi}from"discord.js";var Rn,Xl=_(()=>{"use strict";Ke();Rn=class extends ae{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new Sp({intents:[xn.Guilds,xn.GuildMessages,xn.MessageContent,xn.DirectMessages]}),this.client.on(Fi.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(Fi.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Fi.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 Cn,Yl=_(()=>{"use strict";Ke();Cn=class extends ae{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),l=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of l)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(),g=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??g.length,data:g}}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 Nn,Jl=_(()=>{"use strict";Ke();Nn=class extends ae{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 l=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),l){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 l of i)l.message&&(l.key.fromMe||this.processMessage(l).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 Ln,Zl=_(()=>{"use strict";Ke();Ln=class extends ae{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 l=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(`Signal send failed: ${l.status} ${await l.text()}`);let d=await l.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 l={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",l)}}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 ji from"node:readline";var Dn,Ql=_(()=>{"use strict";Ke();Dn=class extends ae{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=ji.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
867
+ `);if(i>0&&(n=i),n<0){let l=r.slice(0,t).match(/.*[.!?]\s/s);l&&(n=l[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as vp,InputFile as Ui}from"grammy";function Vl(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var In,Kl=_(()=>{"use strict";Xe();u(Vl,"mapParseMode");In=class extends ce{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new vp(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:Vl(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:Vl(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 Ui(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 Ui(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Ui(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 l=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:l.length,data:l}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as Sp,GatewayIntentBits as xn,Events as Fi}from"discord.js";var Rn,Xl=_(()=>{"use strict";Xe();Rn=class extends ce{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new Sp({intents:[xn.Guilds,xn.GuildMessages,xn.MessageContent,xn.DirectMessages]}),this.client.on(Fi.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(Fi.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Fi.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 Cn,Yl=_(()=>{"use strict";Xe();Cn=class extends ce{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),l=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of l)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(),g=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??g.length,data:g}}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 Nn,Jl=_(()=>{"use strict";Xe();Nn=class extends ce{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 l=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),l){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 l of i)l.message&&(l.key.fromMe||this.processMessage(l).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 Dn,Zl=_(()=>{"use strict";Xe();Dn=class extends ce{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 l=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(`Signal send failed: ${l.status} ${await l.text()}`);let d=await l.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 l={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",l)}}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 ji from"node:readline";var Ln,Ql=_(()=>{"use strict";Xe();Ln=class extends ce{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=ji.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
868
868
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
869
869
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
870
870
  Goodbye!
871
871
  `),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(`
872
872
  Alfred: ${t}
873
- `),this.prompt(),r}async editMessage(e,t,s,r){ji.clearLine(process.stdout,0),ji.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Ap from"node:http";import Ip from"node:crypto";var Mn,ed=_(()=>{"use strict";Ke();Mn=class extends ae{static{u(this,"HttpAdapter")}port;host;platform="api";server=null;streams=new Map;messageCounter=0;constructor(e,t){super(),this.port=e,this.host=t}async connect(){this.status="connecting",this.server=Ap.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("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),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/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}handleHealth(e){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok"}))}handleMessage(e,t){let s="";e.on("data",r=>{s+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(s),n=r.text;if(!n||typeof n!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let o=r.chatId??`api-chat-${Ip.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(o);a&&(this.writeSseEvent(a,"done",{type:"done"}),a.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(o,t),e.on("close",()=>{this.streams.delete(o)}),this.messageCounter++;let l={id:`api-${this.messageCounter}`,platform:"api",chatId:o,chatType:"dm",userId:i,userName:i,displayName:"API User",text:n,timestamp:new Date};this.emit("message",l)}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}
873
+ `),this.prompt(),r}async editMessage(e,t,s,r){ji.clearLine(process.stdout,0),ji.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Ap from"node:http";import Ip from"node:crypto";var Mn,ed=_(()=>{"use strict";Xe();Mn=class extends ce{static{u(this,"HttpAdapter")}port;host;platform="api";server=null;streams=new Map;messageCounter=0;constructor(e,t){super(),this.port=e,this.host=t}async connect(){this.status="connecting",this.server=Ap.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("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),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/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}handleHealth(e){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok"}))}handleMessage(e,t){let s="";e.on("data",r=>{s+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(s),n=r.text;if(!n||typeof n!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let o=r.chatId??`api-chat-${Ip.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(o);a&&(this.writeSseEvent(a,"done",{type:"done"}),a.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(o,t),e.on("close",()=>{this.streams.delete(o)}),this.messageCounter++;let l={id:`api-${this.messageCounter}`,platform:"api",chatId:o,chatType:"dm",userId:i,userName:i,displayName:"API User",text:n,timestamp:new Date};this.emit("message",l)}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}
874
874
  data: ${JSON.stringify(s)}
875
875
 
876
- `)}}});var tt={};oe(tt,{CLIAdapter:()=>Dn,DiscordAdapter:()=>Rn,HttpAdapter:()=>Mn,MatrixAdapter:()=>Cn,MessagingAdapter:()=>ae,SignalAdapter:()=>Ln,TelegramAdapter:()=>In,WhatsAppAdapter:()=>Nn});var st=_(()=>{"use strict";Ke();Kl();Xl();Yl();Jl();Zl();Ql();ed()});import On from"node:fs";import Pn from"node:path";import xp from"js-yaml";var St,td=_(()=>{"use strict";vo();Io();ze();Fo();Qr();Y();_i();bi();$i();ki();vi();Si();Ai();Ii();xi();Ri();Ci();Ni();Gl();Oi();Pi();St=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;adapters=new Map;formatter=new kr;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Ls("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ht(this.config.storage.path);let e=this.database.getDb(),t=new Ds(e),s=new Ms(e);this.userRepo=s;let r=new ft(e),n=new Os(e),o=new Ps(e),i=new Us(e),a=new Fs(e),l=new js(e),d=new Bs(e),m=new Hs(e);this.logger.info("Storage initialized");let p=new tr,g=this.loadSecurityRules();p.loadRules(g);let f=new sr(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:g.length},"Security engine initialized");let h=Uo(this.config.llm,this.logger.child({component:"llm"}));await h.initialize();let T=new vr(h,a,this.logger.child({component:"embeddings"})),b=this.config.activeLearning?.enabled!==!1,A,C;b&&(A=new Rr({llm:h,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:T,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),C=new Cr(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let U=new Dt(this.logger.child({component:"sandbox"})),x=this.skillRegistry=new Lt;x.register(new Mt),x.register(new Ot),x.register(new Pt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),x.register(new Ut(o)),x.register(new Ft(i));let V=new zs(e);if(x.register(new rs(V)),x.register(new jt),x.register(new Bt),x.register(new Ht(n,T)),x.register(new qt(h,x,U,f)),this.config.email?.accounts?.length){let N=new Map;for(let G of this.config.email.accounts)try{G.provider==="microsoft"&&!G.microsoft?.clientId&&this.config.calendar?.microsoft&&(G.microsoft={...this.config.calendar.microsoft});let $e=await rr(G);N.set(G.name,$e),this.logger.info({account:G.name,provider:G.provider??"imap-smtp"},"Email account initialized")}catch($e){this.logger.warn({err:$e,account:G.name},"Email account initialization failed, skipping")}x.register(N.size>0?new Ze(N):new Ze)}else x.register(new Ze);x.register(new zt),x.register(new Wt);let be=new as;be.setReloadCallback(N=>this.reloadService(N)),x.register(be),x.register(new Vt),x.register(new Kt),x.register(new Xt),x.register(new Yt(s)),x.register(new Jt(s,l,this.adapters,(N,G)=>t.findByPlatformAndUser(N,G))),x.register(new Zt(d)),x.register(new Qt(m));let he=new qs(e),ce=new Sr(he,T,this.logger.child({component:"documents"}));x.register(new es(he,ce,T));let le;if(this.config.calendar)try{let N=await ir(this.config.calendar);le=new Tt(N),x.register(le),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(N){this.logger.warn({err:N},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=le,this.config.mcp?.servers?.length){let{MCPManager:N}=await Promise.resolve().then(()=>(Y(),Z));this.mcpManager=new N(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let G of this.mcpManager.getSkills())x.register(G);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},h)),this.logger.info({agents:this.config.codeAgents.agents.map(G=>G.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:N,createContactsProvider:G}=await Promise.resolve().then(()=>(Y(),Z)),$e=await G(this.config.contacts);x.register(new N($e)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(N){this.logger.warn({err:N},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}this.logger.info({skills:x.getAll().map(N=>N.metadata.name)},"Skills registered");let W;if(this.config.speech?.apiKey&&(W=new _r(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 N=new Er(this.config.speech,this.logger.child({component:"tts"}));x.register(new ts(N)),this.logger.info("Text-to-speech skill registered")}let fe=this.detectImageGenProvider();if(fe){let N=new br(fe,this.logger.child({component:"image-gen"}));x.register(new ss(N)),this.logger.info({provider:fe.provider},"Image generation skill registered")}try{let N=new $r(this.logger.child({component:"transit"}));x.register(new os(N)),this.logger.info("Public transit skill registered")}catch(N){this.logger.warn({err:N},"Failed to register transit skill")}let ge=new yr(t),de=Pn.resolve(Pn.dirname(this.config.storage.path),"inbox");this.pipeline=new wr({llm:h,conversationManager:ge,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:x,skillSandbox:U,securityManager:f,memoryRepo:n,speechTranscriber:W,inboxPath:de,embeddingService:T,activeLearning:A,memoryRetriever:C,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:ce}),this.reminderScheduler=new Tr(o,async(N,G,$e)=>{let J=this.adapters.get(N);J?await J.sendMessage(G,$e):this.logger.warn({platform:N,chatId:G},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(N=>s.getMasterUserId(N),"getMasterUserId"),getLinkedUsers:u(N=>s.getLinkedUsers(N),"getLinkedUsers"),findConversation:u((N,G)=>t.findByPlatformAndUser(N,G),"findConversation")}),this.backgroundTaskRunner=new Ar(x,U,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Ir(m,x,U,h,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,ge);let re=new Ws(e);x.register(new cs(re)),this.watchEngine=new An(re,x,U,this.adapters,s,this.logger.child({component:"watch-engine"})),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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";this.adapters.set("api",new t(s,r)),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.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(()=>(st(),tt)),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.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{$o();let t=new ne().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z)),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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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}}}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 d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(m){this.logger.debug({err:m,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),l=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,l)}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,l)}else await t.sendMessage(s.chatId,a.text,l)}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 d of i.attachments)try{let m=d.mimeType.startsWith("image/"),p=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):p?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.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=Pn.resolve(this.config.security.rulesPath),t=[];if(!On.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!On.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=On.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Pn.join(e,n),i=On.readFileSync(o,"utf-8"),a=xp.load(i);a?.rules&&Array.isArray(a.rules)&&(t.push(...a.rules),this.logger.info({file:n,count:a.rules.length},"Loaded security rules"))}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var sd=_(()=>{"use strict"});var Bi=_(()=>{"use strict";td();bi();_i();$i();ki();vi();Ii();xi();Ci();Ni();ms();Ri();Si();Ai();Oi();Pi();Mi();sd();Di()});import Un from"node:fs";import rd from"node:path";import Rp from"node:os";function nd(){try{let c=Un.readFileSync(Hi,"utf-8"),e=JSON.parse(c);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function od(c){try{let e=rd.dirname(Hi);Un.existsSync(e)||Un.mkdirSync(e,{recursive:!0}),Un.writeFileSync(Hi,JSON.stringify(c,null,2),"utf-8")}catch{}}async function At(c,e){let t=new AbortController,s=setTimeout(()=>t.abort(),Np);try{return await fetch(c,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function id(c,e,t){switch(c){case"anthropic":{let s=await At("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 At(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 At(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await At("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 At("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 At(`${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 At(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function qi(c,e,t){let s=nd(),r=s.providers[c];if(r&&Date.now()-r.fetchedAt<Cp)return r.models;try{let n=await id(c,e,t);if(n.length>0)return s.providers[c]={fetchedAt:Date.now(),models:n},od(s),n}catch{}return r?r.models:[]}function Fn(c,e,t){id(c,e,t).then(s=>{if(s.length>0){let r=nd();r.providers[c]={fetchedAt:Date.now(),models:s},od(r)}}).catch(()=>{})}function zi(c,e){let t=new Set,s=[];for(let r of c)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 Cp,Np,Hi,Wi=_(()=>{"use strict";Cp=24*60*60*1e3,Np=5e3,Hi=rd.join(Rp.homedir(),".alfred","model-cache.json");u(nd,"readCache");u(od,"writeCache");u(At,"fetchWithTimeout");u(id,"fetchModelsFromAPI");u(qi,"getModels");u(Fn,"refreshCacheInBackground");u(zi,"mergeModels")});var ad={};oe(ad,{startCommand:()=>Lp});async function Lp(){let c=new ne,e;try{e=c.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Ls("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new St(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?Fn(o.default.provider,o.default.apiKey,o.default.baseUrl):o?.provider&&Fn(o.provider,void 0,o.baseUrl);for(let i of["strong","fast"]){let a=o?.[i];a?.provider&&Fn(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 cd=_(()=>{"use strict";ze();vo();Bi();Wi();u(Lp,"startCommand")});var dd={};oe(dd,{chatCommand:()=>Op});import ld from"node:http";import Nr from"node:readline";function Dp(c,e){return new Promise(t=>{let s=ld.get(`http://${c}:${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 Mp(c,e){let t=Nr.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
876
+ `)}}});var tt={};ie(tt,{CLIAdapter:()=>Ln,DiscordAdapter:()=>Rn,HttpAdapter:()=>Mn,MatrixAdapter:()=>Cn,MessagingAdapter:()=>ce,SignalAdapter:()=>Dn,TelegramAdapter:()=>In,WhatsAppAdapter:()=>Nn});var st=_(()=>{"use strict";Xe();Kl();Xl();Yl();Jl();Zl();Ql();ed()});import On from"node:fs";import Pn from"node:path";import xp from"js-yaml";var St,td=_(()=>{"use strict";vo();Io();We();Fo();Qr();Y();_i();bi();$i();ki();vi();Si();Ai();Ii();xi();Ri();Ci();Ni();Gl();Oi();Pi();St=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;adapters=new Map;formatter=new kr;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Ds("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ht(this.config.storage.path);let e=this.database.getDb(),t=new Ls(e),s=new Ms(e);this.userRepo=s;let r=new ft(e),n=new Os(e),o=new Ps(e),i=new Us(e),a=new Fs(e),l=new js(e),d=new Bs(e),m=new Hs(e);this.logger.info("Storage initialized");let p=new tr,g=this.loadSecurityRules();p.loadRules(g);let f=new sr(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:g.length},"Security engine initialized");let h=Uo(this.config.llm,this.logger.child({component:"llm"}));await h.initialize();let T=new vr(h,a,this.logger.child({component:"embeddings"})),b=this.config.activeLearning?.enabled!==!1,A,C;b&&(A=new Rr({llm:h,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:T,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),C=new Cr(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let U=new Lt(this.logger.child({component:"sandbox"})),x=this.skillRegistry=new Dt;x.register(new Mt),x.register(new Ot),x.register(new Pt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),x.register(new Ut(o)),x.register(new Ft(i));let V=new zs(e);if(x.register(new rs(V)),x.register(new jt),x.register(new Bt),x.register(new Ht(n,T)),x.register(new qt(h,x,U,f)),this.config.email?.accounts?.length){let N=new Map;for(let G of this.config.email.accounts)try{G.provider==="microsoft"&&!G.microsoft?.clientId&&this.config.calendar?.microsoft&&(G.microsoft={...this.config.calendar.microsoft});let $e=await rr(G);N.set(G.name,$e),this.logger.info({account:G.name,provider:G.provider??"imap-smtp"},"Email account initialized")}catch($e){this.logger.warn({err:$e,account:G.name},"Email account initialization failed, skipping")}x.register(N.size>0?new Qe(N):new Qe)}else x.register(new Qe);x.register(new zt),x.register(new Wt);let Te=new as;Te.setReloadCallback(N=>this.reloadService(N)),x.register(Te),x.register(new Vt),x.register(new Kt),x.register(new Xt),x.register(new Yt(s)),x.register(new Jt(s,l,this.adapters,(N,G)=>t.findByPlatformAndUser(N,G))),x.register(new Zt(d)),x.register(new Qt(m));let he=new qs(e),le=new Sr(he,T,this.logger.child({component:"documents"}));x.register(new es(he,le,T));let re;if(this.config.calendar)try{let N=await ir(this.config.calendar);re=new Tt(N),x.register(re),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(N){this.logger.warn({err:N},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=re,this.config.mcp?.servers?.length){let{MCPManager:N}=await Promise.resolve().then(()=>(Y(),Z));this.mcpManager=new N(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let G of this.mcpManager.getSkills())x.register(G);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},h)),this.logger.info({agents:this.config.codeAgents.agents.map(G=>G.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:N,createContactsProvider:G}=await Promise.resolve().then(()=>(Y(),Z)),$e=await G(this.config.contacts);x.register(new N($e)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(N){this.logger.warn({err:N},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:N}=await Promise.resolve().then(()=>(Y(),Z));x.register(new N(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}this.logger.info({skills:x.getAll().map(N=>N.metadata.name)},"Skills registered");let W;if(this.config.speech?.apiKey&&(W=new _r(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 N=new Er(this.config.speech,this.logger.child({component:"tts"}));x.register(new ts(N)),this.logger.info("Text-to-speech skill registered")}let fe=this.detectImageGenProvider();if(fe){let N=new br(fe,this.logger.child({component:"image-gen"}));x.register(new ss(N)),this.logger.info({provider:fe.provider},"Image generation skill registered")}try{let N=new $r(this.logger.child({component:"transit"}));x.register(new os(N)),this.logger.info("Public transit skill registered")}catch(N){this.logger.warn({err:N},"Failed to register transit skill")}let ge=new yr(t),de=Pn.resolve(Pn.dirname(this.config.storage.path),"inbox");this.pipeline=new wr({llm:h,conversationManager:ge,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:x,skillSandbox:U,securityManager:f,memoryRepo:n,speechTranscriber:W,inboxPath:de,embeddingService:T,activeLearning:A,memoryRetriever:C,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:le}),this.reminderScheduler=new Tr(o,async(N,G,$e)=>{let J=this.adapters.get(N);J?await J.sendMessage(G,$e):this.logger.warn({platform:N,chatId:G},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(N=>s.getMasterUserId(N),"getMasterUserId"),getLinkedUsers:u(N=>s.getLinkedUsers(N),"getLinkedUsers"),findConversation:u((N,G)=>t.findByPlatformAndUser(N,G),"findConversation")}),this.backgroundTaskRunner=new Ar(x,U,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Ir(m,x,U,h,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,ge);let ne=new Ws(e);x.register(new cs(ne)),this.watchEngine=new An(ne,x,U,this.adapters,s,this.logger.child({component:"watch-engine"})),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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt));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(()=>(st(),tt)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";this.adapters.set("api",new t(s,r)),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.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(()=>(st(),tt)),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.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{$o();let t=new oe().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z)),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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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(()=>(Y(),Z));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}}}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 d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(m){this.logger.debug({err:m,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),l=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,l)}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,l)}else await t.sendMessage(s.chatId,a.text,l)}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 d of i.attachments)try{let m=d.mimeType.startsWith("image/"),p=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):p?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.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=Pn.resolve(this.config.security.rulesPath),t=[];if(!On.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!On.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=On.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Pn.join(e,n),i=On.readFileSync(o,"utf-8"),a=xp.load(i);a?.rules&&Array.isArray(a.rules)&&(t.push(...a.rules),this.logger.info({file:n,count:a.rules.length},"Loaded security rules"))}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var sd=_(()=>{"use strict"});var Bi=_(()=>{"use strict";td();bi();_i();$i();ki();vi();Ii();xi();Ci();Ni();ms();Ri();Si();Ai();Oi();Pi();Mi();sd();Li()});import Un from"node:fs";import rd from"node:path";import Rp from"node:os";function nd(){try{let c=Un.readFileSync(Hi,"utf-8"),e=JSON.parse(c);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function od(c){try{let e=rd.dirname(Hi);Un.existsSync(e)||Un.mkdirSync(e,{recursive:!0}),Un.writeFileSync(Hi,JSON.stringify(c,null,2),"utf-8")}catch{}}async function At(c,e){let t=new AbortController,s=setTimeout(()=>t.abort(),Np);try{return await fetch(c,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function id(c,e,t){switch(c){case"anthropic":{let s=await At("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 At(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 At(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await At("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 At("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 At(`${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 At(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function qi(c,e,t){let s=nd(),r=s.providers[c];if(r&&Date.now()-r.fetchedAt<Cp)return r.models;try{let n=await id(c,e,t);if(n.length>0)return s.providers[c]={fetchedAt:Date.now(),models:n},od(s),n}catch{}return r?r.models:[]}function Fn(c,e,t){id(c,e,t).then(s=>{if(s.length>0){let r=nd();r.providers[c]={fetchedAt:Date.now(),models:s},od(r)}}).catch(()=>{})}function zi(c,e){let t=new Set,s=[];for(let r of c)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 Cp,Np,Hi,Wi=_(()=>{"use strict";Cp=24*60*60*1e3,Np=5e3,Hi=rd.join(Rp.homedir(),".alfred","model-cache.json");u(nd,"readCache");u(od,"writeCache");u(At,"fetchWithTimeout");u(id,"fetchModelsFromAPI");u(qi,"getModels");u(Fn,"refreshCacheInBackground");u(zi,"mergeModels")});var ad={};ie(ad,{startCommand:()=>Dp});async function Dp(){let c=new oe,e;try{e=c.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Ds("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new St(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?Fn(o.default.provider,o.default.apiKey,o.default.baseUrl):o?.provider&&Fn(o.provider,void 0,o.baseUrl);for(let i of["strong","fast"]){let a=o?.[i];a?.provider&&Fn(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 cd=_(()=>{"use strict";We();vo();Bi();Wi();u(Dp,"startCommand")});var dd={};ie(dd,{chatCommand:()=>Op});import ld from"node:http";import Nr from"node:readline";function Lp(c,e){return new Promise(t=>{let s=ld.get(`http://${c}:${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 Mp(c,e){let t=Nr.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
877
877
  Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
878
878
  `),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
879
879
  Goodbye!
@@ -888,42 +888,42 @@ Error: ${g.text??"Unknown error"}
888
888
  `),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let l=a.split(`
889
889
  `).find(d=>d.startsWith("data: "));if(l)try{let d=JSON.parse(l.slice(6));(d.type==="done"||d.type==="error")&&t.prompt()}catch{}}}),i.on("error",l=>{console.error(`
890
890
  Connection error: ${l.message}`),t.prompt()})});o.on("error",i=>{console.error(`
891
- Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function Op(c){let e=new ne,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 Dp(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Mp(s,r);return}if(t.logger.level="warn",c.model&&(t.llm.default.model=c.model),c.tier){let i=t.llm[c.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${c.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new St(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var ud=_(()=>{"use strict";ze();Bi();u(Dp,"checkHealth");u(Mp,"startClientMode");u(Op,"chatCommand")});var hd={};oe(hd,{setupCommand:()=>Vp});import{createInterface as Pp}from"node:readline/promises";import{stdin as Up,stdout as Fp}from"node:process";import{execFileSync as jp}from"node:child_process";import pe from"node:fs";import Bp from"node:os";import Ee from"node:path";import Gi from"js-yaml";function D(c){return`${jn}${c}${k}`}function zp(c){return`${M}${c}${k}`}function me(c){return`${Bn}${c}${k}`}function pd(c){return`${Hp}${c}${k}`}function R(c){return`${H}${c}${k}`}function E(c){return`${rt}${c}${k}`}function we(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Wp(c){let e=process.platform==="win32",t=e?"where":"which";try{let n=jp(t,[c],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=Bp.homedir(),r=e?[Ee.join(s,".local","bin",`${c}.exe`),Ee.join(s,"AppData","Roaming","npm",`${c}.cmd`),Ee.join(s,"AppData","Roaming","npm",`${c}`)]:[Ee.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,Ee.join(s,".npm-global","bin",c)];for(let n of r)try{return pe.accessSync(n,pe.constants.X_OK),n}catch{}return null}function Gp(c){let e={},t={},s=!1,r=!1,n=30,o=Ee.join(c,"config","default.yml");if(pe.existsSync(o))try{let p=Gi.load(pe.readFileSync(o,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=Ee.join(c,".env");if(pe.existsSync(i))try{let p=pe.readFileSync(i,"utf-8").split(`
892
- `);for(let g of p){let f=g.trim();if(!f||f.startsWith("#"))continue;let h=f.indexOf("=");h>0&&(t[f.slice(0,h)]=f.slice(h+1))}}catch{}let a=Ee.join(c,"config","rules","default-rules.yml");if(pe.existsSync(a))try{let p=Gi.load(pe.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 f=p.rules.find(h=>h.id==="rate-limit-write");f?.rateLimit?.maxInvocations&&(n=f.rateLimit.maxInvocations)}}catch{}let l=!!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:l,multiModelTiers:m}}async function Vp(){let c=Pp({input:Up,output:Fp}),e=process.cwd(),t=Gp(e),s=Object.keys(t.config).length>0;try{Kp(),console.log(s?`${Bn}Existing configuration found \u2014 press Enter to keep current values.${k}
891
+ Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function Op(c){let e=new oe,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 Lp(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Mp(s,r);return}if(t.logger.level="warn",c.model&&(t.llm.default.model=c.model),c.tier){let i=t.llm[c.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${c.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new St(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var ud=_(()=>{"use strict";We();Bi();u(Lp,"checkHealth");u(Mp,"startClientMode");u(Op,"chatCommand")});var hd={};ie(hd,{setupCommand:()=>Vp});import{createInterface as Pp}from"node:readline/promises";import{stdin as Up,stdout as Fp}from"node:process";import{execFileSync as jp}from"node:child_process";import pe from"node:fs";import Bp from"node:os";import be from"node:path";import Gi from"js-yaml";function L(c){return`${jn}${c}${k}`}function zp(c){return`${M}${c}${k}`}function me(c){return`${Bn}${c}${k}`}function pd(c){return`${Hp}${c}${k}`}function R(c){return`${H}${c}${k}`}function E(c){return`${rt}${c}${k}`}function we(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Wp(c){let e=process.platform==="win32",t=e?"where":"which";try{let n=jp(t,[c],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=Bp.homedir(),r=e?[be.join(s,".local","bin",`${c}.exe`),be.join(s,"AppData","Roaming","npm",`${c}.cmd`),be.join(s,"AppData","Roaming","npm",`${c}`)]:[be.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,be.join(s,".npm-global","bin",c)];for(let n of r)try{return pe.accessSync(n,pe.constants.X_OK),n}catch{}return null}function Gp(c){let e={},t={},s=!1,r=!1,n=30,o=be.join(c,"config","default.yml");if(pe.existsSync(o))try{let p=Gi.load(pe.readFileSync(o,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=be.join(c,".env");if(pe.existsSync(i))try{let p=pe.readFileSync(i,"utf-8").split(`
892
+ `);for(let g of p){let f=g.trim();if(!f||f.startsWith("#"))continue;let h=f.indexOf("=");h>0&&(t[f.slice(0,h)]=f.slice(h+1))}}catch{}let a=be.join(c,"config","rules","default-rules.yml");if(pe.existsSync(a))try{let p=Gi.load(pe.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 f=p.rules.find(h=>h.id==="rate-limit-write");f?.rateLimit?.maxInvocations&&(n=f.rateLimit.maxInvocations)}}catch{}let l=!!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:l,multiModelTiers:m}}async function Vp(){let c=Pp({input:Up,output:Fp}),e=process.cwd(),t=Gp(e),s=Object.keys(t.config).length>0;try{Kp(),console.log(s?`${Bn}Existing configuration found \u2014 press Enter to keep current values.${k}
893
893
  ${rt}Only change what you need to update.${k}
894
894
  `:`${Bn}Welcome to the Alfred setup wizard!${k}
895
895
  ${rt}This will walk you through configuring your AI assistant.${k}
896
896
  ${rt}Press Enter to accept defaults shown in [brackets].${k}
897
- `);let r=await O(c,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Xe.findIndex(w=>w.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
898
- ${R("Which LLM provider would you like to use?")}`);for(let w=0;w<Xe.length;w++){let $=w===n?` ${E("(current)")}`:"";console.log(` ${me(String(w+1)+")")} ${Xe[w].label}${$}`)}let i=await Lr(c,"> ",1,Xe.length,o),a=Xe[i-1];console.log(` ${D(">")} Selected: ${R(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await O(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await Ie(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${D(">")} API key set: ${E(we(l))}`));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 S={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 O(c,S[a.name]??"API Base URL",$.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${D(">")} URL: ${E(m)}`)}}let g=t.config.llm?.model??a.defaultModel;console.log("");let f,h=await qi(a.name,l,m),T=zi(h,a.models??[]);if(T.length>0){console.log(`${R("Available models:")}`);for(let S=0;S<T.length;S++){let j=T[S],L=j.desc??j.name??"",F=j.id===g?` ${D("(current)")}`:"";console.log(` ${me(`${S+1})`)} ${j.id}${L?` ${E(`\u2014 ${L}`)}`:""}${F}`)}console.log(` ${me(`${T.length+1})`)} ${E("Other (enter manually)")}`);let w=await O(c,"Choose model","1"),$=parseInt(w,10)-1;$>=0&&$<T.length?f=T[$].id:f=await O(c,"Model ID",g)}else f=await O(c,"Which model?",g);let b=Object.keys(t.multiModelTiers).length>0,A=b?"Y/n":"y/N";console.log(`
897
+ `);let r=await O(c,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Ye.findIndex(w=>w.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
898
+ ${R("Which LLM provider would you like to use?")}`);for(let w=0;w<Ye.length;w++){let $=w===n?` ${E("(current)")}`:"";console.log(` ${me(String(w+1)+")")} ${Ye[w].label}${$}`)}let i=await Dr(c,"> ",1,Ye.length,o),a=Ye[i-1];console.log(` ${L(">")} Selected: ${R(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await O(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await Ie(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${L(">")} API key set: ${E(we(l))}`));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 S={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 O(c,S[a.name]??"API Base URL",$.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${L(">")} URL: ${E(m)}`)}}let g=t.config.llm?.model??a.defaultModel;console.log("");let f,h=await qi(a.name,l,m),T=zi(h,a.models??[]);if(T.length>0){console.log(`${R("Available models:")}`);for(let S=0;S<T.length;S++){let j=T[S],D=j.desc??j.name??"",F=j.id===g?` ${L("(current)")}`:"";console.log(` ${me(`${S+1})`)} ${j.id}${D?` ${E(`\u2014 ${D}`)}`:""}${F}`)}console.log(` ${me(`${T.length+1})`)} ${E("Other (enter manually)")}`);let w=await O(c,"Choose model","1"),$=parseInt(w,10)-1;$>=0&&$<T.length?f=T[$].id:f=await O(c,"Model ID",g)}else f=await O(c,"Which model?",g);let b=Object.keys(t.multiModelTiers).length>0,A=b?"Y/n":"y/N";console.log(`
899
899
  ${R("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let C=(await c.question(`${M}> ${k}${E(`[${A}] `)}`)).trim().toLowerCase(),U=C===""?b:C==="y"||C==="yes",x={};if(U){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 S=t.multiModelTiers[$.key],j=!!S?.model;console.log(`
900
- ${R(`${$.label} model`)} ${E(`(${$.hint})`)}`),j&&console.log(` ${E(`Current: ${S.provider}/${S.model}`)}`);let L=S?.provider??a.name,F=Xe.map(Se=>Se.name).join(", ");console.log(` ${E(`Providers: ${F}`)}`);let Te=(await c.question(` ${M}Provider: ${k}${E(`[${L}] `)}`)).trim()||L;if(!Te&&!j){console.log(` ${E("Skipped.")}`);continue}let q=Te,_e,Ce;if(q!==a.name){let Se=S?.apiKey??t.env[`ALFRED_LLM_${$.key.toUpperCase()}_API_KEY`]??"";if(Se?_e=await O(c,` API key for ${q}`,Se):(Xe.find(qe=>qe.name===q)?.needsApiKey??!0)&&(_e=await Ie(c,` API key for ${q}`)),["ollama","openwebui"].includes(q)){let qe=(S?.baseUrl??"")||Xe.find(Yr=>Yr.name===q)?.baseUrl||"";qe&&(Ce=await O(c,` ${q} URL`,qe))}}let mt=_e??(q===a.name?l:void 0),Ns=Ce??(q===a.name?m:void 0),yo=Xe.find(Se=>Se.name===q),wo=await qi(q,mt,Ns),Je=zi(wo,yo?.models??[]),He;if(Je.length>0){console.log(` ${R("Available models:")}`);for(let Rt=0;Rt<Je.length;Rt++){let qe=Je[Rt],Yr=qe.desc??qe.name??"",iu=qe.id===S?.model?` ${D("(current)")}`:"";console.log(` ${me(`${Rt+1})`)} ${qe.id}${Yr?` ${E(`\u2014 ${Yr}`)}`:""}${iu}`)}console.log(` ${me(`${Je.length+1})`)} ${E("Other (enter manually)")}`),console.log(` ${me("0)")} ${E("Skip this tier")}`);let Se=(await c.question(` ${M}> ${k}${j?E(`[${S.model}] `):""}`)).trim();if(Se==="0"){console.log(` ${E("Skipped.")}`);continue}let Xr=parseInt(Se,10)-1;Xr>=0&&Xr<Je.length?He=Je[Xr].id:!Se&&j?He=S.model:He=await O(c," Model ID",j?S.model:$.defaultModel)}else if(console.log(` ${E("Press Enter to skip.")}`),He=(await c.question(` ${M}Model: ${k}${j?E(`[${S.model}] `):""}`)).trim()||(j?S.model:""),!He){console.log(` ${E("Skipped.")}`);continue}x[$.key]={provider:q,model:He,..._e?{apiKey:_e}:{},...Ce?{baseUrl:Ce}:{}},console.log(` ${D(">")} ${$.label}: ${R(q)}/${R(He)}`)}Object.keys(x).length===0&&console.log(`
901
- ${E("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${E("Using single model for all tasks.")}`);let V=["brave","tavily","duckduckgo","searxng"],be=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",he=V.indexOf(be),ce=he>=0?he+1:0;console.log(`
902
- ${R("Web Search provider (for searching the internet):")}`);let le=["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"],W=u(w=>he===w?` ${E("(current)")}`:"","mark");console.log(` ${me("0)")} None (disable web search)${he===-1&&be===""?` ${E("(current)")}`:""}`);for(let w=0;w<le.length;w++)console.log(` ${me(String(w+1)+")")} ${le[w]}${W(w)}`);let fe=await Lr(c,"> ",0,V.length,ce),ge,de="",re="";if(fe>=1&&fe<=V.length&&(ge=V[fe-1]),ge==="brave"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?de=await O(c," Brave Search API key",w):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),de=await Ie(c," Brave Search API key")),console.log(` ${D(">")} Brave Search: ${E(we(de))}`)}else if(ge==="tavily"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?de=await O(c," Tavily API key",w):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),de=await Ie(c," Tavily API key")),console.log(` ${D(">")} Tavily: ${E(we(de))}`)}else if(ge==="duckduckgo")console.log(` ${D(">")} DuckDuckGo: ${E("no API key needed")}`);else if(ge==="searxng"){let w=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";re=await O(c," SearXNG URL",w),re=re.replace(/\/+$/,""),console.log(` ${D(">")} SearXNG: ${E(re)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let N=[];for(let w=0;w<hs.length;w++){let $=hs[w];t.config[$.configKey]?.enabled&&N.push(w+1)}let G=N.length>0?N.join(","):"";console.log(`
903
- ${R("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<hs.length;w++){let $=N.includes(w+1)?` ${E("(enabled)")}`:"";console.log(` ${me(String(w+1)+")")} ${hs[w].label}${$}`)}console.log(` ${me("0)")} None (configure later)`);let $e=(await c.question(`${M}> ${k}${G?E(`[${G}] `):""}`)).trim(),J=[],fs=$e||G;if(fs&&fs!=="0"){let w=fs.split(",").map($=>parseInt($.trim(),10));for(let $ of w)if($>=1&&$<=hs.length){let S=hs[$-1];J.includes(S)||J.push(S)}}J.length>0?console.log(` ${D(">")} Enabling: ${J.map(w=>R(w.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let B={},Q={};for(let w of J){if(w.credentials.length===0){w.name==="whatsapp"&&console.log(`
900
+ ${R(`${$.label} model`)} ${E(`(${$.hint})`)}`),j&&console.log(` ${E(`Current: ${S.provider}/${S.model}`)}`);let D=S?.provider??a.name,F=Ye.map(Se=>Se.name).join(", ");console.log(` ${E(`Providers: ${F}`)}`);let _e=(await c.question(` ${M}Provider: ${k}${E(`[${D}] `)}`)).trim()||D;if(!_e&&!j){console.log(` ${E("Skipped.")}`);continue}let q=_e,Ee,Ce;if(q!==a.name){let Se=S?.apiKey??t.env[`ALFRED_LLM_${$.key.toUpperCase()}_API_KEY`]??"";if(Se?Ee=await O(c,` API key for ${q}`,Se):(Ye.find(ze=>ze.name===q)?.needsApiKey??!0)&&(Ee=await Ie(c,` API key for ${q}`)),["ollama","openwebui"].includes(q)){let ze=(S?.baseUrl??"")||Ye.find(Yr=>Yr.name===q)?.baseUrl||"";ze&&(Ce=await O(c,` ${q} URL`,ze))}}let mt=Ee??(q===a.name?l:void 0),Ns=Ce??(q===a.name?m:void 0),yo=Ye.find(Se=>Se.name===q),wo=await qi(q,mt,Ns),Ze=zi(wo,yo?.models??[]),qe;if(Ze.length>0){console.log(` ${R("Available models:")}`);for(let Rt=0;Rt<Ze.length;Rt++){let ze=Ze[Rt],Yr=ze.desc??ze.name??"",iu=ze.id===S?.model?` ${L("(current)")}`:"";console.log(` ${me(`${Rt+1})`)} ${ze.id}${Yr?` ${E(`\u2014 ${Yr}`)}`:""}${iu}`)}console.log(` ${me(`${Ze.length+1})`)} ${E("Other (enter manually)")}`),console.log(` ${me("0)")} ${E("Skip this tier")}`);let Se=(await c.question(` ${M}> ${k}${j?E(`[${S.model}] `):""}`)).trim();if(Se==="0"){console.log(` ${E("Skipped.")}`);continue}let Xr=parseInt(Se,10)-1;Xr>=0&&Xr<Ze.length?qe=Ze[Xr].id:!Se&&j?qe=S.model:qe=await O(c," Model ID",j?S.model:$.defaultModel)}else if(console.log(` ${E("Press Enter to skip.")}`),qe=(await c.question(` ${M}Model: ${k}${j?E(`[${S.model}] `):""}`)).trim()||(j?S.model:""),!qe){console.log(` ${E("Skipped.")}`);continue}x[$.key]={provider:q,model:qe,...Ee?{apiKey:Ee}:{},...Ce?{baseUrl:Ce}:{}},console.log(` ${L(">")} ${$.label}: ${R(q)}/${R(qe)}`)}Object.keys(x).length===0&&console.log(`
901
+ ${E("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${E("Using single model for all tasks.")}`);let V=["brave","tavily","duckduckgo","searxng"],Te=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",he=V.indexOf(Te),le=he>=0?he+1:0;console.log(`
902
+ ${R("Web Search provider (for searching the internet):")}`);let re=["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"],W=u(w=>he===w?` ${E("(current)")}`:"","mark");console.log(` ${me("0)")} None (disable web search)${he===-1&&Te===""?` ${E("(current)")}`:""}`);for(let w=0;w<re.length;w++)console.log(` ${me(String(w+1)+")")} ${re[w]}${W(w)}`);let fe=await Dr(c,"> ",0,V.length,le),ge,de="",ne="";if(fe>=1&&fe<=V.length&&(ge=V[fe-1]),ge==="brave"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?de=await O(c," Brave Search API key",w):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),de=await Ie(c," Brave Search API key")),console.log(` ${L(">")} Brave Search: ${E(we(de))}`)}else if(ge==="tavily"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?de=await O(c," Tavily API key",w):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),de=await Ie(c," Tavily API key")),console.log(` ${L(">")} Tavily: ${E(we(de))}`)}else if(ge==="duckduckgo")console.log(` ${L(">")} DuckDuckGo: ${E("no API key needed")}`);else if(ge==="searxng"){let w=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";ne=await O(c," SearXNG URL",w),ne=ne.replace(/\/+$/,""),console.log(` ${L(">")} SearXNG: ${E(ne)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let N=[];for(let w=0;w<hs.length;w++){let $=hs[w];t.config[$.configKey]?.enabled&&N.push(w+1)}let G=N.length>0?N.join(","):"";console.log(`
903
+ ${R("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<hs.length;w++){let $=N.includes(w+1)?` ${E("(enabled)")}`:"";console.log(` ${me(String(w+1)+")")} ${hs[w].label}${$}`)}console.log(` ${me("0)")} None (configure later)`);let $e=(await c.question(`${M}> ${k}${G?E(`[${G}] `):""}`)).trim(),J=[],fs=$e||G;if(fs&&fs!=="0"){let w=fs.split(",").map($=>parseInt($.trim(),10));for(let $ of w)if($>=1&&$<=hs.length){let S=hs[$-1];J.includes(S)||J.push(S)}}J.length>0?console.log(` ${L(">")} Enabling: ${J.map(w=>R(w.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let B={},Q={};for(let w of J){if(w.credentials.length===0){w.name==="whatsapp"&&console.log(`
904
904
  ${zp("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
905
- ${R(w.label+" configuration:")}`);let $={};for(let S of w.credentials){let j=t.env[S.envKey]??"",L;j?L=await O(c,` ${S.prompt}`,j):S.defaultValue?L=await O(c,` ${S.prompt}`,S.defaultValue):S.required?L=await Ie(c,` ${S.prompt}`):(L=(await c.question(` ${S.prompt}: ${M}`)).trim(),process.stdout.write(k)),$[S.configField]=L,Q[S.envKey]=L,S.configField==="token"||S.configField==="accessToken"?console.log(` ${D(">")} Set: ${E(we(L))}`):console.log(` ${D(">")} Set: ${E(L)}`)}B[w.configKey]=$}let se=t.config.email?.accounts??[],ee=se[0],It=ee?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",ke=ee?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",qn=se.length>0||!!It||ke==="microsoft",Cd=qn?"Y/n":"y/N";console.log(`
906
- ${R("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let zn=(await c.question(`${M}> ${k}${E(`[${Cd}] `)}`)).trim().toLowerCase(),Mr=zn===""?qn:zn==="y"||zn==="yes",Pe=[],Nd={"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"}},Yi=u(async(w,$)=>{let S={name:w,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},j=$?.provider??"",L=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],F=j==="microsoft"?1:0;console.log("");for(let q=0;q<L.length;q++){let _e=q===F?` ${E("(current)")}`:"";console.log(` ${me(`${q+1})`)} ${L[q]}${_e}`)}let K=(await c.question(`${M}> ${k}${E(`[${F+1}] `)}`)).trim(),Te=K===""?F:parseInt(K,10)-1;if(S.provider=Te===1?"microsoft":"imap-smtp",S.provider==="microsoft"){let q=t.config.calendar?.microsoft,_e=$?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",Ce=$?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",mt=$?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(q&&!_e)console.log(` ${D(">")} 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")}`),S.msClientId=await O(c," Client ID",_e),S.msClientId||(S.msClientId=await Ie(c," Client ID"));let Ns=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";S.msClientSecret=await O(c," Client Secret",Ns),S.msClientSecret||(S.msClientSecret=await Ie(c," Client Secret")),S.msTenantId=await O(c," Tenant ID",Ce),S.msTenantId||(S.msTenantId=await Ie(c," Tenant ID")),console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),S.msRefreshToken=await O(c," Refresh Token",mt),S.msRefreshToken||(S.msRefreshToken=await Ie(c," Refresh Token"))}console.log(` ${D(">")} Email [${w}]: Microsoft 365 (Graph API)`)}else{let q=$?.auth?.user??"";console.log(""),S.user=await O(c," Email address",q||""),S.user||(S.user=await Ie(c," Email address"));let _e=$?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";_e?S.pass=await O(c," Password / App password",_e):(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")}`),S.pass=await Ie(c," Password / App password"));let Ce=S.user.split("@")[1]?.toLowerCase()??"",mt=Nd[Ce],Ns=$?.imap?.host??mt?.imap??`imap.${Ce}`,yo=$?.smtp?.host??mt?.smtp??`smtp.${Ce}`,wo=$?.imap?.port??993,Je=$?.smtp?.port??587;mt&&console.log(` ${D(">")} Detected ${Ce} \u2014 using preset server settings`),S.imapHost=await O(c," IMAP server",Ns);let He=await O(c," IMAP port",String(wo));S.imapPort=parseInt(He,10)||993,S.smtpHost=await O(c," SMTP server",yo);let Se=await O(c," SMTP port",String(Je));S.smtpPort=parseInt(Se,10)||587,console.log(` ${D(">")} Email [${w}]: ${E(S.user)} via ${E(S.imapHost)}`)}return S},"configureEmailAccount");if(Mr){let w=ee??(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);Pe.push(await Yi("default",w));let $=!0;for(;$;){let S=(await c.question(`
907
- ${R("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if(S==="y"||S==="yes"){let L=(await c.question(` ${R("Account name:")} `)).trim()||`account${Pe.length+1}`,F=se.find(K=>K.name===L);Pe.push(await Yi(L,F))}else $=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let Or=["openai","groq"],Ld=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",Pr=Or.indexOf(Ld),Dd=Pr>=0?Pr+1:0;console.log(`
908
- ${R("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let Ji=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${me("0)")} None (disable voice transcription)${Pr===-1?` ${E("(current)")}`:""}`);for(let w=0;w<Ji.length;w++){let $=Pr===w?` ${E("(current)")}`:"";console.log(` ${me(String(w+1)+")")} ${Ji[w]}${$}`)}let Wn=await Lr(c,"> ",0,Or.length,Dd),Ue,Ye="",gs="";if(Wn>=1&&Wn<=Or.length&&(Ue=Or[Wn-1]),Ue==="openai"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?Ye=await O(c," OpenAI API key (for Whisper)",w):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),Ye=await Ie(c," OpenAI API key")),console.log(` ${D(">")} OpenAI Whisper: ${E(we(Ye))}`)}else if(Ue==="groq"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?Ye=await O(c," Groq API key",w):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),Ye=await Ie(c," Groq API key"));let $=t.env.ALFRED_SPEECH_BASE_URL??"";$&&(gs=await O(c," Groq API URL",$)),console.log(` ${D(">")} Groq Whisper: ${E(we(Ye))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let ys=!1,ws="alloy";if(Ue){let w=t.config.speech?.ttsEnabled??!1,$=w?"Y/n":"y/N";console.log(`
909
- ${R("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let S=(await c.question(`${M}> ${k}${E(`[${$}] `)}`)).trim().toLowerCase();if(ys=S===""?w:S==="y"||S==="yes",ys){let j=["alloy","echo","fable","onyx","nova","shimmer"],L=t.config.speech?.ttsVoice??"alloy",F=j.indexOf(L),K=F>=0?F+1:1;console.log(`
910
- ${R("Which voice?")}`);for(let q=0;q<j.length;q++){let _e=F===q?` ${E("(current)")}`:"";console.log(` ${me(String(q+1)+")")} ${j[q]}${_e}`)}let Te=await Lr(c," > ",1,j.length,K);ws=j[Te-1],console.log(` ${D(">")} TTS voice: ${R(ws)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Md=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
911
- ${R("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Gn=(await c.question(`${M}> ${k}${E(`[${Md}] `)}`)).trim().toLowerCase(),Vn=Gn===""?t.codeSandboxEnabled:Gn==="y"||Gn==="yes";console.log(Vn?` ${D(">")} Code Sandbox ${R("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
912
- ${R("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let Kn=[];for(let w of md){let $=Wp(w.whichCmd);$?(Kn.push({...w,resolvedPath:$}),console.log(` ${D("\u2713")} ${R(w.label)} ${E(`(${$})`)}`)):console.log(` ${E("\xB7")} ${E(w.label)} ${E("\u2014 not found")}`)}let Xn=(t.config.codeAgents?.agents??[]).filter(w=>!md.some($=>$.name===w.name));for(let w of Xn)console.log(` ${D("\u2713")} ${R(w.name)} ${E(`(${w.command}) \u2014 from existing config`)}`);let nt=[];if(Kn.length===0&&Xn.length===0)console.log(`
913
- ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let w=[...Kn.map(L=>({name:L.name,command:L.resolvedPath??L.command,argsTemplate:L.argsTemplate,promptVia:L.promptVia,label:L.label,detected:!0})),...Xn.map(L=>({name:L.name,command:L.command,argsTemplate:L.argsTemplate,promptVia:L.promptVia??"arg",label:L.name,detected:!1}))];console.log(`
914
- ${R("Which agents should Alfred use?")} ${E("(comma-separated, e.g. 1,2)")}`);let $=new Set((t.config.codeAgents?.agents??[]).map(L=>L.name));for(let L=0;L<w.length;L++){let F=w[L],K=$.has(F.name)?` ${E("(current)")}`:"";console.log(` ${M}${L+1}${k}) ${F.label}${K}`)}console.log(` ${M}0${k}) None`);let S=w.map((L,F)=>$.size>0?$.has(L.name)?String(F+1):null:L.detected?String(F+1):null).filter(Boolean).join(",")||"0",j=(await c.question(` ${M}> ${k}${E(`[${S}] `)}`)).trim()||S;j!=="0"&&(nt=j.split(",").map(F=>parseInt(F.trim(),10)).filter(F=>!isNaN(F)&&F>=1&&F<=w.length).map(F=>{let K=w[F-1];return{name:K.name,command:K.command,argsTemplate:K.argsTemplate,promptVia:K.promptVia}})),nt.length>0?console.log(` ${D(">")} ${R(String(nt.length))} agent(s) selected: ${nt.map(L=>L.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let Yn=t.config.codeAgents?.forge,Jn=Yn?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
915
- ${R("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 Zi=[{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 Zi){let $=w.name===Jn?` ${E("(current)")}`:"";console.log(` ${M}${w.num}${k}) ${w.label}${$}`)}let Qi=Jn==="github"?"2":Jn==="gitlab"?"3":"1",Od=(await c.question(`${M}> ${k}${E(`[${Qi}] `)}`)).trim()||Qi,ot=Zi.find(w=>w.num===Od)?.name??"",Ts="",_s="";if(ot==="github"){console.log(` ${D(">")} Forge: ${R("GitHub")}`);let w=t.env.ALFRED_GITHUB_TOKEN??Yn?.github?.token??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),Ts=(await c.question(` ${H}GitHub Token${k}: ${M}`)).trim(),process.stdout.write(k),!Ts&&w&&(Ts=w)}else if(ot==="gitlab"){console.log(` ${D(">")} Forge: ${R("GitLab")}`);let w=t.env.ALFRED_GITLAB_TOKEN??Yn?.gitlab?.token??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),_s=(await c.question(` ${H}GitLab Token${k}: ${M}`)).trim(),process.stdout.write(k),!_s&&w&&(_s=w)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
916
- ${R("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Es=t.config.proxmox,Zn=t.env.ALFRED_PROXMOX_BASE_URL??Es?.baseUrl??"",Pd=Zn?"Y/n":"y/N",ea=(await c.question(` ${H}Enable Proxmox VE?${k} ${E(`[${Pd}]`)}: ${M}`)).trim().toLowerCase()||(Zn?"y":"n");process.stdout.write(k);let Ur=ea==="y"||ea==="yes",bs="",Qn="",$s="",eo=!0;if(Ur){bs=await O(c," Proxmox URL (e.g. https://pve.local:8006)",Zn||"https://pve.local:8006");let w=t.env.ALFRED_PROXMOX_TOKEN_ID??Es?.tokenId??"";w&&console.log(` ${E(`Current token ID: ${w}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),Qn=await O(c," API Token ID (user@realm!name)",w);let $=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Es?.tokenSecret??"";$&&console.log(` ${E(`Current secret: ${we($)}`)}`),$s=(await c.question(` ${H}API Token Secret${k}: ${M}`)).trim(),process.stdout.write(k),!$s&&$&&($s=$);let S=Es?.verifyTls===!1?"y/N":"Y/n",j=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${S}]`)}: ${M}`)).trim().toLowerCase()||(Es?.verifyTls===!1?"n":"y");process.stdout.write(k),eo=j==="y"||j==="yes",console.log(` ${D(">")} Proxmox: ${R(bs)} ${E(`(TLS verify: ${eo?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let it=t.config.unifi,to=t.env.ALFRED_UNIFI_BASE_URL??it?.baseUrl??"",Ud=to?"Y/n":"y/N",ta=(await c.question(`
917
- ${H}Enable UniFi Network?${k} ${E(`[${Ud}]`)}: ${M}`)).trim().toLowerCase()||(to?"y":"n");process.stdout.write(k);let ks=ta==="y"||ta==="yes",xt="",at="",so="",vs="",ro=!0;if(ks){xt=await O(c," UniFi URL (e.g. https://unifi.local)",to||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let w=t.env.ALFRED_UNIFI_API_KEY??it?.apiKey??"",$=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],S=w?"1":it?.username?"2":"1";for(let K of $)console.log(` ${M}${K.num}${k}) ${K.label}`);if(((await c.question(` ${M}> ${k}${E(`[${S}] `)}`)).trim()||S)==="1")w&&console.log(` ${E(`Current key: ${we(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),at=(await c.question(` ${H}API Key${k}: ${M}`)).trim(),process.stdout.write(k),!at&&w&&(at=w);else{let K=t.env.ALFRED_UNIFI_USERNAME??it?.username??"";so=await O(c," Username",K||"alfred");let Te=t.env.ALFRED_UNIFI_PASSWORD??it?.password??"";Te&&console.log(` ${E(`Current password: ${we(Te)}`)}`),vs=(await c.question(` ${H}Password${k}: ${M}`)).trim(),process.stdout.write(k),!vs&&Te&&(vs=Te)}let L=it?.verifyTls===!1?"y/N":"Y/n",F=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${L}]`)}: ${M}`)).trim().toLowerCase()||(it?.verifyTls===!1?"n":"y");process.stdout.write(k),ro=F==="y"||F==="yes",console.log(` ${D(">")} UniFi: ${R(xt)} ${E(`(TLS verify: ${ro?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let Fr=t.config.homeassistant,no=t.env.ALFRED_HOMEASSISTANT_URL??Fr?.baseUrl??"",Fd=no?"Y/n":"y/N",sa=(await c.question(`
918
- ${H}Enable Home Assistant?${k} ${E(`[${Fd}]`)}: ${M}`)).trim().toLowerCase()||(no?"y":"n");process.stdout.write(k);let jr=sa==="y"||sa==="yes",Ss="",As="",oo=!0;if(jr){Ss=await O(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",no||"http://homeassistant.local:8123");let w=t.env.ALFRED_HOMEASSISTANT_TOKEN??Fr?.accessToken??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),As=(await c.question(` ${H}Long-Lived Access Token${k}: ${M}`)).trim(),process.stdout.write(k),!As&&w&&(As=w);let $=Fr?.verifyTls===!1?"y/N":"Y/n",S=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${$}]`)}: ${M}`)).trim().toLowerCase()||(Fr?.verifyTls===!1?"n":"y");process.stdout.write(k),oo=S==="y"||S==="yes",console.log(` ${D(">")} Home Assistant: ${R(Ss)} ${E(`(TLS verify: ${oo?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let xe=t.config.contacts,io=t.env.ALFRED_CONTACTS_PROVIDER??xe?.provider??"",jd=io?"Y/n":"y/N",ra=(await c.question(`
919
- ${H}Enable Contacts management?${k} ${E(`[${jd}]`)}: ${M}`)).trim().toLowerCase()||(io?"y":"n");process.stdout.write(k);let Br=ra==="y"||ra==="yes",Re="",ue={};if(Br){let w=["carddav","google","microsoft"],$=w.indexOf(io),S=$>=0?$+1:1;console.log(` ${me("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${me("2)")} Google Contacts`),console.log(` ${me("3)")} Microsoft 365`);let j=await Lr(c," > ",1,3,S);if(Re=w[j-1],ue.ALFRED_CONTACTS_PROVIDER=Re,Re==="carddav"){let L=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??xe?.carddav?.serverUrl??"";ue.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await O(c," CardDAV Server URL",L||"https://cloud.example.com/remote.php/dav");let F=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??xe?.carddav?.username??"";ue.ALFRED_CARDDAV_CONTACTS_USERNAME=await O(c," Username",F);let K=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??xe?.carddav?.password??"";K&&console.log(` ${E(`Current password: ${we(K)}`)}`);let Te=(await c.question(` ${H}Password${k}: ${M}`)).trim();process.stdout.write(k),ue.ALFRED_CARDDAV_CONTACTS_PASSWORD=Te||K}else if(Re==="google"){let L=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??xe?.google?.clientId??"";L&&console.log(` ${E(`Current client ID: ${we(L)}`)}`),ue.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await c.question(` ${H}Google Client ID${k}: ${M}`)).trim()||L,process.stdout.write(k);let F=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??xe?.google?.clientSecret??"";ue.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await c.question(` ${H}Google Client Secret${k}: ${M}`)).trim()||F,process.stdout.write(k);let K=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??xe?.google?.refreshToken??"";ue.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await c.question(` ${H}Refresh Token${k}: ${M}`)).trim()||K,process.stdout.write(k)}else if(Re==="microsoft"){let L=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??xe?.microsoft?.clientId??"";L&&console.log(` ${E(`Current client ID: ${we(L)}`)}`),ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await c.question(` ${H}Microsoft Client ID${k}: ${M}`)).trim()||L,process.stdout.write(k);let F=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??xe?.microsoft?.clientSecret??"";ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await c.question(` ${H}Microsoft Client Secret${k}: ${M}`)).trim()||F,process.stdout.write(k);let K=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??xe?.microsoft?.tenantId??"";ue.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await O(c," Tenant ID",K||"common");let Te=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??xe?.microsoft?.refreshToken??"";console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),ue.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await c.question(` ${H}Refresh Token${k}: ${M}`)).trim()||Te,process.stdout.write(k)}console.log(` ${D(">")} Contacts: ${R(Re)}`)}else console.log(` ${E("Contacts disabled.")}`);let na=t.config.docker,ao=t.env.ALFRED_DOCKER_SOCKET_PATH??na?.socketPath??"",co=t.env.ALFRED_DOCKER_HOST??na?.host??"",Bd=ao||co?"Y/n":"y/N",oa=(await c.question(`
920
- ${H}Enable Docker management?${k} ${E(`[${Bd}]`)}: ${M}`)).trim().toLowerCase()||(ao||co?"y":"n");process.stdout.write(k);let Hr=oa==="y"||oa==="yes",ct="",lt="";if(Hr){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.")}`),ct=await O(c," Docker socket path",ao||w);let $=(await c.question(` ${H}Docker host URL (optional, for remote)${k}: ${M}`)).trim();process.stdout.write(k),lt=$||co,console.log(` ${D(">")} Docker: ${R(lt||ct)}`)}else console.log(` ${E("Docker disabled.")}`);let Hd=t.config.bmw,lo=t.env.ALFRED_BMW_CLIENT_ID??Hd?.clientId??"",qd=lo?"Y/n":"y/N",ia=(await c.question(`
921
- ${H}Enable BMW CarData (vehicle status, charging)?${k} ${E(`[${qd}]`)}: ${M}`)).trim().toLowerCase()||(lo?"y":"n");process.stdout.write(k);let qr=ia==="y"||ia==="yes",uo="";qr?(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)')}`),uo=await O(c," BMW CarData Client ID",lo),console.log(` ${D(">")} BMW CarData: ${R("enabled")}`)):console.log(` ${E("BMW CarData disabled.")}`);let zd=t.config.routing,mo=t.env.ALFRED_ROUTING_API_KEY??zd?.apiKey??"",Wd=mo?"Y/n":"y/N",aa=(await c.question(`
922
- ${H}Enable route planning with live traffic (Google Routes)?${k} ${E(`[${Wd}]`)}: ${M}`)).trim().toLowerCase()||(mo?"y":"n");process.stdout.write(k);let zr=aa==="y"||aa==="yes",po="";zr?(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")}`),po=await O(c," Google Maps API Key",mo),console.log(` ${D(">")} Routing: ${R("enabled")}`)):console.log(` ${E("Routing disabled.")}`);let Be=t.config.energy,Gd=t.env.ALFRED_ENERGY_GRID_NAME??Be?.gridName??"",ho=t.env.ALFRED_ENERGY_GRID_USAGE_CT??(Be?.gridUsageCt!=null?String(Be.gridUsageCt):""),Vd=t.env.ALFRED_ENERGY_GRID_LOSS_CT??(Be?.gridLossCt!=null?String(Be.gridLossCt):""),Kd=t.env.ALFRED_ENERGY_GRID_CAPACITY_FEE??(Be?.gridCapacityFee!=null?String(Be.gridCapacityFee):""),Xd=t.env.ALFRED_ENERGY_GRID_METER_FEE??(Be?.gridMeterFee!=null?String(Be.gridMeterFee):""),Yd=ho?"Y/n":"y/N",ca=(await c.question(`
923
- ${H}Enable energy prices (aWATTar HOURLY / EPEX Spot AT)?${k} ${E(`[${Yd}]`)}: ${M}`)).trim().toLowerCase()||(ho?"y":"n");process.stdout.write(k);let Wr=ca==="y"||ca==="yes",dt="",ut="",Gr="",Is="",xs="";Wr?(console.log(` ${E('Die Werte findest du auf deiner Stromrechnung unter "Netzentgelte".')}`),console.log(` ${E("Marktpreis + aWATTar-Aufschlag + Abgaben werden automatisch berechnet.")}`),console.log(""),dt=await O(c," Netzbetreiber Name (z.B. Netz Nieder\xF6sterreich)",Gd),ut=await O(c," Netznutzungsentgelt (ct/kWh netto)",ho),Gr=await O(c," Netzverlustentgelt (ct/kWh netto)",Vd||"0.38"),Is=await O(c," Leistungspauschale (\u20AC/Monat netto)",Kd),xs=await O(c," Messentgelt (\u20AC/Monat netto)",Xd||"2.22"),console.log(` ${D(">")} Energy: ${R(dt||"enabled")} (${ut} + ${Gr} ct/kWh)`)):console.log(` ${E("Energy prices disabled (Marktpreise weiterhin ohne Netzentgelte verf\xFCgbar).")}`),console.log(`
924
- ${R("Security configuration:")}`);let la=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",ve;if(la)ve=await O(c,"Owner user ID (for elevated permissions)",la);else{let w=(await c.question(`${H}Owner user ID${k} ${E("(optional, for elevated permissions)")}: ${M}`)).trim();process.stdout.write(k),ve=w}let Rs=!1;if(ve){let w=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${R("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let $=(await c.question(` ${M}> ${k}${E(`[${w}] `)}`)).trim().toLowerCase();$===""?Rs=t.shellEnabled:Rs=$==="y"||$==="yes",console.log(Rs?` ${D(">")} Shell access ${R("enabled")} for owner ${E(ve)}`:` ${E("Shell access disabled.")}`)}let Jd=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${R("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let fo=(await c.question(` ${M}> ${k}${E(`[${Jd}] `)}`)).trim().toLowerCase(),Cs;fo===""?Cs=t.writeInGroups:Cs=fo==="y"||fo==="yes",console.log(Cs?` ${D(">")} Write actions ${R("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let Zd=t.rateLimit??30;console.log("");let Qd=await O(c," Rate limit (max write actions per hour per user)",String(Zd)),Vr=Math.max(1,parseInt(Qd,10)||30);console.log(` ${D(">")} Rate limit: ${R(String(Vr))} per hour`),console.log(`
925
- ${R("Writing configuration files...")}`);let v=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";v.push(`${w}=${l}`)}if(f!==a.defaultModel&&v.push(`ALFRED_LLM_MODEL=${f}`),m&&v.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(x).length>0){v.push("","# === Additional Model Tiers ===");for(let[w,$]of Object.entries(x)){let S=`ALFRED_LLM_${w.toUpperCase()}`;v.push(""),v.push(`${S}_PROVIDER=${$.provider}`),v.push(`${S}_MODEL=${$.model}`),$.apiKey&&v.push(`${S}_API_KEY=${$.apiKey}`),$.baseUrl&&v.push(`${S}_BASE_URL=${$.baseUrl}`)}}v.push("","# === Messaging Platforms ===","");for(let[w,$]of Object.entries(Q))v.push(`${w}=${$}`);if(v.push("","# === Web Search ===",""),ge?(v.push(`ALFRED_SEARCH_PROVIDER=${ge}`),de&&v.push(`ALFRED_SEARCH_API_KEY=${de}`),re&&v.push(`ALFRED_SEARCH_BASE_URL=${re}`)):(v.push("# ALFRED_SEARCH_PROVIDER=brave"),v.push("# ALFRED_SEARCH_API_KEY=")),v.push("","# === Email ===",""),Mr&&Pe.length>0){let w=Pe[0];w.provider==="microsoft"?(v.push("ALFRED_EMAIL_PROVIDER=microsoft"),w.msClientId?(v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${w.msClientId}`),v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${w.msClientSecret}`),v.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${w.msTenantId}`),v.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${w.msRefreshToken}`)):v.push("# Microsoft email credentials shared from calendar config")):(v.push(`ALFRED_EMAIL_USER=${w.user}`),v.push(`ALFRED_EMAIL_PASS=${w.pass}`)),Pe.length>1&&v.push("# Additional email accounts configured in config/default.yml")}else v.push("# ALFRED_EMAIL_USER="),v.push("# ALFRED_EMAIL_PASS=");if(v.push("","# === Speech ===",""),Ue?(v.push(`ALFRED_SPEECH_PROVIDER=${Ue}`),v.push(`ALFRED_SPEECH_API_KEY=${Ye}`),gs&&v.push(`ALFRED_SPEECH_BASE_URL=${gs}`),ys&&(v.push("ALFRED_TTS_ENABLED=true"),v.push(`ALFRED_TTS_VOICE=${ws}`))):(v.push("# ALFRED_SPEECH_PROVIDER=groq"),v.push("# ALFRED_SPEECH_API_KEY=")),v.push("","# === Forge (GitHub / GitLab) ===",""),ot==="github"?(v.push("ALFRED_FORGE_PROVIDER=github"),v.push(`ALFRED_GITHUB_TOKEN=${Ts}`)):ot==="gitlab"?(v.push("ALFRED_FORGE_PROVIDER=gitlab"),v.push(`ALFRED_GITLAB_TOKEN=${_s}`)):(v.push("# ALFRED_FORGE_PROVIDER=github"),v.push("# ALFRED_GITHUB_TOKEN=")),v.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Ur?(v.push(`ALFRED_PROXMOX_BASE_URL=${bs}`),v.push(`ALFRED_PROXMOX_TOKEN_ID=${Qn}`),v.push(`ALFRED_PROXMOX_TOKEN_SECRET=${$s}`)):(v.push("# ALFRED_PROXMOX_BASE_URL="),v.push("# ALFRED_PROXMOX_TOKEN_ID="),v.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),ks&&at?(v.push(`ALFRED_UNIFI_BASE_URL=${xt}`),v.push(`ALFRED_UNIFI_API_KEY=${at}`)):ks?(v.push(`ALFRED_UNIFI_BASE_URL=${xt}`),v.push(`ALFRED_UNIFI_USERNAME=${so}`),v.push(`ALFRED_UNIFI_PASSWORD=${vs}`)):(v.push("# ALFRED_UNIFI_BASE_URL="),v.push("# ALFRED_UNIFI_API_KEY=")),jr?(v.push(`ALFRED_HOMEASSISTANT_URL=${Ss}`),v.push(`ALFRED_HOMEASSISTANT_TOKEN=${As}`)):(v.push("# ALFRED_HOMEASSISTANT_URL="),v.push("# ALFRED_HOMEASSISTANT_TOKEN=")),v.push("","# === Contacts ===",""),Br)for(let[w,$]of Object.entries(ue))v.push(`${w}=${$}`);else v.push("# ALFRED_CONTACTS_PROVIDER=carddav");v.push("","# === Docker ===",""),Hr?(ct&&v.push(`ALFRED_DOCKER_SOCKET_PATH=${ct}`),lt&&v.push(`ALFRED_DOCKER_HOST=${lt}`)):(v.push("# ALFRED_DOCKER_SOCKET_PATH="),v.push("# ALFRED_DOCKER_HOST=")),v.push("","# === BMW CarData ===",""),qr?v.push(`ALFRED_BMW_CLIENT_ID=${uo}`):v.push("# ALFRED_BMW_CLIENT_ID="),v.push("","# === Routing ===",""),zr?v.push(`ALFRED_ROUTING_API_KEY=${po}`):v.push("# ALFRED_ROUTING_API_KEY="),v.push("","# === Energy / aWATTar ===",""),Wr&&ut?(dt&&v.push(`ALFRED_ENERGY_GRID_NAME=${dt}`),v.push(`ALFRED_ENERGY_GRID_USAGE_CT=${ut}`),v.push(`ALFRED_ENERGY_GRID_LOSS_CT=${Gr}`),Is&&v.push(`ALFRED_ENERGY_GRID_CAPACITY_FEE=${Is}`),xs&&v.push(`ALFRED_ENERGY_GRID_METER_FEE=${xs}`)):(v.push("# ALFRED_ENERGY_GRID_NAME="),v.push("# ALFRED_ENERGY_GRID_USAGE_CT="),v.push("# ALFRED_ENERGY_GRID_LOSS_CT="),v.push("# ALFRED_ENERGY_GRID_CAPACITY_FEE="),v.push("# ALFRED_ENERGY_GRID_METER_FEE=")),v.push("","# === Security ===",""),ve?v.push(`ALFRED_OWNER_USER_ID=${ve}`):v.push("# ALFRED_OWNER_USER_ID="),v.push("");let eu=Ee.join(e,".env");pe.writeFileSync(eu,v.join(`
926
- `),"utf-8"),console.log(` ${D("+")} ${E(".env")} written`);let Kr=Ee.join(e,"config");pe.existsSync(Kr)||pe.mkdirSync(Kr,{recursive:!0});let da={name:r,telegram:{token:B.telegram?.token??"",enabled:J.some(w=>w.name==="telegram")},discord:{token:B.discord?.token??"",enabled:J.some(w=>w.name==="discord")},whatsapp:{enabled:J.some(w=>w.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:B.matrix?.homeserverUrl??"https://matrix.org",accessToken:B.matrix?.accessToken??"",userId:B.matrix?.userId??"",enabled:J.some(w=>w.name==="matrix")},signal:{apiUrl:B.signal?.apiUrl??"http://localhost:8080",phoneNumber:B.signal?.phoneNumber??"",enabled:J.some(w=>w.name==="signal")},llm:Object.keys(x).length>0?{default:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...x}:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...ge?{search:{provider:ge,...de?{apiKey:de}:{},...re?{baseUrl:re}:{}}}:{},...Mr&&Pe.length>0?{email:{accounts:Pe.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}})}}:{},...Ue?{speech:{provider:Ue,apiKey:Ye,...gs?{baseUrl:gs}:{},...ys?{ttsEnabled:!0,ttsVoice:ws}:{}}}:{},...Vn?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...nt.length>0||ot?{codeAgents:{enabled:nt.length>0,agents:nt,...ot==="github"?{forge:{provider:"github",github:{token:Ts}}}:ot==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:_s}}}:{}}}:{},...Ur?{proxmox:{baseUrl:bs,tokenId:Qn,tokenSecret:$s,verifyTls:eo}}:{},...ks?{unifi:{baseUrl:xt,...at?{apiKey:at}:{username:so,password:vs},site:"default",verifyTls:ro}}:{},...jr?{homeassistant:{baseUrl:Ss,accessToken:As,verifyTls:oo}}:{},...Br?{contacts:{provider:Re,...Re==="carddav"?{carddav:{serverUrl:ue.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:ue.ALFRED_CARDDAV_CONTACTS_USERNAME}}:Re==="google"?{google:{clientId:ue.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:Re==="microsoft"?{microsoft:{clientId:ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:ue.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...Hr?{docker:{...ct?{socketPath:ct}:{},...lt?{host:lt}:{}}}:{},...qr?{bmw:{clientId:uo}}:{},...zr?{routing:{apiKey:po}}:{},...Wr&&ut?{energy:{...dt?{gridName:dt}:{},gridUsageCt:parseFloat(ut),gridLossCt:parseFloat(Gr||"0"),...Is?{gridCapacityFee:parseFloat(Is)}:{},...xs?{gridMeterFee:parseFloat(xs)}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};ve&&(da.security.ownerUserId=ve);let tu="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Gi.dump(da,{lineWidth:120,noRefs:!0,sortKeys:!1}),su=Ee.join(Kr,"default.yml");pe.writeFileSync(su,tu,"utf-8"),console.log(` ${D("+")} ${E("config/default.yml")} written`);let go=Ee.join(Kr,"rules");pe.existsSync(go)||pe.mkdirSync(go,{recursive:!0});let ru=Rs&&ve?`
905
+ ${R(w.label+" configuration:")}`);let $={};for(let S of w.credentials){let j=t.env[S.envKey]??"",D;j?D=await O(c,` ${S.prompt}`,j):S.defaultValue?D=await O(c,` ${S.prompt}`,S.defaultValue):S.required?D=await Ie(c,` ${S.prompt}`):(D=(await c.question(` ${S.prompt}: ${M}`)).trim(),process.stdout.write(k)),$[S.configField]=D,Q[S.envKey]=D,S.configField==="token"||S.configField==="accessToken"?console.log(` ${L(">")} Set: ${E(we(D))}`):console.log(` ${L(">")} Set: ${E(D)}`)}B[w.configKey]=$}let se=t.config.email?.accounts??[],ee=se[0],It=ee?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",ke=ee?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",qn=se.length>0||!!It||ke==="microsoft",Cd=qn?"Y/n":"y/N";console.log(`
906
+ ${R("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let zn=(await c.question(`${M}> ${k}${E(`[${Cd}] `)}`)).trim().toLowerCase(),Mr=zn===""?qn:zn==="y"||zn==="yes",Fe=[],Nd={"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"}},Yi=u(async(w,$)=>{let S={name:w,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},j=$?.provider??"",D=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],F=j==="microsoft"?1:0;console.log("");for(let q=0;q<D.length;q++){let Ee=q===F?` ${E("(current)")}`:"";console.log(` ${me(`${q+1})`)} ${D[q]}${Ee}`)}let K=(await c.question(`${M}> ${k}${E(`[${F+1}] `)}`)).trim(),_e=K===""?F:parseInt(K,10)-1;if(S.provider=_e===1?"microsoft":"imap-smtp",S.provider==="microsoft"){let q=t.config.calendar?.microsoft,Ee=$?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",Ce=$?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",mt=$?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(q&&!Ee)console.log(` ${L(">")} 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")}`),S.msClientId=await O(c," Client ID",Ee),S.msClientId||(S.msClientId=await Ie(c," Client ID"));let Ns=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";S.msClientSecret=await O(c," Client Secret",Ns),S.msClientSecret||(S.msClientSecret=await Ie(c," Client Secret")),S.msTenantId=await O(c," Tenant ID",Ce),S.msTenantId||(S.msTenantId=await Ie(c," Tenant ID")),console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),S.msRefreshToken=await O(c," Refresh Token",mt),S.msRefreshToken||(S.msRefreshToken=await Ie(c," Refresh Token"))}console.log(` ${L(">")} Email [${w}]: Microsoft 365 (Graph API)`)}else{let q=$?.auth?.user??"";console.log(""),S.user=await O(c," Email address",q||""),S.user||(S.user=await Ie(c," Email address"));let Ee=$?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";Ee?S.pass=await O(c," Password / App password",Ee):(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")}`),S.pass=await Ie(c," Password / App password"));let Ce=S.user.split("@")[1]?.toLowerCase()??"",mt=Nd[Ce],Ns=$?.imap?.host??mt?.imap??`imap.${Ce}`,yo=$?.smtp?.host??mt?.smtp??`smtp.${Ce}`,wo=$?.imap?.port??993,Ze=$?.smtp?.port??587;mt&&console.log(` ${L(">")} Detected ${Ce} \u2014 using preset server settings`),S.imapHost=await O(c," IMAP server",Ns);let qe=await O(c," IMAP port",String(wo));S.imapPort=parseInt(qe,10)||993,S.smtpHost=await O(c," SMTP server",yo);let Se=await O(c," SMTP port",String(Ze));S.smtpPort=parseInt(Se,10)||587,console.log(` ${L(">")} Email [${w}]: ${E(S.user)} via ${E(S.imapHost)}`)}return S},"configureEmailAccount");if(Mr){let w=ee??(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);Fe.push(await Yi("default",w));let $=!0;for(;$;){let S=(await c.question(`
907
+ ${R("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if(S==="y"||S==="yes"){let D=(await c.question(` ${R("Account name:")} `)).trim()||`account${Fe.length+1}`,F=se.find(K=>K.name===D);Fe.push(await Yi(D,F))}else $=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let Or=["openai","groq"],Dd=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",Pr=Or.indexOf(Dd),Ld=Pr>=0?Pr+1:0;console.log(`
908
+ ${R("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let Ji=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${me("0)")} None (disable voice transcription)${Pr===-1?` ${E("(current)")}`:""}`);for(let w=0;w<Ji.length;w++){let $=Pr===w?` ${E("(current)")}`:"";console.log(` ${me(String(w+1)+")")} ${Ji[w]}${$}`)}let Wn=await Dr(c,"> ",0,Or.length,Ld),je,Je="",gs="";if(Wn>=1&&Wn<=Or.length&&(je=Or[Wn-1]),je==="openai"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?Je=await O(c," OpenAI API key (for Whisper)",w):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),Je=await Ie(c," OpenAI API key")),console.log(` ${L(">")} OpenAI Whisper: ${E(we(Je))}`)}else if(je==="groq"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?Je=await O(c," Groq API key",w):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),Je=await Ie(c," Groq API key"));let $=t.env.ALFRED_SPEECH_BASE_URL??"";$&&(gs=await O(c," Groq API URL",$)),console.log(` ${L(">")} Groq Whisper: ${E(we(Je))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let ys=!1,ws="alloy";if(je){let w=t.config.speech?.ttsEnabled??!1,$=w?"Y/n":"y/N";console.log(`
909
+ ${R("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let S=(await c.question(`${M}> ${k}${E(`[${$}] `)}`)).trim().toLowerCase();if(ys=S===""?w:S==="y"||S==="yes",ys){let j=["alloy","echo","fable","onyx","nova","shimmer"],D=t.config.speech?.ttsVoice??"alloy",F=j.indexOf(D),K=F>=0?F+1:1;console.log(`
910
+ ${R("Which voice?")}`);for(let q=0;q<j.length;q++){let Ee=F===q?` ${E("(current)")}`:"";console.log(` ${me(String(q+1)+")")} ${j[q]}${Ee}`)}let _e=await Dr(c," > ",1,j.length,K);ws=j[_e-1],console.log(` ${L(">")} TTS voice: ${R(ws)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Md=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
911
+ ${R("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Gn=(await c.question(`${M}> ${k}${E(`[${Md}] `)}`)).trim().toLowerCase(),Vn=Gn===""?t.codeSandboxEnabled:Gn==="y"||Gn==="yes";console.log(Vn?` ${L(">")} Code Sandbox ${R("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
912
+ ${R("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let Kn=[];for(let w of md){let $=Wp(w.whichCmd);$?(Kn.push({...w,resolvedPath:$}),console.log(` ${L("\u2713")} ${R(w.label)} ${E(`(${$})`)}`)):console.log(` ${E("\xB7")} ${E(w.label)} ${E("\u2014 not found")}`)}let Xn=(t.config.codeAgents?.agents??[]).filter(w=>!md.some($=>$.name===w.name));for(let w of Xn)console.log(` ${L("\u2713")} ${R(w.name)} ${E(`(${w.command}) \u2014 from existing config`)}`);let nt=[];if(Kn.length===0&&Xn.length===0)console.log(`
913
+ ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let w=[...Kn.map(D=>({name:D.name,command:D.resolvedPath??D.command,argsTemplate:D.argsTemplate,promptVia:D.promptVia,label:D.label,detected:!0})),...Xn.map(D=>({name:D.name,command:D.command,argsTemplate:D.argsTemplate,promptVia:D.promptVia??"arg",label:D.name,detected:!1}))];console.log(`
914
+ ${R("Which agents should Alfred use?")} ${E("(comma-separated, e.g. 1,2)")}`);let $=new Set((t.config.codeAgents?.agents??[]).map(D=>D.name));for(let D=0;D<w.length;D++){let F=w[D],K=$.has(F.name)?` ${E("(current)")}`:"";console.log(` ${M}${D+1}${k}) ${F.label}${K}`)}console.log(` ${M}0${k}) None`);let S=w.map((D,F)=>$.size>0?$.has(D.name)?String(F+1):null:D.detected?String(F+1):null).filter(Boolean).join(",")||"0",j=(await c.question(` ${M}> ${k}${E(`[${S}] `)}`)).trim()||S;j!=="0"&&(nt=j.split(",").map(F=>parseInt(F.trim(),10)).filter(F=>!isNaN(F)&&F>=1&&F<=w.length).map(F=>{let K=w[F-1];return{name:K.name,command:K.command,argsTemplate:K.argsTemplate,promptVia:K.promptVia}})),nt.length>0?console.log(` ${L(">")} ${R(String(nt.length))} agent(s) selected: ${nt.map(D=>D.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let Yn=t.config.codeAgents?.forge,Jn=Yn?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
915
+ ${R("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 Zi=[{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 Zi){let $=w.name===Jn?` ${E("(current)")}`:"";console.log(` ${M}${w.num}${k}) ${w.label}${$}`)}let Qi=Jn==="github"?"2":Jn==="gitlab"?"3":"1",Od=(await c.question(`${M}> ${k}${E(`[${Qi}] `)}`)).trim()||Qi,ot=Zi.find(w=>w.num===Od)?.name??"",Ts="",_s="";if(ot==="github"){console.log(` ${L(">")} Forge: ${R("GitHub")}`);let w=t.env.ALFRED_GITHUB_TOKEN??Yn?.github?.token??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),Ts=(await c.question(` ${H}GitHub Token${k}: ${M}`)).trim(),process.stdout.write(k),!Ts&&w&&(Ts=w)}else if(ot==="gitlab"){console.log(` ${L(">")} Forge: ${R("GitLab")}`);let w=t.env.ALFRED_GITLAB_TOKEN??Yn?.gitlab?.token??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),_s=(await c.question(` ${H}GitLab Token${k}: ${M}`)).trim(),process.stdout.write(k),!_s&&w&&(_s=w)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
916
+ ${R("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Es=t.config.proxmox,Zn=t.env.ALFRED_PROXMOX_BASE_URL??Es?.baseUrl??"",Pd=Zn?"Y/n":"y/N",ea=(await c.question(` ${H}Enable Proxmox VE?${k} ${E(`[${Pd}]`)}: ${M}`)).trim().toLowerCase()||(Zn?"y":"n");process.stdout.write(k);let Ur=ea==="y"||ea==="yes",bs="",Qn="",$s="",eo=!0;if(Ur){bs=await O(c," Proxmox URL (e.g. https://pve.local:8006)",Zn||"https://pve.local:8006");let w=t.env.ALFRED_PROXMOX_TOKEN_ID??Es?.tokenId??"";w&&console.log(` ${E(`Current token ID: ${w}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),Qn=await O(c," API Token ID (user@realm!name)",w);let $=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Es?.tokenSecret??"";$&&console.log(` ${E(`Current secret: ${we($)}`)}`),$s=(await c.question(` ${H}API Token Secret${k}: ${M}`)).trim(),process.stdout.write(k),!$s&&$&&($s=$);let S=Es?.verifyTls===!1?"y/N":"Y/n",j=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${S}]`)}: ${M}`)).trim().toLowerCase()||(Es?.verifyTls===!1?"n":"y");process.stdout.write(k),eo=j==="y"||j==="yes",console.log(` ${L(">")} Proxmox: ${R(bs)} ${E(`(TLS verify: ${eo?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let it=t.config.unifi,to=t.env.ALFRED_UNIFI_BASE_URL??it?.baseUrl??"",Ud=to?"Y/n":"y/N",ta=(await c.question(`
917
+ ${H}Enable UniFi Network?${k} ${E(`[${Ud}]`)}: ${M}`)).trim().toLowerCase()||(to?"y":"n");process.stdout.write(k);let ks=ta==="y"||ta==="yes",xt="",at="",so="",vs="",ro=!0;if(ks){xt=await O(c," UniFi URL (e.g. https://unifi.local)",to||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let w=t.env.ALFRED_UNIFI_API_KEY??it?.apiKey??"",$=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],S=w?"1":it?.username?"2":"1";for(let K of $)console.log(` ${M}${K.num}${k}) ${K.label}`);if(((await c.question(` ${M}> ${k}${E(`[${S}] `)}`)).trim()||S)==="1")w&&console.log(` ${E(`Current key: ${we(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),at=(await c.question(` ${H}API Key${k}: ${M}`)).trim(),process.stdout.write(k),!at&&w&&(at=w);else{let K=t.env.ALFRED_UNIFI_USERNAME??it?.username??"";so=await O(c," Username",K||"alfred");let _e=t.env.ALFRED_UNIFI_PASSWORD??it?.password??"";_e&&console.log(` ${E(`Current password: ${we(_e)}`)}`),vs=(await c.question(` ${H}Password${k}: ${M}`)).trim(),process.stdout.write(k),!vs&&_e&&(vs=_e)}let D=it?.verifyTls===!1?"y/N":"Y/n",F=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${D}]`)}: ${M}`)).trim().toLowerCase()||(it?.verifyTls===!1?"n":"y");process.stdout.write(k),ro=F==="y"||F==="yes",console.log(` ${L(">")} UniFi: ${R(xt)} ${E(`(TLS verify: ${ro?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let Fr=t.config.homeassistant,no=t.env.ALFRED_HOMEASSISTANT_URL??Fr?.baseUrl??"",Fd=no?"Y/n":"y/N",sa=(await c.question(`
918
+ ${H}Enable Home Assistant?${k} ${E(`[${Fd}]`)}: ${M}`)).trim().toLowerCase()||(no?"y":"n");process.stdout.write(k);let jr=sa==="y"||sa==="yes",Ss="",As="",oo=!0;if(jr){Ss=await O(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",no||"http://homeassistant.local:8123");let w=t.env.ALFRED_HOMEASSISTANT_TOKEN??Fr?.accessToken??"";w&&console.log(` ${E(`Current token: ${we(w)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),As=(await c.question(` ${H}Long-Lived Access Token${k}: ${M}`)).trim(),process.stdout.write(k),!As&&w&&(As=w);let $=Fr?.verifyTls===!1?"y/N":"Y/n",S=(await c.question(` ${H}Verify TLS?${k} ${E(`(self-signed? \u2192 no) [${$}]`)}: ${M}`)).trim().toLowerCase()||(Fr?.verifyTls===!1?"n":"y");process.stdout.write(k),oo=S==="y"||S==="yes",console.log(` ${L(">")} Home Assistant: ${R(Ss)} ${E(`(TLS verify: ${oo?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let xe=t.config.contacts,io=t.env.ALFRED_CONTACTS_PROVIDER??xe?.provider??"",jd=io?"Y/n":"y/N",ra=(await c.question(`
919
+ ${H}Enable Contacts management?${k} ${E(`[${jd}]`)}: ${M}`)).trim().toLowerCase()||(io?"y":"n");process.stdout.write(k);let Br=ra==="y"||ra==="yes",Re="",ue={};if(Br){let w=["carddav","google","microsoft"],$=w.indexOf(io),S=$>=0?$+1:1;console.log(` ${me("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${me("2)")} Google Contacts`),console.log(` ${me("3)")} Microsoft 365`);let j=await Dr(c," > ",1,3,S);if(Re=w[j-1],ue.ALFRED_CONTACTS_PROVIDER=Re,Re==="carddav"){let D=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??xe?.carddav?.serverUrl??"";ue.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await O(c," CardDAV Server URL",D||"https://cloud.example.com/remote.php/dav");let F=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??xe?.carddav?.username??"";ue.ALFRED_CARDDAV_CONTACTS_USERNAME=await O(c," Username",F);let K=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??xe?.carddav?.password??"";K&&console.log(` ${E(`Current password: ${we(K)}`)}`);let _e=(await c.question(` ${H}Password${k}: ${M}`)).trim();process.stdout.write(k),ue.ALFRED_CARDDAV_CONTACTS_PASSWORD=_e||K}else if(Re==="google"){let D=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??xe?.google?.clientId??"";D&&console.log(` ${E(`Current client ID: ${we(D)}`)}`),ue.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await c.question(` ${H}Google Client ID${k}: ${M}`)).trim()||D,process.stdout.write(k);let F=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??xe?.google?.clientSecret??"";ue.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await c.question(` ${H}Google Client Secret${k}: ${M}`)).trim()||F,process.stdout.write(k);let K=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??xe?.google?.refreshToken??"";ue.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await c.question(` ${H}Refresh Token${k}: ${M}`)).trim()||K,process.stdout.write(k)}else if(Re==="microsoft"){let D=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??xe?.microsoft?.clientId??"";D&&console.log(` ${E(`Current client ID: ${we(D)}`)}`),ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await c.question(` ${H}Microsoft Client ID${k}: ${M}`)).trim()||D,process.stdout.write(k);let F=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??xe?.microsoft?.clientSecret??"";ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await c.question(` ${H}Microsoft Client Secret${k}: ${M}`)).trim()||F,process.stdout.write(k);let K=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??xe?.microsoft?.tenantId??"";ue.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await O(c," Tenant ID",K||"common");let _e=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??xe?.microsoft?.refreshToken??"";console.log(` ${E("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),ue.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await c.question(` ${H}Refresh Token${k}: ${M}`)).trim()||_e,process.stdout.write(k)}console.log(` ${L(">")} Contacts: ${R(Re)}`)}else console.log(` ${E("Contacts disabled.")}`);let na=t.config.docker,ao=t.env.ALFRED_DOCKER_SOCKET_PATH??na?.socketPath??"",co=t.env.ALFRED_DOCKER_HOST??na?.host??"",Bd=ao||co?"Y/n":"y/N",oa=(await c.question(`
920
+ ${H}Enable Docker management?${k} ${E(`[${Bd}]`)}: ${M}`)).trim().toLowerCase()||(ao||co?"y":"n");process.stdout.write(k);let Hr=oa==="y"||oa==="yes",ct="",lt="";if(Hr){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.")}`),ct=await O(c," Docker socket path",ao||w);let $=(await c.question(` ${H}Docker host URL (optional, for remote)${k}: ${M}`)).trim();process.stdout.write(k),lt=$||co,console.log(` ${L(">")} Docker: ${R(lt||ct)}`)}else console.log(` ${E("Docker disabled.")}`);let Hd=t.config.bmw,lo=t.env.ALFRED_BMW_CLIENT_ID??Hd?.clientId??"",qd=lo?"Y/n":"y/N",ia=(await c.question(`
921
+ ${H}Enable BMW CarData (vehicle status, charging)?${k} ${E(`[${qd}]`)}: ${M}`)).trim().toLowerCase()||(lo?"y":"n");process.stdout.write(k);let qr=ia==="y"||ia==="yes",uo="";qr?(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)')}`),uo=await O(c," BMW CarData Client ID",lo),console.log(` ${L(">")} BMW CarData: ${R("enabled")}`)):console.log(` ${E("BMW CarData disabled.")}`);let zd=t.config.routing,mo=t.env.ALFRED_ROUTING_API_KEY??zd?.apiKey??"",Wd=mo?"Y/n":"y/N",aa=(await c.question(`
922
+ ${H}Enable route planning with live traffic (Google Routes)?${k} ${E(`[${Wd}]`)}: ${M}`)).trim().toLowerCase()||(mo?"y":"n");process.stdout.write(k);let zr=aa==="y"||aa==="yes",po="";zr?(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")}`),po=await O(c," Google Maps API Key",mo),console.log(` ${L(">")} Routing: ${R("enabled")}`)):console.log(` ${E("Routing disabled.")}`);let He=t.config.energy,Gd=t.env.ALFRED_ENERGY_GRID_NAME??He?.gridName??"",ho=t.env.ALFRED_ENERGY_GRID_USAGE_CT??(He?.gridUsageCt!=null?String(He.gridUsageCt):""),Vd=t.env.ALFRED_ENERGY_GRID_LOSS_CT??(He?.gridLossCt!=null?String(He.gridLossCt):""),Kd=t.env.ALFRED_ENERGY_GRID_CAPACITY_FEE??(He?.gridCapacityFee!=null?String(He.gridCapacityFee):""),Xd=t.env.ALFRED_ENERGY_GRID_METER_FEE??(He?.gridMeterFee!=null?String(He.gridMeterFee):""),Yd=ho?"Y/n":"y/N",ca=(await c.question(`
923
+ ${H}Enable energy prices (aWATTar HOURLY / EPEX Spot AT)?${k} ${E(`[${Yd}]`)}: ${M}`)).trim().toLowerCase()||(ho?"y":"n");process.stdout.write(k);let Wr=ca==="y"||ca==="yes",dt="",ut="",Gr="",Is="",xs="";Wr?(console.log(` ${E('Die Werte findest du auf deiner Stromrechnung unter "Netzentgelte".')}`),console.log(` ${E("Marktpreis + aWATTar-Aufschlag + Abgaben werden automatisch berechnet.")}`),console.log(""),dt=await O(c," Netzbetreiber Name (z.B. Netz Nieder\xF6sterreich)",Gd),ut=await O(c," Netznutzungsentgelt (ct/kWh netto)",ho),Gr=await O(c," Netzverlustentgelt (ct/kWh netto)",Vd||"0.38"),Is=await O(c," Leistungspauschale (\u20AC/Monat netto)",Kd),xs=await O(c," Messentgelt (\u20AC/Monat netto)",Xd||"2.22"),console.log(` ${L(">")} Energy: ${R(dt||"enabled")} (${ut} + ${Gr} ct/kWh)`)):console.log(` ${E("Energy prices disabled (Marktpreise weiterhin ohne Netzentgelte verf\xFCgbar).")}`),console.log(`
924
+ ${R("Security configuration:")}`);let la=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",ve;if(la)ve=await O(c,"Owner user ID (for elevated permissions)",la);else{let w=(await c.question(`${H}Owner user ID${k} ${E("(optional, for elevated permissions)")}: ${M}`)).trim();process.stdout.write(k),ve=w}let Rs=!1;if(ve){let w=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${R("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let $=(await c.question(` ${M}> ${k}${E(`[${w}] `)}`)).trim().toLowerCase();$===""?Rs=t.shellEnabled:Rs=$==="y"||$==="yes",console.log(Rs?` ${L(">")} Shell access ${R("enabled")} for owner ${E(ve)}`:` ${E("Shell access disabled.")}`)}let Jd=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${R("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let fo=(await c.question(` ${M}> ${k}${E(`[${Jd}] `)}`)).trim().toLowerCase(),Cs;fo===""?Cs=t.writeInGroups:Cs=fo==="y"||fo==="yes",console.log(Cs?` ${L(">")} Write actions ${R("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let Zd=t.rateLimit??30;console.log("");let Qd=await O(c," Rate limit (max write actions per hour per user)",String(Zd)),Vr=Math.max(1,parseInt(Qd,10)||30);console.log(` ${L(">")} Rate limit: ${R(String(Vr))} per hour`),console.log(`
925
+ ${R("Writing configuration files...")}`);let v=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";v.push(`${w}=${l}`)}if(f!==a.defaultModel&&v.push(`ALFRED_LLM_MODEL=${f}`),m&&v.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(x).length>0){v.push("","# === Additional Model Tiers ===");for(let[w,$]of Object.entries(x)){let S=`ALFRED_LLM_${w.toUpperCase()}`;v.push(""),v.push(`${S}_PROVIDER=${$.provider}`),v.push(`${S}_MODEL=${$.model}`),$.apiKey&&v.push(`${S}_API_KEY=${$.apiKey}`),$.baseUrl&&v.push(`${S}_BASE_URL=${$.baseUrl}`)}}v.push("","# === Messaging Platforms ===","");for(let[w,$]of Object.entries(Q))v.push(`${w}=${$}`);if(v.push("","# === Web Search ===",""),ge?(v.push(`ALFRED_SEARCH_PROVIDER=${ge}`),de&&v.push(`ALFRED_SEARCH_API_KEY=${de}`),ne&&v.push(`ALFRED_SEARCH_BASE_URL=${ne}`)):(v.push("# ALFRED_SEARCH_PROVIDER=brave"),v.push("# ALFRED_SEARCH_API_KEY=")),v.push("","# === Email ===",""),Mr&&Fe.length>0){let w=Fe[0];w.provider==="microsoft"?(v.push("ALFRED_EMAIL_PROVIDER=microsoft"),w.msClientId?(v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${w.msClientId}`),v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${w.msClientSecret}`),v.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${w.msTenantId}`),v.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${w.msRefreshToken}`)):v.push("# Microsoft email credentials shared from calendar config")):(v.push(`ALFRED_EMAIL_USER=${w.user}`),v.push(`ALFRED_EMAIL_PASS=${w.pass}`)),Fe.length>1&&v.push("# Additional email accounts configured in config/default.yml")}else v.push("# ALFRED_EMAIL_USER="),v.push("# ALFRED_EMAIL_PASS=");if(v.push("","# === Speech ===",""),je?(v.push(`ALFRED_SPEECH_PROVIDER=${je}`),v.push(`ALFRED_SPEECH_API_KEY=${Je}`),gs&&v.push(`ALFRED_SPEECH_BASE_URL=${gs}`),ys&&(v.push("ALFRED_TTS_ENABLED=true"),v.push(`ALFRED_TTS_VOICE=${ws}`))):(v.push("# ALFRED_SPEECH_PROVIDER=groq"),v.push("# ALFRED_SPEECH_API_KEY=")),v.push("","# === Forge (GitHub / GitLab) ===",""),ot==="github"?(v.push("ALFRED_FORGE_PROVIDER=github"),v.push(`ALFRED_GITHUB_TOKEN=${Ts}`)):ot==="gitlab"?(v.push("ALFRED_FORGE_PROVIDER=gitlab"),v.push(`ALFRED_GITLAB_TOKEN=${_s}`)):(v.push("# ALFRED_FORGE_PROVIDER=github"),v.push("# ALFRED_GITHUB_TOKEN=")),v.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Ur?(v.push(`ALFRED_PROXMOX_BASE_URL=${bs}`),v.push(`ALFRED_PROXMOX_TOKEN_ID=${Qn}`),v.push(`ALFRED_PROXMOX_TOKEN_SECRET=${$s}`)):(v.push("# ALFRED_PROXMOX_BASE_URL="),v.push("# ALFRED_PROXMOX_TOKEN_ID="),v.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),ks&&at?(v.push(`ALFRED_UNIFI_BASE_URL=${xt}`),v.push(`ALFRED_UNIFI_API_KEY=${at}`)):ks?(v.push(`ALFRED_UNIFI_BASE_URL=${xt}`),v.push(`ALFRED_UNIFI_USERNAME=${so}`),v.push(`ALFRED_UNIFI_PASSWORD=${vs}`)):(v.push("# ALFRED_UNIFI_BASE_URL="),v.push("# ALFRED_UNIFI_API_KEY=")),jr?(v.push(`ALFRED_HOMEASSISTANT_URL=${Ss}`),v.push(`ALFRED_HOMEASSISTANT_TOKEN=${As}`)):(v.push("# ALFRED_HOMEASSISTANT_URL="),v.push("# ALFRED_HOMEASSISTANT_TOKEN=")),v.push("","# === Contacts ===",""),Br)for(let[w,$]of Object.entries(ue))v.push(`${w}=${$}`);else v.push("# ALFRED_CONTACTS_PROVIDER=carddav");v.push("","# === Docker ===",""),Hr?(ct&&v.push(`ALFRED_DOCKER_SOCKET_PATH=${ct}`),lt&&v.push(`ALFRED_DOCKER_HOST=${lt}`)):(v.push("# ALFRED_DOCKER_SOCKET_PATH="),v.push("# ALFRED_DOCKER_HOST=")),v.push("","# === BMW CarData ===",""),qr?v.push(`ALFRED_BMW_CLIENT_ID=${uo}`):v.push("# ALFRED_BMW_CLIENT_ID="),v.push("","# === Routing ===",""),zr?v.push(`ALFRED_ROUTING_API_KEY=${po}`):v.push("# ALFRED_ROUTING_API_KEY="),v.push("","# === Energy / aWATTar ===",""),Wr&&ut?(dt&&v.push(`ALFRED_ENERGY_GRID_NAME=${dt}`),v.push(`ALFRED_ENERGY_GRID_USAGE_CT=${ut}`),v.push(`ALFRED_ENERGY_GRID_LOSS_CT=${Gr}`),Is&&v.push(`ALFRED_ENERGY_GRID_CAPACITY_FEE=${Is}`),xs&&v.push(`ALFRED_ENERGY_GRID_METER_FEE=${xs}`)):(v.push("# ALFRED_ENERGY_GRID_NAME="),v.push("# ALFRED_ENERGY_GRID_USAGE_CT="),v.push("# ALFRED_ENERGY_GRID_LOSS_CT="),v.push("# ALFRED_ENERGY_GRID_CAPACITY_FEE="),v.push("# ALFRED_ENERGY_GRID_METER_FEE=")),v.push("","# === Security ===",""),ve?v.push(`ALFRED_OWNER_USER_ID=${ve}`):v.push("# ALFRED_OWNER_USER_ID="),v.push("");let eu=be.join(e,".env");pe.writeFileSync(eu,v.join(`
926
+ `),"utf-8"),console.log(` ${L("+")} ${E(".env")} written`);let Kr=be.join(e,"config");pe.existsSync(Kr)||pe.mkdirSync(Kr,{recursive:!0});let da={name:r,telegram:{token:B.telegram?.token??"",enabled:J.some(w=>w.name==="telegram")},discord:{token:B.discord?.token??"",enabled:J.some(w=>w.name==="discord")},whatsapp:{enabled:J.some(w=>w.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:B.matrix?.homeserverUrl??"https://matrix.org",accessToken:B.matrix?.accessToken??"",userId:B.matrix?.userId??"",enabled:J.some(w=>w.name==="matrix")},signal:{apiUrl:B.signal?.apiUrl??"http://localhost:8080",phoneNumber:B.signal?.phoneNumber??"",enabled:J.some(w=>w.name==="signal")},llm:Object.keys(x).length>0?{default:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...x}:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...ge?{search:{provider:ge,...de?{apiKey:de}:{},...ne?{baseUrl:ne}:{}}}:{},...Mr&&Fe.length>0?{email:{accounts:Fe.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}})}}:{},...je?{speech:{provider:je,apiKey:Je,...gs?{baseUrl:gs}:{},...ys?{ttsEnabled:!0,ttsVoice:ws}:{}}}:{},...Vn?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...nt.length>0||ot?{codeAgents:{enabled:nt.length>0,agents:nt,...ot==="github"?{forge:{provider:"github",github:{token:Ts}}}:ot==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:_s}}}:{}}}:{},...Ur?{proxmox:{baseUrl:bs,tokenId:Qn,tokenSecret:$s,verifyTls:eo}}:{},...ks?{unifi:{baseUrl:xt,...at?{apiKey:at}:{username:so,password:vs},site:"default",verifyTls:ro}}:{},...jr?{homeassistant:{baseUrl:Ss,accessToken:As,verifyTls:oo}}:{},...Br?{contacts:{provider:Re,...Re==="carddav"?{carddav:{serverUrl:ue.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:ue.ALFRED_CARDDAV_CONTACTS_USERNAME}}:Re==="google"?{google:{clientId:ue.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:Re==="microsoft"?{microsoft:{clientId:ue.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:ue.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...Hr?{docker:{...ct?{socketPath:ct}:{},...lt?{host:lt}:{}}}:{},...qr?{bmw:{clientId:uo}}:{},...zr?{routing:{apiKey:po}}:{},...Wr&&ut?{energy:{...dt?{gridName:dt}:{},gridUsageCt:parseFloat(ut),gridLossCt:parseFloat(Gr||"0"),...Is?{gridCapacityFee:parseFloat(Is)}:{},...xs?{gridMeterFee:parseFloat(xs)}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};ve&&(da.security.ownerUserId=ve);let tu="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Gi.dump(da,{lineWidth:120,noRefs:!0,sortKeys:!1}),su=be.join(Kr,"default.yml");pe.writeFileSync(su,tu,"utf-8"),console.log(` ${L("+")} ${E("config/default.yml")} written`);let go=be.join(Kr,"rules");pe.existsSync(go)||pe.mkdirSync(go,{recursive:!0});let ru=Rs&&ve?`
927
927
  # Allow admin actions (shell, etc.) for the owner only
928
928
  - id: allow-owner-admin
929
929
  effect: allow
@@ -999,23 +999,23 @@ ${ru}
999
999
  scope: global
1000
1000
  actions: ["*"]
1001
1001
  riskLevels: [read, write, destructive, admin]
1002
- `,ou=Ee.join(go,"default-rules.yml");pe.writeFileSync(ou,nu,"utf-8"),console.log(` ${D("+")} ${E("config/rules/default-rules.yml")} written`);let ua=Ee.join(e,"data");pe.existsSync(ua)||(pe.mkdirSync(ua,{recursive:!0}),console.log(` ${D("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${jn}${"=".repeat(52)}${k}`),console.log(`${jn}${H} Setup complete!${k}`),console.log(`${jn}${"=".repeat(52)}${k}`),console.log(""),console.log(` ${R("Bot name:")} ${r}`),console.log(` ${R("LLM default:")} ${a.name} (${f})`),l&&console.log(` ${R("API key:")} ${we(l)}`);for(let[w,$]of Object.entries(x)){let S=w.charAt(0).toUpperCase()+w.slice(1);console.log(` ${R(`LLM ${S}:`)}${" ".repeat(Math.max(1,10-S.length))}${$.provider} (${$.model})`)}if(J.length>0?console.log(` ${R("Platforms:")} ${J.map(w=>w.label).join(", ")}`):console.log(` ${R("Platforms:")} none (configure later)`),ge){let w={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${re})`};console.log(` ${R("Web search:")} ${w[ge]}`)}else console.log(` ${R("Web search:")} ${E("disabled")}`);if(Mr&&Pe.length>0){let w=Pe.map($=>$.provider==="microsoft"?`${$.name} (Microsoft 365)${$.msClientId?"":" \u2014 shared from Calendar"}`:`${$.name} (${$.imapHost})`);console.log(` ${R("Email:")} ${w.join(", ")}`)}else console.log(` ${R("Email:")} ${E("disabled")}`);if(Ue){let w={openai:"OpenAI Whisper",groq:"Groq Whisper"},$=ys?`, TTS: ${ws}`:"";console.log(` ${R("Voice:")} ${w[Ue]}${$}`)}else console.log(` ${R("Voice:")} ${E("disabled")}`);console.log(` ${R("Code Sandbox:")} ${Vn?D("enabled"):E("disabled")}`),Ur&&console.log(` ${R("Proxmox:")} ${D(bs)}`),ks&&console.log(` ${R("UniFi:")} ${D(xt)}`),jr&&console.log(` ${R("Home Assist.:")} ${D(Ss)}`),Br&&console.log(` ${R("Contacts:")} ${D(Re)}`),Hr&&console.log(` ${R("Docker:")} ${D(lt||ct)}`),qr&&console.log(` ${R("BMW CarData:")} ${D("enabled")}`),zr&&console.log(` ${R("Routing:")} ${D("enabled")}`),Wr&&console.log(` ${R("Energy:")} ${D(dt||"enabled")} ${E(`(${ut} ct/kWh)`)}`),ve&&(console.log(` ${R("Owner ID:")} ${ve}`),console.log(` ${R("Shell access:")} ${Rs?D("enabled"):E("disabled")}`)),console.log(` ${R("Write scope:")} ${Cs?"DMs + Groups":"DMs only"}`),console.log(` ${R("Rate limit:")} ${Vr}/hour per user`),console.log(""),console.log(`${Bn}Next steps:${k}`),console.log(` ${R("alfred start")} Start Alfred`),console.log(` ${R("alfred status")} Check configuration`),console.log(` ${R("alfred --help")} Show all commands`),console.log(""),console.log(`${rt}Edit ${R(".env")}${rt} or ${R("config/default.yml")}${rt} for manual configuration.${k}`),console.log("")}finally{c.close()}}async function O(c,e,t){let s=(await c.question(`${H}${e}${k} ${E(`[${t}]`)}: ${M}`)).trim();return process.stdout.write(k),s||t}async function Ie(c,e){for(;;){let t=(await c.question(`${H}${e}${k}: ${M}`)).trim();if(process.stdout.write(k),t)return t;console.log(` ${pd("!")} This field is required. Please enter a value.`)}}async function Lr(c,e,t,s,r){for(;;){let n=(await c.question(`${M}${e}${k}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${pd("!")} Please enter a number between ${t} and ${s}.`)}}function Kp(){console.log(`
1002
+ `,ou=be.join(go,"default-rules.yml");pe.writeFileSync(ou,nu,"utf-8"),console.log(` ${L("+")} ${E("config/rules/default-rules.yml")} written`);let ua=be.join(e,"data");pe.existsSync(ua)||(pe.mkdirSync(ua,{recursive:!0}),console.log(` ${L("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${jn}${"=".repeat(52)}${k}`),console.log(`${jn}${H} Setup complete!${k}`),console.log(`${jn}${"=".repeat(52)}${k}`),console.log(""),console.log(` ${R("Bot name:")} ${r}`),console.log(` ${R("LLM default:")} ${a.name} (${f})`),l&&console.log(` ${R("API key:")} ${we(l)}`);for(let[w,$]of Object.entries(x)){let S=w.charAt(0).toUpperCase()+w.slice(1);console.log(` ${R(`LLM ${S}:`)}${" ".repeat(Math.max(1,10-S.length))}${$.provider} (${$.model})`)}if(J.length>0?console.log(` ${R("Platforms:")} ${J.map(w=>w.label).join(", ")}`):console.log(` ${R("Platforms:")} none (configure later)`),ge){let w={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${ne})`};console.log(` ${R("Web search:")} ${w[ge]}`)}else console.log(` ${R("Web search:")} ${E("disabled")}`);if(Mr&&Fe.length>0){let w=Fe.map($=>$.provider==="microsoft"?`${$.name} (Microsoft 365)${$.msClientId?"":" \u2014 shared from Calendar"}`:`${$.name} (${$.imapHost})`);console.log(` ${R("Email:")} ${w.join(", ")}`)}else console.log(` ${R("Email:")} ${E("disabled")}`);if(je){let w={openai:"OpenAI Whisper",groq:"Groq Whisper"},$=ys?`, TTS: ${ws}`:"";console.log(` ${R("Voice:")} ${w[je]}${$}`)}else console.log(` ${R("Voice:")} ${E("disabled")}`);console.log(` ${R("Code Sandbox:")} ${Vn?L("enabled"):E("disabled")}`),Ur&&console.log(` ${R("Proxmox:")} ${L(bs)}`),ks&&console.log(` ${R("UniFi:")} ${L(xt)}`),jr&&console.log(` ${R("Home Assist.:")} ${L(Ss)}`),Br&&console.log(` ${R("Contacts:")} ${L(Re)}`),Hr&&console.log(` ${R("Docker:")} ${L(lt||ct)}`),qr&&console.log(` ${R("BMW CarData:")} ${L("enabled")}`),zr&&console.log(` ${R("Routing:")} ${L("enabled")}`),Wr&&console.log(` ${R("Energy:")} ${L(dt||"enabled")} ${E(`(${ut} ct/kWh)`)}`),ve&&(console.log(` ${R("Owner ID:")} ${ve}`),console.log(` ${R("Shell access:")} ${Rs?L("enabled"):E("disabled")}`)),console.log(` ${R("Write scope:")} ${Cs?"DMs + Groups":"DMs only"}`),console.log(` ${R("Rate limit:")} ${Vr}/hour per user`),console.log(""),console.log(`${Bn}Next steps:${k}`),console.log(` ${R("alfred start")} Start Alfred`),console.log(` ${R("alfred status")} Check configuration`),console.log(` ${R("alfred --help")} Show all commands`),console.log(""),console.log(`${rt}Edit ${R(".env")}${rt} or ${R("config/default.yml")}${rt} for manual configuration.${k}`),console.log("")}finally{c.close()}}async function O(c,e,t){let s=(await c.question(`${H}${e}${k} ${E(`[${t}]`)}: ${M}`)).trim();return process.stdout.write(k),s||t}async function Ie(c,e){for(;;){let t=(await c.question(`${H}${e}${k}: ${M}`)).trim();if(process.stdout.write(k),t)return t;console.log(` ${pd("!")} This field is required. Please enter a value.`)}}async function Dr(c,e,t,s,r){for(;;){let n=(await c.question(`${M}${e}${k}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${pd("!")} Please enter a number between ${t} and ${s}.`)}}function Kp(){console.log(`
1003
1003
  ${qp}${H} _ _ _____ ____ _____ ____
1004
1004
  / \\ | | | ___| _ \\| ____| _ \\
1005
1005
  / _ \\ | | | |_ | |_) | _| | | | |
1006
1006
  / ___ \\| |___| _| | _ <| |___| |_| |
1007
1007
  /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${k}
1008
1008
  ${rt} Personal AI Assistant \u2014 Setup Wizard${k}
1009
- `)}var k,H,rt,jn,M,Bn,Hp,qp,Xe,hs,md,fd=_(()=>{"use strict";Wi();k="\x1B[0m",H="\x1B[1m",rt="\x1B[2m",jn="\x1B[32m",M="\x1B[33m",Bn="\x1B[36m",Hp="\x1B[31m",qp="\x1B[35m";u(D,"green");u(zp,"yellow");u(me,"cyan");u(pd,"red");u(R,"bold");u(E,"dim");u(we,"maskKey");Xe=[{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"}]}],hs=[{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(Wp,"findCommand");md=[{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(Gp,"loadExistingConfig");u(Vp,"setupCommand");u(O,"askWithDefault");u(Ie,"askRequired");u(Lr,"askNumber");u(Kp,"printBanner")});var yd={};oe(yd,{configCommand:()=>Zp});function Yp(c){let e=c.toLowerCase();return Xp.some(t=>e.includes(t))}function Jp(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function gd(c){let e={};for(let[t,s]of Object.entries(c))Yp(t)?e[t]=Jp(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=gd(s):e[t]=s;return e}async function Zp(){let c=new ne,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=gd(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Xp,wd=_(()=>{"use strict";ze();Xp=["token","apikey","api_key","accesstoken","secret","password"];u(Yp,"isSensitiveKey");u(Jp,"redactValue");u(gd,"redactObject");u(Zp,"configCommand")});var _d={};oe(_d,{rulesCommand:()=>eh});import Hn from"node:fs";import Td from"node:path";import Qp from"js-yaml";async function eh(){let c=new ne,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Td.resolve(e.security.rulesPath);if(!Hn.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Hn.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Hn.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 yt,o=[],i=[];for(let a of r){let l=Td.join(t,a);try{let d=Hn.readFileSync(l,"utf-8"),m=Qp.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,l)=>a.priority-l.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let l=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(", ")}${l}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Ed=_(()=>{"use strict";ze();Qr();u(eh,"rulesCommand")});var bd={};oe(bd,{statusCommand:()=>sh});import Dr from"node:fs";import Vi from"node:path";import th from"js-yaml";async function sh(){let c=new ne,e;try{e=c.loadConfig()}catch(l){console.error("Failed to load configuration:",l.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 l of t){let d=l.enabled?"enabled":l.configured?"configured (disabled)":"not configured",m=l.enabled?"+":"-";console.log(` [${m}] ${l.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 l of["strong","fast","embeddings","local"]){let d=e.llm[l];d&&console.log(` ${l}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=Vi.resolve(e.storage.path),n=Dr.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Vi.resolve(e.security.rulesPath),i=0,a=0;if(Dr.existsSync(o)&&Dr.statSync(o).isDirectory()){let l=Dr.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new yt;for(let m of l){let p=Vi.join(o,m);try{let g=Dr.readFileSync(p,"utf-8"),f=th.load(g),h=d.loadFromObject(f);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 $d=_(()=>{"use strict";ze();Qr();u(sh,"statusCommand")});var Sd={};oe(Sd,{authCommand:()=>wh});import{createServer as rh}from"node:http";import{exec as nh}from"node:child_process";import{readFileSync as oh,writeFileSync as ih,existsSync as ah}from"node:fs";import{createInterface as ch}from"node:readline";import{resolve as lh}from"node:path";async function Ki(c){let e=ch({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(c,s=>{e.close(),t(s.trim())})})}function uh(){let c={};try{let s=new ne().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!c.clientId&&a.clientId&&(c.clientId=a.clientId),!c.clientSecret&&a.clientSecret&&(c.clientSecret=a.clientSecret),!c.tenantId&&a.tenantId&&(c.tenantId=a.tenantId))}let r=s.todo;r&&(!c.clientId&&r.clientId&&(c.clientId=r.clientId),!c.clientSecret&&r.clientSecret&&(c.clientSecret=r.clientSecret),!c.tenantId&&r.tenantId&&(c.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&&(!c.clientId&&i.clientId&&(c.clientId=i.clientId),!c.clientSecret&&i.clientSecret&&(c.clientSecret=i.clientSecret),!c.tenantId&&i.tenantId&&(c.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)c.clientId||(c.clientId=process.env[`${t}_CLIENT_ID`]),c.clientSecret||(c.clientSecret=process.env[`${t}_CLIENT_SECRET`]),c.tenantId||(c.tenantId=process.env[`${t}_TENANT_ID`]);return c}async function mh(){let c=uh(),e=c.clientId||await Ki(" Client ID: "),t=c.clientSecret||await Ki(" Client Secret: "),s=c.tenantId||await Ki(' 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 ph(c){let e=new URLSearchParams({client_id:c.clientId,response_type:"code",redirect_uri:kd,response_mode:"query",scope:vd,prompt:"consent"});return`https://login.microsoftonline.com/${c.tenantId}/oauth2/v2.0/authorize?${e}`}async function hh(c,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:c,redirect_uri:kd,grant_type:"authorization_code",scope:vd}),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 fh(c){let t={win32:`start "" "${c}"`,darwin:`open "${c}"`,linux:`xdg-open "${c}"`}[process.platform];t&&nh(t,()=>{})}function gh(c,e){let t=lh(process.cwd(),".env"),s=[];ah(t)&&(s=oh(t,"utf-8").split(`
1009
+ `)}var k,H,rt,jn,M,Bn,Hp,qp,Ye,hs,md,fd=_(()=>{"use strict";Wi();k="\x1B[0m",H="\x1B[1m",rt="\x1B[2m",jn="\x1B[32m",M="\x1B[33m",Bn="\x1B[36m",Hp="\x1B[31m",qp="\x1B[35m";u(L,"green");u(zp,"yellow");u(me,"cyan");u(pd,"red");u(R,"bold");u(E,"dim");u(we,"maskKey");Ye=[{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"}]}],hs=[{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(Wp,"findCommand");md=[{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(Gp,"loadExistingConfig");u(Vp,"setupCommand");u(O,"askWithDefault");u(Ie,"askRequired");u(Dr,"askNumber");u(Kp,"printBanner")});var yd={};ie(yd,{configCommand:()=>Zp});function Yp(c){let e=c.toLowerCase();return Xp.some(t=>e.includes(t))}function Jp(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function gd(c){let e={};for(let[t,s]of Object.entries(c))Yp(t)?e[t]=Jp(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=gd(s):e[t]=s;return e}async function Zp(){let c=new oe,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=gd(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Xp,wd=_(()=>{"use strict";We();Xp=["token","apikey","api_key","accesstoken","secret","password"];u(Yp,"isSensitiveKey");u(Jp,"redactValue");u(gd,"redactObject");u(Zp,"configCommand")});var _d={};ie(_d,{rulesCommand:()=>eh});import Hn from"node:fs";import Td from"node:path";import Qp from"js-yaml";async function eh(){let c=new oe,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Td.resolve(e.security.rulesPath);if(!Hn.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Hn.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Hn.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 yt,o=[],i=[];for(let a of r){let l=Td.join(t,a);try{let d=Hn.readFileSync(l,"utf-8"),m=Qp.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,l)=>a.priority-l.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let l=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(", ")}${l}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Ed=_(()=>{"use strict";We();Qr();u(eh,"rulesCommand")});var bd={};ie(bd,{statusCommand:()=>sh});import Lr from"node:fs";import Vi from"node:path";import th from"js-yaml";async function sh(){let c=new oe,e;try{e=c.loadConfig()}catch(l){console.error("Failed to load configuration:",l.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 l of t){let d=l.enabled?"enabled":l.configured?"configured (disabled)":"not configured",m=l.enabled?"+":"-";console.log(` [${m}] ${l.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 l of["strong","fast","embeddings","local"]){let d=e.llm[l];d&&console.log(` ${l}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=Vi.resolve(e.storage.path),n=Lr.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Vi.resolve(e.security.rulesPath),i=0,a=0;if(Lr.existsSync(o)&&Lr.statSync(o).isDirectory()){let l=Lr.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new yt;for(let m of l){let p=Vi.join(o,m);try{let g=Lr.readFileSync(p,"utf-8"),f=th.load(g),h=d.loadFromObject(f);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 $d=_(()=>{"use strict";We();Qr();u(sh,"statusCommand")});var Sd={};ie(Sd,{authCommand:()=>wh});import{createServer as rh}from"node:http";import{exec as nh}from"node:child_process";import{readFileSync as oh,writeFileSync as ih,existsSync as ah}from"node:fs";import{createInterface as ch}from"node:readline";import{resolve as lh}from"node:path";async function Ki(c){let e=ch({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(c,s=>{e.close(),t(s.trim())})})}function uh(){let c={};try{let s=new oe().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!c.clientId&&a.clientId&&(c.clientId=a.clientId),!c.clientSecret&&a.clientSecret&&(c.clientSecret=a.clientSecret),!c.tenantId&&a.tenantId&&(c.tenantId=a.tenantId))}let r=s.todo;r&&(!c.clientId&&r.clientId&&(c.clientId=r.clientId),!c.clientSecret&&r.clientSecret&&(c.clientSecret=r.clientSecret),!c.tenantId&&r.tenantId&&(c.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&&(!c.clientId&&i.clientId&&(c.clientId=i.clientId),!c.clientSecret&&i.clientSecret&&(c.clientSecret=i.clientSecret),!c.tenantId&&i.tenantId&&(c.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)c.clientId||(c.clientId=process.env[`${t}_CLIENT_ID`]),c.clientSecret||(c.clientSecret=process.env[`${t}_CLIENT_SECRET`]),c.tenantId||(c.tenantId=process.env[`${t}_TENANT_ID`]);return c}async function mh(){let c=uh(),e=c.clientId||await Ki(" Client ID: "),t=c.clientSecret||await Ki(" Client Secret: "),s=c.tenantId||await Ki(' 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 ph(c){let e=new URLSearchParams({client_id:c.clientId,response_type:"code",redirect_uri:kd,response_mode:"query",scope:vd,prompt:"consent"});return`https://login.microsoftonline.com/${c.tenantId}/oauth2/v2.0/authorize?${e}`}async function hh(c,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:c,redirect_uri:kd,grant_type:"authorization_code",scope:vd}),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 fh(c){let t={win32:`start "" "${c}"`,darwin:`open "${c}"`,linux:`xdg-open "${c}"`}[process.platform];t&&nh(t,()=>{})}function gh(c,e){let t=lh(process.cwd(),".env"),s=[];ah(t)&&(s=oh(t,"utf-8").split(`
1010
1010
  `));let r={ALFRED_EMAIL_PROVIDER:"microsoft",ALFRED_CALENDAR_PROVIDER:"microsoft",ALFRED_CONTACTS_PROVIDER:"microsoft",ALFRED_MICROSOFT_EMAIL_CLIENT_ID:c.clientId,ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:c.clientSecret,ALFRED_MICROSOFT_EMAIL_TENANT_ID:c.tenantId,ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:c.clientId,ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:c.clientSecret,ALFRED_MICROSOFT_CALENDAR_TENANT_ID:c.tenantId,ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:c.clientId,ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:c.clientSecret,ALFRED_MICROSOFT_CONTACTS_TENANT_ID:c.tenantId,ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:e,ALFRED_MICROSOFT_TODO_CLIENT_ID:c.clientId,ALFRED_MICROSOFT_TODO_CLIENT_SECRET:c.clientSecret,ALFRED_MICROSOFT_TODO_TENANT_ID:c.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(`
1011
1011
  `).replace(/\n*$/,`
1012
1012
  `);ih(t,o)}function yh(c){return new Promise((e,t)=>{let s=rh(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 l=await hh(i,c);n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(dh),s.close(),e(l)}catch(l){n.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>Fehler beim Token-Austausch</h1><p>${l.message}</p>`),s.close(),t(l)}});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 wh(c){c||(console.error("Usage: alfred auth <provider>"),console.error(" Unterst\xFCtzte Provider: microsoft"),process.exit(1)),c!=="microsoft"&&(console.error(`Unbekannter Provider: ${c}`),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 mh(),t=ph(e);console.log(""),console.log(" \xD6ffne diese URL im Browser:"),console.log(` ${t}`),console.log(""),fh(t);try{let s=await yh(e);console.log(""),console.log(" Refresh Token erhalten! Schreibe in .env ..."),gh(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(`
1013
- Fehler: ${s.message}`),process.exit(1)}process.exit(0)}var kd,vd,dh,Ad=_(()=>{"use strict";ze();kd="http://localhost:3000/callback",vd=["offline_access","Mail.Read","Mail.ReadWrite","Mail.Send","Contacts.Read","Contacts.ReadWrite","Calendars.Read","Calendars.ReadWrite","Tasks.ReadWrite"].join(" "),dh=`<!DOCTYPE html>
1013
+ Fehler: ${s.message}`),process.exit(1)}process.exit(0)}var kd,vd,dh,Ad=_(()=>{"use strict";We();kd="http://localhost:3000/callback",vd=["offline_access","Mail.Read","Mail.ReadWrite","Mail.Send","Contacts.Read","Contacts.ReadWrite","Calendars.Read","Calendars.ReadWrite","Tasks.ReadWrite"].join(" "),dh=`<!DOCTYPE html>
1014
1014
  <html><head><meta charset="utf-8"><title>Alfred \u2014 Auth erfolgreich</title>
1015
1015
  <style>body{font-family:system-ui,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0d1117;color:#e6edf3}
1016
1016
  .card{text-align:center;padding:2rem;border:1px solid #30363d;border-radius:12px;background:#161b22}
1017
1017
  h1{color:#3fb950;margin-bottom:.5rem}p{color:#8b949e}</style></head>
1018
- <body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(Ki,"askQuestion");u(uh,"resolveCredentials");u(mh,"ensureCredentials");u(ph,"buildAuthUrl");u(hh,"exchangeCode");u(fh,"openBrowser");u(gh,"updateEnvFile");u(yh,"waitForCallback");u(wh,"authCommand")});var Id={};oe(Id,{logsCommand:()=>Eh});import Th from"node:fs";import _h from"node:path";async function Eh(c){let e=new ne,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=_h.resolve(t.storage.path);if(!Th.existsSync(s)){console.log(`Database not found at: ${s}`),console.log("No audit log entries. Alfred has not been run yet, or the database path is incorrect.");return}let r;try{r=new ht(s);let n=new ft(r.getDb()),o=n.count({}),i=n.query({limit:c});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(c,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let l=a.timestamp.toISOString(),d=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${l} [${d}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var xd=_(()=>{"use strict";ze();Io();u(Eh,"logsCommand")});import{readFileSync as bh}from"node:fs";import{fileURLToPath as $h}from"node:url";import{dirname as kh,join as vh}from"node:path";function Sh(){try{let c=kh($h(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(bh(vh(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Sh,"getVersion");var Rd=Sh(),Xi=`
1018
+ <body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(Ki,"askQuestion");u(uh,"resolveCredentials");u(mh,"ensureCredentials");u(ph,"buildAuthUrl");u(hh,"exchangeCode");u(fh,"openBrowser");u(gh,"updateEnvFile");u(yh,"waitForCallback");u(wh,"authCommand")});var Id={};ie(Id,{logsCommand:()=>Eh});import Th from"node:fs";import _h from"node:path";async function Eh(c){let e=new oe,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=_h.resolve(t.storage.path);if(!Th.existsSync(s)){console.log(`Database not found at: ${s}`),console.log("No audit log entries. Alfred has not been run yet, or the database path is incorrect.");return}let r;try{r=new ht(s);let n=new ft(r.getDb()),o=n.count({}),i=n.query({limit:c});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(c,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let l=a.timestamp.toISOString(),d=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${l} [${d}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var xd=_(()=>{"use strict";We();Io();u(Eh,"logsCommand")});import{readFileSync as bh}from"node:fs";import{fileURLToPath as $h}from"node:url";import{dirname as kh,join as vh}from"node:path";function Sh(){try{let c=kh($h(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(bh(vh(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Sh,"getVersion");var Rd=Sh(),Xi=`
1019
1019
  Alfred CLI v${Rd}
1020
1020
  Personal AI Assistant
1021
1021