@madh-io/alfred-ai 0.9.53 → 0.9.56

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 +195 -169
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0});var b=(c,e)=>()=>(c&&(e=c(c=0)),e);var le=(c,e)=>{for(var t in e)po(c,t,{get:e[t],enumerable:!0})};import{z as w}from"zod";var mo,ho,fo,go,yo,wo,bo,To,Pe,za,Ka,Ga,Ya,Ja,Za,Qa,ec,tc,sc,rc,nc,oc,ic,ac,cc,lc,dc,uc,pc,mc,Br,qr=b(()=>{"use strict";mo=w.object({token:w.string().optional(),enabled:w.boolean()}),ho=w.object({token:w.string().optional(),enabled:w.boolean()}),fo=w.object({enabled:w.boolean(),dataPath:w.string()}),go=w.object({homeserverUrl:w.string(),accessToken:w.string().optional(),userId:w.string().optional(),enabled:w.boolean()}),yo=w.object({apiUrl:w.string(),phoneNumber:w.string().optional(),enabled:w.boolean()}),wo=w.object({path:w.string()}),bo=w.object({level:w.enum(["trace","debug","info","warn","error","fatal"]),pretty:w.boolean(),auditLogPath:w.string().optional()}),To=w.object({rulesPath:w.string(),defaultEffect:w.enum(["allow","deny"]),ownerUserId:w.string().optional()}),Pe=w.object({provider:w.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:w.string().optional(),baseUrl:w.string().optional(),model:w.string(),temperature:w.number().optional(),maxTokens:w.number().optional()}),za=w.object({default:Pe,strong:Pe.optional(),fast:Pe.optional(),embeddings:Pe.optional(),local:Pe.optional()}),Ka=w.union([Pe,za]),Ga=w.object({provider:w.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:w.string().optional(),baseUrl:w.string().optional()}),Ya=w.object({imap:w.object({host:w.string(),port:w.number(),secure:w.boolean()}),smtp:w.object({host:w.string(),port:w.number(),secure:w.boolean()}),auth:w.object({user:w.string(),pass:w.string()})}),Ja=w.object({provider:w.enum(["openai","groq","google"]),apiKey:w.string(),baseUrl:w.string().optional(),ttsEnabled:w.boolean().optional(),ttsModel:w.string().optional(),ttsVoice:w.string().optional()}),Za=w.object({serverUrl:w.string(),username:w.string(),password:w.string()}),Qa=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),ec=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),tc=w.object({provider:w.enum(["caldav","google","microsoft"]),caldav:Za.optional(),google:Qa.optional(),microsoft:ec.optional()}),sc=w.object({name:w.string(),command:w.string().optional(),args:w.array(w.string()).optional(),env:w.record(w.string()).optional(),url:w.string().optional()}),rc=w.object({servers:w.array(sc)}),nc=w.object({enabled:w.boolean(),allowedLanguages:w.array(w.enum(["javascript","python"])).optional(),maxTimeoutMs:w.number().optional(),allowNetwork:w.boolean().optional()}),oc=w.object({enabled:w.boolean().optional(),minMessageLength:w.number().optional(),minConfidence:w.number().min(0).max(1).optional(),maxExtractionsPerMinute:w.number().optional()}),ic=w.object({enabled:w.boolean(),port:w.coerce.number().int().min(1).max(65535),host:w.string()}),ac=w.object({name:w.string(),command:w.string(),argsTemplate:w.array(w.string()),promptVia:w.enum(["arg","stdin"]).default("arg"),env:w.record(w.string()).optional(),cwd:w.string().optional(),timeoutMs:w.number().max(9e5).optional()}),cc=w.object({token:w.string(),baseUrl:w.string().optional()}),lc=w.object({token:w.string(),baseUrl:w.string().optional()}),dc=w.object({provider:w.enum(["github","gitlab"]),baseBranch:w.string().optional(),github:cc.optional(),gitlab:lc.optional()}),uc=w.object({enabled:w.boolean(),agents:w.array(ac),forge:dc.optional()}),pc=w.object({baseUrl:w.string(),tokenId:w.string(),tokenSecret:w.string(),verifyTls:w.boolean().optional(),defaultNode:w.string().optional()}),mc=w.object({baseUrl:w.string(),apiKey:w.string().optional(),username:w.string().optional(),password:w.string().optional(),site:w.string().optional(),verifyTls:w.boolean().optional()}),Br=w.object({name:w.string(),telegram:mo,discord:ho.optional(),whatsapp:fo.optional(),matrix:go.optional(),signal:yo.optional(),llm:Ka,storage:wo,logger:bo,security:To,search:Ga.optional(),email:Ya.optional(),speech:Ja.optional(),calendar:tc.optional(),mcp:rc.optional(),codeSandbox:nc.optional(),activeLearning:oc.optional(),api:ic.optional(),codeAgents:uc.optional(),proxmox:pc.optional(),unifi:mc.optional()})});var Wr,Xr=b(()=>{"use strict";Wr={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 Eo from"node:fs";import hc from"node:path";import{config as _o}from"dotenv";import fc from"js-yaml";function vo(c,e){let t={...c};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=vo(n,r):t[s]=r}return t}function yc(c){let e={...c};for(let[t,s]of Object.entries(gc)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function Hr(){_o({override:!0})}var gc,Q,ko=b(()=>{"use strict";qr();Xr();u(vo,"deepMerge");gc={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_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],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"]};u(yc,"applyEnvOverrides");u(Hr,"reloadDotenv");Q=class{static{u(this,"ConfigLoader")}loadConfig(e){_o();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=hc.resolve(t);if(Eo.existsSync(r)){let l=Eo.readFileSync(r,"utf-8"),d=fc.load(l);d&&typeof d=="object"&&(s=d)}let n=vo(Wr,s),o=yc(n),i=Br.parse(o),a=i.llm;return a&&"provider"in a&&(i.llm={default:a}),i}}});var xe=b(()=>{"use strict";qr();Xr();ko()});import Vr from"pino";function qt(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Vr.transport({target:"pino-pretty",options:{colorize:!0}});return Vr({name:c,level:t},r)}return Vr({name:c,level:t})}var $o=b(()=>{"use strict";u(qt,"createLogger")});import Fd from"pino";var So=b(()=>{"use strict"});var zr=b(()=>{"use strict";$o();So()});var Ze,Ks=b(()=>{"use strict";Ze=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var xo=Object.defineProperty;var u=(c,e)=>xo(c,"name",{value:e,configurable:!0});var w=(c,e)=>()=>(c&&(e=c(c=0)),e);var oe=(c,e)=>{for(var t in e)xo(c,t,{get:e[t],enumerable:!0})};import{z as f}from"zod";var Ao,Ro,Lo,Mo,No,Co,Oo,Do,He,yc,wc,bc,Io,Tc,Ec,_c,$c,vc,kc,Sc,xc,Ic,Ac,Rc,Lc,Mc,Nc,Cc,Oc,Dc,Uc,Pc,Qr,en=w(()=>{"use strict";Ao=f.object({token:f.string().optional(),enabled:f.boolean()}),Ro=f.object({token:f.string().optional(),enabled:f.boolean()}),Lo=f.object({enabled:f.boolean(),dataPath:f.string()}),Mo=f.object({homeserverUrl:f.string(),accessToken:f.string().optional(),userId:f.string().optional(),enabled:f.boolean()}),No=f.object({apiUrl:f.string(),phoneNumber:f.string().optional(),enabled:f.boolean()}),Co=f.object({path:f.string()}),Oo=f.object({level:f.enum(["trace","debug","info","warn","error","fatal"]),pretty:f.boolean(),auditLogPath:f.string().optional()}),Do=f.object({rulesPath:f.string(),defaultEffect:f.enum(["allow","deny"]),ownerUserId:f.string().optional()}),He=f.object({provider:f.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:f.string().optional(),baseUrl:f.string().optional(),model:f.string(),temperature:f.number().optional(),maxTokens:f.number().optional()}),yc=f.object({default:He,strong:He.optional(),fast:He.optional(),embeddings:He.optional(),local:He.optional()}),wc=f.union([He,yc]),bc=f.object({provider:f.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:f.string().optional(),baseUrl:f.string().optional()}),Io=f.object({name:f.string().optional(),provider:f.enum(["imap-smtp","microsoft"]).optional(),imap:f.object({host:f.string(),port:f.number(),secure:f.boolean()}).optional(),smtp:f.object({host:f.string(),port:f.number(),secure:f.boolean()}).optional(),auth:f.object({user:f.string(),pass:f.string()}).optional(),microsoft:f.object({clientId:f.string(),clientSecret:f.string(),tenantId:f.string(),refreshToken:f.string()}).optional()}),Tc=f.union([f.object({accounts:f.array(Io)}),Io]),Ec=f.object({provider:f.enum(["openai","groq","google"]),apiKey:f.string(),baseUrl:f.string().optional(),ttsEnabled:f.boolean().optional(),ttsModel:f.string().optional(),ttsVoice:f.string().optional()}),_c=f.object({serverUrl:f.string(),username:f.string(),password:f.string()}),$c=f.object({clientId:f.string(),clientSecret:f.string(),refreshToken:f.string()}),vc=f.object({clientId:f.string(),clientSecret:f.string(),tenantId:f.string(),refreshToken:f.string()}),kc=f.object({provider:f.enum(["caldav","google","microsoft"]),caldav:_c.optional(),google:$c.optional(),microsoft:vc.optional()}),Sc=f.object({name:f.string(),command:f.string().optional(),args:f.array(f.string()).optional(),env:f.record(f.string()).optional(),url:f.string().optional()}),xc=f.object({servers:f.array(Sc)}),Ic=f.object({enabled:f.boolean(),allowedLanguages:f.array(f.enum(["javascript","python"])).optional(),maxTimeoutMs:f.number().optional(),allowNetwork:f.boolean().optional()}),Ac=f.object({enabled:f.boolean().optional(),minMessageLength:f.number().optional(),minConfidence:f.number().min(0).max(1).optional(),maxExtractionsPerMinute:f.number().optional()}),Rc=f.object({enabled:f.boolean(),port:f.coerce.number().int().min(1).max(65535),host:f.string()}),Lc=f.object({name:f.string(),command:f.string(),argsTemplate:f.array(f.string()),promptVia:f.enum(["arg","stdin"]).default("arg"),env:f.record(f.string()).optional(),cwd:f.string().optional(),timeoutMs:f.number().max(9e5).optional()}),Mc=f.object({token:f.string(),baseUrl:f.string().optional()}),Nc=f.object({token:f.string(),baseUrl:f.string().optional()}),Cc=f.object({provider:f.enum(["github","gitlab"]),baseBranch:f.string().optional(),github:Mc.optional(),gitlab:Nc.optional()}),Oc=f.object({enabled:f.boolean(),agents:f.array(Lc),forge:Cc.optional()}),Dc=f.object({baseUrl:f.string(),tokenId:f.string(),tokenSecret:f.string(),verifyTls:f.boolean().optional(),defaultNode:f.string().optional()}),Uc=f.object({baseUrl:f.string(),apiKey:f.string().optional(),username:f.string().optional(),password:f.string().optional(),site:f.string().optional(),verifyTls:f.boolean().optional()}),Pc=f.object({baseUrl:f.string(),accessToken:f.string(),verifyTls:f.boolean().optional()}),Qr=f.object({name:f.string(),telegram:Ao,discord:Ro.optional(),whatsapp:Lo.optional(),matrix:Mo.optional(),signal:No.optional(),llm:wc,storage:Co,logger:Oo,security:Do,search:bc.optional(),email:Tc.optional(),speech:Ec.optional(),calendar:kc.optional(),mcp:xc.optional(),codeSandbox:Ic.optional(),activeLearning:Ac.optional(),api:Rc.optional(),codeAgents:Oc.optional(),proxmox:Dc.optional(),unifi:Uc.optional(),homeassistant:Pc.optional()})});var tn,sn=w(()=>{"use strict";tn={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"}}});import Uo from"node:fs";import Fc from"node:path";import{config as Po}from"dotenv";import jc from"js-yaml";function Fo(c,e){let t={...c};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=Fo(n,r):t[s]=r}return t}function qc(c){let e={...c};for(let[t,s]of Object.entries(Bc)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function rn(){Po({override:!0})}var Bc,te,jo=w(()=>{"use strict";en();sn();u(Fo,"deepMerge");Bc={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"]};u(qc,"applyEnvOverrides");u(rn,"reloadDotenv");te=class{static{u(this,"ConfigLoader")}loadConfig(e){Po();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Fc.resolve(t);if(Uo.existsSync(r)){let d=Uo.readFileSync(r,"utf-8"),m=jc.load(d);m&&typeof m=="object"&&(s=m)}let n=Fo(tn,s),o=qc(n),i=Qr.parse(o),a=i.llm;a&&"provider"in a&&(i.llm={default:a});let l=i.email;return l&&!("accounts"in l)&&(i.email={accounts:[{name:"default",...l}]}),i}}});var Le=w(()=>{"use strict";en();sn();jo()});import nn from"pino";function Jt(c,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=nn.transport({target:"pino-pretty",options:{colorize:!0}});return nn({name:c,level:t},r)}return nn({name:c,level:t})}var Bo=w(()=>{"use strict";u(Jt,"createLogger")});import du from"pino";var qo=w(()=>{"use strict"});var on=w(()=>{"use strict";Bo();qo()});var ot,er=w(()=>{"use strict";ot=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
3
3
  CREATE TABLE IF NOT EXISTS _migrations (
4
4
  version INTEGER PRIMARY KEY,
5
5
  description TEXT,
6
6
  applied_at TEXT NOT NULL
7
7
  )
8
- `)}getCurrentVersion(){return this.db.prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}migrate(e){let t=[...e].sort((r,n)=>r.version-n.version),s=this.getCurrentVersion();for(let r of t){if(r.version<=s)continue;this.db.transaction(()=>{r.up(this.db),this.db.prepare("INSERT INTO _migrations (version, description, applied_at) VALUES (?, ?, ?)").run(r.version,r.description,new Date().toISOString())})()}}getAppliedMigrations(){return this.db.prepare("SELECT version, applied_at FROM _migrations ORDER BY version ASC").all().map(t=>({version:t.version,appliedAt:t.applied_at}))}}});var Kr,Gr=b(()=>{"use strict";Ks();Kr=[{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,n)=>r.version-n.version),s=this.getCurrentVersion();for(let r of t){if(r.version<=s)continue;this.db.transaction(()=>{r.up(this.db),this.db.prepare("INSERT INTO _migrations (version, description, applied_at) VALUES (?, ?, ?)").run(r.version,r.description,new Date().toISOString())})()}}getAppliedMigrations(){return this.db.prepare("SELECT version, applied_at FROM _migrations ORDER BY version ASC").all().map(t=>({version:t.version,appliedAt:t.applied_at}))}}});var an,cn=w(()=>{"use strict";er();an=[{version:1,description:"Initial schema \u2014 conversations, messages, users, audit_log",up(c){}},{version:2,description:"Add plugin_skills table for tracking loaded external plugins",up(c){c.exec(`
9
9
  CREATE TABLE IF NOT EXISTS plugin_skills (
10
10
  name TEXT PRIMARY KEY,
11
11
  file_path TEXT NOT NULL,
@@ -190,7 +190,7 @@ var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0})
190
190
  CREATE INDEX IF NOT EXISTS idx_audit_log_user_ts ON audit_log(user_id, timestamp);
191
191
  CREATE INDEX IF NOT EXISTS idx_background_tasks_status ON background_tasks(status);
192
192
  CREATE INDEX IF NOT EXISTS idx_background_tasks_user ON background_tasks(user_id);
193
- `)}}]});import wc from"better-sqlite3";import bc from"node:fs";import Tc from"node:path";var Fe,xo=b(()=>{"use strict";Ks();Gr();Fe=class{static{u(this,"Database")}db;constructor(e){let t=Tc.dirname(e);bc.mkdirSync(t,{recursive:!0}),this.db=new wc(e),this.db.pragma("journal_mode = WAL"),this.db.pragma("foreign_keys = ON"),this.db.pragma("busy_timeout = 5000"),this.initTables(),this.runMigrations()}initTables(){this.db.exec(`
193
+ `)}}]});import Hc from"better-sqlite3";import Wc from"node:fs";import Xc from"node:path";var We,Ho=w(()=>{"use strict";er();cn();We=class{static{u(this,"Database")}db;constructor(e){let t=Xc.dirname(e);Wc.mkdirSync(t,{recursive:!0}),this.db=new Hc(e),this.db.pragma("journal_mode = WAL"),this.db.pragma("foreign_keys = ON"),this.db.pragma("busy_timeout = 5000"),this.initTables(),this.runMigrations()}initTables(){this.db.exec(`
194
194
  CREATE TABLE IF NOT EXISTS conversations (
195
195
  id TEXT PRIMARY KEY,
196
196
  platform TEXT NOT NULL,
@@ -240,19 +240,19 @@ var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0})
240
240
 
241
241
  CREATE UNIQUE INDEX IF NOT EXISTS idx_users_platform
242
242
  ON users(platform, platform_user_id);
243
- `)}runMigrations(){new Ze(this.db).migrate(Kr)}getDb(){return this.db}close(){this.db.close()}}});import Io from"node:crypto";var Wt,Ao=b(()=>{"use strict";Wt=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Io.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
243
+ `)}runMigrations(){new ot(this.db).migrate(an)}getDb(){return this.db}close(){this.db.close()}}});import Wo from"node:crypto";var Zt,Xo=w(()=>{"use strict";Zt=class{static{u(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Wo.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
244
244
  INSERT INTO conversations (id, platform, chat_id, user_id, created_at, updated_at)
245
245
  VALUES (?, ?, ?, ?, ?, ?)
246
- `).run(n.id,n.platform,n.chatId,n.userId,n.createdAt,n.updatedAt),n}findById(e){let t=this.db.prepare("SELECT * FROM conversations WHERE id = ?").get(e);if(t)return this.mapRow(t)}findByPlatformChat(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND chat_id = ?").get(e,t);if(s)return this.mapRow(s)}findByPlatformAndUser(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND user_id = ? ORDER BY updated_at DESC LIMIT 1").get(e,t);if(s)return this.mapRow(s)}addMessage(e,t,s,r){let n={id:Io.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
246
+ `).run(n.id,n.platform,n.chatId,n.userId,n.createdAt,n.updatedAt),n}findById(e){let t=this.db.prepare("SELECT * FROM conversations WHERE id = ?").get(e);if(t)return this.mapRow(t)}findByPlatformChat(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND chat_id = ?").get(e,t);if(s)return this.mapRow(s)}findByPlatformAndUser(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND user_id = ? ORDER BY updated_at DESC LIMIT 1").get(e,t);if(s)return this.mapRow(s)}addMessage(e,t,s,r){let n={id:Wo.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
247
247
  INSERT INTO messages (id, conversation_id, role, content, tool_calls, created_at)
248
248
  VALUES (?, ?, ?, ?, ?, ?)
249
- `).run(n.id,n.conversationId,n.role,n.content,n.toolCalls??null,n.createdAt),n}getMessages(e,t=50){return this.db.prepare("SELECT * FROM (SELECT *, rowid AS _rn FROM messages WHERE conversation_id = ? ORDER BY created_at DESC, _rn DESC LIMIT ?) ORDER BY created_at ASC, _rn ASC").all(e,t).map(r=>({id:r.id,conversationId:r.conversation_id,role:r.role,content:r.content,toolCalls:r.tool_calls??void 0,createdAt:r.created_at}))}updateTimestamp(e){this.db.prepare("UPDATE conversations SET updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}mapRow(e){return{id:e.id,platform:e.platform,chatId:e.chat_id,userId:e.user_id,createdAt:e.created_at,updatedAt:e.updated_at}}}});import Ec from"node:crypto";var Xt,Ro=b(()=>{"use strict";Xt=class{static{u(this,"UserRepository")}db;constructor(e){this.db=e}findOrCreate(e,t,s,r){let n=this.db.prepare("SELECT * FROM users WHERE platform = ? AND platform_user_id = ?").get(e,t);if(n)return this.mapRow(n);let o=new Date().toISOString(),i={id:Ec.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:o,updatedAt:o};return this.db.prepare(`
249
+ `).run(n.id,n.conversationId,n.role,n.content,n.toolCalls??null,n.createdAt),n}getMessages(e,t=50){return this.db.prepare("SELECT * FROM (SELECT *, rowid AS _rn FROM messages WHERE conversation_id = ? ORDER BY created_at DESC, _rn DESC LIMIT ?) ORDER BY created_at ASC, _rn ASC").all(e,t).map(r=>({id:r.id,conversationId:r.conversation_id,role:r.role,content:r.content,toolCalls:r.tool_calls??void 0,createdAt:r.created_at}))}updateTimestamp(e){this.db.prepare("UPDATE conversations SET updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}mapRow(e){return{id:e.id,platform:e.platform,chatId:e.chat_id,userId:e.user_id,createdAt:e.created_at,updatedAt:e.updated_at}}}});import zc from"node:crypto";var Qt,zo=w(()=>{"use strict";Qt=class{static{u(this,"UserRepository")}db;constructor(e){this.db=e}findOrCreate(e,t,s,r){let n=this.db.prepare("SELECT * FROM users WHERE platform = ? AND platform_user_id = ?").get(e,t);if(n)return this.mapRow(n);let o=new Date().toISOString(),i={id:zc.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:o,updatedAt:o};return this.db.prepare(`
250
250
  INSERT INTO users (id, platform, platform_user_id, username, display_name, created_at, updated_at)
251
251
  VALUES (?, ?, ?, ?, ?, ?, ?)
252
- `).run(i.id,i.platform,i.platformUserId,i.username??null,i.displayName??null,i.createdAt,i.updatedAt),i}findById(e){let t=this.db.prepare("SELECT * FROM users WHERE id = ?").get(e);if(t)return this.mapRow(t)}update(e,t){let s=[],r=[];t.username!==void 0&&(s.push("username = ?"),r.push(t.username??null)),t.displayName!==void 0&&(s.push("display_name = ?"),r.push(t.displayName??null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}updateProfile(e,t){let s=[],r=[];t.timezone!==void 0&&(s.push("timezone = ?"),r.push(t.timezone??null)),t.language!==void 0&&(s.push("language = ?"),r.push(t.language??null)),t.bio!==void 0&&(s.push("bio = ?"),r.push(t.bio??null)),t.preferences!==void 0&&(s.push("preferences = ?"),r.push(t.preferences?JSON.stringify(t.preferences):null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}getProfile(e){let t=this.db.prepare("SELECT display_name, timezone, language, bio, preferences FROM users WHERE id = ?").get(e);if(t)return{displayName:t.display_name??void 0,timezone:t.timezone??void 0,language:t.language??void 0,bio:t.bio??void 0,preferences:t.preferences?JSON.parse(t.preferences):void 0}}setMasterUser(e,t){this.db.prepare("UPDATE users SET master_user_id = ?, updated_at = ? WHERE id = ?").run(t,new Date().toISOString(),e)}getLinkedUsers(e){return this.db.prepare("SELECT DISTINCT * FROM users WHERE master_user_id = ? OR id = ?").all(e,e).map(s=>this.mapRow(s))}findFirstByPlatformNotIn(e){let t=e.map(()=>"?").join(", "),s=this.db.prepare(`SELECT * FROM users WHERE platform NOT IN (${t}) LIMIT 1`).get(...e);if(s)return this.mapRow(s)}getMasterUserId(e){return this.db.prepare("SELECT master_user_id FROM users WHERE id = ?").get(e)?.master_user_id??e}mapRow(e){return{id:e.id,platform:e.platform,platformUserId:e.platform_user_id,username:e.username??void 0,displayName:e.display_name??void 0,timezone:e.timezone??void 0,language:e.language??void 0,bio:e.bio??void 0,preferences:e.preferences?JSON.parse(e.preferences):void 0,masterUserId:e.master_user_id??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}}});var je,Lo=b(()=>{"use strict";je=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
252
+ `).run(i.id,i.platform,i.platformUserId,i.username??null,i.displayName??null,i.createdAt,i.updatedAt),i}findById(e){let t=this.db.prepare("SELECT * FROM users WHERE id = ?").get(e);if(t)return this.mapRow(t)}update(e,t){let s=[],r=[];t.username!==void 0&&(s.push("username = ?"),r.push(t.username??null)),t.displayName!==void 0&&(s.push("display_name = ?"),r.push(t.displayName??null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}updateProfile(e,t){let s=[],r=[];t.timezone!==void 0&&(s.push("timezone = ?"),r.push(t.timezone??null)),t.language!==void 0&&(s.push("language = ?"),r.push(t.language??null)),t.bio!==void 0&&(s.push("bio = ?"),r.push(t.bio??null)),t.preferences!==void 0&&(s.push("preferences = ?"),r.push(t.preferences?JSON.stringify(t.preferences):null)),s.length!==0&&(s.push("updated_at = ?"),r.push(new Date().toISOString()),r.push(e),this.db.prepare(`UPDATE users SET ${s.join(", ")} WHERE id = ?`).run(...r))}getProfile(e){let t=this.db.prepare("SELECT display_name, timezone, language, bio, preferences FROM users WHERE id = ?").get(e);if(t)return{displayName:t.display_name??void 0,timezone:t.timezone??void 0,language:t.language??void 0,bio:t.bio??void 0,preferences:t.preferences?JSON.parse(t.preferences):void 0}}setMasterUser(e,t){this.db.prepare("UPDATE users SET master_user_id = ?, updated_at = ? WHERE id = ?").run(t,new Date().toISOString(),e)}getLinkedUsers(e){return this.db.prepare("SELECT DISTINCT * FROM users WHERE master_user_id = ? OR id = ?").all(e,e).map(s=>this.mapRow(s))}findFirstByPlatformNotIn(e){let t=e.map(()=>"?").join(", "),s=this.db.prepare(`SELECT * FROM users WHERE platform NOT IN (${t}) LIMIT 1`).get(...e);if(s)return this.mapRow(s)}getMasterUserId(e){return this.db.prepare("SELECT master_user_id FROM users WHERE id = ?").get(e)?.master_user_id??e}mapRow(e){return{id:e.id,platform:e.platform,platformUserId:e.platform_user_id,username:e.username??void 0,displayName:e.display_name??void 0,timezone:e.timezone??void 0,language:e.language??void 0,bio:e.bio??void 0,preferences:e.preferences?JSON.parse(e.preferences):void 0,masterUserId:e.master_user_id??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}}});var Xe,Vo=w(()=>{"use strict";Xe=class{static{u(this,"AuditRepository")}db;constructor(e){this.db=e}log(e){this.db.prepare(`
253
253
  INSERT INTO audit_log (id, timestamp, user_id, action, risk_level, rule_id, effect, platform, chat_id, context)
254
254
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
255
- `).run(e.id,e.timestamp.toISOString(),e.userId,e.action,e.riskLevel,e.ruleId??null,e.effect,e.platform,e.chatId??null,e.context?JSON.stringify(e.context):null)}query(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.action&&(t.push("action = ?"),s.push(e.action)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"",n=e.limit??100;return s.push(n),this.db.prepare(`SELECT * FROM audit_log ${r} ORDER BY timestamp DESC LIMIT ?`).all(...s).map(i=>this.mapRow(i))}count(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"";return this.db.prepare(`SELECT COUNT(*) as count FROM audit_log ${r}`).get(...s).count}mapRow(e){return{id:e.id,timestamp:new Date(e.timestamp),userId:e.user_id,action:e.action,riskLevel:e.risk_level,ruleId:e.rule_id??void 0,effect:e.effect,platform:e.platform,chatId:e.chat_id??void 0,context:e.context?JSON.parse(e.context):void 0}}}});import{randomUUID as _c}from"node:crypto";var Ht,Mo=b(()=>{"use strict";Ht=class{static{u(this,"MemoryRepository")}db;constructor(e){this.db=e}save(e,t,s,r="general"){return this.saveWithMetadata(e,t,s,r,"general",1,"manual")}saveWithMetadata(e,t,s,r,n,o,i){let a=new Date().toISOString(),l=_c();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
255
+ `).run(e.id,e.timestamp.toISOString(),e.userId,e.action,e.riskLevel,e.ruleId??null,e.effect,e.platform,e.chatId??null,e.context?JSON.stringify(e.context):null)}query(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.action&&(t.push("action = ?"),s.push(e.action)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"",n=e.limit??100;return s.push(n),this.db.prepare(`SELECT * FROM audit_log ${r} ORDER BY timestamp DESC LIMIT ?`).all(...s).map(i=>this.mapRow(i))}count(e){let t=[],s=[];e.userId&&(t.push("user_id = ?"),s.push(e.userId)),e.effect&&(t.push("effect = ?"),s.push(e.effect));let r=t.length>0?`WHERE ${t.join(" AND ")}`:"";return this.db.prepare(`SELECT COUNT(*) as count FROM audit_log ${r}`).get(...s).count}mapRow(e){return{id:e.id,timestamp:new Date(e.timestamp),userId:e.user_id,action:e.action,riskLevel:e.risk_level,ruleId:e.rule_id??void 0,effect:e.effect,platform:e.platform,chatId:e.chat_id??void 0,context:e.context?JSON.parse(e.context):void 0}}}});import{randomUUID as Vc}from"node:crypto";var es,Ko=w(()=>{"use strict";es=class{static{u(this,"MemoryRepository")}db;constructor(e){this.db=e}save(e,t,s,r="general"){return this.saveWithMetadata(e,t,s,r,"general",1,"manual")}saveWithMetadata(e,t,s,r,n,o,i){let a=new Date().toISOString(),l=Vc();this.db.prepare(`INSERT INTO memories (id, user_id, key, value, category, type, confidence, source, created_at, updated_at)
256
256
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
257
257
  ON CONFLICT(user_id, key) DO UPDATE SET
258
258
  value = excluded.value,
@@ -260,13 +260,13 @@ var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0})
260
260
  type = excluded.type,
261
261
  confidence = excluded.confidence,
262
262
  source = excluded.source,
263
- updated_at = excluded.updated_at`).run(l,e,t,s,r,n,o,i,a,a);let d=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(d)}recall(e,t){let s=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);if(s)return this.mapRow(s)}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND (key LIKE ? OR value LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}keywordSearch(e,t,s=20){let r=t.toLowerCase().split(/\s+/).filter(l=>l.length>=2);if(r.length===0)return[];let n=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),o=[e];for(let l of r)o.push(`%${l}%`,`%${l}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${n}) ORDER BY updated_at DESC`).all(...o).map(l=>{let d=this.mapRow(l),p=`${d.key} ${d.value}`.toLowerCase(),m=0;for(let g of r)p.includes(g)&&(m+=1);return{entry:d,score:m/r.length}});return a.sort((l,d)=>d.score-l.score),a.slice(0,s).map(l=>l.entry)}recordAccess(e){let t=new Date().toISOString();this.db.prepare("UPDATE memories SET last_accessed_at = ?, access_count = access_count + 1 WHERE id = ?").run(t,e)}findStale(e,t,s){let r=new Date(Date.now()-t*24*60*60*1e3).toISOString();return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND updated_at < ? AND confidence <= ? ORDER BY confidence ASC").all(e,r,s).map(o=>this.mapRow(o))}deleteByIds(e){if(e.length===0)return 0;let t=e.map(()=>"?").join(",");return this.db.prepare(`DELETE FROM memories WHERE id IN (${t})`).run(...e).changes}listByCategory(e,t){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND category = ? ORDER BY updated_at DESC").all(e,t).map(r=>this.mapRow(r))}listAll(e){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC").all(e).map(s=>this.mapRow(s))}delete(e,t){return this.db.prepare("DELETE FROM memories WHERE user_id = ? AND key = ?").run(e,t).changes>0}getRecentForPrompt(e,t=20){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}mapRow(e){return{id:e.id,userId:e.user_id,key:e.key,value:e.value,category:e.category||"general",type:e.type||"general",confidence:e.confidence??1,source:e.source||"manual",lastAccessedAt:e.last_accessed_at||null,accessCount:e.access_count??0,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as vc}from"node:crypto";var Vt,No=b(()=>{"use strict";Vt=class{static{u(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n){let o={id:vc(),userId:e,platform:t,chatId:s,message:r,triggerAt:n.toISOString(),createdAt:new Date().toISOString(),fired:!1};return this.db.prepare(`
263
+ updated_at = excluded.updated_at`).run(l,e,t,s,r,n,o,i,a,a);let d=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(d)}recall(e,t){let s=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);if(s)return this.mapRow(s)}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND (key LIKE ? OR value LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}keywordSearch(e,t,s=20){let r=t.toLowerCase().split(/\s+/).filter(l=>l.length>=2);if(r.length===0)return[];let n=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),o=[e];for(let l of r)o.push(`%${l}%`,`%${l}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${n}) ORDER BY updated_at DESC`).all(...o).map(l=>{let d=this.mapRow(l),m=`${d.key} ${d.value}`.toLowerCase(),h=0;for(let b of r)m.includes(b)&&(h+=1);return{entry:d,score:h/r.length}});return a.sort((l,d)=>d.score-l.score),a.slice(0,s).map(l=>l.entry)}recordAccess(e){let t=new Date().toISOString();this.db.prepare("UPDATE memories SET last_accessed_at = ?, access_count = access_count + 1 WHERE id = ?").run(t,e)}findStale(e,t,s){let r=new Date(Date.now()-t*24*60*60*1e3).toISOString();return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND updated_at < ? AND confidence <= ? ORDER BY confidence ASC").all(e,r,s).map(o=>this.mapRow(o))}deleteByIds(e){if(e.length===0)return 0;let t=e.map(()=>"?").join(",");return this.db.prepare(`DELETE FROM memories WHERE id IN (${t})`).run(...e).changes}listByCategory(e,t){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND category = ? ORDER BY updated_at DESC").all(e,t).map(r=>this.mapRow(r))}listAll(e){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC").all(e).map(s=>this.mapRow(s))}delete(e,t){return this.db.prepare("DELETE FROM memories WHERE user_id = ? AND key = ?").run(e,t).changes>0}getRecentForPrompt(e,t=20){return this.db.prepare("SELECT * FROM memories WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}mapRow(e){return{id:e.id,userId:e.user_id,key:e.key,value:e.value,category:e.category||"general",type:e.type||"general",confidence:e.confidence??1,source:e.source||"manual",lastAccessedAt:e.last_accessed_at||null,accessCount:e.access_count??0,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as Kc}from"node:crypto";var ts,Go=w(()=>{"use strict";ts=class{static{u(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n){let o={id:Kc(),userId:e,platform:t,chatId:s,message:r,triggerAt:n.toISOString(),createdAt:new Date().toISOString(),fired:!1};return this.db.prepare(`
264
264
  INSERT INTO reminders (id, user_id, platform, chat_id, message, trigger_at, created_at, fired)
265
265
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
266
- `).run(o.id,o.userId,o.platform,o.chatId,o.message,o.triggerAt,o.createdAt,0),o}getDue(){let e=new Date().toISOString();return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND trigger_at <= ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND user_id = ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}markFired(e){this.db.prepare("UPDATE reminders SET fired = 1 WHERE id = ?").run(e)}cancel(e){return this.db.prepare("DELETE FROM reminders WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,message:e.message,triggerAt:e.trigger_at,createdAt:e.created_at,fired:e.fired===1}}}});import{randomUUID as kc}from"node:crypto";var zt,Co=b(()=>{"use strict";zt=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),n=kc();return this.db.prepare("INSERT INTO notes (id, user_id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r,r),{id:n,userId:e,title:t,content:s,createdAt:r,updatedAt:r}}getById(e){let t=this.db.prepare("SELECT * FROM notes WHERE id = ?").get(e);return t?this.mapRow(t):void 0}list(e,t=50){return this.db.prepare("SELECT * FROM notes WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM notes WHERE user_id = ? AND (title LIKE ? OR content LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}update(e,t,s){let r=this.getById(e);if(!r)return;let n=new Date().toISOString(),o=t??r.title,i=s??r.content;return this.db.prepare("UPDATE notes SET title = ?, content = ?, updated_at = ? WHERE id = ?").run(o,i,n,e),{...r,title:o,content:i,updatedAt:n}}delete(e){return this.db.prepare("DELETE FROM notes WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,title:e.title,content:e.content,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as $c}from"node:crypto";var Kt,Oo=b(()=>{"use strict";Kt=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=$c(),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 Sc from"node:crypto";var Gt,Do=b(()=>{"use strict";Gt=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:Sc.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(`
266
+ `).run(o.id,o.userId,o.platform,o.chatId,o.message,o.triggerAt,o.createdAt,0),o}getDue(){let e=new Date().toISOString();return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND trigger_at <= ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}getByUser(e){return this.db.prepare("SELECT * FROM reminders WHERE fired = 0 AND user_id = ? ORDER BY trigger_at ASC").all(e).map(s=>this.mapRow(s))}markFired(e){this.db.prepare("UPDATE reminders SET fired = 1 WHERE id = ?").run(e)}cancel(e){return this.db.prepare("DELETE FROM reminders WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,message:e.message,triggerAt:e.trigger_at,createdAt:e.created_at,fired:e.fired===1}}}});import{randomUUID as Gc}from"node:crypto";var ss,Yo=w(()=>{"use strict";ss=class{static{u(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),n=Gc();return this.db.prepare("INSERT INTO notes (id, user_id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r,r),{id:n,userId:e,title:t,content:s,createdAt:r,updatedAt:r}}getById(e){let t=this.db.prepare("SELECT * FROM notes WHERE id = ?").get(e);return t?this.mapRow(t):void 0}list(e,t=50){return this.db.prepare("SELECT * FROM notes WHERE user_id = ? ORDER BY updated_at DESC LIMIT ?").all(e,t).map(r=>this.mapRow(r))}search(e,t){let s=`%${t}%`;return this.db.prepare("SELECT * FROM notes WHERE user_id = ? AND (title LIKE ? OR content LIKE ?) ORDER BY updated_at DESC").all(e,s,s).map(n=>this.mapRow(n))}update(e,t,s){let r=this.getById(e);if(!r)return;let n=new Date().toISOString(),o=t??r.title,i=s??r.content;return this.db.prepare("UPDATE notes SET title = ?, content = ?, updated_at = ? WHERE id = ?").run(o,i,n,e),{...r,title:o,content:i,updatedAt:n}}delete(e){return this.db.prepare("DELETE FROM notes WHERE id = ?").run(e).changes>0}mapRow(e){return{id:e.id,userId:e.user_id,title:e.title,content:e.content,createdAt:e.created_at,updatedAt:e.updated_at}}}});import{randomUUID as Yc}from"node:crypto";var rs,Jo=w(()=>{"use strict";rs=class{static{u(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=Yc(),s=new Date().toISOString(),r=Buffer.from(new Float32Array(e.embedding).buffer);return this.db.transaction(()=>{this.db.prepare("DELETE FROM embeddings WHERE user_id = ? AND source_type = ? AND source_id = ?").run(e.userId,e.sourceType,e.sourceId),this.db.prepare("INSERT INTO embeddings (id, user_id, source_type, source_id, content, embedding, model, dimensions, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)").run(t,e.userId,e.sourceType,e.sourceId,e.content,r,e.model,e.dimensions,s)})(),{id:t,userId:e.userId,sourceType:e.sourceType,sourceId:e.sourceId,content:e.content,embedding:e.embedding,model:e.model,dimensions:e.dimensions,createdAt:s}}findByUser(e){return this.db.prepare("SELECT * FROM embeddings WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapRow(s))}findBySource(e,t){let s=this.db.prepare("SELECT * FROM embeddings WHERE source_type = ? AND source_id = ?").get(e,t);if(s)return this.mapRow(s)}delete(e,t){return this.db.prepare("DELETE FROM embeddings WHERE source_type = ? AND source_id = ?").run(e,t).changes>0}mapRow(e){let t=e.embedding,s=new Float32Array(t.buffer,t.byteOffset,t.byteLength/4),r=Array.from(s);return{id:e.id,userId:e.user_id,sourceType:e.source_type,sourceId:e.source_id,content:e.content,embedding:r,model:e.model,dimensions:e.dimensions,createdAt:e.created_at}}}});import Jc from"node:crypto";var ns,Zo=w(()=>{"use strict";ns=class{static{u(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:Jc.randomUUID(),code:String(Math.floor(1e5+Math.random()*9e5)),userId:e,platform:t,createdAt:new Date().toISOString(),expiresAt:new Date(Date.now()+6e5).toISOString()};try{return this.db.prepare(`
267
267
  INSERT INTO link_tokens (id, code, user_id, platform, created_at, expires_at)
268
268
  VALUES (?, ?, ?, ?, ?, ?)
269
- `).run(r.id,r.code,r.userId,r.platform,r.createdAt,r.expiresAt),r}catch(n){if(!(n instanceof Error?n.message:"").includes("UNIQUE")||s===4)throw n}}throw new Error("Failed to generate unique link code after retries")}findByCode(e){let t=this.db.prepare("SELECT * FROM link_tokens WHERE code = ? AND expires_at > ?").get(e,new Date().toISOString());if(t)return{id:t.id,code:t.code,userId:t.user_id,platform:t.platform,createdAt:t.created_at,expiresAt:t.expires_at}}consume(e){this.db.prepare("DELETE FROM link_tokens WHERE id = ?").run(e)}countRecentByUser(e,t=10){let s=new Date(Date.now()-t*6e4).toISOString();return this.db.prepare("SELECT COUNT(*) as cnt FROM link_tokens WHERE user_id = ? AND created_at > ?").get(e,s).cnt}cleanup(){this.db.prepare("DELETE FROM link_tokens WHERE expires_at <= ?").run(new Date().toISOString())}}});import{randomUUID as xc}from"node:crypto";var Yt,Uo=b(()=>{"use strict";Yt=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n,o){let i={id:xc(),userId:e,platform:t,chatId:s,description:r,skillName:n,skillInput:o,status:"pending",createdAt:new Date().toISOString()};return this.db.prepare(`
269
+ `).run(r.id,r.code,r.userId,r.platform,r.createdAt,r.expiresAt),r}catch(n){if(!(n instanceof Error?n.message:"").includes("UNIQUE")||s===4)throw n}}throw new Error("Failed to generate unique link code after retries")}findByCode(e){let t=this.db.prepare("SELECT * FROM link_tokens WHERE code = ? AND expires_at > ?").get(e,new Date().toISOString());if(t)return{id:t.id,code:t.code,userId:t.user_id,platform:t.platform,createdAt:t.created_at,expiresAt:t.expires_at}}consume(e){this.db.prepare("DELETE FROM link_tokens WHERE id = ?").run(e)}countRecentByUser(e,t=10){let s=new Date(Date.now()-t*6e4).toISOString();return this.db.prepare("SELECT COUNT(*) as cnt FROM link_tokens WHERE user_id = ? AND created_at > ?").get(e,s).cnt}cleanup(){this.db.prepare("DELETE FROM link_tokens WHERE expires_at <= ?").run(new Date().toISOString())}}});import{randomUUID as Zc}from"node:crypto";var os,Qo=w(()=>{"use strict";os=class{static{u(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n,o){let i={id:Zc(),userId:e,platform:t,chatId:s,description:r,skillName:n,skillInput:o,status:"pending",createdAt:new Date().toISOString()};return this.db.prepare(`
270
270
  INSERT INTO background_tasks (id, user_id, platform, chat_id, description, skill_name, skill_input, status, created_at)
271
271
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
272
272
  `).run(i.id,i.userId,i.platform,i.chatId,i.description,i.skillName,i.skillInput,i.status,i.createdAt),i}updateStatus(e,t,s,r){let n=new Date().toISOString(),o=null,i=null;t==="running"&&(o=n),(t==="completed"||t==="failed")&&(i=n),this.db.prepare(`
@@ -282,7 +282,7 @@ var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0})
282
282
  AND (status IN ('pending', 'running') OR completed_at > datetime('now', '-1 day'))
283
283
  ORDER BY created_at DESC`).all(e).map(s=>this.mapRow(s))}cancel(e){return this.db.prepare("DELETE FROM background_tasks WHERE id = ? AND status IN ('pending', 'running')").run(e).changes>0}cleanup(e=7){return this.db.prepare(`DELETE FROM background_tasks
284
284
  WHERE status IN ('completed', 'failed')
285
- AND completed_at < datetime('now', '-' || ? || ' days')`).run(e).changes}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,description:e.description,skillName:e.skill_name,skillInput:e.skill_input,status:e.status,result:e.result,error:e.error,createdAt:e.created_at,startedAt:e.started_at,completedAt:e.completed_at}}}});import{randomUUID as Ic}from"node:crypto";var Jt,Po=b(()=>{"use strict";Jt=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Ic(),r=this.calculateInitialNextRun(e.scheduleType,e.scheduleValue);return this.db.prepare(`
285
+ AND completed_at < datetime('now', '-' || ? || ' days')`).run(e).changes}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,description:e.description,skillName:e.skill_name,skillInput:e.skill_input,status:e.status,result:e.result,error:e.error,createdAt:e.created_at,startedAt:e.started_at,completedAt:e.completed_at}}}});import{randomUUID as Qc}from"node:crypto";var is,ei=w(()=>{"use strict";is=class{static{u(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Qc(),r=this.calculateInitialNextRun(e.scheduleType,e.scheduleValue);return this.db.prepare(`
286
286
  INSERT INTO scheduled_actions
287
287
  (id, user_id, platform, chat_id, name, description, schedule_type, schedule_value,
288
288
  skill_name, skill_input, prompt_template, enabled, next_run_at, created_at)
@@ -293,9 +293,9 @@ var po=Object.defineProperty;var u=(c,e)=>po(c,"name",{value:e,configurable:!0})
293
293
  UPDATE scheduled_actions
294
294
  SET last_run_at = ?, next_run_at = ?
295
295
  WHERE id = ?
296
- `).run(t,s,e)}setEnabled(e,t){return this.db.prepare("UPDATE scheduled_actions SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM scheduled_actions WHERE id = ?").run(e).changes>0}calculateInitialNextRun(e,t){let s=new Date;switch(e){case"interval":{let r=parseInt(t,10);return isNaN(r)||r<=0?null:new Date(s.getTime()+r*6e4).toISOString()}case"once":return new Date(t).toISOString();case"cron":return this.getNextCronDate(t,s)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,name:e.name,description:e.description,scheduleType:e.schedule_type,scheduleValue:e.schedule_value,skillName:e.skill_name,skillInput:e.skill_input,promptTemplate:e.prompt_template,enabled:e.enabled===1,lastRunAt:e.last_run_at,nextRunAt:e.next_run_at,createdAt:e.created_at}}}});import{randomUUID as Fo}from"node:crypto";var Zt,jo=b(()=>{"use strict";Zt=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=Fo(),o=new Date().toISOString();return this.db.prepare("INSERT INTO documents (id, user_id, filename, mime_type, size_bytes, chunk_count, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)").run(n,e,t,s,r,o),{id:n,userId:e,filename:t,mimeType:s,sizeBytes:r,chunkCount:0,createdAt:o}}updateChunkCount(e,t){this.db.prepare("UPDATE documents SET chunk_count = ? WHERE id = ?").run(t,e)}addChunk(e,t,s,r){let n=Fo(),o=new Date().toISOString();return this.db.prepare("INSERT INTO document_chunks (id, document_id, chunk_index, content, embedding_id, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r??null,o),{id:n,documentId:e,chunkIndex:t,content:s,embeddingId:r,createdAt:o}}getDocument(e){let t=this.db.prepare("SELECT * FROM documents WHERE id = ?").get(e);return t?this.mapDocumentRow(t):void 0}getChunks(e){return this.db.prepare("SELECT * FROM document_chunks WHERE document_id = ? ORDER BY chunk_index ASC").all(e).map(s=>this.mapChunkRow(s))}listByUser(e){return this.db.prepare("SELECT * FROM documents WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapDocumentRow(s))}deleteDocument(e){this.db.transaction(()=>{let s=this.db.prepare("SELECT embedding_id FROM document_chunks WHERE document_id = ? AND embedding_id IS NOT NULL").all(e);if(s.length>0){let r=s.map(o=>o.embedding_id),n=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM embeddings WHERE id IN (${n})`).run(...r)}this.db.prepare("DELETE FROM document_chunks WHERE document_id = ?").run(e),this.db.prepare("DELETE FROM documents WHERE id = ?").run(e)})()}getChunksByEmbeddingIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT * FROM document_chunks WHERE embedding_id IN (${t}) ORDER BY chunk_index ASC`).all(...e).map(r=>this.mapChunkRow(r))}mapDocumentRow(e){return{id:e.id,userId:e.user_id,filename:e.filename,mimeType:e.mime_type,sizeBytes:e.size_bytes,chunkCount:e.chunk_count,createdAt:e.created_at}}mapChunkRow(e){return{id:e.id,documentId:e.document_id,chunkIndex:e.chunk_index,content:e.content,embeddingId:e.embedding_id||void 0,createdAt:e.created_at}}}});var Yr=b(()=>{"use strict";xo();Ao();Ro();Lo();Mo();Ks();Gr();No();Co();Oo();Do();Uo();Po();jo()});function Be(c){if(Jr[c])return Jr[c];let e=Object.entries(Jr).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var Jr,Ac,pe,Qe=b(()=>{"use strict";Jr={"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}},Ac={maxInputTokens:8192,maxOutputTokens:4096};u(Be,"lookupContextWindow");pe=class{static{u(this,"LLMProvider")}config;contextWindow=Ac;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import Rc from"@anthropic-ai/sdk";var Qt,Zr=b(()=>{"use strict";Qe();Qt=class extends pe{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Rc({apiKey:this.config.apiKey});let e=Be(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s},n=await this.client.messages.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=this.client.messages.stream({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s});for await(let n of r)if(n.type==="content_block_delta")n.delta.type==="text_delta"?yield{type:"text_delta",text:n.delta.text}:n.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:n.delta.partial_json}});else if(n.type==="content_block_start")n.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:n.content_block.id,name:n.content_block.name}});else if(n.type==="message_stop"){let o=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(o)}}}isAvailable(){return!!this.config.apiKey}mapMessages(e){return e.map(t=>{if(typeof t.content=="string")return{role:t.role,content:t.content};let s=t.content.map(r=>{switch(r.type){case"text":return{type:"text",text:r.text};case"image":return{type:"image",source:{type:"base64",media_type:r.source.media_type,data:r.source.data}};case"tool_use":return{type:"tool_use",id:r.id,name:r.name,input:r.input};case"tool_result":return{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content,is_error:r.is_error};default:return{type:"text",text:"[Unsupported block type]"}}}).filter(r=>r!==void 0);return{role:t.role,content:s}})}mapTools(e){return e.map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}mapResponse(e){let t="",s=[];for(let r of e.content)r.type==="text"?t+=r.text:r.type==="tool_use"&&s.push({id:r.id,name:r.name,input:r.input});return{content:t,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens},stopReason:e.stop_reason}}}});import Lc from"openai";var ce,qe=b(()=>{"use strict";Qe();ce=class extends pe{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Lc({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=Be(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",l=[],d=null,p=0,m=0;for await(let g of r){let f=g.choices[0];if(!f)continue;let h=f.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let T of h.tool_calls)if(T.id){if(n){let _;try{_=JSON.parse(i||"{}")}catch{_={}}l.push({id:n,name:o,input:_})}n=T.id,o=T.function?.name,i=T.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else T.function?.arguments&&(i+=T.function.arguments,yield{type:"tool_use_delta",toolCall:{input:T.function.arguments}});f.finish_reason&&(d=f.finish_reason),g.usage&&(p=g.usage.prompt_tokens,m=g.usage.completion_tokens)}if(n){let g;try{g=JSON.parse(i||"{}")}catch{g={}}l.push({id:n,name:o,input:g})}yield{type:"message_complete",response:{content:a,toolCalls:l.length>0?l:void 0,usage:{inputTokens:p,outputTokens:m},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(l=>l.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,toolCalls:n&&n.length>0?n:void 0,usage:{inputTokens:e.usage?.prompt_tokens??0,outputTokens:e.usage?.completion_tokens??0},stopReason:this.mapStopReason(t?.finish_reason??null)}}mapStopReason(e){switch(e){case"stop":return"end_turn";case"tool_calls":return"tool_use";case"length":return"max_tokens";default:return"end_turn"}}}});var es,Qr=b(()=>{"use strict";qe();es=class extends ce{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 ts,en=b(()=>{"use strict";Qe();ts=class extends pe{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=Be(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let g=await n.text();throw new Error(`Ollama API error (${n.status}): ${g}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",l="",d=0,p=0,m=[];try{for(;;){let{done:g,value:f}=await o.read();if(g)break;a+=i.decode(f,{stream:!0});let h=a.split(`
297
- `);a=h.pop()??"";for(let T of h){let _=T.trim();if(!_)continue;let x;try{x=JSON.parse(_)}catch{continue}if(x.message?.content&&(l+=x.message.content,yield{type:"text_delta",text:x.message.content}),x.message?.tool_calls)for(let k of x.message.tool_calls){let C={id:`ollama_tool_${m.length}`,name:k.function.name,input:k.function.arguments};m.push(C),yield{type:"tool_use_start",toolCall:{id:C.id,name:C.name}},yield{type:"tool_use_delta",toolCall:{input:C.input}}}x.done&&(d=x.prompt_eval_count??0,p=x.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:m.length>0?m:void 0,usage:{inputTokens:d,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let g;try{g=JSON.parse(a.trim())}catch{return}if(g.message?.content&&(l+=g.message.content,yield{type:"text_delta",text:g.message.content}),g.message?.tool_calls)for(let f of g.message.tool_calls){let h={id:`ollama_tool_${m.length}`,name:f.function.name,input:f.function.arguments};m.push(h),yield{type:"tool_use_start",toolCall:{id:h.id,name:h.name}},yield{type:"tool_use_delta",toolCall:{input:h.input}}}g.done&&(d=g.prompt_eval_count??0,p=g.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:m.length>0?m:void 0,usage:{inputTokens:d,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
298
- `)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var ss,tn=b(()=>{"use strict";qe();ss=class extends ce{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,sn=b(()=>{"use strict";qe();rs=class extends ce{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 ns,rn=b(()=>{"use strict";qe();ns=class extends ce{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 nn(c){switch(c.provider){case"anthropic":return new Qt(c);case"openai":return new ce(c);case"openrouter":return new es(c);case"ollama":return new ts(c);case"openwebui":return new ss(c);case"google":return new rs(c);case"mistral":return new ns(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var on=b(()=>{"use strict";Zr();qe();Qr();en();tn();sn();rn();u(nn,"createLLMProvider")});function an(c){return new Gs(c)}var Mc,Gs,Bo=b(()=>{"use strict";Qe();on();Mc=["default","strong","fast","embeddings","local"],Gs=class extends pe{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of Mc){let t=this.multiConfig[e];if(t){let s=nn(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(an,"createModelRouter")});function ye(c){return Math.ceil(c.length/3.5)}function is(c){if(typeof c.content=="string")return ye(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=ye(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=ye(t.name)+ye(JSON.stringify(t.input));break;case"tool_result":e+=ye(t.content);break}return e}var os,qo=b(()=>{"use strict";u(ye,"estimateTokens");u(is,"estimateMessageTokens");os=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
296
+ `).run(t,s,e)}setEnabled(e,t){return this.db.prepare("UPDATE scheduled_actions SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM scheduled_actions WHERE id = ?").run(e).changes>0}calculateInitialNextRun(e,t){let s=new Date;switch(e){case"interval":{let r=parseInt(t,10);return isNaN(r)||r<=0?null:new Date(s.getTime()+r*6e4).toISOString()}case"once":return new Date(t).toISOString();case"cron":return this.getNextCronDate(t,s)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,name:e.name,description:e.description,scheduleType:e.schedule_type,scheduleValue:e.schedule_value,skillName:e.skill_name,skillInput:e.skill_input,promptTemplate:e.prompt_template,enabled:e.enabled===1,lastRunAt:e.last_run_at,nextRunAt:e.next_run_at,createdAt:e.created_at}}}});import{randomUUID as ti}from"node:crypto";var as,si=w(()=>{"use strict";as=class{static{u(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=ti(),o=new Date().toISOString();return this.db.prepare("INSERT INTO documents (id, user_id, filename, mime_type, size_bytes, chunk_count, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)").run(n,e,t,s,r,o),{id:n,userId:e,filename:t,mimeType:s,sizeBytes:r,chunkCount:0,createdAt:o}}updateChunkCount(e,t){this.db.prepare("UPDATE documents SET chunk_count = ? WHERE id = ?").run(t,e)}addChunk(e,t,s,r){let n=ti(),o=new Date().toISOString();return this.db.prepare("INSERT INTO document_chunks (id, document_id, chunk_index, content, embedding_id, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r??null,o),{id:n,documentId:e,chunkIndex:t,content:s,embeddingId:r,createdAt:o}}getDocument(e){let t=this.db.prepare("SELECT * FROM documents WHERE id = ?").get(e);return t?this.mapDocumentRow(t):void 0}getChunks(e){return this.db.prepare("SELECT * FROM document_chunks WHERE document_id = ? ORDER BY chunk_index ASC").all(e).map(s=>this.mapChunkRow(s))}listByUser(e){return this.db.prepare("SELECT * FROM documents WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapDocumentRow(s))}deleteDocument(e){this.db.transaction(()=>{let s=this.db.prepare("SELECT embedding_id FROM document_chunks WHERE document_id = ? AND embedding_id IS NOT NULL").all(e);if(s.length>0){let r=s.map(o=>o.embedding_id),n=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM embeddings WHERE id IN (${n})`).run(...r)}this.db.prepare("DELETE FROM document_chunks WHERE document_id = ?").run(e),this.db.prepare("DELETE FROM documents WHERE id = ?").run(e)})()}getChunksByEmbeddingIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT * FROM document_chunks WHERE embedding_id IN (${t}) ORDER BY chunk_index ASC`).all(...e).map(r=>this.mapChunkRow(r))}mapDocumentRow(e){return{id:e.id,userId:e.user_id,filename:e.filename,mimeType:e.mime_type,sizeBytes:e.size_bytes,chunkCount:e.chunk_count,createdAt:e.created_at}}mapChunkRow(e){return{id:e.id,documentId:e.document_id,chunkIndex:e.chunk_index,content:e.content,embeddingId:e.embedding_id||void 0,createdAt:e.created_at}}}});var ln=w(()=>{"use strict";Ho();Xo();zo();Vo();Ko();er();cn();Go();Yo();Jo();Zo();Qo();ei();si()});function ze(c){if(dn[c])return dn[c];let e=Object.entries(dn).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(c.startsWith(t))return s}var dn,el,ge,it=w(()=>{"use strict";dn={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},mistral:{maxInputTokens:32e3,maxOutputTokens:4096},"mistral-small":{maxInputTokens:32e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"mistral-large-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"mistral-medium-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"mistral-small-latest":{maxInputTokens:128e3,maxOutputTokens:8192},"codestral-latest":{maxInputTokens:256e3,maxOutputTokens:8192},"magistral-medium-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"magistral-small-latest":{maxInputTokens:4e4,maxOutputTokens:8192},"ministral-8b-latest":{maxInputTokens:128e3,maxOutputTokens:4096}},el={maxInputTokens:8192,maxOutputTokens:4096};u(ze,"lookupContextWindow");ge=class{static{u(this,"LLMProvider")}config;contextWindow=el;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import tl from"@anthropic-ai/sdk";var cs,un=w(()=>{"use strict";it();cs=class extends ge{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new tl({apiKey:this.config.apiKey});let e=ze(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s},n=await this.client.messages.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=this.client.messages.stream({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s});for await(let n of r)if(n.type==="content_block_delta")n.delta.type==="text_delta"?yield{type:"text_delta",text:n.delta.text}:n.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:n.delta.partial_json}});else if(n.type==="content_block_start")n.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:n.content_block.id,name:n.content_block.name}});else if(n.type==="message_stop"){let o=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(o)}}}isAvailable(){return!!this.config.apiKey}mapMessages(e){return e.map(t=>{if(typeof t.content=="string")return{role:t.role,content:t.content};let s=t.content.map(r=>{switch(r.type){case"text":return{type:"text",text:r.text};case"image":return{type:"image",source:{type:"base64",media_type:r.source.media_type,data:r.source.data}};case"tool_use":return{type:"tool_use",id:r.id,name:r.name,input:r.input};case"tool_result":return{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content,is_error:r.is_error};default:return{type:"text",text:"[Unsupported block type]"}}}).filter(r=>r!==void 0);return{role:t.role,content:s}})}mapTools(e){return e.map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}mapResponse(e){let t="",s=[];for(let r of e.content)r.type==="text"?t+=r.text:r.type==="tool_use"&&s.push({id:r.id,name:r.name,input:r.input});return{content:t,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens},stopReason:e.stop_reason}}}});import sl from"openai";var de,Ve=w(()=>{"use strict";it();de=class extends ge{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new sl({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=ze(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",l=[],d=null,m=0,h=0;for await(let b of r){let y=b.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 E of g.tool_calls)if(E.id){if(n){let v;try{v=JSON.parse(i||"{}")}catch{v={}}l.push({id:n,name:o,input:v})}n=E.id,o=E.function?.name,i=E.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else E.function?.arguments&&(i+=E.function.arguments,yield{type:"tool_use_delta",toolCall:{input:E.function.arguments}});y.finish_reason&&(d=y.finish_reason),b.usage&&(m=b.usage.prompt_tokens,h=b.usage.completion_tokens)}if(n){let b;try{b=JSON.parse(i||"{}")}catch{b={}}l.push({id:n,name:o,input:b})}yield{type:"message_complete",response:{content:a,toolCalls:l.length>0?l:void 0,usage:{inputTokens:m,outputTokens:h},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(l=>l.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,toolCalls:n&&n.length>0?n:void 0,usage:{inputTokens:e.usage?.prompt_tokens??0,outputTokens:e.usage?.completion_tokens??0},stopReason:this.mapStopReason(t?.finish_reason??null)}}mapStopReason(e){switch(e){case"stop":return"end_turn";case"tool_calls":return"tool_use";case"length":return"max_tokens";default:return"end_turn"}}}});var ls,mn=w(()=>{"use strict";Ve();ls=class extends de{static{u(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var ds,pn=w(()=>{"use strict";it();ds=class extends ge{static{u(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=ze(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let b=await n.text();throw new Error(`Ollama API error (${n.status}): ${b}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",l="",d=0,m=0,h=[];try{for(;;){let{done:b,value:y}=await o.read();if(b)break;a+=i.decode(y,{stream:!0});let g=a.split(`
297
+ `);a=g.pop()??"";for(let E of g){let v=E.trim();if(!v)continue;let R;try{R=JSON.parse(v)}catch{continue}if(R.message?.content&&(l+=R.message.content,yield{type:"text_delta",text:R.message.content}),R.message?.tool_calls)for(let x of R.message.tool_calls){let O={id:`ollama_tool_${h.length}`,name:x.function.name,input:x.function.arguments};h.push(O),yield{type:"tool_use_start",toolCall:{id:O.id,name:O.name}},yield{type:"tool_use_delta",toolCall:{input:O.input}}}R.done&&(d=R.prompt_eval_count??0,m=R.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:h.length>0?h:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:h.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let b;try{b=JSON.parse(a.trim())}catch{return}if(b.message?.content&&(l+=b.message.content,yield{type:"text_delta",text:b.message.content}),b.message?.tool_calls)for(let y of b.message.tool_calls){let g={id:`ollama_tool_${h.length}`,name:y.function.name,input:y.function.arguments};h.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}},yield{type:"tool_use_delta",toolCall:{input:g.input}}}b.done&&(d=b.prompt_eval_count??0,m=b.eval_count??0,yield{type:"message_complete",response:{content:l,toolCalls:h.length>0?h:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:h.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
298
+ `)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var us,hn=w(()=>{"use strict";Ve();us=class extends de{static{u(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});var ms,fn=w(()=>{"use strict";Ve();ms=class extends de{static{u(this,"GoogleProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://generativelanguage.googleapis.com/v1beta/openai/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var ps,gn=w(()=>{"use strict";Ve();ps=class extends de{static{u(this,"MistralProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://api.mistral.ai/v1/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});function yn(c){switch(c.provider){case"anthropic":return new cs(c);case"openai":return new de(c);case"openrouter":return new ls(c);case"ollama":return new ds(c);case"openwebui":return new us(c);case"google":return new ms(c);case"mistral":return new ps(c);default:throw new Error(`Unknown LLM provider: ${c.provider}`)}}var wn=w(()=>{"use strict";un();Ve();mn();pn();hn();fn();gn();u(yn,"createLLMProvider")});function bn(c){return new tr(c)}var rl,tr,ri=w(()=>{"use strict";it();wn();rl=["default","strong","fast","embeddings","local"],tr=class extends ge{static{u(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of rl){let t=this.multiConfig[e];if(t){let s=yn(t);await s.initialize(),this.providers.set(e,s)}}}resolve(e){return e&&this.providers.has(e)?this.providers.get(e):this.providers.get("default")}async complete(e){return this.resolve(e.tier).complete(e)}async*stream(e){yield*this.resolve(e.tier).stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve()).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve()).supportsEmbeddings()}isAvailable(){return this.resolve().isAvailable()}getContextWindow(){return this.resolve().getContextWindow()}};u(bn,"createModelRouter")});function ve(c){return Math.ceil(c.length/3.5)}function fs(c){if(typeof c.content=="string")return ve(c.content)+4;let e=4;for(let t of c.content)switch(t.type){case"text":e+=ve(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=ve(t.name)+ve(JSON.stringify(t.input));break;case"tool_result":e+=ve(t.content);break}return e}var hs,ni=w(()=>{"use strict";u(ve,"estimateTokens");u(fs,"estimateMessageTokens");hs=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
299
299
 
300
300
  ## Core principles
301
301
  - **When the user's intent is clear**, ACT immediately using your tools. Don't explain what you'll do \u2014 just do it.
@@ -324,17 +324,17 @@ For complex tasks, work through multiple steps:
324
324
  - Home: ${i}
325
325
  - Documents: ${i}/Documents
326
326
  - Desktop: ${i}/Desktop
327
- - Downloads: ${i}/Downloads`,l=Intl.DateTimeFormat().resolvedOptions().timeZone,d=r?.timezone||l,p=new Date,m=p.toLocaleTimeString("en-GB",{timeZone:d,hour:"2-digit",minute:"2-digit"}),g=p.toLocaleDateString("en-CA",{timeZone:d}),f=p.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
327
+ - Downloads: ${i}/Downloads`,l=Intl.DateTimeFormat().resolvedOptions().timeZone,d=r?.timezone||l,m=new Date,h=m.toLocaleTimeString("en-GB",{timeZone:d,hour:"2-digit",minute:"2-digit"}),b=m.toLocaleDateString("en-CA",{timeZone:d}),y=m.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
328
328
 
329
329
  ## Current date & time`,a+=`
330
330
  - Timezone: ${d}`,a+=`
331
- - Date: ${g} (${f})`,a+=`
332
- - Time: ${m}`,r?.timezone&&r.timezone!==l&&(a+=`
331
+ - Date: ${b} (${y})`,a+=`
332
+ - Time: ${h}`,r?.timezone&&r.timezone!==l&&(a+=`
333
333
  - Server timezone: ${l}`),s&&s.length>0){a+=`
334
334
 
335
335
  ## Available tools
336
- `;for(let h of s)a+=`- **${h.name}** (${h.riskLevel}): ${h.description}
337
- `;s.some(h=>h.name==="code_agent")&&(a+='\n## Code agent delegation\nWhen the user asks you to **write code, edit files, fix bugs, refactor, implement features, or perform any coding task**, you MUST delegate to the `code_agent` tool instead of doing it yourself. You are an orchestrator, not a coder.\n\n- For **single, focused tasks**: use `code_agent` with `action: "run"` and pick the best agent.\n- For **complex, multi-step tasks**: use `code_agent` with `action: "orchestrate"` \u2014 the system will decompose the task, run agents in parallel, and validate results.\n- Add `git: true` when the user wants the changes committed, pushed, and a PR/MR created.\n- Use `action: "list_agents"` if you\'re unsure which agents are available.\n\n**Do NOT** attempt to write code or edit files yourself through conversation. Always delegate to a code agent.')}if(r&&(a+=`
336
+ `;for(let g of s)a+=`- **${g.name}** (${g.riskLevel}): ${g.description}
337
+ `;s.some(g=>g.name==="code_agent")&&(a+='\n## Code agent delegation\nWhen the user asks you to **write code, edit files, fix bugs, refactor, implement features, or perform any coding task**, you MUST delegate to the `code_agent` tool instead of doing it yourself. You are an orchestrator, not a coder.\n\n- For **single, focused tasks**: use `code_agent` with `action: "run"` and pick the best agent.\n- For **complex, multi-step tasks**: use `code_agent` with `action: "orchestrate"` \u2014 the system will decompose the task, run agents in parallel, and validate results.\n- Add `git: true` when the user wants the changes committed, pushed, and a PR/MR created.\n- Use `action: "list_agents"` if you\'re unsure which agents are available.\n\n**Do NOT** attempt to write code or edit files yourself through conversation. Always delegate to a code agent.')}if(r&&(a+=`
338
338
 
339
339
  ## User profile`,r.displayName&&(a+=`
340
340
  - Name: ${r.displayName}`),r.timezone&&(a+=`
@@ -342,63 +342,51 @@ For complex tasks, work through multiple steps:
342
342
  - Language: ${r.language}`),r.bio&&(a+=`
343
343
  - Bio: ${r.bio}`)),n&&n.length>0){a+=`
344
344
 
345
- ## Today's events`;for(let h of n){let T=h.allDay?"All day":h.start.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}}),_=h.allDay?"":`-${h.end.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}})}`,x=h.location?` @ ${h.location}`:"";a+=`
346
- - ${T}${_}: ${h.title}${x}`}}if(t&&t.length>0){if(a+=`
345
+ ## Today's events`;for(let g of n){let E=g.allDay?"All day":g.start.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}}),v=g.allDay?"":`-${g.end.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}})}`,R=g.location?` @ ${g.location}`:"";a+=`
346
+ - ${E}${v}: ${g.title}${R}`}}if(t&&t.length>0){if(a+=`
347
347
 
348
348
  ## Memories about this user
349
- `,t.some(T=>T.type&&T.type!=="general")){let T=new Map;for(let x of t){let k=x.type||"general",C=T.get(k);C||(C=[],T.set(k,C)),C.push(x)}let _={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[x,k]of T){a+=`
350
- ### ${_[x]||x}
351
- `;for(let C of k)a+=`- ${C.key}: ${C.value}
352
- `}}else for(let T of t)a+=`- [${T.category}] ${T.key}: ${T.value}
349
+ `,t.some(E=>E.type&&E.type!=="general")){let E=new Map;for(let R of t){let x=R.type||"general",O=E.get(x);O||(O=[],E.set(x,O)),O.push(R)}let v={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[R,x]of E){a+=`
350
+ ### ${v[R]||R}
351
+ `;for(let O of x)a+=`- ${O.key}: ${O.value}
352
+ `}}else for(let E of t)a+=`- [${E.category}] ${E.key}: ${E.value}
353
353
  `;a+=`
354
354
  Use these memories to personalize your responses. When the user tells you new facts or preferences, use the memory tool to save them.`}else a+=`
355
355
 
356
- When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let l of i)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});return a.length===0&&a.push({type:"text",text:""}),{role:"assistant",content:a}}let n=r,o=[];for(let i of n)i.type==="tool_result"&&o.push(i);return o.length>0?{role:"user",content:o}:{role:"user",content:s.content||""}}return{role:s.role,content:s.content}});return this.sanitizeToolMessages(t)}sanitizeToolMessages(e){let t=new Set,s=new Set;for(let a of e)if(a.role==="assistant"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_use"&&t.add(l.id);else if(a.role==="user"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_result"&&t.has(l.tool_use_id)&&s.add(l.tool_use_id);let r=new Set,n=new Set,o=[];for(let a of e){if(!Array.isArray(a.content)){o.push(a);continue}let l=a.content.filter(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);l.length!==0&&o.push({...a,content:l})}let i=[];for(let a of o){let l=i[i.length-1];if(l&&l.role===a.role){let d=typeof l.content=="string"?[{type:"text",text:l.content}]:l.content,p=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...l,content:[...d,...p]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var cn=b(()=>{"use strict";Qe();Zr();qe();Qr();en();tn();sn();rn();on();Bo();qo()});var as,ln=b(()=>{"use strict";as=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var cs,Wo=b(()=>{"use strict";ln();cs=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new as;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 Xo,Ho,Vo,We,zo=b(()=>{"use strict";Xo=["allow","deny"],Ho=["global","user","conversation","platform"],Vo=["read","write","destructive","admin"],We=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"||!Xo.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${Xo.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"||!Ho.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${Ho.join(", ")}`);if(!Array.isArray(s.actions)||s.actions.length===0)throw new Error(`Rule "${s.id}" is missing a valid "actions" array`);for(let n of s.actions)if(typeof n!="string")throw new Error(`Rule "${s.id}" has a non-string entry in "actions"`);if(!Array.isArray(s.riskLevels)||s.riskLevels.length===0)throw new Error(`Rule "${s.id}" is missing a valid "riskLevels" array`);for(let n of s.riskLevels)if(!Vo.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${Vo.join(", ")}`);let r={id:s.id,effect:s.effect,priority:s.priority,scope:s.scope,actions:s.actions,riskLevels:s.riskLevels};if(s.conditions!==void 0){if(typeof s.conditions!="object"||s.conditions===null)throw new Error(`Rule "${s.id}" has invalid "conditions": expected an object`);r.conditions=s.conditions}if(s.rateLimit!==void 0){if(typeof s.rateLimit!="object"||s.rateLimit===null)throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected an object`);let n=s.rateLimit;if(typeof n.maxInvocations!="number"||typeof n.windowSeconds!="number")throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected maxInvocations and windowSeconds numbers`);r.rateLimit=s.rateLimit}return r}}});import Nc from"node:crypto";var ls,Ko=b(()=>{"use strict";ls=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:Nc.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 Ys=b(()=>{"use strict";Wo();ln();zo();Ko()});var $,D=b(()=>{"use strict";$=class{static{u(this,"Skill")}}});var et,Go=b(()=>{"use strict";et=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 tt,Yo=b(()=>{"use strict";tt=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,l,d,p,m=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),p&&clearTimeout(p)},"cleanup"),g=u(f=>{a||(a=!0,m(),i(f))},"finish");e.execute(t,s).then(f=>{this.logger.info({skill:r,success:f.success},"Skill execution completed"),g(f)},f=>{let h=f instanceof Error?f.message:String(f);this.logger.error({skill:r,error:h},"Skill execution failed"),g({success:!1,error:h})}),p=setTimeout(()=>{if(a)return;let f=o.getIdleMs();if(f>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:f,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),g({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(f/1e3)}s (last state: ${T.state})`});return}let h=o.getSnapshot();this.logger.info({skill:r,idleMs:f,state:h.state,iteration:h.iteration,totalMs:h.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){m();return}let T=o.getIdleMs(),_=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:_.state,iteration:_.iteration,totalMs:_.totalElapsedMs},"Agent went inactive \u2014 aborting"),g({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${_.state})`})):this.logger.debug({skill:r,idleMs:T,state:_.state,iteration:_.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let f=o.getSnapshot();this.logger.error({skill:r,totalMs:f.totalElapsedMs,state:f.state,iteration:f.iteration},"Absolute time limit reached \u2014 force killing agent"),g({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var Xe,dn=b(()=>{"use strict";Xe=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 Cc from"node:fs";import un from"node:path";var Js,Jo=b(()=>{"use strict";D();Js=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=un.resolve(e),s;try{s=await Cc.promises.readdir(t)}catch(o){let i=o instanceof Error?o.message:String(o);return console.warn(`PluginLoader: failed to read directory "${t}": ${i}`),[]}let r=s.filter(o=>o.endsWith(".js")),n=[];for(let o of r){let i=un.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let l=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${l}`)}}return n}async loadFromFile(e){let t=un.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof $))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var Oc,Dc,st,Zo=b(()=>{"use strict";D();Oc=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,Dc=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,st=class extends ${static{u(this,"CalculatorSkill")}metadata={name:"calculator",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!Dc.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(Oc,"");if(/[a-zA-Z]/.test(n))return{success:!1,error:`Invalid expression: "${r}" contains disallowed identifiers`};try{let i=new Function("Math",`"use strict"; return (${r});`)(Math);return typeof i!="number"||!isFinite(i)?{success:!1,error:`Invalid expression: "${r}" did not produce a finite number`}:{success:!0,data:i,display:`${r} = ${i}`}}catch{return{success:!1,error:`Invalid expression: "${r}"`}}}}});var rt,Qo=b(()=>{"use strict";D();rt=class extends ${static{u(this,"SystemInfoSkill")}metadata={name:"system_info",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var nt,ei=b(()=>{"use strict";D();nt=class extends ${static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,l)=>`${l+1}. **${a.title}**
356
+ When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let l of i)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});return a.length===0&&a.push({type:"text",text:""}),{role:"assistant",content:a}}let n=r,o=[];for(let i of n)i.type==="tool_result"&&o.push(i);return o.length>0?{role:"user",content:o}:{role:"user",content:s.content||""}}return{role:s.role,content:s.content}});return this.sanitizeToolMessages(t)}sanitizeToolMessages(e){let t=new Set,s=new Set;for(let a of e)if(a.role==="assistant"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_use"&&t.add(l.id);else if(a.role==="user"&&Array.isArray(a.content))for(let l of a.content)l.type==="tool_result"&&t.has(l.tool_use_id)&&s.add(l.tool_use_id);let r=new Set,n=new Set,o=[];for(let a of e){if(!Array.isArray(a.content)){o.push(a);continue}let l=a.content.filter(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);l.length!==0&&o.push({...a,content:l})}let i=[];for(let a of o){let l=i[i.length-1];if(l&&l.role===a.role){let d=typeof l.content=="string"?[{type:"text",text:l.content}]:l.content,m=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...l,content:[...d,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Tn=w(()=>{"use strict";it();un();Ve();mn();pn();hn();fn();gn();wn();ri();ni()});var gs,En=w(()=>{"use strict";gs=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var ys,oi=w(()=>{"use strict";En();ys=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new gs;loadRules(e){this.rules=[...e].sort((t,s)=>t.priority-s.priority)}getRules(){return this.rules}evaluate(e){for(let t of this.rules)if(this.ruleMatches(t,e))return t.rateLimit&&t.effect==="allow"&&!this.checkRateLimit(t,e)?{allowed:!1,matchedRule:t,reason:`Rate limit exceeded for rule: ${t.id}`,timestamp:new Date}:{allowed:t.effect==="allow",matchedRule:t,reason:`Matched rule: ${t.id}`,timestamp:new Date};return{allowed:!1,matchedRule:void 0,reason:"No matching rule found \u2014 default deny",timestamp:new Date}}checkRateLimit(e,t){if(!e.rateLimit)return!0;let s=this.getScopeKey(e.scope,t),r=`${e.id}:${s}`;return this.rateLimiter.check(r,e.rateLimit).allowed?(this.rateLimiter.increment(r,e.rateLimit),!0):!1}resetRateLimits(){this.rateLimiter.reset()}getScopeKey(e,t){switch(e){case"global":return"global";case"user":return t.userId;case"conversation":return t.chatId??"unknown";case"platform":return t.platform}}ruleMatches(e,t){return!(!e.actions.includes("*")&&!e.actions.includes(t.action)||!e.riskLevels.includes(t.riskLevel)||e.conditions&&(e.conditions.users&&e.conditions.users.length>0&&!e.conditions.users.includes(t.userId)||e.conditions.platforms&&e.conditions.platforms.length>0&&!e.conditions.platforms.includes(t.platform)||e.conditions.chatType&&t.chatType&&e.conditions.chatType!==t.chatType||e.conditions.timeWindow&&!this.matchesTimeWindow(e.conditions.timeWindow)))}matchesTimeWindow(e){if(!e)return!0;let t=new Date;if(e.daysOfWeek&&e.daysOfWeek.length>0&&!e.daysOfWeek.includes(t.getDay()))return!1;let s=t.getHours();if(e.startHour!==void 0&&e.endHour!==void 0){if(e.startHour<=e.endHour){if(s<e.startHour||s>=e.endHour)return!1}else if(s>=e.endHour&&s<e.startHour)return!1}else if(e.startHour!==void 0){if(s<e.startHour)return!1}else if(e.endHour!==void 0&&s>=e.endHour)return!1;return!0}}});var ii,ai,ci,Ke,li=w(()=>{"use strict";ii=["allow","deny"],ai=["global","user","conversation","platform"],ci=["read","write","destructive","admin"],Ke=class{static{u(this,"RuleLoader")}loadFromObject(e){if(!e||!Array.isArray(e.rules))throw new Error('Invalid data: expected an object with a "rules" array');return e.rules.map((t,s)=>this.validateRule(t,s))}validateRule(e,t){if(typeof e!="object"||e===null)throw new Error(`Rule at index ${t} is not an object`);let s=e;if(typeof s.id!="string"||s.id.length===0)throw new Error(`Rule at index ${t} is missing a valid "id" string`);if(typeof s.effect!="string"||!ii.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${ii.join(", ")}`);if(typeof s.priority!="number"||!Number.isFinite(s.priority))throw new Error(`Rule "${s.id}" is missing a valid "priority" number`);if(typeof s.scope!="string"||!ai.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${ai.join(", ")}`);if(!Array.isArray(s.actions)||s.actions.length===0)throw new Error(`Rule "${s.id}" is missing a valid "actions" array`);for(let n of s.actions)if(typeof n!="string")throw new Error(`Rule "${s.id}" has a non-string entry in "actions"`);if(!Array.isArray(s.riskLevels)||s.riskLevels.length===0)throw new Error(`Rule "${s.id}" is missing a valid "riskLevels" array`);for(let n of s.riskLevels)if(!ci.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${ci.join(", ")}`);let r={id:s.id,effect:s.effect,priority:s.priority,scope:s.scope,actions:s.actions,riskLevels:s.riskLevels};if(s.conditions!==void 0){if(typeof s.conditions!="object"||s.conditions===null)throw new Error(`Rule "${s.id}" has invalid "conditions": expected an object`);r.conditions=s.conditions}if(s.rateLimit!==void 0){if(typeof s.rateLimit!="object"||s.rateLimit===null)throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected an object`);let n=s.rateLimit;if(typeof n.maxInvocations!="number"||typeof n.windowSeconds!="number")throw new Error(`Rule "${s.id}" has invalid "rateLimit": expected maxInvocations and windowSeconds numbers`);r.rateLimit=s.rateLimit}return r}}});import nl from"node:crypto";var ws,di=w(()=>{"use strict";ws=class{static{u(this,"SecurityManager")}ruleEngine;auditRepository;logger;constructor(e,t,s){this.ruleEngine=e,this.auditRepository=t,this.logger=s}evaluate(e){let t=this.ruleEngine.evaluate(e),s={id:nl.randomUUID(),timestamp:t.timestamp,userId:e.userId,action:e.action,riskLevel:e.riskLevel,ruleId:t.matchedRule?.id,effect:t.allowed?"allow":"deny",platform:e.platform,chatId:e.chatId,context:{chatType:e.chatType,reason:t.reason}};try{this.auditRepository.log(s)}catch(r){this.logger.error({err:r,auditEntry:s},"Failed to write audit log entry")}return this.logger.debug({userId:e.userId,action:e.action,allowed:t.allowed,ruleId:t.matchedRule?.id,reason:t.reason},"Security evaluation completed"),t}}});var sr=w(()=>{"use strict";oi();En();li();di()});var I,P=w(()=>{"use strict";I=class{static{u(this,"Skill")}}});var at,ui=w(()=>{"use strict";at=class{static{u(this,"SkillRegistry")}skills=new Map;register(e){let{name:t}=e.metadata;if(this.skills.has(t))throw new Error(`Skill "${t}" is already registered`);this.skills.set(t,e)}get(e){return this.skills.get(e)}getAll(){return[...this.skills.values()]}has(e){return this.skills.has(e)}unregister(e){return this.skills.delete(e)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var ct,mi=w(()=>{"use strict";ct=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,l,d,m,h=u(()=>{l&&clearInterval(l),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),b=u(y=>{a||(a=!0,h(),i(y))},"finish");e.execute(t,s).then(y=>{this.logger.info({skill:r,success:y.success},"Skill execution completed"),b(y)},y=>{let g=y instanceof Error?y.message:String(y);this.logger.error({skill:r,error:g},"Skill execution failed"),b({success:!1,error:g})}),m=setTimeout(()=>{if(a)return;let y=o.getIdleMs();if(y>=12e4){let E=o.getSnapshot();this.logger.warn({skill:r,idleMs:y,state:E.state,iteration:E.iteration},"Agent inactive after initial timeout \u2014 aborting"),b({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(y/1e3)}s (last state: ${E.state})`});return}let g=o.getSnapshot();this.logger.info({skill:r,idleMs:y,state:g.state,iteration:g.iteration,totalMs:g.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),l=setInterval(()=>{if(a){h();return}let E=o.getIdleMs(),v=o.getSnapshot();E>=12e4?(this.logger.warn({skill:r,idleMs:E,state:v.state,iteration:v.iteration,totalMs:v.totalElapsedMs},"Agent went inactive \u2014 aborting"),b({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(E/1e3)}s (last state: ${v.state})`})):this.logger.debug({skill:r,idleMs:E,state:v.state,iteration:v.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let y=o.getSnapshot();this.logger.error({skill:r,totalMs:y.totalElapsedMs,state:y.state,iteration:y.iteration},"Absolute time limit reached \u2014 force killing agent"),b({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var Ge,_n=w(()=>{"use strict";Ge=class{static{u(this,"ActivityTracker")}state="starting";iteration=0;maxIterations=0;currentTool;lastPingAt;startedAt;history=[];onProgress;constructor(e){this.startedAt=Date.now(),this.lastPingAt=Date.now(),this.onProgress=e}ping(e,t){this.state=e,this.lastPingAt=Date.now(),t?.iteration!==void 0&&(this.iteration=t.iteration),t?.maxIterations!==void 0&&(this.maxIterations=t.maxIterations),this.currentTool=t?.tool,this.history.push({state:e,tool:t?.tool,iteration:this.iteration,timestamp:this.lastPingAt}),this.onProgress&&this.onProgress(this.formatStatus())}getIdleMs(){return Date.now()-this.lastPingAt}getTotalElapsedMs(){return Date.now()-this.startedAt}formatStatus(){let e=this.maxIterations>0?` (${this.iteration}/${this.maxIterations})`:"";switch(this.state){case"starting":return"Sub-agent starting...";case"llm_call":return`Sub-agent thinking...${e}`;case"tool_call":return this.currentTool?`Sub-agent using ${this.currentTool}${e}`:`Sub-agent using tool...${e}`;case"processing":return`Sub-agent processing...${e}`;case"done":return`Sub-agent done${e}`;default:return`Sub-agent working...${e}`}}getSnapshot(){return{state:this.state,iteration:this.iteration,maxIterations:this.maxIterations,lastPingAt:this.lastPingAt,idleMs:this.getIdleMs(),currentTool:this.currentTool,totalElapsedMs:this.getTotalElapsedMs(),history:[...this.history]}}}});import ol from"node:fs";import $n from"node:path";var rr,pi=w(()=>{"use strict";P();rr=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=$n.resolve(e),s;try{s=await ol.promises.readdir(t)}catch(o){let i=o instanceof Error?o.message:String(o);return console.warn(`PluginLoader: failed to read directory "${t}": ${i}`),[]}let r=s.filter(o=>o.endsWith(".js")),n=[];for(let o of r){let i=$n.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let l=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${l}`)}}return n}async loadFromFile(e){let t=$n.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var il,al,lt,hi=w(()=>{"use strict";P();il=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,al=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,lt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!al.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(il,"");if(/[a-zA-Z]/.test(n))return{success:!1,error:`Invalid expression: "${r}" contains disallowed identifiers`};try{let i=new Function("Math",`"use strict"; return (${r});`)(Math);return typeof i!="number"||!isFinite(i)?{success:!1,error:`Invalid expression: "${r}" did not produce a finite number`}:{success:!0,data:i,display:`${r} = ${i}`}}catch{return{success:!1,error:`Invalid expression: "${r}"`}}}}});var dt,fi=w(()=>{"use strict";P();dt=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var ut,gi=w(()=>{"use strict";P();ut=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,l)=>`${l+1}. **${a.title}**
357
357
  ${a.url}
358
358
  ${a.snippet}`).join(`
359
359
 
360
360
  `);return{success:!0,data:{query:s,results:o},display:`Search results for "${s}":
361
361
 
362
- ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let l=i[1],d=this.stripHtml(i[2]).trim(),p=this.extractDdgUrl(l);d&&p&&o.push({url:p,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let l=0;l<Math.min(o.length,t);l++)s.push({title:o[l].title,url:o[l].url,snippet:a[l]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var ot,ti=b(()=>{"use strict";D();ot=class extends ${static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let p=this.parseTriggerAt(r,t.timezone);if(!p)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(p.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=p}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),l=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${l} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),l=parseInt(n[4],10),d=parseInt(n[5],10);return l>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(l,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let g=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||g.setHours(e,t,0,0),g}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let g=i.formatToParts(n),f=parseInt(g.find(P=>P.type==="year").value,10),h=parseInt(g.find(P=>P.type==="month").value,10)-1,T=parseInt(g.find(P=>P.type==="day").value,10),_=new Date(Date.UTC(f,h,T,e,t,0)),x=i.formatToParts(_),k=parseInt(x.find(P=>P.type==="hour").value,10),C=parseInt(x.find(P=>P.type==="minute").value,10),M=(e-k)*60+(t-C);return _=new Date(_.getTime()+M*6e4),_}let a=o,l=i.formatToParts(a),d=parseInt(l.find(g=>g.type==="hour").value,10),p=parseInt(l.find(g=>g.type==="minute").value,10),m=(e-d)*60+(t-p);return a=new Date(a.getTime()+m*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:
362
+ ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let l=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(l);d&&m&&o.push({url:m,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let l=0;l<Math.min(o.length,t);l++)s.push({title:o[l].title,url:o[l].url,snippet:a[l]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var mt,yi=w(()=>{"use strict";P();mt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let m=this.parseTriggerAt(r,t.timezone);if(!m)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(m.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=m}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),l=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${l} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),l=parseInt(n[4],10),d=parseInt(n[5],10);return l>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(l,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let b=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||b.setHours(e,t,0,0),b}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let b=i.formatToParts(n),y=parseInt(b.find(B=>B.type==="year").value,10),g=parseInt(b.find(B=>B.type==="month").value,10)-1,E=parseInt(b.find(B=>B.type==="day").value,10),v=new Date(Date.UTC(y,g,E,e,t,0)),R=i.formatToParts(v),x=parseInt(R.find(B=>B.type==="hour").value,10),O=parseInt(R.find(B=>B.type==="minute").value,10),N=(e-x)*60+(t-O);return v=new Date(v.getTime()+N*6e4),v}let a=o,l=i.formatToParts(a),d=parseInt(l.find(b=>b.type==="hour").value,10),m=parseInt(l.find(b=>b.type==="minute").value,10),h=(e-d)*60+(t-m);return a=new Date(a.getTime()+h*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
363
363
  ${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).join(`
364
- `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var it,si=b(()=>{"use strict";D();it=class extends ${static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(this.effectiveUserId(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of this.allUserIds(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
364
+ `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var pt,wi=w(()=>{"use strict";P();pt=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(this.effectiveUserId(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of this.allUserIds(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
365
365
  ${n.content.slice(0,100)}${n.content.length>100?"\u2026":""}`).join(`
366
366
  `);return{success:!0,data:s,display:`${s.length} note(s):
367
367
  ${r}`}}searchNotes(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let i of this.allUserIds(t))for(let a of this.noteRepo.search(i,s))r.has(a.id)||(r.add(a.id),n.push(a));if(n.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let o=n.map(i=>`- **${i.title}** (${i.id.slice(0,8)}\u2026)
368
368
  ${i.content.slice(0,100)}${i.content.length>100?"\u2026":""}`).join(`
369
369
  `);return{success:!0,data:n,display:`Found ${n.length} note(s):
370
- ${o}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var Uc,at,ri=b(()=>{"use strict";D();Uc={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"},at=class extends ${static{u(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let n=await this.fetchWeather(r.latitude,r.longitude),o=Uc[n.weathercode]??`Code ${n.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:n.temperature,unit:"\xB0C",condition:o,windSpeed:n.windspeed,windDirection:n.winddirection,isDay:n.is_day===1},l=`${i}: ${n.temperature}\xB0C, ${o}
371
- Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:l}}catch(r){return{success:!1,error:`Weather fetch failed: ${r instanceof Error?r.message:String(r)}`}}}async geocode(e){let t=`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(e)}&count=1&language=en&format=json`,s=await fetch(t);if(!s.ok)throw new Error(`Geocoding API returned ${s.status}`);return(await s.json()).results?.[0]}async fetchWeather(e,t){let s=`https://api.open-meteo.com/v1/forecast?latitude=${e}&longitude=${t}&current_weather=true&timezone=auto`,r=await fetch(s);if(!r.ok)throw new Error(`Weather API returned ${r.status}`);return(await r.json()).current_weather}}});import{exec as Pc}from"node:child_process";function oi(c){return c.length>ni?c.slice(0,ni)+`
372
- [output truncated]`:c}var Fc,ni,ct,ii=b(()=>{"use strict";D();Fc=3e4,ni=1e4;u(oi,"truncate");ct=class extends ${static{u(this,"ShellSkill")}metadata={name:"shell",description:"Execute shell commands on the host system. Use this for ANY task involving files, folders, system operations, or running programs: ls, cat, find, file, du, mkdir, cp, mv, grep, etc. When the user asks about their documents, files, or anything on disk \u2014 use this tool.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds (default: 30000)"},cwd:{type:"string",description:"Working directory for the command"}},required:["command"]}};async execute(e,t){let s=e.command;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "command"'};let r=[/\brm\s+-rf\s+\/(?:\s|$)/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r)[a-zA-Z]*\s+\/(?:\s|$)/,/\brm\s+-rf\s+\/\*/,/:(){ :|:& };:/,/:\(\)\s*\{.*\|.*&\s*\}\s*;/,/>\s*\/dev\/sd[a-z]/,/\bmkfs\b/,/\bdd\s+.*\bif=/,/\bchmod\s+777\b/,/\bcurl\b.*\|\s*\bbash\b/,/\bwget\b.*\|\s*\bsh\b/,/\bpython[23]?\s+-c\b/,/\bnode\s+-e\b/,/\b(bash|sh)\s+-i\b.*\/dev\/tcp/,/\bnc\s+.*-e\b/];for(let i of r)if(i.test(s))return{success:!1,error:"Command blocked: potentially destructive system operation"};let n=typeof e.timeout=="number"&&e.timeout>0?e.timeout:Fc,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:l}=await this.run(s,n,o),d=[];return i&&d.push(`stdout:
373
- ${oi(i)}`),a&&d.push(`stderr:
374
- ${oi(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(`
370
+ ${o}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var cl,ht,bi=w(()=>{"use strict";P();cl={0:"Clear sky",1:"Mainly clear",2:"Partly cloudy",3:"Overcast",45:"Foggy",48:"Depositing rime fog",51:"Light drizzle",53:"Moderate drizzle",55:"Dense drizzle",61:"Slight rain",63:"Moderate rain",65:"Heavy rain",71:"Slight snow",73:"Moderate snow",75:"Heavy snow",77:"Snow grains",80:"Slight rain showers",81:"Moderate rain showers",82:"Violent rain showers",85:"Slight snow showers",86:"Heavy snow showers",95:"Thunderstorm",96:"Thunderstorm with slight hail",99:"Thunderstorm with heavy hail"},ht=class extends I{static{u(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let n=await this.fetchWeather(r.latitude,r.longitude),o=cl[n.weathercode]??`Code ${n.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:n.temperature,unit:"\xB0C",condition:o,windSpeed:n.windspeed,windDirection:n.winddirection,isDay:n.is_day===1},l=`${i}: ${n.temperature}\xB0C, ${o}
371
+ Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:l}}catch(r){return{success:!1,error:`Weather fetch failed: ${r instanceof Error?r.message:String(r)}`}}}async geocode(e){let t=`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(e)}&count=1&language=en&format=json`,s=await fetch(t);if(!s.ok)throw new Error(`Geocoding API returned ${s.status}`);return(await s.json()).results?.[0]}async fetchWeather(e,t){let s=`https://api.open-meteo.com/v1/forecast?latitude=${e}&longitude=${t}&current_weather=true&timezone=auto`,r=await fetch(s);if(!r.ok)throw new Error(`Weather API returned ${r.status}`);return(await r.json()).current_weather}}});import{exec as ll}from"node:child_process";function Ei(c){return c.length>Ti?c.slice(0,Ti)+`
372
+ [output truncated]`:c}var dl,Ti,ft,_i=w(()=>{"use strict";P();dl=3e4,Ti=1e4;u(Ei,"truncate");ft=class extends I{static{u(this,"ShellSkill")}metadata={name:"shell",description:"Execute shell commands on the host system. Use this for ANY task involving files, folders, system operations, or running programs: ls, cat, find, file, du, mkdir, cp, mv, grep, etc. When the user asks about their documents, files, or anything on disk \u2014 use this tool.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds (default: 30000)"},cwd:{type:"string",description:"Working directory for the command"}},required:["command"]}};async execute(e,t){let s=e.command;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "command"'};let r=[/\brm\s+-rf\s+\/(?:\s|$)/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r)[a-zA-Z]*\s+\/(?:\s|$)/,/\brm\s+-rf\s+\/\*/,/:(){ :|:& };:/,/:\(\)\s*\{.*\|.*&\s*\}\s*;/,/>\s*\/dev\/sd[a-z]/,/\bmkfs\b/,/\bdd\s+.*\bif=/,/\bchmod\s+777\b/,/\bcurl\b.*\|\s*\bbash\b/,/\bwget\b.*\|\s*\bsh\b/,/\bpython[23]?\s+-c\b/,/\bnode\s+-e\b/,/\b(bash|sh)\s+-i\b.*\/dev\/tcp/,/\bnc\s+.*-e\b/];for(let i of r)if(i.test(s))return{success:!1,error:"Command blocked: potentially destructive system operation"};let n=typeof e.timeout=="number"&&e.timeout>0?e.timeout:dl,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:l}=await this.run(s,n,o),d=[];return i&&d.push(`stdout:
373
+ ${Ei(i)}`),a&&d.push(`stderr:
374
+ ${Ei(a)}`),d.length===0&&d.push("(no output)"),d.push(`exit code: ${l}`),{success:l===0,data:{stdout:i,stderr:a,exitCode:l},display:d.join(`
375
375
 
376
- `),...l!==0&&{error:`Command exited with code ${l}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{Pc(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var lt,ai=b(()=>{"use strict";D();lt=class extends ${static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(this.effectiveUserId(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r;for(let n of this.allUserIds(t))if(r=this.memoryRepo.recall(n,s),r)break;return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of this.memoryRepo.search(o,s))r.has(i.id)||(r.add(i.id),n.push(i));return{success:!0,data:n,display:n.length===0?`No memories matching "${s}".`:`Found ${n.length} memory(ies):
376
+ `),...l!==0&&{error:`Command exited with code ${l}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{ll(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var gt,$i=w(()=>{"use strict";P();gt=class extends I{static{u(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(this.effectiveUserId(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r;for(let n of this.allUserIds(t))if(r=this.memoryRepo.recall(n,s),r)break;return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of this.memoryRepo.search(o,s))r.has(i.id)||(r.add(i.id),n.push(i));return{success:!0,data:n,display:n.length===0?`No memories matching "${s}".`:`Found ${n.length} memory(ies):
377
377
  ${n.map(o=>`- ${o.key}: "${o.value}"`).join(`
378
378
  `)}`}}listMemories(e,t){let s=e.category,r=new Set,n=[];for(let i of this.allUserIds(t)){let a=s&&typeof s=="string"?this.memoryRepo.listByCategory(i,s):this.memoryRepo.listAll(i);for(let l of a)r.has(l.id)||(r.add(l.id),n.push(l))}let o=s?`in category "${s}"`:"total";return{success:!0,data:n,display:n.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${n.length} memory(ies) ${o}:
379
379
  ${n.map(i=>`- [${i.category}] ${i.key}: "${i.value}"`).join(`
380
380
  `)}`}}deleteMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for delete action'};let r=!1;for(let n of this.allUserIds(t))if(this.memoryRepo.delete(n,s)){r=!0;break}return{success:!0,data:{key:s,deleted:r},display:r?`Memory "${s}" deleted.`:`No memory found for key "${s}".`}}async semanticSearchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for semantic_search action'};if(!this.embeddingService)return this.searchMemories(e,t);let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of await this.embeddingService.semanticSearch(o,s,10))r.has(i.key)||(r.add(i.key),n.push(i));return n.length===0?this.searchMemories(e,t):{success:!0,data:n,display:`Found ${n.length} semantically related memory(ies):
381
381
  ${n.map(o=>`- ${o.key}: "${o.value}" (score: ${o.score.toFixed(2)})`).join(`
382
- `)}`}}}});var jc,Bc,qc,dt,ci=b(()=>{"use strict";D();dn();jc=5,Bc=15,qc=12e4,dt=class extends ${static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",description:'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',riskLevel:"write",version:"3.0.0",timeoutMs:qc,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 Xe(this.onProgress)}async execute(e,t){let s=e.task,r=e.context;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task"'};let n=e.max_iterations,o=n?Math.max(1,Math.min(Bc,Math.round(n))):jc,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new Xe(i);a.ping("starting",{maxIterations:o});let l=this.buildSubAgentTools(),d="You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.",p=s;r&&typeof r=="string"&&(p=`${s}
382
+ `)}`}}}});var ul,ml,pl,yt,vi=w(()=>{"use strict";P();_n();ul=5,ml=15,pl=12e4,yt=class extends I{static{u(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",description:'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',riskLevel:"write",version:"3.0.0",timeoutMs:pl,inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to delegate to the sub-agent. Be specific about what you want."},context:{type:"string",description:"Additional context the sub-agent needs (optional)"},max_iterations:{type:"number",description:"Max tool iterations (1-15). Use higher values for complex multi-step tasks. Default: 5."}},required:["task"]}};onProgress;constructor(e,t,s,r){super(),this.llm=e,this.skillRegistry=t,this.skillSandbox=s,this.securityManager=r}setProgressCallback(e){this.onProgress=e}createTracker(){return new Ge(this.onProgress)}async execute(e,t){let s=e.task,r=e.context;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task"'};let n=e.max_iterations,o=n?Math.max(1,Math.min(ml,Math.round(n))):ul,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new Ge(i);a.ping("starting",{maxIterations:o});let l=this.buildSubAgentTools(),d="You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.",m=s;r&&typeof r=="string"&&(m=`${s}
383
383
 
384
- Additional context: ${r}`);let m=[{role:"user",content:p}];try{let g=0,f=0,h=0;for(;;){a.ping("llm_call",{iteration:g,maxIterations:o});let T=await this.llm.complete({messages:m,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(f+=T.usage.inputTokens,h+=T.usage.outputTokens,a.ping("processing",{iteration:g,maxIterations:o}),!T.toolCalls||T.toolCalls.length===0||g>=o)return a.ping("done",{iteration:g,maxIterations:o}),{success:!0,data:{response:T.content,iterations:g,usage:{inputTokens:f,outputTokens:h}},display:T.content};g++;let _=[];T.content&&_.push({type:"text",text:T.content});for(let k of T.toolCalls)_.push({type:"tool_use",id:k.id,name:k.name,input:k.input});m.push({role:"assistant",content:_});let x=[];for(let k of T.toolCalls){a.ping("tool_call",{iteration:g,maxIterations:o,tool:k.name});let C=await this.executeSubAgentTool(k,t);x.push({type:"tool_result",tool_use_id:k.id,content:C.content,is_error:C.isError})}m.push({role:"user",content:x})}}catch(g){return{success:!1,error:`Sub-agent failed: ${g instanceof Error?g.message:String(g)}`}}}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 ut,li=b(()=>{"use strict";D();ut=class extends ${static{u(this,"EmailSkill")}config;metadata={name:"email",description:"Access the user's email: check inbox, read messages, search emails, or send new emails. Use when the user asks about their emails or wants to send one.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send"],description:"The email action to perform"},count:{type:"number",description:"Number of emails to fetch (for inbox, default: 10)"},messageId:{type:"string",description:"Message sequence number to read (for read action)"},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 action)"}},required:["action"]}};constructor(e){super(),this.config=e}async execute(e,t){if(!this.config)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.fetchInbox(e.count);case"read":return await this.readMessage(e.messageId);case"search":return await this.searchMessages(e.query,e.count);case"send":return await this.sendMessage(e.to,e.subject,e.body);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}async fetchInbox(e){let t=Math.min(Math.max(1,e??10),50),{ImapFlow:s}=await import("imapflow"),r=new s({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1});try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=[],i=r.mailbox,a=i&&typeof i=="object"?i.exists??0:0;if(a===0)return{success:!0,data:{messages:[]},display:"Inbox is empty."};let d=`${Math.max(1,a-t+1)}:*`;for await(let g of r.fetch(d,{envelope:!0,flags:!0})){let f=g.envelope?.from?.[0],h=f?f.name?`${f.name} <${f.address}>`:f.address??"unknown":"unknown";o.push({seq:g.seq,from:h,subject:g.envelope?.subject??"(no subject)",date:g.envelope?.date?.toISOString()??"",seen:g.flags?.has("\\Seen")??!1})}o.reverse();let p=o.length===0?"No messages found.":o.map((g,f)=>{let h=g.seen?"":" [UNREAD]";return`${f+1}. [#${g.seq}]${h} ${g.subject}
385
- From: ${g.from}
386
- Date: ${g.date}`}).join(`
384
+ Additional context: ${r}`);let h=[{role:"user",content:m}];try{let b=0,y=0,g=0;for(;;){a.ping("llm_call",{iteration:b,maxIterations:o});let E=await this.llm.complete({messages:h,system:d,tools:l.length>0?l:void 0,maxTokens:2048,tier:"strong"});if(y+=E.usage.inputTokens,g+=E.usage.outputTokens,a.ping("processing",{iteration:b,maxIterations:o}),!E.toolCalls||E.toolCalls.length===0||b>=o)return a.ping("done",{iteration:b,maxIterations:o}),{success:!0,data:{response:E.content,iterations:b,usage:{inputTokens:y,outputTokens:g}},display:E.content};b++;let v=[];E.content&&v.push({type:"text",text:E.content});for(let x of E.toolCalls)v.push({type:"tool_use",id:x.id,name:x.name,input:x.input});h.push({role:"assistant",content:v});let R=[];for(let x of E.toolCalls){a.ping("tool_call",{iteration:b,maxIterations:o,tool:x.name});let O=await this.executeSubAgentTool(x,t);R.push({type:"tool_result",tool_use_id:x.id,content:O.content,is_error:O.isError})}h.push({role:"user",content:R})}}catch(b){return{success:!1,error:`Sub-agent failed: ${b instanceof Error?b.message:String(b)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var xe,nr=w(()=>{"use strict";xe=class{static{u(this,"EmailProvider")}}});var ki={};oe(ki,{MicrosoftGraphEmailProvider:()=>or});var or,vn=w(()=>{"use strict";nr();or=class extends xe{static{u(this,"MicrosoftGraphEmailProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let n=await s(this.accessToken);if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return n.status===204?void 0:n.json()}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);if(r.status!==204)return r.json()}async graphRequestRaw(e){let t=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${n}`}}),"doFetch"),s=await t(this.accessToken);if(s.status===401&&(await this.refreshAccessToken(),s=await t(this.accessToken)),!s.ok)throw new Error(`Graph API error: ${s.status}`);let r=await s.arrayBuffer();return Buffer.from(r)}async fetchInbox(e){let t=new URLSearchParams({$top:String(Math.min(Math.max(1,e),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/inbox/messages?${t}`)).value??[]).map(r=>this.mapMessage(r))}async readMessage(e){let t=new URLSearchParams({$select:"id,from,toRecipients,ccRecipients,bccRecipients,subject,body,receivedDateTime,isRead,hasAttachments"}),s=await this.graphRequest(`/me/messages/${e}?${t}`),r=[];return s.hasAttachments&&(r=((await this.graphRequest(`/me/messages/${e}/attachments?$select=id,name,contentType,size`)).value??[]).map(o=>({id:o.id,name:o.name,contentType:o.contentType,size:o.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(n=>this.formatGraphAddress(n)),subject:s.subject??"(no subject)",date:new Date(s.receivedDateTime),read:s.isRead??!1,body:s.body?.contentType==="html"?this.stripHtml(s.body.content??""):s.body?.content??"",bodyHtml:s.body?.contentType==="html"?s.body.content:void 0,cc:s.ccRecipients?.map(n=>this.formatGraphAddress(n)),bcc:s.bccRecipients?.map(n=>this.formatGraphAddress(n)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=new URLSearchParams({$search:`"${e}"`,$top:String(Math.min(Math.max(1,t),50)),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/messages?${s}`)).value??[]).map(n=>this.mapMessage(n))}async sendMessage(e){if(e.replyTo)return await this.graphRequest(`/me/messages/${e.replyTo}/reply`,{method:"POST",body:JSON.stringify({comment:e.body})}),{messageId:e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(s=>({emailAddress:{address:s.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(s=>({emailAddress:{address:s.trim()}}))),await this.graphRequest("/me/sendMail",{method:"POST",body:JSON.stringify({message:t})}),{messageId:`sent-${Date.now()}`}}async listFolders(){return((await this.graphRequest("/me/mailFolders?$select=displayName&$top=100")).value??[]).map(t=>t.displayName)}async fetchFolder(e,t){let r=((await this.graphRequest("/me/mailFolders?$select=id,displayName&$top=100")).value??[]).find(i=>i.displayName.toLowerCase()===e.toLowerCase());if(!r)throw new Error(`Folder "${e}" not found. Use the 'folders' action to list available folders.`);let n=new URLSearchParams({$top:String(Math.min(Math.max(1,t),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/${r.id}/messages?${n}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}mapMessage(e){return{id:e.id,from:this.formatGraphAddress(e.from),to:(e.toRecipients??[]).map(t=>this.formatGraphAddress(t)),subject:e.subject??"(no subject)",date:new Date(e.receivedDateTime),read:e.isRead??!1,preview:e.bodyPreview??void 0,hasAttachments:e.hasAttachments??!1}}formatGraphAddress(e){if(!e)return"unknown";let t=e.emailAddress??e;return t?.address?t.name?`${t.name} <${t.address}>`:t.address:"unknown"}stripHtml(e){return e.replace(/<br\s*\/?>/gi,`
385
+ `).replace(/<\/p>/gi,`
387
386
 
388
- `),m=o.filter(g=>!g.seen).length;return{success:!0,data:{messages:o,totalMessages:a,unreadCount:m},display:`Inbox (${a} total, ${m} unread):
387
+ `).replace(/<[^>]+>/g,"").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\n{3,}/g,`
389
388
 
390
- ${p}`}}finally{n.release()}}finally{await r.logout()}}async readMessage(e){if(!e)return{success:!1,error:"messageId is required. Use the sequence number from inbox."};let t=parseInt(e,10);if(isNaN(t)||t<1)return{success:!1,error:"messageId must be a positive number (sequence number)."};let{ImapFlow:s}=await import("imapflow"),r=new s({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1});try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=await r.fetchOne(String(t),{envelope:!0,source:!0});if(!o)return{success:!1,error:`Message #${t} not found.`};let i=o.envelope?.from?.[0],a=i?i.name?`${i.name} <${i.address}>`:i.address??"unknown":"unknown",l=o.envelope?.to?.map(m=>m.name?`${m.name} <${m.address}>`:m.address??"").join(", ")??"",d=o.source?.toString()??"",p=this.extractTextBody(d);return{success:!0,data:{seq:t,from:a,to:l,subject:o.envelope?.subject??"(no subject)",date:o.envelope?.date?.toISOString()??"",body:p},display:[`From: ${a}`,`To: ${l}`,`Subject: ${o.envelope?.subject??"(no subject)"}`,`Date: ${o.envelope?.date?.toISOString()??""}`,"",p.slice(0,3e3)+(p.length>3e3?`
391
-
392
- ... (truncated)`:"")].join(`
393
- `)}}finally{n.release()}}finally{await r.logout()}}async searchMessages(e,t){if(!e)return{success:!1,error:"query is required for search."};let s=Math.min(Math.max(1,t??10),50),{ImapFlow:r}=await import("imapflow"),n=new r({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1});try{await n.connect();let o=await n.getMailboxLock("INBOX");try{let i=await n.search({or:[{subject:e},{from:e},{body:e}]}),a=Array.isArray(i)?i:[];if(a.length===0)return{success:!0,data:{results:[]},display:`No emails found for "${e}".`};let l=a.slice(-s),d=[];for await(let m of n.fetch(l,{envelope:!0})){let g=m.envelope?.from?.[0],f=g?g.name?`${g.name} <${g.address}>`:g.address??"unknown":"unknown";d.push({seq:m.seq,from:f,subject:m.envelope?.subject??"(no subject)",date:m.envelope?.date?.toISOString()??""})}d.reverse();let p=d.map((m,g)=>`${g+1}. [#${m.seq}] ${m.subject}
394
- From: ${m.from}
395
- Date: ${m.date}`).join(`
396
-
397
- `);return{success:!0,data:{query:e,results:d,totalMatches:l.length},display:`Search results for "${e}" (${l.length} matches):
398
-
399
- ${p}`}}finally{o.release()}}finally{await n.logout()}}async sendMessage(e,t,s){if(!e)return{success:!1,error:'"to" (recipient email) is required.'};if(!t)return{success:!1,error:'"subject" is required.'};if(!s)return{success:!1,error:'"body" is required.'};let o=await(await import("nodemailer")).createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure,auth:this.config.auth}).sendMail({from:this.config.auth.user,to:e,subject:t,text:s});return{success:!0,data:{messageId:o.messageId,to:e,subject:t},display:`Email sent to ${e}
400
- Subject: ${t}
401
- Message ID: ${o.messageId}`}}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(`
389
+ `).trim()}}});var Si={};oe(Si,{StandardEmailProvider:()=>ir});var ir,kn=w(()=>{"use strict";nr();ir=class extends xe{static{u(this,"StandardEmailProvider")}config;constructor(e){super(),this.config=e}async initialize(){}createImapClient(){return import("imapflow").then(({ImapFlow:e})=>new e({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1}))}formatAddress(e){return e?e.name?`${e.name} <${e.address}>`:e.address??"unknown":"unknown"}async fetchInbox(e){return this.fetchFolder("INBOX",e)}async readMessage(e){let t=parseInt(e,10);if(isNaN(t)||t<1)throw new Error("messageId must be a positive number (sequence number).");let s=await this.createImapClient();try{await s.connect();let r=await s.getMailboxLock("INBOX");try{let n=await s.fetchOne(String(t),{envelope:!0,source:!0,bodyStructure:!0});if(!n)throw new Error(`Message #${t} not found.`);let o=this.formatAddress(n.envelope?.from?.[0]),i=n.envelope?.to?.map(h=>h.name?`${h.name} <${h.address}>`:h.address??"")??[],a=n.envelope?.cc?.map(h=>h.name?`${h.name} <${h.address}>`:h.address??""),l=n.source?.toString()??"",d=this.extractTextBody(l),m=this.extractAttachmentInfo(n.bodyStructure);return{id:String(t),from:o,to:i,subject:n.envelope?.subject??"(no subject)",date:n.envelope?.date??new Date,read:n.flags?.has("\\Seen")??!1,body:d,cc:a,attachments:m}}finally{r.release()}}finally{await s.logout()}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=await r.search({or:[{subject:e},{from:e},{body:e}]}),i=Array.isArray(o)?o:[];if(i.length===0)return[];let a=i.slice(-s),l=[];for await(let d of r.fetch(a,{envelope:!0,flags:!0}))l.push({id:String(d.seq),from:this.formatAddress(d.envelope?.from?.[0]),to:d.envelope?.to?.map(m=>m.name?`${m.name} <${m.address}>`:m.address??"")??[],subject:d.envelope?.subject??"(no subject)",date:d.envelope?.date??new Date,read:d.flags?.has("\\Seen")??!1});return l.reverse(),l}finally{n.release()}}finally{await r.logout()}}async sendMessage(e){let s=(await import("nodemailer")).createTransport({host:this.config.smtp.host,port:this.config.smtp.port,secure:this.config.smtp.secure,auth:this.config.auth}),r={from:this.config.auth.user,to:e.to,subject:e.subject};return e.cc&&(r.cc=e.cc),e.isHtml?r.html=e.body:r.text=e.body,e.replyTo&&(r.inReplyTo=e.replyTo,r.references=e.replyTo),{messageId:(await s.sendMail(r)).messageId}}async listFolders(){let e=await this.createImapClient();try{await e.connect();let t=await e.list(),s=[];for(let r of t)s.push(r.path);return s}finally{await e.logout()}}async fetchFolder(e,t){let s=Math.min(Math.max(1,t),50),r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock(e);try{let o=[],i=r.mailbox,a=i&&typeof i=="object"?i.exists??0:0;if(a===0)return[];let d=`${Math.max(1,a-s+1)}:*`;for await(let m of r.fetch(d,{envelope:!0,flags:!0})){let h=this.formatAddress(m.envelope?.from?.[0]);o.push({id:String(m.seq),from:h,to:m.envelope?.to?.map(b=>b.name?`${b.name} <${b.address}>`:b.address??"")??[],subject:m.envelope?.subject??"(no subject)",date:m.envelope?.date??new Date,read:m.flags?.has("\\Seen")??!1})}return o.reverse(),o}finally{n.release()}}finally{await r.logout()}}async downloadAttachment(e,t){let s=parseInt(e,10);if(isNaN(s)||s<1)throw new Error("messageId must be a positive number.");let r=await this.createImapClient();try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let i=(await r.fetchOne(String(s),{bodyParts:[t]}))?.bodyParts?.get(t);if(!i)throw new Error(`Attachment "${t}" not found in message #${s}.`);return Buffer.from(i)}finally{n.release()}}finally{await r.logout()}}extractAttachmentInfo(e){let t=[];if(!e)return t;let s=u((r,n)=>{if(r.childNodes){for(let i=0;i<r.childNodes.length;i++)s(r.childNodes[i],n?`${n}.${i+1}`:String(i+1));return}let o=r.disposition?.toLowerCase();if(o==="attachment"||r.type&&!r.type.startsWith("text/")&&o!=="inline"){let i=r.dispositionParameters?.filename??r.parameters?.name??`part-${n}`;t.push({id:r.part??n,name:i,contentType:r.type??"application/octet-stream",size:r.size??0})}},"walk");return s(e,""),t}extractTextBody(e){let t=e.split(/\r?\n\r?\n/);if(t.length<2)return e;let s=t[0].toLowerCase();if(!s.includes("multipart"))return this.decodeBody(t.slice(1).join(`
402
390
 
403
391
  `));let r=s.match(/boundary="?([^"\s;]+)"?/i)??e.match(/boundary="?([^"\s;]+)"?/i);if(!r)return t.slice(1).join(`
404
392
 
@@ -408,35 +396,61 @@ Message ID: ${o.messageId}`}}extractTextBody(e){let t=e.split(/\r?\n\r?\n/);if(t
408
396
  \r
409
397
  `);if(d>=0)return this.decodeBody(i.slice(d+4))}}return this.decodeBody(t.slice(1).join(`
410
398
 
411
- `).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()}}});var di,pt,ui=b(()=>{"use strict";D();di=1e5,pt=class extends ${static{u(this,"HttpSkill")}metadata={name:"http",description:"Make HTTP requests to fetch web pages or call REST APIs. Use when you need to read a URL, call an API endpoint, or fetch data from the web. Supports GET, POST, PUT, PATCH, DELETE methods.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL to request"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method (default: GET)"},headers:{type:"object",description:"Request headers as key-value pairs (optional)"},body:{type:"string",description:"Request body for POST/PUT/PATCH (optional)"}},required:["url"]}};async execute(e,t){let s=e.url,r=(e.method??"GET").toUpperCase(),n=e.headers,o=e.body;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "url"'};let i;try{i=new URL(s)}catch{return{success:!1,error:`Invalid URL: "${s}"`}}if(i.protocol!=="http:"&&i.protocol!=="https:")return{success:!1,error:`Unsupported URL scheme "${i.protocol}". Only http: and https: are allowed.`};if(this.isPrivateHost(i.hostname))return{success:!1,error:`Access to private/internal network address "${i.hostname}" is blocked.`};try{let a={method:r,headers:{"User-Agent":"Alfred/1.0",...n??{}},signal:AbortSignal.timeout(15e3)};o&&["POST","PUT","PATCH"].includes(r)&&(a.body=o,!n?.["Content-Type"]&&!n?.["content-type"]&&(a.headers["Content-Type"]="application/json"));let l=await fetch(s,a),d=l.headers.get("content-type")??"",p=await l.text(),m=p.length>di,g=m?p.slice(0,di)+`
399
+ `).slice(0,5e3))}decodeBody(e){return e.replace(/=\r?\n/g,"").replace(/=([0-9A-Fa-f]{2})/g,(t,s)=>String.fromCharCode(parseInt(s,16))).trim()}}});async function bs(c){if(c.provider==="microsoft"){if(!c.microsoft)throw new Error("Microsoft email config missing");let{MicrosoftGraphEmailProvider:s}=await Promise.resolve().then(()=>(vn(),ki)),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(()=>(kn(),Si)),t=new e(c);return await t.initialize(),t}var xi=w(()=>{"use strict";u(bs,"createEmailProvider")});var Me,Ii=w(()=>{"use strict";nr();xi();kn();vn();P();Me=class extends I{static{u(this,"EmailSkill")}metadata;providers;accountNames;defaultAccount;multiAccount;constructor(e){super(),e instanceof Map?this.providers=e:e?this.providers=new Map([["default",e]]):this.providers=new Map,this.accountNames=[...this.providers.keys()],this.defaultAccount=this.accountNames[0]??"default",this.multiAccount=this.providers.size>1;let t=this.multiAccount?{account:{type:"string",enum:this.accountNames,description:`Email account to use (available: ${this.accountNames.join(", ")})`}}:{},s=this.multiAccount?`Access the user's email accounts (${this.accountNames.join(", ")}): check inbox, read messages, search emails, send new emails, list folders, read from specific folders, reply to messages, or download attachments.`:"Access the user's email: check inbox, read messages, search emails, send new emails, list folders, read from specific folders, reply to messages, or download attachments. Use when the user asks about their emails or wants to send one.";this.metadata={name:"email",description:s,riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send","folders","folder","reply","attachment"],description:"The email action to perform"},...t,count:{type:"number",description:"Number of emails to fetch (for inbox/search/folder, default: 10)"},messageId:{type:"string",description:"Message ID to read or reply to"},query:{type:"string",description:"Search query (for search action)"},to:{type:"string",description:"Recipient email address (for send action)"},subject:{type:"string",description:"Email subject (for send action)"},body:{type:"string",description:"Email body text (for send/reply action)"},cc:{type:"string",description:"CC recipients, comma-separated (for send action)"},folder:{type:"string",description:"Folder name (for folder action)"},attachmentId:{type:"string",description:"Attachment ID (for attachment action)"},isHtml:{type:"boolean",description:"Whether the body is HTML (for send action)"}},required:["action"]}}}async execute(e,t){if(this.providers.size===0)return{success:!1,error:"Email is not configured. Run `alfred setup` to configure email access."};let s=e.action;try{switch(s){case"inbox":return await this.handleInbox(e);case"read":return await this.handleRead(e);case"search":return await this.handleSearch(e);case"send":return await this.handleSend(e);case"folders":return await this.handleFolders(e);case"folder":return await this.handleFolder(e);case"reply":return await this.handleReply(e);case"attachment":return await this.handleAttachment(e);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send, folders, folder, reply, attachment`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}resolveProvider(e){let t=e.account??this.defaultAccount,s=this.providers.get(t);return s?{provider:s,account:t}:{success:!1,error:`Unknown email account "${t}". Available: ${this.accountNames.join(", ")}`}}encodeId(e,t){return this.multiAccount?`${e}::${t}`:t}decodeId(e){if(this.multiAccount){let t=e.indexOf("::");if(t>=0)return{account:e.slice(0,t),rawId:e.slice(t+2)}}return{account:this.defaultAccount,rawId:e}}accountLabel(e,t){return this.multiAccount?`[${e}] ${t}`:t}async handleInbox(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,n=Math.min(Math.max(1,e.count??10),50),o=await s.fetchInbox(n);if(o.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(r,"Inbox is empty.")};let i=o.filter(l=>!l.read).length,a=o.map((l,d)=>{let m=l.read?"":" [UNREAD]",h=l.hasAttachments?" [ATT]":"";return`${d+1}. [${this.encodeId(r,l.id)}]${m}${h} ${l.subject}
400
+ From: ${l.from}
401
+ Date: ${l.date.toISOString()}`}).join(`
402
+
403
+ `);return{success:!0,data:{messages:o.map(l=>({...l,id:this.encodeId(r,l.id)})),unreadCount:i},display:this.accountLabel(r,`Inbox (${i} unread):
404
+
405
+ ${a}`)}}async handleRead(e){let t=e.messageId;if(!t)return{success:!1,error:"messageId is required."};let{account:s,rawId:r}=this.decodeId(t),n=this.providers.get(s);if(!n)return{success:!1,error:`Unknown email account "${s}".`};let o=await n.readMessage(r),i=o.attachments?.length?`
406
+ Attachments: ${o.attachments.map(a=>`${a.name} (${a.contentType}, ${this.formatSize(a.size)})`).join(", ")}`:"";return{success:!0,data:{...o,id:this.encodeId(s,o.id)},display:this.accountLabel(s,[`From: ${o.from}`,`To: ${o.to.join(", ")}`,...o.cc?.length?[`CC: ${o.cc.join(", ")}`]:[],`Subject: ${o.subject}`,`Date: ${o.date.toISOString()}`,i,"",o.body.slice(0,3e3)+(o.body.length>3e3?`
407
+
408
+ ... (truncated)`:"")].join(`
409
+ `))}}async handleSearch(e){let t=e.query;if(!t)return{success:!1,error:"query is required for search."};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.count??10),50),i=await r.searchMessages(t,o);if(i.length===0)return{success:!0,data:{results:[]},display:this.accountLabel(n,`No emails found for "${t}".`)};let a=i.map((l,d)=>`${d+1}. [${this.encodeId(n,l.id)}] ${l.subject}
410
+ From: ${l.from}
411
+ Date: ${l.date.toISOString()}`).join(`
412
+
413
+ `);return{success:!0,data:{query:t,results:i.map(l=>({...l,id:this.encodeId(n,l.id)})),totalMatches:i.length},display:this.accountLabel(n,`Search results for "${t}" (${i.length} matches):
414
+
415
+ ${a}`)}}async handleSend(e){let t=e.to,s=e.subject,r=e.body;if(!t)return{success:!1,error:'"to" (recipient email) is required.'};if(!s)return{success:!1,error:'"subject" is required.'};if(!r)return{success:!1,error:'"body" is required.'};let n=this.resolveProvider(e);if("success"in n)return n;let{provider:o,account:i}=n,a=await o.sendMessage({to:t,subject:s,body:r,cc:e.cc,isHtml:e.isHtml});return{success:!0,data:{messageId:a.messageId,to:t,subject:s},display:this.accountLabel(i,`Email sent to ${t}
416
+ Subject: ${s}
417
+ Message ID: ${a.messageId}`)}}async handleFolders(e){let t=this.resolveProvider(e);if("success"in t)return t;let{provider:s,account:r}=t,n=await s.listFolders();return{success:!0,data:{folders:n},display:n.length===0?this.accountLabel(r,"No folders found."):this.accountLabel(r,`Email folders:
418
+ ${n.map((o,i)=>` ${i+1}. ${o}`).join(`
419
+ `)}`)}}async handleFolder(e){let t=e.folder;if(!t)return{success:!1,error:'"folder" name is required. Use the "folders" action to list available folders.'};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.count??10),50),i=await r.fetchFolder(t,o);if(i.length===0)return{success:!0,data:{messages:[]},display:this.accountLabel(n,`Folder "${t}" is empty.`)};let a=i.map((l,d)=>{let m=l.read?"":" [UNREAD]";return`${d+1}. [${this.encodeId(n,l.id)}]${m} ${l.subject}
420
+ From: ${l.from}
421
+ Date: ${l.date.toISOString()}`}).join(`
422
+
423
+ `);return{success:!0,data:{folder:t,messages:i.map(l=>({...l,id:this.encodeId(n,l.id)}))},display:this.accountLabel(n,`Folder "${t}" (${i.length} messages):
424
+
425
+ ${a}`)}}async handleReply(e){let t=e.messageId,s=e.body;if(!t)return{success:!1,error:'"messageId" is required for reply.'};if(!s)return{success:!1,error:'"body" is required for reply.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);return o?{success:!0,data:{messageId:(await o.sendMessage({to:"",subject:"",body:s,replyTo:n})).messageId},display:this.accountLabel(r,`Reply sent to message ${n}.`)}:{success:!1,error:`Unknown email account "${r}".`}}async handleAttachment(e){let t=e.messageId,s=e.attachmentId;if(!t)return{success:!1,error:'"messageId" is required.'};if(!s)return{success:!1,error:'"attachmentId" is required.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);if(!o)return{success:!1,error:`Unknown email account "${r}".`};let a=(await o.readMessage(n)).attachments?.find(h=>h.id===s),l=await o.downloadAttachment(n,s),d=a?.name??`attachment-${s}`,m=a?.contentType??"application/octet-stream";return{success:!0,data:{messageId:t,attachmentId:s,fileName:d,size:l.length},display:this.accountLabel(r,`Downloaded attachment: ${d} (${this.formatSize(l.length)})`),attachments:[{fileName:d,data:l,mimeType:m}]}}formatSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Ai,wt,Ri=w(()=>{"use strict";P();Ai=1e5,wt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",description:"Make HTTP requests to fetch web pages or call REST APIs. Use when you need to read a URL, call an API endpoint, or fetch data from the web. Supports GET, POST, PUT, PATCH, DELETE methods.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL to request"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method (default: GET)"},headers:{type:"object",description:"Request headers as key-value pairs (optional)"},body:{type:"string",description:"Request body for POST/PUT/PATCH (optional)"}},required:["url"]}};async execute(e,t){let s=e.url,r=(e.method??"GET").toUpperCase(),n=e.headers,o=e.body;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "url"'};let i;try{i=new URL(s)}catch{return{success:!1,error:`Invalid URL: "${s}"`}}if(i.protocol!=="http:"&&i.protocol!=="https:")return{success:!1,error:`Unsupported URL scheme "${i.protocol}". Only http: and https: are allowed.`};if(this.isPrivateHost(i.hostname))return{success:!1,error:`Access to private/internal network address "${i.hostname}" is blocked.`};try{let a={method:r,headers:{"User-Agent":"Alfred/1.0",...n??{}},signal:AbortSignal.timeout(15e3)};o&&["POST","PUT","PATCH"].includes(r)&&(a.body=o,!n?.["Content-Type"]&&!n?.["content-type"]&&(a.headers["Content-Type"]="application/json"));let l=await fetch(s,a),d=l.headers.get("content-type")??"",m=await l.text(),h=m.length>Ai,b=h?m.slice(0,Ai)+`
412
426
 
413
- [... truncated]`:p,f=g;d.includes("text/html")&&(f=this.stripHtml(g).slice(0,1e4));let h={status:l.status,statusText:l.statusText,contentType:d,bodyLength:p.length,truncated:m,body:g};return l.ok?{success:!0,data:h,display:`HTTP ${l.status} OK (${p.length} bytes)
427
+ [... truncated]`:m,y=b;d.includes("text/html")&&(y=this.stripHtml(b).slice(0,1e4));let g={status:l.status,statusText:l.statusText,contentType:d,bodyLength:m.length,truncated:h,body:b};return l.ok?{success:!0,data:g,display:`HTTP ${l.status} OK (${m.length} bytes)
414
428
 
415
- ${f.slice(0,5e3)}`}:{success:!0,data:h,display:`HTTP ${l.status} ${l.statusText}
429
+ ${y.slice(0,5e3)}`}:{success:!0,data:g,display:`HTTP ${l.status} ${l.statusText}
416
430
 
417
- ${f.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import H from"node:fs";import Ie from"node:path";var pn,pi,Wc,mt,mi=b(()=>{"use strict";D();pn=5e5,pi=5e7,Wc={".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"},mt=class extends ${static{u(this,"FileSkill")}metadata={name:"file",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. The content is likely too large to include in a tool call. Use the code_sandbox skill instead \u2014 write COMPACT data-driven code: define your data as arrays/objects, then build HTML/text programmatically with .map()/.join(). Example: const data = [{h:8,p:5.2},{h:9,p:4.1}]; const rows = data.map(r => \`<tr><td>\${r.h}</td><td>\${r.p}</td></tr>\`).join(''); fs.writeFileSync('output.html', \`<table>\${rows}</table>\`); \u2014 the sandbox collects output files automatically. Do NOT embed large string literals.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(H.existsSync(i)&&H.lstatSync(i).isSymbolicLink()){let l=H.realpathSync(i);if(this.checkBlocked(l))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return Ie.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=Ie.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=H.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>pn){let r=H.readFileSync(e,"utf-8").slice(0,pn);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${pn}):
431
+ ${y.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import z from"node:fs";import Ne from"node:path";var Sn,Li,hl,bt,Mi=w(()=>{"use strict";P();Sn=5e5,Li=5e7,hl={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".rtf":"application/rtf",".epub":"application/epub+zip",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".tsv":"text/tab-separated-values",".html":"text/html",".htm":"text/html",".xml":"application/xml",".yaml":"application/yaml",".yml":"application/yaml",".toml":"application/toml",".ini":"text/plain",".cfg":"text/plain",".log":"text/plain",".json":"application/json",".js":"application/javascript",".ts":"application/typescript",".py":"text/x-python",".sh":"application/x-sh",".sql":"application/sql",".css":"text/css",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".flac":"audio/flac",".aac":"audio/aac",".m4a":"audio/mp4",".mp4":"video/mp4",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".mov":"video/quicktime",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2"},bt=class extends I{static{u(this,"FileSkill")}metadata={name:"file",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it. IMPORTANT: For large content (HTML pages, long text), use code_sandbox instead to generate the file programmatically.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. The content is likely too large to include in a tool call. Use the code_sandbox skill instead \u2014 write COMPACT data-driven code: define your data as arrays/objects, then build HTML/text programmatically with .map()/.join(). Example: const data = [{h:8,p:5.2},{h:9,p:4.1}]; const rows = data.map(r => \`<tr><td>\${r.h}</td><td>\${r.p}</td></tr>\`).join(''); fs.writeFileSync('output.html', \`<table>\${rows}</table>\`); \u2014 the sandbox collects output files automatically. Do NOT embed large string literals.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(z.existsSync(i)&&z.lstatSync(i).isSymbolicLink()){let l=z.realpathSync(i);if(this.checkBlocked(l))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return Ne.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=Ne.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=z.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Sn){let r=z.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}):
418
432
 
419
- ${r}`}}let s=H.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=Ie.dirname(e);return H.mkdirSync(s,{recursive:!0}),H.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 H.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=H.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
420
- `);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=H.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}
433
+ ${r}`}}let s=z.readFileSync(e,"utf-8");return{success:!0,data:{path:e,size:t.size,content:s},display:s}}catch(t){return{success:!1,error:`Cannot read "${e}": ${t.message}`}}}writeFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for write action'};try{let s=Ne.dirname(e);return z.mkdirSync(s,{recursive:!0}),z.writeFileSync(e,t,"utf-8"),{success:!0,data:{path:e,bytes:Buffer.byteLength(t)},display:`Written ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}appendFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for append action'};try{return z.appendFileSync(e,t,"utf-8"),{success:!0,data:{path:e,appendedBytes:Buffer.byteLength(t)},display:`Appended ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot append to "${e}": ${s.message}`}}}listDir(e){try{let s=z.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
434
+ `);return{success:!0,data:{path:e,entries:s},display:r}}catch(t){return{success:!1,error:`Cannot list "${e}": ${t.message}`}}}fileInfo(e){try{let t=z.statSync(e),s={path:e,type:t.isDirectory()?"directory":t.isFile()?"file":"other",size:t.size,created:t.birthtime.toISOString(),modified:t.mtime.toISOString(),permissions:t.mode.toString(8)};return{success:!0,data:s,display:`${s.type}: ${e}
421
435
  Size: ${t.size} bytes
422
- Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=H.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=Ie.dirname(e);H.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return H.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Ie.dirname(s);return H.mkdirSync(n,{recursive:!0}),H.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return H.copyFileSync(e,s),H.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Ie.dirname(s);return H.mkdirSync(n,{recursive:!0}),H.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!H.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=H.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>pi)return{success:!1,error:`File too large to send (${t.size} bytes, max ${pi})`};let s=H.readFileSync(e),r=Ie.basename(e),n=Ie.extname(e).toLowerCase(),o=Wc[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return H.existsSync(e)?H.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(H.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 ht}from"node:child_process";var ft,hi=b(()=>{"use strict";D();ft=class extends ${static{u(this,"ClipboardSkill")}metadata={name:"clipboard",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=ht("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=ht("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=ht("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)+`
436
+ Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=z.existsSync(e);return{success:!0,data:{path:e,exists:t},display:t?`Yes, "${e}" exists`:`No, "${e}" does not exist`}}writeBinaryFile(e,t){if(!t)return{success:!1,error:'Missing "content" (base64-encoded) for write_binary action'};try{let s=Ne.dirname(e);z.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return z.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Ne.dirname(s);return z.mkdirSync(n,{recursive:!0}),z.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return z.copyFileSync(e,s),z.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=Ne.dirname(s);return z.mkdirSync(n,{recursive:!0}),z.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!z.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=z.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Li)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Li})`};let s=z.readFileSync(e),r=Ne.basename(e),n=Ne.extname(e).toLowerCase(),o=hl[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return z.existsSync(e)?z.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(z.unlinkSync(e),{success:!0,data:{path:e},display:`Deleted ${e}`}):{success:!1,error:`"${e}" does not exist`}}catch(t){return{success:!1,error:`Cannot delete "${e}": ${t.message}`}}}}});import{execSync as Tt}from"node:child_process";var Et,Ni=w(()=>{"use strict";P();Et=class extends I{static{u(this,"ClipboardSkill")}metadata={name:"clipboard",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=Tt("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Tt("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Tt("xclip -selection clipboard -o 2>/dev/null || xsel --clipboard --output",{encoding:"utf-8",timeout:5e3});break}return!e||e.trim().length===0?{success:!0,data:{content:""},display:"Clipboard is empty."}:{success:!0,data:{content:e},display:e.length>2e3?e.slice(0,2e3)+`
423
437
 
424
- [... 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":ht("pbcopy",{input:e,timeout:5e3});break;case"win32":ht('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:ht("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 ds}from"node:child_process";import fi from"node:path";import Xc from"node:os";var gt,gi=b(()=>{"use strict";D();gt=class extends ${static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=fi.join(Xc.homedir(),"Desktop"),n=e.path||fi.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":ds(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":ds(`powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height); $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size); $bitmap.Save('${n.replace(/'/g,"''")}'); $graphics.Dispose(); $bitmap.Dispose()"`,{timeout:1e4});break;default:try{ds(`scrot "${n}"`,{timeout:1e4})}catch{try{ds(`import -window root "${n}"`,{timeout:1e4})}catch{ds(`gnome-screenshot -f "${n}"`,{timeout:1e4})}}break}return{success:!0,data:{path:n},display:`Screenshot saved to ${n}`}}catch(o){return{success:!1,error:`Screenshot failed: ${o.message}`}}}}});import Hc from"node:path";import Vc from"node:os";var yi,yt,wi=b(()=>{"use strict";D();yi=5e4,yt=class extends ${static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
438
+ [... truncated]`:e}}catch(e){return{success:!1,error:`Failed to read clipboard: ${e.message}`}}}writeClipboard(e){if(!e||typeof e!="string")return{success:!1,error:'Missing "text" for write action'};try{switch(process.platform){case"darwin":Tt("pbcopy",{input:e,timeout:5e3});break;case"win32":Tt('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Tt("xclip -selection clipboard 2>/dev/null || xsel --clipboard --input",{input:e,timeout:5e3});break}return{success:!0,data:{copiedLength:e.length},display:`Copied ${e.length} characters to clipboard.`}}catch(t){return{success:!1,error:`Failed to write clipboard: ${t.message}`}}}}});import{execSync as Ts}from"node:child_process";import Ci from"node:path";import fl from"node:os";var _t,Oi=w(()=>{"use strict";P();_t=class extends I{static{u(this,"ScreenshotSkill")}metadata={name:"screenshot",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=Ci.join(fl.homedir(),"Desktop"),n=e.path||Ci.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Ts(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":Ts(`powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height); $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size); $bitmap.Save('${n.replace(/'/g,"''")}'); $graphics.Dispose(); $bitmap.Dispose()"`,{timeout:1e4});break;default:try{Ts(`scrot "${n}"`,{timeout:1e4})}catch{try{Ts(`import -window root "${n}"`,{timeout:1e4})}catch{Ts(`gnome-screenshot -f "${n}"`,{timeout:1e4})}}break}return{success:!0,data:{path:n},display:`Screenshot saved to ${n}`}}catch(o){return{success:!1,error:`Screenshot failed: ${o.message}`}}}}});import gl from"node:path";import yl from"node:os";var Di,$t,Ui=w(()=>{"use strict";P();Di=5e4,$t=class extends I{static{u(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
425
439
  Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.openPage(r,e);case"screenshot":return this.screenshotPage(r,e);case"click":return this.clickElement(e);case"type":return this.typeText(e);case"evaluate":return this.evaluateScript(e);default:return{success:!1,error:`Unknown action "${s}". Valid: open, screenshot, click, type, evaluate, close`}}}async loadPuppeteer(){try{let e=await Function('return import("puppeteer")')();return this.resolvePuppeteerModule(e)}catch{try{let e=await Function('return import("puppeteer-core")')();return this.resolvePuppeteerModule(e)}catch{return null}}}resolvePuppeteerModule(e){let t=e;return typeof t.launch=="function"?t:t.default}async ensureBrowser(e){return this.browser&&this.browser.connected?this.browser:(this.browser=await e.launch({headless:!0,args:["--no-sandbox","--disable-setuid-sandbox","--disable-dev-shm-usage"]}),this.browser)}async ensurePage(e){let t=await this.ensureBrowser(e);return this.page||(this.page=await t.newPage(),await this.page.setViewport({width:1280,height:900})),this.page}async openPage(e,t){let s=t.url;if(!s)return{success:!1,error:'Missing "url" for open action'};let r=this.validateUrl(s);if(r)return{success:!1,error:r};try{let n=await this.ensurePage(e);await n.goto(s,{waitUntil:"networkidle2",timeout:3e4});let o=await n.title(),i=await n.evaluate(`
426
440
  (() => {
427
441
  document.querySelectorAll('script, style, noscript').forEach(el => el.remove());
428
442
  return document.body?.innerText ?? '';
429
443
  })()
430
- `),l=(i.length>yi?i.slice(0,yi)+`
444
+ `),l=(i.length>Di?i.slice(0,Di)+`
431
445
 
432
446
  [... truncated]`:i).replace(/\n{3,}/g,`
433
447
 
434
448
  `).trim();return{success:!0,data:{url:n.url(),title:o,length:i.length},display:`**${o}** (${n.url()})
435
449
 
436
- ${l}`}}catch(n){return{success:!1,error:`Failed to open "${s}": ${n.message}`}}}async screenshotPage(e,t){try{let s=await this.ensurePage(e),r=t.url;r&&await s.goto(r,{waitUntil:"networkidle2",timeout:3e4});let n=s.url();if(n==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let o=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||Hc.join(Vc.homedir(),"Desktop",`browser-${o}.png`);return await s.screenshot({path:i,fullPage:!1}),{success:!0,data:{path:i,url:n},display:`Screenshot saved to ${i}`}}catch(s){return{success:!1,error:`Screenshot failed: ${s.message}`}}}async clickElement(e){let t=e.selector;if(!t)return{success:!1,error:'Missing "selector" for click action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t);try{await this.page.waitForNavigation({timeout:3e3})}catch{}let s=await this.page.title();return{success:!0,data:{selector:t,url:this.page.url(),title:s},display:`Clicked "${t}" \u2014 now on: ${s} (${this.page.url()})`}}catch(s){return{success:!1,error:`Click failed on "${t}": ${s.message}`}}}async typeText(e){let t=e.selector,s=e.text;if(!t)return{success:!1,error:'Missing "selector" for type action'};if(!s)return{success:!1,error:'Missing "text" for type action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{return await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t),await this.page.type(t,s,{delay:50}),{success:!0,data:{selector:t,textLength:s.length},display:`Typed ${s.length} characters into "${t}"`}}catch(r){return{success:!1,error:`Type failed on "${t}": ${r.message}`}}}async evaluateScript(e){let t=e.script;if(!t)return{success:!1,error:'Missing "script" for evaluate action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{let s=await this.page.evaluate(t),r=typeof s=="string"?s:JSON.stringify(s,null,2);return{success:!0,data:{result:s},display:r?.slice(0,1e4)??"(no output)"}}catch(s){return{success:!1,error:`Evaluate failed: ${s.message}`}}}validateUrl(e){let t;try{t=new URL(e)}catch{return`Invalid URL: "${e}"`}if(["file:","chrome:","about:","data:","javascript:"].includes(t.protocol))return`Blocked URL protocol "${t.protocol}". Only http: and https: are allowed.`;if(t.protocol!=="http:"&&t.protocol!=="https:")return`Unsupported URL protocol "${t.protocol}". Only http: and https: are allowed.`;let r=t.hostname;return this.isPrivateHost(r)?`Access to private/internal network address "${r}" is blocked.`:null}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;if(e.startsWith("[")||e.toLowerCase().startsWith("fc")||e.toLowerCase().startsWith("fd")){let s=e.replace(/[\[\]]/g,"").toLowerCase();if(s.startsWith("fc")||s.startsWith("fd")||s==="::1")return!0}let t=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(t){let[,s,r]=t.map(Number);if(s===10||s===172&&r>=16&&r<=31||s===192&&r===168||s===127||s===169&&r===254||s===0)return!0}return!1}async closeBrowser(){try{return this.page=null,this.browser&&(await this.browser.close(),this.browser=null),{success:!0,display:"Browser closed."}}catch(e){return this.browser=null,this.page=null,{success:!1,error:`Close failed: ${e.message}`}}}}});var wt,bi=b(()=>{"use strict";D();wt=class extends ${static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",description:"Manage user profile settings including timezone, language, and bio. Use this to personalize Alfred for each user.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set_timezone","set_language","set_bio","set_preference"],description:"The profile action to perform"},value:{type:"string",description:"The value to set (for set_* actions)"},preference_key:{type:"string",description:"The preference key (for set_preference)"},preference_value:{type:"string",description:"The preference value (for set_preference)"}},required:["action"]}};constructor(e){super(),this.userRepo=e}async execute(e,t){let s=e.action,r=this.userRepo.findOrCreate(t.platform,t.userId),n="getMasterUserId"in this.userRepo?this.userRepo.getMasterUserId(r.id):r.id,o=("findById"in this.userRepo?this.userRepo.findById(n):r)??r;switch(s){case"get":return this.getProfile(o.id);case"set_timezone":return this.setField(o.id,"timezone",e.value);case"set_language":return this.setField(o.id,"language",e.value);case"set_bio":return this.setField(o.id,"bio",e.value);case"set_preference":return this.setPreference(o.id,e.preference_key,e.preference_value);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}getProfile(e){let t=this.userRepo.getProfile(e);if(!t)return{success:!0,data:null,display:"No profile found. Set your timezone, language, or bio to create one."};let s=[];if(t.displayName&&s.push(`Name: ${t.displayName}`),t.timezone&&s.push(`Timezone: ${t.timezone}`),t.language&&s.push(`Language: ${t.language}`),t.bio&&s.push(`Bio: ${t.bio}`),t.preferences)for(let[r,n]of Object.entries(t.preferences))s.push(`${r}: ${String(n)}`);return{success:!0,data:t,display:s.length>0?`Profile:
450
+ ${l}`}}catch(n){return{success:!1,error:`Failed to open "${s}": ${n.message}`}}}async screenshotPage(e,t){try{let s=await this.ensurePage(e),r=t.url;r&&await s.goto(r,{waitUntil:"networkidle2",timeout:3e4});let n=s.url();if(n==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let o=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||gl.join(yl.homedir(),"Desktop",`browser-${o}.png`);return await s.screenshot({path:i,fullPage:!1}),{success:!0,data:{path:i,url:n},display:`Screenshot saved to ${i}`}}catch(s){return{success:!1,error:`Screenshot failed: ${s.message}`}}}async clickElement(e){let t=e.selector;if(!t)return{success:!1,error:'Missing "selector" for click action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t);try{await this.page.waitForNavigation({timeout:3e3})}catch{}let s=await this.page.title();return{success:!0,data:{selector:t,url:this.page.url(),title:s},display:`Clicked "${t}" \u2014 now on: ${s} (${this.page.url()})`}}catch(s){return{success:!1,error:`Click failed on "${t}": ${s.message}`}}}async typeText(e){let t=e.selector,s=e.text;if(!t)return{success:!1,error:'Missing "selector" for type action'};if(!s)return{success:!1,error:'Missing "text" for type action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{return await this.page.waitForSelector(t,{timeout:5e3}),await this.page.click(t),await this.page.type(t,s,{delay:50}),{success:!0,data:{selector:t,textLength:s.length},display:`Typed ${s.length} characters into "${t}"`}}catch(r){return{success:!1,error:`Type failed on "${t}": ${r.message}`}}}async evaluateScript(e){let t=e.script;if(!t)return{success:!1,error:'Missing "script" for evaluate action'};if(!this.page)return{success:!1,error:'No page is open. Use action "open" first.'};try{let s=await this.page.evaluate(t),r=typeof s=="string"?s:JSON.stringify(s,null,2);return{success:!0,data:{result:s},display:r?.slice(0,1e4)??"(no output)"}}catch(s){return{success:!1,error:`Evaluate failed: ${s.message}`}}}validateUrl(e){let t;try{t=new URL(e)}catch{return`Invalid URL: "${e}"`}if(["file:","chrome:","about:","data:","javascript:"].includes(t.protocol))return`Blocked URL protocol "${t.protocol}". Only http: and https: are allowed.`;if(t.protocol!=="http:"&&t.protocol!=="https:")return`Unsupported URL protocol "${t.protocol}". Only http: and https: are allowed.`;let r=t.hostname;return this.isPrivateHost(r)?`Access to private/internal network address "${r}" is blocked.`:null}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;if(e.startsWith("[")||e.toLowerCase().startsWith("fc")||e.toLowerCase().startsWith("fd")){let s=e.replace(/[\[\]]/g,"").toLowerCase();if(s.startsWith("fc")||s.startsWith("fd")||s==="::1")return!0}let t=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(t){let[,s,r]=t.map(Number);if(s===10||s===172&&r>=16&&r<=31||s===192&&r===168||s===127||s===169&&r===254||s===0)return!0}return!1}async closeBrowser(){try{return this.page=null,this.browser&&(await this.browser.close(),this.browser=null),{success:!0,display:"Browser closed."}}catch(e){return this.browser=null,this.page=null,{success:!1,error:`Close failed: ${e.message}`}}}}});var vt,Pi=w(()=>{"use strict";P();vt=class extends I{static{u(this,"ProfileSkill")}userRepo;metadata={name:"profile",description:"Manage user profile settings including timezone, language, and bio. Use this to personalize Alfred for each user.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","set_timezone","set_language","set_bio","set_preference"],description:"The profile action to perform"},value:{type:"string",description:"The value to set (for set_* actions)"},preference_key:{type:"string",description:"The preference key (for set_preference)"},preference_value:{type:"string",description:"The preference value (for set_preference)"}},required:["action"]}};constructor(e){super(),this.userRepo=e}async execute(e,t){let s=e.action,r=this.userRepo.findOrCreate(t.platform,t.userId),n="getMasterUserId"in this.userRepo?this.userRepo.getMasterUserId(r.id):r.id,o=("findById"in this.userRepo?this.userRepo.findById(n):r)??r;switch(s){case"get":return this.getProfile(o.id);case"set_timezone":return this.setField(o.id,"timezone",e.value);case"set_language":return this.setField(o.id,"language",e.value);case"set_bio":return this.setField(o.id,"bio",e.value);case"set_preference":return this.setPreference(o.id,e.preference_key,e.preference_value);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}getProfile(e){let t=this.userRepo.getProfile(e);if(!t)return{success:!0,data:null,display:"No profile found. Set your timezone, language, or bio to create one."};let s=[];if(t.displayName&&s.push(`Name: ${t.displayName}`),t.timezone&&s.push(`Timezone: ${t.timezone}`),t.language&&s.push(`Language: ${t.language}`),t.bio&&s.push(`Bio: ${t.bio}`),t.preferences)for(let[r,n]of Object.entries(t.preferences))s.push(`${r}: ${String(n)}`);return{success:!0,data:t,display:s.length>0?`Profile:
437
451
  ${s.map(r=>`- ${r}`).join(`
438
- `)}`:"Profile is empty."}}setField(e,t,s){return!s||typeof s!="string"?{success:!1,error:`Missing required "value" for ${t}`}:(this.userRepo.updateProfile(e,{[t]:s}),{success:!0,data:{[t]:s},display:`${t} set to "${s}"`})}setPreference(e,t,s){if(!t||typeof t!="string")return{success:!1,error:'Missing required "preference_key"'};let n=this.userRepo.getProfile(e)?.preferences??{};return n[t]=s,this.userRepo.updateProfile(e,{preferences:n}),{success:!0,data:{key:t,value:s},display:`Preference "${t}" set to "${s}"`}}}});var me,us=b(()=>{"use strict";me=class{static{u(this,"CalendarProvider")}}});var Ti={};le(Ti,{CalDAVProvider:()=>Zs});var Zs,mn=b(()=>{"use strict";us();Zs=class extends me{static{u(this,"CalDAVProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"caldav"})}catch(e){throw new Error(`CalDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){let s=await this.client.fetchCalendars();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchCalendarObjects({calendar:n,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of o){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.start.getTime()-o.start.getTime())}async createEvent(e){let t=await this.client.fetchCalendars();if(!t||t.length===0)throw new Error("No calendars found");let s=`alfred-${Date.now()}@alfred`,r=this.buildICalEvent(s,e);return await this.client.createCalendarObject({calendar:t[0],filename:`${s}.ics`,iCalString:r}),{id:s,title:e.title,start:e.start,end:e.end,location:e.location,description:e.description,allDay:e.allDay}}async updateEvent(e,t){let s=await this.client.fetchCalendars();for(let r of s){let n=await this.client.fetchCalendarObjects({calendar:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseICalEvent(o.data,o.url);if(!i)continue;let a={title:t.title??i.title,start:t.start??i.start,end:t.end??i.end,location:t.location??i.location,description:t.description??i.description,allDay:t.allDay??i.allDay},l=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:l}}),{id:e,...a}}}throw new Error(`Event ${e} not found`)}async deleteEvent(e){let t=await this.client.fetchCalendars();for(let s of t){let r=await this.client.fetchCalendarObjects({calendar:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:n});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
439
- `).map(m=>m.trim()),r=u(m=>s.find(g=>g.startsWith(m+":"))?.slice(m.length+1),"get"),n=r("SUMMARY"),o=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),l=r("DESCRIPTION"),d=r("UID")??t;if(!n||!o)return;let p=o.length===8;return{id:d,title:n,start:this.parseICalDate(o),end:i?this.parseICalDate(i):this.parseICalDate(o),location:a||void 0,description:l||void 0,allDay:p}}catch(s){console.error("[caldav] Failed to parse iCal event",s);return}}parseICalDate(e){if(e.length===8)return new Date(`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`);let t=e.replace(/[^0-9TZ]/g,"");return t.length>=15?new Date(`${t.slice(0,4)}-${t.slice(4,6)}-${t.slice(6,8)}T${t.slice(9,11)}:${t.slice(11,13)}:${t.slice(13,15)}Z`):new Date(e)}buildICalEvent(e,t){let s=u((n,o)=>o?n.toISOString().slice(0,10).replace(/-/g,""):n.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
452
+ `)}`:"Profile is empty."}}setField(e,t,s){return!s||typeof s!="string"?{success:!1,error:`Missing required "value" for ${t}`}:(this.userRepo.updateProfile(e,{[t]:s}),{success:!0,data:{[t]:s},display:`${t} set to "${s}"`})}setPreference(e,t,s){if(!t||typeof t!="string")return{success:!1,error:'Missing required "preference_key"'};let n=this.userRepo.getProfile(e)?.preferences??{};return n[t]=s,this.userRepo.updateProfile(e,{preferences:n}),{success:!0,data:{key:t,value:s},display:`Preference "${t}" set to "${s}"`}}}});var ye,Es=w(()=>{"use strict";ye=class{static{u(this,"CalendarProvider")}}});var Fi={};oe(Fi,{CalDAVProvider:()=>ar});var ar,xn=w(()=>{"use strict";Es();ar=class extends ye{static{u(this,"CalDAVProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"caldav"})}catch(e){throw new Error(`CalDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){let s=await this.client.fetchCalendars();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchCalendarObjects({calendar:n,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of o){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.start.getTime()-o.start.getTime())}async createEvent(e){let t=await this.client.fetchCalendars();if(!t||t.length===0)throw new Error("No calendars found");let s=`alfred-${Date.now()}@alfred`,r=this.buildICalEvent(s,e);return await this.client.createCalendarObject({calendar:t[0],filename:`${s}.ics`,iCalString:r}),{id:s,title:e.title,start:e.start,end:e.end,location:e.location,description:e.description,allDay:e.allDay}}async updateEvent(e,t){let s=await this.client.fetchCalendars();for(let r of s){let n=await this.client.fetchCalendarObjects({calendar:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseICalEvent(o.data,o.url);if(!i)continue;let a={title:t.title??i.title,start:t.start??i.start,end:t.end??i.end,location:t.location??i.location,description:t.description??i.description,allDay:t.allDay??i.allDay},l=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:l}}),{id:e,...a}}}throw new Error(`Event ${e} not found`)}async deleteEvent(e){let t=await this.client.fetchCalendars();for(let s of t){let r=await this.client.fetchCalendarObjects({calendar:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:n});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
453
+ `).map(h=>h.trim()),r=u(h=>s.find(b=>b.startsWith(h+":"))?.slice(h.length+1),"get"),n=r("SUMMARY"),o=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),l=r("DESCRIPTION"),d=r("UID")??t;if(!n||!o)return;let m=o.length===8;return{id:d,title:n,start:this.parseICalDate(o),end:i?this.parseICalDate(i):this.parseICalDate(o),location:a||void 0,description:l||void 0,allDay:m}}catch(s){console.error("[caldav] Failed to parse iCal event",s);return}}parseICalDate(e){if(e.length===8)return new Date(`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`);let t=e.replace(/[^0-9TZ]/g,"");return t.length>=15?new Date(`${t.slice(0,4)}-${t.slice(4,6)}-${t.slice(6,8)}T${t.slice(9,11)}:${t.slice(11,13)}:${t.slice(13,15)}Z`):new Date(e)}buildICalEvent(e,t){let s=u((n,o)=>o?n.toISOString().slice(0,10).replace(/-/g,""):n.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
440
454
  VERSION:2.0\r
441
455
  PRODID:-//Alfred//EN\r
442
456
  BEGIN:VEVENT\r
@@ -451,30 +465,30 @@ BEGIN:VEVENT\r
451
465
  `),r+=`DTSTAMP:${s(new Date)}\r
452
466
  `,r+=`END:VEVENT\r
453
467
  END:VCALENDAR\r
454
- `,r}}});var Ei={};le(Ei,{GoogleCalendarProvider:()=>Qs});var Qs,hn=b(()=>{"use strict";us();Qs=class extends me{static{u(this,"GoogleCalendarProvider")}config;calendar;constructor(e){super(),this.config=e}async initialize(){try{let{google:e}=await import("googleapis"),t=new e.auth.OAuth2(this.config.clientId,this.config.clientSecret);t.setCredentials({refresh_token:this.config.refreshToken}),this.calendar=e.calendar({version:"v3",auth:t})}catch(e){throw new Error(`Google Calendar initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){return((await this.calendar.events.list({calendarId:"primary",timeMin:e.toISOString(),timeMax:t.toISOString(),singleEvents:!0,orderBy:"startTime"})).data.items??[]).map(r=>this.mapEvent(r))}async createEvent(e){let t={summary:e.title,location:e.location,description:e.description};e.allDay?(t.start={date:e.start.toISOString().slice(0,10)},t.end={date:e.end.toISOString().slice(0,10)}):(t.start={dateTime:e.start.toISOString()},t.end={dateTime:e.end.toISOString()});let s=await this.calendar.events.insert({calendarId:"primary",requestBody:t});return this.mapEvent(s.data)}async updateEvent(e,t){let s={};t.title&&(s.summary=t.title),t.location&&(s.location=t.location),t.description&&(s.description=t.description),t.start&&(s.start=t.allDay?{date:t.start.toISOString().slice(0,10)}:{dateTime:t.start.toISOString()}),t.end&&(s.end=t.allDay?{date:t.end.toISOString().slice(0,10)}:{dateTime:t.end.toISOString()});let r=await this.calendar.events.patch({calendarId:"primary",eventId:e,requestBody:s});return this.mapEvent(r.data)}async deleteEvent(e){await this.calendar.events.delete({calendarId:"primary",eventId:e})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){let t=!!e.start?.date;return{id:e.id,title:e.summary??"(No title)",start:new Date(e.start?.dateTime??e.start?.date),end:new Date(e.end?.dateTime??e.end?.date),location:e.location??void 0,description:e.description??void 0,allDay:t}}}});var _i={};le(_i,{MicrosoftCalendarProvider:()=>er});var er,fn=b(()=>{"use strict";us();er=class extends me{static{u(this,"MicrosoftCalendarProvider")}config;client;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Calendars.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async listEvents(e,t){let s=new URLSearchParams({startDateTime:e.toISOString(),endDateTime:t.toISOString(),$orderby:"start/dateTime",$top:"50"});return((await this.graphRequest(`/me/calendarView?${s}`)).value??[]).map(n=>this.mapEvent(n))}async createEvent(e){let t={subject:e.title,body:e.description?{contentType:"text",content:e.description}:void 0,location:e.location?{displayName:e.location}:void 0,isAllDay:e.allDay??!1};e.allDay?(t.start={dateTime:e.start.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"},t.end={dateTime:e.end.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"}):(t.start={dateTime:e.start.toISOString(),timeZone:"UTC"},t.end={dateTime:e.end.toISOString(),timeZone:"UTC"});let s=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(t)});return this.mapEvent(s)}async updateEvent(e,t){let s={};t.title&&(s.subject=t.title),t.description&&(s.body={contentType:"text",content:t.description}),t.location&&(s.location={displayName:t.location}),t.start&&(s.start={dateTime:t.start.toISOString(),timeZone:"UTC"}),t.end&&(s.end={dateTime:t.end.toISOString(),timeZone:"UTC"});let r=await this.graphRequest(`/me/events/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapEvent(r)}async deleteEvent(e){await this.graphRequest(`/me/events/${e}`,{method:"DELETE"})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){return{id:e.id,title:e.subject??"(No title)",start:new Date(e.start?.dateTime),end:new Date(e.end?.dateTime),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}}});async function ps(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(mn(),Ti)),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(()=>(hn(),Ei)),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(()=>(fn(),_i)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var vi=b(()=>{"use strict";u(ps,"createCalendarProvider")});var He,ki=b(()=>{"use strict";D();He=class extends ${static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:"Start date/time in ISO 8601 format"},end:{type:"string",description:"End date/time in ISO 8601 format"},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){let s=e.action;switch(s){case"list_events":return this.listEvents(e);case"create_event":return this.createEvent(e);case"update_event":return this.updateEvent(e);case"delete_event":return this.deleteEvent(e);case"check_availability":return this.checkAvailability(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async getTodayEvents(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()),s=new Date(e.getFullYear(),e.getMonth(),e.getDate()+1);try{return await this.calendarProvider.listEvents(t,s)}catch(r){return console.error("[calendar] Failed to fetch today events",r),[]}}async listEvents(e){let t=e.start?new Date(e.start):new Date,s=e.end?new Date(e.end):new Date(t.getTime()+7*24*60*60*1e3);try{let r=await this.calendarProvider.listEvents(t,s);if(r.length===0)return{success:!0,data:[],display:"No events found in this time range."};let n=r.map(o=>this.formatEvent(o)).join(`
468
+ `,r}}});var ji={};oe(ji,{GoogleCalendarProvider:()=>cr});var cr,In=w(()=>{"use strict";Es();cr=class extends ye{static{u(this,"GoogleCalendarProvider")}config;calendar;constructor(e){super(),this.config=e}async initialize(){try{let{google:e}=await import("googleapis"),t=new e.auth.OAuth2(this.config.clientId,this.config.clientSecret);t.setCredentials({refresh_token:this.config.refreshToken}),this.calendar=e.calendar({version:"v3",auth:t})}catch(e){throw new Error(`Google Calendar initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){return((await this.calendar.events.list({calendarId:"primary",timeMin:e.toISOString(),timeMax:t.toISOString(),singleEvents:!0,orderBy:"startTime"})).data.items??[]).map(r=>this.mapEvent(r))}async createEvent(e){let t={summary:e.title,location:e.location,description:e.description};e.allDay?(t.start={date:e.start.toISOString().slice(0,10)},t.end={date:e.end.toISOString().slice(0,10)}):(t.start={dateTime:e.start.toISOString()},t.end={dateTime:e.end.toISOString()});let s=await this.calendar.events.insert({calendarId:"primary",requestBody:t});return this.mapEvent(s.data)}async updateEvent(e,t){let s={};t.title&&(s.summary=t.title),t.location&&(s.location=t.location),t.description&&(s.description=t.description),t.start&&(s.start=t.allDay?{date:t.start.toISOString().slice(0,10)}:{dateTime:t.start.toISOString()}),t.end&&(s.end=t.allDay?{date:t.end.toISOString().slice(0,10)}:{dateTime:t.end.toISOString()});let r=await this.calendar.events.patch({calendarId:"primary",eventId:e,requestBody:s});return this.mapEvent(r.data)}async deleteEvent(e){await this.calendar.events.delete({calendarId:"primary",eventId:e})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){let t=!!e.start?.date;return{id:e.id,title:e.summary??"(No title)",start:new Date(e.start?.dateTime??e.start?.date),end:new Date(e.end?.dateTime??e.end?.date),location:e.location??void 0,description:e.description??void 0,allDay:t}}}});var Bi={};oe(Bi,{MicrosoftCalendarProvider:()=>lr});var lr,An=w(()=>{"use strict";Es();lr=class extends ye{static{u(this,"MicrosoftCalendarProvider")}config;client;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Calendars.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async listEvents(e,t){let s=new URLSearchParams({startDateTime:e.toISOString(),endDateTime:t.toISOString(),$orderby:"start/dateTime",$top:"50"});return((await this.graphRequest(`/me/calendarView?${s}`)).value??[]).map(n=>this.mapEvent(n))}async createEvent(e){let t={subject:e.title,body:e.description?{contentType:"text",content:e.description}:void 0,location:e.location?{displayName:e.location}:void 0,isAllDay:e.allDay??!1};e.allDay?(t.start={dateTime:e.start.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"},t.end={dateTime:e.end.toISOString().slice(0,10)+"T00:00:00",timeZone:"UTC"}):(t.start={dateTime:e.start.toISOString(),timeZone:"UTC"},t.end={dateTime:e.end.toISOString(),timeZone:"UTC"});let s=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(t)});return this.mapEvent(s)}async updateEvent(e,t){let s={};t.title&&(s.subject=t.title),t.description&&(s.body={contentType:"text",content:t.description}),t.location&&(s.location={displayName:t.location}),t.start&&(s.start={dateTime:t.start.toISOString(),timeZone:"UTC"}),t.end&&(s.end={dateTime:t.end.toISOString(),timeZone:"UTC"});let r=await this.graphRequest(`/me/events/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapEvent(r)}async deleteEvent(e){await this.graphRequest(`/me/events/${e}`,{method:"DELETE"})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){return{id:e.id,title:e.subject??"(No title)",start:new Date(e.start?.dateTime),end:new Date(e.end?.dateTime),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}}});async function _s(c){switch(c.provider){case"caldav":{if(!c.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(xn(),Fi)),t=new e(c.caldav);return await t.initialize(),t}case"google":{if(!c.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(In(),ji)),t=new e(c.google);return await t.initialize(),t}case"microsoft":{if(!c.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(An(),Bi)),t=new e(c.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${c.provider}`)}}var qi=w(()=>{"use strict";u(_s,"createCalendarProvider")});var Ye,Hi=w(()=>{"use strict";P();Ye=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:"Start date/time in ISO 8601 format"},end:{type:"string",description:"End date/time in ISO 8601 format"},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){let s=e.action;switch(s){case"list_events":return this.listEvents(e);case"create_event":return this.createEvent(e);case"update_event":return this.updateEvent(e);case"delete_event":return this.deleteEvent(e);case"check_availability":return this.checkAvailability(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async getTodayEvents(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()),s=new Date(e.getFullYear(),e.getMonth(),e.getDate()+1);try{return await this.calendarProvider.listEvents(t,s)}catch(r){return console.error("[calendar] Failed to fetch today events",r),[]}}async listEvents(e){let t=e.start?new Date(e.start):new Date,s=e.end?new Date(e.end):new Date(t.getTime()+7*24*60*60*1e3);try{let r=await this.calendarProvider.listEvents(t,s);if(r.length===0)return{success:!0,data:[],display:"No events found in this time range."};let n=r.map(o=>this.formatEvent(o)).join(`
455
469
  `);return{success:!0,data:r,display:`${r.length} event(s):
456
470
  ${n}`}}catch(r){return{success:!1,error:`Failed to list events: ${r instanceof Error?r.message:String(r)}`}}}async createEvent(e){let t=e.title,s=e.start,r=e.end;if(!t)return{success:!1,error:'Missing required field "title"'};if(!s)return{success:!1,error:'Missing required field "start"'};if(!r)return{success:!1,error:'Missing required field "end"'};try{let n=await this.calendarProvider.createEvent({title:t,start:new Date(s),end:new Date(r),location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:n,display:`Event created: ${this.formatEvent(n)}`}}catch(n){return{success:!1,error:`Failed to create event: ${n instanceof Error?n.message:String(n)}`}}}async updateEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{let s=await this.calendarProvider.updateEvent(t,{title:e.title,start:e.start?new Date(e.start):void 0,end:e.end?new Date(e.end):void 0,location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:s,display:`Event updated: ${this.formatEvent(s)}`}}catch(s){return{success:!1,error:`Failed to update event: ${s instanceof Error?s.message:String(s)}`}}}async deleteEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{return await this.calendarProvider.deleteEvent(t),{success:!0,data:{deleted:t},display:`Event "${t}" deleted.`}}catch(s){return{success:!1,error:`Failed to delete event: ${s instanceof Error?s.message:String(s)}`}}}async checkAvailability(e){let t=e.start,s=e.end;if(!t||!s)return{success:!1,error:'Missing required fields "start" and "end"'};try{let r=await this.calendarProvider.checkAvailability(new Date(t),new Date(s)),n=r.available?"Time slot is available.":`Time slot has ${r.conflicts.length} conflict(s):
457
471
  ${r.conflicts.map(o=>this.formatEvent(o)).join(`
458
- `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var $i=b(()=>{"use strict";us();mn();hn();fn();vi();ki()});var bt,Si=b(()=>{"use strict";D();bt=class extends ${static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
472
+ `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var Wi=w(()=>{"use strict";Es();xn();In();An();qi();Hi()});var kt,Xi=w(()=>{"use strict";P();kt=class extends I{static{u(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
459
473
 
460
474
  Enter this code on your other platform within 10 minutes using:
461
- "Link my account with code ${r.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.resolveInternalId(t),n=this.checkConfirmRateLimit(r);if(n)return{success:!1,error:n};let o=this.linkTokens.findByCode(s.trim());if(!o)return this.recordFailedConfirm(r),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};let i=o.userId;if(i===r)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let a=this.users.getMasterUserId(i),l=this.users.getMasterUserId(r),d;if(a!==i?d=a:l!==r?d=l:d=i,a!==i&&l!==r&&a!==l){let g=this.users.getLinkedUsers(l);for(let f of g)this.users.setMasterUser(f.id,d)}i!==d&&this.users.setMasterUser(i,d),r!==d&&this.users.setMasterUser(r,d),this.linkTokens.consume(o.id);let p=this.users.findById(i),m=o.platform;return{success:!0,data:{masterUserId:d,linkedPlatform:m},display:`Account linked successfully! Your ${m} account (${p?.displayName??p?.username??"unknown"}) is now linked to this ${t.platform} account.
475
+ "Link my account with code ${r.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.resolveInternalId(t),n=this.checkConfirmRateLimit(r);if(n)return{success:!1,error:n};let o=this.linkTokens.findByCode(s.trim());if(!o)return this.recordFailedConfirm(r),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};let i=o.userId;if(i===r)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let a=this.users.getMasterUserId(i),l=this.users.getMasterUserId(r),d;if(a!==i?d=a:l!==r?d=l:d=i,a!==i&&l!==r&&a!==l){let b=this.users.getLinkedUsers(l);for(let y of b)this.users.setMasterUser(y.id,d)}i!==d&&this.users.setMasterUser(i,d),r!==d&&this.users.setMasterUser(r,d),this.linkTokens.consume(o.id);let m=this.users.findById(i),h=o.platform;return{success:!0,data:{masterUserId:d,linkedPlatform:h},display:`Account linked successfully! Your ${h} account (${m?.displayName??m?.username??"unknown"}) is now linked to this ${t.platform} account.
462
476
 
463
- Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e,t){let s=e.platform,r=e.chat_id,n=e.message;if(!s)return{success:!1,error:'Missing required field "platform"'};if(!n)return{success:!1,error:'Missing required field "message"'};let o=this.adapters.get(s);if(!o)return{success:!1,error:`Platform "${s}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};if(!r||!/^[!0-9]/.test(r)){let i=this.resolveInternalId(t),a=this.users.getMasterUserId(i),d=this.users.getLinkedUsers(a).find(p=>p.platform===s);if(d&&this.findConversation){let p=this.findConversation(s,d.id);p&&(r=p.chatId)}!r&&d&&(r=d.platformUserId)}if(!r)return{success:!1,error:"Could not resolve chat_id for target platform. No linked account or conversation found."};try{return{success:!0,data:{messageId:await o.sendMessage(r,n),platform:s,chatId:r},display:`Message sent to ${s}.`}}catch(i){return{success:!1,error:`Failed to send message: ${i instanceof Error?i.message:String(i)}`}}}async listIdentities(e){let t=this.resolveInternalId(e),s=this.users.getMasterUserId(t),r=this.users.getLinkedUsers(s);if(r.length<=1)return{success:!0,data:{identities:r},display:`No linked accounts found. To link another platform, use:
477
+ Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e,t){let s=e.platform,r=e.chat_id,n=e.message;if(!s)return{success:!1,error:'Missing required field "platform"'};if(!n)return{success:!1,error:'Missing required field "message"'};let o=this.adapters.get(s);if(!o)return{success:!1,error:`Platform "${s}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};if(!r||!/^[!0-9]/.test(r)){let i=this.resolveInternalId(t),a=this.users.getMasterUserId(i),d=this.users.getLinkedUsers(a).find(m=>m.platform===s);if(d&&this.findConversation){let m=this.findConversation(s,d.id);m&&(r=m.chatId)}!r&&d&&(r=d.platformUserId)}if(!r)return{success:!1,error:"Could not resolve chat_id for target platform. No linked account or conversation found."};try{return{success:!0,data:{messageId:await o.sendMessage(r,n),platform:s,chatId:r},display:`Message sent to ${s}.`}}catch(i){return{success:!1,error:`Failed to send message: ${i instanceof Error?i.message:String(i)}`}}}async listIdentities(e){let t=this.resolveInternalId(e),s=this.users.getMasterUserId(t),r=this.users.getLinkedUsers(s);if(r.length<=1)return{success:!0,data:{identities:r},display:`No linked accounts found. To link another platform, use:
464
478
  "Start linking my account" on the platform you want to link from, then enter the code on the other platform.`};let n=r.map(o=>{let i=o.id===t?" (current)":"",a=o.displayName??o.username??o.platformUserId;return`- **${o.platform}**: ${a}${i}`});return{success:!0,data:{identities:r.map(o=>({platform:o.platform,username:o.username,displayName:o.displayName}))},display:`Linked accounts:
465
479
  ${n.join(`
466
- `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),n=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(n).find(a=>a.platform===s&&a.id!==r);return i?(this.users.setMasterUser(i.id,i.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:i.id},display:`Unlinked ${s} account (${i.displayName??i.username??i.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var Tt,xi=b(()=>{"use strict";D();Tt=class extends ${static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",description:'Schedule, list, or cancel background tasks that run independently. Use "schedule" to queue a skill to execute in the background (user will be notified when done). Use "list" to see active/recent tasks. Use "cancel" to stop a pending or running task.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["schedule","list","cancel"],description:"The background task action to perform"},description:{type:"string",description:"Human-readable description of what the task does (for schedule)"},skill_name:{type:"string",description:"The skill to run in the background (for schedule)"},skill_input:{type:"object",description:"Input to pass to the skill (for schedule)"},task_id:{type:"string",description:"Task ID (for cancel)"}},required:["action"]}};constructor(e){super(),this.taskRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllTasks(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.taskRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"schedule":return this.scheduleTask(e,t);case"list":return this.listTasks(t);case"cancel":return this.cancelTask(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: schedule, list, cancel`}}}scheduleTask(e,t){let s=e.description,r=e.skill_name,n=e.skill_input;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "description" for schedule action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "skill_name" for schedule action'};let o=this.taskRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,r,JSON.stringify(n??{}));return{success:!0,data:{taskId:o.id,description:s,skillName:r,status:o.status},display:`Background task scheduled (${o.id}): "${s}" using skill "${r}". You'll be notified when it completes.`}}listTasks(e){let t=this.getAllTasks(e);if(t.length===0)return{success:!0,data:[],display:"No active or recent background tasks."};let s={pending:"\u23F3",running:"\u25B6\uFE0F",completed:"\u2705",failed:"\u274C"},r=t.map(n=>`- ${s[n.status]??"?"} ${n.id}: "${n.description}" [${n.status}] (${n.skillName})`);return{success:!0,data:t.map(n=>({taskId:n.id,description:n.description,status:n.status,skillName:n.skillName,createdAt:n.createdAt,completedAt:n.completedAt})),display:`Background tasks:
480
+ `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),n=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(n).find(a=>a.platform===s&&a.id!==r);return i?(this.users.setMasterUser(i.id,i.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:i.id},display:`Unlinked ${s} account (${i.displayName??i.username??i.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var St,zi=w(()=>{"use strict";P();St=class extends I{static{u(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",description:'Schedule, list, or cancel background tasks that run independently. Use "schedule" to queue a skill to execute in the background (user will be notified when done). Use "list" to see active/recent tasks. Use "cancel" to stop a pending or running task.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["schedule","list","cancel"],description:"The background task action to perform"},description:{type:"string",description:"Human-readable description of what the task does (for schedule)"},skill_name:{type:"string",description:"The skill to run in the background (for schedule)"},skill_input:{type:"object",description:"Input to pass to the skill (for schedule)"},task_id:{type:"string",description:"Task ID (for cancel)"}},required:["action"]}};constructor(e){super(),this.taskRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllTasks(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.taskRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"schedule":return this.scheduleTask(e,t);case"list":return this.listTasks(t);case"cancel":return this.cancelTask(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: schedule, list, cancel`}}}scheduleTask(e,t){let s=e.description,r=e.skill_name,n=e.skill_input;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "description" for schedule action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "skill_name" for schedule action'};let o=this.taskRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,r,JSON.stringify(n??{}));return{success:!0,data:{taskId:o.id,description:s,skillName:r,status:o.status},display:`Background task scheduled (${o.id}): "${s}" using skill "${r}". You'll be notified when it completes.`}}listTasks(e){let t=this.getAllTasks(e);if(t.length===0)return{success:!0,data:[],display:"No active or recent background tasks."};let s={pending:"\u23F3",running:"\u25B6\uFE0F",completed:"\u2705",failed:"\u274C"},r=t.map(n=>`- ${s[n.status]??"?"} ${n.id}: "${n.description}" [${n.status}] (${n.skillName})`);return{success:!0,data:t.map(n=>({taskId:n.id,description:n.description,status:n.status,skillName:n.skillName,createdAt:n.createdAt,completedAt:n.completedAt})),display:`Background tasks:
467
481
  ${r.join(`
468
- `)}`}}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 Et,Ii=b(()=>{"use strict";D();Et=class extends ${static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllActions(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,l=e.prompt_template;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "name" for create action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "description" for create action'};if(!n||!["cron","interval","once"].includes(n))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!o||typeof o!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if(!i||typeof i!="string")return{success:!1,error:'Missing required field "skill_name" for create action'};if(n==="interval"){let m=parseInt(o,10);if(isNaN(m)||m<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let m=new Date(o);if(isNaN(m.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(m.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let d=this.actionRepo.create({userId:this.effectiveUserId(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:l}),p=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${d.id}): "${s}" \u2014 ${p}, running "${i}"${d.nextRunAt?`. Next run: ${d.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
482
+ `)}`}}cancelTask(e,t){let s=e.task_id;return!s||typeof s!="string"?{success:!1,error:'Missing required field "task_id" for cancel action'}:this.getAllTasks(t).some(i=>i.id===s)?this.taskRepo.cancel(s)?{success:!0,data:{taskId:s},display:`Background task "${s}" cancelled.`}:{success:!1,error:`Task "${s}" not found or already completed`}:{success:!1,error:`Task "${s}" not found or already completed`}}}});var xt,Vi=w(()=>{"use strict";P();xt=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllActions(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,l=e.prompt_template;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "name" for create action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "description" for create action'};if(!n||!["cron","interval","once"].includes(n))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!o||typeof o!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if(!i||typeof i!="string")return{success:!1,error:'Missing required field "skill_name" for create action'};if(n==="interval"){let h=parseInt(o,10);if(isNaN(h)||h<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let h=new Date(o);if(isNaN(h.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(h.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let d=this.actionRepo.create({userId:this.effectiveUserId(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:l}),m=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${d.id}): "${s}" \u2014 ${m}, running "${i}"${d.nextRunAt?`. Next run: ${d.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
469
483
  ${s.join(`
470
- `)}`}}toggleAction(e,t,s){let r=e.action_id;if(!r||typeof r!="string")return{success:!1,error:`Missing required field "action_id" for ${t?"enable":"disable"} action`};let n=this.actionRepo.findById(r),o=this.allUserIds(s);return!n||!o.includes(n.userId)?{success:!1,error:`Scheduled action "${r}" not found`}:this.actionRepo.setEnabled(r,t)?{success:!0,data:{actionId:r,enabled:t},display:`Scheduled action "${r}" ${t?"enabled":"disabled"}.`}:{success:!1,error:`Scheduled action "${r}" not found`}}deleteAction(e,t){let s=e.action_id;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "action_id" for delete action'};let r=this.actionRepo.findById(s),n=this.allUserIds(t);return!r||!n.includes(r.userId)?{success:!1,error:`Scheduled action "${s}" not found`}:this.actionRepo.delete(s)?{success:!0,data:{actionId:s},display:`Scheduled action "${s}" deleted.`}:{success:!1,error:`Scheduled action "${s}" not found`}}}});var Ve,gn=b(()=>{"use strict";Ve=class{static{u(this,"MCPClient")}serverName;config;logger;client;transport;connected=!1;constructor(e,t,s){this.serverName=e,this.config=t,this.logger=s}async connect(){try{let{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");if(this.client=new e({name:`alfred-${this.serverName}`,version:"1.0.0"},{capabilities:{}}),this.config.command){let{StdioClientTransport:t}=await import("@modelcontextprotocol/sdk/client/stdio.js"),s={PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:process.env.NODE_ENV??"",SYSTEMROOT:process.env.SYSTEMROOT??""};if(this.config.env)for(let[r,n]of Object.entries(this.config.env))s[r]=n.replace(/\$\{(\w+)\}/g,(o,i)=>process.env[i]??"");this.transport=new t({command:this.config.command,args:this.config.args??[],env:s})}else if(this.config.url){let{SSEClientTransport:t}=await import("@modelcontextprotocol/sdk/client/sse.js");this.transport=new t(new URL(this.config.url))}else throw new Error(`MCP server "${this.serverName}": must specify either command or url`);await this.client.connect(this.transport),this.connected=!0,this.logger.info({server:this.serverName},"MCP server connected")}catch(e){throw this.logger.error({server:this.serverName,err:e},"Failed to connect MCP server"),e}}async listTools(){if(!this.connected||!this.client)return[];try{return((await this.client.listTools()).tools??[]).map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema??{type:"object",properties:{}}}))}catch(e){return this.logger.error({server:this.serverName,err:e},"Failed to list MCP tools"),[]}}async callTool(e,t){if(!this.connected||!this.client)return{content:"MCP server not connected",isError:!0};try{let s=await this.client.callTool({name:e,arguments:t});return{content:(s.content??[]).map(n=>n.text??JSON.stringify(n)).join(`
471
- `),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 zc,ze,yn=b(()=>{"use strict";D();zc=["read","write","destructive","admin"],ze=class extends ${static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&zc.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var ms,Ai=b(()=>{"use strict";gn();yn();ms=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 Ve(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new ze(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Ri=b(()=>{"use strict";gn();yn();Ai()});import{spawn as Kc}from"node:child_process";import _t from"node:fs";import wn from"node:path";import Gc from"node:os";import Yc from"node:crypto";var Ke,bn=b(()=>{"use strict";Ke=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=wn.join(Gc.tmpdir(),`alfred-sandbox-${Yc.randomUUID()}`);_t.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=wn.join(n,`script.${o}`);_t.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",l=[i],d=Date.now();return await new Promise(p=>{let m=Kc(a,l,{cwd:n,timeout:r,env:{PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n},stdio:["pipe","pipe","pipe"]}),g="",f="";m.stdout.on("data",h=>{g+=h.toString()}),m.stderr.on("data",h=>{f+=h.toString()}),m.on("close",h=>{let T=Date.now()-d,_=[];try{let x=_t.readdirSync(n).filter(k=>!k.startsWith("script."));for(let k of x){let C=wn.join(n,k),M=_t.statSync(C);if(M.isFile()&&M.size<1e7){let P=_t.readFileSync(C),j=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";_.push({name:k,data:P,mimeType:j})}}}catch{}p({stdout:g.slice(0,5e4),stderr:f.slice(0,1e4),exitCode:h??1,files:_.length>0?_:void 0,durationMs:T})}),m.on("error",h=>{p({stdout:"",stderr:h.message,exitCode:1,durationMs:Date.now()-d})}),m.stdin.end()})}finally{try{_t.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var hs,Li=b(()=>{"use strict";D();bn();hs=class extends ${static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (HTML, CSV, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. IMPORTANT: When generating large files, write compact data-driven code \u2014 define data as arrays/objects, then build the output programmatically. Never embed large HTML/text as string literals.",riskLevel:"destructive",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data to pass (available as DATA env var or stdin)"},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new Ke;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code". IMPORTANT: Do NOT embed large HTML/text as string literals \u2014 write compact code that builds content programmatically from data arrays/objects, e.g. rows.map(r => `<tr><td>${r.time}</td><td>${r.price}</td></tr>`).join(""). Keep the code short and data-driven.'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};let a=r;s==="run_with_data"&&o&&(n==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(o)};
484
+ `)}`}}toggleAction(e,t,s){let r=e.action_id;if(!r||typeof r!="string")return{success:!1,error:`Missing required field "action_id" for ${t?"enable":"disable"} action`};let n=this.actionRepo.findById(r),o=this.allUserIds(s);return!n||!o.includes(n.userId)?{success:!1,error:`Scheduled action "${r}" not found`}:this.actionRepo.setEnabled(r,t)?{success:!0,data:{actionId:r,enabled:t},display:`Scheduled action "${r}" ${t?"enabled":"disabled"}.`}:{success:!1,error:`Scheduled action "${r}" not found`}}deleteAction(e,t){let s=e.action_id;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "action_id" for delete action'};let r=this.actionRepo.findById(s),n=this.allUserIds(t);return!r||!n.includes(r.userId)?{success:!1,error:`Scheduled action "${s}" not found`}:this.actionRepo.delete(s)?{success:!0,data:{actionId:s},display:`Scheduled action "${s}" deleted.`}:{success:!1,error:`Scheduled action "${s}" not found`}}}});var Je,Rn=w(()=>{"use strict";Je=class{static{u(this,"MCPClient")}serverName;config;logger;client;transport;connected=!1;constructor(e,t,s){this.serverName=e,this.config=t,this.logger=s}async connect(){try{let{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");if(this.client=new e({name:`alfred-${this.serverName}`,version:"1.0.0"},{capabilities:{}}),this.config.command){let{StdioClientTransport:t}=await import("@modelcontextprotocol/sdk/client/stdio.js"),s={PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:process.env.NODE_ENV??"",SYSTEMROOT:process.env.SYSTEMROOT??""};if(this.config.env)for(let[r,n]of Object.entries(this.config.env))s[r]=n.replace(/\$\{(\w+)\}/g,(o,i)=>process.env[i]??"");this.transport=new t({command:this.config.command,args:this.config.args??[],env:s})}else if(this.config.url){let{SSEClientTransport:t}=await import("@modelcontextprotocol/sdk/client/sse.js");this.transport=new t(new URL(this.config.url))}else throw new Error(`MCP server "${this.serverName}": must specify either command or url`);await this.client.connect(this.transport),this.connected=!0,this.logger.info({server:this.serverName},"MCP server connected")}catch(e){throw this.logger.error({server:this.serverName,err:e},"Failed to connect MCP server"),e}}async listTools(){if(!this.connected||!this.client)return[];try{return((await this.client.listTools()).tools??[]).map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema??{type:"object",properties:{}}}))}catch(e){return this.logger.error({server:this.serverName,err:e},"Failed to list MCP tools"),[]}}async callTool(e,t){if(!this.connected||!this.client)return{content:"MCP server not connected",isError:!0};try{let s=await this.client.callTool({name:e,arguments:t});return{content:(s.content??[]).map(n=>n.text??JSON.stringify(n)).join(`
485
+ `),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var wl,Ze,Ln=w(()=>{"use strict";P();wl=["read","write","destructive","admin"],Ze=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&wl.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var $s,Ki=w(()=>{"use strict";Rn();Ln();$s=class{static{u(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new Je(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new Ze(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Gi=w(()=>{"use strict";Rn();Ln();Ki()});import{spawn as bl}from"node:child_process";import It from"node:fs";import Mn from"node:path";import Tl from"node:os";import El from"node:crypto";var Qe,Nn=w(()=>{"use strict";Qe=class{static{u(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=Mn.join(Tl.tmpdir(),`alfred-sandbox-${El.randomUUID()}`);It.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=Mn.join(n,`script.${o}`);It.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",l=[i],d=Date.now();return await new Promise(m=>{let h=bl(a,l,{cwd:n,timeout:r,env:{PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n},stdio:["pipe","pipe","pipe"]}),b="",y="";h.stdout.on("data",g=>{b+=g.toString()}),h.stderr.on("data",g=>{y+=g.toString()}),h.on("close",g=>{let E=Date.now()-d,v=[];try{let R=It.readdirSync(n).filter(x=>!x.startsWith("script."));for(let x of R){let O=Mn.join(n,x),N=It.statSync(O);if(N.isFile()&&N.size<1e7){let B=It.readFileSync(O),q=x.endsWith(".png")?"image/png":x.endsWith(".jpg")||x.endsWith(".jpeg")?"image/jpeg":x.endsWith(".svg")?"image/svg+xml":x.endsWith(".csv")?"text/csv":x.endsWith(".json")?"application/json":x.endsWith(".html")||x.endsWith(".htm")?"text/html":x.endsWith(".txt")?"text/plain":x.endsWith(".md")?"text/markdown":x.endsWith(".xml")?"application/xml":x.endsWith(".pdf")?"application/pdf":"application/octet-stream";v.push({name:x,data:B,mimeType:q})}}}catch{}m({stdout:b.slice(0,5e4),stderr:y.slice(0,1e4),exitCode:g??1,files:v.length>0?v:void 0,durationMs:E})}),h.on("error",g=>{m({stdout:"",stderr:g.message,exitCode:1,durationMs:Date.now()-d})}),h.stdin.end()})}finally{try{It.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var vs,Yi=w(()=>{"use strict";P();Nn();vs=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (HTML, CSV, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. IMPORTANT: When generating large files, write compact data-driven code \u2014 define data as arrays/objects, then build the output programmatically. Never embed large HTML/text as string literals.",riskLevel:"destructive",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data to pass (available as DATA env var or stdin)"},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new Qe;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code". IMPORTANT: Do NOT embed large HTML/text as string literals \u2014 write compact code that builds content programmatically from data arrays/objects, e.g. rows.map(r => `<tr><td>${r.time}</td><td>${r.price}</td></tr>`).join(""). Keep the code short and data-driven.'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};let a=r;s==="run_with_data"&&o&&(n==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(o)};
472
486
  ${r}`:a=`INPUT_DATA = ${JSON.stringify(o)}
473
- ${r}`);let l=await this.executor.execute(a,n,{timeout:i}),d=l.files?.map(m=>({fileName:m.name,data:m.data,mimeType:m.mimeType})),p=[l.stdout?`Output:
487
+ ${r}`);let l=await this.executor.execute(a,n,{timeout:i}),d=l.files?.map(h=>({fileName:h.name,data:h.data,mimeType:h.mimeType})),m=[l.stdout?`Output:
474
488
  ${l.stdout}`:"",l.stderr?`Errors:
475
- ${l.stderr}`:"",`Exit code: ${l.exitCode}`,`Duration: ${l.durationMs}ms`,d&&d.length>0?`Files generated: ${d.map(m=>m.fileName).join(", ")}`:""].filter(Boolean).join(`
489
+ ${l.stderr}`:"",`Exit code: ${l.exitCode}`,`Duration: ${l.durationMs}ms`,d&&d.length>0?`Files generated: ${d.map(h=>h.fileName).join(", ")}`:""].filter(Boolean).join(`
476
490
 
477
- `);return{success:l.exitCode===0,data:{stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode,durationMs:l.durationMs,fileCount:l.files?.length??0},display:p,error:l.exitCode!==0?`Code execution failed with exit code ${l.exitCode}`:void 0,attachments:d}}}});var Mi=b(()=>{"use strict";bn();Li()});var vt,Ni=b(()=>{"use strict";D();vt=class extends ${static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,n=e.mime_type;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "file_path" for ingest action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "filename" for ingest action'};if(!n||typeof n!="string")return{success:!1,error:'Missing required field "mime_type" for ingest action'};let o=await import("node:path"),i=o.resolve(s);if(i!==o.normalize(s)&&s.includes(".."))return{success:!1,error:"Invalid file path: path traversal not allowed"};let a=i.toLowerCase();if(a.startsWith("/etc/")||a.startsWith("/proc/")||a.startsWith("/sys/")||a.startsWith("c:\\windows\\")||a.startsWith("/root/"))return{success:!1,error:"Access to system directories is not allowed"};try{let l=await this.processor.ingest(this.effectiveUserId(t),s,r,n);return{success:!0,data:l,display:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`}}catch(l){return{success:!1,error:`Failed to ingest document: ${l instanceof Error?l.message:String(l)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let n=this.allUserIds(t),o=new Set,i=[];for(let d of n)for(let p of await this.embeddingService.semanticSearch(d,s,r))o.has(p.key)||(o.add(p.key),i.push(p));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,p)=>`${p+1}. (score: ${d.score.toFixed(3)}) ${d.value.slice(0,200)}${d.value.length>200?"...":""}`).join(`
491
+ `);return{success:l.exitCode===0,data:{stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode,durationMs:l.durationMs,fileCount:l.files?.length??0},display:m,error:l.exitCode!==0?`Code execution failed with exit code ${l.exitCode}`:void 0,attachments:d}}}});var Ji=w(()=>{"use strict";Nn();Yi()});var At,Zi=w(()=>{"use strict";P();At=class extends I{static{u(this,"DocumentSkill")}docRepo;processor;embeddingService;metadata={name:"document",description:"Ingest, search, summarize, list, or delete documents. Supports PDF, DOCX, TXT, CSV, and Markdown files. Documents are chunked and embedded for semantic search.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["ingest","search","summarize","list","delete"],description:"Action to perform"},file_path:{type:"string",description:"Path to the file (for ingest)"},filename:{type:"string",description:"Original filename (for ingest)"},mime_type:{type:"string",description:"MIME type of the file (for ingest)"},query:{type:"string",description:"Search query (for search)"},document_id:{type:"string",description:"Document ID (for summarize, delete)"},limit:{type:"number",description:"Max results (for search, list)"}},required:["action"]}};constructor(e,t,s){super(),this.docRepo=e,this.processor=t,this.embeddingService=s}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"ingest":return this.ingest(e,t);case"search":return this.search(e,t);case"summarize":return this.summarize(e);case"list":return this.list(e,t);case"delete":return this.deleteDoc(e);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: ingest, search, summarize, list, delete`}}}async ingest(e,t){let s=e.file_path,r=e.filename,n=e.mime_type;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "file_path" for ingest action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "filename" for ingest action'};if(!n||typeof n!="string")return{success:!1,error:'Missing required field "mime_type" for ingest action'};let o=await import("node:path"),i=o.resolve(s);if(i!==o.normalize(s)&&s.includes(".."))return{success:!1,error:"Invalid file path: path traversal not allowed"};let a=i.toLowerCase();if(a.startsWith("/etc/")||a.startsWith("/proc/")||a.startsWith("/sys/")||a.startsWith("c:\\windows\\")||a.startsWith("/root/"))return{success:!1,error:"Access to system directories is not allowed"};try{let l=await this.processor.ingest(this.effectiveUserId(t),s,r,n);return{success:!0,data:l,display:`Document "${r}" ingested successfully (${l.chunkCount} chunks). ID: ${l.documentId.slice(0,8)}...`}}catch(l){return{success:!1,error:`Failed to ingest document: ${l instanceof Error?l.message:String(l)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let n=this.allUserIds(t),o=new Set,i=[];for(let d of n)for(let m of await this.embeddingService.semanticSearch(d,s,r))o.has(m.key)||(o.add(m.key),i.push(m));let a=i.filter(d=>d.category==="document");if(a.length===0)return{success:!0,data:[],display:`No document matches found for "${s}".`};let l=a.map((d,m)=>`${m+1}. (score: ${d.score.toFixed(3)}) ${d.value.slice(0,200)}${d.value.length>200?"...":""}`).join(`
478
492
 
479
493
  `);return{success:!0,data:a,display:`Found ${a.length} relevant chunk(s):
480
494
 
@@ -486,13 +500,13 @@ ${l}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success
486
500
 
487
501
  ${a}`}}list(e,t){let s=e.limit||50,r=this.allUserIds(t),n=new Set,o=[];for(let l of r)for(let d of this.docRepo.listByUser(l))n.has(d.id)||(n.add(d.id),o.push(d));let i=o.slice(0,s);if(i.length===0)return{success:!0,data:[],display:"No documents found."};let a=i.map(l=>`- **${l.filename}** (${l.id.slice(0,8)}...) \u2014 ${l.mimeType}, ${l.chunkCount} chunks, ${l.sizeBytes} bytes`).join(`
488
502
  `);return{success:!0,data:i,display:`${i.length} document(s):
489
- ${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 kt,Ci=b(()=>{"use strict";D();kt=class extends ${static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});function Y(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 fs(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function tr(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 sr,Oi=b(()=>{"use strict";D();u(Y,"bytes");u(fs,"pct");u(tr,"uptimeStr");sr=class c extends ${static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",description:'Manage Proxmox VE virtual machines, containers, and cluster. Use action "list_vms" to see VMs, "start_vm"/"shutdown_vm" to control them, "cluster_status" for health, "create_snapshot" for backups.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["cluster_status","list_nodes","node_stats","list_vms","vm_status","list_snapshots","list_storage","list_tasks","task_status","start_vm","shutdown_vm","reboot_vm","suspend_vm","resume_vm","create_snapshot","backup_vm","migrate_vm","stop_vm","delete_snapshot","rollback_snapshot"],description:"The Proxmox action to perform"},vmid:{type:"number",description:"Virtual machine / container ID"},node:{type:"string",description:"Proxmox node name (optional \u2014 resolved automatically when omitted)"},type:{type:"string",enum:["qemu","lxc"],description:"VM type filter for list_vms (default: both)"},name:{type:"string",description:"Snapshot name (for create/delete/rollback_snapshot)"},description:{type:"string",description:"Snapshot description (optional)"},target:{type:"string",description:"Target node for migration"},storage:{type:"string",description:"Storage target for backup_vm"},upid:{type:"string",description:"Task UPID for task_status"}},required:["action"]}};config;vmCache=null;static VM_CACHE_TTL=3e4;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"cluster_status":return await this.clusterStatus();case"list_nodes":return await this.listNodes();case"node_stats":return await this.nodeStats(e.node);case"list_vms":return await this.listVms(e.node,e.type);case"vm_status":return await this.vmStatus(e.vmid,e.node);case"list_snapshots":return await this.listSnapshots(e.vmid,e.node);case"list_storage":return await this.listStorage(e.node);case"list_tasks":return await this.listTasks(e.node);case"task_status":return await this.taskStatus(e.upid);case"start_vm":return await this.vmPowerAction("start",e);case"shutdown_vm":return await this.vmPowerAction("shutdown",e);case"reboot_vm":return await this.vmPowerAction("reboot",e);case"suspend_vm":return await this.vmPowerAction("suspend",e);case"resume_vm":return await this.vmPowerAction("resume",e);case"stop_vm":return await this.vmPowerAction("stop",e);case"create_snapshot":return await this.createSnapshot(e);case"backup_vm":return await this.backupVm(e);case"migrate_vm":return await this.migrateVm(e);case"delete_snapshot":return await this.deleteSnapshot(e);case"rollback_snapshot":return await this.rollbackSnapshot(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Proxmox API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl}/api2/json${t}`,n={Authorization:`PVEAPIToken=${this.config.tokenId}=${this.config.tokenSecret}`},o={method:e,headers:n};s&&e!=="GET"&&(n["Content-Type"]="application/json",o.body=JSON.stringify(s));let i=this.config.verifyTls===!1,a=process.env.NODE_TLS_REJECT_UNAUTHORIZED;i&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let l;try{l=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let p="";try{p=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${p}`)}return(await l.json()).data}async get(e){return this.api("GET",e)}async post(e,t){return this.api("POST",e,t)}async del(e){return this.api("DELETE",e)}async resolveVm(e,t){if(t)try{return await this.get(`/nodes/${t}/qemu/${e}/status/current`),{node:t,type:"qemu"}}catch{try{return await this.get(`/nodes/${t}/lxc/${e}/status/current`),{node:t,type:"lxc"}}catch{throw new Error(`VM ${e} not found on node "${t}"`)}}let r=(await this.getAllVms()).find(n=>n.vmid===e);if(!r)throw new Error(`VM ${e} not found on any node. Use "list_vms" to see available VMs.`);return{node:r.node,type:r.type}}async getAllVms(){let e=Date.now();if(this.vmCache&&e-this.vmCache.ts<c.VM_CACHE_TTL)return this.vmCache.entries;let t=await this.get("/nodes"),s=[];for(let r of t){let[n,o]=await Promise.all([this.get(`/nodes/${r.node}/qemu`).catch(()=>[]),this.get(`/nodes/${r.node}/lxc`).catch(()=>[])]);for(let i of n)s.push({...i,node:r.node,type:"qemu"});for(let i of o)s.push({...i,node:r.node,type:"lxc"})}return this.vmCache={entries:s,ts:e},s}async clusterStatus(){let e=await this.get("/cluster/status"),t=["## Cluster Status",""],s=e.find(n=>n.type==="cluster");s&&(t.push(`**Cluster:** ${s.name}`),t.push(`**Quorum:** ${s.quorate?"Yes":"No"}`),t.push(`**Nodes:** ${s.nodes??"-"}`),t.push(`**Version:** ${s.version??"-"}`),t.push(""));let r=e.filter(n=>n.type==="node");if(r.length){t.push("| Node | Online | Level | ID |"),t.push("|------|--------|-------|----|");for(let n of r)t.push(`| ${n.name} | ${n.online?"Yes":"**No**"} | ${n.level??"-"} | ${n.nodeid??"-"} |`)}return{success:!0,data:e,display:t.join(`
490
- `)}}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"?fs(s.cpu):"-",n=Y(s.mem),o=Y(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${tr(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
491
- `)}}async nodeStats(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/status`),r=s.cpu,n=s.memory,o=s.rootfs,i=s.swap,a=[`## Node: ${t}`,"",`**Uptime:** ${tr(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${fs(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${Y(n.used)} / ${Y(n.total)} (${fs(n.used/n.total)})`),i&&a.push(`**Swap:** ${Y(i.used)} / ${Y(i.total)}`),o&&a.push(`**Root FS:** ${Y(o.used)} / ${Y(o.total)}`),{success:!0,data:s,display:a.join(`
492
- `)}}async listVms(e,t){let s;if(e){if(s=[],!t||t==="qemu"){let n=await this.get(`/nodes/${e}/qemu`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"qemu"})}if(!t||t==="lxc"){let n=await this.get(`/nodes/${e}/lxc`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"lxc"})}}else s=await this.getAllVms(),t&&(s=s.filter(n=>n.type===t));s.sort((n,o)=>n.vmid-o.vmid);let r=["## Virtual Machines & Containers","","| VMID | Name | Type | Node | Status | CPU | RAM Used / Max | Uptime |","|------|------|------|------|--------|-----|----------------|--------|"];for(let n of s)r.push(`| ${n.vmid} | ${n.name??"-"} | ${n.type} | ${n.node} | ${n.status??"-"} | ${fs(n.cpu)} | ${Y(n.mem)} / ${Y(n.maxmem)} | ${tr(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
493
- `)}}async vmStatus(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/status/current`),n=[`## VM ${e} (${s.type}) on ${s.node}`,"",`**Name:** ${r.name??"-"}`,`**Status:** ${r.status}`,`**CPU:** ${fs(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${Y(r.mem)} / ${Y(r.maxmem)}`,`**Disk:** ${Y(r.disk)} / ${Y(r.maxdisk)}`,`**Uptime:** ${tr(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${Y(r.netin)} / ${Y(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
503
+ ${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for delete action'};let s=this.docRepo.getDocument(t);return s?(this.docRepo.deleteDocument(t),{success:!0,data:{documentId:t},display:`Document "${s.filename}" deleted.`}):{success:!1,error:`Document "${t}" not found`}}}});var Rt,Qi=w(()=>{"use strict";P();Rt=class extends I{static{u(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});function Z(c){return c==null?"-":c<1024?`${c} B`:c<1024**2?`${(c/1024).toFixed(1)} KiB`:c<1024**3?`${(c/1024**2).toFixed(1)} MiB`:`${(c/1024**3).toFixed(2)} GiB`}function ks(c){return c==null?"-":`${(c*100).toFixed(1)}%`}function dr(c){if(!c)return"-";let e=Math.floor(c/86400),t=Math.floor(c%86400/3600),s=Math.floor(c%3600/60),r=[];return e&&r.push(`${e}d`),t&&r.push(`${t}h`),r.push(`${s}m`),r.join(" ")}var ur,ea=w(()=>{"use strict";P();u(Z,"bytes");u(ks,"pct");u(dr,"uptimeStr");ur=class c extends I{static{u(this,"ProxmoxSkill")}metadata={name:"proxmox",description:'Manage Proxmox VE virtual machines, containers, and cluster. Use action "list_vms" to see VMs, "start_vm"/"shutdown_vm" to control them, "cluster_status" for health, "create_snapshot" for backups.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["cluster_status","list_nodes","node_stats","list_vms","vm_status","list_snapshots","list_storage","list_tasks","task_status","start_vm","shutdown_vm","reboot_vm","suspend_vm","resume_vm","create_snapshot","backup_vm","migrate_vm","stop_vm","delete_snapshot","rollback_snapshot"],description:"The Proxmox action to perform"},vmid:{type:"number",description:"Virtual machine / container ID"},node:{type:"string",description:"Proxmox node name (optional \u2014 resolved automatically when omitted)"},type:{type:"string",enum:["qemu","lxc"],description:"VM type filter for list_vms (default: both)"},name:{type:"string",description:"Snapshot name (for create/delete/rollback_snapshot)"},description:{type:"string",description:"Snapshot description (optional)"},target:{type:"string",description:"Target node for migration"},storage:{type:"string",description:"Storage target for backup_vm"},upid:{type:"string",description:"Task UPID for task_status"}},required:["action"]}};config;vmCache=null;static VM_CACHE_TTL=3e4;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"cluster_status":return await this.clusterStatus();case"list_nodes":return await this.listNodes();case"node_stats":return await this.nodeStats(e.node);case"list_vms":return await this.listVms(e.node,e.type);case"vm_status":return await this.vmStatus(e.vmid,e.node);case"list_snapshots":return await this.listSnapshots(e.vmid,e.node);case"list_storage":return await this.listStorage(e.node);case"list_tasks":return await this.listTasks(e.node);case"task_status":return await this.taskStatus(e.upid);case"start_vm":return await this.vmPowerAction("start",e);case"shutdown_vm":return await this.vmPowerAction("shutdown",e);case"reboot_vm":return await this.vmPowerAction("reboot",e);case"suspend_vm":return await this.vmPowerAction("suspend",e);case"resume_vm":return await this.vmPowerAction("resume",e);case"stop_vm":return await this.vmPowerAction("stop",e);case"create_snapshot":return await this.createSnapshot(e);case"backup_vm":return await this.backupVm(e);case"migrate_vm":return await this.migrateVm(e);case"delete_snapshot":return await this.deleteSnapshot(e);case"rollback_snapshot":return await this.rollbackSnapshot(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Proxmox API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl}/api2/json${t}`,n={Authorization:`PVEAPIToken=${this.config.tokenId}=${this.config.tokenSecret}`},o={method:e,headers:n};s&&e!=="GET"&&(n["Content-Type"]="application/json",o.body=JSON.stringify(s));let i=this.config.verifyTls===!1,a=process.env.NODE_TLS_REJECT_UNAUTHORIZED;i&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let l;try{l=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let m="";try{m=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${m}`)}return(await l.json()).data}async get(e){return this.api("GET",e)}async post(e,t){return this.api("POST",e,t)}async del(e){return this.api("DELETE",e)}async resolveVm(e,t){if(t)try{return await this.get(`/nodes/${t}/qemu/${e}/status/current`),{node:t,type:"qemu"}}catch{try{return await this.get(`/nodes/${t}/lxc/${e}/status/current`),{node:t,type:"lxc"}}catch{throw new Error(`VM ${e} not found on node "${t}"`)}}let r=(await this.getAllVms()).find(n=>n.vmid===e);if(!r)throw new Error(`VM ${e} not found on any node. Use "list_vms" to see available VMs.`);return{node:r.node,type:r.type}}async getAllVms(){let e=Date.now();if(this.vmCache&&e-this.vmCache.ts<c.VM_CACHE_TTL)return this.vmCache.entries;let t=await this.get("/nodes"),s=[];for(let r of t){let[n,o]=await Promise.all([this.get(`/nodes/${r.node}/qemu`).catch(()=>[]),this.get(`/nodes/${r.node}/lxc`).catch(()=>[])]);for(let i of n)s.push({...i,node:r.node,type:"qemu"});for(let i of o)s.push({...i,node:r.node,type:"lxc"})}return this.vmCache={entries:s,ts:e},s}async clusterStatus(){let e=await this.get("/cluster/status"),t=["## Cluster Status",""],s=e.find(n=>n.type==="cluster");s&&(t.push(`**Cluster:** ${s.name}`),t.push(`**Quorum:** ${s.quorate?"Yes":"No"}`),t.push(`**Nodes:** ${s.nodes??"-"}`),t.push(`**Version:** ${s.version??"-"}`),t.push(""));let r=e.filter(n=>n.type==="node");if(r.length){t.push("| Node | Online | Level | ID |"),t.push("|------|--------|-------|----|");for(let n of r)t.push(`| ${n.name} | ${n.online?"Yes":"**No**"} | ${n.level??"-"} | ${n.nodeid??"-"} |`)}return{success:!0,data:e,display:t.join(`
504
+ `)}}async listNodes(){let e=await this.get("/nodes"),t=["## Nodes","","| Node | Status | CPU | RAM Used / Total | Uptime |"];t.push("|------|--------|-----|------------------|--------|");for(let s of e){let r=typeof s.cpu=="number"?ks(s.cpu):"-",n=Z(s.mem),o=Z(s.maxmem);t.push(`| ${s.node} | ${s.status} | ${r} | ${n} / ${o} | ${dr(s.uptime)} |`)}return{success:!0,data:e,display:t.join(`
505
+ `)}}async nodeStats(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/status`),r=s.cpu,n=s.memory,o=s.rootfs,i=s.swap,a=[`## Node: ${t}`,"",`**Uptime:** ${dr(s.uptime)}`,`**Kernel:** ${s.kversion??"-"}`,`**PVE Version:** ${s.pveversion??"-"}`,""];return r&&(a.push(`**CPU:** ${r.model??"-"} (${r.cpus??"-"} cores)`),a.push(`**CPU Usage:** ${ks(r.cpu)}`),a.push(`**Load:** ${Array.isArray(s.loadavg)?s.loadavg.join(", "):"-"}`)),n&&a.push(`**RAM:** ${Z(n.used)} / ${Z(n.total)} (${ks(n.used/n.total)})`),i&&a.push(`**Swap:** ${Z(i.used)} / ${Z(i.total)}`),o&&a.push(`**Root FS:** ${Z(o.used)} / ${Z(o.total)}`),{success:!0,data:s,display:a.join(`
506
+ `)}}async listVms(e,t){let s;if(e){if(s=[],!t||t==="qemu"){let n=await this.get(`/nodes/${e}/qemu`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"qemu"})}if(!t||t==="lxc"){let n=await this.get(`/nodes/${e}/lxc`).catch(()=>[]);for(let o of n)s.push({...o,node:e,type:"lxc"})}}else s=await this.getAllVms(),t&&(s=s.filter(n=>n.type===t));s.sort((n,o)=>n.vmid-o.vmid);let r=["## Virtual Machines & Containers","","| VMID | Name | Type | Node | Status | CPU | RAM Used / Max | Uptime |","|------|------|------|------|--------|-----|----------------|--------|"];for(let n of s)r.push(`| ${n.vmid} | ${n.name??"-"} | ${n.type} | ${n.node} | ${n.status??"-"} | ${ks(n.cpu)} | ${Z(n.mem)} / ${Z(n.maxmem)} | ${dr(n.uptime)} |`);return s.length===0&&r.push("| - | No VMs found | - | - | - | - | - | - |"),{success:!0,data:s,display:r.join(`
507
+ `)}}async vmStatus(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/status/current`),n=[`## VM ${e} (${s.type}) on ${s.node}`,"",`**Name:** ${r.name??"-"}`,`**Status:** ${r.status}`,`**CPU:** ${ks(r.cpu)} (${r.cpus??"-"} cores)`,`**RAM:** ${Z(r.mem)} / ${Z(r.maxmem)}`,`**Disk:** ${Z(r.disk)} / ${Z(r.maxdisk)}`,`**Uptime:** ${dr(r.uptime)}`,`**PID:** ${r.pid??"-"}`,`**Net In / Out:** ${Z(r.netin)} / ${Z(r.netout)}`];return r.lock&&n.push(`**Lock:** ${r.lock}`),{success:!0,data:r,display:n.join(`
494
508
  `)}}async listSnapshots(e,t){if(e==null)return{success:!1,error:'Missing required "vmid" parameter'};let s=await this.resolveVm(e,t),r=await this.get(`/nodes/${s.node}/${s.type}/${e}/snapshot`),n=[`## Snapshots for VM ${e}`,"","| Name | Description | Date | Parent |","|------|-------------|------|--------|"];for(let o of r){let i=o.snaptime?new Date(o.snaptime*1e3).toISOString():"-";n.push(`| ${o.name} | ${o.description??"-"} | ${i} | ${o.parent??"-"} |`)}return{success:!0,data:r,display:n.join(`
495
- `)}}async listStorage(e){let t=e??this.config.defaultNode,s=t?`/nodes/${t}/storage`:"/storage",r=await this.get(s),n=[`## Storage${t?` (Node: ${t})`:""}`,"","| Storage | Type | Content | Used / Total | Status |","|---------|------|---------|--------------|--------|"];for(let o of r){let i=Y(o.used),a=Y(o.total);n.push(`| ${o.storage} | ${o.type} | ${o.content??"-"} | ${i} / ${a} | ${o.active?"active":o.enabled?"enabled":"disabled"} |`)}return{success:!0,data:r,display:n.join(`
509
+ `)}}async listStorage(e){let t=e??this.config.defaultNode,s=t?`/nodes/${t}/storage`:"/storage",r=await this.get(s),n=[`## Storage${t?` (Node: ${t})`:""}`,"","| Storage | Type | Content | Used / Total | Status |","|---------|------|---------|--------------|--------|"];for(let o of r){let i=Z(o.used),a=Z(o.total);n.push(`| ${o.storage} | ${o.type} | ${o.content??"-"} | ${i} / ${a} | ${o.active?"active":o.enabled?"enabled":"disabled"} |`)}return{success:!0,data:r,display:n.join(`
496
510
  `)}}async listTasks(e){let t=e??this.config.defaultNode;if(!t)return{success:!1,error:'Missing "node" parameter and no defaultNode configured'};let s=await this.get(`/nodes/${t}/tasks?limit=20`),r=[`## Recent Tasks (Node: ${t})`,"","| UPID | Type | Status | Start | User |","|------|------|--------|-------|------|"];for(let n of s){let o=n.starttime?new Date(n.starttime*1e3).toISOString():"-";r.push(`| \`${n.upid?.slice(-16)??"-"}\` | ${n.type??"-"} | ${n.status??"running"} | ${o} | ${n.user??"-"} |`)}return{success:!0,data:s,display:r.join(`
497
511
  `)}}async taskStatus(e){if(!e)return{success:!1,error:'Missing required "upid" parameter'};let t=e.split(":")[1];if(!t)return{success:!1,error:"Invalid UPID format \u2014 cannot extract node"};let s=await this.get(`/nodes/${t}/tasks/${encodeURIComponent(e)}/status`),r=["## Task Status","",`**UPID:** \`${e}\``,`**Status:** ${s.status}`,`**Type:** ${s.type??"-"}`,`**Exit Status:** ${s.exitstatus??"running"}`,`**Node:** ${t}`];return{success:!0,data:s,display:r.join(`
498
512
  `)}}async vmPowerAction(e,t){let s=t.vmid;if(s==null)return{success:!1,error:'Missing required "vmid" parameter'};let r=await this.resolveVm(s,t.node),n=await this.post(`/nodes/${r.node}/${r.type}/${s}/status/${e}`);return{success:!0,data:{vmid:s,node:r.node,type:r.type,action:e,upid:n},display:[`**${e.charAt(0).toUpperCase()+e.slice(1)}** sent to VM ${s} (${r.type}) on **${r.node}**.`,"",`UPID: \`${n}\``,"","Use `task_status` with this UPID to check progress."].join(`
@@ -501,7 +515,7 @@ ${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success
501
515
  `)}}async migrateVm(e){let t=e.vmid,s=e.target;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "target" parameter (target node)'};let r=await this.resolveVm(t,e.node),n=await this.post(`/nodes/${r.node}/${r.type}/${t}/migrate`,{target:s,online:1});return{success:!0,data:{vmid:t,from:r.node,target:s,type:r.type,upid:n},display:[`Live migration of VM ${t} from **${r.node}** to **${s}** started.`,"",`UPID: \`${n}\``].join(`
502
516
  `)}}async deleteSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),n=await this.del(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:n},display:[`Snapshot **"${s}"** deletion started for VM ${t} on **${r.node}**.`,"",`UPID: \`${n}\``].join(`
503
517
  `)}}async rollbackSnapshot(e){let t=e.vmid,s=e.name;if(t==null)return{success:!1,error:'Missing required "vmid" parameter'};if(!s)return{success:!1,error:'Missing required "name" parameter (snapshot name)'};let r=await this.resolveVm(t,e.node),n=await this.post(`/nodes/${r.node}/${r.type}/${t}/snapshot/${encodeURIComponent(s)}/rollback`);return{success:!0,data:{vmid:t,node:r.node,type:r.type,snapname:s,upid:n},display:[`Rollback to snapshot **"${s}"** started for VM ${t} on **${r.node}**.`,"",`UPID: \`${n}\``,"","**Warning:** The VM will be stopped during rollback."].join(`
504
- `)}}}});var rr,Di=b(()=>{"use strict";D();rr=class extends ${static{u(this,"UniFiSkill")}metadata={name:"unifi",description:'Manage UniFi network devices, clients, and WLANs. Use "list_devices" to see APs/switches, "list_clients" for connected clients, "restart_device" to reboot a device, "block_client"/"unblock_client" for access control.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_devices","device_info","list_clients","client_info","list_networks","list_wlans","site_stats","dpi_stats","list_alerts","list_events","list_vouchers","restart_device","locate_device","reconnect_client","create_voucher","enable_wlan","disable_wlan","archive_alerts","block_client","unblock_client","forget_client","adopt_device"],description:"The UniFi action to perform"},mac:{type:"string",description:"MAC address of device or client (for device_info, client_info, restart_device, locate_device, reconnect_client, block_client, unblock_client, forget_client, adopt_device)"},active:{type:"boolean",description:"If true list only active clients, if false list all known clients (for list_clients, default: true)"},enabled:{type:"boolean",description:"Enable or disable device locate LED (for locate_device, default: true)"},id:{type:"string",description:"WLAN config ID (for enable_wlan, disable_wlan)"},limit:{type:"number",description:"Maximum number of items to return (for list_alerts, list_events)"},count:{type:"number",description:"Number of vouchers to create (for create_voucher, default: 1)"},duration:{type:"number",description:"Voucher validity in minutes (for create_voucher)"},bandwidth_down:{type:"number",description:"Download bandwidth limit in Kbps (for create_voucher, optional)"},bandwidth_up:{type:"number",description:"Upload bandwidth limit in Kbps (for create_voucher, optional)"},quota:{type:"number",description:"Number of uses per voucher (for create_voucher, 0 = unlimited, default: 1)"}},required:["action"]}};config;site;controllerMode;cookies=[];csrfToken;constructor(e){if(super(),!e.apiKey&&!(e.username&&e.password))throw new Error('UniFi config requires either "apiKey" or both "username" and "password".');this.config=e,this.site=e.site??"default",e.apiKey&&(this.controllerMode="unifi-os")}async execute(e,t){let s=e.action;try{switch(s){case"list_devices":return await this.listDevices();case"device_info":return await this.deviceInfo(e.mac);case"list_clients":return await this.listClients(e.active);case"client_info":return await this.clientInfo(e.mac);case"list_networks":return await this.listNetworks();case"list_wlans":return await this.listWlans();case"site_stats":return await this.siteStats();case"dpi_stats":return await this.dpiStats(e.mac);case"list_alerts":return await this.listAlerts(e.limit);case"list_events":return await this.listEvents(e.limit);case"list_vouchers":return await this.listVouchers();case"restart_device":return await this.restartDevice(e.mac);case"locate_device":return await this.locateDevice(e.mac,e.enabled);case"reconnect_client":return await this.reconnectClient(e.mac);case"create_voucher":return await this.createVoucher(e.count,e.duration,e.bandwidth_down,e.bandwidth_up,e.quota);case"enable_wlan":return await this.enableWlan(e.id);case"disable_wlan":return await this.disableWlan(e.id);case"archive_alerts":return await this.archiveAlerts();case"block_client":return await this.blockClient(e.mac);case"unblock_client":return await this.unblockClient(e.mac);case"forget_client":return await this.forgetClient(e.mac);case"adopt_device":return await this.adoptDevice(e.mac);default:return{success:!1,error:`Unknown action: ${s}`}}}catch(r){return{success:!1,error:`UniFi error: ${r instanceof Error?r.message:String(r)}`}}}apiUrl(e){let t=this.config.baseUrl.replace(/\/+$/,"");return this.controllerMode==="unifi-os"?`${t}/proxy/network/api/s/${this.site}/${e}`:`${t}/api/s/${this.site}/${e}`}async ensureAuth(){this.config.apiKey||this.cookies.length>0||await this.login()}async login(){let e=this.config.baseUrl.replace(/\/+$/,""),t=JSON.stringify({username:this.config.username,password:this.config.password}),s=await this.rawFetch(`${e}/api/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(s.status===200){this.controllerMode="unifi-os",this.storeCookies(s);return}if(s.status===404){let r=await this.rawFetch(`${e}/api/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(r.ok){this.controllerMode="classic",this.storeCookies(r);return}throw new Error(`UniFi Classic login failed (HTTP ${r.status}): ${await r.text()}`)}throw new Error(`UniFi OS login failed (HTTP ${s.status}): ${await s.text()}`)}storeCookies(e){let t=e.headers.getSetCookie?.()??[];t.length>0&&(this.cookies=t.map(r=>r.split(";")[0]));let s=e.headers.get("x-csrf-token");s&&(this.csrfToken=s)}clearSession(){this.cookies=[],this.csrfToken=void 0}async rawFetch(e,t){let s=process.env.NODE_TLS_REJECT_UNAUTHORIZED;this.config.verifyTls===!1&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");try{return await fetch(e,t)}finally{this.config.verifyTls===!1&&(s===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=s)}}async request(e,t,s){await this.ensureAuth();let r=await this.doFetch(e,t,s);if(r.status===401&&!this.config.apiKey){this.clearSession(),await this.login();let n=await this.doFetch(e,t,s);if(!n.ok)throw new Error(`UniFi API error after relogin: HTTP ${n.status} ${await n.text()}`);return this.parseResponse(n)}if(!r.ok)throw new Error(`UniFi API error: HTTP ${r.status} ${await r.text()}`);return this.parseResponse(r)}async doFetch(e,t,s){let r=this.apiUrl(t),n={"Content-Type":"application/json"};return this.config.apiKey?n["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(n.Cookie=this.cookies.join("; ")),this.csrfToken&&(n["X-CSRF-Token"]=this.csrfToken)),this.rawFetch(r,{method:e,headers:n,body:s!==void 0?JSON.stringify(s):void 0,signal:AbortSignal.timeout(3e4)})}async parseResponse(e){let t=await e.json(),s=e.headers.get("x-csrf-token");if(s&&(this.csrfToken=s),t.meta?.rc==="error")throw new Error(`UniFi: ${t.meta.msg??"unknown error"}`);return t.data}async listDevices(){let e=await this.request("GET","stat/device"),t=(e??[]).map(r=>({name:r.name??r.hostname??r.mac,model:r.model??"unknown",ip:r.ip??"-",mac:r.mac,status:r.state===1?"online":"offline",clients:r.num_sta??0,load:r["system-stats"]?.cpu!=null?`${r["system-stats"].cpu}%`:"-"})),s=t.length===0?"No devices found.":["| Name | Model | IP | MAC | Status | Clients | CPU |","|------|-------|----|-----|--------|---------|-----|",...t.map(r=>`| ${r.name} | ${r.model} | ${r.ip} | ${r.mac} | ${r.status} | ${r.clients} | ${r.load} |`)].join(`
518
+ `)}}}});var mr,ta=w(()=>{"use strict";P();mr=class extends I{static{u(this,"UniFiSkill")}metadata={name:"unifi",description:'Manage UniFi network devices, clients, and WLANs. Use "list_devices" to see APs/switches, "list_clients" for connected clients, "restart_device" to reboot a device, "block_client"/"unblock_client" for access control.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_devices","device_info","list_clients","client_info","list_networks","list_wlans","site_stats","dpi_stats","list_alerts","list_events","list_vouchers","restart_device","locate_device","reconnect_client","create_voucher","enable_wlan","disable_wlan","archive_alerts","block_client","unblock_client","forget_client","adopt_device"],description:"The UniFi action to perform"},mac:{type:"string",description:"MAC address of device or client (for device_info, client_info, restart_device, locate_device, reconnect_client, block_client, unblock_client, forget_client, adopt_device)"},active:{type:"boolean",description:"If true list only active clients, if false list all known clients (for list_clients, default: true)"},enabled:{type:"boolean",description:"Enable or disable device locate LED (for locate_device, default: true)"},id:{type:"string",description:"WLAN config ID (for enable_wlan, disable_wlan)"},limit:{type:"number",description:"Maximum number of items to return (for list_alerts, list_events)"},count:{type:"number",description:"Number of vouchers to create (for create_voucher, default: 1)"},duration:{type:"number",description:"Voucher validity in minutes (for create_voucher)"},bandwidth_down:{type:"number",description:"Download bandwidth limit in Kbps (for create_voucher, optional)"},bandwidth_up:{type:"number",description:"Upload bandwidth limit in Kbps (for create_voucher, optional)"},quota:{type:"number",description:"Number of uses per voucher (for create_voucher, 0 = unlimited, default: 1)"}},required:["action"]}};config;site;controllerMode;cookies=[];csrfToken;constructor(e){if(super(),!e.apiKey&&!(e.username&&e.password))throw new Error('UniFi config requires either "apiKey" or both "username" and "password".');this.config=e,this.site=e.site??"default",e.apiKey&&(this.controllerMode="unifi-os")}async execute(e,t){let s=e.action;try{switch(s){case"list_devices":return await this.listDevices();case"device_info":return await this.deviceInfo(e.mac);case"list_clients":return await this.listClients(e.active);case"client_info":return await this.clientInfo(e.mac);case"list_networks":return await this.listNetworks();case"list_wlans":return await this.listWlans();case"site_stats":return await this.siteStats();case"dpi_stats":return await this.dpiStats(e.mac);case"list_alerts":return await this.listAlerts(e.limit);case"list_events":return await this.listEvents(e.limit);case"list_vouchers":return await this.listVouchers();case"restart_device":return await this.restartDevice(e.mac);case"locate_device":return await this.locateDevice(e.mac,e.enabled);case"reconnect_client":return await this.reconnectClient(e.mac);case"create_voucher":return await this.createVoucher(e.count,e.duration,e.bandwidth_down,e.bandwidth_up,e.quota);case"enable_wlan":return await this.enableWlan(e.id);case"disable_wlan":return await this.disableWlan(e.id);case"archive_alerts":return await this.archiveAlerts();case"block_client":return await this.blockClient(e.mac);case"unblock_client":return await this.unblockClient(e.mac);case"forget_client":return await this.forgetClient(e.mac);case"adopt_device":return await this.adoptDevice(e.mac);default:return{success:!1,error:`Unknown action: ${s}`}}}catch(r){return{success:!1,error:`UniFi error: ${r instanceof Error?r.message:String(r)}`}}}apiUrl(e){let t=this.config.baseUrl.replace(/\/+$/,"");return this.controllerMode==="unifi-os"?`${t}/proxy/network/api/s/${this.site}/${e}`:`${t}/api/s/${this.site}/${e}`}async ensureAuth(){this.config.apiKey||this.cookies.length>0||await this.login()}async login(){let e=this.config.baseUrl.replace(/\/+$/,""),t=JSON.stringify({username:this.config.username,password:this.config.password}),s=await this.rawFetch(`${e}/api/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(s.status===200){this.controllerMode="unifi-os",this.storeCookies(s);return}if(s.status===404){let r=await this.rawFetch(`${e}/api/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(r.ok){this.controllerMode="classic",this.storeCookies(r);return}throw new Error(`UniFi Classic login failed (HTTP ${r.status}): ${await r.text()}`)}throw new Error(`UniFi OS login failed (HTTP ${s.status}): ${await s.text()}`)}storeCookies(e){let t=e.headers.getSetCookie?.()??[];t.length>0&&(this.cookies=t.map(r=>r.split(";")[0]));let s=e.headers.get("x-csrf-token");s&&(this.csrfToken=s)}clearSession(){this.cookies=[],this.csrfToken=void 0}async rawFetch(e,t){let s=process.env.NODE_TLS_REJECT_UNAUTHORIZED;this.config.verifyTls===!1&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");try{return await fetch(e,t)}finally{this.config.verifyTls===!1&&(s===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=s)}}async request(e,t,s){await this.ensureAuth();let r=await this.doFetch(e,t,s);if(r.status===401&&!this.config.apiKey){this.clearSession(),await this.login();let n=await this.doFetch(e,t,s);if(!n.ok)throw new Error(`UniFi API error after relogin: HTTP ${n.status} ${await n.text()}`);return this.parseResponse(n)}if(!r.ok)throw new Error(`UniFi API error: HTTP ${r.status} ${await r.text()}`);return this.parseResponse(r)}async doFetch(e,t,s){let r=this.apiUrl(t),n={"Content-Type":"application/json"};return this.config.apiKey?n["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(n.Cookie=this.cookies.join("; ")),this.csrfToken&&(n["X-CSRF-Token"]=this.csrfToken)),this.rawFetch(r,{method:e,headers:n,body:s!==void 0?JSON.stringify(s):void 0,signal:AbortSignal.timeout(3e4)})}async parseResponse(e){let t=await e.json(),s=e.headers.get("x-csrf-token");if(s&&(this.csrfToken=s),t.meta?.rc==="error")throw new Error(`UniFi: ${t.meta.msg??"unknown error"}`);return t.data}async listDevices(){let e=await this.request("GET","stat/device"),t=(e??[]).map(r=>({name:r.name??r.hostname??r.mac,model:r.model??"unknown",ip:r.ip??"-",mac:r.mac,status:r.state===1?"online":"offline",clients:r.num_sta??0,load:r["system-stats"]?.cpu!=null?`${r["system-stats"].cpu}%`:"-"})),s=t.length===0?"No devices found.":["| Name | Model | IP | MAC | Status | Clients | CPU |","|------|-------|----|-----|--------|---------|-----|",...t.map(r=>`| ${r.name} | ${r.model} | ${r.ip} | ${r.mac} | ${r.status} | ${r.clients} | ${r.load} |`)].join(`
505
519
  `);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(`
506
520
  `)}}async listClients(e){let t=e!==!1,s=t?"stat/sta":"rest/user",r=await this.request("GET",s),n=(r??[]).map(i=>({name:i.name??i.hostname??i.mac,ip:i.ip??i.fixed_ip??"-",mac:i.mac,network:i.essid??i.network??"-",signal:i.signal!=null?`${i.signal} dBm`:"-",tx:this.formatBytes(i.tx_bytes??0),rx:this.formatBytes(i.rx_bytes??0)})),o=n.length===0?"No clients found.":["| Name | IP | MAC | Network | Signal | TX | RX |","|------|----|-----|---------|--------|----|----|",...n.map(i=>`| ${i.name} | ${i.ip} | ${i.mac} | ${i.network} | ${i.signal} | ${i.tx} | ${i.rx} |`)].join(`
507
521
  `);return{success:!0,data:r,display:`${t?"Active":"All known"} clients (${n.length}):
@@ -509,7 +523,7 @@ ${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success
509
523
  ${o}`}}async clientInfo(e){if(!e)return{success:!1,error:"mac is required for client_info."};let s=(await this.request("GET","stat/sta")??[]).find(n=>n.mac?.toLowerCase()===e.toLowerCase());if(!s)return{success:!1,error:`Client ${e} not found among active clients.`};let r=[`**${s.name??s.hostname??e}**`,`- IP: ${s.ip??"-"}`,`- MAC: ${s.mac}`,`- Network: ${s.essid??s.network??"-"}`,`- Signal: ${s.signal!=null?`${s.signal} dBm`:"-"}`,`- Satisfaction: ${s.satisfaction!=null?`${s.satisfaction}%`:"-"}`,`- TX rate: ${s.tx_rate!=null?`${(s.tx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- RX rate: ${s.rx_rate!=null?`${(s.rx_rate/1e3).toFixed(1)} Mbps`:"-"}`,`- TX bytes: ${this.formatBytes(s.tx_bytes??0)}`,`- RX bytes: ${this.formatBytes(s.rx_bytes??0)}`,`- Uptime: ${s.uptime?this.formatUptime(s.uptime):"-"}`,`- Blocked: ${s.blocked?"yes":"no"}`];return{success:!0,data:s,display:r.join(`
510
524
  `)}}async listNetworks(){let e=await this.request("GET","rest/networkconf"),t=(e??[]).map(r=>({name:r.name??"-",purpose:r.purpose??"-",vlan:r.vlan??"-",subnet:r.ip_subnet??"-",dhcp:r.dhcpd_enabled?"on":"off"})),s=t.length===0?"No networks found.":["| Name | Purpose | VLAN | Subnet | DHCP |","|------|---------|------|--------|------|",...t.map(r=>`| ${r.name} | ${r.purpose} | ${r.vlan} | ${r.subnet} | ${r.dhcp} |`)].join(`
511
525
  `);return{success:!0,data:e,display:s}}async listWlans(){let e=await this.request("GET","rest/wlanconf"),t=(e??[]).map(r=>({name:r.name??"-",id:r._id??"-",security:r.security??"-",band:r.wlan_band??"both",enabled:r.enabled!==!1?"yes":"no"})),s=t.length===0?"No WLANs found.":["| Name | ID | Security | Band | Enabled |","|------|----|----------|------|---------|",...t.map(r=>`| ${r.name} | ${r.id} | ${r.security} | ${r.band} | ${r.enabled} |`)].join(`
512
- `);return{success:!0,data:e,display:s}}async siteStats(){let e=this.config.baseUrl.replace(/\/+$/,"");await this.ensureAuth();let t;this.controllerMode==="unifi-os"?t=`${e}/proxy/network/api/stat/sites`:t=`${e}/api/stat/sites`;let s={"Content-Type":"application/json"};this.config.apiKey?s["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(s.Cookie=this.cookies.join("; ")),this.csrfToken&&(s["X-CSRF-Token"]=this.csrfToken));let r=await this.rawFetch(t,{method:"GET",headers:s,signal:AbortSignal.timeout(3e4)});if(!r.ok)throw new Error(`site_stats failed: HTTP ${r.status}`);let o=(await r.json()).data??[],i=o.map(a=>{let d=(a.health??[]).map(p=>` - ${p.subsystem}: ${p.status} (${p.num_user??0} users)`);return[`**${a.desc??a.name??"site"}**`,`- Devices: ${a.num_new_alarms??0} alarms`,...d].join(`
526
+ `);return{success:!0,data:e,display:s}}async siteStats(){let e=this.config.baseUrl.replace(/\/+$/,"");await this.ensureAuth();let t;this.controllerMode==="unifi-os"?t=`${e}/proxy/network/api/stat/sites`:t=`${e}/api/stat/sites`;let s={"Content-Type":"application/json"};this.config.apiKey?s["X-API-Key"]=this.config.apiKey:(this.cookies.length>0&&(s.Cookie=this.cookies.join("; ")),this.csrfToken&&(s["X-CSRF-Token"]=this.csrfToken));let r=await this.rawFetch(t,{method:"GET",headers:s,signal:AbortSignal.timeout(3e4)});if(!r.ok)throw new Error(`site_stats failed: HTTP ${r.status}`);let o=(await r.json()).data??[],i=o.map(a=>{let d=(a.health??[]).map(m=>` - ${m.subsystem}: ${m.status} (${m.num_user??0} users)`);return[`**${a.desc??a.name??"site"}**`,`- Devices: ${a.num_new_alarms??0} alarms`,...d].join(`
513
527
  `)});return{success:!0,data:o,display:i.join(`
514
528
 
515
529
  `)||"No site data."}}async dpiStats(e){let t=e?"stat/stadpi":"stat/sitedpi",s=e?{type:"by_app",macs:[e]}:{type:"by_app"},r=await this.request("POST",t,s);if(!r||r.length===0)return{success:!0,data:[],display:"No DPI data available."};let n=r.slice(0,20).map(o=>{let i=o.cat!=null?`Cat ${o.cat}`:"Unknown",a=o.app!=null?`App ${o.app}`:"";return`- ${i} ${a}: TX ${this.formatBytes(o.tx_bytes??0)}, RX ${this.formatBytes(o.rx_bytes??0)}`});return{success:!0,data:r,display:n.join(`
@@ -517,32 +531,42 @@ ${o}`}}async clientInfo(e){if(!e)return{success:!1,error:"mac is required for cl
517
531
  `);return{success:!0,data:s,display:n}}async listEvents(e){let t=Math.min(Math.max(1,e??20),200),s=await this.request("GET",`stat/event?_limit=${t}`),r=(s??[]).slice(0,t).map(o=>({time:o.datetime??o.time??"-",type:o.key??"-",message:o.msg??"-"})),n=r.length===0?"No events.":["| Time | Type | Message |","|------|------|---------|",...r.map(o=>`| ${o.time} | ${o.type} | ${o.message} |`)].join(`
518
532
  `);return{success:!0,data:s,display:n}}async listVouchers(){let e=await this.request("GET","stat/voucher"),t=(e??[]).map(r=>({code:r.code??"-",duration:r.duration!=null?`${r.duration} min`:"-",quota:r.quota??0,used:r.used??0,created:r.create_time?new Date(r.create_time*1e3).toISOString():"-",note:r.note??"-"})),s=t.length===0?"No vouchers.":["| Code | Duration | Quota | Used | Created | Note |","|------|----------|-------|------|---------|------|",...t.map(r=>`| ${r.code} | ${r.duration} | ${r.quota} | ${r.used} | ${r.created} | ${r.note} |`)].join(`
519
533
  `);return{success:!0,data:e,display:s}}async restartDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"restart",mac:e}),{success:!0,data:{mac:e},display:`Restart command sent to device ${e}.`}):{success:!1,error:"mac is required for restart_device."}}async locateDevice(e,t){if(!e)return{success:!1,error:"mac is required for locate_device."};let s=t!==!1,r=s?"set-locate":"unset-locate";return await this.request("POST","cmd/devmgr",{cmd:r,mac:e}),{success:!0,data:{mac:e,enabled:s},display:`Device ${e} locate LED ${s?"enabled":"disabled"}.`}}async reconnectClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"kick-sta",mac:e}),{success:!0,data:{mac:e},display:`Reconnect (kick) command sent to client ${e}.`}):{success:!1,error:"mac is required for reconnect_client."}}async createVoucher(e,t,s,r,n){if(!t)return{success:!1,error:"duration (minutes) is required for create_voucher."};let o={cmd:"create-voucher",n:e??1,expire:t,quota:n??1};s!=null&&(o.down=s),r!=null&&(o.up=r);let i=await this.request("POST","cmd/hotspot",o),a=i?.[0]?.create_time;return{success:!0,data:i,display:`Created ${e??1} voucher(s), duration ${t} min.${a?` Batch: ${a}`:""}
520
- Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!0}),{success:!0,data:{id:e,enabled:!0},display:`WLAN ${e} enabled.`}):{success:!1,error:"id is required for enable_wlan."}}async disableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!1}),{success:!0,data:{id:e,enabled:!1},display:`WLAN ${e} disabled.`}):{success:!1,error:"id is required for disable_wlan."}}async archiveAlerts(){return await this.request("POST","cmd/evtmgr",{cmd:"archive-all-alarms"}),{success:!0,data:{},display:"All alerts archived."}}async blockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"block-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} blocked.`}):{success:!1,error:"mac is required for block_client."}}async unblockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"unblock-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} unblocked.`}):{success:!1,error:"mac is required for unblock_client."}}async forgetClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"forget-sta",macs:[e]}),{success:!0,data:{mac:e},display:`Client ${e} forgotten (removed from known clients).`}):{success:!1,error:"mac is required for forget_client."}}async adoptDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"adopt",mac:e}),{success:!0,data:{mac:e},display:`Adopt command sent to device ${e}.`}):{success:!1,error:"mac is required for adopt_device."}}formatBytes(e){if(e===0)return"0 B";let t=["B","KB","MB","GB","TB"],s=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1);return`${(e/Math.pow(1024,s)).toFixed(s===0?0:1)} ${t[s]}`}formatUptime(e){let t=Math.floor(e/86400),s=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),n=[];return t>0&&n.push(`${t}d`),s>0&&n.push(`${s}h`),n.push(`${r}m`),n.join(" ")}}});import Tn from"node:fs";import Ui from"node:path";function Pi(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Jc(){let c=process.cwd();for(let e=0;e<10;e++){let t=Ui.join(c,".env");if(Tn.existsSync(t))return t;let s=Ui.dirname(c);if(s===c)break;c=s}return null}var $t,St,Fi=b(()=>{"use strict";D();$t={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")'}]}},St=class extends ${static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",description:'Configure Alfred services (Proxmox, UniFi, etc.) by writing environment variables. Use action "list_services" to see available services. Use action "show" to check current config of a service. Use action "set" to write config \u2014 provide service name and values. After setting config, the service is activated immediately \u2014 no restart needed.',riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_services","show","set"],description:"Action to perform"},service:{type:"string",enum:["proxmox","unifi"],description:"Service to configure (required for show/set)"},values:{type:"object",description:'Key-value pairs to set. Keys are the ENV variable names (e.g. ALFRED_PROXMOX_BASE_URL). Only for action "set".'}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"list_services":return this.listServices();case"show":return this.showService(e.service);case"set":return this.setService(e.service,e.values);default:return{success:!1,error:`Unknown action "${s}". Use list_services, show, or set.`}}}listServices(){let e=["| Service | Status | ENV Prefix |","|---|---|---|"];for(let[t,s]of Object.entries($t)){let n=s.fields.filter(i=>i.required).every(i=>!!process.env[i.env])?"configured":"not configured",o=`ALFRED_${t.toUpperCase()}_*`;e.push(`| ${s.label} | ${n} | \`${o}\` |`)}return{success:!0,data:Object.keys($t),display:e.join(`
521
- `)}}showService(e){let t=$t[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys($t).join(", ")}`};let s=[`**${t.label}** configuration:
522
- `],r={};for(let n of t.fields){let o=process.env[n.env];r[n.env]=o;let i=o?n.secret?Pi(o):o:"_not set_",a=n.required?" (required)":"";s.push(`- \`${n.env}\`: ${i}${a}`)}return{success:!0,data:r,display:s.join(`
523
- `)}}async setService(e,t){let s=$t[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys($t).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
534
+ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!0}),{success:!0,data:{id:e,enabled:!0},display:`WLAN ${e} enabled.`}):{success:!1,error:"id is required for enable_wlan."}}async disableWlan(e){return e?(await this.request("PUT",`rest/wlanconf/${e}`,{enabled:!1}),{success:!0,data:{id:e,enabled:!1},display:`WLAN ${e} disabled.`}):{success:!1,error:"id is required for disable_wlan."}}async archiveAlerts(){return await this.request("POST","cmd/evtmgr",{cmd:"archive-all-alarms"}),{success:!0,data:{},display:"All alerts archived."}}async blockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"block-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} blocked.`}):{success:!1,error:"mac is required for block_client."}}async unblockClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"unblock-sta",mac:e}),{success:!0,data:{mac:e},display:`Client ${e} unblocked.`}):{success:!1,error:"mac is required for unblock_client."}}async forgetClient(e){return e?(await this.request("POST","cmd/stamgr",{cmd:"forget-sta",macs:[e]}),{success:!0,data:{mac:e},display:`Client ${e} forgotten (removed from known clients).`}):{success:!1,error:"mac is required for forget_client."}}async adoptDevice(e){return e?(await this.request("POST","cmd/devmgr",{cmd:"adopt",mac:e}),{success:!0,data:{mac:e},display:`Adopt command sent to device ${e}.`}):{success:!1,error:"mac is required for adopt_device."}}formatBytes(e){if(e===0)return"0 B";let t=["B","KB","MB","GB","TB"],s=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1);return`${(e/Math.pow(1024,s)).toFixed(s===0?0:1)} ${t[s]}`}formatUptime(e){let t=Math.floor(e/86400),s=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),n=[];return t>0&&n.push(`${t}d`),s>0&&n.push(`${s}h`),n.push(`${r}m`),n.join(" ")}}});function sa(c){let e=c.match(/^(\d+)\s*(h|d|m|w)$/i);if(!e)return new Date(Date.now()-36e5).toISOString();let t=parseInt(e[1],10),s=e[2].toLowerCase(),r={m:6e4,h:36e5,d:864e5,w:6048e5}[s]??36e5;return new Date(Date.now()-t*r).toISOString()}function _l(c){let e=c.indexOf(".");if(e<1)throw new Error(`Invalid entity_id "${c}" \u2014 expected format "domain.name"`);return c.slice(0,e)}var pr,ra=w(()=>{"use strict";P();u(sa,"parsePeriod");u(_l,"extractDomain");pr=class extends I{static{u(this,"HomeAssistantSkill")}metadata={name:"homeassistant",description:'Control Home Assistant smart home devices. Use "states" to list entities, "turn_on"/"turn_off"/"toggle" to control devices, "call_service" for advanced service calls, "history" for entity state history.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["states","state","turn_on","turn_off","toggle","call_service","services","history","logbook","config"],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)"}},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();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Home Assistant API error: ${r instanceof Error?r.message:String(r)}. Check baseUrl and connectivity.`}}}async api(e,t,s){let r=`${this.config.baseUrl.replace(/\/+$/,"")}${t}`,n={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},o={method:e,headers:n,signal:AbortSignal.timeout(15e3)};s&&e!=="GET"&&(o.body=JSON.stringify(s));let i=this.config.verifyTls===!1,a=process.env.NODE_TLS_REJECT_UNAUTHORIZED;i&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let l;try{l=await fetch(r,o)}finally{i&&(a===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=a)}if(!l.ok){let d="";try{d=(await l.text()).slice(0,500)}catch{}throw new Error(`HTTP ${l.status} ${l.statusText} \u2014 ${d}`)}return await l.json()}async getStates(e){let t=await this.api("GET","/api/states");e&&(t=t.filter(r=>r.entity_id.startsWith(`${e}.`)));let s=[`## Entities${e?` (${e})`:""}`,"","| Entity ID | State | Name | Unit |","|-----------|-------|------|------|"];for(let r of t){let n=r.attributes?.friendly_name??"-",o=r.attributes?.unit_of_measurement??"-";s.push(`| ${r.entity_id} | ${r.state} | ${n} | ${o} |`)}return t.length===0&&s.push(`| - | No entities found${e?` for domain "${e}"`:""} | - | - |`),{success:!0,data:t,display:s.join(`
535
+ `)}}async getState(e){if(!e)return{success:!1,error:'Missing required "entityId" parameter'};let t=await this.api("GET",`/api/states/${e}`),s=t.attributes??{},r=[`## ${s.friendly_name??e}`,"",`**Entity ID:** ${t.entity_id}`,`**State:** ${t.state}`,`**Last Changed:** ${t.last_changed??"-"}`,`**Last Updated:** ${t.last_updated??"-"}`,"","### Attributes"];for(let[n,o]of Object.entries(s)){let i=typeof o=="object"?JSON.stringify(o):String(o);r.push(`- **${n}:** ${i}`)}return{success:!0,data:t,display:r.join(`
536
+ `)}}async getServices(){let e=await this.api("GET","/api/services"),t=["## Available Services",""];for(let s of e){let r=s.domain??"unknown",n=Object.keys(s.services??{});if(n.length!==0){t.push(`### ${r}`);for(let o of n){let i=s.services[o]?.description??"";t.push(`- **${o}**${i?`: ${i}`:""}`)}t.push("")}}return{success:!0,data:e,display:t.join(`
537
+ `)}}async getHistory(e,t){let s=sa(t??"1h"),r=e?`?filter_entity_id=${e}`:"",n=await this.api("GET",`/api/history/period/${s}${r}`),o=["## History",""];if(!n||n.length===0||n.every(i=>i.length===0))return o.push("No history entries found for the given period."),{success:!0,data:[],display:o.join(`
538
+ `)};for(let i of n){if(i.length===0)continue;let a=i[0]?.entity_id??"unknown",l=i[0]?.attributes?.friendly_name??a;o.push(`### ${l} (\`${a}\`)`),o.push(""),o.push("| Time | State |"),o.push("|------|-------|");for(let d of i){let m=d.last_changed?new Date(d.last_changed).toLocaleString():"-";o.push(`| ${m} | ${d.state} |`)}o.push("")}return{success:!0,data:n,display:o.join(`
539
+ `)}}async getLogbook(e,t){let s=sa(t??"1h"),r=e?`?entity=${e}`:"",n=await this.api("GET",`/api/logbook/${s}${r}`),o=["## Logbook",""];if(!n||n.length===0)return o.push("No logbook entries found for the given period."),{success:!0,data:[],display:o.join(`
540
+ `)};o.push("| Time | Entity | Message |"),o.push("|------|--------|---------|");for(let i of n){let a=i.when?new Date(i.when).toLocaleString():"-",l=i.name??i.entity_id??"-",d=i.message??i.state??"-";o.push(`| ${a} | ${l} | ${d} |`)}return{success:!0,data:n,display:o.join(`
541
+ `)}}async getConfig(){let e=await this.api("GET","/api/config"),t=["## Home Assistant Configuration","",`**Name:** ${e.location_name??"-"}`,`**Version:** ${e.version??"-"}`,`**Time Zone:** ${e.time_zone??"-"}`,`**Latitude:** ${e.latitude??"-"}`,`**Longitude:** ${e.longitude??"-"}`,`**Elevation:** ${e.elevation??"-"} m`,`**Unit System:** ${e.unit_system?.length?JSON.stringify(e.unit_system):"-"}`,`**Currency:** ${e.currency??"-"}`,`**Internal URL:** ${e.internal_url??"-"}`,`**External URL:** ${e.external_url??"-"}`];return e.components&&Array.isArray(e.components)&&t.push("",`**Components:** ${e.components.length} loaded`),{success:!0,data:e,display:t.join(`
542
+ `)}}async switchAction(e,t,s){if(!t)return{success:!1,error:'Missing required "entityId" parameter'};let r=_l(t),n={entity_id:t};if(s)try{let l=JSON.parse(s);Object.assign(n,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let o=await this.api("POST",`/api/services/${r}/${e}`,n),i=o?.[0]?.state??"unknown",a=o?.[0]?.attributes?.friendly_name??t;return{success:!0,data:o,display:[`**${e.replace("_"," ")}** \u2192 **${a}**`,"",`New state: **${i}**`].join(`
543
+ `)}}async callService(e,t,s,r){if(!e)return{success:!1,error:'Missing required "domain" parameter for call_service'};if(!t)return{success:!1,error:'Missing required "service" parameter for call_service'};let n={};if(s&&(n.entity_id=s),r)try{let l=JSON.parse(r);Object.assign(n,l)}catch{return{success:!1,error:'Invalid "serviceData" \u2014 must be valid JSON'}}let o=await this.api("POST",`/api/services/${e}/${t}`,n),i=o?.length??0,a=[`**Service called:** \`${e}.${t}\``,s?`**Entity:** ${s}`:"",`**Affected entities:** ${i}`].filter(Boolean);if(o&&o.length>0){a.push("");for(let l of o){let d=l.attributes?.friendly_name??l.entity_id??"unknown";a.push(`- **${d}**: ${l.state}`)}}return{success:!0,data:o,display:a.join(`
544
+ `)}}}});import Cn from"node:fs";import na from"node:path";function oa(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function $l(){let c=process.cwd();for(let e=0;e<10;e++){let t=na.join(c,".env");if(Cn.existsSync(t))return t;let s=na.dirname(c);if(s===c)break;c=s}return null}var Lt,Mt,ia=w(()=>{"use strict";P();Lt={proxmox:{label:"Proxmox VE",fields:[{env:"ALFRED_PROXMOX_BASE_URL",label:"Base URL (e.g. https://pve.local:8006)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_ID",label:"API Token ID (user@realm!name)",required:!0},{env:"ALFRED_PROXMOX_TOKEN_SECRET",label:"API Token Secret",required:!0,secret:!0}]},unifi:{label:"UniFi Network",fields:[{env:"ALFRED_UNIFI_BASE_URL",label:"Base URL (e.g. https://unifi.local)",required:!0},{env:"ALFRED_UNIFI_API_KEY",label:"API Key (preferred, UniFi OS)",secret:!0},{env:"ALFRED_UNIFI_USERNAME",label:"Username (alternative to API key)"},{env:"ALFRED_UNIFI_PASSWORD",label:"Password (alternative to API key)",secret:!0},{env:"ALFRED_UNIFI_SITE",label:'Site name (default: "default")'}]}},Mt=class extends I{static{u(this,"ConfigureSkill")}reloadCallback;setReloadCallback(e){this.reloadCallback=e}metadata={name:"configure",description:'Configure Alfred services (Proxmox, UniFi, etc.) by writing environment variables. Use action "list_services" to see available services. Use action "show" to check current config of a service. Use action "set" to write config \u2014 provide service name and values. After setting config, the service is activated immediately \u2014 no restart needed.',riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_services","show","set"],description:"Action to perform"},service:{type:"string",enum:["proxmox","unifi"],description:"Service to configure (required for show/set)"},values:{type:"object",description:'Key-value pairs to set. Keys are the ENV variable names (e.g. ALFRED_PROXMOX_BASE_URL). Only for action "set".'}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"list_services":return this.listServices();case"show":return this.showService(e.service);case"set":return this.setService(e.service,e.values);default:return{success:!1,error:`Unknown action "${s}". Use list_services, show, or set.`}}}listServices(){let e=["| Service | Status | ENV Prefix |","|---|---|---|"];for(let[t,s]of Object.entries(Lt)){let n=s.fields.filter(i=>i.required).every(i=>!!process.env[i.env])?"configured":"not configured",o=`ALFRED_${t.toUpperCase()}_*`;e.push(`| ${s.label} | ${n} | \`${o}\` |`)}return{success:!0,data:Object.keys(Lt),display:e.join(`
545
+ `)}}showService(e){let t=Lt[e];if(!t)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Lt).join(", ")}`};let s=[`**${t.label}** configuration:
546
+ `],r={};for(let n of t.fields){let o=process.env[n.env];r[n.env]=o;let i=o?n.secret?oa(o):o:"_not set_",a=n.required?" (required)":"";s.push(`- \`${n.env}\`: ${i}${a}`)}return{success:!0,data:r,display:s.join(`
547
+ `)}}async setService(e,t){let s=Lt[e];if(!s)return{success:!1,error:`Unknown service "${e}". Available: ${Object.keys(Lt).join(", ")}`};if(!t||Object.keys(t).length===0)return{success:!1,error:`No values provided. Pass an object with ENV variable names as keys.
524
548
 
525
549
  Available keys for ${s.label}:
526
550
  ${s.fields.map(d=>`- \`${d.env}\`: ${d.label}${d.required?" (required)":""}`).join(`
527
- `)}`};let r=new Set(s.fields.map(d=>d.env));for(let d of Object.keys(t))if(!r.has(d))return{success:!1,error:`Invalid key "${d}" for ${s.label}. Valid keys: ${[...r].join(", ")}`};let n=Jc();if(!n)return{success:!1,error:"Could not find .env file. Run `alfred setup` first or create a .env in your project root."};let o=Tn.readFileSync(n,"utf-8"),i=[];for(let[d,p]of Object.entries(t)){let m=p.replace(/\n/g,"\\n"),g=new RegExp(`^#?\\s*${d}=.*$`,"m");g.test(o)?o=o.replace(g,`${d}=${m}`):o=o.trimEnd()+`
528
- ${d}=${m}
529
- `,i.push(d)}Tn.writeFileSync(n,o,"utf-8");let a=s.fields.filter(d=>d.required).filter(d=>!t[d.env]&&!process.env[d.env]).map(d=>`\`${d.env}\``),l=[`Written to \`${n}\`:
530
- `,...i.map(d=>`- \`${d}\` = ${s.fields.find(p=>p.env===d)?.secret?Pi(t[d]):t[d]}`)];if(a.length>0)l.push(`
551
+ `)}`};let r=new Set(s.fields.map(d=>d.env));for(let d of Object.keys(t))if(!r.has(d))return{success:!1,error:`Invalid key "${d}" for ${s.label}. Valid keys: ${[...r].join(", ")}`};let n=$l();if(!n)return{success:!1,error:"Could not find .env file. Run `alfred setup` first or create a .env in your project root."};let o=Cn.readFileSync(n,"utf-8"),i=[];for(let[d,m]of Object.entries(t)){let h=m.replace(/\n/g,"\\n"),b=new RegExp(`^#?\\s*${d}=.*$`,"m");b.test(o)?o=o.replace(b,`${d}=${h}`):o=o.trimEnd()+`
552
+ ${d}=${h}
553
+ `,i.push(d)}Cn.writeFileSync(n,o,"utf-8");let a=s.fields.filter(d=>d.required).filter(d=>!t[d.env]&&!process.env[d.env]).map(d=>`\`${d.env}\``),l=[`Written to \`${n}\`:
554
+ `,...i.map(d=>`- \`${d}\` = ${s.fields.find(m=>m.env===d)?.secret?oa(t[d]):t[d]}`)];if(a.length>0)l.push(`
531
555
  **Still missing:** ${a.join(", ")}`);else if(this.reloadCallback){let d=await this.reloadCallback(e);d.success?l.push(`
532
556
  **${s.label} wurde aktiviert.** Du kannst es jetzt sofort nutzen.`):l.push(`
533
557
  **${s.label} is fully configured.** Hot-Reload fehlgeschlagen: ${d.error??"unbekannter Fehler"}. Restart Alfred: \`alfred start\``)}else l.push(`
534
558
  **${s.label} is fully configured.** Restart Alfred to activate: \`alfred start\``);return{success:!0,data:{envPath:n,written:i},display:l.join(`
535
- `)}}};u(Pi,"maskValue");u(Jc,"findEnvFile")});import{spawn as Zc}from"node:child_process";import ji from"node:fs";import Wi from"node:path";function sl(c){let e={};for(let[t,s]of Object.entries(c))e[t]=s.replace(/\$\{(\w+)\}/g,(r,n)=>process.env[n]??"");return e}function rl(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function nr(c){return c.length<=Bi?c:`[...truncated...]
536
- `+c.slice(-Bi)}function qi(c){let e=new Map;function t(s){let r;try{r=ji.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(tl.has(n.name))continue;let o=Wi.join(s,n.name);if(n.isDirectory())t(o);else if(n.isFile())try{let i=ji.statSync(o);e.set(o,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function nl(c,e,t){let s=[];for(let[r,n]of e){let o=c.get(r);(o===void 0||n>o)&&s.push(Wi.relative(t,r))}return s.sort()}async function gs(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??Qc,n=Math.min(r,el),o=rl(c.argsTemplate,e),i={...process.env,...c.env?sl(c.env):{}},a=process.platform==="win32",l=qi(s),d=Date.now();return new Promise(p=>{let m=Zc(c.command,o,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),g="",f="",h=!1,T=setTimeout(()=>{h=!0,m.kill("SIGTERM"),setTimeout(()=>m.kill("SIGKILL"),5e3)},n);m.stdout?.on("data",_=>{g+=_.toString()}),m.stderr?.on("data",_=>{let x=_.toString();if(f+=x,t.onProgress){let k=x.trim().split(`
537
- `).pop();k&&t.onProgress(`[${c.name}] ${k}`)}}),c.promptVia==="stdin"&&m.stdin&&(m.stdin.write(e),m.stdin.end()),m.on("close",_=>{clearTimeout(T);let x=Date.now()-d,k=qi(s),C=nl(l,k,s);p({stdout:nr(g),stderr:nr(f),exitCode:h?124:_??1,durationMs:x,modifiedFiles:C})}),m.on("error",_=>{clearTimeout(T);let x=Date.now()-d;p({stdout:nr(g),stderr:nr(f+`
538
- `+_.message),exitCode:127,durationMs:x,modifiedFiles:[]})})})}var Qc,el,Bi,tl,or=b(()=>{"use strict";Qc=3e5,el=9e5,Bi=1e5,tl=new Set([".git","node_modules",".next","dist",".cache"]);u(sl,"resolveEnv");u(rl,"buildArgs");u(nr,"truncateOutput");u(qi,"snapshotMtimes");u(nl,"detectModifiedFiles");u(gs,"executeAgent")});import{execFile as ol}from"node:child_process";function he(c,e){return new Promise((t,s)=>{ol("git",c,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,n,o)=>{if(r){let i=o?.trim()||r.message;s(new Error(`git ${c[0]} failed: ${i}`));return}t(n.trim())})})}async function ir(c){try{let e=await he(["rev-parse","--abbrev-ref","HEAD"],c),t=await he(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function En(c,e){await he(["checkout","-b",c],e)}async function _n(c){await he(["add","-A"],c)}async function vn(c,e){await he(["commit","-m",c],e);let t=await he(["rev-parse","--short","HEAD"],e),r=(await he(["diff","--stat","HEAD~1","HEAD"],e)).split(`
539
- `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function kn(c,e,t){await he(["push","-u",c,e],t)}function $n(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function xt(c,e){try{return await he(["remote","get-url",c],e)}catch{return null}}function It(c){let e=c.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],n=e[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}let t=c.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],n=t[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}return null}async function ys(c){await he(["init"],c)}async function ws(c,e,t){await he(["remote","add",c,e],t)}var Sn=b(()=>{"use strict";u(he,"git");u(ir,"gitStatus");u(En,"gitCreateBranch");u(_n,"gitStageAll");u(vn,"gitCommit");u(kn,"gitPush");u($n,"slugifyBranch");u(xt,"gitGetRemoteUrl");u(It,"parseRemoteUrl");u(ys,"gitInitRepo");u(ws,"gitAddRemote")});function At(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new xn(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new In(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var Ge,xn,In,An=b(()=>{"use strict";Ge=class{static{u(this,"ForgeClient")}},xn=class extends Ge{static{u(this,"GitHubForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://api.github.com"}async createPullRequest(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/pulls`,r=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({title:t.title,body:t.body,head:t.head,base:t.base})});if(!r.ok){let o=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${o}`)}let n=await r.json();return{id:n.id,url:n.html_url,number:n.number,state:n.state}}async getPipelineStatus(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/commits/${t}/status`,r=await fetch(s,{headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json"}});if(!r.ok)return{state:"unknown"};let o=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[o]??"unknown"}}async createProject(e){let t=`${this.baseUrl}/user/repos`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",private:(e.visibility??"private")==="private"})});if(!s.ok){let n=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},In=class extends Ge{static{u(this,"GitLabForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://gitlab.com"}async createPullRequest(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/merge_requests`,n=await fetch(r,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({title:t.title,description:t.body,source_branch:t.head,target_branch:t.base})});if(!n.ok){let i=await n.text();throw new Error(`GitLab MR creation failed (${n.status}): ${i}`)}let o=await n.json();return{id:o.id,url:o.web_url,number:o.iid,state:o.state}}async getPipelineStatus(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/pipelines?ref=${encodeURIComponent(t)}&per_page=1`,n=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!n.ok)return{state:"unknown"};let o=await n.json();if(o.length===0)return{state:"unknown"};let i=o[0],a=i.status;return{state:{pending:"pending",running:"running",success:"success",failed:"failure",canceled:"failure"}[a]??"unknown",url:i.web_url}}async createProject(e){let t=`${this.baseUrl}/api/v4/projects`,s=await fetch(t,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",visibility:e.visibility??"private"})});if(!s.ok){let n=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(At,"createForgeClient")});function Xi(c,e){return c.length<=e?c:c.slice(0,e)+`
540
- [...truncated]`}function Hi(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function ml(c,e,t){let r=`Available agents:
559
+ `)}}};u(oa,"maskValue");u($l,"findEnvFile")});import{spawn as vl}from"node:child_process";import aa from"node:fs";import da from"node:path";function Il(c){let e={};for(let[t,s]of Object.entries(c))e[t]=s.replace(/\$\{(\w+)\}/g,(r,n)=>process.env[n]??"");return e}function Al(c,e){return c.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function hr(c){return c.length<=ca?c:`[...truncated...]
560
+ `+c.slice(-ca)}function la(c){let e=new Map;function t(s){let r;try{r=aa.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(xl.has(n.name))continue;let o=da.join(s,n.name);if(n.isDirectory())t(o);else if(n.isFile())try{let i=aa.statSync(o);e.set(o,i.mtimeMs)}catch{}}}return u(t,"walk"),t(c),e}function Rl(c,e,t){let s=[];for(let[r,n]of e){let o=c.get(r);(o===void 0||n>o)&&s.push(da.relative(t,r))}return s.sort()}async function Ss(c,e,t={}){let s=t.cwd??c.cwd??process.cwd(),r=t.timeoutMs??c.timeoutMs??kl,n=Math.min(r,Sl),o=Al(c.argsTemplate,e),i={...process.env,...c.env?Il(c.env):{}},a=process.platform==="win32",l=la(s),d=Date.now();return new Promise(m=>{let h=vl(c.command,o,{cwd:s,env:i,shell:a,stdio:c.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),b="",y="",g=!1,E=setTimeout(()=>{g=!0,h.kill("SIGTERM"),setTimeout(()=>h.kill("SIGKILL"),5e3)},n);h.stdout?.on("data",v=>{b+=v.toString()}),h.stderr?.on("data",v=>{let R=v.toString();if(y+=R,t.onProgress){let x=R.trim().split(`
561
+ `).pop();x&&t.onProgress(`[${c.name}] ${x}`)}}),c.promptVia==="stdin"&&h.stdin&&(h.stdin.write(e),h.stdin.end()),h.on("close",v=>{clearTimeout(E);let R=Date.now()-d,x=la(s),O=Rl(l,x,s);m({stdout:hr(b),stderr:hr(y),exitCode:g?124:v??1,durationMs:R,modifiedFiles:O})}),h.on("error",v=>{clearTimeout(E);let R=Date.now()-d;m({stdout:hr(b),stderr:hr(y+`
562
+ `+v.message),exitCode:127,durationMs:R,modifiedFiles:[]})})})}var kl,Sl,ca,xl,fr=w(()=>{"use strict";kl=3e5,Sl=9e5,ca=1e5,xl=new Set([".git","node_modules",".next","dist",".cache"]);u(Il,"resolveEnv");u(Al,"buildArgs");u(hr,"truncateOutput");u(la,"snapshotMtimes");u(Rl,"detectModifiedFiles");u(Ss,"executeAgent")});import{execFile as Ll}from"node:child_process";function we(c,e){return new Promise((t,s)=>{Ll("git",c,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,n,o)=>{if(r){let i=o?.trim()||r.message;s(new Error(`git ${c[0]} failed: ${i}`));return}t(n.trim())})})}async function gr(c){try{let e=await we(["rev-parse","--abbrev-ref","HEAD"],c),t=await we(["status","--porcelain"],c);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function On(c,e){await we(["checkout","-b",c],e)}async function Dn(c){await we(["add","-A"],c)}async function Un(c,e){await we(["commit","-m",c],e);let t=await we(["rev-parse","--short","HEAD"],e),r=(await we(["diff","--stat","HEAD~1","HEAD"],e)).split(`
563
+ `).length-1;return{sha:t,message:c,filesChanged:Math.max(r,0)}}async function Pn(c,e,t){await we(["push","-u",c,e],t)}function Fn(c){return`alfred/${c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function Nt(c,e){try{return await we(["remote","get-url",c],e)}catch{return null}}function Ct(c){let e=c.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],n=e[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}let t=c.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],n=t[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}return null}async function xs(c){await we(["init"],c)}async function Is(c,e,t){await we(["remote","add",c,e],t)}var jn=w(()=>{"use strict";u(we,"git");u(gr,"gitStatus");u(On,"gitCreateBranch");u(Dn,"gitStageAll");u(Un,"gitCommit");u(Pn,"gitPush");u(Fn,"slugifyBranch");u(Nt,"gitGetRemoteUrl");u(Ct,"parseRemoteUrl");u(xs,"gitInitRepo");u(Is,"gitAddRemote")});function Ot(c){switch(c.provider){case"github":{if(!c.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new Bn(c.github)}case"gitlab":{if(!c.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new qn(c.gitlab)}default:throw new Error(`Unknown forge provider: ${c.provider}`)}}var et,Bn,qn,Hn=w(()=>{"use strict";et=class{static{u(this,"ForgeClient")}},Bn=class extends et{static{u(this,"GitHubForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://api.github.com"}async createPullRequest(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/pulls`,r=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({title:t.title,body:t.body,head:t.head,base:t.base})});if(!r.ok){let o=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${o}`)}let n=await r.json();return{id:n.id,url:n.html_url,number:n.number,state:n.state}}async getPipelineStatus(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/commits/${t}/status`,r=await fetch(s,{headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json"}});if(!r.ok)return{state:"unknown"};let o=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[o]??"unknown"}}async createProject(e){let t=`${this.baseUrl}/user/repos`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",private:(e.visibility??"private")==="private"})});if(!s.ok){let n=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},qn=class extends et{static{u(this,"GitLabForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://gitlab.com"}async createPullRequest(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/merge_requests`,n=await fetch(r,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({title:t.title,description:t.body,source_branch:t.head,target_branch:t.base})});if(!n.ok){let i=await n.text();throw new Error(`GitLab MR creation failed (${n.status}): ${i}`)}let o=await n.json();return{id:o.id,url:o.web_url,number:o.iid,state:o.state}}async getPipelineStatus(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/pipelines?ref=${encodeURIComponent(t)}&per_page=1`,n=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!n.ok)return{state:"unknown"};let o=await n.json();if(o.length===0)return{state:"unknown"};let i=o[0],a=i.status;return{state:{pending:"pending",running:"running",success:"success",failed:"failure",canceled:"failure"}[a]??"unknown",url:i.web_url}}async createProject(e){let t=`${this.baseUrl}/api/v4/projects`,s=await fetch(t,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",visibility:e.visibility??"private"})});if(!s.ok){let n=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(Ot,"createForgeClient")});function ua(c,e){return c.length<=e?c:c.slice(0,e)+`
564
+ [...truncated]`}function ma(c){let e=c.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function Fl(c,e,t){let r=`Available agents:
541
565
  ${e.map(a=>`- ${a.name}: command="${a.command}"`).join(`
542
566
  `)}
543
567
 
544
568
  Task:
545
- ${c}`,n=await t.complete({system:ul,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=Hi(n.content);if(!Array.isArray(o.subtasks)||o.subtasks.length===0)throw new Error("LLM returned an empty plan with no subtasks");let i=new Set(e.map(a=>a.name));for(let a of o.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return o}async function hl(c,e,t,s){let r=new Rn(t),n=[],o=c.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),l=await gs(a,i.prompt,{onProgress:s?p=>s(`[${i.id}] ${p}`):void 0}),d={subtask:i,execution:l};return n.push(d),s?.(`Completed ${i.id}: exit=${l.exitCode}, ${l.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(o),n}async function fl(c,e,t){let s=e.map(o=>{let i=Xi(o.execution.stdout,ll),a=Xi(o.execution.stderr,dl);return[`### ${o.subtask.id} (${o.subtask.description})`,`Agent: ${o.subtask.agent}`,`Exit code: ${o.execution.exitCode}`,`Modified files: ${o.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
569
+ ${c}`,n=await t.complete({system:Ul,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=ma(n.content);if(!Array.isArray(o.subtasks)||o.subtasks.length===0)throw new Error("LLM returned an empty plan with no subtasks");let i=new Set(e.map(a=>a.name));for(let a of o.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return o}async function jl(c,e,t,s){let r=new Wn(t),n=[],o=c.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),l=await Ss(a,i.prompt,{onProgress:s?m=>s(`[${i.id}] ${m}`):void 0}),d={subtask:i,execution:l};return n.push(d),s?.(`Completed ${i.id}: exit=${l.exitCode}, ${l.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(o),n}async function Bl(c,e,t){let s=e.map(o=>{let i=ua(o.execution.stdout,Ol),a=ua(o.execution.stderr,Dl);return[`### ${o.subtask.id} (${o.subtask.description})`,`Agent: ${o.subtask.agent}`,`Exit code: ${o.execution.exitCode}`,`Modified files: ${o.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
546
570
  ${i}`:"",a?`stderr:
547
571
  ${a}`:""].filter(Boolean).join(`
548
572
  `)}).join(`
@@ -551,11 +575,11 @@ ${a}`:""].filter(Boolean).join(`
551
575
  ${c}
552
576
 
553
577
  Results:
554
- ${s}`,n=await t.complete({system:pl,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=Hi(n.content);return{approved:o.approved??!0,summary:o.summary??"",fixTasks:Array.isArray(o.fixTasks)?o.fixTasks:[]}}catch{return{approved:!0,summary:n.content,fixTasks:[]}}}async function Ye(c,e,t,s={}){let r=Math.min(s.maxIterations??il,al),n=s.maxConcurrent??cl,o=s.onProgress,i=Date.now(),a=new Map(e.map(h=>[h.name,h]));o?.("Planning subtasks...");let l=await ml(c,e,t);o?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],p=l.subtasks,m=0,g="";for(;m<r;){m++,o?.(`Iteration ${m}: executing ${p.length} subtask(s)...`);let h=await hl(p,a,n,o);d=d.concat(h),o?.(`Iteration ${m}: validating results...`);let T=await fl(c,d,t);if(g=T.summary,T.approved||T.fixTasks.length===0)break;let _=T.fixTasks.filter(x=>a.has(x.agent)?!0:(o?.(`Warning: fix task "${x.id}" references unknown agent "${x.agent}", skipping`),!1));if(_.length===0)break;p=_,o?.(`Validation requested ${_.length} fix task(s), iterating...`)}let f=[...new Set(d.flatMap(h=>h.execution.modifiedFiles))].sort();return{plan:l,iterations:m,subtaskResults:d,allModifiedFiles:f,summary:g,totalDurationMs:Date.now()-i}}async function bs(c,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await ir({cwd:n});if(!i.isRepo)try{await ys({cwd:n}),i=await ir({cwd:n}),r?.("Initialised new git repository")}catch{return o.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await Ye(c,e,t,s),git:o}}let a=null,l=await xt("origin",{cwd:n});if(l){let f=It(l);f?(a={owner:f.owner,repo:f.repo},r?.(`Detected remote: ${f.owner}/${f.repo} (${f.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let f=At(d),h=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${h}" on forge...`);let T=await f.createProject({name:h,visibility:"private"});await ws("origin",T.cloneUrl,{cwd:n});let _=It(T.cloneUrl);_&&(a={owner:_.owner,repo:_.repo}),r?.(`Project created: ${T.url} \u2014 remote "origin" set`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`Project creation failed: ${h}`),r?.(`Warning: project creation failed \u2014 ${h}`)}let p=$n(c);try{await En(p,{cwd:n}),o.branch=p,r?.(`Created branch: ${p}`)}catch(f){throw new Error(`Failed to create branch "${p}": ${f instanceof Error?f.message:String(f)}`)}let m=await Ye(c,e,t,s);try{await _n({cwd:n});let f=`feat: ${c.slice(0,72)}
578
+ ${s}`,n=await t.complete({system:Pl,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=ma(n.content);return{approved:o.approved??!0,summary:o.summary??"",fixTasks:Array.isArray(o.fixTasks)?o.fixTasks:[]}}catch{return{approved:!0,summary:n.content,fixTasks:[]}}}async function tt(c,e,t,s={}){let r=Math.min(s.maxIterations??Ml,Nl),n=s.maxConcurrent??Cl,o=s.onProgress,i=Date.now(),a=new Map(e.map(g=>[g.name,g]));o?.("Planning subtasks...");let l=await Fl(c,e,t);o?.(`Plan created: ${l.subtasks.length} subtask(s) \u2014 ${l.reasoning}`);let d=[],m=l.subtasks,h=0,b="";for(;h<r;){h++,o?.(`Iteration ${h}: executing ${m.length} subtask(s)...`);let g=await jl(m,a,n,o);d=d.concat(g),o?.(`Iteration ${h}: validating results...`);let E=await Bl(c,d,t);if(b=E.summary,E.approved||E.fixTasks.length===0)break;let v=E.fixTasks.filter(R=>a.has(R.agent)?!0:(o?.(`Warning: fix task "${R.id}" references unknown agent "${R.agent}", skipping`),!1));if(v.length===0)break;m=v,o?.(`Validation requested ${v.length} fix task(s), iterating...`)}let y=[...new Set(d.flatMap(g=>g.execution.modifiedFiles))].sort();return{plan:l,iterations:h,subtaskResults:d,allModifiedFiles:y,summary:b,totalDurationMs:Date.now()-i}}async function As(c,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await gr({cwd:n});if(!i.isRepo)try{await xs({cwd:n}),i=await gr({cwd:n}),r?.("Initialised new git repository")}catch{return o.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await tt(c,e,t,s),git:o}}let a=null,l=await Nt("origin",{cwd:n});if(l){let y=Ct(l);y?(a={owner:y.owner,repo:y.repo},r?.(`Detected remote: ${y.owner}/${y.repo} (${y.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${l}`)}let d=s.forge;if(!l&&d)try{let y=Ot(d),g=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${g}" on forge...`);let E=await y.createProject({name:g,visibility:"private"});await Is("origin",E.cloneUrl,{cwd:n});let v=Ct(E.cloneUrl);v&&(a={owner:v.owner,repo:v.repo}),r?.(`Project created: ${E.url} \u2014 remote "origin" set`)}catch(y){let g=y instanceof Error?y.message:String(y);o.warnings.push(`Project creation failed: ${g}`),r?.(`Warning: project creation failed \u2014 ${g}`)}let m=Fn(c);try{await On(m,{cwd:n}),o.branch=m,r?.(`Created branch: ${m}`)}catch(y){throw new Error(`Failed to create branch "${m}": ${y instanceof Error?y.message:String(y)}`)}let h=await tt(c,e,t,s);try{await Dn({cwd:n});let y=`feat: ${c.slice(0,72)}
555
579
 
556
- Orchestrated by Alfred (${m.iterations} iteration(s), ${m.allModifiedFiles.length} file(s))`,h=await vn(f,{cwd:n});o.commit=h,r?.(`Committed: ${h.sha} (${h.filesChanged} files changed)`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Commit failed: ${h}`),r?.(`Warning: commit failed \u2014 ${h}`),{...m,git:o}}if(!await xt("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...m,git:o};try{await kn("origin",p,{cwd:n}),r?.(`Pushed branch: ${p}`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Push failed: ${h}`),r?.(`Warning: push failed \u2014 ${h}`),{...m,git:o}}if(d&&a)try{let f=At(d),h=s.baseBranch??d.baseBranch??"main",T=s.prTitle??`feat: ${c.slice(0,72)}`,_=["## Summary",m.summary,"",`**Iterations:** ${m.iterations}`,`**Modified files:** ${m.allModifiedFiles.length}`,m.allModifiedFiles.map(k=>`- \`${k}\``).join(`
580
+ Orchestrated by Alfred (${h.iterations} iteration(s), ${h.allModifiedFiles.length} file(s))`,g=await Un(y,{cwd:n});o.commit=g,r?.(`Committed: ${g.sha} (${g.filesChanged} files changed)`)}catch(y){let g=y instanceof Error?y.message:String(y);return o.warnings.push(`Commit failed: ${g}`),r?.(`Warning: commit failed \u2014 ${g}`),{...h,git:o}}if(!await Nt("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...h,git:o};try{await Pn("origin",m,{cwd:n}),r?.(`Pushed branch: ${m}`)}catch(y){let g=y instanceof Error?y.message:String(y);return o.warnings.push(`Push failed: ${g}`),r?.(`Warning: push failed \u2014 ${g}`),{...h,git:o}}if(d&&a)try{let y=Ot(d),g=s.baseBranch??d.baseBranch??"main",E=s.prTitle??`feat: ${c.slice(0,72)}`,v=["## Summary",h.summary,"",`**Iterations:** ${h.iterations}`,`**Modified files:** ${h.allModifiedFiles.length}`,h.allModifiedFiles.map(x=>`- \`${x}\``).join(`
557
581
  `),"","_Automated by Alfred_"].join(`
558
- `),x=await f.createPullRequest(a,{title:T,body:_,head:p,base:h});o.pullRequest=x,r?.(`PR created: ${x.url}`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`PR creation failed: ${h}`),r?.(`Warning: PR creation failed \u2014 ${h}`)}else d||(o.warnings.push("No forge configured \u2014 skipping PR creation"),r?.("No forge configured, skipping PR creation"));return{...m,git:o}}var il,al,cl,ll,dl,ul,pl,Rn,Ln=b(()=>{"use strict";or();Sn();An();il=3,al=5,cl=3,ll=2048,dl=1024,ul=`You are a task planner for a multi-agent coding system.
582
+ `),R=await y.createPullRequest(a,{title:E,body:v,head:m,base:g});o.pullRequest=R,r?.(`PR created: ${R.url}`)}catch(y){let g=y instanceof Error?y.message:String(y);o.warnings.push(`PR creation failed: ${g}`),r?.(`Warning: PR creation failed \u2014 ${g}`)}else d||(o.warnings.push("No forge configured \u2014 skipping PR creation"),r?.("No forge configured, skipping PR creation"));return{...h,git:o}}var Ml,Nl,Cl,Ol,Dl,Ul,Pl,Wn,Xn=w(()=>{"use strict";fr();jn();Hn();Ml=3,Nl=5,Cl=3,Ol=2048,Dl=1024,Ul=`You are a task planner for a multi-agent coding system.
559
583
  You receive a high-level task and a list of available coding agents.
560
584
  Your job is to decompose the task into concrete subtasks, each assigned to an agent.
561
585
 
@@ -571,7 +595,7 @@ Respond with ONLY valid JSON (no markdown fences):
571
595
  "subtasks": [
572
596
  { "id": "task-1", "agent": "<agent-name>", "prompt": "<detailed prompt>", "description": "<short description>" }
573
597
  ]
574
- }`,pl=`You are a code review validator for a multi-agent coding system.
598
+ }`,Pl=`You are a code review validator for a multi-agent coding system.
575
599
  You receive the original task and the results from each subtask execution.
576
600
  Your job is to determine if the task was completed successfully.
577
601
 
@@ -585,9 +609,9 @@ Respond with ONLY valid JSON (no markdown fences):
585
609
  "fixTasks": [
586
610
  { "id": "fix-1", "agent": "<agent-name>", "prompt": "<detailed fix prompt>", "description": "<short description>" }
587
611
  ]
588
- }`;u(Xi,"truncate");u(Hi,"parseJSON");Rn=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(ml,"planSubtasks");u(hl,"executeSubtasksParallel");u(fl,"validateResults");u(Ye,"orchestrate");u(bs,"orchestrateWithGit")});var Ts,Vi=b(()=>{"use strict";D();or();Ln();Ts=class extends ${static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
612
+ }`;u(ua,"truncate");u(ma,"parseJSON");Wn=class{static{u(this,"Semaphore")}max;queue=[];active=0;constructor(e){this.max=e}async acquire(){if(this.active<this.max){this.active++;return}return new Promise(e=>{this.queue.push(()=>{this.active++,e()})})}release(){this.active--;let e=this.queue.shift();e&&e()}};u(Fl,"planSubtasks");u(jl,"executeSubtasksParallel");u(Bl,"validateResults");u(tt,"orchestrate");u(As,"orchestrateWithGit")});var Rs,pa=w(()=>{"use strict";P();fr();Xn();Rs=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
589
613
  `);return{success:!0,data:{agents:e},display:`Available code agents:
590
- ${t}`}}async runAgent(e,t){let s=e.agent,r=e.prompt;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "agent"'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "prompt"'};let n=this.agents.get(s);if(!n){let d=[...this.agents.keys()].join(", ");return{success:!1,error:`Unknown agent "${s}". Available: ${d}`}}let o=typeof e.cwd=="string"?e.cwd:void 0,i=typeof e.timeout=="number"?e.timeout:void 0,a=await gs(n,r,{cwd:o,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
614
+ ${t}`}}async runAgent(e,t){let s=e.agent,r=e.prompt;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "agent"'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "prompt"'};let n=this.agents.get(s);if(!n){let d=[...this.agents.keys()].join(", ");return{success:!1,error:`Unknown agent "${s}". Available: ${d}`}}let o=typeof e.cwd=="string"?e.cwd:void 0,i=typeof e.timeout=="number"?e.timeout:void 0,a=await Ss(n,r,{cwd:o,timeoutMs:i,onProgress:t.onProgress}),l=[];return a.stdout&&l.push(`**stdout:**
591
615
  \`\`\`
592
616
  ${a.stdout}
593
617
  \`\`\``),a.stderr&&l.push(`**stderr:**
@@ -597,7 +621,7 @@ ${a.stderr}
597
621
  ${a.modifiedFiles.map(d=>`- ${d}`).join(`
598
622
  `)}`),{success:a.exitCode===0,data:{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode,durationMs:a.durationMs,modifiedFiles:a.modifiedFiles},display:l.join(`
599
623
 
600
- `),...a.exitCode!==0&&{error:a.exitCode===124?`Agent "${s}" timed out`:`Agent "${s}" exited with code ${a.exitCode}`}}}async orchestrateTask(e,t){if(!this.llm)return{success:!1,error:"Orchestration requires an LLM provider but none was configured."};let s=e.task;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task" for orchestrate action.'};let r=[...this.agents.values()],n=e.agents;if(Array.isArray(n)&&n.length>0&&(r=n.map(d=>this.agents.get(d)).filter(d=>d!==void 0),r.length===0))return{success:!1,error:`None of the specified agents exist. Available: ${[...this.agents.keys()].join(", ")}`};let o=typeof e.maxIterations=="number"?e.maxIterations:void 0,i=e.git===!0,a=typeof e.prTitle=="string"?e.prTitle:void 0,l=typeof e.baseBranch=="string"?e.baseBranch:void 0;try{if(i){let p=await bs(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(p)}let d=await Ye(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress});return this.formatOrchestrationResult(d)}catch(d){return{success:!1,error:`Orchestration failed: ${d instanceof Error?d.message:String(d)}`}}}formatOrchestrationResult(e){let t=[];t.push(`**Orchestration completed in ${e.iterations} iteration(s)**`),t.push(`**Plan:** ${e.plan.reasoning}`),t.push(`**Duration:** ${(e.totalDurationMs/1e3).toFixed(1)}s`);for(let r of e.subtaskResults){let n=r.execution.exitCode===0?"OK":`FAIL (exit ${r.execution.exitCode})`;t.push(`- **${r.subtask.id}** [${r.subtask.agent}]: ${r.subtask.description} \u2014 ${n}`)}return e.allModifiedFiles.length>0&&t.push(`
624
+ `),...a.exitCode!==0&&{error:a.exitCode===124?`Agent "${s}" timed out`:`Agent "${s}" exited with code ${a.exitCode}`}}}async orchestrateTask(e,t){if(!this.llm)return{success:!1,error:"Orchestration requires an LLM provider but none was configured."};let s=e.task;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task" for orchestrate action.'};let r=[...this.agents.values()],n=e.agents;if(Array.isArray(n)&&n.length>0&&(r=n.map(d=>this.agents.get(d)).filter(d=>d!==void 0),r.length===0))return{success:!1,error:`None of the specified agents exist. Available: ${[...this.agents.keys()].join(", ")}`};let o=typeof e.maxIterations=="number"?e.maxIterations:void 0,i=e.git===!0,a=typeof e.prTitle=="string"?e.prTitle:void 0,l=typeof e.baseBranch=="string"?e.baseBranch:void 0;try{if(i){let m=await As(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress,forge:this.forgeConfig,prTitle:a,baseBranch:l});return this.formatGitOrchestrationResult(m)}let d=await tt(s,r,this.llm,{maxIterations:o,onProgress:t.onProgress});return this.formatOrchestrationResult(d)}catch(d){return{success:!1,error:`Orchestration failed: ${d instanceof Error?d.message:String(d)}`}}}formatOrchestrationResult(e){let t=[];t.push(`**Orchestration completed in ${e.iterations} iteration(s)**`),t.push(`**Plan:** ${e.plan.reasoning}`),t.push(`**Duration:** ${(e.totalDurationMs/1e3).toFixed(1)}s`);for(let r of e.subtaskResults){let n=r.execution.exitCode===0?"OK":`FAIL (exit ${r.execution.exitCode})`;t.push(`- **${r.subtask.id}** [${r.subtask.agent}]: ${r.subtask.description} \u2014 ${n}`)}return e.allModifiedFiles.length>0&&t.push(`
601
625
  **Modified files:**
602
626
  ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
603
627
  `)}`),e.summary&&t.push(`
@@ -606,35 +630,35 @@ ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
606
630
 
607
631
  **Git:**
608
632
  ${s.join(`
609
- `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var zi=b(()=>{"use strict";Vi();or();Ln();Sn();An()});var Ee={};le(Ee,{ActivityTracker:()=>Xe,BackgroundTaskSkill:()=>Tt,BrowserSkill:()=>yt,CalculatorSkill:()=>st,CalendarProvider:()=>me,CalendarSkill:()=>He,ClipboardSkill:()=>ft,CodeAgentSkill:()=>Ts,CodeExecutionSkill:()=>hs,CodeExecutor:()=>Ke,ConfigureSkill:()=>St,CrossPlatformSkill:()=>bt,DelegateSkill:()=>dt,DocumentSkill:()=>vt,EmailSkill:()=>ut,FileSkill:()=>mt,ForgeClient:()=>Ge,HttpSkill:()=>pt,MCPClient:()=>Ve,MCPManager:()=>ms,MCPSkillAdapter:()=>ze,MemorySkill:()=>lt,NoteSkill:()=>it,PluginLoader:()=>Js,ProfileSkill:()=>wt,ProxmoxSkill:()=>sr,ReminderSkill:()=>ot,ScheduledTaskSkill:()=>Et,ScreenshotSkill:()=>gt,ShellSkill:()=>ct,Skill:()=>$,SkillRegistry:()=>et,SkillSandbox:()=>tt,SystemInfoSkill:()=>rt,TTSSkill:()=>kt,UniFiSkill:()=>rr,WeatherSkill:()=>at,WebSearchSkill:()=>nt,createCalendarProvider:()=>ps,createForgeClient:()=>At,gitAddRemote:()=>ws,gitGetRemoteUrl:()=>xt,gitInitRepo:()=>ys,orchestrate:()=>Ye,orchestrateWithGit:()=>bs,parseRemoteUrl:()=>It});var we=b(()=>{"use strict";D();Go();Yo();dn();Jo();Zo();Qo();ei();ti();si();ri();ii();ai();ci();li();ui();mi();hi();gi();wi();bi();$i();Si();xi();Ii();Ri();Mi();Ni();Ci();Oi();Di();Fi();zi()});var Es,Mn=b(()=>{"use strict";Es=class{static{u(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}}});import Ki from"node:fs";import Gi from"node:path";var gl,Yi,yl,Ji,wl,bl,Tl,Zi,_s,Nn=b(()=>{"use strict";cn();gl=15*60*1e3,Yi=50,yl=2,Ji=.85,wl=1e5,bl=2e3,Tl=.1,Zi=3,_s=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 os}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let r=this.users.findOrCreate(e.platform,e.userId,e.userName,e.displayName),n="getMasterUserId"in this.users?this.users.getMasterUserId(r.id):r.id,o;"getLinkedUsers"in this.users&&(o=this.users.getLinkedUsers(n).map(V=>V.platformUserId));let i=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),a=this.conversationManager.getHistory(i.id,200);this.conversationManager.addMessage(i.id,"user",e.text);let l,d=this.isSyntheticLabel(e.text),p=e.attachments?.some(B=>B.type==="audio")??!1,m=d&&!p;if(this.memoryRetriever&&e.text&&!m)try{l=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(B){this.logger.debug({err:B},"Hybrid memory retrieval failed")}if(!l&&this.memoryRepo&&!m)try{let B=[n,...(o??[]).filter(V=>V!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let V=new Set;l=[];for(let q of B)for(let z of await this.embeddingService.semanticSearch(q,e.text,10))V.has(z.key)||(V.add(z.key),l.push(z));for(let q of B)for(let z of this.memoryRepo.getRecentForPrompt(q,5))V.has(z.key)||(V.add(z.key),l.push(z))}else{let V=new Set;l=[];for(let q of B)for(let z of this.memoryRepo.getRecentForPrompt(q,20))V.has(z.key)||(V.add(z.key),l.push(z))}}catch(B){this.logger.debug({err:B},"Memory loading failed")}l&&l.length>0&&(l=this.applyMemoryBudget(l));let g;try{"getProfile"in this.users&&(g=this.users.getProfile(n),g&&!g.displayName&&(g.displayName=r.displayName??r.username))}catch(B){this.logger.debug({err:B},"Profile loading failed")}let f=g?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,h=this.skillRegistry?this.skillRegistry.getAll().map(B=>B.metadata):void 0,T=h?this.promptBuilder.buildTools(h):void 0,_=this.promptBuilder.buildSystemPrompt({memories:l,skills:h,userProfile:g}),x=this.buildActiveAgentStatus();x&&(_+=`
633
+ `)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var ha=w(()=>{"use strict";pa();fr();Xn();jn();Hn()});var be={};oe(be,{ActivityTracker:()=>Ge,BackgroundTaskSkill:()=>St,BrowserSkill:()=>$t,CalculatorSkill:()=>lt,CalendarProvider:()=>ye,CalendarSkill:()=>Ye,ClipboardSkill:()=>Et,CodeAgentSkill:()=>Rs,CodeExecutionSkill:()=>vs,CodeExecutor:()=>Qe,ConfigureSkill:()=>Mt,CrossPlatformSkill:()=>kt,DelegateSkill:()=>yt,DocumentSkill:()=>At,EmailProvider:()=>xe,EmailSkill:()=>Me,FileSkill:()=>bt,ForgeClient:()=>et,HomeAssistantSkill:()=>pr,HttpSkill:()=>wt,MCPClient:()=>Je,MCPManager:()=>$s,MCPSkillAdapter:()=>Ze,MemorySkill:()=>gt,NoteSkill:()=>pt,PluginLoader:()=>rr,ProfileSkill:()=>vt,ProxmoxSkill:()=>ur,ReminderSkill:()=>mt,ScheduledTaskSkill:()=>xt,ScreenshotSkill:()=>_t,ShellSkill:()=>ft,Skill:()=>I,SkillRegistry:()=>at,SkillSandbox:()=>ct,SystemInfoSkill:()=>dt,TTSSkill:()=>Rt,UniFiSkill:()=>mr,WeatherSkill:()=>ht,WebSearchSkill:()=>ut,createCalendarProvider:()=>_s,createEmailProvider:()=>bs,createForgeClient:()=>Ot,gitAddRemote:()=>Is,gitGetRemoteUrl:()=>Nt,gitInitRepo:()=>xs,orchestrate:()=>tt,orchestrateWithGit:()=>As,parseRemoteUrl:()=>Ct});var pe=w(()=>{"use strict";P();ui();mi();_n();pi();hi();fi();gi();yi();wi();bi();_i();$i();vi();Ii();Ri();Mi();Ni();Oi();Ui();Pi();Wi();Xi();zi();Vi();Gi();Ji();Zi();Qi();ea();ta();ra();ia();ha()});var Ls,zn=w(()=>{"use strict";Ls=class{static{u(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}}});import fa from"node:fs";import ga from"node:path";var ql,ya,Hl,wa,Wl,Xl,zl,ba,Ms,Vn=w(()=>{"use strict";Tn();ql=15*60*1e3,ya=50,Hl=2,wa=.85,Wl=1e5,Xl=2e3,zl=.1,ba=3,Ms=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;activeAgents=new Map;agentIdCounter=0;constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.promptBuilder=new hs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let r=this.users.findOrCreate(e.platform,e.userId,e.userName,e.displayName),n="getMasterUserId"in this.users?this.users.getMasterUserId(r.id):r.id,o;"getLinkedUsers"in this.users&&(o=this.users.getLinkedUsers(n).map(V=>V.platformUserId));let i=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),a=this.conversationManager.getHistory(i.id,200);this.conversationManager.addMessage(i.id,"user",e.text);let l,d=this.isSyntheticLabel(e.text),m=e.attachments?.some(F=>F.type==="audio")??!1,h=d&&!m;if(this.memoryRetriever&&e.text&&!h)try{l=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(F){this.logger.debug({err:F},"Hybrid memory retrieval failed")}if(!l&&this.memoryRepo&&!h)try{let F=[n,...(o??[]).filter(V=>V!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let V=new Set;l=[];for(let H of F)for(let K of await this.embeddingService.semanticSearch(H,e.text,10))V.has(K.key)||(V.add(K.key),l.push(K));for(let H of F)for(let K of this.memoryRepo.getRecentForPrompt(H,5))V.has(K.key)||(V.add(K.key),l.push(K))}else{let V=new Set;l=[];for(let H of F)for(let K of this.memoryRepo.getRecentForPrompt(H,20))V.has(K.key)||(V.add(K.key),l.push(K))}}catch(F){this.logger.debug({err:F},"Memory loading failed")}l&&l.length>0&&(l=this.applyMemoryBudget(l));let b;try{"getProfile"in this.users&&(b=this.users.getProfile(n),b&&!b.displayName&&(b.displayName=r.displayName??r.username))}catch(F){this.logger.debug({err:F},"Profile loading failed")}let y=b?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,g=this.skillRegistry?this.skillRegistry.getAll().map(F=>F.metadata):void 0,E=g?this.promptBuilder.buildTools(g):void 0,v=this.promptBuilder.buildSystemPrompt({memories:l,skills:g,userProfile:b}),R=this.buildActiveAgentStatus();R&&(v+=`
610
634
 
611
- `+x);let k=this.promptBuilder.buildMessages(a),C=this.collapseRepeatedToolErrors(k),M=await this.buildUserContent(e,t);C.push({role:"user",content:M});let P=this.trimToContextWindow(_,C),j,ne=0,Ne=Date.now(),ue="",K=0,te=[];for(t?.("Thinking...");ne>0&&this.compressToolLoop(P,_),j=await this.llm.complete({messages:P,system:_,tools:T&&T.length>0?T:void 0}),!(!j.toolCalls||j.toolCalls.length===0);){let B=Date.now()-Ne;if(B>=gl){let Te=Math.round(B/6e4);this.logger.warn({iteration:ne,elapsedMin:Te,pendingToolCalls:j.toolCalls.length},"Tool loop timeout reached"),j=await this.abortToolLoop(P,j,i.id,_,`Das Zeitlimit von ${Te} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(ne>=Yi){this.logger.warn({iteration:ne,pendingToolCalls:j.toolCalls.length},"Tool loop iteration cap reached"),j=await this.abortToolLoop(P,j,i.id,_,`Das Iterationslimit von ${Yi} Tool-Aufrufen wurde erreicht.`);break}ne++,this.logger.info({iteration:ne,toolCalls:j.toolCalls.length},"Processing tool calls");let V=[];j.content&&V.push({type:"text",text:j.content});for(let Te of j.toolCalls)V.push({type:"tool_use",id:Te.id,name:Te.name,input:Te.input});P.push({role:"assistant",content:V});let q=await this.executeToolCallsParallel(j.toolCalls,{userId:e.userId,masterUserId:n,linkedPlatformUserIds:o,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:f},t),z=q.blocks;q.attachments.length>0&&te.push(...q.attachments),this.conversationManager.addMessage(i.id,"assistant",j.content??"",JSON.stringify(j.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(z));let oe=this.buildErrorSignature(z);if(oe){if(oe===ue?K++:(K=1,ue=oe),K>=yl){this.logger.warn({iteration:ne,consecutiveErrors:K,errorSignature:oe},"Tool loop aborted: same error repeated consecutively"),j=await this.abortToolLoop(P,j,i.id,_,`Der gleiche Tool-Fehler ist ${K}x hintereinander aufgetreten: "${ue.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else K=0,ue="";P.push({role:"user",content:z}),t?.("Thinking...")}let L=j.content;if(!L)for(let B=P.length-1;B>=0;B--){let V=P[B];if(V.role==="assistant"&&Array.isArray(V.content)){let q=V.content.find(z=>z.type==="text");if(q&&"text"in q&&q.text){L=q.text;break}}}L||(L="(no response)"),this.conversationManager.addMessage(i.id,"assistant",L),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,L);let Z=Date.now()-s;return this.logger.info({duration:Z,tokens:j.usage,stopReason:j.stopReason,toolIterations:ne},"Message processed"),{text:L,attachments:te.length>0?te:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let a=[];t.content&&a.push({type:"text",text:t.content});for(let l of t.toolCalls)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));return e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i)),e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r})}buildErrorSignature(e){let t=[];for(let s of e)s.type==="tool_result"&&s.is_error&&t.push(s.content);return t.length>0?t.join("|"):""}collapseRepeatedToolErrors(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=s+1<e.length?e[s+1]:null;if(n&&n.role==="user"&&Array.isArray(n.content)&&n.content.every(o=>o.type==="tool_result"&&o.is_error)){let o=this.toolPairSignature(r,n),i=1,a=s+2;for(;a+1<e.length;){let l=e[a],d=e[a+1];if(l.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(l,d)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"assistant",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=u((a,l)=>{let d=l.content;if(l.attachments&&l.attachments.length>0){r.push(...l.attachments);let p=l.attachments.map(m=>m.fileName).join(", ");d+=`
635
+ `+R);let x=this.promptBuilder.buildMessages(a),O=this.collapseRepeatedToolErrors(x),N=await this.buildUserContent(e,t);O.push({role:"user",content:N});let B=this.trimToContextWindow(v,O),q,ae=0,Pe=Date.now(),he="",Y=0,re=[];for(t?.("Thinking...");ae>0&&this.compressToolLoop(B,v),q=await this.llm.complete({messages:B,system:v,tools:E&&E.length>0?E:void 0}),!(!q.toolCalls||q.toolCalls.length===0);){let F=Date.now()-Pe;if(F>=ql){let ke=Math.round(F/6e4);this.logger.warn({iteration:ae,elapsedMin:ke,pendingToolCalls:q.toolCalls.length},"Tool loop timeout reached"),q=await this.abortToolLoop(B,q,i.id,v,`Das Zeitlimit von ${ke} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(ae>=ya){this.logger.warn({iteration:ae,pendingToolCalls:q.toolCalls.length},"Tool loop iteration cap reached"),q=await this.abortToolLoop(B,q,i.id,v,`Das Iterationslimit von ${ya} Tool-Aufrufen wurde erreicht.`);break}ae++,this.logger.info({iteration:ae,toolCalls:q.toolCalls.length},"Processing tool calls");let V=[];q.content&&V.push({type:"text",text:q.content});for(let ke of q.toolCalls)V.push({type:"tool_use",id:ke.id,name:ke.name,input:ke.input});B.push({role:"assistant",content:V});let H=await this.executeToolCallsParallel(q.toolCalls,{userId:e.userId,masterUserId:n,linkedPlatformUserIds:o,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:y},t),K=H.blocks;H.attachments.length>0&&re.push(...H.attachments),this.conversationManager.addMessage(i.id,"assistant",q.content??"",JSON.stringify(q.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(K));let ce=this.buildErrorSignature(K);if(ce){if(ce===he?Y++:(Y=1,he=ce),Y>=Hl){this.logger.warn({iteration:ae,consecutiveErrors:Y,errorSignature:ce},"Tool loop aborted: same error repeated consecutively"),q=await this.abortToolLoop(B,q,i.id,v,`Der gleiche Tool-Fehler ist ${Y}x hintereinander aufgetreten: "${he.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else Y=0,he="";B.push({role:"user",content:K}),t?.("Thinking...")}let L=q.content;if(!L)for(let F=B.length-1;F>=0;F--){let V=B[F];if(V.role==="assistant"&&Array.isArray(V.content)){let H=V.content.find(K=>K.type==="text");if(H&&"text"in H&&H.text){L=H.text;break}}}L||(L="(no response)"),this.conversationManager.addMessage(i.id,"assistant",L),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,L);let W=Date.now()-s;return this.logger.info({duration:W,tokens:q.usage,stopReason:q.stopReason,toolIterations:ae},"Message processed"),{text:L,attachments:re.length>0?re:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let a=[];t.content&&a.push({type:"text",text:t.content});for(let l of t.toolCalls)a.push({type:"tool_use",id:l.id,name:l.name,input:l.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));return e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i)),e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r})}buildErrorSignature(e){let t=[];for(let s of e)s.type==="tool_result"&&s.is_error&&t.push(s.content);return t.length>0?t.join("|"):""}collapseRepeatedToolErrors(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=s+1<e.length?e[s+1]:null;if(n&&n.role==="user"&&Array.isArray(n.content)&&n.content.every(o=>o.type==="tool_result"&&o.is_error)){let o=this.toolPairSignature(r,n),i=1,a=s+2;for(;a+1<e.length;){let l=e[a],d=e[a+1];if(l.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(l,d)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"assistant",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=u((a,l)=>{let d=l.content;if(l.attachments&&l.attachments.length>0){r.push(...l.attachments);let m=l.attachments.map(h=>h.fileName).join(", ");d+=`
612
636
 
613
- [${l.attachments.length} Datei(en) werden dem User gesendet: ${p}]`}return{type:"tool_result",tool_use_id:a.id,content:d,is_error:l.isError}},"buildBlock");if(e.length===1){let a=e[0],l=this.getToolLabel(a.name,a.input);s?.(l);let d=await this.executeToolCall(a,t,s);return{blocks:[n(a,d)],attachments:r}}s?.(`Running ${e.length} tools in parallel...`);let o=await Promise.allSettled(e.map(a=>this.executeToolCall(a,t,s)));return{blocks:e.map((a,l)=>{let d=o[l];return d.status==="fulfilled"?n(a,d.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${d.reason}`,is_error:!0}}),attachments:r}}async executeToolCall(e,t,s){let r=this.skillRegistry?.get(e.name);if(!r)return this.logger.warn({tool:e.name},"Unknown skill requested"),{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let n=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!n.allowed)return this.logger.warn({tool:e.name,reason:n.reason,rule:n.matchedRule?.id},"Skill execution denied by security rules"),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(we(),Ee));n=new a(s),o=`agent-${++this.agentIdCounter}`,this.activeAgents.set(o,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:n,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:n,onProgress:s}:s?{...t,onProgress:s}:t;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,n);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){return{content:`Skill execution failed: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),n=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${n}s | Last activity ${Math.round(r.idleMs/1e3)}s ago`)}return e.push(""),e.push("If the user asks what you or the agent is doing, describe the above status in natural language."),e.join(`
614
- `)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=Tl));let r=0,n=[];for(let o of s){let i=ye(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>bl)break;r+=i,n.push(o)}return n.length<e.length&&this.logger.info({original:e.length,kept:n.length,tokenCount:r,droppedByScore:e.length-s.length},"Memory budget applied"),n}compressToolLoop(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*Ji);if(ye(t)+e.reduce((f,h)=>f+is(h),0)<=r)return;let i=[];for(let f=0;f<e.length-1;f++){let h=e[f],T=e[f+1];h.role==="assistant"&&Array.isArray(h.content)&&h.content.some(_=>_.type==="tool_use")&&T.role==="user"&&Array.isArray(T.content)&&T.content.some(_=>_.type==="tool_result")&&i.push({start:f,end:f+1})}if(i.length<=Zi)return;let a=i.length-Zi,l=i.slice(0,a),d=[];for(let f of l){let h=e[f.start],T=[];if(Array.isArray(h.content))for(let k of h.content)k.type==="tool_use"&&T.push(k.name);let _=e[f.end],x="ok";Array.isArray(_.content)&&_.content.some(C=>C.type==="tool_result"&&C.is_error)&&(x="error"),d.push(`- ${T.join(", ")}: ${x}`)}let p=l[0].start,g=l[l.length-1].end-p+1;e.splice(p,g,{role:"assistant",content:`[Earlier tool interactions compressed (${l.length} pairs):
637
+ [${l.attachments.length} Datei(en) werden dem User gesendet: ${m}]`}return{type:"tool_result",tool_use_id:a.id,content:d,is_error:l.isError}},"buildBlock");if(e.length===1){let a=e[0],l=this.getToolLabel(a.name,a.input);s?.(l);let d=await this.executeToolCall(a,t,s);return{blocks:[n(a,d)],attachments:r}}s?.(`Running ${e.length} tools in parallel...`);let o=await Promise.allSettled(e.map(a=>this.executeToolCall(a,t,s)));return{blocks:e.map((a,l)=>{let d=o[l];return d.status==="fulfilled"?n(a,d.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${d.reason}`,is_error:!0}}),attachments:r}}async executeToolCall(e,t,s){let r=this.skillRegistry?.get(e.name);if(!r)return this.logger.warn({tool:e.name},"Unknown skill requested"),{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let n=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!n.allowed)return this.logger.warn({tool:e.name,reason:n.reason,rule:n.matchedRule?.id},"Skill execution denied by security rules"),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(pe(),be));n=new a(s),o=`agent-${++this.agentIdCounter}`,this.activeAgents.set(o,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:n,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:n,onProgress:s}:s?{...t,onProgress:s}:t;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,n);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){return{content:`Skill execution failed: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),n=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${n}s | Last activity ${Math.round(r.idleMs/1e3)}s ago`)}return e.push(""),e.push("If the user asks what you or the agent is doing, describe the above status in natural language."),e.join(`
638
+ `)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=zl));let r=0,n=[];for(let o of s){let i=ve(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>Xl)break;r+=i,n.push(o)}return n.length<e.length&&this.logger.info({original:e.length,kept:n.length,tokenCount:r,droppedByScore:e.length-s.length},"Memory budget applied"),n}compressToolLoop(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*wa);if(ve(t)+e.reduce((y,g)=>y+fs(g),0)<=r)return;let i=[];for(let y=0;y<e.length-1;y++){let g=e[y],E=e[y+1];g.role==="assistant"&&Array.isArray(g.content)&&g.content.some(v=>v.type==="tool_use")&&E.role==="user"&&Array.isArray(E.content)&&E.content.some(v=>v.type==="tool_result")&&i.push({start:y,end:y+1})}if(i.length<=ba)return;let a=i.length-ba,l=i.slice(0,a),d=[];for(let y of l){let g=e[y.start],E=[];if(Array.isArray(g.content))for(let x of g.content)x.type==="tool_use"&&E.push(x.name);let v=e[y.end],R="ok";Array.isArray(v.content)&&v.content.some(O=>O.type==="tool_result"&&O.is_error)&&(R="error"),d.push(`- ${E.join(", ")}: ${R}`)}let m=l[0].start,b=l[l.length-1].end-m+1;e.splice(m,b,{role:"assistant",content:`[Earlier tool interactions compressed (${l.length} pairs):
615
639
  ${d.join(`
616
640
  `)}
617
- ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:l.length,removedMessages:g-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*Ji),n=ye(e),o=t[t.length-1],i=is(o),l=n+i+200+500,d=r-l;if(d<=0)return this.logger.warn({maxInputTokens:r,systemTokens:n,latestTokens:i},"Context window very tight, sending only latest message"),[o];let p=t.slice(0,-1),m=this.groupToolPairs(p),g=[];for(let T=m.length-1;T>=0;T--){let _=m[T].reduce((x,k)=>x+is(k),0);_>d||(d-=_,g.unshift(m[T]))}let f=g.flat(),h=p.length-f.length;if(h>0){this.logger.info({trimmedCount:h,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let T=p.slice(0,p.length-f.length),_=this.summarizeTrimmedMessages(T);f.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${h} messages were trimmed to fit the context window:
618
- ${_}
641
+ ]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:l.length,removedMessages:b-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*wa),n=ve(e),o=t[t.length-1],i=fs(o),l=n+i+200+500,d=r-l;if(d<=0)return this.logger.warn({maxInputTokens:r,systemTokens:n,latestTokens:i},"Context window very tight, sending only latest message"),[o];let m=t.slice(0,-1),h=this.groupToolPairs(m),b=[];for(let E=h.length-1;E>=0;E--){let v=h[E].reduce((R,x)=>R+fs(x),0);v>d||(d-=v,b.unshift(h[E]))}let y=b.flat(),g=m.length-y.length;if(g>0){this.logger.info({trimmedCount:g,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let E=m.slice(0,m.length-y.length),v=this.summarizeTrimmedMessages(E);y.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${g} messages were trimmed to fit the context window:
642
+ ${v}
619
643
 
620
- The conversation continues below with the most recent messages.]`})}return f.push(o),this.promptBuilder.sanitizeToolMessages(f)}summarizeTrimmedMessages(e){let t=[];for(let r of e){let n=this.extractMessageText(r);if(!n)continue;let o=n.length>150?n.slice(0,150)+"...":n,i=r.role==="user"?"User":"Assistant";if(t.push(`- ${i}: ${o}`),r.role==="assistant"&&Array.isArray(r.content)){for(let a of r.content)if(a.type==="tool_use"){let l=JSON.stringify(a.input).slice(0,80);t.push(` \u2192 Tool: ${a.name}(${l})`)}}}let s=40;if(t.length>s){let r=t.slice(0,s);return r.push(` ... and ${t.length-s} more interactions`),r.join(`
644
+ The conversation continues below with the most recent messages.]`})}return y.push(o),this.promptBuilder.sanitizeToolMessages(y)}summarizeTrimmedMessages(e){let t=[];for(let r of e){let n=this.extractMessageText(r);if(!n)continue;let o=n.length>150?n.slice(0,150)+"...":n,i=r.role==="user"?"User":"Assistant";if(t.push(`- ${i}: ${o}`),r.role==="assistant"&&Array.isArray(r.content)){for(let a of r.content)if(a.type==="tool_use"){let l=JSON.stringify(a.input).slice(0,80);t.push(` \u2192 Tool: ${a.name}(${l})`)}}}let s=40;if(t.length>s){let r=t.slice(0,s);return r.push(` ... and ${t.length-s} more interactions`),r.join(`
621
645
  `)}return t.join(`
622
646
  `)}extractMessageText(e){if(typeof e.content=="string")return e.content;if(!Array.isArray(e.content))return"";let t=[];for(let s of e.content)s.type==="text"&&s.text&&t.push(s.text);return t.join(" ")}groupToolPairs(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=[r];if(s+1<e.length&&e[s+1].role==="user"){let o=e[s+1];if(Array.isArray(o.content)&&o.content.some(i=>i.type==="tool_result")){n.push(o),s+=2,t.push(n);continue}}if(n.length===1&&s+1<e.length&&e[s+1].role==="user"){n.push(e[s+1]),s+=2,t.push(n);continue}t.push(n),s++}else t.push([r]),s++}return t}async buildUserContent(e,t){let s=e.attachments?.filter(i=>i.data)??[];if(s.length===0)return e.text;let r=[];for(let i of s)if(i.type==="image"&&i.data)r.push({type:"image",source:{type:"base64",media_type:i.mimeType??"image/jpeg",data:i.data.toString("base64")}}),this.logger.info({mimeType:i.mimeType,size:i.size},"Image attached to LLM request");else if(i.type==="audio"&&i.data)if(this.speechTranscriber){t?.("Transcribing voice...");try{let a=await this.speechTranscriber.transcribe(i.data,i.mimeType??"audio/ogg"),l=e.text==="[Voice message]"?"":`${e.text}
623
647
 
624
648
  `;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"})]
625
- [Saved to: ${a}]`;if(l&&i.data.length<=wl){let p=i.data.toString("utf-8");d+=`
649
+ [Saved to: ${a}]`;if(l&&i.data.length<=Wl){let m=i.data.toString("utf-8");d+=`
626
650
  [File content]:
627
- ${p}`}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");return r.some(i=>i.type==="image")&&!o?r.push({type:"text",text:"What do you see in this image?"}):n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??Gi.resolve("./data/inbox");try{Ki.mkdirSync(t,{recursive:!0})}catch{this.logger.error({inboxDir:t},"Cannot create inbox directory");return}let s=new Date().toISOString().replace(/[:.]/g,"-"),n=(e.fileName??`file_${s}`).replace(/[<>:"/\\|?*]/g,"_"),o=`${s}_${n}`,i=Gi.join(t,o);try{return Ki.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var vs,Cn=b(()=>{"use strict";vs=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,n){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=n,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{let s=`\u23F0 Reminder: ${t.message}`;if(await this.sendMessage(t.platform,t.chatId,s),this.linkedUsers)try{let r=this.linkedUsers.getMasterUserId(t.userId),n=this.linkedUsers.getLinkedUsers(r);for(let o of n){if(o.platform===t.platform)continue;let i=this.linkedUsers.findConversation(o.platform,o.id);i&&await this.sendMessage(o.platform,i.chatId,s)}}catch(r){this.logger.debug({err:r,reminderId:t.id},"Cross-platform reminder delivery failed")}this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var ks,On=b(()=>{"use strict";ks=class{static{u(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var $s,Dn=b(()=>{"use strict";$s=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 Ss,Un=b(()=>{"use strict";Ss=class{static{u(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t=t.replace(/<(?!\/?(?:b|i|s|u|a|pre|code|tg-spoiler|tg-emoji|blockquote)(?:[\s>\/]|$))/gi,"&lt;"),t}toMatrixHTML(e){return this.toTelegramHTML(e)}toWhatsApp(e){let t=e;return t=t.replace(/\*\*(.+?)\*\*/g,"*$1*"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"_$1_"),t=t.replace(/~~(.+?)~~/g,"~$1~"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}stripFormatting(e){let t=e;return t=t.replace(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),t=t.replace(/\*\*(.+?)\*\*/g,"$1"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"$1"),t=t.replace(/~~(.+?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}escapeHTML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}});var xs,Pn=b(()=>{"use strict";xs=class{static{u(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let l=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:l}});return o.sort((a,l)=>l.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var Is,Fn=b(()=>{"use strict";Is=class{static{u(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),l=this.chunkText(n,500,50);for(let d=0;d<l.length;d++){let p;try{await this.embeddingService.embedAndStore(e,l[d],"document",`${a.id}:${d}`),p=`${a.id}:${d}`}catch(m){this.logger.warn({documentId:a.id,chunkIndex:d,err:m},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,d,l[d],p)}return this.docRepo.updateChunkCount(a.id,l.length),this.logger.info({documentId:a.id,filename:s,chunkCount:l.length},"Document ingested"),{documentId:a.id,chunkCount:l.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let l=a+n;if(l>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(l-200,a),p=e.slice(d,l+200),m=p.lastIndexOf(`
651
+ ${m}`}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");return r.some(i=>i.type==="image")&&!o?r.push({type:"text",text:"What do you see in this image?"}):n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??ga.resolve("./data/inbox");try{fa.mkdirSync(t,{recursive:!0})}catch{this.logger.error({inboxDir:t},"Cannot create inbox directory");return}let s=new Date().toISOString().replace(/[:.]/g,"-"),n=(e.fileName??`file_${s}`).replace(/[<>:"/\\|?*]/g,"_"),o=`${s}_${n}`,i=ga.join(t,o);try{return fa.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Ns,Kn=w(()=>{"use strict";Ns=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,n){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=n,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{let s=`\u23F0 Reminder: ${t.message}`;if(await this.sendMessage(t.platform,t.chatId,s),this.linkedUsers)try{let r=this.linkedUsers.getMasterUserId(t.userId),n=this.linkedUsers.getLinkedUsers(r);for(let o of n){if(o.platform===t.platform)continue;let i=this.linkedUsers.findConversation(o.platform,o.id);i&&await this.sendMessage(o.platform,i.chatId,s)}}catch(r){this.logger.debug({err:r,reminderId:t.id},"Cross-platform reminder delivery failed")}this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var Cs,Gn=w(()=>{"use strict";Cs=class{static{u(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var Os,Yn=w(()=>{"use strict";Os=class{static{u(this,"SpeechSynthesizer")}logger;apiKey;baseUrl;model;voice;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,this.baseUrl=e.baseUrl??"https://api.openai.com/v1",this.model=e.ttsModel??"tts-1",this.voice=e.ttsVoice??"alloy"}async synthesize(e){this.logger.info({textLength:e.length,model:this.model,voice:this.voice},"Synthesizing speech");let t=await fetch(`${this.baseUrl}/audio/speech`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:this.model,input:e,voice:this.voice,response_format:"opus"})});if(!t.ok){let r=await t.text();throw new Error(`TTS failed: ${t.status} ${r}`)}let s=Buffer.from(await t.arrayBuffer());return this.logger.info({audioBytes:s.length},"Speech synthesized"),s}}});var Ds,Jn=w(()=>{"use strict";Ds=class{static{u(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t=t.replace(/<(?!\/?(?:b|i|s|u|a|pre|code|tg-spoiler|tg-emoji|blockquote)(?:[\s>\/]|$))/gi,"&lt;"),t}toMatrixHTML(e){return this.toTelegramHTML(e)}toWhatsApp(e){let t=e;return t=t.replace(/\*\*(.+?)\*\*/g,"*$1*"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"_$1_"),t=t.replace(/~~(.+?)~~/g,"~$1~"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}stripFormatting(e){let t=e;return t=t.replace(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),t=t.replace(/\*\*(.+?)\*\*/g,"$1"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"$1"),t=t.replace(/~~(.+?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}escapeHTML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}});var Us,Zn=w(()=>{"use strict";Us=class{static{u(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let l=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:l}});return o.sort((a,l)=>l.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var Ps,Qn=w(()=>{"use strict";Ps=class{static{u(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),l=this.chunkText(n,500,50);for(let d=0;d<l.length;d++){let m;try{await this.embeddingService.embedAndStore(e,l[d],"document",`${a.id}:${d}`),m=`${a.id}:${d}`}catch(h){this.logger.warn({documentId:a.id,chunkIndex:d,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,d,l[d],m)}return this.docRepo.updateChunkCount(a.id,l.length),this.logger.info({documentId:a.id,filename:s,chunkCount:l.length},"Document ingested"),{documentId:a.id,chunkCount:l.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let l=a+n;if(l>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(l-200,a),m=e.slice(d,l+200),h=m.lastIndexOf(`
628
652
 
629
- `);if(m>0)l=d+m;else{let f=p.lastIndexOf(". ");f>0&&(l=d+f+1)}let g=e.slice(a,l).trim();g&&i.push(g),a=l-o}return i.filter(l=>l.length>0)}}});var As,jn=b(()=>{"use strict";As=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.logger=n}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.getPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(l){this.logger.warn({taskId:e.id,err:l},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let r={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},n=new Promise((l,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let l=o.success?`\u2705 Background task completed: ${e.description}
653
+ `);if(h>0)l=d+h;else{let y=m.lastIndexOf(". ");y>0&&(l=d+y+1)}let b=e.slice(a,l).trim();b&&i.push(b),a=l-o}return i.filter(l=>l.length>0)}}});var Fs,eo=w(()=>{"use strict";Fs=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.logger=n}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.getPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(l){this.logger.warn({taskId:e.id,err:l},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let r={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},n=new Promise((l,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let l=o.success?`\u2705 Background task completed: ${e.description}
630
654
 
631
655
  Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${e.description}
632
656
 
633
657
  Error: ${o.error}`;await a.sendMessage(e.chatId,l)}}catch(t){let s=t instanceof Error?t.message:String(t);this.taskRepo.updateStatus(e.id,"failed",void 0,s),this.logger.error({taskId:e.id,err:t},"Background task failed");let r=this.adapters.get(e.platform);r&&await r.sendMessage(e.chatId,`\u274C Background task failed: ${e.description}
634
658
 
635
- Error: ${s}`)}}}});import El from"node:crypto";var Rs,Bn=b(()=>{"use strict";Rs=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.logger=o,this.pipeline=i,this.formatter=a}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s;if(e.promptTemplate&&this.pipeline)try{let o={id:`scheduled-${El.randomUUID()}`,platform:e.platform,chatId:e.chatId,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},i=await this.pipeline.process(o);s=(this.formatter?this.formatter.format(i.text,e.platform):{text:i.text,parseMode:"text"}).text;let l=this.adapters.get(e.platform);if(l&&i.attachments)for(let d of i.attachments)try{let p=d.mimeType.startsWith("image/"),m=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";p?await l.sendPhoto(e.chatId,d.data,d.fileName):m?await l.sendVoice(e.chatId,d.data):await l.sendFile(e.chatId,d.data,d.fileName)}catch(p){this.logger.warn({err:p,fileName:d.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else{let o=this.skillRegistry.get(e.skillName);if(!o)this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;else try{let i;try{i=JSON.parse(e.skillInput)}catch{i={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let a={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},l=await this.skillSandbox.execute(o,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
659
+ Error: ${s}`)}}}});import Vl from"node:crypto";var js,to=w(()=>{"use strict";js=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;pipeline;formatter;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.logger=o,this.pipeline=i,this.formatter=a}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s;if(e.promptTemplate&&this.pipeline)try{let o={id:`scheduled-${Vl.randomUUID()}`,platform:e.platform,chatId:e.chatId,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date},i=await this.pipeline.process(o);s=(this.formatter?this.formatter.format(i.text,e.platform):{text:i.text,parseMode:"text"}).text;let l=this.adapters.get(e.platform);if(l&&i.attachments)for(let d of i.attachments)try{let m=d.mimeType.startsWith("image/"),h=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await l.sendPhoto(e.chatId,d.data,d.fileName):h?await l.sendVoice(e.chatId,d.data):await l.sendFile(e.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(o){let i=o instanceof Error?o.message:String(o);this.logger.error({actionId:e.id,err:o},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${i}`}else{let o=this.skillRegistry.get(e.skillName);if(!o)this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;else try{let i;try{i=JSON.parse(e.skillInput)}catch{i={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let a={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},l=await this.skillSandbox.execute(o,i,a);s=l.success?`\u{1F514} Scheduled: ${e.name}
636
660
 
637
- ${l.display??JSON.stringify(l.data)}`:`\u274C Scheduled action "${e.name}" failed: ${l.error}`}catch(i){let a=i instanceof Error?i.message:String(i);s=`\u274C Scheduled action "${e.name}" failed: ${a}`}}let r=this.adapters.get(e.platform);if(r)try{await r.sendMessage(e.chatId,s)}catch(o){this.logger.error({err:o,actionId:e.id},"Failed to send scheduled action result")}let n=this.calculateNextRun(e);n?this.actionRepo.updateLastRun(e.id,t,n):(this.actionRepo.updateLastRun(e.id,t,null),this.actionRepo.setEnabled(e.id,!1))}calculateNextRun(e){let t=new Date;switch(e.scheduleType){case"interval":{let s=parseInt(e.scheduleValue,10);return isNaN(s)||s<=0?null:new Date(t.getTime()+s*6e4).toISOString()}case"once":return null;case"cron":return this.getNextCronDate(e.scheduleValue,t)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}}});function qn(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of _l)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of vl)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 _l,vl,Wn=b(()=>{"use strict";_l=[/^(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],vl=[{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(qn,"scanSignal")});var kl,$l,Ls,Xn=b(()=>{"use strict";kl=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],$l=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
661
+ ${l.display??JSON.stringify(l.data)}`:`\u274C Scheduled action "${e.name}" failed: ${l.error}`}catch(i){let a=i instanceof Error?i.message:String(i);s=`\u274C Scheduled action "${e.name}" failed: ${a}`}}let r=this.adapters.get(e.platform);if(r)try{await r.sendMessage(e.chatId,s)}catch(o){this.logger.error({err:o,actionId:e.id},"Failed to send scheduled action result")}let n=this.calculateNextRun(e);n?this.actionRepo.updateLastRun(e.id,t,n):(this.actionRepo.updateLastRun(e.id,t,null),this.actionRepo.setEnabled(e.id,!1))}calculateNextRun(e){let t=new Date;switch(e.scheduleType){case"interval":{let s=parseInt(e.scheduleValue,10);return isNaN(s)||s<=0?null:new Date(t.getTime()+s*6e4).toISOString()}case"once":return null;case"cron":return this.getNextCronDate(e.scheduleValue,t)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}}});function so(c){let e=c.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Kl)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Gl)for(let r of s.patterns)if(r.test(e)){t.push(s.name);break}return t.length>0?{level:"high",matchedPatterns:t}:{level:"low",matchedPatterns:[]}}var Kl,Gl,ro=w(()=>{"use strict";Kl=[/^(what|where|when|who|why|how|which|can you|could you|do you|is there|are there|was |wer |wo |wann |warum |wie |welch|kannst du|könntest du|gibt es)/i,/^(hi|hey|hello|hallo|guten (morgen|tag|abend)|moin|servus|grüß|na\b|yo\b|sup\b|good (morning|evening|night))\b/i,/^(tell me|show me|find|search|help|explain|describe|translate|summarize|zeig|such|hilf|erklär|beschreib|übersetze|fass zusammen)/i,/^(ok|okay|yes|no|ja|nein|danke|thanks|thank you|sure|alright|klar|gut|cool|nice|great|perfect|genau|stimmt|richtig)\b/i],Gl=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];u(so,"scanSignal")});var Yl,Jl,Bs,no=w(()=>{"use strict";Yl=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Jl=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
638
662
 
639
663
  Rules:
640
664
  - Only extract information the user STATES about themselves
@@ -654,61 +678,63 @@ Extract memories from this conversation:
654
678
  User: {USER_MESSAGE}
655
679
  Assistant: {ASSISTANT_RESPONSE}
656
680
 
657
- Return ONLY a valid JSON array, no explanation:`,Ls=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=$l.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),n=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),o=this.parseResponse(n.content);if(o.length===0)return 0;let i=0;for(let a of o)if(!(a.confidence<this.minConfidence))try{let l=this.memoryRepo.saveWithMetadata(e,a.key,a.value,a.category,a.type,a.confidence,"auto");this.embeddingService&&this.embeddingService.embedAndStore(e,`${a.key}: ${a.value}`,"memory",l.id).catch(d=>this.logger.debug({err:d},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(l){this.logger.warn({err:l,key:a.key},"Failed to save extracted memory")}return i}catch(r){return this.logger.error({err:r},"Memory extraction failed"),0}}parseResponse(e){try{let t=e.match(/\[[\s\S]*\]/);if(!t)return[];let s=JSON.parse(t[0]);return Array.isArray(s)?s.filter(r=>typeof r=="object"&&r!==null).map(r=>({key:String(r.key||""),value:String(r.value||""),type:this.validateType(String(r.type||"fact")),confidence:this.clampConfidence(Number(r.confidence)||.5),category:String(r.category||"general")})).filter(r=>r.key&&r.value):[]}catch{return this.logger.debug({content:e.slice(0,200)},"Failed to parse extraction response"),[]}}validateType(e){return kl.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var Ms,Hn=b(()=>{"use strict";Wn();Xn();Ms=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 Ls(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=qn(t);if(r.level==="low"){this.logger.debug({signal:"low"},"Skipping extraction \u2014 low signal");return}if(!this.checkRateLimit(e)){this.logger.debug({userId:e},"Skipping extraction \u2014 rate limit reached");return}this.logger.info({signal:r.level,patterns:r.matchedPatterns},"High signal detected, triggering extraction"),this.extractor.extract(e,t,s).then(n=>{n>0&&this.logger.info({userId:e,extractedCount:n},"Auto-extraction complete")}).catch(n=>{this.logger.error({err:n},"Auto-extraction failed")})}checkRateLimit(e){let t=Date.now(),s=t-6e4,r=this.extractionTimestamps.get(e);r||(r=[],this.extractionTimestamps.set(e,r));let n=r.filter(o=>o>s);return this.extractionTimestamps.set(e,n),n.length>=this.maxExtractionsPerMinute?!1:(n.push(t),!0)}}});var Sl,xl,Il,Al,Ns,Vn=b(()=>{"use strict";Sl=Math.LN2,xl=.3,Il=.7,Al=3,Ns=class{static{u(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let h of n)for(let T of this.memoryRepo.keywordSearch(h,t,30))o.has(T.id)||(o.add(T.id),i.push(T));let a=[],l=!1;if(this.embeddingService)try{let h=new Set;for(let T of n)for(let _ of await this.embeddingService.semanticSearch(T,t,30))h.has(_.key)||(h.add(_.key),a.push(_));l=a.length>0}catch(h){this.logger.debug({err:h},"Semantic search failed, falling back to keyword-only")}let d=new Map,p=i.length;for(let h=0;h<i.length;h++){let T=i[h],_=p>0?1-h/p:0,x=l?xl:1,k=this.applyBoosts(_*x,T);d.set(T.key,{memory:{key:T.key,value:T.value,category:T.category,type:T.type,score:k},score:k}),this.memoryRepo.recordAccess(T.id)}if(l)for(let h of a){let T=h.score*Il,_=d.get(h.key);if(_)_.score+=T,_.memory.score=_.score;else{let x=this.memoryRepo.recall(e,h.key),k=this.applyBoosts(T,x||void 0);d.set(h.key,{memory:{key:h.key,value:h.value,category:h.category,type:x?.type||"general",score:k},score:k}),x&&this.memoryRepo.recordAccess(x.id)}}let m=Array.from(d.values()).sort((h,T)=>T.score-h.score),g=new Map,f=[];for(let{memory:h}of m){let T=g.get(h.type)||0;if(!(T>=Al)&&(g.set(h.type,T+1),f.push(h),f.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:f.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),f}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let l of n)for(let d of this.memoryRepo.getRecentForPrompt(l,s))i.has(d.key)||(i.add(d.key),a.push({key:d.key,value:d.value,category:d.category,type:d.type,score:0}));return a.slice(0,s)}}applyBoosts(e,t){let s=e;if(t){s*=.5+.5*t.confidence;let r=new Date(t.updatedAt).getTime(),n=Date.now()-r,o=Math.exp(-Sl*n/2592e6);s*=o}return s}}});import{EventEmitter as Rl}from"node:events";var J,_e=b(()=>{"use strict";J=class extends Rl{static{u(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}async sendVoice(e,t,s){}endStream(e){}getStatus(){return this.status}splitText(e,t){if(e.length<=t)return[e];let s=[],r=e;for(;r.length>0;){if(r.length<=t){s.push(r);break}let n=-1,i=r.slice(0,t).lastIndexOf(`
681
+ Return ONLY a valid JSON array, no explanation:`,Bs=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=Jl.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),n=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),o=this.parseResponse(n.content);if(o.length===0)return 0;let i=0;for(let a of o)if(!(a.confidence<this.minConfidence))try{let l=this.memoryRepo.saveWithMetadata(e,a.key,a.value,a.category,a.type,a.confidence,"auto");this.embeddingService&&this.embeddingService.embedAndStore(e,`${a.key}: ${a.value}`,"memory",l.id).catch(d=>this.logger.debug({err:d},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(l){this.logger.warn({err:l,key:a.key},"Failed to save extracted memory")}return i}catch(r){return this.logger.error({err:r},"Memory extraction failed"),0}}parseResponse(e){try{let t=e.match(/\[[\s\S]*\]/);if(!t)return[];let s=JSON.parse(t[0]);return Array.isArray(s)?s.filter(r=>typeof r=="object"&&r!==null).map(r=>({key:String(r.key||""),value:String(r.value||""),type:this.validateType(String(r.type||"fact")),confidence:this.clampConfidence(Number(r.confidence)||.5),category:String(r.category||"general")})).filter(r=>r.key&&r.value):[]}catch{return this.logger.debug({content:e.slice(0,200)},"Failed to parse extraction response"),[]}}validateType(e){return Yl.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var qs,oo=w(()=>{"use strict";ro();no();qs=class{static{u(this,"ActiveLearningService")}extractor;logger;minMessageLength;maxExtractionsPerMinute;extractionTimestamps=new Map;constructor(e){this.logger=e.logger,this.minMessageLength=e.minMessageLength??15,this.maxExtractionsPerMinute=e.maxExtractionsPerMinute??5,this.extractor=new Bs(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=so(t);if(r.level==="low"){this.logger.debug({signal:"low"},"Skipping extraction \u2014 low signal");return}if(!this.checkRateLimit(e)){this.logger.debug({userId:e},"Skipping extraction \u2014 rate limit reached");return}this.logger.info({signal:r.level,patterns:r.matchedPatterns},"High signal detected, triggering extraction"),this.extractor.extract(e,t,s).then(n=>{n>0&&this.logger.info({userId:e,extractedCount:n},"Auto-extraction complete")}).catch(n=>{this.logger.error({err:n},"Auto-extraction failed")})}checkRateLimit(e){let t=Date.now(),s=t-6e4,r=this.extractionTimestamps.get(e);r||(r=[],this.extractionTimestamps.set(e,r));let n=r.filter(o=>o>s);return this.extractionTimestamps.set(e,n),n.length>=this.maxExtractionsPerMinute?!1:(n.push(t),!0)}}});var Zl,Ql,ed,td,Hs,io=w(()=>{"use strict";Zl=Math.LN2,Ql=.3,ed=.7,td=3,Hs=class{static{u(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let g of n)for(let E of this.memoryRepo.keywordSearch(g,t,30))o.has(E.id)||(o.add(E.id),i.push(E));let a=[],l=!1;if(this.embeddingService)try{let g=new Set;for(let E of n)for(let v of await this.embeddingService.semanticSearch(E,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 E=i[g],v=m>0?1-g/m:0,R=l?Ql:1,x=this.applyBoosts(v*R,E);d.set(E.key,{memory:{key:E.key,value:E.value,category:E.category,type:E.type,score:x},score:x}),this.memoryRepo.recordAccess(E.id)}if(l)for(let g of a){let E=g.score*ed,v=d.get(g.key);if(v)v.score+=E,v.memory.score=v.score;else{let R=this.memoryRepo.recall(e,g.key),x=this.applyBoosts(E,R||void 0);d.set(g.key,{memory:{key:g.key,value:g.value,category:g.category,type:R?.type||"general",score:x},score:x}),R&&this.memoryRepo.recordAccess(R.id)}}let h=Array.from(d.values()).sort((g,E)=>E.score-g.score),b=new Map,y=[];for(let{memory:g}of h){let E=b.get(g.type)||0;if(!(E>=td)&&(b.set(g.type,E+1),y.push(g),y.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:y.length,hasSemanticSearch:l},"Hybrid memory retrieval complete"),y}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let l of n)for(let d of this.memoryRepo.getRecentForPrompt(l,s))i.has(d.key)||(i.add(d.key),a.push({key:d.key,value:d.value,category:d.category,type:d.type,score:0}));return a.slice(0,s)}}applyBoosts(e,t){let s=e;if(t){s*=.5+.5*t.confidence;let r=new Date(t.updatedAt).getTime(),n=Date.now()-r,o=Math.exp(-Zl*n/2592e6);s*=o}return s}}});import{EventEmitter as sd}from"node:events";var Q,Ie=w(()=>{"use strict";Q=class extends sd{static{u(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}async sendVoice(e,t,s){}endStream(e){}getStatus(){return this.status}splitText(e,t){if(e.length<=t)return[e];let s=[],r=e;for(;r.length>0;){if(r.length<=t){s.push(r);break}let n=-1,i=r.slice(0,t).lastIndexOf(`
658
682
 
659
- `);if(i>0&&(n=i),n<0){let l=r.slice(0,t).match(/.*[.!?]\s/s);l&&(n=l[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as Ll,InputFile as zn}from"grammy";function Qi(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var ar,ea=b(()=>{"use strict";_e();u(Qi,"mapParseMode");ar=class extends J{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new Ll(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:Qi(s?.parseMode)});n=String(i.message_id)}return n}async editMessage(e,t,s,r){await this.bot.api.editMessageText(Number(e),Number(t),s,{parse_mode:Qi(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 n=await this.bot.api.sendDocument(Number(e),new zn(t,s),{caption:r});return String(n.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 o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let l=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:l.length,data:l}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as Ml,GatewayIntentBits as cr,Events as Kn}from"discord.js";var lr,ta=b(()=>{"use strict";_e();lr=class extends J{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new Ml({intents:[cr.Guilds,cr.GuildMessages,cr.MessageContent,cr.DirectMessages]}),this.client.on(Kn.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(Kn.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Kn.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var dr,sa=b(()=>{"use strict";_e();dr=class extends J{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),l=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of l)try{let p=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(p.status===404)continue;if(!p.ok){console.error(`[matrix] Download failed (${p.status})`,s,d);continue}let m=await p.arrayBuffer(),g=Buffer.from(m);return{type:t,mimeType:n,fileName:i,size:o??g.length,data:g}}catch(p){console.error("[matrix] Download error",s,d,p);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 ur,ra=b(()=>{"use strict";_e();ur=class extends J{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:n,downloadMediaMessage:o}=t;this.downloadMedia=o;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",l=>{if(l.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),l.connection==="close"){let p=l.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),p){let m=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),m)}}}),this.socket.ev.on("messages.upsert",({messages:l,type:d})=>{if(d==="notify")for(let p of l)p.message&&(p.key.fromMe||this.processMessage(p).catch(m=>{this.emit("error",m instanceof Error?m:new Error(String(m)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var pr,na=b(()=>{"use strict";_e();pr=class extends J{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let l=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(`Signal send failed: ${l.status} ${await l.text()}`);let d=await l.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let p=await this.downloadAttachment(d);p&&i.push(p)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let l={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",l)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Gn from"node:readline";var mr,oa=b(()=>{"use strict";_e();mr=class extends J{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Gn.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
683
+ `);if(i>0&&(n=i),n<0){let l=r.slice(0,t).match(/.*[.!?]\s/s);l&&(n=l[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as rd,InputFile as ao}from"grammy";function Ta(c){if(c==="markdown")return"MarkdownV2";if(c==="html")return"HTML"}var yr,Ea=w(()=>{"use strict";Ie();u(Ta,"mapParseMode");yr=class extends Q{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new rd(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:Ta(s?.parseMode)});n=String(i.message_id)}return n}async editMessage(e,t,s,r){await this.bot.api.editMessageText(Number(e),Number(t),s,{parse_mode:Ta(r?.parseMode)})}async deleteMessage(e,t){await this.bot.api.deleteMessage(Number(e),Number(t))}async sendPhoto(e,t,s){let r=await this.bot.api.sendPhoto(Number(e),new ao(t,"image.png"),{caption:s});return String(r.message_id)}async sendFile(e,t,s,r){let n=await this.bot.api.sendDocument(Number(e),new ao(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new ao(t,"voice.ogg"),{caption:s});return String(r.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let l=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:l.length,data:l}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as nd,GatewayIntentBits as wr,Events as co}from"discord.js";var br,_a=w(()=>{"use strict";Ie();br=class extends Q{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new nd({intents:[wr.Guilds,wr.GuildMessages,wr.MessageContent,wr.DirectMessages]}),this.client.on(co.MessageCreate,async e=>{if(!e.author.bot)try{let t=await this.downloadAttachments(e),s=e.content||this.inferTextFromAttachments(t),r={id:e.id,platform:"discord",chatId:e.channelId,chatType:e.channel.isDMBased()?"dm":"group",userId:e.author.id,userName:e.author.username,displayName:e.author.displayName,text:s,timestamp:e.createdAt,replyToMessageId:e.reference?.messageId??void 0,attachments:t.length>0?t:void 0};this.emit("message",r)}catch(t){this.emit("error",t instanceof Error?t:new Error(String(t)))}}),this.client.on(co.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(co.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var Tr,$a=w(()=>{"use strict";Ie();Tr=class extends Q{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),l=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of l)try{let m=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(m.status===404)continue;if(!m.ok){console.error(`[matrix] Download failed (${m.status})`,s,d);continue}let h=await m.arrayBuffer(),b=Buffer.from(h);return{type:t,mimeType:n,fileName:i,size:o??b.length,data:b}}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 Er,va=w(()=>{"use strict";Ie();Er=class extends Q{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:n,downloadMediaMessage:o}=t;this.downloadMedia=o;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",l=>{if(l.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),l.connection==="close"){let m=l.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),m){let h=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),h)}}}),this.socket.ev.on("messages.upsert",({messages:l,type:d})=>{if(d==="notify")for(let m of l)m.message&&(m.key.fromMe||this.processMessage(m).catch(h=>{this.emit("error",h instanceof Error?h:new Error(String(h)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var _r,ka=w(()=>{"use strict";Ie();_r=class extends Q{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let l=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(`Signal send failed: ${l.status} ${await l.text()}`);let d=await l.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let m=await this.downloadAttachment(d);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let l={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",l)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import lo from"node:readline";var $r,Sa=w(()=>{"use strict";Ie();$r=class extends Q{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=lo.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
660
684
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
661
685
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
662
686
  Goodbye!
663
687
  `),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(`
664
688
  Alfred: ${t}
665
- `),this.prompt(),r}async editMessage(e,t,s,r){Gn.clearLine(process.stdout,0),Gn.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Nl from"node:http";import Cl from"node:crypto";var hr,ia=b(()=>{"use strict";_e();hr=class extends J{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=Nl.createServer((e,t)=>{this.handleRequest(e,t)}),await new Promise((e,t)=>{this.server.listen(this.port,this.host,()=>{e()}),this.server.once("error",t)}),this.status="connected",this.emit("connected")}async disconnect(){for(let[e,t]of this.streams)this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e);this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=`api-resp-${++this.messageCounter}`,n=this.streams.get(e);return n&&this.writeSseEvent(n,"response",{type:"response",text:t}),r}async editMessage(e,t,s,r){let n=this.streams.get(e);n&&this.writeSseEvent(n,"status",{type:"status",text:s})}async deleteMessage(e,t){}async sendPhoto(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"image",data:t.toString("base64"),caption:s}),`api-photo-${++this.messageCounter}`}async sendFile(e,t,s,r){let n=this.streams.get(e);return n&&this.writeSseEvent(n,"attachment",{type:"attachment",attachmentType:"file",data:t.toString("base64"),fileName:s,caption:r}),`api-file-${++this.messageCounter}`}async sendVoice(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"voice",data:t.toString("base64"),caption:s}),`api-voice-${++this.messageCounter}`}endStream(e){let t=this.streams.get(e);t&&(this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e))}handleRequest(e,t){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),e.method==="OPTIONS"){t.writeHead(204),t.end();return}let s=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`);s.pathname==="/api/health"&&e.method==="GET"?this.handleHealth(t):s.pathname==="/api/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}handleHealth(e){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok"}))}handleMessage(e,t){let s="";e.on("data",r=>{s+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(s),n=r.text;if(!n||typeof n!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let o=r.chatId??`api-chat-${Cl.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(o);a&&(this.writeSseEvent(a,"done",{type:"done"}),a.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(o,t),e.on("close",()=>{this.streams.delete(o)}),this.messageCounter++;let l={id:`api-${this.messageCounter}`,platform:"api",chatId:o,chatType:"dm",userId:i,userName:i,displayName:"API User",text:n,timestamp:new Date};this.emit("message",l)}catch{t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON body"}))}})}writeSseEvent(e,t,s){e.writableEnded||e.write(`event: ${t}
689
+ `),this.prompt(),r}async editMessage(e,t,s,r){lo.clearLine(process.stdout,0),lo.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import od from"node:http";import id from"node:crypto";var vr,xa=w(()=>{"use strict";Ie();vr=class extends Q{static{u(this,"HttpAdapter")}port;host;platform="api";server=null;streams=new Map;messageCounter=0;constructor(e,t){super(),this.port=e,this.host=t}async connect(){this.status="connecting",this.server=od.createServer((e,t)=>{this.handleRequest(e,t)}),await new Promise((e,t)=>{this.server.listen(this.port,this.host,()=>{e()}),this.server.once("error",t)}),this.status="connected",this.emit("connected")}async disconnect(){for(let[e,t]of this.streams)this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e);this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=`api-resp-${++this.messageCounter}`,n=this.streams.get(e);return n&&this.writeSseEvent(n,"response",{type:"response",text:t}),r}async editMessage(e,t,s,r){let n=this.streams.get(e);n&&this.writeSseEvent(n,"status",{type:"status",text:s})}async deleteMessage(e,t){}async sendPhoto(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"image",data:t.toString("base64"),caption:s}),`api-photo-${++this.messageCounter}`}async sendFile(e,t,s,r){let n=this.streams.get(e);return n&&this.writeSseEvent(n,"attachment",{type:"attachment",attachmentType:"file",data:t.toString("base64"),fileName:s,caption:r}),`api-file-${++this.messageCounter}`}async sendVoice(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"voice",data:t.toString("base64"),caption:s}),`api-voice-${++this.messageCounter}`}endStream(e){let t=this.streams.get(e);t&&(this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e))}handleRequest(e,t){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),e.method==="OPTIONS"){t.writeHead(204),t.end();return}let s=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`);s.pathname==="/api/health"&&e.method==="GET"?this.handleHealth(t):s.pathname==="/api/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}handleHealth(e){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok"}))}handleMessage(e,t){let s="";e.on("data",r=>{s+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(s),n=r.text;if(!n||typeof n!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let o=r.chatId??`api-chat-${id.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(o);a&&(this.writeSseEvent(a,"done",{type:"done"}),a.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(o,t),e.on("close",()=>{this.streams.delete(o)}),this.messageCounter++;let l={id:`api-${this.messageCounter}`,platform:"api",chatId:o,chatType:"dm",userId:i,userName:i,displayName:"API User",text:n,timestamp:new Date};this.emit("message",l)}catch{t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON body"}))}})}writeSseEvent(e,t,s){e.writableEnded||e.write(`event: ${t}
666
690
  data: ${JSON.stringify(s)}
667
691
 
668
- `)}}});var Ae={};le(Ae,{CLIAdapter:()=>mr,DiscordAdapter:()=>lr,HttpAdapter:()=>hr,MatrixAdapter:()=>dr,MessagingAdapter:()=>J,SignalAdapter:()=>pr,TelegramAdapter:()=>ar,WhatsAppAdapter:()=>ur});var Re=b(()=>{"use strict";_e();ea();ta();sa();ra();na();oa();ia()});import fr from"node:fs";import gr from"node:path";import Ol from"js-yaml";var Je,aa=b(()=>{"use strict";zr();Yr();xe();cn();Ys();we();Mn();Nn();Cn();On();Dn();Un();Pn();Fn();jn();Bn();Hn();Vn();Je=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Ss;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=qt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new Fe(this.config.storage.path);let e=this.database.getDb(),t=new Wt(e),s=new Xt(e);this.userRepo=s;let r=new je(e),n=new Ht(e),o=new Vt(e),i=new zt(e),a=new Kt(e),l=new Gt(e),d=new Yt(e),p=new Jt(e);this.logger.info("Storage initialized");let m=new cs,g=this.loadSecurityRules();m.loadRules(g);let f=new ls(m,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:g.length},"Security engine initialized");let h=an(this.config.llm);await h.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let T=new xs(h,a,this.logger.child({component:"embeddings"})),_=this.config.activeLearning?.enabled!==!1,x,k;_&&(x=new Ms({llm:h,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:T,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),k=new Ns(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let C=new tt(this.logger.child({component:"sandbox"})),M=this.skillRegistry=new et;M.register(new st),M.register(new rt),M.register(new nt(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),M.register(new ot(o)),M.register(new it(i)),M.register(new at),M.register(new ct),M.register(new lt(n,T)),M.register(new dt(h,M,C,f)),M.register(new ut(this.config.email?{imap:this.config.email.imap,smtp:this.config.email.smtp,auth:this.config.email.auth}:void 0)),M.register(new pt),M.register(new mt);let P=new St;P.setReloadCallback(L=>this.reloadService(L)),M.register(P),M.register(new ft),M.register(new gt),M.register(new yt),M.register(new wt(s)),M.register(new bt(s,l,this.adapters,(L,Z)=>t.findByPlatformAndUser(L,Z))),M.register(new Tt(d)),M.register(new Et(p));let j=new Zt(e),ne=new Is(j,T,this.logger.child({component:"documents"}));M.register(new vt(j,ne,T));let Ne;if(this.config.calendar)try{let L=await ps(this.config.calendar);Ne=new He(L),M.register(Ne),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(L){this.logger.warn({err:L},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=Ne,this.config.mcp?.servers?.length){let{MCPManager:L}=await Promise.resolve().then(()=>(we(),Ee));this.mcpManager=new L(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let Z of this.mcpManager.getSkills())M.register(Z);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:L}=await Promise.resolve().then(()=>(we(),Ee));M.register(new L({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:L}=await Promise.resolve().then(()=>(we(),Ee));M.register(new L({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},h)),this.logger.info({agents:this.config.codeAgents.agents.map(Z=>Z.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:L}=await Promise.resolve().then(()=>(we(),Ee));M.register(new L(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:L}=await Promise.resolve().then(()=>(we(),Ee));M.register(new L(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}this.logger.info({skills:M.getAll().map(L=>L.metadata.name)},"Skills registered");let ue;if(this.config.speech?.apiKey&&(ue=new ks(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let L=new $s(this.config.speech,this.logger.child({component:"tts"}));M.register(new kt(L)),this.logger.info("Text-to-speech skill registered")}let K=new Es(t),te=gr.resolve(gr.dirname(this.config.storage.path),"inbox");this.pipeline=new _s({llm:h,conversationManager:K,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:M,skillSandbox:C,securityManager:f,memoryRepo:n,speechTranscriber:ue,inboxPath:te,embeddingService:T,activeLearning:x,memoryRetriever:k}),this.reminderScheduler=new vs(o,async(L,Z,B)=>{let V=this.adapters.get(L);V?await V.sendMessage(Z,B):this.logger.warn({platform:L,chatId:Z},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(L=>s.getMasterUserId(L),"getMasterUserId"),getLinkedUsers:u(L=>s.getLinkedUsers(L),"getLinkedUsers"),findConversation:u((L,Z)=>t.findByPlatformAndUser(L,Z),"findConversation")}),this.backgroundTaskRunner=new As(M,C,d,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Rs(p,M,C,h,this.adapters,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(Re(),Ae));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(()=>(Re(),Ae));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(()=>(Re(),Ae));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(()=>(Re(),Ae));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(()=>(Re(),Ae));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(()=>(Re(),Ae)),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(()=>(Re(),Ae)),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{Hr();let t=new Q().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(we(),Ee));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(()=>(we(),Ee));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(p){this.logger.debug({err:p,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),l=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,l)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,l)}else await t.sendMessage(s.chatId,a.text,l)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let p=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,p.text)}if(i.attachments)for(let d of i.attachments)try{let p=d.mimeType.startsWith("image/"),m=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";p?await t.sendPhoto(s.chatId,d.data,d.fileName):m?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(p){this.logger.warn({err:p,fileName:d.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}loadSecurityRules(){let e=gr.resolve(this.config.security.rulesPath),t=[];if(!fr.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!fr.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=fr.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=gr.join(e,n),i=fr.readFileSync(o,"utf-8"),a=Ol.load(i);a?.rules&&Array.isArray(a.rules)&&(t.push(...a.rules),this.logger.info({file:n,count:a.rules.length},"Loaded security rules"))}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var ca=b(()=>{"use strict"});var Yn=b(()=>{"use strict";aa();Nn();Mn();Cn();On();Dn();Un();Pn();jn();Bn();Fn();Hn();Vn();Xn();ca();Wn()});var la={};le(la,{startCommand:()=>Dl});async function Dl(){let c=new Q,e;try{e=c.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=qt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new Je(e),r=!1,n=u(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready")}catch(o){t.fatal({error:o},"Failed to start Alfred"),process.exit(1)}}var da=b(()=>{"use strict";xe();zr();Yn();u(Dl,"startCommand")});var pa={};le(pa,{chatCommand:()=>Fl});import ua from"node:http";import Cs from"node:readline";function Ul(c,e){return new Promise(t=>{let s=ua.get(`http://${c}:${e}/api/health`,{timeout:2e3},r=>{let n="";r.on("data",o=>{n+=o.toString()}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function Pl(c,e){let t=Cs.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
692
+ `)}}});var Ce={};oe(Ce,{CLIAdapter:()=>$r,DiscordAdapter:()=>br,HttpAdapter:()=>vr,MatrixAdapter:()=>Tr,MessagingAdapter:()=>Q,SignalAdapter:()=>_r,TelegramAdapter:()=>yr,WhatsAppAdapter:()=>Er});var Oe=w(()=>{"use strict";Ie();Ea();_a();$a();va();ka();Sa();xa()});import kr from"node:fs";import Sr from"node:path";import ad from"js-yaml";var st,Ia=w(()=>{"use strict";on();ln();Le();Tn();sr();pe();zn();Vn();Kn();Gn();Yn();Jn();Zn();Qn();eo();to();oo();io();st=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Ds;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Jt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new We(this.config.storage.path);let e=this.database.getDb(),t=new Zt(e),s=new Qt(e);this.userRepo=s;let r=new Xe(e),n=new es(e),o=new ts(e),i=new ss(e),a=new rs(e),l=new ns(e),d=new os(e),m=new is(e);this.logger.info("Storage initialized");let h=new ys,b=this.loadSecurityRules();h.loadRules(b);let y=new ws(h,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:b.length},"Security engine initialized");let g=bn(this.config.llm);await g.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let E=new Us(g,a,this.logger.child({component:"embeddings"})),v=this.config.activeLearning?.enabled!==!1,R,x;v&&(R=new qs({llm:g,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:E,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),x=new Hs(n,this.logger.child({component:"memory-retriever"}),E),this.logger.info("Active learning & memory retriever initialized"));let O=new ct(this.logger.child({component:"sandbox"})),N=this.skillRegistry=new at;if(N.register(new lt),N.register(new dt),N.register(new ut(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),N.register(new mt(o)),N.register(new pt(i)),N.register(new ht),N.register(new ft),N.register(new gt(n,E)),N.register(new yt(g,N,O,y)),this.config.email?.accounts?.length){let L=new Map;for(let W of this.config.email.accounts)try{W.provider==="microsoft"&&!W.microsoft?.clientId&&this.config.calendar?.microsoft&&(W.microsoft={...this.config.calendar.microsoft});let F=await bs(W);L.set(W.name,F),this.logger.info({account:W.name,provider:W.provider??"imap-smtp"},"Email account initialized")}catch(F){this.logger.warn({err:F,account:W.name},"Email account initialization failed, skipping")}N.register(L.size>0?new Me(L):new Me)}else N.register(new Me);N.register(new wt),N.register(new bt);let B=new Mt;B.setReloadCallback(L=>this.reloadService(L)),N.register(B),N.register(new Et),N.register(new _t),N.register(new $t),N.register(new vt(s)),N.register(new kt(s,l,this.adapters,(L,W)=>t.findByPlatformAndUser(L,W))),N.register(new St(d)),N.register(new xt(m));let q=new as(e),ae=new Ps(q,E,this.logger.child({component:"documents"}));N.register(new At(q,ae,E));let Pe;if(this.config.calendar)try{let L=await _s(this.config.calendar);Pe=new Ye(L),N.register(Pe),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(L){this.logger.warn({err:L},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=Pe,this.config.mcp?.servers?.length){let{MCPManager:L}=await Promise.resolve().then(()=>(pe(),be));this.mcpManager=new L(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let W of this.mcpManager.getSkills())N.register(W);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},g)),this.logger.info({agents:this.config.codeAgents.agents.map(W=>W.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:L}=await Promise.resolve().then(()=>(pe(),be));N.register(new L(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}this.logger.info({skills:N.getAll().map(L=>L.metadata.name)},"Skills registered");let he;if(this.config.speech?.apiKey&&(he=new Cs(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let L=new Os(this.config.speech,this.logger.child({component:"tts"}));N.register(new Rt(L)),this.logger.info("Text-to-speech skill registered")}let Y=new Ls(t),re=Sr.resolve(Sr.dirname(this.config.storage.path),"inbox");this.pipeline=new Ms({llm:g,conversationManager:Y,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:N,skillSandbox:O,securityManager:y,memoryRepo:n,speechTranscriber:he,inboxPath:re,embeddingService:E,activeLearning:R,memoryRetriever:x}),this.reminderScheduler=new Ns(o,async(L,W,F)=>{let V=this.adapters.get(L);V?await V.sendMessage(W,F):this.logger.warn({platform:L,chatId:W},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(L=>s.getMasterUserId(L),"getMasterUserId"),getLinkedUsers:u(L=>s.getLinkedUsers(L),"getLinkedUsers"),findConversation:u((L,W)=>t.findByPlatformAndUser(L,W),"findConversation")}),this.backgroundTaskRunner=new Fs(N,O,d,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new js(m,N,O,g,this.adapters,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce));this.adapters.set("telegram",new t(e.telegram.token)),this.logger.info("Telegram adapter registered")}if(e.discord?.enabled&&e.discord.token){let{DiscordAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce));this.adapters.set("discord",new t(e.discord.token)),this.logger.info("Discord adapter registered")}if(e.whatsapp?.enabled){let{WhatsAppAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce));this.adapters.set("whatsapp",new t(e.whatsapp.dataPath)),this.logger.info("WhatsApp adapter registered")}if(e.matrix?.enabled&&e.matrix.accessToken){let{MatrixAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce));this.adapters.set("matrix",new t(e.matrix.homeserverUrl,e.matrix.accessToken,e.matrix.userId)),this.logger.info("Matrix adapter registered")}if(e.signal?.enabled&&e.signal.phoneNumber){let{SignalAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}if(e.api?.enabled!==!1){let{HttpAdapter:t}=await Promise.resolve().then(()=>(Oe(),Ce)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";this.adapters.set("api",new t(s,r)),this.logger.info({port:s,host:r},"HTTP API adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(Oe(),Ce)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{rn();let t=new te().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(pe(),be));this.skillRegistry.register(new s(t.proxmox)),this.config.proxmox=t.proxmox,this.logger.info({baseUrl:t.proxmox.baseUrl},"Proxmox skill hot-reloaded")}if(e==="unifi"&&t.unifi){let{UniFiSkill:s}=await Promise.resolve().then(()=>(pe(),be));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}if(e==="homeassistant"&&t.homeassistant){let{HomeAssistantSkill:s}=await Promise.resolve().then(()=>(pe(),be));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(m){this.logger.debug({err:m,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),l=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,l)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,l)}else await t.sendMessage(s.chatId,a.text,l)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let m=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,m.text)}if(i.attachments)for(let d of i.attachments)try{let m=d.mimeType.startsWith("image/"),h=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):h?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}loadSecurityRules(){let e=Sr.resolve(this.config.security.rulesPath),t=[];if(!kr.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!kr.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=kr.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Sr.join(e,n),i=kr.readFileSync(o,"utf-8"),a=ad.load(i);a?.rules&&Array.isArray(a.rules)&&(t.push(...a.rules),this.logger.info({file:n,count:a.rules.length},"Loaded security rules"))}catch(o){this.logger.error({err:o,file:n},"Failed to load security rules file")}return t}}});var Aa=w(()=>{"use strict"});var uo=w(()=>{"use strict";Ia();Vn();zn();Kn();Gn();Yn();Jn();Zn();eo();to();Qn();oo();io();no();Aa();ro()});var Ra={};oe(Ra,{startCommand:()=>cd});async function cd(){let c=new te,e;try{e=c.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Jt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new st(e),r=!1,n=u(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready")}catch(o){t.fatal({error:o},"Failed to start Alfred"),process.exit(1)}}var La=w(()=>{"use strict";Le();on();uo();u(cd,"startCommand")});var Na={};oe(Na,{chatCommand:()=>ud});import Ma from"node:http";import Ws from"node:readline";function ld(c,e){return new Promise(t=>{let s=Ma.get(`http://${c}:${e}/api/health`,{timeout:2e3},r=>{let n="";r.on("data",o=>{n+=o.toString()}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function dd(c,e){let t=Ws.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
669
693
  Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
670
694
  `),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
671
695
  Goodbye!
672
- `),t.close(),process.exit(0));let n=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),o=ua.request({hostname:c,port:e,path:"/api/message",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n)}},i=>{let a="";i.on("data",l=>{a+=l.toString();let d=a.split(`
696
+ `),t.close(),process.exit(0));let n=JSON.stringify({text:r,chatId:"api-chat",userId:"api-user"}),o=Ma.request({hostname:c,port:e,path:"/api/message",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n)}},i=>{let a="";i.on("data",l=>{a+=l.toString();let d=a.split(`
673
697
 
674
- `);a=d.pop()??"";for(let p of d){let m=p.split(`
675
- `).find(g=>g.startsWith("data: "));if(m)try{let g=JSON.parse(m.slice(6));switch(g.type){case"status":Cs.clearLine(process.stdout,0),Cs.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${g.text??""}`);break;case"response":Cs.clearLine(process.stdout,0),Cs.cursorTo(process.stdout,0),process.stdout.write(`
676
- Alfred: ${g.text??""}
677
- `);break;case"attachment":{let f=g.fileName??g.attachmentType??"file";process.stdout.write(`[Attachment: ${f}]
698
+ `);a=d.pop()??"";for(let m of d){let h=m.split(`
699
+ `).find(b=>b.startsWith("data: "));if(h)try{let b=JSON.parse(h.slice(6));switch(b.type){case"status":Ws.clearLine(process.stdout,0),Ws.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${b.text??""}`);break;case"response":Ws.clearLine(process.stdout,0),Ws.cursorTo(process.stdout,0),process.stdout.write(`
700
+ Alfred: ${b.text??""}
701
+ `);break;case"attachment":{let y=b.fileName??b.attachmentType??"file";process.stdout.write(`[Attachment: ${y}]
678
702
  `);break}case"done":t.prompt();break;case"error":process.stdout.write(`
679
- Error: ${g.text??"Unknown error"}
703
+ Error: ${b.text??"Unknown error"}
680
704
  `),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let l=a.split(`
681
705
  `).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(`
682
706
  Connection error: ${l.message}`),t.prompt()})});o.on("error",i=>{console.error(`
683
- Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function Fl(c){let e=new Q,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 Ul(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Pl(s,r);return}if(t.logger.level="warn",c.model&&(t.llm.default.model=c.model),c.tier){let i=t.llm[c.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${c.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new Je(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var ma=b(()=>{"use strict";xe();Yn();u(Ul,"checkHealth");u(Pl,"startClientMode");u(Fl,"chatCommand")});var ga={};le(ga,{setupCommand:()=>Yl});import{createInterface as jl}from"node:readline/promises";import{stdin as Bl,stdout as ql}from"node:process";import{execFileSync as Wl}from"node:child_process";import ee from"node:fs";import Xl from"node:os";import re from"node:path";import Jn from"js-yaml";function O(c){return`${wr}${c}${S}`}function zl(c){return`${U}${c}${S}`}function be(c){return`${br}${c}${S}`}function fa(c){return`${Hl}${c}${S}`}function I(c){return`${se}${c}${S}`}function E(c){return`${Me}${c}${S}`}function de(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Kl(c){let e=process.platform==="win32",t=e?"where":"which";try{let n=Wl(t,[c],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=Xl.homedir(),r=e?[re.join(s,".local","bin",`${c}.exe`),re.join(s,"AppData","Roaming","npm",`${c}.cmd`),re.join(s,"AppData","Roaming","npm",`${c}`)]:[re.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,re.join(s,".npm-global","bin",c)];for(let n of r)try{return ee.accessSync(n,ee.constants.X_OK),n}catch{}return null}function Gl(c){let e={},t={},s=!1,r=!1,n=30,o=re.join(c,"config","default.yml");if(ee.existsSync(o))try{let m=Jn.load(ee.readFileSync(o,"utf-8"));m&&typeof m=="object"&&Object.assign(e,m)}catch{}let i=re.join(c,".env");if(ee.existsSync(i))try{let m=ee.readFileSync(i,"utf-8").split(`
684
- `);for(let g of m){let f=g.trim();if(!f||f.startsWith("#"))continue;let h=f.indexOf("=");h>0&&(t[f.slice(0,h)]=f.slice(h+1))}}catch{}let a=re.join(c,"config","rules","default-rules.yml");if(ee.existsSync(a))try{let m=Jn.load(ee.readFileSync(a,"utf-8"));if(m?.rules){s=m.rules.some(h=>h.id==="allow-owner-admin"&&h.effect==="allow"),m.rules.find(h=>h.id==="allow-write-for-dm"||h.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let f=m.rules.find(h=>h.id==="rate-limit-write");f?.rateLimit?.maxInvocations&&(n=f.rateLimit.maxInvocations)}}catch{}let l=!!e.codeSandbox?.enabled,d=e.llm,p={};if(d){for(let m of["strong","fast","embeddings","local"])d[m]?.provider&&d[m]?.model&&(p[m]=d[m]);d.default?.provider&&(e.llm={...e.llm,provider:d.default.provider,model:d.default.model,baseUrl:d.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:l,multiModelTiers:p}}async function Yl(){let c=jl({input:Bl,output:ql}),e=process.cwd(),t=Gl(e),s=Object.keys(t.config).length>0;try{Jl(),console.log(s?`${br}Existing configuration found \u2014 press Enter to keep current values.${S}
685
- ${Me}Only change what you need to update.${S}
686
- `:`${br}Welcome to the Alfred setup wizard!${S}
687
- ${Me}This will walk you through configuring your AI assistant.${S}
688
- ${Me}Press Enter to accept defaults shown in [brackets].${S}
689
- `);let r=await F(c,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Le.findIndex(y=>y.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
690
- ${I("Which LLM provider would you like to use?")}`);for(let y=0;y<Le.length;y++){let v=y===n?` ${E("(current)")}`:"";console.log(` ${be(String(y+1)+")")} ${Le[y].label}${v}`)}let i=await yr(c,"> ",1,Le.length,o),a=Le[i-1];console.log(` ${O(">")} Selected: ${I(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await F(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await ve(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${O(">")} API key set: ${E(de(l))}`));let p=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let v=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(v){let R={ollama:"Ollama URL (use a remote address if Ollama runs on another machine)",openwebui:"OpenWebUI URL",openai:"OpenAI-compatible API URL (leave default for official API)",openrouter:"OpenRouter API URL",google:"Google Gemini API URL (leave default for official API)"};console.log(""),p=await F(c,R[a.name]??"API Base URL",v.replace(/\/+$/,"")),p=p.replace(/\/+$/,""),console.log(` ${O(">")} URL: ${E(p)}`)}}let g=t.config.llm?.model??a.defaultModel;console.log("");let f;if(a.models&&a.models.length>0){console.log(`${I("Available models:")}`);for(let R=0;R<a.models.length;R++){let W=a.models[R],N=W.id===g?` ${O("(current)")}`:"";console.log(` ${be(`${R+1})`)} ${W.id} ${E(`\u2014 ${W.desc}`)}${N}`)}console.log(` ${be(`${a.models.length+1})`)} ${E("Other (enter manually)")}`);let y=await F(c,"Choose model","1"),v=parseInt(y,10)-1;v>=0&&v<a.models.length?f=a.models[v].id:v===a.models.length?f=await F(c,"Model ID",g):f=await F(c,"Model ID",g)}else f=await F(c,"Which model?",g);let h=Object.keys(t.multiModelTiers).length>0,T=h?"Y/n":"y/N";console.log(`
691
- ${I("Configure additional model tiers for specialized tasks?")}`),console.log(`${E("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let _=(await c.question(`${U}> ${S}${E(`[${T}] `)}`)).trim().toLowerCase(),x=_===""?h:_==="y"||_==="yes",k={};if(x){let y=[{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 v of y){let R=t.multiModelTiers[v.key],W=!!R?.model;console.log(`
692
- ${I(`${v.label} model`)} ${E(`(${v.hint})`)}`),W&&console.log(` ${E(`Current: ${R.provider}/${R.model}`)}`),console.log(` ${E("Press Enter to skip.")}`);let X=(await c.question(` ${U}Model: ${S}${W?E(`[${R.model}] `):""}`)).trim()||(W?R.model:"");if(!X){console.log(` ${E("Skipped.")}`);continue}let G=R?.provider??a.name,ge=Le.map(Vs=>Vs.name).join(", ");console.log(` ${E(`Providers: ${ge}`)}`);let ae=(await c.question(` ${U}Provider: ${S}${E(`[${G}] `)}`)).trim()||G,Hs,jr;if(ae!==a.name){let Vs=R?.apiKey??t.env[`ALFRED_LLM_${v.key.toUpperCase()}_API_KEY`]??"";if(Vs?Hs=await F(c,` API key for ${ae}`,Vs):(Le.find(zs=>zs.name===ae)?.needsApiKey??!0)&&(Hs=await ve(c,` API key for ${ae}`)),["ollama","openwebui"].includes(ae)){let zs=(R?.baseUrl??"")||Le.find(Va=>Va.name===ae)?.baseUrl||"";zs&&(jr=await F(c,` ${ae} URL`,zs))}}k[v.key]={provider:ae,model:X,...Hs?{apiKey:Hs}:{},...jr?{baseUrl:jr}:{}},console.log(` ${O(">")} ${v.label}: ${I(ae)}/${I(X)}`)}Object.keys(k).length===0&&console.log(`
693
- ${E("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${E("Using single model for all tasks.")}`);let C=["brave","tavily","duckduckgo","searxng"],M=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",P=C.indexOf(M),j=P>=0?P+1:0;console.log(`
694
- ${I("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"],Ne=u(y=>P===y?` ${E("(current)")}`:"","mark");console.log(` ${be("0)")} None (disable web search)${P===-1&&M===""?` ${E("(current)")}`:""}`);for(let y=0;y<ne.length;y++)console.log(` ${be(String(y+1)+")")} ${ne[y]}${Ne(y)}`);let ue=await yr(c,"> ",0,C.length,j),K,te="",L="";if(ue>=1&&ue<=C.length&&(K=C[ue-1]),K==="brave"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?te=await F(c," Brave Search API key",y):(console.log(` ${E("Get your free API key at: https://brave.com/search/api/")}`),te=await ve(c," Brave Search API key")),console.log(` ${O(">")} Brave Search: ${E(de(te))}`)}else if(K==="tavily"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?te=await F(c," Tavily API key",y):(console.log(` ${E("Get your free API key at: https://tavily.com/")}`),te=await ve(c," Tavily API key")),console.log(` ${O(">")} Tavily: ${E(de(te))}`)}else if(K==="duckduckgo")console.log(` ${O(">")} DuckDuckGo: ${E("no API key needed")}`);else if(K==="searxng"){let y=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";L=await F(c," SearXNG URL",y),L=L.replace(/\/+$/,""),console.log(` ${O(">")} SearXNG: ${E(L)}`)}else console.log(` ${E("Web search disabled \u2014 you can configure it later.")}`);let Z=[];for(let y=0;y<Rt.length;y++){let v=Rt[y];t.config[v.configKey]?.enabled&&Z.push(y+1)}let B=Z.length>0?Z.join(","):"";console.log(`
695
- ${I("Which messaging platforms do you want to enable?")}`),console.log(`${E("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let y=0;y<Rt.length;y++){let v=Z.includes(y+1)?` ${E("(enabled)")}`:"";console.log(` ${be(String(y+1)+")")} ${Rt[y].label}${v}`)}console.log(` ${be("0)")} None (configure later)`);let V=(await c.question(`${U}> ${S}${B?E(`[${B}] `):""}`)).trim(),q=[],z=V||B;if(z&&z!=="0"){let y=z.split(",").map(v=>parseInt(v.trim(),10));for(let v of y)if(v>=1&&v<=Rt.length){let R=Rt[v-1];q.includes(R)||q.push(R)}}q.length>0?console.log(` ${O(">")} Enabling: ${q.map(y=>I(y.label)).join(", ")}`):console.log(` ${E("No platforms selected \u2014 you can configure them later.")}`);let oe={},Te={};for(let y of q){if(y.credentials.length===0){y.name==="whatsapp"&&console.log(`
696
- ${zl("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
697
- ${I(y.label+" configuration:")}`);let v={};for(let R of y.credentials){let W=t.env[R.envKey]??"",N;W?N=await F(c,` ${R.prompt}`,W):R.defaultValue?N=await F(c,` ${R.prompt}`,R.defaultValue):R.required?N=await ve(c,` ${R.prompt}`):(N=(await c.question(` ${R.prompt}: ${U}`)).trim(),process.stdout.write(S)),v[R.configField]=N,Te[R.envKey]=N,R.configField==="token"||R.configField==="accessToken"?console.log(` ${O(">")} Set: ${E(de(N))}`):console.log(` ${O(">")} Set: ${E(N)}`)}oe[y.configKey]=v}let eo=t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",to=!!eo,Aa=to?"Y/n":"y/N";console.log(`
698
- ${I("Email access (read & send emails via IMAP/SMTP)?")}`),console.log(`${E("Works with Gmail, Outlook, or any IMAP/SMTP provider.")}`);let Er=(await c.question(`${U}> ${S}${E(`[${Aa}] `)}`)).trim().toLowerCase(),Ds=Er===""?to:Er==="y"||Er==="yes",ke="",Us="",Ps="",_r=993,so="",vr=587;if(Ds){console.log(""),ke=await F(c," Email address",eo||""),ke||(ke=await ve(c," Email address"));let y=t.env.ALFRED_EMAIL_PASS??"";y?Us=await F(c," Password / App password",y):(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")}`),Us=await ve(c," Password / App password"));let v=ke.split("@")[1]?.toLowerCase()??"",W={"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"}}[v],N=t.config.email?.imap?.host??W?.imap??`imap.${v}`,X=t.config.email?.smtp?.host??W?.smtp??`smtp.${v}`,G=t.config.email?.imap?.port??993,ge=t.config.email?.smtp?.port??587;W&&console.log(` ${O(">")} Detected ${v} \u2014 using preset server settings`),Ps=await F(c," IMAP server",N);let Se=await F(c," IMAP port",String(G));_r=parseInt(Se,10)||993,so=await F(c," SMTP server",X);let ae=await F(c," SMTP port",String(ge));vr=parseInt(ae,10)||587,console.log(` ${O(">")} Email: ${E(ke)} via ${E(Ps)}`)}else console.log(` ${E("Email disabled \u2014 you can configure it later.")}`);let Fs=["openai","groq"],Ra=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",js=Fs.indexOf(Ra),La=js>=0?js+1:0;console.log(`
699
- ${I("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${E("Transcribes voice messages from Telegram, Discord, etc.")}`);let ro=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${be("0)")} None (disable voice transcription)${js===-1?` ${E("(current)")}`:""}`);for(let y=0;y<ro.length;y++){let v=js===y?` ${E("(current)")}`:"";console.log(` ${be(String(y+1)+")")} ${ro[y]}${v}`)}let kr=await yr(c,"> ",0,Fs.length,La),fe,$e="",Lt="";if(kr>=1&&kr<=Fs.length&&(fe=Fs[kr-1]),fe==="openai"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?$e=await F(c," OpenAI API key (for Whisper)",y):(console.log(` ${E("Uses your OpenAI API key for Whisper transcription.")}`),$e=await ve(c," OpenAI API key")),console.log(` ${O(">")} OpenAI Whisper: ${E(de($e))}`)}else if(fe==="groq"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?$e=await F(c," Groq API key",y):(console.log(` ${E("Get your free API key at: https://console.groq.com/")}`),$e=await ve(c," Groq API key"));let v=t.env.ALFRED_SPEECH_BASE_URL??"";v&&(Lt=await F(c," Groq API URL",v)),console.log(` ${O(">")} Groq Whisper: ${E(de($e))}`)}else console.log(` ${E("Voice transcription disabled \u2014 you can configure it later.")}`);let Mt=!1,Nt="alloy";if(fe){let y=t.config.speech?.ttsEnabled??!1,v=y?"Y/n":"y/N";console.log(`
700
- ${I("Voice responses (Text-to-Speech)?")}`),console.log(`${E("Alfred can reply as a voice message when the user asks for it.")}`);let R=(await c.question(`${U}> ${S}${E(`[${v}] `)}`)).trim().toLowerCase();if(Mt=R===""?y:R==="y"||R==="yes",Mt){let W=["alloy","echo","fable","onyx","nova","shimmer"],N=t.config.speech?.ttsVoice??"alloy",X=W.indexOf(N),G=X>=0?X+1:1;console.log(`
701
- ${I("Which voice?")}`);for(let Se=0;Se<W.length;Se++){let ae=X===Se?` ${E("(current)")}`:"";console.log(` ${be(String(Se+1)+")")} ${W[Se]}${ae}`)}let ge=await yr(c," > ",1,W.length,G);Nt=W[ge-1],console.log(` ${O(">")} TTS voice: ${I(Nt)}`)}else console.log(` ${E("Voice responses disabled.")}`)}let Ma=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
702
- ${I("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${E("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let $r=(await c.question(`${U}> ${S}${E(`[${Ma}] `)}`)).trim().toLowerCase(),Sr=$r===""?t.codeSandboxEnabled:$r==="y"||$r==="yes";console.log(Sr?` ${O(">")} Code Sandbox ${I("enabled")} (JavaScript + Python)`:` ${E("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
703
- ${I("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${E("Scanning for known coding agents on this system...")}`);let xr=[];for(let y of ha){let v=Kl(y.whichCmd);v?(xr.push({...y,resolvedPath:v}),console.log(` ${O("\u2713")} ${I(y.label)} ${E(`(${v})`)}`)):console.log(` ${E("\xB7")} ${E(y.label)} ${E("\u2014 not found")}`)}let Ir=(t.config.codeAgents?.agents??[]).filter(y=>!ha.some(v=>v.name===y.name));for(let y of Ir)console.log(` ${O("\u2713")} ${I(y.name)} ${E(`(${y.command}) \u2014 from existing config`)}`);let Ce=[];if(xr.length===0&&Ir.length===0)console.log(`
704
- ${E("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let y=[...xr.map(N=>({name:N.name,command:N.resolvedPath??N.command,argsTemplate:N.argsTemplate,promptVia:N.promptVia,label:N.label,detected:!0})),...Ir.map(N=>({name:N.name,command:N.command,argsTemplate:N.argsTemplate,promptVia:N.promptVia??"arg",label:N.name,detected:!1}))];console.log(`
705
- ${I("Which agents should Alfred use?")} ${E("(comma-separated, e.g. 1,2)")}`);let v=new Set((t.config.codeAgents?.agents??[]).map(N=>N.name));for(let N=0;N<y.length;N++){let X=y[N],G=v.has(X.name)?` ${E("(current)")}`:"";console.log(` ${U}${N+1}${S}) ${X.label}${G}`)}console.log(` ${U}0${S}) None`);let R=y.map((N,X)=>v.size>0?v.has(N.name)?String(X+1):null:N.detected?String(X+1):null).filter(Boolean).join(",")||"0",W=(await c.question(` ${U}> ${S}${E(`[${R}] `)}`)).trim()||R;W!=="0"&&(Ce=W.split(",").map(X=>parseInt(X.trim(),10)).filter(X=>!isNaN(X)&&X>=1&&X<=y.length).map(X=>{let G=y[X-1];return{name:G.name,command:G.command,argsTemplate:G.argsTemplate,promptVia:G.promptVia}})),Ce.length>0?console.log(` ${O(">")} ${I(String(Ce.length))} agent(s) selected: ${Ce.map(N=>N.name).join(", ")}`):console.log(` ${E("No agents selected.")}`)}let Ar=t.config.codeAgents?.forge,Rr=Ar?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
706
- ${I("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 no=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let y of no){let v=y.name===Rr?` ${E("(current)")}`:"";console.log(` ${U}${y.num}${S}) ${y.label}${v}`)}let oo=Rr==="github"?"2":Rr==="gitlab"?"3":"1",Na=(await c.question(`${U}> ${S}${E(`[${oo}] `)}`)).trim()||oo,Oe=no.find(y=>y.num===Na)?.name??"",Ct="",Ot="";if(Oe==="github"){console.log(` ${O(">")} Forge: ${I("GitHub")}`);let y=t.env.ALFRED_GITHUB_TOKEN??Ar?.github?.token??"";y&&console.log(` ${E(`Current token: ${de(y)}`)}`),console.log(` ${E("Create a token at https://github.com/settings/tokens (scope: repo)")}`),Ct=(await c.question(` ${se}GitHub Token${S}: ${U}`)).trim(),process.stdout.write(S),!Ct&&y&&(Ct=y)}else if(Oe==="gitlab"){console.log(` ${O(">")} Forge: ${I("GitLab")}`);let y=t.env.ALFRED_GITLAB_TOKEN??Ar?.gitlab?.token??"";y&&console.log(` ${E(`Current token: ${de(y)}`)}`),console.log(` ${E("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),Ot=(await c.question(` ${se}GitLab Token${S}: ${U}`)).trim(),process.stdout.write(S),!Ot&&y&&(Ot=y)}else console.log(` ${E("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
707
- ${I("Infrastructure Management (Proxmox / UniFi)?")}`),console.log(`${E("Control VMs, containers, and network devices through Alfred.")}`);let Dt=t.config.proxmox,Lr=t.env.ALFRED_PROXMOX_BASE_URL??Dt?.baseUrl??"",Ca=Lr?"Y/n":"y/N",io=(await c.question(` ${se}Enable Proxmox VE?${S} ${E(`[${Ca}]`)}: ${U}`)).trim().toLowerCase()||(Lr?"y":"n");process.stdout.write(S);let Mr=io==="y"||io==="yes",Bs="",Nr="",Ut="",Cr=!0;if(Mr){Bs=await F(c," Proxmox URL (e.g. https://pve.local:8006)",Lr||"https://pve.local:8006");let y=t.env.ALFRED_PROXMOX_TOKEN_ID??Dt?.tokenId??"";y&&console.log(` ${E(`Current token ID: ${y}`)}`),console.log(` ${E("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),Nr=await F(c," API Token ID (user@realm!name)",y);let v=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Dt?.tokenSecret??"";v&&console.log(` ${E(`Current secret: ${de(v)}`)}`),Ut=(await c.question(` ${se}API Token Secret${S}: ${U}`)).trim(),process.stdout.write(S),!Ut&&v&&(Ut=v);let R=Dt?.verifyTls===!1?"y/N":"Y/n",W=(await c.question(` ${se}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${R}]`)}: ${U}`)).trim().toLowerCase()||(Dt?.verifyTls===!1?"n":"y");process.stdout.write(S),Cr=W==="y"||W==="yes",console.log(` ${O(">")} Proxmox: ${I(Bs)} ${E(`(TLS verify: ${Cr?"yes":"no"})`)}`)}else console.log(` ${E("Proxmox disabled.")}`);let De=t.config.unifi,Or=t.env.ALFRED_UNIFI_BASE_URL??De?.baseUrl??"",Oa=Or?"Y/n":"y/N",ao=(await c.question(`
708
- ${se}Enable UniFi Network?${S} ${E(`[${Oa}]`)}: ${U}`)).trim().toLowerCase()||(Or?"y":"n");process.stdout.write(S);let qs=ao==="y"||ao==="yes",Pt="",Ue="",Dr="",Ft="",Ur=!0;if(qs){Pt=await F(c," UniFi URL (e.g. https://unifi.local)",Or||"https://unifi.local"),console.log(` ${E("Auth: API Key (recommended) or Username/Password")}`);let y=t.env.ALFRED_UNIFI_API_KEY??De?.apiKey??"",v=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],R=y?"1":De?.username?"2":"1";for(let G of v)console.log(` ${U}${G.num}${S}) ${G.label}`);if(((await c.question(` ${U}> ${S}${E(`[${R}] `)}`)).trim()||R)==="1")y&&console.log(` ${E(`Current key: ${de(y)}`)}`),console.log(` ${E("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),Ue=(await c.question(` ${se}API Key${S}: ${U}`)).trim(),process.stdout.write(S),!Ue&&y&&(Ue=y);else{let G=t.env.ALFRED_UNIFI_USERNAME??De?.username??"";Dr=await F(c," Username",G||"alfred");let ge=t.env.ALFRED_UNIFI_PASSWORD??De?.password??"";ge&&console.log(` ${E(`Current password: ${de(ge)}`)}`),Ft=(await c.question(` ${se}Password${S}: ${U}`)).trim(),process.stdout.write(S),!Ft&&ge&&(Ft=ge)}let N=De?.verifyTls===!1?"y/N":"Y/n",X=(await c.question(` ${se}Verify TLS?${S} ${E(`(self-signed? \u2192 no) [${N}]`)}: ${U}`)).trim().toLowerCase()||(De?.verifyTls===!1?"n":"y");process.stdout.write(S),Ur=X==="y"||X==="yes",console.log(` ${O(">")} UniFi: ${I(Pt)} ${E(`(TLS verify: ${Ur?"yes":"no"})`)}`)}else console.log(` ${E("UniFi disabled.")}`);console.log(`
709
- ${I("Security configuration:")}`);let co=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",ie;if(co)ie=await F(c,"Owner user ID (for elevated permissions)",co);else{let y=(await c.question(`${se}Owner user ID${S} ${E("(optional, for elevated permissions)")}: ${U}`)).trim();process.stdout.write(S),ie=y}let jt=!1;if(ie){let y=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${I("Enable shell access (admin commands) for the owner?")}`),console.log(` ${E("Allows Alfred to execute shell commands. Only for the owner.")}`);let v=(await c.question(` ${U}> ${S}${E(`[${y}] `)}`)).trim().toLowerCase();v===""?jt=t.shellEnabled:jt=v==="y"||v==="yes",console.log(jt?` ${O(">")} Shell access ${I("enabled")} for owner ${E(ie)}`:` ${E("Shell access disabled.")}`)}let Da=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${I("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${E("By default, write actions are only allowed in DMs.")}`);let Pr=(await c.question(` ${U}> ${S}${E(`[${Da}] `)}`)).trim().toLowerCase(),Bt;Pr===""?Bt=t.writeInGroups:Bt=Pr==="y"||Pr==="yes",console.log(Bt?` ${O(">")} Write actions ${I("enabled")} in groups`:` ${E("Write actions only in DMs (default).")}`);let Ua=t.rateLimit??30;console.log("");let Pa=await F(c," Rate limit (max write actions per hour per user)",String(Ua)),Ws=Math.max(1,parseInt(Pa,10)||30);console.log(` ${O(">")} Rate limit: ${I(String(Ws))} per hour`),console.log(`
710
- ${I("Writing configuration files...")}`);let A=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let y=a.envKeyName||"ALFRED_OLLAMA_API_KEY";A.push(`${y}=${l}`)}if(f!==a.defaultModel&&A.push(`ALFRED_LLM_MODEL=${f}`),p&&A.push(`ALFRED_LLM_BASE_URL=${p}`),Object.keys(k).length>0){A.push("","# === Additional Model Tiers ===");for(let[y,v]of Object.entries(k)){let R=`ALFRED_LLM_${y.toUpperCase()}`;A.push(""),A.push(`${R}_PROVIDER=${v.provider}`),A.push(`${R}_MODEL=${v.model}`),v.apiKey&&A.push(`${R}_API_KEY=${v.apiKey}`),v.baseUrl&&A.push(`${R}_BASE_URL=${v.baseUrl}`)}}A.push("","# === Messaging Platforms ===","");for(let[y,v]of Object.entries(Te))A.push(`${y}=${v}`);A.push("","# === Web Search ===",""),K?(A.push(`ALFRED_SEARCH_PROVIDER=${K}`),te&&A.push(`ALFRED_SEARCH_API_KEY=${te}`),L&&A.push(`ALFRED_SEARCH_BASE_URL=${L}`)):(A.push("# ALFRED_SEARCH_PROVIDER=brave"),A.push("# ALFRED_SEARCH_API_KEY=")),A.push("","# === Email ===",""),Ds?(A.push(`ALFRED_EMAIL_USER=${ke}`),A.push(`ALFRED_EMAIL_PASS=${Us}`)):(A.push("# ALFRED_EMAIL_USER="),A.push("# ALFRED_EMAIL_PASS=")),A.push("","# === Speech ===",""),fe?(A.push(`ALFRED_SPEECH_PROVIDER=${fe}`),A.push(`ALFRED_SPEECH_API_KEY=${$e}`),Lt&&A.push(`ALFRED_SPEECH_BASE_URL=${Lt}`),Mt&&(A.push("ALFRED_TTS_ENABLED=true"),A.push(`ALFRED_TTS_VOICE=${Nt}`))):(A.push("# ALFRED_SPEECH_PROVIDER=groq"),A.push("# ALFRED_SPEECH_API_KEY=")),A.push("","# === Forge (GitHub / GitLab) ===",""),Oe==="github"?(A.push("ALFRED_FORGE_PROVIDER=github"),A.push(`ALFRED_GITHUB_TOKEN=${Ct}`)):Oe==="gitlab"?(A.push("ALFRED_FORGE_PROVIDER=gitlab"),A.push(`ALFRED_GITLAB_TOKEN=${Ot}`)):(A.push("# ALFRED_FORGE_PROVIDER=github"),A.push("# ALFRED_GITHUB_TOKEN=")),A.push("","# === Infrastructure (Proxmox / UniFi) ===",""),Mr?(A.push(`ALFRED_PROXMOX_BASE_URL=${Bs}`),A.push(`ALFRED_PROXMOX_TOKEN_ID=${Nr}`),A.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Ut}`)):(A.push("# ALFRED_PROXMOX_BASE_URL="),A.push("# ALFRED_PROXMOX_TOKEN_ID="),A.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),qs&&Ue?(A.push(`ALFRED_UNIFI_BASE_URL=${Pt}`),A.push(`ALFRED_UNIFI_API_KEY=${Ue}`)):qs?(A.push(`ALFRED_UNIFI_BASE_URL=${Pt}`),A.push(`ALFRED_UNIFI_USERNAME=${Dr}`),A.push(`ALFRED_UNIFI_PASSWORD=${Ft}`)):(A.push("# ALFRED_UNIFI_BASE_URL="),A.push("# ALFRED_UNIFI_API_KEY=")),A.push("","# === Security ===",""),ie?A.push(`ALFRED_OWNER_USER_ID=${ie}`):A.push("# ALFRED_OWNER_USER_ID="),A.push("");let Fa=re.join(e,".env");ee.writeFileSync(Fa,A.join(`
711
- `),"utf-8"),console.log(` ${O("+")} ${E(".env")} written`);let Xs=re.join(e,"config");ee.existsSync(Xs)||ee.mkdirSync(Xs,{recursive:!0});let lo={name:r,telegram:{token:oe.telegram?.token??"",enabled:q.some(y=>y.name==="telegram")},discord:{token:oe.discord?.token??"",enabled:q.some(y=>y.name==="discord")},whatsapp:{enabled:q.some(y=>y.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:oe.matrix?.homeserverUrl??"https://matrix.org",accessToken:oe.matrix?.accessToken??"",userId:oe.matrix?.userId??"",enabled:q.some(y=>y.name==="matrix")},signal:{apiUrl:oe.signal?.apiUrl??"http://localhost:8080",phoneNumber:oe.signal?.phoneNumber??"",enabled:q.some(y=>y.name==="signal")},llm:Object.keys(k).length>0?{default:{provider:a.name,model:f,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...k}:{provider:a.name,model:f,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...K?{search:{provider:K,...te?{apiKey:te}:{},...L?{baseUrl:L}:{}}}:{},...Ds?{email:{imap:{host:Ps,port:_r,secure:_r===993},smtp:{host:so,port:vr,secure:vr===465},auth:{user:ke,pass:Us}}}:{},...fe?{speech:{provider:fe,apiKey:$e,...Lt?{baseUrl:Lt}:{},...Mt?{ttsEnabled:!0,ttsVoice:Nt}:{}}}:{},...Sr?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...Ce.length>0||Oe?{codeAgents:{enabled:Ce.length>0,agents:Ce,...Oe==="github"?{forge:{provider:"github",github:{token:Ct}}}:Oe==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:Ot}}}:{}}}:{},...Mr?{proxmox:{baseUrl:Bs,tokenId:Nr,tokenSecret:Ut,verifyTls:Cr}}:{},...qs?{unifi:{baseUrl:Pt,...Ue?{apiKey:Ue}:{username:Dr,password:Ft},site:"default",verifyTls:Ur}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};ie&&(lo.security.ownerUserId=ie);let ja="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+Jn.dump(lo,{lineWidth:120,noRefs:!0,sortKeys:!1}),Ba=re.join(Xs,"default.yml");ee.writeFileSync(Ba,ja,"utf-8"),console.log(` ${O("+")} ${E("config/default.yml")} written`);let Fr=re.join(Xs,"rules");ee.existsSync(Fr)||ee.mkdirSync(Fr,{recursive:!0});let qa=jt&&ie?`
707
+ Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function ud(c){let e=new te,t;try{t=e.loadConfig()}catch(i){console.error("Failed to load configuration:",i.message),process.exit(1)}let s=t.api?.host??"127.0.0.1",r=t.api?.port??3420;if(await ld(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),dd(s,r);return}if(t.logger.level="warn",c.model&&(t.llm.default.model=c.model),c.tier){let i=t.llm[c.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${c.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new st(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var Ca=w(()=>{"use strict";Le();uo();u(ld,"checkHealth");u(dd,"startClientMode");u(ud,"chatCommand")});var Ua={};oe(Ua,{setupCommand:()=>_d});import{createInterface as md}from"node:readline/promises";import{stdin as pd,stdout as hd}from"node:process";import{execFileSync as fd}from"node:child_process";import se from"node:fs";import gd from"node:os";import ie from"node:path";import mo from"js-yaml";function C(c){return`${Ir}${c}${S}`}function bd(c){return`${D}${c}${S}`}function Te(c){return`${Ar}${c}${S}`}function Da(c){return`${yd}${c}${S}`}function A(c){return`${ee}${c}${S}`}function T(c){return`${Ue}${c}${S}`}function ue(c){return c.length<=4?"****":"*".repeat(c.length-4)+c.slice(-4)}function Td(c){let e=process.platform==="win32",t=e?"where":"which";try{let n=fd(t,[c],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=gd.homedir(),r=e?[ie.join(s,".local","bin",`${c}.exe`),ie.join(s,"AppData","Roaming","npm",`${c}.cmd`),ie.join(s,"AppData","Roaming","npm",`${c}`)]:[ie.join(s,".local","bin",c),"/usr/local/bin/"+c,"/opt/homebrew/bin/"+c,ie.join(s,".npm-global","bin",c)];for(let n of r)try{return se.accessSync(n,se.constants.X_OK),n}catch{}return null}function Ed(c){let e={},t={},s=!1,r=!1,n=30,o=ie.join(c,"config","default.yml");if(se.existsSync(o))try{let h=mo.load(se.readFileSync(o,"utf-8"));h&&typeof h=="object"&&Object.assign(e,h)}catch{}let i=ie.join(c,".env");if(se.existsSync(i))try{let h=se.readFileSync(i,"utf-8").split(`
708
+ `);for(let b of h){let y=b.trim();if(!y||y.startsWith("#"))continue;let g=y.indexOf("=");g>0&&(t[y.slice(0,g)]=y.slice(g+1))}}catch{}let a=ie.join(c,"config","rules","default-rules.yml");if(se.existsSync(a))try{let h=mo.load(se.readFileSync(a,"utf-8"));if(h?.rules){s=h.rules.some(g=>g.id==="allow-owner-admin"&&g.effect==="allow"),h.rules.find(g=>g.id==="allow-write-for-dm"||g.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let y=h.rules.find(g=>g.id==="rate-limit-write");y?.rateLimit?.maxInvocations&&(n=y.rateLimit.maxInvocations)}}catch{}let l=!!e.codeSandbox?.enabled,d=e.llm,m={};if(d){for(let h of["strong","fast","embeddings","local"])d[h]?.provider&&d[h]?.model&&(m[h]=d[h]);d.default?.provider&&(e.llm={...e.llm,provider:d.default.provider,model:d.default.model,baseUrl:d.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:l,multiModelTiers:m}}async function _d(){let c=md({input:pd,output:hd}),e=process.cwd(),t=Ed(e),s=Object.keys(t.config).length>0;try{$d(),console.log(s?`${Ar}Existing configuration found \u2014 press Enter to keep current values.${S}
709
+ ${Ue}Only change what you need to update.${S}
710
+ `:`${Ar}Welcome to the Alfred setup wizard!${S}
711
+ ${Ue}This will walk you through configuring your AI assistant.${S}
712
+ ${Ue}Press Enter to accept defaults shown in [brackets].${S}
713
+ `);let r=await U(c,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?De.findIndex(p=>p.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
714
+ ${A("Which LLM provider would you like to use?")}`);for(let p=0;p<De.length;p++){let _=p===n?` ${T("(current)")}`:"";console.log(` ${Te(String(p+1)+")")} ${De[p].label}${_}`)}let i=await xr(c,"> ",1,De.length,o),a=De[i-1];console.log(` ${C(">")} Selected: ${A(a.label)}`);let l="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?l=await U(c,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):l=await me(c,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${C(">")} API key set: ${T(ue(l))}`));let m=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let _=(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(` ${C(">")} URL: ${T(m)}`)}}let b=t.config.llm?.model??a.defaultModel;console.log("");let y;if(a.models&&a.models.length>0){console.log(`${A("Available models:")}`);for(let $=0;$<a.models.length;$++){let X=a.models[$],M=X.id===b?` ${C("(current)")}`:"";console.log(` ${Te(`${$+1})`)} ${X.id} ${T(`\u2014 ${X.desc}`)}${M}`)}console.log(` ${Te(`${a.models.length+1})`)} ${T("Other (enter manually)")}`);let p=await U(c,"Choose model","1"),_=parseInt(p,10)-1;_>=0&&_<a.models.length?y=a.models[_].id:_===a.models.length?y=await U(c,"Model ID",b):y=await U(c,"Model ID",b)}else y=await U(c,"Which model?",b);let g=Object.keys(t.multiModelTiers).length>0,E=g?"Y/n":"y/N";console.log(`
715
+ ${A("Configure additional model tiers for specialized tasks?")}`),console.log(`${T("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let v=(await c.question(`${D}> ${S}${T(`[${E}] `)}`)).trim().toLowerCase(),R=v===""?g:v==="y"||v==="yes",x={};if(R){let p=[{key:"strong",label:"Strong",hint:"complex reasoning, coding, long documents",defaultModel:"claude-opus-4-20250514"},{key:"fast",label:"Fast",hint:"quick responses, simple tasks",defaultModel:"claude-haiku-4-5-20251001"},{key:"embeddings",label:"Embeddings",hint:"semantic search & memory",defaultModel:"text-embedding-3-small"},{key:"local",label:"Local",hint:"offline fallback via Ollama",defaultModel:"llama3.2"}];for(let _ of p){let $=t.multiModelTiers[_.key],X=!!$?.model;console.log(`
716
+ ${A(`${_.label} model`)} ${T(`(${_.hint})`)}`),X&&console.log(` ${T(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${T("Press Enter to skip.")}`);let j=(await c.question(` ${D}Model: ${S}${X?T(`[${$.model}] `):""}`)).trim()||(X?$.model:"");if(!j){console.log(` ${T("Skipped.")}`);continue}let G=$?.provider??a.name,$e=De.map(Re=>Re.name).join(", ");console.log(` ${T(`Providers: ${$e}`)}`);let J=(await c.question(` ${D}Provider: ${S}${T(`[${G}] `)}`)).trim()||G,fe,Se;if(J!==a.name){let Re=$?.apiKey??t.env[`ALFRED_LLM_${_.key.toUpperCase()}_API_KEY`]??"";if(Re?fe=await U(c,` API key for ${J}`,Re):(De.find(nt=>nt.name===J)?.needsApiKey??!0)&&(fe=await me(c,` API key for ${J}`)),["ollama","openwebui"].includes(J)){let nt=($?.baseUrl??"")||De.find(Zr=>Zr.name===J)?.baseUrl||"";nt&&(Se=await U(c,` ${J} URL`,nt))}}x[_.key]={provider:J,model:j,...fe?{apiKey:fe}:{},...Se?{baseUrl:Se}:{}},console.log(` ${C(">")} ${_.label}: ${A(J)}/${A(j)}`)}Object.keys(x).length===0&&console.log(`
717
+ ${T("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${T("Using single model for all tasks.")}`);let O=["brave","tavily","duckduckgo","searxng"],N=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",B=O.indexOf(N),q=B>=0?B+1:0;console.log(`
718
+ ${A("Web Search provider (for searching the internet):")}`);let ae=["Brave Search \u2014 recommended, free tier (2,000/month)","Tavily \u2014 built for AI agents, free tier (1,000/month)","DuckDuckGo \u2014 free, no API key needed","SearXNG \u2014 self-hosted, no API key needed"],Pe=u(p=>B===p?` ${T("(current)")}`:"","mark");console.log(` ${Te("0)")} None (disable web search)${B===-1&&N===""?` ${T("(current)")}`:""}`);for(let p=0;p<ae.length;p++)console.log(` ${Te(String(p+1)+")")} ${ae[p]}${Pe(p)}`);let he=await xr(c,"> ",0,O.length,q),Y,re="",L="";if(he>=1&&he<=O.length&&(Y=O[he-1]),Y==="brave"){let p=t.env.ALFRED_SEARCH_API_KEY??"";p?re=await U(c," Brave Search API key",p):(console.log(` ${T("Get your free API key at: https://brave.com/search/api/")}`),re=await me(c," Brave Search API key")),console.log(` ${C(">")} Brave Search: ${T(ue(re))}`)}else if(Y==="tavily"){let p=t.env.ALFRED_SEARCH_API_KEY??"";p?re=await U(c," Tavily API key",p):(console.log(` ${T("Get your free API key at: https://tavily.com/")}`),re=await me(c," Tavily API key")),console.log(` ${C(">")} Tavily: ${T(ue(re))}`)}else if(Y==="duckduckgo")console.log(` ${C(">")} DuckDuckGo: ${T("no API key needed")}`);else if(Y==="searxng"){let p=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";L=await U(c," SearXNG URL",p),L=L.replace(/\/+$/,""),console.log(` ${C(">")} SearXNG: ${T(L)}`)}else console.log(` ${T("Web search disabled \u2014 you can configure it later.")}`);let W=[];for(let p=0;p<Dt.length;p++){let _=Dt[p];t.config[_.configKey]?.enabled&&W.push(p+1)}let F=W.length>0?W.join(","):"";console.log(`
719
+ ${A("Which messaging platforms do you want to enable?")}`),console.log(`${T("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let p=0;p<Dt.length;p++){let _=W.includes(p+1)?` ${T("(enabled)")}`:"";console.log(` ${Te(String(p+1)+")")} ${Dt[p].label}${_}`)}console.log(` ${Te("0)")} None (configure later)`);let V=(await c.question(`${D}> ${S}${F?T(`[${F}] `):""}`)).trim(),H=[],K=V||F;if(K&&K!=="0"){let p=K.split(",").map(_=>parseInt(_.trim(),10));for(let _ of p)if(_>=1&&_<=Dt.length){let $=Dt[_-1];H.includes($)||H.push($)}}H.length>0?console.log(` ${C(">")} Enabling: ${H.map(p=>A(p.label)).join(", ")}`):console.log(` ${T("No platforms selected \u2014 you can configure them later.")}`);let ce={},ke={};for(let p of H){if(p.credentials.length===0){p.name==="whatsapp"&&console.log(`
720
+ ${bd("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
721
+ ${A(p.label+" configuration:")}`);let _={};for(let $ of p.credentials){let X=t.env[$.envKey]??"",M;X?M=await U(c,` ${$.prompt}`,X):$.defaultValue?M=await U(c,` ${$.prompt}`,$.defaultValue):$.required?M=await me(c,` ${$.prompt}`):(M=(await c.question(` ${$.prompt}: ${D}`)).trim(),process.stdout.write(S)),_[$.configField]=M,ke[$.envKey]=M,$.configField==="token"||$.configField==="accessToken"?console.log(` ${C(">")} Set: ${T(ue(M))}`):console.log(` ${C(">")} Set: ${T(M)}`)}ce[p.configKey]=_}let Lr=t.config.email?.accounts??[],Mr=Lr[0],Ya=Mr?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",Ja=Mr?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",fo=Lr.length>0||!!Ya||Ja==="microsoft",Za=fo?"Y/n":"y/N";console.log(`
722
+ ${A("Email access (read & send emails)?")}`),console.log(`${T("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let Nr=(await c.question(`${D}> ${S}${T(`[${Za}] `)}`)).trim().toLowerCase(),zs=Nr===""?fo:Nr==="y"||Nr==="yes",Ee=[],Qa={"gmail.com":{imap:"imap.gmail.com",smtp:"smtp.gmail.com"},"googlemail.com":{imap:"imap.gmail.com",smtp:"smtp.gmail.com"},"outlook.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"hotmail.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"live.com":{imap:"outlook.office365.com",smtp:"smtp.office365.com"},"yahoo.com":{imap:"imap.mail.yahoo.com",smtp:"smtp.mail.yahoo.com"},"icloud.com":{imap:"imap.mail.me.com",smtp:"smtp.mail.me.com"},"me.com":{imap:"imap.mail.me.com",smtp:"smtp.mail.me.com"},"gmx.de":{imap:"imap.gmx.net",smtp:"mail.gmx.net"},"gmx.net":{imap:"imap.gmx.net",smtp:"mail.gmx.net"},"web.de":{imap:"imap.web.de",smtp:"smtp.web.de"},"posteo.de":{imap:"posteo.de",smtp:"posteo.de"},"mailbox.org":{imap:"imap.mailbox.org",smtp:"smtp.mailbox.org"},"protonmail.com":{imap:"127.0.0.1",smtp:"127.0.0.1"},"proton.me":{imap:"127.0.0.1",smtp:"127.0.0.1"}},go=u(async(p,_)=>{let $={name:p,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},X=_?.provider??"",M=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],j=X==="microsoft"?1:0;console.log("");for(let ne=0;ne<M.length;ne++){let J=ne===j?` ${T("(current)")}`:"";console.log(` ${Te(`${ne+1})`)} ${M[ne]}${J}`)}let G=(await c.question(`${D}> ${S}${T(`[${j+1}] `)}`)).trim(),$e=G===""?j:parseInt(G,10)-1;if($.provider=$e===1?"microsoft":"imap-smtp",$.provider==="microsoft"){let ne=t.config.calendar?.microsoft,J=_?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",fe=_?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",Se=_?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(ne&&!J)console.log(` ${C(">")} Microsoft Calendar already configured \u2014 credentials will be shared.`),console.log(` ${T("The same Azure App Registration will be used for Mail + Calendar.")}`),console.log(` ${T("Ensure the app has Mail.ReadWrite and Mail.Send scopes.")}`);else{console.log(` ${T("Azure Portal \u2192 App Registrations \u2192 your app \u2192 Mail.ReadWrite + Mail.Send scopes")}`),$.msClientId=await U(c," Client ID",J),$.msClientId||($.msClientId=await me(c," Client ID"));let Re=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";$.msClientSecret=await U(c," Client Secret",Re),$.msClientSecret||($.msClientSecret=await me(c," Client Secret")),$.msTenantId=await U(c," Tenant ID",fe),$.msTenantId||($.msTenantId=await me(c," Tenant ID")),$.msRefreshToken=await U(c," Refresh Token",Se),$.msRefreshToken||($.msRefreshToken=await me(c," Refresh Token"))}console.log(` ${C(">")} Email [${p}]: Microsoft 365 (Graph API)`)}else{let ne=_?.auth?.user??"";console.log(""),$.user=await U(c," Email address",ne||""),$.user||($.user=await me(c," Email address"));let J=_?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";J?$.pass=await U(c," Password / App password",J):(console.log(` ${T("For Gmail: use an App Password (not your regular password)")}`),console.log(` ${T(" \u2192 Google Account \u2192 Security \u2192 2-Step \u2192 App passwords")}`),$.pass=await me(c," Password / App password"));let fe=$.user.split("@")[1]?.toLowerCase()??"",Se=Qa[fe],Re=_?.imap?.host??Se?.imap??`imap.${fe}`,So=_?.smtp?.host??Se?.smtp??`smtp.${fe}`,Jr=_?.imap?.port??993,nt=_?.smtp?.port??587;Se&&console.log(` ${C(">")} Detected ${fe} \u2014 using preset server settings`),$.imapHost=await U(c," IMAP server",Re);let Zr=await U(c," IMAP port",String(Jr));$.imapPort=parseInt(Zr,10)||993,$.smtpHost=await U(c," SMTP server",So);let gc=await U(c," SMTP port",String(nt));$.smtpPort=parseInt(gc,10)||587,console.log(` ${C(">")} Email [${p}]: ${T($.user)} via ${T($.imapHost)}`)}return $},"configureEmailAccount");if(zs){let p=Mr??(t.config.email?.auth?{provider:t.config.email.provider,auth:t.config.email.auth,imap:t.config.email.imap,smtp:t.config.email.smtp,microsoft:t.config.email.microsoft}:void 0);Ee.push(await go("default",p));let _=!0;for(;_;){let $=(await c.question(`
723
+ ${A("Add another email account?")} ${T("[y/N]")} `)).trim().toLowerCase();if($==="y"||$==="yes"){let M=(await c.question(` ${A("Account name:")} `)).trim()||`account${Ee.length+1}`,j=Lr.find(G=>G.name===M);Ee.push(await go(M,j))}else _=!1}}else console.log(` ${T("Email disabled \u2014 you can configure it later.")}`);let Vs=["openai","groq"],ec=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",Ks=Vs.indexOf(ec),tc=Ks>=0?Ks+1:0;console.log(`
724
+ ${A("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${T("Transcribes voice messages from Telegram, Discord, etc.")}`);let yo=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Te("0)")} None (disable voice transcription)${Ks===-1?` ${T("(current)")}`:""}`);for(let p=0;p<yo.length;p++){let _=Ks===p?` ${T("(current)")}`:"";console.log(` ${Te(String(p+1)+")")} ${yo[p]}${_}`)}let Cr=await xr(c,"> ",0,Vs.length,tc),_e,Ae="",Ut="";if(Cr>=1&&Cr<=Vs.length&&(_e=Vs[Cr-1]),_e==="openai"){let p=t.env.ALFRED_SPEECH_API_KEY??"";p?Ae=await U(c," OpenAI API key (for Whisper)",p):(console.log(` ${T("Uses your OpenAI API key for Whisper transcription.")}`),Ae=await me(c," OpenAI API key")),console.log(` ${C(">")} OpenAI Whisper: ${T(ue(Ae))}`)}else if(_e==="groq"){let p=t.env.ALFRED_SPEECH_API_KEY??"";p?Ae=await U(c," Groq API key",p):(console.log(` ${T("Get your free API key at: https://console.groq.com/")}`),Ae=await me(c," Groq API key"));let _=t.env.ALFRED_SPEECH_BASE_URL??"";_&&(Ut=await U(c," Groq API URL",_)),console.log(` ${C(">")} Groq Whisper: ${T(ue(Ae))}`)}else console.log(` ${T("Voice transcription disabled \u2014 you can configure it later.")}`);let Pt=!1,Ft="alloy";if(_e){let p=t.config.speech?.ttsEnabled??!1,_=p?"Y/n":"y/N";console.log(`
725
+ ${A("Voice responses (Text-to-Speech)?")}`),console.log(`${T("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await c.question(`${D}> ${S}${T(`[${_}] `)}`)).trim().toLowerCase();if(Pt=$===""?p:$==="y"||$==="yes",Pt){let X=["alloy","echo","fable","onyx","nova","shimmer"],M=t.config.speech?.ttsVoice??"alloy",j=X.indexOf(M),G=j>=0?j+1:1;console.log(`
726
+ ${A("Which voice?")}`);for(let ne=0;ne<X.length;ne++){let J=j===ne?` ${T("(current)")}`:"";console.log(` ${Te(String(ne+1)+")")} ${X[ne]}${J}`)}let $e=await xr(c," > ",1,X.length,G);Ft=X[$e-1],console.log(` ${C(">")} TTS voice: ${A(Ft)}`)}else console.log(` ${T("Voice responses disabled.")}`)}let sc=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
727
+ ${A("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${T("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Or=(await c.question(`${D}> ${S}${T(`[${sc}] `)}`)).trim().toLowerCase(),Dr=Or===""?t.codeSandboxEnabled:Or==="y"||Or==="yes";console.log(Dr?` ${C(">")} Code Sandbox ${A("enabled")} (JavaScript + Python)`:` ${T("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
728
+ ${A("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${T("Scanning for known coding agents on this system...")}`);let Ur=[];for(let p of Oa){let _=Td(p.whichCmd);_?(Ur.push({...p,resolvedPath:_}),console.log(` ${C("\u2713")} ${A(p.label)} ${T(`(${_})`)}`)):console.log(` ${T("\xB7")} ${T(p.label)} ${T("\u2014 not found")}`)}let Pr=(t.config.codeAgents?.agents??[]).filter(p=>!Oa.some(_=>_.name===p.name));for(let p of Pr)console.log(` ${C("\u2713")} ${A(p.name)} ${T(`(${p.command}) \u2014 from existing config`)}`);let Fe=[];if(Ur.length===0&&Pr.length===0)console.log(`
729
+ ${T("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let p=[...Ur.map(M=>({name:M.name,command:M.resolvedPath??M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia,label:M.label,detected:!0})),...Pr.map(M=>({name:M.name,command:M.command,argsTemplate:M.argsTemplate,promptVia:M.promptVia??"arg",label:M.name,detected:!1}))];console.log(`
730
+ ${A("Which agents should Alfred use?")} ${T("(comma-separated, e.g. 1,2)")}`);let _=new Set((t.config.codeAgents?.agents??[]).map(M=>M.name));for(let M=0;M<p.length;M++){let j=p[M],G=_.has(j.name)?` ${T("(current)")}`:"";console.log(` ${D}${M+1}${S}) ${j.label}${G}`)}console.log(` ${D}0${S}) None`);let $=p.map((M,j)=>_.size>0?_.has(M.name)?String(j+1):null:M.detected?String(j+1):null).filter(Boolean).join(",")||"0",X=(await c.question(` ${D}> ${S}${T(`[${$}] `)}`)).trim()||$;X!=="0"&&(Fe=X.split(",").map(j=>parseInt(j.trim(),10)).filter(j=>!isNaN(j)&&j>=1&&j<=p.length).map(j=>{let G=p[j-1];return{name:G.name,command:G.command,argsTemplate:G.argsTemplate,promptVia:G.promptVia}})),Fe.length>0?console.log(` ${C(">")} ${A(String(Fe.length))} agent(s) selected: ${Fe.map(M=>M.name).join(", ")}`):console.log(` ${T("No agents selected.")}`)}let Fr=t.config.codeAgents?.forge,jr=Fr?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
731
+ ${A("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${T("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${T("Owner/repo are detected automatically from the git remote at runtime.")}`);let wo=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let p of wo){let _=p.name===jr?` ${T("(current)")}`:"";console.log(` ${D}${p.num}${S}) ${p.label}${_}`)}let bo=jr==="github"?"2":jr==="gitlab"?"3":"1",rc=(await c.question(`${D}> ${S}${T(`[${bo}] `)}`)).trim()||bo,je=wo.find(p=>p.num===rc)?.name??"",jt="",Bt="";if(je==="github"){console.log(` ${C(">")} Forge: ${A("GitHub")}`);let p=t.env.ALFRED_GITHUB_TOKEN??Fr?.github?.token??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create a token at https://github.com/settings/tokens (scope: repo)")}`),jt=(await c.question(` ${ee}GitHub Token${S}: ${D}`)).trim(),process.stdout.write(S),!jt&&p&&(jt=p)}else if(je==="gitlab"){console.log(` ${C(">")} Forge: ${A("GitLab")}`);let p=t.env.ALFRED_GITLAB_TOKEN??Fr?.gitlab?.token??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),Bt=(await c.question(` ${ee}GitLab Token${S}: ${D}`)).trim(),process.stdout.write(S),!Bt&&p&&(Bt=p)}else console.log(` ${T("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
732
+ ${A("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${T("Control VMs, containers, network devices, and smart home through Alfred.")}`);let qt=t.config.proxmox,Br=t.env.ALFRED_PROXMOX_BASE_URL??qt?.baseUrl??"",nc=Br?"Y/n":"y/N",To=(await c.question(` ${ee}Enable Proxmox VE?${S} ${T(`[${nc}]`)}: ${D}`)).trim().toLowerCase()||(Br?"y":"n");process.stdout.write(S);let Gs=To==="y"||To==="yes",Ht="",qr="",Wt="",Hr=!0;if(Gs){Ht=await U(c," Proxmox URL (e.g. https://pve.local:8006)",Br||"https://pve.local:8006");let p=t.env.ALFRED_PROXMOX_TOKEN_ID??qt?.tokenId??"";p&&console.log(` ${T(`Current token ID: ${p}`)}`),console.log(` ${T("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),qr=await U(c," API Token ID (user@realm!name)",p);let _=t.env.ALFRED_PROXMOX_TOKEN_SECRET??qt?.tokenSecret??"";_&&console.log(` ${T(`Current secret: ${ue(_)}`)}`),Wt=(await c.question(` ${ee}API Token Secret${S}: ${D}`)).trim(),process.stdout.write(S),!Wt&&_&&(Wt=_);let $=qt?.verifyTls===!1?"y/N":"Y/n",X=(await c.question(` ${ee}Verify TLS?${S} ${T(`(self-signed? \u2192 no) [${$}]`)}: ${D}`)).trim().toLowerCase()||(qt?.verifyTls===!1?"n":"y");process.stdout.write(S),Hr=X==="y"||X==="yes",console.log(` ${C(">")} Proxmox: ${A(Ht)} ${T(`(TLS verify: ${Hr?"yes":"no"})`)}`)}else console.log(` ${T("Proxmox disabled.")}`);let Be=t.config.unifi,Wr=t.env.ALFRED_UNIFI_BASE_URL??Be?.baseUrl??"",oc=Wr?"Y/n":"y/N",Eo=(await c.question(`
733
+ ${ee}Enable UniFi Network?${S} ${T(`[${oc}]`)}: ${D}`)).trim().toLowerCase()||(Wr?"y":"n");process.stdout.write(S);let Xt=Eo==="y"||Eo==="yes",rt="",qe="",Xr="",zt="",zr=!0;if(Xt){rt=await U(c," UniFi URL (e.g. https://unifi.local)",Wr||"https://unifi.local"),console.log(` ${T("Auth: API Key (recommended) or Username/Password")}`);let p=t.env.ALFRED_UNIFI_API_KEY??Be?.apiKey??"",_=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],$=p?"1":Be?.username?"2":"1";for(let G of _)console.log(` ${D}${G.num}${S}) ${G.label}`);if(((await c.question(` ${D}> ${S}${T(`[${$}] `)}`)).trim()||$)==="1")p&&console.log(` ${T(`Current key: ${ue(p)}`)}`),console.log(` ${T("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),qe=(await c.question(` ${ee}API Key${S}: ${D}`)).trim(),process.stdout.write(S),!qe&&p&&(qe=p);else{let G=t.env.ALFRED_UNIFI_USERNAME??Be?.username??"";Xr=await U(c," Username",G||"alfred");let $e=t.env.ALFRED_UNIFI_PASSWORD??Be?.password??"";$e&&console.log(` ${T(`Current password: ${ue($e)}`)}`),zt=(await c.question(` ${ee}Password${S}: ${D}`)).trim(),process.stdout.write(S),!zt&&$e&&(zt=$e)}let M=Be?.verifyTls===!1?"y/N":"Y/n",j=(await c.question(` ${ee}Verify TLS?${S} ${T(`(self-signed? \u2192 no) [${M}]`)}: ${D}`)).trim().toLowerCase()||(Be?.verifyTls===!1?"n":"y");process.stdout.write(S),zr=j==="y"||j==="yes",console.log(` ${C(">")} UniFi: ${A(rt)} ${T(`(TLS verify: ${zr?"yes":"no"})`)}`)}else console.log(` ${T("UniFi disabled.")}`);let Ys=t.config.homeassistant,Vr=t.env.ALFRED_HOMEASSISTANT_URL??Ys?.baseUrl??"",ic=Vr?"Y/n":"y/N",_o=(await c.question(`
734
+ ${ee}Enable Home Assistant?${S} ${T(`[${ic}]`)}: ${D}`)).trim().toLowerCase()||(Vr?"y":"n");process.stdout.write(S);let Js=_o==="y"||_o==="yes",Vt="",Kt="",Kr=!0;if(Js){Vt=await U(c," Home Assistant URL (e.g. http://homeassistant.local:8123)",Vr||"http://homeassistant.local:8123");let p=t.env.ALFRED_HOMEASSISTANT_TOKEN??Ys?.accessToken??"";p&&console.log(` ${T(`Current token: ${ue(p)}`)}`),console.log(` ${T("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),Kt=(await c.question(` ${ee}Long-Lived Access Token${S}: ${D}`)).trim(),process.stdout.write(S),!Kt&&p&&(Kt=p);let _=Ys?.verifyTls===!1?"y/N":"Y/n",$=(await c.question(` ${ee}Verify TLS?${S} ${T(`(self-signed? \u2192 no) [${_}]`)}: ${D}`)).trim().toLowerCase()||(Ys?.verifyTls===!1?"n":"y");process.stdout.write(S),Kr=$==="y"||$==="yes",console.log(` ${C(">")} Home Assistant: ${A(Vt)} ${T(`(TLS verify: ${Kr?"yes":"no"})`)}`)}else console.log(` ${T("Home Assistant disabled.")}`);console.log(`
735
+ ${A("Security configuration:")}`);let $o=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",le;if($o)le=await U(c,"Owner user ID (for elevated permissions)",$o);else{let p=(await c.question(`${ee}Owner user ID${S} ${T("(optional, for elevated permissions)")}: ${D}`)).trim();process.stdout.write(S),le=p}let Gt=!1;if(le){let p=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${A("Enable shell access (admin commands) for the owner?")}`),console.log(` ${T("Allows Alfred to execute shell commands. Only for the owner.")}`);let _=(await c.question(` ${D}> ${S}${T(`[${p}] `)}`)).trim().toLowerCase();_===""?Gt=t.shellEnabled:Gt=_==="y"||_==="yes",console.log(Gt?` ${C(">")} Shell access ${A("enabled")} for owner ${T(le)}`:` ${T("Shell access disabled.")}`)}let ac=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${A("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${T("By default, write actions are only allowed in DMs.")}`);let Gr=(await c.question(` ${D}> ${S}${T(`[${ac}] `)}`)).trim().toLowerCase(),Yt;Gr===""?Yt=t.writeInGroups:Yt=Gr==="y"||Gr==="yes",console.log(Yt?` ${C(">")} Write actions ${A("enabled")} in groups`:` ${T("Write actions only in DMs (default).")}`);let cc=t.rateLimit??30;console.log("");let lc=await U(c," Rate limit (max write actions per hour per user)",String(cc)),Zs=Math.max(1,parseInt(lc,10)||30);console.log(` ${C(">")} Rate limit: ${A(String(Zs))} per hour`),console.log(`
736
+ ${A("Writing configuration files...")}`);let k=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(l){let p=a.envKeyName||"ALFRED_OLLAMA_API_KEY";k.push(`${p}=${l}`)}if(y!==a.defaultModel&&k.push(`ALFRED_LLM_MODEL=${y}`),m&&k.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(x).length>0){k.push("","# === Additional Model Tiers ===");for(let[p,_]of Object.entries(x)){let $=`ALFRED_LLM_${p.toUpperCase()}`;k.push(""),k.push(`${$}_PROVIDER=${_.provider}`),k.push(`${$}_MODEL=${_.model}`),_.apiKey&&k.push(`${$}_API_KEY=${_.apiKey}`),_.baseUrl&&k.push(`${$}_BASE_URL=${_.baseUrl}`)}}k.push("","# === Messaging Platforms ===","");for(let[p,_]of Object.entries(ke))k.push(`${p}=${_}`);if(k.push("","# === Web Search ===",""),Y?(k.push(`ALFRED_SEARCH_PROVIDER=${Y}`),re&&k.push(`ALFRED_SEARCH_API_KEY=${re}`),L&&k.push(`ALFRED_SEARCH_BASE_URL=${L}`)):(k.push("# ALFRED_SEARCH_PROVIDER=brave"),k.push("# ALFRED_SEARCH_API_KEY=")),k.push("","# === Email ===",""),zs&&Ee.length>0){let p=Ee[0];p.provider==="microsoft"?(k.push("ALFRED_EMAIL_PROVIDER=microsoft"),p.msClientId?(k.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${p.msClientId}`),k.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${p.msClientSecret}`),k.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${p.msTenantId}`),k.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${p.msRefreshToken}`)):k.push("# Microsoft email credentials shared from calendar config")):(k.push(`ALFRED_EMAIL_USER=${p.user}`),k.push(`ALFRED_EMAIL_PASS=${p.pass}`)),Ee.length>1&&k.push("# Additional email accounts configured in config/default.yml")}else k.push("# ALFRED_EMAIL_USER="),k.push("# ALFRED_EMAIL_PASS=");k.push("","# === Speech ===",""),_e?(k.push(`ALFRED_SPEECH_PROVIDER=${_e}`),k.push(`ALFRED_SPEECH_API_KEY=${Ae}`),Ut&&k.push(`ALFRED_SPEECH_BASE_URL=${Ut}`),Pt&&(k.push("ALFRED_TTS_ENABLED=true"),k.push(`ALFRED_TTS_VOICE=${Ft}`))):(k.push("# ALFRED_SPEECH_PROVIDER=groq"),k.push("# ALFRED_SPEECH_API_KEY=")),k.push("","# === Forge (GitHub / GitLab) ===",""),je==="github"?(k.push("ALFRED_FORGE_PROVIDER=github"),k.push(`ALFRED_GITHUB_TOKEN=${jt}`)):je==="gitlab"?(k.push("ALFRED_FORGE_PROVIDER=gitlab"),k.push(`ALFRED_GITLAB_TOKEN=${Bt}`)):(k.push("# ALFRED_FORGE_PROVIDER=github"),k.push("# ALFRED_GITHUB_TOKEN=")),k.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Gs?(k.push(`ALFRED_PROXMOX_BASE_URL=${Ht}`),k.push(`ALFRED_PROXMOX_TOKEN_ID=${qr}`),k.push(`ALFRED_PROXMOX_TOKEN_SECRET=${Wt}`)):(k.push("# ALFRED_PROXMOX_BASE_URL="),k.push("# ALFRED_PROXMOX_TOKEN_ID="),k.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),Xt&&qe?(k.push(`ALFRED_UNIFI_BASE_URL=${rt}`),k.push(`ALFRED_UNIFI_API_KEY=${qe}`)):Xt?(k.push(`ALFRED_UNIFI_BASE_URL=${rt}`),k.push(`ALFRED_UNIFI_USERNAME=${Xr}`),k.push(`ALFRED_UNIFI_PASSWORD=${zt}`)):(k.push("# ALFRED_UNIFI_BASE_URL="),k.push("# ALFRED_UNIFI_API_KEY=")),Js?(k.push(`ALFRED_HOMEASSISTANT_URL=${Vt}`),k.push(`ALFRED_HOMEASSISTANT_TOKEN=${Kt}`)):(k.push("# ALFRED_HOMEASSISTANT_URL="),k.push("# ALFRED_HOMEASSISTANT_TOKEN=")),k.push("","# === Security ===",""),le?k.push(`ALFRED_OWNER_USER_ID=${le}`):k.push("# ALFRED_OWNER_USER_ID="),k.push("");let dc=ie.join(e,".env");se.writeFileSync(dc,k.join(`
737
+ `),"utf-8"),console.log(` ${C("+")} ${T(".env")} written`);let Qs=ie.join(e,"config");se.existsSync(Qs)||se.mkdirSync(Qs,{recursive:!0});let vo={name:r,telegram:{token:ce.telegram?.token??"",enabled:H.some(p=>p.name==="telegram")},discord:{token:ce.discord?.token??"",enabled:H.some(p=>p.name==="discord")},whatsapp:{enabled:H.some(p=>p.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:ce.matrix?.homeserverUrl??"https://matrix.org",accessToken:ce.matrix?.accessToken??"",userId:ce.matrix?.userId??"",enabled:H.some(p=>p.name==="matrix")},signal:{apiUrl:ce.signal?.apiUrl??"http://localhost:8080",phoneNumber:ce.signal?.phoneNumber??"",enabled:H.some(p=>p.name==="signal")},llm:Object.keys(x).length>0?{default:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...x}:{provider:a.name,model:y,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...Y?{search:{provider:Y,...re?{apiKey:re}:{},...L?{baseUrl:L}:{}}}:{},...zs&&Ee.length>0?{email:{accounts:Ee.map(p=>p.provider==="microsoft"?{name:p.name,provider:"microsoft",...p.msClientId?{microsoft:{clientId:p.msClientId,clientSecret:p.msClientSecret,tenantId:p.msTenantId,refreshToken:p.msRefreshToken}}:{}}:{name:p.name,imap:{host:p.imapHost,port:p.imapPort,secure:p.imapPort===993},smtp:{host:p.smtpHost,port:p.smtpPort,secure:p.smtpPort===465},auth:{user:p.user,pass:p.pass}})}}:{},..._e?{speech:{provider:_e,apiKey:Ae,...Ut?{baseUrl:Ut}:{},...Pt?{ttsEnabled:!0,ttsVoice:Ft}:{}}}:{},...Dr?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...Fe.length>0||je?{codeAgents:{enabled:Fe.length>0,agents:Fe,...je==="github"?{forge:{provider:"github",github:{token:jt}}}:je==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:Bt}}}:{}}}:{},...Gs?{proxmox:{baseUrl:Ht,tokenId:qr,tokenSecret:Wt,verifyTls:Hr}}:{},...Xt?{unifi:{baseUrl:rt,...qe?{apiKey:qe}:{username:Xr,password:zt},site:"default",verifyTls:zr}}:{},...Js?{homeassistant:{baseUrl:Vt,accessToken:Kt,verifyTls:Kr}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};le&&(vo.security.ownerUserId=le);let uc="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+mo.dump(vo,{lineWidth:120,noRefs:!0,sortKeys:!1}),mc=ie.join(Qs,"default.yml");se.writeFileSync(mc,uc,"utf-8"),console.log(` ${C("+")} ${T("config/default.yml")} written`);let Yr=ie.join(Qs,"rules");se.existsSync(Yr)||se.mkdirSync(Yr,{recursive:!0});let pc=Gt&&le?`
712
738
  # Allow admin actions (shell, etc.) for the owner only
713
739
  - id: allow-owner-admin
714
740
  effect: allow
@@ -717,7 +743,7 @@ ${I("Writing configuration files...")}`);let A=["# Alfred Environment Variables"
717
743
  actions: ["*"]
718
744
  riskLevels: [admin, destructive]
719
745
  conditions:
720
- users: ["${ie}"]
746
+ users: ["${le}"]
721
747
  `:`
722
748
  # Allow admin actions (shell, etc.) for the owner only
723
749
  # Uncomment and set your user ID to enable:
@@ -728,8 +754,8 @@ ${I("Writing configuration files...")}`);let A=["# Alfred Environment Variables"
728
754
  # actions: ["*"]
729
755
  # riskLevels: [admin, destructive]
730
756
  # conditions:
731
- # users: ["${ie||"YOUR_USER_ID_HERE"}"]
732
- `,Wa=`# Alfred \u2014 Default Security Rules
757
+ # users: ["${le||"YOUR_USER_ID_HERE"}"]
758
+ `,hc=`# Alfred \u2014 Default Security Rules
733
759
  # Rules are evaluated in priority order (lower number = higher priority).
734
760
  # First matching rule wins.
735
761
 
@@ -742,7 +768,7 @@ rules:
742
768
  actions: ["*"]
743
769
  riskLevels: [read]
744
770
 
745
- ${Bt?` # Allow write-level skills everywhere (DMs and groups)
771
+ ${Yt?` # Allow write-level skills everywhere (DMs and groups)
746
772
  - id: allow-write-all
747
773
  effect: allow
748
774
  priority: 200
@@ -758,7 +784,7 @@ ${Bt?` # Allow write-level skills everywhere (DMs and groups)
758
784
  conditions:
759
785
  chatType: dm`}
760
786
 
761
- # Rate-limit write actions: max ${Ws} per hour per user
787
+ # Rate-limit write actions: max ${Zs} per hour per user
762
788
  - id: rate-limit-write
763
789
  effect: allow
764
790
  priority: 250
@@ -766,9 +792,9 @@ ${Bt?` # Allow write-level skills everywhere (DMs and groups)
766
792
  actions: ["*"]
767
793
  riskLevels: [write]
768
794
  rateLimit:
769
- maxInvocations: ${Ws}
795
+ maxInvocations: ${Zs}
770
796
  windowSeconds: 3600
771
- ${qa}
797
+ ${pc}
772
798
  # Deny destructive and admin actions by default
773
799
  - id: deny-destructive
774
800
  effect: deny
@@ -784,15 +810,15 @@ ${qa}
784
810
  scope: global
785
811
  actions: ["*"]
786
812
  riskLevels: [read, write, destructive, admin]
787
- `,Xa=re.join(Fr,"default-rules.yml");ee.writeFileSync(Xa,Wa,"utf-8"),console.log(` ${O("+")} ${E("config/rules/default-rules.yml")} written`);let uo=re.join(e,"data");ee.existsSync(uo)||(ee.mkdirSync(uo,{recursive:!0}),console.log(` ${O("+")} ${E("data/")} directory created`)),console.log(""),console.log(`${wr}${"=".repeat(52)}${S}`),console.log(`${wr}${se} Setup complete!${S}`),console.log(`${wr}${"=".repeat(52)}${S}`),console.log(""),console.log(` ${I("Bot name:")} ${r}`),console.log(` ${I("LLM default:")} ${a.name} (${f})`),l&&console.log(` ${I("API key:")} ${de(l)}`);for(let[y,v]of Object.entries(k)){let R=y.charAt(0).toUpperCase()+y.slice(1);console.log(` ${I(`LLM ${R}:`)}${" ".repeat(Math.max(1,10-R.length))}${v.provider} (${v.model})`)}if(q.length>0?console.log(` ${I("Platforms:")} ${q.map(y=>y.label).join(", ")}`):console.log(` ${I("Platforms:")} none (configure later)`),K){let y={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${L})`};console.log(` ${I("Web search:")} ${y[K]}`)}else console.log(` ${I("Web search:")} ${E("disabled")}`);if(console.log(Ds?` ${I("Email:")} ${ke} (${Ps})`:` ${I("Email:")} ${E("disabled")}`),fe){let y={openai:"OpenAI Whisper",groq:"Groq Whisper"},v=Mt?`, TTS: ${Nt}`:"";console.log(` ${I("Voice:")} ${y[fe]}${v}`)}else console.log(` ${I("Voice:")} ${E("disabled")}`);console.log(` ${I("Code Sandbox:")} ${Sr?O("enabled"):E("disabled")}`),ie&&(console.log(` ${I("Owner ID:")} ${ie}`),console.log(` ${I("Shell access:")} ${jt?O("enabled"):E("disabled")}`)),console.log(` ${I("Write scope:")} ${Bt?"DMs + Groups":"DMs only"}`),console.log(` ${I("Rate limit:")} ${Ws}/hour per user`),console.log(""),console.log(`${br}Next steps:${S}`),console.log(` ${I("alfred start")} Start Alfred`),console.log(` ${I("alfred status")} Check configuration`),console.log(` ${I("alfred --help")} Show all commands`),console.log(""),console.log(`${Me}Edit ${I(".env")}${Me} or ${I("config/default.yml")}${Me} for manual configuration.${S}`),console.log("")}finally{c.close()}}async function F(c,e,t){let s=(await c.question(`${se}${e}${S} ${E(`[${t}]`)}: ${U}`)).trim();return process.stdout.write(S),s||t}async function ve(c,e){for(;;){let t=(await c.question(`${se}${e}${S}: ${U}`)).trim();if(process.stdout.write(S),t)return t;console.log(` ${fa("!")} This field is required. Please enter a value.`)}}async function yr(c,e,t,s,r){for(;;){let n=(await c.question(`${U}${e}${S}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${fa("!")} Please enter a number between ${t} and ${s}.`)}}function Jl(){console.log(`
788
- ${Vl}${se} _ _ _____ ____ _____ ____
813
+ `,fc=ie.join(Yr,"default-rules.yml");se.writeFileSync(fc,hc,"utf-8"),console.log(` ${C("+")} ${T("config/rules/default-rules.yml")} written`);let ko=ie.join(e,"data");se.existsSync(ko)||(se.mkdirSync(ko,{recursive:!0}),console.log(` ${C("+")} ${T("data/")} directory created`)),console.log(""),console.log(`${Ir}${"=".repeat(52)}${S}`),console.log(`${Ir}${ee} Setup complete!${S}`),console.log(`${Ir}${"=".repeat(52)}${S}`),console.log(""),console.log(` ${A("Bot name:")} ${r}`),console.log(` ${A("LLM default:")} ${a.name} (${y})`),l&&console.log(` ${A("API key:")} ${ue(l)}`);for(let[p,_]of Object.entries(x)){let $=p.charAt(0).toUpperCase()+p.slice(1);console.log(` ${A(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${_.provider} (${_.model})`)}if(H.length>0?console.log(` ${A("Platforms:")} ${H.map(p=>p.label).join(", ")}`):console.log(` ${A("Platforms:")} none (configure later)`),Y){let p={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${L})`};console.log(` ${A("Web search:")} ${p[Y]}`)}else console.log(` ${A("Web search:")} ${T("disabled")}`);if(zs&&Ee.length>0){let p=Ee.map(_=>_.provider==="microsoft"?`${_.name} (Microsoft 365)${_.msClientId?"":" \u2014 shared from Calendar"}`:`${_.name} (${_.imapHost})`);console.log(` ${A("Email:")} ${p.join(", ")}`)}else console.log(` ${A("Email:")} ${T("disabled")}`);if(_e){let p={openai:"OpenAI Whisper",groq:"Groq Whisper"},_=Pt?`, TTS: ${Ft}`:"";console.log(` ${A("Voice:")} ${p[_e]}${_}`)}else console.log(` ${A("Voice:")} ${T("disabled")}`);console.log(` ${A("Code Sandbox:")} ${Dr?C("enabled"):T("disabled")}`),Gs&&console.log(` ${A("Proxmox:")} ${C(Ht)}`),Xt&&console.log(` ${A("UniFi:")} ${C(rt)}`),Js&&console.log(` ${A("Home Assist.:")} ${C(Vt)}`),le&&(console.log(` ${A("Owner ID:")} ${le}`),console.log(` ${A("Shell access:")} ${Gt?C("enabled"):T("disabled")}`)),console.log(` ${A("Write scope:")} ${Yt?"DMs + Groups":"DMs only"}`),console.log(` ${A("Rate limit:")} ${Zs}/hour per user`),console.log(""),console.log(`${Ar}Next steps:${S}`),console.log(` ${A("alfred start")} Start Alfred`),console.log(` ${A("alfred status")} Check configuration`),console.log(` ${A("alfred --help")} Show all commands`),console.log(""),console.log(`${Ue}Edit ${A(".env")}${Ue} or ${A("config/default.yml")}${Ue} for manual configuration.${S}`),console.log("")}finally{c.close()}}async function U(c,e,t){let s=(await c.question(`${ee}${e}${S} ${T(`[${t}]`)}: ${D}`)).trim();return process.stdout.write(S),s||t}async function me(c,e){for(;;){let t=(await c.question(`${ee}${e}${S}: ${D}`)).trim();if(process.stdout.write(S),t)return t;console.log(` ${Da("!")} This field is required. Please enter a value.`)}}async function xr(c,e,t,s,r){for(;;){let n=(await c.question(`${D}${e}${S}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Da("!")} Please enter a number between ${t} and ${s}.`)}}function $d(){console.log(`
814
+ ${wd}${ee} _ _ _____ ____ _____ ____
789
815
  / \\ | | | ___| _ \\| ____| _ \\
790
816
  / _ \\ | | | |_ | |_) | _| | | | |
791
817
  / ___ \\| |___| _| | _ <| |___| |_| |
792
818
  /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${S}
793
- ${Me} Personal AI Assistant \u2014 Setup Wizard${S}
794
- `)}var S,se,Me,wr,U,br,Hl,Vl,Le,Rt,ha,ya=b(()=>{"use strict";S="\x1B[0m",se="\x1B[1m",Me="\x1B[2m",wr="\x1B[32m",U="\x1B[33m",br="\x1B[36m",Hl="\x1B[31m",Vl="\x1B[35m";u(O,"green");u(zl,"yellow");u(be,"cyan");u(fa,"red");u(I,"bold");u(E,"dim");u(de,"maskKey");Le=[{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"}]}],Rt=[{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(Kl,"findCommand");ha=[{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(Gl,"loadExistingConfig");u(Yl,"setupCommand");u(F,"askWithDefault");u(ve,"askRequired");u(yr,"askNumber");u(Jl,"printBanner")});var ba={};le(ba,{configCommand:()=>td});function Ql(c){let e=c.toLowerCase();return Zl.some(t=>e.includes(t))}function ed(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function wa(c){let e={};for(let[t,s]of Object.entries(c))Ql(t)?e[t]=ed(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=wa(s):e[t]=s;return e}async function td(){let c=new Q,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=wa(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Zl,Ta=b(()=>{"use strict";xe();Zl=["token","apikey","api_key","accesstoken","secret","password"];u(Ql,"isSensitiveKey");u(ed,"redactValue");u(wa,"redactObject");u(td,"configCommand")});var _a={};le(_a,{rulesCommand:()=>rd});import Tr from"node:fs";import Ea from"node:path";import sd from"js-yaml";async function rd(){let c=new Q,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ea.resolve(e.security.rulesPath);if(!Tr.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Tr.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Tr.readdirSync(t).filter(a=>a.endsWith(".yml")||a.endsWith(".yaml"));if(r.length===0){console.log(`No YAML rule files found in: ${t}`);return}let n=new We,o=[],i=[];for(let a of r){let l=Ea.join(t,a);try{let d=Tr.readFileSync(l,"utf-8"),p=sd.load(d),m=n.loadFromObject(p);o.push(...m)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,l)=>a.priority-l.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let l=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${l}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var va=b(()=>{"use strict";xe();Ys();u(rd,"rulesCommand")});var ka={};le(ka,{statusCommand:()=>od});import Os from"node:fs";import Zn from"node:path";import nd from"js-yaml";async function od(){let c=new Q,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",p=l.enabled?"+":"-";console.log(` [${p}] ${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=Zn.resolve(e.storage.path),n=Os.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Zn.resolve(e.security.rulesPath),i=0,a=0;if(Os.existsSync(o)&&Os.statSync(o).isDirectory()){let l=Os.readdirSync(o).filter(p=>p.endsWith(".yml")||p.endsWith(".yaml"));a=l.length;let d=new We;for(let p of l){let m=Zn.join(o,p);try{let g=Os.readFileSync(m,"utf-8"),f=nd.load(g),h=d.loadFromObject(f);i+=h.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var $a=b(()=>{"use strict";xe();Ys();u(od,"statusCommand")});var Sa={};le(Sa,{logsCommand:()=>cd});import id from"node:fs";import ad from"node:path";async function cd(c){let e=new Q,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=ad.resolve(t.storage.path);if(!id.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 Fe(s);let n=new je(r.getDb()),o=n.count({}),i=n.query({limit:c});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(c,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let l=a.timestamp.toISOString(),d=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${l} [${d}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var xa=b(()=>{"use strict";xe();Yr();u(cd,"logsCommand")});import{readFileSync as ld}from"node:fs";import{fileURLToPath as dd}from"node:url";import{dirname as ud,join as pd}from"node:path";function md(){try{let c=ud(dd(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(ld(pd(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(md,"getVersion");var Ia=md(),Qn=`
795
- Alfred CLI v${Ia}
819
+ ${Ue} Personal AI Assistant \u2014 Setup Wizard${S}
820
+ `)}var S,ee,Ue,Ir,D,Ar,yd,wd,De,Dt,Oa,Pa=w(()=>{"use strict";S="\x1B[0m",ee="\x1B[1m",Ue="\x1B[2m",Ir="\x1B[32m",D="\x1B[33m",Ar="\x1B[36m",yd="\x1B[31m",wd="\x1B[35m";u(C,"green");u(bd,"yellow");u(Te,"cyan");u(Da,"red");u(A,"bold");u(T,"dim");u(ue,"maskKey");De=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0,models:[{id:"claude-sonnet-4-20250514",desc:"Sonnet 4 \u2014 fast, smart, recommended"},{id:"claude-opus-4-20250514",desc:"Opus 4 \u2014 most capable, slower"},{id:"claude-haiku-4-5-20251001",desc:"Haiku 4.5 \u2014 fastest, cheapest"}]},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0,models:[{id:"gpt-4o",desc:"GPT-4o \u2014 flagship, 128k context"},{id:"gpt-4o-mini",desc:"GPT-4o Mini \u2014 fast, cheap, 128k context"},{id:"o3-mini",desc:"o3-mini \u2014 reasoning, 200k context"}]},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0,models:[{id:"gemini-2.0-flash",desc:"Flash 2.0 \u2014 fast, 1M context"},{id:"gemini-2.0-pro",desc:"Pro 2.0 \u2014 capable, 1M context"},{id:"gemini-1.5-pro",desc:"Pro 1.5 \u2014 2M context"},{id:"gemini-1.5-flash",desc:"Flash 1.5 \u2014 fast, 1M context"}]},{name:"mistral",label:"Mistral AI",defaultModel:"mistral-small-latest",envKeyName:"ALFRED_MISTRAL_API_KEY",needsApiKey:!0,models:[{id:"mistral-small-latest",desc:"Small 3.2 \u2014 fast, 128k context, best value"},{id:"mistral-medium-latest",desc:"Medium 3.1 \u2014 balanced, 128k context"},{id:"mistral-large-latest",desc:"Large 3 \u2014 flagship, 256k context"},{id:"codestral-latest",desc:"Codestral \u2014 code-optimized, 256k context"},{id:"magistral-medium-latest",desc:"Magistral Medium \u2014 reasoning, 40k context"},{id:"magistral-small-latest",desc:"Magistral Small \u2014 reasoning (light), 40k context"},{id:"ministral-8b-latest",desc:"Ministral 8B \u2014 edge/tiny, 128k context"}]}],Dt=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];u(Td,"findCommand");Oa=[{name:"claude-code",label:"Claude Code",command:"claude",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"claude"},{name:"codex",label:"OpenAI Codex CLI",command:"codex",argsTemplate:["{{prompt}}"],promptVia:"arg",whichCmd:"codex"},{name:"aider",label:"Aider",command:"aider",argsTemplate:["--message","{{prompt}}"],promptVia:"arg",whichCmd:"aider"},{name:"gemini",label:"Gemini CLI",command:"gemini",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"gemini"}];u(Ed,"loadExistingConfig");u(_d,"setupCommand");u(U,"askWithDefault");u(me,"askRequired");u(xr,"askNumber");u($d,"printBanner")});var ja={};oe(ja,{configCommand:()=>xd});function kd(c){let e=c.toLowerCase();return vd.some(t=>e.includes(t))}function Sd(c){return typeof c!="string"||c.length===0?"(empty)":c.length<=8?"***":c.slice(0,4)+"..."+c.slice(-4)}function Fa(c){let e={};for(let[t,s]of Object.entries(c))kd(t)?e[t]=Sd(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Fa(s):e[t]=s;return e}async function xd(){let c=new te,e;try{e=c.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Fa(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var vd,Ba=w(()=>{"use strict";Le();vd=["token","apikey","api_key","accesstoken","secret","password"];u(kd,"isSensitiveKey");u(Sd,"redactValue");u(Fa,"redactObject");u(xd,"configCommand")});var Ha={};oe(Ha,{rulesCommand:()=>Ad});import Rr from"node:fs";import qa from"node:path";import Id from"js-yaml";async function Ad(){let c=new te,e;try{e=c.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=qa.resolve(e.security.rulesPath);if(!Rr.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Rr.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Rr.readdirSync(t).filter(a=>a.endsWith(".yml")||a.endsWith(".yaml"));if(r.length===0){console.log(`No YAML rule files found in: ${t}`);return}let n=new Ke,o=[],i=[];for(let a of r){let l=qa.join(t,a);try{let d=Rr.readFileSync(l,"utf-8"),m=Id.load(d),h=n.loadFromObject(m);o.push(...h)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,l)=>a.priority-l.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let l=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${l}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Wa=w(()=>{"use strict";Le();sr();u(Ad,"rulesCommand")});var Xa={};oe(Xa,{statusCommand:()=>Ld});import Xs from"node:fs";import po from"node:path";import Rd from"js-yaml";async function Ld(){let c=new te,e;try{e=c.loadConfig()}catch(l){console.error("Failed to load configuration:",l.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let l of t){let d=l.enabled?"enabled":l.configured?"configured (disabled)":"not configured",m=l.enabled?"+":"-";console.log(` [${m}] ${l.name}: ${d}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let l of["strong","fast","embeddings","local"]){let d=e.llm[l];d&&console.log(` ${l}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=po.resolve(e.storage.path),n=Xs.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=po.resolve(e.security.rulesPath),i=0,a=0;if(Xs.existsSync(o)&&Xs.statSync(o).isDirectory()){let l=Xs.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=l.length;let d=new Ke;for(let m of l){let h=po.join(o,m);try{let b=Xs.readFileSync(h,"utf-8"),y=Rd.load(b),g=d.loadFromObject(y);i+=g.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var za=w(()=>{"use strict";Le();sr();u(Ld,"statusCommand")});var Va={};oe(Va,{logsCommand:()=>Cd});import Md from"node:fs";import Nd from"node:path";async function Cd(c){let e=new te,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=Nd.resolve(t.storage.path);if(!Md.existsSync(s)){console.log(`Database not found at: ${s}`),console.log("No audit log entries. Alfred has not been run yet, or the database path is incorrect.");return}let r;try{r=new We(s);let n=new Xe(r.getDb()),o=n.count({}),i=n.query({limit:c});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(c,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let l=a.timestamp.toISOString(),d=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${l} [${d}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var Ka=w(()=>{"use strict";Le();ln();u(Cd,"logsCommand")});import{readFileSync as Od}from"node:fs";import{fileURLToPath as Dd}from"node:url";import{dirname as Ud,join as Pd}from"node:path";function Fd(){try{let c=Ud(Dd(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Od(Pd(c,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(Fd,"getVersion");var Ga=Fd(),ho=`
821
+ Alfred CLI v${Ga}
796
822
  Personal AI Assistant
797
823
 
798
824
  Usage:
@@ -810,4 +836,4 @@ Commands:
810
836
  Options:
811
837
  --help, -h Show this help message
812
838
  --version, -v Show version number
813
- `.trim();function hd(c){let e=c.slice(2),t=e.length>0&&!e[0].startsWith("-")?e[0]:"",s=t?e.slice(1):e,r={},n=[],o=0;for(;o<s.length;){let i=s[o];if(i.startsWith("--")){let a=i.slice(2);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else if(i.startsWith("-")&&i.length===2){let a=i.slice(1);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else n.push(i),o+=1}return{command:t,flags:r,positional:n}}u(hd,"parseArgs");async function fd(){let c=hd(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(Qn),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Ia}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(da(),la));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(ma(),pa));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(()=>(ya(),ga));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(Ta(),ba));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(va(),_a));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>($a(),ka));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(()=>(xa(),Sa));await s(t);break}case"help":console.log(Qn);break;case"":console.log(Qn),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(fd,"main");fd().catch(c=>{console.error("Fatal error:",c),process.exit(1)});
839
+ `.trim();function jd(c){let e=c.slice(2),t=e.length>0&&!e[0].startsWith("-")?e[0]:"",s=t?e.slice(1):e,r={},n=[],o=0;for(;o<s.length;){let i=s[o];if(i.startsWith("--")){let a=i.slice(2);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else if(i.startsWith("-")&&i.length===2){let a=i.slice(1);o+1<s.length&&!s[o+1].startsWith("-")?(r[a]=s[o+1],o+=2):(r[a]=!0,o+=1)}else n.push(i),o+=1}return{command:t,flags:r,positional:n}}u(jd,"parseArgs");async function Bd(){let c=jd(process.argv);switch((c.flags.help||c.flags.h)&&(console.log(ho),process.exit(0)),(c.flags.version||c.flags.v)&&(console.log(`alfred v${Ga}`),process.exit(0)),c.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(La(),Ra));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(Ca(),Na));await e({model:typeof c.flags.model=="string"?c.flags.model:void 0,tier:typeof c.flags.tier=="string"?c.flags.tier:void 0});break}case"setup":{let{setupCommand:e}=await Promise.resolve().then(()=>(Pa(),Ua));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(Ba(),ja));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(Wa(),Ha));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(za(),Xa));await e();break}case"logs":{let e=c.flags.tail,t=20;if(typeof e=="string"){let r=parseInt(e,10);(Number.isNaN(r)||r<=0)&&(console.error("Error: --tail must be a positive integer"),process.exit(1)),t=r}let{logsCommand:s}=await Promise.resolve().then(()=>(Ka(),Va));await s(t);break}case"help":console.log(ho);break;case"":console.log(ho),process.exit(0);break;default:console.error(`Unknown command: ${c.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}u(Bd,"main");Bd().catch(c=>{console.error("Fatal error:",c),process.exit(1)});