@madh-io/alfred-ai 0.10.48 → 0.10.52
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.
- package/bundle/index.js +91 -90
- package/package.json +1 -1
package/bundle/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var ba=Object.defineProperty;var u=(l,e)=>ba(l,"name",{value:e,configurable:!0}),Ea=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var _=(l,e)=>()=>(l&&(e=l(l=0)),e);var me=(l,e)=>{for(var t in e)ba(l,t,{get:e[t],enumerable:!0})};import{z as y}from"zod";var ka,va,Sa,Aa,Ia,xa,Ra,Ca,ht,bu,Eu,$u,$a,ku,vu,Su,Au,Iu,xu,Ru,Cu,Du,Lu,Nu,Mu,Ou,Pu,Uu,Fu,ju,Bu,Hu,qu,zu,Wu,Gu,Vu,Ku,Xu,Yu,Ju,Zu,vo,So=_(()=>{"use strict";ka=y.object({token:y.string().optional(),enabled:y.boolean()}),va=y.object({token:y.string().optional(),enabled:y.boolean()}),Sa=y.object({enabled:y.boolean(),dataPath:y.string()}),Aa=y.object({homeserverUrl:y.string(),accessToken:y.string().optional(),userId:y.string().optional(),enabled:y.boolean()}),Ia=y.object({apiUrl:y.string(),phoneNumber:y.string().optional(),enabled:y.boolean()}),xa=y.object({path:y.string()}),Ra=y.object({level:y.enum(["trace","debug","info","warn","error","fatal"]),pretty:y.boolean(),auditLogPath:y.string().optional()}),Ca=y.object({rulesPath:y.string(),defaultEffect:y.enum(["allow","deny"]),ownerUserId:y.string().optional()}),ht=y.object({provider:y.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:y.string().optional(),baseUrl:y.string().optional(),model:y.string(),temperature:y.number().optional(),maxTokens:y.number().optional()}),bu=y.object({default:ht,strong:ht.optional(),fast:ht.optional(),embeddings:ht.optional(),local:ht.optional()}).passthrough(),Eu=y.union([ht,bu]),$u=y.object({provider:y.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:y.string().optional(),baseUrl:y.string().optional()}),$a=y.object({name:y.string().optional(),provider:y.enum(["imap-smtp","microsoft"]).optional(),imap:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),smtp:y.object({host:y.string(),port:y.number(),secure:y.boolean()}).optional(),auth:y.object({user:y.string(),pass:y.string()}).optional(),microsoft:y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}).optional()}),ku=y.union([y.object({accounts:y.array($a)}),$a]),vu=y.object({provider:y.enum(["openai","groq","google"]),apiKey:y.string(),baseUrl:y.string().optional(),ttsEnabled:y.boolean().optional(),ttsModel:y.string().optional(),ttsVoice:y.string().optional()}),Su=y.object({serverUrl:y.string(),username:y.string(),password:y.string()}),Au=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),Iu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),xu=y.object({provider:y.enum(["caldav","google","microsoft"]),caldav:Su.optional(),google:Au.optional(),microsoft:Iu.optional()}),Ru=y.object({name:y.string(),command:y.string().optional(),args:y.array(y.string()).optional(),env:y.record(y.string()).optional(),url:y.string().optional()}),Cu=y.object({servers:y.array(Ru)}),Du=y.object({enabled:y.boolean(),allowedLanguages:y.array(y.enum(["javascript","python"])).optional(),maxTimeoutMs:y.number().optional(),allowNetwork:y.boolean().optional()}),Lu=y.object({enabled:y.boolean().optional(),minMessageLength:y.number().optional(),minConfidence:y.number().min(0).max(1).optional(),maxExtractionsPerMinute:y.number().optional()}),Nu=y.object({enabled:y.boolean(),port:y.coerce.number().int().min(1).max(65535),host:y.string()}),Mu=y.object({name:y.string(),command:y.string(),argsTemplate:y.array(y.string()),promptVia:y.enum(["arg","stdin"]).default("arg"),env:y.record(y.string()).optional(),cwd:y.string().optional(),timeoutMs:y.number().max(9e5).optional()}),Ou=y.object({token:y.string(),baseUrl:y.string().optional()}),Pu=y.object({token:y.string(),baseUrl:y.string().optional()}),Uu=y.object({provider:y.enum(["github","gitlab"]),baseBranch:y.string().optional(),github:Ou.optional(),gitlab:Pu.optional()}),Fu=y.object({enabled:y.boolean(),agents:y.array(Mu),forge:Uu.optional()}),ju=y.object({baseUrl:y.string(),tokenId:y.string(),tokenSecret:y.string(),verifyTls:y.boolean().optional(),defaultNode:y.string().optional()}),Bu=y.object({baseUrl:y.string(),apiKey:y.string().optional(),username:y.string().optional(),password:y.string().optional(),site:y.string().optional(),verifyTls:y.boolean().optional()}),Hu=y.object({baseUrl:y.string(),accessToken:y.string(),verifyTls:y.boolean().optional()}),qu=y.object({serverUrl:y.string(),username:y.string(),password:y.string(),addressBookPath:y.string().optional()}),zu=y.object({clientId:y.string(),clientSecret:y.string(),refreshToken:y.string()}),Wu=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Gu=y.object({provider:y.enum(["carddav","google","microsoft"]),carddav:qu.optional(),google:zu.optional(),microsoft:Wu.optional()}),Vu=y.object({socketPath:y.string().optional(),host:y.string().optional(),verifyTls:y.boolean().optional()}),Ku=y.object({clientId:y.string()}),Xu=y.object({apiKey:y.string()}),Yu=y.object({gridName:y.string().optional(),gridUsageCt:y.coerce.number().optional(),gridLossCt:y.coerce.number().optional(),gridCapacityFee:y.coerce.number().optional(),gridMeterFee:y.coerce.number().optional()}),Ju=y.object({clientId:y.string(),clientSecret:y.string(),tenantId:y.string(),refreshToken:y.string()}),Zu=y.object({maxHistoryMessages:y.number().min(10).max(500).optional()}).optional(),vo=y.object({name:y.string(),telegram:ka,discord:va.optional(),whatsapp:Sa.optional(),matrix:Aa.optional(),signal:Ia.optional(),llm:Eu,storage:xa,logger:Ra,security:Ca,search:$u.optional(),email:ku.optional(),speech:vu.optional(),calendar:xu.optional(),mcp:Cu.optional(),codeSandbox:Du.optional(),activeLearning:Lu.optional(),api:Nu.optional(),codeAgents:Fu.optional(),proxmox:ju.optional(),unifi:Bu.optional(),homeassistant:Hu.optional(),contacts:Gu.optional(),docker:Vu.optional(),bmw:Ku.optional(),routing:Xu.optional(),todo:Ju.optional(),energy:Yu.optional(),conversation:Zu})});var Ao,Io=_(()=>{"use strict";Ao={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"},conversation:{maxHistoryMessages:100}}});import Da from"node:fs";import Qu from"node:path";import{config as La}from"dotenv";import em from"js-yaml";function Na(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]=Na(n,r):t[s]=r}return t}function sm(l){let e={...l};for(let[t,s]of Object.entries(tm)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function xo(){La({override:!0})}var tm,ue,Ma=_(()=>{"use strict";So();Io();u(Na,"deepMerge");tm={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"],ALFRED_EBAY_APP_ID:["marketplace","ebay","appId"],ALFRED_EBAY_CERT_ID:["marketplace","ebay","certId"],ALFRED_BRIEFING_LOCATION:["briefing","location"],ALFRED_BRIEFING_HOME_ADDRESS:["briefing","homeAddress"],ALFRED_BRIEFING_OFFICE_ADDRESS:["briefing","officeAddress"]};u(sm,"applyEnvOverrides");u(xo,"reloadDotenv");ue=class{static{u(this,"ConfigLoader")}loadConfig(e){La();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Qu.resolve(t);if(Da.existsSync(r)){let g=Da.readFileSync(r,"utf-8"),f=em.load(g);f&&typeof f=="object"&&(s=f)}let n=Na(Ao,s),o=sm(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(f=>a[f]&&typeof a[f]=="object")){let f={};for(let[T,E]of Object.entries(a))!i.includes(T)&&T!=="default"&&(f[T]=E);let h={default:f};for(let T of i)a[T]&&(h[T]=a[T]);o.llm=h}let c=vo.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let m=c.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let f of["default","strong","fast","embeddings","local"]){let h=m[f];h&&!h.apiKey&&(h.apiKey=g)}}let p=c.email;if(p&&!("accounts"in p))c.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let g=p.microsoft;if(g){let h=p.accounts.find(T=>T.provider==="microsoft");if(h){let T=h.microsoft??{};h.microsoft={...T,...g}}delete p.microsoft}}return c}}});var We=_(()=>{"use strict";So();Io();Ma()});import Ro from"pino";function Ns(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Ro.transport({target:"pino-pretty",options:{colorize:!0}});return Ro({name:l,level:t},r)}return Ro({name:l,level:t})}var Oa=_(()=>{"use strict";u(Ns,"createLogger")});import ff from"pino";var Pa=_(()=>{"use strict"});var Co=_(()=>{"use strict";Oa();Pa()});var Lt,tn=_(()=>{"use strict";Lt=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
|
|
2
|
+
var ba=Object.defineProperty;var u=(l,e)=>ba(l,"name",{value:e,configurable:!0}),Ea=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var _=(l,e)=>()=>(l&&(e=l(l=0)),e);var me=(l,e)=>{for(var t in e)ba(l,t,{get:e[t],enumerable:!0})};import{z as w}from"zod";var ka,va,Sa,Aa,Ia,xa,Ra,Ca,ht,bu,Eu,$u,$a,ku,vu,Su,Au,Iu,xu,Ru,Cu,Du,Lu,Nu,Mu,Ou,Pu,Uu,Fu,ju,Bu,Hu,qu,zu,Wu,Gu,Vu,Ku,Xu,Yu,Ju,Zu,vo,So=_(()=>{"use strict";ka=w.object({token:w.string().optional(),enabled:w.boolean()}),va=w.object({token:w.string().optional(),enabled:w.boolean()}),Sa=w.object({enabled:w.boolean(),dataPath:w.string()}),Aa=w.object({homeserverUrl:w.string(),accessToken:w.string().optional(),userId:w.string().optional(),enabled:w.boolean()}),Ia=w.object({apiUrl:w.string(),phoneNumber:w.string().optional(),enabled:w.boolean()}),xa=w.object({path:w.string()}),Ra=w.object({level:w.enum(["trace","debug","info","warn","error","fatal"]),pretty:w.boolean(),auditLogPath:w.string().optional()}),Ca=w.object({rulesPath:w.string(),defaultEffect:w.enum(["allow","deny"]),ownerUserId:w.string().optional()}),ht=w.object({provider:w.enum(["anthropic","openai","openrouter","ollama","openwebui","google","mistral"]),apiKey:w.string().optional(),baseUrl:w.string().optional(),model:w.string(),temperature:w.number().optional(),maxTokens:w.number().optional()}),bu=w.object({default:ht,strong:ht.optional(),fast:ht.optional(),embeddings:ht.optional(),local:ht.optional()}).passthrough(),Eu=w.union([ht,bu]),$u=w.object({provider:w.enum(["brave","searxng","tavily","duckduckgo"]),apiKey:w.string().optional(),baseUrl:w.string().optional()}),$a=w.object({name:w.string().optional(),provider:w.enum(["imap-smtp","microsoft"]).optional(),imap:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),smtp:w.object({host:w.string(),port:w.number(),secure:w.boolean()}).optional(),auth:w.object({user:w.string(),pass:w.string()}).optional(),microsoft:w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}).optional()}),ku=w.union([w.object({accounts:w.array($a)}),$a]),vu=w.object({provider:w.enum(["openai","groq","google"]),apiKey:w.string(),baseUrl:w.string().optional(),ttsEnabled:w.boolean().optional(),ttsModel:w.string().optional(),ttsVoice:w.string().optional()}),Su=w.object({serverUrl:w.string(),username:w.string(),password:w.string()}),Au=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),Iu=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),xu=w.object({provider:w.enum(["caldav","google","microsoft"]),caldav:Su.optional(),google:Au.optional(),microsoft:Iu.optional()}),Ru=w.object({name:w.string(),command:w.string().optional(),args:w.array(w.string()).optional(),env:w.record(w.string()).optional(),url:w.string().optional()}),Cu=w.object({servers:w.array(Ru)}),Du=w.object({enabled:w.boolean(),allowedLanguages:w.array(w.enum(["javascript","python"])).optional(),maxTimeoutMs:w.number().optional(),allowNetwork:w.boolean().optional()}),Lu=w.object({enabled:w.boolean().optional(),minMessageLength:w.number().optional(),minConfidence:w.number().min(0).max(1).optional(),maxExtractionsPerMinute:w.number().optional()}),Nu=w.object({enabled:w.boolean(),port:w.coerce.number().int().min(1).max(65535),host:w.string()}),Mu=w.object({name:w.string(),command:w.string(),argsTemplate:w.array(w.string()),promptVia:w.enum(["arg","stdin"]).default("arg"),env:w.record(w.string()).optional(),cwd:w.string().optional(),timeoutMs:w.number().max(9e5).optional()}),Ou=w.object({token:w.string(),baseUrl:w.string().optional()}),Pu=w.object({token:w.string(),baseUrl:w.string().optional()}),Uu=w.object({provider:w.enum(["github","gitlab"]),baseBranch:w.string().optional(),github:Ou.optional(),gitlab:Pu.optional()}),Fu=w.object({enabled:w.boolean(),agents:w.array(Mu),forge:Uu.optional()}),ju=w.object({baseUrl:w.string(),tokenId:w.string(),tokenSecret:w.string(),verifyTls:w.boolean().optional(),defaultNode:w.string().optional()}),Bu=w.object({baseUrl:w.string(),apiKey:w.string().optional(),username:w.string().optional(),password:w.string().optional(),site:w.string().optional(),verifyTls:w.boolean().optional()}),Hu=w.object({baseUrl:w.string(),accessToken:w.string(),verifyTls:w.boolean().optional()}),qu=w.object({serverUrl:w.string(),username:w.string(),password:w.string(),addressBookPath:w.string().optional()}),zu=w.object({clientId:w.string(),clientSecret:w.string(),refreshToken:w.string()}),Wu=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),Gu=w.object({provider:w.enum(["carddav","google","microsoft"]),carddav:qu.optional(),google:zu.optional(),microsoft:Wu.optional()}),Vu=w.object({socketPath:w.string().optional(),host:w.string().optional(),verifyTls:w.boolean().optional()}),Ku=w.object({clientId:w.string()}),Xu=w.object({apiKey:w.string()}),Yu=w.object({gridName:w.string().optional(),gridUsageCt:w.coerce.number().optional(),gridLossCt:w.coerce.number().optional(),gridCapacityFee:w.coerce.number().optional(),gridMeterFee:w.coerce.number().optional()}),Ju=w.object({clientId:w.string(),clientSecret:w.string(),tenantId:w.string(),refreshToken:w.string()}),Zu=w.object({maxHistoryMessages:w.number().min(10).max(500).optional()}).optional(),vo=w.object({name:w.string(),telegram:ka,discord:va.optional(),whatsapp:Sa.optional(),matrix:Aa.optional(),signal:Ia.optional(),llm:Eu,storage:xa,logger:Ra,security:Ca,search:$u.optional(),email:ku.optional(),speech:vu.optional(),calendar:xu.optional(),mcp:Cu.optional(),codeSandbox:Du.optional(),activeLearning:Lu.optional(),api:Nu.optional(),codeAgents:Fu.optional(),proxmox:ju.optional(),unifi:Bu.optional(),homeassistant:Hu.optional(),contacts:Gu.optional(),docker:Vu.optional(),bmw:Ku.optional(),routing:Xu.optional(),todo:Ju.optional(),energy:Yu.optional(),conversation:Zu})});var Ao,Io=_(()=>{"use strict";Ao={name:"Alfred",telegram:{token:"",enabled:!1},discord:{token:"",enabled:!1},whatsapp:{enabled:!1,dataPath:"./data/whatsapp"},matrix:{homeserverUrl:"https://matrix.org",accessToken:"",userId:"",enabled:!1},signal:{apiUrl:"http://localhost:8080",phoneNumber:"",enabled:!1},llm:{provider:"anthropic",model:"claude-sonnet-4-20250514",temperature:.7,maxTokens:4096},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0},security:{rulesPath:"./config/rules",defaultEffect:"deny"},api:{enabled:!0,port:3420,host:"127.0.0.1"},conversation:{maxHistoryMessages:100}}});import Da from"node:fs";import Qu from"node:path";import{config as La}from"dotenv";import em from"js-yaml";function Na(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]=Na(n,r):t[s]=r}return t}function sm(l){let e={...l};for(let[t,s]of Object.entries(tm)){let r=process.env[t];if(r===void 0)continue;let n=e;for(let o=0;o<s.length-1;o++){let i=s[o];(n[i]===void 0||n[i]===null||typeof n[i]!="object")&&(n[i]={}),n[i]={...n[i]},n=n[i]}n[s[s.length-1]]=r}return e}function xo(){La({override:!0})}var tm,ue,Ma=_(()=>{"use strict";So();Io();u(Na,"deepMerge");tm={ALFRED_TELEGRAM_TOKEN:["telegram","token"],ALFRED_DISCORD_TOKEN:["discord","token"],ALFRED_MATRIX_HOMESERVER_URL:["matrix","homeserverUrl"],ALFRED_MATRIX_ACCESS_TOKEN:["matrix","accessToken"],ALFRED_MATRIX_USER_ID:["matrix","userId"],ALFRED_SIGNAL_API_URL:["signal","apiUrl"],ALFRED_SIGNAL_PHONE_NUMBER:["signal","phoneNumber"],ALFRED_ANTHROPIC_API_KEY:["llm","apiKey"],ALFRED_OPENAI_API_KEY:["llm","apiKey"],ALFRED_GOOGLE_API_KEY:["llm","apiKey"],ALFRED_OPENROUTER_API_KEY:["llm","apiKey"],ALFRED_OPENWEBUI_API_KEY:["llm","apiKey"],ALFRED_LLM_PROVIDER:["llm","provider"],ALFRED_LLM_MODEL:["llm","model"],ALFRED_LLM_BASE_URL:["llm","baseUrl"],ALFRED_LLM_STRONG_PROVIDER:["llm","strong","provider"],ALFRED_LLM_STRONG_MODEL:["llm","strong","model"],ALFRED_LLM_STRONG_API_KEY:["llm","strong","apiKey"],ALFRED_LLM_FAST_PROVIDER:["llm","fast","provider"],ALFRED_LLM_FAST_MODEL:["llm","fast","model"],ALFRED_LLM_FAST_API_KEY:["llm","fast","apiKey"],ALFRED_LLM_EMBEDDINGS_PROVIDER:["llm","embeddings","provider"],ALFRED_LLM_EMBEDDINGS_MODEL:["llm","embeddings","model"],ALFRED_LLM_EMBEDDINGS_API_KEY:["llm","embeddings","apiKey"],ALFRED_LLM_LOCAL_PROVIDER:["llm","local","provider"],ALFRED_LLM_LOCAL_MODEL:["llm","local","model"],ALFRED_LLM_LOCAL_BASE_URL:["llm","local","baseUrl"],ALFRED_STORAGE_PATH:["storage","path"],ALFRED_LOG_LEVEL:["logger","level"],ALFRED_OWNER_USER_ID:["security","ownerUserId"],ALFRED_SEARCH_PROVIDER:["search","provider"],ALFRED_SEARCH_API_KEY:["search","apiKey"],ALFRED_SEARCH_BASE_URL:["search","baseUrl"],ALFRED_EMAIL_PROVIDER:["email","provider"],ALFRED_EMAIL_USER:["email","auth","user"],ALFRED_EMAIL_PASS:["email","auth","pass"],ALFRED_MICROSOFT_EMAIL_CLIENT_ID:["email","microsoft","clientId"],ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:["email","microsoft","clientSecret"],ALFRED_MICROSOFT_EMAIL_TENANT_ID:["email","microsoft","tenantId"],ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:["email","microsoft","refreshToken"],ALFRED_SPEECH_PROVIDER:["speech","provider"],ALFRED_SPEECH_API_KEY:["speech","apiKey"],ALFRED_SPEECH_BASE_URL:["speech","baseUrl"],ALFRED_CALENDAR_PROVIDER:["calendar","provider"],ALFRED_CALDAV_SERVER_URL:["calendar","caldav","serverUrl"],ALFRED_CALDAV_USERNAME:["calendar","caldav","username"],ALFRED_CALDAV_PASSWORD:["calendar","caldav","password"],ALFRED_GOOGLE_CALENDAR_CLIENT_ID:["calendar","google","clientId"],ALFRED_GOOGLE_CALENDAR_CLIENT_SECRET:["calendar","google","clientSecret"],ALFRED_GOOGLE_CALENDAR_REFRESH_TOKEN:["calendar","google","refreshToken"],ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:["calendar","microsoft","clientId"],ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:["calendar","microsoft","clientSecret"],ALFRED_MICROSOFT_CALENDAR_TENANT_ID:["calendar","microsoft","tenantId"],ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:["calendar","microsoft","refreshToken"],ALFRED_FORGE_PROVIDER:["codeAgents","forge","provider"],ALFRED_FORGE_BASE_BRANCH:["codeAgents","forge","baseBranch"],ALFRED_GITHUB_TOKEN:["codeAgents","forge","github","token"],ALFRED_GITHUB_BASE_URL:["codeAgents","forge","github","baseUrl"],ALFRED_GITLAB_TOKEN:["codeAgents","forge","gitlab","token"],ALFRED_GITLAB_BASE_URL:["codeAgents","forge","gitlab","baseUrl"],ALFRED_PROXMOX_BASE_URL:["proxmox","baseUrl"],ALFRED_PROXMOX_TOKEN_ID:["proxmox","tokenId"],ALFRED_PROXMOX_TOKEN_SECRET:["proxmox","tokenSecret"],ALFRED_UNIFI_BASE_URL:["unifi","baseUrl"],ALFRED_UNIFI_API_KEY:["unifi","apiKey"],ALFRED_UNIFI_USERNAME:["unifi","username"],ALFRED_UNIFI_PASSWORD:["unifi","password"],ALFRED_UNIFI_SITE:["unifi","site"],ALFRED_HOMEASSISTANT_URL:["homeassistant","baseUrl"],ALFRED_HOMEASSISTANT_TOKEN:["homeassistant","accessToken"],ALFRED_CONTACTS_PROVIDER:["contacts","provider"],ALFRED_CARDDAV_CONTACTS_SERVER_URL:["contacts","carddav","serverUrl"],ALFRED_CARDDAV_CONTACTS_USERNAME:["contacts","carddav","username"],ALFRED_CARDDAV_CONTACTS_PASSWORD:["contacts","carddav","password"],ALFRED_GOOGLE_CONTACTS_CLIENT_ID:["contacts","google","clientId"],ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET:["contacts","google","clientSecret"],ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN:["contacts","google","refreshToken"],ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:["contacts","microsoft","clientId"],ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:["contacts","microsoft","clientSecret"],ALFRED_MICROSOFT_CONTACTS_TENANT_ID:["contacts","microsoft","tenantId"],ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:["contacts","microsoft","refreshToken"],ALFRED_DOCKER_SOCKET_PATH:["docker","socketPath"],ALFRED_DOCKER_HOST:["docker","host"],ALFRED_BMW_CLIENT_ID:["bmw","clientId"],ALFRED_ROUTING_API_KEY:["routing","apiKey"],ALFRED_MICROSOFT_TODO_CLIENT_ID:["todo","clientId"],ALFRED_MICROSOFT_TODO_CLIENT_SECRET:["todo","clientSecret"],ALFRED_MICROSOFT_TODO_TENANT_ID:["todo","tenantId"],ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:["todo","refreshToken"],ALFRED_ENERGY_GRID_NAME:["energy","gridName"],ALFRED_ENERGY_GRID_USAGE_CT:["energy","gridUsageCt"],ALFRED_ENERGY_GRID_LOSS_CT:["energy","gridLossCt"],ALFRED_ENERGY_GRID_CAPACITY_FEE:["energy","gridCapacityFee"],ALFRED_ENERGY_GRID_METER_FEE:["energy","gridMeterFee"],ALFRED_EBAY_APP_ID:["marketplace","ebay","appId"],ALFRED_EBAY_CERT_ID:["marketplace","ebay","certId"],ALFRED_BRIEFING_LOCATION:["briefing","location"],ALFRED_BRIEFING_HOME_ADDRESS:["briefing","homeAddress"],ALFRED_BRIEFING_OFFICE_ADDRESS:["briefing","officeAddress"]};u(sm,"applyEnvOverrides");u(xo,"reloadDotenv");ue=class{static{u(this,"ConfigLoader")}loadConfig(e){La();let t=e??process.env.ALFRED_CONFIG_PATH??"./config/default.yml",s={},r=Qu.resolve(t);if(Da.existsSync(r)){let g=Da.readFileSync(r,"utf-8"),f=em.load(g);f&&typeof f=="object"&&(s=f)}let n=Na(Ao,s),o=sm(n),i=["strong","fast","embeddings","local"],a=o.llm;if(a&&"provider"in a&&i.some(f=>a[f]&&typeof a[f]=="object")){let f={};for(let[y,E]of Object.entries(a))!i.includes(y)&&y!=="default"&&(f[y]=E);let h={default:f};for(let y of i)a[y]&&(h[y]=a[y]);o.llm=h}let c=vo.parse(o),d=c.llm;d&&"provider"in d&&(c.llm={default:d});let m=c.llm;if(m&&typeof m=="object"){let g=m.apiKey??m.default?.apiKey;if(g)for(let f of["default","strong","fast","embeddings","local"]){let h=m[f];h&&!h.apiKey&&(h.apiKey=g)}}let p=c.email;if(p&&!("accounts"in p))c.email={accounts:[{name:"default",...p}]};else if(p&&"accounts"in p&&"microsoft"in p){let g=p.microsoft;if(g){let h=p.accounts.find(y=>y.provider==="microsoft");if(h){let y=h.microsoft??{};h.microsoft={...y,...g}}delete p.microsoft}}return c}}});var We=_(()=>{"use strict";So();Io();Ma()});import Ro from"pino";function Ns(l,e){let t=e??process.env.LOG_LEVEL??"info";if(t==="debug"||t==="trace"||process.env.NODE_ENV!=="production"){let r=Ro.transport({target:"pino-pretty",options:{colorize:!0}});return Ro({name:l,level:t},r)}return Ro({name:l,level:t})}var Oa=_(()=>{"use strict";u(Ns,"createLogger")});import gf from"pino";var Pa=_(()=>{"use strict"});var Co=_(()=>{"use strict";Oa();Pa()});var Lt,tn=_(()=>{"use strict";Lt=class{static{u(this,"Migrator")}db;constructor(e){this.db=e,this.ensureMigrationsTable()}ensureMigrationsTable(){this.db.exec(`
|
|
3
3
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
4
4
|
version INTEGER PRIMARY KEY,
|
|
5
5
|
description TEXT,
|
|
@@ -368,8 +368,8 @@ var ba=Object.defineProperty;var u=(l,e)=>ba(l,"name",{value:e,configurable:!0})
|
|
|
368
368
|
UPDATE watches
|
|
369
369
|
SET last_checked_at = ?, last_value = ?
|
|
370
370
|
WHERE id = ?
|
|
371
|
-
`).run(t.lastCheckedAt,t.lastValue,e)}findByChatId(e,t){return this.db.prepare("SELECT * FROM watches WHERE chat_id = ? AND platform = ? ORDER BY created_at DESC").all(e,t).map(r=>this.mapRow(r))}toggle(e,t){return this.db.prepare("UPDATE watches SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM watches WHERE id = ?").run(e).changes>0}getById(e){let t=this.db.prepare("SELECT * FROM watches WHERE id = ?").get(e);return t?this.mapRow(t):void 0}mapRow(e){let t={};try{t=JSON.parse(e.skill_params)}catch{}let s={field:e.condition_field,operator:e.condition_operator};if(e.condition_value!=null){let r=Number(e.condition_value);s.value=isNaN(r)?e.condition_value:r}return{id:e.id,chatId:e.chat_id,platform:e.platform,name:e.name,skillName:e.skill_name,skillParams:t,condition:s,intervalMinutes:e.interval_minutes,cooldownMinutes:e.cooldown_minutes,enabled:e.enabled===1,lastCheckedAt:e.last_checked_at??null,lastTriggeredAt:e.last_triggered_at??null,lastValue:e.last_value??null,createdAt:e.created_at,messageTemplate:e.message_template}}}});var No=_(()=>{"use strict";Ua();ja();Ba();Ha();qa();tn();Lo();za();Wa();Ga();Va();Ka();Xa();Ja();Za();Qa()});function Ge(l){if(Mo[l])return Mo[l];let e=Object.entries(Mo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var Mo,gm,Ae,yt=_(()=>{"use strict";Mo={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-opus-4-5-20251101":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-sonnet-4-5-20250929":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-3-5-sonnet-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-sonnet-20240620":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-haiku-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-4-5-20251001":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-opus-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-sonnet-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-haiku-20240307":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-":{maxInputTokens:2e5,maxOutputTokens:16e3},"gpt-4.1":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-mini":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-nano":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o3:{maxInputTokens:2e5,maxOutputTokens:1e5},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"o4-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"gpt-5.4":{maxInputTokens:105e4,maxOutputTokens:128e3},"gpt-5":{maxInputTokens:4e5,maxOutputTokens:128e3},"gemini-3.1-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3.1-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"mistral-large":{maxInputTokens:262144,maxOutputTokens:262144},"mistral-medium":{maxInputTokens:128e3,maxOutputTokens:128e3},"mistral-small":{maxInputTokens:128e3,maxOutputTokens:128e3},codestral:{maxInputTokens:262144,maxOutputTokens:262144},"magistral-medium":{maxInputTokens:128e3,maxOutputTokens:131072},"magistral-small":{maxInputTokens:128e3,maxOutputTokens:131072},ministral:{maxInputTokens:128e3,maxOutputTokens:128e3},llama4:{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},gemma3:{maxInputTokens:128e3,maxOutputTokens:8192},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},qwen3:{maxInputTokens:128e3,maxOutputTokens:8192},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},phi4:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-v3":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-chat":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"command-r-plus":{maxInputTokens:128e3,maxOutputTokens:4096}},gm={maxInputTokens:128e3,maxOutputTokens:8192};u(Ge,"lookupContextWindow");Ae=class{static{u(this,"LLMProvider")}config;contextWindow=gm;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import ym from"@anthropic-ai/sdk";var Vs,Oo=_(()=>{"use strict";yt();Vs=class extends Ae{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new ym({apiKey:this.config.apiKey,maxRetries:5});let e=Ge(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s},n=await this.client.messages.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=this.client.messages.stream({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system,messages:t,tools:s});for await(let n of r)if(n.type==="content_block_delta")n.delta.type==="text_delta"?yield{type:"text_delta",text:n.delta.text}:n.delta.type==="input_json_delta"&&(yield{type:"tool_use_delta",toolCall:{input:n.delta.partial_json}});else if(n.type==="content_block_start")n.content_block.type==="tool_use"&&(yield{type:"tool_use_start",toolCall:{id:n.content_block.id,name:n.content_block.name}});else if(n.type==="message_stop"){let o=await r.finalMessage();yield{type:"message_complete",response:this.mapResponse(o)}}}isAvailable(){return!!this.config.apiKey}mapMessages(e){return e.map(t=>{if(typeof t.content=="string")return{role:t.role,content:t.content};let s=t.content.map(r=>{switch(r.type){case"text":return{type:"text",text:r.text};case"image":return{type:"image",source:{type:"base64",media_type:r.source.media_type,data:r.source.data}};case"tool_use":return{type:"tool_use",id:r.id,name:r.name,input:r.input};case"tool_result":return{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content,is_error:r.is_error};default:return{type:"text",text:"[Unsupported block type]"}}}).filter(r=>r!==void 0);return{role:t.role,content:s}})}mapTools(e){return e.map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}mapResponse(e){let t="",s=[];for(let r of e.content)r.type==="text"?t+=r.text:r.type==="tool_use"&&s.push({id:r.id,name:r.name,input:r.input});return{content:t,toolCalls:s.length>0?s:void 0,usage:{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens},stopReason:e.stop_reason}}}});import wm from"openai";var De,Nt=_(()=>{"use strict";yt();De=class extends Ae{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new wm({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=Ge(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",c=[],d=null,m=0,p=0;for await(let g of r){let f=g.choices[0];if(!f)continue;let h=f.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let T of h.tool_calls)if(T.id){if(n){let E;try{E=JSON.parse(i||"{}")}catch{E={}}c.push({id:n,name:o,input:E})}n=T.id,o=T.function?.name,i=T.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else T.function?.arguments&&(i+=T.function.arguments,yield{type:"tool_use_delta",toolCall:{input:T.function.arguments}});f.finish_reason&&(d=f.finish_reason),g.usage&&(m=g.usage.prompt_tokens,p=g.usage.completion_tokens)}if(n){let g;try{g=JSON.parse(i||"{}")}catch{g={}}c.push({id:n,name:o,input:g})}yield{type:"message_complete",response:{content:a,toolCalls:c.length>0?c:void 0,usage:{inputTokens:m,outputTokens:p},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}isReasoningModel(){return/^(o[1-9]|gpt-5($|[.-][01]))/.test(this.config.model)}tokenLimitParam(e){let t=e??this.config.maxTokens??4096;return/^(gpt-5|o[1-9])/.test(this.config.model)?{max_completion_tokens:t}:{max_tokens:t}}safeTemperature(e){if(!this.isReasoningModel())return e??this.config.temperature}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(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 Ks,Po=_(()=>{"use strict";Nt();Ks=class extends De{static{u(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var Xs,Uo=_(()=>{"use strict";yt();Xs=class extends Ae{static{u(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=Ge(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let g=await n.text();throw new Error(`Ollama API error (${n.status}): ${g}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",d=0,m=0,p=[];try{for(;;){let{done:g,value:f}=await o.read();if(g)break;a+=i.decode(f,{stream:!0});let h=a.split(`
|
|
372
|
-
`);a=h.pop()??"";for(let
|
|
371
|
+
`).run(t.lastCheckedAt,t.lastValue,e)}findByChatId(e,t){return this.db.prepare("SELECT * FROM watches WHERE chat_id = ? AND platform = ? ORDER BY created_at DESC").all(e,t).map(r=>this.mapRow(r))}toggle(e,t){return this.db.prepare("UPDATE watches SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM watches WHERE id = ?").run(e).changes>0}getById(e){let t=this.db.prepare("SELECT * FROM watches WHERE id = ?").get(e);return t?this.mapRow(t):void 0}mapRow(e){let t={};try{t=JSON.parse(e.skill_params)}catch{}let s={field:e.condition_field,operator:e.condition_operator};if(e.condition_value!=null){let r=Number(e.condition_value);s.value=isNaN(r)?e.condition_value:r}return{id:e.id,chatId:e.chat_id,platform:e.platform,name:e.name,skillName:e.skill_name,skillParams:t,condition:s,intervalMinutes:e.interval_minutes,cooldownMinutes:e.cooldown_minutes,enabled:e.enabled===1,lastCheckedAt:e.last_checked_at??null,lastTriggeredAt:e.last_triggered_at??null,lastValue:e.last_value??null,createdAt:e.created_at,messageTemplate:e.message_template}}}});var No=_(()=>{"use strict";Ua();ja();Ba();Ha();qa();tn();Lo();za();Wa();Ga();Va();Ka();Xa();Ja();Za();Qa()});function Ge(l){if(Mo[l])return Mo[l];let e=Object.entries(Mo).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var Mo,gm,Ae,yt=_(()=>{"use strict";Mo={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-opus-4-5-20251101":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-sonnet-4-5-20250929":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-3-5-sonnet-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-sonnet-20240620":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-5-haiku-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-haiku-4-5-20251001":{maxInputTokens:2e5,maxOutputTokens:8192},"claude-3-opus-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-sonnet-20240229":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-3-haiku-20240307":{maxInputTokens:2e5,maxOutputTokens:4096},"claude-":{maxInputTokens:2e5,maxOutputTokens:16e3},"gpt-4.1":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-mini":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4.1-nano":{maxInputTokens:1047576,maxOutputTokens:32768},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o3:{maxInputTokens:2e5,maxOutputTokens:1e5},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"o4-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"gpt-5.4":{maxInputTokens:105e4,maxOutputTokens:128e3},"gpt-5":{maxInputTokens:4e5,maxOutputTokens:128e3},"gemini-3.1-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3.1-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-3-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-pro":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.5-flash":{maxInputTokens:1048576,maxOutputTokens:65536},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"mistral-large":{maxInputTokens:262144,maxOutputTokens:262144},"mistral-medium":{maxInputTokens:128e3,maxOutputTokens:128e3},"mistral-small":{maxInputTokens:128e3,maxOutputTokens:128e3},codestral:{maxInputTokens:262144,maxOutputTokens:262144},"magistral-medium":{maxInputTokens:128e3,maxOutputTokens:131072},"magistral-small":{maxInputTokens:128e3,maxOutputTokens:131072},ministral:{maxInputTokens:128e3,maxOutputTokens:128e3},llama4:{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},gemma3:{maxInputTokens:128e3,maxOutputTokens:8192},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},qwen3:{maxInputTokens:128e3,maxOutputTokens:8192},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},phi4:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-v3":{maxInputTokens:128e3,maxOutputTokens:8192},"deepseek-chat":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"command-r-plus":{maxInputTokens:128e3,maxOutputTokens:4096}},gm={maxInputTokens:128e3,maxOutputTokens:8192};u(Ge,"lookupContextWindow");Ae=class{static{u(this,"LLMProvider")}config;contextWindow=gm;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import ym from"@anthropic-ai/sdk";var Vs,Oo=_(()=>{"use strict";yt();Vs=class extends Ae{static{u(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new ym({apiKey:this.config.apiKey,maxRetries:5});let e=Ge(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,system:e.system?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,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?[{type:"text",text:e.system,cache_control:{type:"ephemeral"}}]:void 0,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){let t=e.map(s=>({name:s.name,description:s.description,input_schema:s.inputSchema}));return t.length>0&&(t[t.length-1].cache_control={type:"ephemeral"}),t}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,cacheCreationTokens:e.usage.cache_creation_input_tokens??0,cacheReadTokens:e.usage.cache_read_input_tokens??0},stopReason:e.stop_reason}}}});import wm from"openai";var De,Nt=_(()=>{"use strict";yt();De=class extends Ae{static{u(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new wm({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,maxRetries:5});let e=Ge(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,...this.tokenLimitParam(e.maxTokens),temperature:this.safeTemperature(e.temperature),messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",c=[],d=null,m=0,p=0;for await(let g of r){let f=g.choices[0];if(!f)continue;let h=f.delta;if(h?.content&&(a+=h.content,yield{type:"text_delta",text:h.content}),h?.tool_calls)for(let y of h.tool_calls)if(y.id){if(n){let E;try{E=JSON.parse(i||"{}")}catch{E={}}c.push({id:n,name:o,input:E})}n=y.id,o=y.function?.name,i=y.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else y.function?.arguments&&(i+=y.function.arguments,yield{type:"tool_use_delta",toolCall:{input:y.function.arguments}});f.finish_reason&&(d=f.finish_reason),g.usage&&(m=g.usage.prompt_tokens,p=g.usage.completion_tokens)}if(n){let g;try{g=JSON.parse(i||"{}")}catch{g={}}c.push({id:n,name:o,input:g})}yield{type:"message_complete",response:{content:a,toolCalls:c.length>0?c:void 0,usage:{inputTokens:m,outputTokens:p},stopReason:this.mapStopReason(d)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}isReasoningModel(){return/^(o[1-9]|gpt-5($|[.-][01]))/.test(this.config.model)}tokenLimitParam(e){let t=e??this.config.maxTokens??4096;return/^(gpt-5|o[1-9])/.test(this.config.model)?{max_completion_tokens:t}:{max_tokens:t}}safeTemperature(e){if(!this.isReasoningModel())return e??this.config.temperature}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(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 Ks,Po=_(()=>{"use strict";Nt();Ks=class extends De{static{u(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var Xs,Uo=_(()=>{"use strict";yt();Xs=class extends Ae{static{u(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=Ge(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let g=await n.text();throw new Error(`Ollama API error (${n.status}): ${g}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",d=0,m=0,p=[];try{for(;;){let{done:g,value:f}=await o.read();if(g)break;a+=i.decode(f,{stream:!0});let h=a.split(`
|
|
372
|
+
`);a=h.pop()??"";for(let y of h){let E=y.trim();if(!E)continue;let A;try{A=JSON.parse(E)}catch{continue}if(A.message?.content&&(c+=A.message.content,yield{type:"text_delta",text:A.message.content}),A.message?.tool_calls)for(let R of A.message.tool_calls){let F={id:`ollama_tool_${p.length}`,name:R.function.name,input:R.function.arguments};p.push(F),yield{type:"tool_use_start",toolCall:{id:F.id,name:F.name}},yield{type:"tool_use_delta",toolCall:{input:F.input}}}A.done&&(d=A.prompt_eval_count??0,m=A.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let g;try{g=JSON.parse(a.trim())}catch{return}if(g.message?.content&&(c+=g.message.content,yield{type:"text_delta",text:g.message.content}),g.message?.tool_calls)for(let f of g.message.tool_calls){let h={id:`ollama_tool_${p.length}`,name:f.function.name,input:f.function.arguments};p.push(h),yield{type:"tool_use_start",toolCall:{id:h.id,name:h.name}},yield{type:"tool_use_delta",toolCall:{input:h.input}}}g.done&&(d=g.prompt_eval_count??0,m=g.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:p.length>0?p:void 0,usage:{inputTokens:d,outputTokens:m},stopReason:p.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
|
|
373
373
|
`)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var Ys,Fo=_(()=>{"use strict";Nt();Ys=class extends De{static{u(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});import{GoogleGenAI as Tm}from"@google/genai";var Js,jo=_(()=>{"use strict";yt();Js=class extends Ae{static{u(this,"GoogleProvider")}client;rawContentCache=new Map;constructor(e){super(e)}async initialize(){this.client=new Tm({apiKey:this.config.apiKey});let e=Ge(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContent({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}});return this.cacheRawContent(r),this.mapResponse(r)}async*stream(e){let t=this.mapContents(e.messages),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.models.generateContentStream({model:this.config.model,contents:t,config:{systemInstruction:e.system,...s?{tools:[{functionDeclarations:s}]}:{},temperature:e.temperature??this.config.temperature,maxOutputTokens:e.maxTokens??this.config.maxTokens??4096}}),n="",o=[],i=0,a=0,c;for await(let d of r){c=d;let m=d.text;if(m&&(n+=m,yield{type:"text_delta",text:m}),d.functionCalls)for(let p of d.functionCalls){let g={id:p.id??`google_tool_${o.length}`,name:p.name,input:p.args??{}};o.push(g),yield{type:"tool_use_start",toolCall:{id:g.id,name:g.name}}}d.usageMetadata&&(i=d.usageMetadata.promptTokenCount??0,a=d.usageMetadata.candidatesTokenCount??0)}c&&this.cacheRawContent(c),yield{type:"message_complete",response:{content:n,toolCalls:o.length>0?o:void 0,usage:{inputTokens:i,outputTokens:a},stopReason:o.length>0?"tool_use":"end_turn"}}}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}cacheRawContent(e){let t=e.candidates?.[0]?.content;if(!t?.parts)return;let s=t.parts.filter(n=>n.functionCall);if(s.length===0)return;let r=this.buildCacheKey(s);if(this.rawContentCache.set(r,t),this.rawContentCache.size>20){let n=this.rawContentCache.keys().next().value;n&&this.rawContentCache.delete(n)}}buildCacheKey(e){return e.map(t=>`${t.functionCall.id??""}:${t.functionCall.name}`).sort().join("|")}buildCacheKeyFromBlocks(e){return e.map(t=>`${t.id}:${t.name}`).sort().join("|")}mapContents(e){let t=new Map;for(let r of e)if(!(r.role!=="assistant"||typeof r.content=="string"))for(let n of r.content)n.type==="tool_use"&&t.set(n.id,n.name);let s=[];for(let r of e){let n=r.role==="assistant"?"model":"user";if(typeof r.content=="string"){s.push({role:n,parts:[{text:r.content}]});continue}let o=[],i=[],a=[];for(let c of r.content)switch(c.type){case"text":i.push({text:c.text});break;case"image":i.push({inlineData:{mimeType:c.source.media_type,data:c.source.data}});break;case"tool_use":o.push({id:c.id,name:c.name,input:c.input});break;case"tool_result":{let d=t.get(c.tool_use_id)??c.tool_use_id,m;try{let p=JSON.parse(c.content);m=typeof p=="object"&&p!==null?p:{result:p}}catch{m={result:c.content}}a.push({functionResponse:{id:c.tool_use_id,name:d,response:m}});break}}if(r.role==="assistant"&&o.length>0){let c=this.buildCacheKeyFromBlocks(o),d=this.rawContentCache.get(c);if(d)s.push(d);else{let m=[...i];for(let p=0;p<o.length;p++){let g=o[p];m.push({functionCall:{id:g.id,name:g.name,args:g.input},...p===0?{thoughtSignature:"skip_thought_signature_validator"}:{}})}s.push({role:"model",parts:m})}}else i.length>0&&s.push({role:n,parts:i});a.length>0&&s.push({role:"user",parts:a})}return this.sanitizeContents(s)}sanitizeContents(e){let t=new Set,s=[];for(let i of e)if(i.role==="model"){for(let a of i.parts??[])if(a.functionCall){let c=a.functionCall.id??a.functionCall.name??"";c&&t.add(c)}s.push(i)}else{let a=(i.parts??[]).filter(c=>{if(c.functionResponse){let d=c.functionResponse.id??c.functionResponse.name??"";return d?t.has(d):!1}return!0});a.length>0&&s.push({role:i.role,parts:a})}let r=new Set;for(let i of s)if(i.role!=="model"){for(let a of i.parts??[])if(a.functionResponse){let c=a.functionResponse.id??a.functionResponse.name??"";c&&r.add(c)}}let n=[];for(let i of s)if(i.role==="model"){let a=(i.parts??[]).filter(c=>{if(c.functionCall){let d=c.functionCall.id??c.functionCall.name??"";return d?r.has(d):!1}return!0});a.length>0&&n.push({role:i.role,parts:a})}else n.push(i);if(n.length<=1)return n;let o=[n[0]];for(let i=1;i<n.length;i++){let a=o[o.length-1],c=n[i];a.role===c.role?a.parts=[...a.parts??[],...c.parts??[]]:o.push(c)}return o}mapTools(e){return e.map(t=>({name:t.name,description:t.description,parameters:t.inputSchema}))}mapResponse(e){let t=e.text??"",r=e.functionCalls?.map((n,o)=>({id:n.id??`google_tool_${o}`,name:n.name,input:n.args??{}}));return{content:t,toolCalls:r&&r.length>0?r:void 0,usage:{inputTokens:e.usageMetadata?.promptTokenCount??0,outputTokens:e.usageMetadata?.candidatesTokenCount??0},stopReason:r&&r.length>0?"tool_use":"end_turn"}}}});var Zs,Bo=_(()=>{"use strict";Nt();Zs=class extends De{static{u(this,"MistralProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://api.mistral.ai/v1/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});function Ho(l){switch(l.provider){case"anthropic":return new Vs(l);case"openai":return new De(l);case"openrouter":return new Ks(l);case"ollama":return new Xs(l);case"openwebui":return new Ys(l);case"google":return new Js(l);case"mistral":return new Zs(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var qo=_(()=>{"use strict";Oo();Nt();Po();Uo();Fo();jo();Bo();u(Ho,"createLLMProvider")});function zo(l,e){return new sn(l,e)}var _m,sn,ec=_(()=>{"use strict";yt();qo();_m=["default","strong","fast","embeddings","local"],sn=class extends Ae{static{u(this,"ModelRouter")}providers=new Map;multiConfig;logger;constructor(e,t){super(e.default),this.multiConfig=e,this.logger=t}async initialize(){for(let e of _m){let t=this.multiConfig[e];if(t){let s=Ho(t);await s.initialize(),this.providers.set(e,s),this.logger?.info({tier:e,provider:t.provider,model:t.model},"LLM tier initialized")}}}resolve(e){return e&&this.providers.has(e)?{provider:this.providers.get(e),resolvedTier:e}:{provider:this.providers.get("default"),resolvedTier:"default"}}async complete(e){let{provider:t,resolvedTier:s}=this.resolve(e.tier),r=this.multiConfig[s];this.logger?.debug({requestedTier:e.tier??"default",resolvedTier:s,model:r?.model},"LLM routing request");let n=await t.complete(e);return this.logger?.info({tier:s,model:r?.model,inputTokens:n.usage?.inputTokens,outputTokens:n.usage?.outputTokens},"LLM call completed"),n}async*stream(e){let{provider:t}=this.resolve(e.tier);yield*t.stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve().provider).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve().provider).supportsEmbeddings()}isAvailable(){return this.resolve().provider.isAvailable()}getContextWindow(){return this.resolve().provider.getContextWindow()}};u(zo,"createModelRouter")});function Le(l){return Math.ceil(l.length/3.5)}function er(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 Qs,tc=_(()=>{"use strict";u(Le,"estimateTokens");u(er,"estimateMessageTokens");Qs=class{static{u(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
|
|
374
374
|
|
|
375
375
|
## Core principles
|
|
@@ -400,42 +400,42 @@ For complex tasks, work through multiple steps:
|
|
|
400
400
|
- Home: ${i}
|
|
401
401
|
- Documents: ${i}/Documents
|
|
402
402
|
- Desktop: ${i}/Desktop
|
|
403
|
-
- Downloads: ${i}/Downloads
|
|
404
|
-
|
|
405
|
-
## Current date & time`,a+=`
|
|
406
|
-
- Timezone: ${d}`,a+=`
|
|
407
|
-
- Date: ${g} (${f})`,a+=`
|
|
408
|
-
- Time: ${p}`,r?.timezone&&r.timezone!==c&&(a+=`
|
|
409
|
-
- Server timezone: ${c}`),s&&s.length>0){a+=`
|
|
403
|
+
- Downloads: ${i}/Downloads`;if(s&&s.length>0){a+=`
|
|
410
404
|
|
|
411
405
|
## Available tools
|
|
412
406
|
`;for(let h of s)a+=`- **${h.name}** (${h.riskLevel}): ${h.description}
|
|
413
|
-
`;s.some(h=>h.name==="code_sandbox")&&(a+="\n## File generation (PDF, HTML, images, etc.)\nTo generate and send a file to the user:\n1. Use `code_sandbox` to run code that creates the file (e.g. pdfkit for PDF, HTML generation, etc.)\n2. The sandbox **automatically collects all files** written to the working directory and sends them as attachments to the user.\n3. Do NOT use `file send` afterwards \u2014 the files are already delivered. Using `file send` on sandbox-generated files will fail because the sandbox runs in an isolated temp directory.\n"),s.some(h=>h.name==="code_agent")&&(a+='\n## Code agent delegation\nWhen the user asks you to **write code, edit files, fix bugs, refactor, implement features, or perform any coding task in a repository**, delegate to the `code_agent` tool. You are an orchestrator, not a coder.\n\n- For **single, focused tasks**: use `code_agent` with `action: "run"` and pick the best agent.\n- For **complex, multi-step tasks**: use `code_agent` with `action: "orchestrate"` \u2014 the system will decompose the task, run agents in parallel, and validate results.\n- Add `git: true` when the user wants the changes committed, pushed, and a PR/MR created.\n- Use `action: "list_agents"` if you\'re unsure which agents are available.\n\n**Do NOT delegate to code_agent** when the task requires your own data or tools (documents, memories, emails, todos, calendar, etc.). For these tasks, use your tools directly \u2014 the code agent has no access to your skills or data.\n\n## Data-to-file workflow\nWhen the user asks to **collect data and produce a file** (e.g. "list all invoices in an Excel"):\n1. **Gather data** using your own tools first (document search/summarize, file list, email, etc.)\n2. **Generate the file** using `code_sandbox` \u2014 pass the collected data as variables in the code, then write the output file (Excel via exceljs, PDF via pdfkit, CSV, etc.)\n3. Do NOT try to do both steps inside code_sandbox \u2014 it cannot access your documents or skills.'),s.some(h=>h.name==="watch")&&s.some(h=>h.name==="scheduled_task")&&(a+='\n## Automation: watch vs. scheduled_task\n- **"Alert me when X happens"** \u2192 use `watch` (polls a skill, evaluates condition, no LLM cost per check)\n- **"Do X every day at 9 AM"** / **"Check X and report"** \u2192 use `scheduled_task` (time-based, can use LLM via prompt_template)\n- For infrastructure monitoring on a schedule, use `scheduled_task` with `prompt_template` that instructs you to run the `monitor` tool and report only problems.'),s.some(h=>h.name==="background_task")&&s.some(h=>h.name==="delegate")&&(a+='\n## background_task vs. delegate\n- **`background_task`**: Runs a **single skill call** asynchronously (e.g. schedule one email send, one file download). It does NOT support multi-step workflows.\n- **`delegate`**: Runs a **multi-step sub-agent** with full tool access. Use for any task that requires multiple tool calls (search \u2192 read \u2192 process \u2192 generate).\n- **NEVER use `background_task` for complex tasks** like "search emails and create a report" \u2014 use `delegate` instead.')}
|
|
407
|
+
`;s.some(h=>h.name==="code_sandbox")&&(a+="\n## File generation (PDF, HTML, images, etc.)\nTo generate and send a file to the user:\n1. Use `code_sandbox` to run code that creates the file (e.g. pdfkit for PDF, HTML generation, etc.)\n2. The sandbox **automatically collects all files** written to the working directory and sends them as attachments to the user.\n3. Do NOT use `file send` afterwards \u2014 the files are already delivered. Using `file send` on sandbox-generated files will fail because the sandbox runs in an isolated temp directory.\n"),s.some(h=>h.name==="code_agent")&&(a+='\n## Code agent delegation\nWhen the user asks you to **write code, edit files, fix bugs, refactor, implement features, or perform any coding task in a repository**, delegate to the `code_agent` tool. You are an orchestrator, not a coder.\n\n- For **single, focused tasks**: use `code_agent` with `action: "run"` and pick the best agent.\n- For **complex, multi-step tasks**: use `code_agent` with `action: "orchestrate"` \u2014 the system will decompose the task, run agents in parallel, and validate results.\n- Add `git: true` when the user wants the changes committed, pushed, and a PR/MR created.\n- Use `action: "list_agents"` if you\'re unsure which agents are available.\n\n**Do NOT delegate to code_agent** when the task requires your own data or tools (documents, memories, emails, todos, calendar, etc.). For these tasks, use your tools directly \u2014 the code agent has no access to your skills or data.\n\n## Data-to-file workflow\nWhen the user asks to **collect data and produce a file** (e.g. "list all invoices in an Excel"):\n1. **Gather data** using your own tools first (document search/summarize, file list, email, etc.)\n2. **Generate the file** using `code_sandbox` \u2014 pass the collected data as variables in the code, then write the output file (Excel via exceljs, PDF via pdfkit, CSV, etc.)\n3. Do NOT try to do both steps inside code_sandbox \u2014 it cannot access your documents or skills.'),s.some(h=>h.name==="watch")&&s.some(h=>h.name==="scheduled_task")&&(a+='\n## Automation: watch vs. scheduled_task\n- **"Alert me when X happens"** \u2192 use `watch` (polls a skill, evaluates condition, no LLM cost per check)\n- **"Do X every day at 9 AM"** / **"Check X and report"** \u2192 use `scheduled_task` (time-based, can use LLM via prompt_template)\n- For infrastructure monitoring on a schedule, use `scheduled_task` with `prompt_template` that instructs you to run the `monitor` tool and report only problems.'),s.some(h=>h.name==="background_task")&&s.some(h=>h.name==="delegate")&&(a+='\n## background_task vs. delegate\n- **`background_task`**: Runs a **single skill call** asynchronously (e.g. schedule one email send, one file download). It does NOT support multi-step workflows.\n- **`delegate`**: Runs a **multi-step sub-agent** with full tool access. Use for any task that requires multiple tool calls (search \u2192 read \u2192 process \u2192 generate).\n- **NEVER use `background_task` for complex tasks** like "search emails and create a report" \u2014 use `delegate` instead.')}r&&(a+=`
|
|
414
408
|
|
|
415
409
|
## User profile`,r.displayName&&(a+=`
|
|
416
410
|
- Name: ${r.displayName}`),r.timezone&&(a+=`
|
|
417
411
|
- Timezone: ${r.timezone}`),r.language&&(a+=`
|
|
418
412
|
- Language: ${r.language}`),r.bio&&(a+=`
|
|
419
|
-
- Bio: ${r.bio}`)),
|
|
413
|
+
- Bio: ${r.bio}`));let c=Intl.DateTimeFormat().resolvedOptions().timeZone,d=r?.timezone||c,m=new Date,p=m.toLocaleTimeString("en-GB",{timeZone:d,hour:"2-digit",minute:"2-digit"}),g=m.toLocaleDateString("en-CA",{timeZone:d}),f=m.toLocaleDateString("en-US",{timeZone:d,weekday:"long"});if(a+=`
|
|
414
|
+
|
|
415
|
+
## Current date & time`,a+=`
|
|
416
|
+
- Timezone: ${d}`,a+=`
|
|
417
|
+
- Date: ${g} (${f})`,a+=`
|
|
418
|
+
- Time: ${p}`,r?.timezone&&r.timezone!==c&&(a+=`
|
|
419
|
+
- Server timezone: ${c}`),n&&n.length>0){a+=`
|
|
420
420
|
|
|
421
|
-
## Today's events`;for(let h of n){let
|
|
422
|
-
- ${
|
|
421
|
+
## Today's events`;for(let h of n){let y=h.allDay?"All day":h.start.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}}),E=h.allDay?"":`-${h.end.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...r?.timezone?{timeZone:r.timezone}:{}})}`,A=h.location?` @ ${h.location}`:"";a+=`
|
|
422
|
+
- ${y}${E}: ${h.title}${A}`}}if(t&&t.length>0){if(a+=`
|
|
423
423
|
|
|
424
424
|
## Memories about this user
|
|
425
|
-
`,t.some(
|
|
425
|
+
`,t.some(y=>y.type&&y.type!=="general")){let y=new Map;for(let A of t){let R=A.type||"general",F=y.get(R);F||(F=[],y.set(R,F)),F.push(A)}let E={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[A,R]of y){a+=`
|
|
426
426
|
### ${E[A]||A}
|
|
427
427
|
`;for(let F of R)a+=`- ${F.key}: ${F.value}
|
|
428
|
-
`}}else for(let
|
|
428
|
+
`}}else for(let y of t)a+=`- [${y.category}] ${y.key}: ${y.value}
|
|
429
429
|
`;a+=`
|
|
430
430
|
Use these memories to personalize your responses. When the user tells you new facts or preferences, use the memory tool to save them.`}else a+=`
|
|
431
431
|
|
|
432
|
-
When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let 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(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);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 d=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:[...d,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Wo=_(()=>{"use strict";yt();Oo();Nt();Po();Uo();Fo();jo();Bo();qo();ec();tc()});var tr,Go=_(()=>{"use strict";tr=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var sr,sc=_(()=>{"use strict";Go();sr=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new tr;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 rc,nc,oc,wt,ic=_(()=>{"use strict";rc=["allow","deny"],nc=["global","user","conversation","platform"],oc=["read","write","destructive","admin"],wt=class{static{u(this,"RuleLoader")}loadFromObject(e){if(!e||!Array.isArray(e.rules))throw new Error('Invalid data: expected an object with a "rules" array');return e.rules.map((t,s)=>this.validateRule(t,s))}validateRule(e,t){if(typeof e!="object"||e===null)throw new Error(`Rule at index ${t} is not an object`);let s=e;if(typeof s.id!="string"||s.id.length===0)throw new Error(`Rule at index ${t} is missing a valid "id" string`);if(typeof s.effect!="string"||!rc.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${rc.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"||!nc.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${nc.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(!oc.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${oc.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 bm from"node:crypto";var rr,ac=_(()=>{"use strict";rr=class{static{u(this,"SecurityManager")}ruleEngine;auditRepository;logger;constructor(e,t,s){this.ruleEngine=e,this.auditRepository=t,this.logger=s}evaluate(e){let t=this.ruleEngine.evaluate(e),s={id:bm.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 rn=_(()=>{"use strict";sc();Go();ic();ac()});var I,P=_(()=>{"use strict";I=class{static{u(this,"Skill")}}});function ie(l){return l.masterUserId??l.userId}function W(l){let e=new Set;if(e.add(ie(l)),e.add(l.userId),l.linkedPlatformUserIds)for(let t of l.linkedPlatformUserIds)e.add(t);return[...e]}var Ne=_(()=>{"use strict";u(ie,"effectiveUserId");u(W,"allUserIds")});var Mt,cc=_(()=>{"use strict";Mt=class{static{u(this,"SkillRegistry")}skills=new Map;register(e){let{name:t}=e.metadata;if(this.skills.has(t))throw new Error(`Skill "${t}" is already registered`);this.skills.set(t,e)}get(e){return this.skills.get(e)}getAll(){return[...this.skills.values()]}has(e){return this.skills.has(e)}unregister(e){return this.skills.delete(e)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Ot,lc=_(()=>{"use strict";Ot=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,c,d,m,p=u(()=>{c&&clearInterval(c),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),g=u(f=>{a||(a=!0,p(),i(f))},"finish");e.execute(t,s).then(f=>{this.logger.info({skill:r,success:f.success,...f.success?{}:{error:f.error}},"Skill execution completed"),g(f)},f=>{let h=f instanceof Error?f.message:String(f);this.logger.error({skill:r,error:h},"Skill execution failed"),g({success:!1,error:h})}),m=setTimeout(()=>{if(a)return;let f=o.getIdleMs();if(f>=12e4){let T=o.getSnapshot();this.logger.warn({skill:r,idleMs:f,state:T.state,iteration:T.iteration},"Agent inactive after initial timeout \u2014 aborting"),g({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(f/1e3)}s (last state: ${T.state})`});return}let h=o.getSnapshot();this.logger.info({skill:r,idleMs:f,state:h.state,iteration:h.iteration,totalMs:h.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),c=setInterval(()=>{if(a){p();return}let T=o.getIdleMs(),E=o.getSnapshot();T>=12e4?(this.logger.warn({skill:r,idleMs:T,state:E.state,iteration:E.iteration,totalMs:E.totalElapsedMs},"Agent went inactive \u2014 aborting"),g({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(T/1e3)}s (last state: ${E.state})`})):this.logger.debug({skill:r,idleMs:T,state:E.state,iteration:E.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let f=o.getSnapshot();this.logger.error({skill:r,totalMs:f.totalElapsedMs,state:f.state,iteration:f.iteration},"Absolute time limit reached \u2014 force killing agent"),g({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success,...o.success?{}:{error:o.error}},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var Tt,Vo=_(()=>{"use strict";Tt=class{static{u(this,"ActivityTracker")}state="starting";iteration=0;maxIterations=0;currentTool;lastPingAt;startedAt;history=[];onProgress;constructor(e){this.startedAt=Date.now(),this.lastPingAt=Date.now(),this.onProgress=e}ping(e,t){this.state=e,this.lastPingAt=Date.now(),t?.iteration!==void 0&&(this.iteration=t.iteration),t?.maxIterations!==void 0&&(this.maxIterations=t.maxIterations),this.currentTool=t?.tool,this.history.push({state:e,tool:t?.tool,iteration:this.iteration,timestamp:this.lastPingAt}),this.onProgress&&this.onProgress(this.formatStatus())}getIdleMs(){return Date.now()-this.lastPingAt}getTotalElapsedMs(){return Date.now()-this.startedAt}formatStatus(){let e=this.maxIterations>0?` (${this.iteration}/${this.maxIterations})`:"";switch(this.state){case"starting":return"Sub-agent starting...";case"llm_call":return`Sub-agent thinking...${e}`;case"tool_call":return this.currentTool?`Sub-agent using ${this.currentTool}${e}`:`Sub-agent using tool...${e}`;case"processing":return`Sub-agent processing...${e}`;case"done":return`Sub-agent done${e}`;default:return`Sub-agent working...${e}`}}getSnapshot(){return{state:this.state,iteration:this.iteration,maxIterations:this.maxIterations,lastPingAt:this.lastPingAt,idleMs:this.getIdleMs(),currentTool:this.currentTool,totalElapsedMs:this.getTotalElapsedMs(),history:[...this.history]}}}});import Em from"node:fs";import Ko from"node:path";var nn,dc=_(()=>{"use strict";P();nn=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Ko.resolve(e),s;try{s=await Em.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=Ko.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=Ko.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var $m,km,Pt,uc=_(()=>{"use strict";P();$m=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,km=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Pt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!km.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace($m,"");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 Ut,mc=_(()=>{"use strict";P();Ut=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var Ft,pc=_(()=>{"use strict";P();Ft=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,c)=>`${c+1}. **${a.title}**
|
|
432
|
+
When the user tells you facts about themselves or preferences, use the memory tool to save them for future reference.`;return a}buildMessages(e){let t=e.filter(s=>s.role==="user"||s.role==="assistant").map(s=>{if(s.toolCalls){let r;try{r=JSON.parse(s.toolCalls)}catch{r=[]}if(s.role==="assistant"){let i=r,a=[];s.content&&a.push({type:"text",text:s.content});for(let 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(d=>d.type==="tool_use"?!s.has(d.id)||r.has(d.id)?!1:(r.add(d.id),!0):d.type==="tool_result"?!s.has(d.tool_use_id)||n.has(d.tool_use_id)?!1:(n.add(d.tool_use_id),!0):!0);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 d=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:[...d,...m]}}else i.push(a)}return i}buildTools(e){return e.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema}))}}});var Wo=_(()=>{"use strict";yt();Oo();Nt();Po();Uo();Fo();jo();Bo();qo();ec();tc()});var tr,Go=_(()=>{"use strict";tr=class{static{u(this,"RateLimiter")}buckets=new Map;checkCount=0;check(e,t){this.checkCount++,this.checkCount%100===0&&this.cleanup();let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);if(!n)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};if(s>n.windowStart+r)return{allowed:!0,remaining:t.maxInvocations,resetsAt:s+r};let o=Math.max(0,t.maxInvocations-n.count);return{allowed:n.count<t.maxInvocations,remaining:o,resetsAt:n.windowStart+r}}increment(e,t){let s=Date.now(),r=t.windowSeconds*1e3,n=this.buckets.get(e);!n||s>n.windowStart+r?this.buckets.set(e,{count:1,windowStart:s}):n.count+=1}cleanup(){let e=Date.now();for(let[t,s]of this.buckets)e>s.windowStart+36e5&&this.buckets.delete(t)}reset(){this.buckets.clear()}}});var sr,sc=_(()=>{"use strict";Go();sr=class{static{u(this,"RuleEngine")}rules=[];rateLimiter=new tr;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 rc,nc,oc,wt,ic=_(()=>{"use strict";rc=["allow","deny"],nc=["global","user","conversation","platform"],oc=["read","write","destructive","admin"],wt=class{static{u(this,"RuleLoader")}loadFromObject(e){if(!e||!Array.isArray(e.rules))throw new Error('Invalid data: expected an object with a "rules" array');return e.rules.map((t,s)=>this.validateRule(t,s))}validateRule(e,t){if(typeof e!="object"||e===null)throw new Error(`Rule at index ${t} is not an object`);let s=e;if(typeof s.id!="string"||s.id.length===0)throw new Error(`Rule at index ${t} is missing a valid "id" string`);if(typeof s.effect!="string"||!rc.includes(s.effect))throw new Error(`Rule "${s.id}" has invalid "effect": expected one of ${rc.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"||!nc.includes(s.scope))throw new Error(`Rule "${s.id}" has invalid "scope": expected one of ${nc.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(!oc.includes(n))throw new Error(`Rule "${s.id}" has invalid risk level "${n}": expected one of ${oc.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 bm from"node:crypto";var rr,ac=_(()=>{"use strict";rr=class{static{u(this,"SecurityManager")}ruleEngine;auditRepository;logger;constructor(e,t,s){this.ruleEngine=e,this.auditRepository=t,this.logger=s}evaluate(e){let t=this.ruleEngine.evaluate(e),s={id:bm.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 rn=_(()=>{"use strict";sc();Go();ic();ac()});var I,P=_(()=>{"use strict";I=class{static{u(this,"Skill")}}});function ie(l){return l.masterUserId??l.userId}function W(l){let e=new Set;if(e.add(ie(l)),e.add(l.userId),l.linkedPlatformUserIds)for(let t of l.linkedPlatformUserIds)e.add(t);return[...e]}var Ne=_(()=>{"use strict";u(ie,"effectiveUserId");u(W,"allUserIds")});var Mt,cc=_(()=>{"use strict";Mt=class{static{u(this,"SkillRegistry")}skills=new Map;register(e){let{name:t}=e.metadata;if(this.skills.has(t))throw new Error(`Skill "${t}" is already registered`);this.skills.set(t,e)}get(e){return this.skills.get(e)}getAll(){return[...this.skills.values()]}has(e){return this.skills.has(e)}unregister(e){return this.skills.delete(e)}toToolDefinitions(){return this.getAll().map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema}))}}});var Ot,lc=_(()=>{"use strict";Ot=class{static{u(this,"SkillSandbox")}logger;constructor(e){this.logger=e}async execute(e,t,s,r,n){r=r??e.metadata.timeoutMs??3e4;let{name:o}=e.metadata;return this.logger.info({skill:o,input:t},"Skill execution started"),n?this.executeWithTracker(e,t,s,o,r,n):this.executeWithHardTimeout(e,t,s,o,r)}async executeWithTracker(e,t,s,r,n,o){return new Promise(i=>{let a=!1,c,d,m,p=u(()=>{c&&clearInterval(c),d&&clearTimeout(d),m&&clearTimeout(m)},"cleanup"),g=u(f=>{a||(a=!0,p(),i(f))},"finish");e.execute(t,s).then(f=>{this.logger.info({skill:r,success:f.success,...f.success?{}:{error:f.error}},"Skill execution completed"),g(f)},f=>{let h=f instanceof Error?f.message:String(f);this.logger.error({skill:r,error:h},"Skill execution failed"),g({success:!1,error:h})}),m=setTimeout(()=>{if(a)return;let f=o.getIdleMs();if(f>=12e4){let y=o.getSnapshot();this.logger.warn({skill:r,idleMs:f,state:y.state,iteration:y.iteration},"Agent inactive after initial timeout \u2014 aborting"),g({success:!1,error:`Skill "${r}" timed out \u2014 inactive for ${Math.round(f/1e3)}s (last state: ${y.state})`});return}let h=o.getSnapshot();this.logger.info({skill:r,idleMs:f,state:h.state,iteration:h.iteration,totalMs:h.totalElapsedMs},"Initial timeout reached but agent is active \u2014 extending"),c=setInterval(()=>{if(a){p();return}let y=o.getIdleMs(),E=o.getSnapshot();y>=12e4?(this.logger.warn({skill:r,idleMs:y,state:E.state,iteration:E.iteration,totalMs:E.totalElapsedMs},"Agent went inactive \u2014 aborting"),g({success:!1,error:`Skill "${r}" killed \u2014 inactive for ${Math.round(y/1e3)}s (last state: ${E.state})`})):this.logger.debug({skill:r,idleMs:y,state:E.state,iteration:E.iteration},"Agent still active, continuing...")},1e4)},n),d=setTimeout(()=>{if(a)return;let f=o.getSnapshot();this.logger.error({skill:r,totalMs:f.totalElapsedMs,state:f.state,iteration:f.iteration},"Absolute time limit reached \u2014 force killing agent"),g({success:!1,error:`Skill "${r}" force-killed after ${Math.round(12e5/6e4)} minutes (safety limit)`})},12e5)})}async executeWithHardTimeout(e,t,s,r,n){try{let o=await Promise.race([e.execute(t,s),new Promise((i,a)=>{setTimeout(()=>a(new Error(`Skill "${r}" timed out after ${n}ms`)),n)})]);return this.logger.info({skill:r,success:o.success,...o.success?{}:{error:o.error}},"Skill execution completed"),o}catch(o){let i=o instanceof Error?o.message:String(o);return this.logger.error({skill:r,error:i},"Skill execution failed"),{success:!1,error:i}}}}});var Tt,Vo=_(()=>{"use strict";Tt=class{static{u(this,"ActivityTracker")}state="starting";iteration=0;maxIterations=0;currentTool;lastPingAt;startedAt;history=[];onProgress;constructor(e){this.startedAt=Date.now(),this.lastPingAt=Date.now(),this.onProgress=e}ping(e,t){this.state=e,this.lastPingAt=Date.now(),t?.iteration!==void 0&&(this.iteration=t.iteration),t?.maxIterations!==void 0&&(this.maxIterations=t.maxIterations),this.currentTool=t?.tool,this.history.push({state:e,tool:t?.tool,iteration:this.iteration,timestamp:this.lastPingAt}),this.onProgress&&this.onProgress(this.formatStatus())}getIdleMs(){return Date.now()-this.lastPingAt}getTotalElapsedMs(){return Date.now()-this.startedAt}formatStatus(){let e=this.maxIterations>0?` (${this.iteration}/${this.maxIterations})`:"";switch(this.state){case"starting":return"Sub-agent starting...";case"llm_call":return`Sub-agent thinking...${e}`;case"tool_call":return this.currentTool?`Sub-agent using ${this.currentTool}${e}`:`Sub-agent using tool...${e}`;case"processing":return`Sub-agent processing...${e}`;case"done":return`Sub-agent done${e}`;default:return`Sub-agent working...${e}`}}getSnapshot(){return{state:this.state,iteration:this.iteration,maxIterations:this.maxIterations,lastPingAt:this.lastPingAt,idleMs:this.getIdleMs(),currentTool:this.currentTool,totalElapsedMs:this.getTotalElapsedMs(),history:[...this.history]}}}});import Em from"node:fs";import Ko from"node:path";var nn,dc=_(()=>{"use strict";P();nn=class{static{u(this,"PluginLoader")}async loadFromDirectory(e){let t=Ko.resolve(e),s;try{s=await Em.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=Ko.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=Ko.resolve(e),n=(await import(`file:///${t.replace(/\\/g,"/")}`)).default;if(typeof n!="function")throw new Error(`Module "${t}" does not have a default export that is a class`);let o=new n;if(!(o instanceof I))throw new Error(`Default export of "${t}" does not extend Skill`);return this.validateMetadata(o,t),o}validateMetadata(e,t){let{metadata:s}=e;if(!s)throw new Error(`Plugin "${t}" is missing metadata`);if(!s.name||typeof s.name!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.name`);if(!s.description||typeof s.description!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.description`);if(!["read","write","destructive","admin"].includes(s.riskLevel))throw new Error(`Plugin "${t}" has invalid metadata.riskLevel: "${String(s.riskLevel)}"`);if(!s.version||typeof s.version!="string")throw new Error(`Plugin "${t}" has invalid or missing metadata.version`)}}});var $m,km,Pt,uc=_(()=>{"use strict";P();$m=/Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)/g,km=/^[\d+\-*/().,\s%]*(Math\.(sin|cos|tan|sqrt|pow|abs|floor|ceil|round|log|log2|log10|PI|E)[\d+\-*/().,\s(%)]*)*$/,Pt=class extends I{static{u(this,"CalculatorSkill")}metadata={name:"calculator",category:"information",description:"Evaluate mathematical expressions. Use for any calculation, unit conversion, or math question the user asks.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{expression:{type:"string",description:"The mathematical expression to evaluate"}},required:["expression"]}};async execute(e,t){let s=e.expression;if(!s||typeof s!="string")return{success:!1,error:"Invalid expression: input must be a non-empty string"};let r=s.trim();if(!km.test(r))return{success:!1,error:`Invalid expression: "${r}" contains disallowed constructs`};let n=r.replace($m,"");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 Ut,mc=_(()=>{"use strict";P();Ut=class extends I{static{u(this,"SystemInfoSkill")}metadata={name:"system_info",category:"information",description:'Get system information: current date/time (datetime), system stats (general), memory usage (memory), or uptime (uptime). Use "datetime" when the user asks what day/time it is.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{category:{type:"string",enum:["general","memory","uptime","datetime"],description:"Category of system info (use datetime for current date/time)"}},required:["category"]}};async execute(e,t){let s=e.category;switch(s){case"general":return this.getGeneralInfo();case"memory":return this.getMemoryInfo();case"uptime":return this.getUptimeInfo();case"datetime":return this.getDateTimeInfo();default:return{success:!1,error:`Unknown category: "${String(s)}". Valid categories: general, memory, uptime`}}}getGeneralInfo(){let e={nodeVersion:process.version,platform:process.platform,arch:process.arch};return{success:!0,data:e,display:`Node.js ${e.nodeVersion} on ${e.platform} (${e.arch})`}}getMemoryInfo(){let e=process.memoryUsage(),t=u(r=>(r/1024/1024).toFixed(2),"toMB"),s={rss:`${t(e.rss)} MB`,heapTotal:`${t(e.heapTotal)} MB`,heapUsed:`${t(e.heapUsed)} MB`,external:`${t(e.external)} MB`};return{success:!0,data:s,display:`Memory \u2014 RSS: ${s.rss}, Heap: ${s.heapUsed} / ${s.heapTotal}, External: ${s.external}`}}getUptimeInfo(){let e=process.uptime(),t=Math.floor(e/3600),s=Math.floor(e%3600/60),r=Math.floor(e%60),n={uptimeSeconds:e,formatted:`${t}h ${s}m ${r}s`};return{success:!0,data:n,display:`Uptime: ${n.formatted}`}}getDateTimeInfo(){let e=new Date,t={iso:e.toISOString(),date:e.toLocaleDateString("de-DE",{weekday:"long",year:"numeric",month:"long",day:"numeric"}),time:e.toLocaleTimeString("de-DE"),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:e.getTime()};return{success:!0,data:t,display:`${t.date}, ${t.time} (${t.timezone})`}}}});var Ft,pc=_(()=>{"use strict";P();Ft=class extends I{static{u(this,"WebSearchSkill")}config;metadata={name:"web_search",category:"information",description:"Search the internet for current information, news, facts, or anything the user asks about that you don't know. Use this whenever you need up-to-date information.",riskLevel:"read",version:"1.1.0",inputSchema:{type:"object",properties:{query:{type:"string",description:"The search query"},count:{type:"number",description:"Number of results to return (default: 5, max: 10)"}},required:["query"]}};constructor(e){super(),this.config=e}async execute(e,t){let s=e.query,r=Math.min(Math.max(1,e.count||5),10);if(!s||typeof s!="string")return{success:!1,error:'Invalid input: "query" must be a non-empty string'};if(!this.config)return{success:!1,error:"Web search is not configured. Run `alfred setup` to configure a search provider."};if((this.config.provider==="brave"||this.config.provider==="tavily")&&!this.config.apiKey)return{success:!1,error:`Web search requires an API key for ${this.config.provider}. Run \`alfred setup\` to configure it.`};try{let o;switch(this.config.provider){case"brave":o=await this.searchBrave(s,r);break;case"searxng":o=await this.searchSearXNG(s,r);break;case"tavily":o=await this.searchTavily(s,r);break;case"duckduckgo":o=await this.searchDuckDuckGo(s,r);break;default:return{success:!1,error:`Unknown search provider: ${this.config.provider}`}}if(o.length===0)return{success:!0,data:{results:[]},display:`No results found for "${s}".`};let i=o.map((a,c)=>`${c+1}. **${a.title}**
|
|
433
433
|
${a.url}
|
|
434
434
|
${a.snippet}`).join(`
|
|
435
435
|
|
|
436
436
|
`);return{success:!0,data:{query:s,results:o},display:`Search results for "${s}":
|
|
437
437
|
|
|
438
|
-
${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let c=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(c);d&&m&&o.push({url:m,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let 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(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/ /g," ").replace(/\s+/g," ")}}});var jt,hc=_(()=>{"use strict";P();Ne();jt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of W(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let m=this.parseTriggerAt(r,t.timezone);if(!m)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(m.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=m}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(ie(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${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),d=parseInt(n[5],10);return c>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(c,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let g=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||g.setHours(e,t,0,0),g}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let g=i.formatToParts(n),f=parseInt(g.find(G=>G.type==="year").value,10),h=parseInt(g.find(G=>G.type==="month").value,10)-1,
|
|
438
|
+
${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let c=i[1],d=this.stripHtml(i[2]).trim(),m=this.extractDdgUrl(c);d&&m&&o.push({url:m,title:d})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let 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(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/ /g," ").replace(/\s+/g," ")}}});var jt,hc=_(()=>{"use strict";P();Ne();jt=class extends I{static{u(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",category:"productivity",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}getAllReminders(e){let t=new Set,s=[];for(let r of W(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let m=this.parseTriggerAt(r,t.timezone);if(!m)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(m.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=m}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(ie(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),d=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${d} (in ${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),d=parseInt(n[5],10);return c>23||d>59||i>11||a>31?void 0:this.buildDateInTimezone(c,d,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let g=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||g.setHours(e,t,0,0),g}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let g=i.formatToParts(n),f=parseInt(g.find(G=>G.type==="year").value,10),h=parseInt(g.find(G=>G.type==="month").value,10)-1,y=parseInt(g.find(G=>G.type==="day").value,10),E=new Date(Date.UTC(f,h,y,e,t,0)),A=i.formatToParts(E),R=parseInt(A.find(G=>G.type==="hour").value,10),F=parseInt(A.find(G=>G.type==="minute").value,10),x=(e-R)*60+(t-F);return E=new Date(E.getTime()+x*6e4),E}let a=o,c=i.formatToParts(a),d=parseInt(c.find(g=>g.type==="hour").value,10),m=parseInt(c.find(g=>g.type==="minute").value,10),p=(e-d)*60+(t-m);return a=new Date(a.getTime()+p*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
|
|
439
439
|
${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).join(`
|
|
440
440
|
`)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var Bt,fc=_(()=>{"use strict";P();Ne();Bt=class extends I{static{u(this,"NoteSkill")}noteRepo;metadata={name:"note",category:"productivity",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(ie(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of W(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
|
|
441
441
|
${n.content.slice(0,100)}${n.content.length>100?"\u2026":""}`).join(`
|
|
@@ -460,9 +460,9 @@ ${n.map(o=>`- ${o.key}: "${o.value}" (score: ${o.score.toFixed(2)})`).join(`
|
|
|
460
460
|
When tool results contain "[Data stored as result_N]", use code_sandbox with action "run_with_data" and data="result_N" to process the data. The data will be injected as INPUT_DATA (parsed array/object). Never hardcode data in code.
|
|
461
461
|
Available JS libraries in code_sandbox (no install needed): exceljs, pdfkit, pdf-parse.`,g=s;r&&typeof r=="string"&&(g=`${s}
|
|
462
462
|
|
|
463
|
-
Additional context: ${r}`);let f=[{role:"user",content:g}];try{let h=0,
|
|
463
|
+
Additional context: ${r}`);let f=[{role:"user",content:g}];try{let h=0,y=0,E=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let A=await this.llm.complete({messages:f,system:p,tools:c.length>0?c:void 0,maxTokens:8192,tier:"strong"});if(y+=A.usage.inputTokens,E+=A.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!A.toolCalls||A.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:A.content,iterations:h,usage:{inputTokens:y,outputTokens:E}},display:A.content};h++;let R=[];A.content&&R.push({type:"text",text:A.content});for(let x of A.toolCalls)R.push({type:"tool_use",id:x.id,name:x.name,input:x.input});f.push({role:"assistant",content:R});let F=[];for(let x of A.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:x.name});let G=x.input;if(x.name==="code_sandbox"&&x.input.data){let N=String(x.input.data);d.has(N)&&(G={...x.input,data:d.get(N)},G.action==="run"&&(G.action="run_with_data"))}let ce=await this.executeSubAgentTool({...x,input:G},t),se=ce.content;if(!ce.isError&&se.length>500){let N=`result_${++m}`,K=ce.rawData!=null?JSON.stringify(ce.rawData):se;d.set(N,K),se+=`
|
|
464
464
|
|
|
465
|
-
[Data stored as "${N}" \u2014 use code_sandbox action "run_with_data" with data="${N}" to process this data. Do NOT copy data into code.]`}F.push({type:"tool_result",tool_use_id:x.id,content:se,is_error:ce.isError})}f.push({role:"user",content:F})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var Ve,on=_(()=>{"use strict";Ve=class{static{u(this,"EmailProvider")}async extractFromSearch(e,t,s,r,n){throw new Error("Extract is not supported by this email provider.")}async createDraft(e){throw new Error("Draft creation is not supported by this email provider.")}async forwardMessage(e,t,s){throw new Error("Email forwarding is not supported by this email provider.")}}});var Ec={};me(Ec,{MicrosoftGraphEmailProvider:()=>an});var an,Xo=_(()=>{"use strict";on();an=class extends Ve{static{u(this,"MicrosoftGraphEmailProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){if(!this.config.refreshToken)throw new Error("Microsoft email: refreshToken is missing from config");let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Microsoft token refresh failed: ${s.status} \u2014 ${n.slice(0,300)}`)}let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let n=await s(this.accessToken);if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return this.parseJsonOrUndefined(n)}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return this.parseJsonOrUndefined(r)}async parseJsonOrUndefined(e){if(e.status===204||e.status===202)return;let t=await e.text();if(!(!t||t.length===0))return JSON.parse(t)}async graphRequestRaw(e){let t=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${n}`}}),"doFetch"),s=await t(this.accessToken);if(s.status===401&&(await this.refreshAccessToken(),s=await t(this.accessToken)),!s.ok)throw new Error(`Graph API error: ${s.status}`);let r=await s.arrayBuffer();return Buffer.from(r)}async fetchInbox(e){let t=new URLSearchParams({$top:String(Math.min(Math.max(1,e),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/inbox/messages?${t}`)).value??[]).map(r=>this.mapMessage(r))}async readMessage(e){let t=new URLSearchParams({$select:"id,from,toRecipients,ccRecipients,bccRecipients,subject,body,receivedDateTime,isRead,hasAttachments"}),s=await this.graphRequest(`/me/messages/${e}?${t}`),r=[];return s.hasAttachments&&(r=((await this.graphRequest(`/me/messages/${e}/attachments?$select=id,name,contentType,size`)).value??[]).map(o=>({id:o.id,name:o.name,contentType:o.contentType,size:o.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(n=>this.formatGraphAddress(n)),subject:s.subject??"(no subject)",date:new Date(s.receivedDateTime),read:s.isRead??!1,body:s.body?.contentType==="html"?this.stripHtml(s.body.content??""):s.body?.content??"",bodyHtml:s.body?.contentType==="html"?s.body.content:void 0,cc:s.ccRecipients?.map(n=>this.formatGraphAddress(n)),bcc:s.bccRecipients?.map(n=>this.formatGraphAddress(n)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=new URLSearchParams({$search:`"${e}"`,$top:String(s),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"}),n=await this.graphRequest(`/me/messages?${r}`),o=(n.value??[]).map(i=>this.mapMessage(i));if(t>50){let i=n["@odata.nextLink"];for(;i&&o.length<t;){let a=await this.graphRequest(i.replace("https://graph.microsoft.com/v1.0","")),c=(a.value??[]).map(d=>this.mapMessage(d));o.push(...c),i=a["@odata.nextLink"]}}return o.slice(0,t)}async extractFromSearch(e,t,s,r,n){let o=await this.searchWithDateFilter(e,t,r,n),i=s.includes("amount"),a=[];if(i)for(let d=0;d<o.length;d+=5){let m=o.slice(d,d+5),p=await Promise.allSettled(m.map(async g=>{let f={id:g.id,from:g.from,subject:g.subject,date:g.date.toISOString().split("T")[0],preview:(g.preview??"").slice(0,200)};try{let h=await this.readMessage(g.id),T=this.extractAmount(h.body);T&&(f.amount=T.amount,f.currency=T.currency)}catch{}return f}));for(let g of p)g.status==="fulfilled"&&a.push(g.value)}else for(let c of o)a.push({id:c.id,from:c.from,subject:c.subject,date:c.date.toISOString().split("T")[0],preview:(c.preview??"").slice(0,200)});return a}async searchWithDateFilter(e,t,s,r){let n=Math.min(Math.max(1,t),50),o=[];if(s||r){let p=s?this.toKqlDate(s):"01/01/2000",g=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${g}`)}e&&o.push(e.includes(" ")?`(${e})`:e);let i=o.join(" AND "),a=new URLSearchParams({$top:String(n),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});i?a.set("$search",`"${i}"`):a.set("$orderby","receivedDateTime desc");let c=await this.graphRequest(`/me/messages?${a}`),d=(c.value??[]).map(p=>this.mapMessage(p)),m=c["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),g=(p.value??[]).map(f=>this.mapMessage(f));d.push(...g),m=p["@odata.nextLink"]}return d.slice(0,t)}toKqlDate(e){let[t,s,r]=e.split("-");return`${s}/${r}/${t}`}extractAmount(e){let t=[{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*€\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*€/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*EUR\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*EUR/i,currency:"EUR"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*\$\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*USD\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*([\d.,]+)\s*USD/i,currency:"USD"},{regex:/€\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\b([\d]+[.,]\d{2})\s*€/,currency:"EUR"},{regex:/EUR\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\$([\d]+[.,]\d{2})\b/,currency:"USD"},{regex:/USD\s*([\d]+[.,]\d{2})\b/,currency:"USD"}];for(let{regex:s,currency:r}of t){let n=e.match(s);if(n?.[1])return{amount:n[1].trim(),currency:r}}return null}async sendMessage(e){if(e.replyTo)return await this.graphRequest(`/me/messages/${e.replyTo}/reply`,{method:"POST",body:JSON.stringify({comment:e.body})}),{messageId:e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(s=>({emailAddress:{address:s.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(s=>({emailAddress:{address:s.trim()}}))),await this.graphRequest("/me/sendMail",{method:"POST",body:JSON.stringify({message:t})}),{messageId:`sent-${Date.now()}`}}async createDraft(e){if(e.replyTo)return{messageId:(await this.graphRequest(`/me/messages/${e.replyTo}/createReply`,{method:"POST",body:JSON.stringify({comment:e.body})}))?.id??e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(r=>({emailAddress:{address:r.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(r=>({emailAddress:{address:r.trim()}}))),{messageId:(await this.graphRequest("/me/messages",{method:"POST",body:JSON.stringify(t)}))?.id??`draft-${Date.now()}`}}async listFolders(){return((await this.graphRequest("/me/mailFolders?$select=displayName&$top=100")).value??[]).map(t=>t.displayName)}async fetchFolder(e,t){let r=((await this.graphRequest("/me/mailFolders?$select=id,displayName&$top=100")).value??[]).find(i=>i.displayName.toLowerCase()===e.toLowerCase());if(!r)throw new Error(`Folder "${e}" not found. Use the 'folders' action to list available folders.`);let n=new URLSearchParams({$top:String(Math.min(Math.max(1,t),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/${r.id}/messages?${n}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}async forwardMessage(e,t,s){return await this.graphRequest(`/me/messages/${e}/forward`,{method:"POST",body:JSON.stringify({comment:s??"",toRecipients:t.split(",").map(r=>({emailAddress:{address:r.trim()}}))})}),{messageId:`fwd-${Date.now()}`}}mapMessage(e){return{id:e.id,from:this.formatGraphAddress(e.from),to:(e.toRecipients??[]).map(t=>this.formatGraphAddress(t)),subject:e.subject??"(no subject)",date:new Date(e.receivedDateTime),read:e.isRead??!1,preview:e.bodyPreview??void 0,hasAttachments:e.hasAttachments??!1}}formatGraphAddress(e){if(!e)return"unknown";let t=e.emailAddress??e;return t?.address?t.name?`${t.name} <${t.address}>`:t.address:"unknown"}stripHtml(e){return e.replace(/<br\s*\/?>/gi,`
|
|
465
|
+
[Data stored as "${N}" \u2014 use code_sandbox action "run_with_data" with data="${N}" to process this data. Do NOT copy data into code.]`}F.push({type:"tool_result",tool_use_id:x.id,content:se,is_error:ce.isError})}f.push({role:"user",content:F})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success,rawData:r.data}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var Ve,on=_(()=>{"use strict";Ve=class{static{u(this,"EmailProvider")}async extractFromSearch(e,t,s,r,n){throw new Error("Extract is not supported by this email provider.")}async createDraft(e){throw new Error("Draft creation is not supported by this email provider.")}async forwardMessage(e,t,s){throw new Error("Email forwarding is not supported by this email provider.")}}});var Ec={};me(Ec,{MicrosoftGraphEmailProvider:()=>an});var an,Xo=_(()=>{"use strict";on();an=class extends Ve{static{u(this,"MicrosoftGraphEmailProvider")}config;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){if(!this.config.refreshToken)throw new Error("Microsoft email: refreshToken is missing from config");let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Microsoft token refresh failed: ${s.status} \u2014 ${n.slice(0,300)}`)}let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json",...t.headers}}),"doFetch"),r=await s(this.accessToken);if(r.status===401){await this.refreshAccessToken();let n=await s(this.accessToken);if(!n.ok)throw new Error(`Graph API error: ${n.status}`);return this.parseJsonOrUndefined(n)}if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return this.parseJsonOrUndefined(r)}async parseJsonOrUndefined(e){if(e.status===204||e.status===202)return;let t=await e.text();if(!(!t||t.length===0))return JSON.parse(t)}async graphRequestRaw(e){let t=u(n=>fetch(`https://graph.microsoft.com/v1.0${e}`,{headers:{Authorization:`Bearer ${n}`}}),"doFetch"),s=await t(this.accessToken);if(s.status===401&&(await this.refreshAccessToken(),s=await t(this.accessToken)),!s.ok)throw new Error(`Graph API error: ${s.status}`);let r=await s.arrayBuffer();return Buffer.from(r)}async fetchInbox(e){let t=new URLSearchParams({$top:String(Math.min(Math.max(1,e),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/inbox/messages?${t}`)).value??[]).map(r=>this.mapMessage(r))}async readMessage(e){let t=new URLSearchParams({$select:"id,from,toRecipients,ccRecipients,bccRecipients,subject,body,receivedDateTime,isRead,hasAttachments"}),s=await this.graphRequest(`/me/messages/${e}?${t}`),r=[];return s.hasAttachments&&(r=((await this.graphRequest(`/me/messages/${e}/attachments?$select=id,name,contentType,size`)).value??[]).map(o=>({id:o.id,name:o.name,contentType:o.contentType,size:o.size??0}))),{id:s.id,from:this.formatGraphAddress(s.from),to:(s.toRecipients??[]).map(n=>this.formatGraphAddress(n)),subject:s.subject??"(no subject)",date:new Date(s.receivedDateTime),read:s.isRead??!1,body:s.body?.contentType==="html"?this.stripHtml(s.body.content??""):s.body?.content??"",bodyHtml:s.body?.contentType==="html"?s.body.content:void 0,cc:s.ccRecipients?.map(n=>this.formatGraphAddress(n)),bcc:s.bccRecipients?.map(n=>this.formatGraphAddress(n)),hasAttachments:s.hasAttachments,attachments:r}}async searchMessages(e,t){let s=Math.min(Math.max(1,t),50),r=new URLSearchParams({$search:`"${e}"`,$top:String(s),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"}),n=await this.graphRequest(`/me/messages?${r}`),o=(n.value??[]).map(i=>this.mapMessage(i));if(t>50){let i=n["@odata.nextLink"];for(;i&&o.length<t;){let a=await this.graphRequest(i.replace("https://graph.microsoft.com/v1.0","")),c=(a.value??[]).map(d=>this.mapMessage(d));o.push(...c),i=a["@odata.nextLink"]}}return o.slice(0,t)}async extractFromSearch(e,t,s,r,n){let o=await this.searchWithDateFilter(e,t,r,n),i=s.includes("amount"),a=[];if(i)for(let d=0;d<o.length;d+=5){let m=o.slice(d,d+5),p=await Promise.allSettled(m.map(async g=>{let f={id:g.id,from:g.from,subject:g.subject,date:g.date.toISOString().split("T")[0],preview:(g.preview??"").slice(0,200)};try{let h=await this.readMessage(g.id),y=this.extractAmount(h.body);y&&(f.amount=y.amount,f.currency=y.currency)}catch{}return f}));for(let g of p)g.status==="fulfilled"&&a.push(g.value)}else for(let c of o)a.push({id:c.id,from:c.from,subject:c.subject,date:c.date.toISOString().split("T")[0],preview:(c.preview??"").slice(0,200)});return a}async searchWithDateFilter(e,t,s,r){let n=Math.min(Math.max(1,t),50),o=[];if(s||r){let p=s?this.toKqlDate(s):"01/01/2000",g=r?this.toKqlDate(r):"12/31/2099";o.push(`received:${p}..${g}`)}e&&o.push(e.includes(" ")?`(${e})`:e);let i=o.join(" AND "),a=new URLSearchParams({$top:String(n),$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});i?a.set("$search",`"${i}"`):a.set("$orderby","receivedDateTime desc");let c=await this.graphRequest(`/me/messages?${a}`),d=(c.value??[]).map(p=>this.mapMessage(p)),m=c["@odata.nextLink"];for(;m&&d.length<t;){let p=await this.graphRequest(m.replace("https://graph.microsoft.com/v1.0","")),g=(p.value??[]).map(f=>this.mapMessage(f));d.push(...g),m=p["@odata.nextLink"]}return d.slice(0,t)}toKqlDate(e){let[t,s,r]=e.split("-");return`${s}/${r}/${t}`}extractAmount(e){let t=[{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*€\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*€/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*EUR\s*([\d.,]+)/i,currency:"EUR"},{regex:/(?:gesamt|total|summe|betrag|amount|charged|bezahlt|preis|price)[:\s]*([\d.,]+)\s*EUR/i,currency:"EUR"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*\$\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*USD\s*([\d.,]+)/i,currency:"USD"},{regex:/(?:total|amount|charged|price|subtotal)[:\s]*([\d.,]+)\s*USD/i,currency:"USD"},{regex:/€\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\b([\d]+[.,]\d{2})\s*€/,currency:"EUR"},{regex:/EUR\s*([\d]+[.,]\d{2})\b/,currency:"EUR"},{regex:/\$([\d]+[.,]\d{2})\b/,currency:"USD"},{regex:/USD\s*([\d]+[.,]\d{2})\b/,currency:"USD"}];for(let{regex:s,currency:r}of t){let n=e.match(s);if(n?.[1])return{amount:n[1].trim(),currency:r}}return null}async sendMessage(e){if(e.replyTo)return await this.graphRequest(`/me/messages/${e.replyTo}/reply`,{method:"POST",body:JSON.stringify({comment:e.body})}),{messageId:e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(s=>({emailAddress:{address:s.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(s=>({emailAddress:{address:s.trim()}}))),await this.graphRequest("/me/sendMail",{method:"POST",body:JSON.stringify({message:t})}),{messageId:`sent-${Date.now()}`}}async createDraft(e){if(e.replyTo)return{messageId:(await this.graphRequest(`/me/messages/${e.replyTo}/createReply`,{method:"POST",body:JSON.stringify({comment:e.body})}))?.id??e.replyTo};let t={subject:e.subject,body:{contentType:e.isHtml?"html":"text",content:e.body},toRecipients:e.to.split(",").map(r=>({emailAddress:{address:r.trim()}}))};return e.cc&&(t.ccRecipients=e.cc.split(",").map(r=>({emailAddress:{address:r.trim()}}))),{messageId:(await this.graphRequest("/me/messages",{method:"POST",body:JSON.stringify(t)}))?.id??`draft-${Date.now()}`}}async listFolders(){return((await this.graphRequest("/me/mailFolders?$select=displayName&$top=100")).value??[]).map(t=>t.displayName)}async fetchFolder(e,t){let r=((await this.graphRequest("/me/mailFolders?$select=id,displayName&$top=100")).value??[]).find(i=>i.displayName.toLowerCase()===e.toLowerCase());if(!r)throw new Error(`Folder "${e}" not found. Use the 'folders' action to list available folders.`);let n=new URLSearchParams({$top:String(Math.min(Math.max(1,t),50)),$orderby:"receivedDateTime desc",$select:"id,from,toRecipients,subject,receivedDateTime,isRead,bodyPreview,hasAttachments"});return((await this.graphRequest(`/me/mailFolders/${r.id}/messages?${n}`)).value??[]).map(i=>this.mapMessage(i))}async downloadAttachment(e,t){return this.graphRequestRaw(`/me/messages/${e}/attachments/${t}/$value`)}async forwardMessage(e,t,s){return await this.graphRequest(`/me/messages/${e}/forward`,{method:"POST",body:JSON.stringify({comment:s??"",toRecipients:t.split(",").map(r=>({emailAddress:{address:r.trim()}}))})}),{messageId:`fwd-${Date.now()}`}}mapMessage(e){return{id:e.id,from:this.formatGraphAddress(e.from),to:(e.toRecipients??[]).map(t=>this.formatGraphAddress(t)),subject:e.subject??"(no subject)",date:new Date(e.receivedDateTime),read:e.isRead??!1,preview:e.bodyPreview??void 0,hasAttachments:e.hasAttachments??!1}}formatGraphAddress(e){if(!e)return"unknown";let t=e.emailAddress??e;return t?.address?t.name?`${t.name} <${t.address}>`:t.address:"unknown"}stripHtml(e){return e.replace(/<br\s*\/?>/gi,`
|
|
466
466
|
`).replace(/<\/p>/gi,`
|
|
467
467
|
|
|
468
468
|
`).replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/\n{3,}/g,`
|
|
@@ -512,12 +512,12 @@ ${n.map((o,i)=>` ${i+1}. ${o}`).join(`
|
|
|
512
512
|
|
|
513
513
|
`);return{success:!0,data:{folder:t,messages:i.map(c=>({...c,id:this.encodeId(n,c.id)}))},display:this.accountLabel(n,`Folder "${t}" (${i.length} messages):
|
|
514
514
|
|
|
515
|
-
${a}`)}}async handleReply(e){let t=e.messageId,s=e.body;if(!t)return{success:!1,error:'"messageId" is required for reply.'};if(!s)return{success:!1,error:'"body" is required for reply.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);return o?{success:!0,data:{messageId:(await o.sendMessage({to:"",subject:"",body:s,replyTo:n})).messageId},display:this.accountLabel(r,`Reply sent to message ${n}.`)}:{success:!1,error:`Unknown email account "${r}".`}}async handleForward(e){let t=e.messageId,s=e.to;if(!t)return{success:!1,error:'"messageId" is required for forward.'};if(!s)return{success:!1,error:'"to" (recipient email) is required for forward.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);if(!o)return{success:!1,error:`Unknown email account "${r}".`};let i=e.body??void 0;return{success:!0,data:{messageId:(await o.forwardMessage(n,s,i)).messageId,to:s},display:this.accountLabel(r,`Email forwarded to ${s}.`)}}async handleAttachment(e){let t=e.messageId,s=e.attachmentId,r=e.save;if(!t)return{success:!1,error:'"messageId" is required.'};if(!s)return{success:!1,error:'"attachmentId" is required.'};let{account:n,rawId:o}=this.decodeId(t),i=this.providers.get(n);if(!i)return{success:!1,error:`Unknown email account "${n}".`};let a=await i.readMessage(o),c=a.attachments?.find(f=>f.id===s);if(c||(c=a.attachments?.find(f=>f.name.toLowerCase()===s.toLowerCase())),!c){let f=a.attachments?.map(h=>`[${h.id}] ${h.name}`).join(", ")??"none";return{success:!1,error:`Attachment "${s}" not found. Available: ${f}`}}let d=await i.downloadAttachment(o,c.id),m=c.name,p=c.contentType;if(r){let f=await import("node:fs"),h=await import("node:path"),
|
|
515
|
+
${a}`)}}async handleReply(e){let t=e.messageId,s=e.body;if(!t)return{success:!1,error:'"messageId" is required for reply.'};if(!s)return{success:!1,error:'"body" is required for reply.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);return o?{success:!0,data:{messageId:(await o.sendMessage({to:"",subject:"",body:s,replyTo:n})).messageId},display:this.accountLabel(r,`Reply sent to message ${n}.`)}:{success:!1,error:`Unknown email account "${r}".`}}async handleForward(e){let t=e.messageId,s=e.to;if(!t)return{success:!1,error:'"messageId" is required for forward.'};if(!s)return{success:!1,error:'"to" (recipient email) is required for forward.'};let{account:r,rawId:n}=this.decodeId(t),o=this.providers.get(r);if(!o)return{success:!1,error:`Unknown email account "${r}".`};let i=e.body??void 0;return{success:!0,data:{messageId:(await o.forwardMessage(n,s,i)).messageId,to:s},display:this.accountLabel(r,`Email forwarded to ${s}.`)}}async handleAttachment(e){let t=e.messageId,s=e.attachmentId,r=e.save;if(!t)return{success:!1,error:'"messageId" is required.'};if(!s)return{success:!1,error:'"attachmentId" is required.'};let{account:n,rawId:o}=this.decodeId(t),i=this.providers.get(n);if(!i)return{success:!1,error:`Unknown email account "${n}".`};let a=await i.readMessage(o),c=a.attachments?.find(f=>f.id===s);if(c||(c=a.attachments?.find(f=>f.name.toLowerCase()===s.toLowerCase())),!c){let f=a.attachments?.map(h=>`[${h.id}] ${h.name}`).join(", ")??"none";return{success:!1,error:`Attachment "${s}" not found. Available: ${f}`}}let d=await i.downloadAttachment(o,c.id),m=c.name,p=c.contentType;if(r){let f=await import("node:fs"),h=await import("node:path"),y=h.resolve(r);f.existsSync(y)||f.mkdirSync(y,{recursive:!0});let E=h.join(y,m);return f.writeFileSync(E,d),{success:!0,data:{messageId:t,attachmentId:c.id,fileName:m,size:d.length,savedTo:E},display:this.accountLabel(n,`Saved attachment: ${m} (${this.formatSize(d.length)}) \u2192 ${E}`)}}let g=await this.extractText(d,p,m);if(g!==null){let f=g.length>6e3?g.slice(0,6e3)+`
|
|
516
516
|
|
|
517
517
|
... (truncated)`:g;return{success:!0,data:{messageId:t,attachmentId:c.id,fileName:m,size:d.length,hasContent:!0},display:this.accountLabel(n,`Attachment: ${m} (${this.formatSize(d.length)})
|
|
518
518
|
|
|
519
519
|
Content:
|
|
520
|
-
${f}`),attachments:[{fileName:m,data:d,mimeType:p}]}}return{success:!0,data:{messageId:t,attachmentId:c.id,fileName:m,size:d.length},display:this.accountLabel(n,`Downloaded attachment: ${m} (${this.formatSize(d.length)})`),attachments:[{fileName:m,data:d,mimeType:p}]}}async handleExtract(e){let t=e.query;if(!t)return{success:!1,error:'query is required for extract. Example: "rechnung OR invoice OR receipt 2026"'};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.maxResults??200),1e3),i=e.fields??["from","subject","date","amount"],a=e.dateFrom,c=e.dateTo;try{let d=await r.extractFromSearch(t,o,i,a,c);if(d.length===0)return{success:!0,data:{results:[]},display:this.accountLabel(n,`No emails found for "${t}".`)};let m=d.map((f,h)=>{let
|
|
520
|
+
${f}`),attachments:[{fileName:m,data:d,mimeType:p}]}}return{success:!0,data:{messageId:t,attachmentId:c.id,fileName:m,size:d.length},display:this.accountLabel(n,`Downloaded attachment: ${m} (${this.formatSize(d.length)})`),attachments:[{fileName:m,data:d,mimeType:p}]}}async handleExtract(e){let t=e.query;if(!t)return{success:!1,error:'query is required for extract. Example: "rechnung OR invoice OR receipt 2026"'};let s=this.resolveProvider(e);if("success"in s)return s;let{provider:r,account:n}=s,o=Math.min(Math.max(1,e.maxResults??200),1e3),i=e.fields??["from","subject","date","amount"],a=e.dateFrom,c=e.dateTo;try{let d=await r.extractFromSearch(t,o,i,a,c);if(d.length===0)return{success:!0,data:{results:[]},display:this.accountLabel(n,`No emails found for "${t}".`)};let m=d.map((f,h)=>{let y=f.amount?` | ${f.amount} ${f.currency??""}`:"";return`${h+1}. ${f.date} | ${f.from} | ${f.subject}${y}`}),p=d.filter(f=>f.amount),g=`Found ${d.length} emails (${p.length} with detected amounts)`;return{success:!0,data:{results:d,totalFound:d.length,withAmounts:p.length},display:this.accountLabel(n,`${g}:
|
|
521
521
|
|
|
522
522
|
${m.join(`
|
|
523
523
|
`)}`)}}catch(d){if((d instanceof Error?d.message:String(d)).includes("Extract is not supported"))return{success:!1,error:"The extract action is only supported with Microsoft Graph email. Use search + read for other providers."};throw d}}async extractText(e,t,s){try{if(t==="application/pdf"){let r=(await import("pdf-parse")).default;return(await r(e)).text?.trim()||null}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")return(await(await import("mammoth")).extractRawText({buffer:e})).value?.trim()||null;if(t.startsWith("text/")||s.endsWith(".csv")||s.endsWith(".json")||s.endsWith(".md"))return e.toString("utf-8")}catch{}return null}formatSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Sc,Gt,Ac=_(()=>{"use strict";P();Sc=1e5,Gt=class extends I{static{u(this,"HttpSkill")}metadata={name:"http",category:"files",description:"Make HTTP requests to fetch web pages or call REST APIs. Use when you need to read a URL, call an API endpoint, or fetch data from the web. Supports GET, POST, PUT, PATCH, DELETE methods.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL to request"},method:{type:"string",enum:["GET","POST","PUT","PATCH","DELETE"],description:"HTTP method (default: GET)"},headers:{type:"object",description:"Request headers as key-value pairs (optional)"},body:{type:"string",description:"Request body for POST/PUT/PATCH (optional)"}},required:["url"]}};async execute(e,t){let s=e.url,r=(e.method??"GET").toUpperCase(),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),d=c.headers.get("content-type")??"",m=await c.text(),p=m.length>Sc,g=p?m.slice(0,Sc)+`
|
|
@@ -563,7 +563,7 @@ BEGIN:VEVENT\r
|
|
|
563
563
|
`),r+=`DTSTAMP:${s(new Date)}\r
|
|
564
564
|
`,r+=`END:VEVENT\r
|
|
565
565
|
END:VCALENDAR\r
|
|
566
|
-
`,r}}});var Pc={};me(Pc,{GoogleCalendarProvider:()=>dn});var dn,Qo=_(()=>{"use strict";ir();dn=class extends Me{static{u(this,"GoogleCalendarProvider")}config;calendar;constructor(e){super(),this.config=e}async initialize(){try{let{google:e}=await import("googleapis"),t=new e.auth.OAuth2(this.config.clientId,this.config.clientSecret);t.setCredentials({refresh_token:this.config.refreshToken}),this.calendar=e.calendar({version:"v3",auth:t})}catch(e){throw new Error(`Google Calendar initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){return((await this.calendar.events.list({calendarId:"primary",timeMin:e.toISOString(),timeMax:t.toISOString(),singleEvents:!0,orderBy:"startTime"})).data.items??[]).map(r=>this.mapEvent(r))}async createEvent(e){let t={summary:e.title,location:e.location,description:e.description};e.allDay?(t.start={date:e.start.toISOString().slice(0,10)},t.end={date:e.end.toISOString().slice(0,10)}):(t.start={dateTime:e.start.toISOString()},t.end={dateTime:e.end.toISOString()});let s=await this.calendar.events.insert({calendarId:"primary",requestBody:t});return this.mapEvent(s.data)}async updateEvent(e,t){let s={};t.title&&(s.summary=t.title),t.location&&(s.location=t.location),t.description&&(s.description=t.description),t.start&&(s.start=t.allDay?{date:t.start.toISOString().slice(0,10)}:{dateTime:t.start.toISOString()}),t.end&&(s.end=t.allDay?{date:t.end.toISOString().slice(0,10)}:{dateTime:t.end.toISOString()});let r=await this.calendar.events.patch({calendarId:"primary",eventId:e,requestBody:s});return this.mapEvent(r.data)}async deleteEvent(e){await this.calendar.events.delete({calendarId:"primary",eventId:e})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){let t=!!e.start?.date;return{id:e.id,title:e.summary??"(No title)",start:new Date(e.start?.dateTime??e.start?.date),end:new Date(e.end?.dateTime??e.end?.date),location:e.location??void 0,description:e.description??void 0,allDay:t}}}});var Uc={};me(Uc,{MicrosoftCalendarProvider:()=>un});var un,ei=_(()=>{"use strict";ir();un=class extends Me{static{u(this,"MicrosoftCalendarProvider")}config;client;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Calendars.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async listEvents(e,t){let s=new URLSearchParams({startDateTime:e.toISOString(),endDateTime:t.toISOString(),$orderby:"start/dateTime",$top:"50"});return((await this.graphRequest(`/me/calendarView?${s}
|
|
566
|
+
`,r}}});var Pc={};me(Pc,{GoogleCalendarProvider:()=>dn});var dn,Qo=_(()=>{"use strict";ir();dn=class extends Me{static{u(this,"GoogleCalendarProvider")}config;calendar;constructor(e){super(),this.config=e}async initialize(){try{let{google:e}=await import("googleapis"),t=new e.auth.OAuth2(this.config.clientId,this.config.clientSecret);t.setCredentials({refresh_token:this.config.refreshToken}),this.calendar=e.calendar({version:"v3",auth:t})}catch(e){throw new Error(`Google Calendar initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async listEvents(e,t){return((await this.calendar.events.list({calendarId:"primary",timeMin:e.toISOString(),timeMax:t.toISOString(),singleEvents:!0,orderBy:"startTime"})).data.items??[]).map(r=>this.mapEvent(r))}async createEvent(e){let t={summary:e.title,location:e.location,description:e.description};e.allDay?(t.start={date:e.start.toISOString().slice(0,10)},t.end={date:e.end.toISOString().slice(0,10)}):(t.start={dateTime:e.start.toISOString()},t.end={dateTime:e.end.toISOString()});let s=await this.calendar.events.insert({calendarId:"primary",requestBody:t});return this.mapEvent(s.data)}async updateEvent(e,t){let s={};t.title&&(s.summary=t.title),t.location&&(s.location=t.location),t.description&&(s.description=t.description),t.start&&(s.start=t.allDay?{date:t.start.toISOString().slice(0,10)}:{dateTime:t.start.toISOString()}),t.end&&(s.end=t.allDay?{date:t.end.toISOString().slice(0,10)}:{dateTime:t.end.toISOString()});let r=await this.calendar.events.patch({calendarId:"primary",eventId:e,requestBody:s});return this.mapEvent(r.data)}async deleteEvent(e){await this.calendar.events.delete({calendarId:"primary",eventId:e})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}mapEvent(e){let t=!!e.start?.date;return{id:e.id,title:e.summary??"(No title)",start:new Date(e.start?.dateTime??e.start?.date),end:new Date(e.end?.dateTime??e.end?.date),location:e.location??void 0,description:e.description??void 0,allDay:t}}}});var Uc={};me(Uc,{MicrosoftCalendarProvider:()=>un});var un,ei=_(()=>{"use strict";ir();un=class extends Me{static{u(this,"MicrosoftCalendarProvider")}config;client;accessToken="";constructor(e){super(),this.config=e}async initialize(){await this.refreshAccessToken()}async refreshAccessToken(){let e=`https://login.microsoftonline.com/${this.config.tenantId}/oauth2/v2.0/token`,t=new URLSearchParams({client_id:this.config.clientId,client_secret:this.config.clientSecret,refresh_token:this.config.refreshToken,grant_type:"refresh_token",scope:"https://graph.microsoft.com/Calendars.ReadWrite offline_access"}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!s.ok)throw new Error(`Microsoft token refresh failed: ${s.status}`);let r=await s.json();this.accessToken=r.access_token}async graphRequest(e,t={}){let s=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(s.status===401){await this.refreshAccessToken();let r=await fetch(`https://graph.microsoft.com/v1.0${e}`,{...t,headers:{Authorization:`Bearer ${this.accessToken}`,"Content-Type":"application/json",...t.headers}});if(!r.ok)throw new Error(`Graph API error: ${r.status}`);return r.json()}if(!s.ok)throw new Error(`Graph API error: ${s.status}`);if(s.status!==204)return s.json()}async listEvents(e,t){let s=new URLSearchParams({startDateTime:e.toISOString(),endDateTime:t.toISOString(),$orderby:"start/dateTime",$top:"50"});return((await this.graphRequest(`/me/calendarView?${s}`,{headers:{Prefer:'outlook.timezone="UTC"'}})).value??[]).map(n=>this.mapEvent(n))}async createEvent(e){let t=this.timezone,s={subject:e.title,body:e.description?{contentType:"text",content:e.description}:void 0,location:e.location?{displayName:e.location}:void 0,isAllDay:e.allDay??!1};e.allDay?(s.start={dateTime:this.formatDateInTz(e.start,t).slice(0,10)+"T00:00:00",timeZone:t},s.end={dateTime:this.formatDateInTz(e.end,t).slice(0,10)+"T00:00:00",timeZone:t}):(s.start={dateTime:this.formatDateInTz(e.start,t),timeZone:t},s.end={dateTime:this.formatDateInTz(e.end,t),timeZone:t});let r=await this.graphRequest("/me/events",{method:"POST",body:JSON.stringify(s)});return this.mapEvent(r)}async updateEvent(e,t){let s={};t.title&&(s.subject=t.title),t.description&&(s.body={contentType:"text",content:t.description}),t.location&&(s.location={displayName:t.location}),t.start&&(s.start={dateTime:this.formatDateInTz(t.start,this.timezone),timeZone:this.timezone}),t.end&&(s.end={dateTime:this.formatDateInTz(t.end,this.timezone),timeZone:this.timezone});let r=await this.graphRequest(`/me/events/${e}`,{method:"PATCH",body:JSON.stringify(s)});return this.mapEvent(r)}async deleteEvent(e){await this.graphRequest(`/me/events/${e}`,{method:"DELETE"})}async checkAvailability(e,t){let r=(await this.listEvents(e,t)).filter(n=>!n.allDay&&n.start<t&&n.end>e);return{available:r.length===0,conflicts:r}}formatDateInTz(e,t){let s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),r=u(n=>s.find(o=>o.type===n)?.value??"00","g");return`${r("year")}-${r("month")}-${r("day")}T${r("hour")}:${r("minute")}:${r("second")}`}mapEvent(e){return{id:e.id,title:e.subject??"(No title)",start:this.parseGraphDateTime(e.start),end:this.parseGraphDateTime(e.end),location:e.location?.displayName??void 0,description:e.body?.content??void 0,allDay:e.isAllDay??!1}}parseGraphDateTime(e){if(!e?.dateTime)return new Date;let t=e.dateTime.replace(/(\.\d{3})\d*$/,"$1");return new Date(t+"Z")}}});async function ar(l){switch(l.provider){case"caldav":{if(!l.caldav)throw new Error("CalDAV config missing");let{CalDAVProvider:e}=await Promise.resolve().then(()=>(Zo(),Oc)),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(()=>(Qo(),Pc)),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(()=>(ei(),Uc)),t=new e(l.microsoft);return await t.initialize(),t}default:throw new Error(`Unknown calendar provider: ${l.provider}`)}}var Fc=_(()=>{"use strict";u(ar,"createCalendarProvider")});var _t,jc=_(()=>{"use strict";P();_t=class extends I{static{u(this,"CalendarSkill")}calendarProvider;timezone;metadata={name:"calendar",category:"productivity",description:"Manage calendar events. List upcoming events, create new events, update or delete existing ones, and check availability.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_events","create_event","update_event","delete_event","check_availability"],description:"The calendar action to perform"},start:{type:"string",description:"Start date/time in ISO 8601 format"},end:{type:"string",description:"End date/time in ISO 8601 format"},title:{type:"string",description:"Event title (for create/update)"},location:{type:"string",description:"Event location (for create/update)"},description:{type:"string",description:"Event description (for create/update)"},event_id:{type:"string",description:"Event ID (for update/delete)"},all_day:{type:"boolean",description:"Whether this is an all-day event"}},required:["action"]}};constructor(e,t){super(),this.calendarProvider=e,this.timezone=t}async execute(e,t){t.timezone&&(this.calendarProvider.timezone=t.timezone);let s=e.action;switch(s){case"list_events":return this.listEvents(e);case"create_event":return this.createEvent(e);case"update_event":return this.updateEvent(e);case"delete_event":return this.deleteEvent(e);case"check_availability":return this.checkAvailability(e);default:return{success:!1,error:`Unknown action: "${String(s)}"`}}}async getTodayEvents(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()),s=new Date(e.getFullYear(),e.getMonth(),e.getDate()+1);try{return await this.calendarProvider.listEvents(t,s)}catch(r){return console.error("[calendar] Failed to fetch today events",r),[]}}async listEvents(e){let t=e.start?new Date(e.start):new Date,s=e.end?new Date(e.end):new Date(t.getTime()+7*24*60*60*1e3);try{let r=await this.calendarProvider.listEvents(t,s);if(r.length===0)return{success:!0,data:[],display:"No events found in this time range."};let n=r.map(o=>this.formatEvent(o)).join(`
|
|
567
567
|
`);return{success:!0,data:r,display:`${r.length} event(s):
|
|
568
568
|
${n}`}}catch(r){return{success:!1,error:`Failed to list events: ${r instanceof Error?r.message:String(r)}`}}}async createEvent(e){let t=e.title,s=e.start,r=e.end;if(!t)return{success:!1,error:'Missing required field "title"'};if(!s)return{success:!1,error:'Missing required field "start"'};if(!r)return{success:!1,error:'Missing required field "end"'};try{let n=await this.calendarProvider.createEvent({title:t,start:new Date(s),end:new Date(r),location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:n,display:`Event created: ${this.formatEvent(n)}`}}catch(n){return{success:!1,error:`Failed to create event: ${n instanceof Error?n.message:String(n)}`}}}async updateEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{let s=await this.calendarProvider.updateEvent(t,{title:e.title,start:e.start?new Date(e.start):void 0,end:e.end?new Date(e.end):void 0,location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:s,display:`Event updated: ${this.formatEvent(s)}`}}catch(s){return{success:!1,error:`Failed to update event: ${s instanceof Error?s.message:String(s)}`}}}async deleteEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{return await this.calendarProvider.deleteEvent(t),{success:!0,data:{deleted:t},display:`Event "${t}" deleted.`}}catch(s){return{success:!1,error:`Failed to delete event: ${s instanceof Error?s.message:String(s)}`}}}async checkAvailability(e){let t=e.start,s=e.end;if(!t||!s)return{success:!1,error:'Missing required fields "start" and "end"'};try{let r=await this.calendarProvider.checkAvailability(new Date(t),new Date(s)),n=r.available?"Time slot is available.":`Time slot has ${r.conflicts.length} conflict(s):
|
|
569
569
|
${r.conflicts.map(o=>this.formatEvent(o)).join(`
|
|
@@ -580,7 +580,7 @@ ${r.join(`
|
|
|
580
580
|
`)}`}}cancelTask(e,t){let s=e.task_id;return!s||typeof s!="string"?{success:!1,error:'Missing required field "task_id" for cancel action'}:this.getAllTasks(t).some(i=>i.id===s)?this.taskRepo.cancel(s)?{success:!0,data:{taskId:s},display:`Background task "${s}" cancelled.`}:{success:!1,error:`Task "${s}" not found or already completed`}:{success:!1,error:`Task "${s}" not found or already completed`}}}});var ts,zc=_(()=>{"use strict";P();Ne();ts=class extends I{static{u(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",category:"automation",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time. Use this for time-based tasks (reports, periodic checks, reminders). For condition-based alerts ("notify me WHEN X happens"), use the watch tool instead.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}getAllActions(e){let t=new Set,s=[];for(let r of W(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,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")&&!c)return{success:!1,error:'Missing required field "skill_name" (or "prompt_template") for create action'};if(n==="interval"){let p=parseInt(o,10);if(isNaN(p)||p<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let p=new Date(o);if(isNaN(p.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(p.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let d=this.actionRepo.create({userId:ie(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i??"llm_prompt",skillInput:JSON.stringify(a??{}),promptTemplate:c}),m=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:d.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${d.id}): "${s}" \u2014 ${m}, running "${i}"${d.nextRunAt?`. Next run: ${d.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
|
|
581
581
|
${s.join(`
|
|
582
582
|
`)}`}}toggleAction(e,t,s){let r=e.action_id;if(!r||typeof r!="string")return{success:!1,error:`Missing required field "action_id" for ${t?"enable":"disable"} action`};let n=this.actionRepo.findById(r),o=W(s);return!n||!o.includes(n.userId)?{success:!1,error:`Scheduled action "${r}" not found`}:this.actionRepo.setEnabled(r,t)?{success:!0,data:{actionId:r,enabled:t},display:`Scheduled action "${r}" ${t?"enabled":"disabled"}.`}:{success:!1,error:`Scheduled action "${r}" not found`}}deleteAction(e,t){let s=e.action_id;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "action_id" for delete action'};let r=this.actionRepo.findById(s),n=W(t);return!r||!n.includes(r.userId)?{success:!1,error:`Scheduled action "${s}" not found`}:this.actionRepo.delete(s)?{success:!0,data:{actionId:s},display:`Scheduled action "${s}" deleted.`}:{success:!1,error:`Scheduled action "${s}" not found`}}}});var bt,ti=_(()=>{"use strict";bt=class{static{u(this,"MCPClient")}serverName;config;logger;client;transport;connected=!1;constructor(e,t,s){this.serverName=e,this.config=t,this.logger=s}async connect(){try{let{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");if(this.client=new e({name:`alfred-${this.serverName}`,version:"1.0.0"},{capabilities:{}}),this.config.command){let{StdioClientTransport:t}=await import("@modelcontextprotocol/sdk/client/stdio.js"),s={PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:process.env.NODE_ENV??"",SYSTEMROOT:process.env.SYSTEMROOT??""};if(this.config.env)for(let[r,n]of Object.entries(this.config.env))s[r]=n.replace(/\$\{(\w+)\}/g,(o,i)=>process.env[i]??"");this.transport=new t({command:this.config.command,args:this.config.args??[],env:s})}else if(this.config.url){let{SSEClientTransport:t}=await import("@modelcontextprotocol/sdk/client/sse.js");this.transport=new t(new URL(this.config.url))}else throw new Error(`MCP server "${this.serverName}": must specify either command or url`);await this.client.connect(this.transport),this.connected=!0,this.logger.info({server:this.serverName},"MCP server connected")}catch(e){throw this.logger.error({server:this.serverName,err:e},"Failed to connect MCP server"),e}}async listTools(){if(!this.connected||!this.client)return[];try{return((await this.client.listTools()).tools??[]).map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema??{type:"object",properties:{}}}))}catch(e){return this.logger.error({server:this.serverName,err:e},"Failed to list MCP tools"),[]}}async callTool(e,t){if(!this.connected||!this.client)return{content:"MCP server not connected",isError:!0};try{let s=await this.client.callTool({name:e,arguments:t});return{content:(s.content??[]).map(n=>n.text??JSON.stringify(n)).join(`
|
|
583
|
-
`),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var Mm,Et,si=_(()=>{"use strict";P();Mm=["read","write","destructive","admin"],Et=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&Mm.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var cr,Wc=_(()=>{"use strict";ti();si();cr=class{static{u(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new bt(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new Et(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Gc=_(()=>{"use strict";ti();si();Wc()});import{spawn as Om}from"node:child_process";import Oe from"node:fs";import Pe from"node:path";import Pm from"node:os";import Um from"node:crypto";var $t,ri=_(()=>{"use strict";$t=class{static{u(this,"CodeExecutor")}resolveNodePath(){let e=new Set;for(let s of["pdf-parse","exceljs","pdfkit"])try{let r=Ea.resolve(`${s}/package.json`);e.add(Pe.dirname(Pe.dirname(r)))}catch{}try{let s=Oe.realpathSync(process.argv[1]??""),r=Pe.dirname(s),n=Pe.join(r,"node_modules");Oe.existsSync(n)&&e.add(n);let o=Pe.join(r,"..","node_modules");Oe.existsSync(o)&&e.add(Oe.realpathSync(o))}catch{}let t=Pe.join(process.cwd(),"node_modules");if(Oe.existsSync(t)&&e.add(t),process.env.NODE_PATH)for(let s of process.env.NODE_PATH.split(Pe.delimiter))s&&e.add(s);return[...e].join(Pe.delimiter)}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=Pe.join(Pm.tmpdir(),`alfred-sandbox-${Um.randomUUID()}`);Oe.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=Pe.join(n,`script.${o}`);Oe.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],d=Date.now();return await new Promise(m=>{let p=Om(a,c,{cwd:n,timeout:r,env:{...process.env,NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n,NODE_PATH:this.resolveNodePath()},stdio:["pipe","pipe","pipe"]}),g="",f="";p.stdout.on("data",h=>{g+=h.toString()}),p.stderr.on("data",h=>{f+=h.toString()}),p.on("close",h=>{let
|
|
583
|
+
`),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var Mm,Et,si=_(()=>{"use strict";P();Mm=["read","write","destructive","admin"],Et=class extends I{static{u(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&Mm.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,category:"mcp",description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var cr,Wc=_(()=>{"use strict";ti();si();cr=class{static{u(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new bt(t.name,t,this.logger.child({mcp:t.name}));await s.connect(),this.clients.push(s);let r=await s.listTools();for(let n of r){let o=new Et(s,t.name,n.name,n.description??"",n.inputSchema);this.skills.push(o)}this.logger.info({server:t.name,tools:r.length},"MCP server initialized")}catch(s){this.logger.error({server:t.name,err:s},"Failed to initialize MCP server")}}getSkills(){return this.skills}async shutdown(){for(let e of this.clients)await e.disconnect();this.clients.length=0,this.skills.length=0}}});var Gc=_(()=>{"use strict";ti();si();Wc()});import{spawn as Om}from"node:child_process";import Oe from"node:fs";import Pe from"node:path";import Pm from"node:os";import Um from"node:crypto";var $t,ri=_(()=>{"use strict";$t=class{static{u(this,"CodeExecutor")}resolveNodePath(){let e=new Set;for(let s of["pdf-parse","exceljs","pdfkit"])try{let r=Ea.resolve(`${s}/package.json`);e.add(Pe.dirname(Pe.dirname(r)))}catch{}try{let s=Oe.realpathSync(process.argv[1]??""),r=Pe.dirname(s),n=Pe.join(r,"node_modules");Oe.existsSync(n)&&e.add(n);let o=Pe.join(r,"..","node_modules");Oe.existsSync(o)&&e.add(Oe.realpathSync(o))}catch{}let t=Pe.join(process.cwd(),"node_modules");if(Oe.existsSync(t)&&e.add(t),process.env.NODE_PATH)for(let s of process.env.NODE_PATH.split(Pe.delimiter))s&&e.add(s);return[...e].join(Pe.delimiter)}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=Pe.join(Pm.tmpdir(),`alfred-sandbox-${Um.randomUUID()}`);Oe.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=Pe.join(n,`script.${o}`);Oe.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],d=Date.now();return await new Promise(m=>{let p=Om(a,c,{cwd:n,timeout:r,env:{...process.env,NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n,NODE_PATH:this.resolveNodePath()},stdio:["pipe","pipe","pipe"]}),g="",f="";p.stdout.on("data",h=>{g+=h.toString()}),p.stderr.on("data",h=>{f+=h.toString()}),p.on("close",h=>{let y=Date.now()-d,E=[];try{let A=Oe.readdirSync(n).filter(R=>!R.startsWith("script."));for(let R of A){let F=Pe.join(n,R),x=Oe.statSync(F);if(x.isFile()&&x.size<1e7){let G=Oe.readFileSync(F),ce=R.endsWith(".png")?"image/png":R.endsWith(".jpg")||R.endsWith(".jpeg")?"image/jpeg":R.endsWith(".svg")?"image/svg+xml":R.endsWith(".csv")?"text/csv":R.endsWith(".json")?"application/json":R.endsWith(".html")||R.endsWith(".htm")?"text/html":R.endsWith(".txt")?"text/plain":R.endsWith(".md")?"text/markdown":R.endsWith(".xml")?"application/xml":R.endsWith(".xlsx")?"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":R.endsWith(".xls")?"application/vnd.ms-excel":R.endsWith(".pdf")?"application/pdf":"application/octet-stream";E.push({name:R,data:G,mimeType:ce})}}}catch{}m({stdout:g.slice(0,5e4),stderr:f.slice(0,1e4),exitCode:h??1,files:E.length>0?E:void 0,durationMs:y})}),p.on("error",h=>{m({stdout:"",stderr:h.message,exitCode:1,durationMs:Date.now()-d})}),p.stdin.end()})}finally{try{Oe.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var lr,Vc=_(()=>{"use strict";P();ri();lr=class extends I{static{u(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",category:"automation",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating files (PDF, HTML, CSV, images, etc.), or testing code snippets. Code runs in an isolated temp directory with a timeout. Any files written to the working directory are automatically collected and sent to the user as attachments \u2014 do NOT use the file skill to send them afterwards. For PDF generation use pdfkit (Node.js) or reportlab/fpdf (Python). IMPORTANT: When generating large files, write compact data-driven code \u2014 define data as arrays/objects, then build the output programmatically. Never embed large HTML/text as string literals.",riskLevel:"write",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data (available as variable INPUT_DATA, already parsed if JSON). Do NOT use os.environ or process.env \u2014 use INPUT_DATA directly."},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new $t;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code". IMPORTANT: Do NOT embed large HTML/text as string literals \u2014 write compact code that builds content programmatically from data arrays/objects, e.g. rows.map(r => `<tr><td>${r.time}</td><td>${r.price}</td></tr>`).join(""). Keep the code short and data-driven.'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};if(s==="run"&&r.length>4e3)return{success:!1,error:`Code too large (${r.length} chars, limit 4000 for action "run"). This usually means data is hardcoded in the code. Use action "run_with_data" with the data parameter instead. The data will be available as INPUT_DATA (already parsed). If you received a data reference like "result_1", pass it as the data parameter.`};let a=r;if(s==="run_with_data"&&o){let p=!1;try{JSON.parse(o),p=!0}catch{}n==="javascript"?a=p?`const INPUT_DATA = ${o};
|
|
584
584
|
${r}`:`const INPUT_DATA = ${JSON.stringify(o)};
|
|
585
585
|
${r}`:a=p?`import json as _json
|
|
586
586
|
INPUT_DATA = _json.loads(${JSON.stringify(o)})
|
|
@@ -660,7 +660,7 @@ Use "list_vouchers" to see the codes.`}}async enableWlan(e){return e?(await this
|
|
|
660
660
|
`)}}async getBriefingSummary(e,t){let s=await this.api("GET","/api/states");if(e?.length){let n=new Set(e.map(i=>i.toLowerCase())),o=s.filter(i=>n.has(i.entity_id.toLowerCase()));return this.formatBriefingSummary(o)}if(t?.length){let n=new Set(t.map(i=>i.toLowerCase())),o=s.filter(i=>{let a=i.entity_id.split(".")[0];return n.has(a)});return this.formatBriefingSummary(o)}let r=[];for(let n of s){let o=n.entity_id,i=o.split(".")[0],a=n.state,c=n.attributes??{},d=c.device_class??"";if(i==="binary_sensor"){["door","window","opening","garage_door","lock","motion","occupancy","smoke","gas","moisture"].includes(d)&&a==="on"&&r.push(n);continue}if(i==="light"){a==="on"&&r.push(n);continue}if(i==="sensor"){let p=`${o.toLowerCase()} ${(c.friendly_name??"").toLowerCase()}`;(d==="battery"||d==="energy"||d==="power"||/soc|battery|akku|ladezustand/.test(p)||/energy_consumption|power_consumption|stromverbrauch|gesamtverbrauch|total_energy/.test(p))&&a!=="unavailable"&&a!=="unknown"&&r.push(n);continue}if(i==="climate"){r.push(n);continue}if(i==="person"){r.push(n);continue}}return this.formatBriefingSummary(r)}formatBriefingSummary(e){if(e.length===0)return{success:!0,data:[],display:"Keine relevanten Smart-Home-Daten gefunden."};let t=new Map;for(let o of e){let i=o.entity_id.split(".")[0];t.has(i)||t.set(i,[]),t.get(i).push(o)}let s={binary_sensor:"Kontakte & Melder",light:"Lichter (an)",sensor:"Sensoren",climate:"Klima",person:"Anwesenheit"},r=[];for(let[o,i]of t){let a=s[o]??o;r.push(`**${a}:**`);for(let c of i){let d=c.attributes?.friendly_name??c.entity_id,m=c.attributes?.unit_of_measurement??"",p=c.state;r.push(`- ${d}: ${p}${m?` ${m}`:""}`)}r.push("")}return{success:!0,data:e.map(o=>({entity_id:o.entity_id,state:o.state,friendly_name:o.attributes?.friendly_name,unit:o.attributes?.unit_of_measurement,device_class:o.attributes?.device_class})),display:r.join(`
|
|
661
661
|
`).trim()}}async createConfig(e,t,s){if(!t)return{success:!1,error:`Missing required "configId" for create_${e}`};if(!s)return{success:!1,error:`Missing required "configData" for create_${e}`};let r;try{r=JSON.parse(s)}catch{return{success:!1,error:'Invalid "configData" \u2014 must be valid JSON'}}return{success:!0,data:await this.apiPost(`/api/config/${e}/config/${t}`,r),display:`**${e} created:** \`${t}\`
|
|
662
662
|
|
|
663
|
-
${r.alias??r.name??t}`}}async deleteConfig(e,t){return t?(await this.apiDelete(`/api/config/${e}/config/${t}`),{success:!0,data:{deleted:t},display:`**${e} deleted:** \`${t}\``}):{success:!1,error:`Missing required "configId" for delete_${e}`}}async apiPost(e,t){let s=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,r={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n=this.config.verifyTls===!1,o=process.env.NODE_TLS_REJECT_UNAUTHORIZED;n&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let i;try{i=await fetch(s,{method:"POST",headers:r,body:JSON.stringify(t),signal:AbortSignal.timeout(15e3)})}finally{n&&(o===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}if(!i.ok){let a="";try{a=(await i.text()).slice(0,500)}catch{}throw new Error(`HTTP ${i.status} ${i.statusText} \u2014 ${a}`)}return await i.json()}async apiDelete(e){let t=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,s={Authorization:`Bearer ${this.config.accessToken}`},r=this.config.verifyTls===!1,n=process.env.NODE_TLS_REJECT_UNAUTHORIZED;r&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let o;try{o=await fetch(t,{method:"DELETE",headers:s,signal:AbortSignal.timeout(15e3)})}finally{r&&(n===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=n)}if(!o.ok){let i="";try{i=(await o.text()).slice(0,500)}catch{}throw new Error(`HTTP ${o.status} ${o.statusText} \u2014 ${i}`)}}}});var Ue,ur=_(()=>{"use strict";Ue=class{static{u(this,"ContactsProvider")}}});var sl={};me(sl,{CardDAVContactsProvider:()=>gn});var gn,ni=_(()=>{"use strict";ur();gn=class extends Ue{static{u(this,"CardDAVContactsProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"carddav"})}catch(e){throw new Error(`CardDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async list(e,t){let s=await this.client.fetchAddressBooks();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchVCards({addressBook:n});for(let i of o){let a=this.parseVCard(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.displayName.localeCompare(o.displayName)),e?r.slice(0,e):r}async search(e){let t=await this.list(),s=e.toLowerCase();return t.filter(r=>r.displayName.toLowerCase().includes(s)||r.emails.some(n=>n.address.toLowerCase().includes(s))||r.phones.some(n=>n.number.includes(s)))}async get(e){return(await this.list()).find(s=>s.id===e)}async create(e){let t=await this.client.fetchAddressBooks();if(!t||t.length===0)throw new Error("No address books found");let s=`alfred-${Date.now()}@alfred`,r=this.buildVCard(s,e);await this.client.createVCard({addressBook:t[0],filename:`${s}.vcf`,vCardString:r});let n=e.displayName??([e.firstName,e.lastName].filter(Boolean).join(" ")||"Unknown");return{id:s,displayName:n,firstName:e.firstName,lastName:e.lastName,emails:e.emails??[],phones:e.phones??[],addresses:e.addresses??[],organization:e.organization,birthday:e.birthday,notes:e.notes}}async update(e,t){let s=await this.client.fetchAddressBooks();for(let r of s){let n=await this.client.fetchVCards({addressBook:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseVCard(o.data,o.url);if(!i)continue;let a={firstName:t.firstName??i.firstName,lastName:t.lastName??i.lastName,displayName:t.displayName??i.displayName,emails:t.emails??i.emails,phones:t.phones??i.phones,addresses:t.addresses??i.addresses,organization:t.organization??i.organization,birthday:t.birthday??i.birthday,notes:t.notes??i.notes},c=this.buildVCard(e,a);await this.client.updateVCard({vCard:{...o,data:c}});let d=a.displayName??([a.firstName,a.lastName].filter(Boolean).join(" ")||"Unknown");return{id:e,displayName:d,firstName:a.firstName,lastName:a.lastName,emails:a.emails??[],phones:a.phones??[],addresses:a.addresses??[],organization:a.organization,birthday:a.birthday,notes:a.notes}}}throw new Error(`Contact ${e} not found`)}async delete(e){let t=await this.client.fetchAddressBooks();for(let s of t){let r=await this.client.fetchVCards({addressBook:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteVCard({vCard:n});return}}throw new Error(`Contact ${e} not found`)}parseVCard(e,t){let s=u(h=>e.match(new RegExp(`^${h}[;:](.*)$`,"mi"))?.[1]?.trim(),"get"),r=s("FN");if(!r)return;let n=s("N"),[o,i]=n?n.split(";"):[void 0,void 0],a=[];for(let h of e.matchAll(/^EMAIL[^:]*:(.+)$/gmi)){let
|
|
663
|
+
${r.alias??r.name??t}`}}async deleteConfig(e,t){return t?(await this.apiDelete(`/api/config/${e}/config/${t}`),{success:!0,data:{deleted:t},display:`**${e} deleted:** \`${t}\``}):{success:!1,error:`Missing required "configId" for delete_${e}`}}async apiPost(e,t){let s=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,r={Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json"},n=this.config.verifyTls===!1,o=process.env.NODE_TLS_REJECT_UNAUTHORIZED;n&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let i;try{i=await fetch(s,{method:"POST",headers:r,body:JSON.stringify(t),signal:AbortSignal.timeout(15e3)})}finally{n&&(o===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}if(!i.ok){let a="";try{a=(await i.text()).slice(0,500)}catch{}throw new Error(`HTTP ${i.status} ${i.statusText} \u2014 ${a}`)}return await i.json()}async apiDelete(e){let t=`${this.config.baseUrl.replace(/\/+$/,"")}${e}`,s={Authorization:`Bearer ${this.config.accessToken}`},r=this.config.verifyTls===!1,n=process.env.NODE_TLS_REJECT_UNAUTHORIZED;r&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED="0");let o;try{o=await fetch(t,{method:"DELETE",headers:s,signal:AbortSignal.timeout(15e3)})}finally{r&&(n===void 0?delete process.env.NODE_TLS_REJECT_UNAUTHORIZED:process.env.NODE_TLS_REJECT_UNAUTHORIZED=n)}if(!o.ok){let i="";try{i=(await o.text()).slice(0,500)}catch{}throw new Error(`HTTP ${o.status} ${o.statusText} \u2014 ${i}`)}}}});var Ue,ur=_(()=>{"use strict";Ue=class{static{u(this,"ContactsProvider")}}});var sl={};me(sl,{CardDAVContactsProvider:()=>gn});var gn,ni=_(()=>{"use strict";ur();gn=class extends Ue{static{u(this,"CardDAVContactsProvider")}config;client;constructor(e){super(),this.config=e}async initialize(){try{let e=await import("tsdav"),{createDAVClient:t}=e;this.client=await t({serverUrl:this.config.serverUrl,credentials:{username:this.config.username,password:this.config.password},authMethod:"Basic",defaultAccountType:"carddav"})}catch(e){throw new Error(`CardDAV initialization failed: ${e instanceof Error?e.message:String(e)}`)}}async list(e,t){let s=await this.client.fetchAddressBooks();if(!s||s.length===0)return[];let r=[];for(let n of s){let o=await this.client.fetchVCards({addressBook:n});for(let i of o){let a=this.parseVCard(i.data,i.url);a&&r.push(a)}}return r.sort((n,o)=>n.displayName.localeCompare(o.displayName)),e?r.slice(0,e):r}async search(e){let t=await this.list(),s=e.toLowerCase();return t.filter(r=>r.displayName.toLowerCase().includes(s)||r.emails.some(n=>n.address.toLowerCase().includes(s))||r.phones.some(n=>n.number.includes(s)))}async get(e){return(await this.list()).find(s=>s.id===e)}async create(e){let t=await this.client.fetchAddressBooks();if(!t||t.length===0)throw new Error("No address books found");let s=`alfred-${Date.now()}@alfred`,r=this.buildVCard(s,e);await this.client.createVCard({addressBook:t[0],filename:`${s}.vcf`,vCardString:r});let n=e.displayName??([e.firstName,e.lastName].filter(Boolean).join(" ")||"Unknown");return{id:s,displayName:n,firstName:e.firstName,lastName:e.lastName,emails:e.emails??[],phones:e.phones??[],addresses:e.addresses??[],organization:e.organization,birthday:e.birthday,notes:e.notes}}async update(e,t){let s=await this.client.fetchAddressBooks();for(let r of s){let n=await this.client.fetchVCards({addressBook:r});for(let o of n)if(o.url?.includes(e)||o.data?.includes(e)){let i=this.parseVCard(o.data,o.url);if(!i)continue;let a={firstName:t.firstName??i.firstName,lastName:t.lastName??i.lastName,displayName:t.displayName??i.displayName,emails:t.emails??i.emails,phones:t.phones??i.phones,addresses:t.addresses??i.addresses,organization:t.organization??i.organization,birthday:t.birthday??i.birthday,notes:t.notes??i.notes},c=this.buildVCard(e,a);await this.client.updateVCard({vCard:{...o,data:c}});let d=a.displayName??([a.firstName,a.lastName].filter(Boolean).join(" ")||"Unknown");return{id:e,displayName:d,firstName:a.firstName,lastName:a.lastName,emails:a.emails??[],phones:a.phones??[],addresses:a.addresses??[],organization:a.organization,birthday:a.birthday,notes:a.notes}}}throw new Error(`Contact ${e} not found`)}async delete(e){let t=await this.client.fetchAddressBooks();for(let s of t){let r=await this.client.fetchVCards({addressBook:s});for(let n of r)if(n.url?.includes(e)||n.data?.includes(e)){await this.client.deleteVCard({vCard:n});return}}throw new Error(`Contact ${e} not found`)}parseVCard(e,t){let s=u(h=>e.match(new RegExp(`^${h}[;:](.*)$`,"mi"))?.[1]?.trim(),"get"),r=s("FN");if(!r)return;let n=s("N"),[o,i]=n?n.split(";"):[void 0,void 0],a=[];for(let h of e.matchAll(/^EMAIL[^:]*:(.+)$/gmi)){let y=h[0],E=h[1].trim(),A=y.match(/TYPE=([^;:,]+)/i)?.[1],R=/TYPE=pref/i.test(y);a.push({address:E,label:A,primary:R})}let c=[];for(let h of e.matchAll(/^TEL[^:]*:(.+)$/gmi)){let y=h[0],E=h[1].trim(),A=y.match(/TYPE=([^;:,]+)/i)?.[1],R=/TYPE=pref/i.test(y);c.push({number:E,label:A,primary:R})}let d=[];for(let h of e.matchAll(/^ADR[^:]*:(.+)$/gmi)){let y=h[1].split(";");d.push({street:y[2]?.trim()||void 0,city:y[3]?.trim()||void 0,region:y[4]?.trim()||void 0,postalCode:y[5]?.trim()||void 0,country:y[6]?.trim()||void 0})}let m=s("ORG")?.replace(/;.*$/,""),p=s("BDAY"),g=s("NOTE");return{id:s("UID")??t,displayName:r,firstName:i,lastName:o,emails:a,phones:c,addresses:d,organization:m,birthday:p,notes:g}}buildVCard(e,t){let s=t.displayName??([t.firstName,t.lastName].filter(Boolean).join(" ")||"Unknown"),r=`BEGIN:VCARD\r
|
|
664
664
|
VERSION:3.0\r
|
|
665
665
|
`;r+=`UID:${e}\r
|
|
666
666
|
`,r+=`FN:${s}\r
|
|
@@ -706,16 +706,17 @@ ${n}`}}clearCompleted(e,t){let s=e.list,r=this.todoRepo.clearCompleted(ie(t),s);
|
|
|
706
706
|
`)}}}});import{readFile as hl,writeFile as fl,mkdir as gl}from"node:fs/promises";import{homedir as di}from"node:os";import{join as ui}from"node:path";import Tl from"node:crypto";function Km(){let l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",e=Tl.randomBytes(86);return Array.from(e).map(t=>l[t%l.length]).join("")}function Xm(l){return Tl.createHash("sha256").update(l).digest("base64url")}function ge(l,e){return l[e]?.value??"?"}var zm,yl,bn,Wm,Gm,Vm,wl,En,Ym,$n,_l=_(()=>{"use strict";P();zm="https://customer.bmwgroup.com/gcdm/oauth/device/code",yl="https://customer.bmwgroup.com/gcdm/oauth/token",bn="https://api-cardata.bmwgroup.com",Wm="v1",Gm="authenticate_user openid cardata:api:read cardata:streaming:read",Vm=5*6e4,wl="Alfred",En=ui(di(),".alfred","bmw-tokens.json");u(Km,"generateCodeVerifier");u(Xm,"generateCodeChallenge");Ym=["vehicle.drivetrain.batteryManagement.header","vehicle.drivetrain.batteryManagement.maxEnergy","vehicle.drivetrain.batteryManagement.batterySizeMax","vehicle.powertrain.electric.battery.stateOfHealth.displayed","vehicle.powertrain.electric.battery.stateOfCharge.target","vehicle.drivetrain.electricEngine.remainingElectricRange","vehicle.drivetrain.electricEngine.charging.status","vehicle.drivetrain.electricEngine.charging.level","vehicle.drivetrain.electricEngine.charging.timeRemaining","vehicle.drivetrain.electricEngine.charging.timeToFullyCharged","vehicle.drivetrain.electricEngine.charging.hvStatus","vehicle.drivetrain.electricEngine.charging.method","vehicle.drivetrain.electricEngine.charging.phaseNumber","vehicle.drivetrain.electricEngine.charging.lastChargingReason","vehicle.drivetrain.electricEngine.charging.lastChargingResult","vehicle.drivetrain.electricEngine.charging.reasonChargingEnd","vehicle.powertrain.electric.battery.charging.power","vehicle.drivetrain.electricEngine.charging.acVoltage","vehicle.drivetrain.electricEngine.charging.acAmpere","vehicle.powertrain.electric.battery.charging.acLimit.selected","vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged","vehicle.powertrain.tractionBattery.charging.port.anyPosition.flap.isOpen","vehicle.body.chargingPort.lockedStatus","vehicle.body.chargingPort.plugEventId","vehicle.powertrain.electric.battery.preconditioning.automaticMode.statusFeedback","vehicle.powertrain.electric.battery.preconditioning.manualMode.statusFeedback","vehicle.vehicle.avgAuxPower","vehicle.trip.segment.end.drivetrain.batteryManagement.hvSoc","vehicle.trip.segment.accumulated.drivetrain.electricEngine.recuperationTotal","vehicle.vehicleIdentification.basicVehicleData"];u(ge,"tv");$n=class extends I{static{u(this,"BMWSkill")}metadata={name:"bmw",category:"infrastructure",description:'BMW CarData \u2014 Fahrzeugdaten abrufen. "authorize" startet den Device-Auth-Flow (einmalig). "status" zeigt SoC, Reichweite, Modell, Batterie-Gesundheit. "charging" zeigt Ladestatus, Leistung, Restzeit, Ziel-SoC, Stecker. "charging_sessions" listet Lade-Sessions (from/to Zeitraum). "consumption" berechnet Durchschnittsverbrauch (kWh/100km) aus Lade-Sessions \u2014 optional mit period: "last" (letzte Fahrt), "week", "month", "year", "all" (default: month).',riskLevel:"read",version:"2.1.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["authorize","status","charging","charging_sessions","consumption"],description:"BMW CarData action"},vin:{type:"string",description:"Vehicle Identification Number (optional \u2014 uses stored VIN if omitted)"},device_code:{type:"string",description:"Device code from authorize step 1 (for polling token in step 2)"},from:{type:"string",description:"ISO date-time start for charging_sessions (required for that action)"},to:{type:"string",description:"ISO date-time end for charging_sessions (required for that action)"},period:{type:"string",enum:["last","week","month","year","all"],description:"Zeitraum f\xFCr consumption: last (letzte Fahrt), week, month, year, all (default: month)"}},required:["action"]}};config;tokens=null;cache=new Map;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"authorize":return await this.authorize(e.device_code);case"status":return await this.getStatus(e.vin);case"charging":return await this.getCharging(e.vin);case"charging_sessions":return await this.getChargingSessions(e.vin,e.from,e.to);case"consumption":return await this.getConsumption(e.vin,e.period);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`BMW API error: ${r instanceof Error?r.message:String(r)}`}}}async authorize(e){if(e)return await this.pollToken(e);let t=Km(),s=Xm(t),r=await fetch(zm,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,response_type:"device_code",code_challenge:s,code_challenge_method:"S256",scope:Gm}),signal:AbortSignal.timeout(15e3)});if(!r.ok){let i=await r.text().catch(()=>"");throw new Error(`Device code request failed: HTTP ${r.status} \u2014 ${i.slice(0,300)}`)}let n=await r.json(),o={codeVerifier:t,deviceCode:n.device_code};return await this.savePartialTokens(o),this.tokens=null,{success:!0,data:n,display:["## BMW Autorisierung","",`1. \xD6ffne: **${n.verification_uri_complete??n.verification_uri}**`,`2. Gib diesen Code ein: **${n.user_code}**`,"",`Danach ruf diese Action erneut auf mit \`device_code: "${n.device_code}"\` um den Token abzuholen.`].join(`
|
|
707
707
|
`)}}async pollToken(e){let s=(await this.loadTokens())?.codeVerifier;if(!s)throw new Error('Kein code_verifier gefunden. Bitte zuerst "authorize" ohne device_code aufrufen.');let r=await fetch(yl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,device_code:e,grant_type:"urn:ietf:params:oauth:grant-type:device_code",code_verifier:s}),signal:AbortSignal.timeout(15e3)});if(!r.ok){let p=await r.text().catch(()=>"");if(p.includes("authorization_pending"))return{success:!0,data:{status:"pending"},display:"Autorisierung noch ausstehend \u2014 bitte zuerst im Browser best\xE4tigen, dann erneut versuchen."};throw new Error(`Token poll failed: HTTP ${r.status} \u2014 ${p.slice(0,300)}`)}let n=await r.json(),o=n.access_token,i={accessToken:o,refreshToken:n.refresh_token,idToken:n.id_token,expiresAt:Date.now()+(n.expires_in??3600)*1e3,vin:"",containerId:""},a=await this.fetchVin(o);i.vin=a,await this.saveTokens(i);let c="",d="";try{c=await this.ensureContainer(o),i.containerId=c,await this.saveTokens(i)}catch(p){d=p instanceof Error?p.message:String(p)}this.tokens=i;let m=["## BMW Autorisierung erfolgreich","",`**VIN:** ${a}`];return c?(m.push(`**Container:** ${c}`),m.push("Tokens gespeichert. Du kannst jetzt Fahrzeugdaten abrufen.")):(m.push(`**Container-Fehler:** ${d}`),m.push("Tokens + VIN gespeichert, aber Container konnte nicht erstellt werden."),m.push("Erstelle den Container manuell im BMW CarData Portal oder versuche es erneut.")),{success:c!=="",data:{vin:a,containerId:c,containerError:d||void 0},display:m.join(`
|
|
708
708
|
`)}}async fetchVin(e){let t=await fetch(`${bn}/customers/vehicles/mappings`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw new Error(`Failed to fetch vehicles: HTTP ${t.status}`);let s=await t.json();if(typeof s.vin=="string")return s.vin;if(Array.isArray(s)){let r=s;return r.find(o=>o.mappingType==="PRIMARY")?.vin??r[0]?.vin??(()=>{throw new Error("No vehicles found")})()}throw new Error(`No vehicles found in account (response: ${JSON.stringify(s).slice(0,200)})`)}async ensureContainer(e){let t=await fetch(`${bn}/customers/containers`,{headers:this.apiHeaders(e),signal:AbortSignal.timeout(15e3)});if(t.ok){let n=await t.json(),i=(Array.isArray(n)?n:Array.isArray(n.containers)?n.containers:[]).find(a=>a.name===wl);if(i)return i.containerId}let s=await fetch(`${bn}/customers/containers`,{method:"POST",headers:{...this.apiHeaders(e),"Content-Type":"application/json"},body:JSON.stringify({name:wl,purpose:"Alfred AI Assistant",technicalDescriptors:Ym}),signal:AbortSignal.timeout(15e3)});if(!s.ok){let n=await s.text().catch(()=>"");throw new Error(`Container creation failed: HTTP ${s.status} \u2014 ${n.slice(0,300)}`)}return(await s.json()).containerId}apiHeaders(e){return{Authorization:`Bearer ${e}`,"x-version":Wm,Accept:"application/json"}}async apiGet(e){let t=e,s=this.cache.get(t);if(s&&Date.now()-s.ts<Vm)return s.data;let r=await this.ensureToken(),n=`${bn}${e}`,o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)});if(o.status===401){let a=await this.loadTokens();a&&(r=await this.refreshAccessToken(a),o=await fetch(n,{headers:this.apiHeaders(r),signal:AbortSignal.timeout(15e3)}))}if(!o.ok){let a=await o.text().catch(()=>"");throw new Error(`HTTP ${o.status} \u2014 ${a.slice(0,300)}`)}let i=await o.json();return this.cache.set(t,{data:i,ts:Date.now()}),i}async loadTokens(){if(this.tokens)return this.tokens;try{let e=await hl(En,"utf-8");return this.tokens=JSON.parse(e),this.tokens}catch{return null}}async saveTokens(e){await gl(ui(di(),".alfred"),{recursive:!0}),await fl(En,JSON.stringify(e,null,2),"utf-8")}async savePartialTokens(e){await gl(ui(di(),".alfred"),{recursive:!0});let t={};try{let s=await hl(En,"utf-8");t=JSON.parse(s)}catch{}await fl(En,JSON.stringify({...t,...e},null,2),"utf-8")}async ensureToken(){let e=await this.loadTokens();if(!e?.accessToken)throw new Error('Nicht autorisiert. Bitte zuerst die "authorize"-Action aufrufen, um den BMW-Account zu verbinden.');return Date.now()>e.expiresAt-6e4?await this.refreshAccessToken(e):e.accessToken}async refreshAccessToken(e){let t=await fetch(yl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:this.config.clientId,grant_type:"refresh_token",refresh_token:e.refreshToken}),signal:AbortSignal.timeout(15e3)});if(!t.ok)throw this.tokens=null,new Error('Token-Refresh fehlgeschlagen. Bitte erneut "authorize" aufrufen.');let s=await t.json(),r={...e,accessToken:s.access_token,refreshToken:s.refresh_token??e.refreshToken,idToken:s.id_token??e.idToken,expiresAt:Date.now()+(s.expires_in??3600)*1e3};return delete r.codeVerifier,delete r.deviceCode,await this.saveTokens(r),this.tokens=r,r.accessToken}async resolveVin(e){if(e)return e;let t=await this.loadTokens();if(t?.vin)return t.vin;throw new Error('Keine VIN angegeben und keine gespeicherte VIN gefunden. Bitte zuerst "authorize" aufrufen.')}async resolveContainerId(){let e=await this.loadTokens();if(e?.containerId)return e.containerId;throw new Error('Kein Container gefunden. Bitte zuerst "authorize" aufrufen.')}async getStatus(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),[r,n]=await Promise.all([this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`),this.apiGet(`/customers/vehicles/${t}/basicData`)]),o=r.telematicData??{},i=ge(o,"vehicle.drivetrain.batteryManagement.header"),a=ge(o,"vehicle.drivetrain.electricEngine.remainingElectricRange"),c=ge(o,"vehicle.drivetrain.batteryManagement.maxEnergy"),d=ge(o,"vehicle.powertrain.electric.battery.stateOfHealth.displayed"),p=["## BMW Fahrzeugstatus","",`**Modell:** ${n.modelName??n.model??"?"}`,`**VIN:** ${t}`,`**Ladestand (SoC):** ${i} %`,`**Elektrische Reichweite:** ${a} km`,`**Batteriekapazit\xE4t:** ${c} kWh`,`**Batterie-Gesundheit (SoH):** ${d} %`];return{success:!0,data:{telematic:o,basic:n},display:p.join(`
|
|
709
|
-
`)}}async getCharging(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),n=(await this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`)).telematicData??{},o=ge(n,"vehicle.drivetrain.electricEngine.charging.status"),i=ge(n,"vehicle.drivetrain.batteryManagement.header"),a=ge(n,"vehicle.drivetrain.electricEngine.charging.level"),c=ge(n,"vehicle.drivetrain.electricEngine.charging.timeRemaining"),d=ge(n,"vehicle.powertrain.electric.battery.charging.power"),m=ge(n,"vehicle.drivetrain.electricEngine.charging.hvStatus"),p=ge(n,"vehicle.powertrain.electric.battery.stateOfCharge.target"),g=ge(n,"vehicle.drivetrain.electricEngine.charging.acVoltage"),f=ge(n,"vehicle.drivetrain.electricEngine.charging.acAmpere"),h=ge(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged"),
|
|
710
|
-
`)}}async getChargingSessions(e,t,s){let r=await this.resolveVin(e),n=new Date,o=s??n.toISOString(),i=t??new Date(n.getTime()-30*24*60*6e4).toISOString(),a=await this.apiGet(`/customers/vehicles/${r}/chargingHistory?from=${encodeURIComponent(i)}&to=${encodeURIComponent(o)}`),c=a.data??a.chargingSessions??[],d=[`## BMW Lade-Sessions (${i.slice(0,10)} \u2013 ${o.slice(0,10)})`,"","| Start | Ende | Dauer | Energie | Start-SoC | End-SoC | km-Stand | Ort |","|-------|------|-------|---------|-----------|---------|----------|-----|"];for(let m of c.slice(0,20)){let p=m.startTime,g=m.endTime,f=u(N=>new Date(N*1e3).toLocaleString("de-AT",{day:"2-digit",month:"2-digit",year:"2-digit",hour:"2-digit",minute:"2-digit"}),"fmtDateTime"),h=p?f(p):"-",
|
|
709
|
+
`)}}async getCharging(e){let t=await this.resolveVin(e),s=await this.resolveContainerId(),n=(await this.apiGet(`/customers/vehicles/${t}/telematicData?containerId=${s}`)).telematicData??{},o=ge(n,"vehicle.drivetrain.electricEngine.charging.status"),i=ge(n,"vehicle.drivetrain.batteryManagement.header"),a=ge(n,"vehicle.drivetrain.electricEngine.charging.level"),c=ge(n,"vehicle.drivetrain.electricEngine.charging.timeRemaining"),d=ge(n,"vehicle.powertrain.electric.battery.charging.power"),m=ge(n,"vehicle.drivetrain.electricEngine.charging.hvStatus"),p=ge(n,"vehicle.powertrain.electric.battery.stateOfCharge.target"),g=ge(n,"vehicle.drivetrain.electricEngine.charging.acVoltage"),f=ge(n,"vehicle.drivetrain.electricEngine.charging.acAmpere"),h=ge(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.isPlugged"),y=ge(n,"vehicle.powertrain.tractionBattery.charging.port.anyPosition.flap.isOpen"),E=ge(n,"vehicle.body.chargingPort.lockedStatus"),A=["## BMW Ladestatus","",`**Status:** ${o}`,`**Ladestand:** ${i} %`,`**Ladelevel:** ${a}`,`**Ladeleistung:** ${d} kW`,`**Restzeit:** ${c} min`,`**Ziel-SoC:** ${p} %`,`**HV-Batterie:** ${m}`,`**AC Spannung:** ${g} V`,`**AC Strom:** ${f} A`,`**Stecker eingesteckt:** ${h}`,`**Ladeklappe offen:** ${y}`,`**Ladeport-Schloss:** ${E}`];return{success:!0,data:n,display:A.join(`
|
|
710
|
+
`)}}async getChargingSessions(e,t,s){let r=await this.resolveVin(e),n=new Date,o=s??n.toISOString(),i=t??new Date(n.getTime()-30*24*60*6e4).toISOString(),a=await this.apiGet(`/customers/vehicles/${r}/chargingHistory?from=${encodeURIComponent(i)}&to=${encodeURIComponent(o)}`),c=a.data??a.chargingSessions??[],d=[`## BMW Lade-Sessions (${i.slice(0,10)} \u2013 ${o.slice(0,10)})`,"","| Start | Ende | Dauer | Energie | Start-SoC | End-SoC | km-Stand | Ort |","|-------|------|-------|---------|-----------|---------|----------|-----|"];for(let m of c.slice(0,20)){let p=m.startTime,g=m.endTime,f=u(N=>new Date(N*1e3).toLocaleString("de-AT",{day:"2-digit",month:"2-digit",year:"2-digit",hour:"2-digit",minute:"2-digit"}),"fmtDateTime"),h=p?f(p):"-",y=g?f(g):"-",E=m.totalChargingDurationSec,A=E!=null?Math.round(E/60):"-",R=m.energyConsumedFromPowerGridKwh??"-",F=m.displayedStartSoc??"-",x=m.displayedSoc??"-",G=m.mileage!=null?`${m.mileage}`:"-",ce=m.chargingLocation,se=ce?.formattedAddress??ce?.streetAddress??"-";d.push(`| ${h} | ${y} | ${A} min | ${R} kWh | ${F}% | ${x}% | ${G} | ${se} |`)}return c.length===0&&d.push("| - | - | Keine Sessions gefunden | - | - | - | - | - |"),{success:!0,data:a,display:d.join(`
|
|
711
711
|
`)}}async getConsumption(e,t){let s=await this.resolveVin(e),r=await this.resolveContainerId(),n=new Date,i={last:7,week:7,month:30,year:365,all:730}[t??"month"]??30,a=new Date(n.getTime()-i*864e5).toISOString(),c=n.toISOString(),[d,m]=await Promise.all([this.apiGet(`/customers/vehicles/${s}/chargingHistory?from=${encodeURIComponent(a)}&to=${encodeURIComponent(c)}`),this.apiGet(`/customers/vehicles/${s}/telematicData?containerId=${r}`)]),p=d.data??d.chargingSessions??[],g=parseFloat(ge(m.telematicData??{},"vehicle.drivetrain.batteryManagement.maxEnergy"))||63;if(p.length<2)return{success:!0,data:{sessions:p.length},display:"Nicht gen\xFCgend Lade-Sessions f\xFCr Verbrauchsberechnung (min. 2 n\xF6tig)."};let f=p.filter(N=>typeof N.mileage=="number"&&typeof N.displayedStartSoc=="number"&&typeof N.displayedSoc=="number").sort((N,K)=>N.mileage-K.mileage);if(f.length<2)return{success:!0,data:{sessions:f.length},display:"Nicht gen\xFCgend Lade-Sessions mit vollst\xE4ndigen Daten."};let h=[];for(let N=1;N<f.length;N++){let K=f[N-1],q=f[N],le=K.mileage,de=q.mileage,re=de-le;if(re<=0)continue;let ne=K.displayedSoc,D=q.displayedStartSoc,z=ne-D;if(z<=0)continue;let Te=z/100*g,Q=Te/re*100,Je=q.startTime,B=Je?new Date(Je*1e3).toLocaleDateString("de-AT"):"-";h.push({fromKm:le,toKm:de,distance:re,socUsed:z,kWhUsed:Te,consumption:Q,date:B})}if(h.length===0)return{success:!0,data:{},display:"Keine auswertbaren Fahrtabschnitte gefunden."};if(t==="last"){let N=h[h.length-1];return{success:!0,data:N,display:["## Letzte Fahrt (gesch\xE4tzt)","",`**Datum:** ${N.date}`,`**Strecke:** ${N.distance} km`,`**Verbrauch:** ${N.consumption.toFixed(1)} kWh/100km`,`**Energie:** ${N.kWhUsed.toFixed(1)} kWh (${N.socUsed}% SoC)`,`**km-Stand:** ${N.fromKm} \u2192 ${N.toKm}`].join(`
|
|
712
|
-
`)}}let
|
|
712
|
+
`)}}let y=h.reduce((N,K)=>N+K.distance,0),E=h.reduce((N,K)=>N+K.kWhUsed,0),A=E/y*100,R=h.map(N=>N.consumption).sort((N,K)=>N-K),F=R[0],x=R[R.length-1],G=R[Math.floor(R.length/2)],se=[`## BMW Verbrauchsstatistik \u2014 ${{week:"Letzte Woche",month:"Letzter Monat",year:"Letztes Jahr",all:"Gesamt"}[t??"month"]??"Letzter Monat"}`,"",`**Batteriekapazit\xE4t:** ${g} kWh`,`**Ausgewertete Fahrten:** ${h.length}`,`**Gesamtstrecke:** ${y.toLocaleString("de-AT")} km`,`**Gesamtverbrauch:** ${E.toFixed(1)} kWh`,"",`**Durchschnitt:** ${A.toFixed(1)} kWh/100km`,`**Min:** ${F.toFixed(1)} kWh/100km`,`**Max:** ${x.toFixed(1)} kWh/100km`,`**Median:** ${G.toFixed(1)} kWh/100km`,"","### Einzelne Fahrten","","| Datum | Strecke | Verbrauch | Energie |","|-------|---------|-----------|---------|"];for(let N of h)se.push(`| ${N.date} | ${N.distance} km | ${N.consumption.toFixed(1)} kWh/100km | ${N.kWhUsed.toFixed(1)} kWh |`);return{success:!0,data:{avgConsumption:A,totalDistance:y,totalKwh:E,segments:h},display:se.join(`
|
|
713
713
|
`)}}}});var Jm,kn,bl=_(()=>{"use strict";P();Jm="https://routes.googleapis.com/directions/v2:computeRoutes",kn=class extends I{static{u(this,"RoutingSkill")}metadata={name:"routing",category:"information",description:'Routenberechnung mit Live-Traffic via Google Routes API. "route" berechnet Route mit Distanz, Dauer und Dauer im aktuellen Verkehr. "departure_time" empfiehlt wann man losfahren soll, um zu einer bestimmten Zeit anzukommen. Orte als Adresse oder "lat,lng" angeben.',riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["route","departure_time"],description:"Routing action"},origin:{type:"string",description:'Start-Adresse oder "lat,lng"'},destination:{type:"string",description:'Ziel-Adresse oder "lat,lng"'},departure_time:{type:"string",description:"ISO-Zeitpunkt f\xFCr Abfahrt (optional, f\xFCr Traffic-Berechnung)"},arrival_time:{type:"string",description:"ISO-Zeitpunkt gew\xFCnschte Ankunft (f\xFCr departure_time-Action)"},travel_mode:{type:"string",enum:["DRIVE","BICYCLE","WALK","TRANSIT"],description:"Fortbewegungsart (Standard: DRIVE)"}},required:["action","origin","destination"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};let r=e.origin,n=e.destination;if(!r)return{success:!1,error:'Missing required field "origin"'};if(!n)return{success:!1,error:'Missing required field "destination"'};try{switch(s){case"route":return await this.computeRoute(r,n,e.departure_time,e.travel_mode);case"departure_time":return await this.computeDepartureTime(r,n,e.arrival_time,e.travel_mode);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(o){return{success:!1,error:`Google Routes API error: ${o instanceof Error?o.message:String(o)}`}}}async computeRoute(e,t,s,r){let n=this.buildRequestBody(e,t,r,s),i=(await this.callRoutesApi(n)).routes?.[0];if(!i)return{success:!1,error:"Keine Route gefunden."};let a=(i.distanceMeters/1e3).toFixed(1),c=this.parseDuration(i.duration),d=this.parseDuration(i.staticDuration),m=c-d,p=["## Route","",`**${e}** \u2192 **${t}**`,"",`**Distanz:** ${a} km`,`**Fahrzeit (aktuell):** ${this.formatMinutes(c)}`,`**Fahrzeit (ohne Verkehr):** ${this.formatMinutes(d)}`];if(m>1&&p.push(`**Verkehrsverz\xF6gerung:** +${this.formatMinutes(m)}`),s){let g=new Date(new Date(s).getTime()+c*6e4);p.push(`**Gesch\xE4tzte Ankunft:** ${g.toLocaleString("de-AT")}`)}return{success:!0,data:{distanceKm:parseFloat(a),durationMinutes:c,staticDurationMinutes:d},display:p.join(`
|
|
714
714
|
`)}}async computeDepartureTime(e,t,s,r){if(!s)return{success:!1,error:'Missing required field "arrival_time" for departure_time action'};let n=this.buildRequestBody(e,t,r),i=(await this.callRoutesApi(n)).routes?.[0];if(!i)return{success:!1,error:"Keine Route gefunden."};let a=this.parseDuration(i.duration),c=Math.max(5,Math.round(a*.15)),d=new Date(s),m=new Date(d.getTime()-(a+c)*6e4),p=["## Abfahrtszeit-Empfehlung","",`**Route:** ${e} \u2192 ${t}`,`**Gew\xFCnschte Ankunft:** ${d.toLocaleString("de-AT")}`,`**Gesch\xE4tzte Fahrzeit:** ${this.formatMinutes(a)} (inkl. Verkehr)`,`**Puffer:** ${c} min`,"",`**Empfohlene Abfahrt:** ${m.toLocaleString("de-AT")}`];return{success:!0,data:{departureTime:m.toISOString(),durationMinutes:a,bufferMinutes:c},display:p.join(`
|
|
715
|
-
`)}}buildWaypoint(e){let t=e.match(/^(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)$/);return t?{location:{latLng:{latitude:parseFloat(t[1]),longitude:parseFloat(t[2])}}}:{address:e}}normalizeTimestamp(e){let t=new Date(e);if(isNaN(t.getTime()))return e;if(/[Zz]|[+-]\d{2}:\d{2}$/.test(e))return t.toISOString();let s=t.getTimezoneOffset(),r=s<=0?"+":"-",n=Math.abs(s),o=String(Math.floor(n/60)).padStart(2,"0"),i=String(n%60).padStart(2,"0"),a=u(c=>String(c).padStart(2,"0"),"pad");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())}T${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}${r}${o}:${i}`}buildRequestBody(e,t,s,r,n){let o={origin:this.buildWaypoint(e),destination:this.buildWaypoint(t),travelMode:s??"DRIVE",routingPreference:"TRAFFIC_AWARE"};if(r){let i=this.normalizeTimestamp(r);new Date(i).getTime()>Date.now()+6e4&&(o.departureTime=i)}if(n){let i=this.normalizeTimestamp(n);new Date(i).getTime()>Date.now()+6e4&&(o.arrivalTime=i)}return o}async callRoutesApi(e){let t=await fetch(Jm,{method:"POST",headers:{"Content-Type":"application/json","X-Goog-Api-Key":this.config.apiKey,"X-Goog-FieldMask":"routes.duration,routes.staticDuration,routes.distanceMeters,routes.legs"},body:JSON.stringify(e),signal:AbortSignal.timeout(15e3)});if(!t.ok){let s=await t.text().catch(()=>"");throw new Error(`HTTP ${t.status} \u2014 ${s.slice(0,300)}`)}return await t.json()}parseDuration(e){let t=e?.match(/(\d+)s/);return t?Math.round(parseInt(t[1],10)/60):0}formatMinutes(e){if(e<60)return`${e} min`;let t=Math.floor(e/60),s=e%60;return s>0?`${t} h ${s} min`:`${t} h`}}});var El,$l,Zm,Qm,ep,is,kl,vl,Sl,mi,pi,Al,vn,Il=_(()=>{"use strict";P();El=1.5,$l=4.79,Zm=5.75,Qm=1.03,ep=new Date("2026-04-01T00:00:00+02:00"),is=1.2,kl=.1,vl=.58,Sl=.04,mi=.32,pi=1.62,Al="https://api.awattar.at/v1/marketdata",vn=class extends I{static{u(this,"EnergyPriceSkill")}metadata={name:"energy_price",category:"information",description:'Strompreise (aWATTar HOURLY Tarif, EPEX Spot AT). "current" zeigt den aktuellen Strompreis mit Aufschl\xFCsselung (Marktpreis, Netzentgelte, Abgaben, Brutto). "today" zeigt alle Stundenpreise f\xFCr heute. "tomorrow" zeigt Stundenpreise f\xFCr morgen (verf\xFCgbar ab ~14:00). "cheapest" findet die g\xFCnstigsten Stunden (Standard: 3 Stunden in den n\xE4chsten 24h). "average" zeigt den Durchschnittspreis f\xFCr heute oder ein bestimmtes Datum.',riskLevel:"read",version:"1.0.0",timeoutMs:15e3,inputSchema:{type:"object",properties:{action:{type:"string",enum:["current","today","tomorrow","cheapest","average"],description:"Aktion"},hours:{type:"number",description:"F\xFCr cheapest: Anzahl g\xFCnstigster Stunden (Standard: 3)"},date:{type:"string",description:"ISO-Datum f\xFCr average (Standard: heute)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"current":return await this.current();case"today":return await this.dayPrices("today");case"tomorrow":return await this.dayPrices("tomorrow");case"cheapest":return await this.cheapest(e.hours);case"average":return await this.average(e.date);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`aWATTar API error: ${r instanceof Error?r.message:String(r)}`}}}async current(){let e=Date.now(),s=(await this.fetchMarketData()).find(i=>i.start_timestamp<=e&&i.end_timestamp>e);if(!s)return{success:!1,error:"Kein Marktpreis f\xFCr die aktuelle Stunde verf\xFCgbar."};let r=this.calculatePrice(s.marketprice),o=[`## Aktueller Strompreis (${this.formatHourRange(s.start_timestamp,s.end_timestamp)})`,""];return o.push(this.formatBreakdown(r)),{success:!0,data:r,display:o.join(`
|
|
716
|
-
`)}}async dayPrices(e){let t=new Date,s=new Date(t);e==="tomorrow"&&s.setDate(s.getDate()+1);let r=new Date(s);r.setHours(0,0,0,0);let n=new Date(r);n.setDate(n.getDate()+1);let o=await this.fetchMarketData(r.getTime(),n.getTime());if(o.length===0)return{success:!1,error:`Keine Preisdaten f\xFCr ${e==="today"?"heute":"morgen"} verf\xFCgbar.${e==="tomorrow"?" Preise f\xFCr morgen sind ab ca. 14:00 verf\xFCgbar.":""}`};let i=e==="today"?"Heute":"Morgen",a=r.toLocaleDateString("de-AT"),c=[`## Strompreise ${i} (${a})`,""];c.push("| Uhrzeit | Markt ct/kWh | Brutto ct/kWh |"),c.push("|---|---|---|");let d=1/0,m=-1/0,p=0;for(let f of o){let h=this.calculatePrice(f.marketprice),
|
|
715
|
+
`)}}buildWaypoint(e){let t=e.match(/^(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)$/);return t?{location:{latLng:{latitude:parseFloat(t[1]),longitude:parseFloat(t[2])}}}:{address:e}}normalizeTimestamp(e){let t=new Date(e);if(isNaN(t.getTime()))return e;if(/[Zz]|[+-]\d{2}:\d{2}$/.test(e))return t.toISOString();let s=t.getTimezoneOffset(),r=s<=0?"+":"-",n=Math.abs(s),o=String(Math.floor(n/60)).padStart(2,"0"),i=String(n%60).padStart(2,"0"),a=u(c=>String(c).padStart(2,"0"),"pad");return`${t.getFullYear()}-${a(t.getMonth()+1)}-${a(t.getDate())}T${a(t.getHours())}:${a(t.getMinutes())}:${a(t.getSeconds())}${r}${o}:${i}`}buildRequestBody(e,t,s,r,n){let o={origin:this.buildWaypoint(e),destination:this.buildWaypoint(t),travelMode:s??"DRIVE",routingPreference:"TRAFFIC_AWARE"};if(r){let i=this.normalizeTimestamp(r);new Date(i).getTime()>Date.now()+6e4&&(o.departureTime=i)}if(n){let i=this.normalizeTimestamp(n);new Date(i).getTime()>Date.now()+6e4&&(o.arrivalTime=i)}return o}async callRoutesApi(e){let t=await fetch(Jm,{method:"POST",headers:{"Content-Type":"application/json","X-Goog-Api-Key":this.config.apiKey,"X-Goog-FieldMask":"routes.duration,routes.staticDuration,routes.distanceMeters,routes.legs"},body:JSON.stringify(e),signal:AbortSignal.timeout(15e3)});if(!t.ok){let s=await t.text().catch(()=>"");throw new Error(`HTTP ${t.status} \u2014 ${s.slice(0,300)}`)}return await t.json()}parseDuration(e){let t=e?.match(/(\d+)s/);return t?Math.round(parseInt(t[1],10)/60):0}formatMinutes(e){if(e<60)return`${e} min`;let t=Math.floor(e/60),s=e%60;return s>0?`${t} h ${s} min`:`${t} h`}}});var El,$l,Zm,Qm,ep,is,kl,vl,Sl,mi,pi,Al,vn,Il=_(()=>{"use strict";P();El=1.5,$l=4.79,Zm=5.75,Qm=1.03,ep=new Date("2026-04-01T00:00:00+02:00"),is=1.2,kl=.1,vl=.58,Sl=.04,mi=.32,pi=1.62,Al="https://api.awattar.at/v1/marketdata",vn=class extends I{static{u(this,"EnergyPriceSkill")}metadata={name:"energy_price",category:"information",description:'Strompreise (aWATTar HOURLY Tarif, EPEX Spot AT). "current" zeigt den aktuellen Strompreis mit Aufschl\xFCsselung (Marktpreis, Netzentgelte, Abgaben, Brutto). "today" zeigt alle Stundenpreise f\xFCr heute. "tomorrow" zeigt Stundenpreise f\xFCr morgen (verf\xFCgbar ab ~14:00). "cheapest" findet die g\xFCnstigsten Stunden (Standard: 3 Stunden in den n\xE4chsten 24h). "average" zeigt den Durchschnittspreis f\xFCr heute oder ein bestimmtes Datum.',riskLevel:"read",version:"1.0.0",timeoutMs:15e3,inputSchema:{type:"object",properties:{action:{type:"string",enum:["current","today","tomorrow","cheapest","average","briefing"],description:"Aktion (briefing = kompakte Tages\xFCbersicht f\xFCr Morgenbriefing)"},hours:{type:"number",description:"F\xFCr cheapest: Anzahl g\xFCnstigster Stunden (Standard: 3)"},date:{type:"string",description:"ISO-Datum f\xFCr average (Standard: heute)"}},required:["action"]}};config;constructor(e){super(),this.config=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"current":return await this.current();case"today":return await this.dayPrices("today");case"tomorrow":return await this.dayPrices("tomorrow");case"cheapest":return await this.cheapest(e.hours);case"average":return await this.average(e.date);case"briefing":return await this.briefingSummary();default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`aWATTar API error: ${r instanceof Error?r.message:String(r)}`}}}async current(){let e=Date.now(),s=(await this.fetchMarketData()).find(i=>i.start_timestamp<=e&&i.end_timestamp>e);if(!s)return{success:!1,error:"Kein Marktpreis f\xFCr die aktuelle Stunde verf\xFCgbar."};let r=this.calculatePrice(s.marketprice),o=[`## Aktueller Strompreis (${this.formatHourRange(s.start_timestamp,s.end_timestamp)})`,""];return o.push(this.formatBreakdown(r)),{success:!0,data:r,display:o.join(`
|
|
716
|
+
`)}}async dayPrices(e){let t=new Date,s=new Date(t);e==="tomorrow"&&s.setDate(s.getDate()+1);let r=new Date(s);r.setHours(0,0,0,0);let n=new Date(r);n.setDate(n.getDate()+1);let o=await this.fetchMarketData(r.getTime(),n.getTime());if(o.length===0)return{success:!1,error:`Keine Preisdaten f\xFCr ${e==="today"?"heute":"morgen"} verf\xFCgbar.${e==="tomorrow"?" Preise f\xFCr morgen sind ab ca. 14:00 verf\xFCgbar.":""}`};let i=e==="today"?"Heute":"Morgen",a=r.toLocaleDateString("de-AT"),c=[`## Strompreise ${i} (${a})`,""];c.push("| Uhrzeit | Markt ct/kWh | Brutto ct/kWh |"),c.push("|---|---|---|");let d=1/0,m=-1/0,p=0;for(let f of o){let h=this.calculatePrice(f.marketprice),y=this.formatHourRange(f.start_timestamp,f.end_timestamp),E=this.spotCtKwh(f.marketprice);c.push(`| ${y} | ${E.toFixed(2)} | ${h.bruttoCt.toFixed(2)} |`),d=Math.min(d,h.bruttoCt),m=Math.max(m,h.bruttoCt),p+=h.bruttoCt}let g=p/o.length;return c.push(""),c.push(`**Min:** ${d.toFixed(2)} ct/kWh | **Max:** ${m.toFixed(2)} ct/kWh | **\xD8:** ${g.toFixed(2)} ct/kWh`),{success:!0,data:{entries:o.length,min:d,max:m,avg:g},display:c.join(`
|
|
717
717
|
`)}}async cheapest(e){let t=e??3,s=Date.now(),r=s+24*60*60*1e3,n=await this.fetchMarketData(s,r);if(n.length===0)return{success:!1,error:"Keine Preisdaten f\xFCr die n\xE4chsten 24 Stunden verf\xFCgbar."};let o=n.map(c=>({entry:c,breakdown:this.calculatePrice(c.marketprice)}));o.sort((c,d)=>c.breakdown.bruttoCt-d.breakdown.bruttoCt);let i=o.slice(0,Math.min(t,o.length));i.sort((c,d)=>c.entry.start_timestamp-d.entry.start_timestamp);let a=[`## ${t} g\xFCnstigste Stunden (n\xE4chste 24h)`,""];for(let{entry:c,breakdown:d}of i){let m=this.formatHourRange(c.start_timestamp,c.end_timestamp),p=new Date(c.start_timestamp).toLocaleDateString("de-AT",{weekday:"short"});a.push(`- **${p} ${m}**: ${d.bruttoCt.toFixed(2)} ct/kWh brutto (Markt: ${this.spotCtKwh(c.marketprice).toFixed(2)} ct/kWh)`)}return{success:!0,data:i.map(c=>({time:this.formatHourRange(c.entry.start_timestamp,c.entry.end_timestamp),bruttoCt:c.breakdown.bruttoCt})),display:a.join(`
|
|
718
718
|
`)}}async average(e){let t;e?(t=new Date(e),t.setHours(0,0,0,0)):(t=new Date,t.setHours(0,0,0,0));let s=new Date(t);s.setDate(s.getDate()+1);let r=await this.fetchMarketData(t.getTime(),s.getTime());if(r.length===0)return{success:!1,error:`Keine Preisdaten f\xFCr ${t.toLocaleDateString("de-AT")} verf\xFCgbar.`};let n=0,o=0;for(let m of r)n+=this.spotCtKwh(m.marketprice),o+=this.calculatePrice(m.marketprice).bruttoCt;let i=n/r.length,a=o/r.length,c=t.toLocaleDateString("de-AT"),d=[`## Durchschnittspreis ${c}`,"",`**\xD8 Marktpreis:** ${i.toFixed(2)} ct/kWh`,`**\xD8 Brutto-Gesamtpreis:** ${a.toFixed(2)} ct/kWh`,"",`Basierend auf ${r.length} Stundenwerten.`];return{success:!0,data:{date:c,avgSpotCt:i,avgBruttoCt:a,hours:r.length},display:d.join(`
|
|
719
|
+
`)}}async briefingSummary(){let e=Date.now(),t=new Date;t.setHours(0,0,0,0);let s=new Date(t);s.setDate(s.getDate()+1);let r=await this.fetchMarketData(t.getTime(),s.getTime());if(r.length===0)return{success:!1,error:"Keine Preisdaten f\xFCr heute verf\xFCgbar."};let n=r.map(y=>({time:this.formatHourRange(y.start_timestamp,y.end_timestamp),bruttoCt:this.calculatePrice(y.marketprice).bruttoCt,start:y.start_timestamp,isCurrent:y.start_timestamp<=e&&y.end_timestamp>e,isPast:y.end_timestamp<=e})),o=n.find(y=>y.isCurrent),i=n.filter(y=>!y.isPast),a=n.map(y=>y.bruttoCt),c=a.reduce((y,E)=>y+E,0)/a.length,d=Math.min(...a),m=Math.max(...a),p=[...i].sort((y,E)=>y.bruttoCt-E.bruttoCt),g=p.slice(0,3),f=p.slice(-3).reverse(),h=[];o&&h.push(`**Aktuell (${o.time}):** ${o.bruttoCt.toFixed(2)} ct/kWh brutto`),h.push(`**Tagesdurchschnitt:** ${c.toFixed(2)} ct/kWh | **Min:** ${d.toFixed(2)} | **Max:** ${m.toFixed(2)}`),h.push(""),h.push("**G\xFCnstigste 3 Stunden (Rest des Tages):**");for(let y of g)h.push(`- ${y.time}: ${y.bruttoCt.toFixed(2)} ct/kWh`);h.push(""),h.push("**Teuerste 3 Stunden (Rest des Tages):**");for(let y of f)h.push(`- ${y.time}: ${y.bruttoCt.toFixed(2)} ct/kWh`);return{success:!0,data:{currentCt:o?.bruttoCt,avgCt:c,minCt:d,maxCt:m,cheapest:g.map(y=>({time:y.time,bruttoCt:y.bruttoCt})),expensive:f.map(y=>({time:y.time,bruttoCt:y.bruttoCt}))},display:h.join(`
|
|
719
720
|
`)}}spotCtKwh(e){return e/10}calculatePrice(e){let t=this.spotCtKwh(e),s=new Date<ep,n=(s?t*Qm:t)+El,o=this.getGridCosts(),i=o.usageCt+o.lossCt,a=kl+vl+Sl,c=n+i+a,d=c*is;return{spotCt:t,ausgleichCt:s?t*.03:0,aufschlagCt:El,energieNettoCt:n,netznutzungCt:o.usageCt,netzverlustCt:o.lossCt,eAbgabeCt:kl,oekoArbeitCt:vl,oekoVerlustCt:Sl,gesamtNettoCt:c,ustCt:c*.2,bruttoCt:d,gridName:o.name,hasGrid:o.usageCt>0}}getGridCosts(){let e=this.config?.gridUsageCt??0,t=this.config?.gridLossCt??0,s=this.config?.gridName??"";return e>0?{name:s,usageCt:e,lossCt:t}:{name:"",usageCt:0,lossCt:0}}formatBreakdown(e){let t=["| Komponente | ct/kWh |","|---|---:|",`| EPEX Spot Marktpreis | ${e.spotCt.toFixed(2)} |`];e.ausgleichCt>0&&t.push(`| Ausgleichsenergie (3%) | ${e.ausgleichCt.toFixed(2)} |`),t.push(`| aWATTar Aufschlag | ${e.aufschlagCt.toFixed(2)} |`),t.push(`| **Energie netto** | **${e.energieNettoCt.toFixed(2)}** |`),e.hasGrid&&(t.push(`| Netznutzung (${e.gridName}) | ${e.netznutzungCt.toFixed(2)} |`),t.push(`| Netzverlust | ${e.netzverlustCt.toFixed(2)} |`)),t.push(`| Elektrizit\xE4tsabgabe | ${e.eAbgabeCt.toFixed(2)} |`),t.push(`| \xD6kostrom-F\xF6rderbeitrag | ${e.oekoArbeitCt.toFixed(2)} |`),t.push(`| \xD6kostrom-Verlust | ${e.oekoVerlustCt.toFixed(2)} |`),t.push(`| **Gesamt netto** | **${e.gesamtNettoCt.toFixed(2)}** |`),t.push(`| USt (20%) | ${e.ustCt.toFixed(2)} |`),t.push(`| **Gesamt brutto** | **${e.bruttoCt.toFixed(2)}** |`),e.hasGrid||(t.push(""),t.push("*Netzentgelte nicht inkludiert \u2014 Netzkosten via `alfred setup` oder ENV konfigurieren*"));let s=this.config?.gridCapacityFee??0,r=this.config?.gridMeterFee??0;if(t.push(""),t.push("**Fixe Monatskosten (netto \u2192 brutto):**"),t.push(`- aWATTar Grundgeb\xFChr: ${$l.toFixed(2)} \u20AC \u2192 ${Zm.toFixed(2)} \u20AC`),s>0){let i=this.config?.gridName?` (${this.config.gridName})`:"";t.push(`- Leistungspauschale${i}: ${s.toFixed(2)} \u20AC \u2192 ${(s*is).toFixed(2)} \u20AC`)}r>0&&t.push(`- Messentgelt: ${r.toFixed(2)} \u20AC \u2192 ${(r*is).toFixed(2)} \u20AC`),t.push(`- \xD6kostrom-F\xF6rderpauschale: ${mi.toFixed(2)} \u20AC \u2192 ${(mi*is).toFixed(2)} \u20AC`),t.push(`- Erneuerbaren-F\xF6rderpauschale: ${pi.toFixed(2)} \u20AC \u2192 ${(pi*is).toFixed(2)} \u20AC`);let n=$l+mi+pi+s+r,o=n*is;return t.push(`- **Summe:** ${n.toFixed(2)} \u20AC \u2192 **${o.toFixed(2)} \u20AC brutto/Monat**`),t.join(`
|
|
720
721
|
`)}async fetchMarketData(e,t){let s=new URLSearchParams;e!=null&&s.set("start",e.toString()),t!=null&&s.set("end",t.toString());let r=s.toString()?`${Al}?${s}`:Al,n=await fetch(r,{signal:AbortSignal.timeout(1e4)});if(!n.ok){let i=await n.text().catch(()=>"");throw new Error(`HTTP ${n.status} \u2014 ${i.slice(0,300)}`)}return(await n.json()).data||[]}formatHourRange(e,t){let s=new Date(e).toLocaleTimeString("de-AT",{hour:"2-digit",minute:"2-digit"}),r=new Date(t).toLocaleTimeString("de-AT",{hour:"2-digit",minute:"2-digit"});return`${s}\u2013${r}`}}});var as,xl=_(()=>{"use strict";P();as=class extends I{static{u(this,"TransitSkill")}metadata={name:"transit_search",category:"information",description:'\xD6ffentlicher Nahverkehr in \xD6sterreich (\xD6BB, Wiener Linien, etc.). "search_stop" sucht Haltestellen nach Name. "journeys" berechnet Verbindungen zwischen zwei Orten (Name oder Stop-ID). "departures" zeigt Abfahrten an einer Haltestelle (Stop-ID erforderlich, zuerst search_stop verwenden). Deckt Busse, Stra\xDFenbahnen, U-Bahn, S-Bahn, Regionalz\xFCge und Fernz\xFCge ab.',riskLevel:"read",version:"1.0.0",timeoutMs:3e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["journeys","departures","search_stop"],description:"Transit action"},query:{type:"string",description:"Haltestellenname f\xFCr search_stop"},from:{type:"string",description:"Start-Haltestelle (Name oder ID) f\xFCr journeys"},to:{type:"string",description:"Ziel-Haltestelle (Name oder ID) f\xFCr journeys"},stop_id:{type:"string",description:"Stop-ID f\xFCr departures (von search_stop erhalten)"},departure:{type:"string",description:"ISO-Zeitpunkt f\xFCr gew\xFCnschte Abfahrt (optional)"},arrival:{type:"string",description:"ISO-Zeitpunkt f\xFCr gew\xFCnschte Ankunft (optional, nur f\xFCr journeys)"},results:{type:"number",description:"Anzahl Ergebnisse (Standard: 3)"},duration:{type:"number",description:"Zeitfenster in Minuten f\xFCr departures (Standard: 30)"}},required:["action"]}};client;constructor(e){super(),this.client=e}async execute(e,t){let s=e.action;if(!s)return{success:!1,error:'Missing required field "action"'};try{switch(s){case"search_stop":return await this.searchStop(e);case"journeys":return await this.findJourneys(e);case"departures":return await this.findDepartures(e);default:return{success:!1,error:`Unknown action "${s}"`}}}catch(r){return{success:!1,error:`Transit API error: ${r instanceof Error?r.message:String(r)}`}}}async searchStop(e){let t=e.query;if(!t)return{success:!1,error:'Missing required field "query" for search_stop'};let s=await this.client.searchStops(t);if(s.length===0)return{success:!0,data:[],display:`Keine Haltestellen gefunden f\xFCr "${t}".`};let r=["## Haltestellen",""];for(let n of s.slice(0,10))r.push(`- **${n.name}** (ID: \`${n.id}\`)`);return{success:!0,data:s,display:r.join(`
|
|
721
722
|
`)}}async findJourneys(e){let t=e.from,s=e.to;if(!t)return{success:!1,error:'Missing required field "from" for journeys'};if(!s)return{success:!1,error:'Missing required field "to" for journeys'};let r={};e.departure&&(r.departure=new Date(e.departure)),e.arrival&&(r.arrival=new Date(e.arrival)),e.results&&(r.results=e.results);let n=await this.client.journeys(t,s,r);if(n.length===0)return{success:!0,data:[],display:`Keine Verbindungen gefunden von ${t} nach ${s}.`};let o=[`## Verbindungen: ${t} \u2192 ${s}`,""];for(let i=0;i<n.length;i++){let a=n[i],c=this.formatTime(a.departure),d=this.formatTime(a.arrival);o.push(`### Verbindung ${i+1}: ${c} \u2192 ${d} (${a.duration} min, ${a.transfers} Umstieg${a.transfers!==1?"e":""})`);for(let m of a.legs)m.walking?o.push(` - \u{1F6B6} Fu\xDFweg \u2192 ${m.destination} (${this.formatTime(m.departure)}\u2013${this.formatTime(m.arrival)})`):o.push(` - ${m.line||m.mode} Ri. ${m.direction||m.destination}: ${m.origin} ${this.formatTime(m.departure)} \u2192 ${m.destination} ${this.formatTime(m.arrival)}`);o.push("")}return{success:!0,data:n,display:o.join(`
|
|
@@ -746,11 +747,11 @@ ${s.join(`
|
|
|
746
747
|
`)}}async handleCompare(e,t){let r=(await this.searchAll(e,t)).flatMap(d=>d.listings),n=r.map(d=>d.price).filter(d=>d!=null);if(n.length===0)return{success:!0,data:`Keine Inserate mit Preisangabe gefunden f\xFCr "${t.query}".`};let i=r.filter(d=>d.price!=null).sort((d,m)=>d.price-m.price).slice(0,5),a=n.reduce((d,m)=>d+m,0)/n.length,c=[];c.push(`**Preisvergleich** "${t.query}" \u2014 ${r.length} Inserate (${n.length} mit Preis)
|
|
747
748
|
`),c.push("| Statistik | Wert |"),c.push("|-----------|------|"),c.push(`| Anzahl | ${n.length} |`),c.push(`| Minimum | ${Math.min(...n).toFixed(2)} EUR |`),c.push(`| Maximum | ${Math.max(...n).toFixed(2)} EUR |`),c.push(`| Median | ${Pl(n).toFixed(2)} EUR |`),c.push(`| Durchschnitt | ${a.toFixed(2)} EUR |`),c.push(""),c.push(`**G\xFCnstigste 5:**
|
|
748
749
|
`),c.push("| # | Titel | Preis | Standort | Plattform | Link |"),c.push("|---|-------|-------|----------|-----------|------|");for(let d=0;d<i.length;d++){let m=i[d],p=m.title.length>60?m.title.slice(0,57)+"...":m.title;c.push(`| ${d+1} | ${p} | ${Ul(m.price,m.currency)} | ${m.location??"\u2014"} | ${m.platform} | [Link](${m.url}) |`)}return{success:!0,data:c.join(`
|
|
749
|
-
`)}}async searchAll(e,t){return await Promise.all(e.map(r=>r.search(t).catch(n=>({listings:[],totalCount:0,query:t.query,platform:r.platform,error:String(n)}))))}}});var jl=_(()=>{"use strict";Fl();In();fi();gi()});function rp(l){let e=l.split(",").map(s=>s.trim());for(let s of e){let r=s.match(/^\d{4,5}\s+(.+)/);if(r)return r[1].trim()}return e.length>=3?e[e.length-2]:e[e.length-1]}function
|
|
750
|
+
`)}}async searchAll(e,t){return await Promise.all(e.map(r=>r.search(t).catch(n=>({listings:[],totalCount:0,query:t.query,platform:r.platform,error:String(n)}))))}}});var jl=_(()=>{"use strict";Fl();In();fi();gi()});function rp(){let l=new Date,e=new Date(l.getFullYear(),l.getMonth(),l.getDate()),t=new Date(e.getTime()+24*60*60*1e3);return{start:e.toISOString(),end:t.toISOString()}}function np(l){let e=l.split(",").map(s=>s.trim());for(let s of e){let r=s.match(/^\d{4,5}\s+(.+)/);if(r)return r[1].trim()}return e.length>=3?e[e.length-2]:e[e.length-1]}function op(){let l=new Date().getDay();return l>=1&&l<=5}var yi,xn,Bl=_(()=>{"use strict";P();Ne();u(rp,"todayRange");yi=[{name:"calendar",skill:"calendar",input:{action:"list_events"},label:"Kalender"},{name:"weather",skill:"weather",input:{},label:"Wetter"},{name:"todo",skill:"todo",input:{action:"list"},label:"Lokale Todos"},{name:"mstodo",skill:"microsoft_todo",input:{action:"list_tasks"},label:"Microsoft To Do"},{name:"email",skill:"email",input:{action:"inbox"},label:"E-Mail"},{name:"energy",skill:"energy_price",input:{action:"briefing"},label:"Strompreise"},{name:"bmw",skill:"bmw",input:{action:"status"},label:"BMW Status"},{name:"home",skill:"homeassistant",input:{action:"briefing_summary"},label:"Smart Home"},{name:"infra",skill:"monitor",input:{},label:"Infrastruktur"}];u(np,"extractCity");u(op,"isWeekday");xn=class extends I{static{u(this,"BriefingSkill")}skillRegistry;alfredConfig;memoryRepo;metadata={name:"briefing",category:"productivity",description:'T\xE4gliches Morgenbriefing \u2014 sammelt Daten aus mehreren Skills parallel und liefert ein strukturiertes Ergebnis: Kalender, Wetter, Todos, E-Mails, Strompreise, Auto-Status, Smart Home, Infrastruktur. Mo\u2013Fr automatisch: Pendelzeit Heim\u2192B\xFCro + BMW-Akkucheck (wenn kein ausw\xE4rtiger Termin). "run" f\xFChrt das Briefing aus (optional mit location f\xFCr Wetter). "modules" zeigt verf\xFCgbare und aktive Module.',riskLevel:"read",version:"1.1.0",timeoutMs:6e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","modules"],description:"run = Briefing ausf\xFChren, modules = verf\xFCgbare Module anzeigen"},location:{type:"string",description:'Ort f\xFCr Wetterabfrage (default: aus Config oder "Vienna")'},modules:{type:"array",items:{type:"string"},description:"Optionale Liste aktiver Module (default: alle verf\xFCgbaren)"}},required:["action"]}};constructor(e,t,s){super(),this.skillRegistry=e,this.alfredConfig=t,this.memoryRepo=s}async execute(e,t){let s=e.action??"run";switch(s){case"run":return this.runBriefing(e,t);case"modules":return this.showModules();default:return{success:!1,error:`Unbekannte Aktion: ${s}`}}}getAvailableModules(){return yi.filter(e=>this.skillRegistry.has(e.skill))}showModules(){let e=this.getAvailableModules(),t=yi.map(n=>`${e.some(i=>i.name===n.name)?"\u2705":"\u274C"} ${n.name} (${n.label}) \u2192 ${n.skill}`),s=this.skillRegistry.has("routing"),r=!!(this.alfredConfig.briefing?.homeAddress&&this.alfredConfig.briefing?.officeAddress);return{success:!0,data:{available:e.map(n=>n.name),all:yi.map(n=>n.name),commuteAvailable:s,commuteConfigured:r},display:`Briefing-Module:
|
|
750
751
|
${t.join(`
|
|
751
752
|
`)}
|
|
752
753
|
|
|
753
|
-
Pendler-Check (Mo\u2013Fr): ${s?r?"\u2705 konfiguriert (Config)":"\u23F3 Adressen werden aus Memories gelesen (oder ALFRED_BRIEFING_HOME/OFFICE_ADDRESS setzen)":"\u274C Routing-Skill nicht verf\xFCgbar"}`}}async runBriefing(e,t){let{home:s}=this.resolveAddresses(t),r=e.location??this.alfredConfig.briefing?.location??(s?
|
|
754
|
+
Pendler-Check (Mo\u2013Fr): ${s?r?"\u2705 konfiguriert (Config)":"\u23F3 Adressen werden aus Memories gelesen (oder ALFRED_BRIEFING_HOME/OFFICE_ADDRESS setzen)":"\u274C Routing-Skill nicht verf\xFCgbar"}`}}async runBriefing(e,t){let{home:s}=this.resolveAddresses(t),r=e.location??this.alfredConfig.briefing?.location??(s?np(s):void 0)??"Vienna",n=e.modules,o=this.getAvailableModules();n?.length&&(o=o.filter(p=>n.includes(p.name)));let i=this.resolveHaPreferences(t),a=o.map(p=>{let g={...p.input};if(p.name==="calendar"){let{start:f,end:h}=rp();g.start=f,g.end=h}return p.name==="weather"&&(g.location=r),p.name==="home"&&(i.entities?.length&&(g.entities=i.entities),i.domains?.length&&(g.domains=i.domains)),{module:p,input:g}}),c=await Promise.all(a.map(p=>this.executeModule(p.module,p.input,t))),d=await this.runCommuteCheck(c,t);d&&c.push(d);let m=[];m.push(`**Morgenbriefing** \u2014 ${new Date().toLocaleDateString("de-AT",{weekday:"long",year:"numeric",month:"long",day:"numeric"})}
|
|
754
755
|
`);for(let p of c)p.success&&p.display?m.push(`### ${p.label}
|
|
755
756
|
${p.display}
|
|
756
757
|
`):p.success&&p.data?m.push(`### ${p.label}
|
|
@@ -758,21 +759,21 @@ ${typeof p.data=="string"?p.data:JSON.stringify(p.data,null,2)}
|
|
|
758
759
|
`):!p.success&&p.error&&m.push(`### ${p.label}
|
|
759
760
|
\u26A0\uFE0F ${p.error}
|
|
760
761
|
`);return{success:!0,data:c,display:m.join(`
|
|
761
|
-
`)}}async executeModule(e,t,s){try{let r=this.skillRegistry.get(e.skill);if(!r)return{module:e.name,label:e.label,success:!1,error:"Skill nicht gefunden"};let n=await r.execute(t,s);return{module:e.name,label:e.label,success:n.success,data:n.data,display:n.display,error:n.error}}catch(r){return{module:e.name,label:e.label,success:!1,error:String(r instanceof Error?r.message:r)}}}async runCommuteCheck(e,t){if(!
|
|
762
|
+
`)}}async executeModule(e,t,s){try{let r=this.skillRegistry.get(e.skill);if(!r)return{module:e.name,label:e.label,success:!1,error:"Skill nicht gefunden"};let n=await r.execute(t,s);return{module:e.name,label:e.label,success:n.success,data:n.data,display:n.display,error:n.error}}catch(r){return{module:e.name,label:e.label,success:!1,error:String(r instanceof Error?r.message:r)}}}async runCommuteCheck(e,t){if(!op()||!this.skillRegistry.has("routing"))return null;let{home:s,office:r}=this.resolveAddresses(t);if(!s||!r)return null;let n=e.find(m=>m.module==="calendar");if(n?.success&&n.data&&this.detectExternalAppointment(n.data))return null;let o=[];o.push(this.executeModule({name:"commute",skill:"routing",input:{},label:"Pendelzeit"},{action:"route",origin:s,destination:r},t));let a=(await Promise.all(o))[0],c=e.find(m=>m.module==="bmw"),d=[];if(a.success&&a.display?d.push(`**Route Heim \u2192 B\xFCro:**
|
|
762
763
|
${a.display}`):a.error&&d.push(`**Route:** \u26A0\uFE0F ${a.error}`),c?.success&&c.data){let m=this.extractBatteryLevel(c.data);m!=null&&m<30?d.push(`
|
|
763
764
|
\u26A0\uFE0F **BMW Akku niedrig (${m}%)** \u2014 Laden vor der Fahrt empfohlen!`):m!=null&&d.push(`
|
|
764
765
|
\u{1F50B} BMW Akku: ${m}% \u2014 ausreichend f\xFCr den Arbeitsweg`)}return d.length===0?null:{module:"commute",label:"Arbeitsweg (Mo\u2013Fr)",success:!0,data:{route:a.data,bmwBattery:this.extractBatteryLevel(c?.data)},display:d.join(`
|
|
765
|
-
`)}}resolveAddresses(e){let t=this.alfredConfig.briefing?.homeAddress,s=this.alfredConfig.briefing?.officeAddress;if(!this.memoryRepo)return{home:t,office:s};let r=t,n=s;for(let o of W(e)){let i=this.memoryRepo.search(o,"adresse");for(let a of i){let c=a.key.toLowerCase(),d=a.value;!r&&/heim|home|wohn|zuhause|privat/.test(c)&&(r=d),!n&&/büro|office|arbeit|firma|work/.test(c)&&(n=d)}if(r&&n)break}return{home:r,office:n}}resolveHaPreferences(e){let t=this.alfredConfig.briefing?.homeAssistant?.entities,s=this.alfredConfig.briefing?.homeAssistant?.domains;if(t?.length||s?.length)return{entities:t,domains:s};if(!this.memoryRepo)return{};for(let r of W(e)){let n=this.memoryRepo.search(r,"briefing");for(let o of n){let i=o.key.toLowerCase();if(/ha_entit|home.?assistant.*entit|briefing.*entit/.test(i)){let a=o.value.split(/[,;]\s*/).map(c=>c.trim()).filter(Boolean);if(a.length)return{entities:a}}if(/ha_domain|home.?assistant.*domain|briefing.*domain/.test(i)){let a=o.value.split(/[,;]\s*/).map(c=>c.trim()).filter(Boolean);if(a.length)return{domains:a}}}}return{}}detectExternalAppointment(e){return Array.isArray(e)?e.some(t=>{let s=t.location??t.loc??"";return!s||typeof s!="string"||/teams|zoom|meet\.google|webex|skype/i.test(s)?!1:s.trim().length>0}):!1}extractBatteryLevel(e){if(!e||typeof e!="object")return null;let t=e,s=t.chargingLevelPercent??t.batterySoc??t.soc??t.chargingState?.chargingLevelPercent;if(typeof s=="number")return s;if(typeof s=="string"){let r=parseFloat(s);return isNaN(r)?null:r}return null}}});import{spawn as
|
|
766
|
-
`+l.slice(-ql)}function zl(l){let e=new Map;function t(s){let r;try{r=Hl.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(
|
|
767
|
-
`).pop();R&&t.onProgress(`[${l.name}] ${R}`)}}),l.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",E=>{clearTimeout(
|
|
768
|
-
`+E.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var
|
|
766
|
+
`)}}resolveAddresses(e){let t=this.alfredConfig.briefing?.homeAddress,s=this.alfredConfig.briefing?.officeAddress;if(!this.memoryRepo)return{home:t,office:s};let r=t,n=s;for(let o of W(e)){let i=this.memoryRepo.search(o,"adresse");for(let a of i){let c=a.key.toLowerCase(),d=a.value;!r&&/heim|home|wohn|zuhause|privat/.test(c)&&(r=d),!n&&/büro|office|arbeit|firma|work/.test(c)&&(n=d)}if(r&&n)break}return{home:r,office:n}}resolveHaPreferences(e){let t=this.alfredConfig.briefing?.homeAssistant?.entities,s=this.alfredConfig.briefing?.homeAssistant?.domains;if(t?.length||s?.length)return{entities:t,domains:s};if(!this.memoryRepo)return{};for(let r of W(e)){let n=this.memoryRepo.search(r,"briefing");for(let o of n){let i=o.key.toLowerCase();if(/ha_entit|home.?assistant.*entit|briefing.*entit/.test(i)){let a=o.value.split(/[,;]\s*/).map(c=>c.trim()).filter(Boolean);if(a.length)return{entities:a}}if(/ha_domain|home.?assistant.*domain|briefing.*domain/.test(i)){let a=o.value.split(/[,;]\s*/).map(c=>c.trim()).filter(Boolean);if(a.length)return{domains:a}}}}return{}}detectExternalAppointment(e){return Array.isArray(e)?e.some(t=>{let s=t.location??t.loc??"";return!s||typeof s!="string"||/teams|zoom|meet\.google|webex|skype/i.test(s)?!1:s.trim().length>0}):!1}extractBatteryLevel(e){if(!e||typeof e!="object")return null;let t=e,s=t.chargingLevelPercent??t.batterySoc??t.soc??t.chargingState?.chargingLevelPercent;if(typeof s=="number")return s;if(typeof s=="string"){let r=parseFloat(s);return isNaN(r)?null:r}return null}}});import{spawn as ip}from"node:child_process";import Hl from"node:fs";import Wl from"node:path";function dp(l){let e={};for(let[t,s]of Object.entries(l))e[t]=s.replace(/\$\{(\w+)\}/g,(r,n)=>process.env[n]??"");return e}function up(l,e){return l.map(t=>t.replace(/\{\{prompt\}\}/g,e))}function Rn(l){return l.length<=ql?l:`[...truncated...]
|
|
767
|
+
`+l.slice(-ql)}function zl(l){let e=new Map;function t(s){let r;try{r=Hl.readdirSync(s,{withFileTypes:!0})}catch{return}for(let n of r){if(lp.has(n.name))continue;let o=Wl.join(s,n.name);if(n.isDirectory())t(o);else if(n.isFile())try{let i=Hl.statSync(o);e.set(o,i.mtimeMs)}catch{}}}return u(t,"walk"),t(l),e}function mp(l,e,t){let s=[];for(let[r,n]of e){let o=l.get(r);(o===void 0||n>o)&&s.push(Wl.relative(t,r))}return s.sort()}async function gr(l,e,t={}){let s=t.cwd??l.cwd??process.cwd(),r=t.timeoutMs??l.timeoutMs??ap,n=Math.min(r,cp),o=up(l.argsTemplate,e),i={...process.env,...l.env?dp(l.env):{}},a=process.platform==="win32",c=zl(s),d=Date.now();return new Promise(m=>{let p=ip(l.command,o,{cwd:s,env:i,shell:a,stdio:l.promptVia==="stdin"?["pipe","pipe","pipe"]:["ignore","pipe","pipe"]}),g="",f="",h=!1,y=setTimeout(()=>{h=!0,p.kill("SIGTERM"),setTimeout(()=>p.kill("SIGKILL"),5e3)},n);p.stdout?.on("data",E=>{g+=E.toString()}),p.stderr?.on("data",E=>{let A=E.toString();if(f+=A,t.onProgress){let R=A.trim().split(`
|
|
768
|
+
`).pop();R&&t.onProgress(`[${l.name}] ${R}`)}}),l.promptVia==="stdin"&&p.stdin&&(p.stdin.write(e),p.stdin.end()),p.on("close",E=>{clearTimeout(y);let A=Date.now()-d,R=zl(s),F=mp(c,R,s);m({stdout:Rn(g),stderr:Rn(f),exitCode:h?124:E??1,durationMs:A,modifiedFiles:F})}),p.on("error",E=>{clearTimeout(y);let A=Date.now()-d;m({stdout:Rn(g),stderr:Rn(f+`
|
|
769
|
+
`+E.message),exitCode:127,durationMs:A,modifiedFiles:[]})})})}var ap,cp,ql,lp,Cn=_(()=>{"use strict";ap=3e5,cp=9e5,ql=1e5,lp=new Set([".git","node_modules",".next","dist",".cache"]);u(dp,"resolveEnv");u(up,"buildArgs");u(Rn,"truncateOutput");u(zl,"snapshotMtimes");u(mp,"detectModifiedFiles");u(gr,"executeAgent")});import{execFile as pp}from"node:child_process";function Fe(l,e){return new Promise((t,s)=>{pp("git",l,{cwd:e.cwd,maxBuffer:10*1024*1024},(r,n,o)=>{if(r){let i=o?.trim()||r.message;s(new Error(`git ${l[0]} failed: ${i}`));return}t(n.trim())})})}async function Dn(l){try{let e=await Fe(["rev-parse","--abbrev-ref","HEAD"],l),t=await Fe(["status","--porcelain"],l);return{isRepo:!0,branch:e,dirty:t.length>0}}catch{return{isRepo:!1,branch:"",dirty:!1}}}async function wi(l,e){await Fe(["checkout","-b",l],e)}async function Ti(l){await Fe(["add","-A"],l)}async function _i(l,e){await Fe(["commit","-m",l],e);let t=await Fe(["rev-parse","--short","HEAD"],e),r=(await Fe(["diff","--stat","HEAD~1","HEAD"],e)).split(`
|
|
769
770
|
`).length-1;return{sha:t,message:l,filesChanged:Math.max(r,0)}}async function bi(l,e,t){await Fe(["push","-u",l,e],t)}function Ei(l){return`alfred/${l.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}`}async function us(l,e){try{return await Fe(["remote","get-url",l],e)}catch{return null}}function ms(l){let e=l.match(/^git@([^:]+):(.+?)(?:\.git)?$/);if(e){let s=e[1],n=e[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}let t=l.match(/^https?:\/\/([^/]+)\/(.+?)(?:\.git)?$/);if(t){let s=t[1],n=t[2].split("/");if(n.length<2)return null;let o=n.pop();return{owner:n.join("/"),repo:o,baseUrl:`https://${s}`}}return null}async function yr(l){await Fe(["init"],l)}async function wr(l,e,t){await Fe(["remote","add",l,e],t)}var $i=_(()=>{"use strict";u(Fe,"git");u(Dn,"gitStatus");u(wi,"gitCreateBranch");u(Ti,"gitStageAll");u(_i,"gitCommit");u(bi,"gitPush");u(Ei,"slugifyBranch");u(us,"gitGetRemoteUrl");u(ms,"parseRemoteUrl");u(yr,"gitInitRepo");u(wr,"gitAddRemote")});function ps(l){switch(l.provider){case"github":{if(!l.github)throw new Error('ForgeConfig.github is required when provider is "github"');return new ki(l.github)}case"gitlab":{if(!l.gitlab)throw new Error('ForgeConfig.gitlab is required when provider is "gitlab"');return new vi(l.gitlab)}default:throw new Error(`Unknown forge provider: ${l.provider}`)}}var St,ki,vi,Si=_(()=>{"use strict";St=class{static{u(this,"ForgeClient")}},ki=class extends St{static{u(this,"GitHubForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://api.github.com"}async createPullRequest(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/pulls`,r=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({title:t.title,body:t.body,head:t.head,base:t.base})});if(!r.ok){let o=await r.text();throw new Error(`GitHub PR creation failed (${r.status}): ${o}`)}let n=await r.json();return{id:n.id,url:n.html_url,number:n.number,state:n.state}}async getPipelineStatus(e,t){let s=`${this.baseUrl}/repos/${e.owner}/${e.repo}/commits/${t}/status`,r=await fetch(s,{headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json"}});if(!r.ok)return{state:"unknown"};let o=(await r.json()).state;return{state:{pending:"pending",success:"success",failure:"failure",error:"failure"}[o]??"unknown"}}async createProject(e){let t=`${this.baseUrl}/user/repos`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.config.token}`,Accept:"application/vnd.github+json","Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",private:(e.visibility??"private")==="private"})});if(!s.ok){let n=await s.text();throw new Error(`GitHub project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.html_url,cloneUrl:r.clone_url}}},vi=class extends St{static{u(this,"GitLabForgeClient")}config;baseUrl;constructor(e){super(),this.config=e,this.baseUrl=e.baseUrl?.replace(/\/+$/,"")??"https://gitlab.com"}async createPullRequest(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/merge_requests`,n=await fetch(r,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({title:t.title,description:t.body,source_branch:t.head,target_branch:t.base})});if(!n.ok){let i=await n.text();throw new Error(`GitLab MR creation failed (${n.status}): ${i}`)}let o=await n.json();return{id:o.id,url:o.web_url,number:o.iid,state:o.state}}async getPipelineStatus(e,t){let s=encodeURIComponent(`${e.owner}/${e.repo}`),r=`${this.baseUrl}/api/v4/projects/${s}/pipelines?ref=${encodeURIComponent(t)}&per_page=1`,n=await fetch(r,{headers:{"PRIVATE-TOKEN":this.config.token}});if(!n.ok)return{state:"unknown"};let o=await n.json();if(o.length===0)return{state:"unknown"};let i=o[0],a=i.status;return{state:{pending:"pending",running:"running",success:"success",failed:"failure",canceled:"failure"}[a]??"unknown",url:i.web_url}}async createProject(e){let t=`${this.baseUrl}/api/v4/projects`,s=await fetch(t,{method:"POST",headers:{"PRIVATE-TOKEN":this.config.token,"Content-Type":"application/json"},body:JSON.stringify({name:e.name,description:e.description??"",visibility:e.visibility??"private"})});if(!s.ok){let n=await s.text();throw new Error(`GitLab project creation failed (${s.status}): ${n}`)}let r=await s.json();return{id:r.id,url:r.web_url,cloneUrl:r.http_url_to_repo}}};u(ps,"createForgeClient")});function Gl(l,e){return l.length<=e?l:l.slice(0,e)+`
|
|
770
|
-
[...truncated]`}function Vl(l){let e=l.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function
|
|
771
|
+
[...truncated]`}function Vl(l){let e=l.replace(/^```(?:json)?\s*\n?/m,"").replace(/\n?```\s*$/m,"");return JSON.parse(e)}async function bp(l,e,t){let r=`Available agents:
|
|
771
772
|
${e.map(a=>`- ${a.name}: command="${a.command}"`).join(`
|
|
772
773
|
`)}
|
|
773
774
|
|
|
774
775
|
Task:
|
|
775
|
-
${l}`,n=await t.complete({system:
|
|
776
|
+
${l}`,n=await t.complete({system:Tp,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"}),o=Vl(n.content);if(!Array.isArray(o.subtasks)||o.subtasks.length===0)throw new Error("LLM returned an empty plan with no subtasks");let i=new Set(e.map(a=>a.name));for(let a of o.subtasks)if(!i.has(a.agent))throw new Error(`Plan references unknown agent "${a.agent}". Available: ${[...i].join(", ")}`);return o}async function Ep(l,e,t,s){let r=new Ai(t),n=[],o=l.map(async i=>{await r.acquire();try{s?.(`Running ${i.id}: ${i.description}`);let a=e.get(i.agent),c=await gr(a,i.prompt,{onProgress:s?m=>s(`[${i.id}] ${m}`):void 0}),d={subtask:i,execution:c};return n.push(d),s?.(`Completed ${i.id}: exit=${c.exitCode}, ${c.modifiedFiles.length} files modified`),d}finally{r.release()}});return await Promise.all(o),n}async function $p(l,e,t){let s=e.map(o=>{let i=Gl(o.execution.stdout,yp),a=Gl(o.execution.stderr,wp);return[`### ${o.subtask.id} (${o.subtask.description})`,`Agent: ${o.subtask.agent}`,`Exit code: ${o.execution.exitCode}`,`Modified files: ${o.execution.modifiedFiles.join(", ")||"none"}`,i?`stdout:
|
|
776
777
|
${i}`:"",a?`stderr:
|
|
777
778
|
${a}`:""].filter(Boolean).join(`
|
|
778
779
|
`)}).join(`
|
|
@@ -781,11 +782,11 @@ ${a}`:""].filter(Boolean).join(`
|
|
|
781
782
|
${l}
|
|
782
783
|
|
|
783
784
|
Results:
|
|
784
|
-
${s}`,n=await t.complete({system:
|
|
785
|
+
${s}`,n=await t.complete({system:_p,messages:[{role:"user",content:r}],temperature:.2,tier:"strong"});try{let o=Vl(n.content);return{approved:o.approved??!0,summary:o.summary??"",fixTasks:Array.isArray(o.fixTasks)?o.fixTasks:[]}}catch{return{approved:!0,summary:n.content,fixTasks:[]}}}async function At(l,e,t,s={}){let r=Math.min(s.maxIterations??hp,fp),n=s.maxConcurrent??gp,o=s.onProgress,i=Date.now(),a=new Map(e.map(h=>[h.name,h]));o?.("Planning subtasks...");let c=await bp(l,e,t);o?.(`Plan created: ${c.subtasks.length} subtask(s) \u2014 ${c.reasoning}`);let d=[],m=c.subtasks,p=0,g="";for(;p<r;){p++,o?.(`Iteration ${p}: executing ${m.length} subtask(s)...`);let h=await Ep(m,a,n,o);d=d.concat(h),o?.(`Iteration ${p}: validating results...`);let y=await $p(l,d,t);if(g=y.summary,y.approved||y.fixTasks.length===0)break;let E=y.fixTasks.filter(A=>a.has(A.agent)?!0:(o?.(`Warning: fix task "${A.id}" references unknown agent "${A.agent}", skipping`),!1));if(E.length===0)break;m=E,o?.(`Validation requested ${E.length} fix task(s), iterating...`)}let f=[...new Set(d.flatMap(h=>h.execution.modifiedFiles))].sort();return{plan:c,iterations:p,subtaskResults:d,allModifiedFiles:f,summary:g,totalDurationMs:Date.now()-i}}async function Tr(l,e,t,s={}){let r=s.onProgress,n=s.cwd??process.cwd(),o={warnings:[]},i=await Dn({cwd:n});if(!i.isRepo)try{await yr({cwd:n}),i=await Dn({cwd:n}),r?.("Initialised new git repository")}catch{return o.warnings.push("Not a git repository and init failed \u2014 skipping git operations"),r?.("Warning: not a git repository, skipping git operations"),{...await At(l,e,t,s),git:o}}let a=null,c=await us("origin",{cwd:n});if(c){let f=ms(c);f?(a={owner:f.owner,repo:f.repo},r?.(`Detected remote: ${f.owner}/${f.repo} (${f.baseUrl})`)):o.warnings.push(`Could not parse remote URL: ${c}`)}let d=s.forge;if(!c&&d)try{let f=ps(d),h=n.split(/[\\/]/).pop()??"alfred-project";r?.(`No remote found \u2014 creating project "${h}" on forge...`);let y=await f.createProject({name:h,visibility:"private"});await wr("origin",y.cloneUrl,{cwd:n});let E=ms(y.cloneUrl);E&&(a={owner:E.owner,repo:E.repo}),r?.(`Project created: ${y.url} \u2014 remote "origin" set`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`Project creation failed: ${h}`),r?.(`Warning: project creation failed \u2014 ${h}`)}let m=Ei(l);try{await wi(m,{cwd:n}),o.branch=m,r?.(`Created branch: ${m}`)}catch(f){throw new Error(`Failed to create branch "${m}": ${f instanceof Error?f.message:String(f)}`)}let p=await At(l,e,t,s);try{await Ti({cwd:n});let f=`feat: ${l.slice(0,72)}
|
|
785
786
|
|
|
786
|
-
Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,h=await _i(f,{cwd:n});o.commit=h,r?.(`Committed: ${h.sha} (${h.filesChanged} files changed)`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Commit failed: ${h}`),r?.(`Warning: commit failed \u2014 ${h}`),{...p,git:o}}if(!await us("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...p,git:o};try{await bi("origin",m,{cwd:n}),r?.(`Pushed branch: ${m}`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Push failed: ${h}`),r?.(`Warning: push failed \u2014 ${h}`),{...p,git:o}}if(d&&a)try{let f=ps(d),h=s.baseBranch??d.baseBranch??"main",
|
|
787
|
+
Orchestrated by Alfred (${p.iterations} iteration(s), ${p.allModifiedFiles.length} file(s))`,h=await _i(f,{cwd:n});o.commit=h,r?.(`Committed: ${h.sha} (${h.filesChanged} files changed)`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Commit failed: ${h}`),r?.(`Warning: commit failed \u2014 ${h}`),{...p,git:o}}if(!await us("origin",{cwd:n}))return o.warnings.push("No remote configured \u2014 skipping push and PR creation"),r?.("No remote configured, skipping push and PR"),{...p,git:o};try{await bi("origin",m,{cwd:n}),r?.(`Pushed branch: ${m}`)}catch(f){let h=f instanceof Error?f.message:String(f);return o.warnings.push(`Push failed: ${h}`),r?.(`Warning: push failed \u2014 ${h}`),{...p,git:o}}if(d&&a)try{let f=ps(d),h=s.baseBranch??d.baseBranch??"main",y=s.prTitle??`feat: ${l.slice(0,72)}`,E=["## Summary",p.summary,"",`**Iterations:** ${p.iterations}`,`**Modified files:** ${p.allModifiedFiles.length}`,p.allModifiedFiles.map(R=>`- \`${R}\``).join(`
|
|
787
788
|
`),"","_Automated by Alfred_"].join(`
|
|
788
|
-
`),A=await f.createPullRequest(a,{title:
|
|
789
|
+
`),A=await f.createPullRequest(a,{title:y,body:E,head:m,base:h});o.pullRequest=A,r?.(`PR created: ${A.url}`)}catch(f){let h=f instanceof Error?f.message:String(f);o.warnings.push(`PR creation failed: ${h}`),r?.(`Warning: PR creation failed \u2014 ${h}`)}else d||(o.warnings.push("No forge configured \u2014 skipping PR creation"),r?.("No forge configured, skipping PR creation"));return{...p,git:o}}var hp,fp,gp,yp,wp,Tp,_p,Ai,Ii=_(()=>{"use strict";Cn();$i();Si();hp=3,fp=5,gp=3,yp=2048,wp=1024,Tp=`You are a task planner for a multi-agent coding system.
|
|
789
790
|
You receive a high-level task and a list of available coding agents.
|
|
790
791
|
Your job is to decompose the task into concrete subtasks, each assigned to an agent.
|
|
791
792
|
|
|
@@ -801,7 +802,7 @@ Respond with ONLY valid JSON (no markdown fences):
|
|
|
801
802
|
"subtasks": [
|
|
802
803
|
{ "id": "task-1", "agent": "<agent-name>", "prompt": "<detailed prompt>", "description": "<short description>" }
|
|
803
804
|
]
|
|
804
|
-
}`,
|
|
805
|
+
}`,_p=`You are a code review validator for a multi-agent coding system.
|
|
805
806
|
You receive the original task and the results from each subtask execution.
|
|
806
807
|
Your job is to determine if the task was completed successfully.
|
|
807
808
|
|
|
@@ -815,7 +816,7 @@ Respond with ONLY valid JSON (no markdown fences):
|
|
|
815
816
|
"fixTasks": [
|
|
816
817
|
{ "id": "fix-1", "agent": "<agent-name>", "prompt": "<detailed fix prompt>", "description": "<short description>" }
|
|
817
818
|
]
|
|
818
|
-
}`;u(Gl,"truncate");u(Vl,"parseJSON");Ai=class{static{u(this,"Semaphore")}max;queue=[];active=0;constructor(e){this.max=e}async acquire(){if(this.active<this.max){this.active++;return}return new Promise(e=>{this.queue.push(()=>{this.active++,e()})})}release(){this.active--;let e=this.queue.shift();e&&e()}};u(
|
|
819
|
+
}`;u(Gl,"truncate");u(Vl,"parseJSON");Ai=class{static{u(this,"Semaphore")}max;queue=[];active=0;constructor(e){this.max=e}async acquire(){if(this.active<this.max){this.active++;return}return new Promise(e=>{this.queue.push(()=>{this.active++,e()})})}release(){this.active--;let e=this.queue.shift();e&&e()}};u(bp,"planSubtasks");u(Ep,"executeSubtasksParallel");u($p,"validateResults");u(At,"orchestrate");u(Tr,"orchestrateWithGit")});var _r,Kl=_(()=>{"use strict";P();Cn();Ii();_r=class extends I{static{u(this,"CodeAgentSkill")}llm;metadata={name:"code_agent",category:"automation",description:'Run a CLI-based coding agent (e.g. Claude Code, Codex, Gemini CLI, Aider) as a subprocess. Use action "list_agents" to see available agents, "run" to execute one with a prompt, or "orchestrate" to have the LLM decompose a task into parallel subtasks. The agent runs in a specified working directory and returns stdout, stderr, exit code, duration, and a list of files it modified.',riskLevel:"admin",version:"1.0.0",timeoutMs:6e5,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list_agents","run","orchestrate"],description:"The action to perform"},task:{type:"string",description:'High-level task description for "orchestrate" action'},agents:{type:"array",items:{type:"string"},description:'Optional agent name filter for "orchestrate" (uses all agents if omitted)'},maxIterations:{type:"number",description:'Max validation iterations for "orchestrate" (1-5, default 3)'},agent:{type:"string",description:'Name of the agent to run (required for "run" action)'},prompt:{type:"string",description:'The prompt / task description to send to the agent (required for "run" action)'},cwd:{type:"string",description:"Working directory for the agent (optional, uses agent default or process.cwd())"},timeout:{type:"number",description:"Timeout in milliseconds (optional, max 900000)"},git:{type:"boolean",description:'Enable git workflow: auto-branch, commit, push, and PR creation (for "orchestrate")'},prTitle:{type:"string",description:"Custom PR/MR title (used with git=true)"},baseBranch:{type:"string",description:'Target branch for the PR/MR (default: "main")'}},required:["action"]}};agents;forgeConfig;constructor(e,t){super(),this.llm=t,this.agents=new Map(e.agents.map(s=>[s.name,s])),this.forgeConfig=e.forge}async execute(e,t){let s=e.action;switch(s){case"list_agents":return this.listAgents();case"run":return this.runAgent(e,t);case"orchestrate":return this.orchestrateTask(e,t);default:return{success:!1,error:`Unknown action "${s}". Use "list_agents", "run", or "orchestrate".`}}}listAgents(){let e=[...this.agents.values()].map(s=>({name:s.name,command:s.command,promptVia:s.promptVia??"arg",timeoutMs:s.timeoutMs})),t=e.length===0?"No code agents configured.":e.map(s=>`- **${s.name}**: \`${s.command}\` (prompt via ${s.promptVia})`).join(`
|
|
819
820
|
`);return{success:!0,data:{agents:e},display:`Available code agents:
|
|
820
821
|
${t}`}}async runAgent(e,t){let s=e.agent,r=e.prompt;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "agent"'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "prompt"'};let n=this.agents.get(s);if(!n){let d=[...this.agents.keys()].join(", ");return{success:!1,error:`Unknown agent "${s}". Available: ${d}`}}let o=typeof e.cwd=="string"?e.cwd:void 0,i=typeof e.timeout=="number"?e.timeout:void 0,a=await gr(n,r,{cwd:o,timeoutMs:i,onProgress:t.onProgress}),c=[];return a.stdout&&c.push(`**stdout:**
|
|
821
822
|
\`\`\`
|
|
@@ -836,27 +837,27 @@ ${e.allModifiedFiles.map(r=>`- ${r}`).join(`
|
|
|
836
837
|
|
|
837
838
|
**Git:**
|
|
838
839
|
${s.join(`
|
|
839
|
-
`)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var Xl=_(()=>{"use strict";Kl();Cn();Ii();$i();Si()});var ee={};me(ee,{ActivityTracker:()=>Tt,BMWSkill:()=>$n,BackgroundTaskSkill:()=>es,BriefingSkill:()=>xn,BrowserSkill:()=>Jt,CalculatorSkill:()=>Pt,CalendarProvider:()=>Me,CalendarSkill:()=>_t,ClipboardSkill:()=>Xt,CodeAgentSkill:()=>_r,CodeExecutionSkill:()=>lr,CodeExecutor:()=>$t,ConfigureSkill:()=>ls,ContactsProvider:()=>Ue,ContactsSkill:()=>mr,CrossPlatformSkill:()=>Qt,DelegateSkill:()=>Wt,DockerSkill:()=>_n,DocumentSkill:()=>ss,EmailProvider:()=>Ve,EmailSkill:()=>et,EnergyPriceSkill:()=>vn,FileSkill:()=>Vt,ForgeClient:()=>St,HomeAssistantSkill:()=>fn,HttpSkill:()=>Gt,ImageGenerateSkill:()=>ns,MCPClient:()=>bt,MCPManager:()=>cr,MCPSkillAdapter:()=>Et,MarketplaceSkill:()=>fr,MemorySkill:()=>zt,MicrosoftTodoSkill:()=>An,MonitorSkill:()=>Sn,NoteSkill:()=>Bt,PluginLoader:()=>nn,ProfileSkill:()=>Zt,ProxmoxSkill:()=>pn,ReminderSkill:()=>jt,RoutingSkill:()=>kn,ScheduledTaskSkill:()=>ts,ScreenshotSkill:()=>Yt,ShellSkill:()=>qt,Skill:()=>I,SkillRegistry:()=>Mt,SkillSandbox:()=>Ot,SystemInfoSkill:()=>Ut,TTSSkill:()=>rs,TodoSkill:()=>os,TransitSkill:()=>as,UniFiSkill:()=>hn,WatchSkill:()=>ds,WeatherSkill:()=>Ht,WebSearchSkill:()=>Ft,allUserIds:()=>W,createCalendarProvider:()=>ar,createContactsProvider:()=>ai,createEmailProvider:()=>nr,createForgeClient:()=>ps,effectiveUserId:()=>ie,gitAddRemote:()=>wr,gitGetRemoteUrl:()=>us,gitInitRepo:()=>yr,orchestrate:()=>At,orchestrateWithGit:()=>Tr,parseRemoteUrl:()=>ms});var Z=_(()=>{"use strict";P();Ne();cc();lc();Vo();dc();uc();mc();pc();hc();fc();gc();Tc();_c();bc();vc();Ac();xc();Rc();Dc();Nc();Mc();Bc();Hc();qc();zc();Gc();Kc();Xc();Yc();Jc();Zc();Qc();tl();al();cl();pl();_l();bl();Il();xl();Dl();Ll();Nl();Ol();jl();Bl();Xl()});var br,xi=_(()=>{"use strict";br=class{static{u(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}pruneMessages(e,t){return this.conversations.pruneMessages(e,t)}}});function Ke(l,e){let t;if(e.platformUserId)t=l.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=l.findById(e.userId)??l.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in l?l.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in l&&(r=l.getLinkedUsers(s).map(a=>a.platformUserId));let n;try{"getProfile"in l?n=l.getProfile(s)?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone:n=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{n=Intl.DateTimeFormat().resolvedOptions().timeZone}return{context:{userId:t.platformUserId,masterUserId:s,linkedPlatformUserIds:r,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:e.conversationId??"",timezone:n},user:t,masterUserId:s,linkedPlatformUserIds:r}}var hs=_(()=>{"use strict";u(Ke,"buildSkillContext")});function Yl(l,e){let t=new Set(["core"]),s=!1;for(let[r,n]of Object.entries(
|
|
840
|
+
`)}`:"";return{...t,data:{...t.data,git:{branch:r.branch,commit:r.commit,pullRequest:r.pullRequest,warnings:r.warnings}},display:(t.display??"")+n}}}});var Xl=_(()=>{"use strict";Kl();Cn();Ii();$i();Si()});var ee={};me(ee,{ActivityTracker:()=>Tt,BMWSkill:()=>$n,BackgroundTaskSkill:()=>es,BriefingSkill:()=>xn,BrowserSkill:()=>Jt,CalculatorSkill:()=>Pt,CalendarProvider:()=>Me,CalendarSkill:()=>_t,ClipboardSkill:()=>Xt,CodeAgentSkill:()=>_r,CodeExecutionSkill:()=>lr,CodeExecutor:()=>$t,ConfigureSkill:()=>ls,ContactsProvider:()=>Ue,ContactsSkill:()=>mr,CrossPlatformSkill:()=>Qt,DelegateSkill:()=>Wt,DockerSkill:()=>_n,DocumentSkill:()=>ss,EmailProvider:()=>Ve,EmailSkill:()=>et,EnergyPriceSkill:()=>vn,FileSkill:()=>Vt,ForgeClient:()=>St,HomeAssistantSkill:()=>fn,HttpSkill:()=>Gt,ImageGenerateSkill:()=>ns,MCPClient:()=>bt,MCPManager:()=>cr,MCPSkillAdapter:()=>Et,MarketplaceSkill:()=>fr,MemorySkill:()=>zt,MicrosoftTodoSkill:()=>An,MonitorSkill:()=>Sn,NoteSkill:()=>Bt,PluginLoader:()=>nn,ProfileSkill:()=>Zt,ProxmoxSkill:()=>pn,ReminderSkill:()=>jt,RoutingSkill:()=>kn,ScheduledTaskSkill:()=>ts,ScreenshotSkill:()=>Yt,ShellSkill:()=>qt,Skill:()=>I,SkillRegistry:()=>Mt,SkillSandbox:()=>Ot,SystemInfoSkill:()=>Ut,TTSSkill:()=>rs,TodoSkill:()=>os,TransitSkill:()=>as,UniFiSkill:()=>hn,WatchSkill:()=>ds,WeatherSkill:()=>Ht,WebSearchSkill:()=>Ft,allUserIds:()=>W,createCalendarProvider:()=>ar,createContactsProvider:()=>ai,createEmailProvider:()=>nr,createForgeClient:()=>ps,effectiveUserId:()=>ie,gitAddRemote:()=>wr,gitGetRemoteUrl:()=>us,gitInitRepo:()=>yr,orchestrate:()=>At,orchestrateWithGit:()=>Tr,parseRemoteUrl:()=>ms});var Z=_(()=>{"use strict";P();Ne();cc();lc();Vo();dc();uc();mc();pc();hc();fc();gc();Tc();_c();bc();vc();Ac();xc();Rc();Dc();Nc();Mc();Bc();Hc();qc();zc();Gc();Kc();Xc();Yc();Jc();Zc();Qc();tl();al();cl();pl();_l();bl();Il();xl();Dl();Ll();Nl();Ol();jl();Bl();Xl()});var br,xi=_(()=>{"use strict";br=class{static{u(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}pruneMessages(e,t){return this.conversations.pruneMessages(e,t)}}});function Ke(l,e){let t;if(e.platformUserId)t=l.findOrCreate(e.platform,e.platformUserId,e.userName,e.displayName);else if(e.userId)t=l.findById(e.userId)??l.findOrCreate(e.platform,e.userId);else throw new Error("ContextSource must provide either platformUserId or userId");let s="getMasterUserId"in l?l.getMasterUserId(t.id):t.id,r=[];"getLinkedUsers"in l&&(r=l.getLinkedUsers(s).map(a=>a.platformUserId));let n;try{"getProfile"in l?n=l.getProfile(s)?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone:n=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{n=Intl.DateTimeFormat().resolvedOptions().timeZone}return{context:{userId:t.platformUserId,masterUserId:s,linkedPlatformUserIds:r,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:e.conversationId??"",timezone:n},user:t,masterUserId:s,linkedPlatformUserIds:r}}var hs=_(()=>{"use strict";u(Ke,"buildSkillContext")});function Yl(l,e){let t=new Set(["core"]),s=!1;for(let[r,n]of Object.entries(kp))e.has(r)&&n.test(l)&&(t.add(r),s=!0);if(!s)for(let r of e)t.add(r);return t}function Jl(l,e){return l.filter(t=>e.has(t.category??"core"))}var kp,Zl=_(()=>{"use strict";kp={productivity:/\b(todo|note|remind|calendar|termin|event|email|e-mail|mail|contact|kontakt|briefing|morgenbriefing|tagesbriefing)\b/i,information:/\b(search|such|weather|wetter|calculat|rechn|time|date|zeit|datum|uhrzeit|system.?info|transit|bahn|zug|bus|tram|u.?bahn|s.?bahn|abfahrt|verbindung|haltestelle|öffi|fahrplan|strom|energy|preis|price|kwh|awattar|marktpreis|spot|günstig|cheapest|netzentgelt)\b/i,media:/\b(voice|stimme|tts|speak|sprech|sprich|screenshot|clipboard|zwischenablage|brows)\b/i,automation:/\b(background|hintergrund|shell|bash|cron|schedul|code.?agent|sandbox|automat|watch|alert|benachrichtig|bescheid|meld|überwach|monitor|tägliche?r?s?|stündliche?r?s?|wöchentliche?r?s?|monatliche?r?s?|jeden\s+(tag|morgen|abend|montag|dienstag|mittwoch|donnerstag|freitag|samstag|sonntag)|um\s+\d{1,2}\s*(uhr|:|h)|alle\s+\d+\s*(min|stund|sekund)|daily|hourly|weekly|every\s+(day|hour|morning|evening|night|\d+\s*min))\b/i,files:/\b(file|datei|document|dokument|pdf|http|download|upload)\b/i,infrastructure:/\b(proxmox|vm|container|docker|unifi|wifi|wlan|homeassistant|home.?assistant|smarthome|smart.?home|licht|light|schalter|switch)\b/i,identity:/\b(link|verknüpf|cross.?platform|identity|identität)\b/i,mcp:/\bmcp\b/i};u(Yl,"selectCategories");u(Jl,"filterSkills")});import Ri from"node:fs";import Ql from"node:path";var vp,ed,Sp,td,Ap,Ip,xp,sd,Er,Ci=_(()=>{"use strict";Wo();hs();Zl();vp=15*60*1e3,ed=50,Sp=2,td=.85,Ap=1e5,Ip=2e3,xp=.1,sd=3,Er=class{static{u(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;maxHistoryMessages;documentProcessor;activeAgents=new Map;agentIdCounter=0;constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.maxHistoryMessages=e.maxHistoryMessages??100,this.documentProcessor=e.documentProcessor,this.promptBuilder=new Qs}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let{user:r,masterUserId:n,linkedPlatformUserIds:o,context:i}=Ke(this.users,{platformUserId:e.userId,platform:e.platform,chatId:e.chatId,chatType:e.chatType,userName:e.userName,displayName:e.displayName}),a=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),c=e.metadata?.skipHistory?[]:this.conversationManager.getHistory(a.id,this.maxHistoryMessages);this.conversationManager.addMessage(a.id,"user",e.text);let d,m=this.isSyntheticLabel(e.text),p=e.attachments?.some(B=>B.type==="audio")??!1,g=m&&!p;if(this.memoryRetriever&&e.text&&!g)try{d=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(B){this.logger.debug({err:B},"Hybrid memory retrieval failed")}if(!d&&this.memoryRepo&&!g)try{let B=[n,...(o??[]).filter(te=>te!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let te=new Set;d=[];for(let ae of B)for(let oe of await this.embeddingService.semanticSearch(ae,e.text,10))te.has(oe.key)||(te.add(oe.key),d.push(oe));for(let ae of B)for(let oe of this.memoryRepo.getRecentForPrompt(ae,5))te.has(oe.key)||(te.add(oe.key),d.push(oe))}else{let te=new Set;d=[];for(let ae of B)for(let oe of this.memoryRepo.getRecentForPrompt(ae,20))te.has(oe.key)||(te.add(oe.key),d.push(oe))}}catch(B){this.logger.debug({err:B},"Memory loading failed")}d&&d.length>0&&(d=this.applyMemoryBudget(d));let f;try{"getProfile"in this.users&&(f=this.users.getProfile(n),f&&!f.displayName&&(f.displayName=r.displayName??r.username))}catch(B){this.logger.debug({err:B},"Profile loading failed")}let h=i.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone,y=this.skillRegistry?this.skillRegistry.getAll().map(B=>B.metadata):void 0,E=y;if(y&&e.text){let B=new Set(y.map(ae=>ae.category??"core")),te=Yl(e.text,B);E=Jl(y,te)}let A=E?this.promptBuilder.buildTools(E):void 0,R=this.promptBuilder.buildSystemPrompt({memories:d,skills:E,userProfile:f}),F=this.buildActiveAgentStatus();F&&(R+=`
|
|
840
841
|
|
|
841
|
-
`+F);let x=this.promptBuilder.buildMessages(c),G=this.collapseRepeatedToolErrors(x),ce=await this.buildUserContent(e,t);G.push({role:"user",content:ce});let se=A?Le(JSON.stringify(A)):0,N=1,K=this.trimToContextWindow(R,G,se,N),q,le=0,de=Date.now(),re="",ne=0,D=0,z=0,Te=[];for(t?.("Thinking...");;){le>0&&this.compressToolLoop(K,R,se);try{q=await this.llm.complete({messages:K,system:R,tools:A&&A.length>0?A:void 0}),D+=q.usage?.inputTokens??0,z+=q.usage?.outputTokens??0}catch(ke){if((ke instanceof Error?ke.message:String(ke)).includes("prompt is too long")&&N>.3){N*=.5,this.logger.warn({budgetMultiplier:N},"Prompt too long, retrimming with reduced budget"),K=this.trimToContextWindow(R,G,se,N);continue}throw ke}if(!q.toolCalls||q.toolCalls.length===0)break;let B=Date.now()-de;if(B>=
|
|
842
|
+
`+F);let x=this.promptBuilder.buildMessages(c),G=this.collapseRepeatedToolErrors(x),ce=await this.buildUserContent(e,t);G.push({role:"user",content:ce});let se=A?Le(JSON.stringify(A)):0,N=1,K=this.trimToContextWindow(R,G,se,N),q,le=0,de=Date.now(),re="",ne=0,D=0,z=0,Te=[];for(t?.("Thinking...");;){le>0&&this.compressToolLoop(K,R,se);try{q=await this.llm.complete({messages:K,system:R,tools:A&&A.length>0?A:void 0,tier:e.metadata?.tier}),D+=q.usage?.inputTokens??0,z+=q.usage?.outputTokens??0}catch(ke){if((ke instanceof Error?ke.message:String(ke)).includes("prompt is too long")&&N>.3){N*=.5,this.logger.warn({budgetMultiplier:N},"Prompt too long, retrimming with reduced budget"),K=this.trimToContextWindow(R,G,se,N);continue}throw ke}if(!q.toolCalls||q.toolCalls.length===0)break;let B=Date.now()-de;if(B>=vp){let ke=Math.round(B/6e4);this.logger.warn({iteration:le,elapsedMin:ke,pendingToolCalls:q.toolCalls.length},"Tool loop timeout reached"),q=await this.abortToolLoop(K,q,a.id,R,`Das Zeitlimit von ${ke} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`,!1,e.metadata?.tier);break}if(le>=ed){this.logger.warn({iteration:le,pendingToolCalls:q.toolCalls.length},"Tool loop iteration cap reached"),q=await this.abortToolLoop(K,q,a.id,R,`Das Iterationslimit von ${ed} Tool-Aufrufen wurde erreicht.`,!1,e.metadata?.tier);break}le++,this.logger.info({iteration:le,toolCalls:q.toolCalls.length},"Processing tool calls");let te=[];q.content&&te.push({type:"text",text:q.content});for(let ke of q.toolCalls)te.push({type:"tool_use",id:ke.id,name:ke.name,input:ke.input});K.push({role:"assistant",content:te});let ae=await this.executeToolCallsParallel(q.toolCalls,{...i,conversationId:a.id,timezone:h},t),oe=ae.blocks;ae.attachments.length>0&&Te.push(...ae.attachments),this.conversationManager.addMessage(a.id,"assistant",q.content??"",JSON.stringify(q.toolCalls)),this.conversationManager.addMessage(a.id,"user","",JSON.stringify(oe));let Rt=this.buildErrorSignature(oe);if(Rt){if(Rt===re?ne++:(ne=1,re=Rt),ne>=Sp){this.logger.warn({iteration:le,consecutiveErrors:ne,errorSignature:Rt},"Tool loop aborted: same error repeated consecutively"),q=await this.abortToolLoop(K,q,a.id,R,`Der gleiche Tool-Fehler ist ${ne}x hintereinander aufgetreten: "${re.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0,e.metadata?.tier);break}}else ne=0,re="";K.push({role:"user",content:oe}),t?.("Thinking...")}let Q=q.content;if(!Q)for(let B=K.length-1;B>=0;B--){let te=K[B];if(te.role==="assistant"&&Array.isArray(te.content)){let ae=te.content.find(oe=>oe.type==="text");if(ae&&"text"in ae&&ae.text){Q=ae.text;break}}}Q||(Q="(no response)"),this.conversationManager.addMessage(a.id,"assistant",Q),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,Q);let Je=Date.now()-s;return this.logger.info({duration:Je,tokens:q.usage,totalTokens:{inputTokens:D,outputTokens:z},stopReason:q.stopReason,toolIterations:le},"Message processed"),{text:Q,attachments:Te.length>0?Te:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1,i){if(!o){let d=[];t.content&&d.push({type:"text",text:t.content});for(let m of t.toolCalls)d.push({type:"tool_use",id:m.id,name:m.name,input:m.input});e.push({role:"assistant",content:d})}let a=t.toolCalls.map(d=>({type:"tool_result",tool_use_id:d.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));e.push({role:"user",content:a}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(a));let c=e[e.length-1];return c&&c.role==="user"&&Array.isArray(c.content)?c.content.push({type:"text",text:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}):e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r,tier:i})}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],d=e[a+1];if(c.role==="assistant"&&d?.role==="user"&&this.toolPairSignature(c,d)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"user",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=u((m,p)=>{let g=p.content;if(p.attachments&&p.attachments.length>0){r.push(...p.attachments);let f=p.attachments.map(h=>h.fileName).join(", ");g+=`
|
|
842
843
|
|
|
843
|
-
[${p.attachments.length} Datei(en) werden dem User gesendet: ${f}]`}return{type:"tool_result",tool_use_id:m.id,content:g,is_error:p.isError}},"buildBlock");if(e.length===1){let m=e[0],p=this.getToolLabel(m.name,m.input);s?.(p);let g=await this.executeToolCall(m,t,s);return{blocks:[n(m,g)],attachments:r}}let o=3;s?.(`Running ${e.length} tools...`);let i=new Map;for(let m=0;m<e.length;m++){let p=e[m].name,g=i.get(p);g||(g=[],i.set(p,g)),g.push(m)}let a=[...i.values()].some(m=>m.length>o),c;if(a){c=new Map;let m=[...i.entries()].map(async([p,g])=>{for(let f=0;f<g.length;f+=o){let h=g.slice(f,f+o),
|
|
844
|
-
`)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=
|
|
844
|
+
[${p.attachments.length} Datei(en) werden dem User gesendet: ${f}]`}return{type:"tool_result",tool_use_id:m.id,content:g,is_error:p.isError}},"buildBlock");if(e.length===1){let m=e[0],p=this.getToolLabel(m.name,m.input);s?.(p);let g=await this.executeToolCall(m,t,s);return{blocks:[n(m,g)],attachments:r}}let o=3;s?.(`Running ${e.length} tools...`);let i=new Map;for(let m=0;m<e.length;m++){let p=e[m].name,g=i.get(p);g||(g=[],i.set(p,g)),g.push(m)}let a=[...i.values()].some(m=>m.length>o),c;if(a){c=new Map;let m=[...i.entries()].map(async([p,g])=>{for(let f=0;f<g.length;f+=o){let h=g.slice(f,f+o),y=await Promise.allSettled(h.map(E=>this.executeToolCall(e[E],t,s)));for(let E=0;E<h.length;E++)c.set(h[E],y[E])}});await Promise.all(m)}else{let m=await Promise.allSettled(e.map(p=>this.executeToolCall(p,t,s)));c=new Map(m.map((p,g)=>[g,p]))}return{blocks:e.map((m,p)=>{let g=c.get(p);return g.status==="fulfilled"?n(m,g.value):{type:"tool_result",tool_use_id:m.id,content:`Tool execution failed: ${g.reason}`,is_error:!0}}),attachments:r}}async executeToolCall(e,t,s){let r=this.skillRegistry?.get(e.name);if(!r)return this.logger.warn({tool:e.name},"Unknown skill requested"),{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let n=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!n.allowed)return this.logger.warn({tool:e.name,reason:n.reason,rule:n.matchedRule?.id},"Skill execution denied by security rules"),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(Z(),ee));n=new a(s),o=`agent-${++this.agentIdCounter}`,this.activeAgents.set(o,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:n,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:n,onProgress:s}:s?{...t,onProgress:s}:t;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,n);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){return{content:`Skill execution failed: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),n=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${n}s | Last activity ${Math.round(r.idleMs/1e3)}s ago`)}return e.push(""),e.push("If the user asks what you or the agent is doing, describe the above status in natural language."),e.join(`
|
|
845
|
+
`)}applyMemoryBudget(e){let t=e.some(o=>o.score!=null&&o.score>0),s=e;t&&(s=e.filter(o=>(o.score??1)>=xp));let r=0,n=[];for(let o of s){let i=Le(`[${o.category}] ${o.key}: ${o.value}`);if(r+i>Ip)break;r+=i,n.push(o)}return n.length<e.length&&this.logger.info({original:e.length,kept:n.length,tokenCount:r,droppedByScore:e.length-s.length},"Memory budget applied"),n}compressToolLoop(e,t,s=0){let r=this.llm.getContextWindow(),n=Math.floor(r.maxInputTokens*td);if(Le(t)+s+e.reduce((h,y)=>h+er(y),0)<=n)return;let a=[];for(let h=0;h<e.length-1;h++){let y=e[h],E=e[h+1];y.role==="assistant"&&Array.isArray(y.content)&&y.content.some(A=>A.type==="tool_use")&&E.role==="user"&&Array.isArray(E.content)&&E.content.some(A=>A.type==="tool_result")&&a.push({start:h,end:h+1})}if(a.length<=sd)return;let c=a.length-sd,d=a.slice(0,c),m=[];for(let h of d){let y=e[h.start],E=[];if(Array.isArray(y.content))for(let F of y.content)F.type==="tool_use"&&E.push(F.name);let A=e[h.end],R="ok";Array.isArray(A.content)&&A.content.some(x=>x.type==="tool_result"&&x.is_error)&&(R="error"),m.push(`- ${E.join(", ")}: ${R}`)}let p=d[0].start,f=d[d.length-1].end-p+1;e.splice(p,f,{role:"assistant",content:`[Earlier tool interactions compressed (${d.length} pairs):
|
|
845
846
|
${m.join(`
|
|
846
847
|
`)}
|
|
847
|
-
]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:f-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let n=this.llm.getContextWindow(),o=Math.floor(n.maxInputTokens*td*r),i=Le(e)+s,a=t[t.length-1],c=er(a),m=i+c+200+500,p=o-m;if(p<=0)return this.logger.warn({maxInputTokens:o,systemTokens:i,latestTokens:c},"Context window very tight, sending only latest message"),[a];let g=t.slice(0,-1),f=this.groupToolPairs(g),h=[];for(let A=f.length-1;A>=0;A--){let R=f[A].reduce((F,x)=>F+er(x),0);if(R>p)break;p-=R,h.unshift(f[A])}let
|
|
848
|
+
]`},{role:"user",content:"[Context compressed to fit context window. Continue with the current task.]"}),this.logger.info({compressedPairs:d.length,removedMessages:f-2},"Compressed tool loop to fit context window")}trimToContextWindow(e,t,s=0,r=1){let n=this.llm.getContextWindow(),o=Math.floor(n.maxInputTokens*td*r),i=Le(e)+s,a=t[t.length-1],c=er(a),m=i+c+200+500,p=o-m;if(p<=0)return this.logger.warn({maxInputTokens:o,systemTokens:i,latestTokens:c},"Context window very tight, sending only latest message"),[a];let g=t.slice(0,-1),f=this.groupToolPairs(g),h=[];for(let A=f.length-1;A>=0;A--){let R=f[A].reduce((F,x)=>F+er(x),0);if(R>p)break;p-=R,h.unshift(f[A])}let y=h.flat(),E=g.length-y.length;if(E>0){this.logger.info({trimmedCount:E,totalMessages:t.length,maxInputTokens:o},"Trimmed conversation history to fit context window");let A=g.slice(0,g.length-y.length),R=this.summarizeTrimmedMessages(A);y.unshift({role:"user",content:`[Earlier conversation summary \u2014 ${E} messages were trimmed to fit the context window:
|
|
848
849
|
${R}
|
|
849
850
|
|
|
850
|
-
The conversation continues below with the most recent messages.]`})}return
|
|
851
|
+
The conversation continues below with the most recent messages.]`})}return y.push(a),this.promptBuilder.sanitizeToolMessages(y)}summarizeTrimmedMessages(e){let t=[];for(let r of e){let n=this.extractMessageText(r);if(!n)continue;let o=n.length>150?n.slice(0,150)+"...":n,i=r.role==="user"?"User":"Assistant";if(t.push(`- ${i}: ${o}`),r.role==="assistant"&&Array.isArray(r.content)){for(let a of r.content)if(a.type==="tool_use"){let 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(`
|
|
851
852
|
`)}return t.join(`
|
|
852
853
|
`)}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}
|
|
853
854
|
|
|
854
855
|
`;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),d=`[File received: "${i.fileName??"unknown"}" (${this.formatBytes(i.data.length)}, ${i.mimeType??"unknown type"})]
|
|
855
|
-
[Saved to: ${a}]`;if(c&&i.data.length<=
|
|
856
|
+
[Saved to: ${a}]`;if(c&&i.data.length<=Ap){let m=i.data.toString("utf-8");d+=`
|
|
856
857
|
[File content]:
|
|
857
858
|
${m}`}if(this.documentProcessor&&this.isIngestable(i.mimeType))try{let m=await this.documentProcessor.ingest(e.userId,a,i.fileName??"unknown",i.mimeType??"application/octet-stream");if(m.existing){try{Ri.unlinkSync(a)}catch{}d=`[File received: "${i.fileName??"unknown"}" (duplicate, not saved again)]
|
|
858
859
|
[IMPORTANT: This document is already indexed (${m.chunkCount} chunks). To read or answer questions about it, use the "document" skill with action "search" and a relevant query. Do NOT use shell/file tools to read the PDF.]`}else d+=`
|
|
859
|
-
[IMPORTANT: Document has been indexed (${m.chunkCount} chunks). To read or answer questions about it, use the "document" skill with action "search" and a relevant query. Do NOT use shell/file tools to read the PDF.]`}catch(m){this.logger.warn({err:m,fileName:i.fileName},"Auto-ingest failed")}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");if(r.some(i=>i.type==="image")&&!o)r.push({type:"text",text:"What do you see in this image?"});else if(n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))){let i=r.some(c=>c.type==="text"&&c.text.includes("document is already indexed")),a=r.some(c=>c.type==="text"&&c.text.includes("Document has been indexed"));i||a?r.push({type:"text",text:"The user sent this document. It has been automatically indexed. Acknowledge receipt and tell the user the document is ready \u2014 they can ask questions about its content anytime."}):r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."})}else r.length===0&&r.push({type:"text",text:e.text||"(empty message)"});return r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??Ql.resolve("./data/inbox");try{Ri.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=Ql.join(t,o);try{return Ri.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isIngestable(e){return e?["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/msword","text/plain","text/csv","text/markdown","text/html","application/json","application/xml"].includes(e)||e.startsWith("text/"):!1}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var $r,Di=_(()=>{"use strict";$r=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,n){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=n,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{let s=`\u23F0 Reminder: ${t.message}`;if(await this.sendMessage(t.platform,t.chatId,s),this.linkedUsers)try{let r=this.linkedUsers.getMasterUserId(t.userId),n=this.linkedUsers.getLinkedUsers(r);for(let o of n){if(o.platform===t.platform)continue;let i=this.linkedUsers.findConversation(o.platform,o.id);i&&await this.sendMessage(o.platform,i.chatId,s)}}catch(r){this.logger.debug({err:r,reminderId:t.id},"Cross-platform reminder delivery failed")}this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var kr,Li=_(()=>{"use strict";kr=class{static{u(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var vr,Ni=_(()=>{"use strict";vr=class{static{u(this,"SpeechSynthesizer")}logger;apiKey;baseUrl;model;voice;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,this.baseUrl=e.baseUrl??"https://api.openai.com/v1",this.model=e.ttsModel??"tts-1",this.voice=e.ttsVoice??"alloy"}async synthesize(e){this.logger.info({textLength:e.length,model:this.model,voice:this.voice},"Synthesizing speech");let t=await fetch(`${this.baseUrl}/audio/speech`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:this.model,input:e,voice:this.voice,response_format:"opus"})});if(!t.ok){let r=await t.text();throw new Error(`TTS failed: ${t.status} ${r}`)}let s=Buffer.from(await t.arrayBuffer());return this.logger.info({audioBytes:s.length},"Speech synthesized"),s}}});var Sr,Mi=_(()=>{"use strict";Sr=class{static{u(this,"ImageGenerator")}config;logger;constructor(e,t){this.config=e,this.logger=t}async generate(e,t={}){return this.logger.info({provider:this.config.provider,model:t.model,size:t.size},"Generating image"),this.config.provider==="openai"?this.generateOpenAI(e,t):this.generateGoogle(e,t)}async generateOpenAI(e,t){let{default:s}=await import("openai"),r=new s({apiKey:this.config.apiKey,...this.config.baseUrl&&{baseURL:this.config.baseUrl}}),n=t.model??"gpt-image-1",i=(await r.images.generate({model:n,prompt:e,n:1,size:t.size??"1024x1024",quality:t.quality??"medium"})).data?.[0]?.b64_json;if(!i)throw new Error("OpenAI image generation returned no data");let a=Buffer.from(i,"base64");return this.logger.info({model:n,bytes:a.length},"Image generated via OpenAI"),{data:a,mimeType:"image/png"}}async generateGoogle(e,t){let{GoogleGenAI:s}=await import("@google/genai"),r=new s({apiKey:this.config.apiKey}),n=t.model??"gemini-2.0-flash-exp",a=(await r.models.generateContent({model:n,contents:[{role:"user",parts:[{text:e}]}],config:{responseModalities:["IMAGE","TEXT"]}})).candidates?.[0]?.content?.parts?.find(m=>m.inlineData?.mimeType?.startsWith("image/"));if(!a?.inlineData)throw new Error("Google image generation returned no image data");let c=Buffer.from(a.inlineData.data,"base64"),d=a.inlineData.mimeType??"image/png";return this.logger.info({model:n,bytes:c.length,mimeType:d},"Image generated via Google"),{data:c,mimeType:d}}}});var Ar,Oi=_(()=>{"use strict";Ar=class{static{u(this,"TransitClient")}logger;hafasClient;constructor(e){this.logger=e}async getClient(){if(this.hafasClient)return this.hafasClient;let{createClient:e}=await import("hafas-client"),{profile:t}=await import("hafas-client/p/oebb/index.js");return this.hafasClient=e(t,"alfred-ai-assistant"),this.hafasClient}async searchStops(e){return(await(await this.getClient()).locations(e,{results:10})).filter(r=>r.type==="stop"||r.type==="station").map(r=>({id:r.id,name:r.name,location:r.location?{latitude:r.location.latitude,longitude:r.location.longitude}:void 0}))}async journeys(e,t,s){let r=await this.getClient(),n={results:s?.results??3};return s?.departure&&(n.departure=s.departure),s?.arrival&&(n.arrival=s.arrival),((await r.journeys(e,t,n)).journeys||[]).map(i=>{let a=(i.legs||[]).map(f=>({origin:f.origin?.name||f.origin?.id||"Unknown",destination:f.destination?.name||f.destination?.id||"Unknown",departure:f.departure||f.plannedDeparture||"",arrival:f.arrival||f.plannedArrival||"",line:f.line?.name,direction:f.direction,mode:f.line?.mode||(f.walking?"walking":"unknown"),walking:f.walking===!0})),c=a[0]?.departure||"",d=a[a.length-1]?.arrival||"",m=c&&d?Math.round((new Date(d).getTime()-new Date(c).getTime())/6e4):0,p=a.filter(f=>!f.walking),g=Math.max(0,p.length-1);return{legs:a,departure:c,arrival:d,duration:m,transfers:g}})}async departures(e,t){let s=await this.getClient(),r={duration:t?.duration??30};t?.when&&(r.when=t.when);let n=await s.departures(e,r);return(n.departures||n||[]).map(o=>{let i=o.plannedWhen?new Date(o.plannedWhen):null,a=o.when?new Date(o.when):null,c=i&&a?Math.round((a.getTime()-i.getTime())/6e4):o.delay!=null?Math.round(o.delay/60):void 0;return{line:o.line?.name||o.line?.fahrtNr||"Unknown",direction:o.direction||o.destination?.name||"Unknown",when:o.when||o.plannedWhen||"",delay:c&&c>0?c:void 0,platform:o.platform||void 0}})}}});var Ir,Pi=_(()=>{"use strict";Ir=class{static{u(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t=t.replace(/<(?!\/?(?:b|i|s|u|a|pre|code|tg-spoiler|tg-emoji|blockquote)(?:[\s>\/]|$))/gi,"<"),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,"&").replace(/</g,"<").replace(/>/g,">")}}});var xr,Ui=_(()=>{"use strict";xr=class{static{u(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;let o=this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions});return this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored"),o.id}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content");return}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let 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}}});import{createHash as xp}from"node:crypto";var Rr,Fi=_(()=>{"use strict";Rr=class{static{u(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await import("node:fs"),o=n.readFileSync(t),i=xp("sha256").update(o).digest("hex"),a=this.docRepo.findByContentHash(e,i);if(a&&a.chunkCount>0)return this.logger.info({documentId:a.id,filename:s,contentHash:i.slice(0,12)},"Document already ingested (duplicate)"),{documentId:a.id,chunkCount:a.chunkCount,existing:!0};a&&a.chunkCount===0&&(this.logger.info({documentId:a.id,filename:s},"Removing failed previous ingest attempt"),this.docRepo.deleteDocument(a.id));let c=await this.extractText(t,r),d=n.statSync(t),m=this.docRepo.createDocument(e,s,r,d.size,i),p=this.chunkText(c,500,50);for(let g=0;g<p.length;g++){let f;try{f=await this.embeddingService.embedAndStore(e,p[g],"document",`${m.id}:${g}`)}catch(h){this.logger.warn({documentId:m.id,chunkIndex:g,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(m.id,g,p[g],f)}return this.docRepo.updateChunkCount(m.id,p.length),this.logger.info({documentId:m.id,filename:s,chunkCount:p.length},"Document ingested"),{documentId:m.id,chunkCount:p.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(c-200,a),m=e.slice(d,c+200),p=m.lastIndexOf(`
|
|
860
|
+
[IMPORTANT: Document has been indexed (${m.chunkCount} chunks). To read or answer questions about it, use the "document" skill with action "search" and a relevant query. Do NOT use shell/file tools to read the PDF.]`}catch(m){this.logger.warn({err:m,fileName:i.fileName},"Auto-ingest failed")}r.push({type:"text",text:d}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");if(r.some(i=>i.type==="image")&&!o)r.push({type:"text",text:"What do you see in this image?"});else if(n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))){let i=r.some(c=>c.type==="text"&&c.text.includes("document is already indexed")),a=r.some(c=>c.type==="text"&&c.text.includes("Document has been indexed"));i||a?r.push({type:"text",text:"The user sent this document. It has been automatically indexed. Acknowledge receipt and tell the user the document is ready \u2014 they can ask questions about its content anytime."}):r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."})}else r.length===0&&r.push({type:"text",text:e.text||"(empty message)"});return r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??Ql.resolve("./data/inbox");try{Ri.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=Ql.join(t,o);try{return Ri.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isIngestable(e){return e?["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/msword","text/plain","text/csv","text/markdown","text/html","application/json","application/xml"].includes(e)||e.startsWith("text/"):!1}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var $r,Di=_(()=>{"use strict";$r=class{static{u(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;linkedUsers;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3,n){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.linkedUsers=n,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{let s=`\u23F0 Reminder: ${t.message}`;if(await this.sendMessage(t.platform,t.chatId,s),this.linkedUsers)try{let r=this.linkedUsers.getMasterUserId(t.userId),n=this.linkedUsers.getLinkedUsers(r);for(let o of n){if(o.platform===t.platform)continue;let i=this.linkedUsers.findConversation(o.platform,o.id);i&&await this.sendMessage(o.platform,i.chatId,s)}}catch(r){this.logger.debug({err:r,reminderId:t.id},"Cross-platform reminder delivery failed")}this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var kr,Li=_(()=>{"use strict";kr=class{static{u(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var vr,Ni=_(()=>{"use strict";vr=class{static{u(this,"SpeechSynthesizer")}logger;apiKey;baseUrl;model;voice;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,this.baseUrl=e.baseUrl??"https://api.openai.com/v1",this.model=e.ttsModel??"tts-1",this.voice=e.ttsVoice??"alloy"}async synthesize(e){this.logger.info({textLength:e.length,model:this.model,voice:this.voice},"Synthesizing speech");let t=await fetch(`${this.baseUrl}/audio/speech`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:this.model,input:e,voice:this.voice,response_format:"opus"})});if(!t.ok){let r=await t.text();throw new Error(`TTS failed: ${t.status} ${r}`)}let s=Buffer.from(await t.arrayBuffer());return this.logger.info({audioBytes:s.length},"Speech synthesized"),s}}});var Sr,Mi=_(()=>{"use strict";Sr=class{static{u(this,"ImageGenerator")}config;logger;constructor(e,t){this.config=e,this.logger=t}async generate(e,t={}){return this.logger.info({provider:this.config.provider,model:t.model,size:t.size},"Generating image"),this.config.provider==="openai"?this.generateOpenAI(e,t):this.generateGoogle(e,t)}async generateOpenAI(e,t){let{default:s}=await import("openai"),r=new s({apiKey:this.config.apiKey,...this.config.baseUrl&&{baseURL:this.config.baseUrl}}),n=t.model??"gpt-image-1",i=(await r.images.generate({model:n,prompt:e,n:1,size:t.size??"1024x1024",quality:t.quality??"medium"})).data?.[0]?.b64_json;if(!i)throw new Error("OpenAI image generation returned no data");let a=Buffer.from(i,"base64");return this.logger.info({model:n,bytes:a.length},"Image generated via OpenAI"),{data:a,mimeType:"image/png"}}async generateGoogle(e,t){let{GoogleGenAI:s}=await import("@google/genai"),r=new s({apiKey:this.config.apiKey}),n=t.model??"gemini-2.0-flash-exp",a=(await r.models.generateContent({model:n,contents:[{role:"user",parts:[{text:e}]}],config:{responseModalities:["IMAGE","TEXT"]}})).candidates?.[0]?.content?.parts?.find(m=>m.inlineData?.mimeType?.startsWith("image/"));if(!a?.inlineData)throw new Error("Google image generation returned no image data");let c=Buffer.from(a.inlineData.data,"base64"),d=a.inlineData.mimeType??"image/png";return this.logger.info({model:n,bytes:c.length,mimeType:d},"Image generated via Google"),{data:c,mimeType:d}}}});var Ar,Oi=_(()=>{"use strict";Ar=class{static{u(this,"TransitClient")}logger;hafasClient;constructor(e){this.logger=e}async getClient(){if(this.hafasClient)return this.hafasClient;let{createClient:e}=await import("hafas-client"),{profile:t}=await import("hafas-client/p/oebb/index.js");return this.hafasClient=e(t,"alfred-ai-assistant"),this.hafasClient}async searchStops(e){return(await(await this.getClient()).locations(e,{results:10})).filter(r=>r.type==="stop"||r.type==="station").map(r=>({id:r.id,name:r.name,location:r.location?{latitude:r.location.latitude,longitude:r.location.longitude}:void 0}))}async journeys(e,t,s){let r=await this.getClient(),n={results:s?.results??3};return s?.departure&&(n.departure=s.departure),s?.arrival&&(n.arrival=s.arrival),((await r.journeys(e,t,n)).journeys||[]).map(i=>{let a=(i.legs||[]).map(f=>({origin:f.origin?.name||f.origin?.id||"Unknown",destination:f.destination?.name||f.destination?.id||"Unknown",departure:f.departure||f.plannedDeparture||"",arrival:f.arrival||f.plannedArrival||"",line:f.line?.name,direction:f.direction,mode:f.line?.mode||(f.walking?"walking":"unknown"),walking:f.walking===!0})),c=a[0]?.departure||"",d=a[a.length-1]?.arrival||"",m=c&&d?Math.round((new Date(d).getTime()-new Date(c).getTime())/6e4):0,p=a.filter(f=>!f.walking),g=Math.max(0,p.length-1);return{legs:a,departure:c,arrival:d,duration:m,transfers:g}})}async departures(e,t){let s=await this.getClient(),r={duration:t?.duration??30};t?.when&&(r.when=t.when);let n=await s.departures(e,r);return(n.departures||n||[]).map(o=>{let i=o.plannedWhen?new Date(o.plannedWhen):null,a=o.when?new Date(o.when):null,c=i&&a?Math.round((a.getTime()-i.getTime())/6e4):o.delay!=null?Math.round(o.delay/60):void 0;return{line:o.line?.name||o.line?.fahrtNr||"Unknown",direction:o.direction||o.destination?.name||"Unknown",when:o.when||o.plannedWhen||"",delay:c&&c>0?c:void 0,platform:o.platform||void 0}})}}});var Ir,Pi=_(()=>{"use strict";Ir=class{static{u(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t=t.replace(/<(?!\/?(?:b|i|s|u|a|pre|code|tg-spoiler|tg-emoji|blockquote)(?:[\s>\/]|$))/gi,"<"),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,"&").replace(/</g,"<").replace(/>/g,">")}}});var xr,Ui=_(()=>{"use strict";xr=class{static{u(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;let o=this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions});return this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored"),o.id}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content");return}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let 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}}});import{createHash as Rp}from"node:crypto";var Rr,Fi=_(()=>{"use strict";Rr=class{static{u(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await import("node:fs"),o=n.readFileSync(t),i=Rp("sha256").update(o).digest("hex"),a=this.docRepo.findByContentHash(e,i);if(a&&a.chunkCount>0)return this.logger.info({documentId:a.id,filename:s,contentHash:i.slice(0,12)},"Document already ingested (duplicate)"),{documentId:a.id,chunkCount:a.chunkCount,existing:!0};a&&a.chunkCount===0&&(this.logger.info({documentId:a.id,filename:s},"Removing failed previous ingest attempt"),this.docRepo.deleteDocument(a.id));let c=await this.extractText(t,r),d=n.statSync(t),m=this.docRepo.createDocument(e,s,r,d.size,i),p=this.chunkText(c,500,50);for(let g=0;g<p.length;g++){let f;try{f=await this.embeddingService.embedAndStore(e,p[g],"document",`${m.id}:${g}`)}catch(h){this.logger.warn({documentId:m.id,chunkIndex:g,err:h},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(m.id,g,p[g],f)}return this.docRepo.updateChunkCount(m.id,p.length),this.logger.info({documentId:m.id,filename:s,chunkCount:p.length},"Document ingested"),{documentId:m.id,chunkCount:p.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let d=Math.max(c-200,a),m=e.slice(d,c+200),p=m.lastIndexOf(`
|
|
860
861
|
|
|
861
862
|
`);if(p>0)c=d+p;else{let f=m.lastIndexOf(". ");f>0&&(c=d+f+1)}let g=e.slice(a,c).trim();g&&i.push(g),a=c-o}return i.filter(c=>c.length>0)}}});var Cr,ji=_(()=>{"use strict";hs();Cr=class{static{u(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;users;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n,o){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.users=n,this.logger=o}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.getPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(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{context:r}=Ke(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=new Promise((c,d)=>setTimeout(()=>d(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let c=o.success?`\u2705 Background task completed: ${e.description}
|
|
862
863
|
|
|
@@ -864,12 +865,12 @@ Result: ${o.display??JSON.stringify(o.data)}`:`\u274C Background task failed: ${
|
|
|
864
865
|
|
|
865
866
|
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}
|
|
866
867
|
|
|
867
|
-
Error: ${s}`)}}}});import
|
|
868
|
+
Error: ${s}`)}}}});import Cp from"node:crypto";var Dr,Bi=_(()=>{"use strict";hs();Dr=class{static{u(this,"ProactiveScheduler")}actionRepo;skillRegistry;skillSandbox;llm;adapters;users;logger;pipeline;formatter;conversationManager;tickTimer;tickIntervalMs=6e4;constructor(e,t,s,r,n,o,i,a,c,d){this.actionRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.llm=r,this.adapters=n,this.users=o,this.logger=i,this.pipeline=a,this.formatter=c,this.conversationManager=d}start(){this.tickTimer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Proactive scheduler started")}stop(){this.tickTimer&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.logger.info("Proactive scheduler stopped")}async tick(){try{let e=this.actionRepo.getDue();for(let t of e)try{await this.executeAction(t)}catch(s){this.logger.error({err:s,actionId:t.id},"Failed to execute scheduled action")}}catch(e){this.logger.error({err:e},"Error during proactive scheduler tick")}}async executeAction(e){let t=new Date().toISOString();this.logger.info({actionId:e.id,name:e.name},"Executing scheduled action");let s;if(e.promptTemplate&&this.pipeline)try{let d=`scheduled-${e.id}`,m={id:`scheduled-${Cp.randomUUID()}`,platform:e.platform,chatId:d,chatType:"dm",userId:e.userId,userName:e.userId,text:e.promptTemplate,timestamp:new Date,metadata:{scheduled:!0,skipHistory:!0,tier:"fast"}},p=await this.pipeline.process(m);s=(this.formatter?this.formatter.format(p.text,e.platform):{text:p.text,parseMode:"text"}).text;let f=this.adapters.get(e.platform);if(f&&p.attachments)for(let h of p.attachments)try{let y=h.mimeType.startsWith("image/"),E=h.mimeType==="audio/ogg"||h.mimeType==="audio/opus";y?await f.sendPhoto(e.chatId,h.data,h.fileName):E?await f.sendVoice(e.chatId,h.data):await f.sendFile(e.chatId,h.data,h.fileName)}catch(y){this.logger.warn({err:y,fileName:h.fileName,actionId:e.id},"Failed to send scheduled action attachment")}}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"Pipeline execution failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else if(e.promptTemplate)try{s=(await this.llm.complete({messages:[{role:"user",content:e.promptTemplate}],maxTokens:1024,tier:"fast"})).content}catch(d){let m=d instanceof Error?d.message:String(d);this.logger.error({actionId:e.id,err:d},"LLM call failed for scheduled action"),s=`Scheduled action "${e.name}" failed: ${m}`}else{let d=this.skillRegistry.get(e.skillName);if(!d)this.logger.warn({actionId:e.id,skillName:e.skillName},"Unknown skill for scheduled action"),s=`Scheduled action "${e.name}" failed: unknown skill "${e.skillName}"`;else try{let m;try{m=JSON.parse(e.skillInput)}catch{m={},this.logger.warn({actionId:e.id},"Invalid skillInput JSON, using empty input")}let{context:p}=Ke(this.users,{userId:e.userId,platform:e.platform,chatId:e.chatId,chatType:"dm"}),g=await this.skillSandbox.execute(d,m,p);s=g.success?`\u{1F514} Scheduled: ${e.name}
|
|
868
869
|
|
|
869
870
|
${g.display??JSON.stringify(g.data)}`:`\u274C Scheduled action "${e.name}" failed: ${g.error}`}catch(m){let p=m instanceof Error?m.message:String(m);s=`\u274C Scheduled action "${e.name}" failed: ${p}`}}let r=s.trim(),n=(e.promptTemplate??"").toLowerCase(),o=/nichts|silent|no\s*output|don't\s*respond|do\s*not\s*respond/i.test(n),i=/offline|down|fehler|error|warn|critical|alert|fail|nicht\s+(erreichbar|verf[uü]gbar|gefunden|online)|ausgefallen|stopped|unreachable|unavailable|⚠|❌|🚨|🔴/i.test(r)&&!/keine\s+(probleme|fehler|auff[aä]lligkeiten)/i.test(r);if(!r||r.length<3||o&&!i)this.logger.info({actionId:e.id,name:e.name},"Scheduled action produced no actionable output \u2014 skipping notification");else{let d=this.adapters.get(e.platform);if(d)try{if(await d.sendMessage(e.chatId,s),e.promptTemplate&&this.conversationManager){let m=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,e.userId),p=`[Automated Scheduled Alert: ${e.name}]
|
|
870
|
-
${s}`;this.conversationManager.addMessage(m.id,"assistant",p)}}catch(m){this.logger.error({err:m,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let d=`scheduled-${e.id}`,m=this.conversationManager.getOrCreateConversation(e.platform,d,e.userId);this.conversationManager.pruneMessages(m.id,20)}catch{}let c=this.calculateNextRun(e);c?this.actionRepo.updateLastRun(e.id,t,c):(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 rd(l,e){let t=e.split("."),s=l;for(let r of t){if(s==null)return;if(typeof s=="object"){if(r==="length"&&Array.isArray(s)){s=s.length;continue}s=s[r]}else return}return s}function nd(l,e,t,s){let r=
|
|
871
|
+
${s}`;this.conversationManager.addMessage(m.id,"assistant",p)}}catch(m){this.logger.error({err:m,actionId:e.id},"Failed to send scheduled action result")}}if(e.promptTemplate&&this.conversationManager)try{let d=`scheduled-${e.id}`,m=this.conversationManager.getOrCreateConversation(e.platform,d,e.userId);this.conversationManager.pruneMessages(m.id,20)}catch{}let c=this.calculateNextRun(e);c?this.actionRepo.updateLastRun(e.id,t,c):(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 rd(l,e){let t=e.split("."),s=l;for(let r of t){if(s==null)return;if(typeof s=="object"){if(r==="length"&&Array.isArray(s)){s=s.length;continue}s=s[r]}else return}return s}function nd(l,e,t,s){let r=Dp(l);if(s===null)return{triggered:!1,displayValue:r};switch(e){case"lt":case"gt":case"lte":case"gte":{let n=fs(l),o=fs(t);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:e==="lt"?n<o:e==="gt"?n>o:e==="lte"?n<=o:n>=o,displayValue:r}}case"eq":return{triggered:String(l)===String(t),displayValue:r};case"neq":return{triggered:String(l)!==String(t),displayValue:r};case"contains":return{triggered:String(l).includes(String(t??"")),displayValue:r};case"not_contains":return{triggered:!String(l).includes(String(t??"")),displayValue:r};case"changed":return{triggered:JSON.stringify(l)!==JSON.stringify(s),displayValue:r};case"increased":{let n=fs(l),o=fs(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n>o,displayValue:r}}case"decreased":{let n=fs(l),o=fs(s);return n===null||o===null?{triggered:!1,displayValue:r}:{triggered:n<o,displayValue:r}}default:return{triggered:!1,displayValue:r}}}function fs(l){if(typeof l=="number")return l;let e=parseFloat(String(l));return isNaN(e)?null:e}function Dp(l){return l==null?"null":typeof l=="object"?JSON.stringify(l):String(l)}var od=_(()=>{"use strict";u(rd,"extractField");u(nd,"evaluateCondition");u(fs,"toNumber");u(Dp,"formatValue")});var Lp,Ln,id=_(()=>{"use strict";od();hs();Lp={lt:"<",gt:">",lte:"<=",gte:">=",eq:"=",neq:"!=",contains:"contains",not_contains:"not contains",changed:"changed",increased:"increased",decreased:"decreased"},Ln=class{static{u(this,"WatchEngine")}watchRepo;skillRegistry;skillSandbox;adapters;users;logger;timer=null;tickIntervalMs=6e4;constructor(e,t,s,r,n,o){this.watchRepo=e,this.skillRegistry=t,this.skillSandbox=s,this.adapters=r,this.users=n,this.logger=o}start(){this.timer=setInterval(()=>this.tick(),this.tickIntervalMs),this.logger.info("Watch engine started")}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.logger.info("Watch engine stopped")}async tick(){try{let e=this.watchRepo.getDue();for(let t of e)try{await this.checkWatch(t)}catch(s){this.logger.error({err:s,watchId:t.id},"Failed to check watch")}}catch(e){this.logger.error({err:e},"Error during watch engine tick")}}async checkWatch(e){let t=new Date().toISOString();this.logger.debug({watchId:e.id,name:e.name,skill:e.skillName},"Checking watch");let s=this.skillRegistry.get(e.skillName);if(!s){this.logger.warn({watchId:e.id,skillName:e.skillName},"Unknown skill for watch"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let{context:r}=Ke(this.users,{platform:e.platform,chatId:e.chatId,chatType:"dm"}),n=await this.skillSandbox.execute(s,e.skillParams,r);if(!n.success){this.logger.warn({watchId:e.id,error:n.error},"Watch skill execution failed"),this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:e.lastValue});return}let o=rd(n.data,e.condition.field),i=e.lastValue!==null?JSON.parse(e.lastValue):null,{triggered:a,displayValue:c}=nd(o,e.condition.operator,e.condition.value,i),d=JSON.stringify(o);if(a&&this.isCooldownExpired(e)){let m=e.messageTemplate??this.formatAlert(e,c),p=this.adapters.get(e.platform);if(p)try{await p.sendMessage(e.chatId,m),this.logger.info({watchId:e.id,name:e.name,value:c},"Watch alert sent")}catch(g){this.logger.error({err:g,watchId:e.id},"Failed to send watch alert")}this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d,lastTriggeredAt:t})}else this.watchRepo.updateAfterCheck(e.id,{lastCheckedAt:t,lastValue:d})}isCooldownExpired(e){if(!e.lastTriggeredAt)return!0;let t=e.cooldownMinutes*6e4;return Date.now()-new Date(e.lastTriggeredAt).getTime()>=t}formatAlert(e,t){let s=Lp[e.condition.operator]??e.condition.operator,r=e.condition.value!=null?` ${s} ${e.condition.value}`:` ${s}`;return`\u26A1 Watch Alert: ${e.name}
|
|
871
872
|
Bedingung erf\xFCllt: ${e.condition.field}${r}
|
|
872
|
-
Aktueller Wert: ${t}`}}});function Hi(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of
|
|
873
|
+
Aktueller Wert: ${t}`}}});function Hi(l){let e=l.trim();if(e.length<10)return{level:"low",matchedPatterns:[]};for(let s of Np)if(s.test(e))return{level:"low",matchedPatterns:[]};let t=[];for(let s of Mp)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 Np,Mp,qi=_(()=>{"use strict";Np=[/^(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],Mp=[{name:"fact:name",patterns:[/\b(my name is|i'm called|i am called|ich heiße|ich bin der|ich bin die|mein name ist)\b/i]},{name:"fact:location",patterns:[/\b(i live in|i'm from|i am from|ich wohne|ich lebe in|ich komme aus|ich bin aus)\b/i]},{name:"fact:work",patterns:[/\b(i work at|i work as|i work for|ich arbeite|mein job|mein beruf|ich bin .{0,20}(entwickler|ingenieur|lehrer|arzt|designer))\b/i]},{name:"fact:birthday",patterns:[/\b(my birthday|i was born|ich bin geboren|mein geburtstag|ich habe am .{1,15} geburtstag)\b/i]},{name:"fact:age",patterns:[/\b(i'm \d+ years|i am \d+ years|ich bin \d+ (jahre|jahr))\b/i]},{name:"preference:like",patterns:[/\b(i love|i really like|i enjoy|ich liebe|ich mag|mir gefällt|mir gefallen)\b/i]},{name:"preference:dislike",patterns:[/\b(i hate|i dislike|i can't stand|ich hasse|ich mag .{0,5} nicht|ich kann .{0,10} nicht leiden)\b/i]},{name:"preference:prefer",patterns:[/\b(i prefer|i'd rather|ich bevorzuge|ich nehme lieber|mir ist .{0,10} lieber)\b/i]},{name:"preference:favorite",patterns:[/\b(my fav|my favorite|my favourite|mein lieblings|meine lieblings|am liebsten)\b/i]},{name:"correction",patterns:[/\b(actually|actually,? (i|my|it)|eigentlich|das stimmt nicht|nein,? ich|that's not right|that's wrong|nicht ganz)\b/i]},{name:"relationship:family",patterns:[/\b(my wife|my husband|my partner|meine frau|mein mann|mein partner|meine partnerin|my daughter|my son|mein sohn|meine tochter|my kids|meine kinder|my mother|my father|meine mutter|mein vater)\b/i]},{name:"relationship:professional",patterns:[/\b(my boss|my manager|my colleague|mein chef|mein vorgesetzter|mein kollege|meine kollegin)\b/i]},{name:"relationship:social",patterns:[/\b(my friend|my best friend|mein freund|meine freundin|mein bester freund)\b/i]},{name:"fact:language",patterns:[/\b(i speak|ich spreche|my native|meine muttersprache)\b/i]},{name:"fact:education",patterns:[/\b(i studied|i went to|ich habe .{0,10} studiert|ich war auf der|mein studium)\b/i]},{name:"fact:hobby",patterns:[/\b(my hobby|i play .{0,10}(guitar|piano|football|tennis|chess)|mein hobby|ich spiele|in my free time|in meiner freizeit)\b/i]},{name:"decision",patterns:[/\b(i've decided|i decided|i will always|ich habe (mich )?entschieden|ich werde immer)\b/i]},{name:"commitment",patterns:[/\b(i always|i never|ich mache immer|ich mache nie|i'm trying to|ich versuche)\b/i]}];u(Hi,"scanSignal")});var Op,Pp,Lr,zi=_(()=>{"use strict";Op=["fact","preference","correction","entity","decision","relationship","principle","commitment","moment","skill"],Pp=`You are a memory extraction system. Analyze the user message and extract personal facts about the USER (not about what they're asking).
|
|
873
874
|
|
|
874
875
|
Rules:
|
|
875
876
|
- Only extract information the user STATES about themselves
|
|
@@ -889,18 +890,18 @@ Extract memories from this conversation:
|
|
|
889
890
|
User: {USER_MESSAGE}
|
|
890
891
|
Assistant: {ASSISTANT_RESPONSE}
|
|
891
892
|
|
|
892
|
-
Return ONLY a valid JSON array, no explanation:`,Lr=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=
|
|
893
|
+
Return ONLY a valid JSON array, no explanation:`,Lr=class{static{u(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=Pp.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(d=>this.logger.debug({err:d},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(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 Op.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var Nr,Wi=_(()=>{"use strict";qi();zi();Nr=class{static{u(this,"ActiveLearningService")}extractor;logger;minMessageLength;maxExtractionsPerMinute;extractionTimestamps=new Map;constructor(e){this.logger=e.logger,this.minMessageLength=e.minMessageLength??15,this.maxExtractionsPerMinute=e.maxExtractionsPerMinute??5,this.extractor=new Lr(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Hi(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 Up,Fp,jp,Bp,Mr,Gi=_(()=>{"use strict";Up=Math.LN2,Fp=.3,jp=.7,Bp=3,Mr=class{static{u(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let h of n)for(let y of this.memoryRepo.keywordSearch(h,t,30))o.has(y.id)||(o.add(y.id),i.push(y));let a=[],c=!1;if(this.embeddingService)try{let h=new Set;for(let y of n)for(let E of await this.embeddingService.semanticSearch(y,t,30))h.has(E.key)||(h.add(E.key),a.push(E));c=a.length>0}catch(h){this.logger.debug({err:h},"Semantic search failed, falling back to keyword-only")}let d=new Map,m=i.length;for(let h=0;h<i.length;h++){let y=i[h],E=m>0?1-h/m:0,A=c?Fp:1,R=this.applyBoosts(E*A,y);d.set(y.key,{memory:{key:y.key,value:y.value,category:y.category,type:y.type,score:R},score:R}),this.memoryRepo.recordAccess(y.id)}if(c)for(let h of a){let y=h.score*jp,E=d.get(h.key);if(E)E.score+=y,E.memory.score=E.score;else{let A=this.memoryRepo.recall(e,h.key),R=this.applyBoosts(y,A||void 0);d.set(h.key,{memory:{key:h.key,value:h.value,category:h.category,type:A?.type||"general",score:R},score:R}),A&&this.memoryRepo.recordAccess(A.id)}}let p=Array.from(d.values()).sort((h,y)=>y.score-h.score),g=new Map,f=[];for(let{memory:h}of p){let y=g.get(h.type)||0;if(!(y>=Bp)&&(g.set(h.type,y+1),f.push(h),f.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:f.length,hasSemanticSearch:c},"Hybrid memory retrieval complete"),f}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let c of n)for(let d of this.memoryRepo.getRecentForPrompt(c,s))i.has(d.key)||(i.add(d.key),a.push({key:d.key,value:d.value,category:d.category,type:d.type,score:0}));return a.slice(0,s)}}applyBoosts(e,t){let s=e;if(t){s*=.5+.5*t.confidence;let r=new Date(t.updatedAt).getTime(),n=Date.now()-r,o=Math.exp(-Up*n/2592e6);s*=o}return s}}});import{EventEmitter as Hp}from"node:events";var he,Xe=_(()=>{"use strict";he=class extends Hp{static{u(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}async sendVoice(e,t,s){}endStream(e){}getStatus(){return this.status}splitText(e,t){if(e.length<=t)return[e];let s=[],r=e;for(;r.length>0;){if(r.length<=t){s.push(r);break}let n=-1,i=r.slice(0,t).lastIndexOf(`
|
|
893
894
|
|
|
894
|
-
`);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 Hp,InputFile as Vi}from"grammy";function ad(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var Nn,cd=_(()=>{"use strict";Xe();u(ad,"mapParseMode");Nn=class extends he{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new Hp(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:ad(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:ad(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 Vi(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 Vi(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Vi(t,"voice.ogg"),{caption:s});return String(r.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let 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 qp,GatewayIntentBits as Mn,Events as Ki}from"discord.js";var On,ld=_(()=>{"use strict";Xe();On=class extends he{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new qp({intents:[Mn.Guilds,Mn.GuildMessages,Mn.MessageContent,Mn.DirectMessages]}),this.client.on(Ki.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(Ki.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Ki.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var Pn,dd=_(()=>{"use strict";Xe();Pn=class extends he{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),c=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of c)try{let m=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(m.status===404)continue;if(!m.ok){console.error(`[matrix] Download failed (${m.status})`,s,d);continue}let p=await m.arrayBuffer(),g=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??g.length,data:g}}catch(m){console.error("[matrix] Download error",s,d,m);continue}console.error("[matrix] All download endpoints failed for",s)}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Un,ud=_(()=>{"use strict";Xe();Un=class extends he{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let{makeWASocket:e,useMultiFileAuthState:t,DisconnectReason:s,downloadMediaMessage:r}=await import("@whiskeysockets/baileys");this.downloadMedia=r;let{state:n,saveCreds:o}=await t(this.dataPath);this.socket=e({auth:n,printQRInTerminal:!0}),this.socket.ev.on("creds.update",o),this.socket.ev.on("connection.update",i=>{if(i.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),i.connection==="close"){let c=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),c){let d=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),d)}}}),this.socket.ev.on("messages.upsert",({messages:i,type:a})=>{if(a==="notify")for(let c of i)c.message&&(c.key.fromMe||this.processMessage(c).catch(d=>{this.emit("error",d instanceof Error?d:new Error(String(d)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Fn,md=_(()=>{"use strict";Xe();Fn=class extends he{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let 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 d=await c.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let m=await this.downloadAttachment(d);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let 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 Xi from"node:readline";var jn,pd=_(()=>{"use strict";Xe();jn=class extends he{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Xi.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
|
|
895
|
+
`);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 qp,InputFile as Vi}from"grammy";function ad(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var Nn,cd=_(()=>{"use strict";Xe();u(ad,"mapParseMode");Nn=class extends he{static{u(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new qp(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:u(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:ad(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:ad(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 Vi(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 Vi(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Vi(t,"voice.ogg"),{caption:s});return String(r.message_id)}normalizeMessage(e,t){return{id:String(e.message_id),platform:"telegram",chatId:String(e.chat.id),chatType:e.chat.type==="private"?"dm":"group",userId:String(e.from.id),userName:e.from.username??String(e.from.id),displayName:[e.from.first_name,e.from.last_name].filter(Boolean).join(" "),text:t,timestamp:new Date(e.date*1e3),replyToMessageId:e.reply_to_message?String(e.reply_to_message.message_id):void 0}}async downloadAttachment(e,t,s,r){try{let o=(await this.bot.api.getFile(e)).file_path;if(!o)return;let i=`https://api.telegram.org/file/bot${this.bot.token}/${o}`,a=await fetch(i);if(!a.ok)return;let 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 zp,GatewayIntentBits as Mn,Events as Ki}from"discord.js";var On,ld=_(()=>{"use strict";Xe();On=class extends he{static{u(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new zp({intents:[Mn.Guilds,Mn.GuildMessages,Mn.MessageContent,Mn.DirectMessages]}),this.client.on(Ki.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(Ki.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(Ki.Error,e=>{this.emit("error",e)}),await this.client.login(this.token)}async disconnect(){this.client?.destroy(),this.client=null,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){if(!this.client)throw new Error("Client is not connected");let r=await this.client.channels.fetch(e);if(!r?.isTextBased()||!("send"in r))throw new Error(`Channel ${e} is not a text channel`);let n=this.splitText(t,2e3),o="";for(let i=0;i<n.length;i++)i===0&&s?.replyToMessageId?o=(await(await r.messages.fetch(s.replyToMessageId)).reply(n[i])).id:o=(await r.send(n[i])).id;return o}async editMessage(e,t,s,r){if(!this.client)throw new Error("Client is not connected");let n=await this.client.channels.fetch(e);if(!n?.isTextBased()||!("messages"in n))throw new Error(`Channel ${e} is not a text channel`);await(await n.messages.fetch(t)).edit(s)}async deleteMessage(e,t){if(!this.client)throw new Error("Client is not connected");let s=await this.client.channels.fetch(e);if(!s?.isTextBased()||!("messages"in s))throw new Error(`Channel ${e} is not a text channel`);await(await s.messages.fetch(t)).delete()}async sendPhoto(e,t,s){if(!this.client)return;let r=await this.client.channels.fetch(e);return!r?.isTextBased()||!("send"in r)?void 0:(await r.send({content:s,files:[{attachment:t,name:"image.png"}]})).id}async sendFile(e,t,s,r){if(!this.client)return;let n=await this.client.channels.fetch(e);return!n?.isTextBased()||!("send"in n)?void 0:(await n.send({content:r,files:[{attachment:t,name:s}]})).id}async sendVoice(e,t,s){return this.sendFile(e,t,"voice.ogg",s)}async downloadAttachments(e){let t=[],s=e.attachments;if(!s||s.size===0)return t;for(let[,r]of s)try{let n=await fetch(r.url);if(!n.ok)continue;let o=await n.arrayBuffer(),i=Buffer.from(o),a=this.classifyContentType(r.contentType);t.push({type:a,url:r.url,mimeType:r.contentType??void 0,fileName:r.name??void 0,size:r.size??i.length,data:i})}catch(n){console.error("[discord] Failed to download attachment",r.url,n)}return t}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});var Pn,dd=_(()=>{"use strict";Xe();Pn=class extends he{static{u(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),c=[`${this.homeserverUrl}/_matrix/client/v1/media/download/${a}`,`${this.homeserverUrl}/_matrix/media/v3/download/${a}`];for(let d of c)try{let m=await fetch(d,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(m.status===404)continue;if(!m.ok){console.error(`[matrix] Download failed (${m.status})`,s,d);continue}let p=await m.arrayBuffer(),g=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??g.length,data:g}}catch(m){console.error("[matrix] Download error",s,d,m);continue}console.error("[matrix] All download endpoints failed for",s)}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Un,ud=_(()=>{"use strict";Xe();Un=class extends he{static{u(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let{makeWASocket:e,useMultiFileAuthState:t,DisconnectReason:s,downloadMediaMessage:r}=await import("@whiskeysockets/baileys");this.downloadMedia=r;let{state:n,saveCreds:o}=await t(this.dataPath);this.socket=e({auth:n,printQRInTerminal:!0}),this.socket.ev.on("creds.update",o),this.socket.ev.on("connection.update",i=>{if(i.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),i.connection==="close"){let c=i.lastDisconnect?.error?.output?.statusCode!==s.loggedOut;if(this.status="disconnected",this.emit("disconnected"),c){let d=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),d)}}}),this.socket.ev.on("messages.upsert",({messages:i,type:a})=>{if(a==="notify")for(let c of i)c.message&&(c.key.fromMe||this.processMessage(c).catch(d=>{this.emit("error",d instanceof Error?d:new Error(String(d)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Fn,md=_(()=>{"use strict";Xe();Fn=class extends he{static{u(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let 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 d=await c.json();n=String(d.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let d of r.attachments){let m=await this.downloadAttachment(d);m&&i.push(m)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let 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 Xi from"node:readline";var jn,pd=_(()=>{"use strict";Xe();jn=class extends he{static{u(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Xi.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
|
|
895
896
|
Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
|
|
896
897
|
`),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
|
|
897
898
|
Goodbye!
|
|
898
899
|
`),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(`
|
|
899
900
|
Alfred: ${t}
|
|
900
|
-
`),this.prompt(),r}async editMessage(e,t,s,r){Xi.clearLine(process.stdout,0),Xi.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import
|
|
901
|
+
`),this.prompt(),r}async editMessage(e,t,s,r){Xi.clearLine(process.stdout,0),Xi.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});import Wp from"node:http";import Gp from"node:crypto";var Bn,hd=_(()=>{"use strict";Xe();Bn=class extends he{static{u(this,"HttpAdapter")}port;host;platform="api";server=null;streams=new Map;messageCounter=0;constructor(e,t){super(),this.port=e,this.host=t}async connect(){this.status="connecting",this.server=Wp.createServer((e,t)=>{this.handleRequest(e,t)}),await new Promise((e,t)=>{this.server.listen(this.port,this.host,()=>{e()}),this.server.once("error",t)}),this.status="connected",this.emit("connected")}async disconnect(){for(let[e,t]of this.streams)this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e);this.server&&(await new Promise(e=>{this.server.close(()=>e())}),this.server=null),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=`api-resp-${++this.messageCounter}`,n=this.streams.get(e);return n&&this.writeSseEvent(n,"response",{type:"response",text:t}),r}async editMessage(e,t,s,r){let n=this.streams.get(e);n&&this.writeSseEvent(n,"status",{type:"status",text:s})}async deleteMessage(e,t){}async sendPhoto(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"image",data:t.toString("base64"),caption:s}),`api-photo-${++this.messageCounter}`}async sendFile(e,t,s,r){let n=this.streams.get(e);return n&&this.writeSseEvent(n,"attachment",{type:"attachment",attachmentType:"file",data:t.toString("base64"),fileName:s,caption:r}),`api-file-${++this.messageCounter}`}async sendVoice(e,t,s){let r=this.streams.get(e);return r&&this.writeSseEvent(r,"attachment",{type:"attachment",attachmentType:"voice",data:t.toString("base64"),caption:s}),`api-voice-${++this.messageCounter}`}endStream(e){let t=this.streams.get(e);t&&(this.writeSseEvent(t,"done",{type:"done"}),t.end(),this.streams.delete(e))}handleRequest(e,t){if(t.setHeader("Access-Control-Allow-Origin","*"),t.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type"),e.method==="OPTIONS"){t.writeHead(204),t.end();return}let s=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`);s.pathname==="/api/health"&&e.method==="GET"?this.handleHealth(t):s.pathname==="/api/message"&&e.method==="POST"?this.handleMessage(e,t):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Not found"})))}handleHealth(e){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok"}))}handleMessage(e,t){let s="";e.on("data",r=>{s+=r.toString()}),e.on("end",()=>{try{let r=JSON.parse(s),n=r.text;if(!n||typeof n!="string"){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:'Missing or invalid "text" field'}));return}let o=r.chatId??`api-chat-${Gp.randomUUID()}`,i=r.userId??"api-user",a=this.streams.get(o);a&&(this.writeSseEvent(a,"done",{type:"done"}),a.end()),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this.streams.set(o,t),e.on("close",()=>{this.streams.delete(o)}),this.messageCounter++;let c={id:`api-${this.messageCounter}`,platform:"api",chatId:o,chatType:"dm",userId:i,userName:i,displayName:"API User",text:n,timestamp:new Date};this.emit("message",c)}catch{t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON body"}))}})}writeSseEvent(e,t,s){e.writableEnded||e.write(`event: ${t}
|
|
901
902
|
data: ${JSON.stringify(s)}
|
|
902
903
|
|
|
903
|
-
`)}}});var st={};me(st,{CLIAdapter:()=>jn,DiscordAdapter:()=>On,HttpAdapter:()=>Bn,MatrixAdapter:()=>Pn,MessagingAdapter:()=>he,SignalAdapter:()=>Fn,TelegramAdapter:()=>Nn,WhatsAppAdapter:()=>Un});var rt=_(()=>{"use strict";Xe();cd();ld();dd();ud();md();pd();hd()});import Hn from"node:fs";import qn from"node:path";import Gp from"js-yaml";var It,fd=_(()=>{"use strict";Co();No();We();Wo();rn();Z();xi();Ci();Di();Li();Ni();Mi();Oi();Pi();Ui();Fi();ji();Bi();id();Wi();Gi();It=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;adapters=new Map;formatter=new Ir;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Ns("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ft(this.config.storage.path);let e=this.database.getDb(),t=new Ms(e),s=new Os(e);this.userRepo=s;let r=new gt(e),n=new Ps(e),o=new Us(e),i=new Fs(e),a=new js(e),c=new Bs(e),d=new Hs(e),m=new qs(e);this.logger.info("Storage initialized");let p=new sr,g=this.loadSecurityRules();p.loadRules(g);let f=new rr(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:g.length},"Security engine initialized");let h=zo(this.config.llm,this.logger.child({component:"llm"}));await h.initialize();let T=new xr(h,a,this.logger.child({component:"embeddings"})),E=this.config.activeLearning?.enabled!==!1,A,R;E&&(A=new Nr({llm:h,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:T,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),R=new Mr(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let F=new Ot(this.logger.child({component:"sandbox"})),x=this.skillRegistry=new Mt;x.register(new Pt),x.register(new Ut),x.register(new Ft(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),x.register(new jt(o)),x.register(new Bt(i));let G=new Ws(e);if(x.register(new os(G)),x.register(new Ht),x.register(new qt),x.register(new zt(n,T)),x.register(new Wt(h,x,F,f)),this.config.email?.accounts?.length){let D=new Map;for(let z of this.config.email.accounts)try{z.provider==="microsoft"&&!z.microsoft?.clientId&&this.config.calendar?.microsoft&&(z.microsoft={...this.config.calendar.microsoft});let Te=await nr(z);D.set(z.name,Te),this.logger.info({account:z.name,provider:z.provider??"imap-smtp"},"Email account initialized")}catch(Te){this.logger.warn({err:Te,account:z.name},"Email account initialization failed, skipping")}x.register(D.size>0?new et(D):new et)}else x.register(new et);x.register(new Gt),x.register(new Vt);let ce=new ls;ce.setReloadCallback(D=>this.reloadService(D)),x.register(ce),x.register(new Xt),x.register(new Yt),x.register(new Jt),x.register(new Zt(s)),x.register(new Qt(s,c,this.adapters,(D,z)=>t.findByPlatformAndUser(D,z))),x.register(new es(d)),x.register(new ts(m));let se=new zs(e),N=new Rr(se,T,this.logger.child({component:"documents"}));x.register(new ss(se,N,T));let K;if(this.config.calendar)try{let D=await ar(this.config.calendar);K=new _t(D),x.register(K),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(D){this.logger.warn({err:D},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=K,this.config.mcp?.servers?.length){let{MCPManager:D}=await Promise.resolve().then(()=>(Z(),ee));this.mcpManager=new D(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let z of this.mcpManager.getSkills())x.register(z);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},h)),this.logger.info({agents:this.config.codeAgents.agents.map(z=>z.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:D,createContactsProvider:z}=await Promise.resolve().then(()=>(Z(),ee)),Te=await z(this.config.contacts);x.register(new D(Te)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(D){this.logger.warn({err:D},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}{let{MarketplaceSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.marketplace)),this.logger.info("Marketplace skill registered")}{let{BriefingSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(x,this.config,n)),this.logger.info("Briefing skill registered")}this.logger.info({skills:x.getAll().map(D=>D.metadata.name)},"Skills registered");let q;if(this.config.speech?.apiKey&&(q=new kr(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let D=new vr(this.config.speech,this.logger.child({component:"tts"}));x.register(new rs(D)),this.logger.info("Text-to-speech skill registered")}let le=this.detectImageGenProvider();if(le){let D=new Sr(le,this.logger.child({component:"image-gen"}));x.register(new ns(D)),this.logger.info({provider:le.provider},"Image generation skill registered")}try{let D=new Ar(this.logger.child({component:"transit"}));x.register(new as(D)),this.logger.info("Public transit skill registered")}catch(D){this.logger.warn({err:D},"Failed to register transit skill")}let de=new br(t),re=qn.resolve(qn.dirname(this.config.storage.path),"inbox");this.pipeline=new Er({llm:h,conversationManager:de,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:x,skillSandbox:F,securityManager:f,memoryRepo:n,speechTranscriber:q,inboxPath:re,embeddingService:T,activeLearning:A,memoryRetriever:R,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:N}),this.reminderScheduler=new $r(o,async(D,z,Te)=>{let Q=this.adapters.get(D);Q?await Q.sendMessage(z,Te):this.logger.warn({platform:D,chatId:z},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(D=>s.getMasterUserId(D),"getMasterUserId"),getLinkedUsers:u(D=>s.getLinkedUsers(D),"getLinkedUsers"),findConversation:u((D,z)=>t.findByPlatformAndUser(D,z),"findConversation")}),this.backgroundTaskRunner=new Cr(x,F,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Dr(m,x,F,h,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,de);let ne=new Gs(e);x.register(new ds(ne)),this.watchEngine=new Ln(ne,x,F,this.adapters,s,this.logger.child({component:"watch-engine"})),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}if(e.api?.enabled!==!1){let{HttpAdapter:t}=await Promise.resolve().then(()=>(rt(),st)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";this.adapters.set("api",new t(s,r)),this.logger.info({port:s,host:r},"HTTP API adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.watchEngine?.start(),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(rt(),st)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.watchEngine?.stop(),this.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{xo();let t=new ue().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.proxmox)),this.config.proxmox=t.proxmox,this.logger.info({baseUrl:t.proxmox.baseUrl},"Proxmox skill hot-reloaded")}if(e==="unifi"&&t.unifi){let{UniFiSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}if(e==="homeassistant"&&t.homeassistant){let{HomeAssistantSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant skill hot-reloaded")}if(e==="contacts"&&t.contacts){let{ContactsSkill:s,createContactsProvider:r}=await Promise.resolve().then(()=>(Z(),ee)),n=await r(t.contacts);this.skillRegistry.register(new s(n)),this.config.contacts=t.contacts,this.logger.info({provider:t.contacts.provider},"Contacts skill hot-reloaded")}if(e==="docker"&&t.docker){let{DockerSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.docker)),this.config.docker=t.docker,this.logger.info("Docker skill hot-reloaded")}if(e==="bmw"&&t.bmw){let{BMWSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.bmw)),this.config.bmw=t.bmw,this.logger.info("BMW CarData skill hot-reloaded")}if(e==="routing"&&t.routing){let{RoutingSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.routing)),this.config.routing=t.routing,this.logger.info("Routing skill hot-reloaded")}if(e==="todo"&&t.todo){let{MicrosoftTodoSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.todo)),this.config.todo=t.todo,this.logger.info("Microsoft To Do skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(m){this.logger.debug({err:m,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,c)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let m=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,m.text)}if(i.attachments)for(let d of i.attachments)try{let m=d.mimeType.startsWith("image/"),p=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):p?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}detectImageGenProvider(){let e=["default","strong","fast","embeddings","local"];for(let t of["openai","google"])for(let s of e){let r=this.config.llm[s];if(r?.provider===t&&r.apiKey)return{provider:t,apiKey:r.apiKey,baseUrl:r.baseUrl}}}loadSecurityRules(){let e=qn.resolve(this.config.security.rulesPath),t=[];if(!Hn.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Hn.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Hn.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=qn.join(e,n),i=Hn.readFileSync(o,"utf-8"),a=Gp.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 gd=_(()=>{"use strict"});var Yi=_(()=>{"use strict";fd();Ci();xi();Di();Li();Ni();Pi();Ui();ji();Bi();hs();Fi();Mi();Oi();Wi();Gi();zi();gd();qi()});import zn from"node:fs";import yd from"node:path";import Vp from"node:os";function wd(){try{let l=zn.readFileSync(Ji,"utf-8"),e=JSON.parse(l);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function Td(l){try{let e=yd.dirname(Ji);zn.existsSync(e)||zn.mkdirSync(e,{recursive:!0}),zn.writeFileSync(Ji,JSON.stringify(l,null,2),"utf-8")}catch{}}async function xt(l,e){let t=new AbortController,s=setTimeout(()=>t.abort(),Xp);try{return await fetch(l,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function _d(l,e,t){switch(l){case"anthropic":{let s=await xt("https://api.anthropic.com/v1/models",{headers:{"x-api-key":e??"","anthropic-version":"2023-06-01"}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.display_name})):[]}case"openai":{let s=t?`${t.replace(/\/+$/,"")}/models`:"https://api.openai.com/v1/models",r=await xt(s,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}case"google":{let s=`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(e??"")}`,r=await xt(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await xt("https://api.mistral.ai/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"openrouter":{let s=await xt("https://openrouter.ai/api/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"ollama":{let s=(t??"http://localhost:11434").replace(/\/+$/,""),r=await xt(`${s}/api/tags`);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name})):[]}case"openwebui":{let s=(t??"http://localhost:3000/api/v1").replace(/\/+$/,""),r=await xt(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function Zi(l,e,t){let s=wd(),r=s.providers[l];if(r&&Date.now()-r.fetchedAt<Kp)return r.models;try{let n=await _d(l,e,t);if(n.length>0)return s.providers[l]={fetchedAt:Date.now(),models:n},Td(s),n}catch{}return r?r.models:[]}function Wn(l,e,t){_d(l,e,t).then(s=>{if(s.length>0){let r=wd();r.providers[l]={fetchedAt:Date.now(),models:s},Td(r)}}).catch(()=>{})}function Qi(l,e){let t=new Set,s=[];for(let r of l)if(!t.has(r.id)){t.add(r.id);let n=e.find(o=>o.id===r.id);s.push({id:r.id,name:r.name,desc:n?.desc})}for(let r of e)t.has(r.id)||(t.add(r.id),s.push({id:r.id,desc:r.desc}));return s}var Kp,Xp,Ji,ea=_(()=>{"use strict";Kp=24*60*60*1e3,Xp=5e3,Ji=yd.join(Vp.homedir(),".alfred","model-cache.json");u(wd,"readCache");u(Td,"writeCache");u(xt,"fetchWithTimeout");u(_d,"fetchModelsFromAPI");u(Zi,"getModels");u(Wn,"refreshCacheInBackground");u(Qi,"mergeModels")});var bd={};me(bd,{startCommand:()=>Yp});async function Yp(){let l=new ue,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Ns("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new It(e),r=!1,n=u(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready");let o=e.llm;o?.default?.provider?Wn(o.default.provider,o.default.apiKey,o.default.baseUrl):o?.provider&&Wn(o.provider,void 0,o.baseUrl);for(let i of["strong","fast"]){let a=o?.[i];a?.provider&&Wn(a.provider,a.apiKey,a.baseUrl)}}catch(o){let i=o instanceof Error?o:new Error(String(o));t.fatal({err:i},"Failed to start Alfred"),process.exit(1)}}var Ed=_(()=>{"use strict";We();Co();Yi();ea();u(Yp,"startCommand")});var kd={};me(kd,{chatCommand:()=>Qp});import $d from"node:http";import Or from"node:readline";function Jp(l,e){return new Promise(t=>{let s=$d.get(`http://${l}:${e}/api/health`,{timeout:2e3},r=>{let n="";r.on("data",o=>{n+=o.toString()}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function Zp(l,e){let t=Or.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
|
|
904
|
+
`)}}});var st={};me(st,{CLIAdapter:()=>jn,DiscordAdapter:()=>On,HttpAdapter:()=>Bn,MatrixAdapter:()=>Pn,MessagingAdapter:()=>he,SignalAdapter:()=>Fn,TelegramAdapter:()=>Nn,WhatsAppAdapter:()=>Un});var rt=_(()=>{"use strict";Xe();cd();ld();dd();ud();md();pd();hd()});import Hn from"node:fs";import qn from"node:path";import Vp from"js-yaml";var It,fd=_(()=>{"use strict";Co();No();We();Wo();rn();Z();xi();Ci();Di();Li();Ni();Mi();Oi();Pi();Ui();Fi();ji();Bi();id();Wi();Gi();It=class{static{u(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;watchEngine;adapters=new Map;formatter=new Ir;userRepo;skillRegistry;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=Ns("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ft(this.config.storage.path);let e=this.database.getDb(),t=new Ms(e),s=new Os(e);this.userRepo=s;let r=new gt(e),n=new Ps(e),o=new Us(e),i=new Fs(e),a=new js(e),c=new Bs(e),d=new Hs(e),m=new qs(e);this.logger.info("Storage initialized");let p=new sr,g=this.loadSecurityRules();p.loadRules(g);let f=new rr(p,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:g.length},"Security engine initialized");let h=zo(this.config.llm,this.logger.child({component:"llm"}));await h.initialize();let y=new xr(h,a,this.logger.child({component:"embeddings"})),E=this.config.activeLearning?.enabled!==!1,A,R;E&&(A=new Nr({llm:h,memoryRepo:n,logger:this.logger.child({component:"active-learning"}),embeddingService:y,minMessageLength:this.config.activeLearning?.minMessageLength,minConfidence:this.config.activeLearning?.minConfidence,maxExtractionsPerMinute:this.config.activeLearning?.maxExtractionsPerMinute}),R=new Mr(n,this.logger.child({component:"memory-retriever"}),y),this.logger.info("Active learning & memory retriever initialized"));let F=new Ot(this.logger.child({component:"sandbox"})),x=this.skillRegistry=new Mt;x.register(new Pt),x.register(new Ut),x.register(new Ft(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),x.register(new jt(o)),x.register(new Bt(i));let G=new Ws(e);if(x.register(new os(G)),x.register(new Ht),x.register(new qt),x.register(new zt(n,y)),x.register(new Wt(h,x,F,f)),this.config.email?.accounts?.length){let D=new Map;for(let z of this.config.email.accounts)try{z.provider==="microsoft"&&!z.microsoft?.clientId&&this.config.calendar?.microsoft&&(z.microsoft={...this.config.calendar.microsoft});let Te=await nr(z);D.set(z.name,Te),this.logger.info({account:z.name,provider:z.provider??"imap-smtp"},"Email account initialized")}catch(Te){this.logger.warn({err:Te,account:z.name},"Email account initialization failed, skipping")}x.register(D.size>0?new et(D):new et)}else x.register(new et);x.register(new Gt),x.register(new Vt);let ce=new ls;ce.setReloadCallback(D=>this.reloadService(D)),x.register(ce),x.register(new Xt),x.register(new Yt),x.register(new Jt),x.register(new Zt(s)),x.register(new Qt(s,c,this.adapters,(D,z)=>t.findByPlatformAndUser(D,z))),x.register(new es(d)),x.register(new ts(m));let se=new zs(e),N=new Rr(se,y,this.logger.child({component:"documents"}));x.register(new ss(se,N,y));let K;if(this.config.calendar)try{let D=await ar(this.config.calendar);K=new _t(D),x.register(K),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(D){this.logger.warn({err:D},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=K,this.config.mcp?.servers?.length){let{MCPManager:D}=await Promise.resolve().then(()=>(Z(),ee));this.mcpManager=new D(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let z of this.mcpManager.getSkills())x.register(z);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}if(this.config.codeAgents?.enabled){let{CodeAgentSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({agents:this.config.codeAgents.agents,forge:this.config.codeAgents.forge},h)),this.logger.info({agents:this.config.codeAgents.agents.map(z=>z.name)},"Code agent skill enabled")}if(this.config.proxmox){let{ProxmoxSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.proxmox)),this.logger.info({baseUrl:this.config.proxmox.baseUrl},"Proxmox skill enabled")}if(this.config.unifi){let{UniFiSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.unifi)),this.logger.info({baseUrl:this.config.unifi.baseUrl},"UniFi skill enabled")}if(this.config.homeassistant){let{HomeAssistantSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.homeassistant)),this.logger.info({baseUrl:this.config.homeassistant.baseUrl},"Home Assistant skill enabled")}if(this.config.contacts)try{let{ContactsSkill:D,createContactsProvider:z}=await Promise.resolve().then(()=>(Z(),ee)),Te=await z(this.config.contacts);x.register(new D(Te)),this.logger.info({provider:this.config.contacts.provider},"Contacts skill enabled")}catch(D){this.logger.warn({err:D},"Contacts initialization failed, continuing without contacts")}if(this.config.docker){let{DockerSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.docker)),this.logger.info("Docker skill enabled")}if(this.config.bmw){let{BMWSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.bmw)),this.logger.info("BMW CarData skill enabled")}if(this.config.routing){let{RoutingSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.routing)),this.logger.info("Routing skill enabled")}if(this.config.todo){let{MicrosoftTodoSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.todo)),this.logger.info("Microsoft To Do skill enabled")}if(this.config.proxmox||this.config.unifi||this.config.homeassistant){let{MonitorSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D({proxmox:this.config.proxmox,unifi:this.config.unifi,homeassistant:this.config.homeassistant})),this.logger.info("Infrastructure monitor skill enabled")}{let{EnergyPriceSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.energy)),this.logger.info({grid:this.config.energy?.gridName},"Energy price skill registered")}{let{MarketplaceSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(this.config.marketplace)),this.logger.info("Marketplace skill registered")}{let{BriefingSkill:D}=await Promise.resolve().then(()=>(Z(),ee));x.register(new D(x,this.config,n)),this.logger.info("Briefing skill registered")}this.logger.info({skills:x.getAll().map(D=>D.metadata.name)},"Skills registered");let q;if(this.config.speech?.apiKey&&(q=new kr(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let D=new vr(this.config.speech,this.logger.child({component:"tts"}));x.register(new rs(D)),this.logger.info("Text-to-speech skill registered")}let le=this.detectImageGenProvider();if(le){let D=new Sr(le,this.logger.child({component:"image-gen"}));x.register(new ns(D)),this.logger.info({provider:le.provider},"Image generation skill registered")}try{let D=new Ar(this.logger.child({component:"transit"}));x.register(new as(D)),this.logger.info("Public transit skill registered")}catch(D){this.logger.warn({err:D},"Failed to register transit skill")}let de=new br(t),re=qn.resolve(qn.dirname(this.config.storage.path),"inbox");this.pipeline=new Er({llm:h,conversationManager:de,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:x,skillSandbox:F,securityManager:f,memoryRepo:n,speechTranscriber:q,inboxPath:re,embeddingService:y,activeLearning:A,memoryRetriever:R,maxHistoryMessages:this.config.conversation?.maxHistoryMessages??100,documentProcessor:N}),this.reminderScheduler=new $r(o,async(D,z,Te)=>{let Q=this.adapters.get(D);Q?await Q.sendMessage(z,Te):this.logger.warn({platform:D,chatId:z},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:u(D=>s.getMasterUserId(D),"getMasterUserId"),getLinkedUsers:u(D=>s.getLinkedUsers(D),"getLinkedUsers"),findConversation:u((D,z)=>t.findByPlatformAndUser(D,z),"findConversation")}),this.backgroundTaskRunner=new Cr(x,F,d,this.adapters,s,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new Dr(m,x,F,h,this.adapters,s,this.logger.child({component:"proactive-scheduler"}),this.pipeline,this.formatter,de);let ne=new Gs(e);x.register(new ds(ne)),this.watchEngine=new Ln(ne,x,F,this.adapters,s,this.logger.child({component:"watch-engine"})),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));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(()=>(rt(),st));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}if(e.api?.enabled!==!1){let{HttpAdapter:t}=await Promise.resolve().then(()=>(rt(),st)),s=e.api?.port??3420,r=e.api?.host??"127.0.0.1";this.adapters.set("api",new t(s,r)),this.logger.info({port:s,host:r},"HTTP API adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.watchEngine?.start(),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(rt(),st)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.watchEngine?.stop(),this.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}async reloadService(e){try{xo();let t=new ue().loadConfig();if(this.skillRegistry.has(e)&&this.skillRegistry.unregister(e),e==="proxmox"&&t.proxmox){let{ProxmoxSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.proxmox)),this.config.proxmox=t.proxmox,this.logger.info({baseUrl:t.proxmox.baseUrl},"Proxmox skill hot-reloaded")}if(e==="unifi"&&t.unifi){let{UniFiSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.unifi)),this.config.unifi=t.unifi,this.logger.info({baseUrl:t.unifi.baseUrl},"UniFi skill hot-reloaded")}if(e==="homeassistant"&&t.homeassistant){let{HomeAssistantSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.homeassistant)),this.config.homeassistant=t.homeassistant,this.logger.info({baseUrl:t.homeassistant.baseUrl},"Home Assistant skill hot-reloaded")}if(e==="contacts"&&t.contacts){let{ContactsSkill:s,createContactsProvider:r}=await Promise.resolve().then(()=>(Z(),ee)),n=await r(t.contacts);this.skillRegistry.register(new s(n)),this.config.contacts=t.contacts,this.logger.info({provider:t.contacts.provider},"Contacts skill hot-reloaded")}if(e==="docker"&&t.docker){let{DockerSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.docker)),this.config.docker=t.docker,this.logger.info("Docker skill hot-reloaded")}if(e==="bmw"&&t.bmw){let{BMWSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.bmw)),this.config.bmw=t.bmw,this.logger.info("BMW CarData skill hot-reloaded")}if(e==="routing"&&t.routing){let{RoutingSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.routing)),this.config.routing=t.routing,this.logger.info("Routing skill hot-reloaded")}if(e==="todo"&&t.todo){let{MicrosoftTodoSkill:s}=await Promise.resolve().then(()=>(Z(),ee));this.skillRegistry.register(new s(t.todo)),this.config.todo=t.todo,this.logger.info("Microsoft To Do skill hot-reloaded")}return{success:!0}}catch(t){let s=t instanceof Error?t.message:String(t);return this.logger.error({err:t,service:e},"Failed to hot-reload service"),{success:!1,error:s}}}autoLinkApiUser(e){if(e.platform==="api")try{let t=this.userRepo.findOrCreate("api",e.userId,e.userName);if(this.userRepo.getMasterUserId(t.id)!==t.id)return;let r=this.userRepo.findFirstByPlatformNotIn(["api","cli"]);if(r){let n=this.userRepo.getMasterUserId(r.id);this.userRepo.setMasterUser(t.id,n),this.logger.info({apiUserId:t.id,masterUserId:n},"Auto-linked API user")}}catch(t){this.logger.debug({err:t},"Auto-link API user failed")}}setupAdapterHandlers(e,t){t.on("message",async s=>{try{this.autoLinkApiUser(s);let r,n="",o=u(async d=>{if(d!==n){n=d;try{r?await t.editMessage(s.chatId,r,d):r=await t.sendMessage(s.chatId,d)}catch(m){this.logger.debug({err:m,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;try{if(r&&e!=="api")try{await t.editMessage(s.chatId,r,a.text,c)}catch(d){this.logger.debug({err:d,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c)}catch(d){this.logger.warn({err:d,chatId:s.chatId},"Formatted send failed, retrying as plain text");let m=this.formatter.format(i.text,"signal");await t.sendMessage(s.chatId,m.text)}if(i.attachments)for(let d of i.attachments)try{let m=d.mimeType.startsWith("image/"),p=d.mimeType==="audio/ogg"||d.mimeType==="audio/opus";m?await t.sendPhoto(s.chatId,d.data,d.fileName):p?await t.sendVoice(s.chatId,d.data):await t.sendFile(s.chatId,d.data,d.fileName)}catch(m){this.logger.warn({err:m,fileName:d.fileName,chatId:s.chatId},"Failed to send attachment")}t.endStream(s.chatId)}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}t.endStream(s.chatId)}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}detectImageGenProvider(){let e=["default","strong","fast","embeddings","local"];for(let t of["openai","google"])for(let s of e){let r=this.config.llm[s];if(r?.provider===t&&r.apiKey)return{provider:t,apiKey:r.apiKey,baseUrl:r.baseUrl}}}loadSecurityRules(){let e=qn.resolve(this.config.security.rulesPath),t=[];if(!Hn.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Hn.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Hn.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=qn.join(e,n),i=Hn.readFileSync(o,"utf-8"),a=Vp.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 gd=_(()=>{"use strict"});var Yi=_(()=>{"use strict";fd();Ci();xi();Di();Li();Ni();Pi();Ui();ji();Bi();hs();Fi();Mi();Oi();Wi();Gi();zi();gd();qi()});import zn from"node:fs";import yd from"node:path";import Kp from"node:os";function wd(){try{let l=zn.readFileSync(Ji,"utf-8"),e=JSON.parse(l);if(e?.version===1&&e.providers)return e}catch{}return{version:1,providers:{}}}function Td(l){try{let e=yd.dirname(Ji);zn.existsSync(e)||zn.mkdirSync(e,{recursive:!0}),zn.writeFileSync(Ji,JSON.stringify(l,null,2),"utf-8")}catch{}}async function xt(l,e){let t=new AbortController,s=setTimeout(()=>t.abort(),Yp);try{return await fetch(l,{...e,signal:t.signal})}finally{clearTimeout(s)}}async function _d(l,e,t){switch(l){case"anthropic":{let s=await xt("https://api.anthropic.com/v1/models",{headers:{"x-api-key":e??"","anthropic-version":"2023-06-01"}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.display_name})):[]}case"openai":{let s=t?`${t.replace(/\/+$/,"")}/models`:"https://api.openai.com/v1/models",r=await xt(s,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}case"google":{let s=`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(e??"")}`,r=await xt(s);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name.replace(/^models\//,""),name:o.displayName})):[]}case"mistral":{let s=await xt("https://api.mistral.ai/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"openrouter":{let s=await xt("https://openrouter.ai/api/v1/models",{headers:{Authorization:`Bearer ${e??""}`}});return s.ok?((await s.json()).data??[]).map(n=>({id:n.id,name:n.name})):[]}case"ollama":{let s=(t??"http://localhost:11434").replace(/\/+$/,""),r=await xt(`${s}/api/tags`);return r.ok?((await r.json()).models??[]).map(o=>({id:o.name})):[]}case"openwebui":{let s=(t??"http://localhost:3000/api/v1").replace(/\/+$/,""),r=await xt(`${s}/models`,{headers:{Authorization:`Bearer ${e??""}`}});return r.ok?((await r.json()).data??[]).map(o=>({id:o.id})):[]}default:return[]}}async function Zi(l,e,t){let s=wd(),r=s.providers[l];if(r&&Date.now()-r.fetchedAt<Xp)return r.models;try{let n=await _d(l,e,t);if(n.length>0)return s.providers[l]={fetchedAt:Date.now(),models:n},Td(s),n}catch{}return r?r.models:[]}function Wn(l,e,t){_d(l,e,t).then(s=>{if(s.length>0){let r=wd();r.providers[l]={fetchedAt:Date.now(),models:s},Td(r)}}).catch(()=>{})}function Qi(l,e){let t=new Set,s=[];for(let r of l)if(!t.has(r.id)){t.add(r.id);let n=e.find(o=>o.id===r.id);s.push({id:r.id,name:r.name,desc:n?.desc})}for(let r of e)t.has(r.id)||(t.add(r.id),s.push({id:r.id,desc:r.desc}));return s}var Xp,Yp,Ji,ea=_(()=>{"use strict";Xp=24*60*60*1e3,Yp=5e3,Ji=yd.join(Kp.homedir(),".alfred","model-cache.json");u(wd,"readCache");u(Td,"writeCache");u(xt,"fetchWithTimeout");u(_d,"fetchModelsFromAPI");u(Zi,"getModels");u(Wn,"refreshCacheInBackground");u(Qi,"mergeModels")});var bd={};me(bd,{startCommand:()=>Jp});async function Jp(){let l=new ue,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=Ns("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new It(e),r=!1,n=u(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready");let o=e.llm;o?.default?.provider?Wn(o.default.provider,o.default.apiKey,o.default.baseUrl):o?.provider&&Wn(o.provider,void 0,o.baseUrl);for(let i of["strong","fast"]){let a=o?.[i];a?.provider&&Wn(a.provider,a.apiKey,a.baseUrl)}}catch(o){let i=o instanceof Error?o:new Error(String(o));t.fatal({err:i},"Failed to start Alfred"),process.exit(1)}}var Ed=_(()=>{"use strict";We();Co();Yi();ea();u(Jp,"startCommand")});var kd={};me(kd,{chatCommand:()=>eh});import $d from"node:http";import Or from"node:readline";function Zp(l,e){return new Promise(t=>{let s=$d.get(`http://${l}:${e}/api/health`,{timeout:2e3},r=>{let n="";r.on("data",o=>{n+=o.toString()}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.status==="ok")}catch{t(!1)}})});s.on("error",()=>t(!1)),s.on("timeout",()=>{s.destroy(),t(!1)})})}function Qp(l,e){let t=Or.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "});console.log(`
|
|
904
905
|
Alfred Chat (connected to server) \u2014 type your message and press Enter. Use /quit or /exit to leave.
|
|
905
906
|
`),t.prompt(),t.on("line",s=>{let r=s.trim();if(!r){t.prompt();return}(r==="/quit"||r==="/exit")&&(console.log(`
|
|
906
907
|
Goodbye!
|
|
@@ -915,42 +916,42 @@ Error: ${g.text??"Unknown error"}
|
|
|
915
916
|
`),t.prompt();break}}catch{}}}),i.on("end",()=>{if(a.length>0){let c=a.split(`
|
|
916
917
|
`).find(d=>d.startsWith("data: "));if(c)try{let d=JSON.parse(c.slice(6));(d.type==="done"||d.type==="error")&&t.prompt()}catch{}}}),i.on("error",c=>{console.error(`
|
|
917
918
|
Connection error: ${c.message}`),t.prompt()})});o.on("error",i=>{console.error(`
|
|
918
|
-
Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function
|
|
919
|
-
`);for(let g of p){let f=g.trim();if(!f||f.startsWith("#"))continue;let h=f.indexOf("=");h>0&&(t[f.slice(0,h)]=f.slice(h+1))}}catch{}let a=$e.join(l,"config","rules","default-rules.yml");if(we.existsSync(a))try{let p=ta.load(we.readFileSync(a,"utf-8"));if(p?.rules){s=p.rules.some(h=>h.id==="allow-owner-admin"&&h.effect==="allow"),p.rules.find(h=>h.id==="allow-write-for-dm"||h.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let f=p.rules.find(h=>h.id==="rate-limit-write");f?.rateLimit?.maxInvocations&&(n=f.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled,d=e.llm,m={};if(d){for(let p of["strong","fast","embeddings","local"])d[p]?.provider&&d[p]?.model&&(m[p]=d[p]);d.default?.provider&&(e.llm={...e.llm,provider:d.default.provider,model:d.default.model,baseUrl:d.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c,multiModelTiers:m}}async function
|
|
919
|
+
Failed to send message: ${i.message}`),t.prompt()}),o.write(n),o.end()}),t.on("close",()=>{process.exit(0)})}async function eh(l){let e=new ue,t;try{t=e.loadConfig()}catch(i){console.error("Failed to load configuration:",i.message),process.exit(1)}let s=t.api?.host??"127.0.0.1",r=t.api?.port??3420;if(await Zp(s,r)){console.log(`Connected to Alfred server at ${s}:${r}`),Qp(s,r);return}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let i=t.llm[l.tier];i?t.llm.default=i:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let o=new It(t);try{await o.initialize(),await o.startWithCLI()}catch(i){console.error("Failed to start chat:",i.message),process.exit(1)}}var vd=_(()=>{"use strict";We();Yi();u(Zp,"checkHealth");u(Qp,"startClientMode");u(eh,"chatCommand")});var Id={};me(Id,{setupCommand:()=>uh});import{createInterface as th}from"node:readline/promises";import{stdin as sh,stdout as rh}from"node:process";import{execFileSync as nh}from"node:child_process";import we from"node:fs";import oh from"node:os";import $e from"node:path";import ta from"js-yaml";function M(l){return`${Gn}${l}${k}`}function ch(l){return`${O}${l}${k}`}function ye(l){return`${Vn}${l}${k}`}function Ad(l){return`${ih}${l}${k}`}function C(l){return`${V}${l}${k}`}function b(l){return`${nt}${l}${k}`}function _e(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function lh(l){let e=process.platform==="win32",t=e?"where":"which";try{let n=nh(t,[l],{stdio:"pipe"}).toString().trim();if(n)return n.split(/\r?\n/)[0]}catch{}let s=oh.homedir(),r=e?[$e.join(s,".local","bin",`${l}.exe`),$e.join(s,"AppData","Roaming","npm",`${l}.cmd`),$e.join(s,"AppData","Roaming","npm",`${l}`)]:[$e.join(s,".local","bin",l),"/usr/local/bin/"+l,"/opt/homebrew/bin/"+l,$e.join(s,".npm-global","bin",l)];for(let n of r)try{return we.accessSync(n,we.constants.X_OK),n}catch{}return null}function dh(l){let e={},t={},s=!1,r=!1,n=30,o=$e.join(l,"config","default.yml");if(we.existsSync(o))try{let p=ta.load(we.readFileSync(o,"utf-8"));p&&typeof p=="object"&&Object.assign(e,p)}catch{}let i=$e.join(l,".env");if(we.existsSync(i))try{let p=we.readFileSync(i,"utf-8").split(`
|
|
920
|
+
`);for(let g of p){let f=g.trim();if(!f||f.startsWith("#"))continue;let h=f.indexOf("=");h>0&&(t[f.slice(0,h)]=f.slice(h+1))}}catch{}let a=$e.join(l,"config","rules","default-rules.yml");if(we.existsSync(a))try{let p=ta.load(we.readFileSync(a,"utf-8"));if(p?.rules){s=p.rules.some(h=>h.id==="allow-owner-admin"&&h.effect==="allow"),p.rules.find(h=>h.id==="allow-write-for-dm"||h.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let f=p.rules.find(h=>h.id==="rate-limit-write");f?.rateLimit?.maxInvocations&&(n=f.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled,d=e.llm,m={};if(d){for(let p of["strong","fast","embeddings","local"])d[p]?.provider&&d[p]?.model&&(m[p]=d[p]);d.default?.provider&&(e.llm={...e.llm,provider:d.default.provider,model:d.default.model,baseUrl:d.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c,multiModelTiers:m}}async function uh(){let l=th({input:sh,output:rh}),e=process.cwd(),t=dh(e),s=Object.keys(t.config).length>0;try{mh(),console.log(s?`${Vn}Existing configuration found \u2014 press Enter to keep current values.${k}
|
|
920
921
|
${nt}Only change what you need to update.${k}
|
|
921
922
|
`:`${Vn}Welcome to the Alfred setup wizard!${k}
|
|
922
923
|
${nt}This will walk you through configuring your AI assistant.${k}
|
|
923
924
|
${nt}Press Enter to accept defaults shown in [brackets].${k}
|
|
924
|
-
`);let r=await U(l,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Ye.findIndex(
|
|
925
|
-
${C("Which LLM provider would you like to use?")}`);for(let
|
|
926
|
-
${C("Configure additional model tiers for specialized tasks?")}`),console.log(`${b("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let R=(await l.question(`${O}> ${k}${b(`[${A}] `)}`)).trim().toLowerCase(),F=R===""?E:R==="y"||R==="yes",x={};if(F){let
|
|
925
|
+
`);let r=await U(l,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Ye.findIndex(T=>T.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
|
|
926
|
+
${C("Which LLM provider would you like to use?")}`);for(let T=0;T<Ye.length;T++){let $=T===n?` ${b("(current)")}`:"";console.log(` ${ye(String(T+1)+")")} ${Ye[T].label}${$}`)}let i=await Pr(l,"> ",1,Ye.length,o),a=Ye[i-1];console.log(` ${M(">")} Selected: ${C(a.label)}`);let c="",d=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),d?c=await U(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,d):c=await Ie(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${M(">")} API key set: ${b(_e(c))}`));let m=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let $=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if($){let S={ollama:"Ollama URL (use a remote address if Ollama runs on another machine)",openwebui:"OpenWebUI URL",openai:"OpenAI-compatible API URL (leave default for official API)",openrouter:"OpenRouter API URL",google:"Google Gemini API URL (leave default for official API)"};console.log(""),m=await U(l,S[a.name]??"API Base URL",$.replace(/\/+$/,"")),m=m.replace(/\/+$/,""),console.log(` ${M(">")} URL: ${b(m)}`)}}let g=t.config.llm?.model??a.defaultModel;console.log("");let f,h=await Zi(a.name,c,m),y=Qi(h,a.models??[]);if(y.length>0){console.log(`${C("Available models:")}`);for(let S=0;S<y.length;S++){let H=y[S],L=H.desc??H.name??"",j=H.id===g?` ${M("(current)")}`:"";console.log(` ${ye(`${S+1})`)} ${H.id}${L?` ${b(`\u2014 ${L}`)}`:""}${j}`)}console.log(` ${ye(`${y.length+1})`)} ${b("Other (enter manually)")}`);let T=await U(l,"Choose model","1"),$=parseInt(T,10)-1;$>=0&&$<y.length?f=y[$].id:f=await U(l,"Model ID",g)}else f=await U(l,"Which model?",g);let E=Object.keys(t.multiModelTiers).length>0,A=E?"Y/n":"y/N";console.log(`
|
|
927
|
+
${C("Configure additional model tiers for specialized tasks?")}`),console.log(`${b("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let R=(await l.question(`${O}> ${k}${b(`[${A}] `)}`)).trim().toLowerCase(),F=R===""?E:R==="y"||R==="yes",x={};if(F){let T=[{key:"strong",label:"Strong",hint:"complex reasoning, coding, long documents",defaultModel:"claude-opus-4-20250514"},{key:"fast",label:"Fast",hint:"quick responses, simple tasks",defaultModel:"claude-haiku-4-5-20251001"},{key:"embeddings",label:"Embeddings",hint:"semantic search & memory",defaultModel:"text-embedding-3-small"},{key:"local",label:"Local",hint:"offline fallback via Ollama",defaultModel:"llama3.2"}];for(let $ of T){let S=t.multiModelTiers[$.key],H=!!S?.model;console.log(`
|
|
927
928
|
${C(`${$.label} model`)} ${b(`(${$.hint})`)}`),H&&console.log(` ${b(`Current: ${S.provider}/${S.model}`)}`);let L=S?.provider??a.name,j=Ye.map(Se=>Se.name).join(", ");console.log(` ${b(`Providers: ${j}`)}`);let be=(await l.question(` ${O}Provider: ${k}${b(`[${L}] `)}`)).trim()||L;if(!be&&!H){console.log(` ${b("Skipped.")}`);continue}let X=be,Ee,Ce;if(X!==a.name){let Se=S?.apiKey??t.env[`ALFRED_LLM_${$.key.toUpperCase()}_API_KEY`]??"";if(Se?Ee=await U(l,` API key for ${X}`,Se):(Ye.find(ze=>ze.name===X)?.needsApiKey??!0)&&(Ee=await Ie(l,` API key for ${X}`)),["ollama","openwebui"].includes(X)){let ze=(S?.baseUrl??"")||Ye.find(en=>en.name===X)?.baseUrl||"";ze&&(Ce=await U(l,` ${X} URL`,ze))}}let pt=Ee??(X===a.name?c:void 0),Ls=Ce??(X===a.name?m:void 0),$o=Ye.find(Se=>Se.name===X),ko=await Zi(X,pt,Ls),Qe=Qi(ko,$o?.models??[]),qe;if(Qe.length>0){console.log(` ${C("Available models:")}`);for(let Dt=0;Dt<Qe.length;Dt++){let ze=Qe[Dt],en=ze.desc??ze.name??"",_u=ze.id===S?.model?` ${M("(current)")}`:"";console.log(` ${ye(`${Dt+1})`)} ${ze.id}${en?` ${b(`\u2014 ${en}`)}`:""}${_u}`)}console.log(` ${ye(`${Qe.length+1})`)} ${b("Other (enter manually)")}`),console.log(` ${ye("0)")} ${b("Skip this tier")}`);let Se=(await l.question(` ${O}> ${k}${H?b(`[${S.model}] `):""}`)).trim();if(Se==="0"){console.log(` ${b("Skipped.")}`);continue}let Qr=parseInt(Se,10)-1;Qr>=0&&Qr<Qe.length?qe=Qe[Qr].id:!Se&&H?qe=S.model:qe=await U(l," Model ID",H?S.model:$.defaultModel)}else if(console.log(` ${b("Press Enter to skip.")}`),qe=(await l.question(` ${O}Model: ${k}${H?b(`[${S.model}] `):""}`)).trim()||(H?S.model:""),!qe){console.log(` ${b("Skipped.")}`);continue}x[$.key]={provider:X,model:qe,...Ee?{apiKey:Ee}:{},...Ce?{baseUrl:Ce}:{}},console.log(` ${M(">")} ${$.label}: ${C(X)}/${C(qe)}`)}Object.keys(x).length===0&&console.log(`
|
|
928
929
|
${b("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${b("Using single model for all tasks.")}`);let G=["brave","tavily","duckduckgo","searxng"],ce=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",se=G.indexOf(ce),N=se>=0?se+1:0;console.log(`
|
|
929
|
-
${C("Web Search provider (for searching the internet):")}`);let K=["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"],q=u(
|
|
930
|
-
${C("Which messaging platforms do you want to enable?")}`),console.log(`${b("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let
|
|
931
|
-
${
|
|
932
|
-
${C(
|
|
933
|
-
${C("Email access (read & send emails)?")}`),console.log(`${b("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let Yn=(await l.question(`${O}> ${k}${b(`[${Wd}] `)}`)).trim().toLowerCase(),Fr=Yn===""?Xn:Yn==="y"||Yn==="yes",je=[],Gd={"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"}},oa=u(async(
|
|
930
|
+
${C("Web Search provider (for searching the internet):")}`);let K=["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"],q=u(T=>se===T?` ${b("(current)")}`:"","mark");console.log(` ${ye("0)")} None (disable web search)${se===-1&&ce===""?` ${b("(current)")}`:""}`);for(let T=0;T<K.length;T++)console.log(` ${ye(String(T+1)+")")} ${K[T]}${q(T)}`);let le=await Pr(l,"> ",0,G.length,N),de,re="",ne="";if(le>=1&&le<=G.length&&(de=G[le-1]),de==="brave"){let T=t.env.ALFRED_SEARCH_API_KEY??"";T?re=await U(l," Brave Search API key",T):(console.log(` ${b("Get your free API key at: https://brave.com/search/api/")}`),re=await Ie(l," Brave Search API key")),console.log(` ${M(">")} Brave Search: ${b(_e(re))}`)}else if(de==="tavily"){let T=t.env.ALFRED_SEARCH_API_KEY??"";T?re=await U(l," Tavily API key",T):(console.log(` ${b("Get your free API key at: https://tavily.com/")}`),re=await Ie(l," Tavily API key")),console.log(` ${M(">")} Tavily: ${b(_e(re))}`)}else if(de==="duckduckgo")console.log(` ${M(">")} DuckDuckGo: ${b("no API key needed")}`);else if(de==="searxng"){let T=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";ne=await U(l," SearXNG URL",T),ne=ne.replace(/\/+$/,""),console.log(` ${M(">")} SearXNG: ${b(ne)}`)}else console.log(` ${b("Web search disabled \u2014 you can configure it later.")}`);let D=[];for(let T=0;T<gs.length;T++){let $=gs[T];t.config[$.configKey]?.enabled&&D.push(T+1)}let z=D.length>0?D.join(","):"";console.log(`
|
|
931
|
+
${C("Which messaging platforms do you want to enable?")}`),console.log(`${b("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let T=0;T<gs.length;T++){let $=D.includes(T+1)?` ${b("(enabled)")}`:"";console.log(` ${ye(String(T+1)+")")} ${gs[T].label}${$}`)}console.log(` ${ye("0)")} None (configure later)`);let Te=(await l.question(`${O}> ${k}${z?b(`[${z}] `):""}`)).trim(),Q=[],Je=Te||z;if(Je&&Je!=="0"){let T=Je.split(",").map($=>parseInt($.trim(),10));for(let $ of T)if($>=1&&$<=gs.length){let S=gs[$-1];Q.includes(S)||Q.push(S)}}Q.length>0?console.log(` ${M(">")} Enabling: ${Q.map(T=>C(T.label)).join(", ")}`):console.log(` ${b("No platforms selected \u2014 you can configure them later.")}`);let B={},te={};for(let T of Q){if(T.credentials.length===0){T.name==="whatsapp"&&console.log(`
|
|
932
|
+
${ch("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
|
|
933
|
+
${C(T.label+" configuration:")}`);let $={};for(let S of T.credentials){let H=t.env[S.envKey]??"",L;H?L=await U(l,` ${S.prompt}`,H):S.defaultValue?L=await U(l,` ${S.prompt}`,S.defaultValue):S.required?L=await Ie(l,` ${S.prompt}`):(L=(await l.question(` ${S.prompt}: ${O}`)).trim(),process.stdout.write(k)),$[S.configField]=L,te[S.envKey]=L,S.configField==="token"||S.configField==="accessToken"?console.log(` ${M(">")} Set: ${b(_e(L))}`):console.log(` ${M(">")} Set: ${b(L)}`)}B[T.configKey]=$}let ae=t.config.email?.accounts??[],oe=ae[0],Rt=oe?.auth?.user??t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",ke=oe?.provider??t.config.email?.provider??t.env.ALFRED_EMAIL_PROVIDER??"",Xn=ae.length>0||!!Rt||ke==="microsoft",Wd=Xn?"Y/n":"y/N";console.log(`
|
|
934
|
+
${C("Email access (read & send emails)?")}`),console.log(`${b("Works with Gmail, Outlook, Microsoft 365, or any IMAP/SMTP provider. Supports multiple accounts.")}`);let Yn=(await l.question(`${O}> ${k}${b(`[${Wd}] `)}`)).trim().toLowerCase(),Fr=Yn===""?Xn:Yn==="y"||Yn==="yes",je=[],Gd={"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"}},oa=u(async(T,$)=>{let S={name:T,provider:"imap-smtp",user:"",pass:"",imapHost:"",imapPort:993,smtpHost:"",smtpPort:587,msClientId:"",msClientSecret:"",msTenantId:"",msRefreshToken:""},H=$?.provider??"",L=["IMAP/SMTP (classic)","Microsoft 365 (Graph API, OAuth)"],j=H==="microsoft"?1:0;console.log("");for(let X=0;X<L.length;X++){let Ee=X===j?` ${b("(current)")}`:"";console.log(` ${ye(`${X+1})`)} ${L[X]}${Ee}`)}let Y=(await l.question(`${O}> ${k}${b(`[${j+1}] `)}`)).trim(),be=Y===""?j:parseInt(Y,10)-1;if(S.provider=be===1?"microsoft":"imap-smtp",S.provider==="microsoft"){let X=t.config.calendar?.microsoft,Ee=$?.microsoft?.clientId??t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_ID??"",Ce=$?.microsoft?.tenantId??t.env.ALFRED_MICROSOFT_EMAIL_TENANT_ID??"",pt=$?.microsoft?.refreshToken??t.env.ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN??"";if(X&&!Ee)console.log(` ${M(">")} Microsoft Calendar already configured \u2014 credentials will be shared.`),console.log(` ${b("The same Azure App Registration will be used for Mail + Calendar.")}`),console.log(` ${b("Ensure the app has Mail.ReadWrite and Mail.Send scopes.")}`);else{console.log(` ${b("Azure Portal \u2192 App Registrations \u2192 your app \u2192 Mail.ReadWrite + Mail.Send scopes")}`),S.msClientId=await U(l," Client ID",Ee),S.msClientId||(S.msClientId=await Ie(l," Client ID"));let Ls=t.env.ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET??"";S.msClientSecret=await U(l," Client Secret",Ls),S.msClientSecret||(S.msClientSecret=await Ie(l," Client Secret")),S.msTenantId=await U(l," Tenant ID",Ce),S.msTenantId||(S.msTenantId=await Ie(l," Tenant ID")),console.log(` ${b("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),S.msRefreshToken=await U(l," Refresh Token",pt),S.msRefreshToken||(S.msRefreshToken=await Ie(l," Refresh Token"))}console.log(` ${M(">")} Email [${T}]: Microsoft 365 (Graph API)`)}else{let X=$?.auth?.user??"";console.log(""),S.user=await U(l," Email address",X||""),S.user||(S.user=await Ie(l," Email address"));let Ee=$?.auth?.pass??t.env.ALFRED_EMAIL_PASS??"";Ee?S.pass=await U(l," Password / App password",Ee):(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")}`),S.pass=await Ie(l," Password / App password"));let Ce=S.user.split("@")[1]?.toLowerCase()??"",pt=Gd[Ce],Ls=$?.imap?.host??pt?.imap??`imap.${Ce}`,$o=$?.smtp?.host??pt?.smtp??`smtp.${Ce}`,ko=$?.imap?.port??993,Qe=$?.smtp?.port??587;pt&&console.log(` ${M(">")} Detected ${Ce} \u2014 using preset server settings`),S.imapHost=await U(l," IMAP server",Ls);let qe=await U(l," IMAP port",String(ko));S.imapPort=parseInt(qe,10)||993,S.smtpHost=await U(l," SMTP server",$o);let Se=await U(l," SMTP port",String(Qe));S.smtpPort=parseInt(Se,10)||587,console.log(` ${M(">")} Email [${T}]: ${b(S.user)} via ${b(S.imapHost)}`)}return S},"configureEmailAccount");if(Fr){let T=oe??(t.config.email?.auth?{provider:t.config.email.provider,auth:t.config.email.auth,imap:t.config.email.imap,smtp:t.config.email.smtp,microsoft:t.config.email.microsoft}:void 0);je.push(await oa("default",T));let $=!0;for(;$;){let S=(await l.question(`
|
|
934
935
|
${C("Add another email account?")} ${b("[y/N]")} `)).trim().toLowerCase();if(S==="y"||S==="yes"){let L=(await l.question(` ${C("Account name:")} `)).trim()||`account${je.length+1}`,j=ae.find(Y=>Y.name===L);je.push(await oa(L,j))}else $=!1}}else console.log(` ${b("Email disabled \u2014 you can configure it later.")}`);let jr=["openai","groq"],Vd=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",Br=jr.indexOf(Vd),Kd=Br>=0?Br+1:0;console.log(`
|
|
935
|
-
${C("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${b("Transcribes voice messages from Telegram, Discord, etc.")}`);let ia=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${ye("0)")} None (disable voice transcription)${Br===-1?` ${b("(current)")}`:""}`);for(let
|
|
936
|
-
${C("Voice responses (Text-to-Speech)?")}`),console.log(`${b("Alfred can reply as a voice message when the user asks for it.")}`);let S=(await l.question(`${O}> ${k}${b(`[${$}] `)}`)).trim().toLowerCase();if(ws=S===""?
|
|
936
|
+
${C("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${b("Transcribes voice messages from Telegram, Discord, etc.")}`);let ia=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${ye("0)")} None (disable voice transcription)${Br===-1?` ${b("(current)")}`:""}`);for(let T=0;T<ia.length;T++){let $=Br===T?` ${b("(current)")}`:"";console.log(` ${ye(String(T+1)+")")} ${ia[T]}${$}`)}let Jn=await Pr(l,"> ",0,jr.length,Kd),Be,Ze="",ys="";if(Jn>=1&&Jn<=jr.length&&(Be=jr[Jn-1]),Be==="openai"){let T=t.env.ALFRED_SPEECH_API_KEY??"";T?Ze=await U(l," OpenAI API key (for Whisper)",T):(console.log(` ${b("Uses your OpenAI API key for Whisper transcription.")}`),Ze=await Ie(l," OpenAI API key")),console.log(` ${M(">")} OpenAI Whisper: ${b(_e(Ze))}`)}else if(Be==="groq"){let T=t.env.ALFRED_SPEECH_API_KEY??"";T?Ze=await U(l," Groq API key",T):(console.log(` ${b("Get your free API key at: https://console.groq.com/")}`),Ze=await Ie(l," Groq API key"));let $=t.env.ALFRED_SPEECH_BASE_URL??"";$&&(ys=await U(l," Groq API URL",$)),console.log(` ${M(">")} Groq Whisper: ${b(_e(Ze))}`)}else console.log(` ${b("Voice transcription disabled \u2014 you can configure it later.")}`);let ws=!1,Ts="alloy";if(Be){let T=t.config.speech?.ttsEnabled??!1,$=T?"Y/n":"y/N";console.log(`
|
|
937
|
+
${C("Voice responses (Text-to-Speech)?")}`),console.log(`${b("Alfred can reply as a voice message when the user asks for it.")}`);let S=(await l.question(`${O}> ${k}${b(`[${$}] `)}`)).trim().toLowerCase();if(ws=S===""?T:S==="y"||S==="yes",ws){let H=["alloy","echo","fable","onyx","nova","shimmer"],L=t.config.speech?.ttsVoice??"alloy",j=H.indexOf(L),Y=j>=0?j+1:1;console.log(`
|
|
937
938
|
${C("Which voice?")}`);for(let X=0;X<H.length;X++){let Ee=j===X?` ${b("(current)")}`:"";console.log(` ${ye(String(X+1)+")")} ${H[X]}${Ee}`)}let be=await Pr(l," > ",1,H.length,Y);Ts=H[be-1],console.log(` ${M(">")} TTS voice: ${C(Ts)}`)}else console.log(` ${b("Voice responses disabled.")}`)}let Xd=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
|
|
938
939
|
${C("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${b("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let Zn=(await l.question(`${O}> ${k}${b(`[${Xd}] `)}`)).trim().toLowerCase(),Qn=Zn===""?t.codeSandboxEnabled:Zn==="y"||Zn==="yes";console.log(Qn?` ${M(">")} Code Sandbox ${C("enabled")} (JavaScript + Python)`:` ${b("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
|
|
939
|
-
${C("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${b("Scanning for known coding agents on this system...")}`);let eo=[];for(let
|
|
940
|
-
${b("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let
|
|
941
|
-
${C("Which agents should Alfred use?")} ${b("(comma-separated, e.g. 1,2)")}`);let $=new Set((t.config.codeAgents?.agents??[]).map(L=>L.name));for(let L=0;L<
|
|
942
|
-
${C("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${b("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${b("Owner/repo are detected automatically from the git remote at runtime.")}`);let aa=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let
|
|
943
|
-
${C("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${b("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Es=t.config.proxmox,no=t.env.ALFRED_PROXMOX_BASE_URL??Es?.baseUrl??"",Jd=no?"Y/n":"y/N",la=(await l.question(` ${V}Enable Proxmox VE?${k} ${b(`[${Jd}]`)}: ${O}`)).trim().toLowerCase()||(no?"y":"n");process.stdout.write(k);let Hr=la==="y"||la==="yes",$s="",oo="",ks="",io=!0;if(Hr){$s=await U(l," Proxmox URL (e.g. https://pve.local:8006)",no||"https://pve.local:8006");let
|
|
944
|
-
${V}Enable UniFi Network?${k} ${b(`[${Zd}]`)}: ${O}`)).trim().toLowerCase()||(ao?"y":"n");process.stdout.write(k);let vs=da==="y"||da==="yes",Ct="",ct="",co="",Ss="",lo=!0;if(vs){Ct=await U(l," UniFi URL (e.g. https://unifi.local)",ao||"https://unifi.local"),console.log(` ${b("Auth: API Key (recommended) or Username/Password")}`);let
|
|
945
|
-
${V}Enable Home Assistant?${k} ${b(`[${Qd}]`)}: ${O}`)).trim().toLowerCase()||(uo?"y":"n");process.stdout.write(k);let zr=ua==="y"||ua==="yes",As="",Is="",mo=!0;if(zr){As=await U(l," Home Assistant URL (e.g. http://homeassistant.local:8123)",uo||"http://homeassistant.local:8123");let
|
|
946
|
-
${V}Enable Contacts management?${k} ${b(`[${eu}]`)}: ${O}`)).trim().toLowerCase()||(po?"y":"n");process.stdout.write(k);let Wr=ma==="y"||ma==="yes",Re="",fe={};if(Wr){let
|
|
947
|
-
${V}Enable Docker management?${k} ${b(`[${tu}]`)}: ${O}`)).trim().toLowerCase()||(ho||fo?"y":"n");process.stdout.write(k);let Gr=ha==="y"||ha==="yes",lt="",dt="";if(Gr){let
|
|
940
|
+
${C("Code Agents (CLI-based coding agents for automated tasks)?")}`),console.log(`${b("Scanning for known coding agents on this system...")}`);let eo=[];for(let T of Sd){let $=lh(T.whichCmd);$?(eo.push({...T,resolvedPath:$}),console.log(` ${M("\u2713")} ${C(T.label)} ${b(`(${$})`)}`)):console.log(` ${b("\xB7")} ${b(T.label)} ${b("\u2014 not found")}`)}let to=(t.config.codeAgents?.agents??[]).filter(T=>!Sd.some($=>$.name===T.name));for(let T of to)console.log(` ${M("\u2713")} ${C(T.name)} ${b(`(${T.command}) \u2014 from existing config`)}`);let ot=[];if(eo.length===0&&to.length===0)console.log(`
|
|
941
|
+
${b("No coding agents found. You can add them manually in config/default.yml later.")}`);else{let T=[...eo.map(L=>({name:L.name,command:L.resolvedPath??L.command,argsTemplate:L.argsTemplate,promptVia:L.promptVia,label:L.label,detected:!0})),...to.map(L=>({name:L.name,command:L.command,argsTemplate:L.argsTemplate,promptVia:L.promptVia??"arg",label:L.name,detected:!1}))];console.log(`
|
|
942
|
+
${C("Which agents should Alfred use?")} ${b("(comma-separated, e.g. 1,2)")}`);let $=new Set((t.config.codeAgents?.agents??[]).map(L=>L.name));for(let L=0;L<T.length;L++){let j=T[L],Y=$.has(j.name)?` ${b("(current)")}`:"";console.log(` ${O}${L+1}${k}) ${j.label}${Y}`)}console.log(` ${O}0${k}) None`);let S=T.map((L,j)=>$.size>0?$.has(L.name)?String(j+1):null:L.detected?String(j+1):null).filter(Boolean).join(",")||"0",H=(await l.question(` ${O}> ${k}${b(`[${S}] `)}`)).trim()||S;H!=="0"&&(ot=H.split(",").map(j=>parseInt(j.trim(),10)).filter(j=>!isNaN(j)&&j>=1&&j<=T.length).map(j=>{let Y=T[j-1];return{name:Y.name,command:Y.command,argsTemplate:Y.argsTemplate,promptVia:Y.promptVia}})),ot.length>0?console.log(` ${M(">")} ${C(String(ot.length))} agent(s) selected: ${ot.map(L=>L.name).join(", ")}`):console.log(` ${b("No agents selected.")}`)}let so=t.config.codeAgents?.forge,ro=so?.provider??t.env.ALFRED_FORGE_PROVIDER??"";console.log(`
|
|
943
|
+
${C("Forge Integration (auto-create PRs/MRs after code agent orchestration)?")}`),console.log(`${b("Connects to GitHub or GitLab to push branches and create pull/merge requests.")}`),console.log(`${b("Owner/repo are detected automatically from the git remote at runtime.")}`);let aa=[{num:"1",name:"",label:"None \u2014 skip forge integration"},{num:"2",name:"github",label:"GitHub"},{num:"3",name:"gitlab",label:"GitLab"}];for(let T of aa){let $=T.name===ro?` ${b("(current)")}`:"";console.log(` ${O}${T.num}${k}) ${T.label}${$}`)}let ca=ro==="github"?"2":ro==="gitlab"?"3":"1",Yd=(await l.question(`${O}> ${k}${b(`[${ca}] `)}`)).trim()||ca,it=aa.find(T=>T.num===Yd)?.name??"",_s="",bs="";if(it==="github"){console.log(` ${M(">")} Forge: ${C("GitHub")}`);let T=t.env.ALFRED_GITHUB_TOKEN??so?.github?.token??"";T&&console.log(` ${b(`Current token: ${_e(T)}`)}`),console.log(` ${b("Create a token at https://github.com/settings/tokens (scope: repo)")}`),_s=(await l.question(` ${V}GitHub Token${k}: ${O}`)).trim(),process.stdout.write(k),!_s&&T&&(_s=T)}else if(it==="gitlab"){console.log(` ${M(">")} Forge: ${C("GitLab")}`);let T=t.env.ALFRED_GITLAB_TOKEN??so?.gitlab?.token??"";T&&console.log(` ${b(`Current token: ${_e(T)}`)}`),console.log(` ${b("Create a token at https://gitlab.com/-/user_settings/personal_access_tokens (scope: api)")}`),bs=(await l.question(` ${V}GitLab Token${k}: ${O}`)).trim(),process.stdout.write(k),!bs&&T&&(bs=T)}else console.log(` ${b("Forge integration disabled \u2014 you can enable it later in config/default.yml.")}`);console.log(`
|
|
944
|
+
${C("Infrastructure Management (Proxmox / UniFi / Home Assistant)?")}`),console.log(`${b("Control VMs, containers, network devices, and smart home through Alfred.")}`);let Es=t.config.proxmox,no=t.env.ALFRED_PROXMOX_BASE_URL??Es?.baseUrl??"",Jd=no?"Y/n":"y/N",la=(await l.question(` ${V}Enable Proxmox VE?${k} ${b(`[${Jd}]`)}: ${O}`)).trim().toLowerCase()||(no?"y":"n");process.stdout.write(k);let Hr=la==="y"||la==="yes",$s="",oo="",ks="",io=!0;if(Hr){$s=await U(l," Proxmox URL (e.g. https://pve.local:8006)",no||"https://pve.local:8006");let T=t.env.ALFRED_PROXMOX_TOKEN_ID??Es?.tokenId??"";T&&console.log(` ${b(`Current token ID: ${T}`)}`),console.log(` ${b("Create: Datacenter \u2192 Permissions \u2192 API Tokens")}`),oo=await U(l," API Token ID (user@realm!name)",T);let $=t.env.ALFRED_PROXMOX_TOKEN_SECRET??Es?.tokenSecret??"";$&&console.log(` ${b(`Current secret: ${_e($)}`)}`),ks=(await l.question(` ${V}API Token Secret${k}: ${O}`)).trim(),process.stdout.write(k),!ks&&$&&(ks=$);let S=Es?.verifyTls===!1?"y/N":"Y/n",H=(await l.question(` ${V}Verify TLS?${k} ${b(`(self-signed? \u2192 no) [${S}]`)}: ${O}`)).trim().toLowerCase()||(Es?.verifyTls===!1?"n":"y");process.stdout.write(k),io=H==="y"||H==="yes",console.log(` ${M(">")} Proxmox: ${C($s)} ${b(`(TLS verify: ${io?"yes":"no"})`)}`)}else console.log(` ${b("Proxmox disabled.")}`);let at=t.config.unifi,ao=t.env.ALFRED_UNIFI_BASE_URL??at?.baseUrl??"",Zd=ao?"Y/n":"y/N",da=(await l.question(`
|
|
945
|
+
${V}Enable UniFi Network?${k} ${b(`[${Zd}]`)}: ${O}`)).trim().toLowerCase()||(ao?"y":"n");process.stdout.write(k);let vs=da==="y"||da==="yes",Ct="",ct="",co="",Ss="",lo=!0;if(vs){Ct=await U(l," UniFi URL (e.g. https://unifi.local)",ao||"https://unifi.local"),console.log(` ${b("Auth: API Key (recommended) or Username/Password")}`);let T=t.env.ALFRED_UNIFI_API_KEY??at?.apiKey??"",$=[{num:"1",name:"apikey",label:"API Key (UniFi OS)"},{num:"2",name:"password",label:"Username / Password"}],S=T?"1":at?.username?"2":"1";for(let Y of $)console.log(` ${O}${Y.num}${k}) ${Y.label}`);if(((await l.question(` ${O}> ${k}${b(`[${S}] `)}`)).trim()||S)==="1")T&&console.log(` ${b(`Current key: ${_e(T)}`)}`),console.log(` ${b("Create: Settings \u2192 Admins \u2192 API Keys (UniFi OS)")}`),ct=(await l.question(` ${V}API Key${k}: ${O}`)).trim(),process.stdout.write(k),!ct&&T&&(ct=T);else{let Y=t.env.ALFRED_UNIFI_USERNAME??at?.username??"";co=await U(l," Username",Y||"alfred");let be=t.env.ALFRED_UNIFI_PASSWORD??at?.password??"";be&&console.log(` ${b(`Current password: ${_e(be)}`)}`),Ss=(await l.question(` ${V}Password${k}: ${O}`)).trim(),process.stdout.write(k),!Ss&&be&&(Ss=be)}let L=at?.verifyTls===!1?"y/N":"Y/n",j=(await l.question(` ${V}Verify TLS?${k} ${b(`(self-signed? \u2192 no) [${L}]`)}: ${O}`)).trim().toLowerCase()||(at?.verifyTls===!1?"n":"y");process.stdout.write(k),lo=j==="y"||j==="yes",console.log(` ${M(">")} UniFi: ${C(Ct)} ${b(`(TLS verify: ${lo?"yes":"no"})`)}`)}else console.log(` ${b("UniFi disabled.")}`);let qr=t.config.homeassistant,uo=t.env.ALFRED_HOMEASSISTANT_URL??qr?.baseUrl??"",Qd=uo?"Y/n":"y/N",ua=(await l.question(`
|
|
946
|
+
${V}Enable Home Assistant?${k} ${b(`[${Qd}]`)}: ${O}`)).trim().toLowerCase()||(uo?"y":"n");process.stdout.write(k);let zr=ua==="y"||ua==="yes",As="",Is="",mo=!0;if(zr){As=await U(l," Home Assistant URL (e.g. http://homeassistant.local:8123)",uo||"http://homeassistant.local:8123");let T=t.env.ALFRED_HOMEASSISTANT_TOKEN??qr?.accessToken??"";T&&console.log(` ${b(`Current token: ${_e(T)}`)}`),console.log(` ${b("Create: Settings \u2192 Security \u2192 Long-Lived Access Tokens")}`),Is=(await l.question(` ${V}Long-Lived Access Token${k}: ${O}`)).trim(),process.stdout.write(k),!Is&&T&&(Is=T);let $=qr?.verifyTls===!1?"y/N":"Y/n",S=(await l.question(` ${V}Verify TLS?${k} ${b(`(self-signed? \u2192 no) [${$}]`)}: ${O}`)).trim().toLowerCase()||(qr?.verifyTls===!1?"n":"y");process.stdout.write(k),mo=S==="y"||S==="yes",console.log(` ${M(">")} Home Assistant: ${C(As)} ${b(`(TLS verify: ${mo?"yes":"no"})`)}`)}else console.log(` ${b("Home Assistant disabled.")}`);let xe=t.config.contacts,po=t.env.ALFRED_CONTACTS_PROVIDER??xe?.provider??"",eu=po?"Y/n":"y/N",ma=(await l.question(`
|
|
947
|
+
${V}Enable Contacts management?${k} ${b(`[${eu}]`)}: ${O}`)).trim().toLowerCase()||(po?"y":"n");process.stdout.write(k);let Wr=ma==="y"||ma==="yes",Re="",fe={};if(Wr){let T=["carddav","google","microsoft"],$=T.indexOf(po),S=$>=0?$+1:1;console.log(` ${ye("1)")} CardDAV (Nextcloud, Radicale, etc.)`),console.log(` ${ye("2)")} Google Contacts`),console.log(` ${ye("3)")} Microsoft 365`);let H=await Pr(l," > ",1,3,S);if(Re=T[H-1],fe.ALFRED_CONTACTS_PROVIDER=Re,Re==="carddav"){let L=t.env.ALFRED_CARDDAV_CONTACTS_SERVER_URL??xe?.carddav?.serverUrl??"";fe.ALFRED_CARDDAV_CONTACTS_SERVER_URL=await U(l," CardDAV Server URL",L||"https://cloud.example.com/remote.php/dav");let j=t.env.ALFRED_CARDDAV_CONTACTS_USERNAME??xe?.carddav?.username??"";fe.ALFRED_CARDDAV_CONTACTS_USERNAME=await U(l," Username",j);let Y=t.env.ALFRED_CARDDAV_CONTACTS_PASSWORD??xe?.carddav?.password??"";Y&&console.log(` ${b(`Current password: ${_e(Y)}`)}`);let be=(await l.question(` ${V}Password${k}: ${O}`)).trim();process.stdout.write(k),fe.ALFRED_CARDDAV_CONTACTS_PASSWORD=be||Y}else if(Re==="google"){let L=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_ID??xe?.google?.clientId??"";L&&console.log(` ${b(`Current client ID: ${_e(L)}`)}`),fe.ALFRED_GOOGLE_CONTACTS_CLIENT_ID=(await l.question(` ${V}Google Client ID${k}: ${O}`)).trim()||L,process.stdout.write(k);let j=t.env.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET??xe?.google?.clientSecret??"";fe.ALFRED_GOOGLE_CONTACTS_CLIENT_SECRET=(await l.question(` ${V}Google Client Secret${k}: ${O}`)).trim()||j,process.stdout.write(k);let Y=t.env.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN??xe?.google?.refreshToken??"";fe.ALFRED_GOOGLE_CONTACTS_REFRESH_TOKEN=(await l.question(` ${V}Refresh Token${k}: ${O}`)).trim()||Y,process.stdout.write(k)}else if(Re==="microsoft"){let L=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID??xe?.microsoft?.clientId??"";L&&console.log(` ${b(`Current client ID: ${_e(L)}`)}`),fe.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID=(await l.question(` ${V}Microsoft Client ID${k}: ${O}`)).trim()||L,process.stdout.write(k);let j=t.env.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET??xe?.microsoft?.clientSecret??"";fe.ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET=(await l.question(` ${V}Microsoft Client Secret${k}: ${O}`)).trim()||j,process.stdout.write(k);let Y=t.env.ALFRED_MICROSOFT_CONTACTS_TENANT_ID??xe?.microsoft?.tenantId??"";fe.ALFRED_MICROSOFT_CONTACTS_TENANT_ID=await U(l," Tenant ID",Y||"common");let be=t.env.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN??xe?.microsoft?.refreshToken??"";console.log(` ${b("Tipp: Du kannst `alfred auth microsoft` ausf\xFChren um den Refresh Token automatisch zu holen.")}`),fe.ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN=(await l.question(` ${V}Refresh Token${k}: ${O}`)).trim()||be,process.stdout.write(k)}console.log(` ${M(">")} Contacts: ${C(Re)}`)}else console.log(` ${b("Contacts disabled.")}`);let pa=t.config.docker,ho=t.env.ALFRED_DOCKER_SOCKET_PATH??pa?.socketPath??"",fo=t.env.ALFRED_DOCKER_HOST??pa?.host??"",tu=ho||fo?"Y/n":"y/N",ha=(await l.question(`
|
|
948
|
+
${V}Enable Docker management?${k} ${b(`[${tu}]`)}: ${O}`)).trim().toLowerCase()||(ho||fo?"y":"n");process.stdout.write(k);let Gr=ha==="y"||ha==="yes",lt="",dt="";if(Gr){let T=process.platform==="win32"?"//./pipe/docker_engine":"/var/run/docker.sock";console.log(` ${b("Use socket path for local Docker, or host URL for remote.")}`),lt=await U(l," Docker socket path",ho||T);let $=(await l.question(` ${V}Docker host URL (optional, for remote)${k}: ${O}`)).trim();process.stdout.write(k),dt=$||fo,console.log(` ${M(">")} Docker: ${C(dt||lt)}`)}else console.log(` ${b("Docker disabled.")}`);let su=t.config.bmw,go=t.env.ALFRED_BMW_CLIENT_ID??su?.clientId??"",ru=go?"Y/n":"y/N",fa=(await l.question(`
|
|
948
949
|
${V}Enable BMW CarData (vehicle status, charging)?${k} ${b(`[${ru}]`)}: ${O}`)).trim().toLowerCase()||(go?"y":"n");process.stdout.write(k);let Vr=fa==="y"||fa==="yes",yo="";Vr?(console.log(` ${b("Setup:")}`),console.log(` ${b(" 1. \xD6ffne https://bmw-cardata.bmwgroup.com/customer")}`),console.log(` ${b(" 2. Login mit deinem MyBMW-Account")}`),console.log(` ${b(" 3. Client-ID generieren")}`),console.log(` ${b(' 4. Scope "CarData API" aktivieren (ca. 60s warten)')}`),yo=await U(l," BMW CarData Client ID",go),console.log(` ${M(">")} BMW CarData: ${C("enabled")}`)):console.log(` ${b("BMW CarData disabled.")}`);let nu=t.config.routing,wo=t.env.ALFRED_ROUTING_API_KEY??nu?.apiKey??"",ou=wo?"Y/n":"y/N",ga=(await l.question(`
|
|
949
950
|
${V}Enable route planning with live traffic (Google Routes)?${k} ${b(`[${ou}]`)}: ${O}`)).trim().toLowerCase()||(wo?"y":"n");process.stdout.write(k);let Kr=ga==="y"||ga==="yes",To="";Kr?(console.log(` ${b("Setup:")}`),console.log(` ${b(" 1. \xD6ffne https://console.cloud.google.com")}`),console.log(` ${b(" 2. Routes API aktivieren")}`),console.log(` ${b(" 3. API Key erstellen")}`),To=await U(l," Google Maps API Key",wo),console.log(` ${M(">")} Routing: ${C("enabled")}`)):console.log(` ${b("Routing disabled.")}`);let He=t.config.energy,iu=t.env.ALFRED_ENERGY_GRID_NAME??He?.gridName??"",_o=t.env.ALFRED_ENERGY_GRID_USAGE_CT??(He?.gridUsageCt!=null?String(He.gridUsageCt):""),au=t.env.ALFRED_ENERGY_GRID_LOSS_CT??(He?.gridLossCt!=null?String(He.gridLossCt):""),cu=t.env.ALFRED_ENERGY_GRID_CAPACITY_FEE??(He?.gridCapacityFee!=null?String(He.gridCapacityFee):""),lu=t.env.ALFRED_ENERGY_GRID_METER_FEE??(He?.gridMeterFee!=null?String(He.gridMeterFee):""),du=_o?"Y/n":"y/N",ya=(await l.question(`
|
|
950
951
|
${V}Enable energy prices (aWATTar HOURLY / EPEX Spot AT)?${k} ${b(`[${du}]`)}: ${O}`)).trim().toLowerCase()||(_o?"y":"n");process.stdout.write(k);let Xr=ya==="y"||ya==="yes",ut="",mt="",Yr="",xs="",Rs="";Xr?(console.log(` ${b('Die Werte findest du auf deiner Stromrechnung unter "Netzentgelte".')}`),console.log(` ${b("Marktpreis + aWATTar-Aufschlag + Abgaben werden automatisch berechnet.")}`),console.log(""),ut=await U(l," Netzbetreiber Name (z.B. Netz Nieder\xF6sterreich)",iu),mt=await U(l," Netznutzungsentgelt (ct/kWh netto)",_o),Yr=await U(l," Netzverlustentgelt (ct/kWh netto)",au||"0.38"),xs=await U(l," Leistungspauschale (\u20AC/Monat netto)",cu),Rs=await U(l," Messentgelt (\u20AC/Monat netto)",lu||"2.22"),console.log(` ${M(">")} Energy: ${C(ut||"enabled")} (${mt} + ${Yr} ct/kWh)`)):console.log(` ${b("Energy prices disabled (Marktpreise weiterhin ohne Netzentgelte verf\xFCgbar).")}`),console.log(`
|
|
951
|
-
${C("Security configuration:")}`);let wa=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",ve;if(wa)ve=await U(l,"Owner user ID (for elevated permissions)",wa);else{let
|
|
952
|
-
${C("Writing configuration files...")}`);let v=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let
|
|
953
|
-
`),"utf-8"),console.log(` ${M("+")} ${b(".env")} written`);let Zr=$e.join(e,"config");we.existsSync(Zr)||we.mkdirSync(Zr,{recursive:!0});let Ta={name:r,telegram:{token:B.telegram?.token??"",enabled:Q.some(
|
|
952
|
+
${C("Security configuration:")}`);let wa=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",ve;if(wa)ve=await U(l,"Owner user ID (for elevated permissions)",wa);else{let T=(await l.question(`${V}Owner user ID${k} ${b("(optional, for elevated permissions)")}: ${O}`)).trim();process.stdout.write(k),ve=T}let Cs=!1;if(ve){let T=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${C("Enable shell access (admin commands) for the owner?")}`),console.log(` ${b("Allows Alfred to execute shell commands. Only for the owner.")}`);let $=(await l.question(` ${O}> ${k}${b(`[${T}] `)}`)).trim().toLowerCase();$===""?Cs=t.shellEnabled:Cs=$==="y"||$==="yes",console.log(Cs?` ${M(">")} Shell access ${C("enabled")} for owner ${b(ve)}`:` ${b("Shell access disabled.")}`)}let uu=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${C("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${b("By default, write actions are only allowed in DMs.")}`);let bo=(await l.question(` ${O}> ${k}${b(`[${uu}] `)}`)).trim().toLowerCase(),Ds;bo===""?Ds=t.writeInGroups:Ds=bo==="y"||bo==="yes",console.log(Ds?` ${M(">")} Write actions ${C("enabled")} in groups`:` ${b("Write actions only in DMs (default).")}`);let mu=t.rateLimit??30;console.log("");let pu=await U(l," Rate limit (max write actions per hour per user)",String(mu)),Jr=Math.max(1,parseInt(pu,10)||30);console.log(` ${M(">")} Rate limit: ${C(String(Jr))} per hour`),console.log(`
|
|
953
|
+
${C("Writing configuration files...")}`);let v=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let T=a.envKeyName||"ALFRED_OLLAMA_API_KEY";v.push(`${T}=${c}`)}if(f!==a.defaultModel&&v.push(`ALFRED_LLM_MODEL=${f}`),m&&v.push(`ALFRED_LLM_BASE_URL=${m}`),Object.keys(x).length>0){v.push("","# === Additional Model Tiers ===");for(let[T,$]of Object.entries(x)){let S=`ALFRED_LLM_${T.toUpperCase()}`;v.push(""),v.push(`${S}_PROVIDER=${$.provider}`),v.push(`${S}_MODEL=${$.model}`),$.apiKey&&v.push(`${S}_API_KEY=${$.apiKey}`),$.baseUrl&&v.push(`${S}_BASE_URL=${$.baseUrl}`)}}v.push("","# === Messaging Platforms ===","");for(let[T,$]of Object.entries(te))v.push(`${T}=${$}`);if(v.push("","# === Web Search ===",""),de?(v.push(`ALFRED_SEARCH_PROVIDER=${de}`),re&&v.push(`ALFRED_SEARCH_API_KEY=${re}`),ne&&v.push(`ALFRED_SEARCH_BASE_URL=${ne}`)):(v.push("# ALFRED_SEARCH_PROVIDER=brave"),v.push("# ALFRED_SEARCH_API_KEY=")),v.push("","# === Email ===",""),Fr&&je.length>0){let T=je[0];T.provider==="microsoft"?(v.push("ALFRED_EMAIL_PROVIDER=microsoft"),T.msClientId?(v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_ID=${T.msClientId}`),v.push(`ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET=${T.msClientSecret}`),v.push(`ALFRED_MICROSOFT_EMAIL_TENANT_ID=${T.msTenantId}`),v.push(`ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN=${T.msRefreshToken}`)):v.push("# Microsoft email credentials shared from calendar config")):(v.push(`ALFRED_EMAIL_USER=${T.user}`),v.push(`ALFRED_EMAIL_PASS=${T.pass}`)),je.length>1&&v.push("# Additional email accounts configured in config/default.yml")}else v.push("# ALFRED_EMAIL_USER="),v.push("# ALFRED_EMAIL_PASS=");if(v.push("","# === Speech ===",""),Be?(v.push(`ALFRED_SPEECH_PROVIDER=${Be}`),v.push(`ALFRED_SPEECH_API_KEY=${Ze}`),ys&&v.push(`ALFRED_SPEECH_BASE_URL=${ys}`),ws&&(v.push("ALFRED_TTS_ENABLED=true"),v.push(`ALFRED_TTS_VOICE=${Ts}`))):(v.push("# ALFRED_SPEECH_PROVIDER=groq"),v.push("# ALFRED_SPEECH_API_KEY=")),v.push("","# === Forge (GitHub / GitLab) ===",""),it==="github"?(v.push("ALFRED_FORGE_PROVIDER=github"),v.push(`ALFRED_GITHUB_TOKEN=${_s}`)):it==="gitlab"?(v.push("ALFRED_FORGE_PROVIDER=gitlab"),v.push(`ALFRED_GITLAB_TOKEN=${bs}`)):(v.push("# ALFRED_FORGE_PROVIDER=github"),v.push("# ALFRED_GITHUB_TOKEN=")),v.push("","# === Infrastructure (Proxmox / UniFi / Home Assistant) ===",""),Hr?(v.push(`ALFRED_PROXMOX_BASE_URL=${$s}`),v.push(`ALFRED_PROXMOX_TOKEN_ID=${oo}`),v.push(`ALFRED_PROXMOX_TOKEN_SECRET=${ks}`)):(v.push("# ALFRED_PROXMOX_BASE_URL="),v.push("# ALFRED_PROXMOX_TOKEN_ID="),v.push("# ALFRED_PROXMOX_TOKEN_SECRET=")),vs&&ct?(v.push(`ALFRED_UNIFI_BASE_URL=${Ct}`),v.push(`ALFRED_UNIFI_API_KEY=${ct}`)):vs?(v.push(`ALFRED_UNIFI_BASE_URL=${Ct}`),v.push(`ALFRED_UNIFI_USERNAME=${co}`),v.push(`ALFRED_UNIFI_PASSWORD=${Ss}`)):(v.push("# ALFRED_UNIFI_BASE_URL="),v.push("# ALFRED_UNIFI_API_KEY=")),zr?(v.push(`ALFRED_HOMEASSISTANT_URL=${As}`),v.push(`ALFRED_HOMEASSISTANT_TOKEN=${Is}`)):(v.push("# ALFRED_HOMEASSISTANT_URL="),v.push("# ALFRED_HOMEASSISTANT_TOKEN=")),v.push("","# === Contacts ===",""),Wr)for(let[T,$]of Object.entries(fe))v.push(`${T}=${$}`);else v.push("# ALFRED_CONTACTS_PROVIDER=carddav");v.push("","# === Docker ===",""),Gr?(lt&&v.push(`ALFRED_DOCKER_SOCKET_PATH=${lt}`),dt&&v.push(`ALFRED_DOCKER_HOST=${dt}`)):(v.push("# ALFRED_DOCKER_SOCKET_PATH="),v.push("# ALFRED_DOCKER_HOST=")),v.push("","# === BMW CarData ===",""),Vr?v.push(`ALFRED_BMW_CLIENT_ID=${yo}`):v.push("# ALFRED_BMW_CLIENT_ID="),v.push("","# === Routing ===",""),Kr?v.push(`ALFRED_ROUTING_API_KEY=${To}`):v.push("# ALFRED_ROUTING_API_KEY="),v.push("","# === Energy / aWATTar ===",""),Xr&&mt?(ut&&v.push(`ALFRED_ENERGY_GRID_NAME=${ut}`),v.push(`ALFRED_ENERGY_GRID_USAGE_CT=${mt}`),v.push(`ALFRED_ENERGY_GRID_LOSS_CT=${Yr}`),xs&&v.push(`ALFRED_ENERGY_GRID_CAPACITY_FEE=${xs}`),Rs&&v.push(`ALFRED_ENERGY_GRID_METER_FEE=${Rs}`)):(v.push("# ALFRED_ENERGY_GRID_NAME="),v.push("# ALFRED_ENERGY_GRID_USAGE_CT="),v.push("# ALFRED_ENERGY_GRID_LOSS_CT="),v.push("# ALFRED_ENERGY_GRID_CAPACITY_FEE="),v.push("# ALFRED_ENERGY_GRID_METER_FEE=")),v.push("","# === Security ===",""),ve?v.push(`ALFRED_OWNER_USER_ID=${ve}`):v.push("# ALFRED_OWNER_USER_ID="),v.push("");let hu=$e.join(e,".env");we.writeFileSync(hu,v.join(`
|
|
954
|
+
`),"utf-8"),console.log(` ${M("+")} ${b(".env")} written`);let Zr=$e.join(e,"config");we.existsSync(Zr)||we.mkdirSync(Zr,{recursive:!0});let Ta={name:r,telegram:{token:B.telegram?.token??"",enabled:Q.some(T=>T.name==="telegram")},discord:{token:B.discord?.token??"",enabled:Q.some(T=>T.name==="discord")},whatsapp:{enabled:Q.some(T=>T.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:B.matrix?.homeserverUrl??"https://matrix.org",accessToken:B.matrix?.accessToken??"",userId:B.matrix?.userId??"",enabled:Q.some(T=>T.name==="matrix")},signal:{apiUrl:B.signal?.apiUrl??"http://localhost:8080",phoneNumber:B.signal?.phoneNumber??"",enabled:Q.some(T=>T.name==="signal")},llm:Object.keys(x).length>0?{default:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...x}:{provider:a.name,model:f,...m?{baseUrl:m}:{},temperature:.7,maxTokens:4096},...de?{search:{provider:de,...re?{apiKey:re}:{},...ne?{baseUrl:ne}:{}}}:{},...Fr&&je.length>0?{email:{accounts:je.map(T=>T.provider==="microsoft"?{name:T.name,provider:"microsoft",...T.msClientId?{microsoft:{clientId:T.msClientId,clientSecret:T.msClientSecret,tenantId:T.msTenantId,refreshToken:T.msRefreshToken}}:{}}:{name:T.name,imap:{host:T.imapHost,port:T.imapPort,secure:T.imapPort===993},smtp:{host:T.smtpHost,port:T.smtpPort,secure:T.smtpPort===465},auth:{user:T.user,pass:T.pass}})}}:{},...Be?{speech:{provider:Be,apiKey:Ze,...ys?{baseUrl:ys}:{},...ws?{ttsEnabled:!0,ttsVoice:Ts}:{}}}:{},...Qn?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},...ot.length>0||it?{codeAgents:{enabled:ot.length>0,agents:ot,...it==="github"?{forge:{provider:"github",github:{token:_s}}}:it==="gitlab"?{forge:{provider:"gitlab",gitlab:{token:bs}}}:{}}}:{},...Hr?{proxmox:{baseUrl:$s,tokenId:oo,tokenSecret:ks,verifyTls:io}}:{},...vs?{unifi:{baseUrl:Ct,...ct?{apiKey:ct}:{username:co,password:Ss},site:"default",verifyTls:lo}}:{},...zr?{homeassistant:{baseUrl:As,accessToken:Is,verifyTls:mo}}:{},...Wr?{contacts:{provider:Re,...Re==="carddav"?{carddav:{serverUrl:fe.ALFRED_CARDDAV_CONTACTS_SERVER_URL,username:fe.ALFRED_CARDDAV_CONTACTS_USERNAME}}:Re==="google"?{google:{clientId:fe.ALFRED_GOOGLE_CONTACTS_CLIENT_ID}}:Re==="microsoft"?{microsoft:{clientId:fe.ALFRED_MICROSOFT_CONTACTS_CLIENT_ID,tenantId:fe.ALFRED_MICROSOFT_CONTACTS_TENANT_ID}}:{}}}:{},...Gr?{docker:{...lt?{socketPath:lt}:{},...dt?{host:dt}:{}}}:{},...Vr?{bmw:{clientId:yo}}:{},...Kr?{routing:{apiKey:To}}:{},...Xr&&mt?{energy:{...ut?{gridName:ut}:{},gridUsageCt:parseFloat(mt),gridLossCt:parseFloat(Yr||"0"),...xs?{gridCapacityFee:parseFloat(xs)}:{},...Rs?{gridMeterFee:parseFloat(Rs)}:{}}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};ve&&(Ta.security.ownerUserId=ve);let fu="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+ta.dump(Ta,{lineWidth:120,noRefs:!0,sortKeys:!1}),gu=$e.join(Zr,"default.yml");we.writeFileSync(gu,fu,"utf-8"),console.log(` ${M("+")} ${b("config/default.yml")} written`);let Eo=$e.join(Zr,"rules");we.existsSync(Eo)||we.mkdirSync(Eo,{recursive:!0});let yu=Cs&&ve?`
|
|
954
955
|
# Allow admin actions (shell, etc.) for the owner only
|
|
955
956
|
- id: allow-owner-admin
|
|
956
957
|
effect: allow
|
|
@@ -1026,23 +1027,23 @@ ${yu}
|
|
|
1026
1027
|
scope: global
|
|
1027
1028
|
actions: ["*"]
|
|
1028
1029
|
riskLevels: [read, write, destructive, admin]
|
|
1029
|
-
`,Tu=$e.join(Eo,"default-rules.yml");we.writeFileSync(Tu,wu,"utf-8"),console.log(` ${M("+")} ${b("config/rules/default-rules.yml")} written`);let _a=$e.join(e,"data");we.existsSync(_a)||(we.mkdirSync(_a,{recursive:!0}),console.log(` ${M("+")} ${b("data/")} directory created`)),console.log(""),console.log(`${Gn}${"=".repeat(52)}${k}`),console.log(`${Gn}${V} Setup complete!${k}`),console.log(`${Gn}${"=".repeat(52)}${k}`),console.log(""),console.log(` ${C("Bot name:")} ${r}`),console.log(` ${C("LLM default:")} ${a.name} (${f})`),c&&console.log(` ${C("API key:")} ${_e(c)}`);for(let[
|
|
1030
|
-
${
|
|
1030
|
+
`,Tu=$e.join(Eo,"default-rules.yml");we.writeFileSync(Tu,wu,"utf-8"),console.log(` ${M("+")} ${b("config/rules/default-rules.yml")} written`);let _a=$e.join(e,"data");we.existsSync(_a)||(we.mkdirSync(_a,{recursive:!0}),console.log(` ${M("+")} ${b("data/")} directory created`)),console.log(""),console.log(`${Gn}${"=".repeat(52)}${k}`),console.log(`${Gn}${V} Setup complete!${k}`),console.log(`${Gn}${"=".repeat(52)}${k}`),console.log(""),console.log(` ${C("Bot name:")} ${r}`),console.log(` ${C("LLM default:")} ${a.name} (${f})`),c&&console.log(` ${C("API key:")} ${_e(c)}`);for(let[T,$]of Object.entries(x)){let S=T.charAt(0).toUpperCase()+T.slice(1);console.log(` ${C(`LLM ${S}:`)}${" ".repeat(Math.max(1,10-S.length))}${$.provider} (${$.model})`)}if(Q.length>0?console.log(` ${C("Platforms:")} ${Q.map(T=>T.label).join(", ")}`):console.log(` ${C("Platforms:")} none (configure later)`),de){let T={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${ne})`};console.log(` ${C("Web search:")} ${T[de]}`)}else console.log(` ${C("Web search:")} ${b("disabled")}`);if(Fr&&je.length>0){let T=je.map($=>$.provider==="microsoft"?`${$.name} (Microsoft 365)${$.msClientId?"":" \u2014 shared from Calendar"}`:`${$.name} (${$.imapHost})`);console.log(` ${C("Email:")} ${T.join(", ")}`)}else console.log(` ${C("Email:")} ${b("disabled")}`);if(Be){let T={openai:"OpenAI Whisper",groq:"Groq Whisper"},$=ws?`, TTS: ${Ts}`:"";console.log(` ${C("Voice:")} ${T[Be]}${$}`)}else console.log(` ${C("Voice:")} ${b("disabled")}`);console.log(` ${C("Code Sandbox:")} ${Qn?M("enabled"):b("disabled")}`),Hr&&console.log(` ${C("Proxmox:")} ${M($s)}`),vs&&console.log(` ${C("UniFi:")} ${M(Ct)}`),zr&&console.log(` ${C("Home Assist.:")} ${M(As)}`),Wr&&console.log(` ${C("Contacts:")} ${M(Re)}`),Gr&&console.log(` ${C("Docker:")} ${M(dt||lt)}`),Vr&&console.log(` ${C("BMW CarData:")} ${M("enabled")}`),Kr&&console.log(` ${C("Routing:")} ${M("enabled")}`),Xr&&console.log(` ${C("Energy:")} ${M(ut||"enabled")} ${b(`(${mt} ct/kWh)`)}`),ve&&(console.log(` ${C("Owner ID:")} ${ve}`),console.log(` ${C("Shell access:")} ${Cs?M("enabled"):b("disabled")}`)),console.log(` ${C("Write scope:")} ${Ds?"DMs + Groups":"DMs only"}`),console.log(` ${C("Rate limit:")} ${Jr}/hour per user`),console.log(""),console.log(`${Vn}Next steps:${k}`),console.log(` ${C("alfred start")} Start Alfred`),console.log(` ${C("alfred status")} Check configuration`),console.log(` ${C("alfred --help")} Show all commands`),console.log(""),console.log(`${nt}Edit ${C(".env")}${nt} or ${C("config/default.yml")}${nt} for manual configuration.${k}`),console.log("")}finally{l.close()}}async function U(l,e,t){let s=(await l.question(`${V}${e}${k} ${b(`[${t}]`)}: ${O}`)).trim();return process.stdout.write(k),s||t}async function Ie(l,e){for(;;){let t=(await l.question(`${V}${e}${k}: ${O}`)).trim();if(process.stdout.write(k),t)return t;console.log(` ${Ad("!")} This field is required. Please enter a value.`)}}async function Pr(l,e,t,s,r){for(;;){let n=(await l.question(`${O}${e}${k}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Ad("!")} Please enter a number between ${t} and ${s}.`)}}function mh(){console.log(`
|
|
1031
|
+
${ah}${V} _ _ _____ ____ _____ ____
|
|
1031
1032
|
/ \\ | | | ___| _ \\| ____| _ \\
|
|
1032
1033
|
/ _ \\ | | | |_ | |_) | _| | | | |
|
|
1033
1034
|
/ ___ \\| |___| _| | _ <| |___| |_| |
|
|
1034
1035
|
/_/ \\_\\_____|_| |_| \\_\\_____|____/ ${k}
|
|
1035
1036
|
${nt} Personal AI Assistant \u2014 Setup Wizard${k}
|
|
1036
|
-
`)}var k,V,nt,Gn,O,Vn,oh,ih,Ye,gs,Sd,xd=_(()=>{"use strict";ea();k="\x1B[0m",V="\x1B[1m",nt="\x1B[2m",Gn="\x1B[32m",O="\x1B[33m",Vn="\x1B[36m",oh="\x1B[31m",ih="\x1B[35m";u(M,"green");u(ah,"yellow");u(ye,"cyan");u(Ad,"red");u(C,"bold");u(b,"dim");u(_e,"maskKey");Ye=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0,models:[{id:"claude-sonnet-4-20250514",desc:"Sonnet 4 \u2014 fast, smart, recommended"},{id:"claude-opus-4-20250514",desc:"Opus 4 \u2014 most capable, slower"},{id:"claude-haiku-4-5-20251001",desc:"Haiku 4.5 \u2014 fastest, cheapest"}]},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0,models:[{id:"gpt-4o",desc:"GPT-4o \u2014 flagship, 128k context"},{id:"gpt-4o-mini",desc:"GPT-4o Mini \u2014 fast, cheap, 128k context"},{id:"o3-mini",desc:"o3-mini \u2014 reasoning, 200k context"}]},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0,models:[{id:"gemini-2.0-flash",desc:"Flash 2.0 \u2014 fast, 1M context"},{id:"gemini-2.0-pro",desc:"Pro 2.0 \u2014 capable, 1M context"},{id:"gemini-1.5-pro",desc:"Pro 1.5 \u2014 2M context"},{id:"gemini-1.5-flash",desc:"Flash 1.5 \u2014 fast, 1M context"}]},{name:"mistral",label:"Mistral AI",defaultModel:"mistral-small-latest",envKeyName:"ALFRED_MISTRAL_API_KEY",needsApiKey:!0,models:[{id:"mistral-small-latest",desc:"Small 3.2 \u2014 fast, 128k context, best value"},{id:"mistral-medium-latest",desc:"Medium 3.1 \u2014 balanced, 128k context"},{id:"mistral-large-latest",desc:"Large 3 \u2014 flagship, 256k context"},{id:"codestral-latest",desc:"Codestral \u2014 code-optimized, 256k context"},{id:"magistral-medium-latest",desc:"Magistral Medium \u2014 reasoning, 40k context"},{id:"magistral-small-latest",desc:"Magistral Small \u2014 reasoning (light), 40k context"},{id:"ministral-8b-latest",desc:"Ministral 8B \u2014 edge/tiny, 128k context"}]}],gs=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];u(ch,"findCommand");Sd=[{name:"claude-code",label:"Claude Code",command:"claude",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"claude"},{name:"codex",label:"OpenAI Codex CLI",command:"codex",argsTemplate:["{{prompt}}"],promptVia:"arg",whichCmd:"codex"},{name:"aider",label:"Aider",command:"aider",argsTemplate:["--message","{{prompt}}"],promptVia:"arg",whichCmd:"aider"},{name:"gemini",label:"Gemini CLI",command:"gemini",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"gemini"}];u(lh,"loadExistingConfig");u(dh,"setupCommand");u(U,"askWithDefault");u(Ie,"askRequired");u(Pr,"askNumber");u(uh,"printBanner")});var Cd={};me(Cd,{configCommand:()=>fh});function ph(l){let e=l.toLowerCase();return mh.some(t=>e.includes(t))}function hh(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Rd(l){let e={};for(let[t,s]of Object.entries(l))ph(t)?e[t]=hh(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Rd(s):e[t]=s;return e}async function fh(){let l=new ue,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Rd(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var mh,Dd=_(()=>{"use strict";We();mh=["token","apikey","api_key","accesstoken","secret","password"];u(ph,"isSensitiveKey");u(hh,"redactValue");u(Rd,"redactObject");u(fh,"configCommand")});var Nd={};me(Nd,{rulesCommand:()=>yh});import Kn from"node:fs";import Ld from"node:path";import gh from"js-yaml";async function yh(){let l=new ue,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ld.resolve(e.security.rulesPath);if(!Kn.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Kn.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Kn.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 wt,o=[],i=[];for(let a of r){let c=Ld.join(t,a);try{let d=Kn.readFileSync(c,"utf-8"),m=gh.load(d),p=n.loadFromObject(m);o.push(...p)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,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 Md=_(()=>{"use strict";We();rn();u(yh,"rulesCommand")});var Od={};me(Od,{statusCommand:()=>Th});import Ur from"node:fs";import sa from"node:path";import wh from"js-yaml";async function Th(){let l=new ue,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 d=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",m=c.enabled?"+":"-";console.log(` [${m}] ${c.name}: ${d}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let d=e.llm[c];d&&console.log(` ${c}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=sa.resolve(e.storage.path),n=Ur.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=sa.resolve(e.security.rulesPath),i=0,a=0;if(Ur.existsSync(o)&&Ur.statSync(o).isDirectory()){let c=Ur.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=c.length;let d=new wt;for(let m of c){let p=sa.join(o,m);try{let g=Ur.readFileSync(p,"utf-8"),f=wh.load(g),h=d.loadFromObject(f);i+=h.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var Pd=_(()=>{"use strict";We();rn();u(Th,"statusCommand")});var jd={};me(jd,{authCommand:()=>Mh});import{createServer as _h}from"node:http";import{exec as bh}from"node:child_process";import{readFileSync as Eh,writeFileSync as $h,existsSync as kh}from"node:fs";import{createInterface as vh}from"node:readline";import{resolve as Sh}from"node:path";async function ra(l){let e=vh({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(l,s=>{e.close(),t(s.trim())})})}function Ih(){let l={};try{let s=new ue().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!l.clientId&&a.clientId&&(l.clientId=a.clientId),!l.clientSecret&&a.clientSecret&&(l.clientSecret=a.clientSecret),!l.tenantId&&a.tenantId&&(l.tenantId=a.tenantId))}let r=s.todo;r&&(!l.clientId&&r.clientId&&(l.clientId=r.clientId),!l.clientSecret&&r.clientSecret&&(l.clientSecret=r.clientSecret),!l.tenantId&&r.tenantId&&(l.tenantId=r.tenantId));let n=s.email;if(n?.accounts&&Array.isArray(n.accounts))for(let o of n.accounts){let i=o.microsoft;i&&(!l.clientId&&i.clientId&&(l.clientId=i.clientId),!l.clientSecret&&i.clientSecret&&(l.clientSecret=i.clientSecret),!l.tenantId&&i.tenantId&&(l.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)l.clientId||(l.clientId=process.env[`${t}_CLIENT_ID`]),l.clientSecret||(l.clientSecret=process.env[`${t}_CLIENT_SECRET`]),l.tenantId||(l.tenantId=process.env[`${t}_TENANT_ID`]);return l}async function xh(){let l=Ih(),e=l.clientId||await ra(" Client ID: "),t=l.clientSecret||await ra(" Client Secret: "),s=l.tenantId||await ra(' Tenant ID (oder "common"): ');return(!e||!t||!s)&&(console.error("Fehler: Client ID, Client Secret und Tenant ID werden ben\xF6tigt."),process.exit(1)),{clientId:e,clientSecret:t,tenantId:s}}function Rh(l){let e=new URLSearchParams({client_id:l.clientId,response_type:"code",redirect_uri:Ud,response_mode:"query",scope:Fd,prompt:"consent"});return`https://login.microsoftonline.com/${l.tenantId}/oauth2/v2.0/authorize?${e}`}async function Ch(l,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:l,redirect_uri:Ud,grant_type:"authorization_code",scope:Fd}),s=await fetch(`https://login.microsoftonline.com/${e.tenantId}/oauth2/v2.0/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t});if(!s.ok){let n=await s.text();throw new Error(`Token-Austausch fehlgeschlagen (${s.status}): ${n}`)}let r=await s.json();if(!r.refresh_token)throw new Error('Kein Refresh Token in der Antwort. Stelle sicher, dass "offline_access" als Scope erlaubt ist.');return r.refresh_token}function Dh(l){let t={win32:`start "" "${l}"`,darwin:`open "${l}"`,linux:`xdg-open "${l}"`}[process.platform];t&&bh(t,()=>{})}function Lh(l,e){let t=Sh(process.cwd(),".env"),s=[];kh(t)&&(s=Eh(t,"utf-8").split(`
|
|
1037
|
+
`)}var k,V,nt,Gn,O,Vn,ih,ah,Ye,gs,Sd,xd=_(()=>{"use strict";ea();k="\x1B[0m",V="\x1B[1m",nt="\x1B[2m",Gn="\x1B[32m",O="\x1B[33m",Vn="\x1B[36m",ih="\x1B[31m",ah="\x1B[35m";u(M,"green");u(ch,"yellow");u(ye,"cyan");u(Ad,"red");u(C,"bold");u(b,"dim");u(_e,"maskKey");Ye=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0,models:[{id:"claude-sonnet-4-20250514",desc:"Sonnet 4 \u2014 fast, smart, recommended"},{id:"claude-opus-4-20250514",desc:"Opus 4 \u2014 most capable, slower"},{id:"claude-haiku-4-5-20251001",desc:"Haiku 4.5 \u2014 fastest, cheapest"}]},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0,models:[{id:"gpt-4o",desc:"GPT-4o \u2014 flagship, 128k context"},{id:"gpt-4o-mini",desc:"GPT-4o Mini \u2014 fast, cheap, 128k context"},{id:"o3-mini",desc:"o3-mini \u2014 reasoning, 200k context"}]},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0,models:[{id:"gemini-2.0-flash",desc:"Flash 2.0 \u2014 fast, 1M context"},{id:"gemini-2.0-pro",desc:"Pro 2.0 \u2014 capable, 1M context"},{id:"gemini-1.5-pro",desc:"Pro 1.5 \u2014 2M context"},{id:"gemini-1.5-flash",desc:"Flash 1.5 \u2014 fast, 1M context"}]},{name:"mistral",label:"Mistral AI",defaultModel:"mistral-small-latest",envKeyName:"ALFRED_MISTRAL_API_KEY",needsApiKey:!0,models:[{id:"mistral-small-latest",desc:"Small 3.2 \u2014 fast, 128k context, best value"},{id:"mistral-medium-latest",desc:"Medium 3.1 \u2014 balanced, 128k context"},{id:"mistral-large-latest",desc:"Large 3 \u2014 flagship, 256k context"},{id:"codestral-latest",desc:"Codestral \u2014 code-optimized, 256k context"},{id:"magistral-medium-latest",desc:"Magistral Medium \u2014 reasoning, 40k context"},{id:"magistral-small-latest",desc:"Magistral Small \u2014 reasoning (light), 40k context"},{id:"ministral-8b-latest",desc:"Ministral 8B \u2014 edge/tiny, 128k context"}]}],gs=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];u(lh,"findCommand");Sd=[{name:"claude-code",label:"Claude Code",command:"claude",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"claude"},{name:"codex",label:"OpenAI Codex CLI",command:"codex",argsTemplate:["{{prompt}}"],promptVia:"arg",whichCmd:"codex"},{name:"aider",label:"Aider",command:"aider",argsTemplate:["--message","{{prompt}}"],promptVia:"arg",whichCmd:"aider"},{name:"gemini",label:"Gemini CLI",command:"gemini",argsTemplate:["-p","{{prompt}}"],promptVia:"arg",whichCmd:"gemini"}];u(dh,"loadExistingConfig");u(uh,"setupCommand");u(U,"askWithDefault");u(Ie,"askRequired");u(Pr,"askNumber");u(mh,"printBanner")});var Cd={};me(Cd,{configCommand:()=>gh});function hh(l){let e=l.toLowerCase();return ph.some(t=>e.includes(t))}function fh(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Rd(l){let e={};for(let[t,s]of Object.entries(l))hh(t)?e[t]=fh(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Rd(s):e[t]=s;return e}async function gh(){let l=new ue,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Rd(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var ph,Dd=_(()=>{"use strict";We();ph=["token","apikey","api_key","accesstoken","secret","password"];u(hh,"isSensitiveKey");u(fh,"redactValue");u(Rd,"redactObject");u(gh,"configCommand")});var Nd={};me(Nd,{rulesCommand:()=>wh});import Kn from"node:fs";import Ld from"node:path";import yh from"js-yaml";async function wh(){let l=new ue,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ld.resolve(e.security.rulesPath);if(!Kn.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Kn.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Kn.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 wt,o=[],i=[];for(let a of r){let c=Ld.join(t,a);try{let d=Kn.readFileSync(c,"utf-8"),m=yh.load(d),p=n.loadFromObject(m);o.push(...p)}catch(d){i.push(` ${a}: ${d.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,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 Md=_(()=>{"use strict";We();rn();u(wh,"rulesCommand")});var Od={};me(Od,{statusCommand:()=>_h});import Ur from"node:fs";import sa from"node:path";import Th from"js-yaml";async function _h(){let l=new ue,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 d=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",m=c.enabled?"+":"-";console.log(` [${m}] ${c.name}: ${d}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let d=e.llm[c];d&&console.log(` ${c}: ${d.provider}/${d.model}`)}console.log(""),console.log("Storage:");let r=sa.resolve(e.storage.path),n=Ur.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=sa.resolve(e.security.rulesPath),i=0,a=0;if(Ur.existsSync(o)&&Ur.statSync(o).isDirectory()){let c=Ur.readdirSync(o).filter(m=>m.endsWith(".yml")||m.endsWith(".yaml"));a=c.length;let d=new wt;for(let m of c){let p=sa.join(o,m);try{let g=Ur.readFileSync(p,"utf-8"),f=Th.load(g),h=d.loadFromObject(f);i+=h.length}catch{}}}console.log("Security:"),console.log(` Rules path: ${o}`),console.log(` Rule files: ${a}`),console.log(` Rules loaded: ${i}`),console.log(` Default effect: ${e.security.defaultEffect}`),e.security.ownerUserId&&console.log(` Owner user ID: ${e.security.ownerUserId}`),console.log(""),console.log("Logger:"),console.log(` Level: ${e.logger.level}`),console.log(` Pretty: ${e.logger.pretty}`)}var Pd=_(()=>{"use strict";We();rn();u(_h,"statusCommand")});var jd={};me(jd,{authCommand:()=>Oh});import{createServer as bh}from"node:http";import{exec as Eh}from"node:child_process";import{readFileSync as $h,writeFileSync as kh,existsSync as vh}from"node:fs";import{createInterface as Sh}from"node:readline";import{resolve as Ah}from"node:path";async function ra(l){let e=Sh({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question(l,s=>{e.close(),t(s.trim())})})}function xh(){let l={};try{let s=new ue().loadConfig();for(let o of["email","calendar","contacts"]){let i=s[o];if(!i)continue;let a=i.microsoft;a&&(!l.clientId&&a.clientId&&(l.clientId=a.clientId),!l.clientSecret&&a.clientSecret&&(l.clientSecret=a.clientSecret),!l.tenantId&&a.tenantId&&(l.tenantId=a.tenantId))}let r=s.todo;r&&(!l.clientId&&r.clientId&&(l.clientId=r.clientId),!l.clientSecret&&r.clientSecret&&(l.clientSecret=r.clientSecret),!l.tenantId&&r.tenantId&&(l.tenantId=r.tenantId));let n=s.email;if(n?.accounts&&Array.isArray(n.accounts))for(let o of n.accounts){let i=o.microsoft;i&&(!l.clientId&&i.clientId&&(l.clientId=i.clientId),!l.clientSecret&&i.clientSecret&&(l.clientSecret=i.clientSecret),!l.tenantId&&i.tenantId&&(l.tenantId=i.tenantId))}}catch{}let e=["ALFRED_MICROSOFT_EMAIL","ALFRED_MICROSOFT_CALENDAR","ALFRED_MICROSOFT_CONTACTS","ALFRED_MICROSOFT_TODO"];for(let t of e)l.clientId||(l.clientId=process.env[`${t}_CLIENT_ID`]),l.clientSecret||(l.clientSecret=process.env[`${t}_CLIENT_SECRET`]),l.tenantId||(l.tenantId=process.env[`${t}_TENANT_ID`]);return l}async function Rh(){let l=xh(),e=l.clientId||await ra(" Client ID: "),t=l.clientSecret||await ra(" Client Secret: "),s=l.tenantId||await ra(' Tenant ID (oder "common"): ');return(!e||!t||!s)&&(console.error("Fehler: Client ID, Client Secret und Tenant ID werden ben\xF6tigt."),process.exit(1)),{clientId:e,clientSecret:t,tenantId:s}}function Ch(l){let e=new URLSearchParams({client_id:l.clientId,response_type:"code",redirect_uri:Ud,response_mode:"query",scope:Fd,prompt:"consent"});return`https://login.microsoftonline.com/${l.tenantId}/oauth2/v2.0/authorize?${e}`}async function Dh(l,e){let t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,code:l,redirect_uri:Ud,grant_type:"authorization_code",scope:Fd}),s=await fetch(`https://login.microsoftonline.com/${e.tenantId}/oauth2/v2.0/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t});if(!s.ok){let n=await s.text();throw new Error(`Token-Austausch fehlgeschlagen (${s.status}): ${n}`)}let r=await s.json();if(!r.refresh_token)throw new Error('Kein Refresh Token in der Antwort. Stelle sicher, dass "offline_access" als Scope erlaubt ist.');return r.refresh_token}function Lh(l){let t={win32:`start "" "${l}"`,darwin:`open "${l}"`,linux:`xdg-open "${l}"`}[process.platform];t&&Eh(t,()=>{})}function Nh(l,e){let t=Ah(process.cwd(),".env"),s=[];vh(t)&&(s=$h(t,"utf-8").split(`
|
|
1037
1038
|
`));let r={ALFRED_EMAIL_PROVIDER:"microsoft",ALFRED_CALENDAR_PROVIDER:"microsoft",ALFRED_CONTACTS_PROVIDER:"microsoft",ALFRED_MICROSOFT_EMAIL_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_EMAIL_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_EMAIL_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_EMAIL_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CALENDAR_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_CALENDAR_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_CALENDAR_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_CALENDAR_REFRESH_TOKEN:e,ALFRED_MICROSOFT_CONTACTS_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_CONTACTS_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_CONTACTS_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_CONTACTS_REFRESH_TOKEN:e,ALFRED_MICROSOFT_TODO_CLIENT_ID:l.clientId,ALFRED_MICROSOFT_TODO_CLIENT_SECRET:l.clientSecret,ALFRED_MICROSOFT_TODO_TENANT_ID:l.tenantId,ALFRED_MICROSOFT_TODO_REFRESH_TOKEN:e},n=new Set(Object.keys(r));for(let i=0;i<s.length;i++){let a=s[i].match(/^#?\s*([A-Z_]+)=/);a&&n.has(a[1])&&(s[i]=`${a[1]}=${r[a[1]]}`,n.delete(a[1]))}if(n.size>0){s.length>0&&s[s.length-1]!==""&&s.push("");for(let i of n)s.push(`${i}=${r[i]}`)}let o=s.join(`
|
|
1038
1039
|
`).replace(/\n*$/,`
|
|
1039
|
-
`)
|
|
1040
|
-
Fehler: ${s.message}`),process.exit(1)}process.exit(0)}var Ud,Fd,
|
|
1040
|
+
`);kh(t,o)}function Mh(l){return new Promise((e,t)=>{let s=bh(async(r,n)=>{let o=new URL(r.url??"/","http://localhost:3000");if(o.pathname!=="/callback"){n.writeHead(404),n.end("Not found");return}let i=o.searchParams.get("code"),a=o.searchParams.get("error");if(a){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>Fehler: ${a}</h1><p>${o.searchParams.get("error_description")??""}</p>`),s.close(),t(new Error(`OAuth-Fehler: ${a}`));return}if(!i){n.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),n.end("<h1>Fehler: Kein Auth-Code erhalten</h1>");return}try{let c=await Dh(i,l);n.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),n.end(Ih),s.close(),e(c)}catch(c){n.writeHead(500,{"Content-Type":"text/html; charset=utf-8"}),n.end(`<h1>Fehler beim Token-Austausch</h1><p>${c.message}</p>`),s.close(),t(c)}});s.listen(3e3,()=>{console.log(" Callback-Server gestartet auf http://localhost:3000")}),s.on("error",r=>{t(new Error(`Server konnte nicht gestartet werden: ${r.message}`))})})}async function Oh(l){l||(console.error("Usage: alfred auth <provider>"),console.error(" Unterst\xFCtzte Provider: microsoft"),process.exit(1)),l!=="microsoft"&&(console.error(`Unbekannter Provider: ${l}`),console.error(" Unterst\xFCtzte Provider: microsoft"),process.exit(1)),console.log(""),console.log(" Microsoft 365 OAuth \u2014 Automatischer Token-Flow"),console.log(" ================================================"),console.log("");let e=await Rh(),t=Ch(e);console.log(""),console.log(" \xD6ffne diese URL im Browser:"),console.log(` ${t}`),console.log(""),Lh(t);try{let s=await Mh(e);console.log(""),console.log(" Refresh Token erhalten! Schreibe in .env ..."),Nh(e,s),console.log(" .env aktualisiert (Email, Calendar, Contacts, To Do)."),console.log(""),console.log(" Fertig! Du kannst Alfred jetzt mit Microsoft 365 nutzen."),console.log("")}catch(s){console.error(`
|
|
1041
|
+
Fehler: ${s.message}`),process.exit(1)}process.exit(0)}var Ud,Fd,Ih,Bd=_(()=>{"use strict";We();Ud="http://localhost:3000/callback",Fd=["offline_access","Mail.Read","Mail.ReadWrite","Mail.Send","Contacts.Read","Contacts.ReadWrite","Calendars.Read","Calendars.ReadWrite","Tasks.ReadWrite"].join(" "),Ih=`<!DOCTYPE html>
|
|
1041
1042
|
<html><head><meta charset="utf-8"><title>Alfred \u2014 Auth erfolgreich</title>
|
|
1042
1043
|
<style>body{font-family:system-ui,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0d1117;color:#e6edf3}
|
|
1043
1044
|
.card{text-align:center;padding:2rem;border:1px solid #30363d;border-radius:12px;background:#161b22}
|
|
1044
1045
|
h1{color:#3fb950;margin-bottom:.5rem}p{color:#8b949e}</style></head>
|
|
1045
|
-
<body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(ra,"askQuestion");u(
|
|
1046
|
+
<body><div class="card"><h1>Authentifizierung erfolgreich!</h1><p>Du kannst dieses Fenster schliessen und zum Terminal zur\xFCckkehren.</p></div></body></html>`;u(ra,"askQuestion");u(xh,"resolveCredentials");u(Rh,"ensureCredentials");u(Ch,"buildAuthUrl");u(Dh,"exchangeCode");u(Lh,"openBrowser");u(Nh,"updateEnvFile");u(Mh,"waitForCallback");u(Oh,"authCommand")});var Hd={};me(Hd,{logsCommand:()=>Fh});import Ph from"node:fs";import Uh from"node:path";async function Fh(l){let e=new ue,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=Uh.resolve(t.storage.path);if(!Ph.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 ft(s);let n=new gt(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(),d=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${c} [${d}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var qd=_(()=>{"use strict";We();No();u(Fh,"logsCommand")});import{readFileSync as jh}from"node:fs";import{fileURLToPath as Bh}from"node:url";import{dirname as Hh,join as qh}from"node:path";function zh(){try{let l=Hh(Bh(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(jh(qh(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}u(zh,"getVersion");var zd=zh(),na=`
|
|
1046
1047
|
Alfred CLI v${zd}
|
|
1047
1048
|
Personal AI Assistant
|
|
1048
1049
|
|
|
@@ -1062,4 +1063,4 @@ Commands:
|
|
|
1062
1063
|
Options:
|
|
1063
1064
|
--help, -h Show this help message
|
|
1064
1065
|
--version, -v Show version number
|
|
1065
|
-
`.trim();function
|
|
1066
|
+
`.trim();function Wh(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}}u(Wh,"parseArgs");async function Gh(){let l=Wh(process.argv);switch((l.flags.help||l.flags.h)&&(console.log(na),process.exit(0)),(l.flags.version||l.flags.v)&&(console.log(`alfred v${zd}`),process.exit(0)),l.command){case"start":{let{startCommand:e}=await Promise.resolve().then(()=>(Ed(),bd));await e();break}case"chat":{let{chatCommand:e}=await Promise.resolve().then(()=>(vd(),kd));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(()=>(xd(),Id));await e();break}case"config":{let{configCommand:e}=await Promise.resolve().then(()=>(Dd(),Cd));await e();break}case"rules":{let{rulesCommand:e}=await Promise.resolve().then(()=>(Md(),Nd));await e();break}case"status":{let{statusCommand:e}=await Promise.resolve().then(()=>(Pd(),Od));await e();break}case"auth":{let e=l.positional[0]??"",{authCommand:t}=await Promise.resolve().then(()=>(Bd(),jd));await t(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(()=>(qd(),Hd));await s(t);break}case"help":console.log(na);break;case"":console.log(na),process.exit(0);break;default:console.error(`Unknown command: ${l.command}`),console.error(""),console.error('Run "alfred --help" for usage information.'),process.exit(1)}}u(Gh,"main");Gh().catch(l=>{console.error("Fatal error:",l),process.exit(1)});
|