@madh-io/alfred-ai 0.9.64 → 0.9.65

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 +161 -161
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0});var y=(c,e)=>()=>(c&&(e=c(c=0)),e);var ie=(c,e)=>{for(var t in e)di(c,t,{get:e[t],enumerable:!0})};import{z as h}from"zod";var mi,pi,fi,hi,gi,yi,wi,Ti,et,gl,yl,wl,ui,Tl,El,bl,_l,$l,vl,Sl,kl,Al,xl,Il,Rl,Cl,Ll,Nl,Ml,Dl,Ol,Ul,Pl,Fl,jl,Bl,ql,Io,Ro=y(()=>{"use strict";mi=h.object({token:h.string().optional(),enabled:h.boolean()}),pi=h.object({token:h.string().optional(),enabled:h.boolean()}),fi=h.object({enabled:h.boolean(),dataPath:h.string()}),hi=h.object({homeserverUrl:h.string(),accessToken:h.string().optional(),userId:h.string().optional(),enabled:h.boolean()}),gi=h.object({apiUrl:h.string(),phoneNumber:h.string().optional(),enabled:h.boolean()}),yi=h.object({path:h.string()}),wi=h.object({level:h.enum(["trace","debug","info","warn","error","fatal"]),pretty:h.boolean(),auditLogPath:h.string().optional()}),Ti=h.object({rulesPath:h.string(),defaultEffect:h.enum(["allow","deny"]),ownerUserId:h.string().optional()}),et=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()}),gl=h.object({default:et,strong:et.optional(),fast:et.optional(),embeddings:et.optional(),local:et.optional()}),yl=h.union([et,gl]),wl=h.object({provider:h.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:h.string().optional(),baseUrl:h.string().optional()}),ui=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()}),Tl=h.union([h.object({accounts:h.array(ui)}),ui]),El=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()}),bl=h.object({serverUrl:h.string(),username:h.string(),password:h.string()}),_l=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),$l=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),vl=h.object({provider:h.enum(["caldav","google","microsoft"]),caldav:bl.optional(),google:_l.optional(),microsoft:$l.optional()}),Sl=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()}),kl=h.object({servers:h.array(Sl)}),Al=h.object({enabled:h.boolean(),allowedLanguages:h.array(h.enum(["javascript","python"])).optional(),maxTimeoutMs:h.number().optional(),allowNetwork:h.boolean().optional()}),xl=h.object({enabled:h.boolean().optional(),minMessageLength:h.number().optional(),minConfidence:h.number().min(0).max(1).optional(),maxExtractionsPerMinute:h.number().optional()}),Il=h.object({enabled:h.boolean(),port:h.coerce.number().int().min(1).max(65535),host:h.string()}),Rl=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()}),Cl=h.object({token:h.string(),baseUrl:h.string().optional()}),Ll=h.object({token:h.string(),baseUrl:h.string().optional()}),Nl=h.object({provider:h.enum(["github","gitlab"]),baseBranch:h.string().optional(),github:Cl.optional(),gitlab:Ll.optional()}),Ml=h.object({enabled:h.boolean(),agents:h.array(Rl),forge:Nl.optional()}),Dl=h.object({baseUrl:h.string(),tokenId:h.string(),tokenSecret:h.string(),verifyTls:h.boolean().optional(),defaultNode:h.string().optional()}),Ol=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()}),Ul=h.object({baseUrl:h.string(),accessToken:h.string(),verifyTls:h.boolean().optional()}),Pl=h.object({serverUrl:h.string(),username:h.string(),password:h.string(),addressBookPath:h.string().optional()}),Fl=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),jl=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),Bl=h.object({provider:h.enum(["carddav","google","microsoft"]),carddav:Pl.optional(),google:Fl.optional(),microsoft:jl.optional()}),ql=h.object({socketPath:h.string().optional(),host:h.string().optional(),verifyTls:h.boolean().optional()}),Io=h.object({name:h.string(),telegram:mi,discord:pi.optional(),whatsapp:fi.optional(),matrix:hi.optional(),signal:gi.optional(),llm:yl,storage:yi,logger:wi,security:Ti,search:wl.optional(),email:Tl.optional(),speech:El.optional(),calendar:vl.optional(),mcp:kl.optional(),codeSandbox:Al.optional(),activeLearning:xl.optional(),api:Il.optional(),codeAgents:Ml.optional(),proxmox:Dl.optional(),unifi:Ol.optional(),homeassistant:Ul.optional(),contacts:Bl.optional(),docker:ql.optional()})});var Co,Lo=y(()=>{"use strict";Co={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 Ei from"node:fs";import Hl from"node:path";import{config as bi}from"dotenv";import zl from"js-yaml";function _i(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]=_i(o,r):t[s]=r}return t}function Wl(c){let e={...c};for(let[t,s]of Object.entries(Vl)){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 No(){bi({override:!0})}var Vl,ae,$i=y(()=>{"use strict";Ro();Lo();u(_i,"deepMerge");Vl={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(Wl,"applyEnvOverrides");u(No,"reloadDotenv");ae=class{static{u(this,"ConfigLoader")}loadConfig(e){bi();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Hl.resolve(t);if(Ei.existsSync(r)){let d=Ei.readFileSync(r,"utf-8"),m=zl.load(d);m&&typeof m=="object"&&(s=m)}let o=_i(Co,s),n=Wl(o),i=Io.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 Be=y(()=>{"use strict";Ro();Lo();$i()});import Mo from"pino";function ps(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Mo.transport({target:"pino-pretty",options:{colorize:!0}});return Mo({name:c,level:t},r)}return Mo({name:c,level:t})}var vi=y(()=>{"use strict";u(ps,"createLogger")});import Em from"pino";var Si=y(()=>{"use strict"});var Do=y(()=>{"use strict";vi();Si()});var Tt,$r=y(()=>{"use strict";Tt=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var ui=Object.defineProperty;var u=(c,e)=>ui(c,"name",{value:e,configurable:!0});var w=(c,e)=>()=>(c&&(e=c(c=0)),e);var ie=(c,e)=>{for(var t in e)ui(c,t,{get:e[t],enumerable:!0})};import{z as h}from"zod";var pi,fi,hi,gi,yi,wi,Ti,bi,rt,gl,yl,wl,mi,Tl,bl,El,_l,$l,vl,Sl,kl,Al,xl,Il,Rl,Cl,Ll,Nl,Ml,Dl,Ol,Ul,Pl,Fl,jl,Bl,ql,Hl,Ro,Co=w(()=>{"use strict";pi=h.object({token:h.string().optional(),enabled:h.boolean()}),fi=h.object({token:h.string().optional(),enabled:h.boolean()}),hi=h.object({enabled:h.boolean(),dataPath:h.string()}),gi=h.object({homeserverUrl:h.string(),accessToken:h.string().optional(),userId:h.string().optional(),enabled:h.boolean()}),yi=h.object({apiUrl:h.string(),phoneNumber:h.string().optional(),enabled:h.boolean()}),wi=h.object({path:h.string()}),Ti=h.object({level:h.enum(["trace","debug","info","warn","error","fatal"]),pretty:h.boolean(),auditLogPath:h.string().optional()}),bi=h.object({rulesPath:h.string(),defaultEffect:h.enum(["allow","deny"]),ownerUserId:h.string().optional()}),rt=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()}),gl=h.object({default:rt,strong:rt.optional(),fast:rt.optional(),embeddings:rt.optional(),local:rt.optional()}).passthrough(),yl=h.union([rt,gl]),wl=h.object({provider:h.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:h.string().optional(),baseUrl:h.string().optional()}),mi=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()}),Tl=h.union([h.object({accounts:h.array(mi)}),mi]),bl=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()}),El=h.object({serverUrl:h.string(),username:h.string(),password:h.string()}),_l=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),$l=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),vl=h.object({provider:h.enum(["caldav","google","microsoft"]),caldav:El.optional(),google:_l.optional(),microsoft:$l.optional()}),Sl=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()}),kl=h.object({servers:h.array(Sl)}),Al=h.object({enabled:h.boolean(),allowedLanguages:h.array(h.enum(["javascript","python"])).optional(),maxTimeoutMs:h.number().optional(),allowNetwork:h.boolean().optional()}),xl=h.object({enabled:h.boolean().optional(),minMessageLength:h.number().optional(),minConfidence:h.number().min(0).max(1).optional(),maxExtractionsPerMinute:h.number().optional()}),Il=h.object({enabled:h.boolean(),port:h.coerce.number().int().min(1).max(65535),host:h.string()}),Rl=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()}),Cl=h.object({token:h.string(),baseUrl:h.string().optional()}),Ll=h.object({token:h.string(),baseUrl:h.string().optional()}),Nl=h.object({provider:h.enum(["github","gitlab"]),baseBranch:h.string().optional(),github:Cl.optional(),gitlab:Ll.optional()}),Ml=h.object({enabled:h.boolean(),agents:h.array(Rl),forge:Nl.optional()}),Dl=h.object({baseUrl:h.string(),tokenId:h.string(),tokenSecret:h.string(),verifyTls:h.boolean().optional(),defaultNode:h.string().optional()}),Ol=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()}),Ul=h.object({baseUrl:h.string(),accessToken:h.string(),verifyTls:h.boolean().optional()}),Pl=h.object({serverUrl:h.string(),username:h.string(),password:h.string(),addressBookPath:h.string().optional()}),Fl=h.object({clientId:h.string(),clientSecret:h.string(),refreshToken:h.string()}),jl=h.object({clientId:h.string(),clientSecret:h.string(),tenantId:h.string(),refreshToken:h.string()}),Bl=h.object({provider:h.enum(["carddav","google","microsoft"]),carddav:Pl.optional(),google:Fl.optional(),microsoft:jl.optional()}),ql=h.object({socketPath:h.string().optional(),host:h.string().optional(),verifyTls:h.boolean().optional()}),Hl=h.object({maxHistoryMessages:h.number().min(10).max(500).optional()}).optional(),Ro=h.object({name:h.string(),telegram:pi,discord:fi.optional(),whatsapp:hi.optional(),matrix:gi.optional(),signal:yi.optional(),llm:yl,storage:wi,logger:Ti,security:bi,search:wl.optional(),email:Tl.optional(),speech:bl.optional(),calendar:vl.optional(),mcp:kl.optional(),codeSandbox:Al.optional(),activeLearning:xl.optional(),api:Il.optional(),codeAgents:Ml.optional(),proxmox:Dl.optional(),unifi:Ol.optional(),homeassistant:Ul.optional(),contacts:Bl.optional(),docker:ql.optional(),conversation:Hl})});var Lo,No=w(()=>{"use strict";Lo={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"},conversation:{maxHistoryMessages:100}}});import Ei from"node:fs";import zl from"node:path";import{config as _i}from"dotenv";import Vl from"js-yaml";function $i(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]=$i(o,r):t[s]=r}return t}function Gl(c){let e={...c};for(let[t,s]of Object.entries(Wl)){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 Mo(){_i({override:!0})}var Wl,ae,vi=w(()=>{"use strict";Co();No();u($i,"deepMerge");Wl={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(Gl,"applyEnvOverrides");u(Mo,"reloadDotenv");ae=class{static{u(this,"ConfigLoader")}loadConfig(e){_i();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=zl.resolve(t);if(Ei.existsSync(r)){let T=Ei.readFileSync(r,"utf-8"),y=Vl.load(T);y&&typeof y=="object"&&(s=y)}let o=$i(Lo,s),n=Gl(o),i=["strong","fast","embeddings","local"],a=n.llm;if(a&&"provider"in a&&i.some(y=>a[y]&&typeof a[y]=="object")){let y={};for(let[b,v]of Object.entries(a))!i.includes(b)&&b!=="default"&&(y[b]=v);let g={default:y};for(let b of i)a[b]&&(g[b]=a[b]);n.llm=g}let l=Ro.parse(n),d=l.llm;d&&"provider"in d&&(l.llm={default:d});let m=l.llm;if(m&&typeof m=="object"){let T=m.apiKey??m.default?.apiKey;if(T)for(let y of["default","strong","fast","embeddings","local"]){let g=m[y];g&&!g.apiKey&&(g.apiKey=T)}}let p=l.email;return p&&!("accounts"in p)&&(l.email={accounts:[{name:"default",...p}]}),l}}});var qe=w(()=>{"use strict";Co();No();vi()});import Do from"pino";function fs(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Do.transport({target:"pino-pretty",options:{colorize:!0}});return Do({name:c,level:t},r)}return Do({name:c,level:t})}var Si=w(()=>{"use strict";u(fs,"createLogger")});import Em from"pino";var ki=w(()=>{"use strict"});var Oo=w(()=>{"use strict";Si();ki()});var Et,kr=w(()=>{"use strict";Et=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,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 Oo,Uo=y(()=>{"use strict";$r();Oo=[{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 Uo,Po=w(()=>{"use strict";kr();Uo=[{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,
@@ -209,7 +209,7 @@ var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0})
209
209
 
210
210
  CREATE INDEX IF NOT EXISTS idx_todos_user_due
211
211
  ON todos(user_id, completed, due_date);
212
- `)}}]});import Gl from"better-sqlite3";import Xl from"node:fs";import Kl from"node:path";var tt,ki=y(()=>{"use strict";$r();Uo();tt=class{static{u(this,"Database")}db;constructor(e){let t=Kl.dirname(e);Xl.mkdirSync(t,{recursive:!0}),this.db=new Gl(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(`
212
+ `)}}]});import Xl from"better-sqlite3";import Kl from"node:fs";import Yl from"node:path";var ot,Ai=w(()=>{"use strict";kr();Po();ot=class{static{u(this,"Database")}db;constructor(e){let t=Yl.dirname(e);Kl.mkdirSync(t,{recursive:!0}),this.db=new Xl(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(`
213
213
  CREATE TABLE IF NOT EXISTS conversations (
214
214
  id TEXT PRIMARY KEY,
215
215
  platform TEXT NOT NULL,
@@ -259,19 +259,19 @@ var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0})
259
259
 
260
260
  CREATE UNIQUE INDEX IF NOT EXISTS idx_users_platform
261
261
  ON users(platform, platform_user_id);
262
- `)}runMigrations(){new Tt(this.db).migrate(Oo)}getDb(){return this.db}close(){this.db.close()}}});import Ai from"node:crypto";var fs,xi=y(()=>{"use strict";fs=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),o={id:Ai.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
262
+ `)}runMigrations(){new Et(this.db).migrate(Uo)}getDb(){return this.db}close(){this.db.close()}}});import xi from"node:crypto";var hs,Ii=w(()=>{"use strict";hs=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),o={id:xi.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
263
263
  INSERT INTO conversations (id, platform, chat_id, user_id, created_at, updated_at)
264
264
  VALUES (?, ?, ?, ?, ?, ?)
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:Ai.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:xi.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
266
266
  INSERT INTO messages (id, conversation_id, role, content, tool_calls, created_at)
267
267
  VALUES (?, ?, ?, ?, ?, ?)
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 Yl from"node:crypto";var hs,Ii=y(()=>{"use strict";hs=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:Yl.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:n,updatedAt:n};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 Jl from"node:crypto";var gs,Ri=w(()=>{"use strict";gs=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:Jl.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:n,updatedAt:n};return this.db.prepare(`
269
269
  INSERT INTO users (id, platform, platform_user_id, username, display_name, created_at, updated_at)
270
270
  VALUES (?, ?, ?, ?, ?, ?, ?)
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 st,Ri=y(()=>{"use strict";st=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 nt,Ci=w(()=>{"use strict";nt=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
272
272
  INSERT INTO audit_log (id, timestamp, user_id, action, risk_level, rule_id, effect, platform, chat_id, context)
273
273
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
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 Jl}from"node:crypto";var gs,Ci=y(()=>{"use strict";gs=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=Jl();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 Zl}from"node:crypto";var ys,Li=w(()=>{"use strict";ys=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=Zl();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
275
275
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
276
276
  ON CONFLICT(user_id, key) DO UPDATE SET
277
277
  value = excluded.value,
@@ -279,13 +279,13 @@ var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0})
279
279
  type = excluded.type,
280
280
  confidence = excluded.confidence,
281
281
  source = excluded.source,
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 T of r)m.includes(T)&&(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 ys,Li=y(()=>{"use strict";ys=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(`
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 T of r)m.includes(T)&&(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 Ql}from"node:crypto";var ws,Ni=w(()=>{"use strict";ws=class{static{u(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,o){let n={id:Ql(),userId:e,platform:t,chatId:s,message:r,triggerAt:o.toISOString(),createdAt:new Date().toISOString(),fired:!1};return this.db.prepare(`
283
283
  INSERT INTO reminders (id, user_id, platform, chat_id, message, trigger_at, created_at, fired)
284
284
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
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 Ql}from"node:crypto";var ws,Ni=y(()=>{"use strict";ws=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),o=Ql();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 ed}from"node:crypto";var Ts,Mi=y(()=>{"use strict";Ts=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=ed(),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 td from"node:crypto";var Es,Di=y(()=>{"use strict";Es=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:td.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 ed}from"node:crypto";var Ts,Mi=w(()=>{"use strict";Ts=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),o=ed();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 td}from"node:crypto";var bs,Di=w(()=>{"use strict";bs=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=td(),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 sd from"node:crypto";var Es,Oi=w(()=>{"use strict";Es=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:sd.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(`
286
286
  INSERT INTO link_tokens (id, code, user_id, platform, created_at, expires_at)
287
287
  VALUES (?, ?, ?, ?, ?, ?)
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 sd}from"node:crypto";var bs,Oi=y(()=>{"use strict";bs=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,o,n){let i={id:sd(),userId:e,platform:t,chatId:s,description:r,skillName:o,skillInput:n,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 rd}from"node:crypto";var _s,Ui=w(()=>{"use strict";_s=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,o,n){let i={id:rd(),userId:e,platform:t,chatId:s,description:r,skillName:o,skillInput:n,status:"pending",createdAt:new Date().toISOString()};return this.db.prepare(`
289
289
  INSERT INTO background_tasks (id, user_id, platform, chat_id, description, skill_name, skill_input, status, created_at)
290
290
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
291
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(`
@@ -301,7 +301,7 @@ var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0})
301
301
  AND (status IN ('pending', 'running') OR completed_at > datetime('now', '-1 day'))
302
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
303
303
  WHERE status IN ('completed', 'failed')
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 rd}from"node:crypto";var _s,Ui=y(()=>{"use strict";_s=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=rd(),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 od}from"node:crypto";var $s,Pi=w(()=>{"use strict";$s=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=od(),r=this.calculateInitialNextRun(e.scheduleType,e.scheduleValue);return this.db.prepare(`
305
305
  INSERT INTO scheduled_actions
306
306
  (id, user_id, platform, chat_id, name, description, schedule_type, schedule_value,
307
307
  skill_name, skill_input, prompt_template, enabled, next_run_at, created_at)
@@ -312,13 +312,13 @@ var di=Object.defineProperty;var u=(c,e)=>di(c,"name",{value:e,configurable:!0})
312
312
  UPDATE scheduled_actions
313
313
  SET last_run_at = ?, next_run_at = ?
314
314
  WHERE id = ?
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 Pi}from"node:crypto";var $s,Fi=y(()=>{"use strict";$s=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let o=Pi(),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=Pi(),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 od}from"node:crypto";var vs,ji=y(()=>{"use strict";vs=class{static{u(this,"TodoRepository")}db;constructor(e){this.db=e}add(e,t,s){let r=new Date().toISOString(),o=od(),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,
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 Fi}from"node:crypto";var vs,ji=w(()=>{"use strict";vs=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let o=Fi(),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=Fi(),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 nd}from"node:crypto";var Ss,Bi=w(()=>{"use strict";Ss=class{static{u(this,"TodoRepository")}db;constructor(e){this.db=e}add(e,t,s){let r=new Date().toISOString(),o=nd(),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
316
  SUM(CASE WHEN completed = 0 THEN 1 ELSE 0 END) as open,
317
317
  SUM(CASE WHEN completed = 1 THEN 1 ELSE 0 END) as completed,
318
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 Po=y(()=>{"use strict";ki();xi();Ii();Ri();Ci();$r();Uo();Li();Ni();Mi();Di();Oi();Ui();Fi();ji()});function rt(c){if(Fo[c])return Fo[c];let e=Object.entries(Fo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var Fo,nd,Se,Et=y(()=>{"use strict";Fo={"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}},nd={maxInputTokens:8192,maxOutputTokens:4096};u(rt,"lookupContextWindow");Se=class{static{u(this,"LLMProvider")}config;contextWindow=nd;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import id from"@anthropic-ai/sdk";var Ss,jo=y(()=>{"use strict";Et();Ss=class extends Se{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new id({apiKey:this.config.apiKey});let e=rt(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 ad from"openai";var Ee,ot=y(()=>{"use strict";Et();Ee=class extends Se{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new ad({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=rt(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 T of r){let w=T.choices[0];if(!w)continue;let g=w.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 S;try{S=JSON.parse(i||"{}")}catch{S={}}l.push({id:o,name:n,input:S})}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}});w.finish_reason&&(d=w.finish_reason),T.usage&&(m=T.usage.prompt_tokens,p=T.usage.completion_tokens)}if(o){let T;try{T=JSON.parse(i||"{}")}catch{T={}}l.push({id:o,name:n,input:T})}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 ks,Bo=y(()=>{"use strict";ot();ks=class extends Ee{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 As,qo=y(()=>{"use strict";Et();As=class extends Se{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=rt(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 T=await o.text();throw new Error(`Ollama API error (${o.status}): ${T}`)}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:T,value:w}=await n.read();if(T)break;a+=i.decode(w,{stream:!0});let g=a.split(`
320
- `);a=g.pop()??"";for(let b of g){let S=b.trim();if(!S)continue;let A;try{A=JSON.parse(S)}catch{continue}if(A.message?.content&&(l+=A.message.content,yield{type:"text_delta",text:A.message.content}),A.message?.tool_calls)for(let k of A.message.tool_calls){let O={id:`ollama_tool_${p.length}`,name:k.function.name,input:k.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 T;try{T=JSON.parse(a.trim())}catch{return}if(T.message?.content&&(l+=T.message.content,yield{type:"text_delta",text:T.message.content}),T.message?.tool_calls)for(let w of T.message.tool_calls){let g={id:`ollama_tool_${p.length}`,name:w.function.name,input:w.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}}}T.done&&(d=T.prompt_eval_count??0,m=T.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 xs,Ho=y(()=>{"use strict";ot();xs=class extends Ee{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 Is,zo=y(()=>{"use strict";ot();Is=class extends Ee{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 Rs,Vo=y(()=>{"use strict";ot();Rs=class extends Ee{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 Wo(c){switch(c.provider){case"anthropic":return new Ss(c);case"openai":return new Ee(c);case"openrouter":return new ks(c);case"ollama":return new As(c);case"openwebui":return new xs(c);case"google":return new Is(c);case"mistral":return new Rs(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var Go=y(()=>{"use strict";jo();ot();Bo();qo();Ho();zo();Vo();u(Wo,"createLLMProvider")});function Xo(c){return new vr(c)}var cd,vr,Bi=y(()=>{"use strict";Et();Go();cd=["default","strong","fast","embeddings","local"],vr=class extends Se{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of cd){let t=this.multiConfig[e];if(t){let s=Wo(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(Xo,"createModelRouter")});function ke(c){return Math.ceil(c.length/3.5)}function Ls(c){if(typeof c.content=="string")return ke(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=ke(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=ke(t.name)+ke(JSON.stringify(t.input));break;case"tool_result":e+=ke(t.content);break}return e}var Cs,qi=y(()=>{"use strict";u(ke,"estimateTokens");u(Ls,"estimateMessageTokens");Cs=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}).
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 Fo=w(()=>{"use strict";Ai();Ii();Ri();Ci();Li();kr();Po();Ni();Mi();Di();Oi();Ui();Pi();ji();Bi()});function it(c){if(jo[c])return jo[c];let e=Object.entries(jo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var jo,id,ke,_t=w(()=>{"use strict";jo={"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}},id={maxInputTokens:8192,maxOutputTokens:4096};u(it,"lookupContextWindow");ke=class{static{u(this,"LLMProvider")}config;contextWindow=id;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import ad from"@anthropic-ai/sdk";var ks,Bo=w(()=>{"use strict";_t();ks=class extends ke{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new ad({apiKey:this.config.apiKey});let e=it(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 cd from"openai";var be,at=w(()=>{"use strict";_t();be=class extends ke{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new cd({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=it(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 T of r){let y=T.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 b of g.tool_calls)if(b.id){if(o){let v;try{v=JSON.parse(i||"{}")}catch{v={}}l.push({id:o,name:n,input:v})}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}});y.finish_reason&&(d=y.finish_reason),T.usage&&(m=T.usage.prompt_tokens,p=T.usage.completion_tokens)}if(o){let T;try{T=JSON.parse(i||"{}")}catch{T={}}l.push({id:o,name:n,input:T})}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 As,qo=w(()=>{"use strict";at();As=class extends be{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 xs,Ho=w(()=>{"use strict";_t();xs=class extends ke{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=it(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 T=await o.text();throw new Error(`Ollama API error (${o.status}): ${T}`)}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:T,value:y}=await n.read();if(T)break;a+=i.decode(y,{stream:!0});let g=a.split(`
320
+ `);a=g.pop()??"";for(let b of g){let v=b.trim();if(!v)continue;let A;try{A=JSON.parse(v)}catch{continue}if(A.message?.content&&(l+=A.message.content,yield{type:"text_delta",text:A.message.content}),A.message?.tool_calls)for(let k of A.message.tool_calls){let O={id:`ollama_tool_${p.length}`,name:k.function.name,input:k.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 T;try{T=JSON.parse(a.trim())}catch{return}if(T.message?.content&&(l+=T.message.content,yield{type:"text_delta",text:T.message.content}),T.message?.tool_calls)for(let y of T.message.tool_calls){let g={id:`ollama_tool_${p.length}`,name:y.function.name,input:y.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}}}T.done&&(d=T.prompt_eval_count??0,m=T.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 Is,zo=w(()=>{"use strict";at();Is=class extends be{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 Rs,Vo=w(()=>{"use strict";at();Rs=class extends be{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 Cs,Wo=w(()=>{"use strict";at();Cs=class extends be{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 Go(c){switch(c.provider){case"anthropic":return new ks(c);case"openai":return new be(c);case"openrouter":return new As(c);case"ollama":return new xs(c);case"openwebui":return new Is(c);case"google":return new Rs(c);case"mistral":return new Cs(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var Xo=w(()=>{"use strict";Bo();at();qo();Ho();zo();Vo();Wo();u(Go,"createLLMProvider")});function Ko(c){return new Ar(c)}var ld,Ar,qi=w(()=>{"use strict";_t();Xo();ld=["default","strong","fast","embeddings","local"],Ar=class extends ke{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of ld){let t=this.multiConfig[e];if(t){let s=Go(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(Ko,"createModelRouter")});function Ae(c){return Math.ceil(c.length/3.5)}function Ns(c){if(typeof c.content=="string")return Ae(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=Ae(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=Ae(t.name)+Ae(JSON.stringify(t.input));break;case"tool_result":e+=Ae(t.content);break}return e}var Ls,Hi=w(()=>{"use strict";u(Ae,"estimateTokens");u(Ns,"estimateMessageTokens");Ls=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}).
322
322
 
323
323
  ## Core principles
324
324
  - **When the user's intent is clear**, ACT immediately using your tools. Don't explain what you'll do \u2014 just do it.
@@ -347,11 +347,11 @@ For complex tasks, work through multiple steps:
347
347
  - Home: ${i}
348
348
  - Documents: ${i}/Documents
349
349
  - Desktop: ${i}/Desktop
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"}),T=m.toLocaleDateString("en-CA",{timeZone:d}),w=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"}),T=m.toLocaleDateString("en-CA",{timeZone:d}),y=m.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
351
351
 
352
352
  ## Current date & time`,a+=`
353
353
  - Timezone: ${d}`,a+=`
354
- - Date: ${T} (${w})`,a+=`
354
+ - Date: ${T} (${y})`,a+=`
355
355
  - Time: ${p}`,r?.timezone&&r.timezone!==l&&(a+=`
356
356
  - Server timezone: ${l}`),s&&s.length>0){a+=`
357
357
 
@@ -365,51 +365,51 @@ For complex tasks, work through multiple steps:
365
365
  - Language: ${r.language}`),r.bio&&(a+=`
366
366
  - Bio: ${r.bio}`)),o&&o.length>0){a+=`
367
367
 
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}:{}}),S=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}${S}: ${g.title}${A}`}}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}:{}}),v=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}${v}: ${g.title}${A}`}}if(t&&t.length>0){if(a+=`
370
370
 
371
371
  ## Memories about this user
372
- `,t.some(b=>b.type&&b.type!=="general")){let b=new Map;for(let A of t){let k=A.type||"general",O=b.get(k);O||(O=[],b.set(k,O)),O.push(A)}let S={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,k]of b){a+=`
373
- ### ${S[A]||A}
372
+ `,t.some(b=>b.type&&b.type!=="general")){let b=new Map;for(let A of t){let k=A.type||"general",O=b.get(k);O||(O=[],b.set(k,O)),O.push(A)}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[A,k]of b){a+=`
373
+ ### ${v[A]||A}
374
374
  `;for(let O of k)a+=`- ${O.key}: ${O.value}
375
375
  `}}else for(let b of t)a+=`- [${b.category}] ${b.key}: ${b.value}
376
376
  `;a+=`
377
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+=`
378
378
 
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 Ko=y(()=>{"use strict";Et();jo();ot();Bo();qo();Ho();zo();Vo();Go();Bi();qi()});var Ns,Yo=y(()=>{"use strict";Ns=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 Ms,Hi=y(()=>{"use strict";Yo();Ms=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new Ns;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 zi,Vi,Wi,nt,Gi=y(()=>{"use strict";zi=["allow","deny"],Vi=["global","user","conversation","platform"],Wi=["read","write","destructive","admin"],nt=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"||!zi.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${zi.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"||!Vi.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Vi.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(!Wi.includes(o))throw new Error(`Rule "${s.id}" has invalid risk level "${o}": expected one of ${Wi.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 ld from"node:crypto";var Ds,Xi=y(()=>{"use strict";Ds=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:ld.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=y(()=>{"use strict";Hi();Yo();Gi();Xi()});var I,j=y(()=>{"use strict";I=class{static{u(this,"Skill")}}});function Q(c){return c.masterUserId??c.userId}function z(c){let e=new Set;if(e.add(Q(c)),e.add(c.userId),c.linkedPlatformUserIds)for(let t of c.linkedPlatformUserIds)e.add(t);return[...e]}var Le=y(()=>{"use strict";u(Q,"effectiveUserId");u(z,"allUserIds")});var bt,Ki=y(()=>{"use strict";bt=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 _t,Yi=y(()=>{"use strict";_t=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"),T=u(w=>{a||(a=!0,p(),i(w))},"finish");e.execute(t,s).then(w=>{this.logger.info({skill:r,success:w.success},"Skill execution completed"),T(w)},w=>{let g=w instanceof Error?w.message:String(w);this.logger.error({skill:r,error:g},"Skill execution failed"),T({success:!1,error:g})}),m=setTimeout(()=>{if(a)return;let w=n.getIdleMs();if(w>=12e4){let b=n.getSnapshot();this.logger.warn({skill:r,idleMs:w,state:b.state,iteration:b.iteration},"Agent inactive after initial timeout \u2014 aborting"),T({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(w/1e3)}s (last state: ${b.state})`});return}let g=n.getSnapshot();this.logger.info({skill:r,idleMs:w,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(),S=n.getSnapshot();b>=12e4?(this.logger.warn({skill:r,idleMs:b,state:S.state,iteration:S.iteration,totalMs:S.totalElapsedMs},"Agent went inactive \u2014 aborting"),T({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(b/1e3)}s (last state: ${S.state})`})):this.logger.debug({skill:r,idleMs:b,state:S.state,iteration:S.iteration},"Agent still active, continuing...")},1e4)},o),d=setTimeout(()=>{if(a)return;let w=n.getSnapshot();this.logger.error({skill:r,totalMs:w.totalElapsedMs,state:w.state,iteration:w.iteration},"Absolute time limit reached \u2014 force killing agent"),T({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 it,Jo=y(()=>{"use strict";it=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 dd from"node:fs";import Zo from"node:path";var kr,Ji=y(()=>{"use strict";j();kr=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Zo.resolve(e),s;try{s=await dd.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 ud,md,$t,Zi=y(()=>{"use strict";j();ud=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,md=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,$t=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!md.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let o=r.replace(ud,"");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 vt,Qi=y(()=>{"use strict";j();vt=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),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 St,ea=y(()=>{"use strict";j();St=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let 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}**
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 Yo=w(()=>{"use strict";_t();Bo();at();qo();Ho();zo();Vo();Wo();Xo();qi();Hi()});var Ms,Jo=w(()=>{"use strict";Ms=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 Ds,zi=w(()=>{"use strict";Jo();Ds=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new Ms;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 Vi,Wi,Gi,ct,Xi=w(()=>{"use strict";Vi=["allow","deny"],Wi=["global","user","conversation","platform"],Gi=["read","write","destructive","admin"],ct=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"||!Vi.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${Vi.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"||!Wi.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Wi.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(!Gi.includes(o))throw new Error(`Rule "${s.id}" has invalid risk level "${o}": expected one of ${Gi.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 dd from"node:crypto";var Os,Ki=w(()=>{"use strict";Os=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:dd.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 xr=w(()=>{"use strict";zi();Jo();Xi();Ki()});var I,j=w(()=>{"use strict";I=class{static{u(this,"Skill")}}});function J(c){return c.masterUserId??c.userId}function H(c){let e=new Set;if(e.add(J(c)),e.add(c.userId),c.linkedPlatformUserIds)for(let t of c.linkedPlatformUserIds)e.add(t);return[...e]}var Ne=w(()=>{"use strict";u(J,"effectiveUserId");u(H,"allUserIds")});var $t,Yi=w(()=>{"use strict";$t=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 vt,Ji=w(()=>{"use strict";vt=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"),T=u(y=>{a||(a=!0,p(),i(y))},"finish");e.execute(t,s).then(y=>{this.logger.info({skill:r,success:y.success},"Skill execution completed"),T(y)},y=>{let g=y instanceof Error?y.message:String(y);this.logger.error({skill:r,error:g},"Skill execution failed"),T({success:!1,error:g})}),m=setTimeout(()=>{if(a)return;let y=n.getIdleMs();if(y>=12e4){let b=n.getSnapshot();this.logger.warn({skill:r,idleMs:y,state:b.state,iteration:b.iteration},"Agent inactive after initial timeout \u2014 aborting"),T({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(y/1e3)}s (last state: ${b.state})`});return}let g=n.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){p();return}let b=n.getIdleMs(),v=n.getSnapshot();b>=12e4?(this.logger.warn({skill:r,idleMs:b,state:v.state,iteration:v.iteration,totalMs:v.totalElapsedMs},"Agent went inactive \u2014 aborting"),T({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(b/1e3)}s (last state: ${v.state})`})):this.logger.debug({skill:r,idleMs:b,state:v.state,iteration:v.iteration},"Agent still active, continuing...")},1e4)},o),d=setTimeout(()=>{if(a)return;let y=n.getSnapshot();this.logger.error({skill:r,totalMs:y.totalElapsedMs,state:y.state,iteration:y.iteration},"Absolute time limit reached \u2014 force killing agent"),T({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 lt,Zo=w(()=>{"use strict";lt=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 ud from"node:fs";import Qo from"node:path";var Ir,Zi=w(()=>{"use strict";j();Ir=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Qo.resolve(e),s;try{s=await ud.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=Qo.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=Qo.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 md,pd,St,Qi=w(()=>{"use strict";j();md=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,pd=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,St=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!pd.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let o=r.replace(md,"");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 kt,ea=w(()=>{"use strict";j();kt=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),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 At,ta=w(()=>{"use strict";j();At=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let 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}**
380
380
  ${a.url}
381
381
  ${a.snippet}`).join(`
382
382
 
383
383
  `);return{success:!0,data:{query:s,results:n},display:`Search results for "${s}":
384
384
 
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 kt,ta=y(()=>{"use strict";j();Le();kt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of z(e))for(let 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(Q(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 T=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||T.setHours(e,t,0,0),T}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 T=i.formatToParts(o),w=parseInt(T.find(K=>K.type==="year").value,10),g=parseInt(T.find(K=>K.type==="month").value,10)-1,b=parseInt(T.find(K=>K.type==="day").value,10),S=new Date(Date.UTC(w,g,b,e,t,0)),A=i.formatToParts(S),k=parseInt(A.find(K=>K.type==="hour").value,10),O=parseInt(A.find(K=>K.type==="minute").value,10),L=(e-k)*60+(t-O);return S=new Date(S.getTime()+L*6e4),S}let a=n,l=i.formatToParts(a),d=parseInt(l.find(T=>T.type==="hour").value,10),m=parseInt(l.find(T=>T.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:
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 xt,sa=w(()=>{"use strict";j();Ne();xt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of H(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(J(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 T=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||T.setHours(e,t,0,0),T}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 T=i.formatToParts(o),y=parseInt(T.find(K=>K.type==="year").value,10),g=parseInt(T.find(K=>K.type==="month").value,10)-1,b=parseInt(T.find(K=>K.type==="day").value,10),v=new Date(Date.UTC(y,g,b,e,t,0)),A=i.formatToParts(v),k=parseInt(A.find(K=>K.type==="hour").value,10),O=parseInt(A.find(K=>K.type==="minute").value,10),L=(e-k)*60+(t-O);return v=new Date(v.getTime()+L*6e4),v}let a=n,l=i.formatToParts(a),d=parseInt(l.find(T=>T.type==="hour").value,10),m=parseInt(l.find(T=>T.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:
386
386
  ${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).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 At,sa=y(()=>{"use strict";j();Le();At=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",category:"productivity",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let o=this.noteRepo.save(Q(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 z(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)
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 It,ra=w(()=>{"use strict";j();Ne();It=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",category:"productivity",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let o=this.noteRepo.save(J(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 H(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
388
  ${o.content.slice(0,100)}${o.content.length>100?"\u2026":""}`).join(`
389
389
  `);return{success:!0,data:s,display:`${s.length} note(s):
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 z(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)
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 H(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)
391
391
  ${i.content.slice(0,100)}${i.content.length>100?"\u2026":""}`).join(`
392
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?z(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 pd,xt,ra=y(()=>{"use strict";j();pd={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"},xt=class extends I{static{u(this,"WeatherSkill")}metadata={name:"weather",category:"information",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=pd[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 fd}from"node:child_process";function na(c){return c.length>oa?c.slice(0,oa)+`
395
- [output truncated]`:c}var hd,oa,It,ia=y(()=>{"use strict";j();hd=3e4,oa=1e4;u(na,"truncate");It=class extends I{static{u(this,"ShellSkill")}metadata={name:"shell",category:"automation",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:hd,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
- ${na(i)}`),a&&d.push(`stderr:
397
- ${na(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(`
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?H(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 fd,Rt,oa=w(()=>{"use strict";j();fd={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"},Rt=class extends I{static{u(this,"WeatherSkill")}metadata={name:"weather",category:"information",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=fd[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 hd}from"node:child_process";function ia(c){return c.length>na?c.slice(0,na)+`
395
+ [output truncated]`:c}var gd,na,Ct,aa=w(()=>{"use strict";j();gd=3e4,na=1e4;u(ia,"truncate");Ct=class extends I{static{u(this,"ShellSkill")}metadata={name:"shell",category:"automation",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:gd,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
+ ${ia(i)}`),a&&d.push(`stderr:
397
+ ${ia(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
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=>{fd(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 Rt,aa=y(()=>{"use strict";j();Le();Rt=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",category:"core",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,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(Q(t),s,r,o??"general");return this.embeddingService&&this.embeddingService.embedAndStore(Q(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 z(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 z(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):
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=>{hd(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 Lt,ca=w(()=>{"use strict";j();Ne();Lt=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",category:"core",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,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(J(t),s,r,o??"general");return this.embeddingService&&this.embeddingService.embedAndStore(J(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 H(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 H(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
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 z(t)){let a=s&&typeof s=="string"?this.memoryRepo.listByCategory(i,s):this.memoryRepo.listAll(i);for(let l of a)r.has(l.id)||(r.add(l.id),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}:
401
+ `)}`}}listMemories(e,t){let s=e.category,r=new Set,o=[];for(let i of H(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
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 z(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 z(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):
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 H(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 H(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
404
  ${o.map(n=>`- ${n.key}: "${n.value}" (score: ${n.score.toFixed(2)})`).join(`
405
- `)}`}}}});var gd,yd,wd,Ct,ca=y(()=>{"use strict";j();Jo();gd=5,yd=15,wd=12e4,Ct=class extends I{static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",category:"core",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:wd,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 it(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(yd,Math.round(o))):gd,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new it(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}
405
+ `)}`}}}});var yd,wd,Td,Nt,la=w(()=>{"use strict";j();Zo();yd=5,wd=15,Td=12e4,Nt=class extends I{static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",category:"core",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:Td,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 lt(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(wd,Math.round(o))):yd,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new lt(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
406
 
407
- Additional context: ${r}`);let p=[{role:"user",content:m}];try{let T=0,w=0,g=0;for(;;){a.ping("llm_call",{iteration:T,maxIterations:n});let b=await this.llm.complete({messages:p,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(w+=b.usage.inputTokens,g+=b.usage.outputTokens,a.ping("processing",{iteration:T,maxIterations:n}),!b.toolCalls||b.toolCalls.length===0||T>=n)return a.ping("done",{iteration:T,maxIterations:n}),{success:!0,data:{response:b.content,iterations:T,usage:{inputTokens:w,outputTokens:g}},display:b.content};T++;let S=[];b.content&&S.push({type:"text",text:b.content});for(let k of b.toolCalls)S.push({type:"tool_use",id:k.id,name:k.name,input:k.input});p.push({role:"assistant",content:S});let A=[];for(let k of b.toolCalls){a.ping("tool_call",{iteration:T,maxIterations:n,tool:k.name});let O=await this.executeSubAgentTool(k,t);A.push({type:"tool_result",tool_use_id:k.id,content:O.content,is_error:O.isError})}p.push({role:"user",content:A})}}catch(T){return{success:!1,error:`Sub-agent failed: ${T instanceof Error?T.message:String(T)}`}}}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 Oe,Ar=y(()=>{"use strict";Oe=class{static{u(this,"EmailProvider")}}});var la={};ie(la,{MicrosoftGraphEmailProvider:()=>xr});var xr,Qo=y(()=>{"use strict";Ar();xr=class extends Oe{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,`
407
+ Additional context: ${r}`);let p=[{role:"user",content:m}];try{let T=0,y=0,g=0;for(;;){a.ping("llm_call",{iteration:T,maxIterations:n});let b=await this.llm.complete({messages:p,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(y+=b.usage.inputTokens,g+=b.usage.outputTokens,a.ping("processing",{iteration:T,maxIterations:n}),!b.toolCalls||b.toolCalls.length===0||T>=n)return a.ping("done",{iteration:T,maxIterations:n}),{success:!0,data:{response:b.content,iterations:T,usage:{inputTokens:y,outputTokens:g}},display:b.content};T++;let v=[];b.content&&v.push({type:"text",text:b.content});for(let k of b.toolCalls)v.push({type:"tool_use",id:k.id,name:k.name,input:k.input});p.push({role:"assistant",content:v});let A=[];for(let k of b.toolCalls){a.ping("tool_call",{iteration:T,maxIterations:n,tool:k.name});let O=await this.executeSubAgentTool(k,t);A.push({type:"tool_result",tool_use_id:k.id,content:O.content,is_error:O.isError})}p.push({role:"user",content:A})}}catch(T){return{success:!1,error:`Sub-agent failed: ${T instanceof Error?T.message:String(T)}`}}}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 Ue,Rr=w(()=>{"use strict";Ue=class{static{u(this,"EmailProvider")}}});var da={};ie(da,{MicrosoftGraphEmailProvider:()=>Cr});var Cr,en=w(()=>{"use strict";Rr();Cr=class extends Ue{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,`
408
408
  `).replace(/<\/p>/gi,`
409
409
 
410
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,`
411
411
 
412
- `).trim()}}});var da={};ie(da,{StandardEmailProvider:()=>Ir});var Ir,en=y(()=>{"use strict";Ar();Ir=class extends Oe{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(T=>T.name?`${T.name} <${T.address}>`:T.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(`
412
+ `).trim()}}});var ua={};ie(ua,{StandardEmailProvider:()=>Lr});var Lr,tn=w(()=>{"use strict";Rr();Lr=class extends Ue{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(T=>T.name?`${T.name} <${T.address}>`:T.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(`
413
413
 
414
414
  `));let r=s.match(/boundary="?([^"\s;]+)"?/i)??e.match(/boundary="?([^"\s;]+)"?/i);if(!r)return t.slice(1).join(`
415
415
 
@@ -419,7 +419,7 @@ Additional context: ${r}`);let p=[{role:"user",content:m}];try{let T=0,w=0,g=0;f
419
419
  \r
420
420
  `);if(d>=0)return this.decodeBody(i.slice(d+4))}}return this.decodeBody(t.slice(1).join(`
421
421
 
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 Os(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(Qo(),la)),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(()=>(en(),da)),t=new e(c);return await t.initialize(),t}var ua=y(()=>{"use strict";u(Os,"createEmailProvider")});var qe,ma=y(()=>{"use strict";Ar();ua();en();Qo();j();qe=class extends I{static{u(this,"EmailSkill")}metadata;providers;accountNames;defaultAccount;multiAccount;constructor(e){super(),e instanceof Map?this.providers=e:e?this.providers=new Map([["default",e]]):this.providers=new Map,this.accountNames=[...this.providers.keys()],this.defaultAccount=this.accountNames[0]??"default",this.multiAccount=this.providers.size>1;let t=this.multiAccount?{account:{type:"string",enum:this.accountNames,description:`Email account to use (available: ${this.accountNames.join(", ")})`}}:{},s=this.multiAccount?`Access the user's email accounts (${this.accountNames.join(", ")}): check inbox, read messages, search emails, send new emails, 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",category:"productivity",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}
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 Us(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(en(),da)),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(()=>(tn(),ua)),t=new e(c);return await t.initialize(),t}var ma=w(()=>{"use strict";u(Us,"createEmailProvider")});var He,pa=w(()=>{"use strict";Rr();ma();tn();en();j();He=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",category:"productivity",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}
423
423
  From: ${l.from}
424
424
  Date: ${l.date.toISOString()}`}).join(`
425
425
 
@@ -445,20 +445,20 @@ ${o.map((n,i)=>` ${i+1}. ${n}`).join(`
445
445
 
446
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):
447
447
 
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 pa,Lt,fa=y(()=>{"use strict";j();pa=1e5,Lt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",category:"files",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>pa,T=p?m.slice(0,pa)+`
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 fa,Mt,ha=w(()=>{"use strict";j();fa=1e5,Mt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",category:"files",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>fa,T=p?m.slice(0,fa)+`
449
449
 
450
- [... truncated]`:m,w=T;d.includes("text/html")&&(w=this.stripHtml(T).slice(0,1e4));let g={status:l.status,statusText:l.statusText,contentType:d,bodyLength:m.length,truncated:p,body:T};return l.ok?{success:!0,data:g,display:`HTTP ${l.status} OK (${m.length} bytes)
450
+ [... truncated]`:m,y=T;d.includes("text/html")&&(y=this.stripHtml(T).slice(0,1e4));let g={status:l.status,statusText:l.statusText,contentType:d,bodyLength:m.length,truncated:p,body:T};return l.ok?{success:!0,data:g,display:`HTTP ${l.status} OK (${m.length} bytes)
451
451
 
452
- ${w.slice(0,5e3)}`}:{success:!0,data:g,display:`HTTP ${l.status} ${l.statusText}
452
+ ${y.slice(0,5e3)}`}:{success:!0,data:g,display:`HTTP ${l.status} ${l.statusText}
453
453
 
454
- ${w.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 He from"node:path";var tn,ha,Td,Nt,ga=y(()=>{"use strict";j();tn=5e5,ha=5e7,Td={".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"},Nt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",category:"files",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,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 He.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=He.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>tn){let r=G.readFileSync(e,"utf-8").slice(0,tn);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${tn}):
454
+ ${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,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 ze from"node:path";var sn,ga,bd,Dt,ya=w(()=>{"use strict";j();sn=5e5,ga=5e7,bd={".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"},Dt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",category:"files",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,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 ze.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=ze.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>sn){let r=G.readFileSync(e,"utf-8").slice(0,sn);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${sn}):
455
455
 
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=He.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(`
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=ze.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
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}
458
458
  Size: ${t.size} bytes
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=He.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=He.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=He.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>ha)return{success:!1,error:`File too large to send (${t.size} bytes, max ${ha})`};let s=G.readFileSync(e),r=He.basename(e),o=He.extname(e).toLowerCase(),n=Td[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 Mt}from"node:child_process";var Dt,ya=y(()=>{"use strict";j();Dt=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",category:"media",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=Mt("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Mt("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Mt("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=ze.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=ze.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=ze.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>ga)return{success:!1,error:`File too large to send (${t.size} bytes, max ${ga})`};let s=G.readFileSync(e),r=ze.basename(e),o=ze.extname(e).toLowerCase(),n=bd[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 Ot}from"node:child_process";var Ut,wa=w(()=>{"use strict";j();Ut=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",category:"media",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=Ot("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Ot("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Ot("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)+`
460
460
 
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":Mt("pbcopy",{input:e,timeout:5e3});break;case"win32":Mt('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Mt("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 Us}from"node:child_process";import wa from"node:path";import Ed from"node:os";var Ot,Ta=y(()=>{"use strict";j();Ot=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",category:"media",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=wa.join(Ed.homedir(),"Desktop"),o=e.path||wa.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Us(`screencapture -x "${o}"`,{timeout:1e4});break;case"win32":Us(`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{Us(`scrot "${o}"`,{timeout:1e4})}catch{try{Us(`import -window root "${o}"`,{timeout:1e4})}catch{Us(`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 bd from"node:path";import _d from"node:os";var Ea,Ut,ba=y(()=>{"use strict";j();Ea=5e4,Ut=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",category:"media",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
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":Ot("pbcopy",{input:e,timeout:5e3});break;case"win32":Ot('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Ot("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 Ps}from"node:child_process";import Ta from"node:path";import Ed from"node:os";var Pt,ba=w(()=>{"use strict";j();Pt=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",category:"media",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=Ta.join(Ed.homedir(),"Desktop"),o=e.path||Ta.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Ps(`screencapture -x "${o}"`,{timeout:1e4});break;case"win32":Ps(`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{Ps(`scrot "${o}"`,{timeout:1e4})}catch{try{Ps(`import -window root "${o}"`,{timeout:1e4})}catch{Ps(`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 _d from"node:path";import $d from"node:os";var Ea,Ft,_a=w(()=>{"use strict";j();Ea=5e4,Ft=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",category:"media",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
462
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(`
463
463
  (() => {
464
464
  document.querySelectorAll('script, style, noscript').forEach(el => el.remove());
@@ -470,9 +470,9 @@ Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.op
470
470
 
471
471
  `).trim();return{success:!0,data:{url:o.url(),title:n,length:i.length},display:`**${n}** (${o.url()})
472
472
 
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||bd.join(_d.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 Pt,_a=y(()=>{"use strict";j();Le();Pt=class extends I{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",category:"core",description:"Manage user profile settings including timezone, language, and bio. Use this to personalize Alfred for each user.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set_timezone","set_language","set_bio","set_preference"],description:"The profile action to perform"},value:{type:"string",description:"The value to set (for set_* actions)"},preference_key:{type:"string",description:"The preference key (for set_preference)"},preference_value:{type:"string",description:"The preference value (for set_preference)"}},required:["action"]}};constructor(e){super(),this.userRepo=e}async execute(e,t){let s=e.action,r=Q(t);switch(s){case"get":return this.getProfile(r);case"set_timezone":return this.setField(r,"timezone",e.value);case"set_language":return this.setField(r,"language",e.value);case"set_bio":return this.setField(r,"bio",e.value);case"set_preference":return this.setPreference(r,e.preference_key,e.preference_value);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}getProfile(e){let t=this.userRepo.getProfile(e);if(!t)return{success:!0,data:null,display:"No profile found. Set your timezone, language, or bio to create one."};let s=[];if(t.displayName&&s.push(`Name: ${t.displayName}`),t.timezone&&s.push(`Timezone: ${t.timezone}`),t.language&&s.push(`Language: ${t.language}`),t.bio&&s.push(`Bio: ${t.bio}`),t.preferences)for(let[r,o]of Object.entries(t.preferences))s.push(`${r}: ${String(o)}`);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||_d.join($d.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 jt,$a=w(()=>{"use strict";j();Ne();jt=class extends I{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",category:"core",description:"Manage user profile settings including timezone, language, and bio. Use this to personalize Alfred for each user.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set_timezone","set_language","set_bio","set_preference"],description:"The profile action to perform"},value:{type:"string",description:"The value to set (for set_* actions)"},preference_key:{type:"string",description:"The preference key (for set_preference)"},preference_value:{type:"string",description:"The preference value (for set_preference)"}},required:["action"]}};constructor(e){super(),this.userRepo=e}async execute(e,t){let s=e.action,r=J(t);switch(s){case"get":return this.getProfile(r);case"set_timezone":return this.setField(r,"timezone",e.value);case"set_language":return this.setField(r,"language",e.value);case"set_bio":return this.setField(r,"bio",e.value);case"set_preference":return this.setPreference(r,e.preference_key,e.preference_value);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}getProfile(e){let t=this.userRepo.getProfile(e);if(!t)return{success:!0,data:null,display:"No profile found. Set your timezone, language, or bio to create one."};let s=[];if(t.displayName&&s.push(`Name: ${t.displayName}`),t.timezone&&s.push(`Timezone: ${t.timezone}`),t.language&&s.push(`Language: ${t.language}`),t.bio&&s.push(`Bio: ${t.bio}`),t.preferences)for(let[r,o]of Object.entries(t.preferences))s.push(`${r}: ${String(o)}`);return{success:!0,data:t,display:s.length>0?`Profile:
474
474
  ${s.map(r=>`- ${r}`).join(`
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 Ae,Ps=y(()=>{"use strict";Ae=class{static{u(this,"CalendarProvider")}}});var $a={};ie($a,{CalDAVProvider:()=>Rr});var Rr,sn=y(()=>{"use strict";Ps();Rr=class extends Ae{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(`
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 xe,Fs=w(()=>{"use strict";xe=class{static{u(this,"CalendarProvider")}}});var va={};ie(va,{CalDAVProvider:()=>Nr});var Nr,rn=w(()=>{"use strict";Fs();Nr=class extends xe{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
476
  `).map(p=>p.trim()),r=u(p=>s.find(T=>T.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
477
477
  VERSION:2.0\r
478
478
  PRODID:-//Alfred//EN\r
@@ -488,30 +488,30 @@ BEGIN:VEVENT\r
488
488
  `),r+=`DTSTAMP:${s(new Date)}\r
489
489
  `,r+=`END:VEVENT\r
490
490
  END:VCALENDAR\r
491
- `,r}}});var va={};ie(va,{GoogleCalendarProvider:()=>Cr});var Cr,rn=y(()=>{"use strict";Ps();Cr=class extends Ae{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 Sa={};ie(Sa,{MicrosoftCalendarProvider:()=>Lr});var Lr,on=y(()=>{"use strict";Ps();Lr=class extends Ae{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 Fs(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(sn(),$a)),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(()=>(rn(),va)),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(()=>(on(),Sa)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var ka=y(()=>{"use strict";u(Fs,"createCalendarProvider")});var at,Aa=y(()=>{"use strict";j();at=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",category:"productivity",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:"Start date/time in ISO 8601 format"},end:{type:"string",description:"End date/time in ISO 8601 format"},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){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(`
491
+ `,r}}});var Sa={};ie(Sa,{GoogleCalendarProvider:()=>Mr});var Mr,on=w(()=>{"use strict";Fs();Mr=class extends xe{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 ka={};ie(ka,{MicrosoftCalendarProvider:()=>Dr});var Dr,nn=w(()=>{"use strict";Fs();Dr=class extends xe{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 js(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(rn(),va)),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(()=>(on(),Sa)),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(()=>(nn(),ka)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var Aa=w(()=>{"use strict";u(js,"createCalendarProvider")});var dt,xa=w(()=>{"use strict";j();dt=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",category:"productivity",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:"Start date/time in ISO 8601 format"},end:{type:"string",description:"End date/time in ISO 8601 format"},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){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(`
492
492
  `);return{success:!0,data:r,display:`${r.length} event(s):
493
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
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 xa=y(()=>{"use strict";Ps();sn();rn();on();ka();Aa()});var Ft,Ia=y(()=>{"use strict";j();Ft=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",category:"identity",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
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 Ia=w(()=>{"use strict";Fs();rn();on();nn();Aa();xa()});var Bt,Ra=w(()=>{"use strict";j();Bt=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",category:"identity",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
496
496
 
497
497
  Enter this code on your other platform within 10 minutes using:
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 T=this.users.getLinkedUsers(l);for(let w of T)this.users.setMasterUser(w.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.
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 T=this.users.getLinkedUsers(l);for(let y of T)this.users.setMasterUser(y.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.
499
499
 
500
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
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
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 jt,Ra=y(()=>{"use strict";j();Le();jt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",category:"automation",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}getAllTasks(e){let t=new Set,s=[];for(let r of z(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(Q(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:
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 qt,Ca=w(()=>{"use strict";j();Ne();qt=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",category:"automation",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}getAllTasks(e){let t=new Set,s=[];for(let r of H(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(J(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:
504
504
  ${r.join(`
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 Bt,Ca=y(()=>{"use strict";j();Le();Bt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",category:"automation",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}getAllActions(e){let t=new Set,s=[];for(let r of z(e))for(let 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:Q(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:
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 Ht,La=w(()=>{"use strict";j();Ne();Ht=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",category:"automation",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}getAllActions(e){let t=new Set,s=[];for(let r of H(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:J(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:
506
506
  ${s.join(`
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=z(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=z(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 ct,nn=y(()=>{"use strict";ct=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 $d,lt,an=y(()=>{"use strict";j();$d=["read","write","destructive","admin"],lt=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&&$d.includes(n)?n:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",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 js,La=y(()=>{"use strict";nn();an();js=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 ct(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 lt(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 Na=y(()=>{"use strict";nn();an();La()});import{spawn as vd}from"node:child_process";import qt from"node:fs";import cn from"node:path";import Sd from"node:os";import kd from"node:crypto";var dt,ln=y(()=>{"use strict";dt=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),o=cn.join(Sd.tmpdir(),`alfred-sandbox-${kd.randomUUID()}`);qt.mkdirSync(o,{recursive:!0});try{let n=t==="javascript"?"js":"py",i=cn.join(o,`script.${n}`);qt.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=vd(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"]}),T="",w="";p.stdout.on("data",g=>{T+=g.toString()}),p.stderr.on("data",g=>{w+=g.toString()}),p.on("close",g=>{let b=Date.now()-d,S=[];try{let A=qt.readdirSync(o).filter(k=>!k.startsWith("script."));for(let k of A){let O=cn.join(o,k),L=qt.statSync(O);if(L.isFile()&&L.size<1e7){let K=qt.readFileSync(O),Pe=k.endsWith(".png")?"image/png":k.endsWith(".jpg")||k.endsWith(".jpeg")?"image/jpeg":k.endsWith(".svg")?"image/svg+xml":k.endsWith(".csv")?"text/csv":k.endsWith(".json")?"application/json":k.endsWith(".html")||k.endsWith(".htm")?"text/html":k.endsWith(".txt")?"text/plain":k.endsWith(".md")?"text/markdown":k.endsWith(".xml")?"application/xml":k.endsWith(".pdf")?"application/pdf":"application/octet-stream";S.push({name:k,data:K,mimeType:Pe})}}}catch{}m({stdout:T.slice(0,5e4),stderr:w.slice(0,1e4),exitCode:g??1,files:S.length>0?S:void 0,durationMs:b})}),p.on("error",g=>{m({stdout:"",stderr:g.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{qt.rmSync(o,{recursive:!0,force:!0})}catch{}}}}});var Bs,Ma=y(()=>{"use strict";j();ln();Bs=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",category:"automation",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (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 dt;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)};
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=H(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=H(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 ut,an=w(()=>{"use strict";ut=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 vd,mt,cn=w(()=>{"use strict";j();vd=["read","write","destructive","admin"],mt=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&&vd.includes(n)?n:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",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 Bs,Na=w(()=>{"use strict";an();cn();Bs=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 ut(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 mt(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 Ma=w(()=>{"use strict";an();cn();Na()});import{spawn as Sd}from"node:child_process";import zt from"node:fs";import ln from"node:path";import kd from"node:os";import Ad from"node:crypto";var pt,dn=w(()=>{"use strict";pt=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),o=ln.join(kd.tmpdir(),`alfred-sandbox-${Ad.randomUUID()}`);zt.mkdirSync(o,{recursive:!0});try{let n=t==="javascript"?"js":"py",i=ln.join(o,`script.${n}`);zt.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=Sd(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"]}),T="",y="";p.stdout.on("data",g=>{T+=g.toString()}),p.stderr.on("data",g=>{y+=g.toString()}),p.on("close",g=>{let b=Date.now()-d,v=[];try{let A=zt.readdirSync(o).filter(k=>!k.startsWith("script."));for(let k of A){let O=ln.join(o,k),L=zt.statSync(O);if(L.isFile()&&L.size<1e7){let K=zt.readFileSync(O),Fe=k.endsWith(".png")?"image/png":k.endsWith(".jpg")||k.endsWith(".jpeg")?"image/jpeg":k.endsWith(".svg")?"image/svg+xml":k.endsWith(".csv")?"text/csv":k.endsWith(".json")?"application/json":k.endsWith(".html")||k.endsWith(".htm")?"text/html":k.endsWith(".txt")?"text/plain":k.endsWith(".md")?"text/markdown":k.endsWith(".xml")?"application/xml":k.endsWith(".pdf")?"application/pdf":"application/octet-stream";v.push({name:k,data:K,mimeType:Fe})}}}catch{}m({stdout:T.slice(0,5e4),stderr:y.slice(0,1e4),exitCode:g??1,files:v.length>0?v:void 0,durationMs:b})}),p.on("error",g=>{m({stdout:"",stderr:g.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{zt.rmSync(o,{recursive:!0,force:!0})}catch{}}}}});var qs,Da=w(()=>{"use strict";j();dn();qs=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",category:"automation",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (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 pt;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
509
  ${r}`:a=`INPUT_DATA = ${JSON.stringify(n)}
510
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:
511
511
  ${l.stdout}`:"",l.stderr?`Errors:
512
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(`
513
513
 
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 Da=y(()=>{"use strict";ln();Ma()});var Ht,Oa=y(()=>{"use strict";j();Le();Ht=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",category:"files",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,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(Q(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=z(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(`
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 Oa=w(()=>{"use strict";dn();Da()});var Vt,Ua=w(()=>{"use strict";j();Ne();Vt=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",category:"files",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,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(J(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=H(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(`
515
515
 
516
516
  `);return{success:!0,data:a,display:`Found ${a.length} relevant chunk(s):
517
517
 
@@ -521,13 +521,13 @@ ${l}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success
521
521
 
522
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)
523
523
 
524
- ${a}`}}list(e,t){let s=e.limit||50,r=z(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(`
524
+ ${a}`}}list(e,t){let s=e.limit||50,r=H(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(`
525
525
  `);return{success:!0,data:i,display:`${i.length} document(s):
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 zt,Ua=y(()=>{"use strict";j();zt=class extends I{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",category:"media",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});function re(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 qs(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function Nr(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 Mr,Pa=y(()=>{"use strict";j();u(re,"bytes");u(qs,"pct");u(Nr,"uptimeStr");Mr=class c extends I{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",category:"infrastructure",description:'Manage Proxmox VE virtual machines, containers, and cluster. Use action "list_vms" to see VMs, "start_vm"/"shutdown_vm" to control them, "cluster_status" for health, "create_snapshot" for backups.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["cluster_status","list_nodes","node_stats","list_vms","vm_status","list_snapshots","list_storage","list_tasks","task_status","start_vm","shutdown_vm","reboot_vm","suspend_vm","resume_vm","create_snapshot","backup_vm","migrate_vm","stop_vm","delete_snapshot","rollback_snapshot"],description:"The Proxmox action to perform"},vmid:{type:"number",description:"Virtual machine / container ID"},node:{type:"string",description:"Proxmox node name (optional \u2014 resolved automatically when omitted)"},type:{type:"string",enum:["qemu","lxc"],description:"VM type filter for list_vms (default: both)"},name:{type:"string",description:"Snapshot name (for create/delete/rollback_snapshot)"},description:{type:"string",description:"Snapshot description (optional)"},target:{type:"string",description:"Target node for migration"},storage:{type:"string",description:"Storage target for backup_vm"},upid:{type:"string",description:"Task UPID for task_status"}},required:["action"]}};config;vmCache=null;static VM_CACHE_TTL=3e4;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"cluster_status":return await this.clusterStatus();case"list_nodes":return await this.listNodes();case"node_stats":return await this.nodeStats(e.node);case"list_vms":return await this.listVms(e.node,e.type);case"vm_status":return await this.vmStatus(e.vmid,e.node);case"list_snapshots":return await this.listSnapshots(e.vmid,e.node);case"list_storage":return await this.listStorage(e.node);case"list_tasks":return await this.listTasks(e.node);case"task_status":return await this.taskStatus(e.upid);case"start_vm":return await this.vmPowerAction("start",e);case"shutdown_vm":return await this.vmPowerAction("shutdown",e);case"reboot_vm":return await this.vmPowerAction("reboot",e);case"suspend_vm":return await this.vmPowerAction("suspend",e);case"resume_vm":return await this.vmPowerAction("resume",e);case"stop_vm":return await this.vmPowerAction("stop",e);case"create_snapshot":return await this.createSnapshot(e);case"backup_vm":return await this.backupVm(e);case"migrate_vm":return await this.migrateVm(e);case"delete_snapshot":return await this.deleteSnapshot(e);case"rollback_snapshot":return await this.rollbackSnapshot(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Proxmox API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl}/api2/json${t}`,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"?qs(s.cpu):"-",o=re(s.mem),n=re(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${o} / ${n} | ${Nr(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:** ${Nr(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${qs(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),o&&a.push(`**RAM:** ${re(o.used)} / ${re(o.total)} (${qs(o.used/o.total)})`),i&&a.push(`**Swap:** ${re(i.used)} / ${re(i.total)}`),n&&a.push(`**Root FS:** ${re(n.used)} / ${re(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??"-"} | ${qs(o.cpu)} | ${re(o.mem)} / ${re(o.maxmem)} | ${Nr(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:** ${qs(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${re(r.mem)} / ${re(r.maxmem)}`,`**Disk:** ${re(r.disk)} / ${re(r.maxdisk)}`,`**Uptime:** ${Nr(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${re(r.netin)} / ${re(r.netout)}`];return r.lock&&o.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:o.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 Wt,Pa=w(()=>{"use strict";j();Wt=class extends I{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",category:"media",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});function re(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 Hs(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function Or(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,Fa=w(()=>{"use strict";j();u(re,"bytes");u(Hs,"pct");u(Or,"uptimeStr");Ur=class c extends I{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",category:"infrastructure",description:'Manage Proxmox VE virtual machines, containers, and cluster. Use action "list_vms" to see VMs, "start_vm"/"shutdown_vm" to control them, "cluster_status" for health, "create_snapshot" for backups.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["cluster_status","list_nodes","node_stats","list_vms","vm_status","list_snapshots","list_storage","list_tasks","task_status","start_vm","shutdown_vm","reboot_vm","suspend_vm","resume_vm","create_snapshot","backup_vm","migrate_vm","stop_vm","delete_snapshot","rollback_snapshot"],description:"The Proxmox action to perform"},vmid:{type:"number",description:"Virtual machine / container ID"},node:{type:"string",description:"Proxmox node name (optional \u2014 resolved automatically when omitted)"},type:{type:"string",enum:["qemu","lxc"],description:"VM type filter for list_vms (default: both)"},name:{type:"string",description:"Snapshot name (for create/delete/rollback_snapshot)"},description:{type:"string",description:"Snapshot description (optional)"},target:{type:"string",description:"Target node for migration"},storage:{type:"string",description:"Storage target for backup_vm"},upid:{type:"string",description:"Task UPID for task_status"}},required:["action"]}};config;vmCache=null;static VM_CACHE_TTL=3e4;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"cluster_status":return await this.clusterStatus();case"list_nodes":return await this.listNodes();case"node_stats":return await this.nodeStats(e.node);case"list_vms":return await this.listVms(e.node,e.type);case"vm_status":return await this.vmStatus(e.vmid,e.node);case"list_snapshots":return await this.listSnapshots(e.vmid,e.node);case"list_storage":return await this.listStorage(e.node);case"list_tasks":return await this.listTasks(e.node);case"task_status":return await this.taskStatus(e.upid);case"start_vm":return await this.vmPowerAction("start",e);case"shutdown_vm":return await this.vmPowerAction("shutdown",e);case"reboot_vm":return await this.vmPowerAction("reboot",e);case"suspend_vm":return await this.vmPowerAction("suspend",e);case"resume_vm":return await this.vmPowerAction("resume",e);case"stop_vm":return await this.vmPowerAction("stop",e);case"create_snapshot":return await this.createSnapshot(e);case"backup_vm":return await this.backupVm(e);case"migrate_vm":return await this.migrateVm(e);case"delete_snapshot":return await this.deleteSnapshot(e);case"rollback_snapshot":return await this.rollbackSnapshot(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Proxmox API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl}/api2/json${t}`,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"?Hs(s.cpu):"-",o=re(s.mem),n=re(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${o} / ${n} | ${Or(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:** ${Or(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${Hs(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),o&&a.push(`**RAM:** ${re(o.used)} / ${re(o.total)} (${Hs(o.used/o.total)})`),i&&a.push(`**Swap:** ${re(i.used)} / ${re(i.total)}`),n&&a.push(`**Root FS:** ${re(n.used)} / ${re(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??"-"} | ${Hs(o.cpu)} | ${re(o.mem)} / ${re(o.maxmem)} | ${Or(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:** ${Hs(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${re(r.mem)} / ${re(r.maxmem)}`,`**Disk:** ${re(r.disk)} / ${re(r.maxdisk)}`,`**Uptime:** ${Or(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${re(r.netin)} / ${re(r.netout)}`];return r.lock&&o.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:o.join(`
531
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
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=re(n.used),a=re(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
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(`
@@ -538,7 +538,7 @@ ${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success
538
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
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
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 Dr,Fa=y(()=>{"use strict";j();Dr=class extends I{static{u(this,"UniFiSkill")}metadata={name:"unifi",category:"infrastructure",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(`
541
+ `)}}}});var Pr,ja=w(()=>{"use strict";j();Pr=class extends I{static{u(this,"UniFiSkill")}metadata={name:"unifi",category:"infrastructure",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(`
542
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(`
543
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
544
  `);return{success:!0,data:r,display:`${t?"Active":"All known"} clients (${o.length}):
@@ -554,15 +554,15 @@ ${n}`}}async clientInfo(e){if(!e)return{success:!1,error:"mac is required for cl
554
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
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
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 ja(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 Ad(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 Or,Ba=y(()=>{"use strict";j();u(ja,"parsePeriod");u(Ad,"extractDomain");Or=class extends I{static{u(this,"HomeAssistantSkill")}metadata={name:"homeassistant",category:"infrastructure",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(`
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 Ba(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 xd(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 Fr,qa=w(()=>{"use strict";j();u(Ba,"parsePeriod");u(xd,"extractDomain");Fr=class extends I{static{u(this,"HomeAssistantSkill")}metadata={name:"homeassistant",category:"infrastructure",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
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
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=ja(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(`
560
+ `)}}async getHistory(e,t){let s=Ba(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
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=ja(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(`
562
+ `)}}async getLogbook(e,t){let s=Ba(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
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(`
564
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(`
565
- `)}}async switchAction(e,t,s){if(!t)return{success:!1,error:'Missing required "entityId" parameter'};let r=Ad(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(`
565
+ `)}}async switchAction(e,t,s){if(!t)return{success:!1,error:'Missing required "entityId" parameter'};let r=xd(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
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
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
568
  {% endfor %}`,a=(await this.apiText("POST","/api/template",{template:n})).trim().split(`
@@ -573,13 +573,13 @@ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this
573
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
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
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 T=p.attributes?.friendly_name??p.entity_id,w=p.attributes?.last_triggered?new Date(p.attributes.last_triggered).toLocaleString():"-";m.push(`| ${p.entity_id} | ${T} | ${p.state} | ${w} |`)}return d.length===0&&m.push("| - | No automations found | - | - |"),{success:!0,data:d,display:m.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 T=p.attributes?.friendly_name??p.entity_id,y=p.attributes?.last_triggered?new Date(p.attributes.last_triggered).toLocaleString():"-";m.push(`| ${p.entity_id} | ${T} | ${p.state} | ${y} |`)}return d.length===0&&m.push("| - | No automations found | - | - |"),{success:!0,data:d,display:m.join(`
577
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(`
578
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(`
579
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(`
580
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(`
581
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(`
582
- `)}}}});var xe,Hs=y(()=>{"use strict";xe=class{static{u(this,"ContactsProvider")}}});var qa={};ie(qa,{CardDAVContactsProvider:()=>Ur});var Ur,dn=y(()=>{"use strict";Hs();Ur=class extends xe{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],S=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],k=/TYPE=pref/i.test(b);a.push({address:S,label:A,primary:k})}let l=[];for(let g of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let b=g[0],S=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],k=/TYPE=pref/i.test(b);l.push({number:S,label:A,primary:k})}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"),T=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:n,emails:a,phones:l,addresses:d,organization:m,birthday:p,notes:T}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
582
+ `)}}}});var Ie,zs=w(()=>{"use strict";Ie=class{static{u(this,"ContactsProvider")}}});var Ha={};ie(Ha,{CardDAVContactsProvider:()=>jr});var jr,un=w(()=>{"use strict";zs();jr=class extends Ie{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],v=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],k=/TYPE=pref/i.test(b);a.push({address:v,label:A,primary:k})}let l=[];for(let g of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let b=g[0],v=g[1].trim(),A=b.match(/TYPE=([^;:,]+)/i)?.[1],k=/TYPE=pref/i.test(b);l.push({number:v,label:A,primary:k})}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"),T=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:n,emails:a,phones:l,addresses:d,organization:m,birthday:p,notes:T}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
583
583
  VERSION:3.0\r
584
584
  `;r+=`UID:${e}\r
585
585
  `,r+=`FN:${s}\r
@@ -591,63 +591,63 @@ VERSION:3.0\r
591
591
  `),t.birthday&&(r+=`BDAY:${t.birthday}\r
592
592
  `),t.notes&&(r+=`NOTE:${t.notes}\r
593
593
  `),r+=`END:VCARD\r
594
- `,r}}});var Ha={};ie(Ha,{GoogleContactsProvider:()=>Fr});var Pr,ut,Fr,un=y(()=>{"use strict";Hs();Pr="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",ut="https://people.googleapis.com/v1",Fr=class extends xe{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=`${ut}/people/me/connections?personFields=${Pr}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${ut}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${Pr}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${ut}/${e}?personFields=${Pr}`,s=await this.apiRequest("GET",t);return this.mapPerson(s)}catch{return}}async create(e){let t=this.buildPersonBody(e),s=await this.apiRequest("POST",`${ut}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${ut}/${e}?personFields=${Pr}`),r=this.buildPersonBody(t);r.etag=s.etag;let n=`${ut}/${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",`${ut}/${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 za={};ie(za,{MicrosoftContactsProvider:()=>jr});var jr,mn=y(()=>{"use strict";Hs();jr=class extends xe{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 pn(c){switch(c.provider){case"carddav":{if(!c.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(dn(),qa)),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(()=>(un(),Ha)),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(()=>(mn(),za)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${c.provider}`)}}var Va=y(()=>{"use strict";u(pn,"createContactsProvider")});var zs,Wa=y(()=>{"use strict";j();zs=class extends I{static{u(this,"ContactsSkill")}contactsProvider;metadata={name:"contacts",category:"productivity",description:"Manage contacts. Search, view, create, update, or delete contacts.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["search","get","list","create","update","delete"],description:"The contacts action to perform"},query:{type:"string",description:"Search query (for search action)"},contactId:{type:"string",description:"Contact ID (for get/update/delete)"},firstName:{type:"string",description:"First name (for create/update)"},lastName:{type:"string",description:"Last name (for create/update)"},displayName:{type:"string",description:"Display name (for create/update)"},email:{type:"string",description:"Single email address (for create/update, shorthand)"},phone:{type:"string",description:"Single phone number (for create/update, shorthand)"},organization:{type:"string",description:"Organization / company (for create/update)"},birthday:{type:"string",description:"Birthday in YYYY-MM-DD format (for create/update)"},notes:{type:"string",description:"Notes (for create/update)"},emailAddresses:{type:"string",description:"JSON array of {address, label?, primary?} for multiple emails"},phoneNumbers:{type:"string",description:"JSON array of {number, label?, primary?} for multiple phones"},addresses:{type:"string",description:"JSON array of {street?, city?, region?, postalCode?, country?, label?}"},limit:{type:"number",description:"Maximum number of contacts to return (for list, default 50)"}},required:["action"]}};constructor(e){super(),this.contactsProvider=e}async execute(e,t){let s=e.action;switch(s){case"search":return this.searchContacts(e);case"get":return this.getContact(e);case"list":return this.listContacts(e);case"create":return this.createContact(e);case"update":return this.updateContact(e);case"delete":return this.deleteContact(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async searchContacts(e){let t=e.query;if(!t)return{success:!1,error:'Missing required field "query"'};try{let s=await this.contactsProvider.search(t);if(s.length===0)return{success:!0,data:[],display:`No contacts found for "${t}".`};let r=this.formatTable(s);return{success:!0,data:s,display:`${s.length} contact(s) found:
594
+ `,r}}});var za={};ie(za,{GoogleContactsProvider:()=>qr});var Br,ft,qr,mn=w(()=>{"use strict";zs();Br="names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,biographies",ft="https://people.googleapis.com/v1",qr=class extends Ie{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=`${ft}/people/me/connections?personFields=${Br}&pageSize=${e}`;return((await this.apiRequest("GET",t)).connections??[]).map(r=>this.mapPerson(r))}async search(e){let t=`${ft}/people:searchContacts?query=${encodeURIComponent(e)}&readMask=${Br}&pageSize=30`;return((await this.apiRequest("GET",t)).results??[]).map(r=>this.mapPerson(r.person))}async get(e){try{let t=`${ft}/${e}?personFields=${Br}`,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",`${ft}/people:createContact`,t);return this.mapPerson(s)}async update(e,t){let s=await this.apiRequest("GET",`${ft}/${e}?personFields=${Br}`),r=this.buildPersonBody(t);r.etag=s.etag;let n=`${ft}/${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",`${ft}/${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 Va={};ie(Va,{MicrosoftContactsProvider:()=>Hr});var Hr,pn=w(()=>{"use strict";zs();Hr=class extends Ie{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 fn(c){switch(c.provider){case"carddav":{if(!c.carddav)throw new Error("CardDAV contacts config missing");let{CardDAVContactsProvider:e}=await Promise.resolve().then(()=>(un(),Ha)),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(()=>(mn(),za)),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(()=>(pn(),Va)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown contacts provider: ${c.provider}`)}}var Wa=w(()=>{"use strict";u(fn,"createContactsProvider")});var Vs,Ga=w(()=>{"use strict";j();Vs=class extends I{static{u(this,"ContactsSkill")}contactsProvider;metadata={name:"contacts",category:"productivity",description:"Manage contacts. Search, view, create, update, or delete contacts.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["search","get","list","create","update","delete"],description:"The contacts action to perform"},query:{type:"string",description:"Search query (for search action)"},contactId:{type:"string",description:"Contact ID (for get/update/delete)"},firstName:{type:"string",description:"First name (for create/update)"},lastName:{type:"string",description:"Last name (for create/update)"},displayName:{type:"string",description:"Display name (for create/update)"},email:{type:"string",description:"Single email address (for create/update, shorthand)"},phone:{type:"string",description:"Single phone number (for create/update, shorthand)"},organization:{type:"string",description:"Organization / company (for create/update)"},birthday:{type:"string",description:"Birthday in YYYY-MM-DD format (for create/update)"},notes:{type:"string",description:"Notes (for create/update)"},emailAddresses:{type:"string",description:"JSON array of {address, label?, primary?} for multiple emails"},phoneNumbers:{type:"string",description:"JSON array of {number, label?, primary?} for multiple phones"},addresses:{type:"string",description:"JSON array of {street?, city?, region?, postalCode?, country?, label?}"},limit:{type:"number",description:"Maximum number of contacts to return (for list, default 50)"}},required:["action"]}};constructor(e){super(),this.contactsProvider=e}async execute(e,t){let s=e.action;switch(s){case"search":return this.searchContacts(e);case"get":return this.getContact(e);case"list":return this.listContacts(e);case"create":return this.createContact(e);case"update":return this.updateContact(e);case"delete":return this.deleteContact(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async searchContacts(e){let t=e.query;if(!t)return{success:!1,error:'Missing required field "query"'};try{let s=await this.contactsProvider.search(t);if(s.length===0)return{success:!0,data:[],display:`No contacts found for "${t}".`};let r=this.formatTable(s);return{success:!0,data:s,display:`${s.length} contact(s) found:
595
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
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
597
  |------|-------|-------|`,s=e.map(r=>{let o=r.emails[0]?.address??"-",n=r.phones[0]?.number??"-";return`| ${r.displayName} | ${o} | ${n} |`});return`${t}
598
598
  ${s.join(`
599
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 Ga=y(()=>{"use strict";Hs();dn();un();mn();Va();Wa()});var Vt,Xa=y(()=>{"use strict";j();Le();Vt=class extends I{static{u(this,"TodoSkill")}todoRepo;metadata={name:"todo",category:"productivity",description:"Manage todo lists with multiple named lists. Actions: add, list, complete, uncomplete, delete, lists, clear.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["add","list","complete","uncomplete","delete","lists","clear"],description:"The todo action to perform"},title:{type:"string",description:"The todo title (required for add)"},list:{type:"string",description:'The list name (default: "default")'},description:{type:"string",description:"Optional description for the todo"},priority:{type:"string",enum:["low","normal","high","urgent"],description:'Priority level (default: "normal")'},dueDate:{type:"string",description:"Due date for the todo (ISO string)"},todoId:{type:"string",description:"The ID of the todo (required for complete, uncomplete, delete)"},includeCompleted:{type:"boolean",description:"Include completed todos in list output (default: false)"}},required:["action"]}};constructor(e){super(),this.todoRepo=e}async execute(e,t){let s=e.action;switch(s){case"add":return this.addTodo(e,t);case"list":return this.listTodos(e,t);case"complete":return this.completeTodo(e,t);case"uncomplete":return this.uncompleteTodo(e,t);case"delete":return this.deleteTodo(e,t);case"lists":return this.showLists(t);case"clear":return this.clearCompleted(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: add, list, complete, uncomplete, delete, lists, clear`}}}addTodo(e,t){let s=e.title;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for add action'};let r=e.list??"default",o=e.description,n=e.priority,i=e.dueDate,a=this.todoRepo.add(Q(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 z(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 |
600
+ `)}}});var Xa=w(()=>{"use strict";zs();un();mn();pn();Wa();Ga()});var Gt,Ka=w(()=>{"use strict";j();Ne();Gt=class extends I{static{u(this,"TodoSkill")}todoRepo;metadata={name:"todo",category:"productivity",description:"Manage todo lists with multiple named lists. Actions: add, list, complete, uncomplete, delete, lists, clear.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["add","list","complete","uncomplete","delete","lists","clear"],description:"The todo action to perform"},title:{type:"string",description:"The todo title (required for add)"},list:{type:"string",description:'The list name (default: "default")'},description:{type:"string",description:"Optional description for the todo"},priority:{type:"string",enum:["low","normal","high","urgent"],description:'Priority level (default: "normal")'},dueDate:{type:"string",description:"Due date for the todo (ISO string)"},todoId:{type:"string",description:"The ID of the todo (required for complete, uncomplete, delete)"},includeCompleted:{type:"boolean",description:"Include completed todos in list output (default: false)"}},required:["action"]}};constructor(e){super(),this.todoRepo=e}async execute(e,t){let s=e.action;switch(s){case"add":return this.addTodo(e,t);case"list":return this.listTodos(e,t);case"complete":return this.completeTodo(e,t);case"uncomplete":return this.uncompleteTodo(e,t);case"delete":return this.deleteTodo(e,t);case"lists":return this.showLists(t);case"clear":return this.clearCompleted(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: add, list, complete, uncomplete, delete, lists, clear`}}}addTodo(e,t){let s=e.title;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for add action'};let r=e.list??"default",o=e.description,n=e.priority,i=e.dueDate,a=this.todoRepo.add(J(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 H(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
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
602
  `);return{success:!0,data:n,display:`${n.length} todo(s):
603
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?z(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?z(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?z(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 z(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 |
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?H(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?H(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?H(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 H(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
605
  |---|---|---|---|`,o=s.map(n=>`| ${n.list} | ${n.open} | ${n.completed} | ${n.total} |`).join(`
606
606
  `);return{success:!0,data:s,display:`${s.length} list(s):
607
607
  ${r}
608
- ${o}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(Q(t),s);return{success:!0,data:{cleared:r},display:`Cleared ${r} completed todo(s).`}}}});import Ka from"node:http";import Ya from"node:https";import{execFile as xd}from"node:child_process";import{promisify as Id}from"node:util";function fn(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 Za(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 hn(c){return!c||c.length===0?"-":c.map(e=>e.replace(/^\//,"")).join(", ")}function Rd(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 Cd(c){return c?new Date(c*1e3).toISOString().replace("T"," ").slice(0,19):"-"}var Ja,Br,Qa=y(()=>{"use strict";j();Ja=Id(xd);u(fn,"formatBytes");u(Za,"formatPorts");u(hn,"containerName");u(Rd,"stripDockerStreamHeaders");u(Cd,"relativeTime");Br=class extends I{static{u(this,"DockerSkill")}metadata={name:"docker",category:"infrastructure",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")?Ya:Ka).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")?Ya:Ka).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(`| ${hn(s.Names)} | ${s.Image??"-"} | ${s.Status??s.State??"-"} | ${Za(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,T])=>`${T.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: ${hn(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(`
608
+ ${o}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(J(t),s);return{success:!0,data:{cleared:r},display:`Cleared ${r} completed todo(s).`}}}});import Ya from"node:http";import Ja from"node:https";import{execFile as Id}from"node:child_process";import{promisify as Rd}from"node:util";function hn(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 Qa(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 gn(c){return!c||c.length===0?"-":c.map(e=>e.replace(/^\//,"")).join(", ")}function Cd(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 Ld(c){return c?new Date(c*1e3).toISOString().replace("T"," ").slice(0,19):"-"}var Za,zr,ec=w(()=>{"use strict";j();Za=Rd(Id);u(hn,"formatBytes");u(Qa,"formatPorts");u(gn,"containerName");u(Cd,"stripDockerStreamHeaders");u(Ld,"relativeTime");zr=class extends I{static{u(this,"DockerSkill")}metadata={name:"docker",category:"infrastructure",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")?Ja:Ya).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")?Ja:Ya).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(`| ${gn(s.Names)} | ${s.Image??"-"} | ${s.Status??s.State??"-"} | ${Qa(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,T])=>`${T.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: ${gn(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
610
  `):"- No port bindings","","### Mounts",l.length>0?l.join(`
611
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=Rd(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=fn(s.Size),i=Cd(s.Created);t.push(`| ${o} | ${n} | ${i} |`)}return e.length===0&&t.push("| - | No images found | - |"),{success:!0,data:e,display:t.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=Cd(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=hn(s.Size),i=Ld(s.Created);t.push(`| ${o} | ${n} | ${i} |`)}return e.length===0&&t.push("| - | No images found | - |"),{success:!0,data:e,display:t.join(`
614
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
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
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:** ${fn(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:** ${fn(l)}`];return{success:!0,data:{containers:e,images:t,volumes:s,networks:r},display:d.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:** ${hn(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:** ${hn(l)}`];return{success:!0,data:{containers:e,images:t,volumes:s,networks:r},display:d.join(`
619
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} | ${hn(a.Names)} | ${a.Status??a.State??"-"} | ${Za(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 Ja("docker",["compose","-p",e,"up","-d"],{timeout:12e4}),r=(t+`
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} | ${gn(a.Names)} | ${a.Status??a.State??"-"} | ${Qa(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
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 Ja("docker",["compose","-p",e,"down"],{timeout:12e4}),r=(t+`
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
624
  `+s).trim();return{success:!0,data:{project:e,output:r},display:[`**Compose down:** \`${e}\``,"","```",r,"```"].join(`
625
- `)}}}});import gn from"node:fs";import ec from"node:path";function tc(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Ld(){let c=process.cwd();for(let e=0;e<10;e++){let t=ec.join(c,".env");if(gn.existsSync(t))return t;let s=ec.dirname(c);if(s===c)break;c=s}return null}var Wt,Gt,sc=y(()=>{"use strict";j();Wt={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)"}]}},Gt=class extends I{static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",category:"core",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(Wt)){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(Wt),display:e.join(`
626
- `)}}showService(e){let t=Wt[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Wt).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?tc(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=Wt[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Wt).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
625
+ `)}}}});import yn from"node:fs";import tc from"node:path";function sc(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Nd(){let c=process.cwd();for(let e=0;e<10;e++){let t=tc.join(c,".env");if(yn.existsSync(t))return t;let s=tc.dirname(c);if(s===c)break;c=s}return null}var Xt,Kt,rc=w(()=>{"use strict";j();Xt={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)"}]}},Kt=class extends I{static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",category:"core",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(Xt)){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(Xt),display:e.join(`
626
+ `)}}showService(e){let t=Xt[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Xt).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?sc(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=Xt[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Xt).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
629
629
 
630
630
  Available keys for ${s.label}:
631
631
  ${s.fields.map(d=>`- \`${d.env}\`: ${d.label}${d.required?" (required)":""}`).join(`
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=Ld();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=gn.readFileSync(o,"utf-8"),i=[];for(let[d,m]of Object.entries(t)){let p=m.replace(/\n/g,"\\n"),T=new RegExp(`^#?\\s*${d}=.*$`,"m");T.test(n)?n=n.replace(T,`${d}=${p}`):n=n.trimEnd()+`
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=Nd();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=yn.readFileSync(o,"utf-8"),i=[];for(let[d,m]of Object.entries(t)){let p=m.replace(/\n/g,"\\n"),T=new RegExp(`^#?\\s*${d}=.*$`,"m");T.test(n)?n=n.replace(T,`${d}=${p}`):n=n.trimEnd()+`
633
633
  ${d}=${p}
634
- `,i.push(d)}gn.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?tc(t[d]):t[d]}`)];if(a.length>0)l.push(`
634
+ `,i.push(d)}yn.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?sc(t[d]):t[d]}`)];if(a.length>0)l.push(`
636
636
  **Still missing:** ${a.join(", ")}`);else if(this.reloadCallback){let d=await this.reloadCallback(e);d.success?l.push(`
637
637
  **${s.label} wurde aktiviert.** Du kannst es jetzt sofort nutzen.`):l.push(`
638
638
  **${s.label} is fully configured.** Hot-Reload fehlgeschlagen: ${d.error??"unbekannter Fehler"}. Restart Alfred: \`alfred start\``)}else l.push(`
639
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(tc,"maskValue");u(Ld,"findEnvFile")});import{spawn as Nd}from"node:child_process";import rc from"node:fs";import ic from"node:path";function Ud(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 Pd(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function qr(c){return c.length<=oc?c:`[...truncated...]
641
- `+c.slice(-oc)}function nc(c){let e=new Map;function t(s){let r;try{r=rc.readdirSync(s,{withFileTypes:!0})}catch{return}for(let o of r){if(Od.has(o.name))continue;let n=ic.join(s,o.name);if(o.isDirectory())t(n);else if(o.isFile())try{let i=rc.statSync(n);e.set(n,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function Fd(c,e,t){let s=[];for(let[r,o]of e){let n=c.get(r);(n===void 0||o>n)&&s.push(ic.relative(t,r))}return s.sort()}async function Vs(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??Md,o=Math.min(r,Dd),n=Pd(c.argsTemplate,e),i={...process.env,...c.env?Ud(c.env):{}},a=process.platform==="win32",l=nc(s),d=Date.now();return new Promise(m=>{let p=Nd(c.command,n,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),T="",w="",g=!1,b=setTimeout(()=>{g=!0,p.kill("SIGTERM"),setTimeout(()=>p.kill("SIGKILL"),5e3)},o);p.stdout?.on("data",S=>{T+=S.toString()}),p.stderr?.on("data",S=>{let A=S.toString();if(w+=A,t.onProgress){let k=A.trim().split(`
642
- `).pop();k&&t.onProgress(`[${c.name}] ${k}`)}}),c.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",S=>{clearTimeout(b);let A=Date.now()-d,k=nc(s),O=Fd(l,k,s);m({stdout:qr(T),stderr:qr(w),exitCode:g?124:S??1,durationMs:A,modifiedFiles:O})}),p.on("error",S=>{clearTimeout(b);let A=Date.now()-d;m({stdout:qr(T),stderr:qr(w+`
643
- `+S.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var Md,Dd,oc,Od,Hr=y(()=>{"use strict";Md=3e5,Dd=9e5,oc=1e5,Od=new Set([".git","node_modules",".next","dist",".cache"]);u(Ud,"resolveEnv");u(Pd,"buildArgs");u(qr,"truncateOutput");u(nc,"snapshotMtimes");u(Fd,"detectModifiedFiles");u(Vs,"executeAgent")});import{execFile as jd}from"node:child_process";function Ie(c,e){return new Promise((t,s)=>{jd("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 zr(c){try{let e=await Ie(["rev-parse","--abbrev-ref","HEAD"],c),t=await Ie(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function yn(c,e){await Ie(["checkout","-b",c],e)}async function wn(c){await Ie(["add","-A"],c)}async function Tn(c,e){await Ie(["commit","-m",c],e);let t=await Ie(["rev-parse","--short","HEAD"],e),r=(await Ie(["diff","--stat","HEAD~1","HEAD"],e)).split(`
644
- `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function En(c,e,t){await Ie(["push","-u",c,e],t)}function bn(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function Xt(c,e){try{return await Ie(["remote","get-url",c],e)}catch{return null}}function Kt(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 Ws(c){await Ie(["init"],c)}async function Gs(c,e,t){await Ie(["remote","add",c,e],t)}var _n=y(()=>{"use strict";u(Ie,"git");u(zr,"gitStatus");u(yn,"gitCreateBranch");u(wn,"gitStageAll");u(Tn,"gitCommit");u(En,"gitPush");u(bn,"slugifyBranch");u(Xt,"gitGetRemoteUrl");u(Kt,"parseRemoteUrl");u(Ws,"gitInitRepo");u(Gs,"gitAddRemote")});function Yt(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new $n(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new vn(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var mt,$n,vn,Sn=y(()=>{"use strict";mt=class{static{u(this,"ForgeClient")}},$n=class extends mt{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}}},vn=class extends mt{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(Yt,"createForgeClient")});function ac(c,e){return c.length<=e?c:c.slice(0,e)+`
645
- [...truncated]`}function cc(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function Xd(c,e,t){let r=`Available agents:
640
+ `)}}};u(sc,"maskValue");u(Nd,"findEnvFile")});import{spawn as Md}from"node:child_process";import oc from"node:fs";import ac from"node:path";function Pd(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 Fd(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function Vr(c){return c.length<=nc?c:`[...truncated...]
641
+ `+c.slice(-nc)}function ic(c){let e=new Map;function t(s){let r;try{r=oc.readdirSync(s,{withFileTypes:!0})}catch{return}for(let o of r){if(Ud.has(o.name))continue;let n=ac.join(s,o.name);if(o.isDirectory())t(n);else if(o.isFile())try{let i=oc.statSync(n);e.set(n,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function jd(c,e,t){let s=[];for(let[r,o]of e){let n=c.get(r);(n===void 0||o>n)&&s.push(ac.relative(t,r))}return s.sort()}async function Ws(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??Dd,o=Math.min(r,Od),n=Fd(c.argsTemplate,e),i={...process.env,...c.env?Pd(c.env):{}},a=process.platform==="win32",l=ic(s),d=Date.now();return new Promise(m=>{let p=Md(c.command,n,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),T="",y="",g=!1,b=setTimeout(()=>{g=!0,p.kill("SIGTERM"),setTimeout(()=>p.kill("SIGKILL"),5e3)},o);p.stdout?.on("data",v=>{T+=v.toString()}),p.stderr?.on("data",v=>{let A=v.toString();if(y+=A,t.onProgress){let k=A.trim().split(`
642
+ `).pop();k&&t.onProgress(`[${c.name}] ${k}`)}}),c.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",v=>{clearTimeout(b);let A=Date.now()-d,k=ic(s),O=jd(l,k,s);m({stdout:Vr(T),stderr:Vr(y),exitCode:g?124:v??1,durationMs:A,modifiedFiles:O})}),p.on("error",v=>{clearTimeout(b);let A=Date.now()-d;m({stdout:Vr(T),stderr:Vr(y+`
643
+ `+v.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var Dd,Od,nc,Ud,Wr=w(()=>{"use strict";Dd=3e5,Od=9e5,nc=1e5,Ud=new Set([".git","node_modules",".next","dist",".cache"]);u(Pd,"resolveEnv");u(Fd,"buildArgs");u(Vr,"truncateOutput");u(ic,"snapshotMtimes");u(jd,"detectModifiedFiles");u(Ws,"executeAgent")});import{execFile as Bd}from"node:child_process";function Re(c,e){return new Promise((t,s)=>{Bd("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 Gr(c){try{let e=await Re(["rev-parse","--abbrev-ref","HEAD"],c),t=await Re(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function wn(c,e){await Re(["checkout","-b",c],e)}async function Tn(c){await Re(["add","-A"],c)}async function bn(c,e){await Re(["commit","-m",c],e);let t=await Re(["rev-parse","--short","HEAD"],e),r=(await Re(["diff","--stat","HEAD~1","HEAD"],e)).split(`
644
+ `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function En(c,e,t){await Re(["push","-u",c,e],t)}function _n(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function Yt(c,e){try{return await Re(["remote","get-url",c],e)}catch{return null}}function Jt(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 Gs(c){await Re(["init"],c)}async function Xs(c,e,t){await Re(["remote","add",c,e],t)}var $n=w(()=>{"use strict";u(Re,"git");u(Gr,"gitStatus");u(wn,"gitCreateBranch");u(Tn,"gitStageAll");u(bn,"gitCommit");u(En,"gitPush");u(_n,"slugifyBranch");u(Yt,"gitGetRemoteUrl");u(Jt,"parseRemoteUrl");u(Gs,"gitInitRepo");u(Xs,"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 vn(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new Sn(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var ht,vn,Sn,kn=w(()=>{"use strict";ht=class{static{u(this,"ForgeClient")}},vn=class extends ht{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}}},Sn=class extends ht{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 cc(c,e){return c.length<=e?c:c.slice(0,e)+`
645
+ [...truncated]`}function lc(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function Kd(c,e,t){let r=`Available agents:
646
646
  ${e.map(a=>`- ${a.name}: command="${a.command}"`).join(`
647
647
  `)}
648
648
 
649
649
  Task:
650
- ${c}`,o=await t.complete({system:Wd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),n=cc(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 Kd(c,e,t,s){let r=new kn(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 Vs(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 Yd(c,e,t){let s=e.map(n=>{let i=ac(n.execution.stdout,zd),a=ac(n.execution.stderr,Vd);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:
650
+ ${c}`,o=await t.complete({system:Gd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),n=lc(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 Yd(c,e,t,s){let r=new An(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 Ws(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 Jd(c,e,t){let s=e.map(n=>{let i=cc(n.execution.stdout,Vd),a=cc(n.execution.stderr,Wd);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:
651
651
  ${i}`:"",a?`stderr:
652
652
  ${a}`:""].filter(Boolean).join(`
653
653
  `)}).join(`
@@ -656,11 +656,11 @@ ${a}`:""].filter(Boolean).join(`
656
656
  ${c}
657
657
 
658
658
  Results:
659
- ${s}`,o=await t.complete({system:Gd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let n=cc(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 pt(c,e,t,s={}){let r=Math.min(s.maxIterations??Bd,qd),o=s.maxConcurrent??Hd,n=s.onProgress,i=Date.now(),a=new Map(e.map(g=>[g.name,g]));n?.("Planning subtasks...");let l=await Xd(c,e,t);n?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,p=0,T="";for(;p<r;){p++,n?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let g=await Kd(m,a,o,n);d=d.concat(g),n?.(`Iteration ${p}: validating results...`);let b=await Yd(c,d,t);if(T=b.summary,b.approved||b.fixTasks.length===0)break;let S=b.fixTasks.filter(A=>a.has(A.agent)?!0:(n?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if(S.length===0)break;m=S,n?.(`Validation requested ${S.length} fix task(s), iterating...`)}let w=[...new Set(d.flatMap(g=>g.execution.modifiedFiles))].sort();return{plan:l,iterations:p,subtaskResults:d,allModifiedFiles:w,summary:T,totalDurationMs:Date.now()-i}}async function Xs(c,e,t,s={}){let r=s.onProgress,o=s.cwd??process.cwd(),n={warnings:[]},i=await zr({cwd:o});if(!i.isRepo)try{await Ws({cwd:o}),i=await zr({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 pt(c,e,t,s),git:n}}let a=null,l=await Xt("origin",{cwd:o});if(l){let w=Kt(l);w?(a={owner:w.owner,repo:w.repo},r?.(`Detected remote: ${w.owner}/${w.repo} (${w.baseUrl})`)):n.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let w=Yt(d),g=o.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${g}" on forge...`);let b=await w.createProject({name:g,visibility:"private"});await Gs("origin",b.cloneUrl,{cwd:o});let S=Kt(b.cloneUrl);S&&(a={owner:S.owner,repo:S.repo}),r?.(`Project created: ${b.url} \u2014 remote "origin" set`)}catch(w){let g=w instanceof Error?w.message:String(w);n.warnings.push(`Project creation failed: ${g}`),r?.(`Warning: project creation failed \u2014 ${g}`)}let m=bn(c);try{await yn(m,{cwd:o}),n.branch=m,r?.(`Created branch: ${m}`)}catch(w){throw new Error(`Failed to create branch "${m}": ${w instanceof Error?w.message:String(w)}`)}let p=await pt(c,e,t,s);try{await wn({cwd:o});let w=`feat: ${c.slice(0,72)}
659
+ ${s}`,o=await t.complete({system:Xd,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let n=lc(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 gt(c,e,t,s={}){let r=Math.min(s.maxIterations??qd,Hd),o=s.maxConcurrent??zd,n=s.onProgress,i=Date.now(),a=new Map(e.map(g=>[g.name,g]));n?.("Planning subtasks...");let l=await Kd(c,e,t);n?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,p=0,T="";for(;p<r;){p++,n?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let g=await Yd(m,a,o,n);d=d.concat(g),n?.(`Iteration ${p}: validating results...`);let b=await Jd(c,d,t);if(T=b.summary,b.approved||b.fixTasks.length===0)break;let v=b.fixTasks.filter(A=>a.has(A.agent)?!0:(n?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if(v.length===0)break;m=v,n?.(`Validation requested ${v.length} fix task(s), iterating...`)}let y=[...new Set(d.flatMap(g=>g.execution.modifiedFiles))].sort();return{plan:l,iterations:p,subtaskResults:d,allModifiedFiles:y,summary:T,totalDurationMs:Date.now()-i}}async function Ks(c,e,t,s={}){let r=s.onProgress,o=s.cwd??process.cwd(),n={warnings:[]},i=await Gr({cwd:o});if(!i.isRepo)try{await Gs({cwd:o}),i=await Gr({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 gt(c,e,t,s),git:n}}let a=null,l=await Yt("origin",{cwd:o});if(l){let y=Jt(l);y?(a={owner:y.owner,repo:y.repo},r?.(`Detected remote: ${y.owner}/${y.repo} (${y.baseUrl})`)):n.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let y=Zt(d),g=o.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${g}" on forge...`);let b=await y.createProject({name:g,visibility:"private"});await Xs("origin",b.cloneUrl,{cwd:o});let v=Jt(b.cloneUrl);v&&(a={owner:v.owner,repo:v.repo}),r?.(`Project created: ${b.url} \u2014 remote "origin" set`)}catch(y){let g=y instanceof Error?y.message:String(y);n.warnings.push(`Project creation failed: ${g}`),r?.(`Warning: project creation failed \u2014 ${g}`)}let m=_n(c);try{await wn(m,{cwd:o}),n.branch=m,r?.(`Created branch: ${m}`)}catch(y){throw new Error(`Failed to create branch "${m}": ${y instanceof Error?y.message:String(y)}`)}let p=await gt(c,e,t,s);try{await Tn({cwd:o});let y=`feat: ${c.slice(0,72)}
660
660
 
661
- Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,g=await Tn(w,{cwd:o});n.commit=g,r?.(`Committed: ${g.sha} (${g.filesChanged} files changed)`)}catch(w){let g=w instanceof Error?w.message:String(w);return n.warnings.push(`Commit failed: ${g}`),r?.(`Warning: commit failed \u2014 ${g}`),{...p,git:n}}if(!await Xt("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 En("origin",m,{cwd:o}),r?.(`Pushed branch: ${m}`)}catch(w){let g=w instanceof Error?w.message:String(w);return n.warnings.push(`Push failed: ${g}`),r?.(`Warning: push failed \u2014 ${g}`),{...p,git:n}}if(d&&a)try{let w=Yt(d),g=s.baseBranch??d.baseBranch??"main",b=s.prTitle??`feat: ${c.slice(0,72)}`,S=["## Summary",p.summary,"",`**Iterations:** ${p.iterations}`,`**Modified files:** ${p.allModifiedFiles.length}`,p.allModifiedFiles.map(k=>`- \`${k}\``).join(`
661
+ Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,g=await bn(y,{cwd:o});n.commit=g,r?.(`Committed: ${g.sha} (${g.filesChanged} files changed)`)}catch(y){let g=y instanceof Error?y.message:String(y);return n.warnings.push(`Commit failed: ${g}`),r?.(`Warning: commit failed \u2014 ${g}`),{...p,git:n}}if(!await Yt("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 En("origin",m,{cwd:o}),r?.(`Pushed branch: ${m}`)}catch(y){let g=y instanceof Error?y.message:String(y);return n.warnings.push(`Push failed: ${g}`),r?.(`Warning: push failed \u2014 ${g}`),{...p,git:n}}if(d&&a)try{let y=Zt(d),g=s.baseBranch??d.baseBranch??"main",b=s.prTitle??`feat: ${c.slice(0,72)}`,v=["## Summary",p.summary,"",`**Iterations:** ${p.iterations}`,`**Modified files:** ${p.allModifiedFiles.length}`,p.allModifiedFiles.map(k=>`- \`${k}\``).join(`
662
662
  `),"","_Automated by Alfred_"].join(`
663
- `),A=await w.createPullRequest(a,{title:b,body:S,head:m,base:g});n.pullRequest=A,r?.(`PR created: ${A.url}`)}catch(w){let g=w instanceof Error?w.message:String(w);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 Bd,qd,Hd,zd,Vd,Wd,Gd,kn,An=y(()=>{"use strict";Hr();_n();Sn();Bd=3,qd=5,Hd=3,zd=2048,Vd=1024,Wd=`You are a task planner for a multi-agent coding system.
663
+ `),A=await y.createPullRequest(a,{title:b,body:v,head:m,base:g});n.pullRequest=A,r?.(`PR created: ${A.url}`)}catch(y){let g=y instanceof Error?y.message:String(y);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 qd,Hd,zd,Vd,Wd,Gd,Xd,An,xn=w(()=>{"use strict";Wr();$n();kn();qd=3,Hd=5,zd=3,Vd=2048,Wd=1024,Gd=`You are a task planner for a multi-agent coding system.
664
664
  You receive a high-level task and a list of available coding agents.
665
665
  Your job is to decompose the task into concrete subtasks, each assigned to an agent.
666
666
 
@@ -676,7 +676,7 @@ Respond with ONLY valid JSON (no markdown fences):
676
676
  "subtasks": [
677
677
  { "id": "task-1", "agent": "<agent-name>", "prompt": "<detailed prompt>", "description": "<short description>" }
678
678
  ]
679
- }`,Gd=`You are a code review validator for a multi-agent coding system.
679
+ }`,Xd=`You are a code review validator for a multi-agent coding system.
680
680
  You receive the original task and the results from each subtask execution.
681
681
  Your job is to determine if the task was completed successfully.
682
682
 
@@ -690,9 +690,9 @@ Respond with ONLY valid JSON (no markdown fences):
690
690
  "fixTasks": [
691
691
  { "id": "fix-1", "agent": "<agent-name>", "prompt": "<detailed fix prompt>", "description": "<short description>" }
692
692
  ]
693
- }`;u(ac,"truncate");u(cc,"parseJSON");kn=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(Xd,"planSubtasks");u(Kd,"executeSubtasksParallel");u(Yd,"validateResults");u(pt,"orchestrate");u(Xs,"orchestrateWithGit")});var Ks,lc=y(()=>{"use strict";j();Hr();An();Ks=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",category:"automation",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
693
+ }`;u(cc,"truncate");u(lc,"parseJSON");An=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(Kd,"planSubtasks");u(Yd,"executeSubtasksParallel");u(Jd,"validateResults");u(gt,"orchestrate");u(Ks,"orchestrateWithGit")});var Ys,dc=w(()=>{"use strict";j();Wr();xn();Ys=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",category:"automation",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
694
694
  `);return{success:!0,data:{agents:e},display:`Available code agents:
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 Vs(o,r,{cwd:n,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 Ws(o,r,{cwd:n,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
696
696
  \`\`\`
697
697
  ${a.stdout}
698
698
  \`\`\``),a.stderr&&l.push(`**stderr:**
@@ -702,7 +702,7 @@ ${a.stderr}
702
702
  ${a.modifiedFiles.map(d=>`- ${d}`).join(`
703
703
  `)}`),{success:a.exitCode===0,data:{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,durationMs:a.durationMs,modifiedFiles:a.modifiedFiles},display:l.join(`
704
704
 
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 Xs(s,r,this.llm,{maxIterations:n,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(m)}let d=await pt(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(`
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 Ks(s,r,this.llm,{maxIterations:n,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(m)}let d=await gt(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(`
706
706
  **Modified files:**
707
707
  ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
708
708
  `)}`),e.summary&&t.push(`
@@ -711,15 +711,15 @@ ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
711
711
 
712
712
  **Git:**
713
713
  ${s.join(`
714
- `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+o}}}});var dc=y(()=>{"use strict";lc();Hr();An();_n();Sn()});var me={};ie(me,{ActivityTracker:()=>it,BackgroundTaskSkill:()=>jt,BrowserSkill:()=>Ut,CalculatorSkill:()=>$t,CalendarProvider:()=>Ae,CalendarSkill:()=>at,ClipboardSkill:()=>Dt,CodeAgentSkill:()=>Ks,CodeExecutionSkill:()=>Bs,CodeExecutor:()=>dt,ConfigureSkill:()=>Gt,ContactsProvider:()=>xe,ContactsSkill:()=>zs,CrossPlatformSkill:()=>Ft,DelegateSkill:()=>Ct,DockerSkill:()=>Br,DocumentSkill:()=>Ht,EmailProvider:()=>Oe,EmailSkill:()=>qe,FileSkill:()=>Nt,ForgeClient:()=>mt,HomeAssistantSkill:()=>Or,HttpSkill:()=>Lt,MCPClient:()=>ct,MCPManager:()=>js,MCPSkillAdapter:()=>lt,MemorySkill:()=>Rt,NoteSkill:()=>At,PluginLoader:()=>kr,ProfileSkill:()=>Pt,ProxmoxSkill:()=>Mr,ReminderSkill:()=>kt,ScheduledTaskSkill:()=>Bt,ScreenshotSkill:()=>Ot,ShellSkill:()=>It,Skill:()=>I,SkillRegistry:()=>bt,SkillSandbox:()=>_t,SystemInfoSkill:()=>vt,TTSSkill:()=>zt,TodoSkill:()=>Vt,UniFiSkill:()=>Dr,WeatherSkill:()=>xt,WebSearchSkill:()=>St,allUserIds:()=>z,createCalendarProvider:()=>Fs,createContactsProvider:()=>pn,createEmailProvider:()=>Os,createForgeClient:()=>Yt,effectiveUserId:()=>Q,gitAddRemote:()=>Gs,gitGetRemoteUrl:()=>Xt,gitInitRepo:()=>Ws,orchestrate:()=>pt,orchestrateWithGit:()=>Xs,parseRemoteUrl:()=>Kt});var de=y(()=>{"use strict";j();Le();Ki();Yi();Jo();Ji();Zi();Qi();ea();ta();sa();ra();ia();aa();ca();ma();fa();ga();ya();Ta();ba();_a();xa();Ia();Ra();Ca();Na();Da();Oa();Ua();Pa();Fa();Ba();Ga();Xa();Qa();sc();dc()});var Ys,xn=y(()=>{"use strict";Ys=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)}}});function ft(c,e){let t;if(e.platformUserId)t=c.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=c.findById(e.userId)??c.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in c?c.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in c&&(r=c.getLinkedUsers(s).map(a=>a.platformUserId));let o;try{"getProfile"in c?o=c.getProfile(s)?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone:o=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{o=Intl.DateTimeFormat().resolvedOptions().timeZone}return{context:{userId:t.platformUserId,masterUserId:s,linkedPlatformUserIds:r,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:e.conversationId??"",timezone:o},user:t,masterUserId:s,linkedPlatformUserIds:r}}var Js=y(()=>{"use strict";u(ft,"buildSkillContext")});function uc(c,e){let t=new Set(["core"]),s=!1;for(let[r,o]of Object.entries(Jd))e.has(r)&&o.test(c)&&(t.add(r),s=!0);if(!s)for(let r of e)t.add(r);return t}function mc(c,e){return c.filter(t=>e.has(t.category??"core"))}var Jd,pc=y(()=>{"use strict";Jd={productivity:/\b(todo|note|remind|calendar|termin|event|email|e-mail|mail|contact|kontakt)\b/i,information:/\b(search|such|weather|wetter|calculat|rechn|time|date|zeit|datum|uhrzeit|system.?info)\b/i,media:/\b(voice|stimme|tts|speak|sprech|sprich|screenshot|clipboard|zwischenablage|brows)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat)\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(uc,"selectCategories");u(mc,"filterSkills")});import fc from"node:fs";import hc from"node:path";var Zd,gc,Qd,yc,eu,tu,su,wc,Zs,In=y(()=>{"use strict";Ko();Js();pc();Zd=15*60*1e3,gc=50,Qd=2,yc=.85,eu=1e5,tu=2e3,su=.1,wc=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 Cs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let{user:r,masterUserId:o,linkedPlatformUserIds:n,context:i}=ft(this.users,{platformUserId:e.userId,platform:e.platform,chatId:e.chatId,chatType:e.chatType,userName:e.userName,displayName:e.displayName}),a=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),l=this.conversationManager.getHistory(a.id,200);this.conversationManager.addMessage(a.id,"user",e.text);let d,m=this.isSyntheticLabel(e.text),p=e.attachments?.some(q=>q.type==="audio")??!1,T=m&&!p;if(this.memoryRetriever&&e.text&&!T)try{d=await this.memoryRetriever.retrieve(o,e.text,15,n)}catch(q){this.logger.debug({err:q},"Hybrid memory retrieval failed")}if(!d&&this.memoryRepo&&!T)try{let q=[o,...(n??[]).filter(Y=>Y!==o)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let Y=new Set;d=[];for(let ee of q)for(let Z of await this.embeddingService.semanticSearch(ee,e.text,10))Y.has(Z.key)||(Y.add(Z.key),d.push(Z));for(let ee of q)for(let Z of this.memoryRepo.getRecentForPrompt(ee,5))Y.has(Z.key)||(Y.add(Z.key),d.push(Z))}else{let Y=new Set;d=[];for(let ee of q)for(let Z of this.memoryRepo.getRecentForPrompt(ee,20))Y.has(Z.key)||(Y.add(Z.key),d.push(Z))}}catch(q){this.logger.debug({err:q},"Memory loading failed")}d&&d.length>0&&(d=this.applyMemoryBudget(d));let w;try{"getProfile"in this.users&&(w=this.users.getProfile(o),w&&!w.displayName&&(w.displayName=r.displayName??r.username))}catch(q){this.logger.debug({err:q},"Profile loading failed")}let g=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,b=this.skillRegistry?this.skillRegistry.getAll().map(q=>q.metadata):void 0,S=b;if(b&&e.text){let q=new Set(b.map(ee=>ee.category??"core")),Y=uc(e.text,q);S=mc(b,Y)}let A=S?this.promptBuilder.buildTools(S):void 0,k=this.promptBuilder.buildSystemPrompt({memories:d,skills:S,userProfile:w}),O=this.buildActiveAgentStatus();O&&(k+=`
714
+ `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+o}}}});var uc=w(()=>{"use strict";dc();Wr();xn();$n();kn()});var pe={};ie(pe,{ActivityTracker:()=>lt,BackgroundTaskSkill:()=>qt,BrowserSkill:()=>Ft,CalculatorSkill:()=>St,CalendarProvider:()=>xe,CalendarSkill:()=>dt,ClipboardSkill:()=>Ut,CodeAgentSkill:()=>Ys,CodeExecutionSkill:()=>qs,CodeExecutor:()=>pt,ConfigureSkill:()=>Kt,ContactsProvider:()=>Ie,ContactsSkill:()=>Vs,CrossPlatformSkill:()=>Bt,DelegateSkill:()=>Nt,DockerSkill:()=>zr,DocumentSkill:()=>Vt,EmailProvider:()=>Ue,EmailSkill:()=>He,FileSkill:()=>Dt,ForgeClient:()=>ht,HomeAssistantSkill:()=>Fr,HttpSkill:()=>Mt,MCPClient:()=>ut,MCPManager:()=>Bs,MCPSkillAdapter:()=>mt,MemorySkill:()=>Lt,NoteSkill:()=>It,PluginLoader:()=>Ir,ProfileSkill:()=>jt,ProxmoxSkill:()=>Ur,ReminderSkill:()=>xt,ScheduledTaskSkill:()=>Ht,ScreenshotSkill:()=>Pt,ShellSkill:()=>Ct,Skill:()=>I,SkillRegistry:()=>$t,SkillSandbox:()=>vt,SystemInfoSkill:()=>kt,TTSSkill:()=>Wt,TodoSkill:()=>Gt,UniFiSkill:()=>Pr,WeatherSkill:()=>Rt,WebSearchSkill:()=>At,allUserIds:()=>H,createCalendarProvider:()=>js,createContactsProvider:()=>fn,createEmailProvider:()=>Us,createForgeClient:()=>Zt,effectiveUserId:()=>J,gitAddRemote:()=>Xs,gitGetRemoteUrl:()=>Yt,gitInitRepo:()=>Gs,orchestrate:()=>gt,orchestrateWithGit:()=>Ks,parseRemoteUrl:()=>Jt});var ue=w(()=>{"use strict";j();Ne();Yi();Ji();Zo();Zi();Qi();ea();ta();sa();ra();oa();aa();ca();la();pa();ha();ya();wa();ba();_a();$a();Ia();Ra();Ca();La();Ma();Oa();Ua();Pa();Fa();ja();qa();Xa();Ka();ec();rc();uc()});var Js,In=w(()=>{"use strict";Js=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)}}});function yt(c,e){let t;if(e.platformUserId)t=c.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=c.findById(e.userId)??c.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in c?c.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in c&&(r=c.getLinkedUsers(s).map(a=>a.platformUserId));let o;try{"getProfile"in c?o=c.getProfile(s)?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone:o=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{o=Intl.DateTimeFormat().resolvedOptions().timeZone}return{context:{userId:t.platformUserId,masterUserId:s,linkedPlatformUserIds:r,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:e.conversationId??"",timezone:o},user:t,masterUserId:s,linkedPlatformUserIds:r}}var Zs=w(()=>{"use strict";u(yt,"buildSkillContext")});function mc(c,e){let t=new Set(["core"]),s=!1;for(let[r,o]of Object.entries(Zd))e.has(r)&&o.test(c)&&(t.add(r),s=!0);if(!s)for(let r of e)t.add(r);return t}function pc(c,e){return c.filter(t=>e.has(t.category??"core"))}var Zd,fc=w(()=>{"use strict";Zd={productivity:/\b(todo|note|remind|calendar|termin|event|email|e-mail|mail|contact|kontakt)\b/i,information:/\b(search|such|weather|wetter|calculat|rechn|time|date|zeit|datum|uhrzeit|system.?info)\b/i,media:/\b(voice|stimme|tts|speak|sprech|sprich|screenshot|clipboard|zwischenablage|brows)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat)\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(mc,"selectCategories");u(pc,"filterSkills")});import hc from"node:fs";import gc from"node:path";var Qd,yc,eu,wc,tu,su,ru,Tc,Qs,Rn=w(()=>{"use strict";Yo();Zs();fc();Qd=15*60*1e3,yc=50,eu=2,wc=.85,tu=1e5,su=2e3,ru=.1,Tc=3,Qs=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;activeAgents=new Map;agentIdCounter=0;constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.maxHistoryMessages=e.maxHistoryMessages??100,this.promptBuilder=new Ls}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let{user:r,masterUserId:o,linkedPlatformUserIds:n,context:i}=yt(this.users,{platformUserId:e.userId,platform:e.platform,chatId:e.chatId,chatType:e.chatType,userName:e.userName,displayName:e.displayName}),a=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),l=this.conversationManager.getHistory(a.id,this.maxHistoryMessages);this.conversationManager.addMessage(a.id,"user",e.text);let d,m=this.isSyntheticLabel(e.text),p=e.attachments?.some(W=>W.type==="audio")??!1,T=m&&!p;if(this.memoryRetriever&&e.text&&!T)try{d=await this.memoryRetriever.retrieve(o,e.text,15,n)}catch(W){this.logger.debug({err:W},"Hybrid memory retrieval failed")}if(!d&&this.memoryRepo&&!T)try{let W=[o,...(n??[]).filter(X=>X!==o)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let X=new Set;d=[];for(let se of W)for(let Z of await this.embeddingService.semanticSearch(se,e.text,10))X.has(Z.key)||(X.add(Z.key),d.push(Z));for(let se of W)for(let Z of this.memoryRepo.getRecentForPrompt(se,5))X.has(Z.key)||(X.add(Z.key),d.push(Z))}else{let X=new Set;d=[];for(let se of W)for(let Z of this.memoryRepo.getRecentForPrompt(se,20))X.has(Z.key)||(X.add(Z.key),d.push(Z))}}catch(W){this.logger.debug({err:W},"Memory loading failed")}d&&d.length>0&&(d=this.applyMemoryBudget(d));let y;try{"getProfile"in this.users&&(y=this.users.getProfile(o),y&&!y.displayName&&(y.displayName=r.displayName??r.username))}catch(W){this.logger.debug({err:W},"Profile loading failed")}let g=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,b=this.skillRegistry?this.skillRegistry.getAll().map(W=>W.metadata):void 0,v=b;if(b&&e.text){let W=new Set(b.map(se=>se.category??"core")),X=mc(e.text,W);v=pc(b,X)}let A=v?this.promptBuilder.buildTools(v):void 0,k=this.promptBuilder.buildSystemPrompt({memories:d,skills:v,userProfile:y}),O=this.buildActiveAgentStatus();O&&(k+=`
715
715
 
716
- `+O);let L=this.promptBuilder.buildMessages(l),K=this.collapseRepeatedToolErrors(L),Pe=await this.buildUserContent(e,t);K.push({role:"user",content:Pe});let Ne=A?ke(JSON.stringify(A)):0,Me=1,se=this.trimToContextWindow(k,K,Ne,Me),P,J=0,ge=Date.now(),N="",B=0,ye=[];for(t?.("Thinking...");;){J>0&&this.compressToolLoop(se,k,Ne);try{P=await this.llm.complete({messages:se,system:k,tools:A&&A.length>0?A:void 0})}catch(we){if((we instanceof Error?we.message:String(we)).includes("prompt is too long")&&Me>.3){Me*=.5,this.logger.warn({budgetMultiplier:Me},"Prompt too long, retrimming with reduced budget"),se=this.trimToContextWindow(k,K,Ne,Me);continue}throw we}if(!P.toolCalls||P.toolCalls.length===0)break;let q=Date.now()-ge;if(q>=Zd){let we=Math.round(q/6e4);this.logger.warn({iteration:J,elapsedMin:we,pendingToolCalls:P.toolCalls.length},"Tool loop timeout reached"),P=await this.abortToolLoop(se,P,a.id,k,`Das Zeitlimit von ${we} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(J>=gc){this.logger.warn({iteration:J,pendingToolCalls:P.toolCalls.length},"Tool loop iteration cap reached"),P=await this.abortToolLoop(se,P,a.id,k,`Das Iterationslimit von ${gc} Tool-Aufrufen wurde erreicht.`);break}J++,this.logger.info({iteration:J,toolCalls:P.toolCalls.length},"Processing tool calls");let Y=[];P.content&&Y.push({type:"text",text:P.content});for(let we of P.toolCalls)Y.push({type:"tool_use",id:we.id,name:we.name,input:we.input});se.push({role:"assistant",content:Y});let ee=await this.executeToolCallsParallel(P.toolCalls,{...i,conversationId:a.id,timezone:g},t),Z=ee.blocks;ee.attachments.length>0&&ye.push(...ee.attachments),this.conversationManager.addMessage(a.id,"assistant",P.content??"",JSON.stringify(P.toolCalls)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(Z));let gt=this.buildErrorSignature(Z);if(gt){if(gt===N?B++:(B=1,N=gt),B>=Qd){this.logger.warn({iteration:J,consecutiveErrors:B,errorSignature:gt},"Tool loop aborted: same error repeated consecutively"),P=await this.abortToolLoop(se,P,a.id,k,`Der gleiche Tool-Fehler ist ${B}x hintereinander aufgetreten: "${N.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else B=0,N="";se.push({role:"user",content:Z}),t?.("Thinking...")}let X=P.content;if(!X)for(let q=se.length-1;q>=0;q--){let Y=se[q];if(Y.role==="assistant"&&Array.isArray(Y.content)){let ee=Y.content.find(Z=>Z.type==="text");if(ee&&"text"in ee&&ee.text){X=ee.text;break}}}X||(X="(no response)"),this.conversationManager.addMessage(a.id,"assistant",X),this.activeLearning&&this.activeLearning.onMessageProcessed(o,e.text,X);let Zt=Date.now()-s;return this.logger.info({duration:Zt,tokens:P.usage,stopReason:P.stopReason,toolIterations:J},"Message processed"),{text:X,attachments:ye.length>0?ye: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+=`
716
+ `+O);let L=this.promptBuilder.buildMessages(l),K=this.collapseRepeatedToolErrors(L),Fe=await this.buildUserContent(e,t);K.push({role:"user",content:Fe});let Me=A?Ae(JSON.stringify(A)):0,De=1,ee=this.trimToContextWindow(k,K,Me,De),U,Y=0,ye=Date.now(),N="",B=0,_e=0,te=0,Ke=[];for(t?.("Thinking...");;){Y>0&&this.compressToolLoop(ee,k,Me);try{U=await this.llm.complete({messages:ee,system:k,tools:A&&A.length>0?A:void 0}),_e+=U.usage?.inputTokens??0,te+=U.usage?.outputTokens??0}catch(we){if((we instanceof Error?we.message:String(we)).includes("prompt is too long")&&De>.3){De*=.5,this.logger.warn({budgetMultiplier:De},"Prompt too long, retrimming with reduced budget"),ee=this.trimToContextWindow(k,K,Me,De);continue}throw we}if(!U.toolCalls||U.toolCalls.length===0)break;let W=Date.now()-ye;if(W>=Qd){let we=Math.round(W/6e4);this.logger.warn({iteration:Y,elapsedMin:we,pendingToolCalls:U.toolCalls.length},"Tool loop timeout reached"),U=await this.abortToolLoop(ee,U,a.id,k,`Das Zeitlimit von ${we} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(Y>=yc){this.logger.warn({iteration:Y,pendingToolCalls:U.toolCalls.length},"Tool loop iteration cap reached"),U=await this.abortToolLoop(ee,U,a.id,k,`Das Iterationslimit von ${yc} Tool-Aufrufen wurde erreicht.`);break}Y++,this.logger.info({iteration:Y,toolCalls:U.toolCalls.length},"Processing tool calls");let X=[];U.content&&X.push({type:"text",text:U.content});for(let we of U.toolCalls)X.push({type:"tool_use",id:we.id,name:we.name,input:we.input});ee.push({role:"assistant",content:X});let se=await this.executeToolCallsParallel(U.toolCalls,{...i,conversationId:a.id,timezone:g},t),Z=se.blocks;se.attachments.length>0&&Ke.push(...se.attachments),this.conversationManager.addMessage(a.id,"assistant",U.content??"",JSON.stringify(U.toolCalls)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(Z));let Ye=this.buildErrorSignature(Z);if(Ye){if(Ye===N?B++:(B=1,N=Ye),B>=eu){this.logger.warn({iteration:Y,consecutiveErrors:B,errorSignature:Ye},"Tool loop aborted: same error repeated consecutively"),U=await this.abortToolLoop(ee,U,a.id,k,`Der gleiche Tool-Fehler ist ${B}x hintereinander aufgetreten: "${N.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else B=0,N="";ee.push({role:"user",content:Z}),t?.("Thinking...")}let le=U.content;if(!le)for(let W=ee.length-1;W>=0;W--){let X=ee[W];if(X.role==="assistant"&&Array.isArray(X.content)){let se=X.content.find(Z=>Z.type==="text");if(se&&"text"in se&&se.text){le=se.text;break}}}le||(le="(no response)"),this.conversationManager.addMessage(a.id,"assistant",le),this.activeLearning&&this.activeLearning.onMessageProcessed(o,e.text,le);let fr=Date.now()-s;return this.logger.info({duration:fr,tokens:U.usage,totalTokens:{inputTokens:_e,outputTokens:te},stopReason:U.stopReason,toolIterations:Y},"Message processed"),{text:le,attachments:Ke.length>0?Ke: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+=`
717
717
 
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(()=>(de(),me));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)>=su));let r=0,o=[];for(let n of s){let i=ke(`[${n.category}] ${n.key}: ${n.value}`);if(r+i>tu)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*yc);if(ke(t)+s+e.reduce((g,b)=>g+Ls(b),0)<=o)return;let a=[];for(let g=0;g<e.length-1;g++){let b=e[g],S=e[g+1];b.role==="assistant"&&Array.isArray(b.content)&&b.content.some(A=>A.type==="tool_use")&&S.role==="user"&&Array.isArray(S.content)&&S.content.some(A=>A.type==="tool_result")&&a.push({start:g,end:g+1})}if(a.length<=wc)return;let l=a.length-wc,d=a.slice(0,l),m=[];for(let g of d){let b=e[g.start],S=[];if(Array.isArray(b.content))for(let O of b.content)O.type==="tool_use"&&S.push(O.name);let A=e[g.end],k="ok";Array.isArray(A.content)&&A.content.some(L=>L.type==="tool_result"&&L.is_error)&&(k="error"),m.push(`- ${S.join(", ")}: ${k}`)}let p=d[0].start,w=d[d.length-1].end-p+1;e.splice(p,w,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
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(()=>(ue(),pe));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)>=ru));let r=0,o=[];for(let n of s){let i=Ae(`[${n.category}] ${n.key}: ${n.value}`);if(r+i>su)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*wc);if(Ae(t)+s+e.reduce((g,b)=>g+Ns(b),0)<=o)return;let a=[];for(let g=0;g<e.length-1;g++){let b=e[g],v=e[g+1];b.role==="assistant"&&Array.isArray(b.content)&&b.content.some(A=>A.type==="tool_use")&&v.role==="user"&&Array.isArray(v.content)&&v.content.some(A=>A.type==="tool_result")&&a.push({start:g,end:g+1})}if(a.length<=Tc)return;let l=a.length-Tc,d=a.slice(0,l),m=[];for(let g of d){let b=e[g.start],v=[];if(Array.isArray(b.content))for(let O of b.content)O.type==="tool_use"&&v.push(O.name);let A=e[g.end],k="ok";Array.isArray(A.content)&&A.content.some(L=>L.type==="tool_result"&&L.is_error)&&(k="error"),m.push(`- ${v.join(", ")}: ${k}`)}let p=d[0].start,y=d[d.length-1].end-p+1;e.splice(p,y,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
720
720
  ${m.join(`
721
721
  `)}
722
- ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:w-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let o=this.llm.getContextWindow(),n=Math.floor(o.maxInputTokens*yc*r),i=ke(e)+s,a=t[t.length-1],l=Ls(a),m=i+l+200+500,p=n-m;if(p<=0)return this.logger.warn({maxInputTokens:n,systemTokens:i,latestTokens:l},"Context window very tight, sending only latest message"),[a];let T=t.slice(0,-1),w=this.groupToolPairs(T),g=[];for(let A=w.length-1;A>=0;A--){let k=w[A].reduce((O,L)=>O+Ls(L),0);if(k>p)break;p-=k,g.unshift(w[A])}let b=g.flat(),S=T.length-b.length;if(S>0){this.logger.info({trimmedCount:S,totalMessages:t.length,maxInputTokens:n},"Trimmed conversation history to fit context window");let A=T.slice(0,T.length-b.length),k=this.summarizeTrimmedMessages(A);b.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${S} messages were trimmed to fit the context window:
722
+ ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:y-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let o=this.llm.getContextWindow(),n=Math.floor(o.maxInputTokens*wc*r),i=Ae(e)+s,a=t[t.length-1],l=Ns(a),m=i+l+200+500,p=n-m;if(p<=0)return this.logger.warn({maxInputTokens:n,systemTokens:i,latestTokens:l},"Context window very tight, sending only latest message"),[a];let T=t.slice(0,-1),y=this.groupToolPairs(T),g=[];for(let A=y.length-1;A>=0;A--){let k=y[A].reduce((O,L)=>O+Ns(L),0);if(k>p)break;p-=k,g.unshift(y[A])}let b=g.flat(),v=T.length-b.length;if(v>0){this.logger.info({trimmedCount:v,totalMessages:t.length,maxInputTokens:n},"Trimmed conversation history to fit context window");let A=T.slice(0,T.length-b.length),k=this.summarizeTrimmedMessages(A);b.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${v} messages were trimmed to fit the context window:
723
723
  ${k}
724
724
 
725
725
  The conversation continues below with the most recent messages.]`})}return b.push(a),this.promptBuilder.sanitizeToolMessages(b)}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(`
@@ -727,19 +727,19 @@ The conversation continues below with the most recent messages.]`})}return b.pus
727
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}
728
728
 
729
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"})]
730
- [Saved to: ${a}]`;if(l&&i.data.length<=eu){let m=i.data.toString("utf-8");d+=`
730
+ [Saved to: ${a}]`;if(l&&i.data.length<=tu){let m=i.data.toString("utf-8");d+=`
731
731
  [File content]:
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??hc.resolve("./data/inbox");try{fc.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=hc.join(t,n);try{return fc.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 Qs,Rn=y(()=>{"use strict";Qs=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 er,Cn=y(()=>{"use strict";er=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 tr,Ln=y(()=>{"use strict";tr=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 sr,Nn=y(()=>{"use strict";sr=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 rr,Mn=y(()=>{"use strict";rr=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 or,Dn=y(()=>{"use strict";or=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(`
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??gc.resolve("./data/inbox");try{hc.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=gc.join(t,n);try{return hc.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 er,Cn=w(()=>{"use strict";er=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 tr,Ln=w(()=>{"use strict";tr=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 sr,Nn=w(()=>{"use strict";sr=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 rr,Mn=w(()=>{"use strict";rr=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 or,Dn=w(()=>{"use strict";or=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 nr,On=w(()=>{"use strict";nr=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(`
733
733
 
734
- `);if(p>0)l=d+p;else{let w=m.lastIndexOf(". ");w>0&&(l=d+w+1)}let T=e.slice(a,l).trim();T&&i.push(T),a=l-n}return i.filter(l=>l.length>0)}}});var nr,On=y(()=>{"use strict";Js();nr=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,o,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=o,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{context:r}=ft(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,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}
734
+ `);if(p>0)l=d+p;else{let y=m.lastIndexOf(". ");y>0&&(l=d+y+1)}let T=e.slice(a,l).trim();T&&i.push(T),a=l-n}return i.filter(l=>l.length>0)}}});var ir,Un=w(()=>{"use strict";Zs();ir=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,o,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=o,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{context:r}=yt(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,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}
735
735
 
736
736
  Result: ${n.display??JSON.stringify(n.data)}`:`\u274C Background task failed: ${e.description}
737
737
 
738
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}
739
739
 
740
- Error: ${s}`)}}}});import ru from"node:crypto";var ir,Un=y(()=>{"use strict";Js();ir=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,o,n,i,a,l){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=o,this.users=n,this.logger=i,this.pipeline=a,this.formatter=l}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-${ru.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{context:a}=ft(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),l=await this.skillSandbox.execute(n,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
740
+ Error: ${s}`)}}}});import ou from"node:crypto";var ar,Pn=w(()=>{"use strict";Zs();ar=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,o,n,i,a,l){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=o,this.users=n,this.logger=i,this.pipeline=a,this.formatter=l}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-${ou.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{context:a}=yt(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),l=await this.skillSandbox.execute(n,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
741
741
 
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 Pn(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of ou)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of nu)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 ou,nu,Fn=y(()=>{"use strict";ou=[/^(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],nu=[{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(Pn,"scanSignal")});var iu,au,ar,jn=y(()=>{"use strict";iu=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],au=`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 Fn(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of nu)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of iu)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 nu,iu,jn=w(()=>{"use strict";nu=[/^(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],iu=[{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(Fn,"scanSignal")});var au,cu,cr,Bn=w(()=>{"use strict";au=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],cu=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
743
743
 
744
744
  Rules:
745
745
  - Only extract information the user STATES about themselves
@@ -759,65 +759,65 @@ Extract memories from this conversation:
759
759
  User: {USER_MESSAGE}
760
760
  Assistant: {ASSISTANT_RESPONSE}
761
761
 
762
- Return ONLY a valid JSON array, no explanation:`,ar=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=au.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 iu.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var cr,Bn=y(()=>{"use strict";Fn();jn();cr=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 ar(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Pn(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 cu,lu,du,uu,lr,qn=y(()=>{"use strict";cu=Math.LN2,lu=.3,du=.7,uu=3,lr=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 S of await this.embeddingService.semanticSearch(b,t,30))g.has(S.key)||(g.add(S.key),a.push(S));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],S=m>0?1-g/m:0,A=l?lu:1,k=this.applyBoosts(S*A,b);d.set(b.key,{memory:{key:b.key,value:b.value,category:b.category,type:b.type,score:k},score:k}),this.memoryRepo.recordAccess(b.id)}if(l)for(let g of a){let b=g.score*du,S=d.get(g.key);if(S)S.score+=b,S.memory.score=S.score;else{let A=this.memoryRepo.recall(e,g.key),k=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:k},score:k}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((g,b)=>b.score-g.score),T=new Map,w=[];for(let{memory:g}of p){let b=T.get(g.type)||0;if(!(b>=uu)&&(T.set(g.type,b+1),w.push(g),w.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:w.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),w}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(-cu*o/2592e6);s*=n}return s}}});import{EventEmitter as mu}from"node:events";var oe,Ue=y(()=>{"use strict";oe=class extends mu{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(`
762
+ Return ONLY a valid JSON array, no explanation:`,cr=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=cu.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 au.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var lr,qn=w(()=>{"use strict";jn();Bn();lr=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 cr(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Fn(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 lu,du,uu,mu,dr,Hn=w(()=>{"use strict";lu=Math.LN2,du=.3,uu=.7,mu=3,dr=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 v of await this.embeddingService.semanticSearch(b,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 b=i[g],v=m>0?1-g/m:0,A=l?du:1,k=this.applyBoosts(v*A,b);d.set(b.key,{memory:{key:b.key,value:b.value,category:b.category,type:b.type,score:k},score:k}),this.memoryRepo.recordAccess(b.id)}if(l)for(let g of a){let b=g.score*uu,v=d.get(g.key);if(v)v.score+=b,v.memory.score=v.score;else{let A=this.memoryRepo.recall(e,g.key),k=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:k},score:k}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((g,b)=>b.score-g.score),T=new Map,y=[];for(let{memory:g}of p){let b=T.get(g.type)||0;if(!(b>=mu)&&(T.set(g.type,b+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(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(-lu*o/2592e6);s*=n}return s}}});import{EventEmitter as pu}from"node:events";var oe,Pe=w(()=>{"use strict";oe=class extends pu{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(`
763
763
 
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 pu,InputFile as Hn}from"grammy";function Tc(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var Vr,Ec=y(()=>{"use strict";Ue();u(Tc,"mapParseMode");Vr=class extends oe{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new pu(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:Tc(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:Tc(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 Hn(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 Hn(t,s),{caption:r});return String(o.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Hn(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 fu,GatewayIntentBits as Wr,Events as zn}from"discord.js";var Gr,bc=y(()=>{"use strict";Ue();Gr=class extends oe{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new fu({intents:[Wr.Guilds,Wr.GuildMessages,Wr.MessageContent,Wr.DirectMessages]}),this.client.on(zn.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(zn.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(zn.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 Xr,_c=y(()=>{"use strict";Ue();Xr=class extends oe{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(),T=Buffer.from(p);return{type:t,mimeType:o,fileName:i,size:n??T.length,data:T}}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 Kr,$c=y(()=>{"use strict";Ue();Kr=class extends oe{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 Yr,vc=y(()=>{"use strict";Ue();Yr=class extends oe{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 Vn from"node:readline";var Jr,Sc=y(()=>{"use strict";Ue();Jr=class extends oe{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Vn.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 fu,InputFile as zn}from"grammy";function bc(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var Xr,Ec=w(()=>{"use strict";Pe();u(bc,"mapParseMode");Xr=class extends oe{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new fu(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:bc(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:bc(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 zn(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 zn(t,s),{caption:r});return String(o.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new zn(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 hu,GatewayIntentBits as Kr,Events as Vn}from"discord.js";var Yr,_c=w(()=>{"use strict";Pe();Yr=class extends oe{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new hu({intents:[Kr.Guilds,Kr.GuildMessages,Kr.MessageContent,Kr.DirectMessages]}),this.client.on(Vn.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(Vn.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Vn.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,$c=w(()=>{"use strict";Pe();Jr=class extends oe{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(),T=Buffer.from(p);return{type:t,mimeType:o,fileName:i,size:n??T.length,data:T}}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 Zr,vc=w(()=>{"use strict";Pe();Zr=class extends oe{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,Sc=w(()=>{"use strict";Pe();Qr=class extends oe{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 Wn from"node:readline";var eo,kc=w(()=>{"use strict";Pe();eo=class extends oe{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Wn.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
765
765
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
766
766
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
767
767
  Goodbye!
768
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(`
769
769
  Alfred: ${t}
770
- `),this.prompt(),r}async editMessage(e,t,s,r){Vn.clearLine(process.stdout,0),Vn.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import hu from"node:http";import gu from"node:crypto";var Zr,kc=y(()=>{"use strict";Ue();Zr=class extends oe{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=hu.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-${gu.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}
770
+ `),this.prompt(),r}async editMessage(e,t,s,r){Wn.clearLine(process.stdout,0),Wn.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import gu from"node:http";import yu from"node:crypto";var to,Ac=w(()=>{"use strict";Pe();to=class extends oe{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=gu.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-${yu.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}
771
771
  data: ${JSON.stringify(s)}
772
772
 
773
- `)}}});var ze={};ie(ze,{CLIAdapter:()=>Jr,DiscordAdapter:()=>Gr,HttpAdapter:()=>Zr,MatrixAdapter:()=>Xr,MessagingAdapter:()=>oe,SignalAdapter:()=>Yr,TelegramAdapter:()=>Vr,WhatsAppAdapter:()=>Kr});var Ve=y(()=>{"use strict";Ue();Ec();bc();_c();$c();vc();Sc();kc()});import Qr from"node:fs";import eo from"node:path";import yu from"js-yaml";var ht,Ac=y(()=>{"use strict";Do();Po();Be();Ko();Sr();de();xn();In();Rn();Cn();Ln();Nn();Mn();Dn();On();Un();Bn();qn();ht=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new sr;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=ps("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new tt(this.config.storage.path);let e=this.database.getDb(),t=new fs(e),s=new hs(e);this.userRepo=s;let r=new st(e),o=new gs(e),n=new ys(e),i=new ws(e),a=new Ts(e),l=new Es(e),d=new bs(e),m=new _s(e);this.logger.info("Storage initialized");let p=new Ms,T=this.loadSecurityRules();p.loadRules(T);let w=new Ds(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:T.length},"Security engine initialized");let g=Xo(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 rr(g,a,this.logger.child({component:"embeddings"})),S=this.config.activeLearning?.enabled!==!1,A,k;S&&(A=new cr({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}),k=new lr(o,this.logger.child({component:"memory-retriever"}),b),this.logger.info("Active learning & memory retriever initialized"));let O=new _t(this.logger.child({component:"sandbox"})),L=this.skillRegistry=new bt;L.register(new $t),L.register(new vt),L.register(new St(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),L.register(new kt(n)),L.register(new At(i));let K=new vs(e);if(L.register(new Vt(K)),L.register(new xt),L.register(new It),L.register(new Rt(o,b)),L.register(new Ct(g,L,O,w)),this.config.email?.accounts?.length){let N=new Map;for(let B of this.config.email.accounts)try{B.provider==="microsoft"&&!B.microsoft?.clientId&&this.config.calendar?.microsoft&&(B.microsoft={...this.config.calendar.microsoft});let ye=await Os(B);N.set(B.name,ye),this.logger.info({account:B.name,provider:B.provider??"imap-smtp"},"Email account initialized")}catch(ye){this.logger.warn({err:ye,account:B.name},"Email account initialization failed, skipping")}L.register(N.size>0?new qe(N):new qe)}else L.register(new qe);L.register(new Lt),L.register(new Nt);let Pe=new Gt;Pe.setReloadCallback(N=>this.reloadService(N)),L.register(Pe),L.register(new Dt),L.register(new Ot),L.register(new Ut),L.register(new Pt(s)),L.register(new Ft(s,l,this.adapters,(N,B)=>t.findByPlatformAndUser(N,B))),L.register(new jt(d)),L.register(new Bt(m));let Ne=new $s(e),Me=new or(Ne,b,this.logger.child({component:"documents"}));L.register(new Ht(Ne,Me,b));let se;if(this.config.calendar)try{let N=await Fs(this.config.calendar);se=new at(N),L.register(se),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(N){this.logger.warn({err:N},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=se,this.config.mcp?.servers?.length){let{MCPManager:N}=await Promise.resolve().then(()=>(de(),me));this.mcpManager=new N(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let B of this.mcpManager.getSkills())L.register(B);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},g)),this.logger.info({agents:this.config.codeAgents.agents.map(B=>B.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:N,createContactsProvider:B}=await Promise.resolve().then(()=>(de(),me)),ye=await B(this.config.contacts);L.register(new N(ye)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(N){this.logger.warn({err:N},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:N}=await Promise.resolve().then(()=>(de(),me));L.register(new N(this.config.docker)),this.logger.info("Docker skill enabled")}this.logger.info({skills:L.getAll().map(N=>N.metadata.name)},"Skills registered");let P;if(this.config.speech?.apiKey&&(P=new er(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let N=new tr(this.config.speech,this.logger.child({component:"tts"}));L.register(new zt(N)),this.logger.info("Text-to-speech skill registered")}let J=new Ys(t),ge=eo.resolve(eo.dirname(this.config.storage.path),"inbox");this.pipeline=new Zs({llm:g,conversationManager:J,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:L,skillSandbox:O,securityManager:w,memoryRepo:o,speechTranscriber:P,inboxPath:ge,embeddingService:b,activeLearning:A,memoryRetriever:k}),this.reminderScheduler=new Qs(n,async(N,B,ye)=>{let X=this.adapters.get(N);X?await X.sendMessage(B,ye):this.logger.warn({platform:N,chatId:B},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(N=>s.getMasterUserId(N),"getMasterUserId"),getLinkedUsers:u(N=>s.getLinkedUsers(N),"getLinkedUsers"),findConversation:u((N,B)=>t.findByPlatformAndUser(N,B),"findConversation")}),this.backgroundTaskRunner=new nr(L,O,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new ir(m,L,O,g,this.adapters,s,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(()=>(Ve(),ze));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(()=>(Ve(),ze));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(()=>(Ve(),ze));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(()=>(Ve(),ze));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(()=>(Ve(),ze));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(()=>(Ve(),ze)),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(()=>(Ve(),ze)),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{No();let t=new ae().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(de(),me));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(()=>(de(),me));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(()=>(de(),me));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(()=>(de(),me)),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(()=>(de(),me));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=eo.resolve(this.config.security.rulesPath),t=[];if(!Qr.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Qr.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Qr.readdirSync(e).filter(o=>o.endsWith(".yml")||o.endsWith(".yaml"));for(let o of r)try{let n=eo.join(e,o),i=Qr.readFileSync(n,"utf-8"),a=yu.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 xc=y(()=>{"use strict"});var Wn=y(()=>{"use strict";Ac();In();xn();Rn();Cn();Ln();Nn();Mn();On();Un();Js();Dn();Bn();qn();jn();xc();Fn()});var Ic={};ie(Ic,{startCommand:()=>wu});async function wu(){let c=new ae,e;try{e=c.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let t=ps("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new ht(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 Rc=y(()=>{"use strict";Be();Do();Wn();u(wu,"startCommand")});var Lc={};ie(Lc,{chatCommand:()=>bu});import Cc from"node:http";import dr from"node:readline";function Tu(c,e){return new Promise(t=>{let s=Cc.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 Eu(c,e){let t=dr.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
773
+ `)}}});var Ve={};ie(Ve,{CLIAdapter:()=>eo,DiscordAdapter:()=>Yr,HttpAdapter:()=>to,MatrixAdapter:()=>Jr,MessagingAdapter:()=>oe,SignalAdapter:()=>Qr,TelegramAdapter:()=>Xr,WhatsAppAdapter:()=>Zr});var We=w(()=>{"use strict";Pe();Ec();_c();$c();vc();Sc();kc();Ac()});import so from"node:fs";import ro from"node:path";import wu from"js-yaml";var wt,xc=w(()=>{"use strict";Oo();Fo();qe();Yo();xr();ue();In();Rn();Cn();Ln();Nn();Mn();Dn();On();Un();Pn();qn();Hn();wt=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new rr;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=fs("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ot(this.config.storage.path);let e=this.database.getDb(),t=new hs(e),s=new gs(e);this.userRepo=s;let r=new nt(e),o=new ys(e),n=new ws(e),i=new Ts(e),a=new bs(e),l=new Es(e),d=new _s(e),m=new $s(e);this.logger.info("Storage initialized");let p=new Ds,T=this.loadSecurityRules();p.loadRules(T);let y=new Os(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:T.length},"Security engine initialized");let g=Ko(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 or(g,a,this.logger.child({component:"embeddings"})),v=this.config.activeLearning?.enabled!==!1,A,k;v&&(A=new lr({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}),k=new dr(o,this.logger.child({component:"memory-retriever"}),b),this.logger.info("Active learning & memory retriever initialized"));let O=new vt(this.logger.child({component:"sandbox"})),L=this.skillRegistry=new $t;L.register(new St),L.register(new kt),L.register(new At(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),L.register(new xt(n)),L.register(new It(i));let K=new Ss(e);if(L.register(new Gt(K)),L.register(new Rt),L.register(new Ct),L.register(new Lt(o,b)),L.register(new Nt(g,L,O,y)),this.config.email?.accounts?.length){let N=new Map;for(let B of this.config.email.accounts)try{B.provider==="microsoft"&&!B.microsoft?.clientId&&this.config.calendar?.microsoft&&(B.microsoft={...this.config.calendar.microsoft});let _e=await Us(B);N.set(B.name,_e),this.logger.info({account:B.name,provider:B.provider??"imap-smtp"},"Email account initialized")}catch(_e){this.logger.warn({err:_e,account:B.name},"Email account initialization failed, skipping")}L.register(N.size>0?new He(N):new He)}else L.register(new He);L.register(new Mt),L.register(new Dt);let Fe=new Kt;Fe.setReloadCallback(N=>this.reloadService(N)),L.register(Fe),L.register(new Ut),L.register(new Pt),L.register(new Ft),L.register(new jt(s)),L.register(new Bt(s,l,this.adapters,(N,B)=>t.findByPlatformAndUser(N,B))),L.register(new qt(d)),L.register(new Ht(m));let Me=new vs(e),De=new nr(Me,b,this.logger.child({component:"documents"}));L.register(new Vt(Me,De,b));let ee;if(this.config.calendar)try{let N=await js(this.config.calendar);ee=new dt(N),L.register(ee),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(N){this.logger.warn({err:N},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=ee,this.config.mcp?.servers?.length){let{MCPManager:N}=await Promise.resolve().then(()=>(ue(),pe));this.mcpManager=new N(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let B of this.mcpManager.getSkills())L.register(B);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},g)),this.logger.info({agents:this.config.codeAgents.agents.map(B=>B.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:N,createContactsProvider:B}=await Promise.resolve().then(()=>(ue(),pe)),_e=await B(this.config.contacts);L.register(new N(_e)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(N){this.logger.warn({err:N},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:N}=await Promise.resolve().then(()=>(ue(),pe));L.register(new N(this.config.docker)),this.logger.info("Docker skill enabled")}this.logger.info({skills:L.getAll().map(N=>N.metadata.name)},"Skills registered");let U;if(this.config.speech?.apiKey&&(U=new tr(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let N=new sr(this.config.speech,this.logger.child({component:"tts"}));L.register(new Wt(N)),this.logger.info("Text-to-speech skill registered")}let Y=new Js(t),ye=ro.resolve(ro.dirname(this.config.storage.path),"inbox");this.pipeline=new Qs({llm:g,conversationManager:Y,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:L,skillSandbox:O,securityManager:y,memoryRepo:o,speechTranscriber:U,inboxPath:ye,embeddingService:b,activeLearning:A,memoryRetriever:k,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100}),this.reminderScheduler=new er(n,async(N,B,_e)=>{let te=this.adapters.get(N);te?await te.sendMessage(B,_e):this.logger.warn({platform:N,chatId:B},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(N=>s.getMasterUserId(N),"getMasterUserId"),getLinkedUsers:u(N=>s.getLinkedUsers(N),"getLinkedUsers"),findConversation:u((N,B)=>t.findByPlatformAndUser(N,B),"findConversation")}),this.backgroundTaskRunner=new ir(L,O,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new ar(m,L,O,g,this.adapters,s,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(()=>(We(),Ve));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(()=>(We(),Ve));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(()=>(We(),Ve));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(()=>(We(),Ve));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(()=>(We(),Ve));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(()=>(We(),Ve)),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(()=>(We(),Ve)),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{Mo();let t=new ae().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(ue(),pe));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(()=>(ue(),pe));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(()=>(ue(),pe));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(()=>(ue(),pe)),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(()=>(ue(),pe));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=ro.resolve(this.config.security.rulesPath),t=[];if(!so.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!so.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=so.readdirSync(e).filter(o=>o.endsWith(".yml")||o.endsWith(".yaml"));for(let o of r)try{let n=ro.join(e,o),i=so.readFileSync(n,"utf-8"),a=wu.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 Ic=w(()=>{"use strict"});var Gn=w(()=>{"use strict";xc();Rn();In();Cn();Ln();Nn();Mn();Dn();Un();Pn();Zs();On();qn();Hn();Bn();Ic();jn()});var Rc={};ie(Rc,{startCommand:()=>Tu});async function Tu(){let c=new ae,e;try{e=c.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let t=fs("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new wt(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 Cc=w(()=>{"use strict";qe();Oo();Gn();u(Tu,"startCommand")});var Nc={};ie(Nc,{chatCommand:()=>_u});import Lc from"node:http";import ur from"node:readline";function bu(c,e){return new Promise(t=>{let s=Lc.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 Eu(c,e){let t=ur.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
774
774
  Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
775
775
  `),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
776
776
  Goodbye!
777
- `),t.close(),process.exit(0));let o=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),n=Cc.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(`
777
+ `),t.close(),process.exit(0));let o=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),n=Lc.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(`
778
778
 
779
779
  `);a=d.pop()??"";for(let m of d){let p=m.split(`
780
- `).find(T=>T.startsWith("data: "));if(p)try{let T=JSON.parse(p.slice(6));switch(T.type){case"status":dr.clearLine(process.stdout,0),dr.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${T.text??""}`);break;case"response":dr.clearLine(process.stdout,0),dr.cursorTo(process.stdout,0),process.stdout.write(`
780
+ `).find(T=>T.startsWith("data: "));if(p)try{let T=JSON.parse(p.slice(6));switch(T.type){case"status":ur.clearLine(process.stdout,0),ur.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${T.text??""}`);break;case"response":ur.clearLine(process.stdout,0),ur.cursorTo(process.stdout,0),process.stdout.write(`
781
781
  Alfred: ${T.text??""}
782
- `);break;case"attachment":{let w=T.fileName??T.attachmentType??"file";process.stdout.write(`[Attachment: ${w}]
782
+ `);break;case"attachment":{let y=T.fileName??T.attachmentType??"file";process.stdout.write(`[Attachment: ${y}]
783
783
  `);break}case"done":t.prompt();break;case"error":process.stdout.write(`
784
784
  Error: ${T.text??"Unknown error"}
785
785
  `),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let l=a.split(`
786
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(`
787
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 bu(c){let e=new ae,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 Tu(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Eu(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 ht(t);try{await n.initialize(),await n.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var Nc=y(()=>{"use strict";Be();Wn();u(Tu,"checkHealth");u(Eu,"startClientMode");u(bu,"chatCommand")});var Oc={};ie(Oc,{setupCommand:()=>Lu});import{createInterface as _u}from"node:readline/promises";import{stdin as $u,stdout as vu}from"node:process";import{execFileSync as Su}from"node:child_process";import ce from"node:fs";import ku from"node:os";import he from"node:path";import Gn from"js-yaml";function D(c){return`${to}${c}${v}`}function Iu(c){return`${M}${c}${v}`}function fe(c){return`${so}${c}${v}`}function Dc(c){return`${Au}${c}${v}`}function R(c){return`${W}${c}${v}`}function E(c){return`${Ge}${c}${v}`}function ue(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Ru(c){let e=process.platform==="win32",t=e?"where":"which";try{let o=Su(t,[c],{stdio:"pipe"}).toString().trim();if(o)return o.split(/\r?\n/)[0]}catch{}let s=ku.homedir(),r=e?[he.join(s,".local","bin",`${c}.exe`),he.join(s,"AppData","Roaming","npm",`${c}.cmd`),he.join(s,"AppData","Roaming","npm",`${c}`)]:[he.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,he.join(s,".npm-global","bin",c)];for(let o of r)try{return ce.accessSync(o,ce.constants.X_OK),o}catch{}return null}function Cu(c){let e={},t={},s=!1,r=!1,o=30,n=he.join(c,"config","default.yml");if(ce.existsSync(n))try{let p=Gn.load(ce.readFileSync(n,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=he.join(c,".env");if(ce.existsSync(i))try{let p=ce.readFileSync(i,"utf-8").split(`
789
- `);for(let T of p){let w=T.trim();if(!w||w.startsWith("#"))continue;let g=w.indexOf("=");g>0&&(t[w.slice(0,g)]=w.slice(g+1))}}catch{}let a=he.join(c,"config","rules","default-rules.yml");if(ce.existsSync(a))try{let p=Gn.load(ce.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 w=p.rules.find(g=>g.id==="rate-limit-write");w?.rateLimit?.maxInvocations&&(o=w.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 Lu(){let c=_u({input:$u,output:vu}),e=process.cwd(),t=Cu(e),s=Object.keys(t.config).length>0;try{Nu(),console.log(s?`${so}Existing configuration found \u2014 press Enter to keep current values.${v}
790
- ${Ge}Only change what you need to update.${v}
791
- `:`${so}Welcome to the Alfred setup wizard!${v}
792
- ${Ge}This will walk you through configuring your AI assistant.${v}
793
- ${Ge}Press Enter to accept defaults shown in [brackets].${v}
794
- `);let r=await U(c,"What should your bot be called?",t.config.name??"Alfred"),o=t.config.llm?.provider?We.findIndex(f=>f.name===t.config.llm?.provider):-1,n=o>=0?o+1:1;console.log(`
795
- ${R("Which LLM provider would you like to use?")}`);for(let f=0;f<We.length;f++){let _=f===o?` ${E("(current)")}`:"";console.log(` ${fe(String(f+1)+")")} ${We[f].label}${_}`)}let i=await ur(c,"> ",1,We.length,n),a=We[i-1];console.log(` ${D(">")} Selected: ${R(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 be(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${D(">")} API key set: ${E(ue(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 $={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",_.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${D(">")} URL: ${E(m)}`)}}let T=t.config.llm?.model??a.defaultModel;console.log("");let w;if(a.models&&a.models.length>0){console.log(`${R("Available models:")}`);for(let $=0;$<a.models.length;$++){let V=a.models[$],C=V.id===T?` ${D("(current)")}`:"";console.log(` ${fe(`${$+1})`)} ${V.id} ${E(`\u2014 ${V.desc}`)}${C}`)}console.log(` ${fe(`${a.models.length+1})`)} ${E("Other (enter manually)")}`);let f=await U(c,"Choose model","1"),_=parseInt(f,10)-1;_>=0&&_<a.models.length?w=a.models[_].id:_===a.models.length?w=await U(c,"Model ID",T):w=await U(c,"Model ID",T)}else w=await U(c,"Which model?",T);let g=Object.keys(t.multiModelTiers).length>0,b=g?"Y/n":"y/N";console.log(`
796
- ${R("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let S=(await c.question(`${M}> ${v}${E(`[${b}] `)}`)).trim().toLowerCase(),A=S===""?g:S==="y"||S==="yes",k={};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 $=t.multiModelTiers[_.key],V=!!$?.model;console.log(`
797
- ${R(`${_.label} model`)} ${E(`(${_.hint})`)}`),V&&console.log(` ${E(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${E("Press Enter to skip.")}`);let F=(await c.question(` ${M}Model: ${v}${V?E(`[${$.model}] `):""}`)).trim()||(V?$.model:"");if(!F){console.log(` ${E("Skipped.")}`);continue}let H=$?.provider??a.name,pe=We.map(je=>je.name).join(", ");console.log(` ${E(`Providers: ${pe}`)}`);let te=(await c.question(` ${M}Provider: ${v}${E(`[${H}] `)}`)).trim()||H,ve,De;if(te!==a.name){let je=$?.apiKey??t.env[`ALFRED_LLM_${_.key.toUpperCase()}_API_KEY`]??"";if(je?ve=await U(c,` API key for ${te}`,je):(We.find(wt=>wt.name===te)?.needsApiKey??!0)&&(ve=await be(c,` API key for ${te}`)),["ollama","openwebui"].includes(te)){let wt=($?.baseUrl??"")||We.find(xo=>xo.name===te)?.baseUrl||"";wt&&(De=await U(c,` ${te} URL`,wt))}}k[_.key]={provider:te,model:F,...ve?{apiKey:ve}:{},...De?{baseUrl:De}:{}},console.log(` ${D(">")} ${_.label}: ${R(te)}/${R(F)}`)}Object.keys(k).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"],L=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",K=O.indexOf(L),Pe=K>=0?K+1:0;console.log(`
799
- ${R("Web Search provider (for searching the internet):")}`);let Ne=["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"],Me=u(f=>K===f?` ${E("(current)")}`:"","mark");console.log(` ${fe("0)")} None (disable web search)${K===-1&&L===""?` ${E("(current)")}`:""}`);for(let f=0;f<Ne.length;f++)console.log(` ${fe(String(f+1)+")")} ${Ne[f]}${Me(f)}`);let se=await ur(c,"> ",0,O.length,Pe),P,J="",ge="";if(se>=1&&se<=O.length&&(P=O[se-1]),P==="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 be(c," Brave Search API key")),console.log(` ${D(">")} Brave Search: ${E(ue(J))}`)}else if(P==="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 be(c," Tavily API key")),console.log(` ${D(">")} Tavily: ${E(ue(J))}`)}else if(P==="duckduckgo")console.log(` ${D(">")} DuckDuckGo: ${E("no API key needed")}`);else if(P==="searxng"){let f=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";ge=await U(c," SearXNG URL",f),ge=ge.replace(/\/+$/,""),console.log(` ${D(">")} SearXNG: ${E(ge)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let N=[];for(let f=0;f<Jt.length;f++){let _=Jt[f];t.config[_.configKey]?.enabled&&N.push(f+1)}let B=N.length>0?N.join(","):"";console.log(`
800
- ${R("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let f=0;f<Jt.length;f++){let _=N.includes(f+1)?` ${E("(enabled)")}`:"";console.log(` ${fe(String(f+1)+")")} ${Jt[f].label}${_}`)}console.log(` ${fe("0)")} None (configure later)`);let ye=(await c.question(`${M}> ${v}${B?E(`[${B}] `):""}`)).trim(),X=[],Zt=ye||B;if(Zt&&Zt!=="0"){let f=Zt.split(",").map(_=>parseInt(_.trim(),10));for(let _ of f)if(_>=1&&_<=Jt.length){let $=Jt[_-1];X.includes($)||X.push($)}}X.length>0?console.log(` ${D(">")} Enabling: ${X.map(f=>R(f.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let q={},Y={};for(let f of X){if(f.credentials.length===0){f.name==="whatsapp"&&console.log(`
801
- ${Iu("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
802
- ${R(f.label+" configuration:")}`);let _={};for(let $ of f.credentials){let V=t.env[$.envKey]??"",C;V?C=await U(c,` ${$.prompt}`,V):$.defaultValue?C=await U(c,` ${$.prompt}`,$.defaultValue):$.required?C=await be(c,` ${$.prompt}`):(C=(await c.question(` ${$.prompt}: ${M}`)).trim(),process.stdout.write(v)),_[$.configField]=C,Y[$.envKey]=C,$.configField==="token"||$.configField==="accessToken"?console.log(` ${D(">")} Set: ${E(ue(C))}`):console.log(` ${D(">")} Set: ${E(C)}`)}q[f.configKey]=_}let ee=t.config.email?.accounts??[],Z=ee[0],gt=Z?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",we=Z?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",oo=ee.length>0||!!gt||we==="microsoft",Kc=oo?"Y/n":"y/N";console.log(`
803
- ${R("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let no=(await c.question(`${M}> ${v}${E(`[${Kc}] `)}`)).trim().toLowerCase(),pr=no===""?oo:no==="y"||no==="yes",Re=[],Yc={"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"}},Yn=u(async(f,_)=>{let $={name:f,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},V=_?.provider??"",C=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],F=V==="microsoft"?1:0;console.log("");for(let le=0;le<C.length;le++){let te=le===F?` ${E("(current)")}`:"";console.log(` ${fe(`${le+1})`)} ${C[le]}${te}`)}let H=(await c.question(`${M}> ${v}${E(`[${F+1}] `)}`)).trim(),pe=H===""?F:parseInt(H,10)-1;if($.provider=pe===1?"microsoft":"imap-smtp",$.provider==="microsoft"){let le=t.config.calendar?.microsoft,te=_?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",ve=_?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",De=_?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(le&&!te)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")}`),$.msClientId=await U(c," Client ID",te),$.msClientId||($.msClientId=await be(c," Client ID"));let je=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";$.msClientSecret=await U(c," Client Secret",je),$.msClientSecret||($.msClientSecret=await be(c," Client Secret")),$.msTenantId=await U(c," Tenant ID",ve),$.msTenantId||($.msTenantId=await be(c," Tenant ID")),$.msRefreshToken=await U(c," Refresh Token",De),$.msRefreshToken||($.msRefreshToken=await be(c," Refresh Token"))}console.log(` ${D(">")} Email [${f}]: Microsoft 365 (Graph API)`)}else{let le=_?.auth?.user??"";console.log(""),$.user=await U(c," Email address",le||""),$.user||($.user=await be(c," Email address"));let te=_?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";te?$.pass=await U(c," Password / App password",te):(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")}`),$.pass=await be(c," Password / App password"));let ve=$.user.split("@")[1]?.toLowerCase()??"",De=Yc[ve],je=_?.imap?.host??De?.imap??`imap.${ve}`,li=_?.smtp?.host??De?.smtp??`smtp.${ve}`,Ao=_?.imap?.port??993,wt=_?.smtp?.port??587;De&&console.log(` ${D(">")} Detected ${ve} \u2014 using preset server settings`),$.imapHost=await U(c," IMAP server",je);let xo=await U(c," IMAP port",String(Ao));$.imapPort=parseInt(xo,10)||993,$.smtpHost=await U(c," SMTP server",li);let hl=await U(c," SMTP port",String(wt));$.smtpPort=parseInt(hl,10)||587,console.log(` ${D(">")} Email [${f}]: ${E($.user)} via ${E($.imapHost)}`)}return $},"configureEmailAccount");if(pr){let f=Z??(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);Re.push(await Yn("default",f));let _=!0;for(;_;){let $=(await c.question(`
804
- ${R("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if($==="y"||$==="yes"){let C=(await c.question(` ${R("Account name:")} `)).trim()||`account${Re.length+1}`,F=ee.find(H=>H.name===C);Re.push(await Yn(C,F))}else _=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let fr=["openai","groq"],Jc=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",hr=fr.indexOf(Jc),Zc=hr>=0?hr+1:0;console.log(`
805
- ${R("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let Jn=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${fe("0)")} None (disable voice transcription)${hr===-1?` ${E("(current)")}`:""}`);for(let f=0;f<Jn.length;f++){let _=hr===f?` ${E("(current)")}`:"";console.log(` ${fe(String(f+1)+")")} ${Jn[f]}${_}`)}let io=await ur(c,"> ",0,fr.length,Zc),Ce,Fe="",Qt="";if(io>=1&&io<=fr.length&&(Ce=fr[io-1]),Ce==="openai"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?Fe=await U(c," OpenAI API key (for Whisper)",f):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),Fe=await be(c," OpenAI API key")),console.log(` ${D(">")} OpenAI Whisper: ${E(ue(Fe))}`)}else if(Ce==="groq"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?Fe=await U(c," Groq API key",f):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),Fe=await be(c," Groq API key"));let _=t.env.ALFRED_SPEECH_BASE_URL??"";_&&(Qt=await U(c," Groq API URL",_)),console.log(` ${D(">")} Groq Whisper: ${E(ue(Fe))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let es=!1,ts="alloy";if(Ce){let f=t.config.speech?.ttsEnabled??!1,_=f?"Y/n":"y/N";console.log(`
806
- ${R("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await c.question(`${M}> ${v}${E(`[${_}] `)}`)).trim().toLowerCase();if(es=$===""?f:$==="y"||$==="yes",es){let V=["alloy","echo","fable","onyx","nova","shimmer"],C=t.config.speech?.ttsVoice??"alloy",F=V.indexOf(C),H=F>=0?F+1:1;console.log(`
807
- ${R("Which voice?")}`);for(let le=0;le<V.length;le++){let te=F===le?` ${E("(current)")}`:"";console.log(` ${fe(String(le+1)+")")} ${V[le]}${te}`)}let pe=await ur(c," > ",1,V.length,H);ts=V[pe-1],console.log(` ${D(">")} TTS voice: ${R(ts)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Qc=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
808
- ${R("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let ao=(await c.question(`${M}> ${v}${E(`[${Qc}] `)}`)).trim().toLowerCase(),co=ao===""?t.codeSandboxEnabled:ao==="y"||ao==="yes";console.log(co?` ${D(">")} Code Sandbox ${R("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
809
- ${R("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let lo=[];for(let f of Mc){let _=Ru(f.whichCmd);_?(lo.push({...f,resolvedPath:_}),console.log(` ${D("\u2713")} ${R(f.label)} ${E(`(${_})`)}`)):console.log(` ${E("\xB7")} ${E(f.label)} ${E("\u2014 not found")}`)}let uo=(t.config.codeAgents?.agents??[]).filter(f=>!Mc.some(_=>_.name===f.name));for(let f of uo)console.log(` ${D("\u2713")} ${R(f.name)} ${E(`(${f.command}) \u2014 from existing config`)}`);let Xe=[];if(lo.length===0&&uo.length===0)console.log(`
810
- ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let f=[...lo.map(C=>({name:C.name,command:C.resolvedPath??C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia,label:C.label,detected:!0})),...uo.map(C=>({name:C.name,command:C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia??"arg",label:C.name,detected:!1}))];console.log(`
811
- ${R("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 F=f[C],H=_.has(F.name)?` ${E("(current)")}`:"";console.log(` ${M}${C+1}${v}) ${F.label}${H}`)}console.log(` ${M}0${v}) None`);let $=f.map((C,F)=>_.size>0?_.has(C.name)?String(F+1):null:C.detected?String(F+1):null).filter(Boolean).join(",")||"0",V=(await c.question(` ${M}> ${v}${E(`[${$}] `)}`)).trim()||$;V!=="0"&&(Xe=V.split(",").map(F=>parseInt(F.trim(),10)).filter(F=>!isNaN(F)&&F>=1&&F<=f.length).map(F=>{let H=f[F-1];return{name:H.name,command:H.command,argsTemplate:H.argsTemplate,promptVia:H.promptVia}})),Xe.length>0?console.log(` ${D(">")} ${R(String(Xe.length))} agent(s) selected: ${Xe.map(C=>C.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let mo=t.config.codeAgents?.forge,po=mo?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
812
- ${R("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${E("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${E("Owner/repo are detected automatically from the git remote at runtime.")}`);let Zn=[{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 Zn){let _=f.name===po?` ${E("(current)")}`:"";console.log(` ${M}${f.num}${v}) ${f.label}${_}`)}let Qn=po==="github"?"2":po==="gitlab"?"3":"1",el=(await c.question(`${M}> ${v}${E(`[${Qn}] `)}`)).trim()||Qn,Ke=Zn.find(f=>f.num===el)?.name??"",ss="",rs="";if(Ke==="github"){console.log(` ${D(">")} Forge: ${R("GitHub")}`);let f=t.env.ALFRED_GITHUB_TOKEN??mo?.github?.token??"";f&&console.log(` ${E(`Current token: ${ue(f)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),ss=(await c.question(` ${W}GitHub Token${v}: ${M}`)).trim(),process.stdout.write(v),!ss&&f&&(ss=f)}else if(Ke==="gitlab"){console.log(` ${D(">")} Forge: ${R("GitLab")}`);let f=t.env.ALFRED_GITLAB_TOKEN??mo?.gitlab?.token??"";f&&console.log(` ${E(`Current token: ${ue(f)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),rs=(await c.question(` ${W}GitLab Token${v}: ${M}`)).trim(),process.stdout.write(v),!rs&&f&&(rs=f)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
813
- ${R("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let os=t.config.proxmox,fo=t.env.ALFRED_PROXMOX_BASE_URL??os?.baseUrl??"",tl=fo?"Y/n":"y/N",ei=(await c.question(` ${W}Enable Proxmox VE?${v} ${E(`[${tl}]`)}: ${M}`)).trim().toLowerCase()||(fo?"y":"n");process.stdout.write(v);let gr=ei==="y"||ei==="yes",ns="",ho="",is="",go=!0;if(gr){ns=await U(c," Proxmox URL (e.g. https://pve.local:8006)",fo||"https://pve.local:8006");let f=t.env.ALFRED_PROXMOX_TOKEN_ID??os?.tokenId??"";f&&console.log(` ${E(`Current token ID: ${f}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),ho=await U(c," API Token ID (user@realm!name)",f);let _=t.env.ALFRED_PROXMOX_TOKEN_SECRET??os?.tokenSecret??"";_&&console.log(` ${E(`Current secret: ${ue(_)}`)}`),is=(await c.question(` ${W}API Token Secret${v}: ${M}`)).trim(),process.stdout.write(v),!is&&_&&(is=_);let $=os?.verifyTls===!1?"y/N":"Y/n",V=(await c.question(` ${W}Verify TLS?${v} ${E(`(self-signed? \u2192 no) [${$}]`)}: ${M}`)).trim().toLowerCase()||(os?.verifyTls===!1?"n":"y");process.stdout.write(v),go=V==="y"||V==="yes",console.log(` ${D(">")} Proxmox: ${R(ns)} ${E(`(TLS verify: ${go?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let Ye=t.config.unifi,yo=t.env.ALFRED_UNIFI_BASE_URL??Ye?.baseUrl??"",sl=yo?"Y/n":"y/N",ti=(await c.question(`
814
- ${W}Enable UniFi Network?${v} ${E(`[${sl}]`)}: ${M}`)).trim().toLowerCase()||(yo?"y":"n");process.stdout.write(v);let as=ti==="y"||ti==="yes",yt="",Je="",wo="",cs="",To=!0;if(as){yt=await U(c," UniFi URL (e.g. https://unifi.local)",yo||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let f=t.env.ALFRED_UNIFI_API_KEY??Ye?.apiKey??"",_=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],$=f?"1":Ye?.username?"2":"1";for(let H of _)console.log(` ${M}${H.num}${v}) ${H.label}`);if(((await c.question(` ${M}> ${v}${E(`[${$}] `)}`)).trim()||$)==="1")f&&console.log(` ${E(`Current key: ${ue(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),Je=(await c.question(` ${W}API Key${v}: ${M}`)).trim(),process.stdout.write(v),!Je&&f&&(Je=f);else{let H=t.env.ALFRED_UNIFI_USERNAME??Ye?.username??"";wo=await U(c," Username",H||"alfred");let pe=t.env.ALFRED_UNIFI_PASSWORD??Ye?.password??"";pe&&console.log(` ${E(`Current password: ${ue(pe)}`)}`),cs=(await c.question(` ${W}Password${v}: ${M}`)).trim(),process.stdout.write(v),!cs&&pe&&(cs=pe)}let C=Ye?.verifyTls===!1?"y/N":"Y/n",F=(await c.question(` ${W}Verify TLS?${v} ${E(`(self-signed? \u2192 no) [${C}]`)}: ${M}`)).trim().toLowerCase()||(Ye?.verifyTls===!1?"n":"y");process.stdout.write(v),To=F==="y"||F==="yes",console.log(` ${D(">")} UniFi: ${R(yt)} ${E(`(TLS verify: ${To?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let yr=t.config.homeassistant,Eo=t.env.ALFRED_HOMEASSISTANT_URL??yr?.baseUrl??"",rl=Eo?"Y/n":"y/N",si=(await c.question(`
815
- ${W}Enable Home Assistant?${v} ${E(`[${rl}]`)}: ${M}`)).trim().toLowerCase()||(Eo?"y":"n");process.stdout.write(v);let wr=si==="y"||si==="yes",ls="",ds="",bo=!0;if(wr){ls=await U(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",Eo||"http://homeassistant.local:8123");let f=t.env.ALFRED_HOMEASSISTANT_TOKEN??yr?.accessToken??"";f&&console.log(` ${E(`Current token: ${ue(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),ds=(await c.question(` ${W}Long-Lived Access Token${v}: ${M}`)).trim(),process.stdout.write(v),!ds&&f&&(ds=f);let _=yr?.verifyTls===!1?"y/N":"Y/n",$=(await c.question(` ${W}Verify TLS?${v} ${E(`(self-signed? \u2192 no) [${_}]`)}: ${M}`)).trim().toLowerCase()||(yr?.verifyTls===!1?"n":"y");process.stdout.write(v),bo=$==="y"||$==="yes",console.log(` ${D(">")} Home Assistant: ${R(ls)} ${E(`(TLS verify: ${bo?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let _e=t.config.contacts,_o=t.env.ALFRED_CONTACTS_PROVIDER??_e?.provider??"",ol=_o?"Y/n":"y/N",ri=(await c.question(`
816
- ${W}Enable Contacts management?${v} ${E(`[${ol}]`)}: ${M}`)).trim().toLowerCase()||(_o?"y":"n");process.stdout.write(v);let Tr=ri==="y"||ri==="yes",$e="",ne={};if(Tr){let f=["carddav","google","microsoft"],_=f.indexOf(_o),$=_>=0?_+1:1;console.log(` ${fe("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${fe("2)")} Google Contacts`),console.log(` ${fe("3)")} Microsoft 365`);let V=await ur(c," > ",1,3,$);if($e=f[V-1],ne.ALFRED_CONTACTS_PROVIDER=$e,$e==="carddav"){let C=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??_e?.carddav?.serverUrl??"";ne.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await U(c," CardDAV Server URL",C||"https://cloud.example.com/remote.php/dav");let F=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??_e?.carddav?.username??"";ne.ALFRED_CARDDAV_CONTACTS_USERNAME=await U(c," Username",F);let H=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??_e?.carddav?.password??"";H&&console.log(` ${E(`Current password: ${ue(H)}`)}`);let pe=(await c.question(` ${W}Password${v}: ${M}`)).trim();process.stdout.write(v),ne.ALFRED_CARDDAV_CONTACTS_PASSWORD=pe||H}else if($e==="google"){let C=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??_e?.google?.clientId??"";C&&console.log(` ${E(`Current client ID: ${ue(C)}`)}`),ne.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await c.question(` ${W}Google Client ID${v}: ${M}`)).trim()||C,process.stdout.write(v);let F=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??_e?.google?.clientSecret??"";ne.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await c.question(` ${W}Google Client Secret${v}: ${M}`)).trim()||F,process.stdout.write(v);let H=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??_e?.google?.refreshToken??"";ne.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await c.question(` ${W}Refresh Token${v}: ${M}`)).trim()||H,process.stdout.write(v)}else if($e==="microsoft"){let C=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??_e?.microsoft?.clientId??"";C&&console.log(` ${E(`Current client ID: ${ue(C)}`)}`),ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await c.question(` ${W}Microsoft Client ID${v}: ${M}`)).trim()||C,process.stdout.write(v);let F=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??_e?.microsoft?.clientSecret??"";ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await c.question(` ${W}Microsoft Client Secret${v}: ${M}`)).trim()||F,process.stdout.write(v);let H=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??_e?.microsoft?.tenantId??"";ne.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await U(c," Tenant ID",H||"common");let pe=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??_e?.microsoft?.refreshToken??"";ne.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await c.question(` ${W}Refresh Token${v}: ${M}`)).trim()||pe,process.stdout.write(v)}console.log(` ${D(">")} Contacts: ${R($e)}`)}else console.log(` ${E("Contacts disabled.")}`);let oi=t.config.docker,$o=t.env.ALFRED_DOCKER_SOCKET_PATH??oi?.socketPath??"",vo=t.env.ALFRED_DOCKER_HOST??oi?.host??"",nl=$o||vo?"Y/n":"y/N",ni=(await c.question(`
817
- ${W}Enable Docker management?${v} ${E(`[${nl}]`)}: ${M}`)).trim().toLowerCase()||($o||vo?"y":"n");process.stdout.write(v);let Er=ni==="y"||ni==="yes",Ze="",Qe="";if(Er){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.")}`),Ze=await U(c," Docker socket path",$o||f);let _=(await c.question(` ${W}Docker host URL (optional, for remote)${v}: ${M}`)).trim();process.stdout.write(v),Qe=_||vo,console.log(` ${D(">")} Docker: ${R(Qe||Ze)}`)}else console.log(` ${E("Docker disabled.")}`);console.log(`
818
- ${R("Security configuration:")}`);let ii=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",Te;if(ii)Te=await U(c,"Owner user ID (for elevated permissions)",ii);else{let f=(await c.question(`${W}Owner user ID${v} ${E("(optional, for elevated permissions)")}: ${M}`)).trim();process.stdout.write(v),Te=f}let us=!1;if(Te){let f=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${R("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let _=(await c.question(` ${M}> ${v}${E(`[${f}] `)}`)).trim().toLowerCase();_===""?us=t.shellEnabled:us=_==="y"||_==="yes",console.log(us?` ${D(">")} Shell access ${R("enabled")} for owner ${E(Te)}`:` ${E("Shell access disabled.")}`)}let il=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${R("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let So=(await c.question(` ${M}> ${v}${E(`[${il}] `)}`)).trim().toLowerCase(),ms;So===""?ms=t.writeInGroups:ms=So==="y"||So==="yes",console.log(ms?` ${D(">")} Write actions ${R("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let al=t.rateLimit??30;console.log("");let cl=await U(c," Rate limit (max write actions per hour per user)",String(al)),br=Math.max(1,parseInt(cl,10)||30);console.log(` ${D(">")} Rate limit: ${R(String(br))} per hour`),console.log(`
819
- ${R("Writing configuration files...")}`);let x=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let f=a.envKeyName||"ALFRED_OLLAMA_API_KEY";x.push(`${f}=${l}`)}if(w!==a.defaultModel&&x.push(`ALFRED_LLM_MODEL=${w}`),m&&x.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(k).length>0){x.push("","# === Additional Model Tiers ===");for(let[f,_]of Object.entries(k)){let $=`ALFRED_LLM_${f.toUpperCase()}`;x.push(""),x.push(`${$}_PROVIDER=${_.provider}`),x.push(`${$}_MODEL=${_.model}`),_.apiKey&&x.push(`${$}_API_KEY=${_.apiKey}`),_.baseUrl&&x.push(`${$}_BASE_URL=${_.baseUrl}`)}}x.push("","# === Messaging Platforms ===","");for(let[f,_]of Object.entries(Y))x.push(`${f}=${_}`);if(x.push("","# === Web Search ===",""),P?(x.push(`ALFRED_SEARCH_PROVIDER=${P}`),J&&x.push(`ALFRED_SEARCH_API_KEY=${J}`),ge&&x.push(`ALFRED_SEARCH_BASE_URL=${ge}`)):(x.push("# ALFRED_SEARCH_PROVIDER=brave"),x.push("# ALFRED_SEARCH_API_KEY=")),x.push("","# === Email ===",""),pr&&Re.length>0){let f=Re[0];f.provider==="microsoft"?(x.push("ALFRED_EMAIL_PROVIDER=microsoft"),f.msClientId?(x.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${f.msClientId}`),x.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${f.msClientSecret}`),x.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${f.msTenantId}`),x.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${f.msRefreshToken}`)):x.push("# Microsoft email credentials shared from calendar config")):(x.push(`ALFRED_EMAIL_USER=${f.user}`),x.push(`ALFRED_EMAIL_PASS=${f.pass}`)),Re.length>1&&x.push("# Additional email accounts configured in config/default.yml")}else x.push("# ALFRED_EMAIL_USER="),x.push("# ALFRED_EMAIL_PASS=");if(x.push("","# === Speech ===",""),Ce?(x.push(`ALFRED_SPEECH_PROVIDER=${Ce}`),x.push(`ALFRED_SPEECH_API_KEY=${Fe}`),Qt&&x.push(`ALFRED_SPEECH_BASE_URL=${Qt}`),es&&(x.push("ALFRED_TTS_ENABLED=true"),x.push(`ALFRED_TTS_VOICE=${ts}`))):(x.push("# ALFRED_SPEECH_PROVIDER=groq"),x.push("# ALFRED_SPEECH_API_KEY=")),x.push("","# === Forge (GitHub / GitLab) ===",""),Ke==="github"?(x.push("ALFRED_FORGE_PROVIDER=github"),x.push(`ALFRED_GITHUB_TOKEN=${ss}`)):Ke==="gitlab"?(x.push("ALFRED_FORGE_PROVIDER=gitlab"),x.push(`ALFRED_GITLAB_TOKEN=${rs}`)):(x.push("# ALFRED_FORGE_PROVIDER=github"),x.push("# ALFRED_GITHUB_TOKEN=")),x.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),gr?(x.push(`ALFRED_PROXMOX_BASE_URL=${ns}`),x.push(`ALFRED_PROXMOX_TOKEN_ID=${ho}`),x.push(`ALFRED_PROXMOX_TOKEN_SECRET=${is}`)):(x.push("# ALFRED_PROXMOX_BASE_URL="),x.push("# ALFRED_PROXMOX_TOKEN_ID="),x.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),as&&Je?(x.push(`ALFRED_UNIFI_BASE_URL=${yt}`),x.push(`ALFRED_UNIFI_API_KEY=${Je}`)):as?(x.push(`ALFRED_UNIFI_BASE_URL=${yt}`),x.push(`ALFRED_UNIFI_USERNAME=${wo}`),x.push(`ALFRED_UNIFI_PASSWORD=${cs}`)):(x.push("# ALFRED_UNIFI_BASE_URL="),x.push("# ALFRED_UNIFI_API_KEY=")),wr?(x.push(`ALFRED_HOMEASSISTANT_URL=${ls}`),x.push(`ALFRED_HOMEASSISTANT_TOKEN=${ds}`)):(x.push("# ALFRED_HOMEASSISTANT_URL="),x.push("# ALFRED_HOMEASSISTANT_TOKEN=")),x.push("","# === Contacts ===",""),Tr)for(let[f,_]of Object.entries(ne))x.push(`${f}=${_}`);else x.push("# ALFRED_CONTACTS_PROVIDER=carddav");x.push("","# === Docker ===",""),Er?(Ze&&x.push(`ALFRED_DOCKER_SOCKET_PATH=${Ze}`),Qe&&x.push(`ALFRED_DOCKER_HOST=${Qe}`)):(x.push("# ALFRED_DOCKER_SOCKET_PATH="),x.push("# ALFRED_DOCKER_HOST=")),x.push("","# === Security ===",""),Te?x.push(`ALFRED_OWNER_USER_ID=${Te}`):x.push("# ALFRED_OWNER_USER_ID="),x.push("");let ll=he.join(e,".env");ce.writeFileSync(ll,x.join(`
820
- `),"utf-8"),console.log(` ${D("+")} ${E(".env")} written`);let _r=he.join(e,"config");ce.existsSync(_r)||ce.mkdirSync(_r,{recursive:!0});let ai={name:r,telegram:{token:q.telegram?.token??"",enabled:X.some(f=>f.name==="telegram")},discord:{token:q.discord?.token??"",enabled:X.some(f=>f.name==="discord")},whatsapp:{enabled:X.some(f=>f.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:q.matrix?.homeserverUrl??"https://matrix.org",accessToken:q.matrix?.accessToken??"",userId:q.matrix?.userId??"",enabled:X.some(f=>f.name==="matrix")},signal:{apiUrl:q.signal?.apiUrl??"http://localhost:8080",phoneNumber:q.signal?.phoneNumber??"",enabled:X.some(f=>f.name==="signal")},llm:Object.keys(k).length>0?{default:{provider:a.name,model:w,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...k}:{provider:a.name,model:w,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...P?{search:{provider:P,...J?{apiKey:J}:{},...ge?{baseUrl:ge}:{}}}:{},...pr&&Re.length>0?{email:{accounts:Re.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}})}}:{},...Ce?{speech:{provider:Ce,apiKey:Fe,...Qt?{baseUrl:Qt}:{},...es?{ttsEnabled:!0,ttsVoice:ts}:{}}}:{},...co?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...Xe.length>0||Ke?{codeAgents:{enabled:Xe.length>0,agents:Xe,...Ke==="github"?{forge:{provider:"github",github:{token:ss}}}:Ke==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:rs}}}:{}}}:{},...gr?{proxmox:{baseUrl:ns,tokenId:ho,tokenSecret:is,verifyTls:go}}:{},...as?{unifi:{baseUrl:yt,...Je?{apiKey:Je}:{username:wo,password:cs},site:"default",verifyTls:To}}:{},...wr?{homeassistant:{baseUrl:ls,accessToken:ds,verifyTls:bo}}:{},...Tr?{contacts:{provider:$e,...$e==="carddav"?{carddav:{serverUrl:ne.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:ne.ALFRED_CARDDAV_CONTACTS_USERNAME}}:$e==="google"?{google:{clientId:ne.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:$e==="microsoft"?{microsoft:{clientId:ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:ne.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...Er?{docker:{...Ze?{socketPath:Ze}:{},...Qe?{host:Qe}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};Te&&(ai.security.ownerUserId=Te);let dl="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Gn.dump(ai,{lineWidth:120,noRefs:!0,sortKeys:!1}),ul=he.join(_r,"default.yml");ce.writeFileSync(ul,dl,"utf-8"),console.log(` ${D("+")} ${E("config/default.yml")} written`);let ko=he.join(_r,"rules");ce.existsSync(ko)||ce.mkdirSync(ko,{recursive:!0});let ml=us&&Te?`
788
+ Failed to send message: ${i.message}`),t.prompt()}),n.write(o),n.end()}),t.on("close",()=>{process.exit(0)})}async function _u(c){let e=new ae,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 bu(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Eu(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 wt(t);try{await n.initialize(),await n.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var Mc=w(()=>{"use strict";qe();Gn();u(bu,"checkHealth");u(Eu,"startClientMode");u(_u,"chatCommand")});var Uc={};ie(Uc,{setupCommand:()=>Nu});import{createInterface as $u}from"node:readline/promises";import{stdin as vu,stdout as Su}from"node:process";import{execFileSync as ku}from"node:child_process";import ce from"node:fs";import Au from"node:os";import ge from"node:path";import Xn from"js-yaml";function D(c){return`${oo}${c}${S}`}function Ru(c){return`${M}${c}${S}`}function he(c){return`${no}${c}${S}`}function Oc(c){return`${xu}${c}${S}`}function R(c){return`${V}${c}${S}`}function E(c){return`${Xe}${c}${S}`}function me(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Cu(c){let e=process.platform==="win32",t=e?"where":"which";try{let o=ku(t,[c],{stdio:"pipe"}).toString().trim();if(o)return o.split(/\r?\n/)[0]}catch{}let s=Au.homedir(),r=e?[ge.join(s,".local","bin",`${c}.exe`),ge.join(s,"AppData","Roaming","npm",`${c}.cmd`),ge.join(s,"AppData","Roaming","npm",`${c}`)]:[ge.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,ge.join(s,".npm-global","bin",c)];for(let o of r)try{return ce.accessSync(o,ce.constants.X_OK),o}catch{}return null}function Lu(c){let e={},t={},s=!1,r=!1,o=30,n=ge.join(c,"config","default.yml");if(ce.existsSync(n))try{let p=Xn.load(ce.readFileSync(n,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=ge.join(c,".env");if(ce.existsSync(i))try{let p=ce.readFileSync(i,"utf-8").split(`
789
+ `);for(let T of p){let y=T.trim();if(!y||y.startsWith("#"))continue;let g=y.indexOf("=");g>0&&(t[y.slice(0,g)]=y.slice(g+1))}}catch{}let a=ge.join(c,"config","rules","default-rules.yml");if(ce.existsSync(a))try{let p=Xn.load(ce.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 y=p.rules.find(g=>g.id==="rate-limit-write");y?.rateLimit?.maxInvocations&&(o=y.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 Nu(){let c=$u({input:vu,output:Su}),e=process.cwd(),t=Lu(e),s=Object.keys(t.config).length>0;try{Mu(),console.log(s?`${no}Existing configuration found \u2014 press Enter to keep current values.${S}
790
+ ${Xe}Only change what you need to update.${S}
791
+ `:`${no}Welcome to the Alfred setup wizard!${S}
792
+ ${Xe}This will walk you through configuring your AI assistant.${S}
793
+ ${Xe}Press Enter to accept defaults shown in [brackets].${S}
794
+ `);let r=await P(c,"What should your bot be called?",t.config.name??"Alfred"),o=t.config.llm?.provider?Ge.findIndex(f=>f.name===t.config.llm?.provider):-1,n=o>=0?o+1:1;console.log(`
795
+ ${R("Which LLM provider would you like to use?")}`);for(let f=0;f<Ge.length;f++){let _=f===o?` ${E("(current)")}`:"";console.log(` ${he(String(f+1)+")")} ${Ge[f].label}${_}`)}let i=await mr(c,"> ",1,Ge.length,n),a=Ge[i-1];console.log(` ${D(">")} Selected: ${R(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await P(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await Ee(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${D(">")} API key set: ${E(me(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 $={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 P(c,$[a.name]??"API Base URL",_.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${D(">")} URL: ${E(m)}`)}}let T=t.config.llm?.model??a.defaultModel;console.log("");let y;if(a.models&&a.models.length>0){console.log(`${R("Available models:")}`);for(let $=0;$<a.models.length;$++){let z=a.models[$],C=z.id===T?` ${D("(current)")}`:"";console.log(` ${he(`${$+1})`)} ${z.id} ${E(`\u2014 ${z.desc}`)}${C}`)}console.log(` ${he(`${a.models.length+1})`)} ${E("Other (enter manually)")}`);let f=await P(c,"Choose model","1"),_=parseInt(f,10)-1;_>=0&&_<a.models.length?y=a.models[_].id:_===a.models.length?y=await P(c,"Model ID",T):y=await P(c,"Model ID",T)}else y=await P(c,"Which model?",T);let g=Object.keys(t.multiModelTiers).length>0,b=g?"Y/n":"y/N";console.log(`
796
+ ${R("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let v=(await c.question(`${M}> ${S}${E(`[${b}] `)}`)).trim().toLowerCase(),A=v===""?g:v==="y"||v==="yes",k={};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 $=t.multiModelTiers[_.key],z=!!$?.model;console.log(`
797
+ ${R(`${_.label} model`)} ${E(`(${_.hint})`)}`),z&&console.log(` ${E(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${E("Press Enter to skip.")}`);let F=(await c.question(` ${M}Model: ${S}${z?E(`[${$.model}] `):""}`)).trim()||(z?$.model:"");if(!F){console.log(` ${E("Skipped.")}`);continue}let q=$?.provider??a.name,fe=Ge.map(Be=>Be.name).join(", ");console.log(` ${E(`Providers: ${fe}`)}`);let Q=(await c.question(` ${M}Provider: ${S}${E(`[${q}] `)}`)).trim()||q,Se,Oe;if(Q!==a.name){let Be=$?.apiKey??t.env[`ALFRED_LLM_${_.key.toUpperCase()}_API_KEY`]??"";if(Be?Se=await P(c,` API key for ${Q}`,Be):(Ge.find(bt=>bt.name===Q)?.needsApiKey??!0)&&(Se=await Ee(c,` API key for ${Q}`)),["ollama","openwebui"].includes(Q)){let bt=($?.baseUrl??"")||Ge.find(Io=>Io.name===Q)?.baseUrl||"";bt&&(Oe=await P(c,` ${Q} URL`,bt))}}k[_.key]={provider:Q,model:F,...Se?{apiKey:Se}:{},...Oe?{baseUrl:Oe}:{}},console.log(` ${D(">")} ${_.label}: ${R(Q)}/${R(F)}`)}Object.keys(k).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"],L=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",K=O.indexOf(L),Fe=K>=0?K+1:0;console.log(`
799
+ ${R("Web Search provider (for searching the internet):")}`);let Me=["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"],De=u(f=>K===f?` ${E("(current)")}`:"","mark");console.log(` ${he("0)")} None (disable web search)${K===-1&&L===""?` ${E("(current)")}`:""}`);for(let f=0;f<Me.length;f++)console.log(` ${he(String(f+1)+")")} ${Me[f]}${De(f)}`);let ee=await mr(c,"> ",0,O.length,Fe),U,Y="",ye="";if(ee>=1&&ee<=O.length&&(U=O[ee-1]),U==="brave"){let f=t.env.ALFRED_SEARCH_API_KEY??"";f?Y=await P(c," Brave Search API key",f):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),Y=await Ee(c," Brave Search API key")),console.log(` ${D(">")} Brave Search: ${E(me(Y))}`)}else if(U==="tavily"){let f=t.env.ALFRED_SEARCH_API_KEY??"";f?Y=await P(c," Tavily API key",f):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),Y=await Ee(c," Tavily API key")),console.log(` ${D(">")} Tavily: ${E(me(Y))}`)}else if(U==="duckduckgo")console.log(` ${D(">")} DuckDuckGo: ${E("no API key needed")}`);else if(U==="searxng"){let f=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";ye=await P(c," SearXNG URL",f),ye=ye.replace(/\/+$/,""),console.log(` ${D(">")} SearXNG: ${E(ye)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let N=[];for(let f=0;f<Qt.length;f++){let _=Qt[f];t.config[_.configKey]?.enabled&&N.push(f+1)}let B=N.length>0?N.join(","):"";console.log(`
800
+ ${R("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let f=0;f<Qt.length;f++){let _=N.includes(f+1)?` ${E("(enabled)")}`:"";console.log(` ${he(String(f+1)+")")} ${Qt[f].label}${_}`)}console.log(` ${he("0)")} None (configure later)`);let _e=(await c.question(`${M}> ${S}${B?E(`[${B}] `):""}`)).trim(),te=[],Ke=_e||B;if(Ke&&Ke!=="0"){let f=Ke.split(",").map(_=>parseInt(_.trim(),10));for(let _ of f)if(_>=1&&_<=Qt.length){let $=Qt[_-1];te.includes($)||te.push($)}}te.length>0?console.log(` ${D(">")} Enabling: ${te.map(f=>R(f.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let le={},fr={};for(let f of te){if(f.credentials.length===0){f.name==="whatsapp"&&console.log(`
801
+ ${Ru("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
802
+ ${R(f.label+" configuration:")}`);let _={};for(let $ of f.credentials){let z=t.env[$.envKey]??"",C;z?C=await P(c,` ${$.prompt}`,z):$.defaultValue?C=await P(c,` ${$.prompt}`,$.defaultValue):$.required?C=await Ee(c,` ${$.prompt}`):(C=(await c.question(` ${$.prompt}: ${M}`)).trim(),process.stdout.write(S)),_[$.configField]=C,fr[$.envKey]=C,$.configField==="token"||$.configField==="accessToken"?console.log(` ${D(">")} Set: ${E(me(C))}`):console.log(` ${D(">")} Set: ${E(C)}`)}le[f.configKey]=_}let W=t.config.email?.accounts??[],X=W[0],se=X?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",Z=X?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",Ye=W.length>0||!!se||Z==="microsoft",we=Ye?"Y/n":"y/N";console.log(`
803
+ ${R("Email access (read & send emails)?")}`),console.log(`${E("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let hr=(await c.question(`${M}> ${S}${E(`[${we}] `)}`)).trim().toLowerCase(),gr=hr===""?Ye:hr==="y"||hr==="yes",Ce=[],Yc={"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"}},Jn=u(async(f,_)=>{let $={name:f,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},z=_?.provider??"",C=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],F=z==="microsoft"?1:0;console.log("");for(let de=0;de<C.length;de++){let Q=de===F?` ${E("(current)")}`:"";console.log(` ${he(`${de+1})`)} ${C[de]}${Q}`)}let q=(await c.question(`${M}> ${S}${E(`[${F+1}] `)}`)).trim(),fe=q===""?F:parseInt(q,10)-1;if($.provider=fe===1?"microsoft":"imap-smtp",$.provider==="microsoft"){let de=t.config.calendar?.microsoft,Q=_?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",Se=_?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",Oe=_?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(de&&!Q)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")}`),$.msClientId=await P(c," Client ID",Q),$.msClientId||($.msClientId=await Ee(c," Client ID"));let Be=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";$.msClientSecret=await P(c," Client Secret",Be),$.msClientSecret||($.msClientSecret=await Ee(c," Client Secret")),$.msTenantId=await P(c," Tenant ID",Se),$.msTenantId||($.msTenantId=await Ee(c," Tenant ID")),$.msRefreshToken=await P(c," Refresh Token",Oe),$.msRefreshToken||($.msRefreshToken=await Ee(c," Refresh Token"))}console.log(` ${D(">")} Email [${f}]: Microsoft 365 (Graph API)`)}else{let de=_?.auth?.user??"";console.log(""),$.user=await P(c," Email address",de||""),$.user||($.user=await Ee(c," Email address"));let Q=_?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";Q?$.pass=await P(c," Password / App password",Q):(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")}`),$.pass=await Ee(c," Password / App password"));let Se=$.user.split("@")[1]?.toLowerCase()??"",Oe=Yc[Se],Be=_?.imap?.host??Oe?.imap??`imap.${Se}`,di=_?.smtp?.host??Oe?.smtp??`smtp.${Se}`,xo=_?.imap?.port??993,bt=_?.smtp?.port??587;Oe&&console.log(` ${D(">")} Detected ${Se} \u2014 using preset server settings`),$.imapHost=await P(c," IMAP server",Be);let Io=await P(c," IMAP port",String(xo));$.imapPort=parseInt(Io,10)||993,$.smtpHost=await P(c," SMTP server",di);let hl=await P(c," SMTP port",String(bt));$.smtpPort=parseInt(hl,10)||587,console.log(` ${D(">")} Email [${f}]: ${E($.user)} via ${E($.imapHost)}`)}return $},"configureEmailAccount");if(gr){let f=X??(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);Ce.push(await Jn("default",f));let _=!0;for(;_;){let $=(await c.question(`
804
+ ${R("Add another email account?")} ${E("[y/N]")} `)).trim().toLowerCase();if($==="y"||$==="yes"){let C=(await c.question(` ${R("Account name:")} `)).trim()||`account${Ce.length+1}`,F=W.find(q=>q.name===C);Ce.push(await Jn(C,F))}else _=!1}}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let yr=["openai","groq"],Jc=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",wr=yr.indexOf(Jc),Zc=wr>=0?wr+1:0;console.log(`
805
+ ${R("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(` ${he("0)")} None (disable voice transcription)${wr===-1?` ${E("(current)")}`:""}`);for(let f=0;f<Zn.length;f++){let _=wr===f?` ${E("(current)")}`:"";console.log(` ${he(String(f+1)+")")} ${Zn[f]}${_}`)}let ao=await mr(c,"> ",0,yr.length,Zc),Le,je="",es="";if(ao>=1&&ao<=yr.length&&(Le=yr[ao-1]),Le==="openai"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?je=await P(c," OpenAI API key (for Whisper)",f):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),je=await Ee(c," OpenAI API key")),console.log(` ${D(">")} OpenAI Whisper: ${E(me(je))}`)}else if(Le==="groq"){let f=t.env.ALFRED_SPEECH_API_KEY??"";f?je=await P(c," Groq API key",f):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),je=await Ee(c," Groq API key"));let _=t.env.ALFRED_SPEECH_BASE_URL??"";_&&(es=await P(c," Groq API URL",_)),console.log(` ${D(">")} Groq Whisper: ${E(me(je))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let ts=!1,ss="alloy";if(Le){let f=t.config.speech?.ttsEnabled??!1,_=f?"Y/n":"y/N";console.log(`
806
+ ${R("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await c.question(`${M}> ${S}${E(`[${_}] `)}`)).trim().toLowerCase();if(ts=$===""?f:$==="y"||$==="yes",ts){let z=["alloy","echo","fable","onyx","nova","shimmer"],C=t.config.speech?.ttsVoice??"alloy",F=z.indexOf(C),q=F>=0?F+1:1;console.log(`
807
+ ${R("Which voice?")}`);for(let de=0;de<z.length;de++){let Q=F===de?` ${E("(current)")}`:"";console.log(` ${he(String(de+1)+")")} ${z[de]}${Q}`)}let fe=await mr(c," > ",1,z.length,q);ss=z[fe-1],console.log(` ${D(">")} TTS voice: ${R(ss)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Qc=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
808
+ ${R("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let co=(await c.question(`${M}> ${S}${E(`[${Qc}] `)}`)).trim().toLowerCase(),lo=co===""?t.codeSandboxEnabled:co==="y"||co==="yes";console.log(lo?` ${D(">")} Code Sandbox ${R("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
809
+ ${R("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let uo=[];for(let f of Dc){let _=Cu(f.whichCmd);_?(uo.push({...f,resolvedPath:_}),console.log(` ${D("\u2713")} ${R(f.label)} ${E(`(${_})`)}`)):console.log(` ${E("\xB7")} ${E(f.label)} ${E("\u2014 not found")}`)}let mo=(t.config.codeAgents?.agents??[]).filter(f=>!Dc.some(_=>_.name===f.name));for(let f of mo)console.log(` ${D("\u2713")} ${R(f.name)} ${E(`(${f.command}) \u2014 from existing config`)}`);let Je=[];if(uo.length===0&&mo.length===0)console.log(`
810
+ ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let f=[...uo.map(C=>({name:C.name,command:C.resolvedPath??C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia,label:C.label,detected:!0})),...mo.map(C=>({name:C.name,command:C.command,argsTemplate:C.argsTemplate,promptVia:C.promptVia??"arg",label:C.name,detected:!1}))];console.log(`
811
+ ${R("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 F=f[C],q=_.has(F.name)?` ${E("(current)")}`:"";console.log(` ${M}${C+1}${S}) ${F.label}${q}`)}console.log(` ${M}0${S}) None`);let $=f.map((C,F)=>_.size>0?_.has(C.name)?String(F+1):null:C.detected?String(F+1):null).filter(Boolean).join(",")||"0",z=(await c.question(` ${M}> ${S}${E(`[${$}] `)}`)).trim()||$;z!=="0"&&(Je=z.split(",").map(F=>parseInt(F.trim(),10)).filter(F=>!isNaN(F)&&F>=1&&F<=f.length).map(F=>{let q=f[F-1];return{name:q.name,command:q.command,argsTemplate:q.argsTemplate,promptVia:q.promptVia}})),Je.length>0?console.log(` ${D(">")} ${R(String(Je.length))} agent(s) selected: ${Je.map(C=>C.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let po=t.config.codeAgents?.forge,fo=po?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
812
+ ${R("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${E("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${E("Owner/repo are detected automatically from the git remote at runtime.")}`);let Qn=[{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 Qn){let _=f.name===fo?` ${E("(current)")}`:"";console.log(` ${M}${f.num}${S}) ${f.label}${_}`)}let ei=fo==="github"?"2":fo==="gitlab"?"3":"1",el=(await c.question(`${M}> ${S}${E(`[${ei}] `)}`)).trim()||ei,Ze=Qn.find(f=>f.num===el)?.name??"",rs="",os="";if(Ze==="github"){console.log(` ${D(">")} Forge: ${R("GitHub")}`);let f=t.env.ALFRED_GITHUB_TOKEN??po?.github?.token??"";f&&console.log(` ${E(`Current token: ${me(f)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),rs=(await c.question(` ${V}GitHub Token${S}: ${M}`)).trim(),process.stdout.write(S),!rs&&f&&(rs=f)}else if(Ze==="gitlab"){console.log(` ${D(">")} Forge: ${R("GitLab")}`);let f=t.env.ALFRED_GITLAB_TOKEN??po?.gitlab?.token??"";f&&console.log(` ${E(`Current token: ${me(f)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),os=(await c.question(` ${V}GitLab Token${S}: ${M}`)).trim(),process.stdout.write(S),!os&&f&&(os=f)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
813
+ ${R("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${E("Control VMs, containers, network devices, and smart home through Alfred.")}`);let ns=t.config.proxmox,ho=t.env.ALFRED_PROXMOX_BASE_URL??ns?.baseUrl??"",tl=ho?"Y/n":"y/N",ti=(await c.question(` ${V}Enable Proxmox VE?${S} ${E(`[${tl}]`)}: ${M}`)).trim().toLowerCase()||(ho?"y":"n");process.stdout.write(S);let Tr=ti==="y"||ti==="yes",is="",go="",as="",yo=!0;if(Tr){is=await P(c," Proxmox URL (e.g. https://pve.local:8006)",ho||"https://pve.local:8006");let f=t.env.ALFRED_PROXMOX_TOKEN_ID??ns?.tokenId??"";f&&console.log(` ${E(`Current token ID: ${f}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),go=await P(c," API Token ID (user@realm!name)",f);let _=t.env.ALFRED_PROXMOX_TOKEN_SECRET??ns?.tokenSecret??"";_&&console.log(` ${E(`Current secret: ${me(_)}`)}`),as=(await c.question(` ${V}API Token Secret${S}: ${M}`)).trim(),process.stdout.write(S),!as&&_&&(as=_);let $=ns?.verifyTls===!1?"y/N":"Y/n",z=(await c.question(` ${V}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${$}]`)}: ${M}`)).trim().toLowerCase()||(ns?.verifyTls===!1?"n":"y");process.stdout.write(S),yo=z==="y"||z==="yes",console.log(` ${D(">")} Proxmox: ${R(is)} ${E(`(TLS verify: ${yo?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let Qe=t.config.unifi,wo=t.env.ALFRED_UNIFI_BASE_URL??Qe?.baseUrl??"",sl=wo?"Y/n":"y/N",si=(await c.question(`
814
+ ${V}Enable UniFi Network?${S} ${E(`[${sl}]`)}: ${M}`)).trim().toLowerCase()||(wo?"y":"n");process.stdout.write(S);let cs=si==="y"||si==="yes",Tt="",et="",To="",ls="",bo=!0;if(cs){Tt=await P(c," UniFi URL (e.g. https://unifi.local)",wo||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let f=t.env.ALFRED_UNIFI_API_KEY??Qe?.apiKey??"",_=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],$=f?"1":Qe?.username?"2":"1";for(let q of _)console.log(` ${M}${q.num}${S}) ${q.label}`);if(((await c.question(` ${M}> ${S}${E(`[${$}] `)}`)).trim()||$)==="1")f&&console.log(` ${E(`Current key: ${me(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),et=(await c.question(` ${V}API Key${S}: ${M}`)).trim(),process.stdout.write(S),!et&&f&&(et=f);else{let q=t.env.ALFRED_UNIFI_USERNAME??Qe?.username??"";To=await P(c," Username",q||"alfred");let fe=t.env.ALFRED_UNIFI_PASSWORD??Qe?.password??"";fe&&console.log(` ${E(`Current password: ${me(fe)}`)}`),ls=(await c.question(` ${V}Password${S}: ${M}`)).trim(),process.stdout.write(S),!ls&&fe&&(ls=fe)}let C=Qe?.verifyTls===!1?"y/N":"Y/n",F=(await c.question(` ${V}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${C}]`)}: ${M}`)).trim().toLowerCase()||(Qe?.verifyTls===!1?"n":"y");process.stdout.write(S),bo=F==="y"||F==="yes",console.log(` ${D(">")} UniFi: ${R(Tt)} ${E(`(TLS verify: ${bo?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);let br=t.config.homeassistant,Eo=t.env.ALFRED_HOMEASSISTANT_URL??br?.baseUrl??"",rl=Eo?"Y/n":"y/N",ri=(await c.question(`
815
+ ${V}Enable Home Assistant?${S} ${E(`[${rl}]`)}: ${M}`)).trim().toLowerCase()||(Eo?"y":"n");process.stdout.write(S);let Er=ri==="y"||ri==="yes",ds="",us="",_o=!0;if(Er){ds=await P(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",Eo||"http://homeassistant.local:8123");let f=t.env.ALFRED_HOMEASSISTANT_TOKEN??br?.accessToken??"";f&&console.log(` ${E(`Current token: ${me(f)}`)}`),console.log(` ${E("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),us=(await c.question(` ${V}Long-Lived Access Token${S}: ${M}`)).trim(),process.stdout.write(S),!us&&f&&(us=f);let _=br?.verifyTls===!1?"y/N":"Y/n",$=(await c.question(` ${V}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${_}]`)}: ${M}`)).trim().toLowerCase()||(br?.verifyTls===!1?"n":"y");process.stdout.write(S),_o=$==="y"||$==="yes",console.log(` ${D(">")} Home Assistant: ${R(ds)} ${E(`(TLS verify: ${_o?"yes":"no"})`)}`)}else console.log(` ${E("Home Assistant disabled.")}`);let $e=t.config.contacts,$o=t.env.ALFRED_CONTACTS_PROVIDER??$e?.provider??"",ol=$o?"Y/n":"y/N",oi=(await c.question(`
816
+ ${V}Enable Contacts management?${S} ${E(`[${ol}]`)}: ${M}`)).trim().toLowerCase()||($o?"y":"n");process.stdout.write(S);let _r=oi==="y"||oi==="yes",ve="",ne={};if(_r){let f=["carddav","google","microsoft"],_=f.indexOf($o),$=_>=0?_+1:1;console.log(` ${he("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${he("2)")} Google Contacts`),console.log(` ${he("3)")} Microsoft 365`);let z=await mr(c," > ",1,3,$);if(ve=f[z-1],ne.ALFRED_CONTACTS_PROVIDER=ve,ve==="carddav"){let C=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??$e?.carddav?.serverUrl??"";ne.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await P(c," CardDAV Server URL",C||"https://cloud.example.com/remote.php/dav");let F=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??$e?.carddav?.username??"";ne.ALFRED_CARDDAV_CONTACTS_USERNAME=await P(c," Username",F);let q=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??$e?.carddav?.password??"";q&&console.log(` ${E(`Current password: ${me(q)}`)}`);let fe=(await c.question(` ${V}Password${S}: ${M}`)).trim();process.stdout.write(S),ne.ALFRED_CARDDAV_CONTACTS_PASSWORD=fe||q}else if(ve==="google"){let C=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??$e?.google?.clientId??"";C&&console.log(` ${E(`Current client ID: ${me(C)}`)}`),ne.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await c.question(` ${V}Google Client ID${S}: ${M}`)).trim()||C,process.stdout.write(S);let F=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??$e?.google?.clientSecret??"";ne.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await c.question(` ${V}Google Client Secret${S}: ${M}`)).trim()||F,process.stdout.write(S);let q=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??$e?.google?.refreshToken??"";ne.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await c.question(` ${V}Refresh Token${S}: ${M}`)).trim()||q,process.stdout.write(S)}else if(ve==="microsoft"){let C=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??$e?.microsoft?.clientId??"";C&&console.log(` ${E(`Current client ID: ${me(C)}`)}`),ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await c.question(` ${V}Microsoft Client ID${S}: ${M}`)).trim()||C,process.stdout.write(S);let F=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??$e?.microsoft?.clientSecret??"";ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await c.question(` ${V}Microsoft Client Secret${S}: ${M}`)).trim()||F,process.stdout.write(S);let q=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??$e?.microsoft?.tenantId??"";ne.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await P(c," Tenant ID",q||"common");let fe=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??$e?.microsoft?.refreshToken??"";ne.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await c.question(` ${V}Refresh Token${S}: ${M}`)).trim()||fe,process.stdout.write(S)}console.log(` ${D(">")} Contacts: ${R(ve)}`)}else console.log(` ${E("Contacts disabled.")}`);let ni=t.config.docker,vo=t.env.ALFRED_DOCKER_SOCKET_PATH??ni?.socketPath??"",So=t.env.ALFRED_DOCKER_HOST??ni?.host??"",nl=vo||So?"Y/n":"y/N",ii=(await c.question(`
817
+ ${V}Enable Docker management?${S} ${E(`[${nl}]`)}: ${M}`)).trim().toLowerCase()||(vo||So?"y":"n");process.stdout.write(S);let $r=ii==="y"||ii==="yes",tt="",st="";if($r){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.")}`),tt=await P(c," Docker socket path",vo||f);let _=(await c.question(` ${V}Docker host URL (optional, for remote)${S}: ${M}`)).trim();process.stdout.write(S),st=_||So,console.log(` ${D(">")} Docker: ${R(st||tt)}`)}else console.log(` ${E("Docker disabled.")}`);console.log(`
818
+ ${R("Security configuration:")}`);let ai=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",Te;if(ai)Te=await P(c,"Owner user ID (for elevated permissions)",ai);else{let f=(await c.question(`${V}Owner user ID${S} ${E("(optional, for elevated permissions)")}: ${M}`)).trim();process.stdout.write(S),Te=f}let ms=!1;if(Te){let f=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${R("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let _=(await c.question(` ${M}> ${S}${E(`[${f}] `)}`)).trim().toLowerCase();_===""?ms=t.shellEnabled:ms=_==="y"||_==="yes",console.log(ms?` ${D(">")} Shell access ${R("enabled")} for owner ${E(Te)}`:` ${E("Shell access disabled.")}`)}let il=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${R("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let ko=(await c.question(` ${M}> ${S}${E(`[${il}] `)}`)).trim().toLowerCase(),ps;ko===""?ps=t.writeInGroups:ps=ko==="y"||ko==="yes",console.log(ps?` ${D(">")} Write actions ${R("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let al=t.rateLimit??30;console.log("");let cl=await P(c," Rate limit (max write actions per hour per user)",String(al)),vr=Math.max(1,parseInt(cl,10)||30);console.log(` ${D(">")} Rate limit: ${R(String(vr))} per hour`),console.log(`
819
+ ${R("Writing configuration files...")}`);let x=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let f=a.envKeyName||"ALFRED_OLLAMA_API_KEY";x.push(`${f}=${l}`)}if(y!==a.defaultModel&&x.push(`ALFRED_LLM_MODEL=${y}`),m&&x.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(k).length>0){x.push("","# === Additional Model Tiers ===");for(let[f,_]of Object.entries(k)){let $=`ALFRED_LLM_${f.toUpperCase()}`;x.push(""),x.push(`${$}_PROVIDER=${_.provider}`),x.push(`${$}_MODEL=${_.model}`),_.apiKey&&x.push(`${$}_API_KEY=${_.apiKey}`),_.baseUrl&&x.push(`${$}_BASE_URL=${_.baseUrl}`)}}x.push("","# === Messaging Platforms ===","");for(let[f,_]of Object.entries(fr))x.push(`${f}=${_}`);if(x.push("","# === Web Search ===",""),U?(x.push(`ALFRED_SEARCH_PROVIDER=${U}`),Y&&x.push(`ALFRED_SEARCH_API_KEY=${Y}`),ye&&x.push(`ALFRED_SEARCH_BASE_URL=${ye}`)):(x.push("# ALFRED_SEARCH_PROVIDER=brave"),x.push("# ALFRED_SEARCH_API_KEY=")),x.push("","# === Email ===",""),gr&&Ce.length>0){let f=Ce[0];f.provider==="microsoft"?(x.push("ALFRED_EMAIL_PROVIDER=microsoft"),f.msClientId?(x.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${f.msClientId}`),x.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${f.msClientSecret}`),x.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${f.msTenantId}`),x.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${f.msRefreshToken}`)):x.push("# Microsoft email credentials shared from calendar config")):(x.push(`ALFRED_EMAIL_USER=${f.user}`),x.push(`ALFRED_EMAIL_PASS=${f.pass}`)),Ce.length>1&&x.push("# Additional email accounts configured in config/default.yml")}else x.push("# ALFRED_EMAIL_USER="),x.push("# ALFRED_EMAIL_PASS=");if(x.push("","# === Speech ===",""),Le?(x.push(`ALFRED_SPEECH_PROVIDER=${Le}`),x.push(`ALFRED_SPEECH_API_KEY=${je}`),es&&x.push(`ALFRED_SPEECH_BASE_URL=${es}`),ts&&(x.push("ALFRED_TTS_ENABLED=true"),x.push(`ALFRED_TTS_VOICE=${ss}`))):(x.push("# ALFRED_SPEECH_PROVIDER=groq"),x.push("# ALFRED_SPEECH_API_KEY=")),x.push("","# === Forge (GitHub / GitLab) ===",""),Ze==="github"?(x.push("ALFRED_FORGE_PROVIDER=github"),x.push(`ALFRED_GITHUB_TOKEN=${rs}`)):Ze==="gitlab"?(x.push("ALFRED_FORGE_PROVIDER=gitlab"),x.push(`ALFRED_GITLAB_TOKEN=${os}`)):(x.push("# ALFRED_FORGE_PROVIDER=github"),x.push("# ALFRED_GITHUB_TOKEN=")),x.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Tr?(x.push(`ALFRED_PROXMOX_BASE_URL=${is}`),x.push(`ALFRED_PROXMOX_TOKEN_ID=${go}`),x.push(`ALFRED_PROXMOX_TOKEN_SECRET=${as}`)):(x.push("# ALFRED_PROXMOX_BASE_URL="),x.push("# ALFRED_PROXMOX_TOKEN_ID="),x.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),cs&&et?(x.push(`ALFRED_UNIFI_BASE_URL=${Tt}`),x.push(`ALFRED_UNIFI_API_KEY=${et}`)):cs?(x.push(`ALFRED_UNIFI_BASE_URL=${Tt}`),x.push(`ALFRED_UNIFI_USERNAME=${To}`),x.push(`ALFRED_UNIFI_PASSWORD=${ls}`)):(x.push("# ALFRED_UNIFI_BASE_URL="),x.push("# ALFRED_UNIFI_API_KEY=")),Er?(x.push(`ALFRED_HOMEASSISTANT_URL=${ds}`),x.push(`ALFRED_HOMEASSISTANT_TOKEN=${us}`)):(x.push("# ALFRED_HOMEASSISTANT_URL="),x.push("# ALFRED_HOMEASSISTANT_TOKEN=")),x.push("","# === Contacts ===",""),_r)for(let[f,_]of Object.entries(ne))x.push(`${f}=${_}`);else x.push("# ALFRED_CONTACTS_PROVIDER=carddav");x.push("","# === Docker ===",""),$r?(tt&&x.push(`ALFRED_DOCKER_SOCKET_PATH=${tt}`),st&&x.push(`ALFRED_DOCKER_HOST=${st}`)):(x.push("# ALFRED_DOCKER_SOCKET_PATH="),x.push("# ALFRED_DOCKER_HOST=")),x.push("","# === Security ===",""),Te?x.push(`ALFRED_OWNER_USER_ID=${Te}`):x.push("# ALFRED_OWNER_USER_ID="),x.push("");let ll=ge.join(e,".env");ce.writeFileSync(ll,x.join(`
820
+ `),"utf-8"),console.log(` ${D("+")} ${E(".env")} written`);let Sr=ge.join(e,"config");ce.existsSync(Sr)||ce.mkdirSync(Sr,{recursive:!0});let ci={name:r,telegram:{token:le.telegram?.token??"",enabled:te.some(f=>f.name==="telegram")},discord:{token:le.discord?.token??"",enabled:te.some(f=>f.name==="discord")},whatsapp:{enabled:te.some(f=>f.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:le.matrix?.homeserverUrl??"https://matrix.org",accessToken:le.matrix?.accessToken??"",userId:le.matrix?.userId??"",enabled:te.some(f=>f.name==="matrix")},signal:{apiUrl:le.signal?.apiUrl??"http://localhost:8080",phoneNumber:le.signal?.phoneNumber??"",enabled:te.some(f=>f.name==="signal")},llm:Object.keys(k).length>0?{default:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...k}:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...U?{search:{provider:U,...Y?{apiKey:Y}:{},...ye?{baseUrl:ye}:{}}}:{},...gr&&Ce.length>0?{email:{accounts:Ce.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}})}}:{},...Le?{speech:{provider:Le,apiKey:je,...es?{baseUrl:es}:{},...ts?{ttsEnabled:!0,ttsVoice:ss}:{}}}:{},...lo?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...Je.length>0||Ze?{codeAgents:{enabled:Je.length>0,agents:Je,...Ze==="github"?{forge:{provider:"github",github:{token:rs}}}:Ze==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:os}}}:{}}}:{},...Tr?{proxmox:{baseUrl:is,tokenId:go,tokenSecret:as,verifyTls:yo}}:{},...cs?{unifi:{baseUrl:Tt,...et?{apiKey:et}:{username:To,password:ls},site:"default",verifyTls:bo}}:{},...Er?{homeassistant:{baseUrl:ds,accessToken:us,verifyTls:_o}}:{},..._r?{contacts:{provider:ve,...ve==="carddav"?{carddav:{serverUrl:ne.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:ne.ALFRED_CARDDAV_CONTACTS_USERNAME}}:ve==="google"?{google:{clientId:ne.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:ve==="microsoft"?{microsoft:{clientId:ne.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:ne.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...$r?{docker:{...tt?{socketPath:tt}:{},...st?{host:st}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};Te&&(ci.security.ownerUserId=Te);let dl="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Xn.dump(ci,{lineWidth:120,noRefs:!0,sortKeys:!1}),ul=ge.join(Sr,"default.yml");ce.writeFileSync(ul,dl,"utf-8"),console.log(` ${D("+")} ${E("config/default.yml")} written`);let Ao=ge.join(Sr,"rules");ce.existsSync(Ao)||ce.mkdirSync(Ao,{recursive:!0});let ml=ms&&Te?`
821
821
  # Allow admin actions (shell, etc.) for the owner only
822
822
  - id: allow-owner-admin
823
823
  effect: allow
@@ -851,7 +851,7 @@ rules:
851
851
  actions: ["*"]
852
852
  riskLevels: [read]
853
853
 
854
- ${ms?` # Allow write-level skills everywhere (DMs and groups)
854
+ ${ps?` # Allow write-level skills everywhere (DMs and groups)
855
855
  - id: allow-write-all
856
856
  effect: allow
857
857
  priority: 200
@@ -867,7 +867,7 @@ ${ms?` # Allow write-level skills everywhere (DMs and groups)
867
867
  conditions:
868
868
  chatType: dm`}
869
869
 
870
- # Rate-limit write actions: max ${br} per hour per user
870
+ # Rate-limit write actions: max ${vr} per hour per user
871
871
  - id: rate-limit-write
872
872
  effect: allow
873
873
  priority: 250
@@ -875,7 +875,7 @@ ${ms?` # Allow write-level skills everywhere (DMs and groups)
875
875
  actions: ["*"]
876
876
  riskLevels: [write]
877
877
  rateLimit:
878
- maxInvocations: ${br}
878
+ maxInvocations: ${vr}
879
879
  windowSeconds: 3600
880
880
  ${ml}
881
881
  # Deny destructive and admin actions by default
@@ -893,15 +893,15 @@ ${ml}
893
893
  scope: global
894
894
  actions: ["*"]
895
895
  riskLevels: [read, write, destructive, admin]
896
- `,fl=he.join(ko,"default-rules.yml");ce.writeFileSync(fl,pl,"utf-8"),console.log(` ${D("+")} ${E("config/rules/default-rules.yml")} written`);let ci=he.join(e,"data");ce.existsSync(ci)||(ce.mkdirSync(ci,{recursive:!0}),console.log(` ${D("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${to}${"=".repeat(52)}${v}`),console.log(`${to}${W} Setup complete!${v}`),console.log(`${to}${"=".repeat(52)}${v}`),console.log(""),console.log(` ${R("Bot name:")} ${r}`),console.log(` ${R("LLM default:")} ${a.name} (${w})`),l&&console.log(` ${R("API key:")} ${ue(l)}`);for(let[f,_]of Object.entries(k)){let $=f.charAt(0).toUpperCase()+f.slice(1);console.log(` ${R(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${_.provider} (${_.model})`)}if(X.length>0?console.log(` ${R("Platforms:")} ${X.map(f=>f.label).join(", ")}`):console.log(` ${R("Platforms:")} none (configure later)`),P){let f={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${ge})`};console.log(` ${R("Web search:")} ${f[P]}`)}else console.log(` ${R("Web search:")} ${E("disabled")}`);if(pr&&Re.length>0){let f=Re.map(_=>_.provider==="microsoft"?`${_.name} (Microsoft 365)${_.msClientId?"":" \u2014 shared from Calendar"}`:`${_.name} (${_.imapHost})`);console.log(` ${R("Email:")} ${f.join(", ")}`)}else console.log(` ${R("Email:")} ${E("disabled")}`);if(Ce){let f={openai:"OpenAI Whisper",groq:"Groq Whisper"},_=es?`, TTS: ${ts}`:"";console.log(` ${R("Voice:")} ${f[Ce]}${_}`)}else console.log(` ${R("Voice:")} ${E("disabled")}`);console.log(` ${R("Code Sandbox:")} ${co?D("enabled"):E("disabled")}`),gr&&console.log(` ${R("Proxmox:")} ${D(ns)}`),as&&console.log(` ${R("UniFi:")} ${D(yt)}`),wr&&console.log(` ${R("Home Assist.:")} ${D(ls)}`),Tr&&console.log(` ${R("Contacts:")} ${D($e)}`),Er&&console.log(` ${R("Docker:")} ${D(Qe||Ze)}`),Te&&(console.log(` ${R("Owner ID:")} ${Te}`),console.log(` ${R("Shell access:")} ${us?D("enabled"):E("disabled")}`)),console.log(` ${R("Write scope:")} ${ms?"DMs + Groups":"DMs only"}`),console.log(` ${R("Rate limit:")} ${br}/hour per user`),console.log(""),console.log(`${so}Next steps:${v}`),console.log(` ${R("alfred start")} Start Alfred`),console.log(` ${R("alfred status")} Check configuration`),console.log(` ${R("alfred --help")} Show all commands`),console.log(""),console.log(`${Ge}Edit ${R(".env")}${Ge} or ${R("config/default.yml")}${Ge} for manual configuration.${v}`),console.log("")}finally{c.close()}}async function U(c,e,t){let s=(await c.question(`${W}${e}${v} ${E(`[${t}]`)}: ${M}`)).trim();return process.stdout.write(v),s||t}async function be(c,e){for(;;){let t=(await c.question(`${W}${e}${v}: ${M}`)).trim();if(process.stdout.write(v),t)return t;console.log(` ${Dc("!")} This field is required. Please enter a value.`)}}async function ur(c,e,t,s,r){for(;;){let o=(await c.question(`${M}${e}${v}`)).trim();if(!o)return r;let n=parseInt(o,10);if(!Number.isNaN(n)&&n>=t&&n<=s)return n;console.log(` ${Dc("!")} Please enter a number between ${t} and ${s}.`)}}function Nu(){console.log(`
897
- ${xu}${W} _ _ _____ ____ _____ ____
896
+ `,fl=ge.join(Ao,"default-rules.yml");ce.writeFileSync(fl,pl,"utf-8"),console.log(` ${D("+")} ${E("config/rules/default-rules.yml")} written`);let li=ge.join(e,"data");ce.existsSync(li)||(ce.mkdirSync(li,{recursive:!0}),console.log(` ${D("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${oo}${"=".repeat(52)}${S}`),console.log(`${oo}${V} Setup complete!${S}`),console.log(`${oo}${"=".repeat(52)}${S}`),console.log(""),console.log(` ${R("Bot name:")} ${r}`),console.log(` ${R("LLM default:")} ${a.name} (${y})`),l&&console.log(` ${R("API key:")} ${me(l)}`);for(let[f,_]of Object.entries(k)){let $=f.charAt(0).toUpperCase()+f.slice(1);console.log(` ${R(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${_.provider} (${_.model})`)}if(te.length>0?console.log(` ${R("Platforms:")} ${te.map(f=>f.label).join(", ")}`):console.log(` ${R("Platforms:")} none (configure later)`),U){let f={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${ye})`};console.log(` ${R("Web search:")} ${f[U]}`)}else console.log(` ${R("Web search:")} ${E("disabled")}`);if(gr&&Ce.length>0){let f=Ce.map(_=>_.provider==="microsoft"?`${_.name} (Microsoft 365)${_.msClientId?"":" \u2014 shared from Calendar"}`:`${_.name} (${_.imapHost})`);console.log(` ${R("Email:")} ${f.join(", ")}`)}else console.log(` ${R("Email:")} ${E("disabled")}`);if(Le){let f={openai:"OpenAI Whisper",groq:"Groq Whisper"},_=ts?`, TTS: ${ss}`:"";console.log(` ${R("Voice:")} ${f[Le]}${_}`)}else console.log(` ${R("Voice:")} ${E("disabled")}`);console.log(` ${R("Code Sandbox:")} ${lo?D("enabled"):E("disabled")}`),Tr&&console.log(` ${R("Proxmox:")} ${D(is)}`),cs&&console.log(` ${R("UniFi:")} ${D(Tt)}`),Er&&console.log(` ${R("Home Assist.:")} ${D(ds)}`),_r&&console.log(` ${R("Contacts:")} ${D(ve)}`),$r&&console.log(` ${R("Docker:")} ${D(st||tt)}`),Te&&(console.log(` ${R("Owner ID:")} ${Te}`),console.log(` ${R("Shell access:")} ${ms?D("enabled"):E("disabled")}`)),console.log(` ${R("Write scope:")} ${ps?"DMs + Groups":"DMs only"}`),console.log(` ${R("Rate limit:")} ${vr}/hour per user`),console.log(""),console.log(`${no}Next steps:${S}`),console.log(` ${R("alfred start")} Start Alfred`),console.log(` ${R("alfred status")} Check configuration`),console.log(` ${R("alfred --help")} Show all commands`),console.log(""),console.log(`${Xe}Edit ${R(".env")}${Xe} or ${R("config/default.yml")}${Xe} for manual configuration.${S}`),console.log("")}finally{c.close()}}async function P(c,e,t){let s=(await c.question(`${V}${e}${S} ${E(`[${t}]`)}: ${M}`)).trim();return process.stdout.write(S),s||t}async function Ee(c,e){for(;;){let t=(await c.question(`${V}${e}${S}: ${M}`)).trim();if(process.stdout.write(S),t)return t;console.log(` ${Oc("!")} This field is required. Please enter a value.`)}}async function mr(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(` ${Oc("!")} Please enter a number between ${t} and ${s}.`)}}function Mu(){console.log(`
897
+ ${Iu}${V} _ _ _____ ____ _____ ____
898
898
  / \\ | | | ___| _ \\| ____| _ \\
899
899
  / _ \\ | | | |_ | |_) | _| | | | |
900
900
  / ___ \\| |___| _| | _ <| |___| |_| |
901
- /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${v}
902
- ${Ge} Personal AI Assistant \u2014 Setup Wizard${v}
903
- `)}var v,W,Ge,to,M,so,Au,xu,We,Jt,Mc,Uc=y(()=>{"use strict";v="\x1B[0m",W="\x1B[1m",Ge="\x1B[2m",to="\x1B[32m",M="\x1B[33m",so="\x1B[36m",Au="\x1B[31m",xu="\x1B[35m";u(D,"green");u(Iu,"yellow");u(fe,"cyan");u(Dc,"red");u(R,"bold");u(E,"dim");u(ue,"maskKey");We=[{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"}]}],Jt=[{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(Ru,"findCommand");Mc=[{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(Cu,"loadExistingConfig");u(Lu,"setupCommand");u(U,"askWithDefault");u(be,"askRequired");u(ur,"askNumber");u(Nu,"printBanner")});var Fc={};ie(Fc,{configCommand:()=>Uu});function Du(c){let e=c.toLowerCase();return Mu.some(t=>e.includes(t))}function Ou(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function Pc(c){let e={};for(let[t,s]of Object.entries(c))Du(t)?e[t]=Ou(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Pc(s):e[t]=s;return e}async function Uu(){let c=new ae,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Pc(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Mu,jc=y(()=>{"use strict";Be();Mu=["token","apikey","api_key","accesstoken","secret","password"];u(Du,"isSensitiveKey");u(Ou,"redactValue");u(Pc,"redactObject");u(Uu,"configCommand")});var qc={};ie(qc,{rulesCommand:()=>Fu});import ro from"node:fs";import Bc from"node:path";import Pu from"js-yaml";async function Fu(){let c=new ae,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Bc.resolve(e.security.rulesPath);if(!ro.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}ro.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=ro.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 nt,n=[],i=[];for(let a of r){let l=Bc.join(t,a);try{let d=ro.readFileSync(l,"utf-8"),m=Pu.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 Hc=y(()=>{"use strict";Be();Sr();u(Fu,"rulesCommand")});var zc={};ie(zc,{statusCommand:()=>Bu});import mr from"node:fs";import Xn from"node:path";import ju from"js-yaml";async function Bu(){let c=new ae,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=Xn.resolve(e.storage.path),o=mr.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${o?"exists":"not yet created"}`),console.log("");let n=Xn.resolve(e.security.rulesPath),i=0,a=0;if(mr.existsSync(n)&&mr.statSync(n).isDirectory()){let l=mr.readdirSync(n).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new nt;for(let m of l){let p=Xn.join(n,m);try{let T=mr.readFileSync(p,"utf-8"),w=ju.load(T),g=d.loadFromObject(w);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 Vc=y(()=>{"use strict";Be();Sr();u(Bu,"statusCommand")});var Wc={};ie(Wc,{logsCommand:()=>zu});import qu from"node:fs";import Hu from"node:path";async function zu(c){let e=new ae,t;try{t=e.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let s=Hu.resolve(t.storage.path);if(!qu.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 tt(s);let o=new st(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 Gc=y(()=>{"use strict";Be();Po();u(zu,"logsCommand")});import{readFileSync as Vu}from"node:fs";import{fileURLToPath as Wu}from"node:url";import{dirname as Gu,join as Xu}from"node:path";function Ku(){try{let c=Gu(Wu(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Vu(Xu(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Ku,"getVersion");var Xc=Ku(),Kn=`
904
- Alfred CLI v${Xc}
901
+ /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${S}
902
+ ${Xe} Personal AI Assistant \u2014 Setup Wizard${S}
903
+ `)}var S,V,Xe,oo,M,no,xu,Iu,Ge,Qt,Dc,Pc=w(()=>{"use strict";S="\x1B[0m",V="\x1B[1m",Xe="\x1B[2m",oo="\x1B[32m",M="\x1B[33m",no="\x1B[36m",xu="\x1B[31m",Iu="\x1B[35m";u(D,"green");u(Ru,"yellow");u(he,"cyan");u(Oc,"red");u(R,"bold");u(E,"dim");u(me,"maskKey");Ge=[{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"}]}],Qt=[{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(Cu,"findCommand");Dc=[{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(Lu,"loadExistingConfig");u(Nu,"setupCommand");u(P,"askWithDefault");u(Ee,"askRequired");u(mr,"askNumber");u(Mu,"printBanner")});var jc={};ie(jc,{configCommand:()=>Pu});function Ou(c){let e=c.toLowerCase();return Du.some(t=>e.includes(t))}function Uu(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function Fc(c){let e={};for(let[t,s]of Object.entries(c))Ou(t)?e[t]=Uu(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Fc(s):e[t]=s;return e}async function Pu(){let c=new ae,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Fc(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Du,Bc=w(()=>{"use strict";qe();Du=["token","apikey","api_key","accesstoken","secret","password"];u(Ou,"isSensitiveKey");u(Uu,"redactValue");u(Fc,"redactObject");u(Pu,"configCommand")});var Hc={};ie(Hc,{rulesCommand:()=>ju});import io from"node:fs";import qc from"node:path";import Fu from"js-yaml";async function ju(){let c=new ae,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=qc.resolve(e.security.rulesPath);if(!io.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}io.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=io.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 ct,n=[],i=[];for(let a of r){let l=qc.join(t,a);try{let d=io.readFileSync(l,"utf-8"),m=Fu.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 zc=w(()=>{"use strict";qe();xr();u(ju,"rulesCommand")});var Vc={};ie(Vc,{statusCommand:()=>qu});import pr from"node:fs";import Kn from"node:path";import Bu from"js-yaml";async function qu(){let c=new ae,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=Kn.resolve(e.storage.path),o=pr.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${o?"exists":"not yet created"}`),console.log("");let n=Kn.resolve(e.security.rulesPath),i=0,a=0;if(pr.existsSync(n)&&pr.statSync(n).isDirectory()){let l=pr.readdirSync(n).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new ct;for(let m of l){let p=Kn.join(n,m);try{let T=pr.readFileSync(p,"utf-8"),y=Bu.load(T),g=d.loadFromObject(y);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 Wc=w(()=>{"use strict";qe();xr();u(qu,"statusCommand")});var Gc={};ie(Gc,{logsCommand:()=>Vu});import Hu from"node:fs";import zu from"node:path";async function Vu(c){let e=new ae,t;try{t=e.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let s=zu.resolve(t.storage.path);if(!Hu.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 ot(s);let o=new nt(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 Xc=w(()=>{"use strict";qe();Fo();u(Vu,"logsCommand")});import{readFileSync as Wu}from"node:fs";import{fileURLToPath as Gu}from"node:url";import{dirname as Xu,join as Ku}from"node:path";function Yu(){try{let c=Xu(Gu(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Wu(Ku(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Yu,"getVersion");var Kc=Yu(),Yn=`
904
+ Alfred CLI v${Kc}
905
905
  Personal AI Assistant
906
906
 
907
907
  Usage:
@@ -919,4 +919,4 @@ Commands:
919
919
  Options:
920
920
  --help, -h Show this help message
921
921
  --version, -v Show version number
922
- `.trim();function Yu(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(Yu,"parseArgs");async function Ju(){let c=Yu(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(Kn),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Xc}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(Rc(),Ic));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(Nc(),Lc));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(()=>(Uc(),Oc));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(jc(),Fc));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(Hc(),qc));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(Vc(),zc));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(()=>(Gc(),Wc));await s(t);break}case"help":console.log(Kn);break;case"":console.log(Kn),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(Ju,"main");Ju().catch(c=>{console.error("Fatal error:",c),process.exit(1)});
922
+ `.trim();function Ju(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(Ju,"parseArgs");async function Zu(){let c=Ju(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(Yn),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Kc}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(Cc(),Rc));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(Mc(),Nc));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(()=>(Pc(),Uc));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(Bc(),jc));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(zc(),Hc));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(Wc(),Vc));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(()=>(Xc(),Gc));await s(t);break}case"help":console.log(Yn);break;case"":console.log(Yn),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(Zu,"main");Zu().catch(c=>{console.error("Fatal error:",c),process.exit(1)});