@madh-io/alfred-ai 0.9.19 → 0.9.20

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 +83 -82
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- var Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"name",{value:e,configurable:!0});var f=(l,e)=>()=>(l&&(e=l(l=0)),e);var J=(l,e)=>{for(var t in e)Rr(l,t,{get:e[t],enumerable:!0})};import{z as g}from"zod";var Lr,Mr,Nr,Dr,Or,Cr,Ur,Pr,fe,qo,Ko,Vo,Go,Yo,Jo,Zo,Qo,ei,ti,si,ri,ni,As,Rs=f(()=>{"use strict";Lr=g.object({token:g.string().optional(),enabled:g.boolean()}),Mr=g.object({token:g.string().optional(),enabled:g.boolean()}),Nr=g.object({enabled:g.boolean(),dataPath:g.string()}),Dr=g.object({homeserverUrl:g.string(),accessToken:g.string().optional(),userId:g.string().optional(),enabled:g.boolean()}),Or=g.object({apiUrl:g.string(),phoneNumber:g.string().optional(),enabled:g.boolean()}),Cr=g.object({path:g.string()}),Ur=g.object({level:g.enum(["trace","debug","info","warn","error","fatal"]),pretty:g.boolean(),auditLogPath:g.string().optional()}),Pr=g.object({rulesPath:g.string(),defaultEffect:g.enum(["allow","deny"]),ownerUserId:g.string().optional()}),fe=g.object({provider:g.enum(["anthropic","openai","openrouter","ollama","openwebui"]),apiKey:g.string().optional(),baseUrl:g.string().optional(),model:g.string(),temperature:g.number().optional(),maxTokens:g.number().optional()}),qo=g.object({default:fe,strong:fe.optional(),fast:fe.optional(),embeddings:fe.optional(),local:fe.optional()}),Ko=g.union([fe,qo]),Vo=g.object({provider:g.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:g.string().optional(),baseUrl:g.string().optional()}),Go=g.object({imap:g.object({host:g.string(),port:g.number(),secure:g.boolean()}),smtp:g.object({host:g.string(),port:g.number(),secure:g.boolean()}),auth:g.object({user:g.string(),pass:g.string()})}),Yo=g.object({provider:g.enum(["openai","groq"]),apiKey:g.string(),baseUrl:g.string().optional()}),Jo=g.object({serverUrl:g.string(),username:g.string(),password:g.string()}),Zo=g.object({clientId:g.string(),clientSecret:g.string(),refreshToken:g.string()}),Qo=g.object({clientId:g.string(),clientSecret:g.string(),tenantId:g.string(),refreshToken:g.string()}),ei=g.object({provider:g.enum(["caldav","google","microsoft"]),caldav:Jo.optional(),google:Zo.optional(),microsoft:Qo.optional()}),ti=g.object({name:g.string(),command:g.string().optional(),args:g.array(g.string()).optional(),env:g.record(g.string()).optional(),url:g.string().optional()}),si=g.object({servers:g.array(ti)}),ri=g.object({enabled:g.boolean(),allowedLanguages:g.array(g.enum(["javascript","python"])).optional(),maxTimeoutMs:g.number().optional(),allowNetwork:g.boolean().optional()}),ni=g.object({enabled:g.boolean().optional(),minMessageLength:g.number().optional(),minConfidence:g.number().min(0).max(1).optional(),maxExtractionsPerMinute:g.number().optional()}),As=g.object({name:g.string(),telegram:Lr,discord:Mr.optional(),whatsapp:Nr.optional(),matrix:Dr.optional(),signal:Or.optional(),llm:Ko,storage:Cr,logger:Ur,security:Pr,search:Vo.optional(),email:Go.optional(),speech:Yo.optional(),calendar:ei.optional(),mcp:si.optional(),codeSandbox:ri.optional(),activeLearning:ni.optional()})});var Ls,Ms=f(()=>{"use strict";Ls={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"}}});import Fr from"node:fs";import oi from"node:path";import{config as ii}from"dotenv";import ai from"js-yaml";function jr(l,e){let t={...l};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=jr(n,r):t[s]=r}return t}function li(l){let e={...l};for(let[t,s]of Object.entries(ci)){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}var ci,q,Br=f(()=>{"use strict";Rs();Ms();d(jr,"deepMerge");ci={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"]};d(li,"applyEnvOverrides");q=class{static{d(this,"ConfigLoader")}loadConfig(e){ii();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=oi.resolve(t);if(Fr.existsSync(r)){let c=Fr.readFileSync(r,"utf-8"),u=ai.load(c);u&&typeof u=="object"&&(s=u)}let n=jr(Ls,s),o=li(n),i=As.parse(o),a=i.llm;return a&&"provider"in a&&(i.llm={default:a}),i}}});var ge=f(()=>{"use strict";Rs();Ms();Br()});import Ns from"pino";function dt(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Ns.transport({target:"pino-pretty",options:{colorize:!0}});return Ns({name:l,level:t},r)}return Ns({name:l,level:t})}var Wr=f(()=>{"use strict";d(dt,"createLogger")});import tc from"pino";var Xr=f(()=>{"use strict"});var Ds=f(()=>{"use strict";Wr();Xr()});var Ne,rs=f(()=>{"use strict";Ne=class{static{d(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
2
+ var Mr=Object.defineProperty;var d=(l,e)=>Mr(l,"name",{value:e,configurable:!0});var f=(l,e)=>()=>(l&&(e=l(l=0)),e);var J=(l,e)=>{for(var t in e)Mr(l,t,{get:e[t],enumerable:!0})};import{z as g}from"zod";var Nr,Dr,Or,Cr,Ur,Pr,Fr,jr,fe,Go,Yo,Jo,Zo,Qo,ei,ti,si,ri,ni,oi,ii,ai,Ls,Ms=f(()=>{"use strict";Nr=g.object({token:g.string().optional(),enabled:g.boolean()}),Dr=g.object({token:g.string().optional(),enabled:g.boolean()}),Or=g.object({enabled:g.boolean(),dataPath:g.string()}),Cr=g.object({homeserverUrl:g.string(),accessToken:g.string().optional(),userId:g.string().optional(),enabled:g.boolean()}),Ur=g.object({apiUrl:g.string(),phoneNumber:g.string().optional(),enabled:g.boolean()}),Pr=g.object({path:g.string()}),Fr=g.object({level:g.enum(["trace","debug","info","warn","error","fatal"]),pretty:g.boolean(),auditLogPath:g.string().optional()}),jr=g.object({rulesPath:g.string(),defaultEffect:g.enum(["allow","deny"]),ownerUserId:g.string().optional()}),fe=g.object({provider:g.enum(["anthropic","openai","openrouter","ollama","openwebui"]),apiKey:g.string().optional(),baseUrl:g.string().optional(),model:g.string(),temperature:g.number().optional(),maxTokens:g.number().optional()}),Go=g.object({default:fe,strong:fe.optional(),fast:fe.optional(),embeddings:fe.optional(),local:fe.optional()}),Yo=g.union([fe,Go]),Jo=g.object({provider:g.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:g.string().optional(),baseUrl:g.string().optional()}),Zo=g.object({imap:g.object({host:g.string(),port:g.number(),secure:g.boolean()}),smtp:g.object({host:g.string(),port:g.number(),secure:g.boolean()}),auth:g.object({user:g.string(),pass:g.string()})}),Qo=g.object({provider:g.enum(["openai","groq"]),apiKey:g.string(),baseUrl:g.string().optional()}),ei=g.object({serverUrl:g.string(),username:g.string(),password:g.string()}),ti=g.object({clientId:g.string(),clientSecret:g.string(),refreshToken:g.string()}),si=g.object({clientId:g.string(),clientSecret:g.string(),tenantId:g.string(),refreshToken:g.string()}),ri=g.object({provider:g.enum(["caldav","google","microsoft"]),caldav:ei.optional(),google:ti.optional(),microsoft:si.optional()}),ni=g.object({name:g.string(),command:g.string().optional(),args:g.array(g.string()).optional(),env:g.record(g.string()).optional(),url:g.string().optional()}),oi=g.object({servers:g.array(ni)}),ii=g.object({enabled:g.boolean(),allowedLanguages:g.array(g.enum(["javascript","python"])).optional(),maxTimeoutMs:g.number().optional(),allowNetwork:g.boolean().optional()}),ai=g.object({enabled:g.boolean().optional(),minMessageLength:g.number().optional(),minConfidence:g.number().min(0).max(1).optional(),maxExtractionsPerMinute:g.number().optional()}),Ls=g.object({name:g.string(),telegram:Nr,discord:Dr.optional(),whatsapp:Or.optional(),matrix:Cr.optional(),signal:Ur.optional(),llm:Yo,storage:Pr,logger:Fr,security:jr,search:Jo.optional(),email:Zo.optional(),speech:Qo.optional(),calendar:ri.optional(),mcp:oi.optional(),codeSandbox:ii.optional(),activeLearning:ai.optional()})});var Ns,Ds=f(()=>{"use strict";Ns={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"}}});import Br from"node:fs";import ci from"node:path";import{config as li}from"dotenv";import di from"js-yaml";function Wr(l,e){let t={...l};for(let s of Object.keys(e)){let r=e[s],n=t[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&n!==null&&n!==void 0&&typeof n=="object"&&!Array.isArray(n)?t[s]=Wr(n,r):t[s]=r}return t}function pi(l){let e={...l};for(let[t,s]of Object.entries(ui)){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}var ui,q,Xr=f(()=>{"use strict";Ms();Ds();d(Wr,"deepMerge");ui={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"]};d(pi,"applyEnvOverrides");q=class{static{d(this,"ConfigLoader")}loadConfig(e){li();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=ci.resolve(t);if(Br.existsSync(r)){let c=Br.readFileSync(r,"utf-8"),u=di.load(c);u&&typeof u=="object"&&(s=u)}let n=Wr(Ns,s),o=pi(n),i=Ls.parse(o),a=i.llm;return a&&"provider"in a&&(i.llm={default:a}),i}}});var ge=f(()=>{"use strict";Ms();Ds();Xr()});import Os from"pino";function dt(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Os.transport({target:"pino-pretty",options:{colorize:!0}});return Os({name:l,level:t},r)}return Os({name:l,level:t})}var zr=f(()=>{"use strict";d(dt,"createLogger")});import nc from"pino";var Hr=f(()=>{"use strict"});var Cs=f(()=>{"use strict";zr();Hr()});var Ne,rs=f(()=>{"use strict";Ne=class{static{d(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 Os,Cs=f(()=>{"use strict";rs();Os=[{version:1,description:"Initial schema \u2014 conversations, messages, users, audit_log",up(l){}},{version:2,description:"Add plugin_skills table for tracking loaded external plugins",up(l){l.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 Us,Ps=f(()=>{"use strict";rs();Us=[{version:1,description:"Initial schema \u2014 conversations, messages, users, audit_log",up(l){}},{version:2,description:"Add plugin_skills table for tracking loaded external plugins",up(l){l.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 Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"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 di from"better-sqlite3";import ui from"node:fs";import pi from"node:path";var ye,zr=f(()=>{"use strict";rs();Cs();ye=class{static{d(this,"Database")}db;constructor(e){let t=pi.dirname(e);ui.mkdirSync(t,{recursive:!0}),this.db=new di(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 mi from"better-sqlite3";import hi from"node:fs";import fi from"node:path";var ye,qr=f(()=>{"use strict";rs();Ps();ye=class{static{d(this,"Database")}db;constructor(e){let t=fi.dirname(e);hi.mkdirSync(t,{recursive:!0}),this.db=new mi(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 Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"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 Ne(this.db).migrate(Os)}getDb(){return this.db}close(){this.db.close()}}});import Hr from"node:crypto";var ut,qr=f(()=>{"use strict";ut=class{static{d(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Hr.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
243
+ `)}runMigrations(){new Ne(this.db).migrate(Us)}getDb(){return this.db}close(){this.db.close()}}});import Kr from"node:crypto";var ut,Vr=f(()=>{"use strict";ut=class{static{d(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:Kr.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)}addMessage(e,t,s,r){let n={id:Hr.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)}addMessage(e,t,s,r){let n={id:Kr.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 mi from"node:crypto";var pt,Kr=f(()=>{"use strict";pt=class{static{d(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:mi.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 gi from"node:crypto";var pt,Gr=f(()=>{"use strict";pt=class{static{d(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:gi.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))}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 we,Vr=f(()=>{"use strict";we=class{static{d(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))}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 we,Yr=f(()=>{"use strict";we=class{static{d(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 hi}from"node:crypto";var mt,Gr=f(()=>{"use strict";mt=class{static{d(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(),c=hi();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 yi}from"node:crypto";var mt,Jr=f(()=>{"use strict";mt=class{static{d(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(),c=yi();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 Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"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(c,e,t,s,r,n,o,i,a,a);let u=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(u)}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(c=>c.length>=2);if(r.length===0)return[];let n=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),o=[e];for(let c of r)o.push(`%${c}%`,`%${c}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${n}) ORDER BY updated_at DESC`).all(...o).map(c=>{let u=this.mapRow(c),m=`${u.key} ${u.value}`.toLowerCase(),p=0;for(let h of r)m.includes(h)&&(p+=1);return{entry:u,score:p/r.length}});return a.sort((c,u)=>u.score-c.score),a.slice(0,s).map(c=>c.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 fi}from"node:crypto";var ht,Yr=f(()=>{"use strict";ht=class{static{d(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n){let o={id:fi(),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(c,e,t,s,r,n,o,i,a,a);let u=this.db.prepare("SELECT * FROM memories WHERE user_id = ? AND key = ?").get(e,t);return this.mapRow(u)}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(c=>c.length>=2);if(r.length===0)return[];let n=r.map(()=>"(LOWER(key) LIKE ? OR LOWER(value) LIKE ?)").join(" OR "),o=[e];for(let c of r)o.push(`%${c}%`,`%${c}%`);let a=this.db.prepare(`SELECT * FROM memories WHERE user_id = ? AND (${n}) ORDER BY updated_at DESC`).all(...o).map(c=>{let u=this.mapRow(c),h=`${u.key} ${u.value}`.toLowerCase(),p=0;for(let m of r)h.includes(m)&&(p+=1);return{entry:u,score:p/r.length}});return a.sort((c,u)=>u.score-c.score),a.slice(0,s).map(c=>c.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 wi}from"node:crypto";var ht,Zr=f(()=>{"use strict";ht=class{static{d(this,"ReminderRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n){let o={id:wi(),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 gi}from"node:crypto";var ft,Jr=f(()=>{"use strict";ft=class{static{d(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),n=gi();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 yi}from"node:crypto";var gt,Zr=f(()=>{"use strict";gt=class{static{d(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=yi(),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 wi from"node:crypto";var yt,Qr=f(()=>{"use strict";yt=class{static{d(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:wi.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 Ei}from"node:crypto";var ft,Qr=f(()=>{"use strict";ft=class{static{d(this,"NoteRepository")}db;constructor(e){this.db=e}save(e,t,s){let r=new Date().toISOString(),n=Ei();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 Ti}from"node:crypto";var gt,en=f(()=>{"use strict";gt=class{static{d(this,"EmbeddingRepository")}db;constructor(e){this.db=e}store(e){let t=Ti(),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 bi from"node:crypto";var yt,tn=f(()=>{"use strict";yt=class{static{d(this,"LinkTokenRepository")}db;constructor(e){this.db=e}create(e,t){for(let s=0;s<5;s++){let r={id:bi.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 Ei}from"node:crypto";var wt,en=f(()=>{"use strict";wt=class{static{d(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n,o){let i={id:Ei(),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 _i}from"node:crypto";var wt,sn=f(()=>{"use strict";wt=class{static{d(this,"BackgroundTaskRepository")}db;constructor(e){this.db=e}create(e,t,s,r,n,o){let i={id:_i(),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 Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"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 Ti}from"node:crypto";var Et,tn=f(()=>{"use strict";Et=class{static{d(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Ti(),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 Si}from"node:crypto";var Et,rn=f(()=>{"use strict";Et=class{static{d(this,"ScheduledActionRepository")}db;constructor(e){this.db=e}create(e){let t=new Date().toISOString(),s=Si(),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 Rr=Object.defineProperty;var d=(l,e)=>Rr(l,"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 sn}from"node:crypto";var Tt,rn=f(()=>{"use strict";Tt=class{static{d(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=sn(),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=sn(),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 Us=f(()=>{"use strict";zr();qr();Kr();Vr();Gr();rs();Cs();Yr();Jr();Zr();Qr();en();tn();rn()});function Ee(l){if(Ps[l])return Ps[l];let e=Object.entries(Ps).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var Ps,bi,Z,De=f(()=>{"use strict";Ps={"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}},bi={maxInputTokens:8192,maxOutputTokens:4096};d(Ee,"lookupContextWindow");Z=class{static{d(this,"LLMProvider")}config;contextWindow=bi;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import _i from"@anthropic-ai/sdk";var bt,Fs=f(()=>{"use strict";De();bt=class extends Z{static{d(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new _i({apiKey:this.config.apiKey});let e=Ee(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 Si from"openai";var oe,_t=f(()=>{"use strict";De();oe=class extends Z{static{d(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Si({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=Ee(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="",c=[],u=null,m=0,p=0;for await(let h of r){let w=h.choices[0];if(!w)continue;let E=w.delta;if(E?.content&&(a+=E.content,yield{type:"text_delta",text:E.content}),E?.tool_calls)for(let T of E.tool_calls)if(T.id){if(n){let v;try{v=JSON.parse(i||"{}")}catch{v={}}c.push({id:n,name:o,input:v})}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}});w.finish_reason&&(u=w.finish_reason),h.usage&&(m=h.usage.prompt_tokens,p=h.usage.completion_tokens)}if(n){let h;try{h=JSON.parse(i||"{}")}catch{h={}}c.push({id:n,name:o,input:h})}yield{type:"message_complete",response:{content:a,toolCalls:c.length>0?c:void 0,usage:{inputTokens:m,outputTokens:p},stopReason:this.mapStopReason(u)}}}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(c=>c.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,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 St,js=f(()=>{"use strict";_t();St=class extends oe{static{d(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var kt,Bs=f(()=>{"use strict";De();kt=class extends Z{static{d(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=Ee(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 h=await n.text();throw new Error(`Ollama API error (${n.status}): ${h}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",u=0,m=0,p=[];try{for(;;){let{done:h,value:w}=await o.read();if(h)break;a+=i.decode(w,{stream:!0});let E=a.split(`
297
- `);a=E.pop()??"";for(let T of E){let v=T.trim();if(!v)continue;let $;try{$=JSON.parse(v)}catch{continue}if($.message?.content&&(c+=$.message.content,yield{type:"text_delta",text:$.message.content}),$.message?.tool_calls)for(let x of $.message.tool_calls){let M={id:`ollama_tool_${p.length}`,name:x.function.name,input:x.function.arguments};p.push(M),yield{type:"tool_use_start",toolCall:{id:M.id,name:M.name}},yield{type:"tool_use_delta",toolCall:{input:M.input}}}$.done&&(u=$.prompt_eval_count??0,m=$.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:u,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let h;try{h=JSON.parse(a.trim())}catch{return}if(h.message?.content&&(c+=h.message.content,yield{type:"text_delta",text:h.message.content}),h.message?.tool_calls)for(let w of h.message.tool_calls){let E={id:`ollama_tool_${p.length}`,name:w.function.name,input:w.function.arguments};p.push(E),yield{type:"tool_use_start",toolCall:{id:E.id,name:E.name}},yield{type:"tool_use_delta",toolCall:{input:E.input}}}h.done&&(u=h.prompt_eval_count??0,m=h.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:u,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
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 vt,Ws=f(()=>{"use strict";_t();vt=class extends oe{static{d(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});function Xs(l){switch(l.provider){case"anthropic":return new bt(l);case"openai":return new oe(l);case"openrouter":return new St(l);case"ollama":return new kt(l);case"openwebui":return new vt(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var zs=f(()=>{"use strict";Fs();_t();js();Bs();Ws();d(Xs,"createLLMProvider")});function Hs(l){return new ns(l)}var ki,ns,nn=f(()=>{"use strict";De();zs();ki=["default","strong","fast","embeddings","local"],ns=class extends Z{static{d(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of ki){let t=this.multiConfig[e];if(t){let s=Xs(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()}};d(Hs,"createModelRouter")});function le(l){return Math.ceil(l.length/3.5)}function os(l){if(typeof l.content=="string")return le(l.content)+4;let e=4;for(let t of l.content)switch(t.type){case"text":e+=le(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=le(t.name)+le(JSON.stringify(t.input));break;case"tool_result":e+=le(t.content);break}return e}var xt,on=f(()=>{"use strict";d(le,"estimateTokens");d(os,"estimateMessageTokens");xt=class{static{d(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 nn}from"node:crypto";var Tt,on=f(()=>{"use strict";Tt=class{static{d(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=nn(),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=nn(),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 Fs=f(()=>{"use strict";qr();Vr();Gr();Yr();Jr();rs();Ps();Zr();Qr();en();tn();sn();rn();on()});function Ee(l){if(js[l])return js[l];let e=Object.entries(js).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var js,ki,Z,De=f(()=>{"use strict";js={"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}},ki={maxInputTokens:8192,maxOutputTokens:4096};d(Ee,"lookupContextWindow");Z=class{static{d(this,"LLMProvider")}config;contextWindow=ki;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import vi from"@anthropic-ai/sdk";var bt,Bs=f(()=>{"use strict";De();bt=class extends Z{static{d(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new vi({apiKey:this.config.apiKey});let e=Ee(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 xi from"openai";var oe,_t=f(()=>{"use strict";De();oe=class extends Z{static{d(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new xi({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=Ee(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="",c=[],u=null,h=0,p=0;for await(let m of r){let w=m.choices[0];if(!w)continue;let E=w.delta;if(E?.content&&(a+=E.content,yield{type:"text_delta",text:E.content}),E?.tool_calls)for(let T of E.tool_calls)if(T.id){if(n){let v;try{v=JSON.parse(i||"{}")}catch{v={}}c.push({id:n,name:o,input:v})}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}});w.finish_reason&&(u=w.finish_reason),m.usage&&(h=m.usage.prompt_tokens,p=m.usage.completion_tokens)}if(n){let m;try{m=JSON.parse(i||"{}")}catch{m={}}c.push({id:n,name:o,input:m})}yield{type:"message_complete",response:{content:a,toolCalls:c.length>0?c:void 0,usage:{inputTokens:h,outputTokens:p},stopReason:this.mapStopReason(u)}}}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(c=>c.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,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 St,Ws=f(()=>{"use strict";_t();St=class extends oe{static{d(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var kt,Xs=f(()=>{"use strict";De();kt=class extends Z{static{d(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=Ee(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 m=await n.text();throw new Error(`Ollama API error (${n.status}): ${m}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",u=0,h=0,p=[];try{for(;;){let{done:m,value:w}=await o.read();if(m)break;a+=i.decode(w,{stream:!0});let E=a.split(`
297
+ `);a=E.pop()??"";for(let T of E){let v=T.trim();if(!v)continue;let $;try{$=JSON.parse(v)}catch{continue}if($.message?.content&&(c+=$.message.content,yield{type:"text_delta",text:$.message.content}),$.message?.tool_calls)for(let x of $.message.tool_calls){let M={id:`ollama_tool_${p.length}`,name:x.function.name,input:x.function.arguments};p.push(M),yield{type:"tool_use_start",toolCall:{id:M.id,name:M.name}},yield{type:"tool_use_delta",toolCall:{input:M.input}}}$.done&&(u=$.prompt_eval_count??0,h=$.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:u,outputTokens:h},stopReason:p.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let m;try{m=JSON.parse(a.trim())}catch{return}if(m.message?.content&&(c+=m.message.content,yield{type:"text_delta",text:m.message.content}),m.message?.tool_calls)for(let w of m.message.tool_calls){let E={id:`ollama_tool_${p.length}`,name:w.function.name,input:w.function.arguments};p.push(E),yield{type:"tool_use_start",toolCall:{id:E.id,name:E.name}},yield{type:"tool_use_delta",toolCall:{input:E.input}}}m.done&&(u=m.prompt_eval_count??0,h=m.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:u,outputTokens:h},stopReason:p.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
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 vt,zs=f(()=>{"use strict";_t();vt=class extends oe{static{d(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});function Hs(l){switch(l.provider){case"anthropic":return new bt(l);case"openai":return new oe(l);case"openrouter":return new St(l);case"ollama":return new kt(l);case"openwebui":return new vt(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var qs=f(()=>{"use strict";Bs();_t();Ws();Xs();zs();d(Hs,"createLLMProvider")});function Ks(l){return new ns(l)}var Ii,ns,an=f(()=>{"use strict";De();qs();Ii=["default","strong","fast","embeddings","local"],ns=class extends Z{static{d(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of Ii){let t=this.multiConfig[e];if(t){let s=Hs(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()}};d(Ks,"createModelRouter")});function le(l){return Math.ceil(l.length/3.5)}function os(l){if(typeof l.content=="string")return le(l.content)+4;let e=4;for(let t of l.content)switch(t.type){case"text":e+=le(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=le(t.name)+le(JSON.stringify(t.input));break;case"tool_result":e+=le(t.content);break}return e}var xt,cn=f(()=>{"use strict";d(le,"estimateTokens");d(os,"estimateMessageTokens");xt=class{static{d(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,11 +324,11 @@ 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`,c=Intl.DateTimeFormat().resolvedOptions().timeZone,u=r?.timezone||c,m=new Date,p=m.toLocaleTimeString("en-GB",{timeZone:u,hour:"2-digit",minute:"2-digit"}),h=m.toLocaleDateString("en-CA",{timeZone:u}),w=m.toLocaleDateString("en-US",{timeZone:u,weekday:"long"});if(a+=`
327
+ - Downloads: ${i}/Downloads`,c=Intl.DateTimeFormat().resolvedOptions().timeZone,u=r?.timezone||c,h=new Date,p=h.toLocaleTimeString("en-GB",{timeZone:u,hour:"2-digit",minute:"2-digit"}),m=h.toLocaleDateString("en-CA",{timeZone:u}),w=h.toLocaleDateString("en-US",{timeZone:u,weekday:"long"});if(a+=`
328
328
 
329
329
  ## Current date & time`,a+=`
330
330
  - Timezone: ${u}`,a+=`
331
- - Date: ${h} (${w})`,a+=`
331
+ - Date: ${m} (${w})`,a+=`
332
332
  - Time: ${p}`,r?.timezone&&r.timezone!==c&&(a+=`
333
333
  - Server timezone: ${c}`),s&&s.length>0){a+=`
334
334
 
@@ -353,50 +353,50 @@ For complex tasks, work through multiple steps:
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 c of i)a.push({type:"tool_use",id:c.id,name:c.name,input:c.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 c of a.content)c.type==="tool_use"&&t.add(c.id);else if(a.role==="user"&&Array.isArray(a.content))for(let c of a.content)c.type==="tool_result"&&t.has(c.tool_use_id)&&s.add(c.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 c=a.content.filter(u=>u.type==="tool_use"?!s.has(u.id)||r.has(u.id)?!1:(r.add(u.id),!0):u.type==="tool_result"?!s.has(u.tool_use_id)||n.has(u.tool_use_id)?!1:(n.add(u.tool_use_id),!0):!0);c.length!==0&&o.push({...a,content:c})}let i=[];for(let a of o){let c=i[i.length-1];if(c&&c.role===a.role){let u=typeof c.content=="string"?[{type:"text",text:c.content}]:c.content,m=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...c,content:[...u,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var qs=f(()=>{"use strict";De();Fs();_t();js();Bs();Ws();zs();nn();on()});var It,Ks=f(()=>{"use strict";It=class{static{d(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 $t,an=f(()=>{"use strict";Ks();$t=class{static{d(this,"RuleEngine")}rules=[];rateLimiter=new It;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 cn,ln,dn,Te,un=f(()=>{"use strict";cn=["allow","deny"],ln=["global","user","conversation","platform"],dn=["read","write","destructive","admin"],Te=class{static{d(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"||!cn.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${cn.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"||!ln.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${ln.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(!dn.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${dn.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 vi from"node:crypto";var At,pn=f(()=>{"use strict";At=class{static{d(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:vi.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 is=f(()=>{"use strict";an();Ks();un();pn()});var b,O=f(()=>{"use strict";b=class{static{d(this,"Skill")}}});var Oe,mn=f(()=>{"use strict";Oe=class{static{d(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)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Ce,hn=f(()=>{"use strict";Ce=class{static{d(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,c,u,m,p=d(()=>{c&&clearInterval(c),u&&clearTimeout(u),m&&clearTimeout(m)},"cleanup"),h=d(w=>{a||(a=!0,p(),i(w))},"finish");e.execute(t,s).then(w=>{this.logger.info({skill:r,success:w.success},"Skill execution completed"),h(w)},w=>{let E=w instanceof Error?w.message:String(w);this.logger.error({skill:r,error:E},"Skill execution failed"),h({success:!1,error:E})}),m=setTimeout(()=>{if(a)return;let w=o.getIdleMs();if(w>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:w,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),h({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(w/1e3)}s (last state: ${T.state})`});return}let E=o.getSnapshot();this.logger.info({skill:r,idleMs:w,state:E.state,iteration:E.iteration,totalMs:E.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),c=setInterval(()=>{if(a){p();return}let T=o.getIdleMs(),v=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:v.state,iteration:v.iteration,totalMs:v.totalElapsedMs},"Agent went inactive \u2014 aborting"),h({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${v.state})`})):this.logger.debug({skill:r,idleMs:T,state:v.state,iteration:v.iteration},"Agent still active, continuing...")},1e4)},n),u=setTimeout(()=>{if(a)return;let w=o.getSnapshot();this.logger.error({skill:r,totalMs:w.totalElapsedMs,state:w.state,iteration:w.iteration},"Absolute time limit reached \u2014 force killing agent"),h({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 be,Vs=f(()=>{"use strict";be=class{static{d(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 xi from"node:fs";import Gs from"node:path";var as,fn=f(()=>{"use strict";O();as=class{static{d(this,"PluginLoader")}async loadFromDirectory(e){let t=Gs.resolve(e),s;try{s=await xi.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=Gs.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let c=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${c}`)}}return n}async loadFromFile(e){let t=Gs.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 b))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 Ii,$i,Ue,gn=f(()=>{"use strict";O();Ii=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,$i=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Ue=class extends b{static{d(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(!$i.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(Ii,"");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 Pe,yn=f(()=>{"use strict";O();Pe=class extends b{static{d(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=d(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 Fe,wn=f(()=>{"use strict";O();Fe=class extends b{static{d(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,c)=>`${c+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 c of i)a.push({type:"tool_use",id:c.id,name:c.name,input:c.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 c of a.content)c.type==="tool_use"&&t.add(c.id);else if(a.role==="user"&&Array.isArray(a.content))for(let c of a.content)c.type==="tool_result"&&t.has(c.tool_use_id)&&s.add(c.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 c=a.content.filter(u=>u.type==="tool_use"?!s.has(u.id)||r.has(u.id)?!1:(r.add(u.id),!0):u.type==="tool_result"?!s.has(u.tool_use_id)||n.has(u.tool_use_id)?!1:(n.add(u.tool_use_id),!0):!0);c.length!==0&&o.push({...a,content:c})}let i=[];for(let a of o){let c=i[i.length-1];if(c&&c.role===a.role){let u=typeof c.content=="string"?[{type:"text",text:c.content}]:c.content,h=typeof a.content=="string"?[{type:"text",text:a.content}]:a.content;i[i.length-1]={...c,content:[...u,...h]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Vs=f(()=>{"use strict";De();Bs();_t();Ws();Xs();zs();qs();an();cn()});var It,Gs=f(()=>{"use strict";It=class{static{d(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 $t,ln=f(()=>{"use strict";Gs();$t=class{static{d(this,"RuleEngine")}rules=[];rateLimiter=new It;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 dn,un,pn,Te,mn=f(()=>{"use strict";dn=["allow","deny"],un=["global","user","conversation","platform"],pn=["read","write","destructive","admin"],Te=class{static{d(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"||!dn.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${dn.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"||!un.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${un.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(!pn.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${pn.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 $i from"node:crypto";var At,hn=f(()=>{"use strict";At=class{static{d(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:$i.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 is=f(()=>{"use strict";ln();Gs();mn();hn()});var _,O=f(()=>{"use strict";_=class{static{d(this,"Skill")}}});var Oe,fn=f(()=>{"use strict";Oe=class{static{d(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)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Ce,gn=f(()=>{"use strict";Ce=class{static{d(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,c,u,h,p=d(()=>{c&&clearInterval(c),u&&clearTimeout(u),h&&clearTimeout(h)},"cleanup"),m=d(w=>{a||(a=!0,p(),i(w))},"finish");e.execute(t,s).then(w=>{this.logger.info({skill:r,success:w.success},"Skill execution completed"),m(w)},w=>{let E=w instanceof Error?w.message:String(w);this.logger.error({skill:r,error:E},"Skill execution failed"),m({success:!1,error:E})}),h=setTimeout(()=>{if(a)return;let w=o.getIdleMs();if(w>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:w,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),m({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(w/1e3)}s (last state: ${T.state})`});return}let E=o.getSnapshot();this.logger.info({skill:r,idleMs:w,state:E.state,iteration:E.iteration,totalMs:E.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),c=setInterval(()=>{if(a){p();return}let T=o.getIdleMs(),v=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:v.state,iteration:v.iteration,totalMs:v.totalElapsedMs},"Agent went inactive \u2014 aborting"),m({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${v.state})`})):this.logger.debug({skill:r,idleMs:T,state:v.state,iteration:v.iteration},"Agent still active, continuing...")},1e4)},n),u=setTimeout(()=>{if(a)return;let w=o.getSnapshot();this.logger.error({skill:r,totalMs:w.totalElapsedMs,state:w.state,iteration:w.iteration},"Absolute time limit reached \u2014 force killing agent"),m({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 be,Ys=f(()=>{"use strict";be=class{static{d(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 Ai from"node:fs";import Js from"node:path";var as,yn=f(()=>{"use strict";O();as=class{static{d(this,"PluginLoader")}async loadFromDirectory(e){let t=Js.resolve(e),s;try{s=await Ai.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=Js.join(t,o);try{let a=await this.loadFromFile(i);n.push(a)}catch(a){let c=a instanceof Error?a.message:String(a);console.warn(`PluginLoader: skipping "${i}": ${c}`)}}return n}async loadFromFile(e){let t=Js.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 Ri,Li,Ue,wn=f(()=>{"use strict";O();Ri=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,Li=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Ue=class extends _{static{d(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(!Li.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace(Ri,"");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 Pe,En=f(()=>{"use strict";O();Pe=class extends _{static{d(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=d(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 Fe,Tn=f(()=>{"use strict";O();Fe=class extends _{static{d(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,c)=>`${c+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 c=i[1],u=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(c);u&&m&&o.push({url:m,title:u})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let c=0;c<Math.min(o.length,t);c++)s.push({title:o[c].title,url:o[c].url,snippet:a[c]??""});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 je,En=f(()=>{"use strict";O();je=class extends b{static{d(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}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(t.userId,t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),u=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 ${u} (in ${c} 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),c=parseInt(n[4],10),u=parseInt(n[5],10);return c>23||u>59||i>11||a>31?void 0:this.buildDateInTimezone(c,u,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let h=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||h.setHours(e,t,0,0),h}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 h=i.formatToParts(n),w=parseInt(h.find(S=>S.type==="year").value,10),E=parseInt(h.find(S=>S.type==="month").value,10)-1,T=parseInt(h.find(S=>S.type==="day").value,10),v=new Date(Date.UTC(w,E,T,e,t,0)),$=i.formatToParts(v),x=parseInt($.find(S=>S.type==="hour").value,10),M=parseInt($.find(S=>S.type==="minute").value,10),k=(e-x)*60+(t-M);return v=new Date(v.getTime()+k*6e4),v}let a=o,c=i.formatToParts(a),u=parseInt(c.find(h=>h.type==="hour").value,10),m=parseInt(c.find(h=>h.type==="minute").value,10),p=(e-u)*60+(t-m);return a=new Date(a.getTime()+p*6e4),a}listReminders(e){let s=this.reminderRepo.getByUser(e.userId).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 c=i[1],u=this.stripHtml(i[2]).trim(),h=this.extractDdgUrl(c);u&&h&&o.push({url:h,title:u})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let c=0;c<Math.min(o.length,t);c++)s.push({title:o[c].title,url:o[c].url,snippet:a[c]??""});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 je,bn=f(()=>{"use strict";O();je=class extends _{static{d(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}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 h=this.parseTriggerAt(r,t.timezone);if(!h)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(h.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=h}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(t.userId,t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),u=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 ${u} (in ${c} 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),c=parseInt(n[4],10),u=parseInt(n[5],10);return c>23||u>59||i>11||a>31?void 0:this.buildDateInTimezone(c,u,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let m=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||m.setHours(e,t,0,0),m}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 m=i.formatToParts(n),w=parseInt(m.find(S=>S.type==="year").value,10),E=parseInt(m.find(S=>S.type==="month").value,10)-1,T=parseInt(m.find(S=>S.type==="day").value,10),v=new Date(Date.UTC(w,E,T,e,t,0)),$=i.formatToParts(v),x=parseInt($.find(S=>S.type==="hour").value,10),M=parseInt($.find(S=>S.type==="minute").value,10),k=(e-x)*60+(t-M);return v=new Date(v.getTime()+k*6e4),v}let a=o,c=i.formatToParts(a),u=parseInt(c.find(m=>m.type==="hour").value,10),h=parseInt(c.find(m=>m.type==="minute").value,10),p=(e-u)*60+(t-h);return a=new Date(a.getTime()+p*6e4),a}listReminders(e){let s=this.reminderRepo.getByUser(e.userId).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.reminderRepo.getByUser(t.userId).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 Be,Tn=f(()=>{"use strict";O();Be=class extends b{static{d(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}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(t.userId,s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=this.noteRepo.list(e.userId);if(t.length===0)return{success:!0,data:[],display:"No notes found."};let s=t.map(r=>`- **${r.title}** (${r.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.reminderRepo.getByUser(t.userId).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 Be,_n=f(()=>{"use strict";O();Be=class extends _{static{d(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}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(t.userId,s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=this.noteRepo.list(e.userId);if(t.length===0)return{success:!0,data:[],display:"No notes found."};let s=t.map(r=>`- **${r.title}** (${r.id.slice(0,8)}\u2026)
365
365
  ${r.content.slice(0,100)}${r.content.length>100?"\u2026":""}`).join(`
366
366
  `);return{success:!0,data:t,display:`${t.length} note(s):
367
367
  ${s}`}}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=this.noteRepo.search(t.userId,s);if(r.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let n=r.map(o=>`- **${o.title}** (${o.id.slice(0,8)}\u2026)
368
368
  ${o.content.slice(0,100)}${o.content.length>100?"\u2026":""}`).join(`
369
369
  `);return{success:!0,data:r,display:`Found ${r.length} note(s):
370
- ${n}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?r.userId!==t.userId?{success:!1,error:`Note "${s}" not found`}: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`}}}});var Ai,We,bn=f(()=>{"use strict";O();Ai={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"},We=class extends b{static{d(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=Ai[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},c=`${i}: ${n.temperature}\xB0C, ${o}
371
- Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:c}}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 Ri}from"node:child_process";function Sn(l){return l.length>_n?l.slice(0,_n)+`
372
- [output truncated]`:l}var Li,_n,Xe,kn=f(()=>{"use strict";O();Li=3e4,_n=1e4;d(Sn,"truncate");Xe=class extends b{static{d(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:Li,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:c}=await this.run(s,n,o),u=[];return i&&u.push(`stdout:
373
- ${Sn(i)}`),a&&u.push(`stderr:
374
- ${Sn(a)}`),u.length===0&&u.push("(no output)"),u.push(`exit code: ${c}`),{success:c===0,data:{stdout:i,stderr:a,exitCode:c},display:u.join(`
370
+ ${n}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?r.userId!==t.userId?{success:!1,error:`Note "${s}" not found`}: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`}}}});var Mi,We,Sn=f(()=>{"use strict";O();Mi={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"},We=class extends _{static{d(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=Mi[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},c=`${i}: ${n.temperature}\xB0C, ${o}
371
+ Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:c}}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 Ni}from"node:child_process";function vn(l){return l.length>kn?l.slice(0,kn)+`
372
+ [output truncated]`:l}var Di,kn,Xe,xn=f(()=>{"use strict";O();Di=3e4,kn=1e4;d(vn,"truncate");Xe=class extends _{static{d(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:Di,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:c}=await this.run(s,n,o),u=[];return i&&u.push(`stdout:
373
+ ${vn(i)}`),a&&u.push(`stderr:
374
+ ${vn(a)}`),u.length===0&&u.push("(no output)"),u.push(`exit code: ${c}`),{success:c===0,data:{stdout:i,stderr:a,exitCode:c},display:u.join(`
375
375
 
376
- `),...c!==0&&{error:`Command exited with code ${c}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{Ri(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 ze,vn=f(()=>{"use strict";O();ze=class extends b{static{d(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}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(t.userId,s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(t.userId,`${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=this.memoryRepo.recall(t.userId,s);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=this.memoryRepo.search(t.userId,s);return{success:!0,data:r,display:r.length===0?`No memories matching "${s}".`:`Found ${r.length} memory(ies):
376
+ `),...c!==0&&{error:`Command exited with code ${c}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{Ni(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 ze,In=f(()=>{"use strict";O();ze=class extends _{static{d(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}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(t.userId,s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(t.userId,`${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=this.memoryRepo.recall(t.userId,s);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=this.memoryRepo.search(t.userId,s);return{success:!0,data:r,display:r.length===0?`No memories matching "${s}".`:`Found ${r.length} memory(ies):
377
377
  ${r.map(n=>`- ${n.key}: "${n.value}"`).join(`
378
378
  `)}`}}listMemories(e,t){let s=e.category,r=s&&typeof s=="string"?this.memoryRepo.listByCategory(t.userId,s):this.memoryRepo.listAll(t.userId),n=s?`in category "${s}"`:"total";return{success:!0,data:r,display:r.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${r.length} memory(ies) ${n}:
379
379
  ${r.map(o=>`- [${o.category}] ${o.key}: "${o.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=this.memoryRepo.delete(t.userId,s);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=await this.embeddingService.semanticSearch(t.userId,s,10);return r.length===0?this.searchMemories(e,t):{success:!0,data:r,display:`Found ${r.length} semantically related memory(ies):
381
381
  ${r.map(n=>`- ${n.key}: "${n.value}" (score: ${n.score.toFixed(2)})`).join(`
382
- `)}`}}}});var Mi,Ni,Di,He,xn=f(()=>{"use strict";O();Vs();Mi=5,Ni=15,Di=12e4,He=class extends b{static{d(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:Di,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 be(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(Ni,Math.round(n))):Mi,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new be(i);a.ping("starting",{maxIterations:o});let c=this.buildSubAgentTools(),u="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}
382
+ `)}`}}}});var Oi,Ci,Ui,He,$n=f(()=>{"use strict";O();Ys();Oi=5,Ci=15,Ui=12e4,He=class extends _{static{d(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:Ui,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 be(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(Ci,Math.round(n))):Oi,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new be(i);a.ping("starting",{maxIterations:o});let c=this.buildSubAgentTools(),u="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.",h=s;r&&typeof r=="string"&&(h=`${s}
383
383
 
384
- Additional context: ${r}`);let p=[{role:"user",content:m}];try{let h=0,w=0,E=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let T=await this.llm.complete({messages:p,system:u,tools:c.length>0?c:void 0,maxTokens:2048,tier:"strong"});if(w+=T.usage.inputTokens,E+=T.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!T.toolCalls||T.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:T.content,iterations:h,usage:{inputTokens:w,outputTokens:E}},display:T.content};h++;let v=[];T.content&&v.push({type:"text",text:T.content});for(let x of T.toolCalls)v.push({type:"tool_use",id:x.id,name:x.name,input:x.input});p.push({role:"assistant",content:v});let $=[];for(let x of T.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:x.name});let M=await this.executeSubAgentTool(x,t);$.push({type:"tool_result",tool_use_id:x.id,content:M.content,is_error:M.isError})}p.push({role:"user",content:$})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var qe,In=f(()=>{"use strict";O();qe=class extends b{static{d(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 u=`${Math.max(1,a-t+1)}:*`;for await(let h of r.fetch(u,{envelope:!0,flags:!0})){let w=h.envelope?.from?.[0],E=w?w.name?`${w.name} <${w.address}>`:w.address??"unknown":"unknown";o.push({seq:h.seq,from:E,subject:h.envelope?.subject??"(no subject)",date:h.envelope?.date?.toISOString()??"",seen:h.flags?.has("\\Seen")??!1})}o.reverse();let m=o.length===0?"No messages found.":o.map((h,w)=>{let E=h.seen?"":" [UNREAD]";return`${w+1}. [#${h.seq}]${E} ${h.subject}
385
- From: ${h.from}
386
- Date: ${h.date}`}).join(`
384
+ Additional context: ${r}`);let p=[{role:"user",content:h}];try{let m=0,w=0,E=0;for(;;){a.ping("llm_call",{iteration:m,maxIterations:o});let T=await this.llm.complete({messages:p,system:u,tools:c.length>0?c:void 0,maxTokens:2048,tier:"strong"});if(w+=T.usage.inputTokens,E+=T.usage.outputTokens,a.ping("processing",{iteration:m,maxIterations:o}),!T.toolCalls||T.toolCalls.length===0||m>=o)return a.ping("done",{iteration:m,maxIterations:o}),{success:!0,data:{response:T.content,iterations:m,usage:{inputTokens:w,outputTokens:E}},display:T.content};m++;let v=[];T.content&&v.push({type:"text",text:T.content});for(let x of T.toolCalls)v.push({type:"tool_use",id:x.id,name:x.name,input:x.input});p.push({role:"assistant",content:v});let $=[];for(let x of T.toolCalls){a.ping("tool_call",{iteration:m,maxIterations:o,tool:x.name});let M=await this.executeSubAgentTool(x,t);$.push({type:"tool_result",tool_use_id:x.id,content:M.content,is_error:M.isError})}p.push({role:"user",content:$})}}catch(m){return{success:!1,error:`Sub-agent failed: ${m instanceof Error?m.message:String(m)}`}}}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 qe,An=f(()=>{"use strict";O();qe=class extends _{static{d(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 u=`${Math.max(1,a-t+1)}:*`;for await(let m of r.fetch(u,{envelope:!0,flags:!0})){let w=m.envelope?.from?.[0],E=w?w.name?`${w.name} <${w.address}>`:w.address??"unknown":"unknown";o.push({seq:m.seq,from:E,subject:m.envelope?.subject??"(no subject)",date:m.envelope?.date?.toISOString()??"",seen:m.flags?.has("\\Seen")??!1})}o.reverse();let h=o.length===0?"No messages found.":o.map((m,w)=>{let E=m.seen?"":" [UNREAD]";return`${w+1}. [#${m.seq}]${E} ${m.subject}
385
+ From: ${m.from}
386
+ Date: ${m.date}`}).join(`
387
387
 
388
- `),p=o.filter(h=>!h.seen).length;return{success:!0,data:{messages:o,totalMessages:a,unreadCount:p},display:`Inbox (${a} total, ${p} unread):
388
+ `),p=o.filter(m=>!m.seen).length;return{success:!0,data:{messages:o,totalMessages:a,unreadCount:p},display:`Inbox (${a} total, ${p} unread):
389
389
 
390
- ${m}`}}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",c=o.envelope?.to?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??"").join(", ")??"",u=o.source?.toString()??"",m=this.extractTextBody(u);return{success:!0,data:{seq:t,from:a,to:c,subject:o.envelope?.subject??"(no subject)",date:o.envelope?.date?.toISOString()??"",body:m},display:[`From: ${a}`,`To: ${c}`,`Subject: ${o.envelope?.subject??"(no subject)"}`,`Date: ${o.envelope?.date?.toISOString()??""}`,"",m.slice(0,3e3)+(m.length>3e3?`
390
+ ${h}`}}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",c=o.envelope?.to?.map(p=>p.name?`${p.name} <${p.address}>`:p.address??"").join(", ")??"",u=o.source?.toString()??"",h=this.extractTextBody(u);return{success:!0,data:{seq:t,from:a,to:c,subject:o.envelope?.subject??"(no subject)",date:o.envelope?.date?.toISOString()??"",body:h},display:[`From: ${a}`,`To: ${c}`,`Subject: ${o.envelope?.subject??"(no subject)"}`,`Date: ${o.envelope?.date?.toISOString()??""}`,"",h.slice(0,3e3)+(h.length>3e3?`
391
391
 
392
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 c=a.slice(-s),u=[];for await(let p of n.fetch(c,{envelope:!0})){let h=p.envelope?.from?.[0],w=h?h.name?`${h.name} <${h.address}>`:h.address??"unknown":"unknown";u.push({seq:p.seq,from:w,subject:p.envelope?.subject??"(no subject)",date:p.envelope?.date?.toISOString()??""})}u.reverse();let m=u.map((p,h)=>`${h+1}. [#${p.seq}] ${p.subject}
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 c=a.slice(-s),u=[];for await(let p of n.fetch(c,{envelope:!0})){let m=p.envelope?.from?.[0],w=m?m.name?`${m.name} <${m.address}>`:m.address??"unknown":"unknown";u.push({seq:p.seq,from:w,subject:p.envelope?.subject??"(no subject)",date:p.envelope?.date?.toISOString()??""})}u.reverse();let h=u.map((p,m)=>`${m+1}. [#${p.seq}] ${p.subject}
394
394
  From: ${p.from}
395
395
  Date: ${p.date}`).join(`
396
396
 
397
397
  `);return{success:!0,data:{query:e,results:u,totalMatches:c.length},display:`Search results for "${e}" (${c.length} matches):
398
398
 
399
- ${m}`}}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}
399
+ ${h}`}}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
400
  Subject: ${t}
401
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(`
402
402
 
@@ -408,35 +408,35 @@ Message ID: ${o.messageId}`}}extractTextBody(e){let t=e.split(/\r?\n\r?\n/);if(t
408
408
  \r
409
409
  `);if(u>=0)return this.decodeBody(i.slice(u+4))}}return this.decodeBody(t.slice(1).join(`
410
410
 
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 $n,Ke,An=f(()=>{"use strict";O();$n=1e5,Ke=class extends b{static{d(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 c=await fetch(s,a),u=c.headers.get("content-type")??"",m=await c.text(),p=m.length>$n,h=p?m.slice(0,$n)+`
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 Rn,Ke,Ln=f(()=>{"use strict";O();Rn=1e5,Ke=class extends _{static{d(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 c=await fetch(s,a),u=c.headers.get("content-type")??"",h=await c.text(),p=h.length>Rn,m=p?h.slice(0,Rn)+`
412
412
 
413
- [... truncated]`:m,w=h;u.includes("text/html")&&(w=this.stripHtml(h).slice(0,1e4));let E={status:c.status,statusText:c.statusText,contentType:u,bodyLength:m.length,truncated:p,body:h};return c.ok?{success:!0,data:E,display:`HTTP ${c.status} OK (${m.length} bytes)
413
+ [... truncated]`:h,w=m;u.includes("text/html")&&(w=this.stripHtml(m).slice(0,1e4));let E={status:c.status,statusText:c.statusText,contentType:u,bodyLength:h.length,truncated:p,body:m};return c.ok?{success:!0,data:E,display:`HTTP ${c.status} OK (${h.length} bytes)
414
414
 
415
415
  ${w.slice(0,5e3)}`}:{success:!0,data:E,display:`HTTP ${c.status} ${c.statusText}
416
416
 
417
- ${w.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,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 C from"node:fs";import de from"node:path";var Ys,Rn,Oi,Ve,Ln=f(()=>{"use strict";O();Ys=5e5,Rn=5e7,Oi={".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"},Ve=class extends b{static{d(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.',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. You must provide the file content.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(C.existsSync(i)&&C.lstatSync(i).isSymbolicLink()){let c=C.realpathSync(i);if(this.checkBlocked(c))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 de.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=de.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=C.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Ys){let r=C.readFileSync(e,"utf-8").slice(0,Ys);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${Ys}):
417
+ ${w.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,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 C from"node:fs";import de from"node:path";var Zs,Mn,Pi,Ve,Nn=f(()=>{"use strict";O();Zs=5e5,Mn=5e7,Pi={".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"},Ve=class extends _{static{d(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.',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. You must provide the file content.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(C.existsSync(i)&&C.lstatSync(i).isSymbolicLink()){let c=C.realpathSync(i);if(this.checkBlocked(c))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 de.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=de.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=C.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>Zs){let r=C.readFileSync(e,"utf-8").slice(0,Zs);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${Zs}):
418
418
 
419
419
  ${r}`}}let s=C.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=de.dirname(e);return C.mkdirSync(s,{recursive:!0}),C.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 C.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=C.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
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=C.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
421
  Size: ${t.size} bytes
422
- Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=C.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=de.dirname(e);C.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return C.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=de.dirname(s);return C.mkdirSync(n,{recursive:!0}),C.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return C.copyFileSync(e,s),C.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=de.dirname(s);return C.mkdirSync(n,{recursive:!0}),C.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(!C.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=C.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Rn)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Rn})`};let s=C.readFileSync(e),r=de.basename(e),n=de.extname(e).toLowerCase(),o=Oi[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 C.existsSync(e)?C.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(C.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 Ge}from"node:child_process";var Ye,Mn=f(()=>{"use strict";O();Ye=class extends b{static{d(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=Ge("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Ge("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Ge("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)+`
422
+ Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=C.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=de.dirname(e);C.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return C.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=de.dirname(s);return C.mkdirSync(n,{recursive:!0}),C.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return C.copyFileSync(e,s),C.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=de.dirname(s);return C.mkdirSync(n,{recursive:!0}),C.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(!C.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=C.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Mn)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Mn})`};let s=C.readFileSync(e),r=de.basename(e),n=de.extname(e).toLowerCase(),o=Pi[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 C.existsSync(e)?C.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(C.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 Ge}from"node:child_process";var Ye,Dn=f(()=>{"use strict";O();Ye=class extends _{static{d(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=Ge("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=Ge("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=Ge("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
423
 
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":Ge("pbcopy",{input:e,timeout:5e3});break;case"win32":Ge('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Ge("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 Rt}from"node:child_process";import Nn from"node:path";import Ci from"node:os";var Je,Dn=f(()=>{"use strict";O();Je=class extends b{static{d(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=Nn.join(Ci.homedir(),"Desktop"),n=e.path||Nn.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Rt(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":Rt(`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{Rt(`scrot "${n}"`,{timeout:1e4})}catch{try{Rt(`import -window root "${n}"`,{timeout:1e4})}catch{Rt(`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 Ui from"node:path";import Pi from"node:os";var On,Ze,Cn=f(()=>{"use strict";O();On=5e4,Ze=class extends b{static{d(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
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":Ge("pbcopy",{input:e,timeout:5e3});break;case"win32":Ge('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:Ge("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 Rt}from"node:child_process";import On from"node:path";import Fi from"node:os";var Je,Cn=f(()=>{"use strict";O();Je=class extends _{static{d(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=On.join(Fi.homedir(),"Desktop"),n=e.path||On.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Rt(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":Rt(`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{Rt(`scrot "${n}"`,{timeout:1e4})}catch{try{Rt(`import -window root "${n}"`,{timeout:1e4})}catch{Rt(`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 ji from"node:path";import Bi from"node:os";var Un,Ze,Pn=f(()=>{"use strict";O();Un=5e4,Ze=class extends _{static{d(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
425
  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
426
  (() => {
427
427
  document.querySelectorAll('script, style, noscript').forEach(el => el.remove());
428
428
  return document.body?.innerText ?? '';
429
429
  })()
430
- `),c=(i.length>On?i.slice(0,On)+`
430
+ `),c=(i.length>Un?i.slice(0,Un)+`
431
431
 
432
432
  [... truncated]`:i).replace(/\n{3,}/g,`
433
433
 
434
434
  `).trim();return{success:!0,data:{url:n.url(),title:o,length:i.length},display:`**${o}** (${n.url()})
435
435
 
436
- ${c}`}}catch(n){return{success:!1,error:`Failed to open "${s}": ${n.message}`}}}async screenshotPage(e,t){try{let s=await this.ensurePage(e),r=t.url;r&&await s.goto(r,{waitUntil:"networkidle2",timeout:3e4});let n=s.url();if(n==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let o=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||Ui.join(Pi.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 Qe,Un=f(()=>{"use strict";O();Qe=class extends b{static{d(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);switch(s){case"get":return this.getProfile(r.id);case"set_timezone":return this.setField(r.id,"timezone",e.value);case"set_language":return this.setField(r.id,"language",e.value);case"set_bio":return this.setField(r.id,"bio",e.value);case"set_preference":return this.setPreference(r.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:
436
+ ${c}`}}catch(n){return{success:!1,error:`Failed to open "${s}": ${n.message}`}}}async screenshotPage(e,t){try{let s=await this.ensurePage(e),r=t.url;r&&await s.goto(r,{waitUntil:"networkidle2",timeout:3e4});let n=s.url();if(n==="about:blank")return{success:!1,error:'No page is open. Use action "open" with a URL first, or provide a URL.'};let o=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),i=t.path||ji.join(Bi.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 Qe,Fn=f(()=>{"use strict";O();Qe=class extends _{static{d(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);switch(s){case"get":return this.getProfile(r.id);case"set_timezone":return this.setField(r.id,"timezone",e.value);case"set_language":return this.setField(r.id,"language",e.value);case"set_bio":return this.setField(r.id,"bio",e.value);case"set_preference":return this.setPreference(r.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
437
  ${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 Q,Lt=f(()=>{"use strict";Q=class{static{d(this,"CalendarProvider")}}});var Pn={};J(Pn,{CalDAVProvider:()=>cs});var cs,Js=f(()=>{"use strict";Lt();cs=class extends Q{static{d(this,"CalDAVProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"caldav"})}catch(e){throw new Error(`CalDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){let s=await this.client.fetchCalendars();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchCalendarObjects({calendar:n,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of o){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.start.getTime()-o.start.getTime())}async createEvent(e){let t=await this.client.fetchCalendars();if(!t||t.length===0)throw new Error("No calendars found");let s=`alfred-${Date.now()}@alfred`,r=this.buildICalEvent(s,e);return await this.client.createCalendarObject({calendar:t[0],filename:`${s}.ics`,iCalString:r}),{id:s,title:e.title,start:e.start,end:e.end,location:e.location,description:e.description,allDay:e.allDay}}async updateEvent(e,t){let s=await this.client.fetchCalendars();for(let r of s){let n=await this.client.fetchCalendarObjects({calendar:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseICalEvent(o.data,o.url);if(!i)continue;let a={title:t.title??i.title,start:t.start??i.start,end:t.end??i.end,location:t.location??i.location,description:t.description??i.description,allDay:t.allDay??i.allDay},c=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:c}}),{id:e,...a}}}throw new Error(`Event ${e} not found`)}async deleteEvent(e){let t=await this.client.fetchCalendars();for(let s of t){let r=await this.client.fetchCalendarObjects({calendar:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:n});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
439
- `).map(p=>p.trim()),r=d(p=>s.find(h=>h.startsWith(p+":"))?.slice(p.length+1),"get"),n=r("SUMMARY"),o=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),c=r("DESCRIPTION"),u=r("UID")??t;if(!n||!o)return;let m=o.length===8;return{id:u,title:n,start:this.parseICalDate(o),end:i?this.parseICalDate(i):this.parseICalDate(o),location:a||void 0,description:c||void 0,allDay:m}}catch(s){console.error("[caldav] Failed to parse iCal event",s);return}}parseICalDate(e){if(e.length===8)return new Date(`${e.slice(0,4)}-${e.slice(4,6)}-${e.slice(6,8)}`);let t=e.replace(/[^0-9TZ]/g,"");return t.length>=15?new Date(`${t.slice(0,4)}-${t.slice(4,6)}-${t.slice(6,8)}T${t.slice(9,11)}:${t.slice(11,13)}:${t.slice(13,15)}Z`):new Date(e)}buildICalEvent(e,t){let s=d((n,o)=>o?n.toISOString().slice(0,10).replace(/-/g,""):n.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
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 Q,Lt=f(()=>{"use strict";Q=class{static{d(this,"CalendarProvider")}}});var jn={};J(jn,{CalDAVProvider:()=>cs});var cs,Qs=f(()=>{"use strict";Lt();cs=class extends Q{static{d(this,"CalDAVProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"caldav"})}catch(e){throw new Error(`CalDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){let s=await this.client.fetchCalendars();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchCalendarObjects({calendar:n,timeRange:{start:e.toISOString(),end:t.toISOString()}});for(let i of o){let a=this.parseICalEvent(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.start.getTime()-o.start.getTime())}async createEvent(e){let t=await this.client.fetchCalendars();if(!t||t.length===0)throw new Error("No calendars found");let s=`alfred-${Date.now()}@alfred`,r=this.buildICalEvent(s,e);return await this.client.createCalendarObject({calendar:t[0],filename:`${s}.ics`,iCalString:r}),{id:s,title:e.title,start:e.start,end:e.end,location:e.location,description:e.description,allDay:e.allDay}}async updateEvent(e,t){let s=await this.client.fetchCalendars();for(let r of s){let n=await this.client.fetchCalendarObjects({calendar:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseICalEvent(o.data,o.url);if(!i)continue;let a={title:t.title??i.title,start:t.start??i.start,end:t.end??i.end,location:t.location??i.location,description:t.description??i.description,allDay:t.allDay??i.allDay},c=this.buildICalEvent(e,a);return await this.client.updateCalendarObject({calendarObject:{...o,data:c}}),{id:e,...a}}}throw new Error(`Event ${e} not found`)}async deleteEvent(e){let t=await this.client.fetchCalendars();for(let s of t){let r=await this.client.fetchCalendarObjects({calendar:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteCalendarObject({calendarObject:n});return}}throw new Error(`Event ${e} not found`)}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}parseICalEvent(e,t){try{let s=e.split(`
439
+ `).map(p=>p.trim()),r=d(p=>s.find(m=>m.startsWith(p+":"))?.slice(p.length+1),"get"),n=r("SUMMARY"),o=r("DTSTART")??r("DTSTART;VALUE=DATE"),i=r("DTEND")??r("DTEND;VALUE=DATE"),a=r("LOCATION"),c=r("DESCRIPTION"),u=r("UID")??t;if(!n||!o)return;let h=o.length===8;return{id:u,title:n,start:this.parseICalDate(o),end:i?this.parseICalDate(i):this.parseICalDate(o),location:a||void 0,description:c||void 0,allDay:h}}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=d((n,o)=>o?n.toISOString().slice(0,10).replace(/-/g,""):n.toISOString().replace(/[-:]/g,"").replace(/\.\d{3}/,""),"formatDate"),r=`BEGIN:VCALENDAR\r
440
440
  VERSION:2.0\r
441
441
  PRODID:-//Alfred//EN\r
442
442
  BEGIN:VEVENT\r
@@ -451,30 +451,30 @@ BEGIN:VEVENT\r
451
451
  `),r+=`DTSTAMP:${s(new Date)}\r
452
452
  `,r+=`END:VEVENT\r
453
453
  END:VCALENDAR\r
454
- `,r}}});var Fn={};J(Fn,{GoogleCalendarProvider:()=>ls});var ls,Zs=f(()=>{"use strict";Lt();ls=class extends Q{static{d(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 jn={};J(jn,{MicrosoftCalendarProvider:()=>ds});var ds,Qs=f(()=>{"use strict";Lt();ds=class extends Q{static{d(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 Mt(l){switch(l.provider){case"caldav":{if(!l.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Js(),Pn)),t=new e(l.caldav);return await t.initialize(),t}case"google":{if(!l.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(Zs(),Fn)),t=new e(l.google);return await t.initialize(),t}case"microsoft":{if(!l.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(Qs(),jn)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${l.provider}`)}}var Bn=f(()=>{"use strict";d(Mt,"createCalendarProvider")});var _e,Wn=f(()=>{"use strict";O();_e=class extends b{static{d(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(`
454
+ `,r}}});var Bn={};J(Bn,{GoogleCalendarProvider:()=>ls});var ls,er=f(()=>{"use strict";Lt();ls=class extends Q{static{d(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 Wn={};J(Wn,{MicrosoftCalendarProvider:()=>ds});var ds,tr=f(()=>{"use strict";Lt();ds=class extends Q{static{d(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 Mt(l){switch(l.provider){case"caldav":{if(!l.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Qs(),jn)),t=new e(l.caldav);return await t.initialize(),t}case"google":{if(!l.google)throw new Error("Google Calendar config missing");let{GoogleCalendarProvider:e}=await Promise.resolve().then(()=>(er(),Bn)),t=new e(l.google);return await t.initialize(),t}case"microsoft":{if(!l.microsoft)throw new Error("Microsoft Calendar config missing");let{MicrosoftCalendarProvider:e}=await Promise.resolve().then(()=>(tr(),Wn)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${l.provider}`)}}var Xn=f(()=>{"use strict";d(Mt,"createCalendarProvider")});var _e,zn=f(()=>{"use strict";O();_e=class extends _{static{d(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
455
  `);return{success:!0,data:r,display:`${r.length} event(s):
456
456
  ${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
457
  ${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 Xn=f(()=>{"use strict";Lt();Js();Zs();Qs();Bn();Wn()});var et,zn=f(()=>{"use strict";O();et=class extends b{static{d(this,"CrossPlatformSkill")}users;linkTokens;adapters;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){super(),this.users=e,this.linkTokens=t,this.adapters=s}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);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){if(this.linkTokens.cleanup(),this.linkTokens.countRecentByUser(e.userId,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let s=this.linkTokens.create(e.userId,e.platform);return{success:!0,data:{code:s.code,expiresAt:s.expiresAt},display:`Your linking code is: **${s.code}**
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 Hn=f(()=>{"use strict";Lt();Qs();er();tr();Xn();zn()});var et,qn=f(()=>{"use strict";O();et=class extends _{static{d(this,"CrossPlatformSkill")}users;linkTokens;adapters;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){super(),this.users=e,this.linkTokens=t,this.adapters=s}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);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){if(this.linkTokens.cleanup(),this.linkTokens.countRecentByUser(e.userId,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let s=this.linkTokens.create(e.userId,e.platform);return{success:!0,data:{code:s.code,expiresAt:s.expiresAt},display:`Your linking code is: **${s.code}**
459
459
 
460
460
  Enter this code on your other platform within 10 minutes using:
461
- "Link my account with code ${s.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.checkConfirmRateLimit(t.userId);if(r)return{success:!1,error:r};let n=this.linkTokens.findByCode(s.trim());if(!n)return this.recordFailedConfirm(t.userId),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};if(n.userId===t.userId)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let o=this.users.getMasterUserId(n.userId),i=this.users.getMasterUserId(t.userId),a;if(o!==n.userId?a=o:i!==t.userId?a=i:a=n.userId,o!==n.userId&&i!==t.userId&&o!==i){let m=this.users.getLinkedUsers(i);for(let p of m)this.users.setMasterUser(p.id,a)}n.userId!==a&&this.users.setMasterUser(n.userId,a),t.userId!==a&&this.users.setMasterUser(t.userId,a),this.linkTokens.consume(n.id);let c=this.users.findById(n.userId),u=n.platform;return{success:!0,data:{masterUserId:a,linkedPlatform:u},display:`Account linked successfully! Your ${u} account (${c?.displayName??c?.username??"unknown"}) is now linked to this ${t.platform} account.
461
+ "Link my account with code ${s.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.checkConfirmRateLimit(t.userId);if(r)return{success:!1,error:r};let n=this.linkTokens.findByCode(s.trim());if(!n)return this.recordFailedConfirm(t.userId),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};if(n.userId===t.userId)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let o=this.users.getMasterUserId(n.userId),i=this.users.getMasterUserId(t.userId),a;if(o!==n.userId?a=o:i!==t.userId?a=i:a=n.userId,o!==n.userId&&i!==t.userId&&o!==i){let h=this.users.getLinkedUsers(i);for(let p of h)this.users.setMasterUser(p.id,a)}n.userId!==a&&this.users.setMasterUser(n.userId,a),t.userId!==a&&this.users.setMasterUser(t.userId,a),this.linkTokens.consume(n.id);let c=this.users.findById(n.userId),u=n.platform;return{success:!0,data:{masterUserId:a,linkedPlatform:u},display:`Account linked successfully! Your ${u} account (${c?.displayName??c?.username??"unknown"}) is now linked to this ${t.platform} account.
462
462
 
463
463
  Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e){let t=e.platform,s=e.chat_id,r=e.message;if(!t)return{success:!1,error:'Missing required field "platform"'};if(!s)return{success:!1,error:'Missing required field "chat_id"'};if(!r)return{success:!1,error:'Missing required field "message"'};let n=this.adapters.get(t);if(!n)return{success:!1,error:`Platform "${t}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};try{return{success:!0,data:{messageId:await n.sendMessage(s,r),platform:t,chatId:s},display:`Message sent to ${t} (chat ${s}).`}}catch(o){return{success:!1,error:`Failed to send message: ${o instanceof Error?o.message:String(o)}`}}}async listIdentities(e){let t=this.users.getMasterUserId(e.userId),s=this.users.getLinkedUsers(t);if(s.length<=1)return{success:!0,data:{identities:s},display:`No linked accounts found. To link another platform, use:
464
464
  "Start linking my account" on the platform you want to link from, then enter the code on the other platform.`};let r=s.map(n=>{let o=n.id===e.userId?" (current)":"",i=n.displayName??n.username??n.platformUserId;return`- **${n.platform}**: ${i}${o}`});return{success:!0,data:{identities:s.map(n=>({platform:n.platform,username:n.username,displayName:n.displayName}))},display:`Linked accounts:
465
465
  ${r.join(`
466
- `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.users.getMasterUserId(t.userId),o=this.users.getLinkedUsers(r).find(i=>i.platform===s&&i.id!==t.userId);return o?(this.users.setMasterUser(o.id,o.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:o.id},display:`Unlinked ${s} account (${o.displayName??o.username??o.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var tt,Hn=f(()=>{"use strict";O();tt=class extends b{static{d(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}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(t.userId,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.taskRepo.getByUser(e.userId);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:
466
+ `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.users.getMasterUserId(t.userId),o=this.users.getLinkedUsers(r).find(i=>i.platform===s&&i.id!==t.userId);return o?(this.users.setMasterUser(o.id,o.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:o.id},display:`Unlinked ${s} account (${o.displayName??o.username??o.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var tt,Kn=f(()=>{"use strict";O();tt=class extends _{static{d(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}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(t.userId,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.taskRepo.getByUser(e.userId);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
467
  ${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.taskRepo.getByUser(t.userId).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 st,qn=f(()=>{"use strict";O();st=class extends b{static{d(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}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,c=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 p=parseInt(o,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let p=new Date(o);if(isNaN(p.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(p.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let u=this.actionRepo.create({userId:t.userId,platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:c}),m=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:u.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${u.id}): "${s}" \u2014 ${m}, running "${i}"${u.nextRunAt?`. Next run: ${u.nextRunAt}`:""}`}}listActions(e){let t=this.actionRepo.getByUser(e.userId);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:
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.taskRepo.getByUser(t.userId).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 st,Vn=f(()=>{"use strict";O();st=class extends _{static{d(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}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,c=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 p=parseInt(o,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let p=new Date(o);if(isNaN(p.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(p.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let u=this.actionRepo.create({userId:t.userId,platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:c}),h=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:u.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${u.id}): "${s}" \u2014 ${h}, running "${i}"${u.nextRunAt?`. Next run: ${u.nextRunAt}`:""}`}}listActions(e){let t=this.actionRepo.getByUser(e.userId);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
469
  ${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);return!n||n.userId!==s.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);return!r||r.userId!==t.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 Se,er=f(()=>{"use strict";Se=class{static{d(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 Fi,ke,tr=f(()=>{"use strict";O();Fi=["read","write","destructive","admin"],ke=class extends b{static{d(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&&Fi.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 Nt,Kn=f(()=>{"use strict";er();tr();Nt=class{static{d(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new Se(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 ke(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 Vn=f(()=>{"use strict";er();tr();Kn()});import{spawn as ji}from"node:child_process";import rt from"node:fs";import sr from"node:path";import Bi from"node:os";import Wi from"node:crypto";var ve,rr=f(()=>{"use strict";ve=class{static{d(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=sr.join(Bi.tmpdir(),`alfred-sandbox-${Wi.randomUUID()}`);rt.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=sr.join(n,`script.${o}`);rt.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],u=Date.now();return await new Promise(m=>{let p=ji(a,c,{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"]}),h="",w="";p.stdout.on("data",E=>{h+=E.toString()}),p.stderr.on("data",E=>{w+=E.toString()}),p.on("close",E=>{let T=Date.now()-u,v=[];try{let $=rt.readdirSync(n).filter(x=>!x.startsWith("script."));for(let x of $){let M=sr.join(n,x),k=rt.statSync(M);if(k.isFile()&&k.size<1e7){let S=rt.readFileSync(M),U=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":"application/octet-stream";v.push({name:x,data:S,mimeType:U})}}}catch{}m({stdout:h.slice(0,5e4),stderr:w.slice(0,1e4),exitCode:E??1,files:v.length>0?v:void 0,durationMs:T})}),p.on("error",E=>{m({stdout:"",stderr:E.message,exitCode:1,durationMs:Date.now()-u})}),p.stdin.end()})}finally{try{rt.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var Dt,Gn=f(()=>{"use strict";O();rr();Dt=class extends b{static{d(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 charts, or testing code snippets. Code runs in an isolated temp directory with a timeout.",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 ve;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"'};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)};
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);return!n||n.userId!==s.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);return!r||r.userId!==t.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 Se,sr=f(()=>{"use strict";Se=class{static{d(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 Wi,ke,rr=f(()=>{"use strict";O();Wi=["read","write","destructive","admin"],ke=class extends _{static{d(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&&Wi.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 Nt,Gn=f(()=>{"use strict";sr();rr();Nt=class{static{d(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new Se(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 ke(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 Yn=f(()=>{"use strict";sr();rr();Gn()});import{spawn as Xi}from"node:child_process";import rt from"node:fs";import nr from"node:path";import zi from"node:os";import Hi from"node:crypto";var ve,or=f(()=>{"use strict";ve=class{static{d(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=nr.join(zi.tmpdir(),`alfred-sandbox-${Hi.randomUUID()}`);rt.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=nr.join(n,`script.${o}`);rt.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],u=Date.now();return await new Promise(h=>{let p=Xi(a,c,{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"]}),m="",w="";p.stdout.on("data",E=>{m+=E.toString()}),p.stderr.on("data",E=>{w+=E.toString()}),p.on("close",E=>{let T=Date.now()-u,v=[];try{let $=rt.readdirSync(n).filter(x=>!x.startsWith("script."));for(let x of $){let M=nr.join(n,x),k=rt.statSync(M);if(k.isFile()&&k.size<1e7){let S=rt.readFileSync(M),P=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":"application/octet-stream";v.push({name:x,data:S,mimeType:P})}}}catch{}h({stdout:m.slice(0,5e4),stderr:w.slice(0,1e4),exitCode:E??1,files:v.length>0?v:void 0,durationMs:T})}),p.on("error",E=>{h({stdout:"",stderr:E.message,exitCode:1,durationMs:Date.now()-u})}),p.stdin.end()})}finally{try{rt.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var Dt,Jn=f(()=>{"use strict";O();or();Dt=class extends _{static{d(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 charts, or testing code snippets. Code runs in an isolated temp directory with a timeout.",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 ve;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"'};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
472
  ${r}`:a=`INPUT_DATA = ${JSON.stringify(o)}
473
- ${r}`);let c=await this.executor.execute(a,n,{timeout:i}),u=c.files?.map(p=>({fileName:p.name,data:p.data,mimeType:p.mimeType})),m=[c.stdout?`Output:
473
+ ${r}`);let c=await this.executor.execute(a,n,{timeout:i}),u=c.files?.map(p=>({fileName:p.name,data:p.data,mimeType:p.mimeType})),h=[c.stdout?`Output:
474
474
  ${c.stdout}`:"",c.stderr?`Errors:
475
475
  ${c.stderr}`:"",`Exit code: ${c.exitCode}`,`Duration: ${c.durationMs}ms`,u&&u.length>0?`Files generated: ${u.map(p=>p.fileName).join(", ")}`:""].filter(Boolean).join(`
476
476
 
477
- `);return{success:c.exitCode===0,data:{stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,durationMs:c.durationMs,fileCount:c.files?.length??0},display:m,error:c.exitCode!==0?`Code execution failed with exit code ${c.exitCode}`:void 0,attachments:u}}}});var Yn=f(()=>{"use strict";rr();Gn()});var nt,Jn=f(()=>{"use strict";O();nt=class extends b{static{d(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}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 c=await this.processor.ingest(t.userId,s,r,n);return{success:!0,data:c,display:`Document "${r}" ingested successfully (${c.chunkCount} chunks). ID: ${c.documentId.slice(0,8)}...`}}catch(c){return{success:!1,error:`Failed to ingest document: ${c instanceof Error?c.message:String(c)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let o=(await this.embeddingService.semanticSearch(t.userId,s,r)).filter(a=>a.category==="document");if(o.length===0)return{success:!0,data:[],display:`No document matches found for "${s}".`};let i=o.map((a,c)=>`${c+1}. (score: ${a.score.toFixed(3)}) ${a.value.slice(0,200)}${a.value.length>200?"...":""}`).join(`
477
+ `);return{success:c.exitCode===0,data:{stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,durationMs:c.durationMs,fileCount:c.files?.length??0},display:h,error:c.exitCode!==0?`Code execution failed with exit code ${c.exitCode}`:void 0,attachments:u}}}});var Zn=f(()=>{"use strict";or();Jn()});var nt,Qn=f(()=>{"use strict";O();nt=class extends _{static{d(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}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 c=await this.processor.ingest(t.userId,s,r,n);return{success:!0,data:c,display:`Document "${r}" ingested successfully (${c.chunkCount} chunks). ID: ${c.documentId.slice(0,8)}...`}}catch(c){return{success:!1,error:`Failed to ingest document: ${c instanceof Error?c.message:String(c)}`}}}async search(e,t){let s=e.query,r=e.limit||5;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};if(!this.embeddingService)return{success:!1,error:"Embedding service not available for document search"};let o=(await this.embeddingService.semanticSearch(t.userId,s,r)).filter(a=>a.category==="document");if(o.length===0)return{success:!0,data:[],display:`No document matches found for "${s}".`};let i=o.map((a,c)=>`${c+1}. (score: ${a.score.toFixed(3)}) ${a.value.slice(0,200)}${a.value.length>200?"...":""}`).join(`
478
478
 
479
479
  `);return{success:!0,data:o,display:`Found ${o.length} relevant chunk(s):
480
480
 
@@ -486,12 +486,12 @@ ${i}`}}summarize(e){let t=e.document_id;if(!t||typeof t!="string")return{success
486
486
 
487
487
  ${a}`}}list(e,t){let s=e.limit||50,n=this.docRepo.listByUser(t.userId).slice(0,s);if(n.length===0)return{success:!0,data:[],display:"No documents found."};let o=n.map(i=>`- **${i.filename}** (${i.id.slice(0,8)}...) \u2014 ${i.mimeType}, ${i.chunkCount} chunks, ${i.sizeBytes} bytes`).join(`
488
488
  `);return{success:!0,data:n,display:`${n.length} document(s):
489
- ${o}`}}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 us={};J(us,{ActivityTracker:()=>be,BackgroundTaskSkill:()=>tt,BrowserSkill:()=>Ze,CalculatorSkill:()=>Ue,CalendarProvider:()=>Q,CalendarSkill:()=>_e,ClipboardSkill:()=>Ye,CodeExecutionSkill:()=>Dt,CodeExecutor:()=>ve,CrossPlatformSkill:()=>et,DelegateSkill:()=>He,DocumentSkill:()=>nt,EmailSkill:()=>qe,FileSkill:()=>Ve,HttpSkill:()=>Ke,MCPClient:()=>Se,MCPManager:()=>Nt,MCPSkillAdapter:()=>ke,MemorySkill:()=>ze,NoteSkill:()=>Be,PluginLoader:()=>as,ProfileSkill:()=>Qe,ReminderSkill:()=>je,ScheduledTaskSkill:()=>st,ScreenshotSkill:()=>Je,ShellSkill:()=>Xe,Skill:()=>b,SkillRegistry:()=>Oe,SkillSandbox:()=>Ce,SystemInfoSkill:()=>Pe,WeatherSkill:()=>We,WebSearchSkill:()=>Fe,createCalendarProvider:()=>Mt});var Ot=f(()=>{"use strict";O();mn();hn();Vs();fn();gn();yn();wn();En();Tn();bn();kn();vn();xn();In();An();Ln();Mn();Dn();Cn();Un();Xn();zn();Hn();qn();Vn();Yn();Jn()});var Ct,nr=f(()=>{"use strict";Ct=class{static{d(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 Zn from"node:fs";import Qn from"node:path";var Xi,eo,zi,Hi,qi,Ut,or=f(()=>{"use strict";qs();Xi=15*60*1e3,eo=50,zi=2,Hi=.85,qi=1e5,Ut=class{static{d(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 xt}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=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),i=this.conversationManager.getHistory(o.id,200);this.conversationManager.addMessage(o.id,"user",e.text);let a,c=this.isSyntheticLabel(e.text),u=e.attachments?.some(N=>N.type==="audio")??!1,m=c&&!u;if(this.memoryRetriever&&e.text&&!m)try{a=await this.memoryRetriever.retrieve(n,e.text,15)}catch(N){this.logger.debug({err:N},"Hybrid memory retrieval failed")}if(!a&&this.memoryRepo&&!m)try{if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let N=await this.embeddingService.semanticSearch(n,e.text,10),H=this.memoryRepo.getRecentForPrompt(n,5),B=new Set;a=[];for(let W of N)B.has(W.key)||(B.add(W.key),a.push(W));for(let W of H)B.has(W.key)||(B.add(W.key),a.push(W))}else a=this.memoryRepo.getRecentForPrompt(n,20)}catch(N){this.logger.debug({err:N},"Memory loading failed")}let p;try{"getProfile"in this.users&&(p=this.users.getProfile(r.id),p&&!p.displayName&&(p.displayName=r.displayName??r.username))}catch(N){this.logger.debug({err:N},"Profile loading failed")}let h=p?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,w=this.skillRegistry?this.skillRegistry.getAll().map(N=>N.metadata):void 0,E=w?this.promptBuilder.buildTools(w):void 0,T=this.promptBuilder.buildSystemPrompt({memories:a,skills:w,userProfile:p}),v=this.buildActiveAgentStatus();v&&(T+=`
489
+ ${o}`}}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 us={};J(us,{ActivityTracker:()=>be,BackgroundTaskSkill:()=>tt,BrowserSkill:()=>Ze,CalculatorSkill:()=>Ue,CalendarProvider:()=>Q,CalendarSkill:()=>_e,ClipboardSkill:()=>Ye,CodeExecutionSkill:()=>Dt,CodeExecutor:()=>ve,CrossPlatformSkill:()=>et,DelegateSkill:()=>He,DocumentSkill:()=>nt,EmailSkill:()=>qe,FileSkill:()=>Ve,HttpSkill:()=>Ke,MCPClient:()=>Se,MCPManager:()=>Nt,MCPSkillAdapter:()=>ke,MemorySkill:()=>ze,NoteSkill:()=>Be,PluginLoader:()=>as,ProfileSkill:()=>Qe,ReminderSkill:()=>je,ScheduledTaskSkill:()=>st,ScreenshotSkill:()=>Je,ShellSkill:()=>Xe,Skill:()=>_,SkillRegistry:()=>Oe,SkillSandbox:()=>Ce,SystemInfoSkill:()=>Pe,WeatherSkill:()=>We,WebSearchSkill:()=>Fe,createCalendarProvider:()=>Mt});var Ot=f(()=>{"use strict";O();fn();gn();Ys();yn();wn();En();Tn();bn();_n();Sn();xn();In();$n();An();Ln();Nn();Dn();Cn();Pn();Fn();Hn();qn();Kn();Vn();Yn();Zn();Qn()});var Ct,ir=f(()=>{"use strict";Ct=class{static{d(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 eo from"node:fs";import to from"node:path";var qi,so,Ki,Vi,Gi,Ut,ar=f(()=>{"use strict";Vs();qi=15*60*1e3,so=50,Ki=2,Vi=.85,Gi=1e5,Ut=class{static{d(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 xt}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=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),i=this.conversationManager.getHistory(o.id,200);this.conversationManager.addMessage(o.id,"user",e.text);let a,c=this.isSyntheticLabel(e.text),u=e.attachments?.some(N=>N.type==="audio")??!1,h=c&&!u;if(this.memoryRetriever&&e.text&&!h)try{a=await this.memoryRetriever.retrieve(n,e.text,15)}catch(N){this.logger.debug({err:N},"Hybrid memory retrieval failed")}if(!a&&this.memoryRepo&&!h)try{if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let N=await this.embeddingService.semanticSearch(n,e.text,10),H=this.memoryRepo.getRecentForPrompt(n,5),B=new Set;a=[];for(let W of N)B.has(W.key)||(B.add(W.key),a.push(W));for(let W of H)B.has(W.key)||(B.add(W.key),a.push(W))}else a=this.memoryRepo.getRecentForPrompt(n,20)}catch(N){this.logger.debug({err:N},"Memory loading failed")}let p;try{"getProfile"in this.users&&(p=this.users.getProfile(r.id),p&&!p.displayName&&(p.displayName=r.displayName??r.username))}catch(N){this.logger.debug({err:N},"Profile loading failed")}let m=p?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,w=this.skillRegistry?this.skillRegistry.getAll().map(N=>N.metadata):void 0,E=w?this.promptBuilder.buildTools(w):void 0,T=this.promptBuilder.buildSystemPrompt({memories:a,skills:w,userProfile:p}),v=this.buildActiveAgentStatus();v&&(T+=`
490
490
 
491
- `+v);let $=this.promptBuilder.buildMessages(i),x=this.collapseRepeatedToolErrors($),M=await this.buildUserContent(e,t);x.push({role:"user",content:M});let k=this.trimToContextWindow(T,x),S,U=0,z=Date.now(),G="",Y=0,he=[];for(t?.("Thinking...");S=await this.llm.complete({messages:k,system:T,tools:E&&E.length>0?E:void 0}),!(!S.toolCalls||S.toolCalls.length===0);){let N=Date.now()-z;if(N>=Xi){let te=Math.round(N/6e4);this.logger.warn({iteration:U,elapsedMin:te,pendingToolCalls:S.toolCalls.length},"Tool loop timeout reached"),S=await this.abortToolLoop(k,S,o.id,T,`Das Zeitlimit von ${te} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(U>=eo){this.logger.warn({iteration:U,pendingToolCalls:S.toolCalls.length},"Tool loop iteration cap reached"),S=await this.abortToolLoop(k,S,o.id,T,`Das Iterationslimit von ${eo} Tool-Aufrufen wurde erreicht.`);break}U++,this.logger.info({iteration:U,toolCalls:S.toolCalls.length},"Processing tool calls");let H=[];S.content&&H.push({type:"text",text:S.content});for(let te of S.toolCalls)H.push({type:"tool_use",id:te.id,name:te.name,input:te.input});k.push({role:"assistant",content:H});let B=await this.executeToolCallsParallel(S.toolCalls,{userId:e.userId,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:o.id,timezone:h},t),W=B.blocks;B.attachments.length>0&&he.push(...B.attachments),this.conversationManager.addMessage(o.id,"assistant",S.content??"",JSON.stringify(S.toolCalls)),this.conversationManager.addMessage(o.id,"user","",JSON.stringify(W));let Le=this.buildErrorSignature(W);if(Le){if(Le===G?Y++:(Y=1,G=Le),Y>=zi){this.logger.warn({iteration:U,consecutiveErrors:Y,errorSignature:Le},"Tool loop aborted: same error repeated consecutively"),S=await this.abortToolLoop(k,S,o.id,T,`Der gleiche Tool-Fehler ist ${Y}x hintereinander aufgetreten: "${G.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else Y=0,G="";k.push({role:"user",content:W}),t?.("Thinking...")}let A=S.content;if(!A)for(let N=k.length-1;N>=0;N--){let H=k[N];if(H.role==="assistant"&&Array.isArray(H.content)){let B=H.content.find(W=>W.type==="text");if(B&&"text"in B&&B.text){A=B.text;break}}}A||(A="(no response)"),this.conversationManager.addMessage(o.id,"assistant",A),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,A);let ee=Date.now()-s;return this.logger.info({duration:ee,tokens:S.usage,stopReason:S.stopReason,toolIterations:U},"Message processed"),{text:A,attachments:he.length>0?he: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 c of t.toolCalls)a.push({type:"tool_use",id:c.id,name:c.name,input:c.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 c=e[a],u=e[a+1];if(c.role==="assistant"&&u?.role==="user"&&this.toolPairSignature(c,u)===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=d((a,c)=>{let u=c.content;if(c.attachments&&c.attachments.length>0){r.push(...c.attachments);let m=c.attachments.map(p=>p.fileName).join(", ");u+=`
491
+ `+v);let $=this.promptBuilder.buildMessages(i),x=this.collapseRepeatedToolErrors($),M=await this.buildUserContent(e,t);x.push({role:"user",content:M});let k=this.trimToContextWindow(T,x),S,P=0,z=Date.now(),G="",Y=0,he=[];for(t?.("Thinking...");S=await this.llm.complete({messages:k,system:T,tools:E&&E.length>0?E:void 0}),!(!S.toolCalls||S.toolCalls.length===0);){let N=Date.now()-z;if(N>=qi){let se=Math.round(N/6e4);this.logger.warn({iteration:P,elapsedMin:se,pendingToolCalls:S.toolCalls.length},"Tool loop timeout reached"),S=await this.abortToolLoop(k,S,o.id,T,`Das Zeitlimit von ${se} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(P>=so){this.logger.warn({iteration:P,pendingToolCalls:S.toolCalls.length},"Tool loop iteration cap reached"),S=await this.abortToolLoop(k,S,o.id,T,`Das Iterationslimit von ${so} Tool-Aufrufen wurde erreicht.`);break}P++,this.logger.info({iteration:P,toolCalls:S.toolCalls.length},"Processing tool calls");let H=[];S.content&&H.push({type:"text",text:S.content});for(let se of S.toolCalls)H.push({type:"tool_use",id:se.id,name:se.name,input:se.input});k.push({role:"assistant",content:H});let B=await this.executeToolCallsParallel(S.toolCalls,{userId:e.userId,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:o.id,timezone:m},t),W=B.blocks;B.attachments.length>0&&he.push(...B.attachments),this.conversationManager.addMessage(o.id,"assistant",S.content??"",JSON.stringify(S.toolCalls)),this.conversationManager.addMessage(o.id,"user","",JSON.stringify(W));let Le=this.buildErrorSignature(W);if(Le){if(Le===G?Y++:(Y=1,G=Le),Y>=Ki){this.logger.warn({iteration:P,consecutiveErrors:Y,errorSignature:Le},"Tool loop aborted: same error repeated consecutively"),S=await this.abortToolLoop(k,S,o.id,T,`Der gleiche Tool-Fehler ist ${Y}x hintereinander aufgetreten: "${G.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else Y=0,G="";k.push({role:"user",content:W}),t?.("Thinking...")}let A=S.content;if(!A)for(let N=k.length-1;N>=0;N--){let H=k[N];if(H.role==="assistant"&&Array.isArray(H.content)){let B=H.content.find(W=>W.type==="text");if(B&&"text"in B&&B.text){A=B.text;break}}}A||(A="(no response)"),this.conversationManager.addMessage(o.id,"assistant",A),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,A);let te=Date.now()-s;return this.logger.info({duration:te,tokens:S.usage,stopReason:S.stopReason,toolIterations:P},"Message processed"),{text:A,attachments:he.length>0?he: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 c of t.toolCalls)a.push({type:"tool_use",id:c.id,name:c.name,input:c.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 c=e[a],u=e[a+1];if(c.role==="assistant"&&u?.role==="user"&&this.toolPairSignature(c,u)===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=d((a,c)=>{let u=c.content;if(c.attachments&&c.attachments.length>0){r.push(...c.attachments);let h=c.attachments.map(p=>p.fileName).join(", ");u+=`
492
492
 
493
- [${c.attachments.length} Datei(en) werden dem User gesendet: ${m}]`}return{type:"tool_result",tool_use_id:a.id,content:u,is_error:c.isError}},"buildBlock");if(e.length===1){let a=e[0],c=this.getToolLabel(a.name,a.input);s?.(c);let u=await this.executeToolCall(a,t,s);return{blocks:[n(a,u)],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,c)=>{let u=o[c];return u.status==="fulfilled"?n(a,u.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${u.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(()=>(Ot(),us));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}: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(`
494
- `)}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*Hi),n=le(e),o=t[t.length-1],i=os(o),c=n+i+200+500,u=r-c;if(u<=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),p=this.groupToolPairs(m),h=[];for(let T=p.length-1;T>=0;T--){let v=p[T].reduce(($,x)=>$+os(x),0);v>u||(u-=v,h.unshift(p[T]))}let w=h.flat(),E=m.length-w.length;if(E>0){this.logger.info({trimmedCount:E,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let T=m.slice(0,m.length-w.length),v=this.summarizeTrimmedMessages(T);w.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${E} messages were trimmed to fit the context window:
493
+ [${c.attachments.length} Datei(en) werden dem User gesendet: ${h}]`}return{type:"tool_result",tool_use_id:a.id,content:u,is_error:c.isError}},"buildBlock");if(e.length===1){let a=e[0],c=this.getToolLabel(a.name,a.input);s?.(c);let u=await this.executeToolCall(a,t,s);return{blocks:[n(a,u)],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,c)=>{let u=o[c];return u.status==="fulfilled"?n(a,u.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${u.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(()=>(Ot(),us));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}: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(`
494
+ `)}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*Vi),n=le(e),o=t[t.length-1],i=os(o),c=n+i+200+500,u=r-c;if(u<=0)return this.logger.warn({maxInputTokens:r,systemTokens:n,latestTokens:i},"Context window very tight, sending only latest message"),[o];let h=t.slice(0,-1),p=this.groupToolPairs(h),m=[];for(let T=p.length-1;T>=0;T--){let v=p[T].reduce(($,x)=>$+os(x),0);v>u||(u-=v,m.unshift(p[T]))}let w=m.flat(),E=h.length-w.length;if(E>0){this.logger.info({trimmedCount:E,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let T=h.slice(0,h.length-w.length),v=this.summarizeTrimmedMessages(T);w.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${E} messages were trimmed to fit the context window:
495
495
  ${v}
496
496
 
497
497
  The conversation continues below with the most recent messages.]`})}return w.push(o),this.promptBuilder.sanitizeToolMessages(w)}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 c=JSON.stringify(a.input).slice(0,80);t.push(` \u2192 Tool: ${a.name}(${c})`)}}}let s=40;if(t.length>s){let r=t.slice(0,s);return r.push(` ... and ${t.length-s} more interactions`),r.join(`
@@ -499,19 +499,19 @@ The conversation continues below with the most recent messages.]`})}return w.pus
499
499
  `)}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"),c=e.text==="[Voice message]"?"":`${e.text}
500
500
 
501
501
  `;if(r.push({type:"text",text:`${c}[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 c=this.isTextMimeType(i.mimeType),u=`[File received: "${i.fileName??"unknown"}" (${this.formatBytes(i.data.length)}, ${i.mimeType??"unknown type"})]
502
- [Saved to: ${a}]`;if(c&&i.data.length<=qi){let m=i.data.toString("utf-8");u+=`
502
+ [Saved to: ${a}]`;if(c&&i.data.length<=Gi){let h=i.data.toString("utf-8");u+=`
503
503
  [File content]:
504
- ${m}`}r.push({type:"text",text:u}),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??Qn.resolve("./data/inbox");try{Zn.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=Qn.join(t,o);try{return Zn.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 Pt,ir=f(()=>{"use strict";Pt=class{static{d(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3){this.reminderRepo=e,this.sendMessage=t,this.logger=s,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{await this.sendMessage(t.platform,t.chatId,`\u23F0 Reminder: ${t.message}`),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 Ft,ar=f(()=>{"use strict";Ft=class{static{d(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 jt,cr=f(()=>{"use strict";jt=class{static{d(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}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 Bt,lr=f(()=>{"use strict";Bt=class{static{d(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 c=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:c}});return o.sort((a,c)=>c.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var Wt,dr=f(()=>{"use strict";Wt=class{static{d(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),c=this.chunkText(n,500,50);for(let u=0;u<c.length;u++){let m;try{await this.embeddingService.embedAndStore(e,c[u],"document",`${a.id}:${u}`),m=`${a.id}:${u}`}catch(p){this.logger.warn({documentId:a.id,chunkIndex:u,err:p},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,u,c[u],m)}return this.docRepo.updateChunkCount(a.id,c.length),this.logger.info({documentId:a.id,filename:s,chunkCount:c.length},"Document ingested"),{documentId:a.id,chunkCount:c.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let u=Math.max(c-200,a),m=e.slice(u,c+200),p=m.lastIndexOf(`
504
+ ${h}`}r.push({type:"text",text:u}),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??to.resolve("./data/inbox");try{eo.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=to.join(t,o);try{return eo.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 Pt,cr=f(()=>{"use strict";Pt=class{static{d(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3){this.reminderRepo=e,this.sendMessage=t,this.logger=s,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{await this.sendMessage(t.platform,t.chatId,`\u23F0 Reminder: ${t.message}`),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 Ft,lr=f(()=>{"use strict";Ft=class{static{d(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 jt,dr=f(()=>{"use strict";jt=class{static{d(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}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 Bt,ur=f(()=>{"use strict";Bt=class{static{d(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 c=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:c}});return o.sort((a,c)=>c.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var Wt,pr=f(()=>{"use strict";Wt=class{static{d(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),c=this.chunkText(n,500,50);for(let u=0;u<c.length;u++){let h;try{await this.embeddingService.embedAndStore(e,c[u],"document",`${a.id}:${u}`),h=`${a.id}:${u}`}catch(p){this.logger.warn({documentId:a.id,chunkIndex:u,err:p},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,u,c[u],h)}return this.docRepo.updateChunkCount(a.id,c.length),this.logger.info({documentId:a.id,filename:s,chunkCount:c.length},"Document ingested"),{documentId:a.id,chunkCount:c.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let u=Math.max(c-200,a),h=e.slice(u,c+200),p=h.lastIndexOf(`
505
505
 
506
- `);if(p>0)c=u+p;else{let w=m.lastIndexOf(". ");w>0&&(c=u+w+1)}let h=e.slice(a,c).trim();h&&i.push(h),a=c-o}return i.filter(c=>c.length>0)}}});var Xt,ur=f(()=>{"use strict";Xt=class{static{d(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(c){this.logger.warn({taskId:e.id,err:c},"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((c,u)=>setTimeout(()=>u(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 c=o.success?`\u2705 Background task completed: ${e.description}
506
+ `);if(p>0)c=u+p;else{let w=h.lastIndexOf(". ");w>0&&(c=u+w+1)}let m=e.slice(a,c).trim();m&&i.push(m),a=c-o}return i.filter(c=>c.length>0)}}});var Xt,mr=f(()=>{"use strict";Xt=class{static{d(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(c){this.logger.warn({taskId:e.id,err:c},"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((c,u)=>setTimeout(()=>u(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 c=o.success?`\u2705 Background task completed: ${e.description}
507
507
 
508
508
  Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${e.description}
509
509
 
510
510
  Error: ${o.error}`;await a.sendMessage(e.chatId,c)}}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}
511
511
 
512
- Error: ${s}`)}}}});var zt,pr=f(()=>{"use strict";zt=class{static{d(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.logger=o}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)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"},c=await this.skillSandbox.execute(o,i,a);s=c.success?`\u{1F514} Scheduled: ${e.name}
512
+ Error: ${s}`)}}}});var zt,hr=f(()=>{"use strict";zt=class{static{d(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;logger;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.logger=o}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)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"},c=await this.skillSandbox.execute(o,i,a);s=c.success?`\u{1F514} Scheduled: ${e.name}
513
513
 
514
- ${c.display??JSON.stringify(c.data)}`:`\u274C Scheduled action "${e.name}" failed: ${c.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 mr(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Ki)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Vi)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 Ki,Vi,hr=f(()=>{"use strict";Ki=[/^(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],Vi=[{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]}];d(mr,"scanSignal")});var Gi,Yi,Ht,fr=f(()=>{"use strict";Gi=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Yi=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
514
+ ${c.display??JSON.stringify(c.data)}`:`\u274C Scheduled action "${e.name}" failed: ${c.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 fr(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Yi)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Ji)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 Yi,Ji,gr=f(()=>{"use strict";Yi=[/^(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],Ji=[{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]}];d(fr,"scanSignal")});var Zi,Qi,Ht,yr=f(()=>{"use strict";Zi=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Qi=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
515
515
 
516
516
  Rules:
517
517
  - Only extract information the user STATES about themselves
@@ -531,31 +531,32 @@ Extract memories from this conversation:
531
531
  User: {USER_MESSAGE}
532
532
  Assistant: {ASSISTANT_RESPONSE}
533
533
 
534
- Return ONLY a valid JSON array, no explanation:`,Ht=class{static{d(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=Yi.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 c=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",c.id).catch(u=>this.logger.debug({err:u},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(c){this.logger.warn({err:c,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 Gi.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var qt,gr=f(()=>{"use strict";hr();fr();qt=class{static{d(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 Ht(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=mr(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 Ji,Zi,Qi,ea,Kt,yr=f(()=>{"use strict";Ji=Math.LN2,Zi=.3,Qi=.7,ea=3,Kt=class{static{d(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15){try{let r=this.memoryRepo.keywordSearch(e,t,30),n=[],o=!1;if(this.embeddingService)try{n=await this.embeddingService.semanticSearch(e,t,30),o=n.length>0}catch(p){this.logger.debug({err:p},"Semantic search failed, falling back to keyword-only")}let i=new Map,a=r.length;for(let p=0;p<r.length;p++){let h=r[p],w=a>0?1-p/a:0,E=o?Zi:1,T=this.applyBoosts(w*E,h);i.set(h.key,{memory:{key:h.key,value:h.value,category:h.category,type:h.type,score:T},score:T}),this.memoryRepo.recordAccess(h.id)}if(o)for(let p of n){let h=p.score*Qi,w=i.get(p.key);if(w)w.score+=h,w.memory.score=w.score;else{let E=this.memoryRepo.recall(e,p.key),T=this.applyBoosts(h,E||void 0);i.set(p.key,{memory:{key:p.key,value:p.value,category:p.category,type:E?.type||"general",score:T},score:T}),E&&this.memoryRepo.recordAccess(E.id)}}let c=Array.from(i.values()).sort((p,h)=>h.score-p.score),u=new Map,m=[];for(let{memory:p}of c){let h=u.get(p.type)||0;if(!(h>=ea)&&(u.set(p.type,h+1),m.push(p),m.length>=s))break}return this.logger.debug({keywordCount:r.length,semanticCount:n.length,resultCount:m.length,hasSemanticSearch:o},"Hybrid memory retrieval complete"),m}catch(r){return this.logger.error({err:r},"Memory retrieval failed"),this.memoryRepo.getRecentForPrompt(e,s).map(n=>({key:n.key,value:n.value,category:n.category,type:n.type,score:0}))}}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(-Ji*n/2592e6);s*=o}return s}}});import{EventEmitter as ta}from"node:events";var X,ue=f(()=>{"use strict";X=class extends ta{static{d(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}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(`
534
+ Return ONLY a valid JSON array, no explanation:`,Ht=class{static{d(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=Qi.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 c=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",c.id).catch(u=>this.logger.debug({err:u},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(c){this.logger.warn({err:c,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 Zi.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var qt,wr=f(()=>{"use strict";gr();yr();qt=class{static{d(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 Ht(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=fr(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 ea,ta,sa,ra,Kt,Er=f(()=>{"use strict";ea=Math.LN2,ta=.3,sa=.7,ra=3,Kt=class{static{d(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15){try{let r=this.memoryRepo.keywordSearch(e,t,30),n=[],o=!1;if(this.embeddingService)try{n=await this.embeddingService.semanticSearch(e,t,30),o=n.length>0}catch(p){this.logger.debug({err:p},"Semantic search failed, falling back to keyword-only")}let i=new Map,a=r.length;for(let p=0;p<r.length;p++){let m=r[p],w=a>0?1-p/a:0,E=o?ta:1,T=this.applyBoosts(w*E,m);i.set(m.key,{memory:{key:m.key,value:m.value,category:m.category,type:m.type,score:T},score:T}),this.memoryRepo.recordAccess(m.id)}if(o)for(let p of n){let m=p.score*sa,w=i.get(p.key);if(w)w.score+=m,w.memory.score=w.score;else{let E=this.memoryRepo.recall(e,p.key),T=this.applyBoosts(m,E||void 0);i.set(p.key,{memory:{key:p.key,value:p.value,category:p.category,type:E?.type||"general",score:T},score:T}),E&&this.memoryRepo.recordAccess(E.id)}}let c=Array.from(i.values()).sort((p,m)=>m.score-p.score),u=new Map,h=[];for(let{memory:p}of c){let m=u.get(p.type)||0;if(!(m>=ra)&&(u.set(p.type,m+1),h.push(p),h.length>=s))break}return this.logger.debug({keywordCount:r.length,semanticCount:n.length,resultCount:h.length,hasSemanticSearch:o},"Hybrid memory retrieval complete"),h}catch(r){return this.logger.error({err:r},"Memory retrieval failed"),this.memoryRepo.getRecentForPrompt(e,s).map(n=>({key:n.key,value:n.value,category:n.category,type:n.type,score:0}))}}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(-ea*n/2592e6);s*=o}return s}}});import{EventEmitter as na}from"node:events";var X,ue=f(()=>{"use strict";X=class extends na{static{d(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}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(`
535
535
 
536
- `);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as sa,InputFile as to}from"grammy";function so(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var ps,ro=f(()=>{"use strict";ue();d(so,"mapParseMode");ps=class extends X{static{d(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new sa(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:d(()=>{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:so(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:so(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 to(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 to(t,s),{caption:r});return String(n.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let c=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:c.length,data:c}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as ra,GatewayIntentBits as ms,Events as wr}from"discord.js";var hs,no=f(()=>{"use strict";ue();hs=class extends X{static{d(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new ra({intents:[ms.Guilds,ms.GuildMessages,ms.MessageContent,ms.DirectMessages]}),this.client.on(wr.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(wr.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(wr.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 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 fs,oo=f(()=>{"use strict";ue();fs=class extends X{static{d(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";try{let a=s.slice(6),c=`${this.homeserverUrl}/_matrix/media/v3/download/${a}`,u=await fetch(c,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!u.ok)return;let m=await u.arrayBuffer(),p=Buffer.from(m);return{type:t,mimeType:n,fileName:i,size:o??p.length,data:p}}catch(a){console.error("[matrix] Failed to download attachment",s,a);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 gs,io=f(()=>{"use strict";ue();gs=class extends X{static{d(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",c=>{if(c.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),c.connection==="close"){let m=c.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),m){let p=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),p)}}}),this.socket.ev.on("messages.upsert",({messages:c,type:u})=>{if(u==="notify")for(let m of c)m.message&&(m.key.fromMe||this.processMessage(m).catch(p=>{this.emit("error",p instanceof Error?p:new Error(String(p)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),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 ys,ao=f(()=>{"use strict";ue();ys=class extends X{static{d(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let u=await c.json();n=String(u.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 u of r.attachments){let m=await this.downloadAttachment(u);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Er from"node:readline";var ws,co=f(()=>{"use strict";ue();ws=class extends X{static{d(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Er.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
536
+ `);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as oa,InputFile as ro}from"grammy";function no(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var ps,oo=f(()=>{"use strict";ue();d(no,"mapParseMode");ps=class extends X{static{d(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new oa(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:d(()=>{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:no(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:no(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 ro(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 ro(t,s),{caption:r});return String(n.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let c=Buffer.from(await a.arrayBuffer());return{type:t,mimeType:s,fileName:r??o.split("/").pop(),size:c.length,data:c}}catch(n){console.error("[telegram] Failed to download file",e,n);return}}}});import{Client as ia,GatewayIntentBits as ms,Events as Tr}from"discord.js";var hs,io=f(()=>{"use strict";ue();hs=class extends X{static{d(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new ia({intents:[ms.Guilds,ms.GuildMessages,ms.MessageContent,ms.DirectMessages]}),this.client.on(Tr.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(Tr.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Tr.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 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 fs,ao=f(()=>{"use strict";ue();fs=class extends X{static{d(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";try{let a=s.slice(6),c=`${this.homeserverUrl}/_matrix/media/v3/download/${a}`,u=await fetch(c,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!u.ok)return;let h=await u.arrayBuffer(),p=Buffer.from(h);return{type:t,mimeType:n,fileName:i,size:o??p.length,data:p}}catch(a){console.error("[matrix] Failed to download attachment",s,a);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 gs,co=f(()=>{"use strict";ue();gs=class extends X{static{d(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",c=>{if(c.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),c.connection==="close"){let h=c.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),h){let p=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),p)}}}),this.socket.ev.on("messages.upsert",({messages:c,type:u})=>{if(u==="notify")for(let h of c)h.message&&(h.key.fromMe||this.processMessage(h).catch(p=>{this.emit("error",p instanceof Error?p:new Error(String(p)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),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 ys,lo=f(()=>{"use strict";ue();ys=class extends X{static{d(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let u=await c.json();n=String(u.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 u of r.attachments){let h=await this.downloadAttachment(u);h&&i.push(h)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import br from"node:readline";var ws,uo=f(()=>{"use strict";ue();ws=class extends X{static{d(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=br.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
537
537
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
538
538
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
539
539
  Goodbye!
540
540
  `),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(`
541
541
  Alfred: ${t}
542
- `),this.prompt(),r}async editMessage(e,t,s,r){Er.clearLine(process.stdout,0),Er.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});var xe={};J(xe,{CLIAdapter:()=>ws,DiscordAdapter:()=>hs,MatrixAdapter:()=>fs,MessagingAdapter:()=>X,SignalAdapter:()=>ys,TelegramAdapter:()=>ps,WhatsAppAdapter:()=>gs});var Ie=f(()=>{"use strict";ue();ro();no();oo();io();ao();co()});import Es from"node:fs";import Ts from"node:path";import na from"js-yaml";var $e,lo=f(()=>{"use strict";Ds();Us();qs();is();Ot();nr();or();ir();ar();cr();lr();dr();ur();pr();gr();yr();$e=class{static{d(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new jt;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=dt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ye(this.config.storage.path);let e=this.database.getDb(),t=new ut(e),s=new pt(e),r=new we(e),n=new mt(e),o=new ht(e),i=new ft(e),a=new gt(e),c=new yt(e),u=new wt(e),m=new Et(e);this.logger.info("Storage initialized");let p=new $t,h=this.loadSecurityRules();p.loadRules(h);let w=new At(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:h.length},"Security engine initialized");let E=Hs(this.config.llm);await E.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let T=new Bt(E,a,this.logger.child({component:"embeddings"})),v=this.config.activeLearning?.enabled!==!1,$,x;v&&($=new qt({llm:E,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}),x=new Kt(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let M=new Ce(this.logger.child({component:"sandbox"})),k=new Oe;k.register(new Ue),k.register(new Pe),k.register(new Fe(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),k.register(new je(o)),k.register(new Be(i)),k.register(new We),k.register(new Xe),k.register(new ze(n,T)),k.register(new He(E,k,M,w)),k.register(new qe(this.config.email?{imap:this.config.email.imap,smtp:this.config.email.smtp,auth:this.config.email.auth}:void 0)),k.register(new Ke),k.register(new Ve),k.register(new Ye),k.register(new Je),k.register(new Ze),k.register(new Qe(s)),k.register(new et(s,c,this.adapters)),k.register(new tt(u)),k.register(new st(m));let S=new Tt(e),U=new Wt(S,T,this.logger.child({component:"documents"}));k.register(new nt(S,U,T));let z;if(this.config.calendar)try{let A=await Mt(this.config.calendar);z=new _e(A),k.register(z),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(A){this.logger.warn({err:A},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=z,this.config.mcp?.servers?.length){let{MCPManager:A}=await Promise.resolve().then(()=>(Ot(),us));this.mcpManager=new A(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let ee of this.mcpManager.getSkills())k.register(ee);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:A}=await Promise.resolve().then(()=>(Ot(),us));k.register(new A({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}this.logger.info({skills:k.getAll().map(A=>A.metadata.name)},"Skills registered");let G;this.config.speech?.apiKey&&(G=new Ft(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized"));let Y=new Ct(t),he=Ts.resolve(Ts.dirname(this.config.storage.path),"inbox");this.pipeline=new Ut({llm:E,conversationManager:Y,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:k,skillSandbox:M,securityManager:w,memoryRepo:n,speechTranscriber:G,inboxPath:he,embeddingService:T,activeLearning:$,memoryRetriever:x}),this.reminderScheduler=new Pt(o,async(A,ee,N)=>{let H=this.adapters.get(A);H?await H.sendMessage(ee,N):this.logger.warn({platform:A,chatId:ee},"No adapter for reminder platform")},this.logger.child({component:"reminders"})),this.backgroundTaskRunner=new Xt(k,M,u,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new zt(m,k,M,E,this.adapters,this.logger.child({component:"proactive-scheduler"})),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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal 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(()=>(Ie(),xe)),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")}setupAdapterHandlers(e,t){t.on("message",async s=>{try{let r,n="",o=d(async u=>{if(u!==n){n=u;try{r?await t.editMessage(s.chatId,r,u):r=await t.sendMessage(s.chatId,u)}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),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;if(r)try{await t.editMessage(s.chatId,r,a.text,c)}catch(u){this.logger.debug({err:u,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c);if(i.attachments)for(let u of i.attachments)try{u.mimeType.startsWith("image/")?await t.sendPhoto(s.chatId,u.data,u.fileName):await t.sendFile(s.chatId,u.data,u.fileName)}catch(m){this.logger.warn({err:m,fileName:u.fileName,chatId:s.chatId},"Failed to send attachment")}}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.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=Ts.resolve(this.config.security.rulesPath),t=[];if(!Es.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Es.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Es.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Ts.join(e,n),i=Es.readFileSync(o,"utf-8"),a=na.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 uo=f(()=>{"use strict"});var Tr=f(()=>{"use strict";lo();or();nr();ir();ar();cr();lr();ur();pr();dr();gr();yr();fr();uo();hr()});var po={};J(po,{startCommand:()=>oa});async function oa(){let l=new q,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=dt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new $e(e),r=!1,n=d(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 mo=f(()=>{"use strict";ge();Ds();Tr();d(oa,"startCommand")});var ho={};J(ho,{chatCommand:()=>ia});async function ia(l){let e=new q,t;try{t=e.loadConfig()}catch(r){console.error("Failed to load configuration:",r.message),process.exit(1)}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let r=t.llm[l.tier];r?t.llm.default=r:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let s=new $e(t);try{await s.initialize(),await s.startWithCLI()}catch(r){console.error("Failed to start chat:",r.message),process.exit(1)}}var fo=f(()=>{"use strict";ge();Tr();d(ia,"chatCommand")});var yo={};J(yo,{setupCommand:()=>ha});import{createInterface as aa}from"node:readline/promises";import{stdin as ca,stdout as la}from"node:process";import K from"node:fs";import ie from"node:path";import _r from"js-yaml";function P(l){return`${bs}${l}${L}`}function pa(l){return`${re}${l}${L}`}function Ae(l){return`${_s}${l}${L}`}function go(l){return`${da}${l}${L}`}function I(l){return`${it}${l}${L}`}function _(l){return`${me}${l}${L}`}function Re(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function ma(l){let e={},t={},s=!1,r=!1,n=30,o=ie.join(l,"config","default.yml");if(K.existsSync(o))try{let c=_r.load(K.readFileSync(o,"utf-8"));c&&typeof c=="object"&&Object.assign(e,c)}catch{}let i=ie.join(l,".env");if(K.existsSync(i))try{let c=K.readFileSync(i,"utf-8").split(`
543
- `);for(let u of c){let m=u.trim();if(!m||m.startsWith("#"))continue;let p=m.indexOf("=");p>0&&(t[m.slice(0,p)]=m.slice(p+1))}}catch{}let a=ie.join(l,"config","rules","default-rules.yml");if(K.existsSync(a))try{let c=_r.load(K.readFileSync(a,"utf-8"));if(c?.rules){s=c.rules.some(p=>p.id==="allow-owner-admin"&&p.effect==="allow"),c.rules.find(p=>p.id==="allow-write-for-dm"||p.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let m=c.rules.find(p=>p.id==="rate-limit-write");m?.rateLimit?.maxInvocations&&(n=m.rateLimit.maxInvocations)}}catch{}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n}}async function ha(){let l=aa({input:ca,output:la}),e=process.cwd(),t=ma(e),s=Object.keys(t.config).length>0;try{fa(),console.log(s?`${_s}Existing configuration found \u2014 press Enter to keep current values.${L}
542
+ `),this.prompt(),r}async editMessage(e,t,s,r){br.clearLine(process.stdout,0),br.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});var xe={};J(xe,{CLIAdapter:()=>ws,DiscordAdapter:()=>hs,MatrixAdapter:()=>fs,MessagingAdapter:()=>X,SignalAdapter:()=>ys,TelegramAdapter:()=>ps,WhatsAppAdapter:()=>gs});var Ie=f(()=>{"use strict";ue();oo();io();ao();co();lo();uo()});import Es from"node:fs";import Ts from"node:path";import aa from"js-yaml";var $e,po=f(()=>{"use strict";Cs();Fs();Vs();is();Ot();ir();ar();cr();lr();dr();ur();pr();mr();hr();wr();Er();$e=class{static{d(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new jt;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=dt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ye(this.config.storage.path);let e=this.database.getDb(),t=new ut(e),s=new pt(e),r=new we(e),n=new mt(e),o=new ht(e),i=new ft(e),a=new gt(e),c=new yt(e),u=new wt(e),h=new Et(e);this.logger.info("Storage initialized");let p=new $t,m=this.loadSecurityRules();p.loadRules(m);let w=new At(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:m.length},"Security engine initialized");let E=Ks(this.config.llm);await E.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let T=new Bt(E,a,this.logger.child({component:"embeddings"})),v=this.config.activeLearning?.enabled!==!1,$,x;v&&($=new qt({llm:E,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}),x=new Kt(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let M=new Ce(this.logger.child({component:"sandbox"})),k=new Oe;k.register(new Ue),k.register(new Pe),k.register(new Fe(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),k.register(new je(o)),k.register(new Be(i)),k.register(new We),k.register(new Xe),k.register(new ze(n,T)),k.register(new He(E,k,M,w)),k.register(new qe(this.config.email?{imap:this.config.email.imap,smtp:this.config.email.smtp,auth:this.config.email.auth}:void 0)),k.register(new Ke),k.register(new Ve),k.register(new Ye),k.register(new Je),k.register(new Ze),k.register(new Qe(s)),k.register(new et(s,c,this.adapters)),k.register(new tt(u)),k.register(new st(h));let S=new Tt(e),P=new Wt(S,T,this.logger.child({component:"documents"}));k.register(new nt(S,P,T));let z;if(this.config.calendar)try{let A=await Mt(this.config.calendar);z=new _e(A),k.register(z),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(A){this.logger.warn({err:A},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=z,this.config.mcp?.servers?.length){let{MCPManager:A}=await Promise.resolve().then(()=>(Ot(),us));this.mcpManager=new A(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let te of this.mcpManager.getSkills())k.register(te);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:A}=await Promise.resolve().then(()=>(Ot(),us));k.register(new A({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}this.logger.info({skills:k.getAll().map(A=>A.metadata.name)},"Skills registered");let G;this.config.speech?.apiKey&&(G=new Ft(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized"));let Y=new Ct(t),he=Ts.resolve(Ts.dirname(this.config.storage.path),"inbox");this.pipeline=new Ut({llm:E,conversationManager:Y,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:k,skillSandbox:M,securityManager:w,memoryRepo:n,speechTranscriber:G,inboxPath:he,embeddingService:T,activeLearning:$,memoryRetriever:x}),this.reminderScheduler=new Pt(o,async(A,te,N)=>{let H=this.adapters.get(A);H?await H.sendMessage(te,N):this.logger.warn({platform:A,chatId:te},"No adapter for reminder platform")},this.logger.child({component:"reminders"})),this.backgroundTaskRunner=new Xt(k,M,u,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new zt(h,k,M,E,this.adapters,this.logger.child({component:"proactive-scheduler"})),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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));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(()=>(Ie(),xe));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal 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(()=>(Ie(),xe)),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")}setupAdapterHandlers(e,t){t.on("message",async s=>{try{let r,n="",o=d(async u=>{if(u!==n){n=u;try{r?await t.editMessage(s.chatId,r,u):r=await t.sendMessage(s.chatId,u)}catch(h){this.logger.debug({err:h,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;if(r)try{await t.editMessage(s.chatId,r,a.text,c)}catch(u){this.logger.debug({err:u,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c);if(i.attachments)for(let u of i.attachments)try{u.mimeType.startsWith("image/")?await t.sendPhoto(s.chatId,u.data,u.fileName):await t.sendFile(s.chatId,u.data,u.fileName)}catch(h){this.logger.warn({err:h,fileName:u.fileName,chatId:s.chatId},"Failed to send attachment")}}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.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=Ts.resolve(this.config.security.rulesPath),t=[];if(!Es.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Es.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Es.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Ts.join(e,n),i=Es.readFileSync(o,"utf-8"),a=aa.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 mo=f(()=>{"use strict"});var _r=f(()=>{"use strict";po();ar();ir();cr();lr();dr();ur();mr();hr();pr();wr();Er();yr();mo();gr()});var ho={};J(ho,{startCommand:()=>ca});async function ca(){let l=new q,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=dt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new $e(e),r=!1,n=d(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 fo=f(()=>{"use strict";ge();Cs();_r();d(ca,"startCommand")});var go={};J(go,{chatCommand:()=>la});async function la(l){let e=new q,t;try{t=e.loadConfig()}catch(r){console.error("Failed to load configuration:",r.message),process.exit(1)}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let r=t.llm[l.tier];r?t.llm.default=r:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let s=new $e(t);try{await s.initialize(),await s.startWithCLI()}catch(r){console.error("Failed to start chat:",r.message),process.exit(1)}}var yo=f(()=>{"use strict";ge();_r();d(la,"chatCommand")});var Eo={};J(Eo,{setupCommand:()=>ya});import{createInterface as da}from"node:readline/promises";import{stdin as ua,stdout as pa}from"node:process";import K from"node:fs";import ie from"node:path";import kr from"js-yaml";function U(l){return`${bs}${l}${L}`}function fa(l){return`${ee}${l}${L}`}function Ae(l){return`${_s}${l}${L}`}function wo(l){return`${ma}${l}${L}`}function I(l){return`${it}${l}${L}`}function b(l){return`${me}${l}${L}`}function Re(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function ga(l){let e={},t={},s=!1,r=!1,n=30,o=ie.join(l,"config","default.yml");if(K.existsSync(o))try{let u=kr.load(K.readFileSync(o,"utf-8"));u&&typeof u=="object"&&Object.assign(e,u)}catch{}let i=ie.join(l,".env");if(K.existsSync(i))try{let u=K.readFileSync(i,"utf-8").split(`
543
+ `);for(let h of u){let p=h.trim();if(!p||p.startsWith("#"))continue;let m=p.indexOf("=");m>0&&(t[p.slice(0,m)]=p.slice(m+1))}}catch{}let a=ie.join(l,"config","rules","default-rules.yml");if(K.existsSync(a))try{let u=kr.load(K.readFileSync(a,"utf-8"));if(u?.rules){s=u.rules.some(m=>m.id==="allow-owner-admin"&&m.effect==="allow"),u.rules.find(m=>m.id==="allow-write-for-dm"||m.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let p=u.rules.find(m=>m.id==="rate-limit-write");p?.rateLimit?.maxInvocations&&(n=p.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled;return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c}}async function ya(){let l=da({input:ua,output:pa}),e=process.cwd(),t=ga(e),s=Object.keys(t.config).length>0;try{wa(),console.log(s?`${_s}Existing configuration found \u2014 press Enter to keep current values.${L}
544
544
  ${me}Only change what you need to update.${L}
545
545
  `:`${_s}Welcome to the Alfred setup wizard!${L}
546
546
  ${me}This will walk you through configuring your AI assistant.${L}
547
547
  ${me}Press Enter to accept defaults shown in [brackets].${L}
548
548
  `);let r=await F(l,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Vt.findIndex(y=>y.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
549
- ${I("Which LLM provider would you like to use?")}`);for(let y=0;y<Vt.length;y++){let R=y===n?` ${_("(current)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${Vt[y].label}${R}`)}let i=await br(l,"> ",1,Vt.length,o),a=Vt[i-1];console.log(` ${P(">")} Selected: ${I(a.label)}`);let c="",u=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),u?c=await F(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,u):c=await pe(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${P(">")} API key set: ${_(Re(c))}`));let m=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter"].includes(a.name)){let R=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(R){let j={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"};console.log(""),m=await F(l,j[a.name]??"API Base URL",R.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${P(">")} URL: ${_(m)}`)}}let h=t.config.llm?.model??a.defaultModel;console.log("");let w=await F(l,"Which model?",h),E=["brave","tavily","duckduckgo","searxng"],T=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",v=E.indexOf(T),$=v>=0?v+1:0;console.log(`
550
- ${I("Web Search provider (for searching the internet):")}`);let x=["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"],M=d(y=>v===y?` ${_("(current)")}`:"","mark");console.log(` ${Ae("0)")} None (disable web search)${v===-1&&T===""?` ${_("(current)")}`:""}`);for(let y=0;y<x.length;y++)console.log(` ${Ae(String(y+1)+")")} ${x[y]}${M(y)}`);let k=await br(l,"> ",0,E.length,$),S,U="",z="";if(k>=1&&k<=E.length&&(S=E[k-1]),S==="brave"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?U=await F(l," Brave Search API key",y):(console.log(` ${_("Get your free API key at: https://brave.com/search/api/")}`),U=await pe(l," Brave Search API key")),console.log(` ${P(">")} Brave Search: ${_(Re(U))}`)}else if(S==="tavily"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?U=await F(l," Tavily API key",y):(console.log(` ${_("Get your free API key at: https://tavily.com/")}`),U=await pe(l," Tavily API key")),console.log(` ${P(">")} Tavily: ${_(Re(U))}`)}else if(S==="duckduckgo")console.log(` ${P(">")} DuckDuckGo: ${_("no API key needed")}`);else if(S==="searxng"){let y=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";z=await F(l," SearXNG URL",y),z=z.replace(/\/+$/,""),console.log(` ${P(">")} SearXNG: ${_(z)}`)}else console.log(` ${_("Web search disabled \u2014 you can configure it later.")}`);let G=[];for(let y=0;y<ot.length;y++){let R=ot[y];t.config[R.configKey]?.enabled&&G.push(y+1)}let Y=G.length>0?G.join(","):"";console.log(`
551
- ${I("Which messaging platforms do you want to enable?")}`),console.log(`${_("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let y=0;y<ot.length;y++){let R=G.includes(y+1)?` ${_("(enabled)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${ot[y].label}${R}`)}console.log(` ${Ae("0)")} None (configure later)`);let he=(await l.question(`${re}> ${L}${Y?_(`[${Y}] `):""}`)).trim(),A=[],ee=he||Y;if(ee&&ee!=="0"){let y=ee.split(",").map(R=>parseInt(R.trim(),10));for(let R of y)if(R>=1&&R<=ot.length){let j=ot[R-1];A.includes(j)||A.push(j)}}A.length>0?console.log(` ${P(">")} Enabling: ${A.map(y=>I(y.label)).join(", ")}`):console.log(` ${_("No platforms selected \u2014 you can configure them later.")}`);let N={},H={};for(let y of A){if(y.credentials.length===0){y.name==="whatsapp"&&console.log(`
552
- ${pa("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
553
- ${I(y.label+" configuration:")}`);let R={};for(let j of y.credentials){let Me=t.env[j.envKey]??"",se;Me?se=await F(l,` ${j.prompt}`,Me):j.defaultValue?se=await F(l,` ${j.prompt}`,j.defaultValue):j.required?se=await pe(l,` ${j.prompt}`):(se=(await l.question(` ${j.prompt}: ${re}`)).trim(),process.stdout.write(L)),R[j.configField]=se,H[j.envKey]=se,j.configField==="token"||j.configField==="accessToken"?console.log(` ${P(">")} Set: ${_(Re(se))}`):console.log(` ${P(">")} Set: ${_(se)}`)}N[y.configKey]=R}let B=t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",W=!!B,Le=W?"Y/n":"y/N";console.log(`
554
- ${I("Email access (read & send emails via IMAP/SMTP)?")}`),console.log(`${_("Works with Gmail, Outlook, or any IMAP/SMTP provider.")}`);let te=(await l.question(`${re}> ${L}${_(`[${Le}] `)}`)).trim().toLowerCase(),Yt=te===""?W:te==="y"||te==="yes",ae="",Jt="",Zt="",ks=993,vr="",vs=587;if(Yt){console.log(""),ae=await F(l," Email address",B||""),ae||(ae=await pe(l," Email address"));let y=t.env.ALFRED_EMAIL_PASS??"";y?Jt=await F(l," Password / App password",y):(console.log(` ${_("For Gmail: use an App Password (not your regular password)")}`),console.log(` ${_(" \u2192 Google Account \u2192 Security \u2192 2-Step \u2192 App passwords")}`),Jt=await pe(l," Password / App password"));let R=ae.split("@")[1]?.toLowerCase()??"",Me={"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"}}[R],se=t.config.email?.imap?.host??Me?.imap??`imap.${R}`,Bo=t.config.email?.smtp?.host??Me?.smtp??`smtp.${R}`,Wo=t.config.email?.imap?.port??993,Xo=t.config.email?.smtp?.port??587;Me&&console.log(` ${P(">")} Detected ${R} \u2014 using preset server settings`),Zt=await F(l," IMAP server",se);let zo=await F(l," IMAP port",String(Wo));ks=parseInt(zo,10)||993,vr=await F(l," SMTP server",Bo);let Ho=await F(l," SMTP port",String(Xo));vs=parseInt(Ho,10)||587,console.log(` ${P(">")} Email: ${_(ae)} via ${_(Zt)}`)}else console.log(` ${_("Email disabled \u2014 you can configure it later.")}`);let Qt=["openai","groq"],Ro=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",es=Qt.indexOf(Ro),Lo=es>=0?es+1:0;console.log(`
555
- ${I("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${_("Transcribes voice messages from Telegram, Discord, etc.")}`);let xr=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Ae("0)")} None (disable voice transcription)${es===-1?` ${_("(current)")}`:""}`);for(let y=0;y<xr.length;y++){let R=es===y?` ${_("(current)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${xr[y]}${R}`)}let xs=await br(l,"> ",0,Qt.length,Lo),ne,ce="",at="";if(xs>=1&&xs<=Qt.length&&(ne=Qt[xs-1]),ne==="openai"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?ce=await F(l," OpenAI API key (for Whisper)",y):(console.log(` ${_("Uses your OpenAI API key for Whisper transcription.")}`),ce=await pe(l," OpenAI API key")),console.log(` ${P(">")} OpenAI Whisper: ${_(Re(ce))}`)}else if(ne==="groq"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?ce=await F(l," Groq API key",y):(console.log(` ${_("Get your free API key at: https://console.groq.com/")}`),ce=await pe(l," Groq API key"));let R=t.env.ALFRED_SPEECH_BASE_URL??"";R&&(at=await F(l," Groq API URL",R)),console.log(` ${P(">")} Groq Whisper: ${_(Re(ce))}`)}else console.log(` ${_("Voice transcription disabled \u2014 you can configure it later.")}`);console.log(`
556
- ${I("Security configuration:")}`);let Ir=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",V;if(Ir)V=await F(l,"Owner user ID (for elevated permissions)",Ir);else{let y=(await l.question(`${it}Owner user ID${L} ${_("(optional, for elevated permissions)")}: ${re}`)).trim();process.stdout.write(L),V=y}let ct=!1;if(V){let y=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${I("Enable shell access (admin commands) for the owner?")}`),console.log(` ${_("Allows Alfred to execute shell commands. Only for the owner.")}`);let R=(await l.question(` ${re}> ${L}${_(`[${y}] `)}`)).trim().toLowerCase();R===""?ct=t.shellEnabled:ct=R==="y"||R==="yes",console.log(ct?` ${P(">")} Shell access ${I("enabled")} for owner ${_(V)}`:` ${_("Shell access disabled.")}`)}let Mo=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${I("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${_("By default, write actions are only allowed in DMs.")}`);let Is=(await l.question(` ${re}> ${L}${_(`[${Mo}] `)}`)).trim().toLowerCase(),lt;Is===""?lt=t.writeInGroups:lt=Is==="y"||Is==="yes",console.log(lt?` ${P(">")} Write actions ${I("enabled")} in groups`:` ${_("Write actions only in DMs (default).")}`);let No=t.rateLimit??30;console.log("");let Do=await F(l," Rate limit (max write actions per hour per user)",String(No)),ts=Math.max(1,parseInt(Do,10)||30);console.log(` ${P(">")} Rate limit: ${I(String(ts))} per hour`),console.log(`
557
- ${I("Writing configuration files...")}`);let D=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let y=a.envKeyName||"ALFRED_OLLAMA_API_KEY";D.push(`${y}=${c}`)}w!==a.defaultModel&&D.push(`ALFRED_LLM_MODEL=${w}`),m&&D.push(`ALFRED_LLM_BASE_URL=${m}`),D.push("","# === Messaging Platforms ===","");for(let[y,R]of Object.entries(H))D.push(`${y}=${R}`);D.push("","# === Web Search ===",""),S?(D.push(`ALFRED_SEARCH_PROVIDER=${S}`),U&&D.push(`ALFRED_SEARCH_API_KEY=${U}`),z&&D.push(`ALFRED_SEARCH_BASE_URL=${z}`)):(D.push("# ALFRED_SEARCH_PROVIDER=brave"),D.push("# ALFRED_SEARCH_API_KEY=")),D.push("","# === Email ===",""),Yt?(D.push(`ALFRED_EMAIL_USER=${ae}`),D.push(`ALFRED_EMAIL_PASS=${Jt}`)):(D.push("# ALFRED_EMAIL_USER="),D.push("# ALFRED_EMAIL_PASS=")),D.push("","# === Speech-to-Text ===",""),ne?(D.push(`ALFRED_SPEECH_PROVIDER=${ne}`),D.push(`ALFRED_SPEECH_API_KEY=${ce}`),at&&D.push(`ALFRED_SPEECH_BASE_URL=${at}`)):(D.push("# ALFRED_SPEECH_PROVIDER=groq"),D.push("# ALFRED_SPEECH_API_KEY=")),D.push("","# === Security ===",""),V?D.push(`ALFRED_OWNER_USER_ID=${V}`):D.push("# ALFRED_OWNER_USER_ID="),D.push("");let Oo=ie.join(e,".env");K.writeFileSync(Oo,D.join(`
558
- `),"utf-8"),console.log(` ${P("+")} ${_(".env")} written`);let ss=ie.join(e,"config");K.existsSync(ss)||K.mkdirSync(ss,{recursive:!0});let $r={name:r,telegram:{token:N.telegram?.token??"",enabled:A.some(y=>y.name==="telegram")},discord:{token:N.discord?.token??"",enabled:A.some(y=>y.name==="discord")},whatsapp:{enabled:A.some(y=>y.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:N.matrix?.homeserverUrl??"https://matrix.org",accessToken:N.matrix?.accessToken??"",userId:N.matrix?.userId??"",enabled:A.some(y=>y.name==="matrix")},signal:{apiUrl:N.signal?.apiUrl??"http://localhost:8080",phoneNumber:N.signal?.phoneNumber??"",enabled:A.some(y=>y.name==="signal")},llm:{provider:a.name,model:w,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...S?{search:{provider:S,...U?{apiKey:U}:{},...z?{baseUrl:z}:{}}}:{},...Yt?{email:{imap:{host:Zt,port:ks,secure:ks===993},smtp:{host:vr,port:vs,secure:vs===465},auth:{user:ae,pass:Jt}}}:{},...ne?{speech:{provider:ne,apiKey:ce,...at?{baseUrl:at}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};V&&($r.security.ownerUserId=V);let Co="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+_r.dump($r,{lineWidth:120,noRefs:!0,sortKeys:!1}),Uo=ie.join(ss,"default.yml");K.writeFileSync(Uo,Co,"utf-8"),console.log(` ${P("+")} ${_("config/default.yml")} written`);let $s=ie.join(ss,"rules");K.existsSync($s)||K.mkdirSync($s,{recursive:!0});let Po=ct&&V?`
549
+ ${I("Which LLM provider would you like to use?")}`);for(let y=0;y<Vt.length;y++){let R=y===n?` ${b("(current)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${Vt[y].label}${R}`)}let i=await Sr(l,"> ",1,Vt.length,o),a=Vt[i-1];console.log(` ${U(">")} Selected: ${I(a.label)}`);let c="",u=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),u?c=await F(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,u):c=await pe(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${U(">")} API key set: ${b(Re(c))}`));let h=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter"].includes(a.name)){let R=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(R){let j={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"};console.log(""),h=await F(l,j[a.name]??"API Base URL",R.replace(/\/+$/,"")),h=h.replace(/\/+$/,""),console.log(` ${U(">")} URL: ${b(h)}`)}}let m=t.config.llm?.model??a.defaultModel;console.log("");let w=await F(l,"Which model?",m),E=["brave","tavily","duckduckgo","searxng"],T=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",v=E.indexOf(T),$=v>=0?v+1:0;console.log(`
550
+ ${I("Web Search provider (for searching the internet):")}`);let x=["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"],M=d(y=>v===y?` ${b("(current)")}`:"","mark");console.log(` ${Ae("0)")} None (disable web search)${v===-1&&T===""?` ${b("(current)")}`:""}`);for(let y=0;y<x.length;y++)console.log(` ${Ae(String(y+1)+")")} ${x[y]}${M(y)}`);let k=await Sr(l,"> ",0,E.length,$),S,P="",z="";if(k>=1&&k<=E.length&&(S=E[k-1]),S==="brave"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?P=await F(l," Brave Search API key",y):(console.log(` ${b("Get your free API key at: https://brave.com/search/api/")}`),P=await pe(l," Brave Search API key")),console.log(` ${U(">")} Brave Search: ${b(Re(P))}`)}else if(S==="tavily"){let y=t.env.ALFRED_SEARCH_API_KEY??"";y?P=await F(l," Tavily API key",y):(console.log(` ${b("Get your free API key at: https://tavily.com/")}`),P=await pe(l," Tavily API key")),console.log(` ${U(">")} Tavily: ${b(Re(P))}`)}else if(S==="duckduckgo")console.log(` ${U(">")} DuckDuckGo: ${b("no API key needed")}`);else if(S==="searxng"){let y=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";z=await F(l," SearXNG URL",y),z=z.replace(/\/+$/,""),console.log(` ${U(">")} SearXNG: ${b(z)}`)}else console.log(` ${b("Web search disabled \u2014 you can configure it later.")}`);let G=[];for(let y=0;y<ot.length;y++){let R=ot[y];t.config[R.configKey]?.enabled&&G.push(y+1)}let Y=G.length>0?G.join(","):"";console.log(`
551
+ ${I("Which messaging platforms do you want to enable?")}`),console.log(`${b("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let y=0;y<ot.length;y++){let R=G.includes(y+1)?` ${b("(enabled)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${ot[y].label}${R}`)}console.log(` ${Ae("0)")} None (configure later)`);let he=(await l.question(`${ee}> ${L}${Y?b(`[${Y}] `):""}`)).trim(),A=[],te=he||Y;if(te&&te!=="0"){let y=te.split(",").map(R=>parseInt(R.trim(),10));for(let R of y)if(R>=1&&R<=ot.length){let j=ot[R-1];A.includes(j)||A.push(j)}}A.length>0?console.log(` ${U(">")} Enabling: ${A.map(y=>I(y.label)).join(", ")}`):console.log(` ${b("No platforms selected \u2014 you can configure them later.")}`);let N={},H={};for(let y of A){if(y.credentials.length===0){y.name==="whatsapp"&&console.log(`
552
+ ${fa("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
553
+ ${I(y.label+" configuration:")}`);let R={};for(let j of y.credentials){let Me=t.env[j.envKey]??"",re;Me?re=await F(l,` ${j.prompt}`,Me):j.defaultValue?re=await F(l,` ${j.prompt}`,j.defaultValue):j.required?re=await pe(l,` ${j.prompt}`):(re=(await l.question(` ${j.prompt}: ${ee}`)).trim(),process.stdout.write(L)),R[j.configField]=re,H[j.envKey]=re,j.configField==="token"||j.configField==="accessToken"?console.log(` ${U(">")} Set: ${b(Re(re))}`):console.log(` ${U(">")} Set: ${b(re)}`)}N[y.configKey]=R}let B=t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",W=!!B,Le=W?"Y/n":"y/N";console.log(`
554
+ ${I("Email access (read & send emails via IMAP/SMTP)?")}`),console.log(`${b("Works with Gmail, Outlook, or any IMAP/SMTP provider.")}`);let se=(await l.question(`${ee}> ${L}${b(`[${Le}] `)}`)).trim().toLowerCase(),Yt=se===""?W:se==="y"||se==="yes",ae="",Jt="",Zt="",ks=993,Ir="",vs=587;if(Yt){console.log(""),ae=await F(l," Email address",B||""),ae||(ae=await pe(l," Email address"));let y=t.env.ALFRED_EMAIL_PASS??"";y?Jt=await F(l," Password / App password",y):(console.log(` ${b("For Gmail: use an App Password (not your regular password)")}`),console.log(` ${b(" \u2192 Google Account \u2192 Security \u2192 2-Step \u2192 App passwords")}`),Jt=await pe(l," Password / App password"));let R=ae.split("@")[1]?.toLowerCase()??"",Me={"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"}}[R],re=t.config.email?.imap?.host??Me?.imap??`imap.${R}`,zo=t.config.email?.smtp?.host??Me?.smtp??`smtp.${R}`,Ho=t.config.email?.imap?.port??993,qo=t.config.email?.smtp?.port??587;Me&&console.log(` ${U(">")} Detected ${R} \u2014 using preset server settings`),Zt=await F(l," IMAP server",re);let Ko=await F(l," IMAP port",String(Ho));ks=parseInt(Ko,10)||993,Ir=await F(l," SMTP server",zo);let Vo=await F(l," SMTP port",String(qo));vs=parseInt(Vo,10)||587,console.log(` ${U(">")} Email: ${b(ae)} via ${b(Zt)}`)}else console.log(` ${b("Email disabled \u2014 you can configure it later.")}`);let Qt=["openai","groq"],Mo=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",es=Qt.indexOf(Mo),No=es>=0?es+1:0;console.log(`
555
+ ${I("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${b("Transcribes voice messages from Telegram, Discord, etc.")}`);let $r=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Ae("0)")} None (disable voice transcription)${es===-1?` ${b("(current)")}`:""}`);for(let y=0;y<$r.length;y++){let R=es===y?` ${b("(current)")}`:"";console.log(` ${Ae(String(y+1)+")")} ${$r[y]}${R}`)}let xs=await Sr(l,"> ",0,Qt.length,No),ne,ce="",at="";if(xs>=1&&xs<=Qt.length&&(ne=Qt[xs-1]),ne==="openai"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?ce=await F(l," OpenAI API key (for Whisper)",y):(console.log(` ${b("Uses your OpenAI API key for Whisper transcription.")}`),ce=await pe(l," OpenAI API key")),console.log(` ${U(">")} OpenAI Whisper: ${b(Re(ce))}`)}else if(ne==="groq"){let y=t.env.ALFRED_SPEECH_API_KEY??"";y?ce=await F(l," Groq API key",y):(console.log(` ${b("Get your free API key at: https://console.groq.com/")}`),ce=await pe(l," Groq API key"));let R=t.env.ALFRED_SPEECH_BASE_URL??"";R&&(at=await F(l," Groq API URL",R)),console.log(` ${U(">")} Groq Whisper: ${b(Re(ce))}`)}else console.log(` ${b("Voice transcription disabled \u2014 you can configure it later.")}`);let Do=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
556
+ ${I("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${b("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Is=(await l.question(`${ee}> ${L}${b(`[${Do}] `)}`)).trim().toLowerCase(),$s=Is===""?t.codeSandboxEnabled:Is==="y"||Is==="yes";console.log($s?` ${U(">")} Code Sandbox ${I("enabled")} (JavaScript + Python)`:` ${b("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
557
+ ${I("Security configuration:")}`);let Ar=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",V;if(Ar)V=await F(l,"Owner user ID (for elevated permissions)",Ar);else{let y=(await l.question(`${it}Owner user ID${L} ${b("(optional, for elevated permissions)")}: ${ee}`)).trim();process.stdout.write(L),V=y}let ct=!1;if(V){let y=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${I("Enable shell access (admin commands) for the owner?")}`),console.log(` ${b("Allows Alfred to execute shell commands. Only for the owner.")}`);let R=(await l.question(` ${ee}> ${L}${b(`[${y}] `)}`)).trim().toLowerCase();R===""?ct=t.shellEnabled:ct=R==="y"||R==="yes",console.log(ct?` ${U(">")} Shell access ${I("enabled")} for owner ${b(V)}`:` ${b("Shell access disabled.")}`)}let Oo=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${I("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${b("By default, write actions are only allowed in DMs.")}`);let As=(await l.question(` ${ee}> ${L}${b(`[${Oo}] `)}`)).trim().toLowerCase(),lt;As===""?lt=t.writeInGroups:lt=As==="y"||As==="yes",console.log(lt?` ${U(">")} Write actions ${I("enabled")} in groups`:` ${b("Write actions only in DMs (default).")}`);let Co=t.rateLimit??30;console.log("");let Uo=await F(l," Rate limit (max write actions per hour per user)",String(Co)),ts=Math.max(1,parseInt(Uo,10)||30);console.log(` ${U(">")} Rate limit: ${I(String(ts))} per hour`),console.log(`
558
+ ${I("Writing configuration files...")}`);let D=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let y=a.envKeyName||"ALFRED_OLLAMA_API_KEY";D.push(`${y}=${c}`)}w!==a.defaultModel&&D.push(`ALFRED_LLM_MODEL=${w}`),h&&D.push(`ALFRED_LLM_BASE_URL=${h}`),D.push("","# === Messaging Platforms ===","");for(let[y,R]of Object.entries(H))D.push(`${y}=${R}`);D.push("","# === Web Search ===",""),S?(D.push(`ALFRED_SEARCH_PROVIDER=${S}`),P&&D.push(`ALFRED_SEARCH_API_KEY=${P}`),z&&D.push(`ALFRED_SEARCH_BASE_URL=${z}`)):(D.push("# ALFRED_SEARCH_PROVIDER=brave"),D.push("# ALFRED_SEARCH_API_KEY=")),D.push("","# === Email ===",""),Yt?(D.push(`ALFRED_EMAIL_USER=${ae}`),D.push(`ALFRED_EMAIL_PASS=${Jt}`)):(D.push("# ALFRED_EMAIL_USER="),D.push("# ALFRED_EMAIL_PASS=")),D.push("","# === Speech-to-Text ===",""),ne?(D.push(`ALFRED_SPEECH_PROVIDER=${ne}`),D.push(`ALFRED_SPEECH_API_KEY=${ce}`),at&&D.push(`ALFRED_SPEECH_BASE_URL=${at}`)):(D.push("# ALFRED_SPEECH_PROVIDER=groq"),D.push("# ALFRED_SPEECH_API_KEY=")),D.push("","# === Security ===",""),V?D.push(`ALFRED_OWNER_USER_ID=${V}`):D.push("# ALFRED_OWNER_USER_ID="),D.push("");let Po=ie.join(e,".env");K.writeFileSync(Po,D.join(`
559
+ `),"utf-8"),console.log(` ${U("+")} ${b(".env")} written`);let ss=ie.join(e,"config");K.existsSync(ss)||K.mkdirSync(ss,{recursive:!0});let Rr={name:r,telegram:{token:N.telegram?.token??"",enabled:A.some(y=>y.name==="telegram")},discord:{token:N.discord?.token??"",enabled:A.some(y=>y.name==="discord")},whatsapp:{enabled:A.some(y=>y.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:N.matrix?.homeserverUrl??"https://matrix.org",accessToken:N.matrix?.accessToken??"",userId:N.matrix?.userId??"",enabled:A.some(y=>y.name==="matrix")},signal:{apiUrl:N.signal?.apiUrl??"http://localhost:8080",phoneNumber:N.signal?.phoneNumber??"",enabled:A.some(y=>y.name==="signal")},llm:{provider:a.name,model:w,...h?{baseUrl:h}:{},temperature:.7,maxTokens:4096},...S?{search:{provider:S,...P?{apiKey:P}:{},...z?{baseUrl:z}:{}}}:{},...Yt?{email:{imap:{host:Zt,port:ks,secure:ks===993},smtp:{host:Ir,port:vs,secure:vs===465},auth:{user:ae,pass:Jt}}}:{},...ne?{speech:{provider:ne,apiKey:ce,...at?{baseUrl:at}:{}}}:{},...$s?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};V&&(Rr.security.ownerUserId=V);let Fo="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+kr.dump(Rr,{lineWidth:120,noRefs:!0,sortKeys:!1}),jo=ie.join(ss,"default.yml");K.writeFileSync(jo,Fo,"utf-8"),console.log(` ${U("+")} ${b("config/default.yml")} written`);let Rs=ie.join(ss,"rules");K.existsSync(Rs)||K.mkdirSync(Rs,{recursive:!0});let Bo=ct&&V?`
559
560
  # Allow admin actions (shell, etc.) for the owner only
560
561
  - id: allow-owner-admin
561
562
  effect: allow
@@ -576,7 +577,7 @@ ${I("Writing configuration files...")}`);let D=["# Alfred Environment Variables"
576
577
  # riskLevels: [admin, destructive]
577
578
  # conditions:
578
579
  # users: ["${V||"YOUR_USER_ID_HERE"}"]
579
- `,Fo=`# Alfred \u2014 Default Security Rules
580
+ `,Wo=`# Alfred \u2014 Default Security Rules
580
581
  # Rules are evaluated in priority order (lower number = higher priority).
581
582
  # First matching rule wins.
582
583
 
@@ -615,7 +616,7 @@ ${lt?` # Allow write-level skills everywhere (DMs and groups)
615
616
  rateLimit:
616
617
  maxInvocations: ${ts}
617
618
  windowSeconds: 3600
618
- ${Po}
619
+ ${Bo}
619
620
  # Deny destructive and admin actions by default
620
621
  - id: deny-destructive
621
622
  effect: deny
@@ -631,15 +632,15 @@ ${Po}
631
632
  scope: global
632
633
  actions: ["*"]
633
634
  riskLevels: [read, write, destructive, admin]
634
- `,jo=ie.join($s,"default-rules.yml");K.writeFileSync(jo,Fo,"utf-8"),console.log(` ${P("+")} ${_("config/rules/default-rules.yml")} written`);let Ar=ie.join(e,"data");if(K.existsSync(Ar)||(K.mkdirSync(Ar,{recursive:!0}),console.log(` ${P("+")} ${_("data/")} directory created`)),console.log(""),console.log(`${bs}${"=".repeat(52)}${L}`),console.log(`${bs}${it} Setup complete!${L}`),console.log(`${bs}${"=".repeat(52)}${L}`),console.log(""),console.log(` ${I("Bot name:")} ${r}`),console.log(` ${I("LLM provider:")} ${a.name} (${w})`),c&&console.log(` ${I("API key:")} ${Re(c)}`),A.length>0?console.log(` ${I("Platforms:")} ${A.map(y=>y.label).join(", ")}`):console.log(` ${I("Platforms:")} none (configure later)`),S){let y={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${z})`};console.log(` ${I("Web search:")} ${y[S]}`)}else console.log(` ${I("Web search:")} ${_("disabled")}`);if(console.log(Yt?` ${I("Email:")} ${ae} (${Zt})`:` ${I("Email:")} ${_("disabled")}`),ne){let y={openai:"OpenAI Whisper",groq:"Groq Whisper"};console.log(` ${I("Voice:")} ${y[ne]}`)}else console.log(` ${I("Voice:")} ${_("disabled")}`);V&&(console.log(` ${I("Owner ID:")} ${V}`),console.log(` ${I("Shell access:")} ${ct?P("enabled"):_("disabled")}`)),console.log(` ${I("Write scope:")} ${lt?"DMs + Groups":"DMs only"}`),console.log(` ${I("Rate limit:")} ${ts}/hour per user`),console.log(""),console.log(`${_s}Next steps:${L}`),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.${L}`),console.log("")}finally{l.close()}}async function F(l,e,t){let s=(await l.question(`${it}${e}${L} ${_(`[${t}]`)}: ${re}`)).trim();return process.stdout.write(L),s||t}async function pe(l,e){for(;;){let t=(await l.question(`${it}${e}${L}: ${re}`)).trim();if(process.stdout.write(L),t)return t;console.log(` ${go("!")} This field is required. Please enter a value.`)}}async function br(l,e,t,s,r){for(;;){let n=(await l.question(`${re}${e}${L}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${go("!")} Please enter a number between ${t} and ${s}.`)}}function fa(){console.log(`
635
- ${ua}${it} _ _ _____ ____ _____ ____
635
+ `,Xo=ie.join(Rs,"default-rules.yml");K.writeFileSync(Xo,Wo,"utf-8"),console.log(` ${U("+")} ${b("config/rules/default-rules.yml")} written`);let Lr=ie.join(e,"data");if(K.existsSync(Lr)||(K.mkdirSync(Lr,{recursive:!0}),console.log(` ${U("+")} ${b("data/")} directory created`)),console.log(""),console.log(`${bs}${"=".repeat(52)}${L}`),console.log(`${bs}${it} Setup complete!${L}`),console.log(`${bs}${"=".repeat(52)}${L}`),console.log(""),console.log(` ${I("Bot name:")} ${r}`),console.log(` ${I("LLM provider:")} ${a.name} (${w})`),c&&console.log(` ${I("API key:")} ${Re(c)}`),A.length>0?console.log(` ${I("Platforms:")} ${A.map(y=>y.label).join(", ")}`):console.log(` ${I("Platforms:")} none (configure later)`),S){let y={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${z})`};console.log(` ${I("Web search:")} ${y[S]}`)}else console.log(` ${I("Web search:")} ${b("disabled")}`);if(console.log(Yt?` ${I("Email:")} ${ae} (${Zt})`:` ${I("Email:")} ${b("disabled")}`),ne){let y={openai:"OpenAI Whisper",groq:"Groq Whisper"};console.log(` ${I("Voice:")} ${y[ne]}`)}else console.log(` ${I("Voice:")} ${b("disabled")}`);console.log(` ${I("Code Sandbox:")} ${$s?U("enabled"):b("disabled")}`),V&&(console.log(` ${I("Owner ID:")} ${V}`),console.log(` ${I("Shell access:")} ${ct?U("enabled"):b("disabled")}`)),console.log(` ${I("Write scope:")} ${lt?"DMs + Groups":"DMs only"}`),console.log(` ${I("Rate limit:")} ${ts}/hour per user`),console.log(""),console.log(`${_s}Next steps:${L}`),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.${L}`),console.log("")}finally{l.close()}}async function F(l,e,t){let s=(await l.question(`${it}${e}${L} ${b(`[${t}]`)}: ${ee}`)).trim();return process.stdout.write(L),s||t}async function pe(l,e){for(;;){let t=(await l.question(`${it}${e}${L}: ${ee}`)).trim();if(process.stdout.write(L),t)return t;console.log(` ${wo("!")} This field is required. Please enter a value.`)}}async function Sr(l,e,t,s,r){for(;;){let n=(await l.question(`${ee}${e}${L}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${wo("!")} Please enter a number between ${t} and ${s}.`)}}function wa(){console.log(`
636
+ ${ha}${it} _ _ _____ ____ _____ ____
636
637
  / \\ | | | ___| _ \\| ____| _ \\
637
638
  / _ \\ | | | |_ | |_) | _| | | | |
638
639
  / ___ \\| |___| _| | _ <| |___| |_| |
639
640
  /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${L}
640
641
  ${me} Personal AI Assistant \u2014 Setup Wizard${L}
641
- `)}var L,it,me,bs,re,_s,da,ua,Vt,ot,wo=f(()=>{"use strict";L="\x1B[0m",it="\x1B[1m",me="\x1B[2m",bs="\x1B[32m",re="\x1B[33m",_s="\x1B[36m",da="\x1B[31m",ua="\x1B[35m";d(P,"green");d(pa,"yellow");d(Ae,"cyan");d(go,"red");d(I,"bold");d(_,"dim");d(Re,"maskKey");Vt=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0},{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"}],ot=[{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}]}];d(ma,"loadExistingConfig");d(ha,"setupCommand");d(F,"askWithDefault");d(pe,"askRequired");d(br,"askNumber");d(fa,"printBanner")});var To={};J(To,{configCommand:()=>Ea});function ya(l){let e=l.toLowerCase();return ga.some(t=>e.includes(t))}function wa(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Eo(l){let e={};for(let[t,s]of Object.entries(l))ya(t)?e[t]=wa(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Eo(s):e[t]=s;return e}async function Ea(){let l=new q,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Eo(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var ga,bo=f(()=>{"use strict";ge();ga=["token","apikey","api_key","accesstoken","secret","password"];d(ya,"isSensitiveKey");d(wa,"redactValue");d(Eo,"redactObject");d(Ea,"configCommand")});var So={};J(So,{rulesCommand:()=>ba});import Ss from"node:fs";import _o from"node:path";import Ta from"js-yaml";async function ba(){let l=new q,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=_o.resolve(e.security.rulesPath);if(!Ss.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Ss.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Ss.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 Te,o=[],i=[];for(let a of r){let c=_o.join(t,a);try{let u=Ss.readFileSync(c,"utf-8"),m=Ta.load(u),p=n.loadFromObject(m);o.push(...p)}catch(u){i.push(` ${a}: ${u.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var ko=f(()=>{"use strict";ge();is();d(ba,"rulesCommand")});var vo={};J(vo,{statusCommand:()=>Sa});import Gt from"node:fs";import Sr from"node:path";import _a from"js-yaml";async function Sa(){let l=new q,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let u=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",m=c.enabled?"+":"-";console.log(` [${m}] ${c.name}: ${u}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let u=e.llm[c];u&&console.log(` ${c}: ${u.provider}/${u.model}`)}console.log(""),console.log("Storage:");let r=Sr.resolve(e.storage.path),n=Gt.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Sr.resolve(e.security.rulesPath),i=0,a=0;if(Gt.existsSync(o)&&Gt.statSync(o).isDirectory()){let c=Gt.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=c.length;let u=new Te;for(let m of c){let p=Sr.join(o,m);try{let h=Gt.readFileSync(p,"utf-8"),w=_a.load(h),E=u.loadFromObject(w);i+=E.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 xo=f(()=>{"use strict";ge();is();d(Sa,"statusCommand")});var Io={};J(Io,{logsCommand:()=>xa});import ka from"node:fs";import va from"node:path";async function xa(l){let e=new q,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=va.resolve(t.storage.path);if(!ka.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 ye(s);let n=new we(r.getDb()),o=n.count({}),i=n.query({limit:l});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(l,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let c=a.timestamp.toISOString(),u=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${c} [${u}] ${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 $o=f(()=>{"use strict";ge();Us();d(xa,"logsCommand")});import{readFileSync as Ia}from"node:fs";import{fileURLToPath as $a}from"node:url";import{dirname as Aa,join as Ra}from"node:path";function La(){try{let l=Aa($a(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Ia(Ra(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}d(La,"getVersion");var Ao=La(),kr=`
642
- Alfred CLI v${Ao}
642
+ `)}var L,it,me,bs,ee,_s,ma,ha,Vt,ot,To=f(()=>{"use strict";L="\x1B[0m",it="\x1B[1m",me="\x1B[2m",bs="\x1B[32m",ee="\x1B[33m",_s="\x1B[36m",ma="\x1B[31m",ha="\x1B[35m";d(U,"green");d(fa,"yellow");d(Ae,"cyan");d(wo,"red");d(I,"bold");d(b,"dim");d(Re,"maskKey");Vt=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0},{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"}],ot=[{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}]}];d(ga,"loadExistingConfig");d(ya,"setupCommand");d(F,"askWithDefault");d(pe,"askRequired");d(Sr,"askNumber");d(wa,"printBanner")});var _o={};J(_o,{configCommand:()=>_a});function Ta(l){let e=l.toLowerCase();return Ea.some(t=>e.includes(t))}function ba(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function bo(l){let e={};for(let[t,s]of Object.entries(l))Ta(t)?e[t]=ba(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=bo(s):e[t]=s;return e}async function _a(){let l=new q,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=bo(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Ea,So=f(()=>{"use strict";ge();Ea=["token","apikey","api_key","accesstoken","secret","password"];d(Ta,"isSensitiveKey");d(ba,"redactValue");d(bo,"redactObject");d(_a,"configCommand")});var vo={};J(vo,{rulesCommand:()=>ka});import Ss from"node:fs";import ko from"node:path";import Sa from"js-yaml";async function ka(){let l=new q,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=ko.resolve(e.security.rulesPath);if(!Ss.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Ss.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Ss.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 Te,o=[],i=[];for(let a of r){let c=ko.join(t,a);try{let u=Ss.readFileSync(c,"utf-8"),h=Sa.load(u),p=n.loadFromObject(h);o.push(...p)}catch(u){i.push(` ${a}: ${u.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var xo=f(()=>{"use strict";ge();is();d(ka,"rulesCommand")});var Io={};J(Io,{statusCommand:()=>xa});import Gt from"node:fs";import vr from"node:path";import va from"js-yaml";async function xa(){let l=new q,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let u=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",h=c.enabled?"+":"-";console.log(` [${h}] ${c.name}: ${u}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let u=e.llm[c];u&&console.log(` ${c}: ${u.provider}/${u.model}`)}console.log(""),console.log("Storage:");let r=vr.resolve(e.storage.path),n=Gt.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=vr.resolve(e.security.rulesPath),i=0,a=0;if(Gt.existsSync(o)&&Gt.statSync(o).isDirectory()){let c=Gt.readdirSync(o).filter(h=>h.endsWith(".yml")||h.endsWith(".yaml"));a=c.length;let u=new Te;for(let h of c){let p=vr.join(o,h);try{let m=Gt.readFileSync(p,"utf-8"),w=va.load(m),E=u.loadFromObject(w);i+=E.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 $o=f(()=>{"use strict";ge();is();d(xa,"statusCommand")});var Ao={};J(Ao,{logsCommand:()=>Aa});import Ia from"node:fs";import $a from"node:path";async function Aa(l){let e=new q,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=$a.resolve(t.storage.path);if(!Ia.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 ye(s);let n=new we(r.getDb()),o=n.count({}),i=n.query({limit:l});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(l,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let c=a.timestamp.toISOString(),u=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${c} [${u}] ${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 Ro=f(()=>{"use strict";ge();Fs();d(Aa,"logsCommand")});import{readFileSync as Ra}from"node:fs";import{fileURLToPath as La}from"node:url";import{dirname as Ma,join as Na}from"node:path";function Da(){try{let l=Ma(La(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Ra(Na(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}d(Da,"getVersion");var Lo=Da(),xr=`
643
+ Alfred CLI v${Lo}
643
644
  Personal AI Assistant
644
645
 
645
646
  Usage:
@@ -657,4 +658,4 @@ Commands:
657
658
  Options:
658
659
  --help, -h Show this help message
659
660
  --version, -v Show version number
660
- `.trim();function Ma(l){let e=l.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}}d(Ma,"parseArgs");async function Na(){let l=Ma(process.argv);switch((l.flags.help||l.flags.h)&&(console.log(kr),process.exit(0)),(l.flags.version||l.flags.v)&&(console.log(`alfred v${Ao}`),process.exit(0)),l.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(mo(),po));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(fo(),ho));await e({model:typeof l.flags.model=="string"?l.flags.model:void 0,tier:typeof l.flags.tier=="string"?l.flags.tier:void 0});break}case"setup":{let{setupCommand:e}=await Promise.resolve().then(()=>(wo(),yo));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(bo(),To));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(ko(),So));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(xo(),vo));await e();break}case"logs":{let e=l.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(()=>($o(),Io));await s(t);break}case"help":console.log(kr);break;case"":console.log(kr),process.exit(0);break;default:console.error(`Unknown command: ${l.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}d(Na,"main");Na().catch(l=>{console.error("Fatal error:",l),process.exit(1)});
661
+ `.trim();function Oa(l){let e=l.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}}d(Oa,"parseArgs");async function Ca(){let l=Oa(process.argv);switch((l.flags.help||l.flags.h)&&(console.log(xr),process.exit(0)),(l.flags.version||l.flags.v)&&(console.log(`alfred v${Lo}`),process.exit(0)),l.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(fo(),ho));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(yo(),go));await e({model:typeof l.flags.model=="string"?l.flags.model:void 0,tier:typeof l.flags.tier=="string"?l.flags.tier:void 0});break}case"setup":{let{setupCommand:e}=await Promise.resolve().then(()=>(To(),Eo));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(So(),_o));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(xo(),vo));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>($o(),Io));await e();break}case"logs":{let e=l.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(()=>(Ro(),Ao));await s(t);break}case"help":console.log(xr);break;case"":console.log(xr),process.exit(0);break;default:console.error(`Unknown command: ${l.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}d(Ca,"main");Ca().catch(l=>{console.error("Fatal error:",l),process.exit(1)});