@madh-io/alfred-ai 0.9.57 → 0.9.58

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 +304 -236
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0});var b=(c,e)=>()=>(c&&(e=c(c=0)),e);var oe=(c,e)=>{for(var t in e)xo(c,t,{get:e[t],enumerable:!0})};import{z as f}from"zod";var Ao,Ro,Lo,Mo,No,Co,Oo,Do,qe,yc,wc,bc,Io,Tc,_c,Ec,$c,vc,Sc,kc,xc,Ic,Ac,Rc,Lc,Mc,Nc,Cc,Oc,Dc,Uc,Pc,Qr,en=b(()=>{"use strict";Ao=f.object({token:f.string().optional(),enabled:f.boolean()}),Ro=f.object({token:f.string().optional(),enabled:f.boolean()}),Lo=f.object({enabled:f.boolean(),dataPath:f.string()}),Mo=f.object({homeserverUrl:f.string(),accessToken:f.string().optional(),userId:f.string().optional(),enabled:f.boolean()}),No=f.object({apiUrl:f.string(),phoneNumber:f.string().optional(),enabled:f.boolean()}),Co=f.object({path:f.string()}),Oo=f.object({level:f.enum(["trace","debug","info","warn","error","fatal"]),pretty:f.boolean(),auditLogPath:f.string().optional()}),Do=f.object({rulesPath:f.string(),defaultEffect:f.enum(["allow","deny"]),ownerUserId:f.string().optional()}),qe=f.object({provider:f.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:f.string().optional(),baseUrl:f.string().optional(),model:f.string(),temperature:f.number().optional(),maxTokens:f.number().optional()}),yc=f.object({default:qe,strong:qe.optional(),fast:qe.optional(),embeddings:qe.optional(),local:qe.optional()}),wc=f.union([qe,yc]),bc=f.object({provider:f.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:f.string().optional(),baseUrl:f.string().optional()}),Io=f.object({name:f.string().optional(),provider:f.enum(["imap-smtp","microsoft"]).optional(),imap:f.object({host:f.string(),port:f.number(),secure:f.boolean()}).optional(),smtp:f.object({host:f.string(),port:f.number(),secure:f.boolean()}).optional(),auth:f.object({user:f.string(),pass:f.string()}).optional(),microsoft:f.object({clientId:f.string(),clientSecret:f.string(),tenantId:f.string(),refreshToken:f.string()}).optional()}),Tc=f.union([f.object({accounts:f.array(Io)}),Io]),_c=f.object({provider:f.enum(["openai","groq","google"]),apiKey:f.string(),baseUrl:f.string().optional(),ttsEnabled:f.boolean().optional(),ttsModel:f.string().optional(),ttsVoice:f.string().optional()}),Ec=f.object({serverUrl:f.string(),username:f.string(),password:f.string()}),$c=f.object({clientId:f.string(),clientSecret:f.string(),refreshToken:f.string()}),vc=f.object({clientId:f.string(),clientSecret:f.string(),tenantId:f.string(),refreshToken:f.string()}),Sc=f.object({provider:f.enum(["caldav","google","microsoft"]),caldav:Ec.optional(),google:$c.optional(),microsoft:vc.optional()}),kc=f.object({name:f.string(),command:f.string().optional(),args:f.array(f.string()).optional(),env:f.record(f.string()).optional(),url:f.string().optional()}),xc=f.object({servers:f.array(kc)}),Ic=f.object({enabled:f.boolean(),allowedLanguages:f.array(f.enum(["javascript","python"])).optional(),maxTimeoutMs:f.number().optional(),allowNetwork:f.boolean().optional()}),Ac=f.object({enabled:f.boolean().optional(),minMessageLength:f.number().optional(),minConfidence:f.number().min(0).max(1).optional(),maxExtractionsPerMinute:f.number().optional()}),Rc=f.object({enabled:f.boolean(),port:f.coerce.number().int().min(1).max(65535),host:f.string()}),Lc=f.object({name:f.string(),command:f.string(),argsTemplate:f.array(f.string()),promptVia:f.enum(["arg","stdin"]).default("arg"),env:f.record(f.string()).optional(),cwd:f.string().optional(),timeoutMs:f.number().max(9e5).optional()}),Mc=f.object({token:f.string(),baseUrl:f.string().optional()}),Nc=f.object({token:f.string(),baseUrl:f.string().optional()}),Cc=f.object({provider:f.enum(["github","gitlab"]),baseBranch:f.string().optional(),github:Mc.optional(),gitlab:Nc.optional()}),Oc=f.object({enabled:f.boolean(),agents:f.array(Lc),forge:Cc.optional()}),Dc=f.object({baseUrl:f.string(),tokenId:f.string(),tokenSecret:f.string(),verifyTls:f.boolean().optional(),defaultNode:f.string().optional()}),Uc=f.object({baseUrl:f.string(),apiKey:f.string().optional(),username:f.string().optional(),password:f.string().optional(),site:f.string().optional(),verifyTls:f.boolean().optional()}),Pc=f.object({baseUrl:f.string(),accessToken:f.string(),verifyTls:f.boolean().optional()}),Qr=f.object({name:f.string(),telegram:Ao,discord:Ro.optional(),whatsapp:Lo.optional(),matrix:Mo.optional(),signal:No.optional(),llm:wc,storage:Co,logger:Oo,security:Do,search:bc.optional(),email:Tc.optional(),speech:_c.optional(),calendar:Sc.optional(),mcp:xc.optional(),codeSandbox:Ic.optional(),activeLearning:Ac.optional(),api:Rc.optional(),codeAgents:Oc.optional(),proxmox:Dc.optional(),unifi:Uc.optional(),homeassistant:Pc.optional()})});var tn,sn=b(()=>{"use strict";tn={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"}}});import Uo from"node:fs";import Fc from"node:path";import{config as Po}from"dotenv";import jc from"js-yaml";function Fo(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]=Fo(n,r):t[s]=r}return t}function Hc(c){let e={...c};for(let[t,s]of Object.entries(Bc)){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 rn(){Po({override:!0})}var Bc,te,jo=b(()=>{"use strict";en();sn();u(Fo,"deepMerge");Bc={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_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"]};u(Hc,"applyEnvOverrides");u(rn,"reloadDotenv");te=class{static{u(this,"ConfigLoader")}loadConfig(e){Po();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Fc.resolve(t);if(Uo.existsSync(r)){let d=Uo.readFileSync(r,"utf-8"),m=jc.load(d);m&&typeof m=="object"&&(s=m)}let n=Fo(tn,s),o=Hc(n),i=Qr.parse(o),a=i.llm;a&&"provider"in a&&(i.llm={default:a});let l=i.email;return l&&!("accounts"in l)&&(i.email={accounts:[{name:"default",...l}]}),i}}});var Le=b(()=>{"use strict";en();sn();jo()});import nn from"pino";function Jt(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=nn.transport({target:"pino-pretty",options:{colorize:!0}});return nn({name:c,level:t},r)}return nn({name:c,level:t})}var Bo=b(()=>{"use strict";u(Jt,"createLogger")});import du from"pino";var Ho=b(()=>{"use strict"});var on=b(()=>{"use strict";Bo();Ho()});var ot,er=b(()=>{"use strict";ot=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var ri=Object.defineProperty;var u=(c,e)=>ri(c,"name",{value:e,configurable:!0});var y=(c,e)=>()=>(c&&(e=c(c=0)),e);var re=(c,e)=>{for(var t in e)ri(c,t,{get:e[t],enumerable:!0})};import{z as h}from"zod";var ni,ii,ai,ci,li,di,ui,mi,Ye,cl,ll,dl,oi,ul,ml,pl,fl,hl,gl,yl,wl,Tl,El,bl,_l,$l,vl,Sl,kl,Al,Il,Rl,xl,Cl,Ll,Nl,Ml,bo,_o=y(()=>{"use strict";ni=h.object({token:h.string().optional(),enabled:h.boolean()}),ii=h.object({token:h.string().optional(),enabled:h.boolean()}),ai=h.object({enabled:h.boolean(),dataPath:h.string()}),ci=h.object({homeserverUrl:h.string(),accessToken:h.string().optional(),userId:h.string().optional(),enabled:h.boolean()}),li=h.object({apiUrl:h.string(),phoneNumber:h.string().optional(),enabled:h.boolean()}),di=h.object({path:h.string()}),ui=h.object({level:h.enum(["trace","debug","info","warn","error","fatal"]),pretty:h.boolean(),auditLogPath:h.string().optional()}),mi=h.object({rulesPath:h.string(),defaultEffect:h.enum(["allow","deny"]),ownerUserId:h.string().optional()}),Ye=h.object({provider:h.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:h.string().optional(),baseUrl:h.string().optional(),model:h.string(),temperature:h.number().optional(),maxTokens:h.number().optional()}),cl=h.object({default:Ye,strong:Ye.optional(),fast:Ye.optional(),embeddings:Ye.optional(),local:Ye.optional()}),ll=h.union([Ye,cl]),dl=h.object({provider:h.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:h.string().optional(),baseUrl:h.string().optional()}),oi=h.object({name:h.string().optional(),provider:h.enum(["imap-smtp","microsoft"]).optional(),imap:h.object({host:h.string(),port:h.number(),secure:h.boolean()}).optional(),smtp:h.object({host:h.string(),port:h.number(),secure:h.boolean()}).optional(),auth:h.object({user:h.string(),pass:h.string()}).optional(),microsoft:h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}).optional()}),ul=h.union([h.object({accounts:h.array(oi)}),oi]),ml=h.object({provider:h.enum(["openai","groq","google"]),apiKey:h.string(),baseUrl:h.string().optional(),ttsEnabled:h.boolean().optional(),ttsModel:h.string().optional(),ttsVoice:h.string().optional()}),pl=h.object({serverUrl:h.string(),username:h.string(),password:h.string()}),fl=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),hl=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),gl=h.object({provider:h.enum(["caldav","google","microsoft"]),caldav:pl.optional(),google:fl.optional(),microsoft:hl.optional()}),yl=h.object({name:h.string(),command:h.string().optional(),args:h.array(h.string()).optional(),env:h.record(h.string()).optional(),url:h.string().optional()}),wl=h.object({servers:h.array(yl)}),Tl=h.object({enabled:h.boolean(),allowedLanguages:h.array(h.enum(["javascript","python"])).optional(),maxTimeoutMs:h.number().optional(),allowNetwork:h.boolean().optional()}),El=h.object({enabled:h.boolean().optional(),minMessageLength:h.number().optional(),minConfidence:h.number().min(0).max(1).optional(),maxExtractionsPerMinute:h.number().optional()}),bl=h.object({enabled:h.boolean(),port:h.coerce.number().int().min(1).max(65535),host:h.string()}),_l=h.object({name:h.string(),command:h.string(),argsTemplate:h.array(h.string()),promptVia:h.enum(["arg","stdin"]).default("arg"),env:h.record(h.string()).optional(),cwd:h.string().optional(),timeoutMs:h.number().max(9e5).optional()}),$l=h.object({token:h.string(),baseUrl:h.string().optional()}),vl=h.object({token:h.string(),baseUrl:h.string().optional()}),Sl=h.object({provider:h.enum(["github","gitlab"]),baseBranch:h.string().optional(),github:$l.optional(),gitlab:vl.optional()}),kl=h.object({enabled:h.boolean(),agents:h.array(_l),forge:Sl.optional()}),Al=h.object({baseUrl:h.string(),tokenId:h.string(),tokenSecret:h.string(),verifyTls:h.boolean().optional(),defaultNode:h.string().optional()}),Il=h.object({baseUrl:h.string(),apiKey:h.string().optional(),username:h.string().optional(),password:h.string().optional(),site:h.string().optional(),verifyTls:h.boolean().optional()}),Rl=h.object({baseUrl:h.string(),accessToken:h.string(),verifyTls:h.boolean().optional()}),xl=h.object({serverUrl:h.string(),username:h.string(),password:h.string(),addressBookPath:h.string().optional()}),Cl=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),Ll=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),Nl=h.object({provider:h.enum(["carddav","google","microsoft"]),carddav:xl.optional(),google:Cl.optional(),microsoft:Ll.optional()}),Ml=h.object({socketPath:h.string().optional(),host:h.string().optional(),verifyTls:h.boolean().optional()}),bo=h.object({name:h.string(),telegram:ni,discord:ii.optional(),whatsapp:ai.optional(),matrix:ci.optional(),signal:li.optional(),llm:ll,storage:di,logger:ui,security:mi,search:dl.optional(),email:ul.optional(),speech:ml.optional(),calendar:gl.optional(),mcp:wl.optional(),codeSandbox:Tl.optional(),activeLearning:El.optional(),api:bl.optional(),codeAgents:kl.optional(),proxmox:Al.optional(),unifi:Il.optional(),homeassistant:Rl.optional(),contacts:Nl.optional(),docker:Ml.optional()})});var $o,vo=y(()=>{"use strict";$o={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"}}});import pi from"node:fs";import Dl from"node:path";import{config as fi}from"dotenv";import Ol from"js-yaml";function hi(c,e){let t={...c};for(let s of Object.keys(e)){let r=e[s],o=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&o!==null&&o!==void 0&&typeof o=="object"&&!Array.isArray(o)?t[s]=hi(o,r):t[s]=r}return t}function Pl(c){let e={...c};for(let[t,s]of Object.entries(Ul)){let r=process.env[t];if(r===void 0)continue;let o=e;for(let n=0;n<s.length-1;n++){let i=s[n];(o[i]===void 0||o[i]===null||typeof o[i]!="object")&&(o[i]={}),o[i]={...o[i]},o=o[i]}o[s[s.length-1]]=r}return e}function So(){fi({override:!0})}var Ul,oe,gi=y(()=>{"use strict";_o();vo();u(hi,"deepMerge");Ul={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_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"]};u(Pl,"applyEnvOverrides");u(So,"reloadDotenv");oe=class{static{u(this,"ConfigLoader")}loadConfig(e){fi();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Dl.resolve(t);if(pi.existsSync(r)){let d=pi.readFileSync(r,"utf-8"),m=Ol.load(d);m&&typeof m=="object"&&(s=m)}let o=hi($o,s),n=Pl(o),i=bo.parse(n),a=i.llm;a&&"provider"in a&&(i.llm={default:a});let l=i.email;return l&&!("accounts"in l)&&(i.email={accounts:[{name:"default",...l}]}),i}}});var Oe=y(()=>{"use strict";_o();vo();gi()});import ko from"pino";function is(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 yi=y(()=>{"use strict";u(is,"createLogger")});import um from"pino";var wi=y(()=>{"use strict"});var Ao=y(()=>{"use strict";yi();wi()});var pt,hr=y(()=>{"use strict";pt=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,
6
6
  applied_at TEXT NOT NULL
7
7
  )
8
- `)}getCurrentVersion(){return this.db.prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}migrate(e){let t=[...e].sort((r,n)=>r.version-n.version),s=this.getCurrentVersion();for(let r of t){if(r.version<=s)continue;this.db.transaction(()=>{r.up(this.db),this.db.prepare("INSERT INTO _migrations (version, description, applied_at) VALUES (?, ?, ?)").run(r.version,r.description,new Date().toISOString())})()}}getAppliedMigrations(){return this.db.prepare("SELECT version, applied_at FROM _migrations ORDER BY version ASC").all().map(t=>({version:t.version,appliedAt:t.applied_at}))}}});var an,cn=b(()=>{"use strict";er();an=[{version:1,description:"Initial schema \u2014 conversations, messages, users, audit_log",up(c){}},{version:2,description:"Add plugin_skills table for tracking loaded external plugins",up(c){c.exec(`
8
+ `)}getCurrentVersion(){return this.db.prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}migrate(e){let t=[...e].sort((r,o)=>r.version-o.version),s=this.getCurrentVersion();for(let r of t){if(r.version<=s)continue;this.db.transaction(()=>{r.up(this.db),this.db.prepare("INSERT INTO _migrations (version, description, applied_at) VALUES (?, ?, ?)").run(r.version,r.description,new Date().toISOString())})()}}getAppliedMigrations(){return this.db.prepare("SELECT version, applied_at FROM _migrations ORDER BY version ASC").all().map(t=>({version:t.version,appliedAt:t.applied_at}))}}});var Io,Ro=y(()=>{"use strict";hr();Io=[{version:1,description:"Initial schema \u2014 conversations, messages, users, audit_log",up(c){}},{version:2,description:"Add plugin_skills table for tracking loaded external plugins",up(c){c.exec(`
9
9
  CREATE TABLE IF NOT EXISTS plugin_skills (
10
10
  name TEXT PRIMARY KEY,
11
11
  file_path TEXT NOT NULL,
@@ -190,7 +190,26 @@ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0})
190
190
  CREATE INDEX IF NOT EXISTS idx_audit_log_user_ts ON audit_log(user_id, timestamp);
191
191
  CREATE INDEX IF NOT EXISTS idx_background_tasks_status ON background_tasks(status);
192
192
  CREATE INDEX IF NOT EXISTS idx_background_tasks_user ON background_tasks(user_id);
193
- `)}}]});import qc from"better-sqlite3";import Wc from"node:fs";import Xc from"node:path";var We,qo=b(()=>{"use strict";er();cn();We=class{static{u(this,"Database")}db;constructor(e){let t=Xc.dirname(e);Wc.mkdirSync(t,{recursive:!0}),this.db=new qc(e),this.db.pragma("journal_mode = WAL"),this.db.pragma("foreign_keys = ON"),this.db.pragma("busy_timeout = 5000"),this.initTables(),this.runMigrations()}initTables(){this.db.exec(`
193
+ `)}},{version:13,description:"Add todos table for todo list management",up(c){c.exec(`
194
+ CREATE TABLE IF NOT EXISTS todos (
195
+ id TEXT PRIMARY KEY,
196
+ user_id TEXT NOT NULL,
197
+ list TEXT NOT NULL DEFAULT 'default',
198
+ title TEXT NOT NULL,
199
+ description TEXT,
200
+ priority TEXT NOT NULL DEFAULT 'normal',
201
+ due_date TEXT,
202
+ completed INTEGER NOT NULL DEFAULT 0,
203
+ created_at TEXT NOT NULL,
204
+ updated_at TEXT NOT NULL
205
+ );
206
+
207
+ CREATE INDEX IF NOT EXISTS idx_todos_user_list
208
+ ON todos(user_id, list, completed, created_at DESC);
209
+
210
+ CREATE INDEX IF NOT EXISTS idx_todos_user_due
211
+ ON todos(user_id, completed, due_date);
212
+ `)}}]});import Fl from"better-sqlite3";import jl from"node:fs";import Bl from"node:path";var Je,Ti=y(()=>{"use strict";hr();Ro();Je=class{static{u(this,"Database")}db;constructor(e){let t=Bl.dirname(e);jl.mkdirSync(t,{recursive:!0}),this.db=new Fl(e),this.db.pragma("journal_mode = WAL"),this.db.pragma("foreign_keys = ON"),this.db.pragma("busy_timeout = 5000"),this.initTables(),this.runMigrations()}initTables(){this.db.exec(`
194
213
  CREATE TABLE IF NOT EXISTS conversations (
195
214
  id TEXT PRIMARY KEY,
196
215
  platform TEXT NOT NULL,
@@ -240,19 +259,19 @@ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0})
240
259
 
241
260
  CREATE UNIQUE INDEX IF NOT EXISTS idx_users_platform
242
261
  ON users(platform, platform_user_id);
243
- `)}runMigrations(){new ot(this.db).migrate(an)}getDb(){return this.db}close(){this.db.close()}}});import Wo from"node:crypto";var Zt,Xo=b(()=>{"use strict";Zt=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Wo.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
262
+ `)}runMigrations(){new pt(this.db).migrate(Io)}getDb(){return this.db}close(){this.db.close()}}});import Ei from"node:crypto";var as,bi=y(()=>{"use strict";as=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),o={id:Ei.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
244
263
  INSERT INTO conversations (id, platform, chat_id, user_id, created_at, updated_at)
245
264
  VALUES (?, ?, ?, ?, ?, ?)
246
- `).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:Wo.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
265
+ `).run(o.id,o.platform,o.chatId,o.userId,o.createdAt,o.updatedAt),o}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 o={id:Ei.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
247
266
  INSERT INTO messages (id, conversation_id, role, content, tool_calls, created_at)
248
267
  VALUES (?, ?, ?, ?, ?, ?)
249
- `).run(n.id,n.conversationId,n.role,n.content,n.toolCalls??null,n.createdAt),n}getMessages(e,t=50){return this.db.prepare("SELECT * FROM (SELECT *, rowid AS _rn FROM messages WHERE conversation_id = ? ORDER BY created_at DESC, _rn DESC LIMIT ?) ORDER BY created_at ASC, _rn ASC").all(e,t).map(r=>({id:r.id,conversationId:r.conversation_id,role:r.role,content:r.content,toolCalls:r.tool_calls??void 0,createdAt:r.created_at}))}updateTimestamp(e){this.db.prepare("UPDATE conversations SET updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}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 zc from"node:crypto";var Qt,zo=b(()=>{"use strict";Qt=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:zc.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:o,updatedAt:o};return this.db.prepare(`
268
+ `).run(o.id,o.conversationId,o.role,o.content,o.toolCalls??null,o.createdAt),o}getMessages(e,t=50){return this.db.prepare("SELECT * FROM (SELECT *, rowid AS _rn FROM messages WHERE conversation_id = ? ORDER BY created_at DESC, _rn DESC LIMIT ?) ORDER BY created_at ASC, _rn ASC").all(e,t).map(r=>({id:r.id,conversationId:r.conversation_id,role:r.role,content:r.content,toolCalls:r.tool_calls??void 0,createdAt:r.created_at}))}updateTimestamp(e){this.db.prepare("UPDATE conversations SET updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}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 ql from"node:crypto";var cs,_i=y(()=>{"use strict";cs=class{static{u(this,"UserRepository")}db;constructor(e){this.db=e}findOrCreate(e,t,s,r){let o=this.db.prepare("SELECT * FROM users WHERE platform = ? AND platform_user_id = ?").get(e,t);if(o)return this.mapRow(o);let n=new Date().toISOString(),i={id:ql.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:n,updatedAt:n};return this.db.prepare(`
250
269
  INSERT INTO users (id, platform, platform_user_id, username, display_name, created_at, updated_at)
251
270
  VALUES (?, ?, ?, ?, ?, ?, ?)
252
- `).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 Xe,Vo=b(()=>{"use strict";Xe=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
271
+ `).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 Ze,$i=y(()=>{"use strict";Ze=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
253
272
  INSERT INTO audit_log (id, timestamp, user_id, action, risk_level, rule_id, effect, platform, chat_id, context)
254
273
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
255
- `).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 Vc}from"node:crypto";var es,Ko=b(()=>{"use strict";es=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=Vc();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
274
+ `).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 ")}`:"",o=e.limit??100;return s.push(o),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 Hl}from"node:crypto";var ls,vi=y(()=>{"use strict";ls=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,o,n,i){let a=new Date().toISOString(),l=Hl();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
256
275
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
257
276
  ON CONFLICT(user_id, key) DO UPDATE SET
258
277
  value = excluded.value,
@@ -260,16 +279,16 @@ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0})
260
279
  type = excluded.type,
261
280
  confidence = excluded.confidence,
262
281
  source = excluded.source,
263
- updated_at = excluded.updated_at`).run(l,e,t,s,r,n,o,i,a,a);let d=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(d)}recall(e,t){let s=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);if(s)return this.mapRow(s)}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND (key LIKE ? OR value LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}keywordSearch(e,t,s=20){let r=t.toLowerCase().split(/\s+/).filter(l=>l.length>=2);if(r.length===0)return[];let n=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),o=[e];for(let l of r)o.push(`%${l}%`,`%${l}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${n}) ORDER BY updated_at DESC`).all(...o).map(l=>{let d=this.mapRow(l),m=`${d.key} ${d.value}`.toLowerCase(),h=0;for(let w of r)m.includes(w)&&(h+=1);return{entry:d,score:h/r.length}});return a.sort((l,d)=>d.score-l.score),a.slice(0,s).map(l=>l.entry)}recordAccess(e){let t=new Date().toISOString();this.db.prepare("UPDATE memories SET last_accessed_at = ?, access_count = access_count + 1 WHERE id = ?").run(t,e)}findStale(e,t,s){let r=new Date(Date.now()-t*24*60*60*1e3).toISOString();return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND updated_at < ? AND confidence <= ? ORDER BY confidence ASC").all(e,r,s).map(o=>this.mapRow(o))}deleteByIds(e){if(e.length===0)return 0;let t=e.map(()=>"?").join(",");return this.db.prepare(`DELETE FROM memories WHERE id IN (${t})`).run(...e).changes}listByCategory(e,t){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND category = ? ORDER BY updated_at DESC").all(e,t).map(r=>this.mapRow(r))}listAll(e){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC").all(e).map(s=>this.mapRow(s))}delete(e,t){return this.db.prepare("DELETE FROM memories WHERE user_id = ? AND key = ?").run(e,t).changes>0}getRecentForPrompt(e,t=20){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}mapRow(e){return{id:e.id,userId:e.user_id,key:e.key,value:e.value,category:e.category||"general",type:e.type||"general",confidence:e.confidence??1,source:e.source||"manual",lastAccessedAt:e.last_accessed_at||null,accessCount:e.access_count??0,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as Kc}from"node:crypto";var ts,Go=b(()=>{"use strict";ts=class{static{u(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n){let o={id:Kc(),userId:e,platform:t,chatId:s,message:r,triggerAt:n.toISOString(),createdAt:new Date().toISOString(),fired:!1};return this.db.prepare(`
282
+ updated_at = excluded.updated_at`).run(l,e,t,s,r,o,n,i,a,a);let d=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(d)}recall(e,t){let s=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);if(s)return this.mapRow(s)}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND (key LIKE ? OR value LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(o=>this.mapRow(o))}keywordSearch(e,t,s=20){let r=t.toLowerCase().split(/\s+/).filter(l=>l.length>=2);if(r.length===0)return[];let o=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),n=[e];for(let l of r)n.push(`%${l}%`,`%${l}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${o}) ORDER BY updated_at DESC`).all(...n).map(l=>{let d=this.mapRow(l),m=`${d.key} ${d.value}`.toLowerCase(),p=0;for(let w of r)m.includes(w)&&(p+=1);return{entry:d,score:p/r.length}});return a.sort((l,d)=>d.score-l.score),a.slice(0,s).map(l=>l.entry)}recordAccess(e){let t=new Date().toISOString();this.db.prepare("UPDATE memories SET last_accessed_at = ?, access_count = access_count + 1 WHERE id = ?").run(t,e)}findStale(e,t,s){let r=new Date(Date.now()-t*24*60*60*1e3).toISOString();return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND updated_at < ? AND confidence <= ? ORDER BY confidence ASC").all(e,r,s).map(n=>this.mapRow(n))}deleteByIds(e){if(e.length===0)return 0;let t=e.map(()=>"?").join(",");return this.db.prepare(`DELETE FROM memories WHERE id IN (${t})`).run(...e).changes}listByCategory(e,t){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND category = ? ORDER BY updated_at DESC").all(e,t).map(r=>this.mapRow(r))}listAll(e){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC").all(e).map(s=>this.mapRow(s))}delete(e,t){return this.db.prepare("DELETE FROM memories WHERE user_id = ? AND key = ?").run(e,t).changes>0}getRecentForPrompt(e,t=20){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}mapRow(e){return{id:e.id,userId:e.user_id,key:e.key,value:e.value,category:e.category||"general",type:e.type||"general",confidence:e.confidence??1,source:e.source||"manual",lastAccessedAt:e.last_accessed_at||null,accessCount:e.access_count??0,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as zl}from"node:crypto";var ds,Si=y(()=>{"use strict";ds=class{static{u(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,o){let n={id:zl(),userId:e,platform:t,chatId:s,message:r,triggerAt:o.toISOString(),createdAt:new Date().toISOString(),fired:!1};return this.db.prepare(`
264
283
  INSERT INTO reminders (id, user_id, platform, chat_id, message, trigger_at, created_at, fired)
265
284
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
266
- `).run(o.id,o.userId,o.platform,o.chatId,o.message,o.triggerAt,o.createdAt,0),o}getDue(){let e=new Date().toISOString();return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND trigger_at <= ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND user_id = ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}markFired(e){this.db.prepare("UPDATE reminders SET fired = 1 WHERE id = ?").run(e)}cancel(e){return this.db.prepare("DELETE FROM reminders WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,message:e.message,triggerAt:e.trigger_at,createdAt:e.created_at,fired:e.fired===1}}}});import{randomUUID as Gc}from"node:crypto";var ss,Yo=b(()=>{"use strict";ss=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),n=Gc();return this.db.prepare("INSERT INTO notes (id, user_id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r,r),{id:n,userId:e,title:t,content:s,createdAt:r,updatedAt:r}}getById(e){let t=this.db.prepare("SELECT * FROM notes WHERE id = ?").get(e);return t?this.mapRow(t):void 0}list(e,t=50){return this.db.prepare("SELECT * FROM notes WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM notes WHERE user_id = ? AND (title LIKE ? OR content LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}update(e,t,s){let r=this.getById(e);if(!r)return;let n=new Date().toISOString(),o=t??r.title,i=s??r.content;return this.db.prepare("UPDATE notes SET title = ?, content = ?, updated_at = ? WHERE id = ?").run(o,i,n,e),{...r,title:o,content:i,updatedAt:n}}delete(e){return this.db.prepare("DELETE FROM notes WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,title:e.title,content:e.content,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as Yc}from"node:crypto";var rs,Jo=b(()=>{"use strict";rs=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=Yc(),s=new Date().toISOString(),r=Buffer.from(new Float32Array(e.embedding).buffer);return this.db.transaction(()=>{this.db.prepare("DELETE FROM embeddings WHERE user_id = ? AND source_type = ? AND source_id = ?").run(e.userId,e.sourceType,e.sourceId),this.db.prepare("INSERT INTO embeddings (id, user_id, source_type, source_id, content, embedding, model, dimensions, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(t,e.userId,e.sourceType,e.sourceId,e.content,r,e.model,e.dimensions,s)})(),{id:t,userId:e.userId,sourceType:e.sourceType,sourceId:e.sourceId,content:e.content,embedding:e.embedding,model:e.model,dimensions:e.dimensions,createdAt:s}}findByUser(e){return this.db.prepare("SELECT * FROM embeddings WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapRow(s))}findBySource(e,t){let s=this.db.prepare("SELECT * FROM embeddings WHERE source_type = ? AND source_id = ?").get(e,t);if(s)return this.mapRow(s)}delete(e,t){return this.db.prepare("DELETE FROM embeddings WHERE source_type = ? AND source_id = ?").run(e,t).changes>0}mapRow(e){let t=e.embedding,s=new Float32Array(t.buffer,t.byteOffset,t.byteLength/4),r=Array.from(s);return{id:e.id,userId:e.user_id,sourceType:e.source_type,sourceId:e.source_id,content:e.content,embedding:r,model:e.model,dimensions:e.dimensions,createdAt:e.created_at}}}});import Jc from"node:crypto";var ns,Zo=b(()=>{"use strict";ns=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:Jc.randomUUID(),code:String(Math.floor(1e5+Math.random()*9e5)),userId:e,platform:t,createdAt:new Date().toISOString(),expiresAt:new Date(Date.now()+6e5).toISOString()};try{return this.db.prepare(`
285
+ `).run(n.id,n.userId,n.platform,n.chatId,n.message,n.triggerAt,n.createdAt,0),n}getDue(){let e=new Date().toISOString();return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND trigger_at <= ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND user_id = ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}markFired(e){this.db.prepare("UPDATE reminders SET fired = 1 WHERE id = ?").run(e)}cancel(e){return this.db.prepare("DELETE FROM reminders WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,message:e.message,triggerAt:e.trigger_at,createdAt:e.created_at,fired:e.fired===1}}}});import{randomUUID as Vl}from"node:crypto";var us,ki=y(()=>{"use strict";us=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),o=Vl();return this.db.prepare("INSERT INTO notes (id, user_id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)").run(o,e,t,s,r,r),{id:o,userId:e,title:t,content:s,createdAt:r,updatedAt:r}}getById(e){let t=this.db.prepare("SELECT * FROM notes WHERE id = ?").get(e);return t?this.mapRow(t):void 0}list(e,t=50){return this.db.prepare("SELECT * FROM notes WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM notes WHERE user_id = ? AND (title LIKE ? OR content LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(o=>this.mapRow(o))}update(e,t,s){let r=this.getById(e);if(!r)return;let o=new Date().toISOString(),n=t??r.title,i=s??r.content;return this.db.prepare("UPDATE notes SET title = ?, content = ?, updated_at = ? WHERE id = ?").run(n,i,o,e),{...r,title:n,content:i,updatedAt:o}}delete(e){return this.db.prepare("DELETE FROM notes WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,title:e.title,content:e.content,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as Wl}from"node:crypto";var ms,Ai=y(()=>{"use strict";ms=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=Wl(),s=new Date().toISOString(),r=Buffer.from(new Float32Array(e.embedding).buffer);return this.db.transaction(()=>{this.db.prepare("DELETE FROM embeddings WHERE user_id = ? AND source_type = ? AND source_id = ?").run(e.userId,e.sourceType,e.sourceId),this.db.prepare("INSERT INTO embeddings (id, user_id, source_type, source_id, content, embedding, model, dimensions, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(t,e.userId,e.sourceType,e.sourceId,e.content,r,e.model,e.dimensions,s)})(),{id:t,userId:e.userId,sourceType:e.sourceType,sourceId:e.sourceId,content:e.content,embedding:e.embedding,model:e.model,dimensions:e.dimensions,createdAt:s}}findByUser(e){return this.db.prepare("SELECT * FROM embeddings WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapRow(s))}findBySource(e,t){let s=this.db.prepare("SELECT * FROM embeddings WHERE source_type = ? AND source_id = ?").get(e,t);if(s)return this.mapRow(s)}delete(e,t){return this.db.prepare("DELETE FROM embeddings WHERE source_type = ? AND source_id = ?").run(e,t).changes>0}mapRow(e){let t=e.embedding,s=new Float32Array(t.buffer,t.byteOffset,t.byteLength/4),r=Array.from(s);return{id:e.id,userId:e.user_id,sourceType:e.source_type,sourceId:e.source_id,content:e.content,embedding:r,model:e.model,dimensions:e.dimensions,createdAt:e.created_at}}}});import Xl from"node:crypto";var ps,Ii=y(()=>{"use strict";ps=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:Xl.randomUUID(),code:String(Math.floor(1e5+Math.random()*9e5)),userId:e,platform:t,createdAt:new Date().toISOString(),expiresAt:new Date(Date.now()+6e5).toISOString()};try{return this.db.prepare(`
267
286
  INSERT INTO link_tokens (id, code, user_id, platform, created_at, expires_at)
268
287
  VALUES (?, ?, ?, ?, ?, ?)
269
- `).run(r.id,r.code,r.userId,r.platform,r.createdAt,r.expiresAt),r}catch(n){if(!(n instanceof Error?n.message:"").includes("UNIQUE")||s===4)throw n}}throw new Error("Failed to generate unique link code after retries")}findByCode(e){let t=this.db.prepare("SELECT * FROM link_tokens WHERE code = ? AND expires_at > ?").get(e,new Date().toISOString());if(t)return{id:t.id,code:t.code,userId:t.user_id,platform:t.platform,createdAt:t.created_at,expiresAt:t.expires_at}}consume(e){this.db.prepare("DELETE FROM link_tokens WHERE id = ?").run(e)}countRecentByUser(e,t=10){let s=new Date(Date.now()-t*6e4).toISOString();return this.db.prepare("SELECT COUNT(*) as cnt FROM link_tokens WHERE user_id = ? AND created_at > ?").get(e,s).cnt}cleanup(){this.db.prepare("DELETE FROM link_tokens WHERE expires_at <= ?").run(new Date().toISOString())}}});import{randomUUID as Zc}from"node:crypto";var os,Qo=b(()=>{"use strict";os=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n,o){let i={id:Zc(),userId:e,platform:t,chatId:s,description:r,skillName:n,skillInput:o,status:"pending",createdAt:new Date().toISOString()};return this.db.prepare(`
288
+ `).run(r.id,r.code,r.userId,r.platform,r.createdAt,r.expiresAt),r}catch(o){if(!(o instanceof Error?o.message:"").includes("UNIQUE")||s===4)throw o}}throw new Error("Failed to generate unique link code after retries")}findByCode(e){let t=this.db.prepare("SELECT * FROM link_tokens WHERE code = ? AND expires_at > ?").get(e,new Date().toISOString());if(t)return{id:t.id,code:t.code,userId:t.user_id,platform:t.platform,createdAt:t.created_at,expiresAt:t.expires_at}}consume(e){this.db.prepare("DELETE FROM link_tokens WHERE id = ?").run(e)}countRecentByUser(e,t=10){let s=new Date(Date.now()-t*6e4).toISOString();return this.db.prepare("SELECT COUNT(*) as cnt FROM link_tokens WHERE user_id = ? AND created_at > ?").get(e,s).cnt}cleanup(){this.db.prepare("DELETE FROM link_tokens WHERE expires_at <= ?").run(new Date().toISOString())}}});import{randomUUID as Gl}from"node:crypto";var fs,Ri=y(()=>{"use strict";fs=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,o,n){let i={id:Gl(),userId:e,platform:t,chatId:s,description:r,skillName:o,skillInput:n,status:"pending",createdAt:new Date().toISOString()};return this.db.prepare(`
270
289
  INSERT INTO background_tasks (id, user_id, platform, chat_id, description, skill_name, skill_input, status, created_at)
271
290
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
272
- `).run(i.id,i.userId,i.platform,i.chatId,i.description,i.skillName,i.skillInput,i.status,i.createdAt),i}updateStatus(e,t,s,r){let n=new Date().toISOString(),o=null,i=null;t==="running"&&(o=n),(t==="completed"||t==="failed")&&(i=n),this.db.prepare(`
291
+ `).run(i.id,i.userId,i.platform,i.chatId,i.description,i.skillName,i.skillInput,i.status,i.createdAt),i}updateStatus(e,t,s,r){let o=new Date().toISOString(),n=null,i=null;t==="running"&&(n=o),(t==="completed"||t==="failed")&&(i=o),this.db.prepare(`
273
292
  UPDATE background_tasks
274
293
  SET status = ?,
275
294
  result = COALESCE(?, result),
@@ -277,12 +296,12 @@ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0})
277
296
  started_at = COALESCE(?, started_at),
278
297
  completed_at = COALESCE(?, completed_at)
279
298
  WHERE id = ?
280
- `).run(t,s??null,r??null,o,i,e)}getPending(e=10){return this.db.prepare("SELECT * FROM background_tasks WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare(`SELECT * FROM background_tasks
299
+ `).run(t,s??null,r??null,n,i,e)}getPending(e=10){return this.db.prepare("SELECT * FROM background_tasks WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare(`SELECT * FROM background_tasks
281
300
  WHERE user_id = ?
282
301
  AND (status IN ('pending', 'running') OR completed_at > datetime('now', '-1 day'))
283
302
  ORDER BY created_at DESC`).all(e).map(s=>this.mapRow(s))}cancel(e){return this.db.prepare("DELETE FROM background_tasks WHERE id = ? AND status IN ('pending', 'running')").run(e).changes>0}cleanup(e=7){return this.db.prepare(`DELETE FROM background_tasks
284
303
  WHERE status IN ('completed', 'failed')
285
- AND completed_at < datetime('now', '-' || ? || ' days')`).run(e).changes}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,description:e.description,skillName:e.skill_name,skillInput:e.skill_input,status:e.status,result:e.result,error:e.error,createdAt:e.created_at,startedAt:e.started_at,completedAt:e.completed_at}}}});import{randomUUID as Qc}from"node:crypto";var is,ei=b(()=>{"use strict";is=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Qc(),r=this.calculateInitialNextRun(e.scheduleType,e.scheduleValue);return this.db.prepare(`
304
+ AND completed_at < datetime('now', '-' || ? || ' days')`).run(e).changes}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,description:e.description,skillName:e.skill_name,skillInput:e.skill_input,status:e.status,result:e.result,error:e.error,createdAt:e.created_at,startedAt:e.started_at,completedAt:e.completed_at}}}});import{randomUUID as Kl}from"node:crypto";var hs,xi=y(()=>{"use strict";hs=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Kl(),r=this.calculateInitialNextRun(e.scheduleType,e.scheduleValue);return this.db.prepare(`
286
305
  INSERT INTO scheduled_actions
287
306
  (id, user_id, platform, chat_id, name, description, schedule_type, schedule_value,
288
307
  skill_name, skill_input, prompt_template, enabled, next_run_at, created_at)
@@ -293,9 +312,13 @@ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0})
293
312
  UPDATE scheduled_actions
294
313
  SET last_run_at = ?, next_run_at = ?
295
314
  WHERE id = ?
296
- `).run(t,s,e)}setEnabled(e,t){return this.db.prepare("UPDATE scheduled_actions SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM scheduled_actions WHERE id = ?").run(e).changes>0}calculateInitialNextRun(e,t){let s=new Date;switch(e){case"interval":{let r=parseInt(t,10);return isNaN(r)||r<=0?null:new Date(s.getTime()+r*6e4).toISOString()}case"once":return new Date(t).toISOString();case"cron":return this.getNextCronDate(t,s)?.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}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,name:e.name,description:e.description,scheduleType:e.schedule_type,scheduleValue:e.schedule_value,skillName:e.skill_name,skillInput:e.skill_input,promptTemplate:e.prompt_template,enabled:e.enabled===1,lastRunAt:e.last_run_at,nextRunAt:e.next_run_at,createdAt:e.created_at}}}});import{randomUUID as ti}from"node:crypto";var as,si=b(()=>{"use strict";as=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=ti(),o=new Date().toISOString();return this.db.prepare("INSERT INTO documents (id, user_id, filename, mime_type, size_bytes, chunk_count, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)").run(n,e,t,s,r,o),{id:n,userId:e,filename:t,mimeType:s,sizeBytes:r,chunkCount:0,createdAt:o}}updateChunkCount(e,t){this.db.prepare("UPDATE documents SET chunk_count = ? WHERE id = ?").run(t,e)}addChunk(e,t,s,r){let n=ti(),o=new Date().toISOString();return this.db.prepare("INSERT INTO document_chunks (id, document_id, chunk_index, content, embedding_id, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r??null,o),{id:n,documentId:e,chunkIndex:t,content:s,embeddingId:r,createdAt:o}}getDocument(e){let t=this.db.prepare("SELECT * FROM documents WHERE id = ?").get(e);return t?this.mapDocumentRow(t):void 0}getChunks(e){return this.db.prepare("SELECT * FROM document_chunks WHERE document_id = ? ORDER BY chunk_index ASC").all(e).map(s=>this.mapChunkRow(s))}listByUser(e){return this.db.prepare("SELECT * FROM documents WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapDocumentRow(s))}deleteDocument(e){this.db.transaction(()=>{let s=this.db.prepare("SELECT embedding_id FROM document_chunks WHERE document_id = ? AND embedding_id IS NOT NULL").all(e);if(s.length>0){let r=s.map(o=>o.embedding_id),n=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM embeddings WHERE id IN (${n})`).run(...r)}this.db.prepare("DELETE FROM document_chunks WHERE document_id = ?").run(e),this.db.prepare("DELETE FROM documents WHERE id = ?").run(e)})()}getChunksByEmbeddingIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT * FROM document_chunks WHERE embedding_id IN (${t}) ORDER BY chunk_index ASC`).all(...e).map(r=>this.mapChunkRow(r))}mapDocumentRow(e){return{id:e.id,userId:e.user_id,filename:e.filename,mimeType:e.mime_type,sizeBytes:e.size_bytes,chunkCount:e.chunk_count,createdAt:e.created_at}}mapChunkRow(e){return{id:e.id,documentId:e.document_id,chunkIndex:e.chunk_index,content:e.content,embeddingId:e.embedding_id||void 0,createdAt:e.created_at}}}});var ln=b(()=>{"use strict";qo();Xo();zo();Vo();Ko();er();cn();Go();Yo();Jo();Zo();Qo();ei();si()});function ze(c){if(dn[c])return dn[c];let e=Object.entries(dn).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var dn,el,ge,it=b(()=>{"use strict";dn={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"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},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},mistral:{maxInputTokens:32e3,maxOutputTokens:4096},"mistral-small":{maxInputTokens:32e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"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-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"mistral-medium-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"mistral-small-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"codestral-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"magistral-medium-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"magistral-small-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"ministral-8b-latest":{maxInputTokens:128e3,maxOutputTokens:4096}},el={maxInputTokens:8192,maxOutputTokens:4096};u(ze,"lookupContextWindow");ge=class{static{u(this,"LLMProvider")}config;contextWindow=el;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import tl from"@anthropic-ai/sdk";var cs,un=b(()=>{"use strict";it();cs=class extends ge{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new tl({apiKey:this.config.apiKey});let e=ze(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 sl from"openai";var de,Ve=b(()=>{"use strict";it();de=class extends ge{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new sl({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=ze(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,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.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,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",l=[],d=null,m=0,h=0;for await(let w of r){let y=w.choices[0];if(!y)continue;let g=y.delta;if(g?.content&&(a+=g.content,yield{type:"text_delta",text:g.content}),g?.tool_calls)for(let _ of g.tool_calls)if(_.id){if(n){let v;try{v=JSON.parse(i||"{}")}catch{v={}}l.push({id:n,name:o,input:v})}n=_.id,o=_.function?.name,i=_.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else _.function?.arguments&&(i+=_.function.arguments,yield{type:"tool_use_delta",toolCall:{input:_.function.arguments}});y.finish_reason&&(d=y.finish_reason),w.usage&&(m=w.usage.prompt_tokens,h=w.usage.completion_tokens)}if(n){let w;try{w=JSON.parse(i||"{}")}catch{w={}}l.push({id:n,name:o,input:w})}yield{type:"message_complete",response:{content:a,toolCalls:l.length>0?l:void 0,usage:{inputTokens:m,outputTokens:h},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}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 ls,mn=b(()=>{"use strict";Ve();ls=class extends de{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 ds,pn=b(()=>{"use strict";it();ds=class extends ge{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=ze(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 w=await n.text();throw new Error(`Ollama API error (${n.status}): ${w}`)}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,h=[];try{for(;;){let{done:w,value:y}=await o.read();if(w)break;a+=i.decode(y,{stream:!0});let g=a.split(`
297
- `);a=g.pop()??"";for(let _ of g){let v=_.trim();if(!v)continue;let R;try{R=JSON.parse(v)}catch{continue}if(R.message?.content&&(l+=R.message.content,yield{type:"text_delta",text:R.message.content}),R.message?.tool_calls)for(let x of R.message.tool_calls){let O={id:`ollama_tool_${h.length}`,name:x.function.name,input:x.function.arguments};h.push(O),yield{type:"tool_use_start",toolCall:{id:O.id,name:O.name}},yield{type:"tool_use_delta",toolCall:{input:O.input}}}R.done&&(d=R.prompt_eval_count??0,m=R.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:h.length>0?h:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:h.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let w;try{w=JSON.parse(a.trim())}catch{return}if(w.message?.content&&(l+=w.message.content,yield{type:"text_delta",text:w.message.content}),w.message?.tool_calls)for(let y of w.message.tool_calls){let g={id:`ollama_tool_${h.length}`,name:y.function.name,input:y.function.arguments};h.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}},yield{type:"tool_use_delta",toolCall:{input:g.input}}}w.done&&(d=w.prompt_eval_count??0,m=w.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:h.length>0?h:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:h.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(`
298
- `)};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 us,hn=b(()=>{"use strict";Ve();us=class extends de{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}}});var ms,fn=b(()=>{"use strict";Ve();ms=class extends de{static{u(this,"GoogleProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://generativelanguage.googleapis.com/v1beta/openai/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var ps,gn=b(()=>{"use strict";Ve();ps=class extends de{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 yn(c){switch(c.provider){case"anthropic":return new cs(c);case"openai":return new de(c);case"openrouter":return new ls(c);case"ollama":return new ds(c);case"openwebui":return new us(c);case"google":return new ms(c);case"mistral":return new ps(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var wn=b(()=>{"use strict";un();Ve();mn();pn();hn();fn();gn();u(yn,"createLLMProvider")});function bn(c){return new tr(c)}var rl,tr,ri=b(()=>{"use strict";it();wn();rl=["default","strong","fast","embeddings","local"],tr=class extends ge{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of rl){let t=this.multiConfig[e];if(t){let s=yn(t);await s.initialize(),this.providers.set(e,s)}}}resolve(e){return e&&this.providers.has(e)?this.providers.get(e):this.providers.get("default")}async complete(e){return this.resolve(e.tier).complete(e)}async*stream(e){yield*this.resolve(e.tier).stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve()).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve()).supportsEmbeddings()}isAvailable(){return this.resolve().isAvailable()}getContextWindow(){return this.resolve().getContextWindow()}};u(bn,"createModelRouter")});function ve(c){return Math.ceil(c.length/3.5)}function fs(c){if(typeof c.content=="string")return ve(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=ve(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=ve(t.name)+ve(JSON.stringify(t.input));break;case"tool_result":e+=ve(t.content);break}return e}var hs,ni=b(()=>{"use strict";u(ve,"estimateTokens");u(fs,"estimateMessageTokens");hs=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}).
315
+ `).run(t,s,e)}setEnabled(e,t){return this.db.prepare("UPDATE scheduled_actions SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM scheduled_actions WHERE id = ?").run(e).changes>0}calculateInitialNextRun(e,t){let s=new Date;switch(e){case"interval":{let r=parseInt(t,10);return isNaN(r)||r<=0?null:new Date(s.getTime()+r*6e4).toISOString()}case"once":return new Date(t).toISOString();case"cron":return this.getNextCronDate(t,s)?.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 o=0;o<1440;o++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),o=t.getDate(),n=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],o)&&this.matchCronField(e[3],n)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let o=parseInt(s[1],10);return t%o===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,name:e.name,description:e.description,scheduleType:e.schedule_type,scheduleValue:e.schedule_value,skillName:e.skill_name,skillInput:e.skill_input,promptTemplate:e.prompt_template,enabled:e.enabled===1,lastRunAt:e.last_run_at,nextRunAt:e.next_run_at,createdAt:e.created_at}}}});import{randomUUID as Ci}from"node:crypto";var gs,Li=y(()=>{"use strict";gs=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let o=Ci(),n=new Date().toISOString();return this.db.prepare("INSERT INTO documents (id, user_id, filename, mime_type, size_bytes, chunk_count, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)").run(o,e,t,s,r,n),{id:o,userId:e,filename:t,mimeType:s,sizeBytes:r,chunkCount:0,createdAt:n}}updateChunkCount(e,t){this.db.prepare("UPDATE documents SET chunk_count = ? WHERE id = ?").run(t,e)}addChunk(e,t,s,r){let o=Ci(),n=new Date().toISOString();return this.db.prepare("INSERT INTO document_chunks (id, document_id, chunk_index, content, embedding_id, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(o,e,t,s,r??null,n),{id:o,documentId:e,chunkIndex:t,content:s,embeddingId:r,createdAt:n}}getDocument(e){let t=this.db.prepare("SELECT * FROM documents WHERE id = ?").get(e);return t?this.mapDocumentRow(t):void 0}getChunks(e){return this.db.prepare("SELECT * FROM document_chunks WHERE document_id = ? ORDER BY chunk_index ASC").all(e).map(s=>this.mapChunkRow(s))}listByUser(e){return this.db.prepare("SELECT * FROM documents WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapDocumentRow(s))}deleteDocument(e){this.db.transaction(()=>{let s=this.db.prepare("SELECT embedding_id FROM document_chunks WHERE document_id = ? AND embedding_id IS NOT NULL").all(e);if(s.length>0){let r=s.map(n=>n.embedding_id),o=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM embeddings WHERE id IN (${o})`).run(...r)}this.db.prepare("DELETE FROM document_chunks WHERE document_id = ?").run(e),this.db.prepare("DELETE FROM documents WHERE id = ?").run(e)})()}getChunksByEmbeddingIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT * FROM document_chunks WHERE embedding_id IN (${t}) ORDER BY chunk_index ASC`).all(...e).map(r=>this.mapChunkRow(r))}mapDocumentRow(e){return{id:e.id,userId:e.user_id,filename:e.filename,mimeType:e.mime_type,sizeBytes:e.size_bytes,chunkCount:e.chunk_count,createdAt:e.created_at}}mapChunkRow(e){return{id:e.id,documentId:e.document_id,chunkIndex:e.chunk_index,content:e.content,embeddingId:e.embedding_id||void 0,createdAt:e.created_at}}}});import{randomUUID as Yl}from"node:crypto";var ys,Ni=y(()=>{"use strict";ys=class{static{u(this,"TodoRepository")}db;constructor(e){this.db=e}add(e,t,s){let r=new Date().toISOString(),o=Yl(),n=s?.list??"default",i=s?.priority??"normal";return this.db.prepare("INSERT INTO todos (id, user_id, list, title, description, priority, due_date, completed, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?)").run(o,e,n,t,s?.description??null,i,s?.dueDate??null,r,r),{id:o,userId:e,list:n,title:t,description:s?.description,priority:i,dueDate:s?.dueDate,completed:!1,createdAt:r,updatedAt:r}}list(e,t,s=!1){let r="SELECT * FROM todos WHERE user_id = ?",o=[e];return t&&(r+=" AND list = ?",o.push(t)),s||(r+=" AND completed = 0"),r+=" ORDER BY CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'normal' THEN 2 WHEN 'low' THEN 3 END, created_at DESC",this.db.prepare(r).all(...o).map(i=>this.mapRow(i))}getById(e){let t=this.db.prepare("SELECT * FROM todos WHERE id = ?").get(e);return t?this.mapRow(t):void 0}complete(e){let t=new Date().toISOString();return this.db.prepare("UPDATE todos SET completed = 1, updated_at = ? WHERE id = ? AND completed = 0").run(t,e).changes>0}uncomplete(e){let t=new Date().toISOString();return this.db.prepare("UPDATE todos SET completed = 0, updated_at = ? WHERE id = ? AND completed = 1").run(t,e).changes>0}delete(e){return this.db.prepare("DELETE FROM todos WHERE id = ?").run(e).changes>0}clearCompleted(e,t){let s="DELETE FROM todos WHERE user_id = ? AND completed = 1",r=[e];return t&&(s+=" AND list = ?",r.push(t)),this.db.prepare(s).run(...r).changes}getLists(e){return this.db.prepare(`SELECT list,
316
+ SUM(CASE WHEN completed = 0 THEN 1 ELSE 0 END) as open,
317
+ SUM(CASE WHEN completed = 1 THEN 1 ELSE 0 END) as completed,
318
+ COUNT(*) as total
319
+ FROM todos WHERE user_id = ? GROUP BY list ORDER BY list`).all(e).map(s=>({list:s.list,open:Number(s.open),completed:Number(s.completed),total:Number(s.total)}))}mapRow(e){return{id:e.id,userId:e.user_id,list:e.list,title:e.title,description:e.description,priority:e.priority,dueDate:e.due_date,completed:e.completed===1,createdAt:e.created_at,updatedAt:e.updated_at}}}});var xo=y(()=>{"use strict";Ti();bi();_i();$i();vi();hr();Ro();Si();ki();Ai();Ii();Ri();xi();Li();Ni()});function Qe(c){if(Co[c])return Co[c];let e=Object.entries(Co).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var Co,Jl,_e,ft=y(()=>{"use strict";Co={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"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},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},mistral:{maxInputTokens:32e3,maxOutputTokens:4096},"mistral-small":{maxInputTokens:32e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"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-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"mistral-medium-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"mistral-small-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"codestral-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"magistral-medium-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"magistral-small-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"ministral-8b-latest":{maxInputTokens:128e3,maxOutputTokens:4096}},Jl={maxInputTokens:8192,maxOutputTokens:4096};u(Qe,"lookupContextWindow");_e=class{static{u(this,"LLMProvider")}config;contextWindow=Jl;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import Zl from"@anthropic-ai/sdk";var ws,Lo=y(()=>{"use strict";ft();ws=class extends _e{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Zl({apiKey:this.config.apiKey});let e=Qe(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},o=await this.client.messages.create(r);return this.mapResponse(o)}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 o of r)if(o.type==="content_block_delta")o.delta.type==="text_delta"?yield{type:"text_delta",text:o.delta.text}:o.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:o.delta.partial_json}});else if(o.type==="content_block_start")o.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:o.content_block.id,name:o.content_block.name}});else if(o.type==="message_stop"){let n=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(n)}}}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 Ql from"openai";var ge,et=y(()=>{"use strict";ft();ge=class extends _e{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Ql({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=Qe(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,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{}},o=await this.client.chat.completions.create(r);return this.mapResponse(o)}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,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{},stream:!0}),o,n,i="",a="",l=[],d=null,m=0,p=0;for await(let w of r){let T=w.choices[0];if(!T)continue;let g=T.delta;if(g?.content&&(a+=g.content,yield{type:"text_delta",text:g.content}),g?.tool_calls)for(let b of g.tool_calls)if(b.id){if(o){let $;try{$=JSON.parse(i||"{}")}catch{$={}}l.push({id:o,name:n,input:$})}o=b.id,n=b.function?.name,i=b.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:o,name:n}}}else b.function?.arguments&&(i+=b.function.arguments,yield{type:"tool_use_delta",toolCall:{input:b.function.arguments}});T.finish_reason&&(d=T.finish_reason),w.usage&&(m=w.usage.prompt_tokens,p=w.usage.completion_tokens)}if(o){let w;try{w=JSON.parse(i||"{}")}catch{w={}}l.push({id:o,name:n,input:w})}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}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 o=[],n=[],i=[];for(let a of r.content)switch(a.type){case"text":o.push({type:"text",text:a.text});break;case"image":o.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":n.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"&&n.length>0){let a=o.map(l=>l.text).join("");s.push({role:"assistant",content:a||null,tool_calls:n})}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 o.length>0&&(r.role==="user"?s.push({role:"user",content:o}):s.push({role:r.role,content:o.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??"",o=s?.tool_calls?.map(n=>({id:n.id,name:n.function.name,input:(()=>{try{return JSON.parse(n.function.arguments)}catch{return{}}})()}));return{content:r,toolCalls:o&&o.length>0?o: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 Ts,No=y(()=>{"use strict";et();Ts=class extends ge{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 Es,Mo=y(()=>{"use strict";ft();Es=class extends _e{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=Qe(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(n=>n.includes("context_length")||n==="num_ctx"),o=r?Number(s[r]):0;o>0&&(this.contextWindow={maxInputTokens:o,maxOutputTokens:Math.min(o,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 o=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!o.ok){let i=await o.text();throw new Error(`Ollama API error (${o.status}): ${i}`)}let n=await o.json();return this.mapResponse(n)}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 o=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!o.ok){let w=await o.text();throw new Error(`Ollama API error (${o.status}): ${w}`)}if(!o.body)throw new Error("Ollama streaming response has no body");let n=o.body.getReader(),i=new TextDecoder,a="",l="",d=0,m=0,p=[];try{for(;;){let{done:w,value:T}=await n.read();if(w)break;a+=i.decode(T,{stream:!0});let g=a.split(`
320
+ `);a=g.pop()??"";for(let b of g){let $=b.trim();if(!$)continue;let A;try{A=JSON.parse($)}catch{continue}if(A.message?.content&&(l+=A.message.content,yield{type:"text_delta",text:A.message.content}),A.message?.tool_calls)for(let R of A.message.tool_calls){let O={id:`ollama_tool_${p.length}`,name:R.function.name,input:R.function.arguments};p.push(O),yield{type:"tool_use_start",toolCall:{id:O.id,name:O.name}},yield{type:"tool_use_delta",toolCall:{input:O.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 w;try{w=JSON.parse(a.trim())}catch{return}if(w.message?.content&&(l+=w.message.content,yield{type:"text_delta",text:w.message.content}),w.message?.tool_calls)for(let T of w.message.tool_calls){let g={id:`ollama_tool_${p.length}`,name:T.function.name,input:T.function.arguments};p.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}},yield{type:"tool_use_delta",toolCall:{input:g.input}}}w.done&&(d=w.prompt_eval_count??0,m=w.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{n.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 n of t)switch(n.type){case"text":s.push(n.text);break;case"image":r.push(n.source.data);break;case"tool_use":s.push(`[Tool call: ${n.name}(${JSON.stringify(n.input)})]`);break;case"tool_result":s.push(`[Tool result for ${n.tool_use_id}]: ${n.content}`);break}let o={role:e,content:s.join(`
321
+ `)};return r.length>0&&(o.images=r),o}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 bs,Do=y(()=>{"use strict";et();bs=class extends ge{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}}});var _s,Oo=y(()=>{"use strict";et();_s=class extends ge{static{u(this,"GoogleProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://generativelanguage.googleapis.com/v1beta/openai/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var $s,Uo=y(()=>{"use strict";et();$s=class extends ge{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 Po(c){switch(c.provider){case"anthropic":return new ws(c);case"openai":return new ge(c);case"openrouter":return new Ts(c);case"ollama":return new Es(c);case"openwebui":return new bs(c);case"google":return new _s(c);case"mistral":return new $s(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var Fo=y(()=>{"use strict";Lo();et();No();Mo();Do();Oo();Uo();u(Po,"createLLMProvider")});function jo(c){return new gr(c)}var ed,gr,Mi=y(()=>{"use strict";ft();Fo();ed=["default","strong","fast","embeddings","local"],gr=class extends _e{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of ed){let t=this.multiConfig[e];if(t){let s=Po(t);await s.initialize(),this.providers.set(e,s)}}}resolve(e){return e&&this.providers.has(e)?this.providers.get(e):this.providers.get("default")}async complete(e){return this.resolve(e.tier).complete(e)}async*stream(e){yield*this.resolve(e.tier).stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve()).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve()).supportsEmbeddings()}isAvailable(){return this.resolve().isAvailable()}getContextWindow(){return this.resolve().getContextWindow()}};u(jo,"createModelRouter")});function $e(c){return Math.ceil(c.length/3.5)}function Ss(c){if(typeof c.content=="string")return $e(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=$e(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=$e(t.name)+$e(JSON.stringify(t.input));break;case"tool_result":e+=$e(t.content);break}return e}var vs,Di=y(()=>{"use strict";u($e,"estimateTokens");u(Ss,"estimateMessageTokens");vs=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:o}=e,n=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 ${n} (home: ${i}).
299
322
 
300
323
  ## Core principles
301
324
  - **When the user's intent is clear**, ACT immediately using your tools. Don't explain what you'll do \u2014 just do it.
@@ -320,16 +343,16 @@ For complex tasks, work through multiple steps:
320
343
  5. **Summarize** the final result clearly.
321
344
 
322
345
  ## Environment
323
- - OS: ${o}
346
+ - OS: ${n}
324
347
  - Home: ${i}
325
348
  - Documents: ${i}/Documents
326
349
  - Desktop: ${i}/Desktop
327
- - Downloads: ${i}/Downloads`,l=Intl.DateTimeFormat().resolvedOptions().timeZone,d=r?.timezone||l,m=new Date,h=m.toLocaleTimeString("en-GB",{timeZone:d,hour:"2-digit",minute:"2-digit"}),w=m.toLocaleDateString("en-CA",{timeZone:d}),y=m.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
350
+ - Downloads: ${i}/Downloads`,l=Intl.DateTimeFormat().resolvedOptions().timeZone,d=r?.timezone||l,m=new Date,p=m.toLocaleTimeString("en-GB",{timeZone:d,hour:"2-digit",minute:"2-digit"}),w=m.toLocaleDateString("en-CA",{timeZone:d}),T=m.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
328
351
 
329
352
  ## Current date & time`,a+=`
330
353
  - Timezone: ${d}`,a+=`
331
- - Date: ${w} (${y})`,a+=`
332
- - Time: ${h}`,r?.timezone&&r.timezone!==l&&(a+=`
354
+ - Date: ${w} (${T})`,a+=`
355
+ - Time: ${p}`,r?.timezone&&r.timezone!==l&&(a+=`
333
356
  - Server timezone: ${l}`),s&&s.length>0){a+=`
334
357
 
335
358
  ## Available tools
@@ -340,117 +363,117 @@ For complex tasks, work through multiple steps:
340
363
  - Name: ${r.displayName}`),r.timezone&&(a+=`
341
364
  - Timezone: ${r.timezone}`),r.language&&(a+=`
342
365
  - Language: ${r.language}`),r.bio&&(a+=`
343
- - Bio: ${r.bio}`)),n&&n.length>0){a+=`
366
+ - Bio: ${r.bio}`)),o&&o.length>0){a+=`
344
367
 
345
- ## Today's events`;for(let g of n){let _=g.allDay?"All day":g.start.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}}),v=g.allDay?"":`-${g.end.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}})}`,R=g.location?` @ ${g.location}`:"";a+=`
346
- - ${_}${v}: ${g.title}${R}`}}if(t&&t.length>0){if(a+=`
368
+ ## Today's events`;for(let g of o){let b=g.allDay?"All day":g.start.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}}),$=g.allDay?"":`-${g.end.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}})}`,A=g.location?` @ ${g.location}`:"";a+=`
369
+ - ${b}${$}: ${g.title}${A}`}}if(t&&t.length>0){if(a+=`
347
370
 
348
371
  ## Memories about this user
349
- `,t.some(_=>_.type&&_.type!=="general")){let _=new Map;for(let R of t){let x=R.type||"general",O=_.get(x);O||(O=[],_.set(x,O)),O.push(R)}let v={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[R,x]of _){a+=`
350
- ### ${v[R]||R}
351
- `;for(let O of x)a+=`- ${O.key}: ${O.value}
352
- `}}else for(let _ of t)a+=`- [${_.category}] ${_.key}: ${_.value}
372
+ `,t.some(b=>b.type&&b.type!=="general")){let b=new Map;for(let A of t){let R=A.type||"general",O=b.get(R);O||(O=[],b.set(R,O)),O.push(A)}let $={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[A,R]of b){a+=`
373
+ ### ${$[A]||A}
374
+ `;for(let O of R)a+=`- ${O.key}: ${O.value}
375
+ `}}else for(let b of t)a+=`- [${b.category}] ${b.key}: ${b.value}
353
376
  `;a+=`
354
377
  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+=`
355
378
 
356
- 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 Tn=b(()=>{"use strict";it();un();Ve();mn();pn();hn();fn();gn();wn();ri();ni()});var gs,_n=b(()=>{"use strict";gs=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 ys,oi=b(()=>{"use strict";_n();ys=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new gs;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 ii,ai,ci,Ke,li=b(()=>{"use strict";ii=["allow","deny"],ai=["global","user","conversation","platform"],ci=["read","write","destructive","admin"],Ke=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"||!ii.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${ii.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"||!ai.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${ai.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(!ci.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${ci.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 nl from"node:crypto";var ws,di=b(()=>{"use strict";ws=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:nl.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 sr=b(()=>{"use strict";oi();_n();li();di()});var I,P=b(()=>{"use strict";I=class{static{u(this,"Skill")}}});var at,ui=b(()=>{"use strict";at=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 ct,mi=b(()=>{"use strict";ct=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,h=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),w=u(y=>{a||(a=!0,h(),i(y))},"finish");e.execute(t,s).then(y=>{this.logger.info({skill:r,success:y.success},"Skill execution completed"),w(y)},y=>{let g=y instanceof Error?y.message:String(y);this.logger.error({skill:r,error:g},"Skill execution failed"),w({success:!1,error:g})}),m=setTimeout(()=>{if(a)return;let y=o.getIdleMs();if(y>=12e4){let _=o.getSnapshot();this.logger.warn({skill:r,idleMs:y,state:_.state,iteration:_.iteration},"Agent inactive after initial timeout \u2014 aborting"),w({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(y/1e3)}s (last state: ${_.state})`});return}let g=o.getSnapshot();this.logger.info({skill:r,idleMs:y,state:g.state,iteration:g.iteration,totalMs:g.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){h();return}let _=o.getIdleMs(),v=o.getSnapshot();_>=12e4?(this.logger.warn({skill:r,idleMs:_,state:v.state,iteration:v.iteration,totalMs:v.totalElapsedMs},"Agent went inactive \u2014 aborting"),w({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(_/1e3)}s (last state: ${v.state})`})):this.logger.debug({skill:r,idleMs:_,state:v.state,iteration:v.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let y=o.getSnapshot();this.logger.error({skill:r,totalMs:y.totalElapsedMs,state:y.state,iteration:y.iteration},"Absolute time limit reached \u2014 force killing agent"),w({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},"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 Ge,En=b(()=>{"use strict";Ge=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 ol from"node:fs";import $n from"node:path";var rr,pi=b(()=>{"use strict";P();rr=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=$n.resolve(e),s;try{s=await ol.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=$n.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=$n.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 il,al,lt,hi=b(()=>{"use strict";P();il=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,al=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,lt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",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(!al.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(il,"");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 dt,fi=b(()=>{"use strict";P();dt=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",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 ut,gi=b(()=>{"use strict";P();ut=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",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}**
379
+ 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 o=r,n=[];for(let i of o)i.type==="tool_result"&&n.push(i);return n.length>0?{role:"user",content:n}:{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,o=new Set,n=[];for(let a of e){if(!Array.isArray(a.content)){n.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)||o.has(d.tool_use_id)?!1:(o.add(d.tool_use_id),!0):!0);l.length!==0&&n.push({...a,content:l})}let i=[];for(let a of n){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 Bo=y(()=>{"use strict";ft();Lo();et();No();Mo();Do();Oo();Uo();Fo();Mi();Di()});var ks,qo=y(()=>{"use strict";ks=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,o=this.buckets.get(e);if(!o)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>o.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let n=Math.max(0,t.maxInvocations-o.count);return{allowed:o.count<t.maxInvocations,remaining:n,resetsAt:o.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,o=this.buckets.get(e);!o||s>o.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):o.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 As,Oi=y(()=>{"use strict";qo();As=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new ks;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 Ui,Pi,Fi,tt,ji=y(()=>{"use strict";Ui=["allow","deny"],Pi=["global","user","conversation","platform"],Fi=["read","write","destructive","admin"],tt=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"||!Ui.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${Ui.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"||!Pi.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Pi.join(", ")}`);if(!Array.isArray(s.actions)||s.actions.length===0)throw new Error(`Rule "${s.id}" is missing a valid "actions" array`);for(let o of s.actions)if(typeof o!="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 o of s.riskLevels)if(!Fi.includes(o))throw new Error(`Rule "${s.id}" has invalid risk level "${o}": expected one of ${Fi.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 o=s.rateLimit;if(typeof o.maxInvocations!="number"||typeof o.windowSeconds!="number")throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected maxInvocations and windowSeconds numbers`);r.rateLimit=s.rateLimit}return r}}});import td from"node:crypto";var Is,Bi=y(()=>{"use strict";Is=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:td.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 yr=y(()=>{"use strict";Oi();qo();ji();Bi()});var I,j=y(()=>{"use strict";I=class{static{u(this,"Skill")}}});var ht,qi=y(()=>{"use strict";ht=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 gt,Hi=y(()=>{"use strict";gt=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,o){r=r??e.metadata.timeoutMs??3e4;let{name:n}=e.metadata;return this.logger.info({skill:n,input:t},"Skill execution started"),o?this.executeWithTracker(e,t,s,n,r,o):this.executeWithHardTimeout(e,t,s,n,r)}async executeWithTracker(e,t,s,r,o,n){return new Promise(i=>{let a=!1,l,d,m,p=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),w=u(T=>{a||(a=!0,p(),i(T))},"finish");e.execute(t,s).then(T=>{this.logger.info({skill:r,success:T.success},"Skill execution completed"),w(T)},T=>{let g=T instanceof Error?T.message:String(T);this.logger.error({skill:r,error:g},"Skill execution failed"),w({success:!1,error:g})}),m=setTimeout(()=>{if(a)return;let T=n.getIdleMs();if(T>=12e4){let b=n.getSnapshot();this.logger.warn({skill:r,idleMs:T,state:b.state,iteration:b.iteration},"Agent inactive after initial timeout \u2014 aborting"),w({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${b.state})`});return}let g=n.getSnapshot();this.logger.info({skill:r,idleMs:T,state:g.state,iteration:g.iteration,totalMs:g.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){p();return}let b=n.getIdleMs(),$=n.getSnapshot();b>=12e4?(this.logger.warn({skill:r,idleMs:b,state:$.state,iteration:$.iteration,totalMs:$.totalElapsedMs},"Agent went inactive \u2014 aborting"),w({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(b/1e3)}s (last state: ${$.state})`})):this.logger.debug({skill:r,idleMs:b,state:$.state,iteration:$.iteration},"Agent still active, continuing...")},1e4)},o),d=setTimeout(()=>{if(a)return;let T=n.getSnapshot();this.logger.error({skill:r,totalMs:T.totalElapsedMs,state:T.state,iteration:T.iteration},"Absolute time limit reached \u2014 force killing agent"),w({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,o){try{let n=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${o}ms`)),o)})]);return this.logger.info({skill:r,success:n.success},"Skill execution completed"),n}catch(n){let i=n instanceof Error?n.message:String(n);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var st,Ho=y(()=>{"use strict";st=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 sd from"node:fs";import zo from"node:path";var wr,zi=y(()=>{"use strict";j();wr=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=zo.resolve(e),s;try{s=await sd.promises.readdir(t)}catch(n){let i=n instanceof Error?n.message:String(n);return console.warn(`PluginLoader: failed to read directory "${t}": ${i}`),[]}let r=s.filter(n=>n.endsWith(".js")),o=[];for(let n of r){let i=zo.join(t,n);try{let a=await this.loadFromFile(i);o.push(a)}catch(a){let l=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${l}`)}}return o}async loadFromFile(e){let t=zo.resolve(e),o=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof o!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let n=new o;if(!(n instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(n,t),n}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 rd,od,yt,Vi=y(()=>{"use strict";j();rd=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,od=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,yt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",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(!od.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let o=r.replace(rd,"");if(/[a-zA-Z]/.test(o))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 wt,Wi=y(()=>{"use strict";j();wt=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",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),o={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:o,display:`Uptime: ${o.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 Tt,Xi=y(()=>{"use strict";j();Tt=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",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 n;switch(this.config.provider){case"brave":n=await this.searchBrave(s,r);break;case"searxng":n=await this.searchSearXNG(s,r);break;case"tavily":n=await this.searchTavily(s,r);break;case"duckduckgo":n=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(n.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=n.map((a,l)=>`${l+1}. **${a.title}**
357
380
  ${a.url}
358
381
  ${a.snippet}`).join(`
359
382
 
360
- `);return{success:!0,data:{query:s,results:o},display:`Search results for "${s}":
383
+ `);return{success:!0,data:{query:s,results:n},display:`Search results for "${s}":
361
384
 
362
- ${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 mt,yi=b(()=>{"use strict";P();mt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(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(this.effectiveUserId(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 w=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||w.setHours(e,t,0,0),w}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 w=i.formatToParts(n),y=parseInt(w.find(B=>B.type==="year").value,10),g=parseInt(w.find(B=>B.type==="month").value,10)-1,_=parseInt(w.find(B=>B.type==="day").value,10),v=new Date(Date.UTC(y,g,_,e,t,0)),R=i.formatToParts(v),x=parseInt(R.find(B=>B.type==="hour").value,10),O=parseInt(R.find(B=>B.type==="minute").value,10),N=(e-x)*60+(t-O);return v=new Date(v.getTime()+N*6e4),v}let a=o,l=i.formatToParts(a),d=parseInt(l.find(w=>w.type==="hour").value,10),m=parseInt(l.find(w=>w.type==="minute").value,10),h=(e-d)*60+(t-m);return a=new Date(a.getTime()+h*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:
385
+ ${i}`}}catch(n){return{success:!1,error:`Search failed: ${n instanceof Error?n.message:String(n)}`}}}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(n=>({title:n.title,url:n.url,snippet:n.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 o=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!o.ok)throw new Error(`SearXNG returned ${o.status}: ${o.statusText}`);return((await o.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(o=>({title:o.title,url:o.url,snippet:o.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 o=await r.text();return this.parseDuckDuckGoHtml(o,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,o=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,n=[],i;for(;(i=r.exec(e))!==null;){let l=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(l);d&&m&&n.push({url:m,title:d})}let a=[];for(;(i=o.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let l=0;l<Math.min(n.length,t);l++)s.push({title:n[l].title,url:n[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 Et,Gi=y(()=>{"use strict";j();Et=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let o of this.reminderRepo.getByUser(r))t.has(o.id)||(t.add(o.id),s.push(o));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,o=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let n;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.`};n=m}else if(o!==void 0&&typeof o=="number"&&o>0)n=new Date(Date.now()+o*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(this.effectiveUserId(t),t.platform,t.chatId,s,n),a=n.getTime()-Date.now(),l=Math.round(a/6e4),d=n.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 n=parseInt(r[1],10),i=parseInt(r[2],10);return n>23||i>59?void 0:this.buildDateInTimezone(n,i,void 0,t)}let o=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(o){let n=parseInt(o[1],10),i=parseInt(o[2],10)-1,a=parseInt(o[3],10),l=parseInt(o[4],10),d=parseInt(o[5],10);return l>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(l,d,{year:n,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let w=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||w.setHours(e,t,0,0),w}let o=new Date,n=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(o.getFullYear(),o.getMonth(),o.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 w=i.formatToParts(o),T=parseInt(w.find(K=>K.type==="year").value,10),g=parseInt(w.find(K=>K.type==="month").value,10)-1,b=parseInt(w.find(K=>K.type==="day").value,10),$=new Date(Date.UTC(T,g,b,e,t,0)),A=i.formatToParts($),R=parseInt(A.find(K=>K.type==="hour").value,10),O=parseInt(A.find(K=>K.type==="minute").value,10),N=(e-R)*60+(t-O);return $=new Date($.getTime()+N*6e4),$}let a=n,l=i.formatToParts(a),d=parseInt(l.find(w=>w.type==="hour").value,10),m=parseInt(l.find(w=>w.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:
363
386
  ${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).join(`
364
- `)}`}}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 pt,wi=b(()=>{"use strict";P();pt=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}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(this.effectiveUserId(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 this.allUserIds(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)
365
- ${n.content.slice(0,100)}${n.content.length>100?"\u2026":""}`).join(`
387
+ `)}`}}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 bt,Ki=y(()=>{"use strict";j();bt=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}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 o=this.noteRepo.save(this.effectiveUserId(t),s,r);return{success:!0,data:{noteId:o.id,title:o.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let o of this.allUserIds(e))for(let n of this.noteRepo.list(o))t.has(n.id)||(t.add(n.id),s.push(n));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(o=>`- **${o.title}** (${o.id.slice(0,8)}\u2026)
388
+ ${o.content.slice(0,100)}${o.content.length>100?"\u2026":""}`).join(`
366
389
  `);return{success:!0,data:s,display:`${s.length} note(s):
367
- ${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 this.allUserIds(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)
390
+ ${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,o=[];for(let i of this.allUserIds(t))for(let a of this.noteRepo.search(i,s))r.has(a.id)||(r.add(a.id),o.push(a));if(o.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let n=o.map(i=>`- **${i.title}** (${i.id.slice(0,8)}\u2026)
368
391
  ${i.content.slice(0,100)}${i.content.length>100?"\u2026":""}`).join(`
369
- `);return{success:!0,data:n,display:`Found ${n.length} note(s):
370
- ${o}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var cl,ht,bi=b(()=>{"use strict";P();cl={0:"Clear sky",1:"Mainly clear",2:"Partly cloudy",3:"Overcast",45:"Foggy",48:"Depositing rime fog",51:"Light drizzle",53:"Moderate drizzle",55:"Dense drizzle",61:"Slight rain",63:"Moderate rain",65:"Heavy rain",71:"Slight snow",73:"Moderate snow",75:"Heavy snow",77:"Snow grains",80:"Slight rain showers",81:"Moderate rain showers",82:"Violent rain showers",85:"Slight snow showers",86:"Heavy snow showers",95:"Thunderstorm",96:"Thunderstorm with slight hail",99:"Thunderstorm with heavy hail"},ht=class extends I{static{u(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let n=await this.fetchWeather(r.latitude,r.longitude),o=cl[n.weathercode]??`Code ${n.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:n.temperature,unit:"\xB0C",condition:o,windSpeed:n.windspeed,windDirection:n.winddirection,isDay:n.is_day===1},l=`${i}: ${n.temperature}\xB0C, ${o}
371
- Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:l}}catch(r){return{success:!1,error:`Weather fetch failed: ${r instanceof Error?r.message:String(r)}`}}}async geocode(e){let t=`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(e)}&count=1&language=en&format=json`,s=await fetch(t);if(!s.ok)throw new Error(`Geocoding API returned ${s.status}`);return(await s.json()).results?.[0]}async fetchWeather(e,t){let s=`https://api.open-meteo.com/v1/forecast?latitude=${e}&longitude=${t}&current_weather=true&timezone=auto`,r=await fetch(s);if(!r.ok)throw new Error(`Weather API returned ${r.status}`);return(await r.json()).current_weather}}});import{exec as ll}from"node:child_process";function _i(c){return c.length>Ti?c.slice(0,Ti)+`
372
- [output truncated]`:c}var dl,Ti,ft,Ei=b(()=>{"use strict";P();dl=3e4,Ti=1e4;u(_i,"truncate");ft=class extends I{static{u(this,"ShellSkill")}metadata={name:"shell",description:"Execute shell commands on the host system. Use this for ANY task involving files, folders, system operations, or running programs: ls, cat, find, file, du, mkdir, cp, mv, grep, etc. When the user asks about their documents, files, or anything on disk \u2014 use this tool.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds (default: 30000)"},cwd:{type:"string",description:"Working directory for the command"}},required:["command"]}};async execute(e,t){let s=e.command;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "command"'};let r=[/\brm\s+-rf\s+\/(?:\s|$)/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r)[a-zA-Z]*\s+\/(?:\s|$)/,/\brm\s+-rf\s+\/\*/,/:(){ :|:& };:/,/:\(\)\s*\{.*\|.*&\s*\}\s*;/,/>\s*\/dev\/sd[a-z]/,/\bmkfs\b/,/\bdd\s+.*\bif=/,/\bchmod\s+777\b/,/\bcurl\b.*\|\s*\bbash\b/,/\bwget\b.*\|\s*\bsh\b/,/\bpython[23]?\s+-c\b/,/\bnode\s+-e\b/,/\b(bash|sh)\s+-i\b.*\/dev\/tcp/,/\bnc\s+.*-e\b/];for(let i of r)if(i.test(s))return{success:!1,error:"Command blocked: potentially destructive system operation"};let n=typeof e.timeout=="number"&&e.timeout>0?e.timeout:dl,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:l}=await this.run(s,n,o),d=[];return i&&d.push(`stdout:
373
- ${_i(i)}`),a&&d.push(`stderr:
374
- ${_i(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(`
375
-
376
- `),...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=>{ll(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 gt,$i=b(()=>{"use strict";P();gt=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...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(this.effectiveUserId(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(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 this.allUserIds(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 this.allUserIds(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):
377
- ${n.map(o=>`- ${o.key}: "${o.value}"`).join(`
378
- `)}`}}listMemories(e,t){let s=e.category,r=new Set,n=[];for(let i of this.allUserIds(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}:
379
- ${n.map(i=>`- [${i.category}] ${i.key}: "${i.value}"`).join(`
380
- `)}`}}deleteMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for delete action'};let r=!1;for(let n of this.allUserIds(t))if(this.memoryRepo.delete(n,s)){r=!0;break}return{success:!0,data:{key:s,deleted:r},display:r?`Memory "${s}" deleted.`:`No memory found for key "${s}".`}}async semanticSearchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for semantic_search action'};if(!this.embeddingService)return this.searchMemories(e,t);let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of await this.embeddingService.semanticSearch(o,s,10))r.has(i.key)||(r.add(i.key),n.push(i));return n.length===0?this.searchMemories(e,t):{success:!0,data:n,display:`Found ${n.length} semantically related memory(ies):
381
- ${n.map(o=>`- ${o.key}: "${o.value}" (score: ${o.score.toFixed(2)})`).join(`
382
- `)}`}}}});var ul,ml,pl,yt,vi=b(()=>{"use strict";P();En();ul=5,ml=15,pl=12e4,yt=class extends I{static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",description:'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',riskLevel:"write",version:"3.0.0",timeoutMs:pl,inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to delegate to the sub-agent. Be specific about what you want."},context:{type:"string",description:"Additional context the sub-agent needs (optional)"},max_iterations:{type:"number",description:"Max tool iterations (1-15). Use higher values for complex multi-step tasks. Default: 5."}},required:["task"]}};onProgress;constructor(e,t,s,r){super(),this.llm=e,this.skillRegistry=t,this.skillSandbox=s,this.securityManager=r}setProgressCallback(e){this.onProgress=e}createTracker(){return new Ge(this.onProgress)}async execute(e,t){let s=e.task,r=e.context;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task"'};let n=e.max_iterations,o=n?Math.max(1,Math.min(ml,Math.round(n))):ul,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new Ge(i);a.ping("starting",{maxIterations:o});let l=this.buildSubAgentTools(),d="You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.",m=s;r&&typeof r=="string"&&(m=`${s}
383
-
384
- Additional context: ${r}`);let h=[{role:"user",content:m}];try{let w=0,y=0,g=0;for(;;){a.ping("llm_call",{iteration:w,maxIterations:o});let _=await this.llm.complete({messages:h,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(y+=_.usage.inputTokens,g+=_.usage.outputTokens,a.ping("processing",{iteration:w,maxIterations:o}),!_.toolCalls||_.toolCalls.length===0||w>=o)return a.ping("done",{iteration:w,maxIterations:o}),{success:!0,data:{response:_.content,iterations:w,usage:{inputTokens:y,outputTokens:g}},display:_.content};w++;let v=[];_.content&&v.push({type:"text",text:_.content});for(let x of _.toolCalls)v.push({type:"tool_use",id:x.id,name:x.name,input:x.input});h.push({role:"assistant",content:v});let R=[];for(let x of _.toolCalls){a.ping("tool_call",{iteration:w,maxIterations:o,tool:x.name});let O=await this.executeSubAgentTool(x,t);R.push({type:"tool_result",tool_use_id:x.id,content:O.content,is_error:O.isError})}h.push({role:"user",content:R})}}catch(w){return{success:!1,error:`Sub-agent failed: ${w instanceof Error?w.message:String(w)}`}}}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 xe,nr=b(()=>{"use strict";xe=class{static{u(this,"EmailProvider")}}});var Si={};oe(Si,{MicrosoftGraphEmailProvider:()=>or});var or,vn=b(()=>{"use strict";nr();or=class extends xe{static{u(this,"MicrosoftGraphEmailProvider")}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/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)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=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 n.status===204?void 0:n.json()}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);if(r.status!==204)return r.json()}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=new URLSearchParams({$search:`"${e}"`,$top:String(Math.min(Math.max(1,t),50)),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/messages?${s}`)).value??[]).map(n=>this.mapMessage(n))}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 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`)}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,`
392
+ `);return{success:!0,data:o,display:`Found ${o.length} note(s):
393
+ ${n}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var nd,_t,Yi=y(()=>{"use strict";j();nd={0:"Clear sky",1:"Mainly clear",2:"Partly cloudy",3:"Overcast",45:"Foggy",48:"Depositing rime fog",51:"Light drizzle",53:"Moderate drizzle",55:"Dense drizzle",61:"Slight rain",63:"Moderate rain",65:"Heavy rain",71:"Slight snow",73:"Moderate snow",75:"Heavy snow",77:"Snow grains",80:"Slight rain showers",81:"Moderate rain showers",82:"Violent rain showers",85:"Slight snow showers",86:"Heavy snow showers",95:"Thunderstorm",96:"Thunderstorm with slight hail",99:"Thunderstorm with heavy hail"},_t=class extends I{static{u(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let o=await this.fetchWeather(r.latitude,r.longitude),n=nd[o.weathercode]??`Code ${o.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:o.temperature,unit:"\xB0C",condition:n,windSpeed:o.windspeed,windDirection:o.winddirection,isDay:o.is_day===1},l=`${i}: ${o.temperature}\xB0C, ${n}
394
+ Wind: ${o.windspeed} km/h`;return{success:!0,data:a,display:l}}catch(r){return{success:!1,error:`Weather fetch failed: ${r instanceof Error?r.message:String(r)}`}}}async geocode(e){let t=`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(e)}&count=1&language=en&format=json`,s=await fetch(t);if(!s.ok)throw new Error(`Geocoding API returned ${s.status}`);return(await s.json()).results?.[0]}async fetchWeather(e,t){let s=`https://api.open-meteo.com/v1/forecast?latitude=${e}&longitude=${t}&current_weather=true&timezone=auto`,r=await fetch(s);if(!r.ok)throw new Error(`Weather API returned ${r.status}`);return(await r.json()).current_weather}}});import{exec as id}from"node:child_process";function Zi(c){return c.length>Ji?c.slice(0,Ji)+`
395
+ [output truncated]`:c}var ad,Ji,$t,Qi=y(()=>{"use strict";j();ad=3e4,Ji=1e4;u(Zi,"truncate");$t=class extends I{static{u(this,"ShellSkill")}metadata={name:"shell",description:"Execute shell commands on the host system. Use this for ANY task involving files, folders, system operations, or running programs: ls, cat, find, file, du, mkdir, cp, mv, grep, etc. When the user asks about their documents, files, or anything on disk \u2014 use this tool.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds (default: 30000)"},cwd:{type:"string",description:"Working directory for the command"}},required:["command"]}};async execute(e,t){let s=e.command;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "command"'};let r=[/\brm\s+-rf\s+\/(?:\s|$)/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r)[a-zA-Z]*\s+\/(?:\s|$)/,/\brm\s+-rf\s+\/\*/,/:(){ :|:& };:/,/:\(\)\s*\{.*\|.*&\s*\}\s*;/,/>\s*\/dev\/sd[a-z]/,/\bmkfs\b/,/\bdd\s+.*\bif=/,/\bchmod\s+777\b/,/\bcurl\b.*\|\s*\bbash\b/,/\bwget\b.*\|\s*\bsh\b/,/\bpython[23]?\s+-c\b/,/\bnode\s+-e\b/,/\b(bash|sh)\s+-i\b.*\/dev\/tcp/,/\bnc\s+.*-e\b/];for(let i of r)if(i.test(s))return{success:!1,error:"Command blocked: potentially destructive system operation"};let o=typeof e.timeout=="number"&&e.timeout>0?e.timeout:ad,n=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:l}=await this.run(s,o,n),d=[];return i&&d.push(`stdout:
396
+ ${Zi(i)}`),a&&d.push(`stderr:
397
+ ${Zi(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(`
398
+
399
+ `),...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=>{id(e,{timeout:t,cwd:s},(o,n,i)=>{let a=o&&"code"in o&&typeof o.code=="number"?o.code:o?1:0;r({stdout:typeof n=="string"?n:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var vt,ea=y(()=>{"use strict";j();vt=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...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,o=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 n=this.memoryRepo.save(this.effectiveUserId(t),s,r,o??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:n,display:`Remembered "${s}" = "${r}" (category: ${n.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 o of this.allUserIds(t))if(r=this.memoryRepo.recall(o,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,o=[];for(let n of this.allUserIds(t))for(let i of this.memoryRepo.search(n,s))r.has(i.id)||(r.add(i.id),o.push(i));return{success:!0,data:o,display:o.length===0?`No memories matching "${s}".`:`Found ${o.length} memory(ies):
400
+ ${o.map(n=>`- ${n.key}: "${n.value}"`).join(`
401
+ `)}`}}listMemories(e,t){let s=e.category,r=new Set,o=[];for(let i of this.allUserIds(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),o.push(l))}let n=s?`in category "${s}"`:"total";return{success:!0,data:o,display:o.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${o.length} memory(ies) ${n}:
402
+ ${o.map(i=>`- [${i.category}] ${i.key}: "${i.value}"`).join(`
403
+ `)}`}}deleteMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for delete action'};let r=!1;for(let o of this.allUserIds(t))if(this.memoryRepo.delete(o,s)){r=!0;break}return{success:!0,data:{key:s,deleted:r},display:r?`Memory "${s}" deleted.`:`No memory found for key "${s}".`}}async semanticSearchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for semantic_search action'};if(!this.embeddingService)return this.searchMemories(e,t);let r=new Set,o=[];for(let n of this.allUserIds(t))for(let i of await this.embeddingService.semanticSearch(n,s,10))r.has(i.key)||(r.add(i.key),o.push(i));return o.length===0?this.searchMemories(e,t):{success:!0,data:o,display:`Found ${o.length} semantically related memory(ies):
404
+ ${o.map(n=>`- ${n.key}: "${n.value}" (score: ${n.score.toFixed(2)})`).join(`
405
+ `)}`}}}});var cd,ld,dd,St,ta=y(()=>{"use strict";j();Ho();cd=5,ld=15,dd=12e4,St=class extends I{static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",description:'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',riskLevel:"write",version:"3.0.0",timeoutMs:dd,inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to delegate to the sub-agent. Be specific about what you want."},context:{type:"string",description:"Additional context the sub-agent needs (optional)"},max_iterations:{type:"number",description:"Max tool iterations (1-15). Use higher values for complex multi-step tasks. Default: 5."}},required:["task"]}};onProgress;constructor(e,t,s,r){super(),this.llm=e,this.skillRegistry=t,this.skillSandbox=s,this.securityManager=r}setProgressCallback(e){this.onProgress=e}createTracker(){return new st(this.onProgress)}async execute(e,t){let s=e.task,r=e.context;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task"'};let o=e.max_iterations,n=o?Math.max(1,Math.min(ld,Math.round(o))):cd,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new st(i);a.ping("starting",{maxIterations:n});let l=this.buildSubAgentTools(),d="You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.",m=s;r&&typeof r=="string"&&(m=`${s}
406
+
407
+ Additional context: ${r}`);let p=[{role:"user",content:m}];try{let w=0,T=0,g=0;for(;;){a.ping("llm_call",{iteration:w,maxIterations:n});let b=await this.llm.complete({messages:p,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(T+=b.usage.inputTokens,g+=b.usage.outputTokens,a.ping("processing",{iteration:w,maxIterations:n}),!b.toolCalls||b.toolCalls.length===0||w>=n)return a.ping("done",{iteration:w,maxIterations:n}),{success:!0,data:{response:b.content,iterations:w,usage:{inputTokens:T,outputTokens:g}},display:b.content};w++;let $=[];b.content&&$.push({type:"text",text:b.content});for(let R of b.toolCalls)$.push({type:"tool_use",id:R.id,name:R.name,input:R.input});p.push({role:"assistant",content:$});let A=[];for(let R of b.toolCalls){a.ping("tool_call",{iteration:w,maxIterations:n,tool:R.name});let O=await this.executeSubAgentTool(R,t);A.push({type:"tool_result",tool_use_id:R.id,content:O.content,is_error:O.isError})}p.push({role:"user",content:A})}}catch(w){return{success:!1,error:`Sub-agent failed: ${w instanceof Error?w.message:String(w)}`}}}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 Le,Tr=y(()=>{"use strict";Le=class{static{u(this,"EmailProvider")}}});var sa={};re(sa,{MicrosoftGraphEmailProvider:()=>Er});var Er,Vo=y(()=>{"use strict";Tr();Er=class extends Le{static{u(this,"MicrosoftGraphEmailProvider")}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/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)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=u(o=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let o=await s(this.accessToken);if(!o.ok)throw new Error(`Graph API error: ${o.status}`);return o.status===204?void 0:o.json()}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);if(r.status!==204)return r.json()}async graphRequestRaw(e){let t=u(o=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${o}`}}),"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(n=>({id:n.id,name:n.name,contentType:n.contentType,size:n.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(o=>this.formatGraphAddress(o)),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(o=>this.formatGraphAddress(o)),bcc:s.bccRecipients?.map(o=>this.formatGraphAddress(o)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=new URLSearchParams({$search:`"${e}"`,$top:String(Math.min(Math.max(1,t),50)),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/messages?${s}`)).value??[]).map(o=>this.mapMessage(o))}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 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 o=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?${o}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}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,`
385
408
  `).replace(/<\/p>/gi,`
386
409
 
387
410
  `).replace(/<[^>]+>/g,"").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\n{3,}/g,`
388
411
 
389
- `).trim()}}});var ki={};oe(ki,{StandardEmailProvider:()=>ir});var ir,Sn=b(()=>{"use strict";nr();ir=class extends xe{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(h=>h.name?`${h.name} <${h.address}>`:h.address??"")??[],a=n.envelope?.cc?.map(h=>h.name?`${h.name} <${h.address}>`:h.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 h=this.formatAddress(m.envelope?.from?.[0]);o.push({id:String(m.seq),from:h,to:m.envelope?.to?.map(w=>w.name?`${w.name} <${w.address}>`:w.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(`
412
+ `).trim()}}});var ra={};re(ra,{StandardEmailProvider:()=>br});var br,Wo=y(()=>{"use strict";Tr();br=class extends Le{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 o=await s.fetchOne(String(t),{envelope:!0,source:!0,bodyStructure:!0});if(!o)throw new Error(`Message #${t} not found.`);let n=this.formatAddress(o.envelope?.from?.[0]),i=o.envelope?.to?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??"")??[],a=o.envelope?.cc?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??""),l=o.source?.toString()??"",d=this.extractTextBody(l),m=this.extractAttachmentInfo(o.bodyStructure);return{id:String(t),from:n,to:i,subject:o.envelope?.subject??"(no subject)",date:o.envelope?.date??new Date,read:o.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 o=await r.getMailboxLock("INBOX");try{let n=await r.search({or:[{subject:e},{from:e},{body:e}]}),i=Array.isArray(n)?n:[];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{o.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 o=await r.getMailboxLock(e);try{let n=[],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]);n.push({id:String(m.seq),from:p,to:m.envelope?.to?.map(w=>w.name?`${w.name} <${w.address}>`:w.address??"")??[],subject:m.envelope?.subject??"(no subject)",date:m.envelope?.date??new Date,read:m.flags?.has("\\Seen")??!1})}return n.reverse(),n}finally{o.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 o=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{o.release()}}finally{await r.logout()}}extractAttachmentInfo(e){let t=[];if(!e)return t;let s=u((r,o)=>{if(r.childNodes){for(let i=0;i<r.childNodes.length;i++)s(r.childNodes[i],o?`${o}.${i+1}`:String(i+1));return}let n=r.disposition?.toLowerCase();if(n==="attachment"||r.type&&!r.type.startsWith("text/")&&n!=="inline"){let i=r.dispositionParameters?.filename??r.parameters?.name??`part-${o}`;t.push({id:r.part??o,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(`
390
413
 
391
414
  `));let r=s.match(/boundary="?([^"\s;]+)"?/i)??e.match(/boundary="?([^"\s;]+)"?/i);if(!r)return t.slice(1).join(`
392
415
 
393
- `).slice(0,5e3);let n=r[1],o=e.split(`--${n}`);for(let i of o){let a=i.toLowerCase();if(a.includes("content-type: text/plain")||a.includes("content-type:text/plain")){let l=i.indexOf(`
416
+ `).slice(0,5e3);let o=r[1],n=e.split(`--${o}`);for(let i of n){let a=i.toLowerCase();if(a.includes("content-type: text/plain")||a.includes("content-type:text/plain")){let l=i.indexOf(`
394
417
 
395
418
  `);if(l>=0)return this.decodeBody(i.slice(l+2));let d=i.indexOf(`\r
396
419
  \r
397
420
  `);if(d>=0)return this.decodeBody(i.slice(d+4))}}return this.decodeBody(t.slice(1).join(`
398
421
 
399
- `).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 bs(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(vn(),Si)),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(()=>(Sn(),ki)),t=new e(c);return await t.initialize(),t}var xi=b(()=>{"use strict";u(bs,"createEmailProvider")});var Me,Ii=b(()=>{"use strict";nr();xi();Sn();vn();P();Me=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, list folders, read from specific folders, reply to messages, or download attachments.`:"Access the user's email: check inbox, read messages, search emails, send new emails, list folders, read from specific folders, reply to messages, or download attachments. Use when the user asks about their emails or wants to send one.";this.metadata={name:"email",description:s,riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send","folders","folder","reply","attachment"],description:"The email action to perform"},...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 (for attachment action)"},isHtml:{type:"boolean",description:"Whether the body is HTML (for send action)"}},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"folders":return await this.handleFolders(e);case"folder":return await this.handleFolder(e);case"reply":return await this.handleReply(e);case"attachment":return await this.handleAttachment(e);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send, folders, folder, reply, 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]",h=l.hasAttachments?" [ATT]":"";return`${d+1}. [${this.encodeId(r,l.id)}]${m}${h} ${l.subject}
422
+ `).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 Rs(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(Vo(),sa)),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(()=>(Wo(),ra)),t=new e(c);return await t.initialize(),t}var oa=y(()=>{"use strict";u(Rs,"createEmailProvider")});var Ue,na=y(()=>{"use strict";Tr();oa();Wo();Vo();j();Ue=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, list folders, read from specific folders, reply to messages, or download attachments.`:"Access the user's email: check inbox, read messages, search emails, send new emails, list folders, read from specific folders, reply to messages, or download attachments. Use when the user asks about their emails or wants to send one.";this.metadata={name:"email",description:s,riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send","folders","folder","reply","attachment"],description:"The email action to perform"},...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 (for attachment action)"},isHtml:{type:"boolean",description:"Whether the body is HTML (for send action)"}},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"folders":return await this.handleFolders(e);case"folder":return await this.handleFolder(e);case"reply":return await this.handleReply(e);case"attachment":return await this.handleAttachment(e);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send, folders, folder, reply, 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,o=Math.min(Math.max(1,e.count??10),50),n=await s.fetchInbox(o);if(n.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(r,"Inbox is empty.")};let i=n.filter(l=>!l.read).length,a=n.map((l,d)=>{let m=l.read?"":" [UNREAD]",p=l.hasAttachments?" [ATT]":"";return`${d+1}. [${this.encodeId(r,l.id)}]${m}${p} ${l.subject}
400
423
  From: ${l.from}
401
424
  Date: ${l.date.toISOString()}`}).join(`
402
425
 
403
- `);return{success:!0,data:{messages:o.map(l=>({...l,id:this.encodeId(r,l.id)})),unreadCount:i},display:this.accountLabel(r,`Inbox (${i} unread):
426
+ `);return{success:!0,data:{messages:n.map(l=>({...l,id:this.encodeId(r,l.id)})),unreadCount:i},display:this.accountLabel(r,`Inbox (${i} unread):
404
427
 
405
- ${a}`)}}async handleRead(e){let t=e.messageId;if(!t)return{success:!1,error:"messageId is required."};let{account:s,rawId:r}=this.decodeId(t),n=this.providers.get(s);if(!n)return{success:!1,error:`Unknown email account "${s}".`};let o=await n.readMessage(r),i=o.attachments?.length?`
406
- Attachments: ${o.attachments.map(a=>`${a.name} (${a.contentType}, ${this.formatSize(a.size)})`).join(", ")}`:"";return{success:!0,data:{...o,id:this.encodeId(s,o.id)},display:this.accountLabel(s,[`From: ${o.from}`,`To: ${o.to.join(", ")}`,...o.cc?.length?[`CC: ${o.cc.join(", ")}`]:[],`Subject: ${o.subject}`,`Date: ${o.date.toISOString()}`,i,"",o.body.slice(0,3e3)+(o.body.length>3e3?`
428
+ ${a}`)}}async handleRead(e){let t=e.messageId;if(!t)return{success:!1,error:"messageId is required."};let{account:s,rawId:r}=this.decodeId(t),o=this.providers.get(s);if(!o)return{success:!1,error:`Unknown email account "${s}".`};let n=await o.readMessage(r),i=n.attachments?.length?`
429
+ Attachments: ${n.attachments.map(a=>`${a.name} (${a.contentType}, ${this.formatSize(a.size)})`).join(", ")}`:"";return{success:!0,data:{...n,id:this.encodeId(s,n.id)},display:this.accountLabel(s,[`From: ${n.from}`,`To: ${n.to.join(", ")}`,...n.cc?.length?[`CC: ${n.cc.join(", ")}`]:[],`Subject: ${n.subject}`,`Date: ${n.date.toISOString()}`,i,"",n.body.slice(0,3e3)+(n.body.length>3e3?`
407
430
 
408
431
  ... (truncated)`:"")].join(`
409
- `))}}async handleSearch(e){let t=e.query;if(!t)return{success:!1,error:"query is required for search."};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.count??10),50),i=await r.searchMessages(t,o);if(i.length===0)return{success:!0,data:{results:[]},display:this.accountLabel(n,`No emails found for "${t}".`)};let a=i.map((l,d)=>`${d+1}. [${this.encodeId(n,l.id)}] ${l.subject}
432
+ `))}}async handleSearch(e){let t=e.query;if(!t)return{success:!1,error:"query is required for search."};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:o}=s,n=Math.min(Math.max(1,e.count??10),50),i=await r.searchMessages(t,n);if(i.length===0)return{success:!0,data:{results:[]},display:this.accountLabel(o,`No emails found for "${t}".`)};let a=i.map((l,d)=>`${d+1}. [${this.encodeId(o,l.id)}] ${l.subject}
410
433
  From: ${l.from}
411
434
  Date: ${l.date.toISOString()}`).join(`
412
435
 
413
- `);return{success:!0,data:{query:t,results:i.map(l=>({...l,id:this.encodeId(n,l.id)})),totalMatches:i.length},display:this.accountLabel(n,`Search results for "${t}" (${i.length} matches):
436
+ `);return{success:!0,data:{query:t,results:i.map(l=>({...l,id:this.encodeId(o,l.id)})),totalMatches:i.length},display:this.accountLabel(o,`Search results for "${t}" (${i.length} matches):
414
437
 
415
- ${a}`)}}async handleSend(e){let t=e.to,s=e.subject,r=e.body;if(!t)return{success:!1,error:'"to" (recipient email) is required.'};if(!s)return{success:!1,error:'"subject" is required.'};if(!r)return{success:!1,error:'"body" is required.'};let n=this.resolveProvider(e);if("success"in n)return n;let{provider:o,account:i}=n,a=await o.sendMessage({to:t,subject:s,body:r,cc:e.cc,isHtml:e.isHtml});return{success:!0,data:{messageId:a.messageId,to:t,subject:s},display:this.accountLabel(i,`Email sent to ${t}
438
+ ${a}`)}}async handleSend(e){let t=e.to,s=e.subject,r=e.body;if(!t)return{success:!1,error:'"to" (recipient email) is required.'};if(!s)return{success:!1,error:'"subject" is required.'};if(!r)return{success:!1,error:'"body" is required.'};let o=this.resolveProvider(e);if("success"in o)return o;let{provider:n,account:i}=o,a=await n.sendMessage({to:t,subject:s,body:r,cc:e.cc,isHtml:e.isHtml});return{success:!0,data:{messageId:a.messageId,to:t,subject:s},display:this.accountLabel(i,`Email sent to ${t}
416
439
  Subject: ${s}
417
- Message ID: ${a.messageId}`)}}async handleFolders(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,n=await s.listFolders();return{success:!0,data:{folders:n},display:n.length===0?this.accountLabel(r,"No folders found."):this.accountLabel(r,`Email folders:
418
- ${n.map((o,i)=>` ${i+1}. ${o}`).join(`
419
- `)}`)}}async handleFolder(e){let t=e.folder;if(!t)return{success:!1,error:'"folder" name is required. Use the "folders" action to list available folders.'};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.count??10),50),i=await r.fetchFolder(t,o);if(i.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(n,`Folder "${t}" is empty.`)};let a=i.map((l,d)=>{let m=l.read?"":" [UNREAD]";return`${d+1}. [${this.encodeId(n,l.id)}]${m} ${l.subject}
440
+ Message ID: ${a.messageId}`)}}async handleFolders(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,o=await s.listFolders();return{success:!0,data:{folders:o},display:o.length===0?this.accountLabel(r,"No folders found."):this.accountLabel(r,`Email folders:
441
+ ${o.map((n,i)=>` ${i+1}. ${n}`).join(`
442
+ `)}`)}}async handleFolder(e){let t=e.folder;if(!t)return{success:!1,error:'"folder" name is required. Use the "folders" action to list available folders.'};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:o}=s,n=Math.min(Math.max(1,e.count??10),50),i=await r.fetchFolder(t,n);if(i.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(o,`Folder "${t}" is empty.`)};let a=i.map((l,d)=>{let m=l.read?"":" [UNREAD]";return`${d+1}. [${this.encodeId(o,l.id)}]${m} ${l.subject}
420
443
  From: ${l.from}
421
444
  Date: ${l.date.toISOString()}`}).join(`
422
445
 
423
- `);return{success:!0,data:{folder:t,messages:i.map(l=>({...l,id:this.encodeId(n,l.id)}))},display:this.accountLabel(n,`Folder "${t}" (${i.length} messages):
446
+ `);return{success:!0,data:{folder:t,messages:i.map(l=>({...l,id:this.encodeId(o,l.id)}))},display:this.accountLabel(o,`Folder "${t}" (${i.length} messages):
424
447
 
425
- ${a}`)}}async handleReply(e){let t=e.messageId,s=e.body;if(!t)return{success:!1,error:'"messageId" is required for reply.'};if(!s)return{success:!1,error:'"body" is required for reply.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);return o?{success:!0,data:{messageId:(await o.sendMessage({to:"",subject:"",body:s,replyTo:n})).messageId},display:this.accountLabel(r,`Reply sent to message ${n}.`)}:{success:!1,error:`Unknown email account "${r}".`}}async handleAttachment(e){let t=e.messageId,s=e.attachmentId;if(!t)return{success:!1,error:'"messageId" is required.'};if(!s)return{success:!1,error:'"attachmentId" is required.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);if(!o)return{success:!1,error:`Unknown email account "${r}".`};let a=(await o.readMessage(n)).attachments?.find(h=>h.id===s),l=await o.downloadAttachment(n,s),d=a?.name??`attachment-${s}`,m=a?.contentType??"application/octet-stream";return{success:!0,data:{messageId:t,attachmentId:s,fileName:d,size:l.length},display:this.accountLabel(r,`Downloaded attachment: ${d} (${this.formatSize(l.length)})`),attachments:[{fileName:d,data:l,mimeType:m}]}}formatSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Ai,wt,Ri=b(()=>{"use strict";P();Ai=1e5,wt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",description:"Make HTTP requests to fetch web pages or call REST APIs. Use when you need to read a URL, call an API endpoint, or fetch data from the web. Supports GET, POST, PUT, PATCH, DELETE methods.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL to request"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method (default: GET)"},headers:{type:"object",description:"Request headers as key-value pairs (optional)"},body:{type:"string",description:"Request body for POST/PUT/PATCH (optional)"}},required:["url"]}};async execute(e,t){let s=e.url,r=(e.method??"GET").toUpperCase(),n=e.headers,o=e.body;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "url"'};let i;try{i=new URL(s)}catch{return{success:!1,error:`Invalid URL: "${s}"`}}if(i.protocol!=="http:"&&i.protocol!=="https:")return{success:!1,error:`Unsupported URL scheme "${i.protocol}". Only http: and https: are allowed.`};if(this.isPrivateHost(i.hostname))return{success:!1,error:`Access to private/internal network address "${i.hostname}" is blocked.`};try{let a={method:r,headers:{"User-Agent":"Alfred/1.0",...n??{}},signal:AbortSignal.timeout(15e3)};o&&["POST","PUT","PATCH"].includes(r)&&(a.body=o,!n?.["Content-Type"]&&!n?.["content-type"]&&(a.headers["Content-Type"]="application/json"));let l=await fetch(s,a),d=l.headers.get("content-type")??"",m=await l.text(),h=m.length>Ai,w=h?m.slice(0,Ai)+`
448
+ ${a}`)}}async handleReply(e){let t=e.messageId,s=e.body;if(!t)return{success:!1,error:'"messageId" is required for reply.'};if(!s)return{success:!1,error:'"body" is required for reply.'};let{account:r,rawId:o}=this.decodeId(t),n=this.providers.get(r);return n?{success:!0,data:{messageId:(await n.sendMessage({to:"",subject:"",body:s,replyTo:o})).messageId},display:this.accountLabel(r,`Reply sent to message ${o}.`)}:{success:!1,error:`Unknown email account "${r}".`}}async handleAttachment(e){let t=e.messageId,s=e.attachmentId;if(!t)return{success:!1,error:'"messageId" is required.'};if(!s)return{success:!1,error:'"attachmentId" is required.'};let{account:r,rawId:o}=this.decodeId(t),n=this.providers.get(r);if(!n)return{success:!1,error:`Unknown email account "${r}".`};let a=(await n.readMessage(o)).attachments?.find(p=>p.id===s),l=await n.downloadAttachment(o,s),d=a?.name??`attachment-${s}`,m=a?.contentType??"application/octet-stream";return{success:!0,data:{messageId:t,attachmentId:s,fileName:d,size:l.length},display:this.accountLabel(r,`Downloaded attachment: ${d} (${this.formatSize(l.length)})`),attachments:[{fileName:d,data:l,mimeType:m}]}}formatSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var ia,kt,aa=y(()=>{"use strict";j();ia=1e5,kt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",description:"Make HTTP requests to fetch web pages or call REST APIs. Use when you need to read a URL, call an API endpoint, or fetch data from the web. Supports GET, POST, PUT, PATCH, DELETE methods.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL to request"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method (default: GET)"},headers:{type:"object",description:"Request headers as key-value pairs (optional)"},body:{type:"string",description:"Request body for POST/PUT/PATCH (optional)"}},required:["url"]}};async execute(e,t){let s=e.url,r=(e.method??"GET").toUpperCase(),o=e.headers,n=e.body;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "url"'};let i;try{i=new URL(s)}catch{return{success:!1,error:`Invalid URL: "${s}"`}}if(i.protocol!=="http:"&&i.protocol!=="https:")return{success:!1,error:`Unsupported URL scheme "${i.protocol}". Only http: and https: are allowed.`};if(this.isPrivateHost(i.hostname))return{success:!1,error:`Access to private/internal network address "${i.hostname}" is blocked.`};try{let a={method:r,headers:{"User-Agent":"Alfred/1.0",...o??{}},signal:AbortSignal.timeout(15e3)};n&&["POST","PUT","PATCH"].includes(r)&&(a.body=n,!o?.["Content-Type"]&&!o?.["content-type"]&&(a.headers["Content-Type"]="application/json"));let l=await fetch(s,a),d=l.headers.get("content-type")??"",m=await l.text(),p=m.length>ia,w=p?m.slice(0,ia)+`
426
449
 
427
- [... truncated]`:m,y=w;d.includes("text/html")&&(y=this.stripHtml(w).slice(0,1e4));let g={status:l.status,statusText:l.statusText,contentType:d,bodyLength:m.length,truncated:h,body:w};return l.ok?{success:!0,data:g,display:`HTTP ${l.status} OK (${m.length} bytes)
450
+ [... truncated]`:m,T=w;d.includes("text/html")&&(T=this.stripHtml(w).slice(0,1e4));let g={status:l.status,statusText:l.statusText,contentType:d,bodyLength:m.length,truncated:p,body:w};return l.ok?{success:!0,data:g,display:`HTTP ${l.status} OK (${m.length} bytes)
428
451
 
429
- ${y.slice(0,5e3)}`}:{success:!0,data:g,display:`HTTP ${l.status} ${l.statusText}
452
+ ${T.slice(0,5e3)}`}:{success:!0,data:g,display:`HTTP ${l.status} ${l.statusText}
430
453
 
431
- ${y.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 z from"node:fs";import Ne from"node:path";var kn,Li,hl,bt,Mi=b(()=>{"use strict";P();kn=5e5,Li=5e7,hl={".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"},bt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",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(z.existsSync(i)&&z.lstatSync(i).isSymbolicLink()){let l=z.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 Ne.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=Ne.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=z.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>kn){let r=z.readFileSync(e,"utf-8").slice(0,kn);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${kn}):
454
+ ${T.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,o]=s.map(Number);if(r===10||r===172&&o>=16&&o<=31||r===192&&o===168||r===127||r===169&&o===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 G from"node:fs";import Pe from"node:path";var Xo,ca,ud,At,la=y(()=>{"use strict";j();Xo=5e5,ca=5e7,ud={".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"},At=class extends I{static{u(this,"FileSkill")}metadata={name:"file",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,o=e.content,n=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!o)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(G.existsSync(i)&&G.lstatSync(i).isSymbolicLink()){let l=G.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,o);case"write_binary":return this.writeBinaryFile(i,o);case"append":return this.appendFile(i,o);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,n);case"copy":return this.copyFile(i,n);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 Pe.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"],o=["/.ssh","/.aws","/.gnupg"],n=[".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&&o.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=Pe.basename(e);return n.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=G.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Xo){let r=G.readFileSync(e,"utf-8").slice(0,Xo);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${Xo}):
432
455
 
433
- ${r}`}}let s=z.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=Ne.dirname(e);return z.mkdirSync(s,{recursive:!0}),z.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 z.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=z.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(`
434
- `);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=z.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}
456
+ ${r}`}}let s=G.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=Pe.dirname(e);return G.mkdirSync(s,{recursive:!0}),G.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 G.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=G.readdirSync(e,{withFileTypes:!0}).map(o=>({name:o.name,type:o.isDirectory()?"dir":o.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(o=>`${o.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${o.name}`).join(`
457
+ `);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=G.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}
435
458
  Size: ${t.size} bytes
436
- Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=z.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=Ne.dirname(e);z.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return z.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=Ne.dirname(s);return z.mkdirSync(n,{recursive:!0}),z.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return z.copyFileSync(e,s),z.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=Ne.dirname(s);return z.mkdirSync(n,{recursive:!0}),z.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(!z.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=z.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Li)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Li})`};let s=z.readFileSync(e),r=Ne.basename(e),n=Ne.extname(e).toLowerCase(),o=hl[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 z.existsSync(e)?z.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(z.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 Tt}from"node:child_process";var _t,Ni=b(()=>{"use strict";P();_t=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",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=Tt("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Tt("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Tt("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)+`
459
+ Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=G.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=Pe.dirname(e);G.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return G.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 o=Pe.dirname(s);return G.mkdirSync(o,{recursive:!0}),G.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return G.copyFileSync(e,s),G.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot move "${e}" to "${s}": ${n.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 o=Pe.dirname(s);return G.mkdirSync(o,{recursive:!0}),G.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${o.message}`}}}sendFile(e){try{if(!G.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=G.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>ca)return{success:!1,error:`File too large to send (${t.size} bytes, max ${ca})`};let s=G.readFileSync(e),r=Pe.basename(e),o=Pe.extname(e).toLowerCase(),n=ud[o]||"application/octet-stream",i={fileName:r,data:s,mimeType:n};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:n},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return G.existsSync(e)?G.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(G.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 It}from"node:child_process";var Rt,da=y(()=>{"use strict";j();Rt=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",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=It("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=It("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=It("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)+`
437
460
 
438
- [... 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":Tt("pbcopy",{input:e,timeout:5e3});break;case"win32":Tt('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Tt("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 Ts}from"node:child_process";import Ci from"node:path";import fl from"node:os";var Et,Oi=b(()=>{"use strict";P();Et=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",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=Ci.join(fl.homedir(),"Desktop"),n=e.path||Ci.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Ts(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":Ts(`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{Ts(`scrot "${n}"`,{timeout:1e4})}catch{try{Ts(`import -window root "${n}"`,{timeout:1e4})}catch{Ts(`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 gl from"node:path";import yl from"node:os";var Di,$t,Ui=b(()=>{"use strict";P();Di=5e4,$t=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",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
439
- 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(`
461
+ [... 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":It("pbcopy",{input:e,timeout:5e3});break;case"win32":It('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:It("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 xs}from"node:child_process";import ua from"node:path";import md from"node:os";var xt,ma=y(()=>{"use strict";j();xt=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",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=ua.join(md.homedir(),"Desktop"),o=e.path||ua.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":xs(`screencapture -x "${o}"`,{timeout:1e4});break;case"win32":xs(`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('${o.replace(/'/g,"''")}'); $graphics.Dispose(); $bitmap.Dispose()"`,{timeout:1e4});break;default:try{xs(`scrot "${o}"`,{timeout:1e4})}catch{try{xs(`import -window root "${o}"`,{timeout:1e4})}catch{xs(`gnome-screenshot -f "${o}"`,{timeout:1e4})}}break}return{success:!0,data:{path:o},display:`Screenshot saved to ${o}`}}catch(n){return{success:!1,error:`Screenshot failed: ${n.message}`}}}}});import pd from"node:path";import fd from"node:os";var pa,Ct,fa=y(()=>{"use strict";j();pa=5e4,Ct=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",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
462
+ 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 o=await this.ensurePage(e);await o.goto(s,{waitUntil:"networkidle2",timeout:3e4});let n=await o.title(),i=await o.evaluate(`
440
463
  (() => {
441
464
  document.querySelectorAll('script, style, noscript').forEach(el => el.remove());
442
465
  return document.body?.innerText ?? '';
443
466
  })()
444
- `),l=(i.length>Di?i.slice(0,Di)+`
467
+ `),l=(i.length>pa?i.slice(0,pa)+`
445
468
 
446
469
  [... truncated]`:i).replace(/\n{3,}/g,`
447
470
 
448
- `).trim();return{success:!0,data:{url:n.url(),title:o,length:i.length},display:`**${o}** (${n.url()})
471
+ `).trim();return{success:!0,data:{url:o.url(),title:n,length:i.length},display:`**${n}** (${o.url()})
449
472
 
450
- ${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||gl.join(yl.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 vt,Pi=b(()=>{"use strict";P();vt=class extends I{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",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=this.userRepo.findOrCreate(t.platform,t.userId),n="getMasterUserId"in this.userRepo?this.userRepo.getMasterUserId(r.id):r.id,o=("findById"in this.userRepo?this.userRepo.findById(n):r)??r;switch(s){case"get":return this.getProfile(o.id);case"set_timezone":return this.setField(o.id,"timezone",e.value);case"set_language":return this.setField(o.id,"language",e.value);case"set_bio":return this.setField(o.id,"bio",e.value);case"set_preference":return this.setPreference(o.id,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:
473
+ ${l}`}}catch(o){return{success:!1,error:`Failed to open "${s}": ${o.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 o=s.url();if(o==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let n=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||pd.join(fd.homedir(),"Desktop",`browser-${n}.png`);return await s.screenshot({path:i,fullPage:!1}),{success:!0,data:{path:i,url:o},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 Lt,ha=y(()=>{"use strict";j();Lt=class extends I{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",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=this.userRepo.findOrCreate(t.platform,t.userId),o="getMasterUserId"in this.userRepo?this.userRepo.getMasterUserId(r.id):r.id,n=("findById"in this.userRepo?this.userRepo.findById(o):r)??r;switch(s){case"get":return this.getProfile(n.id);case"set_timezone":return this.setField(n.id,"timezone",e.value);case"set_language":return this.setField(n.id,"language",e.value);case"set_bio":return this.setField(n.id,"bio",e.value);case"set_preference":return this.setPreference(n.id,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,o]of Object.entries(t.preferences))s.push(`${r}: ${String(o)}`);return{success:!0,data:t,display:s.length>0?`Profile:
451
474
  ${s.map(r=>`- ${r}`).join(`
452
- `)}`:"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 ye,_s=b(()=>{"use strict";ye=class{static{u(this,"CalendarProvider")}}});var Fi={};oe(Fi,{CalDAVProvider:()=>ar});var ar,xn=b(()=>{"use strict";_s();ar=class extends ye{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(`
453
- `).map(h=>h.trim()),r=u(h=>s.find(w=>w.startsWith(h+":"))?.slice(h.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
475
+ `)}`:"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 o=this.userRepo.getProfile(e)?.preferences??{};return o[t]=s,this.userRepo.updateProfile(e,{preferences:o}),{success:!0,data:{key:t,value:s},display:`Preference "${t}" set to "${s}"`}}}});var ve,Cs=y(()=>{"use strict";ve=class{static{u(this,"CalendarProvider")}}});var ga={};re(ga,{CalDAVProvider:()=>_r});var _r,Go=y(()=>{"use strict";Cs();_r=class extends ve{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 o of s){let n=await this.client.fetchCalendarObjects({calendar:o,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of n){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((o,n)=>o.start.getTime()-n.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 o=await this.client.fetchCalendarObjects({calendar:r});for(let n of o)if(n.url?.includes(e)||n.data?.includes(e)){let i=this.parseICalEvent(n.data,n.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:{...n,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 o of r)if(o.url?.includes(e)||o.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:o});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(o=>!o.allDay&&o.start<t&&o.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
476
+ `).map(p=>p.trim()),r=u(p=>s.find(w=>w.startsWith(p+":"))?.slice(p.length+1),"get"),o=r("SUMMARY"),n=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),l=r("DESCRIPTION"),d=r("UID")??t;if(!o||!n)return;let m=n.length===8;return{id:d,title:o,start:this.parseICalDate(n),end:i?this.parseICalDate(i):this.parseICalDate(n),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((o,n)=>n?o.toISOString().slice(0,10).replace(/-/g,""):o.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
454
477
  VERSION:2.0\r
455
478
  PRODID:-//Alfred//EN\r
456
479
  BEGIN:VEVENT\r
@@ -465,123 +488,166 @@ BEGIN:VEVENT\r
465
488
  `),r+=`DTSTAMP:${s(new Date)}\r
466
489
  `,r+=`END:VEVENT\r
467
490
  END:VCALENDAR\r
468
- `,r}}});var ji={};oe(ji,{GoogleCalendarProvider:()=>cr});var cr,In=b(()=>{"use strict";_s();cr=class extends ye{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 Bi={};oe(Bi,{MicrosoftCalendarProvider:()=>lr});var lr,An=b(()=>{"use strict";_s();lr=class extends ye{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={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?(t.start={dateTime:e.start.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"},t.end={dateTime:e.end.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"}):(t.start={dateTime:e.start.toISOString(),timeZone:"UTC"},t.end={dateTime:e.end.toISOString(),timeZone:"UTC"});let s=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(t)});return this.mapEvent(s)}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:t.start.toISOString(),timeZone:"UTC"}),t.end&&(s.end={dateTime:t.end.toISOString(),timeZone:"UTC"});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}}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 Es(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(xn(),Fi)),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(()=>(In(),ji)),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(()=>(An(),Bi)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var Hi=b(()=>{"use strict";u(Es,"createCalendarProvider")});var Ye,qi=b(()=>{"use strict";P();Ye=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",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){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(`
491
+ `,r}}});var ya={};re(ya,{GoogleCalendarProvider:()=>$r});var $r,Ko=y(()=>{"use strict";Cs();$r=class extends ve{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(o=>!o.allDay&&o.start<t&&o.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 wa={};re(wa,{MicrosoftCalendarProvider:()=>vr});var vr,Yo=y(()=>{"use strict";Cs();vr=class extends ve{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(o=>this.mapEvent(o))}async createEvent(e){let t={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?(t.start={dateTime:e.start.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"},t.end={dateTime:e.end.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"}):(t.start={dateTime:e.start.toISOString(),timeZone:"UTC"},t.end={dateTime:e.end.toISOString(),timeZone:"UTC"});let s=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(t)});return this.mapEvent(s)}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:t.start.toISOString(),timeZone:"UTC"}),t.end&&(s.end={dateTime:t.end.toISOString(),timeZone:"UTC"});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(o=>!o.allDay&&o.start<t&&o.end>e);return{available:r.length===0,conflicts:r}}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 Ls(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Go(),ga)),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(()=>(Ko(),ya)),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(()=>(Yo(),wa)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var Ta=y(()=>{"use strict";u(Ls,"createCalendarProvider")});var rt,Ea=y(()=>{"use strict";j();rt=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",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){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 o=r.map(n=>this.formatEvent(n)).join(`
469
492
  `);return{success:!0,data:r,display:`${r.length} event(s):
470
- ${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):
471
- ${r.conflicts.map(o=>this.formatEvent(o)).join(`
472
- `)}`;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}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var Wi=b(()=>{"use strict";_s();xn();In();An();Hi();qi()});var St,Xi=b(()=>{"use strict";P();St=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",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}**
493
+ ${o}`}}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 o=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:o,display:`Event created: ${this.formatEvent(o)}`}}catch(o){return{success:!1,error:`Failed to create event: ${o instanceof Error?o.message:String(o)}`}}}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)),o=r.available?"Time slot is available.":`Time slot has ${r.conflicts.length} conflict(s):
494
+ ${r.conflicts.map(n=>this.formatEvent(n)).join(`
495
+ `)}`;return{success:!0,data:r,display:o}}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}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var ba=y(()=>{"use strict";Cs();Go();Ko();Yo();Ta();Ea()});var Nt,_a=y(()=>{"use strict";j();Nt=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",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}**
473
496
 
474
497
  Enter this code on your other platform within 10 minutes using:
475
- "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 w=this.users.getLinkedUsers(l);for(let y of w)this.users.setMasterUser(y.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),h=o.platform;return{success:!0,data:{masterUserId:d,linkedPlatform:h},display:`Account linked successfully! Your ${h} account (${m?.displayName??m?.username??"unknown"}) is now linked to this ${t.platform} account.
498
+ "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),o=this.checkConfirmRateLimit(r);if(o)return{success:!1,error:o};let n=this.linkTokens.findByCode(s.trim());if(!n)return this.recordFailedConfirm(r),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};let i=n.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 w=this.users.getLinkedUsers(l);for(let T of w)this.users.setMasterUser(T.id,d)}i!==d&&this.users.setMasterUser(i,d),r!==d&&this.users.setMasterUser(r,d),this.linkTokens.consume(n.id);let m=this.users.findById(i),p=n.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.
476
499
 
477
- 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:
478
- "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:
479
- ${n.join(`
480
- `)}`}}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 kt,zi=b(()=>{"use strict";P();kt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",description:'Schedule, list, or cancel background tasks that run independently. Use "schedule" to queue a skill to execute in the background (user will be notified when done). 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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllTasks(e){let t=new Set,s=[];for(let r of this.allUserIds(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(this.effectiveUserId(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:
500
+ Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e,t){let s=e.platform,r=e.chat_id,o=e.message;if(!s)return{success:!1,error:'Missing required field "platform"'};if(!o)return{success:!1,error:'Missing required field "message"'};let n=this.adapters.get(s);if(!n)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 n.sendMessage(r,o),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:
501
+ "Start linking my account" on the platform you want to link from, then enter the code on the other platform.`};let o=r.map(n=>{let i=n.id===t?" (current)":"",a=n.displayName??n.username??n.platformUserId;return`- **${n.platform}**: ${a}${i}`});return{success:!0,data:{identities:r.map(n=>({platform:n.platform,username:n.username,displayName:n.displayName}))},display:`Linked accounts:
502
+ ${o.join(`
503
+ `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),o=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(o).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 Mt,$a=y(()=>{"use strict";j();Mt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",description:'Schedule, list, or cancel background tasks that run independently. Use "schedule" to queue a skill to execute in the background (user will be notified when done). 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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllTasks(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let o of this.taskRepo.getByUser(r))t.has(o.id)||(t.add(o.id),s.push(o));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,o=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 n=this.taskRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,r,JSON.stringify(o??{}));return{success:!0,data:{taskId:n.id,description:s,skillName:r,status:n.status},display:`Background task scheduled (${n.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(o=>`- ${s[o.status]??"?"} ${o.id}: "${o.description}" [${o.status}] (${o.skillName})`);return{success:!0,data:t.map(o=>({taskId:o.id,description:o.description,status:o.status,skillName:o.skillName,createdAt:o.createdAt,completedAt:o.completedAt})),display:`Background tasks:
481
504
  ${r.join(`
482
- `)}`}}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 xt,Vi=b(()=>{"use strict";P();xt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",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.',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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllActions(e){let t=new Set,s=[];for(let r of this.allUserIds(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")return{success:!1,error:'Missing required field "skill_name" for create action'};if(n==="interval"){let h=parseInt(o,10);if(isNaN(h)||h<=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 h=new Date(o);if(isNaN(h.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(h.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:this.effectiveUserId(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,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:
505
+ `)}`}}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 Dt,va=y(()=>{"use strict";j();Dt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",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.',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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllActions(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let o of this.actionRepo.getByUser(r))t.has(o.id)||(t.add(o.id),s.push(o));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,o=e.schedule_type,n=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(!o||!["cron","interval","once"].includes(o))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!n||typeof n!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if(!i||typeof i!="string")return{success:!1,error:'Missing required field "skill_name" for create action'};if(o==="interval"){let p=parseInt(n,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(o==="cron"&&n.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(o==="once"){let p=new Date(n);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:this.effectiveUserId(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:o,scheduleValue:n,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:l}),m=o==="cron"?`cron: ${n}`:o==="interval"?`every ${n} minutes`:`once at ${n}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:o,scheduleValue:n,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 o=r.enabled?"\u2705":"\u23F8\uFE0F",n=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${o} ${r.id}: "${r.name}" [${n}] \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:
483
506
  ${s.join(`
484
- `)}`}}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=this.allUserIds(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=this.allUserIds(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 Je,Rn=b(()=>{"use strict";Je=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(`
485
- `),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 wl,Ze,Ln=b(()=>{"use strict";P();wl=["read","write","destructive","admin"],Ze=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&&wl.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,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 $s,Ki=b(()=>{"use strict";Rn();Ln();$s=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 Je(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 Ze(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 Gi=b(()=>{"use strict";Rn();Ln();Ki()});import{spawn as bl}from"node:child_process";import It from"node:fs";import Mn from"node:path";import Tl from"node:os";import _l from"node:crypto";var Qe,Nn=b(()=>{"use strict";Qe=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=Mn.join(Tl.tmpdir(),`alfred-sandbox-${_l.randomUUID()}`);It.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=Mn.join(n,`script.${o}`);It.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",l=[i],d=Date.now();return await new Promise(m=>{let h=bl(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},stdio:["pipe","pipe","pipe"]}),w="",y="";h.stdout.on("data",g=>{w+=g.toString()}),h.stderr.on("data",g=>{y+=g.toString()}),h.on("close",g=>{let _=Date.now()-d,v=[];try{let R=It.readdirSync(n).filter(x=>!x.startsWith("script."));for(let x of R){let O=Mn.join(n,x),N=It.statSync(O);if(N.isFile()&&N.size<1e7){let B=It.readFileSync(O),H=x.endsWith(".png")?"image/png":x.endsWith(".jpg")||x.endsWith(".jpeg")?"image/jpeg":x.endsWith(".svg")?"image/svg+xml":x.endsWith(".csv")?"text/csv":x.endsWith(".json")?"application/json":x.endsWith(".html")||x.endsWith(".htm")?"text/html":x.endsWith(".txt")?"text/plain":x.endsWith(".md")?"text/markdown":x.endsWith(".xml")?"application/xml":x.endsWith(".pdf")?"application/pdf":"application/octet-stream";v.push({name:x,data:B,mimeType:H})}}}catch{}m({stdout:w.slice(0,5e4),stderr:y.slice(0,1e4),exitCode:g??1,files:v.length>0?v:void 0,durationMs:_})}),h.on("error",g=>{m({stdout:"",stderr:g.message,exitCode:1,durationMs:Date.now()-d})}),h.stdin.end()})}finally{try{It.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var vs,Yi=b(()=>{"use strict";P();Nn();vs=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (HTML, CSV, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. 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:"destructive",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 Qe;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(", ")}`};let a=r;s==="run_with_data"&&o&&(n==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(o)};
486
- ${r}`:a=`INPUT_DATA = ${JSON.stringify(o)}
487
- ${r}`);let l=await this.executor.execute(a,n,{timeout:i}),d=l.files?.map(h=>({fileName:h.name,data:h.data,mimeType:h.mimeType})),m=[l.stdout?`Output:
507
+ `)}`}}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 o=this.actionRepo.findById(r),n=this.allUserIds(s);return!o||!n.includes(o.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),o=this.allUserIds(t);return!r||!o.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 ot,Jo=y(()=>{"use strict";ot=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,o]of Object.entries(this.config.env))s[r]=o.replace(/\$\{(\w+)\}/g,(n,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(o=>o.text??JSON.stringify(o)).join(`
508
+ `),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 hd,nt,Zo=y(()=>{"use strict";j();hd=["read","write","destructive","admin"],nt=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,o,n){super(),this.client=e,this.serverName=t,this.toolName=s;let i=n&&hd.includes(n)?n:"write";this.metadata={name:`mcp__${t}__${s}`,description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:o}}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 Ns,Sa=y(()=>{"use strict";Jo();Zo();Ns=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 ot(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let o of r){let n=new nt(s,t.name,o.name,o.description??"",o.inputSchema);this.skills.push(n)}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 ka=y(()=>{"use strict";Jo();Zo();Sa()});import{spawn as gd}from"node:child_process";import Ot from"node:fs";import Qo from"node:path";import yd from"node:os";import wd from"node:crypto";var it,en=y(()=>{"use strict";it=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),o=Qo.join(yd.tmpdir(),`alfred-sandbox-${wd.randomUUID()}`);Ot.mkdirSync(o,{recursive:!0});try{let n=t==="javascript"?"js":"py",i=Qo.join(o,`script.${n}`);Ot.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=gd(a,l,{cwd:o,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:o,TEMP:o,TMP:o},stdio:["pipe","pipe","pipe"]}),w="",T="";p.stdout.on("data",g=>{w+=g.toString()}),p.stderr.on("data",g=>{T+=g.toString()}),p.on("close",g=>{let b=Date.now()-d,$=[];try{let A=Ot.readdirSync(o).filter(R=>!R.startsWith("script."));for(let R of A){let O=Qo.join(o,R),N=Ot.statSync(O);if(N.isFile()&&N.size<1e7){let K=Ot.readFileSync(O),ie=R.endsWith(".png")?"image/png":R.endsWith(".jpg")||R.endsWith(".jpeg")?"image/jpeg":R.endsWith(".svg")?"image/svg+xml":R.endsWith(".csv")?"text/csv":R.endsWith(".json")?"application/json":R.endsWith(".html")||R.endsWith(".htm")?"text/html":R.endsWith(".txt")?"text/plain":R.endsWith(".md")?"text/markdown":R.endsWith(".xml")?"application/xml":R.endsWith(".pdf")?"application/pdf":"application/octet-stream";$.push({name:R,data:K,mimeType:ie})}}}catch{}m({stdout:w.slice(0,5e4),stderr:T.slice(0,1e4),exitCode:g??1,files:$.length>0?$:void 0,durationMs:b})}),p.on("error",g=>{m({stdout:"",stderr:g.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{Ot.rmSync(o,{recursive:!0,force:!0})}catch{}}}}});var Ms,Aa=y(()=>{"use strict";j();en();Ms=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (HTML, CSV, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. 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:"destructive",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 it;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,o=e.language,n=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(!o)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(o))return{success:!1,error:`Language "${o}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};let a=r;s==="run_with_data"&&n&&(o==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(n)};
509
+ ${r}`:a=`INPUT_DATA = ${JSON.stringify(n)}
510
+ ${r}`);let l=await this.executor.execute(a,o,{timeout:i}),d=l.files?.map(p=>({fileName:p.name,data:p.data,mimeType:p.mimeType})),m=[l.stdout?`Output:
488
511
  ${l.stdout}`:"",l.stderr?`Errors:
489
- ${l.stderr}`:"",`Exit code: ${l.exitCode}`,`Duration: ${l.durationMs}ms`,d&&d.length>0?`Files generated: ${d.map(h=>h.fileName).join(", ")}`:""].filter(Boolean).join(`
512
+ ${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(`
490
513
 
491
- `);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 Ji=b(()=>{"use strict";Nn();Yi()});var At,Zi=b(()=>{"use strict";P();At=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}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(this.effectiveUserId(t),s,r,n);return{success:!0,data:l,display:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`}}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=this.allUserIds(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(`
514
+ `);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 Ia=y(()=>{"use strict";en();Aa()});var Ut,Ra=y(()=>{"use strict";j();Ut=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}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,o=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(!o||typeof o!="string")return{success:!1,error:'Missing required field "mime_type" for ingest action'};let n=await import("node:path"),i=n.resolve(s);if(i!==n.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(this.effectiveUserId(t),s,r,o);return{success:!0,data:l,display:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`}}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 o=this.allUserIds(t),n=new Set,i=[];for(let d of o)for(let m of await this.embeddingService.semanticSearch(d,s,r))n.has(m.key)||(n.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(`
492
515
 
493
516
  `);return{success:!0,data:a,display:`Found ${a.length} relevant chunk(s):
494
517
 
495
- ${l}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for summarize action'};let s=this.docRepo.getDocument(t);if(!s)return{success:!1,error:`Document "${t}" not found`};let r=this.docRepo.getChunks(t);if(r.length===0)return{success:!0,data:{document:s,content:""},display:`Document "${s.filename}" has no content chunks.`};let n=r.map(l=>l.content).join(`
518
+ ${l}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for summarize action'};let s=this.docRepo.getDocument(t);if(!s)return{success:!1,error:`Document "${t}" not found`};let r=this.docRepo.getChunks(t);if(r.length===0)return{success:!0,data:{document:s,content:""},display:`Document "${s.filename}" has no content chunks.`};let o=r.map(l=>l.content).join(`
496
519
 
497
- `),o=8e3,i=n.length>o,a=i?n.slice(0,o)+`
520
+ `),n=8e3,i=o.length>n,a=i?o.slice(0,n)+`
498
521
 
499
- [... truncated]`:n;return{success:!0,data:{document:s,content:a,totalChunks:r.length,truncated:i},display:`Document: **${s.filename}** (${r.length} chunks, ${s.sizeBytes} bytes)
522
+ [... truncated]`:o;return{success:!0,data:{document:s,content:a,totalChunks:r.length,truncated:i},display:`Document: **${s.filename}** (${r.length} chunks, ${s.sizeBytes} bytes)
500
523
 
501
- ${a}`}}list(e,t){let s=e.limit||50,r=this.allUserIds(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}** (${l.id.slice(0,8)}...) \u2014 ${l.mimeType}, ${l.chunkCount} chunks, ${l.sizeBytes} bytes`).join(`
524
+ ${a}`}}list(e,t){let s=e.limit||50,r=this.allUserIds(t),o=new Set,n=[];for(let l of r)for(let d of this.docRepo.listByUser(l))o.has(d.id)||(o.add(d.id),n.push(d));let i=n.slice(0,s);if(i.length===0)return{success:!0,data:[],display:"No documents found."};let a=i.map(l=>`- **${l.filename}** (${l.id.slice(0,8)}...) \u2014 ${l.mimeType}, ${l.chunkCount} chunks, ${l.sizeBytes} bytes`).join(`
502
525
  `);return{success:!0,data:i,display:`${i.length} document(s):
503
- ${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 Rt,Qi=b(()=>{"use strict";P();Rt=class extends I{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",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)}`}}}}});function Z(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 Ss(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function dr(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 ur,ea=b(()=>{"use strict";P();u(Z,"bytes");u(Ss,"pct");u(dr,"uptimeStr");ur=class c extends I{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",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(`
504
- `)}}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"?Ss(s.cpu):"-",n=Z(s.mem),o=Z(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${dr(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
505
- `)}}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:** ${dr(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${Ss(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${Z(n.used)} / ${Z(n.total)} (${Ss(n.used/n.total)})`),i&&a.push(`**Swap:** ${Z(i.used)} / ${Z(i.total)}`),o&&a.push(`**Root FS:** ${Z(o.used)} / ${Z(o.total)}`),{success:!0,data:s,display:a.join(`
506
- `)}}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??"-"} | ${Ss(n.cpu)} | ${Z(n.mem)} / ${Z(n.maxmem)} | ${dr(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
507
- `)}}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:** ${Ss(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${Z(r.mem)} / ${Z(r.maxmem)}`,`**Disk:** ${Z(r.disk)} / ${Z(r.maxdisk)}`,`**Uptime:** ${dr(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${Z(r.netin)} / ${Z(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
508
- `)}}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(`
509
- `)}}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=Z(o.used),a=Z(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(`
510
- `)}}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(`
526
+ ${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 Pt,xa=y(()=>{"use strict";j();Pt=class extends I{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",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)}`}}}}});function ee(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 Ds(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function Sr(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 kr,Ca=y(()=>{"use strict";j();u(ee,"bytes");u(Ds,"pct");u(Sr,"uptimeStr");kr=class c extends I{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",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}`,o={Authorization:`PVEAPIToken=${this.config.tokenId}=${this.config.tokenSecret}`},n={method:e,headers:o};s&&e!=="GET"&&(o["Content-Type"]="application/json",n.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,n)}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(o=>o.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[o,n]=await Promise.all([this.get(`/nodes/${r.node}/qemu`).catch(()=>[]),this.get(`/nodes/${r.node}/lxc`).catch(()=>[])]);for(let i of o)s.push({...i,node:r.node,type:"qemu"});for(let i of n)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(o=>o.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(o=>o.type==="node");if(r.length){t.push("| Node | Online | Level | ID |"),t.push("|------|--------|-------|----|");for(let o of r)t.push(`| ${o.name} | ${o.online?"Yes":"**No**"} | ${o.level??"-"} | ${o.nodeid??"-"} |`)}return{success:!0,data:e,display:t.join(`
527
+ `)}}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"?Ds(s.cpu):"-",o=ee(s.mem),n=ee(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${o} / ${n} | ${Sr(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
528
+ `)}}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,o=s.memory,n=s.rootfs,i=s.swap,a=[`## Node: ${t}`,"",`**Uptime:** ${Sr(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${Ds(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),o&&a.push(`**RAM:** ${ee(o.used)} / ${ee(o.total)} (${Ds(o.used/o.total)})`),i&&a.push(`**Swap:** ${ee(i.used)} / ${ee(i.total)}`),n&&a.push(`**Root FS:** ${ee(n.used)} / ${ee(n.total)}`),{success:!0,data:s,display:a.join(`
529
+ `)}}async listVms(e,t){let s;if(e){if(s=[],!t||t==="qemu"){let o=await this.get(`/nodes/${e}/qemu`).catch(()=>[]);for(let n of o)s.push({...n,node:e,type:"qemu"})}if(!t||t==="lxc"){let o=await this.get(`/nodes/${e}/lxc`).catch(()=>[]);for(let n of o)s.push({...n,node:e,type:"lxc"})}}else s=await this.getAllVms(),t&&(s=s.filter(o=>o.type===t));s.sort((o,n)=>o.vmid-n.vmid);let r=["## Virtual Machines & Containers","","| VMID | Name | Type | Node | Status | CPU | RAM Used / Max | Uptime |","|------|------|------|------|--------|-----|----------------|--------|"];for(let o of s)r.push(`| ${o.vmid} | ${o.name??"-"} | ${o.type} | ${o.node} | ${o.status??"-"} | ${Ds(o.cpu)} | ${ee(o.mem)} / ${ee(o.maxmem)} | ${Sr(o.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
530
+ `)}}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`),o=[`## VM ${e} (${s.type}) on ${s.node}`,"",`**Name:** ${r.name??"-"}`,`**Status:** ${r.status}`,`**CPU:** ${Ds(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${ee(r.mem)} / ${ee(r.maxmem)}`,`**Disk:** ${ee(r.disk)} / ${ee(r.maxdisk)}`,`**Uptime:** ${Sr(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${ee(r.netin)} / ${ee(r.netout)}`];return r.lock&&o.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:o.join(`
531
+ `)}}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`),o=[`## Snapshots for VM ${e}`,"","| Name | Description | Date | Parent |","|------|-------------|------|--------|"];for(let n of r){let i=n.snaptime?new Date(n.snaptime*1e3).toISOString():"-";o.push(`| ${n.name} | ${n.description??"-"} | ${i} | ${n.parent??"-"} |`)}return{success:!0,data:r,display:o.join(`
532
+ `)}}async listStorage(e){let t=e??this.config.defaultNode,s=t?`/nodes/${t}/storage`:"/storage",r=await this.get(s),o=[`## Storage${t?` (Node: ${t})`:""}`,"","| Storage | Type | Content | Used / Total | Status |","|---------|------|---------|--------------|--------|"];for(let n of r){let i=ee(n.used),a=ee(n.total);o.push(`| ${n.storage} | ${n.type} | ${n.content??"-"} | ${i} / ${a} | ${n.active?"active":n.enabled?"enabled":"disabled"} |`)}return{success:!0,data:r,display:o.join(`
533
+ `)}}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 o of s){let n=o.starttime?new Date(o.starttime*1e3).toISOString():"-";r.push(`| \`${o.upid?.slice(-16)??"-"}\` | ${o.type??"-"} | ${o.status??"running"} | ${n} | ${o.user??"-"} |`)}return{success:!0,data:s,display:r.join(`
511
534
  `)}}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(`
512
- `)}}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(`
513
- `)}}async createSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),n={snapname:s};e.description&&(n.description=e.description);let o=await this.post(`/nodes/${r.node}/${r.type}/${t}/snapshot`,n);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:o},display:[`Snapshot **"${s}"** creation started for VM ${t} on **${r.node}**.`,"",`UPID: \`${o}\``].join(`
514
- `)}}async backupVm(e){let t=e.vmid;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(t,e.node),r={vmid:t,mode:"snapshot"};e.storage&&(r.storage=e.storage);let n=await this.post(`/nodes/${s.node}/vzdump`,r);return{success:!0,data:{vmid:t,node:s.node,storage:e.storage??"default",upid:n},display:[`Backup (snapshot mode) started for VM ${t} on **${s.node}**.`,e.storage?`Storage: **${e.storage}**`:"","",`UPID: \`${n}\``].filter(Boolean).join(`
515
- `)}}async migrateVm(e){let t=e.vmid,s=e.target;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "target" parameter (target node)'};let r=await this.resolveVm(t,e.node),n=await this.post(`/nodes/${r.node}/${r.type}/${t}/migrate`,{target:s,online:1});return{success:!0,data:{vmid:t,from:r.node,target:s,type:r.type,upid:n},display:[`Live migration of VM ${t} from **${r.node}** to **${s}** started.`,"",`UPID: \`${n}\``].join(`
516
- `)}}async deleteSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),n=await this.del(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:n},display:[`Snapshot **"${s}"** deletion started for VM ${t} on **${r.node}**.`,"",`UPID: \`${n}\``].join(`
517
- `)}}async rollbackSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),n=await this.post(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}/rollback`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:n},display:[`Rollback to snapshot **"${s}"** started for VM ${t} on **${r.node}**.`,"",`UPID: \`${n}\``,"","**Warning:** The VM will be stopped during rollback."].join(`
518
- `)}}}});var mr,ta=b(()=>{"use strict";P();mr=class extends I{static{u(this,"UniFiSkill")}metadata={name:"unifi",description:'Manage UniFi network devices, clients, and WLANs. Use "list_devices" to see APs/switches, "list_clients" for connected clients, "restart_device" to reboot a device, "block_client"/"unblock_client" for access control.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_devices","device_info","list_clients","client_info","list_networks","list_wlans","site_stats","dpi_stats","list_alerts","list_events","list_vouchers","restart_device","locate_device","reconnect_client","create_voucher","enable_wlan","disable_wlan","archive_alerts","block_client","unblock_client","forget_client","adopt_device"],description:"The UniFi action to perform"},mac:{type:"string",description:"MAC address of device or client (for device_info, client_info, restart_device, locate_device, reconnect_client, block_client, unblock_client, forget_client, adopt_device)"},active:{type:"boolean",description:"If true list only active clients, if false list all known clients (for list_clients, default: true)"},enabled:{type:"boolean",description:"Enable or disable device locate LED (for locate_device, default: true)"},id:{type:"string",description:"WLAN config ID (for enable_wlan, disable_wlan)"},limit:{type:"number",description:"Maximum number of items to return (for list_alerts, list_events)"},count:{type:"number",description:"Number of vouchers to create (for create_voucher, default: 1)"},duration:{type:"number",description:"Voucher validity in minutes (for create_voucher)"},bandwidth_down:{type:"number",description:"Download bandwidth limit in Kbps (for create_voucher, optional)"},bandwidth_up:{type:"number",description:"Upload bandwidth limit in Kbps (for create_voucher, optional)"},quota:{type:"number",description:"Number of uses per voucher (for create_voucher, 0 = unlimited, default: 1)"}},required:["action"]}};config;site;controllerMode;cookies=[];csrfToken;constructor(e){if(super(),!e.apiKey&&!(e.username&&e.password))throw new Error('UniFi config requires either "apiKey" or both "username" and "password".');this.config=e,this.site=e.site??"default",e.apiKey&&(this.controllerMode="unifi-os")}async execute(e,t){let s=e.action;try{switch(s){case"list_devices":return await this.listDevices();case"device_info":return await this.deviceInfo(e.mac);case"list_clients":return await this.listClients(e.active);case"client_info":return await this.clientInfo(e.mac);case"list_networks":return await this.listNetworks();case"list_wlans":return await this.listWlans();case"site_stats":return await this.siteStats();case"dpi_stats":return await this.dpiStats(e.mac);case"list_alerts":return await this.listAlerts(e.limit);case"list_events":return await this.listEvents(e.limit);case"list_vouchers":return await this.listVouchers();case"restart_device":return await this.restartDevice(e.mac);case"locate_device":return await this.locateDevice(e.mac,e.enabled);case"reconnect_client":return await this.reconnectClient(e.mac);case"create_voucher":return await this.createVoucher(e.count,e.duration,e.bandwidth_down,e.bandwidth_up,e.quota);case"enable_wlan":return await this.enableWlan(e.id);case"disable_wlan":return await this.disableWlan(e.id);case"archive_alerts":return await this.archiveAlerts();case"block_client":return await this.blockClient(e.mac);case"unblock_client":return await this.unblockClient(e.mac);case"forget_client":return await this.forgetClient(e.mac);case"adopt_device":return await this.adoptDevice(e.mac);default:return{success:!1,error:`Unknown action: ${s}`}}}catch(r){return{success:!1,error:`UniFi error: ${r instanceof Error?r.message:String(r)}`}}}apiUrl(e){let t=this.config.baseUrl.replace(/\/+$/,"");return this.controllerMode==="unifi-os"?`${t}/proxy/network/api/s/${this.site}/${e}`:`${t}/api/s/${this.site}/${e}`}async ensureAuth(){this.config.apiKey||this.cookies.length>0||await this.login()}async login(){let e=this.config.baseUrl.replace(/\/+$/,""),t=JSON.stringify({username:this.config.username,password:this.config.password}),s=await this.rawFetch(`${e}/api/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(s.status===200){this.controllerMode="unifi-os",this.storeCookies(s);return}if(s.status===404){let r=await this.rawFetch(`${e}/api/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(r.ok){this.controllerMode="classic",this.storeCookies(r);return}throw new Error(`UniFi Classic login failed (HTTP ${r.status}): ${await r.text()}`)}throw new Error(`UniFi OS login failed (HTTP ${s.status}): ${await s.text()}`)}storeCookies(e){let t=e.headers.getSetCookie?.()??[];t.length>0&&(this.cookies=t.map(r=>r.split(";")[0]));let s=e.headers.get("x-csrf-token");s&&(this.csrfToken=s)}clearSession(){this.cookies=[],this.csrfToken=void 0}async rawFetch(e,t){let s=process.env.NODE_TLS_REJECT_UNAUTHORIZED;this.config.verifyTls===!1&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");try{return await fetch(e,t)}finally{this.config.verifyTls===!1&&(s===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=s)}}async request(e,t,s){await this.ensureAuth();let r=await this.doFetch(e,t,s);if(r.status===401&&!this.config.apiKey){this.clearSession(),await this.login();let n=await this.doFetch(e,t,s);if(!n.ok)throw new Error(`UniFi API error after relogin: HTTP ${n.status} ${await n.text()}`);return this.parseResponse(n)}if(!r.ok)throw new Error(`UniFi API error: HTTP ${r.status} ${await r.text()}`);return this.parseResponse(r)}async doFetch(e,t,s){let r=this.apiUrl(t),n={"Content-Type":"application/json"};return this.config.apiKey?n["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(n.Cookie=this.cookies.join("; ")),this.csrfToken&&(n["X-CSRF-Token"]=this.csrfToken)),this.rawFetch(r,{method:e,headers:n,body:s!==void 0?JSON.stringify(s):void 0,signal:AbortSignal.timeout(3e4)})}async parseResponse(e){let t=await e.json(),s=e.headers.get("x-csrf-token");if(s&&(this.csrfToken=s),t.meta?.rc==="error")throw new Error(`UniFi: ${t.meta.msg??"unknown error"}`);return t.data}async listDevices(){let e=await this.request("GET","stat/device"),t=(e??[]).map(r=>({name:r.name??r.hostname??r.mac,model:r.model??"unknown",ip:r.ip??"-",mac:r.mac,status:r.state===1?"online":"offline",clients:r.num_sta??0,load:r["system-stats"]?.cpu!=null?`${r["system-stats"].cpu}%`:"-"})),s=t.length===0?"No devices found.":["| Name | Model | IP | MAC | Status | Clients | CPU |","|------|-------|----|-----|--------|---------|-----|",...t.map(r=>`| ${r.name} | ${r.model} | ${r.ip} | ${r.mac} | ${r.status} | ${r.clients} | ${r.load} |`)].join(`
535
+ `)}}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),o=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:o},display:[`**${e.charAt(0).toUpperCase()+e.slice(1)}** sent to VM ${s} (${r.type}) on **${r.node}**.`,"",`UPID: \`${o}\``,"","Use `task_status` with this UPID to check progress."].join(`
536
+ `)}}async createSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),o={snapname:s};e.description&&(o.description=e.description);let n=await this.post(`/nodes/${r.node}/${r.type}/${t}/snapshot`,o);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:n},display:[`Snapshot **"${s}"** creation started for VM ${t} on **${r.node}**.`,"",`UPID: \`${n}\``].join(`
537
+ `)}}async backupVm(e){let t=e.vmid;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(t,e.node),r={vmid:t,mode:"snapshot"};e.storage&&(r.storage=e.storage);let o=await this.post(`/nodes/${s.node}/vzdump`,r);return{success:!0,data:{vmid:t,node:s.node,storage:e.storage??"default",upid:o},display:[`Backup (snapshot mode) started for VM ${t} on **${s.node}**.`,e.storage?`Storage: **${e.storage}**`:"","",`UPID: \`${o}\``].filter(Boolean).join(`
538
+ `)}}async migrateVm(e){let t=e.vmid,s=e.target;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "target" parameter (target node)'};let r=await this.resolveVm(t,e.node),o=await this.post(`/nodes/${r.node}/${r.type}/${t}/migrate`,{target:s,online:1});return{success:!0,data:{vmid:t,from:r.node,target:s,type:r.type,upid:o},display:[`Live migration of VM ${t} from **${r.node}** to **${s}** started.`,"",`UPID: \`${o}\``].join(`
539
+ `)}}async deleteSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),o=await this.del(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:o},display:[`Snapshot **"${s}"** deletion started for VM ${t} on **${r.node}**.`,"",`UPID: \`${o}\``].join(`
540
+ `)}}async rollbackSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),o=await this.post(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}/rollback`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:o},display:[`Rollback to snapshot **"${s}"** started for VM ${t} on **${r.node}**.`,"",`UPID: \`${o}\``,"","**Warning:** The VM will be stopped during rollback."].join(`
541
+ `)}}}});var Ar,La=y(()=>{"use strict";j();Ar=class extends I{static{u(this,"UniFiSkill")}metadata={name:"unifi",description:'Manage UniFi network devices, clients, and WLANs. Use "list_devices" to see APs/switches, "list_clients" for connected clients, "restart_device" to reboot a device, "block_client"/"unblock_client" for access control.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_devices","device_info","list_clients","client_info","list_networks","list_wlans","site_stats","dpi_stats","list_alerts","list_events","list_vouchers","restart_device","locate_device","reconnect_client","create_voucher","enable_wlan","disable_wlan","archive_alerts","block_client","unblock_client","forget_client","adopt_device"],description:"The UniFi action to perform"},mac:{type:"string",description:"MAC address of device or client (for device_info, client_info, restart_device, locate_device, reconnect_client, block_client, unblock_client, forget_client, adopt_device)"},active:{type:"boolean",description:"If true list only active clients, if false list all known clients (for list_clients, default: true)"},enabled:{type:"boolean",description:"Enable or disable device locate LED (for locate_device, default: true)"},id:{type:"string",description:"WLAN config ID (for enable_wlan, disable_wlan)"},limit:{type:"number",description:"Maximum number of items to return (for list_alerts, list_events)"},count:{type:"number",description:"Number of vouchers to create (for create_voucher, default: 1)"},duration:{type:"number",description:"Voucher validity in minutes (for create_voucher)"},bandwidth_down:{type:"number",description:"Download bandwidth limit in Kbps (for create_voucher, optional)"},bandwidth_up:{type:"number",description:"Upload bandwidth limit in Kbps (for create_voucher, optional)"},quota:{type:"number",description:"Number of uses per voucher (for create_voucher, 0 = unlimited, default: 1)"}},required:["action"]}};config;site;controllerMode;cookies=[];csrfToken;constructor(e){if(super(),!e.apiKey&&!(e.username&&e.password))throw new Error('UniFi config requires either "apiKey" or both "username" and "password".');this.config=e,this.site=e.site??"default",e.apiKey&&(this.controllerMode="unifi-os")}async execute(e,t){let s=e.action;try{switch(s){case"list_devices":return await this.listDevices();case"device_info":return await this.deviceInfo(e.mac);case"list_clients":return await this.listClients(e.active);case"client_info":return await this.clientInfo(e.mac);case"list_networks":return await this.listNetworks();case"list_wlans":return await this.listWlans();case"site_stats":return await this.siteStats();case"dpi_stats":return await this.dpiStats(e.mac);case"list_alerts":return await this.listAlerts(e.limit);case"list_events":return await this.listEvents(e.limit);case"list_vouchers":return await this.listVouchers();case"restart_device":return await this.restartDevice(e.mac);case"locate_device":return await this.locateDevice(e.mac,e.enabled);case"reconnect_client":return await this.reconnectClient(e.mac);case"create_voucher":return await this.createVoucher(e.count,e.duration,e.bandwidth_down,e.bandwidth_up,e.quota);case"enable_wlan":return await this.enableWlan(e.id);case"disable_wlan":return await this.disableWlan(e.id);case"archive_alerts":return await this.archiveAlerts();case"block_client":return await this.blockClient(e.mac);case"unblock_client":return await this.unblockClient(e.mac);case"forget_client":return await this.forgetClient(e.mac);case"adopt_device":return await this.adoptDevice(e.mac);default:return{success:!1,error:`Unknown action: ${s}`}}}catch(r){return{success:!1,error:`UniFi error: ${r instanceof Error?r.message:String(r)}`}}}apiUrl(e){let t=this.config.baseUrl.replace(/\/+$/,"");return this.controllerMode==="unifi-os"?`${t}/proxy/network/api/s/${this.site}/${e}`:`${t}/api/s/${this.site}/${e}`}async ensureAuth(){this.config.apiKey||this.cookies.length>0||await this.login()}async login(){let e=this.config.baseUrl.replace(/\/+$/,""),t=JSON.stringify({username:this.config.username,password:this.config.password}),s=await this.rawFetch(`${e}/api/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(s.status===200){this.controllerMode="unifi-os",this.storeCookies(s);return}if(s.status===404){let r=await this.rawFetch(`${e}/api/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(r.ok){this.controllerMode="classic",this.storeCookies(r);return}throw new Error(`UniFi Classic login failed (HTTP ${r.status}): ${await r.text()}`)}throw new Error(`UniFi OS login failed (HTTP ${s.status}): ${await s.text()}`)}storeCookies(e){let t=e.headers.getSetCookie?.()??[];t.length>0&&(this.cookies=t.map(r=>r.split(";")[0]));let s=e.headers.get("x-csrf-token");s&&(this.csrfToken=s)}clearSession(){this.cookies=[],this.csrfToken=void 0}async rawFetch(e,t){let s=process.env.NODE_TLS_REJECT_UNAUTHORIZED;this.config.verifyTls===!1&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");try{return await fetch(e,t)}finally{this.config.verifyTls===!1&&(s===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=s)}}async request(e,t,s){await this.ensureAuth();let r=await this.doFetch(e,t,s);if(r.status===401&&!this.config.apiKey){this.clearSession(),await this.login();let o=await this.doFetch(e,t,s);if(!o.ok)throw new Error(`UniFi API error after relogin: HTTP ${o.status} ${await o.text()}`);return this.parseResponse(o)}if(!r.ok)throw new Error(`UniFi API error: HTTP ${r.status} ${await r.text()}`);return this.parseResponse(r)}async doFetch(e,t,s){let r=this.apiUrl(t),o={"Content-Type":"application/json"};return this.config.apiKey?o["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(o.Cookie=this.cookies.join("; ")),this.csrfToken&&(o["X-CSRF-Token"]=this.csrfToken)),this.rawFetch(r,{method:e,headers:o,body:s!==void 0?JSON.stringify(s):void 0,signal:AbortSignal.timeout(3e4)})}async parseResponse(e){let t=await e.json(),s=e.headers.get("x-csrf-token");if(s&&(this.csrfToken=s),t.meta?.rc==="error")throw new Error(`UniFi: ${t.meta.msg??"unknown error"}`);return t.data}async listDevices(){let e=await this.request("GET","stat/device"),t=(e??[]).map(r=>({name:r.name??r.hostname??r.mac,model:r.model??"unknown",ip:r.ip??"-",mac:r.mac,status:r.state===1?"online":"offline",clients:r.num_sta??0,load:r["system-stats"]?.cpu!=null?`${r["system-stats"].cpu}%`:"-"})),s=t.length===0?"No devices found.":["| Name | Model | IP | MAC | Status | Clients | CPU |","|------|-------|----|-----|--------|---------|-----|",...t.map(r=>`| ${r.name} | ${r.model} | ${r.ip} | ${r.mac} | ${r.status} | ${r.clients} | ${r.load} |`)].join(`
519
542
  `);return{success:!0,data:e,display:s}}async deviceInfo(e){if(!e)return{success:!1,error:"mac is required for device_info."};let s=(await this.request("GET",`stat/device/${e}`))?.[0];if(!s)return{success:!1,error:`Device ${e} not found.`};let r=[`**${s.name??s.hostname??e}**`,`- Model: ${s.model??"unknown"} (${s.model_in_lts?"LTS":s.model_in_eol?"EOL":"supported"})`,`- IP: ${s.ip??"-"}`,`- MAC: ${s.mac}`,`- Status: ${s.state===1?"online":"offline"}`,`- Version: ${s.version??"-"}`,`- Uptime: ${s.uptime?this.formatUptime(s.uptime):"-"}`,`- Clients: ${s.num_sta??0}`,`- CPU: ${s["system-stats"]?.cpu??"-"}%`,`- Memory: ${s["system-stats"]?.mem??"-"}%`,`- TX bytes: ${this.formatBytes(s.tx_bytes??0)}`,`- RX bytes: ${this.formatBytes(s.rx_bytes??0)}`];return{success:!0,data:s,display:r.join(`
520
- `)}}async listClients(e){let t=e!==!1,s=t?"stat/sta":"rest/user",r=await this.request("GET",s),n=(r??[]).map(i=>({name:i.name??i.hostname??i.mac,ip:i.ip??i.fixed_ip??"-",mac:i.mac,network:i.essid??i.network??"-",signal:i.signal!=null?`${i.signal} dBm`:"-",tx:this.formatBytes(i.tx_bytes??0),rx:this.formatBytes(i.rx_bytes??0)})),o=n.length===0?"No clients found.":["| Name | IP | MAC | Network | Signal | TX | RX |","|------|----|-----|---------|--------|----|----|",...n.map(i=>`| ${i.name} | ${i.ip} | ${i.mac} | ${i.network} | ${i.signal} | ${i.tx} | ${i.rx} |`)].join(`
521
- `);return{success:!0,data:r,display:`${t?"Active":"All known"} clients (${n.length}):
543
+ `)}}async listClients(e){let t=e!==!1,s=t?"stat/sta":"rest/user",r=await this.request("GET",s),o=(r??[]).map(i=>({name:i.name??i.hostname??i.mac,ip:i.ip??i.fixed_ip??"-",mac:i.mac,network:i.essid??i.network??"-",signal:i.signal!=null?`${i.signal} dBm`:"-",tx:this.formatBytes(i.tx_bytes??0),rx:this.formatBytes(i.rx_bytes??0)})),n=o.length===0?"No clients found.":["| Name | IP | MAC | Network | Signal | TX | RX |","|------|----|-----|---------|--------|----|----|",...o.map(i=>`| ${i.name} | ${i.ip} | ${i.mac} | ${i.network} | ${i.signal} | ${i.tx} | ${i.rx} |`)].join(`
544
+ `);return{success:!0,data:r,display:`${t?"Active":"All known"} clients (${o.length}):
522
545
 
523
- ${o}`}}async clientInfo(e){if(!e)return{success:!1,error:"mac is required for client_info."};let s=(await this.request("GET","stat/sta")??[]).find(n=>n.mac?.toLowerCase()===e.toLowerCase());if(!s)return{success:!1,error:`Client ${e} not found among active clients.`};let r=[`**${s.name??s.hostname??e}**`,`- IP: ${s.ip??"-"}`,`- MAC: ${s.mac}`,`- Network: ${s.essid??s.network??"-"}`,`- Signal: ${s.signal!=null?`${s.signal} dBm`:"-"}`,`- Satisfaction: ${s.satisfaction!=null?`${s.satisfaction}%`:"-"}`,`- TX rate: ${s.tx_rate!=null?`${(s.tx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- RX rate: ${s.rx_rate!=null?`${(s.rx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- TX bytes: ${this.formatBytes(s.tx_bytes??0)}`,`- RX bytes: ${this.formatBytes(s.rx_bytes??0)}`,`- Uptime: ${s.uptime?this.formatUptime(s.uptime):"-"}`,`- Blocked: ${s.blocked?"yes":"no"}`];return{success:!0,data:s,display:r.join(`
546
+ ${n}`}}async clientInfo(e){if(!e)return{success:!1,error:"mac is required for client_info."};let s=(await this.request("GET","stat/sta")??[]).find(o=>o.mac?.toLowerCase()===e.toLowerCase());if(!s)return{success:!1,error:`Client ${e} not found among active clients.`};let r=[`**${s.name??s.hostname??e}**`,`- IP: ${s.ip??"-"}`,`- MAC: ${s.mac}`,`- Network: ${s.essid??s.network??"-"}`,`- Signal: ${s.signal!=null?`${s.signal} dBm`:"-"}`,`- Satisfaction: ${s.satisfaction!=null?`${s.satisfaction}%`:"-"}`,`- TX rate: ${s.tx_rate!=null?`${(s.tx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- RX rate: ${s.rx_rate!=null?`${(s.rx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- TX bytes: ${this.formatBytes(s.tx_bytes??0)}`,`- RX bytes: ${this.formatBytes(s.rx_bytes??0)}`,`- Uptime: ${s.uptime?this.formatUptime(s.uptime):"-"}`,`- Blocked: ${s.blocked?"yes":"no"}`];return{success:!0,data:s,display:r.join(`
524
547
  `)}}async listNetworks(){let e=await this.request("GET","rest/networkconf"),t=(e??[]).map(r=>({name:r.name??"-",purpose:r.purpose??"-",vlan:r.vlan??"-",subnet:r.ip_subnet??"-",dhcp:r.dhcpd_enabled?"on":"off"})),s=t.length===0?"No networks found.":["| Name | Purpose | VLAN | Subnet | DHCP |","|------|---------|------|--------|------|",...t.map(r=>`| ${r.name} | ${r.purpose} | ${r.vlan} | ${r.subnet} | ${r.dhcp} |`)].join(`
525
548
  `);return{success:!0,data:e,display:s}}async listWlans(){let e=await this.request("GET","rest/wlanconf"),t=(e??[]).map(r=>({name:r.name??"-",id:r._id??"-",security:r.security??"-",band:r.wlan_band??"both",enabled:r.enabled!==!1?"yes":"no"})),s=t.length===0?"No WLANs found.":["| Name | ID | Security | Band | Enabled |","|------|----|----------|------|---------|",...t.map(r=>`| ${r.name} | ${r.id} | ${r.security} | ${r.band} | ${r.enabled} |`)].join(`
526
- `);return{success:!0,data:e,display:s}}async siteStats(){let e=this.config.baseUrl.replace(/\/+$/,"");await this.ensureAuth();let t;this.controllerMode==="unifi-os"?t=`${e}/proxy/network/api/stat/sites`:t=`${e}/api/stat/sites`;let s={"Content-Type":"application/json"};this.config.apiKey?s["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(s.Cookie=this.cookies.join("; ")),this.csrfToken&&(s["X-CSRF-Token"]=this.csrfToken));let r=await this.rawFetch(t,{method:"GET",headers:s,signal:AbortSignal.timeout(3e4)});if(!r.ok)throw new Error(`site_stats failed: HTTP ${r.status}`);let o=(await r.json()).data??[],i=o.map(a=>{let d=(a.health??[]).map(m=>` - ${m.subsystem}: ${m.status} (${m.num_user??0} users)`);return[`**${a.desc??a.name??"site"}**`,`- Devices: ${a.num_new_alarms??0} alarms`,...d].join(`
527
- `)});return{success:!0,data:o,display:i.join(`
528
-
529
- `)||"No site data."}}async dpiStats(e){let t=e?"stat/stadpi":"stat/sitedpi",s=e?{type:"by_app",macs:[e]}:{type:"by_app"},r=await this.request("POST",t,s);if(!r||r.length===0)return{success:!0,data:[],display:"No DPI data available."};let n=r.slice(0,20).map(o=>{let i=o.cat!=null?`Cat ${o.cat}`:"Unknown",a=o.app!=null?`App ${o.app}`:"";return`- ${i} ${a}: TX ${this.formatBytes(o.tx_bytes??0)}, RX ${this.formatBytes(o.rx_bytes??0)}`});return{success:!0,data:r,display:n.join(`
530
- `)||"No DPI data."}}async listAlerts(e){let t=Math.min(Math.max(1,e??20),200),s=await this.request("GET",`stat/alarm?_limit=${t}`),r=(s??[]).slice(0,t).map(o=>({time:o.datetime??o.time??"-",type:o.key??o.msg??"-",device:o.device_name??o.ap_name??o.mac??"-",archived:o.archived?"yes":"no"})),n=r.length===0?"No alerts.":["| Time | Type | Device | Archived |","|------|------|--------|----------|",...r.map(o=>`| ${o.time} | ${o.type} | ${o.device} | ${o.archived} |`)].join(`
531
- `);return{success:!0,data:s,display:n}}async listEvents(e){let t=Math.min(Math.max(1,e??20),200),s=await this.request("GET",`stat/event?_limit=${t}`),r=(s??[]).slice(0,t).map(o=>({time:o.datetime??o.time??"-",type:o.key??"-",message:o.msg??"-"})),n=r.length===0?"No events.":["| Time | Type | Message |","|------|------|---------|",...r.map(o=>`| ${o.time} | ${o.type} | ${o.message} |`)].join(`
532
- `);return{success:!0,data:s,display:n}}async listVouchers(){let e=await this.request("GET","stat/voucher"),t=(e??[]).map(r=>({code:r.code??"-",duration:r.duration!=null?`${r.duration} min`:"-",quota:r.quota??0,used:r.used??0,created:r.create_time?new Date(r.create_time*1e3).toISOString():"-",note:r.note??"-"})),s=t.length===0?"No vouchers.":["| Code | Duration | Quota | Used | Created | Note |","|------|----------|-------|------|---------|------|",...t.map(r=>`| ${r.code} | ${r.duration} | ${r.quota} | ${r.used} | ${r.created} | ${r.note} |`)].join(`
533
- `);return{success:!0,data:e,display:s}}async restartDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"restart",mac:e}),{success:!0,data:{mac:e},display:`Restart command sent to device ${e}.`}):{success:!1,error:"mac is required for restart_device."}}async locateDevice(e,t){if(!e)return{success:!1,error:"mac is required for locate_device."};let s=t!==!1,r=s?"set-locate":"unset-locate";return await this.request("POST","cmd/devmgr",{cmd:r,mac:e}),{success:!0,data:{mac:e,enabled:s},display:`Device ${e} locate LED ${s?"enabled":"disabled"}.`}}async reconnectClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"kick-sta",mac:e}),{success:!0,data:{mac:e},display:`Reconnect (kick) command sent to client ${e}.`}):{success:!1,error:"mac is required for reconnect_client."}}async createVoucher(e,t,s,r,n){if(!t)return{success:!1,error:"duration (minutes) is required for create_voucher."};let o={cmd:"create-voucher",n:e??1,expire:t,quota:n??1};s!=null&&(o.down=s),r!=null&&(o.up=r);let i=await this.request("POST","cmd/hotspot",o),a=i?.[0]?.create_time;return{success:!0,data:i,display:`Created ${e??1} voucher(s), duration ${t} min.${a?` Batch: ${a}`:""}
534
- Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!0}),{success:!0,data:{id:e,enabled:!0},display:`WLAN ${e} enabled.`}):{success:!1,error:"id is required for enable_wlan."}}async disableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!1}),{success:!0,data:{id:e,enabled:!1},display:`WLAN ${e} disabled.`}):{success:!1,error:"id is required for disable_wlan."}}async archiveAlerts(){return await this.request("POST","cmd/evtmgr",{cmd:"archive-all-alarms"}),{success:!0,data:{},display:"All alerts archived."}}async blockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"block-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} blocked.`}):{success:!1,error:"mac is required for block_client."}}async unblockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"unblock-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} unblocked.`}):{success:!1,error:"mac is required for unblock_client."}}async forgetClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"forget-sta",macs:[e]}),{success:!0,data:{mac:e},display:`Client ${e} forgotten (removed from known clients).`}):{success:!1,error:"mac is required for forget_client."}}async adoptDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"adopt",mac:e}),{success:!0,data:{mac:e},display:`Adopt command sent to device ${e}.`}):{success:!1,error:"mac is required for adopt_device."}}formatBytes(e){if(e===0)return"0 B";let t=["B","KB","MB","GB","TB"],s=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1);return`${(e/Math.pow(1024,s)).toFixed(s===0?0:1)} ${t[s]}`}formatUptime(e){let t=Math.floor(e/86400),s=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),n=[];return t>0&&n.push(`${t}d`),s>0&&n.push(`${s}h`),n.push(`${r}m`),n.join(" ")}}});function sa(c){let e=c.match(/^(\d+)\s*(h|d|m|w)$/i);if(!e)return new Date(Date.now()-36e5).toISOString();let t=parseInt(e[1],10),s=e[2].toLowerCase(),r={m:6e4,h:36e5,d:864e5,w:6048e5}[s]??36e5;return new Date(Date.now()-t*r).toISOString()}function El(c){let e=c.indexOf(".");if(e<1)throw new Error(`Invalid entity_id "${c}" \u2014 expected format "domain.name"`);return c.slice(0,e)}var pr,ra=b(()=>{"use strict";P();u(sa,"parsePeriod");u(El,"extractDomain");pr=class extends I{static{u(this,"HomeAssistantSkill")}metadata={name:"homeassistant",description:'Control Home Assistant smart home devices. Use "states" to list entities, "turn_on"/"turn_off"/"toggle" to control devices, "call_service" for advanced service calls, "history" for entity state history. Also: "areas" for rooms/zones, "presence" for who is home, "activate_scene"/"trigger_automation"/"run_script" for automations, "notify" for notifications, "calendar_events" for calendars, "template" for Jinja2 queries, "error_log" for HA logs.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["states","state","turn_on","turn_off","toggle","call_service","services","history","logbook","config","areas","template","presence","notify","activate_scene","trigger_automation","run_script","calendar_events","error_log"],description:"The Home Assistant action to perform"},entityId:{type:"string",description:"Entity ID, e.g. light.wohnzimmer, switch.garage, sensor.temperature"},domain:{type:"string",description:'Domain filter for "states" (e.g. light, sensor, switch) or domain for "call_service"'},service:{type:"string",description:'Service name for "call_service", e.g. set_temperature, set_hvac_mode'},serviceData:{type:"string",description:'JSON string with service parameters, e.g. {"brightness": 200, "color_name": "red"}'},period:{type:"string",description:"Time period for history/logbook, e.g. 1h, 24h, 7d (default: 1h)"},area:{type:"string",description:"Area name or ID (for areas action)"},template:{type:"string",description:"Jinja2 template string (for template action)"},target:{type:"string",description:"Notification target (for notify action, e.g. mobile_app_pixel)"},message:{type:"string",description:"Notification message (for notify action)"},title:{type:"string",description:"Optional title (for notify action)"},startTime:{type:"string",description:"ISO datetime start (for calendar_events, default: now)"},endTime:{type:"string",description:"ISO datetime end (for calendar_events, default: +24h)"},subAction:{type:"string",enum:["trigger","enable","disable"],description:"Sub-action for trigger_automation"},variables:{type:"string",description:"JSON string with script variables (for run_script)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"states":return await this.getStates(e.domain);case"state":return await this.getState(e.entityId);case"turn_on":return await this.switchAction("turn_on",e.entityId,e.serviceData);case"turn_off":return await this.switchAction("turn_off",e.entityId,e.serviceData);case"toggle":return await this.switchAction("toggle",e.entityId,e.serviceData);case"call_service":return await this.callService(e.domain,e.service,e.entityId,e.serviceData);case"services":return await this.getServices();case"history":return await this.getHistory(e.entityId,e.period);case"logbook":return await this.getLogbook(e.entityId,e.period);case"config":return await this.getConfig();case"areas":return await this.getAreas(e.area);case"template":return await this.renderTemplate(e.template);case"presence":return await this.getPresence();case"notify":return await this.sendNotification(e.message,e.title,e.target);case"activate_scene":return await this.activateScene(e.entityId);case"trigger_automation":return await this.triggerAutomation(e.entityId,e.subAction);case"run_script":return await this.runScript(e.entityId,e.variables);case"calendar_events":return await this.getCalendarEvents(e.entityId,e.startTime,e.endTime);case"error_log":return await this.getErrorLog();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Home Assistant API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl.replace(/\/+$/,"")}${t}`,n={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},o={method:e,headers:n,signal:AbortSignal.timeout(15e3)};s&&e!=="GET"&&(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 d="";try{d=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${d}`)}return await l.json()}async apiText(e,t,s){let r=`${this.config.baseUrl.replace(/\/+$/,"")}${t}`,n={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},o={method:e,headers:n,signal:AbortSignal.timeout(15e3)};s&&e!=="GET"&&(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 d="";try{d=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${d}`)}return await l.text()}async getStates(e){let t=await this.api("GET","/api/states");e&&(t=t.filter(r=>r.entity_id.startsWith(`${e}.`)));let s=[`## Entities${e?` (${e})`:""}`,"","| Entity ID | State | Name | Unit |","|-----------|-------|------|------|"];for(let r of t){let n=r.attributes?.friendly_name??"-",o=r.attributes?.unit_of_measurement??"-";s.push(`| ${r.entity_id} | ${r.state} | ${n} | ${o} |`)}return t.length===0&&s.push(`| - | No entities found${e?` for domain "${e}"`:""} | - | - |`),{success:!0,data:t,display:s.join(`
535
- `)}}async getState(e){if(!e)return{success:!1,error:'Missing required "entityId" parameter'};let t=await this.api("GET",`/api/states/${e}`),s=t.attributes??{},r=[`## ${s.friendly_name??e}`,"",`**Entity ID:** ${t.entity_id}`,`**State:** ${t.state}`,`**Last Changed:** ${t.last_changed??"-"}`,`**Last Updated:** ${t.last_updated??"-"}`,"","### Attributes"];for(let[n,o]of Object.entries(s)){let i=typeof o=="object"?JSON.stringify(o):String(o);r.push(`- **${n}:** ${i}`)}return{success:!0,data:t,display:r.join(`
536
- `)}}async getServices(){let e=await this.api("GET","/api/services"),t=["## Available Services",""];for(let s of e){let r=s.domain??"unknown",n=Object.keys(s.services??{});if(n.length!==0){t.push(`### ${r}`);for(let o of n){let i=s.services[o]?.description??"";t.push(`- **${o}**${i?`: ${i}`:""}`)}t.push("")}}return{success:!0,data:e,display:t.join(`
537
- `)}}async getHistory(e,t){let s=sa(t??"1h"),r=e?`?filter_entity_id=${e}`:"",n=await this.api("GET",`/api/history/period/${s}${r}`),o=["## History",""];if(!n||n.length===0||n.every(i=>i.length===0))return o.push("No history entries found for the given period."),{success:!0,data:[],display:o.join(`
538
- `)};for(let i of n){if(i.length===0)continue;let a=i[0]?.entity_id??"unknown",l=i[0]?.attributes?.friendly_name??a;o.push(`### ${l} (\`${a}\`)`),o.push(""),o.push("| Time | State |"),o.push("|------|-------|");for(let d of i){let m=d.last_changed?new Date(d.last_changed).toLocaleString():"-";o.push(`| ${m} | ${d.state} |`)}o.push("")}return{success:!0,data:n,display:o.join(`
539
- `)}}async getLogbook(e,t){let s=sa(t??"1h"),r=e?`?entity=${e}`:"",n=await this.api("GET",`/api/logbook/${s}${r}`),o=["## Logbook",""];if(!n||n.length===0)return o.push("No logbook entries found for the given period."),{success:!0,data:[],display:o.join(`
540
- `)};o.push("| Time | Entity | Message |"),o.push("|------|--------|---------|");for(let i of n){let a=i.when?new Date(i.when).toLocaleString():"-",l=i.name??i.entity_id??"-",d=i.message??i.state??"-";o.push(`| ${a} | ${l} | ${d} |`)}return{success:!0,data:n,display:o.join(`
549
+ `);return{success:!0,data:e,display:s}}async siteStats(){let e=this.config.baseUrl.replace(/\/+$/,"");await this.ensureAuth();let t;this.controllerMode==="unifi-os"?t=`${e}/proxy/network/api/stat/sites`:t=`${e}/api/stat/sites`;let s={"Content-Type":"application/json"};this.config.apiKey?s["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(s.Cookie=this.cookies.join("; ")),this.csrfToken&&(s["X-CSRF-Token"]=this.csrfToken));let r=await this.rawFetch(t,{method:"GET",headers:s,signal:AbortSignal.timeout(3e4)});if(!r.ok)throw new Error(`site_stats failed: HTTP ${r.status}`);let n=(await r.json()).data??[],i=n.map(a=>{let d=(a.health??[]).map(m=>` - ${m.subsystem}: ${m.status} (${m.num_user??0} users)`);return[`**${a.desc??a.name??"site"}**`,`- Devices: ${a.num_new_alarms??0} alarms`,...d].join(`
550
+ `)});return{success:!0,data:n,display:i.join(`
551
+
552
+ `)||"No site data."}}async dpiStats(e){let t=e?"stat/stadpi":"stat/sitedpi",s=e?{type:"by_app",macs:[e]}:{type:"by_app"},r=await this.request("POST",t,s);if(!r||r.length===0)return{success:!0,data:[],display:"No DPI data available."};let o=r.slice(0,20).map(n=>{let i=n.cat!=null?`Cat ${n.cat}`:"Unknown",a=n.app!=null?`App ${n.app}`:"";return`- ${i} ${a}: TX ${this.formatBytes(n.tx_bytes??0)}, RX ${this.formatBytes(n.rx_bytes??0)}`});return{success:!0,data:r,display:o.join(`
553
+ `)||"No DPI data."}}async listAlerts(e){let t=Math.min(Math.max(1,e??20),200),s=await this.request("GET",`stat/alarm?_limit=${t}`),r=(s??[]).slice(0,t).map(n=>({time:n.datetime??n.time??"-",type:n.key??n.msg??"-",device:n.device_name??n.ap_name??n.mac??"-",archived:n.archived?"yes":"no"})),o=r.length===0?"No alerts.":["| Time | Type | Device | Archived |","|------|------|--------|----------|",...r.map(n=>`| ${n.time} | ${n.type} | ${n.device} | ${n.archived} |`)].join(`
554
+ `);return{success:!0,data:s,display:o}}async listEvents(e){let t=Math.min(Math.max(1,e??20),200),s=await this.request("GET",`stat/event?_limit=${t}`),r=(s??[]).slice(0,t).map(n=>({time:n.datetime??n.time??"-",type:n.key??"-",message:n.msg??"-"})),o=r.length===0?"No events.":["| Time | Type | Message |","|------|------|---------|",...r.map(n=>`| ${n.time} | ${n.type} | ${n.message} |`)].join(`
555
+ `);return{success:!0,data:s,display:o}}async listVouchers(){let e=await this.request("GET","stat/voucher"),t=(e??[]).map(r=>({code:r.code??"-",duration:r.duration!=null?`${r.duration} min`:"-",quota:r.quota??0,used:r.used??0,created:r.create_time?new Date(r.create_time*1e3).toISOString():"-",note:r.note??"-"})),s=t.length===0?"No vouchers.":["| Code | Duration | Quota | Used | Created | Note |","|------|----------|-------|------|---------|------|",...t.map(r=>`| ${r.code} | ${r.duration} | ${r.quota} | ${r.used} | ${r.created} | ${r.note} |`)].join(`
556
+ `);return{success:!0,data:e,display:s}}async restartDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"restart",mac:e}),{success:!0,data:{mac:e},display:`Restart command sent to device ${e}.`}):{success:!1,error:"mac is required for restart_device."}}async locateDevice(e,t){if(!e)return{success:!1,error:"mac is required for locate_device."};let s=t!==!1,r=s?"set-locate":"unset-locate";return await this.request("POST","cmd/devmgr",{cmd:r,mac:e}),{success:!0,data:{mac:e,enabled:s},display:`Device ${e} locate LED ${s?"enabled":"disabled"}.`}}async reconnectClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"kick-sta",mac:e}),{success:!0,data:{mac:e},display:`Reconnect (kick) command sent to client ${e}.`}):{success:!1,error:"mac is required for reconnect_client."}}async createVoucher(e,t,s,r,o){if(!t)return{success:!1,error:"duration (minutes) is required for create_voucher."};let n={cmd:"create-voucher",n:e??1,expire:t,quota:o??1};s!=null&&(n.down=s),r!=null&&(n.up=r);let i=await this.request("POST","cmd/hotspot",n),a=i?.[0]?.create_time;return{success:!0,data:i,display:`Created ${e??1} voucher(s), duration ${t} min.${a?` Batch: ${a}`:""}
557
+ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!0}),{success:!0,data:{id:e,enabled:!0},display:`WLAN ${e} enabled.`}):{success:!1,error:"id is required for enable_wlan."}}async disableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!1}),{success:!0,data:{id:e,enabled:!1},display:`WLAN ${e} disabled.`}):{success:!1,error:"id is required for disable_wlan."}}async archiveAlerts(){return await this.request("POST","cmd/evtmgr",{cmd:"archive-all-alarms"}),{success:!0,data:{},display:"All alerts archived."}}async blockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"block-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} blocked.`}):{success:!1,error:"mac is required for block_client."}}async unblockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"unblock-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} unblocked.`}):{success:!1,error:"mac is required for unblock_client."}}async forgetClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"forget-sta",macs:[e]}),{success:!0,data:{mac:e},display:`Client ${e} forgotten (removed from known clients).`}):{success:!1,error:"mac is required for forget_client."}}async adoptDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"adopt",mac:e}),{success:!0,data:{mac:e},display:`Adopt command sent to device ${e}.`}):{success:!1,error:"mac is required for adopt_device."}}formatBytes(e){if(e===0)return"0 B";let t=["B","KB","MB","GB","TB"],s=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1);return`${(e/Math.pow(1024,s)).toFixed(s===0?0:1)} ${t[s]}`}formatUptime(e){let t=Math.floor(e/86400),s=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),o=[];return t>0&&o.push(`${t}d`),s>0&&o.push(`${s}h`),o.push(`${r}m`),o.join(" ")}}});function Na(c){let e=c.match(/^(\d+)\s*(h|d|m|w)$/i);if(!e)return new Date(Date.now()-36e5).toISOString();let t=parseInt(e[1],10),s=e[2].toLowerCase(),r={m:6e4,h:36e5,d:864e5,w:6048e5}[s]??36e5;return new Date(Date.now()-t*r).toISOString()}function Td(c){let e=c.indexOf(".");if(e<1)throw new Error(`Invalid entity_id "${c}" \u2014 expected format "domain.name"`);return c.slice(0,e)}var Ir,Ma=y(()=>{"use strict";j();u(Na,"parsePeriod");u(Td,"extractDomain");Ir=class extends I{static{u(this,"HomeAssistantSkill")}metadata={name:"homeassistant",description:'Control Home Assistant smart home devices. Use "states" to list entities, "turn_on"/"turn_off"/"toggle" to control devices, "call_service" for advanced service calls, "history" for entity state history. Also: "areas" for rooms/zones, "presence" for who is home, "activate_scene"/"trigger_automation"/"run_script" for automations, "notify" for notifications, "calendar_events" for calendars, "template" for Jinja2 queries, "error_log" for HA logs.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["states","state","turn_on","turn_off","toggle","call_service","services","history","logbook","config","areas","template","presence","notify","activate_scene","trigger_automation","run_script","calendar_events","error_log"],description:"The Home Assistant action to perform"},entityId:{type:"string",description:"Entity ID, e.g. light.wohnzimmer, switch.garage, sensor.temperature"},domain:{type:"string",description:'Domain filter for "states" (e.g. light, sensor, switch) or domain for "call_service"'},service:{type:"string",description:'Service name for "call_service", e.g. set_temperature, set_hvac_mode'},serviceData:{type:"string",description:'JSON string with service parameters, e.g. {"brightness": 200, "color_name": "red"}'},period:{type:"string",description:"Time period for history/logbook, e.g. 1h, 24h, 7d (default: 1h)"},area:{type:"string",description:"Area name or ID (for areas action)"},template:{type:"string",description:"Jinja2 template string (for template action)"},target:{type:"string",description:"Notification target (for notify action, e.g. mobile_app_pixel)"},message:{type:"string",description:"Notification message (for notify action)"},title:{type:"string",description:"Optional title (for notify action)"},startTime:{type:"string",description:"ISO datetime start (for calendar_events, default: now)"},endTime:{type:"string",description:"ISO datetime end (for calendar_events, default: +24h)"},subAction:{type:"string",enum:["trigger","enable","disable"],description:"Sub-action for trigger_automation"},variables:{type:"string",description:"JSON string with script variables (for run_script)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"states":return await this.getStates(e.domain);case"state":return await this.getState(e.entityId);case"turn_on":return await this.switchAction("turn_on",e.entityId,e.serviceData);case"turn_off":return await this.switchAction("turn_off",e.entityId,e.serviceData);case"toggle":return await this.switchAction("toggle",e.entityId,e.serviceData);case"call_service":return await this.callService(e.domain,e.service,e.entityId,e.serviceData);case"services":return await this.getServices();case"history":return await this.getHistory(e.entityId,e.period);case"logbook":return await this.getLogbook(e.entityId,e.period);case"config":return await this.getConfig();case"areas":return await this.getAreas(e.area);case"template":return await this.renderTemplate(e.template);case"presence":return await this.getPresence();case"notify":return await this.sendNotification(e.message,e.title,e.target);case"activate_scene":return await this.activateScene(e.entityId);case"trigger_automation":return await this.triggerAutomation(e.entityId,e.subAction);case"run_script":return await this.runScript(e.entityId,e.variables);case"calendar_events":return await this.getCalendarEvents(e.entityId,e.startTime,e.endTime);case"error_log":return await this.getErrorLog();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Home Assistant API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl.replace(/\/+$/,"")}${t}`,o={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n={method:e,headers:o,signal:AbortSignal.timeout(15e3)};s&&e!=="GET"&&(n.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,n)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let d="";try{d=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${d}`)}return await l.json()}async apiText(e,t,s){let r=`${this.config.baseUrl.replace(/\/+$/,"")}${t}`,o={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n={method:e,headers:o,signal:AbortSignal.timeout(15e3)};s&&e!=="GET"&&(n.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,n)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let d="";try{d=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${d}`)}return await l.text()}async getStates(e){let t=await this.api("GET","/api/states");e&&(t=t.filter(r=>r.entity_id.startsWith(`${e}.`)));let s=[`## Entities${e?` (${e})`:""}`,"","| Entity ID | State | Name | Unit |","|-----------|-------|------|------|"];for(let r of t){let o=r.attributes?.friendly_name??"-",n=r.attributes?.unit_of_measurement??"-";s.push(`| ${r.entity_id} | ${r.state} | ${o} | ${n} |`)}return t.length===0&&s.push(`| - | No entities found${e?` for domain "${e}"`:""} | - | - |`),{success:!0,data:t,display:s.join(`
558
+ `)}}async getState(e){if(!e)return{success:!1,error:'Missing required "entityId" parameter'};let t=await this.api("GET",`/api/states/${e}`),s=t.attributes??{},r=[`## ${s.friendly_name??e}`,"",`**Entity ID:** ${t.entity_id}`,`**State:** ${t.state}`,`**Last Changed:** ${t.last_changed??"-"}`,`**Last Updated:** ${t.last_updated??"-"}`,"","### Attributes"];for(let[o,n]of Object.entries(s)){let i=typeof n=="object"?JSON.stringify(n):String(n);r.push(`- **${o}:** ${i}`)}return{success:!0,data:t,display:r.join(`
559
+ `)}}async getServices(){let e=await this.api("GET","/api/services"),t=["## Available Services",""];for(let s of e){let r=s.domain??"unknown",o=Object.keys(s.services??{});if(o.length!==0){t.push(`### ${r}`);for(let n of o){let i=s.services[n]?.description??"";t.push(`- **${n}**${i?`: ${i}`:""}`)}t.push("")}}return{success:!0,data:e,display:t.join(`
560
+ `)}}async getHistory(e,t){let s=Na(t??"1h"),r=e?`?filter_entity_id=${e}`:"",o=await this.api("GET",`/api/history/period/${s}${r}`),n=["## History",""];if(!o||o.length===0||o.every(i=>i.length===0))return n.push("No history entries found for the given period."),{success:!0,data:[],display:n.join(`
561
+ `)};for(let i of o){if(i.length===0)continue;let a=i[0]?.entity_id??"unknown",l=i[0]?.attributes?.friendly_name??a;n.push(`### ${l} (\`${a}\`)`),n.push(""),n.push("| Time | State |"),n.push("|------|-------|");for(let d of i){let m=d.last_changed?new Date(d.last_changed).toLocaleString():"-";n.push(`| ${m} | ${d.state} |`)}n.push("")}return{success:!0,data:o,display:n.join(`
562
+ `)}}async getLogbook(e,t){let s=Na(t??"1h"),r=e?`?entity=${e}`:"",o=await this.api("GET",`/api/logbook/${s}${r}`),n=["## Logbook",""];if(!o||o.length===0)return n.push("No logbook entries found for the given period."),{success:!0,data:[],display:n.join(`
563
+ `)};n.push("| Time | Entity | Message |"),n.push("|------|--------|---------|");for(let i of o){let a=i.when?new Date(i.when).toLocaleString():"-",l=i.name??i.entity_id??"-",d=i.message??i.state??"-";n.push(`| ${a} | ${l} | ${d} |`)}return{success:!0,data:o,display:n.join(`
541
564
  `)}}async getConfig(){let e=await this.api("GET","/api/config"),t=["## Home Assistant Configuration","",`**Name:** ${e.location_name??"-"}`,`**Version:** ${e.version??"-"}`,`**Time Zone:** ${e.time_zone??"-"}`,`**Latitude:** ${e.latitude??"-"}`,`**Longitude:** ${e.longitude??"-"}`,`**Elevation:** ${e.elevation??"-"} m`,`**Unit System:** ${e.unit_system?.length?JSON.stringify(e.unit_system):"-"}`,`**Currency:** ${e.currency??"-"}`,`**Internal URL:** ${e.internal_url??"-"}`,`**External URL:** ${e.external_url??"-"}`];return e.components&&Array.isArray(e.components)&&t.push("",`**Components:** ${e.components.length} loaded`),{success:!0,data:e,display:t.join(`
542
- `)}}async switchAction(e,t,s){if(!t)return{success:!1,error:'Missing required "entityId" parameter'};let r=El(t),n={entity_id:t};if(s)try{let l=JSON.parse(s);Object.assign(n,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let o=await this.api("POST",`/api/services/${r}/${e}`,n),i=o?.[0]?.state??"unknown",a=o?.[0]?.attributes?.friendly_name??t;return{success:!0,data:o,display:[`**${e.replace("_"," ")}** \u2192 **${a}**`,"",`New state: **${i}**`].join(`
543
- `)}}async callService(e,t,s,r){if(!e)return{success:!1,error:'Missing required "domain" parameter for call_service'};if(!t)return{success:!1,error:'Missing required "service" parameter for call_service'};let n={};if(s&&(n.entity_id=s),r)try{let l=JSON.parse(r);Object.assign(n,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let o=await this.api("POST",`/api/services/${e}/${t}`,n),i=o?.length??0,a=[`**Service called:** \`${e}.${t}\``,s?`**Entity:** ${s}`:"",`**Affected entities:** ${i}`].filter(Boolean);if(o&&o.length>0){a.push("");for(let l of o){let d=l.attributes?.friendly_name??l.entity_id??"unknown";a.push(`- **${d}**: ${l.state}`)}}return{success:!0,data:o,display:a.join(`
544
- `)}}async getAreas(e){if(e){let o=`{% for eid in area_entities('${e.replace(/'/g,"\\'")}') %}{{ eid }}||{{ states(eid) }}||{{ state_attr(eid, 'friendly_name') }}
545
- {% endfor %}`,a=(await this.apiText("POST","/api/template",{template:o})).trim().split(`
546
- `).filter(Boolean),l=[`## Area: ${e}`,"","| Entity ID | State | Name |","|-----------|-------|------|"];for(let d of a){let[m,h,w]=d.split("||");l.push(`| ${m} | ${h} | ${w??"-"} |`)}return a.length===0&&l.push(`| - | No entities found for area "${e}" | - |`),{success:!0,data:a,display:l.join(`
565
+ `)}}async switchAction(e,t,s){if(!t)return{success:!1,error:'Missing required "entityId" parameter'};let r=Td(t),o={entity_id:t};if(s)try{let l=JSON.parse(s);Object.assign(o,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let n=await this.api("POST",`/api/services/${r}/${e}`,o),i=n?.[0]?.state??"unknown",a=n?.[0]?.attributes?.friendly_name??t;return{success:!0,data:n,display:[`**${e.replace("_"," ")}** \u2192 **${a}**`,"",`New state: **${i}**`].join(`
566
+ `)}}async callService(e,t,s,r){if(!e)return{success:!1,error:'Missing required "domain" parameter for call_service'};if(!t)return{success:!1,error:'Missing required "service" parameter for call_service'};let o={};if(s&&(o.entity_id=s),r)try{let l=JSON.parse(r);Object.assign(o,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let n=await this.api("POST",`/api/services/${e}/${t}`,o),i=n?.length??0,a=[`**Service called:** \`${e}.${t}\``,s?`**Entity:** ${s}`:"",`**Affected entities:** ${i}`].filter(Boolean);if(n&&n.length>0){a.push("");for(let l of n){let d=l.attributes?.friendly_name??l.entity_id??"unknown";a.push(`- **${d}**: ${l.state}`)}}return{success:!0,data:n,display:a.join(`
567
+ `)}}async getAreas(e){if(e){let n=`{% for eid in area_entities('${e.replace(/'/g,"\\'")}') %}{{ eid }}||{{ states(eid) }}||{{ state_attr(eid, 'friendly_name') }}
568
+ {% endfor %}`,a=(await this.apiText("POST","/api/template",{template:n})).trim().split(`
569
+ `).filter(Boolean),l=[`## Area: ${e}`,"","| Entity ID | State | Name |","|-----------|-------|------|"];for(let d of a){let[m,p,w]=d.split("||");l.push(`| ${m} | ${p} | ${w??"-"} |`)}return a.length===0&&l.push(`| - | No entities found for area "${e}" | - |`),{success:!0,data:a,display:l.join(`
547
570
  `)}}let r=(await this.apiText("POST","/api/template",{template:`{% for aid in areas() %}{{ area_name(aid) }}||{{ aid }}||{{ area_entities(aid) | length }}
548
571
  {% endfor %}`})).trim().split(`
549
- `).filter(Boolean),n=["## Areas","","| Area Name | Area ID | Entity Count |","|-----------|---------|--------------|"];for(let o of r){let[i,a,l]=o.split("||");n.push(`| ${i} | ${a} | ${l} |`)}return r.length===0&&n.push("| - | No areas configured | - |"),{success:!0,data:r,display:n.join(`
550
- `)}}async renderTemplate(e){if(!e)return{success:!1,error:'Missing required "template" parameter'};let t=await this.apiText("POST","/api/template",{template:e});return{success:!0,data:t,display:t}}async getPresence(){let t=(await this.api("GET","/api/states")).filter(r=>r.entity_id.startsWith("person.")),s=["## Presence","","| Person | Status | Last Changed |","|--------|--------|--------------|"];for(let r of t){let n=r.attributes?.friendly_name??r.entity_id,o=r.state??"unknown",i=r.last_changed?new Date(r.last_changed).toLocaleString():"-";s.push(`| ${n} | ${o} | ${i} |`)}return t.length===0&&s.push("| - | No person entities found | - |"),{success:!0,data:t,display:s.join(`
551
- `)}}async sendNotification(e,t,s){if(!e)return{success:!1,error:'Missing required "message" parameter'};let r=s??"notify",n={message:e};return t&&(n.title=t),{success:!0,data:await this.api("POST",`/api/services/notify/${r}`,n),display:[`**Notification sent** \u2192 \`notify.${r}\``,t?`**Title:** ${t}`:"",`**Message:** ${e.slice(0,200)}${e.length>200?"\u2026":""}`].filter(Boolean).join(`
552
- `)}}async activateScene(e){if(!e){let n=(await this.api("GET","/api/states")).filter(i=>i.entity_id.startsWith("scene.")),o=["## Available Scenes","","| Entity ID | Name |","|-----------|------|"];for(let i of n){let a=i.attributes?.friendly_name??i.entity_id;o.push(`| ${i.entity_id} | ${a} |`)}return n.length===0&&o.push("| - | No scenes found |"),{success:!0,data:n,display:o.join(`
553
- `)}}let t=await this.api("POST","/api/services/scene/turn_on",{entity_id:e}),s=t?.[0]?.attributes?.friendly_name??e;return{success:!0,data:t,display:`**Scene activated:** ${s} (\`${e}\`)`}}async triggerAutomation(e,t){if(!e){let d=(await this.api("GET","/api/states")).filter(h=>h.entity_id.startsWith("automation.")),m=["## Automations","","| Entity ID | Name | State | Last Triggered |","|-----------|------|-------|----------------|"];for(let h of d){let w=h.attributes?.friendly_name??h.entity_id,y=h.attributes?.last_triggered?new Date(h.attributes.last_triggered).toLocaleString():"-";m.push(`| ${h.entity_id} | ${w} | ${h.state} | ${y} |`)}return d.length===0&&m.push("| - | No automations found | - | - |"),{success:!0,data:d,display:m.join(`
554
- `)}}let s={trigger:"trigger",enable:"turn_on",disable:"turn_off"},r=t??"trigger",n=s[r]??"trigger",o=await this.api("POST",`/api/services/automation/${n}`,{entity_id:e}),i=o?.[0]?.attributes?.friendly_name??e,a=o?.[0]?.attributes?.last_triggered?new Date(o[0].attributes.last_triggered).toLocaleString():"-";return{success:!0,data:o,display:[`**Automation ${r}:** ${i} (\`${e}\`)`,`**Last triggered:** ${a}`].join(`
572
+ `).filter(Boolean),o=["## Areas","","| Area Name | Area ID | Entity Count |","|-----------|---------|--------------|"];for(let n of r){let[i,a,l]=n.split("||");o.push(`| ${i} | ${a} | ${l} |`)}return r.length===0&&o.push("| - | No areas configured | - |"),{success:!0,data:r,display:o.join(`
573
+ `)}}async renderTemplate(e){if(!e)return{success:!1,error:'Missing required "template" parameter'};let t=await this.apiText("POST","/api/template",{template:e});return{success:!0,data:t,display:t}}async getPresence(){let t=(await this.api("GET","/api/states")).filter(r=>r.entity_id.startsWith("person.")),s=["## Presence","","| Person | Status | Last Changed |","|--------|--------|--------------|"];for(let r of t){let o=r.attributes?.friendly_name??r.entity_id,n=r.state??"unknown",i=r.last_changed?new Date(r.last_changed).toLocaleString():"-";s.push(`| ${o} | ${n} | ${i} |`)}return t.length===0&&s.push("| - | No person entities found | - |"),{success:!0,data:t,display:s.join(`
574
+ `)}}async sendNotification(e,t,s){if(!e)return{success:!1,error:'Missing required "message" parameter'};let r=s??"notify",o={message:e};return t&&(o.title=t),{success:!0,data:await this.api("POST",`/api/services/notify/${r}`,o),display:[`**Notification sent** \u2192 \`notify.${r}\``,t?`**Title:** ${t}`:"",`**Message:** ${e.slice(0,200)}${e.length>200?"\u2026":""}`].filter(Boolean).join(`
575
+ `)}}async activateScene(e){if(!e){let o=(await this.api("GET","/api/states")).filter(i=>i.entity_id.startsWith("scene.")),n=["## Available Scenes","","| Entity ID | Name |","|-----------|------|"];for(let i of o){let a=i.attributes?.friendly_name??i.entity_id;n.push(`| ${i.entity_id} | ${a} |`)}return o.length===0&&n.push("| - | No scenes found |"),{success:!0,data:o,display:n.join(`
576
+ `)}}let t=await this.api("POST","/api/services/scene/turn_on",{entity_id:e}),s=t?.[0]?.attributes?.friendly_name??e;return{success:!0,data:t,display:`**Scene activated:** ${s} (\`${e}\`)`}}async triggerAutomation(e,t){if(!e){let d=(await this.api("GET","/api/states")).filter(p=>p.entity_id.startsWith("automation.")),m=["## Automations","","| Entity ID | Name | State | Last Triggered |","|-----------|------|-------|----------------|"];for(let p of d){let w=p.attributes?.friendly_name??p.entity_id,T=p.attributes?.last_triggered?new Date(p.attributes.last_triggered).toLocaleString():"-";m.push(`| ${p.entity_id} | ${w} | ${p.state} | ${T} |`)}return d.length===0&&m.push("| - | No automations found | - | - |"),{success:!0,data:d,display:m.join(`
577
+ `)}}let s={trigger:"trigger",enable:"turn_on",disable:"turn_off"},r=t??"trigger",o=s[r]??"trigger",n=await this.api("POST",`/api/services/automation/${o}`,{entity_id:e}),i=n?.[0]?.attributes?.friendly_name??e,a=n?.[0]?.attributes?.last_triggered?new Date(n[0].attributes.last_triggered).toLocaleString():"-";return{success:!0,data:n,display:[`**Automation ${r}:** ${i} (\`${e}\`)`,`**Last triggered:** ${a}`].join(`
555
578
  `)}}async runScript(e,t){if(!e){let i=(await this.api("GET","/api/states")).filter(l=>l.entity_id.startsWith("script.")),a=["## Scripts","","| Entity ID | Name | State |","|-----------|------|-------|"];for(let l of i){let d=l.attributes?.friendly_name??l.entity_id;a.push(`| ${l.entity_id} | ${d} | ${l.state} |`)}return i.length===0&&a.push("| - | No scripts found | - |"),{success:!0,data:i,display:a.join(`
556
579
  `)}}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(`
557
- `)}}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(`
580
+ `)}}let r=t??new Date().toISOString(),o=s??new Date(Date.now()+864e5).toISOString(),n=await this.api("GET",`/api/calendars/${e}?start=${encodeURIComponent(r)}&end=${encodeURIComponent(o)}`),i=[`## Calendar Events: ${e}`,"","| Start | End | Summary | Location |","|-------|-----|---------|----------|"];for(let a of n){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 n.length===0&&i.push("| - | - | No events in range | - |"),{success:!0,data:n,display:i.join(`
558
581
  `)}}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(`
559
- `)}}}});import Cn from"node:fs";import na from"node:path";function oa(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function $l(){let c=process.cwd();for(let e=0;e<10;e++){let t=na.join(c,".env");if(Cn.existsSync(t))return t;let s=na.dirname(c);if(s===c)break;c=s}return null}var Lt,Mt,ia=b(()=>{"use strict";P();Lt={proxmox:{label:"Proxmox VE",fields:[{env:"ALFRED_PROXMOX_BASE_URL",label:"Base URL (e.g. https://pve.local:8006)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_ID",label:"API Token ID (user@realm!name)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_SECRET",label:"API Token Secret",required:!0,secret:!0}]},unifi:{label:"UniFi Network",fields:[{env:"ALFRED_UNIFI_BASE_URL",label:"Base URL (e.g. https://unifi.local)",required:!0},{env:"ALFRED_UNIFI_API_KEY",label:"API Key (preferred, UniFi OS)",secret:!0},{env:"ALFRED_UNIFI_USERNAME",label:"Username (alternative to API key)"},{env:"ALFRED_UNIFI_PASSWORD",label:"Password (alternative to API key)",secret:!0},{env:"ALFRED_UNIFI_SITE",label:'Site name (default: "default")'}]}},Mt=class extends I{static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",description:'Configure Alfred services (Proxmox, UniFi, etc.) by writing environment variables. Use action "list_services" to see available services. Use action "show" to check current config of a service. Use action "set" to write config \u2014 provide service name and values. After setting config, the service is activated immediately \u2014 no restart needed.',riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_services","show","set"],description:"Action to perform"},service:{type:"string",enum:["proxmox","unifi"],description:"Service to configure (required for show/set)"},values:{type:"object",description:'Key-value pairs to set. Keys are the ENV variable names (e.g. ALFRED_PROXMOX_BASE_URL). Only for action "set".'}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"list_services":return this.listServices();case"show":return this.showService(e.service);case"set":return this.setService(e.service,e.values);default:return{success:!1,error:`Unknown action "${s}". Use list_services, show, or set.`}}}listServices(){let e=["| Service | Status | ENV Prefix |","|---|---|---|"];for(let[t,s]of Object.entries(Lt)){let n=s.fields.filter(i=>i.required).every(i=>!!process.env[i.env])?"configured":"not configured",o=`ALFRED_${t.toUpperCase()}_*`;e.push(`| ${s.label} | ${n} | \`${o}\` |`)}return{success:!0,data:Object.keys(Lt),display:e.join(`
560
- `)}}showService(e){let t=Lt[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Lt).join(", ")}`};let s=[`**${t.label}** configuration:
561
- `],r={};for(let n of t.fields){let o=process.env[n.env];r[n.env]=o;let i=o?n.secret?oa(o):o:"_not set_",a=n.required?" (required)":"";s.push(`- \`${n.env}\`: ${i}${a}`)}return{success:!0,data:r,display:s.join(`
562
- `)}}async setService(e,t){let s=Lt[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Lt).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
582
+ `)}}}});var Se,Os=y(()=>{"use strict";Se=class{static{u(this,"ContactsProvider")}}});var Da={};re(Da,{CardDAVContactsProvider:()=>Rr});var Rr,tn=y(()=>{"use strict";Os();Rr=class extends Se{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 o of s){let n=await this.client.fetchVCards({addressBook:o});for(let i of n){let a=this.parseVCard(i.data,i.url);a&&r.push(a)}}return r.sort((o,n)=>o.displayName.localeCompare(n.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(o=>o.address.toLowerCase().includes(s))||r.phones.some(o=>o.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 o=e.displayName??([e.firstName,e.lastName].filter(Boolean).join(" ")||"Unknown");return{id:s,displayName:o,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 o=await this.client.fetchVCards({addressBook:r});for(let n of o)if(n.url?.includes(e)||n.data?.includes(e)){let i=this.parseVCard(n.data,n.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:{...n,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 o of r)if(o.url?.includes(e)||o.data?.includes(e)){await this.client.deleteVCard({vCard:o});return}}throw new Error(`Contact ${e} not found`)}parseVCard(e,t){let s=u(g=>e.match(new RegExp(`^${g}[;:](.*)$`,"mi"))?.[1]?.trim(),"get"),r=s("FN");if(!r)return;let o=s("N"),[n,i]=o?o.split(";"):[void 0,void 0],a=[];for(let g of e.matchAll(/^EMAIL[^:]*:(.+)$/gmi)){let b=g[0],$=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],R=/TYPE=pref/i.test(b);a.push({address:$,label:A,primary:R})}let l=[];for(let g of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let b=g[0],$=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],R=/TYPE=pref/i.test(b);l.push({number:$,label:A,primary:R})}let d=[];for(let g of e.matchAll(/^ADR[^:]*:(.+)$/gmi)){let b=g[1].split(";");d.push({street:b[2]?.trim()||void 0,city:b[3]?.trim()||void 0,region:b[4]?.trim()||void 0,postalCode:b[5]?.trim()||void 0,country:b[6]?.trim()||void 0})}let m=s("ORG")?.replace(/;.*$/,""),p=s("BDAY"),w=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:n,emails:a,phones:l,addresses:d,organization:m,birthday:p,notes:w}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
583
+ VERSION:3.0\r
584
+ `;r+=`UID:${e}\r
585
+ `,r+=`FN:${s}\r
586
+ `,r+=`N:${t.lastName??""};${t.firstName??""};;;\r
587
+ `;for(let o of t.emails??[])r+=`EMAIL;TYPE=${o.label??"internet"}${o.primary?",pref":""}:${o.address}\r
588
+ `;for(let o of t.phones??[])r+=`TEL;TYPE=${o.label??"voice"}${o.primary?",pref":""}:${o.number}\r
589
+ `;for(let o of t.addresses??[])r+=`ADR;TYPE=${o.label??"home"}:;;${o.street??""};${o.city??""};${o.region??""};${o.postalCode??""};${o.country??""}\r
590
+ `;return t.organization&&(r+=`ORG:${t.organization}\r
591
+ `),t.birthday&&(r+=`BDAY:${t.birthday}\r
592
+ `),t.notes&&(r+=`NOTE:${t.notes}\r
593
+ `),r+=`END:VCARD\r
594
+ `,r}}});var Oa={};re(Oa,{GoogleContactsProvider:()=>Cr});var xr,at,Cr,sn=y(()=>{"use strict";Os();xr="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",at="https://people.googleapis.com/v1",Cr=class extends Se{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 o=await fetch(t,r);if(o.status===401){await this.refreshAccessToken();let n=await fetch(t,{...r,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json"}});if(!n.ok)throw new Error(`People API error: ${n.status}`);return n.status===204?void 0:n.json()}if(!o.ok)throw new Error(`People API error: ${o.status}`);if(o.status!==204)return o.json()}async list(e=50){let t=`${at}/people/me/connections?personFields=${xr}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${at}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${xr}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${at}/${e}?personFields=${xr}`,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",`${at}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${at}/${e}?personFields=${xr}`),r=this.buildPersonBody(t);r.etag=s.etag;let n=`${at}/${e}:updateContact?updatePersonFields=names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies`,i=await this.apiRequest("PATCH",n,r);return this.mapPerson(i)}async delete(e){await this.apiRequest("DELETE",`${at}/${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})),o=(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})),n=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:o,organization:n,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 Ua={};re(Ua,{MicrosoftContactsProvider:()=>Lr});var Lr,rn=y(()=>{"use strict";Os();Lr=class extends Se{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(n=>({address:n.address,label:n.name??void 0,primary:!1})),s=[];if(e.mobilePhone&&s.push({number:e.mobilePhone,label:"mobile"}),e.businessPhones)for(let n of e.businessPhones)s.push({number:n,label:"work"});if(e.homePhones)for(let n of e.homePhones)s.push({number:n,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 o=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:o,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"),o=e.phones.filter(i=>i.label==="home"),n=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)),o.length>0&&(t.homePhones=o.map(i=>i.number)),n.length>0&&!r.length&&(t.businessPhones=n.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 on(c){switch(c.provider){case"carddav":{if(!c.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(tn(),Da)),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(()=>(sn(),Oa)),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(()=>(rn(),Ua)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${c.provider}`)}}var Pa=y(()=>{"use strict";u(on,"createContactsProvider")});var Us,Fa=y(()=>{"use strict";j();Us=class extends I{static{u(this,"ContactsSkill")}contactsProvider;metadata={name:"contacts",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:
595
+ ${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):
596
+ ${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 |
597
+ |------|-------|-------|`,s=e.map(r=>{let o=r.emails[0]?.address??"-",n=r.phones[0]?.number??"-";return`| ${r.displayName} | ${o} | ${n} |`});return`${t}
598
+ ${s.join(`
599
+ `)}`}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(`
600
+ `)}}});var ja=y(()=>{"use strict";Os();tn();sn();rn();Pa();Fa()});var Ft,Ba=y(()=>{"use strict";j();Ft=class extends I{static{u(this,"TodoSkill")}todoRepo;metadata={name:"todo",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}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}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",o=e.description,n=e.priority,i=e.dueDate,a=this.todoRepo.add(this.effectiveUserId(t),s,{list:r,description:o,priority:n,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,o=new Set,n=[];for(let l of this.allUserIds(t))for(let d of this.todoRepo.list(l,s,r))o.has(d.id)||(o.add(d.id),n.push(d));if(n.length===0)return{success:!0,data:[],display:"No todos found."};let i=`| | Priority | Title | Due | ID |
601
+ |---|---|---|---|---|`,a=n.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(`
602
+ `);return{success:!0,data:n,display:`${n.length} todo(s):
603
+ ${i}
604
+ ${a}`}}completeTodo(e,t){let s=e.todoId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "todoId" for complete action'};let r=this.todoRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.todoRepo.complete(s)?{success:!0,data:{todoId:s},display:"Todo completed."}:{success:!1,error:`Todo "${s}" is already completed`}:{success:!1,error:`Todo "${s}" not found`}:{success:!1,error:`Todo "${s}" not found`}}uncompleteTodo(e,t){let s=e.todoId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "todoId" for uncomplete action'};let r=this.todoRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.todoRepo.uncomplete(s)?{success:!0,data:{todoId:s},display:"Todo reopened."}:{success:!1,error:`Todo "${s}" is not completed`}:{success:!1,error:`Todo "${s}" not found`}:{success:!1,error:`Todo "${s}" not found`}}deleteTodo(e,t){let s=e.todoId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "todoId" for delete action'};let r=this.todoRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.todoRepo.delete(s)?{success:!0,data:{todoId:s},display:"Todo deleted."}:{success:!1,error:`Todo "${s}" not found`}:{success:!1,error:`Todo "${s}" not found`}:{success:!1,error:`Todo "${s}" not found`}}showLists(e){let t=new Map;for(let n of this.allUserIds(e))for(let i of this.todoRepo.getLists(n)){let a=t.get(i.list);a?(a.open+=i.open,a.completed+=i.completed,a.total+=i.total):t.set(i.list,{open:i.open,completed:i.completed,total:i.total})}if(t.size===0)return{success:!0,data:[],display:"No todo lists found."};let s=[...t.entries()].map(([n,i])=>({list:n,...i})),r=`| List | Open | Completed | Total |
605
+ |---|---|---|---|`,o=s.map(n=>`| ${n.list} | ${n.open} | ${n.completed} | ${n.total} |`).join(`
606
+ `);return{success:!0,data:s,display:`${s.length} list(s):
607
+ ${r}
608
+ ${o}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(this.effectiveUserId(t),s);return{success:!0,data:{cleared:r},display:`Cleared ${r} completed todo(s).`}}}});import qa from"node:http";import Ha from"node:https";import{execFile as Ed}from"node:child_process";import{promisify as bd}from"node:util";function nn(c){return c==null||c<0?"-":c===0?"0 B":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 Va(c){return!c||c.length===0?"-":c.filter(e=>e.PublicPort||e.PrivatePort).map(e=>e.PublicPort?`${e.IP??"0.0.0.0"}:${e.PublicPort}->${e.PrivatePort}/${e.Type??"tcp"}`:`${e.PrivatePort}/${e.Type??"tcp"}`).join(", ")}function an(c){return!c||c.length===0?"-":c.map(e=>e.replace(/^\//,"")).join(", ")}function _d(c){let e=Buffer.from(c,"binary"),t=[],s=0;for(;s<e.length;)if(s+8<=e.length){let r=e.readUInt32BE(s+4),o=e.subarray(s+8,s+8+r).toString("utf8");t.push(o),s+=8+r}else{t.push(e.subarray(s).toString("utf8"));break}return t.join("")}function $d(c){return c?new Date(c*1e3).toISOString().replace("T"," ").slice(0,19):"-"}var za,Nr,Wa=y(()=>{"use strict";j();za=bd(Ed);u(nn,"formatBytes");u(Va,"formatPorts");u(an,"containerName");u(_d,"stripDockerStreamHeaders");u($d,"relativeTime");Nr=class extends I{static{u(this,"DockerSkill")}metadata={name:"docker",description:"Manage Docker containers, images, volumes, networks. Actions: containers, container, logs, start, stop, restart, images, pull_image, remove_image, networks, volumes, system_info, prune, compose_ps, compose_up, compose_down.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["containers","container","logs","start","stop","restart","images","pull_image","remove_image","networks","volumes","system_info","prune","compose_ps","compose_up","compose_down"],description:"The Docker action to perform"},containerId:{type:"string",description:"Container ID or name (for container, logs, start, stop, restart)"},imageName:{type:"string",description:"Image name (for pull_image, remove_image), e.g. nginx, ghcr.io/org/app"},imageTag:{type:"string",description:"Image tag (for pull_image), default: latest"},networkId:{type:"string",description:"Network ID or name"},project:{type:"string",description:"Docker Compose project name (for compose_ps, compose_up, compose_down)"},tail:{type:"number",description:"Number of log lines to retrieve (default: 100)"}},required:["action"]}};config;defaultSocket;constructor(e){super(),this.config=e,this.defaultSocket=process.platform==="win32"?"//./pipe/docker_engine":"/var/run/docker.sock"}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"containers":return await this.listContainers();case"container":return await this.inspectContainer(e.containerId);case"logs":return await this.getLogs(e.containerId,e.tail);case"start":return await this.startContainer(e.containerId);case"stop":return await this.stopContainer(e.containerId);case"restart":return await this.restartContainer(e.containerId);case"images":return await this.listImages();case"pull_image":return await this.pullImage(e.imageName,e.imageTag);case"remove_image":return await this.removeImage(e.imageName);case"networks":return await this.listNetworks();case"volumes":return await this.listVolumes();case"system_info":return await this.getSystemInfo();case"prune":return await this.pruneAll();case"compose_ps":return await this.composePs(e.project);case"compose_up":return await this.composeUp(e.project);case"compose_down":return await this.composeDown(e.project);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Docker API error: ${r instanceof Error?r.message:String(r)}`}}}api(e,t,s){return new Promise((r,o)=>{let n={method:e,path:`/v1.45${t}`,headers:{"Content-Type":"application/json"}};if(this.config.host){let l=new URL(this.config.host);n.hostname=l.hostname,n.port=l.port}else n.socketPath=this.config.socketPath??this.defaultSocket;let a=(this.config.host?.startsWith("https")?Ha:qa).request(n,l=>{let d="";l.on("data",m=>{d+=m}),l.on("end",()=>{if(l.statusCode&&l.statusCode>=400){o(new Error(`Docker API ${l.statusCode}: ${d.slice(0,500)}`));return}try{r(d?JSON.parse(d):void 0)}catch{o(new Error(`Invalid JSON from Docker API: ${d.slice(0,200)}`))}})});a.on("error",o),a.setTimeout(3e4,()=>{a.destroy(),o(new Error("Docker API timeout"))}),s&&a.write(JSON.stringify(s)),a.end()})}apiRaw(e,t,s){return new Promise((r,o)=>{let n={method:e,path:`/v1.45${t}`,headers:{"Content-Type":"application/json"}};if(this.config.host){let l=new URL(this.config.host);n.hostname=l.hostname,n.port=l.port}else n.socketPath=this.config.socketPath??this.defaultSocket;let a=(this.config.host?.startsWith("https")?Ha:qa).request(n,l=>{let d=[];l.on("data",m=>{d.push(m)}),l.on("end",()=>{if(l.statusCode&&l.statusCode>=400){let m=Buffer.concat(d).toString("utf8");o(new Error(`Docker API ${l.statusCode}: ${m.slice(0,500)}`));return}r(Buffer.concat(d).toString("binary"))})});a.on("error",o),a.setTimeout(3e4,()=>{a.destroy(),o(new Error("Docker API timeout"))}),s&&a.write(JSON.stringify(s)),a.end()})}async listContainers(){let e=await this.api("GET","/containers/json?all=true"),t=["## Docker Containers","","| Name | Image | Status | Ports |","|------|-------|--------|-------|"];for(let s of e)t.push(`| ${an(s.Names)} | ${s.Image??"-"} | ${s.Status??s.State??"-"} | ${Va(s.Ports)} |`);return e.length===0&&t.push("| - | No containers found | - | - |"),{success:!0,data:e,display:t.join(`
609
+ `)}}async inspectContainer(e){if(!e)return{success:!1,error:'Missing required "containerId" parameter'};let t=await this.api("GET",`/containers/${encodeURIComponent(e)}/json`),s=t.State??{},r=t.Config??{},o=t.NetworkSettings??{},n=t.Mounts??[],a=Object.entries(o.Ports??{}).filter(([,p])=>p&&p.length>0).map(([p,w])=>`${w.map(g=>`${g.HostIp??"0.0.0.0"}:${g.HostPort}`).join(", ")} -> ${p}`),l=n.map(p=>`- ${p.Source??"-"} -> ${p.Destination??"-"} (${p.Type??"-"}, ${p.RW?"rw":"ro"})`),d=o.IPAddress||Object.values(o.Networks??{}).map(p=>p.IPAddress).filter(Boolean).join(", ")||"-",m=[`## Container: ${an(t.Name?[t.Name]:void 0)}`,"",`**ID:** ${t.Id?.slice(0,12)??"-"}`,`**Image:** ${r.Image??"-"}`,`**Status:** ${s.Status??"-"}`,`**Started:** ${s.StartedAt??"-"}`,`**IP Address:** ${d}`,"","### Ports",a.length>0?a.map(p=>`- ${p}`).join(`
610
+ `):"- No port bindings","","### Mounts",l.length>0?l.join(`
611
+ `):"- No mounts"];return{success:!0,data:t,display:m.join(`
612
+ `)}}async getLogs(e,t){if(!e)return{success:!1,error:'Missing required "containerId" parameter'};let s=t??100,r=await this.apiRaw("GET",`/containers/${encodeURIComponent(e)}/logs?stdout=1&stderr=1&tail=${s}`),o=_d(r),n=[`## Logs: ${e} (last ${s} lines)`,"","```",o.trimEnd(),"```"];return{success:!0,data:o,display:n.join(`
613
+ `)}}async startContainer(e){return e?(await this.api("POST",`/containers/${encodeURIComponent(e)}/start`),{success:!0,data:{containerId:e,action:"start"},display:`**Container started:** \`${e}\``}):{success:!1,error:'Missing required "containerId" parameter'}}async stopContainer(e){return e?(await this.api("POST",`/containers/${encodeURIComponent(e)}/stop`),{success:!0,data:{containerId:e,action:"stop"},display:`**Container stopped:** \`${e}\``}):{success:!1,error:'Missing required "containerId" parameter'}}async restartContainer(e){return e?(await this.api("POST",`/containers/${encodeURIComponent(e)}/restart`),{success:!0,data:{containerId:e,action:"restart"},display:`**Container restarted:** \`${e}\``}):{success:!1,error:'Missing required "containerId" parameter'}}async listImages(){let e=await this.api("GET","/images/json"),t=["## Docker Images","","| Repo:Tag | Size | Created |","|----------|------|---------|"];for(let s of e){let o=(s.RepoTags??["<none>:<none>"]).join(", "),n=nn(s.Size),i=$d(s.Created);t.push(`| ${o} | ${n} | ${i} |`)}return e.length===0&&t.push("| - | No images found | - |"),{success:!0,data:e,display:t.join(`
614
+ `)}}async pullImage(e,t){if(!e)return{success:!1,error:'Missing required "imageName" parameter'};let s=t??"latest",r=await this.apiRaw("POST",`/images/create?fromImage=${encodeURIComponent(e)}&tag=${encodeURIComponent(s)}`);return{success:!0,data:{imageName:e,tag:s,raw:r.slice(0,500)},display:`**Image pulled:** \`${e}:${s}\``}}async removeImage(e){if(!e)return{success:!1,error:'Missing required "imageName" parameter'};let t=await this.api("DELETE",`/images/${encodeURIComponent(e)}`),s=(t??[]).filter(n=>n.Deleted).map(n=>n.Deleted),r=(t??[]).filter(n=>n.Untagged).map(n=>n.Untagged),o=[`**Image removed:** \`${e}\``,"",`**Untagged:** ${r.length>0?r.join(", "):"-"}`,`**Deleted layers:** ${s.length}`];return{success:!0,data:t,display:o.join(`
615
+ `)}}async listNetworks(){let e=await this.api("GET","/networks"),t=["## Docker Networks","","| Name | Driver | Scope | Subnet |","|------|--------|-------|--------|"];for(let s of e){let o=(s.IPAM?.Config??[]).map(n=>n.Subnet).filter(Boolean).join(", ")||"-";t.push(`| ${s.Name??"-"} | ${s.Driver??"-"} | ${s.Scope??"-"} | ${o} |`)}return e.length===0&&t.push("| - | No networks found | - | - |"),{success:!0,data:e,display:t.join(`
616
+ `)}}async listVolumes(){let t=(await this.api("GET","/volumes")).Volumes??[],s=["## Docker Volumes","","| Name | Driver | Mountpoint |","|------|--------|------------|"];for(let r of t)s.push(`| ${r.Name??"-"} | ${r.Driver??"-"} | ${r.Mountpoint??"-"} |`);return t.length===0&&s.push("| - | No volumes found | - |"),{success:!0,data:t,display:s.join(`
617
+ `)}}async getSystemInfo(){let e=await this.api("GET","/info"),t=["## Docker System Info","",`**Docker Version:** ${e.ServerVersion??"-"}`,`**OS:** ${e.OperatingSystem??"-"} (${e.Architecture??"-"})`,`**Kernel:** ${e.KernelVersion??"-"}`,`**CPUs:** ${e.NCPU??"-"}`,`**Memory:** ${nn(e.MemTotal)}`,`**Containers:** ${e.Containers??"-"} (running: ${e.ContainersRunning??"-"}, paused: ${e.ContainersPaused??"-"}, stopped: ${e.ContainersStopped??"-"})`,`**Images:** ${e.Images??"-"}`,`**Storage Driver:** ${e.Driver??"-"}`,`**Docker Root Dir:** ${e.DockerRootDir??"-"}`];return{success:!0,data:e,display:t.join(`
618
+ `)}}async pruneAll(){let[e,t,s,r]=await Promise.all([this.api("POST","/containers/prune"),this.api("POST","/images/prune"),this.api("POST","/volumes/prune"),this.api("POST","/networks/prune")]),o=e.ContainersDeleted?.length??0,n=t.ImagesDeleted?.length??0,i=s.VolumesDeleted?.length??0,a=r.NetworksDeleted?.length??0,l=(e.SpaceReclaimed??0)+(t.SpaceReclaimed??0)+(s.SpaceReclaimed??0),d=["## Docker Prune Results","",`**Containers removed:** ${o}`,`**Images removed:** ${n}`,`**Volumes removed:** ${i}`,`**Networks removed:** ${a}`,"",`**Total space reclaimed:** ${nn(l)}`];return{success:!0,data:{containers:e,images:t,volumes:s,networks:r},display:d.join(`
619
+ `)}}async composePs(e){let s=(await this.api("GET","/containers/json?all=true")).filter(n=>n.Labels?.["com.docker.compose.project"]),r=new Map;for(let n of s){let i=n.Labels["com.docker.compose.project"];e&&i!==e||(r.has(i)||r.set(i,[]),r.get(i).push(n))}let o=["## Docker Compose Projects",""];if(r.size===0)return o.push(e?`No containers found for project "${e}".`:"No Compose-managed containers found."),{success:!0,data:[],display:o.join(`
620
+ `)};for(let[n,i]of r){o.push(`### ${n}`),o.push(""),o.push("| Service | Name | Status | Ports |"),o.push("|---------|------|--------|-------|");for(let a of i){let l=a.Labels?.["com.docker.compose.service"]??"-";o.push(`| ${l} | ${an(a.Names)} | ${a.Status??a.State??"-"} | ${Va(a.Ports)} |`)}o.push("")}return{success:!0,data:[...r.entries()],display:o.join(`
621
+ `)}}async composeUp(e){if(!e)return{success:!1,error:'Missing required "project" parameter'};let{stdout:t,stderr:s}=await za("docker",["compose","-p",e,"up","-d"],{timeout:12e4}),r=(t+`
622
+ `+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose up:** \`${e}\``,"","```",r,"```"].join(`
623
+ `)}}async composeDown(e){if(!e)return{success:!1,error:'Missing required "project" parameter'};let{stdout:t,stderr:s}=await za("docker",["compose","-p",e,"down"],{timeout:12e4}),r=(t+`
624
+ `+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose down:** \`${e}\``,"","```",r,"```"].join(`
625
+ `)}}}});import cn from"node:fs";import Xa from"node:path";function Ga(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function vd(){let c=process.cwd();for(let e=0;e<10;e++){let t=Xa.join(c,".env");if(cn.existsSync(t))return t;let s=Xa.dirname(c);if(s===c)break;c=s}return null}var jt,Bt,Ka=y(()=>{"use strict";j();jt={proxmox:{label:"Proxmox VE",fields:[{env:"ALFRED_PROXMOX_BASE_URL",label:"Base URL (e.g. https://pve.local:8006)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_ID",label:"API Token ID (user@realm!name)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_SECRET",label:"API Token Secret",required:!0,secret:!0}]},unifi:{label:"UniFi Network",fields:[{env:"ALFRED_UNIFI_BASE_URL",label:"Base URL (e.g. https://unifi.local)",required:!0},{env:"ALFRED_UNIFI_API_KEY",label:"API Key (preferred, UniFi OS)",secret:!0},{env:"ALFRED_UNIFI_USERNAME",label:"Username (alternative to API key)"},{env:"ALFRED_UNIFI_PASSWORD",label:"Password (alternative to API key)",secret:!0},{env:"ALFRED_UNIFI_SITE",label:'Site name (default: "default")'}]},homeassistant:{label:"Home Assistant",fields:[{env:"ALFRED_HOMEASSISTANT_URL",label:"Base URL (e.g. http://homeassistant.local:8123)",required:!0},{env:"ALFRED_HOMEASSISTANT_TOKEN",label:"Long-Lived Access Token",required:!0,secret:!0}]},contacts:{label:"Contacts",fields:[{env:"ALFRED_CONTACTS_PROVIDER",label:"Provider (carddav, google, microsoft)",required:!0},{env:"ALFRED_CARDDAV_CONTACTS_SERVER_URL",label:"CardDAV Server URL (if carddav)"},{env:"ALFRED_CARDDAV_CONTACTS_USERNAME",label:"CardDAV Username (if carddav)"},{env:"ALFRED_CARDDAV_CONTACTS_PASSWORD",label:"CardDAV Password (if carddav)",secret:!0},{env:"ALFRED_GOOGLE_CONTACTS_CLIENT_ID",label:"Google Client ID (if google)",secret:!0},{env:"ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET",label:"Google Client Secret (if google)",secret:!0},{env:"ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN",label:"Google Refresh Token (if google)",secret:!0},{env:"ALFRED_MICROSOFT_CONTACTS_CLIENT_ID",label:"Microsoft Client ID (if microsoft)",secret:!0},{env:"ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET",label:"Microsoft Client Secret (if microsoft)",secret:!0},{env:"ALFRED_MICROSOFT_CONTACTS_TENANT_ID",label:"Microsoft Tenant ID (if microsoft)"},{env:"ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN",label:"Microsoft Refresh Token (if microsoft)",secret:!0}]},docker:{label:"Docker",fields:[{env:"ALFRED_DOCKER_SOCKET_PATH",label:"Docker socket path (e.g. /var/run/docker.sock)"},{env:"ALFRED_DOCKER_HOST",label:"Docker host (e.g. http://192.168.1.10:2375)"}]}},Bt=class extends I{static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",description:'Configure Alfred services (Proxmox, UniFi, Home Assistant, Contacts, Docker) by writing environment variables. Use action "list_services" to see available services. Use action "show" to check current config of a service. Use action "set" to write config \u2014 provide service name and values. After setting config, the service is activated immediately \u2014 no restart needed.',riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_services","show","set"],description:"Action to perform"},service:{type:"string",enum:["proxmox","unifi","homeassistant","contacts","docker"],description:"Service to configure (required for show/set)"},values:{type:"object",description:'Key-value pairs to set. Keys are the ENV variable names (e.g. ALFRED_PROXMOX_BASE_URL). Only for action "set".'}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"list_services":return this.listServices();case"show":return this.showService(e.service);case"set":return this.setService(e.service,e.values);default:return{success:!1,error:`Unknown action "${s}". Use list_services, show, or set.`}}}listServices(){let e=["| Service | Status | ENV Prefix |","|---|---|---|"];for(let[t,s]of Object.entries(jt)){let o=s.fields.filter(i=>i.required).every(i=>!!process.env[i.env])?"configured":"not configured",n=`ALFRED_${t.toUpperCase()}_*`;e.push(`| ${s.label} | ${o} | \`${n}\` |`)}return{success:!0,data:Object.keys(jt),display:e.join(`
626
+ `)}}showService(e){let t=jt[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(jt).join(", ")}`};let s=[`**${t.label}** configuration:
627
+ `],r={};for(let o of t.fields){let n=process.env[o.env];r[o.env]=n;let i=n?o.secret?Ga(n):n:"_not set_",a=o.required?" (required)":"";s.push(`- \`${o.env}\`: ${i}${a}`)}return{success:!0,data:r,display:s.join(`
628
+ `)}}async setService(e,t){let s=jt[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(jt).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
563
629
 
564
630
  Available keys for ${s.label}:
565
631
  ${s.fields.map(d=>`- \`${d.env}\`: ${d.label}${d.required?" (required)":""}`).join(`
566
- `)}`};let r=new Set(s.fields.map(d=>d.env));for(let d of Object.keys(t))if(!r.has(d))return{success:!1,error:`Invalid key "${d}" for ${s.label}. Valid keys: ${[...r].join(", ")}`};let n=$l();if(!n)return{success:!1,error:"Could not find .env file. Run `alfred setup` first or create a .env in your project root."};let o=Cn.readFileSync(n,"utf-8"),i=[];for(let[d,m]of Object.entries(t)){let h=m.replace(/\n/g,"\\n"),w=new RegExp(`^#?\\s*${d}=.*$`,"m");w.test(o)?o=o.replace(w,`${d}=${h}`):o=o.trimEnd()+`
567
- ${d}=${h}
568
- `,i.push(d)}Cn.writeFileSync(n,o,"utf-8");let a=s.fields.filter(d=>d.required).filter(d=>!t[d.env]&&!process.env[d.env]).map(d=>`\`${d.env}\``),l=[`Written to \`${n}\`:
569
- `,...i.map(d=>`- \`${d}\` = ${s.fields.find(m=>m.env===d)?.secret?oa(t[d]):t[d]}`)];if(a.length>0)l.push(`
632
+ `)}`};let r=new Set(s.fields.map(d=>d.env));for(let d of Object.keys(t))if(!r.has(d))return{success:!1,error:`Invalid key "${d}" for ${s.label}. Valid keys: ${[...r].join(", ")}`};let o=vd();if(!o)return{success:!1,error:"Could not find .env file. Run `alfred setup` first or create a .env in your project root."};let n=cn.readFileSync(o,"utf-8"),i=[];for(let[d,m]of Object.entries(t)){let p=m.replace(/\n/g,"\\n"),w=new RegExp(`^#?\\s*${d}=.*$`,"m");w.test(n)?n=n.replace(w,`${d}=${p}`):n=n.trimEnd()+`
633
+ ${d}=${p}
634
+ `,i.push(d)}cn.writeFileSync(o,n,"utf-8");let a=s.fields.filter(d=>d.required).filter(d=>!t[d.env]&&!process.env[d.env]).map(d=>`\`${d.env}\``),l=[`Written to \`${o}\`:
635
+ `,...i.map(d=>`- \`${d}\` = ${s.fields.find(m=>m.env===d)?.secret?Ga(t[d]):t[d]}`)];if(a.length>0)l.push(`
570
636
  **Still missing:** ${a.join(", ")}`);else if(this.reloadCallback){let d=await this.reloadCallback(e);d.success?l.push(`
571
637
  **${s.label} wurde aktiviert.** Du kannst es jetzt sofort nutzen.`):l.push(`
572
638
  **${s.label} is fully configured.** Hot-Reload fehlgeschlagen: ${d.error??"unbekannter Fehler"}. Restart Alfred: \`alfred start\``)}else l.push(`
573
- **${s.label} is fully configured.** Restart Alfred to activate: \`alfred start\``);return{success:!0,data:{envPath:n,written:i},display:l.join(`
574
- `)}}};u(oa,"maskValue");u($l,"findEnvFile")});import{spawn as vl}from"node:child_process";import aa from"node:fs";import da from"node:path";function Il(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 Al(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function hr(c){return c.length<=ca?c:`[...truncated...]
575
- `+c.slice(-ca)}function la(c){let e=new Map;function t(s){let r;try{r=aa.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(xl.has(n.name))continue;let o=da.join(s,n.name);if(n.isDirectory())t(o);else if(n.isFile())try{let i=aa.statSync(o);e.set(o,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function Rl(c,e,t){let s=[];for(let[r,n]of e){let o=c.get(r);(o===void 0||n>o)&&s.push(da.relative(t,r))}return s.sort()}async function ks(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??Sl,n=Math.min(r,kl),o=Al(c.argsTemplate,e),i={...process.env,...c.env?Il(c.env):{}},a=process.platform==="win32",l=la(s),d=Date.now();return new Promise(m=>{let h=vl(c.command,o,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),w="",y="",g=!1,_=setTimeout(()=>{g=!0,h.kill("SIGTERM"),setTimeout(()=>h.kill("SIGKILL"),5e3)},n);h.stdout?.on("data",v=>{w+=v.toString()}),h.stderr?.on("data",v=>{let R=v.toString();if(y+=R,t.onProgress){let x=R.trim().split(`
576
- `).pop();x&&t.onProgress(`[${c.name}] ${x}`)}}),c.promptVia==="stdin"&&h.stdin&&(h.stdin.write(e),h.stdin.end()),h.on("close",v=>{clearTimeout(_);let R=Date.now()-d,x=la(s),O=Rl(l,x,s);m({stdout:hr(w),stderr:hr(y),exitCode:g?124:v??1,durationMs:R,modifiedFiles:O})}),h.on("error",v=>{clearTimeout(_);let R=Date.now()-d;m({stdout:hr(w),stderr:hr(y+`
577
- `+v.message),exitCode:127,durationMs:R,modifiedFiles:[]})})})}var Sl,kl,ca,xl,fr=b(()=>{"use strict";Sl=3e5,kl=9e5,ca=1e5,xl=new Set([".git","node_modules",".next","dist",".cache"]);u(Il,"resolveEnv");u(Al,"buildArgs");u(hr,"truncateOutput");u(la,"snapshotMtimes");u(Rl,"detectModifiedFiles");u(ks,"executeAgent")});import{execFile as Ll}from"node:child_process";function we(c,e){return new Promise((t,s)=>{Ll("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 gr(c){try{let e=await we(["rev-parse","--abbrev-ref","HEAD"],c),t=await we(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function On(c,e){await we(["checkout","-b",c],e)}async function Dn(c){await we(["add","-A"],c)}async function Un(c,e){await we(["commit","-m",c],e);let t=await we(["rev-parse","--short","HEAD"],e),r=(await we(["diff","--stat","HEAD~1","HEAD"],e)).split(`
578
- `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function Pn(c,e,t){await we(["push","-u",c,e],t)}function Fn(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function Nt(c,e){try{return await we(["remote","get-url",c],e)}catch{return null}}function Ct(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 xs(c){await we(["init"],c)}async function Is(c,e,t){await we(["remote","add",c,e],t)}var jn=b(()=>{"use strict";u(we,"git");u(gr,"gitStatus");u(On,"gitCreateBranch");u(Dn,"gitStageAll");u(Un,"gitCommit");u(Pn,"gitPush");u(Fn,"slugifyBranch");u(Nt,"gitGetRemoteUrl");u(Ct,"parseRemoteUrl");u(xs,"gitInitRepo");u(Is,"gitAddRemote")});function Ot(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new Bn(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new Hn(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var et,Bn,Hn,qn=b(()=>{"use strict";et=class{static{u(this,"ForgeClient")}},Bn=class extends et{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}}},Hn=class extends et{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(Ot,"createForgeClient")});function ua(c,e){return c.length<=e?c:c.slice(0,e)+`
579
- [...truncated]`}function ma(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function Fl(c,e,t){let r=`Available agents:
639
+ **${s.label} is fully configured.** Restart Alfred to activate: \`alfred start\``);return{success:!0,data:{envPath:o,written:i},display:l.join(`
640
+ `)}}};u(Ga,"maskValue");u(vd,"findEnvFile")});import{spawn as Sd}from"node:child_process";import Ya from"node:fs";import Qa from"node:path";function Rd(c){let e={};for(let[t,s]of Object.entries(c))e[t]=s.replace(/\$\{(\w+)\}/g,(r,o)=>process.env[o]??"");return e}function xd(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function Mr(c){return c.length<=Ja?c:`[...truncated...]
641
+ `+c.slice(-Ja)}function Za(c){let e=new Map;function t(s){let r;try{r=Ya.readdirSync(s,{withFileTypes:!0})}catch{return}for(let o of r){if(Id.has(o.name))continue;let n=Qa.join(s,o.name);if(o.isDirectory())t(n);else if(o.isFile())try{let i=Ya.statSync(n);e.set(n,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function Cd(c,e,t){let s=[];for(let[r,o]of e){let n=c.get(r);(n===void 0||o>n)&&s.push(Qa.relative(t,r))}return s.sort()}async function Ps(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??kd,o=Math.min(r,Ad),n=xd(c.argsTemplate,e),i={...process.env,...c.env?Rd(c.env):{}},a=process.platform==="win32",l=Za(s),d=Date.now();return new Promise(m=>{let p=Sd(c.command,n,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),w="",T="",g=!1,b=setTimeout(()=>{g=!0,p.kill("SIGTERM"),setTimeout(()=>p.kill("SIGKILL"),5e3)},o);p.stdout?.on("data",$=>{w+=$.toString()}),p.stderr?.on("data",$=>{let A=$.toString();if(T+=A,t.onProgress){let R=A.trim().split(`
642
+ `).pop();R&&t.onProgress(`[${c.name}] ${R}`)}}),c.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",$=>{clearTimeout(b);let A=Date.now()-d,R=Za(s),O=Cd(l,R,s);m({stdout:Mr(w),stderr:Mr(T),exitCode:g?124:$??1,durationMs:A,modifiedFiles:O})}),p.on("error",$=>{clearTimeout(b);let A=Date.now()-d;m({stdout:Mr(w),stderr:Mr(T+`
643
+ `+$.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var kd,Ad,Ja,Id,Dr=y(()=>{"use strict";kd=3e5,Ad=9e5,Ja=1e5,Id=new Set([".git","node_modules",".next","dist",".cache"]);u(Rd,"resolveEnv");u(xd,"buildArgs");u(Mr,"truncateOutput");u(Za,"snapshotMtimes");u(Cd,"detectModifiedFiles");u(Ps,"executeAgent")});import{execFile as Ld}from"node:child_process";function ke(c,e){return new Promise((t,s)=>{Ld("git",c,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,o,n)=>{if(r){let i=n?.trim()||r.message;s(new Error(`git ${c[0]} failed: ${i}`));return}t(o.trim())})})}async function Or(c){try{let e=await ke(["rev-parse","--abbrev-ref","HEAD"],c),t=await ke(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function ln(c,e){await ke(["checkout","-b",c],e)}async function dn(c){await ke(["add","-A"],c)}async function un(c,e){await ke(["commit","-m",c],e);let t=await ke(["rev-parse","--short","HEAD"],e),r=(await ke(["diff","--stat","HEAD~1","HEAD"],e)).split(`
644
+ `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function mn(c,e,t){await ke(["push","-u",c,e],t)}function pn(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function qt(c,e){try{return await ke(["remote","get-url",c],e)}catch{return null}}function Ht(c){let e=c.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],o=e[2].split("/");if(o.length<2)return null;let n=o.pop();return{owner:o.join("/"),repo:n,baseUrl:`https://${s}`}}let t=c.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],o=t[2].split("/");if(o.length<2)return null;let n=o.pop();return{owner:o.join("/"),repo:n,baseUrl:`https://${s}`}}return null}async function Fs(c){await ke(["init"],c)}async function js(c,e,t){await ke(["remote","add",c,e],t)}var fn=y(()=>{"use strict";u(ke,"git");u(Or,"gitStatus");u(ln,"gitCreateBranch");u(dn,"gitStageAll");u(un,"gitCommit");u(mn,"gitPush");u(pn,"slugifyBranch");u(qt,"gitGetRemoteUrl");u(Ht,"parseRemoteUrl");u(Fs,"gitInitRepo");u(js,"gitAddRemote")});function zt(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new hn(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new gn(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var ct,hn,gn,yn=y(()=>{"use strict";ct=class{static{u(this,"ForgeClient")}},hn=class extends ct{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 n=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${n}`)}let o=await r.json();return{id:o.id,url:o.html_url,number:o.number,state:o.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 n=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[n]??"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 o=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${o}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},gn=class extends ct{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`,o=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(!o.ok){let i=await o.text();throw new Error(`GitLab MR creation failed (${o.status}): ${i}`)}let n=await o.json();return{id:n.id,url:n.web_url,number:n.iid,state:n.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`,o=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!o.ok)return{state:"unknown"};let n=await o.json();if(n.length===0)return{state:"unknown"};let i=n[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 o=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${o}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(zt,"createForgeClient")});function ec(c,e){return c.length<=e?c:c.slice(0,e)+`
645
+ [...truncated]`}function tc(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function jd(c,e,t){let r=`Available agents:
580
646
  ${e.map(a=>`- ${a.name}: command="${a.command}"`).join(`
581
647
  `)}
582
648
 
583
649
  Task:
584
- ${c}`,n=await t.complete({system:Ul,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=ma(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 jl(c,e,t,s){let r=new Wn(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 ks(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 Bl(c,e,t){let s=e.map(o=>{let i=ua(o.execution.stdout,Ol),a=ua(o.execution.stderr,Dl);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:
650
+ ${c}`,o=await t.complete({system:Pd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),n=tc(o.content);if(!Array.isArray(n.subtasks)||n.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 n.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return n}async function Bd(c,e,t,s){let r=new wn(t),o=[],n=c.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),l=await Ps(a,i.prompt,{onProgress:s?m=>s(`[${i.id}] ${m}`):void 0}),d={subtask:i,execution:l};return o.push(d),s?.(`Completed ${i.id}: exit=${l.exitCode}, ${l.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(n),o}async function qd(c,e,t){let s=e.map(n=>{let i=ec(n.execution.stdout,Od),a=ec(n.execution.stderr,Ud);return[`### ${n.subtask.id} (${n.subtask.description})`,`Agent: ${n.subtask.agent}`,`Exit code: ${n.execution.exitCode}`,`Modified files: ${n.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
585
651
  ${i}`:"",a?`stderr:
586
652
  ${a}`:""].filter(Boolean).join(`
587
653
  `)}).join(`
@@ -590,11 +656,11 @@ ${a}`:""].filter(Boolean).join(`
590
656
  ${c}
591
657
 
592
658
  Results:
593
- ${s}`,n=await t.complete({system:Pl,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=ma(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 tt(c,e,t,s={}){let r=Math.min(s.maxIterations??Ml,Nl),n=s.maxConcurrent??Cl,o=s.onProgress,i=Date.now(),a=new Map(e.map(g=>[g.name,g]));o?.("Planning subtasks...");let l=await Fl(c,e,t);o?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,h=0,w="";for(;h<r;){h++,o?.(`Iteration ${h}: executing ${m.length} subtask(s)...`);let g=await jl(m,a,n,o);d=d.concat(g),o?.(`Iteration ${h}: validating results...`);let _=await Bl(c,d,t);if(w=_.summary,_.approved||_.fixTasks.length===0)break;let v=_.fixTasks.filter(R=>a.has(R.agent)?!0:(o?.(`Warning: fix task "${R.id}" references unknown agent "${R.agent}", skipping`),!1));if(v.length===0)break;m=v,o?.(`Validation requested ${v.length} fix task(s), iterating...`)}let y=[...new Set(d.flatMap(g=>g.execution.modifiedFiles))].sort();return{plan:l,iterations:h,subtaskResults:d,allModifiedFiles:y,summary:w,totalDurationMs:Date.now()-i}}async function As(c,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await gr({cwd:n});if(!i.isRepo)try{await xs({cwd:n}),i=await gr({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 tt(c,e,t,s),git:o}}let a=null,l=await Nt("origin",{cwd:n});if(l){let y=Ct(l);y?(a={owner:y.owner,repo:y.repo},r?.(`Detected remote: ${y.owner}/${y.repo} (${y.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let y=Ot(d),g=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${g}" on forge...`);let _=await y.createProject({name:g,visibility:"private"});await Is("origin",_.cloneUrl,{cwd:n});let v=Ct(_.cloneUrl);v&&(a={owner:v.owner,repo:v.repo}),r?.(`Project created: ${_.url} \u2014 remote "origin" set`)}catch(y){let g=y instanceof Error?y.message:String(y);o.warnings.push(`Project creation failed: ${g}`),r?.(`Warning: project creation failed \u2014 ${g}`)}let m=Fn(c);try{await On(m,{cwd:n}),o.branch=m,r?.(`Created branch: ${m}`)}catch(y){throw new Error(`Failed to create branch "${m}": ${y instanceof Error?y.message:String(y)}`)}let h=await tt(c,e,t,s);try{await Dn({cwd:n});let y=`feat: ${c.slice(0,72)}
659
+ ${s}`,o=await t.complete({system:Fd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let n=tc(o.content);return{approved:n.approved??!0,summary:n.summary??"",fixTasks:Array.isArray(n.fixTasks)?n.fixTasks:[]}}catch{return{approved:!0,summary:o.content,fixTasks:[]}}}async function lt(c,e,t,s={}){let r=Math.min(s.maxIterations??Nd,Md),o=s.maxConcurrent??Dd,n=s.onProgress,i=Date.now(),a=new Map(e.map(g=>[g.name,g]));n?.("Planning subtasks...");let l=await jd(c,e,t);n?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,p=0,w="";for(;p<r;){p++,n?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let g=await Bd(m,a,o,n);d=d.concat(g),n?.(`Iteration ${p}: validating results...`);let b=await qd(c,d,t);if(w=b.summary,b.approved||b.fixTasks.length===0)break;let $=b.fixTasks.filter(A=>a.has(A.agent)?!0:(n?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if($.length===0)break;m=$,n?.(`Validation requested ${$.length} fix task(s), iterating...`)}let T=[...new Set(d.flatMap(g=>g.execution.modifiedFiles))].sort();return{plan:l,iterations:p,subtaskResults:d,allModifiedFiles:T,summary:w,totalDurationMs:Date.now()-i}}async function Bs(c,e,t,s={}){let r=s.onProgress,o=s.cwd??process.cwd(),n={warnings:[]},i=await Or({cwd:o});if(!i.isRepo)try{await Fs({cwd:o}),i=await Or({cwd:o}),r?.("Initialised new git repository")}catch{return n.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await lt(c,e,t,s),git:n}}let a=null,l=await qt("origin",{cwd:o});if(l){let T=Ht(l);T?(a={owner:T.owner,repo:T.repo},r?.(`Detected remote: ${T.owner}/${T.repo} (${T.baseUrl})`)):n.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let T=zt(d),g=o.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${g}" on forge...`);let b=await T.createProject({name:g,visibility:"private"});await js("origin",b.cloneUrl,{cwd:o});let $=Ht(b.cloneUrl);$&&(a={owner:$.owner,repo:$.repo}),r?.(`Project created: ${b.url} \u2014 remote "origin" set`)}catch(T){let g=T instanceof Error?T.message:String(T);n.warnings.push(`Project creation failed: ${g}`),r?.(`Warning: project creation failed \u2014 ${g}`)}let m=pn(c);try{await ln(m,{cwd:o}),n.branch=m,r?.(`Created branch: ${m}`)}catch(T){throw new Error(`Failed to create branch "${m}": ${T instanceof Error?T.message:String(T)}`)}let p=await lt(c,e,t,s);try{await dn({cwd:o});let T=`feat: ${c.slice(0,72)}
594
660
 
595
- Orchestrated by Alfred (${h.iterations} iteration(s), ${h.allModifiedFiles.length} file(s))`,g=await Un(y,{cwd:n});o.commit=g,r?.(`Committed: ${g.sha} (${g.filesChanged} files changed)`)}catch(y){let g=y instanceof Error?y.message:String(y);return o.warnings.push(`Commit failed: ${g}`),r?.(`Warning: commit failed \u2014 ${g}`),{...h,git:o}}if(!await Nt("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...h,git:o};try{await Pn("origin",m,{cwd:n}),r?.(`Pushed branch: ${m}`)}catch(y){let g=y instanceof Error?y.message:String(y);return o.warnings.push(`Push failed: ${g}`),r?.(`Warning: push failed \u2014 ${g}`),{...h,git:o}}if(d&&a)try{let y=Ot(d),g=s.baseBranch??d.baseBranch??"main",_=s.prTitle??`feat: ${c.slice(0,72)}`,v=["## Summary",h.summary,"",`**Iterations:** ${h.iterations}`,`**Modified files:** ${h.allModifiedFiles.length}`,h.allModifiedFiles.map(x=>`- \`${x}\``).join(`
661
+ Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,g=await un(T,{cwd:o});n.commit=g,r?.(`Committed: ${g.sha} (${g.filesChanged} files changed)`)}catch(T){let g=T instanceof Error?T.message:String(T);return n.warnings.push(`Commit failed: ${g}`),r?.(`Warning: commit failed \u2014 ${g}`),{...p,git:n}}if(!await qt("origin",{cwd:o}))return n.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...p,git:n};try{await mn("origin",m,{cwd:o}),r?.(`Pushed branch: ${m}`)}catch(T){let g=T instanceof Error?T.message:String(T);return n.warnings.push(`Push failed: ${g}`),r?.(`Warning: push failed \u2014 ${g}`),{...p,git:n}}if(d&&a)try{let T=zt(d),g=s.baseBranch??d.baseBranch??"main",b=s.prTitle??`feat: ${c.slice(0,72)}`,$=["## Summary",p.summary,"",`**Iterations:** ${p.iterations}`,`**Modified files:** ${p.allModifiedFiles.length}`,p.allModifiedFiles.map(R=>`- \`${R}\``).join(`
596
662
  `),"","_Automated by Alfred_"].join(`
597
- `),R=await y.createPullRequest(a,{title:_,body:v,head:m,base:g});o.pullRequest=R,r?.(`PR created: ${R.url}`)}catch(y){let g=y instanceof Error?y.message:String(y);o.warnings.push(`PR creation failed: ${g}`),r?.(`Warning: PR creation failed \u2014 ${g}`)}else d||(o.warnings.push("No forge configured \u2014 skipping PR creation"),r?.("No forge configured, skipping PR creation"));return{...h,git:o}}var Ml,Nl,Cl,Ol,Dl,Ul,Pl,Wn,Xn=b(()=>{"use strict";fr();jn();qn();Ml=3,Nl=5,Cl=3,Ol=2048,Dl=1024,Ul=`You are a task planner for a multi-agent coding system.
663
+ `),A=await T.createPullRequest(a,{title:b,body:$,head:m,base:g});n.pullRequest=A,r?.(`PR created: ${A.url}`)}catch(T){let g=T instanceof Error?T.message:String(T);n.warnings.push(`PR creation failed: ${g}`),r?.(`Warning: PR creation failed \u2014 ${g}`)}else d||(n.warnings.push("No forge configured \u2014 skipping PR creation"),r?.("No forge configured, skipping PR creation"));return{...p,git:n}}var Nd,Md,Dd,Od,Ud,Pd,Fd,wn,Tn=y(()=>{"use strict";Dr();fn();yn();Nd=3,Md=5,Dd=3,Od=2048,Ud=1024,Pd=`You are a task planner for a multi-agent coding system.
598
664
  You receive a high-level task and a list of available coding agents.
599
665
  Your job is to decompose the task into concrete subtasks, each assigned to an agent.
600
666
 
@@ -610,7 +676,7 @@ Respond with ONLY valid JSON (no markdown fences):
610
676
  "subtasks": [
611
677
  { "id": "task-1", "agent": "<agent-name>", "prompt": "<detailed prompt>", "description": "<short description>" }
612
678
  ]
613
- }`,Pl=`You are a code review validator for a multi-agent coding system.
679
+ }`,Fd=`You are a code review validator for a multi-agent coding system.
614
680
  You receive the original task and the results from each subtask execution.
615
681
  Your job is to determine if the task was completed successfully.
616
682
 
@@ -624,9 +690,9 @@ Respond with ONLY valid JSON (no markdown fences):
624
690
  "fixTasks": [
625
691
  { "id": "fix-1", "agent": "<agent-name>", "prompt": "<detailed fix prompt>", "description": "<short description>" }
626
692
  ]
627
- }`;u(ua,"truncate");u(ma,"parseJSON");Wn=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(Fl,"planSubtasks");u(jl,"executeSubtasksParallel");u(Bl,"validateResults");u(tt,"orchestrate");u(As,"orchestrateWithGit")});var Rs,pa=b(()=>{"use strict";P();fr();Xn();Rs=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",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(`
693
+ }`;u(ec,"truncate");u(tc,"parseJSON");wn=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(jd,"planSubtasks");u(Bd,"executeSubtasksParallel");u(qd,"validateResults");u(lt,"orchestrate");u(Bs,"orchestrateWithGit")});var qs,sc=y(()=>{"use strict";j();Dr();Tn();qs=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",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(`
628
694
  `);return{success:!0,data:{agents:e},display:`Available code agents:
629
- ${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 ks(n,r,{cwd:o,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
695
+ ${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 o=this.agents.get(s);if(!o){let d=[...this.agents.keys()].join(", ");return{success:!1,error:`Unknown agent "${s}". Available: ${d}`}}let n=typeof e.cwd=="string"?e.cwd:void 0,i=typeof e.timeout=="number"?e.timeout:void 0,a=await Ps(o,r,{cwd:n,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
630
696
  \`\`\`
631
697
  ${a.stdout}
632
698
  \`\`\``),a.stderr&&l.push(`**stderr:**
@@ -636,44 +702,44 @@ ${a.stderr}
636
702
  ${a.modifiedFiles.map(d=>`- ${d}`).join(`
637
703
  `)}`),{success:a.exitCode===0,data:{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,durationMs:a.durationMs,modifiedFiles:a.modifiedFiles},display:l.join(`
638
704
 
639
- `),...a.exitCode!==0&&{error:a.exitCode===124?`Agent "${s}" timed out`:`Agent "${s}" exited with code ${a.exitCode}`}}}async orchestrateTask(e,t){if(!this.llm)return{success:!1,error:"Orchestration requires an LLM provider but none was configured."};let s=e.task;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task" for orchestrate action.'};let r=[...this.agents.values()],n=e.agents;if(Array.isArray(n)&&n.length>0&&(r=n.map(d=>this.agents.get(d)).filter(d=>d!==void 0),r.length===0))return{success:!1,error:`None of the specified agents exist. Available: ${[...this.agents.keys()].join(", ")}`};let o=typeof e.maxIterations=="number"?e.maxIterations:void 0,i=e.git===!0,a=typeof e.prTitle=="string"?e.prTitle:void 0,l=typeof e.baseBranch=="string"?e.baseBranch:void 0;try{if(i){let m=await As(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(m)}let d=await tt(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress});return this.formatOrchestrationResult(d)}catch(d){return{success:!1,error:`Orchestration failed: ${d instanceof Error?d.message:String(d)}`}}}formatOrchestrationResult(e){let t=[];t.push(`**Orchestration completed in ${e.iterations} iteration(s)**`),t.push(`**Plan:** ${e.plan.reasoning}`),t.push(`**Duration:** ${(e.totalDurationMs/1e3).toFixed(1)}s`);for(let r of e.subtaskResults){let n=r.execution.exitCode===0?"OK":`FAIL (exit ${r.execution.exitCode})`;t.push(`- **${r.subtask.id}** [${r.subtask.agent}]: ${r.subtask.description} \u2014 ${n}`)}return e.allModifiedFiles.length>0&&t.push(`
705
+ `),...a.exitCode!==0&&{error:a.exitCode===124?`Agent "${s}" timed out`:`Agent "${s}" exited with code ${a.exitCode}`}}}async orchestrateTask(e,t){if(!this.llm)return{success:!1,error:"Orchestration requires an LLM provider but none was configured."};let s=e.task;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task" for orchestrate action.'};let r=[...this.agents.values()],o=e.agents;if(Array.isArray(o)&&o.length>0&&(r=o.map(d=>this.agents.get(d)).filter(d=>d!==void 0),r.length===0))return{success:!1,error:`None of the specified agents exist. Available: ${[...this.agents.keys()].join(", ")}`};let n=typeof e.maxIterations=="number"?e.maxIterations:void 0,i=e.git===!0,a=typeof e.prTitle=="string"?e.prTitle:void 0,l=typeof e.baseBranch=="string"?e.baseBranch:void 0;try{if(i){let m=await Bs(s,r,this.llm,{maxIterations:n,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(m)}let d=await lt(s,r,this.llm,{maxIterations:n,onProgress:t.onProgress});return this.formatOrchestrationResult(d)}catch(d){return{success:!1,error:`Orchestration failed: ${d instanceof Error?d.message:String(d)}`}}}formatOrchestrationResult(e){let t=[];t.push(`**Orchestration completed in ${e.iterations} iteration(s)**`),t.push(`**Plan:** ${e.plan.reasoning}`),t.push(`**Duration:** ${(e.totalDurationMs/1e3).toFixed(1)}s`);for(let r of e.subtaskResults){let o=r.execution.exitCode===0?"OK":`FAIL (exit ${r.execution.exitCode})`;t.push(`- **${r.subtask.id}** [${r.subtask.agent}]: ${r.subtask.description} \u2014 ${o}`)}return e.allModifiedFiles.length>0&&t.push(`
640
706
  **Modified files:**
641
707
  ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
642
708
  `)}`),e.summary&&t.push(`
643
709
  **Summary:** ${e.summary}`),{success:!e.subtaskResults.some(r=>r.execution.exitCode!==0),data:{plan:e.plan,iterations:e.iterations,subtaskResults:e.subtaskResults.map(r=>({id:r.subtask.id,agent:r.subtask.agent,description:r.subtask.description,exitCode:r.execution.exitCode,modifiedFiles:r.execution.modifiedFiles,durationMs:r.execution.durationMs})),allModifiedFiles:e.allModifiedFiles,summary:e.summary,totalDurationMs:e.totalDurationMs},display:t.join(`
644
- `)}}formatGitOrchestrationResult(e){let t=this.formatOrchestrationResult(e),s=[],{git:r}=e;r.branch&&s.push(`**Branch:** ${r.branch}`),r.commit&&s.push(`**Commit:** ${r.commit.sha} (${r.commit.filesChanged} files changed)`),r.pullRequest&&s.push(`**PR:** ${r.pullRequest.url} (#${r.pullRequest.number})`);for(let o of r.warnings)s.push(`**Warning:** ${o}`);let n=s.length>0?`
710
+ `)}}formatGitOrchestrationResult(e){let t=this.formatOrchestrationResult(e),s=[],{git:r}=e;r.branch&&s.push(`**Branch:** ${r.branch}`),r.commit&&s.push(`**Commit:** ${r.commit.sha} (${r.commit.filesChanged} files changed)`),r.pullRequest&&s.push(`**PR:** ${r.pullRequest.url} (#${r.pullRequest.number})`);for(let n of r.warnings)s.push(`**Warning:** ${n}`);let o=s.length>0?`
645
711
 
646
712
  **Git:**
647
713
  ${s.join(`
648
- `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var ha=b(()=>{"use strict";pa();fr();Xn();jn();qn()});var be={};oe(be,{ActivityTracker:()=>Ge,BackgroundTaskSkill:()=>kt,BrowserSkill:()=>$t,CalculatorSkill:()=>lt,CalendarProvider:()=>ye,CalendarSkill:()=>Ye,ClipboardSkill:()=>_t,CodeAgentSkill:()=>Rs,CodeExecutionSkill:()=>vs,CodeExecutor:()=>Qe,ConfigureSkill:()=>Mt,CrossPlatformSkill:()=>St,DelegateSkill:()=>yt,DocumentSkill:()=>At,EmailProvider:()=>xe,EmailSkill:()=>Me,FileSkill:()=>bt,ForgeClient:()=>et,HomeAssistantSkill:()=>pr,HttpSkill:()=>wt,MCPClient:()=>Je,MCPManager:()=>$s,MCPSkillAdapter:()=>Ze,MemorySkill:()=>gt,NoteSkill:()=>pt,PluginLoader:()=>rr,ProfileSkill:()=>vt,ProxmoxSkill:()=>ur,ReminderSkill:()=>mt,ScheduledTaskSkill:()=>xt,ScreenshotSkill:()=>Et,ShellSkill:()=>ft,Skill:()=>I,SkillRegistry:()=>at,SkillSandbox:()=>ct,SystemInfoSkill:()=>dt,TTSSkill:()=>Rt,UniFiSkill:()=>mr,WeatherSkill:()=>ht,WebSearchSkill:()=>ut,createCalendarProvider:()=>Es,createEmailProvider:()=>bs,createForgeClient:()=>Ot,gitAddRemote:()=>Is,gitGetRemoteUrl:()=>Nt,gitInitRepo:()=>xs,orchestrate:()=>tt,orchestrateWithGit:()=>As,parseRemoteUrl:()=>Ct});var pe=b(()=>{"use strict";P();ui();mi();En();pi();hi();fi();gi();yi();wi();bi();Ei();$i();vi();Ii();Ri();Mi();Ni();Oi();Ui();Pi();Wi();Xi();zi();Vi();Gi();Ji();Zi();Qi();ea();ta();ra();ia();ha()});var Ls,zn=b(()=>{"use strict";Ls=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)}}});import fa from"node:fs";import ga from"node:path";var Hl,ya,ql,wa,Wl,Xl,zl,ba,Ms,Vn=b(()=>{"use strict";Tn();Hl=15*60*1e3,ya=50,ql=2,wa=.85,Wl=1e5,Xl=2e3,zl=.1,ba=3,Ms=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;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.promptBuilder=new hs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let r=this.users.findOrCreate(e.platform,e.userId,e.userName,e.displayName),n="getMasterUserId"in this.users?this.users.getMasterUserId(r.id):r.id,o;"getLinkedUsers"in this.users&&(o=this.users.getLinkedUsers(n).map(V=>V.platformUserId));let i=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),a=this.conversationManager.getHistory(i.id,200);this.conversationManager.addMessage(i.id,"user",e.text);let l,d=this.isSyntheticLabel(e.text),m=e.attachments?.some(F=>F.type==="audio")??!1,h=d&&!m;if(this.memoryRetriever&&e.text&&!h)try{l=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(F){this.logger.debug({err:F},"Hybrid memory retrieval failed")}if(!l&&this.memoryRepo&&!h)try{let F=[n,...(o??[]).filter(V=>V!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let V=new Set;l=[];for(let q of F)for(let K of await this.embeddingService.semanticSearch(q,e.text,10))V.has(K.key)||(V.add(K.key),l.push(K));for(let q of F)for(let K of this.memoryRepo.getRecentForPrompt(q,5))V.has(K.key)||(V.add(K.key),l.push(K))}else{let V=new Set;l=[];for(let q of F)for(let K of this.memoryRepo.getRecentForPrompt(q,20))V.has(K.key)||(V.add(K.key),l.push(K))}}catch(F){this.logger.debug({err:F},"Memory loading failed")}l&&l.length>0&&(l=this.applyMemoryBudget(l));let w;try{"getProfile"in this.users&&(w=this.users.getProfile(n),w&&!w.displayName&&(w.displayName=r.displayName??r.username))}catch(F){this.logger.debug({err:F},"Profile loading failed")}let y=w?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,g=this.skillRegistry?this.skillRegistry.getAll().map(F=>F.metadata):void 0,_=g?this.promptBuilder.buildTools(g):void 0,v=this.promptBuilder.buildSystemPrompt({memories:l,skills:g,userProfile:w}),R=this.buildActiveAgentStatus();R&&(v+=`
714
+ `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+o}}}});var rc=y(()=>{"use strict";sc();Dr();Tn();fn();yn()});var ue={};re(ue,{ActivityTracker:()=>st,BackgroundTaskSkill:()=>Mt,BrowserSkill:()=>Ct,CalculatorSkill:()=>yt,CalendarProvider:()=>ve,CalendarSkill:()=>rt,ClipboardSkill:()=>Rt,CodeAgentSkill:()=>qs,CodeExecutionSkill:()=>Ms,CodeExecutor:()=>it,ConfigureSkill:()=>Bt,ContactsProvider:()=>Se,ContactsSkill:()=>Us,CrossPlatformSkill:()=>Nt,DelegateSkill:()=>St,DockerSkill:()=>Nr,DocumentSkill:()=>Ut,EmailProvider:()=>Le,EmailSkill:()=>Ue,FileSkill:()=>At,ForgeClient:()=>ct,HomeAssistantSkill:()=>Ir,HttpSkill:()=>kt,MCPClient:()=>ot,MCPManager:()=>Ns,MCPSkillAdapter:()=>nt,MemorySkill:()=>vt,NoteSkill:()=>bt,PluginLoader:()=>wr,ProfileSkill:()=>Lt,ProxmoxSkill:()=>kr,ReminderSkill:()=>Et,ScheduledTaskSkill:()=>Dt,ScreenshotSkill:()=>xt,ShellSkill:()=>$t,Skill:()=>I,SkillRegistry:()=>ht,SkillSandbox:()=>gt,SystemInfoSkill:()=>wt,TTSSkill:()=>Pt,TodoSkill:()=>Ft,UniFiSkill:()=>Ar,WeatherSkill:()=>_t,WebSearchSkill:()=>Tt,createCalendarProvider:()=>Ls,createContactsProvider:()=>on,createEmailProvider:()=>Rs,createForgeClient:()=>zt,gitAddRemote:()=>js,gitGetRemoteUrl:()=>qt,gitInitRepo:()=>Fs,orchestrate:()=>lt,orchestrateWithGit:()=>Bs,parseRemoteUrl:()=>Ht});var ce=y(()=>{"use strict";j();qi();Hi();Ho();zi();Vi();Wi();Xi();Gi();Ki();Yi();Qi();ea();ta();na();aa();la();da();ma();fa();ha();ba();_a();$a();va();ka();Ia();Ra();xa();Ca();La();Ma();ja();Ba();Wa();Ka();rc()});var Hs,En=y(()=>{"use strict";Hs=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)}}});import oc from"node:fs";import nc from"node:path";var Hd,ic,zd,ac,Vd,Wd,Xd,cc,zs,bn=y(()=>{"use strict";Bo();Hd=15*60*1e3,ic=50,zd=2,ac=.85,Vd=1e5,Wd=2e3,Xd=.1,cc=3,zs=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;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.promptBuilder=new vs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let r=this.users.findOrCreate(e.platform,e.userId,e.userName,e.displayName),o="getMasterUserId"in this.users?this.users.getMasterUserId(r.id):r.id,n;"getLinkedUsers"in this.users&&(n=this.users.getLinkedUsers(o).map(F=>F.platformUserId));let i=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),a=this.conversationManager.getHistory(i.id,200);this.conversationManager.addMessage(i.id,"user",e.text);let l,d=this.isSyntheticLabel(e.text),m=e.attachments?.some(B=>B.type==="audio")??!1,p=d&&!m;if(this.memoryRetriever&&e.text&&!p)try{l=await this.memoryRetriever.retrieve(o,e.text,15,n)}catch(B){this.logger.debug({err:B},"Hybrid memory retrieval failed")}if(!l&&this.memoryRepo&&!p)try{let B=[o,...(n??[]).filter(F=>F!==o)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let F=new Set;l=[];for(let Q of B)for(let X of await this.embeddingService.semanticSearch(Q,e.text,10))F.has(X.key)||(F.add(X.key),l.push(X));for(let Q of B)for(let X of this.memoryRepo.getRecentForPrompt(Q,5))F.has(X.key)||(F.add(X.key),l.push(X))}else{let F=new Set;l=[];for(let Q of B)for(let X of this.memoryRepo.getRecentForPrompt(Q,20))F.has(X.key)||(F.add(X.key),l.push(X))}}catch(B){this.logger.debug({err:B},"Memory loading failed")}l&&l.length>0&&(l=this.applyMemoryBudget(l));let w;try{"getProfile"in this.users&&(w=this.users.getProfile(o),w&&!w.displayName&&(w.displayName=r.displayName??r.username))}catch(B){this.logger.debug({err:B},"Profile loading failed")}let T=w?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,g=this.skillRegistry?this.skillRegistry.getAll().map(B=>B.metadata):void 0,b=g?this.promptBuilder.buildTools(g):void 0,$=this.promptBuilder.buildSystemPrompt({memories:l,skills:g,userProfile:w}),A=this.buildActiveAgentStatus();A&&($+=`
649
715
 
650
- `+R);let x=this.promptBuilder.buildMessages(a),O=this.collapseRepeatedToolErrors(x),N=await this.buildUserContent(e,t);O.push({role:"user",content:N});let B=this.trimToContextWindow(v,O),H,ae=0,Pe=Date.now(),he="",Y=0,re=[];for(t?.("Thinking...");ae>0&&this.compressToolLoop(B,v),H=await this.llm.complete({messages:B,system:v,tools:_&&_.length>0?_:void 0}),!(!H.toolCalls||H.toolCalls.length===0);){let F=Date.now()-Pe;if(F>=Hl){let Se=Math.round(F/6e4);this.logger.warn({iteration:ae,elapsedMin:Se,pendingToolCalls:H.toolCalls.length},"Tool loop timeout reached"),H=await this.abortToolLoop(B,H,i.id,v,`Das Zeitlimit von ${Se} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(ae>=ya){this.logger.warn({iteration:ae,pendingToolCalls:H.toolCalls.length},"Tool loop iteration cap reached"),H=await this.abortToolLoop(B,H,i.id,v,`Das Iterationslimit von ${ya} Tool-Aufrufen wurde erreicht.`);break}ae++,this.logger.info({iteration:ae,toolCalls:H.toolCalls.length},"Processing tool calls");let V=[];H.content&&V.push({type:"text",text:H.content});for(let Se of H.toolCalls)V.push({type:"tool_use",id:Se.id,name:Se.name,input:Se.input});B.push({role:"assistant",content:V});let q=await this.executeToolCallsParallel(H.toolCalls,{userId:e.userId,masterUserId:n,linkedPlatformUserIds:o,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:y},t),K=q.blocks;q.attachments.length>0&&re.push(...q.attachments),this.conversationManager.addMessage(i.id,"assistant",H.content??"",JSON.stringify(H.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(K));let ce=this.buildErrorSignature(K);if(ce){if(ce===he?Y++:(Y=1,he=ce),Y>=ql){this.logger.warn({iteration:ae,consecutiveErrors:Y,errorSignature:ce},"Tool loop aborted: same error repeated consecutively"),H=await this.abortToolLoop(B,H,i.id,v,`Der gleiche Tool-Fehler ist ${Y}x hintereinander aufgetreten: "${he.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else Y=0,he="";B.push({role:"user",content:K}),t?.("Thinking...")}let L=H.content;if(!L)for(let F=B.length-1;F>=0;F--){let V=B[F];if(V.role==="assistant"&&Array.isArray(V.content)){let q=V.content.find(K=>K.type==="text");if(q&&"text"in q&&q.text){L=q.text;break}}}L||(L="(no response)"),this.conversationManager.addMessage(i.id,"assistant",L),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,L);let W=Date.now()-s;return this.logger.info({duration:W,tokens:H.usage,stopReason:H.stopReason,toolIterations:ae},"Message processed"),{text:L,attachments:re.length>0?re: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 a=[];t.content&&a.push({type:"text",text:t.content});for(let l of t.toolCalls)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));return 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)),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:"assistant",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((a,l)=>{let d=l.content;if(l.attachments&&l.attachments.length>0){r.push(...l.attachments);let m=l.attachments.map(h=>h.fileName).join(", ");d+=`
716
+ `+A);let R=this.promptBuilder.buildMessages(a),O=this.collapseRepeatedToolErrors(R),N=await this.buildUserContent(e,t);O.push({role:"user",content:N});let K=b?$e(JSON.stringify(b)):0,ie=this.trimToContextWindow($,O,K),V,we=0,xe=Date.now(),Y="",J=0,de=[];for(t?.("Thinking...");we>0&&this.compressToolLoop(ie,$,K),V=await this.llm.complete({messages:ie,system:$,tools:b&&b.length>0?b:void 0}),!(!V.toolCalls||V.toolCalls.length===0);){let B=Date.now()-xe;if(B>=Hd){let Ae=Math.round(B/6e4);this.logger.warn({iteration:we,elapsedMin:Ae,pendingToolCalls:V.toolCalls.length},"Tool loop timeout reached"),V=await this.abortToolLoop(ie,V,i.id,$,`Das Zeitlimit von ${Ae} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(we>=ic){this.logger.warn({iteration:we,pendingToolCalls:V.toolCalls.length},"Tool loop iteration cap reached"),V=await this.abortToolLoop(ie,V,i.id,$,`Das Iterationslimit von ${ic} Tool-Aufrufen wurde erreicht.`);break}we++,this.logger.info({iteration:we,toolCalls:V.toolCalls.length},"Processing tool calls");let F=[];V.content&&F.push({type:"text",text:V.content});for(let Ae of V.toolCalls)F.push({type:"tool_use",id:Ae.id,name:Ae.name,input:Ae.input});ie.push({role:"assistant",content:F});let Q=await this.executeToolCallsParallel(V.toolCalls,{userId:e.userId,masterUserId:o,linkedPlatformUserIds:n,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:T},t),X=Q.blocks;Q.attachments.length>0&&de.push(...Q.attachments),this.conversationManager.addMessage(i.id,"assistant",V.content??"",JSON.stringify(V.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(X));let He=this.buildErrorSignature(X);if(He){if(He===Y?J++:(J=1,Y=He),J>=zd){this.logger.warn({iteration:we,consecutiveErrors:J,errorSignature:He},"Tool loop aborted: same error repeated consecutively"),V=await this.abortToolLoop(ie,V,i.id,$,`Der gleiche Tool-Fehler ist ${J}x hintereinander aufgetreten: "${Y.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else J=0,Y="";ie.push({role:"user",content:X}),t?.("Thinking...")}let L=V.content;if(!L)for(let B=ie.length-1;B>=0;B--){let F=ie[B];if(F.role==="assistant"&&Array.isArray(F.content)){let Q=F.content.find(X=>X.type==="text");if(Q&&"text"in Q&&Q.text){L=Q.text;break}}}L||(L="(no response)"),this.conversationManager.addMessage(i.id,"assistant",L),this.activeLearning&&this.activeLearning.onMessageProcessed(o,e.text,L);let W=Date.now()-s;return this.logger.info({duration:W,tokens:V.usage,stopReason:V.stopReason,toolIterations:we},"Message processed"),{text:L,attachments:de.length>0?de:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,o,n=!1){if(!n){let a=[];t.content&&a.push({type:"text",text:t.content});for(let l of t.toolCalls)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${o}`,is_error:!0}));return e.push({role:"user",content:i}),n||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i)),e.push({role:"user",content:`[System: ${o} 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(o=>o.type==="tool_use")){let o=s+1<e.length?e[s+1]:null;if(o&&o.role==="user"&&Array.isArray(o.content)&&o.content.every(n=>n.type==="tool_result"&&n.is_error)){let n=this.toolPairSignature(r,o),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)===n)i++,a+=2;else break}if(i>1){t.push(r),t.push(o),t.push({role:"assistant",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(o=>o.type==="tool_use").map(o=>`${o.name}:${JSON.stringify(o.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(o=>o.type==="tool_result").map(o=>o.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],o=u((a,l)=>{let d=l.content;if(l.attachments&&l.attachments.length>0){r.push(...l.attachments);let m=l.attachments.map(p=>p.fileName).join(", ");d+=`
651
717
 
652
- [${l.attachments.length} Datei(en) werden dem User gesendet: ${m}]`}return{type:"tool_result",tool_use_id:a.id,content:d,is_error:l.isError}},"buildBlock");if(e.length===1){let a=e[0],l=this.getToolLabel(a.name,a.input);s?.(l);let d=await this.executeToolCall(a,t,s);return{blocks:[n(a,d)],attachments:r}}s?.(`Running ${e.length} tools in parallel...`);let o=await Promise.allSettled(e.map(a=>this.executeToolCall(a,t,s)));return{blocks:e.map((a,l)=>{let d=o[l];return d.status==="fulfilled"?n(a,d.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${d.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(()=>(pe(),be));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(`
653
- `)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=zl));let r=0,n=[];for(let o of s){let i=ve(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>Xl)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){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*wa);if(ve(t)+e.reduce((y,g)=>y+fs(g),0)<=r)return;let i=[];for(let y=0;y<e.length-1;y++){let g=e[y],_=e[y+1];g.role==="assistant"&&Array.isArray(g.content)&&g.content.some(v=>v.type==="tool_use")&&_.role==="user"&&Array.isArray(_.content)&&_.content.some(v=>v.type==="tool_result")&&i.push({start:y,end:y+1})}if(i.length<=ba)return;let a=i.length-ba,l=i.slice(0,a),d=[];for(let y of l){let g=e[y.start],_=[];if(Array.isArray(g.content))for(let x of g.content)x.type==="tool_use"&&_.push(x.name);let v=e[y.end],R="ok";Array.isArray(v.content)&&v.content.some(O=>O.type==="tool_result"&&O.is_error)&&(R="error"),d.push(`- ${_.join(", ")}: ${R}`)}let m=l[0].start,w=l[l.length-1].end-m+1;e.splice(m,w,{role:"assistant",content:`[Earlier tool interactions compressed (${l.length} pairs):
654
- ${d.join(`
718
+ [${l.attachments.length} Datei(en) werden dem User gesendet: ${m}]`}return{type:"tool_result",tool_use_id:a.id,content:d,is_error:l.isError}},"buildBlock");if(e.length===1){let a=e[0],l=this.getToolLabel(a.name,a.input);s?.(l);let d=await this.executeToolCall(a,t,s);return{blocks:[o(a,d)],attachments:r}}s?.(`Running ${e.length} tools in parallel...`);let n=await Promise.allSettled(e.map(a=>this.executeToolCall(a,t,s)));return{blocks:e.map((a,l)=>{let d=n[l];return d.status==="fulfilled"?o(a,d.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${d.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 o=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!o.allowed)return this.logger.warn({tool:e.name,reason:o.reason,rule:o.matchedRule?.id},"Skill execution denied by security rules"),{content:`Access denied: ${o.reason}`,isError:!0}}if(this.skillSandbox){let o,n;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(ce(),ue));o=new a(s),n=`agent-${++this.agentIdCounter}`,this.activeAgents.set(n,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:o,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:o,onProgress:s}:s?{...t,onProgress:s}:t;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,o);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{n&&this.activeAgents.delete(n)}}try{let o=await r.execute(e.input,t);return{content:o.display??(o.success?JSON.stringify(o.data):o.error??"Unknown error"),isError:!o.success,attachments:o.attachments}}catch(o){return{content:`Skill execution failed: ${o instanceof Error?o.message:String(o)}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),o=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${o}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(`
719
+ `)}applyMemoryBudget(e){let t=e.some(n=>n.score!=null&&n.score>0),s=e;t&&(s=e.filter(n=>(n.score??1)>=Xd));let r=0,o=[];for(let n of s){let i=$e(`[${n.category}] ${n.key}: ${n.value}`);if(r+i>Wd)break;r+=i,o.push(n)}return o.length<e.length&&this.logger.info({original:e.length,kept:o.length,tokenCount:r,droppedByScore:e.length-s.length},"Memory budget applied"),o}compressToolLoop(e,t,s=0){let r=this.llm.getContextWindow(),o=Math.floor(r.maxInputTokens*ac);if($e(t)+s+e.reduce((g,b)=>g+Ss(b),0)<=o)return;let a=[];for(let g=0;g<e.length-1;g++){let b=e[g],$=e[g+1];b.role==="assistant"&&Array.isArray(b.content)&&b.content.some(A=>A.type==="tool_use")&&$.role==="user"&&Array.isArray($.content)&&$.content.some(A=>A.type==="tool_result")&&a.push({start:g,end:g+1})}if(a.length<=cc)return;let l=a.length-cc,d=a.slice(0,l),m=[];for(let g of d){let b=e[g.start],$=[];if(Array.isArray(b.content))for(let O of b.content)O.type==="tool_use"&&$.push(O.name);let A=e[g.end],R="ok";Array.isArray(A.content)&&A.content.some(N=>N.type==="tool_result"&&N.is_error)&&(R="error"),m.push(`- ${$.join(", ")}: ${R}`)}let p=d[0].start,T=d[d.length-1].end-p+1;e.splice(p,T,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
720
+ ${m.join(`
655
721
  `)}
656
- ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:l.length,removedMessages:w-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*wa),n=ve(e),o=t[t.length-1],i=fs(o),l=n+i+200+500,d=r-l;if(d<=0)return this.logger.warn({maxInputTokens:r,systemTokens:n,latestTokens:i},"Context window very tight, sending only latest message"),[o];let m=t.slice(0,-1),h=this.groupToolPairs(m),w=[];for(let _=h.length-1;_>=0;_--){let v=h[_].reduce((R,x)=>R+fs(x),0);v>d||(d-=v,w.unshift(h[_]))}let y=w.flat(),g=m.length-y.length;if(g>0){this.logger.info({trimmedCount:g,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let _=m.slice(0,m.length-y.length),v=this.summarizeTrimmedMessages(_);y.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${g} messages were trimmed to fit the context window:
657
- ${v}
722
+ ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:T-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0){let r=this.llm.getContextWindow(),o=Math.floor(r.maxInputTokens*ac),n=$e(e)+s,i=t[t.length-1],a=Ss(i),d=n+a+200+500,m=o-d;if(m<=0)return this.logger.warn({maxInputTokens:o,systemTokens:n,latestTokens:a},"Context window very tight, sending only latest message"),[i];let p=t.slice(0,-1),w=this.groupToolPairs(p),T=[];for(let $=w.length-1;$>=0;$--){let A=w[$].reduce((R,O)=>R+Ss(O),0);A>m||(m-=A,T.unshift(w[$]))}let g=T.flat(),b=p.length-g.length;if(b>0){this.logger.info({trimmedCount:b,totalMessages:t.length,maxInputTokens:o},"Trimmed conversation history to fit context window");let $=p.slice(0,p.length-g.length),A=this.summarizeTrimmedMessages($);g.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${b} messages were trimmed to fit the context window:
723
+ ${A}
658
724
 
659
- The conversation continues below with the most recent messages.]`})}return y.push(o),this.promptBuilder.sanitizeToolMessages(y)}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(`
725
+ The conversation continues below with the most recent messages.]`})}return g.push(i),this.promptBuilder.sanitizeToolMessages(g)}summarizeTrimmedMessages(e){let t=[];for(let r of e){let o=this.extractMessageText(r);if(!o)continue;let n=o.length>150?o.slice(0,150)+"...":o,i=r.role==="user"?"User":"Assistant";if(t.push(`- ${i}: ${n}`),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(`
660
726
  `)}return t.join(`
661
- `)}extractMessageText(e){if(typeof e.content=="string")return e.content;if(!Array.isArray(e.content))return"";let t=[];for(let s of e.content)s.type==="text"&&s.text&&t.push(s.text);return t.join(" ")}groupToolPairs(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=[r];if(s+1<e.length&&e[s+1].role==="user"){let o=e[s+1];if(Array.isArray(o.content)&&o.content.some(i=>i.type==="tool_result")){n.push(o),s+=2,t.push(n);continue}}if(n.length===1&&s+1<e.length&&e[s+1].role==="user"){n.push(e[s+1]),s+=2,t.push(n);continue}t.push(n),s++}else t.push([r]),s++}return t}async buildUserContent(e,t){let s=e.attachments?.filter(i=>i.data)??[];if(s.length===0)return e.text;let r=[];for(let i of s)if(i.type==="image"&&i.data)r.push({type:"image",source:{type:"base64",media_type:i.mimeType??"image/jpeg",data:i.data.toString("base64")}}),this.logger.info({mimeType:i.mimeType,size:i.size},"Image attached to LLM request");else if(i.type==="audio"&&i.data)if(this.speechTranscriber){t?.("Transcribing voice...");try{let a=await this.speechTranscriber.transcribe(i.data,i.mimeType??"audio/ogg"),l=e.text==="[Voice message]"?"":`${e.text}
727
+ `)}extractMessageText(e){if(typeof e.content=="string")return e.content;if(!Array.isArray(e.content))return"";let t=[];for(let s of e.content)s.type==="text"&&s.text&&t.push(s.text);return t.join(" ")}groupToolPairs(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(o=>o.type==="tool_use")){let o=[r];if(s+1<e.length&&e[s+1].role==="user"){let n=e[s+1];if(Array.isArray(n.content)&&n.content.some(i=>i.type==="tool_result")){o.push(n),s+=2,t.push(o);continue}}if(o.length===1&&s+1<e.length&&e[s+1].role==="user"){o.push(e[s+1]),s+=2,t.push(o);continue}t.push(o),s++}else t.push([r]),s++}return t}async buildUserContent(e,t){let s=e.attachments?.filter(i=>i.data)??[];if(s.length===0)return e.text;let r=[];for(let i of s)if(i.type==="image"&&i.data)r.push({type:"image",source:{type:"base64",media_type:i.mimeType??"image/jpeg",data:i.data.toString("base64")}}),this.logger.info({mimeType:i.mimeType,size:i.size},"Image attached to LLM request");else if(i.type==="audio"&&i.data)if(this.speechTranscriber){t?.("Transcribing voice...");try{let a=await this.speechTranscriber.transcribe(i.data,i.mimeType??"audio/ogg"),l=e.text==="[Voice message]"?"":`${e.text}
662
728
 
663
729
  `;if(r.push({type:"text",text:`${l}[Voice transcript]: ${a}`}),this.logger.info({transcriptLength:a.length},"Voice message transcribed"),s.length===1)return r.length===1&&r[0].type==="text"?r[0].text:r}catch(a){this.logger.error({err:a},"Voice transcription failed"),r.push({type:"text",text:"[Voice message could not be transcribed]"})}}else r.push({type:"text",text:"[Voice message received but speech-to-text is not configured. Add speech config to enable transcription.]"});else if((i.type==="document"||i.type==="video"||i.type==="other")&&i.data){let a=this.saveToInbox(i);if(a){let l=this.isTextMimeType(i.mimeType),d=`[File received: "${i.fileName??"unknown"}" (${this.formatBytes(i.data.length)}, ${i.mimeType??"unknown type"})]
664
- [Saved to: ${a}]`;if(l&&i.data.length<=Wl){let m=i.data.toString("utf-8");d+=`
730
+ [Saved to: ${a}]`;if(l&&i.data.length<=Vd){let m=i.data.toString("utf-8");d+=`
665
731
  [File content]:
666
- ${m}`}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");return r.some(i=>i.type==="image")&&!o?r.push({type:"text",text:"What do you see in this image?"}):n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?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."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),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??ga.resolve("./data/inbox");try{fa.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=ga.join(t,o);try{return fa.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}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 Ns,Kn=b(()=>{"use strict";Ns=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 Cs,Gn=b(()=>{"use strict";Cs=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 Os,Yn=b(()=>{"use strict";Os=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 Ds,Jn=b(()=>{"use strict";Ds=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 Us,Zn=b(()=>{"use strict";Us=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;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}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}}});var Ps,Qn=b(()=>{"use strict";Ps=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 this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),l=this.chunkText(n,500,50);for(let d=0;d<l.length;d++){let m;try{await this.embeddingService.embedAndStore(e,l[d],"document",`${a.id}:${d}`),m=`${a.id}:${d}`}catch(h){this.logger.warn({documentId:a.id,chunkIndex:d,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,d,l[d],m)}return this.docRepo.updateChunkCount(a.id,l.length),this.logger.info({documentId:a.id,filename:s,chunkCount:l.length},"Document ingested"),{documentId:a.id,chunkCount:l.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),h=m.lastIndexOf(`
732
+ ${m}`}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let o=this.isSyntheticLabel(e.text);e.text&&!o&&r.push({type:"text",text:e.text});let n=r.some(i=>i.type==="text");return r.some(i=>i.type==="image")&&!n?r.push({type:"text",text:"What do you see in this image?"}):o&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?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."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),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??nc.resolve("./data/inbox");try{oc.mkdirSync(t,{recursive:!0})}catch{this.logger.error({inboxDir:t},"Cannot create inbox directory");return}let s=new Date().toISOString().replace(/[:.]/g,"-"),o=(e.fileName??`file_${s}`).replace(/[<>:"/\\|?*]/g,"_"),n=`${s}_${o}`,i=nc.join(t,n);try{return oc.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}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 Vs,_n=y(()=>{"use strict";Vs=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,o){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=o,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),o=this.linkedUsers.getLinkedUsers(r);for(let n of o){if(n.platform===t.platform)continue;let i=this.linkedUsers.findConversation(n.platform,n.id);i&&await this.sendMessage(n.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 Ws,$n=y(()=>{"use strict";Ws=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 o=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!o.ok){let i=await o.text();throw new Error(`Whisper API ${o.status}: ${i}`)}let n=await o.json();return this.logger.info({textLength:n.text.length},"Voice transcribed"),n.text}catch(o){throw this.logger.error({err:o},"Voice transcription failed"),o}}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 Xs,vn=y(()=>{"use strict";Xs=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 Gs,Sn=y(()=>{"use strict";Gs=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,o)=>`<pre>${this.escapeHTML(o.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 Ks,kn=y(()=>{"use strict";Ks=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 o=await this.llm.embed(t);if(!o)return;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:o.embedding,model:o.model,dimensions:o.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(o){this.logger.error({err:o,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let o=this.embeddingRepo.findByUser(e);if(o.length===0)return[];let n=o.map(a=>{let l=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:l}});return n.sort((a,l)=>l.score-a.score),n.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,o=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],o+=t[i]*t[i];let n=Math.sqrt(r)*Math.sqrt(o);return n===0?0:s/n}}});var Ys,An=y(()=>{"use strict";Ys=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 o=await this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),l=this.chunkText(o,500,50);for(let d=0;d<l.length;d++){let m;try{await this.embeddingService.embedAndStore(e,l[d],"document",`${a.id}:${d}`),m=`${a.id}:${d}`}catch(p){this.logger.warn({documentId:a.id,chunkIndex:d,err:p},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,d,l[d],m)}return this.docRepo.updateChunkCount(a.id,l.length),this.logger.info({documentId:a.id,filename:s,chunkCount:l.length},"Document ingested"),{documentId:a.id,chunkCount:l.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,o=s.readFileSync(e);return(await r(o)).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 o=Math.round(t*3.5),n=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let l=a+o;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(`
667
733
 
668
- `);if(h>0)l=d+h;else{let y=m.lastIndexOf(". ");y>0&&(l=d+y+1)}let w=e.slice(a,l).trim();w&&i.push(w),a=l-o}return i.filter(l=>l.length>0)}}});var Fs,eo=b(()=>{"use strict";Fs=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.logger=n}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 r={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",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}
734
+ `);if(p>0)l=d+p;else{let T=m.lastIndexOf(". ");T>0&&(l=d+T+1)}let w=e.slice(a,l).trim();w&&i.push(w),a=l-n}return i.filter(l=>l.length>0)}}});var Js,In=y(()=>{"use strict";Js=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,o){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,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 r={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},o=new Promise((l,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),n=await Promise.race([this.skillSandbox.execute(t,s,r),o]),i=JSON.stringify(n.data??n.display??n.error);this.taskRepo.updateStatus(e.id,n.success?"completed":"failed",i,n.error);let a=this.adapters.get(e.platform);if(a){let l=n.success?`\u2705 Background task completed: ${e.description}
669
735
 
670
- Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${e.description}
736
+ Result: ${n.display??JSON.stringify(n.data)}`:`\u274C Background task failed: ${e.description}
671
737
 
672
- 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}
738
+ Error: ${n.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}
673
739
 
674
- Error: ${s}`)}}}});import Vl from"node:crypto";var js,to=b(()=>{"use strict";js=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.logger=o,this.pipeline=i,this.formatter=a}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 o={id:`scheduled-${Vl.randomUUID()}`,platform:e.platform,chatId:e.chatId,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},i=await this.pipeline.process(o);s=(this.formatter?this.formatter.format(i.text,e.platform):{text:i.text,parseMode:"text"}).text;let l=this.adapters.get(e.platform);if(l&&i.attachments)for(let d of i.attachments)try{let m=d.mimeType.startsWith("image/"),h=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await l.sendPhoto(e.chatId,d.data,d.fileName):h?await l.sendVoice(e.chatId,d.data):await l.sendFile(e.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else{let o=this.skillRegistry.get(e.skillName);if(!o)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 i;try{i=JSON.parse(e.skillInput)}catch{i={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let a={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},l=await this.skillSandbox.execute(o,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
740
+ Error: ${s}`)}}}});import Gd from"node:crypto";var Zs,Rn=y(()=>{"use strict";Zs=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,o,n,i,a){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=o,this.logger=n,this.pipeline=i,this.formatter=a}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 n={id:`scheduled-${Gd.randomUUID()}`,platform:e.platform,chatId:e.chatId,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},i=await this.pipeline.process(n);s=(this.formatter?this.formatter.format(i.text,e.platform):{text:i.text,parseMode:"text"}).text;let l=this.adapters.get(e.platform);if(l&&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 l.sendPhoto(e.chatId,d.data,d.fileName):p?await l.sendVoice(e.chatId,d.data):await l.sendFile(e.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(n){let i=n instanceof Error?n.message:String(n);this.logger.error({actionId:e.id,err:n},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(n){let i=n instanceof Error?n.message:String(n);this.logger.error({actionId:e.id,err:n},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else{let n=this.skillRegistry.get(e.skillName);if(!n)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 i;try{i=JSON.parse(e.skillInput)}catch{i={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let a={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},l=await this.skillSandbox.execute(n,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
675
741
 
676
- ${l.display??JSON.stringify(l.data)}`:`\u274C Scheduled action "${e.name}" failed: ${l.error}`}catch(i){let a=i instanceof Error?i.message:String(i);s=`\u274C Scheduled action "${e.name}" failed: ${a}`}}let r=this.adapters.get(e.platform);if(r)try{await r.sendMessage(e.chatId,s)}catch(o){this.logger.error({err:o,actionId:e.id},"Failed to send scheduled action result")}let n=this.calculateNextRun(e);n?this.actionRepo.updateLastRun(e.id,t,n):(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 so(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Kl)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Gl)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 Kl,Gl,ro=b(()=>{"use strict";Kl=[/^(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],Gl=[{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(so,"scanSignal")});var Yl,Jl,Bs,no=b(()=>{"use strict";Yl=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Jl=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
742
+ ${l.display??JSON.stringify(l.data)}`:`\u274C Scheduled action "${e.name}" failed: ${l.error}`}catch(i){let a=i instanceof Error?i.message:String(i);s=`\u274C Scheduled action "${e.name}" failed: ${a}`}}let r=this.adapters.get(e.platform);if(r)try{await r.sendMessage(e.chatId,s)}catch(n){this.logger.error({err:n,actionId:e.id},"Failed to send scheduled action result")}let o=this.calculateNextRun(e);o?this.actionRepo.updateLastRun(e.id,t,o):(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 o=0;o<1440;o++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),o=t.getDate(),n=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],o)&&this.matchCronField(e[3],n)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let o=parseInt(s[1],10);return t%o===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}}});function xn(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Kd)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Yd)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 Kd,Yd,Cn=y(()=>{"use strict";Kd=[/^(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],Yd=[{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(xn,"scanSignal")});var Jd,Zd,Qs,Ln=y(()=>{"use strict";Jd=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Zd=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
677
743
 
678
744
  Rules:
679
745
  - Only extract information the user STATES about themselves
@@ -693,63 +759,65 @@ Extract memories from this conversation:
693
759
  User: {USER_MESSAGE}
694
760
  Assistant: {ASSISTANT_RESPONSE}
695
761
 
696
- Return ONLY a valid JSON array, no explanation:`,Bs=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=Jl.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 Yl.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var Hs,oo=b(()=>{"use strict";ro();no();Hs=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 Bs(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=so(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 Zl,Ql,ed,td,qs,io=b(()=>{"use strict";Zl=Math.LN2,Ql=.3,ed=.7,td=3,qs=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 g of n)for(let _ of this.memoryRepo.keywordSearch(g,t,30))o.has(_.id)||(o.add(_.id),i.push(_));let a=[],l=!1;if(this.embeddingService)try{let g=new Set;for(let _ of n)for(let v of await this.embeddingService.semanticSearch(_,t,30))g.has(v.key)||(g.add(v.key),a.push(v));l=a.length>0}catch(g){this.logger.debug({err:g},"Semantic search failed, falling back to keyword-only")}let d=new Map,m=i.length;for(let g=0;g<i.length;g++){let _=i[g],v=m>0?1-g/m:0,R=l?Ql:1,x=this.applyBoosts(v*R,_);d.set(_.key,{memory:{key:_.key,value:_.value,category:_.category,type:_.type,score:x},score:x}),this.memoryRepo.recordAccess(_.id)}if(l)for(let g of a){let _=g.score*ed,v=d.get(g.key);if(v)v.score+=_,v.memory.score=v.score;else{let R=this.memoryRepo.recall(e,g.key),x=this.applyBoosts(_,R||void 0);d.set(g.key,{memory:{key:g.key,value:g.value,category:g.category,type:R?.type||"general",score:x},score:x}),R&&this.memoryRepo.recordAccess(R.id)}}let h=Array.from(d.values()).sort((g,_)=>_.score-g.score),w=new Map,y=[];for(let{memory:g}of h){let _=w.get(g.type)||0;if(!(_>=td)&&(w.set(g.type,_+1),y.push(g),y.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:y.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),y}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(-Zl*n/2592e6);s*=o}return s}}});import{EventEmitter as sd}from"node:events";var Q,Ie=b(()=>{"use strict";Q=class extends sd{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(`
762
+ Return ONLY a valid JSON array, no explanation:`,Qs=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,o=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=o}async extract(e,t,s){try{let r=Zd.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),o=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),n=this.parseResponse(o.content);if(n.length===0)return 0;let i=0;for(let a of n)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 Jd.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var er,Nn=y(()=>{"use strict";Cn();Ln();er=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 Qs(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=xn(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(o=>{o>0&&this.logger.info({userId:e,extractedCount:o},"Auto-extraction complete")}).catch(o=>{this.logger.error({err:o},"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 o=r.filter(n=>n>s);return this.extractionTimestamps.set(e,o),o.length>=this.maxExtractionsPerMinute?!1:(o.push(t),!0)}}});var Qd,eu,tu,su,tr,Mn=y(()=>{"use strict";Qd=Math.LN2,eu=.3,tu=.7,su=3,tr=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 o=[e];if(r)for(let n of r)n!==e&&o.push(n);try{let n=new Set,i=[];for(let g of o)for(let b of this.memoryRepo.keywordSearch(g,t,30))n.has(b.id)||(n.add(b.id),i.push(b));let a=[],l=!1;if(this.embeddingService)try{let g=new Set;for(let b of o)for(let $ of await this.embeddingService.semanticSearch(b,t,30))g.has($.key)||(g.add($.key),a.push($));l=a.length>0}catch(g){this.logger.debug({err:g},"Semantic search failed, falling back to keyword-only")}let d=new Map,m=i.length;for(let g=0;g<i.length;g++){let b=i[g],$=m>0?1-g/m:0,A=l?eu:1,R=this.applyBoosts($*A,b);d.set(b.key,{memory:{key:b.key,value:b.value,category:b.category,type:b.type,score:R},score:R}),this.memoryRepo.recordAccess(b.id)}if(l)for(let g of a){let b=g.score*tu,$=d.get(g.key);if($)$.score+=b,$.memory.score=$.score;else{let A=this.memoryRepo.recall(e,g.key),R=this.applyBoosts(b,A||void 0);d.set(g.key,{memory:{key:g.key,value:g.value,category:g.category,type:A?.type||"general",score:R},score:R}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((g,b)=>b.score-g.score),w=new Map,T=[];for(let{memory:g}of p){let b=w.get(g.type)||0;if(!(b>=su)&&(w.set(g.type,b+1),T.push(g),T.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:T.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),T}catch(n){this.logger.error({err:n},"Memory retrieval failed");let i=new Set,a=[];for(let l of o)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(),o=Date.now()-r,n=Math.exp(-Qd*o/2592e6);s*=n}return s}}});import{EventEmitter as ru}from"node:events";var te,Ne=y(()=>{"use strict";te=class extends ru{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 o=-1,i=r.slice(0,t).lastIndexOf(`
697
763
 
698
- `);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 rd,InputFile as ao}from"grammy";function Ta(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var yr,_a=b(()=>{"use strict";Ie();u(Ta,"mapParseMode");yr=class extends Q{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new rd(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:Ta(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:Ta(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 ao(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 ao(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new ao(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 nd,GatewayIntentBits as wr,Events as co}from"discord.js";var br,Ea=b(()=>{"use strict";Ie();br=class extends Q{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new nd({intents:[wr.Guilds,wr.GuildMessages,wr.MessageContent,wr.DirectMessages]}),this.client.on(co.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(co.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(co.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 Tr,$a=b(()=>{"use strict";Ie();Tr=class extends Q{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 h=await m.arrayBuffer(),w=Buffer.from(h);return{type:t,mimeType:n,fileName:i,size:o??w.length,data:w}}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 _r,va=b(()=>{"use strict";Ie();_r=class extends Q{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:n,downloadMediaMessage:o}=t;this.downloadMedia=o;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",l=>{if(l.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),l.connection==="close"){let m=l.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),m){let h=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),h)}}}),this.socket.ev.on("messages.upsert",({messages:l,type:d})=>{if(d==="notify")for(let m of l)m.message&&(m.key.fromMe||this.processMessage(m).catch(h=>{this.emit("error",h instanceof Error?h:new Error(String(h)))}))})}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 Er,Sa=b(()=>{"use strict";Ie();Er=class extends Q{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 lo from"node:readline";var $r,ka=b(()=>{"use strict";Ie();$r=class extends Q{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=lo.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
764
+ `);if(i>0&&(o=i),o<0){let l=r.slice(0,t).match(/.*[.!?]\s/s);l&&(o=l[0].length)}o<0&&(o=t),s.push(r.slice(0,o).trimEnd()),r=r.slice(o).trimStart()}return s}}});import{Bot as ou,InputFile as Dn}from"grammy";function lc(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var Ur,dc=y(()=>{"use strict";Ne();u(lc,"mapParseMode");Ur=class extends te{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new ou(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]",o=t.photo[t.photo.length-1],n=await this.downloadAttachment(o.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=n?[n]: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"}]`,o=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),n=this.normalizeMessage(t,r);n.attachments=o?[o]:void 0,this.emit("message",n)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",o=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),n=this.normalizeMessage(t,r);n.attachments=o?[o]:void 0,this.emit("message",n)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,o=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,n=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,o);i.attachments=n?[n]: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),o="";for(let n of r){let i=await this.bot.api.sendMessage(Number(e),n,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:lc(s?.parseMode)});o=String(i.message_id)}return o}async editMessage(e,t,s,r){await this.bot.api.editMessageText(Number(e),Number(t),s,{parse_mode:lc(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 Dn(t,"image.png"),{caption:s});return String(r.message_id)}async sendFile(e,t,s,r){let o=await this.bot.api.sendDocument(Number(e),new Dn(t,s),{caption:r});return String(o.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Dn(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 n=(await this.bot.api.getFile(e)).file_path;if(!n)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${n}`,a=await fetch(i);if(!a.ok)return;let l=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??n.split("/").pop(),size:l.length,data:l}}catch(o){console.error("[telegram] Failed to download file",e,o);return}}}});import{Client as nu,GatewayIntentBits as Pr,Events as On}from"discord.js";var Fr,uc=y(()=>{"use strict";Ne();Fr=class extends te{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new nu({intents:[Pr.Guilds,Pr.GuildMessages,Pr.MessageContent,Pr.DirectMessages]}),this.client.on(On.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(On.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(On.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 o=this.splitText(t,2e3),n="";for(let i=0;i<o.length;i++)i===0&&s?.replyToMessageId?n=(await(await r.messages.fetch(s.replyToMessageId)).reply(o[i])).id:n=(await r.send(o[i])).id;return n}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let o=await this.client.channels.fetch(e);if(!o?.isTextBased()||!("messages"in o))throw new Error(`Channel ${e} is not a text channel`);await(await o.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 o=await this.client.channels.fetch(e);return!o?.isTextBased()||!("send"in o)?void 0:(await o.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 o=await fetch(r.url);if(!o.ok)continue;let n=await o.arrayBuffer(),i=Buffer.from(n),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(o){console.error("[discord] Failed to download attachment",r.url,o)}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 jr,mc=y(()=>{"use strict";Ne();jr=class extends te{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(o,n)=>{if(n.sender===this.botUserId)return;let i=n.content?.msgtype;if(i)try{let a=await this.normalizeEvent(o,n,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),o="";for(let n of r)s?.parseMode==="html"?o=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:n.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:n}):o=await this.client.sendText(e,n);return o}async editMessage(e,t,s,r){let o=r?.parseMode==="html",n={msgtype:"m.text",body:"* "+(o?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:o?s.replace(/<[^>]*>/g,""):s,...o?{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",n)}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"),o={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",o)}async sendFile(e,t,s,r){let o=this.guessMimeType(s),n=await this.client.uploadContent(t,o,s),i={msgtype:"m.file",body:r??s,filename:s,url:n,info:{mimetype:o,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 o={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{...o,text:t.content.body};case"m.image":{let n=await this.downloadAttachment(t.content,"image");return n&&t.content.body&&(n.fileName=t.content.body),{...o,text:"[Photo]",attachments:n?[n]:void 0}}case"m.audio":{let n=await this.downloadAttachment(t.content,"audio");return n&&t.content.body&&(n.fileName=t.content.body),{...o,text:"[Voice message]",attachments:n?[n]:void 0}}case"m.video":{let n=await this.downloadAttachment(t.content,"video");return n&&t.content.body&&(n.fileName=t.content.body),{...o,text:"[Video]",attachments:n?[n]:void 0}}case"m.file":{let n=await this.downloadAttachment(t.content,"document");return n&&t.content.body&&(n.fileName=t.content.body),{...o,text:"[Document]",attachments:n?[n]:void 0}}default:return t.content.body?{...o,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},o=r.mimetype,n=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(),w=Buffer.from(p);return{type:t,mimeType:o,fileName:i,size:n??w.length,data:w}}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 Br,pc=y(()=>{"use strict";Ne();Br=class extends te{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:o,downloadMediaMessage:n}=t;this.downloadMedia=n;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",l=>{if(l.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),l.connection==="close"){let m=l.lastDisconnect?.error?.output?.statusCode!==o.loggedOut;if(this.status="disconnected",this.emit("disconnected"),m){let p=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),p)}}}),this.socket.ev.on("messages.upsert",({messages:l,type:d})=>{if(d==="notify")for(let m of l)m.message&&(m.key.fromMe||this.processMessage(m).catch(p=>{this.emit("error",p instanceof Error?p:new Error(String(p)))}))})}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),o="";for(let n=0;n<r.length;n++)o=(await this.socket.sendMessage(e,{text:r[n]},n===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return o}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=[],o=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})}o||(o="[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})}o||(o="[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}),o||(o="[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}),o||(o="[Document]")}else if(t.stickerMessage&&!s)return;if(!o&&r.length===0)return;let n={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:o,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",n)}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 qr,fc=y(()=>{"use strict";Ne();qr=class extends te{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(o=>{this.emit("error",o instanceof Error?o:new Error(String(o)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let o=1e3*Math.pow(2,s);await new Promise(n=>setTimeout(n,o))}}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),o="";for(let n of r){let i=e.startsWith("group."),a={message:n,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();o=String(d.timestamp??Date.now())}return o}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 o=s.envelope,n=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:o.sourceNumber??o.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:n,chatType:r.groupInfo?"group":"dm",userId:o.sourceNumber??o.source??"",userName:o.sourceName??o.sourceNumber??o.source??"",displayName:o.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 Un from"node:readline";var Hr,hc=y(()=>{"use strict";Ne();Hr=class extends te{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Un.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
699
765
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
700
766
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
701
767
  Goodbye!
702
768
  `),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(`
703
769
  Alfred: ${t}
704
- `),this.prompt(),r}async editMessage(e,t,s,r){lo.clearLine(process.stdout,0),lo.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import od from"node:http";import id from"node:crypto";var vr,xa=b(()=>{"use strict";Ie();vr=class extends Q{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=od.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-${id.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}
770
+ `),this.prompt(),r}async editMessage(e,t,s,r){Un.clearLine(process.stdout,0),Un.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import iu from"node:http";import au from"node:crypto";var zr,gc=y(()=>{"use strict";Ne();zr=class extends te{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=iu.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}`,o=this.streams.get(e);return o&&this.writeSseEvent(o,"response",{type:"response",text:t}),r}async editMessage(e,t,s,r){let o=this.streams.get(e);o&&this.writeSseEvent(o,"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 o=this.streams.get(e);return o&&this.writeSseEvent(o,"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),o=r.text;if(!o||typeof o!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let n=r.chatId??`api-chat-${au.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(n);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(n,t),e.on("close",()=>{this.streams.delete(n)}),this.messageCounter++;let l={id:`api-${this.messageCounter}`,platform:"api",chatId:n,chatType:"dm",userId:i,userName:i,displayName:"API User",text:o,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}
705
771
  data: ${JSON.stringify(s)}
706
772
 
707
- `)}}});var Ce={};oe(Ce,{CLIAdapter:()=>$r,DiscordAdapter:()=>br,HttpAdapter:()=>vr,MatrixAdapter:()=>Tr,MessagingAdapter:()=>Q,SignalAdapter:()=>Er,TelegramAdapter:()=>yr,WhatsAppAdapter:()=>_r});var Oe=b(()=>{"use strict";Ie();_a();Ea();$a();va();Sa();ka();xa()});import Sr from"node:fs";import kr from"node:path";import ad from"js-yaml";var st,Ia=b(()=>{"use strict";on();ln();Le();Tn();sr();pe();zn();Vn();Kn();Gn();Yn();Jn();Zn();Qn();eo();to();oo();io();st=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Ds;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Jt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new We(this.config.storage.path);let e=this.database.getDb(),t=new Zt(e),s=new Qt(e);this.userRepo=s;let r=new Xe(e),n=new es(e),o=new ts(e),i=new ss(e),a=new rs(e),l=new ns(e),d=new os(e),m=new is(e);this.logger.info("Storage initialized");let h=new ys,w=this.loadSecurityRules();h.loadRules(w);let y=new ws(h,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:w.length},"Security engine initialized");let g=bn(this.config.llm);await g.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let _=new Us(g,a,this.logger.child({component:"embeddings"})),v=this.config.activeLearning?.enabled!==!1,R,x;v&&(R=new Hs({llm:g,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:_,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),x=new qs(n,this.logger.child({component:"memory-retriever"}),_),this.logger.info("Active learning & memory retriever initialized"));let O=new ct(this.logger.child({component:"sandbox"})),N=this.skillRegistry=new at;if(N.register(new lt),N.register(new dt),N.register(new ut(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),N.register(new mt(o)),N.register(new pt(i)),N.register(new ht),N.register(new ft),N.register(new gt(n,_)),N.register(new yt(g,N,O,y)),this.config.email?.accounts?.length){let L=new Map;for(let W of this.config.email.accounts)try{W.provider==="microsoft"&&!W.microsoft?.clientId&&this.config.calendar?.microsoft&&(W.microsoft={...this.config.calendar.microsoft});let F=await bs(W);L.set(W.name,F),this.logger.info({account:W.name,provider:W.provider??"imap-smtp"},"Email account initialized")}catch(F){this.logger.warn({err:F,account:W.name},"Email account initialization failed, skipping")}N.register(L.size>0?new Me(L):new Me)}else N.register(new Me);N.register(new wt),N.register(new bt);let B=new Mt;B.setReloadCallback(L=>this.reloadService(L)),N.register(B),N.register(new _t),N.register(new Et),N.register(new $t),N.register(new vt(s)),N.register(new St(s,l,this.adapters,(L,W)=>t.findByPlatformAndUser(L,W))),N.register(new kt(d)),N.register(new xt(m));let H=new as(e),ae=new Ps(H,_,this.logger.child({component:"documents"}));N.register(new At(H,ae,_));let Pe;if(this.config.calendar)try{let L=await Es(this.config.calendar);Pe=new Ye(L),N.register(Pe),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(L){this.logger.warn({err:L},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=Pe,this.config.mcp?.servers?.length){let{MCPManager:L}=await Promise.resolve().then(()=>(pe(),be));this.mcpManager=new L(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let W of this.mcpManager.getSkills())N.register(W);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},g)),this.logger.info({agents:this.config.codeAgents.agents.map(W=>W.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}this.logger.info({skills:N.getAll().map(L=>L.metadata.name)},"Skills registered");let he;if(this.config.speech?.apiKey&&(he=new Cs(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 L=new Os(this.config.speech,this.logger.child({component:"tts"}));N.register(new Rt(L)),this.logger.info("Text-to-speech skill registered")}let Y=new Ls(t),re=kr.resolve(kr.dirname(this.config.storage.path),"inbox");this.pipeline=new Ms({llm:g,conversationManager:Y,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:N,skillSandbox:O,securityManager:y,memoryRepo:n,speechTranscriber:he,inboxPath:re,embeddingService:_,activeLearning:R,memoryRetriever:x}),this.reminderScheduler=new Ns(o,async(L,W,F)=>{let V=this.adapters.get(L);V?await V.sendMessage(W,F):this.logger.warn({platform:L,chatId:W},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(L=>s.getMasterUserId(L),"getMasterUserId"),getLinkedUsers:u(L=>s.getLinkedUsers(L),"getLinkedUsers"),findConversation:u((L,W)=>t.findByPlatformAndUser(L,W),"findConversation")}),this.backgroundTaskRunner=new Fs(N,O,d,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new js(m,N,O,g,this.adapters,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter),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(()=>(Oe(),Ce));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(()=>(Oe(),Ce));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(()=>(Oe(),Ce));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(()=>(Oe(),Ce));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(()=>(Oe(),Ce));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(()=>(Oe(),Ce)),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.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(()=>(Oe(),Ce)),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.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{rn();let t=new te().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(pe(),be));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(()=>(pe(),be));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(()=>(pe(),be));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant 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/"),h=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):h?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")})}loadSecurityRules(){let e=kr.resolve(this.config.security.rulesPath),t=[];if(!Sr.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Sr.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Sr.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=kr.join(e,n),i=Sr.readFileSync(o,"utf-8"),a=ad.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 Aa=b(()=>{"use strict"});var uo=b(()=>{"use strict";Ia();Vn();zn();Kn();Gn();Yn();Jn();Zn();eo();to();Qn();oo();io();no();Aa();ro()});var Ra={};oe(Ra,{startCommand:()=>cd});async function cd(){let c=new te,e;try{e=c.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Jt("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")}catch(o){t.fatal({error:o},"Failed to start Alfred"),process.exit(1)}}var La=b(()=>{"use strict";Le();on();uo();u(cd,"startCommand")});var Na={};oe(Na,{chatCommand:()=>ud});import Ma from"node:http";import Ws from"node:readline";function ld(c,e){return new Promise(t=>{let s=Ma.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 dd(c,e){let t=Ws.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
773
+ `)}}});var Fe={};re(Fe,{CLIAdapter:()=>Hr,DiscordAdapter:()=>Fr,HttpAdapter:()=>zr,MatrixAdapter:()=>jr,MessagingAdapter:()=>te,SignalAdapter:()=>qr,TelegramAdapter:()=>Ur,WhatsAppAdapter:()=>Br});var je=y(()=>{"use strict";Ne();dc();uc();mc();pc();fc();hc();gc()});import Vr from"node:fs";import Wr from"node:path";import cu from"js-yaml";var dt,yc=y(()=>{"use strict";Ao();xo();Oe();Bo();yr();ce();En();bn();_n();$n();vn();Sn();kn();An();In();Rn();Nn();Mn();dt=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Gs;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=is("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new Je(this.config.storage.path);let e=this.database.getDb(),t=new as(e),s=new cs(e);this.userRepo=s;let r=new Ze(e),o=new ls(e),n=new ds(e),i=new us(e),a=new ms(e),l=new ps(e),d=new fs(e),m=new hs(e);this.logger.info("Storage initialized");let p=new As,w=this.loadSecurityRules();p.loadRules(w);let T=new Is(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:w.length},"Security engine initialized");let g=jo(this.config.llm);await g.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let b=new Ks(g,a,this.logger.child({component:"embeddings"})),$=this.config.activeLearning?.enabled!==!1,A,R;$&&(A=new er({llm:g,memoryRepo:o,logger:this.logger.child({component:"active-learning"}),embeddingService:b,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),R=new tr(o,this.logger.child({component:"memory-retriever"}),b),this.logger.info("Active learning & memory retriever initialized"));let O=new gt(this.logger.child({component:"sandbox"})),N=this.skillRegistry=new ht;N.register(new yt),N.register(new wt),N.register(new Tt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),N.register(new Et(n)),N.register(new bt(i));let K=new ys(e);if(N.register(new Ft(K)),N.register(new _t),N.register(new $t),N.register(new vt(o,b)),N.register(new St(g,N,O,T)),this.config.email?.accounts?.length){let L=new Map;for(let W of this.config.email.accounts)try{W.provider==="microsoft"&&!W.microsoft?.clientId&&this.config.calendar?.microsoft&&(W.microsoft={...this.config.calendar.microsoft});let B=await Rs(W);L.set(W.name,B),this.logger.info({account:W.name,provider:W.provider??"imap-smtp"},"Email account initialized")}catch(B){this.logger.warn({err:B,account:W.name},"Email account initialization failed, skipping")}N.register(L.size>0?new Ue(L):new Ue)}else N.register(new Ue);N.register(new kt),N.register(new At);let ie=new Bt;ie.setReloadCallback(L=>this.reloadService(L)),N.register(ie),N.register(new Rt),N.register(new xt),N.register(new Ct),N.register(new Lt(s)),N.register(new Nt(s,l,this.adapters,(L,W)=>t.findByPlatformAndUser(L,W))),N.register(new Mt(d)),N.register(new Dt(m));let V=new gs(e),we=new Ys(V,b,this.logger.child({component:"documents"}));N.register(new Ut(V,we,b));let xe;if(this.config.calendar)try{let L=await Ls(this.config.calendar);xe=new rt(L),N.register(xe),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(L){this.logger.warn({err:L},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=xe,this.config.mcp?.servers?.length){let{MCPManager:L}=await Promise.resolve().then(()=>(ce(),ue));this.mcpManager=new L(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let W of this.mcpManager.getSkills())N.register(W);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},g)),this.logger.info({agents:this.config.codeAgents.agents.map(W=>W.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:L,createContactsProvider:W}=await Promise.resolve().then(()=>(ce(),ue)),B=await W(this.config.contacts);N.register(new L(B)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(L){this.logger.warn({err:L},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:L}=await Promise.resolve().then(()=>(ce(),ue));N.register(new L(this.config.docker)),this.logger.info("Docker skill enabled")}this.logger.info({skills:N.getAll().map(L=>L.metadata.name)},"Skills registered");let Y;if(this.config.speech?.apiKey&&(Y=new Ws(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 L=new Xs(this.config.speech,this.logger.child({component:"tts"}));N.register(new Pt(L)),this.logger.info("Text-to-speech skill registered")}let J=new Hs(t),de=Wr.resolve(Wr.dirname(this.config.storage.path),"inbox");this.pipeline=new zs({llm:g,conversationManager:J,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:N,skillSandbox:O,securityManager:T,memoryRepo:o,speechTranscriber:Y,inboxPath:de,embeddingService:b,activeLearning:A,memoryRetriever:R}),this.reminderScheduler=new Vs(n,async(L,W,B)=>{let F=this.adapters.get(L);F?await F.sendMessage(W,B):this.logger.warn({platform:L,chatId:W},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(L=>s.getMasterUserId(L),"getMasterUserId"),getLinkedUsers:u(L=>s.getLinkedUsers(L),"getLinkedUsers"),findConversation:u((L,W)=>t.findByPlatformAndUser(L,W),"findConversation")}),this.backgroundTaskRunner=new Js(N,O,d,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Zs(m,N,O,g,this.adapters,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter),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(()=>(je(),Fe));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(()=>(je(),Fe));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(()=>(je(),Fe));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(()=>(je(),Fe));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(()=>(je(),Fe));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(()=>(je(),Fe)),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.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(()=>(je(),Fe)),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.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{So();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(()=>(ce(),ue));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(()=>(ce(),ue));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(()=>(ce(),ue));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(()=>(ce(),ue)),o=await r(t.contacts);this.skillRegistry.register(new s(o)),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(()=>(ce(),ue));this.skillRegistry.register(new s(t.docker)),this.config.docker=t.docker,this.logger.info("Docker 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 o=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,o),this.logger.info({apiUserId:t.id,masterUserId:o},"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,o="",n=u(async d=>{if(d!==o){o=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,n),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(o){this.logger.error({err:o},"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")})}loadSecurityRules(){let e=Wr.resolve(this.config.security.rulesPath),t=[];if(!Vr.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Vr.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Vr.readdirSync(e).filter(o=>o.endsWith(".yml")||o.endsWith(".yaml"));for(let o of r)try{let n=Wr.join(e,o),i=Vr.readFileSync(n,"utf-8"),a=cu.load(i);a?.rules&&Array.isArray(a.rules)&&(t.push(...a.rules),this.logger.info({file:o,count:a.rules.length},"Loaded security rules"))}catch(n){this.logger.error({err:n,file:o},"Failed to load security rules file")}return t}}});var wc=y(()=>{"use strict"});var Pn=y(()=>{"use strict";yc();bn();En();_n();$n();vn();Sn();kn();In();Rn();An();Nn();Mn();Ln();wc();Cn()});var Tc={};re(Tc,{startCommand:()=>lu});async function lu(){let c=new oe,e;try{e=c.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let t=is("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new dt(e),r=!1,o=u(async n=>{if(!r){r=!0,t.info({signal:n},"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",()=>o("SIGINT")),process.on("SIGTERM",()=>o("SIGTERM")),process.on("uncaughtException",n=>{t.fatal({error:n},"Uncaught exception"),o("uncaughtException")}),process.on("unhandledRejection",n=>{t.fatal({reason:n},"Unhandled rejection"),o("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready")}catch(n){t.fatal({error:n},"Failed to start Alfred"),process.exit(1)}}var Ec=y(()=>{"use strict";Oe();Ao();Pn();u(lu,"startCommand")});var _c={};re(_c,{chatCommand:()=>mu});import bc from"node:http";import sr from"node:readline";function du(c,e){return new Promise(t=>{let s=bc.get(`http://${c}:${e}/api/health`,{timeout:2e3},r=>{let o="";r.on("data",n=>{o+=n.toString()}),r.on("end",()=>{try{let n=JSON.parse(o);t(n.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function uu(c,e){let t=sr.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
708
774
  Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
709
775
  `),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
710
776
  Goodbye!
711
- `),t.close(),process.exit(0));let n=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),o=Ma.request({hostname:c,port:e,path:"/api/message",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n)}},i=>{let a="";i.on("data",l=>{a+=l.toString();let d=a.split(`
777
+ `),t.close(),process.exit(0));let o=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),n=bc.request({hostname:c,port:e,path:"/api/message",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(o)}},i=>{let a="";i.on("data",l=>{a+=l.toString();let d=a.split(`
712
778
 
713
- `);a=d.pop()??"";for(let m of d){let h=m.split(`
714
- `).find(w=>w.startsWith("data: "));if(h)try{let w=JSON.parse(h.slice(6));switch(w.type){case"status":Ws.clearLine(process.stdout,0),Ws.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${w.text??""}`);break;case"response":Ws.clearLine(process.stdout,0),Ws.cursorTo(process.stdout,0),process.stdout.write(`
779
+ `);a=d.pop()??"";for(let m of d){let p=m.split(`
780
+ `).find(w=>w.startsWith("data: "));if(p)try{let w=JSON.parse(p.slice(6));switch(w.type){case"status":sr.clearLine(process.stdout,0),sr.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${w.text??""}`);break;case"response":sr.clearLine(process.stdout,0),sr.cursorTo(process.stdout,0),process.stdout.write(`
715
781
  Alfred: ${w.text??""}
716
- `);break;case"attachment":{let y=w.fileName??w.attachmentType??"file";process.stdout.write(`[Attachment: ${y}]
782
+ `);break;case"attachment":{let T=w.fileName??w.attachmentType??"file";process.stdout.write(`[Attachment: ${T}]
717
783
  `);break}case"done":t.prompt();break;case"error":process.stdout.write(`
718
784
  Error: ${w.text??"Unknown error"}
719
785
  `),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let l=a.split(`
720
786
  `).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(`
721
- Connection error: ${l.message}`),t.prompt()})});o.on("error",i=>{console.error(`
722
- Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function ud(c){let e=new te,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 ld(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),dd(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 Ca=b(()=>{"use strict";Le();uo();u(ld,"checkHealth");u(dd,"startClientMode");u(ud,"chatCommand")});var Ua={};oe(Ua,{setupCommand:()=>Ed});import{createInterface as md}from"node:readline/promises";import{stdin as pd,stdout as hd}from"node:process";import{execFileSync as fd}from"node:child_process";import se from"node:fs";import gd from"node:os";import ie from"node:path";import mo from"js-yaml";function C(c){return`${Ir}${c}${k}`}function bd(c){return`${D}${c}${k}`}function Te(c){return`${Ar}${c}${k}`}function Da(c){return`${yd}${c}${k}`}function A(c){return`${ee}${c}${k}`}function T(c){return`${Ue}${c}${k}`}function ue(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Td(c){let e=process.platform==="win32",t=e?"where":"which";try{let n=fd(t,[c],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=gd.homedir(),r=e?[ie.join(s,".local","bin",`${c}.exe`),ie.join(s,"AppData","Roaming","npm",`${c}.cmd`),ie.join(s,"AppData","Roaming","npm",`${c}`)]:[ie.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,ie.join(s,".npm-global","bin",c)];for(let n of r)try{return se.accessSync(n,se.constants.X_OK),n}catch{}return null}function _d(c){let e={},t={},s=!1,r=!1,n=30,o=ie.join(c,"config","default.yml");if(se.existsSync(o))try{let h=mo.load(se.readFileSync(o,"utf-8"));h&&typeof h=="object"&&Object.assign(e,h)}catch{}let i=ie.join(c,".env");if(se.existsSync(i))try{let h=se.readFileSync(i,"utf-8").split(`
723
- `);for(let w of h){let y=w.trim();if(!y||y.startsWith("#"))continue;let g=y.indexOf("=");g>0&&(t[y.slice(0,g)]=y.slice(g+1))}}catch{}let a=ie.join(c,"config","rules","default-rules.yml");if(se.existsSync(a))try{let h=mo.load(se.readFileSync(a,"utf-8"));if(h?.rules){s=h.rules.some(g=>g.id==="allow-owner-admin"&&g.effect==="allow"),h.rules.find(g=>g.id==="allow-write-for-dm"||g.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let y=h.rules.find(g=>g.id==="rate-limit-write");y?.rateLimit?.maxInvocations&&(n=y.rateLimit.maxInvocations)}}catch{}let l=!!e.codeSandbox?.enabled,d=e.llm,m={};if(d){for(let h of["strong","fast","embeddings","local"])d[h]?.provider&&d[h]?.model&&(m[h]=d[h]);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 Ed(){let c=md({input:pd,output:hd}),e=process.cwd(),t=_d(e),s=Object.keys(t.config).length>0;try{$d(),console.log(s?`${Ar}Existing configuration found \u2014 press Enter to keep current values.${k}
724
- ${Ue}Only change what you need to update.${k}
725
- `:`${Ar}Welcome to the Alfred setup wizard!${k}
726
- ${Ue}This will walk you through configuring your AI assistant.${k}
727
- ${Ue}Press Enter to accept defaults shown in [brackets].${k}
728
- `);let r=await U(c,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?De.findIndex(p=>p.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
729
- ${A("Which LLM provider would you like to use?")}`);for(let p=0;p<De.length;p++){let E=p===n?` ${T("(current)")}`:"";console.log(` ${Te(String(p+1)+")")} ${De[p].label}${E}`)}let i=await xr(c,"> ",1,De.length,o),a=De[i-1];console.log(` ${C(">")} Selected: ${A(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await U(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await me(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${C(">")} API key set: ${T(ue(l))}`));let m=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let E=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(E){let $={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 U(c,$[a.name]??"API Base URL",E.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${C(">")} URL: ${T(m)}`)}}let w=t.config.llm?.model??a.defaultModel;console.log("");let y;if(a.models&&a.models.length>0){console.log(`${A("Available models:")}`);for(let $=0;$<a.models.length;$++){let X=a.models[$],M=X.id===w?` ${C("(current)")}`:"";console.log(` ${Te(`${$+1})`)} ${X.id} ${T(`\u2014 ${X.desc}`)}${M}`)}console.log(` ${Te(`${a.models.length+1})`)} ${T("Other (enter manually)")}`);let p=await U(c,"Choose model","1"),E=parseInt(p,10)-1;E>=0&&E<a.models.length?y=a.models[E].id:E===a.models.length?y=await U(c,"Model ID",w):y=await U(c,"Model ID",w)}else y=await U(c,"Which model?",w);let g=Object.keys(t.multiModelTiers).length>0,_=g?"Y/n":"y/N";console.log(`
730
- ${A("Configure additional model tiers for specialized tasks?")}`),console.log(`${T("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let v=(await c.question(`${D}> ${k}${T(`[${_}] `)}`)).trim().toLowerCase(),R=v===""?g:v==="y"||v==="yes",x={};if(R){let p=[{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 E of p){let $=t.multiModelTiers[E.key],X=!!$?.model;console.log(`
731
- ${A(`${E.label} model`)} ${T(`(${E.hint})`)}`),X&&console.log(` ${T(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${T("Press Enter to skip.")}`);let j=(await c.question(` ${D}Model: ${k}${X?T(`[${$.model}] `):""}`)).trim()||(X?$.model:"");if(!j){console.log(` ${T("Skipped.")}`);continue}let G=$?.provider??a.name,$e=De.map(Re=>Re.name).join(", ");console.log(` ${T(`Providers: ${$e}`)}`);let J=(await c.question(` ${D}Provider: ${k}${T(`[${G}] `)}`)).trim()||G,fe,ke;if(J!==a.name){let Re=$?.apiKey??t.env[`ALFRED_LLM_${E.key.toUpperCase()}_API_KEY`]??"";if(Re?fe=await U(c,` API key for ${J}`,Re):(De.find(nt=>nt.name===J)?.needsApiKey??!0)&&(fe=await me(c,` API key for ${J}`)),["ollama","openwebui"].includes(J)){let nt=($?.baseUrl??"")||De.find(Zr=>Zr.name===J)?.baseUrl||"";nt&&(ke=await U(c,` ${J} URL`,nt))}}x[E.key]={provider:J,model:j,...fe?{apiKey:fe}:{},...ke?{baseUrl:ke}:{}},console.log(` ${C(">")} ${E.label}: ${A(J)}/${A(j)}`)}Object.keys(x).length===0&&console.log(`
732
- ${T("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${T("Using single model for all tasks.")}`);let O=["brave","tavily","duckduckgo","searxng"],N=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",B=O.indexOf(N),H=B>=0?B+1:0;console.log(`
733
- ${A("Web Search provider (for searching the internet):")}`);let ae=["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"],Pe=u(p=>B===p?` ${T("(current)")}`:"","mark");console.log(` ${Te("0)")} None (disable web search)${B===-1&&N===""?` ${T("(current)")}`:""}`);for(let p=0;p<ae.length;p++)console.log(` ${Te(String(p+1)+")")} ${ae[p]}${Pe(p)}`);let he=await xr(c,"> ",0,O.length,H),Y,re="",L="";if(he>=1&&he<=O.length&&(Y=O[he-1]),Y==="brave"){let p=t.env.ALFRED_SEARCH_API_KEY??"";p?re=await U(c," Brave Search API key",p):(console.log(` ${T("Get your free API key at: https://brave.com/search/api/")}`),re=await me(c," Brave Search API key")),console.log(` ${C(">")} Brave Search: ${T(ue(re))}`)}else if(Y==="tavily"){let p=t.env.ALFRED_SEARCH_API_KEY??"";p?re=await U(c," Tavily API key",p):(console.log(` ${T("Get your free API key at: https://tavily.com/")}`),re=await me(c," Tavily API key")),console.log(` ${C(">")} Tavily: ${T(ue(re))}`)}else if(Y==="duckduckgo")console.log(` ${C(">")} DuckDuckGo: ${T("no API key needed")}`);else if(Y==="searxng"){let p=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";L=await U(c," SearXNG URL",p),L=L.replace(/\/+$/,""),console.log(` ${C(">")} SearXNG: ${T(L)}`)}else console.log(` ${T("Web search disabled \u2014 you can configure it later.")}`);let W=[];for(let p=0;p<Dt.length;p++){let E=Dt[p];t.config[E.configKey]?.enabled&&W.push(p+1)}let F=W.length>0?W.join(","):"";console.log(`
734
- ${A("Which messaging platforms do you want to enable?")}`),console.log(`${T("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let p=0;p<Dt.length;p++){let E=W.includes(p+1)?` ${T("(enabled)")}`:"";console.log(` ${Te(String(p+1)+")")} ${Dt[p].label}${E}`)}console.log(` ${Te("0)")} None (configure later)`);let V=(await c.question(`${D}> ${k}${F?T(`[${F}] `):""}`)).trim(),q=[],K=V||F;if(K&&K!=="0"){let p=K.split(",").map(E=>parseInt(E.trim(),10));for(let E of p)if(E>=1&&E<=Dt.length){let $=Dt[E-1];q.includes($)||q.push($)}}q.length>0?console.log(` ${C(">")} Enabling: ${q.map(p=>A(p.label)).join(", ")}`):console.log(` ${T("No platforms selected \u2014 you can configure them later.")}`);let ce={},Se={};for(let p of q){if(p.credentials.length===0){p.name==="whatsapp"&&console.log(`
735
- ${bd("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
736
- ${A(p.label+" configuration:")}`);let E={};for(let $ of p.credentials){let X=t.env[$.envKey]??"",M;X?M=await U(c,` ${$.prompt}`,X):$.defaultValue?M=await U(c,` ${$.prompt}`,$.defaultValue):$.required?M=await me(c,` ${$.prompt}`):(M=(await c.question(` ${$.prompt}: ${D}`)).trim(),process.stdout.write(k)),E[$.configField]=M,Se[$.envKey]=M,$.configField==="token"||$.configField==="accessToken"?console.log(` ${C(">")} Set: ${T(ue(M))}`):console.log(` ${C(">")} Set: ${T(M)}`)}ce[p.configKey]=E}let Lr=t.config.email?.accounts??[],Mr=Lr[0],Ya=Mr?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",Ja=Mr?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",fo=Lr.length>0||!!Ya||Ja==="microsoft",Za=fo?"Y/n":"y/N";console.log(`
737
- ${A("Email access (read & send emails)?")}`),console.log(`${T("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let Nr=(await c.question(`${D}> ${k}${T(`[${Za}] `)}`)).trim().toLowerCase(),zs=Nr===""?fo:Nr==="y"||Nr==="yes",_e=[],Qa={"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"}},go=u(async(p,E)=>{let $={name:p,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},X=E?.provider??"",M=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],j=X==="microsoft"?1:0;console.log("");for(let ne=0;ne<M.length;ne++){let J=ne===j?` ${T("(current)")}`:"";console.log(` ${Te(`${ne+1})`)} ${M[ne]}${J}`)}let G=(await c.question(`${D}> ${k}${T(`[${j+1}] `)}`)).trim(),$e=G===""?j:parseInt(G,10)-1;if($.provider=$e===1?"microsoft":"imap-smtp",$.provider==="microsoft"){let ne=t.config.calendar?.microsoft,J=E?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",fe=E?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",ke=E?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(ne&&!J)console.log(` ${C(">")} Microsoft Calendar already configured \u2014 credentials will be shared.`),console.log(` ${T("The same Azure App Registration will be used for Mail + Calendar.")}`),console.log(` ${T("Ensure the app has Mail.ReadWrite and Mail.Send scopes.")}`);else{console.log(` ${T("Azure Portal \u2192 App Registrations \u2192 your app \u2192 Mail.ReadWrite + Mail.Send scopes")}`),$.msClientId=await U(c," Client ID",J),$.msClientId||($.msClientId=await me(c," Client ID"));let Re=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";$.msClientSecret=await U(c," Client Secret",Re),$.msClientSecret||($.msClientSecret=await me(c," Client Secret")),$.msTenantId=await U(c," Tenant ID",fe),$.msTenantId||($.msTenantId=await me(c," Tenant ID")),$.msRefreshToken=await U(c," Refresh Token",ke),$.msRefreshToken||($.msRefreshToken=await me(c," Refresh Token"))}console.log(` ${C(">")} Email [${p}]: Microsoft 365 (Graph API)`)}else{let ne=E?.auth?.user??"";console.log(""),$.user=await U(c," Email address",ne||""),$.user||($.user=await me(c," Email address"));let J=E?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";J?$.pass=await U(c," Password / App password",J):(console.log(` ${T("For Gmail: use an App Password (not your regular password)")}`),console.log(` ${T(" \u2192 Google Account \u2192 Security \u2192 2-Step \u2192 App passwords")}`),$.pass=await me(c," Password / App password"));let fe=$.user.split("@")[1]?.toLowerCase()??"",ke=Qa[fe],Re=E?.imap?.host??ke?.imap??`imap.${fe}`,ko=E?.smtp?.host??ke?.smtp??`smtp.${fe}`,Jr=E?.imap?.port??993,nt=E?.smtp?.port??587;ke&&console.log(` ${C(">")} Detected ${fe} \u2014 using preset server settings`),$.imapHost=await U(c," IMAP server",Re);let Zr=await U(c," IMAP port",String(Jr));$.imapPort=parseInt(Zr,10)||993,$.smtpHost=await U(c," SMTP server",ko);let gc=await U(c," SMTP port",String(nt));$.smtpPort=parseInt(gc,10)||587,console.log(` ${C(">")} Email [${p}]: ${T($.user)} via ${T($.imapHost)}`)}return $},"configureEmailAccount");if(zs){let p=Mr??(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);_e.push(await go("default",p));let E=!0;for(;E;){let $=(await c.question(`
738
- ${A("Add another email account?")} ${T("[y/N]")} `)).trim().toLowerCase();if($==="y"||$==="yes"){let M=(await c.question(` ${A("Account name:")} `)).trim()||`account${_e.length+1}`,j=Lr.find(G=>G.name===M);_e.push(await go(M,j))}else E=!1}}else console.log(` ${T("Email disabled \u2014 you can configure it later.")}`);let Vs=["openai","groq"],ec=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",Ks=Vs.indexOf(ec),tc=Ks>=0?Ks+1:0;console.log(`
739
- ${A("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${T("Transcribes voice messages from Telegram, Discord, etc.")}`);let yo=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Te("0)")} None (disable voice transcription)${Ks===-1?` ${T("(current)")}`:""}`);for(let p=0;p<yo.length;p++){let E=Ks===p?` ${T("(current)")}`:"";console.log(` ${Te(String(p+1)+")")} ${yo[p]}${E}`)}let Cr=await xr(c,"> ",0,Vs.length,tc),Ee,Ae="",Ut="";if(Cr>=1&&Cr<=Vs.length&&(Ee=Vs[Cr-1]),Ee==="openai"){let p=t.env.ALFRED_SPEECH_API_KEY??"";p?Ae=await U(c," OpenAI API key (for Whisper)",p):(console.log(` ${T("Uses your OpenAI API key for Whisper transcription.")}`),Ae=await me(c," OpenAI API key")),console.log(` ${C(">")} OpenAI Whisper: ${T(ue(Ae))}`)}else if(Ee==="groq"){let p=t.env.ALFRED_SPEECH_API_KEY??"";p?Ae=await U(c," Groq API key",p):(console.log(` ${T("Get your free API key at: https://console.groq.com/")}`),Ae=await me(c," Groq API key"));let E=t.env.ALFRED_SPEECH_BASE_URL??"";E&&(Ut=await U(c," Groq API URL",E)),console.log(` ${C(">")} Groq Whisper: ${T(ue(Ae))}`)}else console.log(` ${T("Voice transcription disabled \u2014 you can configure it later.")}`);let Pt=!1,Ft="alloy";if(Ee){let p=t.config.speech?.ttsEnabled??!1,E=p?"Y/n":"y/N";console.log(`
740
- ${A("Voice responses (Text-to-Speech)?")}`),console.log(`${T("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await c.question(`${D}> ${k}${T(`[${E}] `)}`)).trim().toLowerCase();if(Pt=$===""?p:$==="y"||$==="yes",Pt){let X=["alloy","echo","fable","onyx","nova","shimmer"],M=t.config.speech?.ttsVoice??"alloy",j=X.indexOf(M),G=j>=0?j+1:1;console.log(`
741
- ${A("Which voice?")}`);for(let ne=0;ne<X.length;ne++){let J=j===ne?` ${T("(current)")}`:"";console.log(` ${Te(String(ne+1)+")")} ${X[ne]}${J}`)}let $e=await xr(c," > ",1,X.length,G);Ft=X[$e-1],console.log(` ${C(">")} TTS voice: ${A(Ft)}`)}else console.log(` ${T("Voice responses disabled.")}`)}let sc=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
742
- ${A("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${T("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Or=(await c.question(`${D}> ${k}${T(`[${sc}] `)}`)).trim().toLowerCase(),Dr=Or===""?t.codeSandboxEnabled:Or==="y"||Or==="yes";console.log(Dr?` ${C(">")} Code Sandbox ${A("enabled")} (JavaScript + Python)`:` ${T("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
743
- ${A("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${T("Scanning for known coding agents on this system...")}`);let Ur=[];for(let p of Oa){let E=Td(p.whichCmd);E?(Ur.push({...p,resolvedPath:E}),console.log(` ${C("\u2713")} ${A(p.label)} ${T(`(${E})`)}`)):console.log(` ${T("\xB7")} ${T(p.label)} ${T("\u2014 not found")}`)}let Pr=(t.config.codeAgents?.agents??[]).filter(p=>!Oa.some(E=>E.name===p.name));for(let p of Pr)console.log(` ${C("\u2713")} ${A(p.name)} ${T(`(${p.command}) \u2014 from existing config`)}`);let Fe=[];if(Ur.length===0&&Pr.length===0)console.log(`
744
- ${T("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let p=[...Ur.map(M=>({name:M.name,command:M.resolvedPath??M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia,label:M.label,detected:!0})),...Pr.map(M=>({name:M.name,command:M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia??"arg",label:M.name,detected:!1}))];console.log(`
745
- ${A("Which agents should Alfred use?")} ${T("(comma-separated, e.g. 1,2)")}`);let E=new Set((t.config.codeAgents?.agents??[]).map(M=>M.name));for(let M=0;M<p.length;M++){let j=p[M],G=E.has(j.name)?` ${T("(current)")}`:"";console.log(` ${D}${M+1}${k}) ${j.label}${G}`)}console.log(` ${D}0${k}) None`);let $=p.map((M,j)=>E.size>0?E.has(M.name)?String(j+1):null:M.detected?String(j+1):null).filter(Boolean).join(",")||"0",X=(await c.question(` ${D}> ${k}${T(`[${$}] `)}`)).trim()||$;X!=="0"&&(Fe=X.split(",").map(j=>parseInt(j.trim(),10)).filter(j=>!isNaN(j)&&j>=1&&j<=p.length).map(j=>{let G=p[j-1];return{name:G.name,command:G.command,argsTemplate:G.argsTemplate,promptVia:G.promptVia}})),Fe.length>0?console.log(` ${C(">")} ${A(String(Fe.length))} agent(s) selected: ${Fe.map(M=>M.name).join(", ")}`):console.log(` ${T("No agents selected.")}`)}let Fr=t.config.codeAgents?.forge,jr=Fr?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
746
- ${A("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${T("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${T("Owner/repo are detected automatically from the git remote at runtime.")}`);let wo=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let p of wo){let E=p.name===jr?` ${T("(current)")}`:"";console.log(` ${D}${p.num}${k}) ${p.label}${E}`)}let bo=jr==="github"?"2":jr==="gitlab"?"3":"1",rc=(await c.question(`${D}> ${k}${T(`[${bo}] `)}`)).trim()||bo,je=wo.find(p=>p.num===rc)?.name??"",jt="",Bt="";if(je==="github"){console.log(` ${C(">")} Forge: ${A("GitHub")}`);let p=t.env.ALFRED_GITHUB_TOKEN??Fr?.github?.token??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create a token at https://github.com/settings/tokens (scope: repo)")}`),jt=(await c.question(` ${ee}GitHub Token${k}: ${D}`)).trim(),process.stdout.write(k),!jt&&p&&(jt=p)}else if(je==="gitlab"){console.log(` ${C(">")} Forge: ${A("GitLab")}`);let p=t.env.ALFRED_GITLAB_TOKEN??Fr?.gitlab?.token??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),Bt=(await c.question(` ${ee}GitLab Token${k}: ${D}`)).trim(),process.stdout.write(k),!Bt&&p&&(Bt=p)}else console.log(` ${T("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
747
- ${A("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${T("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Ht=t.config.proxmox,Br=t.env.ALFRED_PROXMOX_BASE_URL??Ht?.baseUrl??"",nc=Br?"Y/n":"y/N",To=(await c.question(` ${ee}Enable Proxmox VE?${k} ${T(`[${nc}]`)}: ${D}`)).trim().toLowerCase()||(Br?"y":"n");process.stdout.write(k);let Gs=To==="y"||To==="yes",qt="",Hr="",Wt="",qr=!0;if(Gs){qt=await U(c," Proxmox URL (e.g. https://pve.local:8006)",Br||"https://pve.local:8006");let p=t.env.ALFRED_PROXMOX_TOKEN_ID??Ht?.tokenId??"";p&&console.log(` ${T(`Current token ID: ${p}`)}`),console.log(` ${T("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),Hr=await U(c," API Token ID (user@realm!name)",p);let E=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Ht?.tokenSecret??"";E&&console.log(` ${T(`Current secret: ${ue(E)}`)}`),Wt=(await c.question(` ${ee}API Token Secret${k}: ${D}`)).trim(),process.stdout.write(k),!Wt&&E&&(Wt=E);let $=Ht?.verifyTls===!1?"y/N":"Y/n",X=(await c.question(` ${ee}Verify TLS?${k} ${T(`(self-signed? \u2192 no) [${$}]`)}: ${D}`)).trim().toLowerCase()||(Ht?.verifyTls===!1?"n":"y");process.stdout.write(k),qr=X==="y"||X==="yes",console.log(` ${C(">")} Proxmox: ${A(qt)} ${T(`(TLS verify: ${qr?"yes":"no"})`)}`)}else console.log(` ${T("Proxmox disabled.")}`);let Be=t.config.unifi,Wr=t.env.ALFRED_UNIFI_BASE_URL??Be?.baseUrl??"",oc=Wr?"Y/n":"y/N",_o=(await c.question(`
748
- ${ee}Enable UniFi Network?${k} ${T(`[${oc}]`)}: ${D}`)).trim().toLowerCase()||(Wr?"y":"n");process.stdout.write(k);let Xt=_o==="y"||_o==="yes",rt="",He="",Xr="",zt="",zr=!0;if(Xt){rt=await U(c," UniFi URL (e.g. https://unifi.local)",Wr||"https://unifi.local"),console.log(` ${T("Auth: API Key (recommended) or Username/Password")}`);let p=t.env.ALFRED_UNIFI_API_KEY??Be?.apiKey??"",E=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],$=p?"1":Be?.username?"2":"1";for(let G of E)console.log(` ${D}${G.num}${k}) ${G.label}`);if(((await c.question(` ${D}> ${k}${T(`[${$}] `)}`)).trim()||$)==="1")p&&console.log(` ${T(`Current key: ${ue(p)}`)}`),console.log(` ${T("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),He=(await c.question(` ${ee}API Key${k}: ${D}`)).trim(),process.stdout.write(k),!He&&p&&(He=p);else{let G=t.env.ALFRED_UNIFI_USERNAME??Be?.username??"";Xr=await U(c," Username",G||"alfred");let $e=t.env.ALFRED_UNIFI_PASSWORD??Be?.password??"";$e&&console.log(` ${T(`Current password: ${ue($e)}`)}`),zt=(await c.question(` ${ee}Password${k}: ${D}`)).trim(),process.stdout.write(k),!zt&&$e&&(zt=$e)}let M=Be?.verifyTls===!1?"y/N":"Y/n",j=(await c.question(` ${ee}Verify TLS?${k} ${T(`(self-signed? \u2192 no) [${M}]`)}: ${D}`)).trim().toLowerCase()||(Be?.verifyTls===!1?"n":"y");process.stdout.write(k),zr=j==="y"||j==="yes",console.log(` ${C(">")} UniFi: ${A(rt)} ${T(`(TLS verify: ${zr?"yes":"no"})`)}`)}else console.log(` ${T("UniFi disabled.")}`);let Ys=t.config.homeassistant,Vr=t.env.ALFRED_HOMEASSISTANT_URL??Ys?.baseUrl??"",ic=Vr?"Y/n":"y/N",Eo=(await c.question(`
749
- ${ee}Enable Home Assistant?${k} ${T(`[${ic}]`)}: ${D}`)).trim().toLowerCase()||(Vr?"y":"n");process.stdout.write(k);let Js=Eo==="y"||Eo==="yes",Vt="",Kt="",Kr=!0;if(Js){Vt=await U(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",Vr||"http://homeassistant.local:8123");let p=t.env.ALFRED_HOMEASSISTANT_TOKEN??Ys?.accessToken??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),Kt=(await c.question(` ${ee}Long-Lived Access Token${k}: ${D}`)).trim(),process.stdout.write(k),!Kt&&p&&(Kt=p);let E=Ys?.verifyTls===!1?"y/N":"Y/n",$=(await c.question(` ${ee}Verify TLS?${k} ${T(`(self-signed? \u2192 no) [${E}]`)}: ${D}`)).trim().toLowerCase()||(Ys?.verifyTls===!1?"n":"y");process.stdout.write(k),Kr=$==="y"||$==="yes",console.log(` ${C(">")} Home Assistant: ${A(Vt)} ${T(`(TLS verify: ${Kr?"yes":"no"})`)}`)}else console.log(` ${T("Home Assistant disabled.")}`);console.log(`
750
- ${A("Security configuration:")}`);let $o=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",le;if($o)le=await U(c,"Owner user ID (for elevated permissions)",$o);else{let p=(await c.question(`${ee}Owner user ID${k} ${T("(optional, for elevated permissions)")}: ${D}`)).trim();process.stdout.write(k),le=p}let Gt=!1;if(le){let p=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${A("Enable shell access (admin commands) for the owner?")}`),console.log(` ${T("Allows Alfred to execute shell commands. Only for the owner.")}`);let E=(await c.question(` ${D}> ${k}${T(`[${p}] `)}`)).trim().toLowerCase();E===""?Gt=t.shellEnabled:Gt=E==="y"||E==="yes",console.log(Gt?` ${C(">")} Shell access ${A("enabled")} for owner ${T(le)}`:` ${T("Shell access disabled.")}`)}let ac=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${A("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${T("By default, write actions are only allowed in DMs.")}`);let Gr=(await c.question(` ${D}> ${k}${T(`[${ac}] `)}`)).trim().toLowerCase(),Yt;Gr===""?Yt=t.writeInGroups:Yt=Gr==="y"||Gr==="yes",console.log(Yt?` ${C(">")} Write actions ${A("enabled")} in groups`:` ${T("Write actions only in DMs (default).")}`);let cc=t.rateLimit??30;console.log("");let lc=await U(c," Rate limit (max write actions per hour per user)",String(cc)),Zs=Math.max(1,parseInt(lc,10)||30);console.log(` ${C(">")} Rate limit: ${A(String(Zs))} per hour`),console.log(`
751
- ${A("Writing configuration files...")}`);let S=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let p=a.envKeyName||"ALFRED_OLLAMA_API_KEY";S.push(`${p}=${l}`)}if(y!==a.defaultModel&&S.push(`ALFRED_LLM_MODEL=${y}`),m&&S.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(x).length>0){S.push("","# === Additional Model Tiers ===");for(let[p,E]of Object.entries(x)){let $=`ALFRED_LLM_${p.toUpperCase()}`;S.push(""),S.push(`${$}_PROVIDER=${E.provider}`),S.push(`${$}_MODEL=${E.model}`),E.apiKey&&S.push(`${$}_API_KEY=${E.apiKey}`),E.baseUrl&&S.push(`${$}_BASE_URL=${E.baseUrl}`)}}S.push("","# === Messaging Platforms ===","");for(let[p,E]of Object.entries(Se))S.push(`${p}=${E}`);if(S.push("","# === Web Search ===",""),Y?(S.push(`ALFRED_SEARCH_PROVIDER=${Y}`),re&&S.push(`ALFRED_SEARCH_API_KEY=${re}`),L&&S.push(`ALFRED_SEARCH_BASE_URL=${L}`)):(S.push("# ALFRED_SEARCH_PROVIDER=brave"),S.push("# ALFRED_SEARCH_API_KEY=")),S.push("","# === Email ===",""),zs&&_e.length>0){let p=_e[0];p.provider==="microsoft"?(S.push("ALFRED_EMAIL_PROVIDER=microsoft"),p.msClientId?(S.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${p.msClientId}`),S.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${p.msClientSecret}`),S.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${p.msTenantId}`),S.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${p.msRefreshToken}`)):S.push("# Microsoft email credentials shared from calendar config")):(S.push(`ALFRED_EMAIL_USER=${p.user}`),S.push(`ALFRED_EMAIL_PASS=${p.pass}`)),_e.length>1&&S.push("# Additional email accounts configured in config/default.yml")}else S.push("# ALFRED_EMAIL_USER="),S.push("# ALFRED_EMAIL_PASS=");S.push("","# === Speech ===",""),Ee?(S.push(`ALFRED_SPEECH_PROVIDER=${Ee}`),S.push(`ALFRED_SPEECH_API_KEY=${Ae}`),Ut&&S.push(`ALFRED_SPEECH_BASE_URL=${Ut}`),Pt&&(S.push("ALFRED_TTS_ENABLED=true"),S.push(`ALFRED_TTS_VOICE=${Ft}`))):(S.push("# ALFRED_SPEECH_PROVIDER=groq"),S.push("# ALFRED_SPEECH_API_KEY=")),S.push("","# === Forge (GitHub / GitLab) ===",""),je==="github"?(S.push("ALFRED_FORGE_PROVIDER=github"),S.push(`ALFRED_GITHUB_TOKEN=${jt}`)):je==="gitlab"?(S.push("ALFRED_FORGE_PROVIDER=gitlab"),S.push(`ALFRED_GITLAB_TOKEN=${Bt}`)):(S.push("# ALFRED_FORGE_PROVIDER=github"),S.push("# ALFRED_GITHUB_TOKEN=")),S.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Gs?(S.push(`ALFRED_PROXMOX_BASE_URL=${qt}`),S.push(`ALFRED_PROXMOX_TOKEN_ID=${Hr}`),S.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Wt}`)):(S.push("# ALFRED_PROXMOX_BASE_URL="),S.push("# ALFRED_PROXMOX_TOKEN_ID="),S.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),Xt&&He?(S.push(`ALFRED_UNIFI_BASE_URL=${rt}`),S.push(`ALFRED_UNIFI_API_KEY=${He}`)):Xt?(S.push(`ALFRED_UNIFI_BASE_URL=${rt}`),S.push(`ALFRED_UNIFI_USERNAME=${Xr}`),S.push(`ALFRED_UNIFI_PASSWORD=${zt}`)):(S.push("# ALFRED_UNIFI_BASE_URL="),S.push("# ALFRED_UNIFI_API_KEY=")),Js?(S.push(`ALFRED_HOMEASSISTANT_URL=${Vt}`),S.push(`ALFRED_HOMEASSISTANT_TOKEN=${Kt}`)):(S.push("# ALFRED_HOMEASSISTANT_URL="),S.push("# ALFRED_HOMEASSISTANT_TOKEN=")),S.push("","# === Security ===",""),le?S.push(`ALFRED_OWNER_USER_ID=${le}`):S.push("# ALFRED_OWNER_USER_ID="),S.push("");let dc=ie.join(e,".env");se.writeFileSync(dc,S.join(`
752
- `),"utf-8"),console.log(` ${C("+")} ${T(".env")} written`);let Qs=ie.join(e,"config");se.existsSync(Qs)||se.mkdirSync(Qs,{recursive:!0});let vo={name:r,telegram:{token:ce.telegram?.token??"",enabled:q.some(p=>p.name==="telegram")},discord:{token:ce.discord?.token??"",enabled:q.some(p=>p.name==="discord")},whatsapp:{enabled:q.some(p=>p.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:ce.matrix?.homeserverUrl??"https://matrix.org",accessToken:ce.matrix?.accessToken??"",userId:ce.matrix?.userId??"",enabled:q.some(p=>p.name==="matrix")},signal:{apiUrl:ce.signal?.apiUrl??"http://localhost:8080",phoneNumber:ce.signal?.phoneNumber??"",enabled:q.some(p=>p.name==="signal")},llm:Object.keys(x).length>0?{default:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...x}:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...Y?{search:{provider:Y,...re?{apiKey:re}:{},...L?{baseUrl:L}:{}}}:{},...zs&&_e.length>0?{email:{accounts:_e.map(p=>p.provider==="microsoft"?{name:p.name,provider:"microsoft",...p.msClientId?{microsoft:{clientId:p.msClientId,clientSecret:p.msClientSecret,tenantId:p.msTenantId,refreshToken:p.msRefreshToken}}:{}}:{name:p.name,imap:{host:p.imapHost,port:p.imapPort,secure:p.imapPort===993},smtp:{host:p.smtpHost,port:p.smtpPort,secure:p.smtpPort===465},auth:{user:p.user,pass:p.pass}})}}:{},...Ee?{speech:{provider:Ee,apiKey:Ae,...Ut?{baseUrl:Ut}:{},...Pt?{ttsEnabled:!0,ttsVoice:Ft}:{}}}:{},...Dr?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...Fe.length>0||je?{codeAgents:{enabled:Fe.length>0,agents:Fe,...je==="github"?{forge:{provider:"github",github:{token:jt}}}:je==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:Bt}}}:{}}}:{},...Gs?{proxmox:{baseUrl:qt,tokenId:Hr,tokenSecret:Wt,verifyTls:qr}}:{},...Xt?{unifi:{baseUrl:rt,...He?{apiKey:He}:{username:Xr,password:zt},site:"default",verifyTls:zr}}:{},...Js?{homeassistant:{baseUrl:Vt,accessToken:Kt,verifyTls:Kr}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};le&&(vo.security.ownerUserId=le);let uc="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+mo.dump(vo,{lineWidth:120,noRefs:!0,sortKeys:!1}),mc=ie.join(Qs,"default.yml");se.writeFileSync(mc,uc,"utf-8"),console.log(` ${C("+")} ${T("config/default.yml")} written`);let Yr=ie.join(Qs,"rules");se.existsSync(Yr)||se.mkdirSync(Yr,{recursive:!0});let pc=Gt&&le?`
787
+ Connection error: ${l.message}`),t.prompt()})});n.on("error",i=>{console.error(`
788
+ Failed to send message: ${i.message}`),t.prompt()}),n.write(o),n.end()}),t.on("close",()=>{process.exit(0)})}async function mu(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 du(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),uu(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 n=new dt(t);try{await n.initialize(),await n.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var $c=y(()=>{"use strict";Oe();Pn();u(du,"checkHealth");u(uu,"startClientMode");u(mu,"chatCommand")});var kc={};re(kc,{setupCommand:()=>$u});import{createInterface as pu}from"node:readline/promises";import{stdin as fu,stdout as hu}from"node:process";import{execFileSync as gu}from"node:child_process";import ne from"node:fs";import yu from"node:os";import fe from"node:path";import Fn from"js-yaml";function D(c){return`${Xr}${c}${S}`}function Eu(c){return`${M}${c}${S}`}function pe(c){return`${Gr}${c}${S}`}function Sc(c){return`${wu}${c}${S}`}function x(c){return`${z}${c}${S}`}function E(c){return`${qe}${c}${S}`}function le(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function bu(c){let e=process.platform==="win32",t=e?"where":"which";try{let o=gu(t,[c],{stdio:"pipe"}).toString().trim();if(o)return o.split(/\r?\n/)[0]}catch{}let s=yu.homedir(),r=e?[fe.join(s,".local","bin",`${c}.exe`),fe.join(s,"AppData","Roaming","npm",`${c}.cmd`),fe.join(s,"AppData","Roaming","npm",`${c}`)]:[fe.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,fe.join(s,".npm-global","bin",c)];for(let o of r)try{return ne.accessSync(o,ne.constants.X_OK),o}catch{}return null}function _u(c){let e={},t={},s=!1,r=!1,o=30,n=fe.join(c,"config","default.yml");if(ne.existsSync(n))try{let p=Fn.load(ne.readFileSync(n,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=fe.join(c,".env");if(ne.existsSync(i))try{let p=ne.readFileSync(i,"utf-8").split(`
789
+ `);for(let w of p){let T=w.trim();if(!T||T.startsWith("#"))continue;let g=T.indexOf("=");g>0&&(t[T.slice(0,g)]=T.slice(g+1))}}catch{}let a=fe.join(c,"config","rules","default-rules.yml");if(ne.existsSync(a))try{let p=Fn.load(ne.readFileSync(a,"utf-8"));if(p?.rules){s=p.rules.some(g=>g.id==="allow-owner-admin"&&g.effect==="allow"),p.rules.find(g=>g.id==="allow-write-for-dm"||g.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let T=p.rules.find(g=>g.id==="rate-limit-write");T?.rateLimit?.maxInvocations&&(o=T.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:o,codeSandboxEnabled:l,multiModelTiers:m}}async function $u(){let c=pu({input:fu,output:hu}),e=process.cwd(),t=_u(e),s=Object.keys(t.config).length>0;try{vu(),console.log(s?`${Gr}Existing configuration found \u2014 press Enter to keep current values.${S}
790
+ ${qe}Only change what you need to update.${S}
791
+ `:`${Gr}Welcome to the Alfred setup wizard!${S}
792
+ ${qe}This will walk you through configuring your AI assistant.${S}
793
+ ${qe}Press Enter to accept defaults shown in [brackets].${S}
794
+ `);let r=await U(c,"What should your bot be called?",t.config.name??"Alfred"),o=t.config.llm?.provider?Be.findIndex(f=>f.name===t.config.llm?.provider):-1,n=o>=0?o+1:1;console.log(`
795
+ ${x("Which LLM provider would you like to use?")}`);for(let f=0;f<Be.length;f++){let _=f===o?` ${E("(current)")}`:"";console.log(` ${pe(String(f+1)+")")} ${Be[f].label}${_}`)}let i=await rr(c,"> ",1,Be.length,n),a=Be[i-1];console.log(` ${D(">")} Selected: ${x(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await U(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await ye(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${D(">")} API key set: ${E(le(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 v={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 U(c,v[a.name]??"API Base URL",_.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${D(">")} URL: ${E(m)}`)}}let w=t.config.llm?.model??a.defaultModel;console.log("");let T;if(a.models&&a.models.length>0){console.log(`${x("Available models:")}`);for(let v=0;v<a.models.length;v++){let H=a.models[v],C=H.id===w?` ${D("(current)")}`:"";console.log(` ${pe(`${v+1})`)} ${H.id} ${E(`\u2014 ${H.desc}`)}${C}`)}console.log(` ${pe(`${a.models.length+1})`)} ${E("Other (enter manually)")}`);let f=await U(c,"Choose model","1"),_=parseInt(f,10)-1;_>=0&&_<a.models.length?T=a.models[_].id:_===a.models.length?T=await U(c,"Model ID",w):T=await U(c,"Model ID",w)}else T=await U(c,"Which model?",w);let g=Object.keys(t.multiModelTiers).length>0,b=g?"Y/n":"y/N";console.log(`
796
+ ${x("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let $=(await c.question(`${M}> ${S}${E(`[${b}] `)}`)).trim().toLowerCase(),A=$===""?g:$==="y"||$==="yes",R={};if(A){let f=[{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 f){let v=t.multiModelTiers[_.key],H=!!v?.model;console.log(`
797
+ ${x(`${_.label} model`)} ${E(`(${_.hint})`)}`),H&&console.log(` ${E(`Current: ${v.provider}/${v.model}`)}`),console.log(` ${E("Press Enter to skip.")}`);let P=(await c.question(` ${M}Model: ${S}${H?E(`[${v.model}] `):""}`)).trim()||(H?v.model:"");if(!P){console.log(` ${E("Skipped.")}`);continue}let q=v?.provider??a.name,me=Be.map(De=>De.name).join(", ");console.log(` ${E(`Providers: ${me}`)}`);let Z=(await c.question(` ${M}Provider: ${S}${E(`[${q}] `)}`)).trim()||q,be,Ce;if(Z!==a.name){let De=v?.apiKey??t.env[`ALFRED_LLM_${_.key.toUpperCase()}_API_KEY`]??"";if(De?be=await U(c,` API key for ${Z}`,De):(Be.find(mt=>mt.name===Z)?.needsApiKey??!0)&&(be=await ye(c,` API key for ${Z}`)),["ollama","openwebui"].includes(Z)){let mt=(v?.baseUrl??"")||Be.find(Eo=>Eo.name===Z)?.baseUrl||"";mt&&(Ce=await U(c,` ${Z} URL`,mt))}}R[_.key]={provider:Z,model:P,...be?{apiKey:be}:{},...Ce?{baseUrl:Ce}:{}},console.log(` ${D(">")} ${_.label}: ${x(Z)}/${x(P)}`)}Object.keys(R).length===0&&console.log(`
798
+ ${E("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${E("Using single model for all tasks.")}`);let O=["brave","tavily","duckduckgo","searxng"],N=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",K=O.indexOf(N),ie=K>=0?K+1:0;console.log(`
799
+ ${x("Web Search provider (for searching the internet):")}`);let V=["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"],we=u(f=>K===f?` ${E("(current)")}`:"","mark");console.log(` ${pe("0)")} None (disable web search)${K===-1&&N===""?` ${E("(current)")}`:""}`);for(let f=0;f<V.length;f++)console.log(` ${pe(String(f+1)+")")} ${V[f]}${we(f)}`);let xe=await rr(c,"> ",0,O.length,ie),Y,J="",de="";if(xe>=1&&xe<=O.length&&(Y=O[xe-1]),Y==="brave"){let f=t.env.ALFRED_SEARCH_API_KEY??"";f?J=await U(c," Brave Search API key",f):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),J=await ye(c," Brave Search API key")),console.log(` ${D(">")} Brave Search: ${E(le(J))}`)}else if(Y==="tavily"){let f=t.env.ALFRED_SEARCH_API_KEY??"";f?J=await U(c," Tavily API key",f):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),J=await ye(c," Tavily API key")),console.log(` ${D(">")} Tavily: ${E(le(J))}`)}else if(Y==="duckduckgo")console.log(` ${D(">")} DuckDuckGo: ${E("no API key needed")}`);else if(Y==="searxng"){let f=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";de=await U(c," SearXNG URL",f),de=de.replace(/\/+$/,""),console.log(` ${D(">")} SearXNG: ${E(de)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let L=[];for(let f=0;f<Vt.length;f++){let _=Vt[f];t.config[_.configKey]?.enabled&&L.push(f+1)}let W=L.length>0?L.join(","):"";console.log(`
800
+ ${x("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let f=0;f<Vt.length;f++){let _=L.includes(f+1)?` ${E("(enabled)")}`:"";console.log(` ${pe(String(f+1)+")")} ${Vt[f].label}${_}`)}console.log(` ${pe("0)")} None (configure later)`);let B=(await c.question(`${M}> ${S}${W?E(`[${W}] `):""}`)).trim(),F=[],Q=B||W;if(Q&&Q!=="0"){let f=Q.split(",").map(_=>parseInt(_.trim(),10));for(let _ of f)if(_>=1&&_<=Vt.length){let v=Vt[_-1];F.includes(v)||F.push(v)}}F.length>0?console.log(` ${D(">")} Enabling: ${F.map(f=>x(f.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let X={},He={};for(let f of F){if(f.credentials.length===0){f.name==="whatsapp"&&console.log(`
801
+ ${Eu("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
802
+ ${x(f.label+" configuration:")}`);let _={};for(let v of f.credentials){let H=t.env[v.envKey]??"",C;H?C=await U(c,` ${v.prompt}`,H):v.defaultValue?C=await U(c,` ${v.prompt}`,v.defaultValue):v.required?C=await ye(c,` ${v.prompt}`):(C=(await c.question(` ${v.prompt}: ${M}`)).trim(),process.stdout.write(S)),_[v.configField]=C,He[v.envKey]=C,v.configField==="token"||v.configField==="accessToken"?console.log(` ${D(">")} Set: ${E(le(C))}`):console.log(` ${D(">")} Set: ${E(C)}`)}X[f.configKey]=_}let Ae=t.config.email?.accounts??[],Yr=Ae[0],Fc=Yr?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",jc=Yr?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",qn=Ae.length>0||!!Fc||jc==="microsoft",Bc=qn?"Y/n":"y/N";console.log(`
803
+ ${x("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let Jr=(await c.question(`${M}> ${S}${E(`[${Bc}] `)}`)).trim().toLowerCase(),nr=Jr===""?qn:Jr==="y"||Jr==="yes",Ie=[],qc={"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"}},Hn=u(async(f,_)=>{let v={name:f,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},H=_?.provider??"",C=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],P=H==="microsoft"?1:0;console.log("");for(let ae=0;ae<C.length;ae++){let Z=ae===P?` ${E("(current)")}`:"";console.log(` ${pe(`${ae+1})`)} ${C[ae]}${Z}`)}let q=(await c.question(`${M}> ${S}${E(`[${P+1}] `)}`)).trim(),me=q===""?P:parseInt(q,10)-1;if(v.provider=me===1?"microsoft":"imap-smtp",v.provider==="microsoft"){let ae=t.config.calendar?.microsoft,Z=_?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",be=_?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",Ce=_?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(ae&&!Z)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")}`),v.msClientId=await U(c," Client ID",Z),v.msClientId||(v.msClientId=await ye(c," Client ID"));let De=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";v.msClientSecret=await U(c," Client Secret",De),v.msClientSecret||(v.msClientSecret=await ye(c," Client Secret")),v.msTenantId=await U(c," Tenant ID",be),v.msTenantId||(v.msTenantId=await ye(c," Tenant ID")),v.msRefreshToken=await U(c," Refresh Token",Ce),v.msRefreshToken||(v.msRefreshToken=await ye(c," Refresh Token"))}console.log(` ${D(">")} Email [${f}]: Microsoft 365 (Graph API)`)}else{let ae=_?.auth?.user??"";console.log(""),v.user=await U(c," Email address",ae||""),v.user||(v.user=await ye(c," Email address"));let Z=_?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";Z?v.pass=await U(c," Password / App password",Z):(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")}`),v.pass=await ye(c," Password / App password"));let be=v.user.split("@")[1]?.toLowerCase()??"",Ce=qc[be],De=_?.imap?.host??Ce?.imap??`imap.${be}`,si=_?.smtp?.host??Ce?.smtp??`smtp.${be}`,To=_?.imap?.port??993,mt=_?.smtp?.port??587;Ce&&console.log(` ${D(">")} Detected ${be} \u2014 using preset server settings`),v.imapHost=await U(c," IMAP server",De);let Eo=await U(c," IMAP port",String(To));v.imapPort=parseInt(Eo,10)||993,v.smtpHost=await U(c," SMTP server",si);let al=await U(c," SMTP port",String(mt));v.smtpPort=parseInt(al,10)||587,console.log(` ${D(">")} Email [${f}]: ${E(v.user)} via ${E(v.imapHost)}`)}return v},"configureEmailAccount");if(nr){let f=Yr??(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);Ie.push(await Hn("default",f));let _=!0;for(;_;){let v=(await c.question(`
804
+ ${x("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if(v==="y"||v==="yes"){let C=(await c.question(` ${x("Account name:")} `)).trim()||`account${Ie.length+1}`,P=Ae.find(q=>q.name===C);Ie.push(await Hn(C,P))}else _=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let ir=["openai","groq"],Hc=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",ar=ir.indexOf(Hc),zc=ar>=0?ar+1:0;console.log(`
805
+ ${x("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let zn=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${pe("0)")} None (disable voice transcription)${ar===-1?` ${E("(current)")}`:""}`);for(let f=0;f<zn.length;f++){let _=ar===f?` ${E("(current)")}`:"";console.log(` ${pe(String(f+1)+")")} ${zn[f]}${_}`)}let Zr=await rr(c,"> ",0,ir.length,zc),Re,Me="",Wt="";if(Zr>=1&&Zr<=ir.length&&(Re=ir[Zr-1]),Re==="openai"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?Me=await U(c," OpenAI API key (for Whisper)",f):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),Me=await ye(c," OpenAI API key")),console.log(` ${D(">")} OpenAI Whisper: ${E(le(Me))}`)}else if(Re==="groq"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?Me=await U(c," Groq API key",f):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),Me=await ye(c," Groq API key"));let _=t.env.ALFRED_SPEECH_BASE_URL??"";_&&(Wt=await U(c," Groq API URL",_)),console.log(` ${D(">")} Groq Whisper: ${E(le(Me))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let Xt=!1,Gt="alloy";if(Re){let f=t.config.speech?.ttsEnabled??!1,_=f?"Y/n":"y/N";console.log(`
806
+ ${x("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let v=(await c.question(`${M}> ${S}${E(`[${_}] `)}`)).trim().toLowerCase();if(Xt=v===""?f:v==="y"||v==="yes",Xt){let H=["alloy","echo","fable","onyx","nova","shimmer"],C=t.config.speech?.ttsVoice??"alloy",P=H.indexOf(C),q=P>=0?P+1:1;console.log(`
807
+ ${x("Which voice?")}`);for(let ae=0;ae<H.length;ae++){let Z=P===ae?` ${E("(current)")}`:"";console.log(` ${pe(String(ae+1)+")")} ${H[ae]}${Z}`)}let me=await rr(c," > ",1,H.length,q);Gt=H[me-1],console.log(` ${D(">")} TTS voice: ${x(Gt)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Vc=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
808
+ ${x("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Qr=(await c.question(`${M}> ${S}${E(`[${Vc}] `)}`)).trim().toLowerCase(),eo=Qr===""?t.codeSandboxEnabled:Qr==="y"||Qr==="yes";console.log(eo?` ${D(">")} Code Sandbox ${x("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
809
+ ${x("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let to=[];for(let f of vc){let _=bu(f.whichCmd);_?(to.push({...f,resolvedPath:_}),console.log(` ${D("\u2713")} ${x(f.label)} ${E(`(${_})`)}`)):console.log(` ${E("\xB7")} ${E(f.label)} ${E("\u2014 not found")}`)}let so=(t.config.codeAgents?.agents??[]).filter(f=>!vc.some(_=>_.name===f.name));for(let f of so)console.log(` ${D("\u2713")} ${x(f.name)} ${E(`(${f.command}) \u2014 from existing config`)}`);let ze=[];if(to.length===0&&so.length===0)console.log(`
810
+ ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let f=[...to.map(C=>({name:C.name,command:C.resolvedPath??C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia,label:C.label,detected:!0})),...so.map(C=>({name:C.name,command:C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia??"arg",label:C.name,detected:!1}))];console.log(`
811
+ ${x("Which agents should Alfred use?")} ${E("(comma-separated, e.g. 1,2)")}`);let _=new Set((t.config.codeAgents?.agents??[]).map(C=>C.name));for(let C=0;C<f.length;C++){let P=f[C],q=_.has(P.name)?` ${E("(current)")}`:"";console.log(` ${M}${C+1}${S}) ${P.label}${q}`)}console.log(` ${M}0${S}) None`);let v=f.map((C,P)=>_.size>0?_.has(C.name)?String(P+1):null:C.detected?String(P+1):null).filter(Boolean).join(",")||"0",H=(await c.question(` ${M}> ${S}${E(`[${v}] `)}`)).trim()||v;H!=="0"&&(ze=H.split(",").map(P=>parseInt(P.trim(),10)).filter(P=>!isNaN(P)&&P>=1&&P<=f.length).map(P=>{let q=f[P-1];return{name:q.name,command:q.command,argsTemplate:q.argsTemplate,promptVia:q.promptVia}})),ze.length>0?console.log(` ${D(">")} ${x(String(ze.length))} agent(s) selected: ${ze.map(C=>C.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let ro=t.config.codeAgents?.forge,oo=ro?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
812
+ ${x("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 Vn=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let f of Vn){let _=f.name===oo?` ${E("(current)")}`:"";console.log(` ${M}${f.num}${S}) ${f.label}${_}`)}let Wn=oo==="github"?"2":oo==="gitlab"?"3":"1",Wc=(await c.question(`${M}> ${S}${E(`[${Wn}] `)}`)).trim()||Wn,Ve=Vn.find(f=>f.num===Wc)?.name??"",Kt="",Yt="";if(Ve==="github"){console.log(` ${D(">")} Forge: ${x("GitHub")}`);let f=t.env.ALFRED_GITHUB_TOKEN??ro?.github?.token??"";f&&console.log(` ${E(`Current token: ${le(f)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),Kt=(await c.question(` ${z}GitHub Token${S}: ${M}`)).trim(),process.stdout.write(S),!Kt&&f&&(Kt=f)}else if(Ve==="gitlab"){console.log(` ${D(">")} Forge: ${x("GitLab")}`);let f=t.env.ALFRED_GITLAB_TOKEN??ro?.gitlab?.token??"";f&&console.log(` ${E(`Current token: ${le(f)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),Yt=(await c.question(` ${z}GitLab Token${S}: ${M}`)).trim(),process.stdout.write(S),!Yt&&f&&(Yt=f)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
813
+ ${x("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Jt=t.config.proxmox,no=t.env.ALFRED_PROXMOX_BASE_URL??Jt?.baseUrl??"",Xc=no?"Y/n":"y/N",Xn=(await c.question(` ${z}Enable Proxmox VE?${S} ${E(`[${Xc}]`)}: ${M}`)).trim().toLowerCase()||(no?"y":"n");process.stdout.write(S);let cr=Xn==="y"||Xn==="yes",Zt="",io="",Qt="",ao=!0;if(cr){Zt=await U(c," Proxmox URL (e.g. https://pve.local:8006)",no||"https://pve.local:8006");let f=t.env.ALFRED_PROXMOX_TOKEN_ID??Jt?.tokenId??"";f&&console.log(` ${E(`Current token ID: ${f}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),io=await U(c," API Token ID (user@realm!name)",f);let _=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Jt?.tokenSecret??"";_&&console.log(` ${E(`Current secret: ${le(_)}`)}`),Qt=(await c.question(` ${z}API Token Secret${S}: ${M}`)).trim(),process.stdout.write(S),!Qt&&_&&(Qt=_);let v=Jt?.verifyTls===!1?"y/N":"Y/n",H=(await c.question(` ${z}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${v}]`)}: ${M}`)).trim().toLowerCase()||(Jt?.verifyTls===!1?"n":"y");process.stdout.write(S),ao=H==="y"||H==="yes",console.log(` ${D(">")} Proxmox: ${x(Zt)} ${E(`(TLS verify: ${ao?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let We=t.config.unifi,co=t.env.ALFRED_UNIFI_BASE_URL??We?.baseUrl??"",Gc=co?"Y/n":"y/N",Gn=(await c.question(`
814
+ ${z}Enable UniFi Network?${S} ${E(`[${Gc}]`)}: ${M}`)).trim().toLowerCase()||(co?"y":"n");process.stdout.write(S);let es=Gn==="y"||Gn==="yes",ut="",Xe="",lo="",ts="",uo=!0;if(es){ut=await U(c," UniFi URL (e.g. https://unifi.local)",co||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let f=t.env.ALFRED_UNIFI_API_KEY??We?.apiKey??"",_=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],v=f?"1":We?.username?"2":"1";for(let q of _)console.log(` ${M}${q.num}${S}) ${q.label}`);if(((await c.question(` ${M}> ${S}${E(`[${v}] `)}`)).trim()||v)==="1")f&&console.log(` ${E(`Current key: ${le(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),Xe=(await c.question(` ${z}API Key${S}: ${M}`)).trim(),process.stdout.write(S),!Xe&&f&&(Xe=f);else{let q=t.env.ALFRED_UNIFI_USERNAME??We?.username??"";lo=await U(c," Username",q||"alfred");let me=t.env.ALFRED_UNIFI_PASSWORD??We?.password??"";me&&console.log(` ${E(`Current password: ${le(me)}`)}`),ts=(await c.question(` ${z}Password${S}: ${M}`)).trim(),process.stdout.write(S),!ts&&me&&(ts=me)}let C=We?.verifyTls===!1?"y/N":"Y/n",P=(await c.question(` ${z}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${C}]`)}: ${M}`)).trim().toLowerCase()||(We?.verifyTls===!1?"n":"y");process.stdout.write(S),uo=P==="y"||P==="yes",console.log(` ${D(">")} UniFi: ${x(ut)} ${E(`(TLS verify: ${uo?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let lr=t.config.homeassistant,mo=t.env.ALFRED_HOMEASSISTANT_URL??lr?.baseUrl??"",Kc=mo?"Y/n":"y/N",Kn=(await c.question(`
815
+ ${z}Enable Home Assistant?${S} ${E(`[${Kc}]`)}: ${M}`)).trim().toLowerCase()||(mo?"y":"n");process.stdout.write(S);let dr=Kn==="y"||Kn==="yes",ss="",rs="",po=!0;if(dr){ss=await U(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",mo||"http://homeassistant.local:8123");let f=t.env.ALFRED_HOMEASSISTANT_TOKEN??lr?.accessToken??"";f&&console.log(` ${E(`Current token: ${le(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),rs=(await c.question(` ${z}Long-Lived Access Token${S}: ${M}`)).trim(),process.stdout.write(S),!rs&&f&&(rs=f);let _=lr?.verifyTls===!1?"y/N":"Y/n",v=(await c.question(` ${z}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${_}]`)}: ${M}`)).trim().toLowerCase()||(lr?.verifyTls===!1?"n":"y");process.stdout.write(S),po=v==="y"||v==="yes",console.log(` ${D(">")} Home Assistant: ${x(ss)} ${E(`(TLS verify: ${po?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let Te=t.config.contacts,fo=t.env.ALFRED_CONTACTS_PROVIDER??Te?.provider??"",Yc=fo?"Y/n":"y/N",Yn=(await c.question(`
816
+ ${z}Enable Contacts management?${S} ${E(`[${Yc}]`)}: ${M}`)).trim().toLowerCase()||(fo?"y":"n");process.stdout.write(S);let ur=Yn==="y"||Yn==="yes",Ee="",se={};if(ur){let f=["carddav","google","microsoft"],_=f.indexOf(fo),v=_>=0?_+1:1;console.log(` ${pe("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${pe("2)")} Google Contacts`),console.log(` ${pe("3)")} Microsoft 365`);let H=await rr(c," > ",1,3,v);if(Ee=f[H-1],se.ALFRED_CONTACTS_PROVIDER=Ee,Ee==="carddav"){let C=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??Te?.carddav?.serverUrl??"";se.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await U(c," CardDAV Server URL",C||"https://cloud.example.com/remote.php/dav");let P=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??Te?.carddav?.username??"";se.ALFRED_CARDDAV_CONTACTS_USERNAME=await U(c," Username",P);let q=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??Te?.carddav?.password??"";q&&console.log(` ${E(`Current password: ${le(q)}`)}`);let me=(await c.question(` ${z}Password${S}: ${M}`)).trim();process.stdout.write(S),se.ALFRED_CARDDAV_CONTACTS_PASSWORD=me||q}else if(Ee==="google"){let C=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??Te?.google?.clientId??"";C&&console.log(` ${E(`Current client ID: ${le(C)}`)}`),se.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await c.question(` ${z}Google Client ID${S}: ${M}`)).trim()||C,process.stdout.write(S);let P=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??Te?.google?.clientSecret??"";se.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await c.question(` ${z}Google Client Secret${S}: ${M}`)).trim()||P,process.stdout.write(S);let q=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??Te?.google?.refreshToken??"";se.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await c.question(` ${z}Refresh Token${S}: ${M}`)).trim()||q,process.stdout.write(S)}else if(Ee==="microsoft"){let C=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??Te?.microsoft?.clientId??"";C&&console.log(` ${E(`Current client ID: ${le(C)}`)}`),se.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await c.question(` ${z}Microsoft Client ID${S}: ${M}`)).trim()||C,process.stdout.write(S);let P=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??Te?.microsoft?.clientSecret??"";se.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await c.question(` ${z}Microsoft Client Secret${S}: ${M}`)).trim()||P,process.stdout.write(S);let q=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??Te?.microsoft?.tenantId??"";se.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await U(c," Tenant ID",q||"common");let me=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??Te?.microsoft?.refreshToken??"";se.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await c.question(` ${z}Refresh Token${S}: ${M}`)).trim()||me,process.stdout.write(S)}console.log(` ${D(">")} Contacts: ${x(Ee)}`)}else console.log(` ${E("Contacts disabled.")}`);let Jn=t.config.docker,ho=t.env.ALFRED_DOCKER_SOCKET_PATH??Jn?.socketPath??"",go=t.env.ALFRED_DOCKER_HOST??Jn?.host??"",Jc=ho||go?"Y/n":"y/N",Zn=(await c.question(`
817
+ ${z}Enable Docker management?${S} ${E(`[${Jc}]`)}: ${M}`)).trim().toLowerCase()||(ho||go?"y":"n");process.stdout.write(S);let mr=Zn==="y"||Zn==="yes",Ge="",Ke="";if(mr){let f=process.platform==="win32"?"//./pipe/docker_engine":"/var/run/docker.sock";console.log(` ${E("Use socket path for local Docker, or host URL for remote.")}`),Ge=await U(c," Docker socket path",ho||f);let _=(await c.question(` ${z}Docker host URL (optional, for remote)${S}: ${M}`)).trim();process.stdout.write(S),Ke=_||go,console.log(` ${D(">")} Docker: ${x(Ke||Ge)}`)}else console.log(` ${E("Docker disabled.")}`);console.log(`
818
+ ${x("Security configuration:")}`);let Qn=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",he;if(Qn)he=await U(c,"Owner user ID (for elevated permissions)",Qn);else{let f=(await c.question(`${z}Owner user ID${S} ${E("(optional, for elevated permissions)")}: ${M}`)).trim();process.stdout.write(S),he=f}let os=!1;if(he){let f=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${x("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}> ${S}${E(`[${f}] `)}`)).trim().toLowerCase();_===""?os=t.shellEnabled:os=_==="y"||_==="yes",console.log(os?` ${D(">")} Shell access ${x("enabled")} for owner ${E(he)}`:` ${E("Shell access disabled.")}`)}let Zc=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${x("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let yo=(await c.question(` ${M}> ${S}${E(`[${Zc}] `)}`)).trim().toLowerCase(),ns;yo===""?ns=t.writeInGroups:ns=yo==="y"||yo==="yes",console.log(ns?` ${D(">")} Write actions ${x("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let Qc=t.rateLimit??30;console.log("");let el=await U(c," Rate limit (max write actions per hour per user)",String(Qc)),pr=Math.max(1,parseInt(el,10)||30);console.log(` ${D(">")} Rate limit: ${x(String(pr))} per hour`),console.log(`
819
+ ${x("Writing configuration files...")}`);let k=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let f=a.envKeyName||"ALFRED_OLLAMA_API_KEY";k.push(`${f}=${l}`)}if(T!==a.defaultModel&&k.push(`ALFRED_LLM_MODEL=${T}`),m&&k.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(R).length>0){k.push("","# === Additional Model Tiers ===");for(let[f,_]of Object.entries(R)){let v=`ALFRED_LLM_${f.toUpperCase()}`;k.push(""),k.push(`${v}_PROVIDER=${_.provider}`),k.push(`${v}_MODEL=${_.model}`),_.apiKey&&k.push(`${v}_API_KEY=${_.apiKey}`),_.baseUrl&&k.push(`${v}_BASE_URL=${_.baseUrl}`)}}k.push("","# === Messaging Platforms ===","");for(let[f,_]of Object.entries(He))k.push(`${f}=${_}`);if(k.push("","# === Web Search ===",""),Y?(k.push(`ALFRED_SEARCH_PROVIDER=${Y}`),J&&k.push(`ALFRED_SEARCH_API_KEY=${J}`),de&&k.push(`ALFRED_SEARCH_BASE_URL=${de}`)):(k.push("# ALFRED_SEARCH_PROVIDER=brave"),k.push("# ALFRED_SEARCH_API_KEY=")),k.push("","# === Email ===",""),nr&&Ie.length>0){let f=Ie[0];f.provider==="microsoft"?(k.push("ALFRED_EMAIL_PROVIDER=microsoft"),f.msClientId?(k.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${f.msClientId}`),k.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${f.msClientSecret}`),k.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${f.msTenantId}`),k.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${f.msRefreshToken}`)):k.push("# Microsoft email credentials shared from calendar config")):(k.push(`ALFRED_EMAIL_USER=${f.user}`),k.push(`ALFRED_EMAIL_PASS=${f.pass}`)),Ie.length>1&&k.push("# Additional email accounts configured in config/default.yml")}else k.push("# ALFRED_EMAIL_USER="),k.push("# ALFRED_EMAIL_PASS=");if(k.push("","# === Speech ===",""),Re?(k.push(`ALFRED_SPEECH_PROVIDER=${Re}`),k.push(`ALFRED_SPEECH_API_KEY=${Me}`),Wt&&k.push(`ALFRED_SPEECH_BASE_URL=${Wt}`),Xt&&(k.push("ALFRED_TTS_ENABLED=true"),k.push(`ALFRED_TTS_VOICE=${Gt}`))):(k.push("# ALFRED_SPEECH_PROVIDER=groq"),k.push("# ALFRED_SPEECH_API_KEY=")),k.push("","# === Forge (GitHub / GitLab) ===",""),Ve==="github"?(k.push("ALFRED_FORGE_PROVIDER=github"),k.push(`ALFRED_GITHUB_TOKEN=${Kt}`)):Ve==="gitlab"?(k.push("ALFRED_FORGE_PROVIDER=gitlab"),k.push(`ALFRED_GITLAB_TOKEN=${Yt}`)):(k.push("# ALFRED_FORGE_PROVIDER=github"),k.push("# ALFRED_GITHUB_TOKEN=")),k.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),cr?(k.push(`ALFRED_PROXMOX_BASE_URL=${Zt}`),k.push(`ALFRED_PROXMOX_TOKEN_ID=${io}`),k.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Qt}`)):(k.push("# ALFRED_PROXMOX_BASE_URL="),k.push("# ALFRED_PROXMOX_TOKEN_ID="),k.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),es&&Xe?(k.push(`ALFRED_UNIFI_BASE_URL=${ut}`),k.push(`ALFRED_UNIFI_API_KEY=${Xe}`)):es?(k.push(`ALFRED_UNIFI_BASE_URL=${ut}`),k.push(`ALFRED_UNIFI_USERNAME=${lo}`),k.push(`ALFRED_UNIFI_PASSWORD=${ts}`)):(k.push("# ALFRED_UNIFI_BASE_URL="),k.push("# ALFRED_UNIFI_API_KEY=")),dr?(k.push(`ALFRED_HOMEASSISTANT_URL=${ss}`),k.push(`ALFRED_HOMEASSISTANT_TOKEN=${rs}`)):(k.push("# ALFRED_HOMEASSISTANT_URL="),k.push("# ALFRED_HOMEASSISTANT_TOKEN=")),k.push("","# === Contacts ===",""),ur)for(let[f,_]of Object.entries(se))k.push(`${f}=${_}`);else k.push("# ALFRED_CONTACTS_PROVIDER=carddav");k.push("","# === Docker ===",""),mr?(Ge&&k.push(`ALFRED_DOCKER_SOCKET_PATH=${Ge}`),Ke&&k.push(`ALFRED_DOCKER_HOST=${Ke}`)):(k.push("# ALFRED_DOCKER_SOCKET_PATH="),k.push("# ALFRED_DOCKER_HOST=")),k.push("","# === Security ===",""),he?k.push(`ALFRED_OWNER_USER_ID=${he}`):k.push("# ALFRED_OWNER_USER_ID="),k.push("");let tl=fe.join(e,".env");ne.writeFileSync(tl,k.join(`
820
+ `),"utf-8"),console.log(` ${D("+")} ${E(".env")} written`);let fr=fe.join(e,"config");ne.existsSync(fr)||ne.mkdirSync(fr,{recursive:!0});let ei={name:r,telegram:{token:X.telegram?.token??"",enabled:F.some(f=>f.name==="telegram")},discord:{token:X.discord?.token??"",enabled:F.some(f=>f.name==="discord")},whatsapp:{enabled:F.some(f=>f.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:X.matrix?.homeserverUrl??"https://matrix.org",accessToken:X.matrix?.accessToken??"",userId:X.matrix?.userId??"",enabled:F.some(f=>f.name==="matrix")},signal:{apiUrl:X.signal?.apiUrl??"http://localhost:8080",phoneNumber:X.signal?.phoneNumber??"",enabled:F.some(f=>f.name==="signal")},llm:Object.keys(R).length>0?{default:{provider:a.name,model:T,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...R}:{provider:a.name,model:T,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...Y?{search:{provider:Y,...J?{apiKey:J}:{},...de?{baseUrl:de}:{}}}:{},...nr&&Ie.length>0?{email:{accounts:Ie.map(f=>f.provider==="microsoft"?{name:f.name,provider:"microsoft",...f.msClientId?{microsoft:{clientId:f.msClientId,clientSecret:f.msClientSecret,tenantId:f.msTenantId,refreshToken:f.msRefreshToken}}:{}}:{name:f.name,imap:{host:f.imapHost,port:f.imapPort,secure:f.imapPort===993},smtp:{host:f.smtpHost,port:f.smtpPort,secure:f.smtpPort===465},auth:{user:f.user,pass:f.pass}})}}:{},...Re?{speech:{provider:Re,apiKey:Me,...Wt?{baseUrl:Wt}:{},...Xt?{ttsEnabled:!0,ttsVoice:Gt}:{}}}:{},...eo?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...ze.length>0||Ve?{codeAgents:{enabled:ze.length>0,agents:ze,...Ve==="github"?{forge:{provider:"github",github:{token:Kt}}}:Ve==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:Yt}}}:{}}}:{},...cr?{proxmox:{baseUrl:Zt,tokenId:io,tokenSecret:Qt,verifyTls:ao}}:{},...es?{unifi:{baseUrl:ut,...Xe?{apiKey:Xe}:{username:lo,password:ts},site:"default",verifyTls:uo}}:{},...dr?{homeassistant:{baseUrl:ss,accessToken:rs,verifyTls:po}}:{},...ur?{contacts:{provider:Ee,...Ee==="carddav"?{carddav:{serverUrl:se.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:se.ALFRED_CARDDAV_CONTACTS_USERNAME}}:Ee==="google"?{google:{clientId:se.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:Ee==="microsoft"?{microsoft:{clientId:se.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:se.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...mr?{docker:{...Ge?{socketPath:Ge}:{},...Ke?{host:Ke}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};he&&(ei.security.ownerUserId=he);let sl="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Fn.dump(ei,{lineWidth:120,noRefs:!0,sortKeys:!1}),rl=fe.join(fr,"default.yml");ne.writeFileSync(rl,sl,"utf-8"),console.log(` ${D("+")} ${E("config/default.yml")} written`);let wo=fe.join(fr,"rules");ne.existsSync(wo)||ne.mkdirSync(wo,{recursive:!0});let ol=os&&he?`
753
821
  # Allow admin actions (shell, etc.) for the owner only
754
822
  - id: allow-owner-admin
755
823
  effect: allow
@@ -758,7 +826,7 @@ ${A("Writing configuration files...")}`);let S=["# Alfred Environment Variables"
758
826
  actions: ["*"]
759
827
  riskLevels: [admin, destructive]
760
828
  conditions:
761
- users: ["${le}"]
829
+ users: ["${he}"]
762
830
  `:`
763
831
  # Allow admin actions (shell, etc.) for the owner only
764
832
  # Uncomment and set your user ID to enable:
@@ -769,8 +837,8 @@ ${A("Writing configuration files...")}`);let S=["# Alfred Environment Variables"
769
837
  # actions: ["*"]
770
838
  # riskLevels: [admin, destructive]
771
839
  # conditions:
772
- # users: ["${le||"YOUR_USER_ID_HERE"}"]
773
- `,hc=`# Alfred \u2014 Default Security Rules
840
+ # users: ["${he||"YOUR_USER_ID_HERE"}"]
841
+ `,nl=`# Alfred \u2014 Default Security Rules
774
842
  # Rules are evaluated in priority order (lower number = higher priority).
775
843
  # First matching rule wins.
776
844
 
@@ -783,7 +851,7 @@ rules:
783
851
  actions: ["*"]
784
852
  riskLevels: [read]
785
853
 
786
- ${Yt?` # Allow write-level skills everywhere (DMs and groups)
854
+ ${ns?` # Allow write-level skills everywhere (DMs and groups)
787
855
  - id: allow-write-all
788
856
  effect: allow
789
857
  priority: 200
@@ -799,7 +867,7 @@ ${Yt?` # Allow write-level skills everywhere (DMs and groups)
799
867
  conditions:
800
868
  chatType: dm`}
801
869
 
802
- # Rate-limit write actions: max ${Zs} per hour per user
870
+ # Rate-limit write actions: max ${pr} per hour per user
803
871
  - id: rate-limit-write
804
872
  effect: allow
805
873
  priority: 250
@@ -807,9 +875,9 @@ ${Yt?` # Allow write-level skills everywhere (DMs and groups)
807
875
  actions: ["*"]
808
876
  riskLevels: [write]
809
877
  rateLimit:
810
- maxInvocations: ${Zs}
878
+ maxInvocations: ${pr}
811
879
  windowSeconds: 3600
812
- ${pc}
880
+ ${ol}
813
881
  # Deny destructive and admin actions by default
814
882
  - id: deny-destructive
815
883
  effect: deny
@@ -825,15 +893,15 @@ ${pc}
825
893
  scope: global
826
894
  actions: ["*"]
827
895
  riskLevels: [read, write, destructive, admin]
828
- `,fc=ie.join(Yr,"default-rules.yml");se.writeFileSync(fc,hc,"utf-8"),console.log(` ${C("+")} ${T("config/rules/default-rules.yml")} written`);let So=ie.join(e,"data");se.existsSync(So)||(se.mkdirSync(So,{recursive:!0}),console.log(` ${C("+")} ${T("data/")} directory created`)),console.log(""),console.log(`${Ir}${"=".repeat(52)}${k}`),console.log(`${Ir}${ee} Setup complete!${k}`),console.log(`${Ir}${"=".repeat(52)}${k}`),console.log(""),console.log(` ${A("Bot name:")} ${r}`),console.log(` ${A("LLM default:")} ${a.name} (${y})`),l&&console.log(` ${A("API key:")} ${ue(l)}`);for(let[p,E]of Object.entries(x)){let $=p.charAt(0).toUpperCase()+p.slice(1);console.log(` ${A(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${E.provider} (${E.model})`)}if(q.length>0?console.log(` ${A("Platforms:")} ${q.map(p=>p.label).join(", ")}`):console.log(` ${A("Platforms:")} none (configure later)`),Y){let p={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${L})`};console.log(` ${A("Web search:")} ${p[Y]}`)}else console.log(` ${A("Web search:")} ${T("disabled")}`);if(zs&&_e.length>0){let p=_e.map(E=>E.provider==="microsoft"?`${E.name} (Microsoft 365)${E.msClientId?"":" \u2014 shared from Calendar"}`:`${E.name} (${E.imapHost})`);console.log(` ${A("Email:")} ${p.join(", ")}`)}else console.log(` ${A("Email:")} ${T("disabled")}`);if(Ee){let p={openai:"OpenAI Whisper",groq:"Groq Whisper"},E=Pt?`, TTS: ${Ft}`:"";console.log(` ${A("Voice:")} ${p[Ee]}${E}`)}else console.log(` ${A("Voice:")} ${T("disabled")}`);console.log(` ${A("Code Sandbox:")} ${Dr?C("enabled"):T("disabled")}`),Gs&&console.log(` ${A("Proxmox:")} ${C(qt)}`),Xt&&console.log(` ${A("UniFi:")} ${C(rt)}`),Js&&console.log(` ${A("Home Assist.:")} ${C(Vt)}`),le&&(console.log(` ${A("Owner ID:")} ${le}`),console.log(` ${A("Shell access:")} ${Gt?C("enabled"):T("disabled")}`)),console.log(` ${A("Write scope:")} ${Yt?"DMs + Groups":"DMs only"}`),console.log(` ${A("Rate limit:")} ${Zs}/hour per user`),console.log(""),console.log(`${Ar}Next steps:${k}`),console.log(` ${A("alfred start")} Start Alfred`),console.log(` ${A("alfred status")} Check configuration`),console.log(` ${A("alfred --help")} Show all commands`),console.log(""),console.log(`${Ue}Edit ${A(".env")}${Ue} or ${A("config/default.yml")}${Ue} for manual configuration.${k}`),console.log("")}finally{c.close()}}async function U(c,e,t){let s=(await c.question(`${ee}${e}${k} ${T(`[${t}]`)}: ${D}`)).trim();return process.stdout.write(k),s||t}async function me(c,e){for(;;){let t=(await c.question(`${ee}${e}${k}: ${D}`)).trim();if(process.stdout.write(k),t)return t;console.log(` ${Da("!")} This field is required. Please enter a value.`)}}async function xr(c,e,t,s,r){for(;;){let n=(await c.question(`${D}${e}${k}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Da("!")} Please enter a number between ${t} and ${s}.`)}}function $d(){console.log(`
829
- ${wd}${ee} _ _ _____ ____ _____ ____
896
+ `,il=fe.join(wo,"default-rules.yml");ne.writeFileSync(il,nl,"utf-8"),console.log(` ${D("+")} ${E("config/rules/default-rules.yml")} written`);let ti=fe.join(e,"data");ne.existsSync(ti)||(ne.mkdirSync(ti,{recursive:!0}),console.log(` ${D("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${Xr}${"=".repeat(52)}${S}`),console.log(`${Xr}${z} Setup complete!${S}`),console.log(`${Xr}${"=".repeat(52)}${S}`),console.log(""),console.log(` ${x("Bot name:")} ${r}`),console.log(` ${x("LLM default:")} ${a.name} (${T})`),l&&console.log(` ${x("API key:")} ${le(l)}`);for(let[f,_]of Object.entries(R)){let v=f.charAt(0).toUpperCase()+f.slice(1);console.log(` ${x(`LLM ${v}:`)}${" ".repeat(Math.max(1,10-v.length))}${_.provider} (${_.model})`)}if(F.length>0?console.log(` ${x("Platforms:")} ${F.map(f=>f.label).join(", ")}`):console.log(` ${x("Platforms:")} none (configure later)`),Y){let f={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${de})`};console.log(` ${x("Web search:")} ${f[Y]}`)}else console.log(` ${x("Web search:")} ${E("disabled")}`);if(nr&&Ie.length>0){let f=Ie.map(_=>_.provider==="microsoft"?`${_.name} (Microsoft 365)${_.msClientId?"":" \u2014 shared from Calendar"}`:`${_.name} (${_.imapHost})`);console.log(` ${x("Email:")} ${f.join(", ")}`)}else console.log(` ${x("Email:")} ${E("disabled")}`);if(Re){let f={openai:"OpenAI Whisper",groq:"Groq Whisper"},_=Xt?`, TTS: ${Gt}`:"";console.log(` ${x("Voice:")} ${f[Re]}${_}`)}else console.log(` ${x("Voice:")} ${E("disabled")}`);console.log(` ${x("Code Sandbox:")} ${eo?D("enabled"):E("disabled")}`),cr&&console.log(` ${x("Proxmox:")} ${D(Zt)}`),es&&console.log(` ${x("UniFi:")} ${D(ut)}`),dr&&console.log(` ${x("Home Assist.:")} ${D(ss)}`),ur&&console.log(` ${x("Contacts:")} ${D(Ee)}`),mr&&console.log(` ${x("Docker:")} ${D(Ke||Ge)}`),he&&(console.log(` ${x("Owner ID:")} ${he}`),console.log(` ${x("Shell access:")} ${os?D("enabled"):E("disabled")}`)),console.log(` ${x("Write scope:")} ${ns?"DMs + Groups":"DMs only"}`),console.log(` ${x("Rate limit:")} ${pr}/hour per user`),console.log(""),console.log(`${Gr}Next steps:${S}`),console.log(` ${x("alfred start")} Start Alfred`),console.log(` ${x("alfred status")} Check configuration`),console.log(` ${x("alfred --help")} Show all commands`),console.log(""),console.log(`${qe}Edit ${x(".env")}${qe} or ${x("config/default.yml")}${qe} for manual configuration.${S}`),console.log("")}finally{c.close()}}async function U(c,e,t){let s=(await c.question(`${z}${e}${S} ${E(`[${t}]`)}: ${M}`)).trim();return process.stdout.write(S),s||t}async function ye(c,e){for(;;){let t=(await c.question(`${z}${e}${S}: ${M}`)).trim();if(process.stdout.write(S),t)return t;console.log(` ${Sc("!")} This field is required. Please enter a value.`)}}async function rr(c,e,t,s,r){for(;;){let o=(await c.question(`${M}${e}${S}`)).trim();if(!o)return r;let n=parseInt(o,10);if(!Number.isNaN(n)&&n>=t&&n<=s)return n;console.log(` ${Sc("!")} Please enter a number between ${t} and ${s}.`)}}function vu(){console.log(`
897
+ ${Tu}${z} _ _ _____ ____ _____ ____
830
898
  / \\ | | | ___| _ \\| ____| _ \\
831
899
  / _ \\ | | | |_ | |_) | _| | | | |
832
900
  / ___ \\| |___| _| | _ <| |___| |_| |
833
- /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${k}
834
- ${Ue} Personal AI Assistant \u2014 Setup Wizard${k}
835
- `)}var k,ee,Ue,Ir,D,Ar,yd,wd,De,Dt,Oa,Pa=b(()=>{"use strict";k="\x1B[0m",ee="\x1B[1m",Ue="\x1B[2m",Ir="\x1B[32m",D="\x1B[33m",Ar="\x1B[36m",yd="\x1B[31m",wd="\x1B[35m";u(C,"green");u(bd,"yellow");u(Te,"cyan");u(Da,"red");u(A,"bold");u(T,"dim");u(ue,"maskKey");De=[{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"}]}],Dt=[{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(Td,"findCommand");Oa=[{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(_d,"loadExistingConfig");u(Ed,"setupCommand");u(U,"askWithDefault");u(me,"askRequired");u(xr,"askNumber");u($d,"printBanner")});var ja={};oe(ja,{configCommand:()=>xd});function Sd(c){let e=c.toLowerCase();return vd.some(t=>e.includes(t))}function kd(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function Fa(c){let e={};for(let[t,s]of Object.entries(c))Sd(t)?e[t]=kd(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Fa(s):e[t]=s;return e}async function xd(){let c=new te,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Fa(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var vd,Ba=b(()=>{"use strict";Le();vd=["token","apikey","api_key","accesstoken","secret","password"];u(Sd,"isSensitiveKey");u(kd,"redactValue");u(Fa,"redactObject");u(xd,"configCommand")});var qa={};oe(qa,{rulesCommand:()=>Ad});import Rr from"node:fs";import Ha from"node:path";import Id from"js-yaml";async function Ad(){let c=new te,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ha.resolve(e.security.rulesPath);if(!Rr.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Rr.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Rr.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 Ke,o=[],i=[];for(let a of r){let l=Ha.join(t,a);try{let d=Rr.readFileSync(l,"utf-8"),m=Id.load(d),h=n.loadFromObject(m);o.push(...h)}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 Wa=b(()=>{"use strict";Le();sr();u(Ad,"rulesCommand")});var Xa={};oe(Xa,{statusCommand:()=>Ld});import Xs from"node:fs";import po from"node:path";import Rd from"js-yaml";async function Ld(){let c=new te,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=po.resolve(e.storage.path),n=Xs.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=po.resolve(e.security.rulesPath),i=0,a=0;if(Xs.existsSync(o)&&Xs.statSync(o).isDirectory()){let l=Xs.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new Ke;for(let m of l){let h=po.join(o,m);try{let w=Xs.readFileSync(h,"utf-8"),y=Rd.load(w),g=d.loadFromObject(y);i+=g.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 za=b(()=>{"use strict";Le();sr();u(Ld,"statusCommand")});var Va={};oe(Va,{logsCommand:()=>Cd});import Md from"node:fs";import Nd from"node:path";async function Cd(c){let e=new te,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=Nd.resolve(t.storage.path);if(!Md.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 We(s);let n=new Xe(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 Ka=b(()=>{"use strict";Le();ln();u(Cd,"logsCommand")});import{readFileSync as Od}from"node:fs";import{fileURLToPath as Dd}from"node:url";import{dirname as Ud,join as Pd}from"node:path";function Fd(){try{let c=Ud(Dd(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Od(Pd(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Fd,"getVersion");var Ga=Fd(),ho=`
836
- Alfred CLI v${Ga}
901
+ /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${S}
902
+ ${qe} Personal AI Assistant \u2014 Setup Wizard${S}
903
+ `)}var S,z,qe,Xr,M,Gr,wu,Tu,Be,Vt,vc,Ac=y(()=>{"use strict";S="\x1B[0m",z="\x1B[1m",qe="\x1B[2m",Xr="\x1B[32m",M="\x1B[33m",Gr="\x1B[36m",wu="\x1B[31m",Tu="\x1B[35m";u(D,"green");u(Eu,"yellow");u(pe,"cyan");u(Sc,"red");u(x,"bold");u(E,"dim");u(le,"maskKey");Be=[{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"}]}],Vt=[{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(bu,"findCommand");vc=[{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(_u,"loadExistingConfig");u($u,"setupCommand");u(U,"askWithDefault");u(ye,"askRequired");u(rr,"askNumber");u(vu,"printBanner")});var Rc={};re(Rc,{configCommand:()=>Iu});function ku(c){let e=c.toLowerCase();return Su.some(t=>e.includes(t))}function Au(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function Ic(c){let e={};for(let[t,s]of Object.entries(c))ku(t)?e[t]=Au(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Ic(s):e[t]=s;return e}async function Iu(){let c=new oe,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Ic(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Su,xc=y(()=>{"use strict";Oe();Su=["token","apikey","api_key","accesstoken","secret","password"];u(ku,"isSensitiveKey");u(Au,"redactValue");u(Ic,"redactObject");u(Iu,"configCommand")});var Lc={};re(Lc,{rulesCommand:()=>xu});import Kr from"node:fs";import Cc from"node:path";import Ru from"js-yaml";async function xu(){let c=new oe,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Cc.resolve(e.security.rulesPath);if(!Kr.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Kr.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Kr.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 o=new tt,n=[],i=[];for(let a of r){let l=Cc.join(t,a);try{let d=Kr.readFileSync(l,"utf-8"),m=Ru.load(d),p=o.loadFromObject(m);n.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: ${n.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(n.length!==0){n.sort((a,l)=>a.priority-l.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of n){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 Nc=y(()=>{"use strict";Oe();yr();u(xu,"rulesCommand")});var Mc={};re(Mc,{statusCommand:()=>Lu});import or from"node:fs";import jn from"node:path";import Cu from"js-yaml";async function Lu(){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=jn.resolve(e.storage.path),o=or.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${o?"exists":"not yet created"}`),console.log("");let n=jn.resolve(e.security.rulesPath),i=0,a=0;if(or.existsSync(n)&&or.statSync(n).isDirectory()){let l=or.readdirSync(n).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new tt;for(let m of l){let p=jn.join(n,m);try{let w=or.readFileSync(p,"utf-8"),T=Cu.load(w),g=d.loadFromObject(T);i+=g.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${n}`),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 Dc=y(()=>{"use strict";Oe();yr();u(Lu,"statusCommand")});var Oc={};re(Oc,{logsCommand:()=>Du});import Nu from"node:fs";import Mu from"node:path";async function Du(c){let e=new oe,t;try{t=e.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let s=Mu.resolve(t.storage.path);if(!Nu.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 Je(s);let o=new Ze(r.getDb()),n=o.count({}),i=o.query({limit:c});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${n}`),console.log(`Showing last ${Math.min(c,n)} 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(o){console.error("Failed to read audit log:",o.message),process.exit(1)}finally{r&&r.close()}}var Uc=y(()=>{"use strict";Oe();xo();u(Du,"logsCommand")});import{readFileSync as Ou}from"node:fs";import{fileURLToPath as Uu}from"node:url";import{dirname as Pu,join as Fu}from"node:path";function ju(){try{let c=Pu(Uu(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Ou(Fu(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(ju,"getVersion");var Pc=ju(),Bn=`
904
+ Alfred CLI v${Pc}
837
905
  Personal AI Assistant
838
906
 
839
907
  Usage:
@@ -851,4 +919,4 @@ Commands:
851
919
  Options:
852
920
  --help, -h Show this help message
853
921
  --version, -v Show version number
854
- `.trim();function jd(c){let e=c.slice(2),t=e.length>0&&!e[0].startsWith("-")?e[0]:"",s=t?e.slice(1):e,r={},n=[],o=0;for(;o<s.length;){let i=s[o];if(i.startsWith("--")){let a=i.slice(2);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else if(i.startsWith("-")&&i.length===2){let a=i.slice(1);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else n.push(i),o+=1}return{command:t,flags:r,positional:n}}u(jd,"parseArgs");async function Bd(){let c=jd(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(ho),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Ga}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(La(),Ra));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(Ca(),Na));await e({model:typeof c.flags.model=="string"?c.flags.model:void 0,tier:typeof c.flags.tier=="string"?c.flags.tier:void 0});break}case"setup":{let{setupCommand:e}=await Promise.resolve().then(()=>(Pa(),Ua));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(Ba(),ja));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(Wa(),qa));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(za(),Xa));await e();break}case"logs":{let e=c.flags.tail,t=20;if(typeof e=="string"){let r=parseInt(e,10);(Number.isNaN(r)||r<=0)&&(console.error("Error: --tail must be a positive integer"),process.exit(1)),t=r}let{logsCommand:s}=await Promise.resolve().then(()=>(Ka(),Va));await s(t);break}case"help":console.log(ho);break;case"":console.log(ho),process.exit(0);break;default:console.error(`Unknown command: ${c.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}u(Bd,"main");Bd().catch(c=>{console.error("Fatal error:",c),process.exit(1)});
922
+ `.trim();function Bu(c){let e=c.slice(2),t=e.length>0&&!e[0].startsWith("-")?e[0]:"",s=t?e.slice(1):e,r={},o=[],n=0;for(;n<s.length;){let i=s[n];if(i.startsWith("--")){let a=i.slice(2);n+1<s.length&&!s[n+1].startsWith("-")?(r[a]=s[n+1],n+=2):(r[a]=!0,n+=1)}else if(i.startsWith("-")&&i.length===2){let a=i.slice(1);n+1<s.length&&!s[n+1].startsWith("-")?(r[a]=s[n+1],n+=2):(r[a]=!0,n+=1)}else o.push(i),n+=1}return{command:t,flags:r,positional:o}}u(Bu,"parseArgs");async function qu(){let c=Bu(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(Bn),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Pc}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(Ec(),Tc));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>($c(),_c));await e({model:typeof c.flags.model=="string"?c.flags.model:void 0,tier:typeof c.flags.tier=="string"?c.flags.tier:void 0});break}case"setup":{let{setupCommand:e}=await Promise.resolve().then(()=>(Ac(),kc));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(xc(),Rc));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(Nc(),Lc));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(Dc(),Mc));await e();break}case"logs":{let e=c.flags.tail,t=20;if(typeof e=="string"){let r=parseInt(e,10);(Number.isNaN(r)||r<=0)&&(console.error("Error: --tail must be a positive integer"),process.exit(1)),t=r}let{logsCommand:s}=await Promise.resolve().then(()=>(Uc(),Oc));await s(t);break}case"help":console.log(Bn);break;case"":console.log(Bn),process.exit(0);break;default:console.error(`Unknown command: ${c.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}u(qu,"main");qu().catch(c=>{console.error("Fatal error:",c),process.exit(1)});