@madh-io/alfred-ai 0.9.32 → 0.9.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bundle/index.js +54 -54
  2. package/package.json +1 -1
package/bundle/index.js CHANGED
@@ -243,7 +243,7 @@ var Qr=Object.defineProperty;var d=(l,e)=>Qr(l,"name",{value:e,configurable:!0})
243
243
  `)}runMigrations(){new Fe(this.db).migrate(er)}getDb(){return this.db}close(){this.db.close()}}});import fn from"node:crypto";var _t,gn=g(()=>{"use strict";_t=class{static{d(this,"ConversationRepository")}db;constructor(e){this.db=e}create(e,t,s){let r=new Date().toISOString(),n={id:fn.randomUUID(),platform:e,chatId:t,userId:s,createdAt:r,updatedAt:r};return this.db.prepare(`
244
244
  INSERT INTO conversations (id, platform, chat_id, user_id, created_at, updated_at)
245
245
  VALUES (?, ?, ?, ?, ?, ?)
246
- `).run(n.id,n.platform,n.chatId,n.userId,n.createdAt,n.updatedAt),n}findById(e){let t=this.db.prepare("SELECT * FROM conversations WHERE id = ?").get(e);if(t)return this.mapRow(t)}findByPlatformChat(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND chat_id = ?").get(e,t);if(s)return this.mapRow(s)}addMessage(e,t,s,r){let n={id:fn.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
246
+ `).run(n.id,n.platform,n.chatId,n.userId,n.createdAt,n.updatedAt),n}findById(e){let t=this.db.prepare("SELECT * FROM conversations WHERE id = ?").get(e);if(t)return this.mapRow(t)}findByPlatformChat(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND chat_id = ?").get(e,t);if(s)return this.mapRow(s)}findByPlatformAndUser(e,t){let s=this.db.prepare("SELECT * FROM conversations WHERE platform = ? AND user_id = ? ORDER BY updated_at DESC LIMIT 1").get(e,t);if(s)return this.mapRow(s)}addMessage(e,t,s,r){let n={id:fn.randomUUID(),conversationId:e,role:t,content:s,toolCalls:r,createdAt:new Date().toISOString()};return this.db.prepare(`
247
247
  INSERT INTO messages (id, conversation_id, role, content, tool_calls, created_at)
248
248
  VALUES (?, ?, ?, ?, ?, ?)
249
249
  `).run(n.id,n.conversationId,n.role,n.content,n.toolCalls??null,n.createdAt),n}getMessages(e,t=50){return this.db.prepare("SELECT * FROM (SELECT *, rowid AS _rn FROM messages WHERE conversation_id = ? ORDER BY created_at DESC, _rn DESC LIMIT ?) ORDER BY created_at ASC, _rn ASC").all(e,t).map(r=>({id:r.id,conversationId:r.conversation_id,role:r.role,content:r.content,toolCalls:r.tool_calls??void 0,createdAt:r.created_at}))}updateTimestamp(e){this.db.prepare("UPDATE conversations SET updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}mapRow(e){return{id:e.id,platform:e.platform,chatId:e.chat_id,userId:e.user_id,createdAt:e.created_at,updatedAt:e.updated_at}}}});import Oi from"node:crypto";var St,yn=g(()=>{"use strict";St=class{static{d(this,"UserRepository")}db;constructor(e){this.db=e}findOrCreate(e,t,s,r){let n=this.db.prepare("SELECT * FROM users WHERE platform = ? AND platform_user_id = ?").get(e,t);if(n)return this.mapRow(n);let o=new Date().toISOString(),i={id:Oi.randomUUID(),platform:e,platformUserId:t,username:s,displayName:r,createdAt:o,updatedAt:o};return this.db.prepare(`
@@ -294,7 +294,7 @@ var Qr=Object.defineProperty;var d=(l,e)=>Qr(l,"name",{value:e,configurable:!0})
294
294
  SET last_run_at = ?, next_run_at = ?
295
295
  WHERE id = ?
296
296
  `).run(t,s,e)}setEnabled(e,t){return this.db.prepare("UPDATE scheduled_actions SET enabled = ? WHERE id = ?").run(t?1:0,e).changes>0}delete(e){return this.db.prepare("DELETE FROM scheduled_actions WHERE id = ?").run(e).changes>0}calculateInitialNextRun(e,t){let s=new Date;switch(e){case"interval":{let r=parseInt(t,10);return isNaN(r)||r<=0?null:new Date(s.getTime()+r*6e4).toISOString()}case"once":return new Date(t).toISOString();case"cron":return this.getNextCronDate(t,s)?.toISOString()??null;default:return null}}getNextCronDate(e,t){let s=e.trim().split(/\s+/);if(s.length!==5)return null;let r=new Date(t.getTime()+6e4);r.setSeconds(0,0);for(let n=0;n<1440;n++){if(this.matchesCron(s,r))return r;r.setTime(r.getTime()+6e4)}return null}matchesCron(e,t){let s=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,i=t.getDay();return this.matchCronField(e[0],s)&&this.matchCronField(e[1],r)&&this.matchCronField(e[2],n)&&this.matchCronField(e[3],o)&&this.matchCronField(e[4],i)}matchCronField(e,t){if(e==="*")return!0;let s=/^\*\/(\d+)$/.exec(e);if(s){let n=parseInt(s[1],10);return t%n===0}let r=parseInt(e,10);return isNaN(r)?!1:t===r}mapRow(e){return{id:e.id,userId:e.user_id,platform:e.platform,chatId:e.chat_id,name:e.name,description:e.description,scheduleType:e.schedule_type,scheduleValue:e.schedule_value,skillName:e.skill_name,skillInput:e.skill_input,promptTemplate:e.prompt_template,enabled:e.enabled===1,lastRunAt:e.last_run_at,nextRunAt:e.next_run_at,createdAt:e.created_at}}}});import{randomUUID as xn}from"node:crypto";var Lt,In=g(()=>{"use strict";Lt=class{static{d(this,"DocumentRepository")}db;constructor(e){this.db=e}createDocument(e,t,s,r){let n=xn(),o=new Date().toISOString();return this.db.prepare("INSERT INTO documents (id, user_id, filename, mime_type, size_bytes, chunk_count, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)").run(n,e,t,s,r,o),{id:n,userId:e,filename:t,mimeType:s,sizeBytes:r,chunkCount:0,createdAt:o}}updateChunkCount(e,t){this.db.prepare("UPDATE documents SET chunk_count = ? WHERE id = ?").run(t,e)}addChunk(e,t,s,r){let n=xn(),o=new Date().toISOString();return this.db.prepare("INSERT INTO document_chunks (id, document_id, chunk_index, content, embedding_id, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(n,e,t,s,r??null,o),{id:n,documentId:e,chunkIndex:t,content:s,embeddingId:r,createdAt:o}}getDocument(e){let t=this.db.prepare("SELECT * FROM documents WHERE id = ?").get(e);return t?this.mapDocumentRow(t):void 0}getChunks(e){return this.db.prepare("SELECT * FROM document_chunks WHERE document_id = ? ORDER BY chunk_index ASC").all(e).map(s=>this.mapChunkRow(s))}listByUser(e){return this.db.prepare("SELECT * FROM documents WHERE user_id = ? ORDER BY created_at DESC").all(e).map(s=>this.mapDocumentRow(s))}deleteDocument(e){this.db.transaction(()=>{let s=this.db.prepare("SELECT embedding_id FROM document_chunks WHERE document_id = ? AND embedding_id IS NOT NULL").all(e);if(s.length>0){let r=s.map(o=>o.embedding_id),n=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM embeddings WHERE id IN (${n})`).run(...r)}this.db.prepare("DELETE FROM document_chunks WHERE document_id = ?").run(e),this.db.prepare("DELETE FROM documents WHERE id = ?").run(e)})()}getChunksByEmbeddingIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT * FROM document_chunks WHERE embedding_id IN (${t}) ORDER BY chunk_index ASC`).all(...e).map(r=>this.mapChunkRow(r))}mapDocumentRow(e){return{id:e.id,userId:e.user_id,filename:e.filename,mimeType:e.mime_type,sizeBytes:e.size_bytes,chunkCount:e.chunk_count,createdAt:e.created_at}}mapChunkRow(e){return{id:e.id,documentId:e.document_id,chunkIndex:e.chunk_index,content:e.content,embeddingId:e.embedding_id||void 0,createdAt:e.created_at}}}});var sr=g(()=>{"use strict";hn();gn();yn();wn();En();ys();tr();Tn();bn();_n();Sn();kn();vn();In()});function xe(l){if(rr[l])return rr[l];let e=Object.entries(rr).sort((t,s)=>s[0].length-t[0].length);for(let[t,s]of e)if(l.startsWith(t))return s}var rr,zi,re,je=g(()=>{"use strict";rr={"claude-opus-4-20250514":{maxInputTokens:2e5,maxOutputTokens:32e3},"claude-sonnet-4-20250514":{maxInputTokens:2e5,maxOutputTokens:16e3},"claude-haiku-3-5-20241022":{maxInputTokens:2e5,maxOutputTokens:8192},"gpt-4o":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4o-mini":{maxInputTokens:128e3,maxOutputTokens:16384},"gpt-4-turbo":{maxInputTokens:128e3,maxOutputTokens:4096},"gpt-4":{maxInputTokens:8192,maxOutputTokens:4096},"gpt-3.5-turbo":{maxInputTokens:16384,maxOutputTokens:4096},o1:{maxInputTokens:2e5,maxOutputTokens:1e5},"o1-mini":{maxInputTokens:128e3,maxOutputTokens:65536},"o3-mini":{maxInputTokens:2e5,maxOutputTokens:1e5},"llama3.2":{maxInputTokens:128e3,maxOutputTokens:4096},"llama3.1":{maxInputTokens:128e3,maxOutputTokens:4096},llama3:{maxInputTokens:8192,maxOutputTokens:4096},mistral:{maxInputTokens:32e3,maxOutputTokens:4096},"mistral-small":{maxInputTokens:32e3,maxOutputTokens:4096},mixtral:{maxInputTokens:32e3,maxOutputTokens:4096},gemma2:{maxInputTokens:8192,maxOutputTokens:4096},"qwen2.5":{maxInputTokens:128e3,maxOutputTokens:4096},phi3:{maxInputTokens:128e3,maxOutputTokens:4096},"deepseek-r1":{maxInputTokens:128e3,maxOutputTokens:8192},"command-r":{maxInputTokens:128e3,maxOutputTokens:4096},"gemini-2.0-flash":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-2.0-pro":{maxInputTokens:1048576,maxOutputTokens:8192},"gemini-1.5-pro":{maxInputTokens:2097152,maxOutputTokens:8192},"gemini-1.5-flash":{maxInputTokens:1048576,maxOutputTokens:8192}},zi={maxInputTokens:8192,maxOutputTokens:4096};d(xe,"lookupContextWindow");re=class{static{d(this,"LLMProvider")}config;contextWindow=zi;constructor(e){this.config=e}getContextWindow(){return this.contextWindow}async embed(e){}supportsEmbeddings(){return!1}}});import Xi from"@anthropic-ai/sdk";var Mt,nr=g(()=>{"use strict";je();Mt=class extends re{static{d(this,"AnthropicProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Xi({apiKey:this.config.apiKey});let e=xe(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 Hi from"openai";var ne,Be=g(()=>{"use strict";je();ne=class extends re{static{d(this,"OpenAIProvider")}client;constructor(e){super(e)}async initialize(){this.client=new Hi({apiKey:this.config.apiKey,baseURL:this.config.baseUrl});let e=xe(this.config.model);e&&(this.contextWindow=e)}async complete(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{}},n=await this.client.chat.completions.create(r);return this.mapResponse(n)}async*stream(e){let t=this.mapMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r=await this.client.chat.completions.create({model:this.config.model,max_tokens:e.maxTokens??this.config.maxTokens??4096,temperature:e.temperature??this.config.temperature,messages:t,...s?{tools:s}:{},stream:!0}),n,o,i="",a="",c=[],u=null,p=0,m=0;for await(let h of r){let E=h.choices[0];if(!E)continue;let f=E.delta;if(f?.content&&(a+=f.content,yield{type:"text_delta",text:f.content}),f?.tool_calls)for(let T of f.tool_calls)if(T.id){if(n){let _;try{_=JSON.parse(i||"{}")}catch{_={}}c.push({id:n,name:o,input:_})}n=T.id,o=T.function?.name,i=T.function?.arguments??"",yield{type:"tool_use_start",toolCall:{id:n,name:o}}}else T.function?.arguments&&(i+=T.function.arguments,yield{type:"tool_use_delta",toolCall:{input:T.function.arguments}});E.finish_reason&&(u=E.finish_reason),h.usage&&(p=h.usage.prompt_tokens,m=h.usage.completion_tokens)}if(n){let h;try{h=JSON.parse(i||"{}")}catch{h={}}c.push({id:n,name:o,input:h})}yield{type:"message_complete",response:{content:a,toolCalls:c.length>0?c:void 0,usage:{inputTokens:p,outputTokens:m},stopReason:this.mapStopReason(u)}}}isAvailable(){return!!this.config.apiKey}async embed(e){try{let s=(await this.client.embeddings.create({model:"text-embedding-3-small",input:e})).data[0];return{embedding:s.embedding,model:"text-embedding-3-small",dimensions:s.embedding.length}}catch{return}}supportsEmbeddings(){return!0}mapMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e){if(typeof r.content=="string"){s.push({role:r.role,content:r.content});continue}let n=[],o=[],i=[];for(let a of r.content)switch(a.type){case"text":n.push({type:"text",text:a.text});break;case"image":n.push({type:"image_url",image_url:{url:`data:${a.source.media_type};base64,${a.source.data}`}});break;case"tool_use":o.push({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}});break;case"tool_result":i.push({tool_call_id:a.tool_use_id,content:a.content});break}if(r.role==="assistant"&&o.length>0){let a=n.map(c=>c.text).join("");s.push({role:"assistant",content:a||null,tool_calls:o})}else if(i.length>0)for(let a of i)s.push({role:"tool",tool_call_id:a.tool_call_id,content:a.content});else n.length>0&&(r.role==="user"?s.push({role:"user",content:n}):s.push({role:r.role,content:n.map(a=>a.text).join("")}))}return s}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=e.choices[0],s=t?.message,r=s?.content??"",n=s?.tool_calls?.map(o=>({id:o.id,name:o.function.name,input:(()=>{try{return JSON.parse(o.function.arguments)}catch{return{}}})()}));return{content:r,toolCalls:n&&n.length>0?n:void 0,usage:{inputTokens:e.usage?.prompt_tokens??0,outputTokens:e.usage?.completion_tokens??0},stopReason:this.mapStopReason(t?.finish_reason??null)}}mapStopReason(e){switch(e){case"stop":return"end_turn";case"tool_calls":return"tool_use";case"length":return"max_tokens";default:return"end_turn"}}}});var Nt,or=g(()=>{"use strict";Be();Nt=class extends ne{static{d(this,"OpenRouterProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://openrouter.ai/api/v1"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});var Dt,ir=g(()=>{"use strict";je();Dt=class extends re{static{d(this,"OllamaProvider")}baseUrl="";constructor(e){super(e)}apiKey="";async initialize(){let e=this.config.baseUrl??"http://localhost:11434";this.baseUrl=e.replace(/\/v1\/?$/,"").replace(/\/+$/,""),this.apiKey=this.config.apiKey??"";let t=xe(this.config.model);t?this.contextWindow=t:await this.fetchModelContextWindow()}async fetchModelContextWindow(){try{let e=await fetch(`${this.baseUrl}/api/show`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({name:this.config.model})});if(!e.ok)return;let s=(await e.json()).model_info??{},r=Object.keys(s).find(o=>o.includes("context_length")||o==="num_ctx"),n=r?Number(s[r]):0;n>0&&(this.contextWindow={maxInputTokens:n,maxOutputTokens:Math.min(n,4096)})}catch{}}getHeaders(){let e={"Content-Type":"application/json"};return this.apiKey&&(e.Authorization=`Bearer ${this.apiKey}`),e}async complete(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!1,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let i=await n.text();throw new Error(`Ollama API error (${n.status}): ${i}`)}let o=await n.json();return this.mapResponse(o)}async*stream(e){let t=this.buildMessages(e.messages,e.system),s=e.tools?this.mapTools(e.tools):void 0,r={model:this.config.model,messages:t,stream:!0,options:this.buildOptions(e)};s&&s.length>0&&(r.tools=s);let n=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(r)});if(!n.ok){let h=await n.text();throw new Error(`Ollama API error (${n.status}): ${h}`)}if(!n.body)throw new Error("Ollama streaming response has no body");let o=n.body.getReader(),i=new TextDecoder,a="",c="",u=0,p=0,m=[];try{for(;;){let{done:h,value:E}=await o.read();if(h)break;a+=i.decode(E,{stream:!0});let f=a.split(`
297
- `);a=f.pop()??"";for(let T of f){let _=T.trim();if(!_)continue;let I;try{I=JSON.parse(_)}catch{continue}if(I.message?.content&&(c+=I.message.content,yield{type:"text_delta",text:I.message.content}),I.message?.tool_calls)for(let v of I.message.tool_calls){let M={id:`ollama_tool_${m.length}`,name:v.function.name,input:v.function.arguments};m.push(M),yield{type:"tool_use_start",toolCall:{id:M.id,name:M.name}},yield{type:"tool_use_delta",toolCall:{input:M.input}}}I.done&&(u=I.prompt_eval_count??0,p=I.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:m.length>0?m:void 0,usage:{inputTokens:u,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let h;try{h=JSON.parse(a.trim())}catch{return}if(h.message?.content&&(c+=h.message.content,yield{type:"text_delta",text:h.message.content}),h.message?.tool_calls)for(let E of h.message.tool_calls){let f={id:`ollama_tool_${m.length}`,name:E.function.name,input:E.function.arguments};m.push(f),yield{type:"tool_use_start",toolCall:{id:f.id,name:f.name}},yield{type:"tool_use_delta",toolCall:{input:f.input}}}h.done&&(u=h.prompt_eval_count??0,p=h.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:m.length>0?m:void 0,usage:{inputTokens:u,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
297
+ `);a=f.pop()??"";for(let T of f){let _=T.trim();if(!_)continue;let I;try{I=JSON.parse(_)}catch{continue}if(I.message?.content&&(c+=I.message.content,yield{type:"text_delta",text:I.message.content}),I.message?.tool_calls)for(let v of I.message.tool_calls){let N={id:`ollama_tool_${m.length}`,name:v.function.name,input:v.function.arguments};m.push(N),yield{type:"tool_use_start",toolCall:{id:N.id,name:N.name}},yield{type:"tool_use_delta",toolCall:{input:N.input}}}I.done&&(u=I.prompt_eval_count??0,p=I.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:m.length>0?m:void 0,usage:{inputTokens:u,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}if(a.trim()){let h;try{h=JSON.parse(a.trim())}catch{return}if(h.message?.content&&(c+=h.message.content,yield{type:"text_delta",text:h.message.content}),h.message?.tool_calls)for(let E of h.message.tool_calls){let f={id:`ollama_tool_${m.length}`,name:E.function.name,input:E.function.arguments};m.push(f),yield{type:"tool_use_start",toolCall:{id:f.id,name:f.name}},yield{type:"tool_use_delta",toolCall:{input:f.input}}}h.done&&(u=h.prompt_eval_count??0,p=h.eval_count??0,yield{type:"message_complete",response:{content:c,toolCalls:m.length>0?m:void 0,usage:{inputTokens:u,outputTokens:p},stopReason:m.length>0?"tool_use":"end_turn"}})}}finally{o.releaseLock()}}isAvailable(){try{return this.baseUrl.length>0}catch{return!1}}async embed(e){try{let t=await fetch(`${this.baseUrl}/api/embed`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({model:"nomic-embed-text",input:e})});if(!t.ok)return;let s=await t.json();if(!s.embeddings||s.embeddings.length===0)return;let r=s.embeddings[0];return{embedding:r,model:"nomic-embed-text",dimensions:r.length}}catch{return}}supportsEmbeddings(){return!0}buildOptions(e){let t={},s=e.temperature??this.config.temperature;s!==void 0&&(t.temperature=s);let r=e.maxTokens??this.config.maxTokens;return r!==void 0&&(t.num_predict=r),t}buildMessages(e,t){let s=[];t&&s.push({role:"system",content:t});for(let r of e)typeof r.content=="string"?s.push({role:r.role,content:r.content}):s.push(this.mapContentBlocks(r.role,r.content));return s}mapContentBlocks(e,t){let s=[],r=[];for(let o of t)switch(o.type){case"text":s.push(o.text);break;case"image":r.push(o.source.data);break;case"tool_use":s.push(`[Tool call: ${o.name}(${JSON.stringify(o.input)})]`);break;case"tool_result":s.push(`[Tool result for ${o.tool_use_id}]: ${o.content}`);break}let n={role:e,content:s.join(`
298
298
  `)};return r.length>0&&(n.images=r),n}mapTools(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}mapResponse(e){let t=[];if(e.message.tool_calls)for(let s of e.message.tool_calls)t.push({id:`ollama_tool_${t.length}`,name:s.function.name,input:s.function.arguments});return{content:e.message.content,toolCalls:t.length>0?t:void 0,usage:{inputTokens:e.prompt_eval_count??0,outputTokens:e.eval_count??0},stopReason:t.length>0?"tool_use":"end_turn"}}}});var Ot,ar=g(()=>{"use strict";Be();Ot=class extends ne{static{d(this,"OpenWebUIProvider")}constructor(e){super({...e,apiKey:e.apiKey||"openwebui",baseUrl:e.baseUrl??"http://localhost:3000/api/v1"})}isAvailable(){return!0}supportsEmbeddings(){return!1}}});var Ct,cr=g(()=>{"use strict";Be();Ct=class extends ne{static{d(this,"GoogleProvider")}constructor(e){super({...e,baseUrl:e.baseUrl??"https://generativelanguage.googleapis.com/v1beta/openai/"})}isAvailable(){return!!this.config.apiKey}supportsEmbeddings(){return!1}}});function lr(l){switch(l.provider){case"anthropic":return new Mt(l);case"openai":return new ne(l);case"openrouter":return new Nt(l);case"ollama":return new Dt(l);case"openwebui":return new Ot(l);case"google":return new Ct(l);default:throw new Error(`Unknown LLM provider: ${l.provider}`)}}var dr=g(()=>{"use strict";nr();Be();or();ir();ar();cr();d(lr,"createLLMProvider")});function ur(l){return new ws(l)}var qi,ws,$n=g(()=>{"use strict";je();dr();qi=["default","strong","fast","embeddings","local"],ws=class extends re{static{d(this,"ModelRouter")}providers=new Map;multiConfig;constructor(e){super(e.default),this.multiConfig=e}async initialize(){for(let e of qi){let t=this.multiConfig[e];if(t){let s=lr(t);await s.initialize(),this.providers.set(e,s)}}}resolve(e){return e&&this.providers.has(e)?this.providers.get(e):this.providers.get("default")}async complete(e){return this.resolve(e.tier).complete(e)}async*stream(e){yield*this.resolve(e.tier).stream(e)}async embed(e){return(this.providers.get("embeddings")??this.resolve()).embed(e)}supportsEmbeddings(){return(this.providers.get("embeddings")??this.resolve()).supportsEmbeddings()}isAvailable(){return this.resolve().isAvailable()}getContextWindow(){return this.resolve().getContextWindow()}};d(ur,"createModelRouter")});function ge(l){return Math.ceil(l.length/3.5)}function Es(l){if(typeof l.content=="string")return ge(l.content)+4;let e=4;for(let t of l.content)switch(t.type){case"text":e+=ge(t.text);break;case"image":e+=1e3;break;case"tool_use":e+=ge(t.name)+ge(JSON.stringify(t.input));break;case"tool_result":e+=ge(t.content);break}return e}var Ut,An=g(()=>{"use strict";d(ge,"estimateTokens");d(Es,"estimateMessageTokens");Ut=class{static{d(this,"PromptBuilder")}buildSystemPrompt(e={}){let{memories:t,skills:s,userProfile:r,todayEvents:n}=e,o=process.platform==="darwin"?"macOS":process.platform==="win32"?"Windows":"Linux",i=process.env.HOME||process.env.USERPROFILE||"~",a=`You are Alfred, a personal AI assistant. You run on ${o} (home: ${i}).
299
299
 
300
300
  ## Core principles
@@ -346,9 +346,9 @@ For complex tasks, work through multiple steps:
346
346
  - ${T}${_}: ${f.title}${I}`}}if(t&&t.length>0){if(a+=`
347
347
 
348
348
  ## Memories about this user
349
- `,t.some(T=>T.type&&T.type!=="general")){let T=new Map;for(let I of t){let v=I.type||"general",M=T.get(v);M||(M=[],T.set(v,M)),M.push(I)}let _={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[I,v]of T){a+=`
349
+ `,t.some(T=>T.type&&T.type!=="general")){let T=new Map;for(let I of t){let v=I.type||"general",N=T.get(v);N||(N=[],T.set(v,N)),N.push(I)}let _={fact:"Facts",preference:"Preferences",correction:"Corrections",entity:"Entities",decision:"Decisions",relationship:"Relationships",principle:"Principles",commitment:"Commitments",moment:"Moments",skill:"Skills",general:"General"};for(let[I,v]of T){a+=`
350
350
  ### ${_[I]||I}
351
- `;for(let M of v)a+=`- ${M.key}: ${M.value}
351
+ `;for(let N of v)a+=`- ${N.key}: ${N.value}
352
352
  `}}else for(let T of t)a+=`- [${T.category}] ${T.key}: ${T.value}
353
353
  `;a+=`
354
354
  Use these memories to personalize your responses. When the user tells you new facts or preferences, use the memory tool to save them.`}else a+=`
@@ -359,29 +359,29 @@ When the user tells you facts about themselves or preferences, use the memory to
359
359
 
360
360
  `);return{success:!0,data:{query:s,results:o},display:`Search results for "${s}":
361
361
 
362
- ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let c=i[1],u=this.stripHtml(i[2]).trim(),p=this.extractDdgUrl(c);u&&p&&o.push({url:p,title:u})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let c=0;c<Math.min(o.length,t);c++)s.push({title:o[c].title,url:o[c].url,snippet:a[c]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var Ke,Wn=g(()=>{"use strict";P();Ke=class extends k{static{d(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let p=this.parseTriggerAt(r,t.timezone);if(!p)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(p.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=p}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),u=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${u} (in ${c} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),c=parseInt(n[4],10),u=parseInt(n[5],10);return c>23||u>59||i>11||a>31?void 0:this.buildDateInTimezone(c,u,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let h=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||h.setHours(e,t,0,0),h}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let h=i.formatToParts(n),E=parseInt(h.find(D=>D.type==="year").value,10),f=parseInt(h.find(D=>D.type==="month").value,10)-1,T=parseInt(h.find(D=>D.type==="day").value,10),_=new Date(Date.UTC(E,f,T,e,t,0)),I=i.formatToParts(_),v=parseInt(I.find(D=>D.type==="hour").value,10),M=parseInt(I.find(D=>D.type==="minute").value,10),A=(e-v)*60+(t-M);return _=new Date(_.getTime()+A*6e4),_}let a=o,c=i.formatToParts(a),u=parseInt(c.find(h=>h.type==="hour").value,10),p=parseInt(c.find(h=>h.type==="minute").value,10),m=(e-u)*60+(t-p);return a=new Date(a.getTime()+m*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
362
+ ${i}`}}catch(o){return{success:!1,error:`Search failed: ${o instanceof Error?o.message:String(o)}`}}}async searchBrave(e,t){let s=new URL("https://api.search.brave.com/res/v1/web/search");s.searchParams.set("q",e),s.searchParams.set("count",String(t));let r=await fetch(s.toString(),{headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":this.config.apiKey}});if(!r.ok)throw new Error(`Brave Search API returned ${r.status}: ${r.statusText}`);return((await r.json()).web?.results??[]).slice(0,t).map(o=>({title:o.title,url:o.url,snippet:o.description}))}async searchSearXNG(e,t){let s=(this.config.baseUrl??"http://localhost:8080").replace(/\/+$/,""),r=new URL(`${s}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("pageno","1");let n=await fetch(r.toString(),{headers:{Accept:"application/json"}});if(!n.ok)throw new Error(`SearXNG returned ${n.status}: ${n.statusText}`);return((await n.json()).results??[]).slice(0,t).map(i=>({title:i.title,url:i.url,snippet:i.content}))}async searchTavily(e,t){let s=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:this.config.apiKey,query:e,max_results:t,include_answer:!1})});if(!s.ok)throw new Error(`Tavily API returned ${s.status}: ${s.statusText}`);return((await s.json()).results??[]).slice(0,t).map(n=>({title:n.title,url:n.url,snippet:n.content}))}async searchDuckDuckGo(e,t){let s=new URL("https://html.duckduckgo.com/html/");s.searchParams.set("q",e);let r=await fetch(s.toString(),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Alfred/1.0)"}});if(!r.ok)throw new Error(`DuckDuckGo returned ${r.status}: ${r.statusText}`);let n=await r.text();return this.parseDuckDuckGoHtml(n,t)}parseDuckDuckGoHtml(e,t){let s=[],r=/<a[^>]+class="result__a"[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/g,n=/<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g,o=[],i;for(;(i=r.exec(e))!==null;){let c=i[1],u=this.stripHtml(i[2]).trim(),p=this.extractDdgUrl(c);u&&p&&o.push({url:p,title:u})}let a=[];for(;(i=n.exec(e))!==null;)a.push(this.stripHtml(i[1]).trim());for(let c=0;c<Math.min(o.length,t);c++)s.push({title:o[c].title,url:o[c].url,snippet:a[c]??""});return s}extractDdgUrl(e){try{if(e.includes("uddg=")){let s=new URL(e,"https://duckduckgo.com").searchParams.get("uddg");if(s)return decodeURIComponent(s)}}catch{}return e.startsWith("http")?e:""}stripHtml(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ")}}});var Ke,Wn=g(()=>{"use strict";P();Ke=class extends k{static{d(this,"ReminderSkill")}reminderRepo;metadata={name:"reminder",description:'Set timed reminders that notify the user later. Use when the user says "remind me", "erinnere mich", or asks to be notified about something at a specific time. Prefer triggerAt (absolute time like "14:30" or "2026-02-28 09:00") over delayMinutes \u2014 it is more precise and avoids calculation errors.',riskLevel:"write",version:"3.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["set","list","cancel"],description:"The reminder action to perform"},message:{type:"string",description:"The reminder message (required for set)"},triggerAt:{type:"string",description:'Absolute time for the reminder. Accepts "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date. Preferred over delayMinutes for time-specific reminders.'},delayMinutes:{type:"number",description:"Minutes until the reminder triggers. Use triggerAt instead when the user specifies a clock time."},reminderId:{type:"string",description:"The ID of the reminder to cancel (required for cancel)"}},required:["action"]}};constructor(e){super(),this.reminderRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllReminders(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.reminderRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"set":return this.setReminder(e,t);case"list":return this.listReminders(t);case"cancel":return this.cancelReminder(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: set, list, cancel`}}}setReminder(e,t){let s=e.message,r=e.triggerAt,n=e.delayMinutes;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "message" for set action'};let o;if(r&&typeof r=="string"){let p=this.parseTriggerAt(r,t.timezone);if(!p)return{success:!1,error:`Could not parse triggerAt "${r}". Use "HH:MM" for today or "YYYY-MM-DD HH:MM" for a specific date.`};if(p.getTime()<=Date.now())return{success:!1,error:`The time "${r}" is in the past. Please specify a future time.`};o=p}else if(n!==void 0&&typeof n=="number"&&n>0)o=new Date(Date.now()+n*60*1e3);else return{success:!1,error:'Provide either "triggerAt" (e.g. "14:30") or "delayMinutes" (positive number) for set action.'};let i=this.reminderRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,o),a=o.getTime()-Date.now(),c=Math.round(a/6e4),u=o.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit",...t.timezone?{timeZone:t.timezone}:{}});return{success:!0,data:{reminderId:i.id,message:s,triggerAt:i.triggerAt},display:`Reminder set (${i.id}): "${s}" at ${u} (in ${c} min)`}}parseTriggerAt(e,t){let s=e.trim(),r=/^(\d{1,2}):(\d{2})$/.exec(s);if(r){let o=parseInt(r[1],10),i=parseInt(r[2],10);return o>23||i>59?void 0:this.buildDateInTimezone(o,i,void 0,t)}let n=/^(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{2})$/.exec(s);if(n){let o=parseInt(n[1],10),i=parseInt(n[2],10)-1,a=parseInt(n[3],10),c=parseInt(n[4],10),u=parseInt(n[5],10);return c>23||u>59||i>11||a>31?void 0:this.buildDateInTimezone(c,u,{year:o,month:i,day:a},t)}}buildDateInTimezone(e,t,s,r){if(!r){let h=s?new Date(s.year,s.month,s.day,e,t,0,0):new Date;return s||h.setHours(e,t,0,0),h}let n=new Date,o=s?new Date(Date.UTC(s.year,s.month,s.day,e,t,0)):new Date(Date.UTC(n.getFullYear(),n.getMonth(),n.getDate(),e,t,0)),i=new Intl.DateTimeFormat("en-CA",{timeZone:r,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});if(!s){let h=i.formatToParts(n),E=parseInt(h.find(D=>D.type==="year").value,10),f=parseInt(h.find(D=>D.type==="month").value,10)-1,T=parseInt(h.find(D=>D.type==="day").value,10),_=new Date(Date.UTC(E,f,T,e,t,0)),I=i.formatToParts(_),v=parseInt(I.find(D=>D.type==="hour").value,10),N=parseInt(I.find(D=>D.type==="minute").value,10),A=(e-v)*60+(t-N);return _=new Date(_.getTime()+A*6e4),_}let a=o,c=i.formatToParts(a),u=parseInt(c.find(h=>h.type==="hour").value,10),p=parseInt(c.find(h=>h.type==="minute").value,10),m=(e-u)*60+(t-p);return a=new Date(a.getTime()+m*6e4),a}listReminders(e){let s=this.getAllReminders(e).map(r=>({reminderId:r.id,message:r.message,triggerAt:r.triggerAt}));return{success:!0,data:s,display:s.length===0?"No active reminders.":`Active reminders:
363
363
  ${s.map(r=>`- ${r.reminderId}: "${r.message}" (triggers at ${r.triggerAt})`).join(`
364
- `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var Ve,zn=g(()=>{"use strict";P();Ve=class extends k{static{d(this,"NoteSkill")}noteRepo;metadata={name:"note",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(t.masterUserId??t.userId,s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=this.noteRepo.list(e.masterUserId??e.userId);if(t.length===0)return{success:!0,data:[],display:"No notes found."};let s=t.map(r=>`- **${r.title}** (${r.id.slice(0,8)}\u2026)
365
- ${r.content.slice(0,100)}${r.content.length>100?"\u2026":""}`).join(`
366
- `);return{success:!0,data:t,display:`${t.length} note(s):
367
- ${s}`}}searchNotes(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=this.noteRepo.search(t.masterUserId??t.userId,s);if(r.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let n=r.map(o=>`- **${o.title}** (${o.id.slice(0,8)}\u2026)
368
- ${o.content.slice(0,100)}${o.content.length>100?"\u2026":""}`).join(`
369
- `);return{success:!0,data:r,display:`Found ${r.length} note(s):
370
- ${n}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?r.userId!==(t.masterUserId??t.userId)?{success:!1,error:`Note "${s}" not found`}:this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var Ji,Ge,Xn=g(()=>{"use strict";P();Ji={0:"Clear sky",1:"Mainly clear",2:"Partly cloudy",3:"Overcast",45:"Foggy",48:"Depositing rime fog",51:"Light drizzle",53:"Moderate drizzle",55:"Dense drizzle",61:"Slight rain",63:"Moderate rain",65:"Heavy rain",71:"Slight snow",73:"Moderate snow",75:"Heavy snow",77:"Snow grains",80:"Slight rain showers",81:"Moderate rain showers",82:"Violent rain showers",85:"Slight snow showers",86:"Heavy snow showers",95:"Thunderstorm",96:"Thunderstorm with slight hail",99:"Thunderstorm with heavy hail"},Ge=class extends k{static{d(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let n=await this.fetchWeather(r.latitude,r.longitude),o=Ji[n.weathercode]??`Code ${n.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:n.temperature,unit:"\xB0C",condition:o,windSpeed:n.windspeed,windDirection:n.winddirection,isDay:n.is_day===1},c=`${i}: ${n.temperature}\xB0C, ${o}
364
+ `)}`}}cancelReminder(e,t){let s=e.reminderId;return!s||typeof s!="string"?{success:!1,error:'Missing required field "reminderId" for cancel action'}:this.getAllReminders(t).some(i=>i.id===s)?this.reminderRepo.cancel(s)?{success:!0,data:{reminderId:s},display:`Reminder "${s}" cancelled.`}:{success:!1,error:`Reminder "${s}" not found`}:{success:!1,error:`Reminder "${s}" not found`}}}});var Ve,zn=g(()=>{"use strict";P();Ve=class extends k{static{d(this,"NoteSkill")}noteRepo;metadata={name:"note",description:"Save, list, search, or delete persistent notes (stored in SQLite). Use when the user wants to write down or retrieve text notes, lists, or ideas.",riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","list","search","delete"],description:"The note action to perform"},title:{type:"string",description:"The note title (required for save)"},content:{type:"string",description:"The note content (required for save)"},noteId:{type:"string",description:"The ID of the note to delete (required for delete)"},query:{type:"string",description:"Search query to filter notes (required for search)"}},required:["action"]}};constructor(e){super(),this.noteRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveNote(e,t);case"list":return this.listNotes(t);case"search":return this.searchNotes(e,t);case"delete":return this.deleteNote(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, list, search, delete`}}}saveNote(e,t){let s=e.title,r=e.content;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "title" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "content" for save action'};let n=this.noteRepo.save(this.effectiveUserId(t),s,r);return{success:!0,data:{noteId:n.id,title:n.title},display:`Note saved: "${s}"`}}listNotes(e){let t=new Set,s=[];for(let n of this.allUserIds(e))for(let o of this.noteRepo.list(n))t.has(o.id)||(t.add(o.id),s.push(o));if(s.length===0)return{success:!0,data:[],display:"No notes found."};let r=s.map(n=>`- **${n.title}** (${n.id.slice(0,8)}\u2026)
365
+ ${n.content.slice(0,100)}${n.content.length>100?"\u2026":""}`).join(`
366
+ `);return{success:!0,data:s,display:`${s.length} note(s):
367
+ ${r}`}}searchNotes(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let i of this.allUserIds(t))for(let a of this.noteRepo.search(i,s))r.has(a.id)||(r.add(a.id),n.push(a));if(n.length===0)return{success:!0,data:[],display:`No notes matching "${s}".`};let o=n.map(i=>`- **${i.title}** (${i.id.slice(0,8)}\u2026)
368
+ ${i.content.slice(0,100)}${i.content.length>100?"\u2026":""}`).join(`
369
+ `);return{success:!0,data:n,display:`Found ${n.length} note(s):
370
+ ${o}`}}deleteNote(e,t){let s=e.noteId;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "noteId" for delete action'};let r=this.noteRepo.getById(s);return r?this.allUserIds(t).includes(r.userId)?this.noteRepo.delete(s)?{success:!0,data:{noteId:s},display:"Note deleted."}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}:{success:!1,error:`Note "${s}" not found`}}}});var Ji,Ge,Xn=g(()=>{"use strict";P();Ji={0:"Clear sky",1:"Mainly clear",2:"Partly cloudy",3:"Overcast",45:"Foggy",48:"Depositing rime fog",51:"Light drizzle",53:"Moderate drizzle",55:"Dense drizzle",61:"Slight rain",63:"Moderate rain",65:"Heavy rain",71:"Slight snow",73:"Moderate snow",75:"Heavy snow",77:"Snow grains",80:"Slight rain showers",81:"Moderate rain showers",82:"Violent rain showers",85:"Slight snow showers",86:"Heavy snow showers",95:"Thunderstorm",96:"Thunderstorm with slight hail",99:"Thunderstorm with heavy hail"},Ge=class extends k{static{d(this,"WeatherSkill")}metadata={name:"weather",description:"Get current weather for any location. Uses Open-Meteo (free, no API key). Use when the user asks about weather, temperature, or conditions somewhere.",riskLevel:"read",version:"2.0.0",inputSchema:{type:"object",properties:{location:{type:"string",description:'City or place name (e.g. "Vienna", "New York", "Tokyo")'}},required:["location"]}};async execute(e,t){let s=e.location;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "location"'};try{let r=await this.geocode(s);if(!r)return{success:!1,error:`Location "${s}" not found`};let n=await this.fetchWeather(r.latitude,r.longitude),o=Ji[n.weathercode]??`Code ${n.weathercode}`,i=r.admin1?`${r.name}, ${r.admin1}, ${r.country}`:`${r.name}, ${r.country}`,a={location:i,temperature:n.temperature,unit:"\xB0C",condition:o,windSpeed:n.windspeed,windDirection:n.winddirection,isDay:n.is_day===1},c=`${i}: ${n.temperature}\xB0C, ${o}
371
371
  Wind: ${n.windspeed} km/h`;return{success:!0,data:a,display:c}}catch(r){return{success:!1,error:`Weather fetch failed: ${r instanceof Error?r.message:String(r)}`}}}async geocode(e){let t=`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(e)}&count=1&language=en&format=json`,s=await fetch(t);if(!s.ok)throw new Error(`Geocoding API returned ${s.status}`);return(await s.json()).results?.[0]}async fetchWeather(e,t){let s=`https://api.open-meteo.com/v1/forecast?latitude=${e}&longitude=${t}&current_weather=true&timezone=auto`,r=await fetch(s);if(!r.ok)throw new Error(`Weather API returned ${r.status}`);return(await r.json()).current_weather}}});import{exec as Zi}from"node:child_process";function qn(l){return l.length>Hn?l.slice(0,Hn)+`
372
372
  [output truncated]`:l}var Qi,Hn,Ye,Kn=g(()=>{"use strict";P();Qi=3e4,Hn=1e4;d(qn,"truncate");Ye=class extends k{static{d(this,"ShellSkill")}metadata={name:"shell",description:"Execute shell commands on the host system. Use this for ANY task involving files, folders, system operations, or running programs: ls, cat, find, file, du, mkdir, cp, mv, grep, etc. When the user asks about their documents, files, or anything on disk \u2014 use this tool.",riskLevel:"admin",version:"1.0.0",inputSchema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds (default: 30000)"},cwd:{type:"string",description:"Working directory for the command"}},required:["command"]}};async execute(e,t){let s=e.command;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "command"'};let r=[/\brm\s+-rf\s+\/(?:\s|$)/,/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r)[a-zA-Z]*\s+\/(?:\s|$)/,/\brm\s+-rf\s+\/\*/,/:(){ :|:& };:/,/:\(\)\s*\{.*\|.*&\s*\}\s*;/,/>\s*\/dev\/sd[a-z]/,/\bmkfs\b/,/\bdd\s+.*\bif=/,/\bchmod\s+777\b/,/\bcurl\b.*\|\s*\bbash\b/,/\bwget\b.*\|\s*\bsh\b/,/\bpython[23]?\s+-c\b/,/\bnode\s+-e\b/,/\b(bash|sh)\s+-i\b.*\/dev\/tcp/,/\bnc\s+.*-e\b/];for(let i of r)if(i.test(s))return{success:!1,error:"Command blocked: potentially destructive system operation"};let n=typeof e.timeout=="number"&&e.timeout>0?e.timeout:Qi,o=typeof e.cwd=="string"&&e.cwd.length>0?e.cwd:void 0;try{let{stdout:i,stderr:a,exitCode:c}=await this.run(s,n,o),u=[];return i&&u.push(`stdout:
373
373
  ${qn(i)}`),a&&u.push(`stderr:
374
374
  ${qn(a)}`),u.length===0&&u.push("(no output)"),u.push(`exit code: ${c}`),{success:c===0,data:{stdout:i,stderr:a,exitCode:c},display:u.join(`
375
375
 
376
- `),...c!==0&&{error:`Command exited with code ${c}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{Zi(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var Je,Vn=g(()=>{"use strict";P();Je=class extends k{static{d(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}effectiveUserId(e){return e.masterUserId??e.userId}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(this.effectiveUserId(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r=this.memoryRepo.recall(this.effectiveUserId(t),s);return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=this.memoryRepo.search(this.effectiveUserId(t),s);return{success:!0,data:r,display:r.length===0?`No memories matching "${s}".`:`Found ${r.length} memory(ies):
377
- ${r.map(n=>`- ${n.key}: "${n.value}"`).join(`
378
- `)}`}}listMemories(e,t){let s=e.category,r=s&&typeof s=="string"?this.memoryRepo.listByCategory(this.effectiveUserId(t),s):this.memoryRepo.listAll(this.effectiveUserId(t)),n=s?`in category "${s}"`:"total";return{success:!0,data:r,display:r.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${r.length} memory(ies) ${n}:
379
- ${r.map(o=>`- [${o.category}] ${o.key}: "${o.value}"`).join(`
380
- `)}`}}deleteMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for delete action'};let r=this.memoryRepo.delete(this.effectiveUserId(t),s);return{success:!0,data:{key:s,deleted:r},display:r?`Memory "${s}" deleted.`:`No memory found for key "${s}".`}}async semanticSearchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for semantic_search action'};if(!this.embeddingService)return this.searchMemories(e,t);let r=await this.embeddingService.semanticSearch(this.effectiveUserId(t),s,10);return r.length===0?this.searchMemories(e,t):{success:!0,data:r,display:`Found ${r.length} semantically related memory(ies):
381
- ${r.map(n=>`- ${n.key}: "${n.value}" (score: ${n.score.toFixed(2)})`).join(`
376
+ `),...c!==0&&{error:`Command exited with code ${c}`}}}catch(i){return{success:!1,error:`Shell execution failed: ${i instanceof Error?i.message:String(i)}`}}}run(e,t,s){return new Promise(r=>{Zi(e,{timeout:t,cwd:s},(n,o,i)=>{let a=n&&"code"in n&&typeof n.code=="number"?n.code:n?1:0;r({stdout:typeof o=="string"?o:"",stderr:typeof i=="string"?i:"",exitCode:a})})})}}});var Je,Vn=g(()=>{"use strict";P();Je=class extends k{static{d(this,"MemorySkill")}memoryRepo;embeddingService;metadata={name:"memory",description:"Store and retrieve persistent memories. Use this to remember user preferences, facts, and important information across conversations.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["save","recall","search","list","delete","semantic_search"],description:"The memory action to perform"},key:{type:"string",description:"The memory key/label"},value:{type:"string",description:"The value to remember (for save)"},category:{type:"string",description:"Optional category (for save/list)"},query:{type:"string",description:"Search query (for search)"}},required:["action"]}};constructor(e,t){super(),this.memoryRepo=e,this.embeddingService=t}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}async execute(e,t){let s=e.action;switch(s){case"save":return this.saveMemory(e,t);case"recall":return this.recallMemory(e,t);case"search":return this.searchMemories(e,t);case"list":return this.listMemories(e,t);case"delete":return this.deleteMemory(e,t);case"semantic_search":return this.semanticSearchMemories(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: save, recall, search, list, delete, semantic_search`}}}saveMemory(e,t){let s=e.key,r=e.value,n=e.category;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for save action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "value" for save action'};let o=this.memoryRepo.save(this.effectiveUserId(t),s,r,n??"general");return this.embeddingService&&this.embeddingService.embedAndStore(this.effectiveUserId(t),`${s}: ${r}`,"memory",s).catch(()=>{}),{success:!0,data:o,display:`Remembered "${s}" = "${r}" (category: ${o.category})`}}recallMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for recall action'};let r;for(let n of this.allUserIds(t))if(r=this.memoryRepo.recall(n,s),r)break;return r?{success:!0,data:r,display:`${s} = "${r.value}" (category: ${r.category}, updated: ${r.updatedAt})`}:{success:!0,data:null,display:`No memory found for key "${s}".`}}searchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for search action'};let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of this.memoryRepo.search(o,s))r.has(i.id)||(r.add(i.id),n.push(i));return{success:!0,data:n,display:n.length===0?`No memories matching "${s}".`:`Found ${n.length} memory(ies):
377
+ ${n.map(o=>`- ${o.key}: "${o.value}"`).join(`
378
+ `)}`}}listMemories(e,t){let s=e.category,r=new Set,n=[];for(let i of this.allUserIds(t)){let a=s&&typeof s=="string"?this.memoryRepo.listByCategory(i,s):this.memoryRepo.listAll(i);for(let c of a)r.has(c.id)||(r.add(c.id),n.push(c))}let o=s?`in category "${s}"`:"total";return{success:!0,data:n,display:n.length===0?`No memories found${s?` in category "${s}"`:""}.`:`${n.length} memory(ies) ${o}:
379
+ ${n.map(i=>`- [${i.category}] ${i.key}: "${i.value}"`).join(`
380
+ `)}`}}deleteMemory(e,t){let s=e.key;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "key" for delete action'};let r=!1;for(let n of this.allUserIds(t))if(this.memoryRepo.delete(n,s)){r=!0;break}return{success:!0,data:{key:s,deleted:r},display:r?`Memory "${s}" deleted.`:`No memory found for key "${s}".`}}async semanticSearchMemories(e,t){let s=e.query;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "query" for semantic_search action'};if(!this.embeddingService)return this.searchMemories(e,t);let r=new Set,n=[];for(let o of this.allUserIds(t))for(let i of await this.embeddingService.semanticSearch(o,s,10))r.has(i.key)||(r.add(i.key),n.push(i));return n.length===0?this.searchMemories(e,t):{success:!0,data:n,display:`Found ${n.length} semantically related memory(ies):
381
+ ${n.map(o=>`- ${o.key}: "${o.value}" (score: ${o.score.toFixed(2)})`).join(`
382
382
  `)}`}}}});var ea,ta,sa,Ze,Gn=g(()=>{"use strict";P();hr();ea=5,ta=15,sa=12e4,Ze=class extends k{static{d(this,"DelegateSkill")}llm;skillRegistry;skillSandbox;securityManager;metadata={name:"delegate",description:'Delegate a complex sub-task to an autonomous sub-agent that has full tool access. The sub-agent can use shell, web search, calculator, memory, email, and all other tools. Use when a task is independent enough to run in parallel or when it requires a focused, multi-step workflow (e.g. "research X and summarize", "find all TODO files and list them", "check the weather and draft a packing list"). Control depth with max_iterations (default 5, max 15).',riskLevel:"write",version:"3.0.0",timeoutMs:sa,inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to delegate to the sub-agent. Be specific about what you want."},context:{type:"string",description:"Additional context the sub-agent needs (optional)"},max_iterations:{type:"number",description:"Max tool iterations (1-15). Use higher values for complex multi-step tasks. Default: 5."}},required:["task"]}};onProgress;constructor(e,t,s,r){super(),this.llm=e,this.skillRegistry=t,this.skillSandbox=s,this.securityManager=r}setProgressCallback(e){this.onProgress=e}createTracker(){return new $e(this.onProgress)}async execute(e,t){let s=e.task,r=e.context;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "task"'};let n=e.max_iterations,o=n?Math.max(1,Math.min(ta,Math.round(n))):ea,i=t.onProgress??this.onProgress,a=t.tracker?t.tracker:new $e(i);a.ping("starting",{maxIterations:o});let c=this.buildSubAgentTools(),u="You are a sub-agent of Alfred, a personal AI assistant. Complete the assigned task using the tools available to you. Work step by step: use tools to gather information, then synthesize a clear result. Be concise and return only the final answer when done.",p=s;r&&typeof r=="string"&&(p=`${s}
383
383
 
384
- Additional context: ${r}`);let m=[{role:"user",content:p}];try{let h=0,E=0,f=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let T=await this.llm.complete({messages:m,system:u,tools:c.length>0?c:void 0,maxTokens:2048,tier:"strong"});if(E+=T.usage.inputTokens,f+=T.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!T.toolCalls||T.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:T.content,iterations:h,usage:{inputTokens:E,outputTokens:f}},display:T.content};h++;let _=[];T.content&&_.push({type:"text",text:T.content});for(let v of T.toolCalls)_.push({type:"tool_use",id:v.id,name:v.name,input:v.input});m.push({role:"assistant",content:_});let I=[];for(let v of T.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:v.name});let M=await this.executeSubAgentTool(v,t);I.push({type:"tool_result",tool_use_id:v.id,content:M.content,is_error:M.isError})}m.push({role:"user",content:I})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var Qe,Yn=g(()=>{"use strict";P();Qe=class extends k{static{d(this,"EmailSkill")}config;metadata={name:"email",description:"Access the user's email: check inbox, read messages, search emails, or send new emails. Use when the user asks about their emails or wants to send one.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send"],description:"The email action to perform"},count:{type:"number",description:"Number of emails to fetch (for inbox, default: 10)"},messageId:{type:"string",description:"Message sequence number to read (for read action)"},query:{type:"string",description:"Search query (for search action)"},to:{type:"string",description:"Recipient email address (for send action)"},subject:{type:"string",description:"Email subject (for send action)"},body:{type:"string",description:"Email body text (for send action)"}},required:["action"]}};constructor(e){super(),this.config=e}async execute(e,t){if(!this.config)return{success:!1,error:"Email is not configured. Run `alfred setup` to configure email access."};let s=e.action;try{switch(s){case"inbox":return await this.fetchInbox(e.count);case"read":return await this.readMessage(e.messageId);case"search":return await this.searchMessages(e.query,e.count);case"send":return await this.sendMessage(e.to,e.subject,e.body);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}async fetchInbox(e){let t=Math.min(Math.max(1,e??10),50),{ImapFlow:s}=await import("imapflow"),r=new s({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1});try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=[],i=r.mailbox,a=i&&typeof i=="object"?i.exists??0:0;if(a===0)return{success:!0,data:{messages:[]},display:"Inbox is empty."};let u=`${Math.max(1,a-t+1)}:*`;for await(let h of r.fetch(u,{envelope:!0,flags:!0})){let E=h.envelope?.from?.[0],f=E?E.name?`${E.name} <${E.address}>`:E.address??"unknown":"unknown";o.push({seq:h.seq,from:f,subject:h.envelope?.subject??"(no subject)",date:h.envelope?.date?.toISOString()??"",seen:h.flags?.has("\\Seen")??!1})}o.reverse();let p=o.length===0?"No messages found.":o.map((h,E)=>{let f=h.seen?"":" [UNREAD]";return`${E+1}. [#${h.seq}]${f} ${h.subject}
384
+ Additional context: ${r}`);let m=[{role:"user",content:p}];try{let h=0,E=0,f=0;for(;;){a.ping("llm_call",{iteration:h,maxIterations:o});let T=await this.llm.complete({messages:m,system:u,tools:c.length>0?c:void 0,maxTokens:2048,tier:"strong"});if(E+=T.usage.inputTokens,f+=T.usage.outputTokens,a.ping("processing",{iteration:h,maxIterations:o}),!T.toolCalls||T.toolCalls.length===0||h>=o)return a.ping("done",{iteration:h,maxIterations:o}),{success:!0,data:{response:T.content,iterations:h,usage:{inputTokens:E,outputTokens:f}},display:T.content};h++;let _=[];T.content&&_.push({type:"text",text:T.content});for(let v of T.toolCalls)_.push({type:"tool_use",id:v.id,name:v.name,input:v.input});m.push({role:"assistant",content:_});let I=[];for(let v of T.toolCalls){a.ping("tool_call",{iteration:h,maxIterations:o,tool:v.name});let N=await this.executeSubAgentTool(v,t);I.push({type:"tool_result",tool_use_id:v.id,content:N.content,is_error:N.isError})}m.push({role:"user",content:I})}}catch(h){return{success:!1,error:`Sub-agent failed: ${h instanceof Error?h.message:String(h)}`}}}buildSubAgentTools(){return this.skillRegistry?this.skillRegistry.getAll().filter(e=>e.metadata.name!=="delegate").map(e=>({name:e.metadata.name,description:e.metadata.description,inputSchema:e.metadata.inputSchema})):[]}async executeSubAgentTool(e,t){let s=this.skillRegistry?.get(e.name);if(!s)return{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let r=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:s.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!r.allowed)return{content:`Access denied: ${r.reason}`,isError:!0}}if(this.skillSandbox){let r=await this.skillSandbox.execute(s,e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}try{let r=await s.execute(e.input,t);return{content:r.display??(r.success?JSON.stringify(r.data):r.error??"Unknown error"),isError:!r.success}}catch(r){return{content:`Skill execution failed: ${r instanceof Error?r.message:String(r)}`,isError:!0}}}}});var Qe,Yn=g(()=>{"use strict";P();Qe=class extends k{static{d(this,"EmailSkill")}config;metadata={name:"email",description:"Access the user's email: check inbox, read messages, search emails, or send new emails. Use when the user asks about their emails or wants to send one.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["inbox","read","search","send"],description:"The email action to perform"},count:{type:"number",description:"Number of emails to fetch (for inbox, default: 10)"},messageId:{type:"string",description:"Message sequence number to read (for read action)"},query:{type:"string",description:"Search query (for search action)"},to:{type:"string",description:"Recipient email address (for send action)"},subject:{type:"string",description:"Email subject (for send action)"},body:{type:"string",description:"Email body text (for send action)"}},required:["action"]}};constructor(e){super(),this.config=e}async execute(e,t){if(!this.config)return{success:!1,error:"Email is not configured. Run `alfred setup` to configure email access."};let s=e.action;try{switch(s){case"inbox":return await this.fetchInbox(e.count);case"read":return await this.readMessage(e.messageId);case"search":return await this.searchMessages(e.query,e.count);case"send":return await this.sendMessage(e.to,e.subject,e.body);default:return{success:!1,error:`Unknown action: ${s}. Use: inbox, read, search, send`}}}catch(r){return{success:!1,error:`Email error: ${r instanceof Error?r.message:String(r)}`}}}async fetchInbox(e){let t=Math.min(Math.max(1,e??10),50),{ImapFlow:s}=await import("imapflow"),r=new s({host:this.config.imap.host,port:this.config.imap.port,secure:this.config.imap.secure,auth:this.config.auth,logger:!1});try{await r.connect();let n=await r.getMailboxLock("INBOX");try{let o=[],i=r.mailbox,a=i&&typeof i=="object"?i.exists??0:0;if(a===0)return{success:!0,data:{messages:[]},display:"Inbox is empty."};let u=`${Math.max(1,a-t+1)}:*`;for await(let h of r.fetch(u,{envelope:!0,flags:!0})){let E=h.envelope?.from?.[0],f=E?E.name?`${E.name} <${E.address}>`:E.address??"unknown":"unknown";o.push({seq:h.seq,from:f,subject:h.envelope?.subject??"(no subject)",date:h.envelope?.date?.toISOString()??"",seen:h.flags?.has("\\Seen")??!1})}o.reverse();let p=o.length===0?"No messages found.":o.map((h,E)=>{let f=h.seen?"":" [UNREAD]";return`${E+1}. [#${h.seq}]${f} ${h.subject}
385
385
  From: ${h.from}
386
386
  Date: ${h.date}`}).join(`
387
387
 
@@ -414,12 +414,12 @@ Message ID: ${o.messageId}`}}extractTextBody(e){let t=e.split(/\r?\n\r?\n/);if(t
414
414
 
415
415
  ${E.slice(0,5e3)}`}:{success:!0,data:f,display:`HTTP ${c.status} ${c.statusText}
416
416
 
417
- ${E.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import F from"node:fs";import ye from"node:path";var gr,Qn,ra,tt,eo=g(()=>{"use strict";P();gr=5e5,Qn=5e7,ra={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".rtf":"application/rtf",".epub":"application/epub+zip",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".tsv":"text/tab-separated-values",".html":"text/html",".htm":"text/html",".xml":"application/xml",".yaml":"application/yaml",".yml":"application/yaml",".toml":"application/toml",".ini":"text/plain",".cfg":"text/plain",".log":"text/plain",".json":"application/json",".js":"application/javascript",".ts":"application/typescript",".py":"text/x-python",".sh":"application/x-sh",".sql":"application/sql",".css":"text/css",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".flac":"audio/flac",".aac":"audio/aac",".m4a":"audio/mp4",".mp4":"video/mp4",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".mov":"video/quicktime",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2"},tt=class extends k{static{d(this,"FileSkill")}metadata={name:"file",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. You must provide the file content.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(F.existsSync(i)&&F.lstatSync(i).isSymbolicLink()){let c=F.realpathSync(i);if(this.checkBlocked(c))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return ye.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=ye.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=F.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>gr){let r=F.readFileSync(e,"utf-8").slice(0,gr);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${gr}):
417
+ ${E.slice(0,2e3)}`}}catch(a){return{success:!1,error:`HTTP request failed: ${a instanceof Error?a.message:String(a)}`}}}isPrivateHost(e){if(e==="localhost"||e==="127.0.0.1"||e==="::1")return!0;let t=e.replace(/[\[\]]/g,"").toLowerCase();if(t.startsWith("fc")||t.startsWith("fd")||t==="::1")return!0;let s=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(e);if(s){let[,r,n]=s.map(Number);if(r===10||r===172&&n>=16&&n<=31||r===192&&n===168||r===127||r===169&&n===254||r===0)return!0}return!1}stripHtml(e){return e.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,"").replace(/<style[^>]*>[\s\S]*?<\/style>/gi,"").replace(/<[^>]+>/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#x27;/g,"'").replace(/&nbsp;/g," ").replace(/\s+/g," ").trim()}}});import j from"node:fs";import ye from"node:path";var gr,Qn,ra,tt,eo=g(()=>{"use strict";P();gr=5e5,Qn=5e7,ra={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".odt":"application/vnd.oasis.opendocument.text",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odp":"application/vnd.oasis.opendocument.presentation",".rtf":"application/rtf",".epub":"application/epub+zip",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".tsv":"text/tab-separated-values",".html":"text/html",".htm":"text/html",".xml":"application/xml",".yaml":"application/yaml",".yml":"application/yaml",".toml":"application/toml",".ini":"text/plain",".cfg":"text/plain",".log":"text/plain",".json":"application/json",".js":"application/javascript",".ts":"application/typescript",".py":"text/x-python",".sh":"application/x-sh",".sql":"application/sql",".css":"text/css",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".flac":"audio/flac",".aac":"audio/aac",".m4a":"audio/mp4",".mp4":"video/mp4",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".mov":"video/quicktime",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".ttf":"font/ttf",".otf":"font/otf",".woff":"font/woff",".woff2":"font/woff2"},tt=class extends k{static{d(this,"FileSkill")}metadata={name:"file",description:'Read, write, move, copy, or send files. Use for reading file contents, writing text to files, saving binary data, listing directory contents, moving/copying files, or getting file info. Use "send" to deliver a file to the user in the chat (PDF, images, etc.). Prefer this over shell for file operations. When a user sends a file attachment, it is saved to the inbox \u2014 use "move" to relocate it.',riskLevel:"write",version:"2.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write","write_binary","append","list","info","exists","move","copy","delete","send"],description:"The file operation to perform"},path:{type:"string",description:"Absolute or relative file/directory path (~ expands to home)"},destination:{type:"string",description:"Destination path for move/copy actions (~ expands to home)"},content:{type:"string",description:"Content to write (required for write/append; base64-encoded for write_binary)"}},required:["action","path"]}};async execute(e,t){let s=e.action,r=e.path,n=e.content,o=e.destination;if(!s||!r)return{success:!1,error:'Missing required fields "action" and "path"'};if((s==="write"||s==="write_binary"||s==="append")&&!n)return{success:!1,error:`Missing "content" field for "${s}" action. You must provide the file content.`};let i=this.resolvePath(r),a=this.checkBlocked(i);if(a)return a;try{if(j.existsSync(i)&&j.lstatSync(i).isSymbolicLink()){let c=j.realpathSync(i);if(this.checkBlocked(c))return{success:!1,error:"Access denied: symlink target is a blocked path"}}}catch{}switch(s){case"read":return this.readFile(i);case"write":return this.writeFile(i,n);case"write_binary":return this.writeBinaryFile(i,n);case"append":return this.appendFile(i,n);case"list":return this.listDir(i);case"info":return this.fileInfo(i);case"exists":return this.fileExists(i);case"move":return this.moveFile(i,o);case"copy":return this.copyFile(i,o);case"delete":return this.deleteFile(i);case"send":return this.sendFile(i);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write, write_binary, append, list, info, exists, move, copy, delete, send`}}}resolvePath(e){let t=process.env.HOME||process.env.USERPROFILE||"",s=e.startsWith("~")?e.replace("~",t):e;return ye.resolve(s)}checkBlocked(e){let t=e.toLowerCase().replace(/\\/g,"/"),s=(process.env.HOME||process.env.USERPROFILE||"").toLowerCase().replace(/\\/g,"/"),r=["/etc/shadow","/etc/passwd","/etc/sudoers","/proc/","/sys/","/dev/","c:/windows/system32","c:/windows/syswow64"],n=["/.ssh","/.aws","/.gnupg"],o=[".env"];if(r.some(a=>t.startsWith(a)||t===a.replace(/\/$/,"")))return{success:!1,error:"Access to system directories/files is blocked for security"};if(s&&n.some(a=>t.startsWith(s+a)))return{success:!1,error:"Access to sensitive user directories is blocked for security"};let i=ye.basename(e);return o.includes(i.toLowerCase())?{success:!1,error:"Access to sensitive files is blocked for security"}:null}readFile(e){try{let t=j.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file. Use action "list" instead.`};if(t.size>gr){let r=j.readFileSync(e,"utf-8").slice(0,gr);return{success:!0,data:{path:e,size:t.size,truncated:!0},display:`${e} (${t.size} bytes, truncated to ${gr}):
418
418
 
419
- ${r}`}}let s=F.readFileSync(e,"utf-8");return{success:!0,data:{path:e,size:t.size,content:s},display:s}}catch(t){return{success:!1,error:`Cannot read "${e}": ${t.message}`}}}writeFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for write action'};try{let s=ye.dirname(e);return F.mkdirSync(s,{recursive:!0}),F.writeFileSync(e,t,"utf-8"),{success:!0,data:{path:e,bytes:Buffer.byteLength(t)},display:`Written ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}appendFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for append action'};try{return F.appendFileSync(e,t,"utf-8"),{success:!0,data:{path:e,appendedBytes:Buffer.byteLength(t)},display:`Appended ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot append to "${e}": ${s.message}`}}}listDir(e){try{let s=F.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
420
- `);return{success:!0,data:{path:e,entries:s},display:r}}catch(t){return{success:!1,error:`Cannot list "${e}": ${t.message}`}}}fileInfo(e){try{let t=F.statSync(e),s={path:e,type:t.isDirectory()?"directory":t.isFile()?"file":"other",size:t.size,created:t.birthtime.toISOString(),modified:t.mtime.toISOString(),permissions:t.mode.toString(8)};return{success:!0,data:s,display:`${s.type}: ${e}
419
+ ${r}`}}let s=j.readFileSync(e,"utf-8");return{success:!0,data:{path:e,size:t.size,content:s},display:s}}catch(t){return{success:!1,error:`Cannot read "${e}": ${t.message}`}}}writeFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for write action'};try{let s=ye.dirname(e);return j.mkdirSync(s,{recursive:!0}),j.writeFileSync(e,t,"utf-8"),{success:!0,data:{path:e,bytes:Buffer.byteLength(t)},display:`Written ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}appendFile(e,t){if(t==null)return{success:!1,error:'Missing "content" for append action'};try{return j.appendFileSync(e,t,"utf-8"),{success:!0,data:{path:e,appendedBytes:Buffer.byteLength(t)},display:`Appended ${Buffer.byteLength(t)} bytes to ${e}`}}catch(s){return{success:!1,error:`Cannot append to "${e}": ${s.message}`}}}listDir(e){try{let s=j.readdirSync(e,{withFileTypes:!0}).map(n=>({name:n.name,type:n.isDirectory()?"dir":n.isSymbolicLink()?"symlink":"file"})),r=s.length===0?`${e}: (empty)`:s.map(n=>`${n.type==="dir"?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
420
+ `);return{success:!0,data:{path:e,entries:s},display:r}}catch(t){return{success:!1,error:`Cannot list "${e}": ${t.message}`}}}fileInfo(e){try{let t=j.statSync(e),s={path:e,type:t.isDirectory()?"directory":t.isFile()?"file":"other",size:t.size,created:t.birthtime.toISOString(),modified:t.mtime.toISOString(),permissions:t.mode.toString(8)};return{success:!0,data:s,display:`${s.type}: ${e}
421
421
  Size: ${t.size} bytes
422
- Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=F.existsSync(e);return{success:!0,data:{path:e,exists:t},display:t?`Yes, "${e}" exists`:`No, "${e}" does not exist`}}writeBinaryFile(e,t){if(!t)return{success:!1,error:'Missing "content" (base64-encoded) for write_binary action'};try{let s=ye.dirname(e);F.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return F.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=ye.dirname(s);return F.mkdirSync(n,{recursive:!0}),F.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return F.copyFileSync(e,s),F.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=ye.dirname(s);return F.mkdirSync(n,{recursive:!0}),F.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!F.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=F.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Qn)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Qn})`};let s=F.readFileSync(e),r=ye.basename(e),n=ye.extname(e).toLowerCase(),o=ra[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return F.existsSync(e)?F.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(F.unlinkSync(e),{success:!0,data:{path:e},display:`Deleted ${e}`}):{success:!1,error:`"${e}" does not exist`}}catch(t){return{success:!1,error:`Cannot delete "${e}": ${t.message}`}}}}});import{execSync as st}from"node:child_process";var rt,to=g(()=>{"use strict";P();rt=class extends k{static{d(this,"ClipboardSkill")}metadata={name:"clipboard",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=st("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=st("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=st("xclip -selection clipboard -o 2>/dev/null || xsel --clipboard --output",{encoding:"utf-8",timeout:5e3});break}return!e||e.trim().length===0?{success:!0,data:{content:""},display:"Clipboard is empty."}:{success:!0,data:{content:e},display:e.length>2e3?e.slice(0,2e3)+`
422
+ Modified: ${s.modified}`}}catch(t){return{success:!1,error:`Cannot stat "${e}": ${t.message}`}}}fileExists(e){let t=j.existsSync(e);return{success:!0,data:{path:e,exists:t},display:t?`Yes, "${e}" exists`:`No, "${e}" does not exist`}}writeBinaryFile(e,t){if(!t)return{success:!1,error:'Missing "content" (base64-encoded) for write_binary action'};try{let s=ye.dirname(e);j.mkdirSync(s,{recursive:!0});let r=Buffer.from(t,"base64");return j.writeFileSync(e,r),{success:!0,data:{path:e,bytes:r.length},display:`Written ${r.length} bytes (binary) to ${e}`}}catch(s){return{success:!1,error:`Cannot write "${e}": ${s.message}`}}}moveFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for move action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=ye.dirname(s);return j.mkdirSync(n,{recursive:!0}),j.renameSync(e,s),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch{try{return j.copyFileSync(e,s),j.unlinkSync(e),{success:!0,data:{from:e,to:s},display:`Moved ${e} \u2192 ${s}`}}catch(o){return{success:!1,error:`Cannot move "${e}" to "${s}": ${o.message}`}}}}copyFile(e,t){if(!t)return{success:!1,error:'Missing "destination" for copy action'};let s=this.resolvePath(t),r=this.checkBlocked(s);if(r)return r;try{let n=ye.dirname(s);return j.mkdirSync(n,{recursive:!0}),j.copyFileSync(e,s),{success:!0,data:{from:e,to:s},display:`Copied ${e} \u2192 ${s}`}}catch(n){return{success:!1,error:`Cannot copy "${e}" to "${s}": ${n.message}`}}}sendFile(e){try{if(!j.existsSync(e))return{success:!1,error:`"${e}" does not exist`};let t=j.statSync(e);if(t.isDirectory())return{success:!1,error:`"${e}" is a directory, not a file`};if(t.size>Qn)return{success:!1,error:`File too large to send (${t.size} bytes, max ${Qn})`};let s=j.readFileSync(e),r=ye.basename(e),n=ye.extname(e).toLowerCase(),o=ra[n]||"application/octet-stream",i={fileName:r,data:s,mimeType:o};return{success:!0,data:{path:e,size:t.size,fileName:r,mimeType:o},display:`Sending ${r} (${t.size} bytes)`,attachments:[i]}}catch(t){return{success:!1,error:`Cannot send "${e}": ${t.message}`}}}deleteFile(e){try{return j.existsSync(e)?j.statSync(e).isDirectory()?{success:!1,error:`"${e}" is a directory. Use shell for directory deletion.`}:(j.unlinkSync(e),{success:!0,data:{path:e},display:`Deleted ${e}`}):{success:!1,error:`"${e}" does not exist`}}catch(t){return{success:!1,error:`Cannot delete "${e}": ${t.message}`}}}}});import{execSync as st}from"node:child_process";var rt,to=g(()=>{"use strict";P();rt=class extends k{static{d(this,"ClipboardSkill")}metadata={name:"clipboard",description:"Read or write the system clipboard. Use when the user asks to copy something, paste from clipboard, or check what is in their clipboard.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["read","write"],description:'"read" to get clipboard contents, "write" to set clipboard contents'},text:{type:"string",description:"Text to copy to clipboard (required for write)"}},required:["action"]}};async execute(e,t){let s=e.action;switch(s){case"read":return this.readClipboard();case"write":return this.writeClipboard(e.text);default:return{success:!1,error:`Unknown action "${s}". Valid: read, write`}}}readClipboard(){try{let e;switch(process.platform){case"darwin":e=st("pbpaste",{encoding:"utf-8",timeout:5e3});break;case"win32":e=st("powershell -NoProfile -Command Get-Clipboard",{encoding:"utf-8",timeout:5e3}).replace(/\r\n$/,"");break;default:e=st("xclip -selection clipboard -o 2>/dev/null || xsel --clipboard --output",{encoding:"utf-8",timeout:5e3});break}return!e||e.trim().length===0?{success:!0,data:{content:""},display:"Clipboard is empty."}:{success:!0,data:{content:e},display:e.length>2e3?e.slice(0,2e3)+`
423
423
 
424
424
  [... truncated]`:e}}catch(e){return{success:!1,error:`Failed to read clipboard: ${e.message}`}}}writeClipboard(e){if(!e||typeof e!="string")return{success:!1,error:'Missing "text" for write action'};try{switch(process.platform){case"darwin":st("pbcopy",{input:e,timeout:5e3});break;case"win32":st('powershell -NoProfile -Command "$input | Set-Clipboard"',{input:e,timeout:5e3});break;default:st("xclip -selection clipboard 2>/dev/null || xsel --clipboard --input",{input:e,timeout:5e3});break}return{success:!0,data:{copiedLength:e.length},display:`Copied ${e.length} characters to clipboard.`}}catch(t){return{success:!1,error:`Failed to write clipboard: ${t.message}`}}}}});import{execSync as Bt}from"node:child_process";import so from"node:path";import na from"node:os";var nt,ro=g(()=>{"use strict";P();nt=class extends k{static{d(this,"ScreenshotSkill")}metadata={name:"screenshot",description:"Take a screenshot of the current screen and save it to a file. Use when the user asks to capture their screen or take a screenshot.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{path:{type:"string",description:"Output file path (optional, defaults to ~/Desktop/screenshot-<timestamp>.png)"}}}};async execute(e,t){let s=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),r=so.join(na.homedir(),"Desktop"),n=e.path||so.join(r,`screenshot-${s}.png`);try{switch(process.platform){case"darwin":Bt(`screencapture -x "${n}"`,{timeout:1e4});break;case"win32":Bt(`powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; $bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height); $graphics = [System.Drawing.Graphics]::FromImage($bitmap); $graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size); $bitmap.Save('${n.replace(/'/g,"''")}'); $graphics.Dispose(); $bitmap.Dispose()"`,{timeout:1e4});break;default:try{Bt(`scrot "${n}"`,{timeout:1e4})}catch{try{Bt(`import -window root "${n}"`,{timeout:1e4})}catch{Bt(`gnome-screenshot -f "${n}"`,{timeout:1e4})}}break}return{success:!0,data:{path:n},display:`Screenshot saved to ${n}`}}catch(o){return{success:!1,error:`Screenshot failed: ${o.message}`}}}}});import oa from"node:path";import ia from"node:os";var no,ot,oo=g(()=>{"use strict";P();no=5e4,ot=class extends k{static{d(this,"BrowserSkill")}browser=null;page=null;metadata={name:"browser",description:"Open web pages in a real browser (Puppeteer/Chromium). Renders JavaScript, so it works with SPAs and dynamic sites. Can also interact with pages: click buttons, fill forms, take screenshots. Use when http skill returns empty/broken content, or when you need to interact with a web page.",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["open","screenshot","click","type","evaluate","close"],description:"open = navigate to URL and return page text. screenshot = save screenshot of current page. click = click element by CSS selector. type = type text into input by CSS selector. evaluate = run JavaScript on the page. close = close the browser."},url:{type:"string",description:'URL to open (required for "open", optional for "screenshot")'},selector:{type:"string",description:'CSS selector for the element (required for "click" and "type")'},text:{type:"string",description:'Text to type (required for "type")'},script:{type:"string",description:'JavaScript code to evaluate (required for "evaluate")'},path:{type:"string",description:"File path to save screenshot (optional, defaults to Desktop)"}},required:["action"]}};async execute(e,t){let s=e.action;if(s==="close")return this.closeBrowser();let r=await this.loadPuppeteer();if(!r)return{success:!1,error:`Puppeteer is not installed. Run: npm install -g puppeteer
425
425
  Or add it to Alfred: npm install puppeteer`};switch(s){case"open":return this.openPage(r,e);case"screenshot":return this.screenshotPage(r,e);case"click":return this.clickElement(e);case"type":return this.typeText(e);case"evaluate":return this.evaluateScript(e);default:return{success:!1,error:`Unknown action "${s}". Valid: open, screenshot, click, type, evaluate, close`}}}async loadPuppeteer(){try{let e=await Function('return import("puppeteer")')();return this.resolvePuppeteerModule(e)}catch{try{let e=await Function('return import("puppeteer-core")')();return this.resolvePuppeteerModule(e)}catch{return null}}}resolvePuppeteerModule(e){let t=e;return typeof t.launch=="function"?t:t.default}async ensureBrowser(e){return this.browser&&this.browser.connected?this.browser:(this.browser=await e.launch({headless:!0,args:["--no-sandbox","--disable-setuid-sandbox","--disable-dev-shm-usage"]}),this.browser)}async ensurePage(e){let t=await this.ensureBrowser(e);return this.page||(this.page=await t.newPage(),await this.page.setViewport({width:1280,height:900})),this.page}async openPage(e,t){let s=t.url;if(!s)return{success:!1,error:'Missing "url" for open action'};let r=this.validateUrl(s);if(r)return{success:!1,error:r};try{let n=await this.ensurePage(e);await n.goto(s,{waitUntil:"networkidle2",timeout:3e4});let o=await n.title(),i=await n.evaluate(`
@@ -455,12 +455,12 @@ END:VCALENDAR\r
455
455
  `);return{success:!0,data:r,display:`${r.length} event(s):
456
456
  ${n}`}}catch(r){return{success:!1,error:`Failed to list events: ${r instanceof Error?r.message:String(r)}`}}}async createEvent(e){let t=e.title,s=e.start,r=e.end;if(!t)return{success:!1,error:'Missing required field "title"'};if(!s)return{success:!1,error:'Missing required field "start"'};if(!r)return{success:!1,error:'Missing required field "end"'};try{let n=await this.calendarProvider.createEvent({title:t,start:new Date(s),end:new Date(r),location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:n,display:`Event created: ${this.formatEvent(n)}`}}catch(n){return{success:!1,error:`Failed to create event: ${n instanceof Error?n.message:String(n)}`}}}async updateEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{let s=await this.calendarProvider.updateEvent(t,{title:e.title,start:e.start?new Date(e.start):void 0,end:e.end?new Date(e.end):void 0,location:e.location,description:e.description,allDay:e.all_day});return{success:!0,data:s,display:`Event updated: ${this.formatEvent(s)}`}}catch(s){return{success:!1,error:`Failed to update event: ${s instanceof Error?s.message:String(s)}`}}}async deleteEvent(e){let t=e.event_id;if(!t)return{success:!1,error:'Missing required field "event_id"'};try{return await this.calendarProvider.deleteEvent(t),{success:!0,data:{deleted:t},display:`Event "${t}" deleted.`}}catch(s){return{success:!1,error:`Failed to delete event: ${s instanceof Error?s.message:String(s)}`}}}async checkAvailability(e){let t=e.start,s=e.end;if(!t||!s)return{success:!1,error:'Missing required fields "start" and "end"'};try{let r=await this.calendarProvider.checkAvailability(new Date(t),new Date(s)),n=r.available?"Time slot is available.":`Time slot has ${r.conflicts.length} conflict(s):
457
457
  ${r.conflicts.map(o=>this.formatEvent(o)).join(`
458
- `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var mo=g(()=>{"use strict";Wt();yr();wr();Er();uo();po()});var at,ho=g(()=>{"use strict";P();at=class extends k{static{d(this,"CrossPlatformSkill")}users;linkTokens;adapters;metadata={name:"cross_platform",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s){super(),this.users=e,this.linkTokens=t,this.adapters=s}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
458
+ `)}`;return{success:!0,data:r,display:n}}catch(r){return{success:!1,error:`Failed to check availability: ${r instanceof Error?r.message:String(r)}`}}}formatEvent(e){let t={hour:"2-digit",minute:"2-digit",...this.timezone?{timeZone:this.timezone}:{}};if(e.allDay)return`- All day: ${e.title}${e.location?` @ ${e.location}`:""}`;let s=e.start.toLocaleTimeString("en-GB",t),r=e.end.toLocaleTimeString("en-GB",t);return`- ${s}-${r}: ${e.title}${e.location?` @ ${e.location}`:""}`}}});var mo=g(()=>{"use strict";Wt();yr();wr();Er();uo();po()});var at,ho=g(()=>{"use strict";P();at=class extends k{static{d(this,"CrossPlatformSkill")}users;linkTokens;adapters;findConversation;metadata={name:"cross_platform",description:"Manage cross-platform identity linking and messaging. Actions: link_start (generate a linking code on current platform), link_confirm (enter a code from another platform to link accounts), send_message (send a message to a linked platform), list_identities (show all linked platforms), unlink (remove a platform link).",riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["link_start","link_confirm","send_message","list_identities","unlink"],description:"The action to perform"},code:{type:"string",description:"The 6-digit linking code (for link_confirm)"},platform:{type:"string",description:"Target platform (for send_message or unlink)"},chat_id:{type:"string",description:"Target chat ID (for send_message)"},message:{type:"string",description:"Message text to send (for send_message)"}},required:["action"]}};constructor(e,t,s,r){super(),this.users=e,this.linkTokens=t,this.adapters=s,this.findConversation=r}resolveInternalId(e){return this.users.findOrCreate(e.platform,e.userId).id}async execute(e,t){let s=e.action;switch(s){case"link_start":return this.linkStart(t);case"link_confirm":return this.linkConfirm(e,t);case"send_message":return this.sendMessage(e,t);case"list_identities":return this.listIdentities(t);case"unlink":return this.unlink(e,t);default:return{success:!1,error:`Unknown action: ${s}`}}}failedConfirmAttempts=new Map;checkConfirmRateLimit(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);return s&&t<s.resetAt&&s.count>=5?`Too many failed attempts. Please wait ${Math.ceil((s.resetAt-t)/1e3)}s before trying again.`:null}recordFailedConfirm(e){let t=Date.now(),s=this.failedConfirmAttempts.get(e);s&&t<s.resetAt?s.count++:this.failedConfirmAttempts.set(e,{count:1,resetAt:t+5*6e4})}async linkStart(e){this.linkTokens.cleanup();let t=this.resolveInternalId(e);if(this.linkTokens.countRecentByUser(t,10)>=5)return{success:!1,error:"Too many linking codes generated recently. Please wait a few minutes."};let r=this.linkTokens.create(t,e.platform);return{success:!0,data:{code:r.code,expiresAt:r.expiresAt},display:`Your linking code is: **${r.code}**
459
459
 
460
460
  Enter this code on your other platform within 10 minutes using:
461
461
  "Link my account with code ${r.code}"`}}async linkConfirm(e,t){let s=e.code;if(!s)return{success:!1,error:'Missing required field "code"'};let r=this.resolveInternalId(t),n=this.checkConfirmRateLimit(r);if(n)return{success:!1,error:n};let o=this.linkTokens.findByCode(s.trim());if(!o)return this.recordFailedConfirm(r),{success:!1,error:"Invalid or expired linking code. Please generate a new one."};let i=o.userId;if(i===r)return{success:!1,error:"Cannot link an account to itself. Use the code on a different platform."};let a=this.users.getMasterUserId(i),c=this.users.getMasterUserId(r),u;if(a!==i?u=a:c!==r?u=c:u=i,a!==i&&c!==r&&a!==c){let h=this.users.getLinkedUsers(c);for(let E of h)this.users.setMasterUser(E.id,u)}i!==u&&this.users.setMasterUser(i,u),r!==u&&this.users.setMasterUser(r,u),this.linkTokens.consume(o.id);let p=this.users.findById(i),m=o.platform;return{success:!0,data:{masterUserId:u,linkedPlatform:m},display:`Account linked successfully! Your ${m} account (${p?.displayName??p?.username??"unknown"}) is now linked to this ${t.platform} account.
462
462
 
463
- Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e){let t=e.platform,s=e.chat_id,r=e.message;if(!t)return{success:!1,error:'Missing required field "platform"'};if(!s)return{success:!1,error:'Missing required field "chat_id"'};if(!r)return{success:!1,error:'Missing required field "message"'};let n=this.adapters.get(t);if(!n)return{success:!1,error:`Platform "${t}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};try{return{success:!0,data:{messageId:await n.sendMessage(s,r),platform:t,chatId:s},display:`Message sent to ${t} (chat ${s}).`}}catch(o){return{success:!1,error:`Failed to send message: ${o instanceof Error?o.message:String(o)}`}}}async listIdentities(e){let t=this.resolveInternalId(e),s=this.users.getMasterUserId(t),r=this.users.getLinkedUsers(s);if(r.length<=1)return{success:!0,data:{identities:r},display:`No linked accounts found. To link another platform, use:
463
+ Your memories, preferences, and context are now shared across platforms.`}}async sendMessage(e,t){let s=e.platform,r=e.chat_id,n=e.message;if(!s)return{success:!1,error:'Missing required field "platform"'};if(!n)return{success:!1,error:'Missing required field "message"'};let o=this.adapters.get(s);if(!o)return{success:!1,error:`Platform "${s}" is not connected. Available: ${[...this.adapters.keys()].join(", ")}`};if(!r||!/^[!0-9]/.test(r)){let i=this.resolveInternalId(t),a=this.users.getMasterUserId(i),u=this.users.getLinkedUsers(a).find(p=>p.platform===s);if(u&&this.findConversation){let p=this.findConversation(s,u.id);p&&(r=p.chatId)}!r&&u&&(r=u.platformUserId)}if(!r)return{success:!1,error:"Could not resolve chat_id for target platform. No linked account or conversation found."};try{return{success:!0,data:{messageId:await o.sendMessage(r,n),platform:s,chatId:r},display:`Message sent to ${s}.`}}catch(i){return{success:!1,error:`Failed to send message: ${i instanceof Error?i.message:String(i)}`}}}async listIdentities(e){let t=this.resolveInternalId(e),s=this.users.getMasterUserId(t),r=this.users.getLinkedUsers(s);if(r.length<=1)return{success:!0,data:{identities:r},display:`No linked accounts found. To link another platform, use:
464
464
  "Start linking my account" on the platform you want to link from, then enter the code on the other platform.`};let n=r.map(o=>{let i=o.id===t?" (current)":"",a=o.displayName??o.username??o.platformUserId;return`- **${o.platform}**: ${a}${i}`});return{success:!0,data:{identities:r.map(o=>({platform:o.platform,username:o.username,displayName:o.displayName}))},display:`Linked accounts:
465
465
  ${n.join(`
466
466
  `)}`}}async unlink(e,t){let s=e.platform;if(!s)return{success:!1,error:'Missing required field "platform"'};let r=this.resolveInternalId(t),n=this.users.getMasterUserId(r),i=this.users.getLinkedUsers(n).find(a=>a.platform===s&&a.id!==r);return i?(this.users.setMasterUser(i.id,i.id),{success:!0,data:{unlinkedPlatform:s,unlinkedUserId:i.id},display:`Unlinked ${s} account (${i.displayName??i.username??i.platformUserId}).`}):{success:!1,error:`No linked account found on platform "${s}".`}}}});var ct,fo=g(()=>{"use strict";P();ct=class extends k{static{d(this,"BackgroundTaskSkill")}taskRepo;metadata={name:"background_task",description:'Schedule, list, or cancel background tasks that run independently. Use "schedule" to queue a skill to execute in the background (user will be notified when done). Use "list" to see active/recent tasks. Use "cancel" to stop a pending or running task.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["schedule","list","cancel"],description:"The background task action to perform"},description:{type:"string",description:"Human-readable description of what the task does (for schedule)"},skill_name:{type:"string",description:"The skill to run in the background (for schedule)"},skill_input:{type:"object",description:"Input to pass to the skill (for schedule)"},task_id:{type:"string",description:"Task ID (for cancel)"}},required:["action"]}};constructor(e){super(),this.taskRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllTasks(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.taskRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"schedule":return this.scheduleTask(e,t);case"list":return this.listTasks(t);case"cancel":return this.cancelTask(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: schedule, list, cancel`}}}scheduleTask(e,t){let s=e.description,r=e.skill_name,n=e.skill_input;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "description" for schedule action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "skill_name" for schedule action'};let o=this.taskRepo.create(this.effectiveUserId(t),t.platform,t.chatId,s,r,JSON.stringify(n??{}));return{success:!0,data:{taskId:o.id,description:s,skillName:r,status:o.status},display:`Background task scheduled (${o.id}): "${s}" using skill "${r}". You'll be notified when it completes.`}}listTasks(e){let t=this.getAllTasks(e);if(t.length===0)return{success:!0,data:[],display:"No active or recent background tasks."};let s={pending:"\u23F3",running:"\u25B6\uFE0F",completed:"\u2705",failed:"\u274C"},r=t.map(n=>`- ${s[n.status]??"?"} ${n.id}: "${n.description}" [${n.status}] (${n.skillName})`);return{success:!0,data:t.map(n=>({taskId:n.id,description:n.description,status:n.status,skillName:n.skillName,createdAt:n.createdAt,completedAt:n.completedAt})),display:`Background tasks:
@@ -468,7 +468,7 @@ ${r.join(`
468
468
  `)}`}}cancelTask(e,t){let s=e.task_id;return!s||typeof s!="string"?{success:!1,error:'Missing required field "task_id" for cancel action'}:this.getAllTasks(t).some(i=>i.id===s)?this.taskRepo.cancel(s)?{success:!0,data:{taskId:s},display:`Background task "${s}" cancelled.`}:{success:!1,error:`Task "${s}" not found or already completed`}:{success:!1,error:`Task "${s}" not found or already completed`}}}});var lt,go=g(()=>{"use strict";P();lt=class extends k{static{d(this,"ScheduledTaskSkill")}actionRepo;metadata={name:"scheduled_task",description:'Create, list, enable, disable, or delete scheduled actions that run automatically on a recurring basis. Supports cron expressions (e.g. "0 9 * * *" for daily at 9 AM), intervals (in minutes), and one-time schedules. Each scheduled action executes a skill or sends a prompt to the LLM at the configured time.',riskLevel:"write",version:"1.0.0",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","list","enable","disable","delete"],description:"The scheduled task action to perform"},name:{type:"string",description:"Name for the scheduled action (for create)"},description:{type:"string",description:"What the scheduled action does (for create)"},schedule_type:{type:"string",enum:["cron","interval","once"],description:"Type of schedule: cron expression, interval in minutes, or one-time ISO date (for create)"},schedule_value:{type:"string",description:"Schedule value: cron expression, minutes as string, or ISO date (for create)"},skill_name:{type:"string",description:"The skill to execute on schedule (for create)"},skill_input:{type:"object",description:"Input to pass to the skill (for create)"},prompt_template:{type:"string",description:"Optional LLM prompt to run instead of a skill (for create)"},action_id:{type:"string",description:"Scheduled action ID (for enable, disable, delete)"}},required:["action"]}};constructor(e){super(),this.actionRepo=e}effectiveUserId(e){return e.masterUserId??e.userId}allUserIds(e){let t=new Set;if(t.add(this.effectiveUserId(e)),t.add(e.userId),e.linkedPlatformUserIds)for(let s of e.linkedPlatformUserIds)t.add(s);return[...t]}getAllActions(e){let t=new Set,s=[];for(let r of this.allUserIds(e))for(let n of this.actionRepo.getByUser(r))t.has(n.id)||(t.add(n.id),s.push(n));return s}async execute(e,t){let s=e.action;switch(s){case"create":return this.createAction(e,t);case"list":return this.listActions(t);case"enable":return this.toggleAction(e,!0,t);case"disable":return this.toggleAction(e,!1,t);case"delete":return this.deleteAction(e,t);default:return{success:!1,error:`Unknown action: "${String(s)}". Valid actions: create, list, enable, disable, delete`}}}createAction(e,t){let s=e.name,r=e.description,n=e.schedule_type,o=e.schedule_value,i=e.skill_name,a=e.skill_input,c=e.prompt_template;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "name" for create action'};if(!r||typeof r!="string")return{success:!1,error:'Missing required field "description" for create action'};if(!n||!["cron","interval","once"].includes(n))return{success:!1,error:'Missing or invalid "schedule_type". Must be "cron", "interval", or "once"'};if(!o||typeof o!="string")return{success:!1,error:'Missing required field "schedule_value" for create action'};if(!i||typeof i!="string")return{success:!1,error:'Missing required field "skill_name" for create action'};if(n==="interval"){let m=parseInt(o,10);if(isNaN(m)||m<=0)return{success:!1,error:"For interval schedule, value must be a positive number of minutes"}}if(n==="cron"&&o.trim().split(/\s+/).length!==5)return{success:!1,error:"Cron expression must have 5 fields: minute hour dayOfMonth month dayOfWeek"};if(n==="once"){let m=new Date(o);if(isNaN(m.getTime()))return{success:!1,error:"For once schedule, value must be a valid ISO date string"};if(m.getTime()<=Date.now())return{success:!1,error:"The scheduled time is in the past. Please specify a future time."}}let u=this.actionRepo.create({userId:this.effectiveUserId(t),platform:t.platform,chatId:t.chatId,name:s,description:r,scheduleType:n,scheduleValue:o,skillName:i,skillInput:JSON.stringify(a??{}),promptTemplate:c}),p=n==="cron"?`cron: ${o}`:n==="interval"?`every ${o} minutes`:`once at ${o}`;return{success:!0,data:{actionId:u.id,name:s,scheduleType:n,scheduleValue:o,skillName:i},display:`Scheduled action created (${u.id}): "${s}" \u2014 ${p}, running "${i}"${u.nextRunAt?`. Next run: ${u.nextRunAt}`:""}`}}listActions(e){let t=this.getAllActions(e);if(t.length===0)return{success:!0,data:[],display:"No scheduled actions."};let s=t.map(r=>{let n=r.enabled?"\u2705":"\u23F8\uFE0F",o=r.scheduleType==="cron"?`cron: ${r.scheduleValue}`:r.scheduleType==="interval"?`every ${r.scheduleValue} min`:`once: ${r.scheduleValue}`,i=r.nextRunAt?` | next: ${r.nextRunAt}`:"";return`- ${n} ${r.id}: "${r.name}" [${o}] \u2192 ${r.skillName}${i}`});return{success:!0,data:t.map(r=>({actionId:r.id,name:r.name,scheduleType:r.scheduleType,scheduleValue:r.scheduleValue,skillName:r.skillName,enabled:r.enabled,nextRunAt:r.nextRunAt,lastRunAt:r.lastRunAt})),display:`Scheduled actions:
469
469
  ${s.join(`
470
470
  `)}`}}toggleAction(e,t,s){let r=e.action_id;if(!r||typeof r!="string")return{success:!1,error:`Missing required field "action_id" for ${t?"enable":"disable"} action`};let n=this.actionRepo.findById(r),o=this.allUserIds(s);return!n||!o.includes(n.userId)?{success:!1,error:`Scheduled action "${r}" not found`}:this.actionRepo.setEnabled(r,t)?{success:!0,data:{actionId:r,enabled:t},display:`Scheduled action "${r}" ${t?"enabled":"disabled"}.`}:{success:!1,error:`Scheduled action "${r}" not found`}}deleteAction(e,t){let s=e.action_id;if(!s||typeof s!="string")return{success:!1,error:'Missing required field "action_id" for delete action'};let r=this.actionRepo.findById(s),n=this.allUserIds(t);return!r||!n.includes(r.userId)?{success:!1,error:`Scheduled action "${s}" not found`}:this.actionRepo.delete(s)?{success:!0,data:{actionId:s},display:`Scheduled action "${s}" deleted.`}:{success:!1,error:`Scheduled action "${s}" not found`}}}});var Re,Tr=g(()=>{"use strict";Re=class{static{d(this,"MCPClient")}serverName;config;logger;client;transport;connected=!1;constructor(e,t,s){this.serverName=e,this.config=t,this.logger=s}async connect(){try{let{Client:e}=await import("@modelcontextprotocol/sdk/client/index.js");if(this.client=new e({name:`alfred-${this.serverName}`,version:"1.0.0"},{capabilities:{}}),this.config.command){let{StdioClientTransport:t}=await import("@modelcontextprotocol/sdk/client/stdio.js"),s={PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:process.env.NODE_ENV??"",SYSTEMROOT:process.env.SYSTEMROOT??""};if(this.config.env)for(let[r,n]of Object.entries(this.config.env))s[r]=n.replace(/\$\{(\w+)\}/g,(o,i)=>process.env[i]??"");this.transport=new t({command:this.config.command,args:this.config.args??[],env:s})}else if(this.config.url){let{SSEClientTransport:t}=await import("@modelcontextprotocol/sdk/client/sse.js");this.transport=new t(new URL(this.config.url))}else throw new Error(`MCP server "${this.serverName}": must specify either command or url`);await this.client.connect(this.transport),this.connected=!0,this.logger.info({server:this.serverName},"MCP server connected")}catch(e){throw this.logger.error({server:this.serverName,err:e},"Failed to connect MCP server"),e}}async listTools(){if(!this.connected||!this.client)return[];try{return((await this.client.listTools()).tools??[]).map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema??{type:"object",properties:{}}}))}catch(e){return this.logger.error({server:this.serverName,err:e},"Failed to list MCP tools"),[]}}async callTool(e,t){if(!this.connected||!this.client)return{content:"MCP server not connected",isError:!0};try{let s=await this.client.callTool({name:e,arguments:t});return{content:(s.content??[]).map(n=>n.text??JSON.stringify(n)).join(`
471
- `),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var aa,Le,br=g(()=>{"use strict";P();aa=["read","write","destructive","admin"],Le=class extends k{static{d(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&aa.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var Xt,yo=g(()=>{"use strict";Tr();br();Xt=class{static{d(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new Re(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 Le(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 wo=g(()=>{"use strict";Tr();br();yo()});import{spawn as ca}from"node:child_process";import dt from"node:fs";import _r from"node:path";import la from"node:os";import da from"node:crypto";var Me,Sr=g(()=>{"use strict";Me=class{static{d(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=_r.join(la.tmpdir(),`alfred-sandbox-${da.randomUUID()}`);dt.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=_r.join(n,`script.${o}`);dt.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],u=Date.now();return await new Promise(p=>{let m=ca(a,c,{cwd:n,timeout:r,env:{PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n},stdio:["pipe","pipe","pipe"]}),h="",E="";m.stdout.on("data",f=>{h+=f.toString()}),m.stderr.on("data",f=>{E+=f.toString()}),m.on("close",f=>{let T=Date.now()-u,_=[];try{let I=dt.readdirSync(n).filter(v=>!v.startsWith("script."));for(let v of I){let M=_r.join(n,v),A=dt.statSync(M);if(A.isFile()&&A.size<1e7){let D=dt.readFileSync(M),C=v.endsWith(".png")?"image/png":v.endsWith(".jpg")||v.endsWith(".jpeg")?"image/jpeg":v.endsWith(".svg")?"image/svg+xml":v.endsWith(".csv")?"text/csv":v.endsWith(".json")?"application/json":"application/octet-stream";_.push({name:v,data:D,mimeType:C})}}}catch{}p({stdout:h.slice(0,5e4),stderr:E.slice(0,1e4),exitCode:f??1,files:_.length>0?_:void 0,durationMs:T})}),m.on("error",f=>{p({stdout:"",stderr:f.message,exitCode:1,durationMs:Date.now()-u})}),m.stdin.end()})}finally{try{dt.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var Ht,Eo=g(()=>{"use strict";P();Sr();Ht=class extends k{static{d(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating charts, or testing code snippets. Code runs in an isolated temp directory with a timeout.",riskLevel:"destructive",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data to pass (available as DATA env var or stdin)"},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new Me;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code"'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};let a=r;s==="run_with_data"&&o&&(n==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(o)};
471
+ `),isError:s.isError}}catch(s){return{content:`MCP tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}async disconnect(){if(this.transport)try{await this.transport.close?.()}catch{}this.connected=!1,this.logger.info({server:this.serverName},"MCP server disconnected")}}});var aa,Le,br=g(()=>{"use strict";P();aa=["read","write","destructive","admin"],Le=class extends k{static{d(this,"MCPSkillAdapter")}client;serverName;toolName;metadata;constructor(e,t,s,r,n,o){super(),this.client=e,this.serverName=t,this.toolName=s;let i=o&&aa.includes(o)?o:"write";this.metadata={name:`mcp__${t}__${s}`,description:`[MCP/${t}] ${r||s}`,riskLevel:i,version:"1.0.0",inputSchema:n}}async execute(e,t){let s=await this.client.callTool(this.toolName,e);return{success:s.isError!==!0,data:s.content,display:s.content,error:s.isError===!0?s.content:void 0}}}});var Xt,yo=g(()=>{"use strict";Tr();br();Xt=class{static{d(this,"MCPManager")}logger;clients=[];skills=[];constructor(e){this.logger=e}async initialize(e){for(let t of e.servers)try{let s=new Re(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 Le(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 wo=g(()=>{"use strict";Tr();br();yo()});import{spawn as ca}from"node:child_process";import dt from"node:fs";import _r from"node:path";import la from"node:os";import da from"node:crypto";var Me,Sr=g(()=>{"use strict";Me=class{static{d(this,"CodeExecutor")}async execute(e,t,s){let r=Math.min(s?.timeout??3e4,12e4),n=_r.join(la.tmpdir(),`alfred-sandbox-${da.randomUUID()}`);dt.mkdirSync(n,{recursive:!0});try{let o=t==="javascript"?"js":"py",i=_r.join(n,`script.${o}`);dt.writeFileSync(i,e);let a=t==="javascript"?"node":process.platform==="win32"?"python":"python3",c=[i],u=Date.now();return await new Promise(p=>{let m=ca(a,c,{cwd:n,timeout:r,env:{PATH:process.env.PATH??"",HOME:process.env.HOME??process.env.USERPROFILE??"",LANG:process.env.LANG??"en_US.UTF-8",NODE_ENV:"sandbox",PYTHONDONTWRITEBYTECODE:"1",...s?.env,TMPDIR:n,TEMP:n,TMP:n},stdio:["pipe","pipe","pipe"]}),h="",E="";m.stdout.on("data",f=>{h+=f.toString()}),m.stderr.on("data",f=>{E+=f.toString()}),m.on("close",f=>{let T=Date.now()-u,_=[];try{let I=dt.readdirSync(n).filter(v=>!v.startsWith("script."));for(let v of I){let N=_r.join(n,v),A=dt.statSync(N);if(A.isFile()&&A.size<1e7){let D=dt.readFileSync(N),C=v.endsWith(".png")?"image/png":v.endsWith(".jpg")||v.endsWith(".jpeg")?"image/jpeg":v.endsWith(".svg")?"image/svg+xml":v.endsWith(".csv")?"text/csv":v.endsWith(".json")?"application/json":"application/octet-stream";_.push({name:v,data:D,mimeType:C})}}}catch{}p({stdout:h.slice(0,5e4),stderr:E.slice(0,1e4),exitCode:f??1,files:_.length>0?_:void 0,durationMs:T})}),m.on("error",f=>{p({stdout:"",stderr:f.message,exitCode:1,durationMs:Date.now()-u})}),m.stdin.end()})}finally{try{dt.rmSync(n,{recursive:!0,force:!0})}catch{}}}}});var Ht,Eo=g(()=>{"use strict";P();Sr();Ht=class extends k{static{d(this,"CodeExecutionSkill")}metadata={name:"code_sandbox",description:"Execute code in a sandboxed environment. Supports JavaScript (Node.js) and Python. Use for calculations, data processing, generating charts, or testing code snippets. Code runs in an isolated temp directory with a timeout.",riskLevel:"destructive",version:"1.0.0",timeoutMs:12e4,inputSchema:{type:"object",properties:{action:{type:"string",enum:["run","run_with_data"],description:"Action to perform"},code:{type:"string",description:"Code to execute"},language:{type:"string",enum:["javascript","python"],description:"Programming language"},data:{type:"string",description:"Input data to pass (available as DATA env var or stdin)"},timeout:{type:"number",description:"Timeout in ms (max 120000)"}},required:["action","code","language"]}};executor=new Me;allowedLanguages;maxTimeout;constructor(e){super(),this.allowedLanguages=new Set(e?.allowedLanguages??["javascript","python"]),this.maxTimeout=e?.maxTimeoutMs??12e4}async execute(e,t){let s=e.action,r=e.code,n=e.language,o=e.data,i=Math.min(e.timeout??3e4,this.maxTimeout);if(!r)return{success:!1,error:'Missing required field "code"'};if(!n)return{success:!1,error:'Missing required field "language"'};if(!this.allowedLanguages.has(n))return{success:!1,error:`Language "${n}" is not allowed. Allowed: ${[...this.allowedLanguages].join(", ")}`};let a=r;s==="run_with_data"&&o&&(n==="javascript"?a=`const INPUT_DATA = ${JSON.stringify(o)};
472
472
  ${r}`:a=`INPUT_DATA = ${JSON.stringify(o)}
473
473
  ${r}`);let c=await this.executor.execute(a,n,{timeout:i}),u=c.files?.map(m=>({fileName:m.name,data:m.data,mimeType:m.mimeType})),p=[c.stdout?`Output:
474
474
  ${c.stdout}`:"",c.stderr?`Errors:
@@ -488,7 +488,7 @@ ${a}`}}list(e,t){let s=e.limit||50,r=this.allUserIds(t),n=new Set,o=[];for(let c
488
488
  `);return{success:!0,data:i,display:`${i.length} document(s):
489
489
  ${a}`}}deleteDoc(e){let t=e.document_id;if(!t||typeof t!="string")return{success:!1,error:'Missing required field "document_id" for delete action'};let s=this.docRepo.getDocument(t);return s?(this.docRepo.deleteDocument(t),{success:!0,data:{documentId:t},display:`Document "${s.filename}" deleted.`}):{success:!1,error:`Document "${t}" not found`}}}});var pt,_o=g(()=>{"use strict";P();pt=class extends k{static{d(this,"TTSSkill")}synthesizer;metadata={name:"text_to_speech",description:"Send a voice/audio message to the user. You MUST use this tool whenever the user asks you to respond as a voice message, speak, or reply with audio. Pass the full response text \u2014 it will be converted to speech and delivered as a playable voice message.",riskLevel:"read",version:"1.0.0",inputSchema:{type:"object",properties:{text:{type:"string",description:"The text to convert to speech"}},required:["text"]}};constructor(e){super(),this.synthesizer=e}async execute(e,t){let s=e.text;if(!s)return{success:!1,error:"No text provided for speech synthesis."};try{return{success:!0,display:"Voice message sent.",attachments:[{fileName:"voice.ogg",data:await this.synthesizer.synthesize(s),mimeType:"audio/ogg"}]}}catch(r){return{success:!1,error:`Speech synthesis failed: ${r instanceof Error?r.message:String(r)}`}}}}});var vs={};se(vs,{ActivityTracker:()=>$e,BackgroundTaskSkill:()=>ct,BrowserSkill:()=>ot,CalculatorSkill:()=>Xe,CalendarProvider:()=>oe,CalendarSkill:()=>Ae,ClipboardSkill:()=>rt,CodeExecutionSkill:()=>Ht,CodeExecutor:()=>Me,CrossPlatformSkill:()=>at,DelegateSkill:()=>Ze,DocumentSkill:()=>ut,EmailSkill:()=>Qe,FileSkill:()=>tt,HttpSkill:()=>et,MCPClient:()=>Re,MCPManager:()=>Xt,MCPSkillAdapter:()=>Le,MemorySkill:()=>Je,NoteSkill:()=>Ve,PluginLoader:()=>bs,ProfileSkill:()=>it,ReminderSkill:()=>Ke,ScheduledTaskSkill:()=>lt,ScreenshotSkill:()=>nt,ShellSkill:()=>Ye,Skill:()=>k,SkillRegistry:()=>We,SkillSandbox:()=>ze,SystemInfoSkill:()=>He,TTSSkill:()=>pt,WeatherSkill:()=>Ge,WebSearchSkill:()=>qe,createCalendarProvider:()=>zt});var qt=g(()=>{"use strict";P();Cn();Un();hr();Pn();Fn();jn();Bn();Wn();zn();Xn();Kn();Vn();Gn();Yn();Zn();eo();to();ro();oo();io();mo();ho();fo();go();wo();To();bo();_o()});var Kt,kr=g(()=>{"use strict";Kt=class{static{d(this,"ConversationManager")}conversations;constructor(e){this.conversations=e}getOrCreateConversation(e,t,s){let r=this.conversations.findByPlatformChat(e,t);return r?(this.conversations.updateTimestamp(r.id),r):this.conversations.create(e,t,s)}addMessage(e,t,s,r){return this.conversations.addMessage(e,t,s,r)}getHistory(e,t=20){return this.conversations.getMessages(e,t)}}});import So from"node:fs";import ko from"node:path";var ua,vo,pa,ma,ha,Vt,vr=g(()=>{"use strict";pr();ua=15*60*1e3,vo=50,pa=2,ma=.85,ha=1e5,Vt=class{static{d(this,"MessagePipeline")}promptBuilder;llm;conversationManager;users;logger;skillRegistry;skillSandbox;securityManager;memoryRepo;speechTranscriber;inboxPath;embeddingService;activeLearning;memoryRetriever;activeAgents=new Map;agentIdCounter=0;constructor(e){this.llm=e.llm,this.conversationManager=e.conversationManager,this.users=e.users,this.logger=e.logger,this.skillRegistry=e.skillRegistry,this.skillSandbox=e.skillSandbox,this.securityManager=e.securityManager,this.memoryRepo=e.memoryRepo,this.speechTranscriber=e.speechTranscriber,this.inboxPath=e.inboxPath,this.embeddingService=e.embeddingService,this.activeLearning=e.activeLearning,this.memoryRetriever=e.memoryRetriever,this.promptBuilder=new Ut}async process(e,t){let s=Date.now();this.logger.info({platform:e.platform,userId:e.userId,chatId:e.chatId},"Processing message");try{let r=this.users.findOrCreate(e.platform,e.userId,e.userName,e.displayName),n="getMasterUserId"in this.users?this.users.getMasterUserId(r.id):r.id,o;"getLinkedUsers"in this.users&&(o=this.users.getLinkedUsers(n).map(z=>z.platformUserId));let i=this.conversationManager.getOrCreateConversation(e.platform,e.chatId,r.id),a=this.conversationManager.getHistory(i.id,200);this.conversationManager.addMessage(i.id,"user",e.text);let c,u=this.isSyntheticLabel(e.text),p=e.attachments?.some(O=>O.type==="audio")??!1,m=u&&!p;if(this.memoryRetriever&&e.text&&!m)try{c=await this.memoryRetriever.retrieve(n,e.text,15,o)}catch(O){this.logger.debug({err:O},"Hybrid memory retrieval failed")}if(!c&&this.memoryRepo&&!m)try{let O=[n,...(o??[]).filter(z=>z!==n)];if(this.embeddingService&&e.text&&this.llm.supportsEmbeddings()){let z=new Set;c=[];for(let U of O)for(let X of await this.embeddingService.semanticSearch(U,e.text,10))z.has(X.key)||(z.add(X.key),c.push(X));for(let U of O)for(let X of this.memoryRepo.getRecentForPrompt(U,5))z.has(X.key)||(z.add(X.key),c.push(X))}else{let z=new Set;c=[];for(let U of O)for(let X of this.memoryRepo.getRecentForPrompt(U,20))z.has(X.key)||(z.add(X.key),c.push(X))}}catch(O){this.logger.debug({err:O},"Memory loading failed")}let h;try{"getProfile"in this.users&&(h=this.users.getProfile(n),h&&!h.displayName&&(h.displayName=r.displayName??r.username))}catch(O){this.logger.debug({err:O},"Profile loading failed")}let E=h?.timezone||Intl.DateTimeFormat().resolvedOptions().timeZone,f=this.skillRegistry?this.skillRegistry.getAll().map(O=>O.metadata):void 0,T=f?this.promptBuilder.buildTools(f):void 0,_=this.promptBuilder.buildSystemPrompt({memories:c,skills:f,userProfile:h}),I=this.buildActiveAgentStatus();I&&(_+=`
490
490
 
491
- `+I);let v=this.promptBuilder.buildMessages(a),M=this.collapseRepeatedToolErrors(v),A=await this.buildUserContent(e,t);M.push({role:"user",content:A});let D=this.trimToContextWindow(_,M),C,J=0,Ue=Date.now(),ie="",H=0,N=[];for(t?.("Thinking...");C=await this.llm.complete({messages:D,system:_,tools:T&&T.length>0?T:void 0}),!(!C.toolCalls||C.toolCalls.length===0);){let O=Date.now()-Ue;if(O>=ua){let ce=Math.round(O/6e4);this.logger.warn({iteration:J,elapsedMin:ce,pendingToolCalls:C.toolCalls.length},"Tool loop timeout reached"),C=await this.abortToolLoop(D,C,i.id,_,`Das Zeitlimit von ${ce} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(J>=vo){this.logger.warn({iteration:J,pendingToolCalls:C.toolCalls.length},"Tool loop iteration cap reached"),C=await this.abortToolLoop(D,C,i.id,_,`Das Iterationslimit von ${vo} Tool-Aufrufen wurde erreicht.`);break}J++,this.logger.info({iteration:J,toolCalls:C.toolCalls.length},"Processing tool calls");let z=[];C.content&&z.push({type:"text",text:C.content});for(let ce of C.toolCalls)z.push({type:"tool_use",id:ce.id,name:ce.name,input:ce.input});D.push({role:"assistant",content:z});let U=await this.executeToolCallsParallel(C.toolCalls,{userId:e.userId,masterUserId:n,linkedPlatformUserIds:o,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:E},t),X=U.blocks;U.attachments.length>0&&N.push(...U.attachments),this.conversationManager.addMessage(i.id,"assistant",C.content??"",JSON.stringify(C.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(X));let Z=this.buildErrorSignature(X);if(Z){if(Z===ie?H++:(H=1,ie=Z),H>=pa){this.logger.warn({iteration:J,consecutiveErrors:H,errorSignature:Z},"Tool loop aborted: same error repeated consecutively"),C=await this.abortToolLoop(D,C,i.id,_,`Der gleiche Tool-Fehler ist ${H}x hintereinander aufgetreten: "${ie.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else H=0,ie="";D.push({role:"user",content:X}),t?.("Thinking...")}let B=C.content;if(!B)for(let O=D.length-1;O>=0;O--){let z=D[O];if(z.role==="assistant"&&Array.isArray(z.content)){let U=z.content.find(X=>X.type==="text");if(U&&"text"in U&&U.text){B=U.text;break}}}B||(B="(no response)"),this.conversationManager.addMessage(i.id,"assistant",B),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,B);let pe=Date.now()-s;return this.logger.info({duration:pe,tokens:C.usage,stopReason:C.stopReason,toolIterations:J},"Message processed"),{text:B,attachments:N.length>0?N:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let a=[];t.content&&a.push({type:"text",text:t.content});for(let c of t.toolCalls)a.push({type:"tool_use",id:c.id,name:c.name,input:c.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));return e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i)),e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r})}buildErrorSignature(e){let t=[];for(let s of e)s.type==="tool_result"&&s.is_error&&t.push(s.content);return t.length>0?t.join("|"):""}collapseRepeatedToolErrors(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=s+1<e.length?e[s+1]:null;if(n&&n.role==="user"&&Array.isArray(n.content)&&n.content.every(o=>o.type==="tool_result"&&o.is_error)){let o=this.toolPairSignature(r,n),i=1,a=s+2;for(;a+1<e.length;){let c=e[a],u=e[a+1];if(c.role==="assistant"&&u?.role==="user"&&this.toolPairSignature(c,u)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"assistant",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=d((a,c)=>{let u=c.content;if(c.attachments&&c.attachments.length>0){r.push(...c.attachments);let p=c.attachments.map(m=>m.fileName).join(", ");u+=`
491
+ `+I);let v=this.promptBuilder.buildMessages(a),N=this.collapseRepeatedToolErrors(v),A=await this.buildUserContent(e,t);N.push({role:"user",content:A});let D=this.trimToContextWindow(_,N),C,J=0,Ue=Date.now(),ie="",H=0,R=[];for(t?.("Thinking...");C=await this.llm.complete({messages:D,system:_,tools:T&&T.length>0?T:void 0}),!(!C.toolCalls||C.toolCalls.length===0);){let O=Date.now()-Ue;if(O>=ua){let ce=Math.round(O/6e4);this.logger.warn({iteration:J,elapsedMin:ce,pendingToolCalls:C.toolCalls.length},"Tool loop timeout reached"),C=await this.abortToolLoop(D,C,i.id,_,`Das Zeitlimit von ${ce} Minuten f\xFCr Tool-Aufrufe wurde erreicht.`);break}if(J>=vo){this.logger.warn({iteration:J,pendingToolCalls:C.toolCalls.length},"Tool loop iteration cap reached"),C=await this.abortToolLoop(D,C,i.id,_,`Das Iterationslimit von ${vo} Tool-Aufrufen wurde erreicht.`);break}J++,this.logger.info({iteration:J,toolCalls:C.toolCalls.length},"Processing tool calls");let z=[];C.content&&z.push({type:"text",text:C.content});for(let ce of C.toolCalls)z.push({type:"tool_use",id:ce.id,name:ce.name,input:ce.input});D.push({role:"assistant",content:z});let U=await this.executeToolCallsParallel(C.toolCalls,{userId:e.userId,masterUserId:n,linkedPlatformUserIds:o,chatId:e.chatId,chatType:e.chatType,platform:e.platform,conversationId:i.id,timezone:E},t),X=U.blocks;U.attachments.length>0&&R.push(...U.attachments),this.conversationManager.addMessage(i.id,"assistant",C.content??"",JSON.stringify(C.toolCalls)),this.conversationManager.addMessage(i.id,"user","",JSON.stringify(X));let Z=this.buildErrorSignature(X);if(Z){if(Z===ie?H++:(H=1,ie=Z),H>=pa){this.logger.warn({iteration:J,consecutiveErrors:H,errorSignature:Z},"Tool loop aborted: same error repeated consecutively"),C=await this.abortToolLoop(D,C,i.id,_,`Der gleiche Tool-Fehler ist ${H}x hintereinander aufgetreten: "${ie.slice(0,200)}". Erkl\xE4re dem User kurz was nicht funktioniert hat und schlage eine Alternative vor.`,!0);break}}else H=0,ie="";D.push({role:"user",content:X}),t?.("Thinking...")}let F=C.content;if(!F)for(let O=D.length-1;O>=0;O--){let z=D[O];if(z.role==="assistant"&&Array.isArray(z.content)){let U=z.content.find(X=>X.type==="text");if(U&&"text"in U&&U.text){F=U.text;break}}}F||(F="(no response)"),this.conversationManager.addMessage(i.id,"assistant",F),this.activeLearning&&this.activeLearning.onMessageProcessed(n,e.text,F);let pe=Date.now()-s;return this.logger.info({duration:pe,tokens:C.usage,stopReason:C.stopReason,toolIterations:J},"Message processed"),{text:F,attachments:R.length>0?R:void 0}}catch(r){throw this.logger.error({err:r},"Failed to process message"),r}}async abortToolLoop(e,t,s,r,n,o=!1){if(!o){let a=[];t.content&&a.push({type:"text",text:t.content});for(let c of t.toolCalls)a.push({type:"tool_use",id:c.id,name:c.name,input:c.input});e.push({role:"assistant",content:a})}let i=t.toolCalls.map(a=>({type:"tool_result",tool_use_id:a.id,content:`Error: tool loop aborted \u2014 ${n}`,is_error:!0}));return e.push({role:"user",content:i}),o||this.conversationManager.addMessage(s,"assistant",t.content??"",JSON.stringify(t.toolCalls)),this.conversationManager.addMessage(s,"user","",JSON.stringify(i)),e.push({role:"user",content:`[System: ${n} Fasse dem User kurz zusammen was du bisher geschafft hast und was noch offen ist.]`}),await this.llm.complete({messages:e,system:r})}buildErrorSignature(e){let t=[];for(let s of e)s.type==="tool_result"&&s.is_error&&t.push(s.content);return t.length>0?t.join("|"):""}collapseRepeatedToolErrors(e){let t=[],s=0;for(;s<e.length;){let r=e[s];if(r.role==="assistant"&&Array.isArray(r.content)&&r.content.some(n=>n.type==="tool_use")){let n=s+1<e.length?e[s+1]:null;if(n&&n.role==="user"&&Array.isArray(n.content)&&n.content.every(o=>o.type==="tool_result"&&o.is_error)){let o=this.toolPairSignature(r,n),i=1,a=s+2;for(;a+1<e.length;){let c=e[a],u=e[a+1];if(c.role==="assistant"&&u?.role==="user"&&this.toolPairSignature(c,u)===o)i++,a+=2;else break}if(i>1){t.push(r),t.push(n),t.push({role:"assistant",content:`[System: The above tool error repeated ${i} times with identical input. The loop was aborted.]`}),s=a;continue}}}t.push(r),s++}return t}toolPairSignature(e,t){let s=Array.isArray(e.content)?e.content.filter(n=>n.type==="tool_use").map(n=>`${n.name}:${JSON.stringify(n.input)}`).join(","):"",r=Array.isArray(t.content)?t.content.filter(n=>n.type==="tool_result").map(n=>n.content).join(","):"";return`${s}|${r}`}async executeToolCallsParallel(e,t,s){let r=[],n=d((a,c)=>{let u=c.content;if(c.attachments&&c.attachments.length>0){r.push(...c.attachments);let p=c.attachments.map(m=>m.fileName).join(", ");u+=`
492
492
 
493
493
  [${c.attachments.length} Datei(en) werden dem User gesendet: ${p}]`}return{type:"tool_result",tool_use_id:a.id,content:u,is_error:c.isError}},"buildBlock");if(e.length===1){let a=e[0],c=this.getToolLabel(a.name,a.input);s?.(c);let u=await this.executeToolCall(a,t,s);return{blocks:[n(a,u)],attachments:r}}s?.(`Running ${e.length} tools in parallel...`);let o=await Promise.allSettled(e.map(a=>this.executeToolCall(a,t,s)));return{blocks:e.map((a,c)=>{let u=o[c];return u.status==="fulfilled"?n(a,u.value):{type:"tool_result",tool_use_id:a.id,content:`Tool execution failed: ${u.reason}`,is_error:!0}}),attachments:r}}async executeToolCall(e,t,s){let r=this.skillRegistry?.get(e.name);if(!r)return this.logger.warn({tool:e.name},"Unknown skill requested"),{content:`Error: Unknown tool "${e.name}"`,isError:!0};if(this.securityManager){let n=this.securityManager.evaluate({userId:t.userId,action:e.name,riskLevel:r.metadata.riskLevel,platform:t.platform,chatId:t.chatId,chatType:t.chatType});if(!n.allowed)return this.logger.warn({tool:e.name,reason:n.reason,rule:n.matchedRule?.id},"Skill execution denied by security rules"),{content:`Access denied: ${n.reason}`,isError:!0}}if(this.skillSandbox){let n,o;if(e.name==="delegate"){let{ActivityTracker:a}=await Promise.resolve().then(()=>(qt(),vs));n=new a(s),o=`agent-${++this.agentIdCounter}`,this.activeAgents.set(o,{chatId:t.chatId,task:String(e.input.task??"").slice(0,200),tracker:n,startedAt:Date.now()})}let i=e.name==="delegate"?{...t,tracker:n,onProgress:s}:t;try{let a=await this.skillSandbox.execute(r,e.input,i,void 0,n);return{content:a.display??(a.success?JSON.stringify(a.data):a.error??"Unknown error"),isError:!a.success,attachments:a.attachments}}finally{o&&this.activeAgents.delete(o)}}try{let n=await r.execute(e.input,t);return{content:n.display??(n.success?JSON.stringify(n.data):n.error??"Unknown error"),isError:!n.success,attachments:n.attachments}}catch(n){return{content:`Skill execution failed: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}getToolLabel(e,t){switch(e){case"shell":return`Running: ${String(t.command??"").slice(0,60)}`;case"web_search":return`Searching: ${String(t.query??"")}`;case"email":return`Email: ${String(t.action??"")}`;case"memory":return`Memory: ${String(t.action??"")}`;case"reminder":return`Reminder: ${String(t.action??"")}`;case"calculator":return"Calculating...";case"system_info":return"Getting system info...";case"delegate":return"Delegating sub-task...";case"http":return`Fetching: ${String(t.url??"").slice(0,60)}`;case"file":return`File: ${String(t.action??"")} ${String(t.path??"").slice(0,50)}`;case"clipboard":return`Clipboard: ${String(t.action??"")}`;case"screenshot":return"Taking screenshot...";case"browser":return`Browser: ${String(t.action??"")} ${String(t.url??"").slice(0,50)}`;case"weather":return`Weather: ${String(t.location??"")}`;case"note":return`Note: ${String(t.action??"")}`;case"profile":return`Profile: ${String(t.action??"")}`;case"calendar":return`Calendar: ${String(t.action??"")}`;case"background_task":return`Background task: ${String(t.action??"")}`;case"scheduled_task":return`Scheduled task: ${String(t.action??"")}`;case"cross_platform":return`Cross-platform: ${String(t.action??"")}`;case"code_sandbox":return"Running code...";case"document":return`Document: ${String(t.action??"")}`;default:return`Using ${e}...`}}buildActiveAgentStatus(){if(this.activeAgents.size===0)return;let e=["## Currently running sub-agents"];for(let[t,s]of this.activeAgents){let r=s.tracker.getSnapshot(),n=Math.round(r.totalElapsedMs/1e3);e.push(`- **${t}**: "${s.task}"`,` Status: ${s.tracker.formatStatus()}`,` Running for ${n}s | Last activity ${Math.round(r.idleMs/1e3)}s ago`)}return e.push(""),e.push("If the user asks what you or the agent is doing, describe the above status in natural language."),e.join(`
494
494
  `)}trimToContextWindow(e,t){let s=this.llm.getContextWindow(),r=Math.floor(s.maxInputTokens*ma),n=ge(e),o=t[t.length-1],i=Es(o),c=n+i+200+500,u=r-c;if(u<=0)return this.logger.warn({maxInputTokens:r,systemTokens:n,latestTokens:i},"Context window very tight, sending only latest message"),[o];let p=t.slice(0,-1),m=this.groupToolPairs(p),h=[];for(let T=m.length-1;T>=0;T--){let _=m[T].reduce((I,v)=>I+Es(v),0);_>u||(u-=_,h.unshift(m[T]))}let E=h.flat(),f=p.length-E.length;if(f>0){this.logger.info({trimmedCount:f,totalMessages:t.length,maxInputTokens:r},"Trimmed conversation history to fit context window");let T=p.slice(0,p.length-E.length),_=this.summarizeTrimmedMessages(T);E.unshift({role:"assistant",content:`[Earlier conversation summary \u2014 ${f} messages were trimmed to fit the context window:
@@ -501,7 +501,7 @@ The conversation continues below with the most recent messages.]`})}return E.pus
501
501
  `;if(r.push({type:"text",text:`${c}[Voice transcript]: ${a}`}),this.logger.info({transcriptLength:a.length},"Voice message transcribed"),s.length===1)return r.length===1&&r[0].type==="text"?r[0].text:r}catch(a){this.logger.error({err:a},"Voice transcription failed"),r.push({type:"text",text:"[Voice message could not be transcribed]"})}}else r.push({type:"text",text:"[Voice message received but speech-to-text is not configured. Add speech config to enable transcription.]"});else if((i.type==="document"||i.type==="video"||i.type==="other")&&i.data){let a=this.saveToInbox(i);if(a){let c=this.isTextMimeType(i.mimeType),u=`[File received: "${i.fileName??"unknown"}" (${this.formatBytes(i.data.length)}, ${i.mimeType??"unknown type"})]
502
502
  [Saved to: ${a}]`;if(c&&i.data.length<=ha){let p=i.data.toString("utf-8");u+=`
503
503
  [File content]:
504
- ${p}`}r.push({type:"text",text:u}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");return r.some(i=>i.type==="image")&&!o?r.push({type:"text",text:"What do you see in this image?"}):n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??ko.resolve("./data/inbox");try{So.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=ko.join(t,o);try{return So.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Gt,xr=g(()=>{"use strict";Gt=class{static{d(this,"ReminderScheduler")}reminderRepo;sendMessage;logger;intervalId;checkIntervalMs;constructor(e,t,s,r=15e3){this.reminderRepo=e,this.sendMessage=t,this.logger=s,this.checkIntervalMs=r}start(){this.logger.info("Reminder scheduler started"),this.intervalId=setInterval(()=>this.checkDueReminders(),this.checkIntervalMs),this.checkDueReminders()}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.logger.info("Reminder scheduler stopped")}async checkDueReminders(){try{let e=this.reminderRepo.getDue();for(let t of e)try{await this.sendMessage(t.platform,t.chatId,`\u23F0 Reminder: ${t.message}`),this.reminderRepo.markFired(t.id),this.logger.info({reminderId:t.id},"Reminder fired")}catch(s){this.logger.error({err:s,reminderId:t.id},"Failed to send reminder")}}catch(e){this.logger.error({err:e},"Error checking due reminders")}}}});var Yt,Ir=g(()=>{"use strict";Yt=class{static{d(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var Jt,$r=g(()=>{"use strict";Jt=class{static{d(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 Zt,Ar=g(()=>{"use strict";Zt=class{static{d(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t}toMatrixHTML(e){return this.toTelegramHTML(e)}toWhatsApp(e){let t=e;return t=t.replace(/\*\*(.+?)\*\*/g,"*$1*"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"_$1_"),t=t.replace(/~~(.+?)~~/g,"~$1~"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}stripFormatting(e){let t=e;return t=t.replace(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),t=t.replace(/\*\*(.+?)\*\*/g,"$1"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"$1"),t=t.replace(/~~(.+?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}escapeHTML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}});var Qt,Rr=g(()=>{"use strict";Qt=class{static{d(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let c=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:c}});return o.sort((a,c)=>c.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var es,Lr=g(()=>{"use strict";es=class{static{d(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),c=this.chunkText(n,500,50);for(let u=0;u<c.length;u++){let p;try{await this.embeddingService.embedAndStore(e,c[u],"document",`${a.id}:${u}`),p=`${a.id}:${u}`}catch(m){this.logger.warn({documentId:a.id,chunkIndex:u,err:m},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,u,c[u],p)}return this.docRepo.updateChunkCount(a.id,c.length),this.logger.info({documentId:a.id,filename:s,chunkCount:c.length},"Document ingested"),{documentId:a.id,chunkCount:c.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let u=Math.max(c-200,a),p=e.slice(u,c+200),m=p.lastIndexOf(`
504
+ ${p}`}r.push({type:"text",text:u}),this.logger.info({fileName:i.fileName,savedPath:a,size:i.data.length},"File saved to inbox")}}let n=this.isSyntheticLabel(e.text);e.text&&!n&&r.push({type:"text",text:e.text});let o=r.some(i=>i.type==="text");return r.some(i=>i.type==="image")&&!o?r.push({type:"text",text:"What do you see in this image?"}):n&&r.some(i=>i.type==="text"&&i.text.startsWith("[File received:"))?r.push({type:"text",text:"The user sent this file without any instructions. Ask them what they would like you to do with it. Do NOT take any other actions, do NOT use any tools, and do NOT act on conversation history or memories. ONLY ask what the user wants."}):r.length===0&&r.push({type:"text",text:e.text||"(empty message)"}),r}isSyntheticLabel(e){return e?["[Photo","[Voice message","[Video","[Document","[File","[Sticker","[Audio"].some(s=>e.startsWith(s)):!0}saveToInbox(e){if(!e.data)return;let t=this.inboxPath??ko.resolve("./data/inbox");try{So.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=ko.join(t,o);try{return So.writeFileSync(i,e.data),i}catch(a){this.logger.error({err:a,filePath:i},"Failed to save file to inbox");return}}isTextMimeType(e){return e?["text/","application/json","application/xml","application/javascript","application/typescript","application/x-yaml","application/yaml","application/toml","application/x-sh","application/sql","application/csv","application/x-csv"].some(s=>e.startsWith(s)):!1}formatBytes(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}}});var Gt,xr=g(()=>{"use strict";Gt=class{static{d(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 Yt,Ir=g(()=>{"use strict";Yt=class{static{d(this,"SpeechTranscriber")}logger;apiKey;baseUrl;constructor(e,t){this.logger=t,this.apiKey=e.apiKey,e.provider==="groq"?this.baseUrl=e.baseUrl??"https://api.groq.com/openai/v1":this.baseUrl=e.baseUrl??"https://api.openai.com/v1"}async transcribe(e,t){let s=this.mimeToExtension(t),r=new FormData;r.append("file",new Blob([e],{type:t}),`audio.${s}`),r.append("model","whisper-1");try{let n=await fetch(`${this.baseUrl}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:r});if(!n.ok){let i=await n.text();throw new Error(`Whisper API ${n.status}: ${i}`)}let o=await n.json();return this.logger.info({textLength:o.text.length},"Voice transcribed"),o.text}catch(n){throw this.logger.error({err:n},"Voice transcription failed"),n}}mimeToExtension(e){return{"audio/ogg":"ogg","audio/mpeg":"mp3","audio/mp4":"m4a","audio/wav":"wav","audio/webm":"webm","audio/x-m4a":"m4a"}[e]??"ogg"}}});var Jt,$r=g(()=>{"use strict";Jt=class{static{d(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 Zt,Ar=g(()=>{"use strict";Zt=class{static{d(this,"ResponseFormatter")}format(e,t){switch(t){case"telegram":return{text:this.toTelegramHTML(e),parseMode:"html"};case"discord":return{text:e,parseMode:"markdown"};case"matrix":return{text:this.toMatrixHTML(e),parseMode:"html"};case"whatsapp":return{text:this.toWhatsApp(e),parseMode:"text"};case"signal":return{text:this.stripFormatting(e),parseMode:"text"};default:return{text:e,parseMode:"text"}}}toTelegramHTML(e){let t=e;return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(s,r,n)=>`<pre>${this.escapeHTML(n.trimEnd())}</pre>`),t=t.replace(/`([^`]+)`/g,(s,r)=>`<code>${this.escapeHTML(r)}</code>`),t=t.replace(/\*\*(.+?)\*\*/g,"<b>$1</b>"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"<i>$1</i>"),t=t.replace(/~~(.+?)~~/g,"<s>$1</s>"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2">$1</a>'),t}toMatrixHTML(e){return this.toTelegramHTML(e)}toWhatsApp(e){let t=e;return t=t.replace(/\*\*(.+?)\*\*/g,"*$1*"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"_$1_"),t=t.replace(/~~(.+?)~~/g,"~$1~"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}stripFormatting(e){let t=e;return t=t.replace(/```\w*\n?/g,""),t=t.replace(/`([^`]+)`/g,"$1"),t=t.replace(/\*\*(.+?)\*\*/g,"$1"),t=t.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"$1"),t=t.replace(/~~(.+?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 ($2)"),t}escapeHTML(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}});var Qt,Rr=g(()=>{"use strict";Qt=class{static{d(this,"EmbeddingService")}llm;embeddingRepo;logger;constructor(e,t,s){this.llm=e,this.embeddingRepo=t,this.logger=s}async embedAndStore(e,t,s,r){if(this.llm.supportsEmbeddings())try{let n=await this.llm.embed(t);if(!n)return;this.embeddingRepo.store({userId:e,sourceType:s,sourceId:r,content:t,embedding:n.embedding,model:n.model,dimensions:n.dimensions}),this.logger.debug({userId:e,sourceType:s,sourceId:r},"Embedding stored")}catch(n){this.logger.error({err:n,userId:e,sourceType:s,sourceId:r},"Failed to embed content")}}async semanticSearch(e,t,s=10){if(!this.llm.supportsEmbeddings())return[];try{let r=await this.llm.embed(t);if(!r)return[];let n=this.embeddingRepo.findByUser(e);if(n.length===0)return[];let o=n.map(a=>{let c=this.cosineSimilarity(r.embedding,a.embedding);return{...a,score:c}});return o.sort((a,c)=>c.score-a.score),o.slice(0,s).map(a=>({key:a.sourceId,value:a.content,category:a.sourceType,score:a.score}))}catch(r){return this.logger.error({err:r},"Semantic search failed"),[]}}cosineSimilarity(e,t){if(e.length!==t.length)return 0;let s=0,r=0,n=0;for(let i=0;i<e.length;i++)s+=e[i]*t[i],r+=e[i]*e[i],n+=t[i]*t[i];let o=Math.sqrt(r)*Math.sqrt(n);return o===0?0:s/o}}});var es,Lr=g(()=>{"use strict";es=class{static{d(this,"DocumentProcessor")}docRepo;embeddingService;logger;constructor(e,t,s){this.docRepo=e,this.embeddingService=t,this.logger=s}async ingest(e,t,s,r){let n=await this.extractText(t,r),i=(await import("node:fs")).statSync(t),a=this.docRepo.createDocument(e,s,r,i.size),c=this.chunkText(n,500,50);for(let u=0;u<c.length;u++){let p;try{await this.embeddingService.embedAndStore(e,c[u],"document",`${a.id}:${u}`),p=`${a.id}:${u}`}catch(m){this.logger.warn({documentId:a.id,chunkIndex:u,err:m},"Embedding failed for chunk, continuing")}this.docRepo.addChunk(a.id,u,c[u],p)}return this.docRepo.updateChunkCount(a.id,c.length),this.logger.info({documentId:a.id,filename:s,chunkCount:c.length},"Document ingested"),{documentId:a.id,chunkCount:c.length}}async extractText(e,t){let s=await import("node:fs");if(t==="application/pdf")try{let r=(await import("pdf-parse")).default,n=s.readFileSync(e);return(await r(n)).text}catch(r){throw this.logger.error({err:r},"PDF parsing failed"),new Error("Failed to parse PDF")}if(t==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"||t==="application/msword")try{return(await(await import("mammoth")).extractRawText({path:e})).value}catch(r){throw this.logger.error({err:r},"DOCX parsing failed"),new Error("Failed to parse DOCX")}return s.readFileSync(e,"utf-8")}chunkText(e,t,s){let n=Math.round(t*3.5),o=Math.round(s*3.5),i=[],a=0;for(;a<e.length;){let c=a+n;if(c>=e.length){i.push(e.slice(a).trim());break}let u=Math.max(c-200,a),p=e.slice(u,c+200),m=p.lastIndexOf(`
505
505
 
506
506
  `);if(m>0)c=u+m;else{let E=p.lastIndexOf(". ");E>0&&(c=u+E+1)}let h=e.slice(a,c).trim();h&&i.push(h),a=c-o}return i.filter(c=>c.length>0)}}});var ts,Mr=g(()=>{"use strict";ts=class{static{d(this,"BackgroundTaskRunner")}skillRegistry;skillSandbox;taskRepo;adapters;logger;pollTimer;running=0;maxConcurrent=3;pollIntervalMs=5e3;taskTimeoutMs=5*6e4;constructor(e,t,s,r,n){this.skillRegistry=e,this.skillSandbox=t,this.taskRepo=s,this.adapters=r,this.logger=n}start(){this.pollTimer=setInterval(()=>this.poll(),this.pollIntervalMs),this.logger.info("Background task runner started")}stop(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0),this.logger.info("Background task runner stopped")}async poll(){if(!(this.running>=this.maxConcurrent))try{let e=this.maxConcurrent-this.running,t=this.taskRepo.getPending(e);for(let s of t)this.running++,this.runTask(s).finally(()=>{this.running--})}catch(e){this.logger.error({err:e},"Error polling for background tasks")}}async runTask(e){this.taskRepo.updateStatus(e.id,"running");try{let t=this.skillRegistry.get(e.skillName);if(!t){this.taskRepo.updateStatus(e.id,"failed",void 0,`Unknown skill: ${e.skillName}`);return}let s;try{s=JSON.parse(e.skillInput)}catch(c){this.logger.warn({taskId:e.id,err:c},"Malformed skill input JSON"),this.taskRepo.updateStatus(e.id,"failed",void 0,"Malformed skill input JSON");return}let r={userId:e.userId,chatId:e.chatId,platform:e.platform,conversationId:"",chatType:"dm"},n=new Promise((c,u)=>setTimeout(()=>u(new Error("Background task timed out")),this.taskTimeoutMs)),o=await Promise.race([this.skillSandbox.execute(t,s,r),n]),i=JSON.stringify(o.data??o.display??o.error);this.taskRepo.updateStatus(e.id,o.success?"completed":"failed",i,o.error);let a=this.adapters.get(e.platform);if(a){let c=o.success?`\u2705 Background task completed: ${e.description}
507
507
 
@@ -533,35 +533,35 @@ Assistant: {ASSISTANT_RESPONSE}
533
533
 
534
534
  Return ONLY a valid JSON array, no explanation:`,rs=class{static{d(this,"MemoryExtractor")}llm;memoryRepo;logger;embeddingService;minConfidence;constructor(e,t,s,r,n=.4){this.llm=e,this.memoryRepo=t,this.logger=s,this.embeddingService=r,this.minConfidence=n}async extract(e,t,s){try{let r=wa.replace("{USER_MESSAGE}",t).replace("{ASSISTANT_RESPONSE}",s),n=await this.llm.complete({messages:[{role:"user",content:r}],temperature:.1,tier:"fast",maxTokens:1024}),o=this.parseResponse(n.content);if(o.length===0)return 0;let i=0;for(let a of o)if(!(a.confidence<this.minConfidence))try{let c=this.memoryRepo.saveWithMetadata(e,a.key,a.value,a.category,a.type,a.confidence,"auto");this.embeddingService&&this.embeddingService.embedAndStore(e,`${a.key}: ${a.value}`,"memory",c.id).catch(u=>this.logger.debug({err:u},"Auto-embed failed")),i++,this.logger.info({key:a.key,type:a.type,confidence:a.confidence},"Auto-extracted memory saved")}catch(c){this.logger.warn({err:c,key:a.key},"Failed to save extracted memory")}return i}catch(r){return this.logger.error({err:r},"Memory extraction failed"),0}}parseResponse(e){try{let t=e.match(/\[[\s\S]*\]/);if(!t)return[];let s=JSON.parse(t[0]);return Array.isArray(s)?s.filter(r=>typeof r=="object"&&r!==null).map(r=>({key:String(r.key||""),value:String(r.value||""),type:this.validateType(String(r.type||"fact")),confidence:this.clampConfidence(Number(r.confidence)||.5),category:String(r.category||"general")})).filter(r=>r.key&&r.value):[]}catch{return this.logger.debug({content:e.slice(0,200)},"Failed to parse extraction response"),[]}}validateType(e){return ya.includes(e)?e:"fact"}clampConfidence(e){return Math.max(0,Math.min(1,e))}}});var ns,Ur=g(()=>{"use strict";Or();Cr();ns=class{static{d(this,"ActiveLearningService")}extractor;logger;minMessageLength;maxExtractionsPerMinute;extractionTimestamps=new Map;constructor(e){this.logger=e.logger,this.minMessageLength=e.minMessageLength??15,this.maxExtractionsPerMinute=e.maxExtractionsPerMinute??5,this.extractor=new rs(e.llm,e.memoryRepo,this.logger,e.embeddingService,e.minConfidence??.4)}onMessageProcessed(e,t,s){if(!t||t.length<this.minMessageLength)return;let r=Dr(t);if(r.level==="low"){this.logger.debug({signal:"low"},"Skipping extraction \u2014 low signal");return}if(!this.checkRateLimit(e)){this.logger.debug({userId:e},"Skipping extraction \u2014 rate limit reached");return}this.logger.info({signal:r.level,patterns:r.matchedPatterns},"High signal detected, triggering extraction"),this.extractor.extract(e,t,s).then(n=>{n>0&&this.logger.info({userId:e,extractedCount:n},"Auto-extraction complete")}).catch(n=>{this.logger.error({err:n},"Auto-extraction failed")})}checkRateLimit(e){let t=Date.now(),s=t-6e4,r=this.extractionTimestamps.get(e);r||(r=[],this.extractionTimestamps.set(e,r));let n=r.filter(o=>o>s);return this.extractionTimestamps.set(e,n),n.length>=this.maxExtractionsPerMinute?!1:(n.push(t),!0)}}});var Ea,Ta,ba,_a,os,Pr=g(()=>{"use strict";Ea=Math.LN2,Ta=.3,ba=.7,_a=3,os=class{static{d(this,"MemoryRetriever")}memoryRepo;logger;embeddingService;constructor(e,t,s){this.memoryRepo=e,this.logger=t,this.embeddingService=s}async retrieve(e,t,s=15,r){let n=[e];if(r)for(let o of r)o!==e&&n.push(o);try{let o=new Set,i=[];for(let f of n)for(let T of this.memoryRepo.keywordSearch(f,t,30))o.has(T.id)||(o.add(T.id),i.push(T));let a=[],c=!1;if(this.embeddingService)try{let f=new Set;for(let T of n)for(let _ of await this.embeddingService.semanticSearch(T,t,30))f.has(_.key)||(f.add(_.key),a.push(_));c=a.length>0}catch(f){this.logger.debug({err:f},"Semantic search failed, falling back to keyword-only")}let u=new Map,p=i.length;for(let f=0;f<i.length;f++){let T=i[f],_=p>0?1-f/p:0,I=c?Ta:1,v=this.applyBoosts(_*I,T);u.set(T.key,{memory:{key:T.key,value:T.value,category:T.category,type:T.type,score:v},score:v}),this.memoryRepo.recordAccess(T.id)}if(c)for(let f of a){let T=f.score*ba,_=u.get(f.key);if(_)_.score+=T,_.memory.score=_.score;else{let I=this.memoryRepo.recall(e,f.key),v=this.applyBoosts(T,I||void 0);u.set(f.key,{memory:{key:f.key,value:f.value,category:f.category,type:I?.type||"general",score:v},score:v}),I&&this.memoryRepo.recordAccess(I.id)}}let m=Array.from(u.values()).sort((f,T)=>T.score-f.score),h=new Map,E=[];for(let{memory:f}of m){let T=h.get(f.type)||0;if(!(T>=_a)&&(h.set(f.type,T+1),E.push(f),E.length>=s))break}return this.logger.debug({keywordCount:i.length,semanticCount:a.length,resultCount:E.length,hasSemanticSearch:c},"Hybrid memory retrieval complete"),E}catch(o){this.logger.error({err:o},"Memory retrieval failed");let i=new Set,a=[];for(let c of n)for(let u of this.memoryRepo.getRecentForPrompt(c,s))i.has(u.key)||(i.add(u.key),a.push({key:u.key,value:u.value,category:u.category,type:u.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(-Ea*n/2592e6);s*=o}return s}}});import{EventEmitter as Sa}from"node:events";var K,we=g(()=>{"use strict";K=class extends Sa{static{d(this,"MessagingAdapter")}status="disconnected";async sendPhoto(e,t,s){}async sendFile(e,t,s,r){}async sendVoice(e,t,s){}getStatus(){return this.status}splitText(e,t){if(e.length<=t)return[e];let s=[],r=e;for(;r.length>0;){if(r.length<=t){s.push(r);break}let n=-1,i=r.slice(0,t).lastIndexOf(`
535
535
 
536
- `);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as ka,InputFile as Fr}from"grammy";function xo(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var xs,Io=g(()=>{"use strict";we();d(xo,"mapParseMode");xs=class extends K{static{d(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new ka(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:d(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:xo(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:xo(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 Fr(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 Fr(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Fr(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 va,GatewayIntentBits as Is,Events as jr}from"discord.js";var $s,$o=g(()=>{"use strict";we();$s=class extends K{static{d(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new va({intents:[Is.Guilds,Is.GuildMessages,Is.MessageContent,Is.DirectMessages]}),this.client.on(jr.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(jr.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(jr.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 As,Ao=g(()=>{"use strict";we();As=class extends K{static{d(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file";try{let a=s.slice(6),c=`${this.homeserverUrl}/_matrix/media/v3/download/${a}`,u=await fetch(c,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!u.ok)return;let p=await u.arrayBuffer(),m=Buffer.from(p);return{type:t,mimeType:n,fileName:i,size:o??m.length,data:m}}catch(a){console.error("[matrix] Failed to download attachment",s,a);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Rs,Ro=g(()=>{"use strict";we();Rs=class extends K{static{d(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:n,downloadMediaMessage:o}=t;this.downloadMedia=o;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",c=>{if(c.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),c.connection==="close"){let p=c.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),p){let m=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),m)}}}),this.socket.ev.on("messages.upsert",({messages:c,type:u})=>{if(u==="notify")for(let p of c)p.message&&(p.key.fromMe||this.processMessage(p).catch(m=>{this.emit("error",m instanceof Error?m:new Error(String(m)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Ls,Lo=g(()=>{"use strict";we();Ls=class extends K{static{d(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let u=await c.json();n=String(u.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let u of r.attachments){let p=await this.downloadAttachment(u);p&&i.push(p)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Br from"node:readline";var Ms,Mo=g(()=>{"use strict";we();Ms=class extends K{static{d(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Br.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
536
+ `);if(i>0&&(n=i),n<0){let c=r.slice(0,t).match(/.*[.!?]\s/s);c&&(n=c[0].length)}n<0&&(n=t),s.push(r.slice(0,n).trimEnd()),r=r.slice(n).trimStart()}return s}}});import{Bot as ka,InputFile as Fr}from"grammy";function xo(l){if(l==="markdown")return"MarkdownV2";if(l==="html")return"HTML"}var xs,Io=g(()=>{"use strict";we();d(xo,"mapParseMode");xs=class extends K{static{d(this,"TelegramAdapter")}platform="telegram";bot;constructor(e){super(),this.bot=new ka(e)}async connect(){this.status="connecting",this.bot.on("message:text",e=>{this.emit("message",this.normalizeMessage(e.message,e.message.text))}),this.bot.on("message:photo",async e=>{let t=e.message,r=(t.caption??"")||"[Photo]",n=t.photo[t.photo.length-1],o=await this.downloadAttachment(n.file_id,"image","image/jpeg"),i=this.normalizeMessage(t,r);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:voice",async e=>{let t=e.message,s=await this.downloadAttachment(t.voice.file_id,"audio",t.voice.mime_type??"audio/ogg"),r=this.normalizeMessage(t,"[Voice message]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:audio",async e=>{let t=e.message,r=(t.caption??"")||`[Audio: ${t.audio.file_name??"audio"}]`,n=await this.downloadAttachment(t.audio.file_id,"audio",t.audio.mime_type??"audio/mpeg"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:video",async e=>{let t=e.message,r=(t.caption??"")||"[Video]",n=await this.downloadAttachment(t.video.file_id,"video",t.video.mime_type??"video/mp4"),o=this.normalizeMessage(t,r);o.attachments=n?[n]:void 0,this.emit("message",o)}),this.bot.on("message:document",async e=>{let t=e.message,s=t.document,n=(t.caption??"")||`[Document: ${s.file_name??"file"}]`,o=await this.downloadAttachment(s.file_id,"document",s.mime_type??"application/octet-stream",s.file_name),i=this.normalizeMessage(t,n);i.attachments=o?[o]:void 0,this.emit("message",i)}),this.bot.on("message:video_note",async e=>{let t=e.message,s=await this.downloadAttachment(t.video_note.file_id,"video","video/mp4"),r=this.normalizeMessage(t,"[Video note]");r.attachments=s?[s]:void 0,this.emit("message",r)}),this.bot.on("message:sticker",e=>{let t=e.message,s=t.sticker.emoji??"\u{1F3F7}\uFE0F";this.emit("message",this.normalizeMessage(t,`[Sticker: ${s}]`))}),this.bot.catch(e=>{this.emit("error",e.error)}),this.bot.start({onStart:d(()=>{this.status="connected",this.emit("connected")},"onStart")})}async disconnect(){await this.bot.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,4096),n="";for(let o of r){let i=await this.bot.api.sendMessage(Number(e),o,{reply_to_message_id:s?.replyToMessageId?Number(s.replyToMessageId):void 0,parse_mode:xo(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:xo(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 Fr(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 Fr(t,s),{caption:r});return String(n.message_id)}async sendVoice(e,t,s){let r=await this.bot.api.sendVoice(Number(e),new Fr(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 va,GatewayIntentBits as Is,Events as jr}from"discord.js";var $s,$o=g(()=>{"use strict";we();$s=class extends K{static{d(this,"DiscordAdapter")}platform="discord";client=null;token;constructor(e){super(),this.token=e}async connect(){this.status="connecting",this.client=new va({intents:[Is.Guilds,Is.GuildMessages,Is.MessageContent,Is.DirectMessages]}),this.client.on(jr.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(jr.ClientReady,()=>{this.status="connected",this.emit("connected")}),this.client.on(jr.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 As,Ao=g(()=>{"use strict";we();As=class extends K{static{d(this,"MatrixAdapter")}platform="matrix";client;homeserverUrl;accessToken;botUserId;constructor(e,t,s){super(),this.homeserverUrl=e.replace(/\/+$/,""),this.accessToken=t,this.botUserId=s}async connect(){this.status="connecting";let{MatrixClient:e,SimpleFsStorageProvider:t,AutojoinRoomsMixin:s}=await import("matrix-bot-sdk"),r=new t("./data/matrix-storage");this.client=new e(this.homeserverUrl,this.accessToken,r),s.setupOnClient(this.client),this.client.on("room.message",async(n,o)=>{if(o.sender===this.botUserId)return;let i=o.content?.msgtype;if(i)try{let a=await this.normalizeEvent(n,o,i);a&&this.emit("message",a)}catch(a){this.emit("error",a instanceof Error?a:new Error(String(a)))}}),await this.client.start(),this.status="connected",this.emit("connected")}async disconnect(){this.client.stop(),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,32e3),n="";for(let o of r)s?.parseMode==="html"?n=await this.client.sendEvent(e,"m.room.message",{msgtype:"m.text",body:o.replace(/<[^>]*>/g,""),format:"org.matrix.custom.html",formatted_body:o}):n=await this.client.sendText(e,o);return n}async editMessage(e,t,s,r){let n=r?.parseMode==="html",o={msgtype:"m.text",body:"* "+(n?s.replace(/<[^>]*>/g,""):s),"m.new_content":{msgtype:"m.text",body:n?s.replace(/<[^>]*>/g,""):s,...n?{format:"org.matrix.custom.html",formatted_body:s}:{}},"m.relates_to":{rel_type:"m.replace",event_id:t}};await this.client.sendEvent(e,"m.room.message",o)}async deleteMessage(e,t){await this.client.redactEvent(e,t)}async sendPhoto(e,t,s){let r=await this.client.uploadContent(t,"image/png","image.png"),n={msgtype:"m.image",body:s??"image.png",url:r,info:{mimetype:"image/png",size:t.length}};return await this.client.sendEvent(e,"m.room.message",n)}async sendFile(e,t,s,r){let n=this.guessMimeType(s),o=await this.client.uploadContent(t,n,s),i={msgtype:"m.file",body:r??s,filename:s,url:o,info:{mimetype:n,size:t.length}};return await this.client.sendEvent(e,"m.room.message",i)}async normalizeEvent(e,t,s){let r;try{r=(await this.client.getUserProfile(t.sender))?.displayname??void 0}catch{}let n={id:t.event_id,platform:"matrix",chatId:e,chatType:"group",userId:t.sender,userName:t.sender.split(":")[0].slice(1),displayName:r,timestamp:new Date(t.origin_server_ts),replyToMessageId:t.content["m.relates_to"]?.["m.in_reply_to"]?.event_id};switch(s){case"m.text":return{...n,text:t.content.body};case"m.image":{let o=await this.downloadAttachment(t.content,"image");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Photo]",attachments:o?[o]:void 0}}case"m.audio":{let o=await this.downloadAttachment(t.content,"audio");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Voice message]",attachments:o?[o]:void 0}}case"m.video":{let o=await this.downloadAttachment(t.content,"video");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Video]",attachments:o?[o]:void 0}}case"m.file":{let o=await this.downloadAttachment(t.content,"document");return o&&t.content.body&&(o.fileName=t.content.body),{...n,text:"[Document]",attachments:o?[o]:void 0}}default:return t.content.body?{...n,text:t.content.body}:void 0}}async downloadAttachment(e,t){let s=e.url;if(!s||!s.startsWith("mxc://"))return;let r=e.info??{},n=r.mimetype,o=r.size,i=e.filename??e.body??"file",a=s.slice(6),c=`${this.homeserverUrl}/_matrix/media/v3/download/${a}`,u=2;for(let p=0;p<=u;p++)try{let m=await fetch(c,{headers:{Authorization:`Bearer ${this.accessToken}`}});if(!m.ok){if(console.error(`[matrix] Download failed (${m.status}), attempt ${p+1}/${u+1}`,s),p<u){await new Promise(f=>setTimeout(f,500*(p+1)));continue}return}let h=await m.arrayBuffer(),E=Buffer.from(h);return{type:t,mimeType:n,fileName:i,size:o??E.length,data:E}}catch(m){if(console.error(`[matrix] Download error, attempt ${p+1}/${u+1}`,s,m),p<u){await new Promise(h=>setTimeout(h,500*(p+1)));continue}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 Rs,Ro=g(()=>{"use strict";we();Rs=class extends K{static{d(this,"WhatsAppAdapter")}platform="whatsapp";socket;downloadMedia;dataPath;reconnectAttempts=0;reconnectTimer;constructor(e){super(),this.dataPath=e}async connect(){this.status="connecting";let e=await import("@whiskeysockets/baileys"),t=e.default??e,{makeWASocket:s,useMultiFileAuthState:r,DisconnectReason:n,downloadMediaMessage:o}=t;this.downloadMedia=o;let{state:i,saveCreds:a}=await r(this.dataPath);this.socket=s({auth:i,printQRInTerminal:!0}),this.socket.ev.on("creds.update",a),this.socket.ev.on("connection.update",c=>{if(c.connection==="open"&&(this.status="connected",this.reconnectAttempts=0,this.emit("connected")),c.connection==="close"){let p=c.lastDisconnect?.error?.output?.statusCode!==n.loggedOut;if(this.status="disconnected",this.emit("disconnected"),p){let m=Math.min(1e3*Math.pow(2,this.reconnectAttempts),6e4);this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>this.connect(),m)}}}),this.socket.ev.on("messages.upsert",({messages:c,type:u})=>{if(u==="notify")for(let p of c)p.message&&(p.key.fromMe||this.processMessage(p).catch(m=>{this.emit("error",m instanceof Error?m:new Error(String(m)))}))})}async disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.reconnectAttempts=0,this.socket?.end(void 0),this.socket=void 0,this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,65e3),n="";for(let o=0;o<r.length;o++)n=(await this.socket.sendMessage(e,{text:r[o]},o===0&&s?.replyToMessageId?{quoted:{key:{remoteJid:e,id:s.replyToMessageId},message:{}}}:void 0))?.key?.id??"";return n}async editMessage(e,t,s,r){await this.socket.sendMessage(e,{text:s,edit:{remoteJid:e,id:t,fromMe:!0}})}async deleteMessage(e,t){await this.socket.sendMessage(e,{delete:{remoteJid:e,id:t,fromMe:!0}})}async sendPhoto(e,t,s){return(await this.socket.sendMessage(e,{image:t,caption:s}))?.key?.id}async sendFile(e,t,s,r){return(await this.socket.sendMessage(e,{document:t,fileName:s,caption:r,mimetype:this.guessMimeType(s)}))?.key?.id}async processMessage(e){let t=e.message,s=t.conversation??t.extendedTextMessage?.text??t.imageMessage?.caption??t.videoMessage?.caption??t.documentMessage?.caption??"",r=[],n=s;if(t.imageMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.imageMessage.mimetype??"image/jpeg";r.push({type:"image",mimeType:a,fileName:t.imageMessage.fileName??`image.${a.split("/")[1]??"jpeg"}`,size:t.imageMessage.fileLength??i.length,data:i})}n||(n="[Photo]")}else if(t.audioMessage){let i=await this.downloadMediaSafe(e);if(i){let a=t.audioMessage.mimetype??"audio/ogg";r.push({type:"audio",mimeType:a,fileName:t.audioMessage.fileName??`audio.${a.split("/")[1]??"ogg"}`,size:t.audioMessage.fileLength??i.length,data:i})}n||(n="[Voice message]")}else if(t.videoMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"video",mimeType:t.videoMessage.mimetype??"video/mp4",size:t.videoMessage.fileLength??i.length,data:i}),n||(n="[Video]")}else if(t.documentMessage){let i=await this.downloadMediaSafe(e);i&&r.push({type:"document",mimeType:t.documentMessage.mimetype??"application/octet-stream",fileName:t.documentMessage.fileName??"document",size:t.documentMessage.fileLength??i.length,data:i}),n||(n="[Document]")}else if(t.stickerMessage&&!s)return;if(!n&&r.length===0)return;let o={id:e.key.id??"",platform:"whatsapp",chatId:e.key.remoteJid??"",chatType:e.key.remoteJid?.endsWith("@g.us")?"group":"dm",userId:e.key.participant??e.key.remoteJid??"",userName:e.pushName??e.key.participant??e.key.remoteJid??"",displayName:e.pushName??void 0,text:n,timestamp:new Date(e.messageTimestamp*1e3),replyToMessageId:t.extendedTextMessage?.contextInfo?.stanzaId??void 0,attachments:r.length>0?r:void 0};this.emit("message",o)}async downloadMediaSafe(e){try{if(!this.downloadMedia)return;let t=await this.downloadMedia(e,"buffer",{});return Buffer.isBuffer(t)?t:Buffer.from(t)}catch(t){console.error("[whatsapp] Failed to download media",t);return}}guessMimeType(e){let t=e.split(".").pop()?.toLowerCase();return{pdf:"application/pdf",txt:"text/plain",json:"application/json",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",mp3:"audio/mpeg",ogg:"audio/ogg",mp4:"video/mp4",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}[t??""]??"application/octet-stream"}}});var Ls,Lo=g(()=>{"use strict";we();Ls=class extends K{static{d(this,"SignalAdapter")}apiUrl;phoneNumber;platform="signal";pollingInterval;constructor(e,t){super(),this.apiUrl=e,this.phoneNumber=t}async connect(){this.status="connecting";let e=3,t;for(let s=0;s<=e;s++)try{let r=await fetch(`${this.apiUrl}/v1/about`);if(!r.ok)throw new Error(`Signal API not reachable: ${r.status}`);this.pollingInterval=setInterval(()=>{this.pollMessages().catch(n=>{this.emit("error",n instanceof Error?n:new Error(String(n)))})},2e3),this.status="connected",this.emit("connected");return}catch(r){if(t=r instanceof Error?r:new Error(String(r)),s<e){let n=1e3*Math.pow(2,s);await new Promise(o=>setTimeout(o,n))}}this.status="error",this.emit("error",t)}async disconnect(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=void 0),this.status="disconnected",this.emit("disconnected")}async sendMessage(e,t,s){let r=this.splitText(t,6e3),n="";for(let o of r){let i=e.startsWith("group."),a={message:o,number:this.phoneNumber};i?a.recipients=[e.replace("group.","")]:a.recipients=[e];let c=await fetch(`${this.apiUrl}/v2/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Signal send failed: ${c.status} ${await c.text()}`);let u=await c.json();n=String(u.timestamp??Date.now())}return n}async editMessage(e,t,s,r){throw new Error("Signal does not support message editing")}async deleteMessage(e,t){let s={number:this.phoneNumber,recipients:[e],timestamp:Number(t)},r=await fetch(`${this.apiUrl}/v1/deleteMessage`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok)throw new Error(`Signal delete failed: ${r.status} ${await r.text()}`)}async pollMessages(){let e=await fetch(`${this.apiUrl}/v1/receive/${this.phoneNumber}`);if(!e.ok)return;let t=await e.json();for(let s of t){let r=s.envelope?.dataMessage;if(!r||!r.message&&(!r.attachments||r.attachments.length===0))continue;let n=s.envelope,o=r.groupInfo?.groupId?`group.${r.groupInfo.groupId}`:n.sourceNumber??n.source??"",i=[];if(r.attachments)for(let u of r.attachments){let p=await this.downloadAttachment(u);p&&i.push(p)}let a=r.message||this.inferTextFromAttachments(i)||"";if(!a&&i.length===0)continue;let c={id:String(r.timestamp??Date.now()),platform:"signal",chatId:o,chatType:r.groupInfo?"group":"dm",userId:n.sourceNumber??n.source??"",userName:n.sourceName??n.sourceNumber??n.source??"",displayName:n.sourceName,text:a,timestamp:new Date(r.timestamp??Date.now()),attachments:i.length>0?i:void 0};this.emit("message",c)}}async downloadAttachment(e){if(e.id)try{let t=await fetch(`${this.apiUrl}/v1/attachments/${e.id}`);if(!t.ok)return;let s=await t.arrayBuffer(),r=Buffer.from(s);return{type:this.classifyContentType(e.contentType),mimeType:e.contentType??void 0,fileName:e.filename??void 0,size:e.size??r.length,data:r}}catch(t){console.error("[signal] Failed to download attachment",e.id,t);return}}classifyContentType(e){return e?e.startsWith("image/")?"image":e.startsWith("audio/")?"audio":e.startsWith("video/")?"video":"document":"other"}inferTextFromAttachments(e){if(e.length===0)return"";let t=e.map(s=>s.type);return t.includes("image")?"[Photo]":t.includes("audio")?"[Voice message]":t.includes("video")?"[Video]":t.includes("document")?"[Document]":"[File]"}}});import Br from"node:readline";var Ms,Mo=g(()=>{"use strict";we();Ms=class extends K{static{d(this,"CLIAdapter")}platform="cli";rl;messageCounter=0;async connect(){this.status="connecting",this.rl=Br.createInterface({input:process.stdin,output:process.stdout,prompt:"You: "}),console.log(`
537
537
  Alfred Chat \u2014 type your message and press Enter. Use /quit or /exit to leave.
538
538
  `),this.rl.on("line",e=>{let t=e.trim();if(!t){this.prompt();return}if(t==="/quit"||t==="/exit"){console.log(`
539
539
  Goodbye!
540
540
  `),this.emit("disconnected");return}this.messageCounter++;let s={id:`cli-${this.messageCounter}`,platform:"cli",chatId:"cli-chat",chatType:"dm",userId:"cli-user",userName:"cli-user",displayName:"You",text:t,timestamp:new Date};this.emit("message",s)}),this.rl.on("close",()=>{this.emit("disconnected")}),this.status="connected",this.emit("connected"),this.prompt()}async disconnect(){this.rl?.close(),this.rl=void 0,this.status="disconnected"}async sendMessage(e,t,s){let r=`cli-resp-${++this.messageCounter}`;return process.stdout.write(`
541
541
  Alfred: ${t}
542
- `),this.prompt(),r}async editMessage(e,t,s,r){Br.clearLine(process.stdout,0),Br.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});var Ne={};se(Ne,{CLIAdapter:()=>Ms,DiscordAdapter:()=>$s,MatrixAdapter:()=>As,MessagingAdapter:()=>K,SignalAdapter:()=>Ls,TelegramAdapter:()=>xs,WhatsAppAdapter:()=>Rs});var De=g(()=>{"use strict";we();Io();$o();Ao();Ro();Lo();Mo()});import Ns from"node:fs";import Ds from"node:path";import xa from"js-yaml";var Oe,No=g(()=>{"use strict";Qs();sr();pr();Ts();qt();kr();vr();xr();Ir();$r();Ar();Rr();Lr();Mr();Nr();Ur();Pr();Oe=class{static{d(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Zt;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=bt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ke(this.config.storage.path);let e=this.database.getDb(),t=new _t(e),s=new St(e),r=new ve(e),n=new kt(e),o=new vt(e),i=new xt(e),a=new It(e),c=new $t(e),u=new At(e),p=new Rt(e);this.logger.info("Storage initialized");let m=new Ft,h=this.loadSecurityRules();m.loadRules(h);let E=new jt(m,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:h.length},"Security engine initialized");let f=ur(this.config.llm);await f.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let T=new Qt(f,a,this.logger.child({component:"embeddings"})),_=this.config.activeLearning?.enabled!==!1,I,v;_&&(I=new ns({llm:f,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}),v=new os(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let M=new ze(this.logger.child({component:"sandbox"})),A=new We;A.register(new Xe),A.register(new He),A.register(new qe(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),A.register(new Ke(o)),A.register(new Ve(i)),A.register(new Ge),A.register(new Ye),A.register(new Je(n,T)),A.register(new Ze(f,A,M,E)),A.register(new Qe(this.config.email?{imap:this.config.email.imap,smtp:this.config.email.smtp,auth:this.config.email.auth}:void 0)),A.register(new et),A.register(new tt),A.register(new rt),A.register(new nt),A.register(new ot),A.register(new it(s)),A.register(new at(s,c,this.adapters)),A.register(new ct(u)),A.register(new lt(p));let D=new Lt(e),C=new es(D,T,this.logger.child({component:"documents"}));A.register(new ut(D,C,T));let J;if(this.config.calendar)try{let N=await zt(this.config.calendar);J=new Ae(N),A.register(J),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(N){this.logger.warn({err:N},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=J,this.config.mcp?.servers?.length){let{MCPManager:N}=await Promise.resolve().then(()=>(qt(),vs));this.mcpManager=new N(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let B of this.mcpManager.getSkills())A.register(B);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:N}=await Promise.resolve().then(()=>(qt(),vs));A.register(new N({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}this.logger.info({skills:A.getAll().map(N=>N.metadata.name)},"Skills registered");let Ue;if(this.config.speech?.apiKey&&(Ue=new Yt(this.config.speech,this.logger.child({component:"speech"})),this.logger.info({provider:this.config.speech.provider},"Speech-to-text initialized")),this.config.speech?.ttsEnabled){let N=new Jt(this.config.speech,this.logger.child({component:"tts"}));A.register(new pt(N)),this.logger.info("Text-to-speech skill registered")}let ie=new Kt(t),H=Ds.resolve(Ds.dirname(this.config.storage.path),"inbox");this.pipeline=new Vt({llm:f,conversationManager:ie,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:A,skillSandbox:M,securityManager:E,memoryRepo:n,speechTranscriber:Ue,inboxPath:H,embeddingService:T,activeLearning:I,memoryRetriever:v}),this.reminderScheduler=new Gt(o,async(N,B,pe)=>{let O=this.adapters.get(N);O?await O.sendMessage(B,pe):this.logger.warn({platform:N,chatId:B},"No adapter for reminder platform")},this.logger.child({component:"reminders"})),this.backgroundTaskRunner=new ts(A,M,u,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new ss(p,A,M,f,this.adapters,this.logger.child({component:"proactive-scheduler"})),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(De(),Ne)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}setupAdapterHandlers(e,t){t.on("message",async s=>{try{let r,n="",o=d(async u=>{if(u!==n){n=u;try{r?await t.editMessage(s.chatId,r,u):r=await t.sendMessage(s.chatId,u)}catch(p){this.logger.debug({err:p,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;if(r)try{await t.editMessage(s.chatId,r,a.text,c)}catch(u){this.logger.debug({err:u,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c);if(i.attachments)for(let u of i.attachments)try{let p=u.mimeType.startsWith("image/"),m=u.mimeType==="audio/ogg"||u.mimeType==="audio/opus";p?await t.sendPhoto(s.chatId,u.data,u.fileName):m?await t.sendVoice(s.chatId,u.data):await t.sendFile(s.chatId,u.data,u.fileName)}catch(p){this.logger.warn({err:p,fileName:u.fileName,chatId:s.chatId},"Failed to send attachment")}}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}loadSecurityRules(){let e=Ds.resolve(this.config.security.rulesPath),t=[];if(!Ns.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Ns.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Ns.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Ds.join(e,n),i=Ns.readFileSync(o,"utf-8"),a=xa.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 Do=g(()=>{"use strict"});var Wr=g(()=>{"use strict";No();vr();kr();xr();Ir();$r();Ar();Rr();Mr();Nr();Lr();Ur();Pr();Cr();Do();Or()});var Oo={};se(Oo,{startCommand:()=>Ia});async function Ia(){let l=new V,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=bt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new Oe(e),r=!1,n=d(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready")}catch(o){t.fatal({error:o},"Failed to start Alfred"),process.exit(1)}}var Co=g(()=>{"use strict";Se();Qs();Wr();d(Ia,"startCommand")});var Uo={};se(Uo,{chatCommand:()=>$a});async function $a(l){let e=new V,t;try{t=e.loadConfig()}catch(r){console.error("Failed to load configuration:",r.message),process.exit(1)}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let r=t.llm[l.tier];r?t.llm.default=r:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let s=new Oe(t);try{await s.initialize(),await s.startWithCLI()}catch(r){console.error("Failed to start chat:",r.message),process.exit(1)}}var Po=g(()=>{"use strict";Se();Wr();d($a,"chatCommand")});var jo={};se(jo,{setupCommand:()=>Ca});import{createInterface as Aa}from"node:readline/promises";import{stdin as Ra,stdout as La}from"node:process";import Y from"node:fs";import ue from"node:path";import zr from"js-yaml";function j(l){return`${Cs}${l}${L}`}function Da(l){return`${G}${l}${L}`}function Ee(l){return`${Us}${l}${L}`}function Fo(l){return`${Ma}${l}${L}`}function x(l){return`${ht}${l}${L}`}function b(l){return`${be}${l}${L}`}function Ce(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function Oa(l){let e={},t={},s=!1,r=!1,n=30,o=ue.join(l,"config","default.yml");if(Y.existsSync(o))try{let m=zr.load(Y.readFileSync(o,"utf-8"));m&&typeof m=="object"&&Object.assign(e,m)}catch{}let i=ue.join(l,".env");if(Y.existsSync(i))try{let m=Y.readFileSync(i,"utf-8").split(`
543
- `);for(let h of m){let E=h.trim();if(!E||E.startsWith("#"))continue;let f=E.indexOf("=");f>0&&(t[E.slice(0,f)]=E.slice(f+1))}}catch{}let a=ue.join(l,"config","rules","default-rules.yml");if(Y.existsSync(a))try{let m=zr.load(Y.readFileSync(a,"utf-8"));if(m?.rules){s=m.rules.some(f=>f.id==="allow-owner-admin"&&f.effect==="allow"),m.rules.find(f=>f.id==="allow-write-for-dm"||f.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let E=m.rules.find(f=>f.id==="rate-limit-write");E?.rateLimit?.maxInvocations&&(n=E.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled,u=e.llm,p={};if(u){for(let m of["strong","fast","embeddings","local"])u[m]?.provider&&u[m]?.model&&(p[m]=u[m]);u.default?.provider&&(e.llm={...e.llm,provider:u.default.provider,model:u.default.model,baseUrl:u.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c,multiModelTiers:p}}async function Ca(){let l=Aa({input:Ra,output:La}),e=process.cwd(),t=Oa(e),s=Object.keys(t.config).length>0;try{Ua(),console.log(s?`${Us}Existing configuration found \u2014 press Enter to keep current values.${L}
544
- ${be}Only change what you need to update.${L}
545
- `:`${Us}Welcome to the Alfred setup wizard!${L}
546
- ${be}This will walk you through configuring your AI assistant.${L}
547
- ${be}Press Enter to accept defaults shown in [brackets].${L}
542
+ `),this.prompt(),r}async editMessage(e,t,s,r){Br.clearLine(process.stdout,0),Br.cursorTo(process.stdout,0),process.stdout.write(`Alfred: ${s}`)}async deleteMessage(e,t){}prompt(){this.rl?.prompt()}}});var Ne={};se(Ne,{CLIAdapter:()=>Ms,DiscordAdapter:()=>$s,MatrixAdapter:()=>As,MessagingAdapter:()=>K,SignalAdapter:()=>Ls,TelegramAdapter:()=>xs,WhatsAppAdapter:()=>Rs});var De=g(()=>{"use strict";we();Io();$o();Ao();Ro();Lo();Mo()});import Ns from"node:fs";import Ds from"node:path";import xa from"js-yaml";var Oe,No=g(()=>{"use strict";Qs();sr();pr();Ts();qt();kr();vr();xr();Ir();$r();Ar();Rr();Lr();Mr();Nr();Ur();Pr();Oe=class{static{d(this,"Alfred")}config;logger;database;pipeline;reminderScheduler;backgroundTaskRunner;proactiveScheduler;adapters=new Map;formatter=new Zt;mcpManager;calendarSkill;constructor(e){this.config=e,this.logger=bt("alfred",e.logger.level)}async initialize(){this.logger.info("Initializing Alfred..."),this.database=new ke(this.config.storage.path);let e=this.database.getDb(),t=new _t(e),s=new St(e),r=new ve(e),n=new kt(e),o=new vt(e),i=new xt(e),a=new It(e),c=new $t(e),u=new At(e),p=new Rt(e);this.logger.info("Storage initialized");let m=new Ft,h=this.loadSecurityRules();m.loadRules(h);let E=new jt(m,r,this.logger.child({component:"security"}));this.logger.info({ruleCount:h.length},"Security engine initialized");let f=ur(this.config.llm);await f.initialize(),this.logger.info({provider:this.config.llm.default.provider,model:this.config.llm.default.model},"LLM provider initialized");let T=new Qt(f,a,this.logger.child({component:"embeddings"})),_=this.config.activeLearning?.enabled!==!1,I,v;_&&(I=new ns({llm:f,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}),v=new os(n,this.logger.child({component:"memory-retriever"}),T),this.logger.info("Active learning & memory retriever initialized"));let N=new ze(this.logger.child({component:"sandbox"})),A=new We;A.register(new Xe),A.register(new He),A.register(new qe(this.config.search?{provider:this.config.search.provider,apiKey:this.config.search.apiKey,baseUrl:this.config.search.baseUrl}:void 0)),A.register(new Ke(o)),A.register(new Ve(i)),A.register(new Ge),A.register(new Ye),A.register(new Je(n,T)),A.register(new Ze(f,A,N,E)),A.register(new Qe(this.config.email?{imap:this.config.email.imap,smtp:this.config.email.smtp,auth:this.config.email.auth}:void 0)),A.register(new et),A.register(new tt),A.register(new rt),A.register(new nt),A.register(new ot),A.register(new it(s)),A.register(new at(s,c,this.adapters,(R,F)=>t.findByPlatformAndUser(R,F))),A.register(new ct(u)),A.register(new lt(p));let D=new Lt(e),C=new es(D,T,this.logger.child({component:"documents"}));A.register(new ut(D,C,T));let J;if(this.config.calendar)try{let R=await zt(this.config.calendar);J=new Ae(R),A.register(J),this.logger.info({provider:this.config.calendar.provider},"Calendar initialized")}catch(R){this.logger.warn({err:R},"Calendar initialization failed, continuing without calendar")}if(this.calendarSkill=J,this.config.mcp?.servers?.length){let{MCPManager:R}=await Promise.resolve().then(()=>(qt(),vs));this.mcpManager=new R(this.logger.child({component:"mcp"})),await this.mcpManager.initialize(this.config.mcp);for(let F of this.mcpManager.getSkills())A.register(F);this.logger.info({mcpSkills:this.mcpManager.getSkills().length},"MCP skills registered")}if(this.config.codeSandbox?.enabled){let{CodeExecutionSkill:R}=await Promise.resolve().then(()=>(qt(),vs));A.register(new R({allowedLanguages:this.config.codeSandbox.allowedLanguages,maxTimeoutMs:this.config.codeSandbox.maxTimeoutMs})),this.logger.info("Code sandbox enabled")}this.logger.info({skills:A.getAll().map(R=>R.metadata.name)},"Skills registered");let Ue;if(this.config.speech?.apiKey&&(Ue=new Yt(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 R=new Jt(this.config.speech,this.logger.child({component:"tts"}));A.register(new pt(R)),this.logger.info("Text-to-speech skill registered")}let ie=new Kt(t),H=Ds.resolve(Ds.dirname(this.config.storage.path),"inbox");this.pipeline=new Vt({llm:f,conversationManager:ie,users:s,logger:this.logger.child({component:"pipeline"}),skillRegistry:A,skillSandbox:N,securityManager:E,memoryRepo:n,speechTranscriber:Ue,inboxPath:H,embeddingService:T,activeLearning:I,memoryRetriever:v}),this.reminderScheduler=new Gt(o,async(R,F,pe)=>{let O=this.adapters.get(R);O?await O.sendMessage(F,pe):this.logger.warn({platform:R,chatId:F},"No adapter for reminder platform")},this.logger.child({component:"reminders"}),15e3,{getMasterUserId:d(R=>s.getMasterUserId(R),"getMasterUserId"),getLinkedUsers:d(R=>s.getLinkedUsers(R),"getLinkedUsers"),findConversation:d((R,F)=>t.findByPlatformAndUser(R,F),"findConversation")}),this.backgroundTaskRunner=new ts(A,N,u,this.adapters,this.logger.child({component:"background-tasks"})),this.proactiveScheduler=new ss(p,A,N,f,this.adapters,this.logger.child({component:"proactive-scheduler"})),await this.initializeAdapters(),this.logger.info("Alfred initialized")}async initializeAdapters(){let{config:e}=this;if(e.telegram.enabled&&e.telegram.token){let{TelegramAdapter:t}=await Promise.resolve().then(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));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(()=>(De(),Ne));this.adapters.set("signal",new t(e.signal.apiUrl,e.signal.phoneNumber)),this.logger.info("Signal adapter registered")}}async start(){this.logger.info("Starting Alfred...");for(let[e,t]of this.adapters)this.setupAdapterHandlers(e,t),await t.connect(),this.logger.info({platform:e},"Adapter connected");this.reminderScheduler?.start(),this.backgroundTaskRunner?.start(),this.proactiveScheduler?.start(),this.adapters.size===0&&this.logger.warn("No messaging adapters enabled. Configure at least one platform."),this.logger.info(`Alfred is running with ${this.adapters.size} adapter(s)`)}async startWithCLI(){this.adapters.clear();let{CLIAdapter:e}=await Promise.resolve().then(()=>(De(),Ne)),t=new e;this.adapters.set("cli",t),this.setupAdapterHandlers("cli",t),t.on("disconnected",()=>{this.stop().then(()=>process.exit(0))}),await this.start()}async stop(){this.logger.info("Stopping Alfred..."),this.reminderScheduler?.stop(),this.backgroundTaskRunner?.stop(),this.proactiveScheduler?.stop(),this.mcpManager&&await this.mcpManager.shutdown();for(let[e,t]of this.adapters)try{await t.disconnect(),this.logger.info({platform:e},"Adapter disconnected")}catch(s){this.logger.error({platform:e,err:s},"Failed to disconnect adapter")}this.database.close(),this.logger.info("Alfred stopped")}setupAdapterHandlers(e,t){t.on("message",async s=>{try{let r,n="",o=d(async u=>{if(u!==n){n=u;try{r?await t.editMessage(s.chatId,r,u):r=await t.sendMessage(s.chatId,u)}catch(p){this.logger.debug({err:p,chatId:s.chatId},"Status message edit failed")}}},"onProgress"),i=await this.pipeline.process(s,o),a=this.formatter.format(i.text,s.platform),c=a.parseMode!=="text"?{parseMode:a.parseMode}:void 0;if(r)try{await t.editMessage(s.chatId,r,a.text,c)}catch(u){this.logger.debug({err:u,chatId:s.chatId},"Final response edit failed, sending as new message"),await t.sendMessage(s.chatId,a.text,c)}else await t.sendMessage(s.chatId,a.text,c);if(i.attachments)for(let u of i.attachments)try{let p=u.mimeType.startsWith("image/"),m=u.mimeType==="audio/ogg"||u.mimeType==="audio/opus";p?await t.sendPhoto(s.chatId,u.data,u.fileName):m?await t.sendVoice(s.chatId,u.data):await t.sendFile(s.chatId,u.data,u.fileName)}catch(p){this.logger.warn({err:p,fileName:u.fileName,chatId:s.chatId},"Failed to send attachment")}}catch(r){this.logger.error({platform:e,err:r,chatId:s.chatId},"Failed to handle message");try{await t.sendMessage(s.chatId,"Sorry, I encountered an error processing your message. Please try again.")}catch(n){this.logger.error({err:n},"Failed to send error message")}}}),t.on("error",s=>{this.logger.error({platform:e,err:s},"Adapter error")}),t.on("connected",()=>{this.logger.info({platform:e},"Adapter connected")}),t.on("disconnected",()=>{this.logger.warn({platform:e},"Adapter disconnected")})}loadSecurityRules(){let e=Ds.resolve(this.config.security.rulesPath),t=[];if(!Ns.existsSync(e))return this.logger.warn({rulesPath:e},"Security rules directory not found, using default deny"),t;if(!Ns.statSync(e).isDirectory())return this.logger.warn({rulesPath:e},"Security rules path is not a directory"),t;let r=Ns.readdirSync(e).filter(n=>n.endsWith(".yml")||n.endsWith(".yaml"));for(let n of r)try{let o=Ds.join(e,n),i=Ns.readFileSync(o,"utf-8"),a=xa.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 Do=g(()=>{"use strict"});var Wr=g(()=>{"use strict";No();vr();kr();xr();Ir();$r();Ar();Rr();Mr();Nr();Lr();Ur();Pr();Cr();Do();Or()});var Oo={};se(Oo,{startCommand:()=>Ia});async function Ia(){let l=new V,e;try{e=l.loadConfig()}catch(o){console.error("Failed to load configuration:",o.message),process.exit(1)}let t=bt("cli",e.logger.level);t.info({name:e.name},"Configuration loaded");let s=new Oe(e),r=!1,n=d(async o=>{if(!r){r=!0,t.info({signal:o},"Received shutdown signal");try{await s.stop(),t.info("Graceful shutdown complete"),process.exit(0)}catch(i){t.error({error:i},"Error during shutdown"),process.exit(1)}}},"shutdown");process.on("SIGINT",()=>n("SIGINT")),process.on("SIGTERM",()=>n("SIGTERM")),process.on("uncaughtException",o=>{t.fatal({error:o},"Uncaught exception"),n("uncaughtException")}),process.on("unhandledRejection",o=>{t.fatal({reason:o},"Unhandled rejection"),n("unhandledRejection")});try{await s.initialize(),await s.start(),t.info("Alfred is ready")}catch(o){t.fatal({error:o},"Failed to start Alfred"),process.exit(1)}}var Co=g(()=>{"use strict";Se();Qs();Wr();d(Ia,"startCommand")});var Uo={};se(Uo,{chatCommand:()=>$a});async function $a(l){let e=new V,t;try{t=e.loadConfig()}catch(r){console.error("Failed to load configuration:",r.message),process.exit(1)}if(t.logger.level="warn",l.model&&(t.llm.default.model=l.model),l.tier){let r=t.llm[l.tier];r?t.llm.default=r:(console.error(`Unknown tier: ${l.tier}. Available tiers: default, strong, fast, embeddings, local`),process.exit(1))}let s=new Oe(t);try{await s.initialize(),await s.startWithCLI()}catch(r){console.error("Failed to start chat:",r.message),process.exit(1)}}var Po=g(()=>{"use strict";Se();Wr();d($a,"chatCommand")});var jo={};se(jo,{setupCommand:()=>Ca});import{createInterface as Aa}from"node:readline/promises";import{stdin as Ra,stdout as La}from"node:process";import Y from"node:fs";import ue from"node:path";import zr from"js-yaml";function B(l){return`${Cs}${l}${M}`}function Da(l){return`${G}${l}${M}`}function Ee(l){return`${Us}${l}${M}`}function Fo(l){return`${Ma}${l}${M}`}function x(l){return`${ht}${l}${M}`}function b(l){return`${be}${l}${M}`}function Ce(l){return l.length<=4?"****":"*".repeat(l.length-4)+l.slice(-4)}function Oa(l){let e={},t={},s=!1,r=!1,n=30,o=ue.join(l,"config","default.yml");if(Y.existsSync(o))try{let m=zr.load(Y.readFileSync(o,"utf-8"));m&&typeof m=="object"&&Object.assign(e,m)}catch{}let i=ue.join(l,".env");if(Y.existsSync(i))try{let m=Y.readFileSync(i,"utf-8").split(`
543
+ `);for(let h of m){let E=h.trim();if(!E||E.startsWith("#"))continue;let f=E.indexOf("=");f>0&&(t[E.slice(0,f)]=E.slice(f+1))}}catch{}let a=ue.join(l,"config","rules","default-rules.yml");if(Y.existsSync(a))try{let m=zr.load(Y.readFileSync(a,"utf-8"));if(m?.rules){s=m.rules.some(f=>f.id==="allow-owner-admin"&&f.effect==="allow"),m.rules.find(f=>f.id==="allow-write-for-dm"||f.id==="allow-write-all")?.id==="allow-write-all"&&(r=!0);let E=m.rules.find(f=>f.id==="rate-limit-write");E?.rateLimit?.maxInvocations&&(n=E.rateLimit.maxInvocations)}}catch{}let c=!!e.codeSandbox?.enabled,u=e.llm,p={};if(u){for(let m of["strong","fast","embeddings","local"])u[m]?.provider&&u[m]?.model&&(p[m]=u[m]);u.default?.provider&&(e.llm={...e.llm,provider:u.default.provider,model:u.default.model,baseUrl:u.default.baseUrl})}return{config:e,env:t,shellEnabled:s,writeInGroups:r,rateLimit:n,codeSandboxEnabled:c,multiModelTiers:p}}async function Ca(){let l=Aa({input:Ra,output:La}),e=process.cwd(),t=Oa(e),s=Object.keys(t.config).length>0;try{Ua(),console.log(s?`${Us}Existing configuration found \u2014 press Enter to keep current values.${M}
544
+ ${be}Only change what you need to update.${M}
545
+ `:`${Us}Welcome to the Alfred setup wizard!${M}
546
+ ${be}This will walk you through configuring your AI assistant.${M}
547
+ ${be}Press Enter to accept defaults shown in [brackets].${M}
548
548
  `);let r=await W(l,"What should your bot be called?",t.config.name??"Alfred"),n=t.config.llm?.provider?Te.findIndex(w=>w.name===t.config.llm?.provider):-1,o=n>=0?n+1:1;console.log(`
549
- ${x("Which LLM provider would you like to use?")}`);for(let w=0;w<Te.length;w++){let S=w===n?` ${b("(current)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${Te[w].label}${S}`)}let i=await Os(l,"> ",1,Te.length,o),a=Te[i-1];console.log(` ${j(">")} Selected: ${x(a.label)}`);let c="",u=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),u?c=await W(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,u):c=await de(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${j(">")} API key set: ${b(Ce(c))}`));let p=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let S=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(S){let $={ollama:"Ollama URL (use a remote address if Ollama runs on another machine)",openwebui:"OpenWebUI URL",openai:"OpenAI-compatible API URL (leave default for official API)",openrouter:"OpenRouter API URL",google:"Google Gemini API URL (leave default for official API)"};console.log(""),p=await W(l,$[a.name]??"API Base URL",S.replace(/\/+$/,"")),p=p.replace(/\/+$/,""),console.log(` ${j(">")} URL: ${b(p)}`)}}let h=t.config.llm?.model??a.defaultModel;console.log("");let E=await W(l,"Which model?",h),f=Object.keys(t.multiModelTiers).length>0,T=f?"Y/n":"y/N";console.log(`
550
- ${x("Configure additional model tiers for specialized tasks?")}`),console.log(`${b("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let _=(await l.question(`${G}> ${L}${b(`[${T}] `)}`)).trim().toLowerCase(),I=_===""?f:_==="y"||_==="yes",v={};if(I){let w=[{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 S of w){let $=t.multiModelTiers[S.key],q=!!$?.model;console.log(`
551
- ${x(`${S.label} model`)} ${b(`(${S.hint})`)}`),q&&console.log(` ${b(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${b("Press Enter to skip.")}`);let le=(await l.question(` ${G}Model: ${L}${q?b(`[${$.model}] `):""}`)).trim()||(q?$.model:"");if(!le){console.log(` ${b("Skipped.")}`);continue}let Pe=$?.provider??a.name,Tt=Te.map(fs=>fs.name).join(", ");console.log(` ${b(`Providers: ${Tt}`)}`);let te=(await l.question(` ${G}Provider: ${L}${b(`[${Pe}] `)}`)).trim()||Pe,hs,Ks;if(te!==a.name){let fs=$?.apiKey??t.env[`ALFRED_LLM_${S.key.toUpperCase()}_API_KEY`]??"";if(fs?hs=await W(l,` API key for ${te}`,fs):(Te.find(gs=>gs.name===te)?.needsApiKey??!0)&&(hs=await de(l,` API key for ${te}`)),["ollama","openwebui"].includes(te)){let gs=($?.baseUrl??"")||Te.find(mi=>mi.name===te)?.baseUrl||"";gs&&(Ks=await W(l,` ${te} URL`,gs))}}v[S.key]={provider:te,model:le,...hs?{apiKey:hs}:{},...Ks?{baseUrl:Ks}:{}},console.log(` ${j(">")} ${S.label}: ${x(te)}/${x(le)}`)}Object.keys(v).length===0&&console.log(`
552
- ${b("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${b("Using single model for all tasks.")}`);let M=["brave","tavily","duckduckgo","searxng"],A=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",D=M.indexOf(A),C=D>=0?D+1:0;console.log(`
553
- ${x("Web Search provider (for searching the internet):")}`);let J=["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"],Ue=d(w=>D===w?` ${b("(current)")}`:"","mark");console.log(` ${Ee("0)")} None (disable web search)${D===-1&&A===""?` ${b("(current)")}`:""}`);for(let w=0;w<J.length;w++)console.log(` ${Ee(String(w+1)+")")} ${J[w]}${Ue(w)}`);let ie=await Os(l,"> ",0,M.length,C),H,N="",B="";if(ie>=1&&ie<=M.length&&(H=M[ie-1]),H==="brave"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?N=await W(l," Brave Search API key",w):(console.log(` ${b("Get your free API key at: https://brave.com/search/api/")}`),N=await de(l," Brave Search API key")),console.log(` ${j(">")} Brave Search: ${b(Ce(N))}`)}else if(H==="tavily"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?N=await W(l," Tavily API key",w):(console.log(` ${b("Get your free API key at: https://tavily.com/")}`),N=await de(l," Tavily API key")),console.log(` ${j(">")} Tavily: ${b(Ce(N))}`)}else if(H==="duckduckgo")console.log(` ${j(">")} DuckDuckGo: ${b("no API key needed")}`);else if(H==="searxng"){let w=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";B=await W(l," SearXNG URL",w),B=B.replace(/\/+$/,""),console.log(` ${j(">")} SearXNG: ${b(B)}`)}else console.log(` ${b("Web search disabled \u2014 you can configure it later.")}`);let pe=[];for(let w=0;w<mt.length;w++){let S=mt[w];t.config[S.configKey]?.enabled&&pe.push(w+1)}let O=pe.length>0?pe.join(","):"";console.log(`
554
- ${x("Which messaging platforms do you want to enable?")}`),console.log(`${b("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<mt.length;w++){let S=pe.includes(w+1)?` ${b("(enabled)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${mt[w].label}${S}`)}console.log(` ${Ee("0)")} None (configure later)`);let z=(await l.question(`${G}> ${L}${O?b(`[${O}] `):""}`)).trim(),U=[],X=z||O;if(X&&X!=="0"){let w=X.split(",").map(S=>parseInt(S.trim(),10));for(let S of w)if(S>=1&&S<=mt.length){let $=mt[S-1];U.includes($)||U.push($)}}U.length>0?console.log(` ${j(">")} Enabling: ${U.map(w=>x(w.label)).join(", ")}`):console.log(` ${b("No platforms selected \u2014 you can configure them later.")}`);let Z={},ce={};for(let w of U){if(w.credentials.length===0){w.name==="whatsapp"&&console.log(`
549
+ ${x("Which LLM provider would you like to use?")}`);for(let w=0;w<Te.length;w++){let S=w===n?` ${b("(current)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${Te[w].label}${S}`)}let i=await Os(l,"> ",1,Te.length,o),a=Te[i-1];console.log(` ${B(">")} Selected: ${x(a.label)}`);let c="",u=t.env[a.envKeyName]??"";a.needsApiKey&&(console.log(""),u?c=await W(l,`${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`,u):c=await de(l,`Enter your ${a.name.charAt(0).toUpperCase()+a.name.slice(1)} API key`),console.log(` ${B(">")} API key set: ${b(Ce(c))}`));let p=a.baseUrl??"";if(["ollama","openwebui","openai","openrouter","google"].includes(a.name)){let S=(t.config.llm?.baseUrl??t.env.ALFRED_LLM_BASE_URL??"")||a.baseUrl||"";if(S){let $={ollama:"Ollama URL (use a remote address if Ollama runs on another machine)",openwebui:"OpenWebUI URL",openai:"OpenAI-compatible API URL (leave default for official API)",openrouter:"OpenRouter API URL",google:"Google Gemini API URL (leave default for official API)"};console.log(""),p=await W(l,$[a.name]??"API Base URL",S.replace(/\/+$/,"")),p=p.replace(/\/+$/,""),console.log(` ${B(">")} URL: ${b(p)}`)}}let h=t.config.llm?.model??a.defaultModel;console.log("");let E=await W(l,"Which model?",h),f=Object.keys(t.multiModelTiers).length>0,T=f?"Y/n":"y/N";console.log(`
550
+ ${x("Configure additional model tiers for specialized tasks?")}`),console.log(`${b("Optional: use different models for complex tasks, quick replies, embeddings, or offline.")}`);let _=(await l.question(`${G}> ${M}${b(`[${T}] `)}`)).trim().toLowerCase(),I=_===""?f:_==="y"||_==="yes",v={};if(I){let w=[{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 S of w){let $=t.multiModelTiers[S.key],q=!!$?.model;console.log(`
551
+ ${x(`${S.label} model`)} ${b(`(${S.hint})`)}`),q&&console.log(` ${b(`Current: ${$.provider}/${$.model}`)}`),console.log(` ${b("Press Enter to skip.")}`);let le=(await l.question(` ${G}Model: ${M}${q?b(`[${$.model}] `):""}`)).trim()||(q?$.model:"");if(!le){console.log(` ${b("Skipped.")}`);continue}let Pe=$?.provider??a.name,Tt=Te.map(fs=>fs.name).join(", ");console.log(` ${b(`Providers: ${Tt}`)}`);let te=(await l.question(` ${G}Provider: ${M}${b(`[${Pe}] `)}`)).trim()||Pe,hs,Ks;if(te!==a.name){let fs=$?.apiKey??t.env[`ALFRED_LLM_${S.key.toUpperCase()}_API_KEY`]??"";if(fs?hs=await W(l,` API key for ${te}`,fs):(Te.find(gs=>gs.name===te)?.needsApiKey??!0)&&(hs=await de(l,` API key for ${te}`)),["ollama","openwebui"].includes(te)){let gs=($?.baseUrl??"")||Te.find(mi=>mi.name===te)?.baseUrl||"";gs&&(Ks=await W(l,` ${te} URL`,gs))}}v[S.key]={provider:te,model:le,...hs?{apiKey:hs}:{},...Ks?{baseUrl:Ks}:{}},console.log(` ${B(">")} ${S.label}: ${x(te)}/${x(le)}`)}Object.keys(v).length===0&&console.log(`
552
+ ${b("No additional tiers configured \u2014 using single model.")}`)}else console.log(` ${b("Using single model for all tasks.")}`);let N=["brave","tavily","duckduckgo","searxng"],A=t.config.search?.provider??t.env.ALFRED_SEARCH_PROVIDER??"",D=N.indexOf(A),C=D>=0?D+1:0;console.log(`
553
+ ${x("Web Search provider (for searching the internet):")}`);let J=["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"],Ue=d(w=>D===w?` ${b("(current)")}`:"","mark");console.log(` ${Ee("0)")} None (disable web search)${D===-1&&A===""?` ${b("(current)")}`:""}`);for(let w=0;w<J.length;w++)console.log(` ${Ee(String(w+1)+")")} ${J[w]}${Ue(w)}`);let ie=await Os(l,"> ",0,N.length,C),H,R="",F="";if(ie>=1&&ie<=N.length&&(H=N[ie-1]),H==="brave"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?R=await W(l," Brave Search API key",w):(console.log(` ${b("Get your free API key at: https://brave.com/search/api/")}`),R=await de(l," Brave Search API key")),console.log(` ${B(">")} Brave Search: ${b(Ce(R))}`)}else if(H==="tavily"){let w=t.env.ALFRED_SEARCH_API_KEY??"";w?R=await W(l," Tavily API key",w):(console.log(` ${b("Get your free API key at: https://tavily.com/")}`),R=await de(l," Tavily API key")),console.log(` ${B(">")} Tavily: ${b(Ce(R))}`)}else if(H==="duckduckgo")console.log(` ${B(">")} DuckDuckGo: ${b("no API key needed")}`);else if(H==="searxng"){let w=t.config.search?.baseUrl??t.env.ALFRED_SEARCH_BASE_URL??"http://localhost:8080";F=await W(l," SearXNG URL",w),F=F.replace(/\/+$/,""),console.log(` ${B(">")} SearXNG: ${b(F)}`)}else console.log(` ${b("Web search disabled \u2014 you can configure it later.")}`);let pe=[];for(let w=0;w<mt.length;w++){let S=mt[w];t.config[S.configKey]?.enabled&&pe.push(w+1)}let O=pe.length>0?pe.join(","):"";console.log(`
554
+ ${x("Which messaging platforms do you want to enable?")}`),console.log(`${b("(Enter comma-separated numbers, e.g. 1,3)")}`);for(let w=0;w<mt.length;w++){let S=pe.includes(w+1)?` ${b("(enabled)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${mt[w].label}${S}`)}console.log(` ${Ee("0)")} None (configure later)`);let z=(await l.question(`${G}> ${M}${O?b(`[${O}] `):""}`)).trim(),U=[],X=z||O;if(X&&X!=="0"){let w=X.split(",").map(S=>parseInt(S.trim(),10));for(let S of w)if(S>=1&&S<=mt.length){let $=mt[S-1];U.includes($)||U.push($)}}U.length>0?console.log(` ${B(">")} Enabling: ${U.map(w=>x(w.label)).join(", ")}`):console.log(` ${b("No platforms selected \u2014 you can configure them later.")}`);let Z={},ce={};for(let w of U){if(w.credentials.length===0){w.name==="whatsapp"&&console.log(`
555
555
  ${Da("i")} WhatsApp: a QR code will be displayed on first start.`);continue}console.log(`
556
- ${x(w.label+" configuration:")}`);let S={};for(let $ of w.credentials){let q=t.env[$.envKey]??"",ee;q?ee=await W(l,` ${$.prompt}`,q):$.defaultValue?ee=await W(l,` ${$.prompt}`,$.defaultValue):$.required?ee=await de(l,` ${$.prompt}`):(ee=(await l.question(` ${$.prompt}: ${G}`)).trim(),process.stdout.write(L)),S[$.configField]=ee,ce[$.envKey]=ee,$.configField==="token"||$.configField==="accessToken"?console.log(` ${j(">")} Set: ${b(Ce(ee))}`):console.log(` ${j(">")} Set: ${b(ee)}`)}Z[w.configKey]=S}let qr=t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",Kr=!!qr,Qo=Kr?"Y/n":"y/N";console.log(`
557
- ${x("Email access (read & send emails via IMAP/SMTP)?")}`),console.log(`${b("Works with Gmail, Outlook, or any IMAP/SMTP provider.")}`);let Fs=(await l.question(`${G}> ${L}${b(`[${Qo}] `)}`)).trim().toLowerCase(),as=Fs===""?Kr:Fs==="y"||Fs==="yes",me="",cs="",ls="",js=993,Vr="",Bs=587;if(as){console.log(""),me=await W(l," Email address",qr||""),me||(me=await de(l," Email address"));let w=t.env.ALFRED_EMAIL_PASS??"";w?cs=await W(l," Password / App password",w):(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")}`),cs=await de(l," Password / App password"));let S=me.split("@")[1]?.toLowerCase()??"",q={"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"}}[S],ee=t.config.email?.imap?.host??q?.imap??`imap.${S}`,le=t.config.email?.smtp?.host??q?.smtp??`smtp.${S}`,Pe=t.config.email?.imap?.port??993,Tt=t.config.email?.smtp?.port??587;q&&console.log(` ${j(">")} Detected ${S} \u2014 using preset server settings`),ls=await W(l," IMAP server",ee);let fe=await W(l," IMAP port",String(Pe));js=parseInt(fe,10)||993,Vr=await W(l," SMTP server",le);let te=await W(l," SMTP port",String(Tt));Bs=parseInt(te,10)||587,console.log(` ${j(">")} Email: ${b(me)} via ${b(ls)}`)}else console.log(` ${b("Email disabled \u2014 you can configure it later.")}`);let ds=["openai","groq"],ei=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",us=ds.indexOf(ei),ti=us>=0?us+1:0;console.log(`
558
- ${x("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${b("Transcribes voice messages from Telegram, Discord, etc.")}`);let Gr=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Ee("0)")} None (disable voice transcription)${us===-1?` ${b("(current)")}`:""}`);for(let w=0;w<Gr.length;w++){let S=us===w?` ${b("(current)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${Gr[w]}${S}`)}let Ws=await Os(l,"> ",0,ds.length,ti),ae,he="",ft="";if(Ws>=1&&Ws<=ds.length&&(ae=ds[Ws-1]),ae==="openai"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?he=await W(l," OpenAI API key (for Whisper)",w):(console.log(` ${b("Uses your OpenAI API key for Whisper transcription.")}`),he=await de(l," OpenAI API key")),console.log(` ${j(">")} OpenAI Whisper: ${b(Ce(he))}`)}else if(ae==="groq"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?he=await W(l," Groq API key",w):(console.log(` ${b("Get your free API key at: https://console.groq.com/")}`),he=await de(l," Groq API key"));let S=t.env.ALFRED_SPEECH_BASE_URL??"";S&&(ft=await W(l," Groq API URL",S)),console.log(` ${j(">")} Groq Whisper: ${b(Ce(he))}`)}else console.log(` ${b("Voice transcription disabled \u2014 you can configure it later.")}`);let gt=!1,yt="alloy";if(ae){let w=t.config.speech?.ttsEnabled??!1,S=w?"Y/n":"y/N";console.log(`
559
- ${x("Voice responses (Text-to-Speech)?")}`),console.log(`${b("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await l.question(`${G}> ${L}${b(`[${S}] `)}`)).trim().toLowerCase();if(gt=$===""?w:$==="y"||$==="yes",gt){let q=["alloy","echo","fable","onyx","nova","shimmer"],ee=t.config.speech?.ttsVoice??"alloy",le=q.indexOf(ee),Pe=le>=0?le+1:1;console.log(`
560
- ${x("Which voice?")}`);for(let fe=0;fe<q.length;fe++){let te=le===fe?` ${b("(current)")}`:"";console.log(` ${Ee(String(fe+1)+")")} ${q[fe]}${te}`)}let Tt=await Os(l," > ",1,q.length,Pe);yt=q[Tt-1],console.log(` ${j(">")} TTS voice: ${x(yt)}`)}else console.log(` ${b("Voice responses disabled.")}`)}let si=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
561
- ${x("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${b("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let zs=(await l.question(`${G}> ${L}${b(`[${si}] `)}`)).trim().toLowerCase(),Xs=zs===""?t.codeSandboxEnabled:zs==="y"||zs==="yes";console.log(Xs?` ${j(">")} Code Sandbox ${x("enabled")} (JavaScript + Python)`:` ${b("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
562
- ${x("Security configuration:")}`);let Yr=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",Q;if(Yr)Q=await W(l,"Owner user ID (for elevated permissions)",Yr);else{let w=(await l.question(`${ht}Owner user ID${L} ${b("(optional, for elevated permissions)")}: ${G}`)).trim();process.stdout.write(L),Q=w}let wt=!1;if(Q){let w=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${x("Enable shell access (admin commands) for the owner?")}`),console.log(` ${b("Allows Alfred to execute shell commands. Only for the owner.")}`);let S=(await l.question(` ${G}> ${L}${b(`[${w}] `)}`)).trim().toLowerCase();S===""?wt=t.shellEnabled:wt=S==="y"||S==="yes",console.log(wt?` ${j(">")} Shell access ${x("enabled")} for owner ${b(Q)}`:` ${b("Shell access disabled.")}`)}let ri=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${x("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${b("By default, write actions are only allowed in DMs.")}`);let Hs=(await l.question(` ${G}> ${L}${b(`[${ri}] `)}`)).trim().toLowerCase(),Et;Hs===""?Et=t.writeInGroups:Et=Hs==="y"||Hs==="yes",console.log(Et?` ${j(">")} Write actions ${x("enabled")} in groups`:` ${b("Write actions only in DMs (default).")}`);let ni=t.rateLimit??30;console.log("");let oi=await W(l," Rate limit (max write actions per hour per user)",String(ni)),ps=Math.max(1,parseInt(oi,10)||30);console.log(` ${j(">")} Rate limit: ${x(String(ps))} per hour`),console.log(`
563
- ${x("Writing configuration files...")}`);let R=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";R.push(`${w}=${c}`)}if(E!==a.defaultModel&&R.push(`ALFRED_LLM_MODEL=${E}`),p&&R.push(`ALFRED_LLM_BASE_URL=${p}`),Object.keys(v).length>0){R.push("","# === Additional Model Tiers ===");for(let[w,S]of Object.entries(v)){let $=`ALFRED_LLM_${w.toUpperCase()}`;R.push(""),R.push(`${$}_PROVIDER=${S.provider}`),R.push(`${$}_MODEL=${S.model}`),S.apiKey&&R.push(`${$}_API_KEY=${S.apiKey}`),S.baseUrl&&R.push(`${$}_BASE_URL=${S.baseUrl}`)}}R.push("","# === Messaging Platforms ===","");for(let[w,S]of Object.entries(ce))R.push(`${w}=${S}`);R.push("","# === Web Search ===",""),H?(R.push(`ALFRED_SEARCH_PROVIDER=${H}`),N&&R.push(`ALFRED_SEARCH_API_KEY=${N}`),B&&R.push(`ALFRED_SEARCH_BASE_URL=${B}`)):(R.push("# ALFRED_SEARCH_PROVIDER=brave"),R.push("# ALFRED_SEARCH_API_KEY=")),R.push("","# === Email ===",""),as?(R.push(`ALFRED_EMAIL_USER=${me}`),R.push(`ALFRED_EMAIL_PASS=${cs}`)):(R.push("# ALFRED_EMAIL_USER="),R.push("# ALFRED_EMAIL_PASS=")),R.push("","# === Speech ===",""),ae?(R.push(`ALFRED_SPEECH_PROVIDER=${ae}`),R.push(`ALFRED_SPEECH_API_KEY=${he}`),ft&&R.push(`ALFRED_SPEECH_BASE_URL=${ft}`),gt&&(R.push("ALFRED_TTS_ENABLED=true"),R.push(`ALFRED_TTS_VOICE=${yt}`))):(R.push("# ALFRED_SPEECH_PROVIDER=groq"),R.push("# ALFRED_SPEECH_API_KEY=")),R.push("","# === Security ===",""),Q?R.push(`ALFRED_OWNER_USER_ID=${Q}`):R.push("# ALFRED_OWNER_USER_ID="),R.push("");let ii=ue.join(e,".env");Y.writeFileSync(ii,R.join(`
564
- `),"utf-8"),console.log(` ${j("+")} ${b(".env")} written`);let ms=ue.join(e,"config");Y.existsSync(ms)||Y.mkdirSync(ms,{recursive:!0});let Jr={name:r,telegram:{token:Z.telegram?.token??"",enabled:U.some(w=>w.name==="telegram")},discord:{token:Z.discord?.token??"",enabled:U.some(w=>w.name==="discord")},whatsapp:{enabled:U.some(w=>w.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:Z.matrix?.homeserverUrl??"https://matrix.org",accessToken:Z.matrix?.accessToken??"",userId:Z.matrix?.userId??"",enabled:U.some(w=>w.name==="matrix")},signal:{apiUrl:Z.signal?.apiUrl??"http://localhost:8080",phoneNumber:Z.signal?.phoneNumber??"",enabled:U.some(w=>w.name==="signal")},llm:Object.keys(v).length>0?{default:{provider:a.name,model:E,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...v}:{provider:a.name,model:E,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...H?{search:{provider:H,...N?{apiKey:N}:{},...B?{baseUrl:B}:{}}}:{},...as?{email:{imap:{host:ls,port:js,secure:js===993},smtp:{host:Vr,port:Bs,secure:Bs===465},auth:{user:me,pass:cs}}}:{},...ae?{speech:{provider:ae,apiKey:he,...ft?{baseUrl:ft}:{},...gt?{ttsEnabled:!0,ttsVoice:yt}:{}}}:{},...Xs?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};Q&&(Jr.security.ownerUserId=Q);let ai="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+zr.dump(Jr,{lineWidth:120,noRefs:!0,sortKeys:!1}),ci=ue.join(ms,"default.yml");Y.writeFileSync(ci,ai,"utf-8"),console.log(` ${j("+")} ${b("config/default.yml")} written`);let qs=ue.join(ms,"rules");Y.existsSync(qs)||Y.mkdirSync(qs,{recursive:!0});let li=wt&&Q?`
556
+ ${x(w.label+" configuration:")}`);let S={};for(let $ of w.credentials){let q=t.env[$.envKey]??"",ee;q?ee=await W(l,` ${$.prompt}`,q):$.defaultValue?ee=await W(l,` ${$.prompt}`,$.defaultValue):$.required?ee=await de(l,` ${$.prompt}`):(ee=(await l.question(` ${$.prompt}: ${G}`)).trim(),process.stdout.write(M)),S[$.configField]=ee,ce[$.envKey]=ee,$.configField==="token"||$.configField==="accessToken"?console.log(` ${B(">")} Set: ${b(Ce(ee))}`):console.log(` ${B(">")} Set: ${b(ee)}`)}Z[w.configKey]=S}let qr=t.config.email?.auth?.user??t.env.ALFRED_EMAIL_USER??"",Kr=!!qr,Qo=Kr?"Y/n":"y/N";console.log(`
557
+ ${x("Email access (read & send emails via IMAP/SMTP)?")}`),console.log(`${b("Works with Gmail, Outlook, or any IMAP/SMTP provider.")}`);let Fs=(await l.question(`${G}> ${M}${b(`[${Qo}] `)}`)).trim().toLowerCase(),as=Fs===""?Kr:Fs==="y"||Fs==="yes",me="",cs="",ls="",js=993,Vr="",Bs=587;if(as){console.log(""),me=await W(l," Email address",qr||""),me||(me=await de(l," Email address"));let w=t.env.ALFRED_EMAIL_PASS??"";w?cs=await W(l," Password / App password",w):(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")}`),cs=await de(l," Password / App password"));let S=me.split("@")[1]?.toLowerCase()??"",q={"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"}}[S],ee=t.config.email?.imap?.host??q?.imap??`imap.${S}`,le=t.config.email?.smtp?.host??q?.smtp??`smtp.${S}`,Pe=t.config.email?.imap?.port??993,Tt=t.config.email?.smtp?.port??587;q&&console.log(` ${B(">")} Detected ${S} \u2014 using preset server settings`),ls=await W(l," IMAP server",ee);let fe=await W(l," IMAP port",String(Pe));js=parseInt(fe,10)||993,Vr=await W(l," SMTP server",le);let te=await W(l," SMTP port",String(Tt));Bs=parseInt(te,10)||587,console.log(` ${B(">")} Email: ${b(me)} via ${b(ls)}`)}else console.log(` ${b("Email disabled \u2014 you can configure it later.")}`);let ds=["openai","groq"],ei=t.config.speech?.provider??t.env.ALFRED_SPEECH_PROVIDER??"",us=ds.indexOf(ei),ti=us>=0?us+1:0;console.log(`
558
+ ${x("Voice message transcription (Speech-to-Text via Whisper)?")}`),console.log(`${b("Transcribes voice messages from Telegram, Discord, etc.")}`);let Gr=["OpenAI Whisper \u2014 best quality","Groq Whisper \u2014 fast & free"];console.log(` ${Ee("0)")} None (disable voice transcription)${us===-1?` ${b("(current)")}`:""}`);for(let w=0;w<Gr.length;w++){let S=us===w?` ${b("(current)")}`:"";console.log(` ${Ee(String(w+1)+")")} ${Gr[w]}${S}`)}let Ws=await Os(l,"> ",0,ds.length,ti),ae,he="",ft="";if(Ws>=1&&Ws<=ds.length&&(ae=ds[Ws-1]),ae==="openai"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?he=await W(l," OpenAI API key (for Whisper)",w):(console.log(` ${b("Uses your OpenAI API key for Whisper transcription.")}`),he=await de(l," OpenAI API key")),console.log(` ${B(">")} OpenAI Whisper: ${b(Ce(he))}`)}else if(ae==="groq"){let w=t.env.ALFRED_SPEECH_API_KEY??"";w?he=await W(l," Groq API key",w):(console.log(` ${b("Get your free API key at: https://console.groq.com/")}`),he=await de(l," Groq API key"));let S=t.env.ALFRED_SPEECH_BASE_URL??"";S&&(ft=await W(l," Groq API URL",S)),console.log(` ${B(">")} Groq Whisper: ${b(Ce(he))}`)}else console.log(` ${b("Voice transcription disabled \u2014 you can configure it later.")}`);let gt=!1,yt="alloy";if(ae){let w=t.config.speech?.ttsEnabled??!1,S=w?"Y/n":"y/N";console.log(`
559
+ ${x("Voice responses (Text-to-Speech)?")}`),console.log(`${b("Alfred can reply as a voice message when the user asks for it.")}`);let $=(await l.question(`${G}> ${M}${b(`[${S}] `)}`)).trim().toLowerCase();if(gt=$===""?w:$==="y"||$==="yes",gt){let q=["alloy","echo","fable","onyx","nova","shimmer"],ee=t.config.speech?.ttsVoice??"alloy",le=q.indexOf(ee),Pe=le>=0?le+1:1;console.log(`
560
+ ${x("Which voice?")}`);for(let fe=0;fe<q.length;fe++){let te=le===fe?` ${b("(current)")}`:"";console.log(` ${Ee(String(fe+1)+")")} ${q[fe]}${te}`)}let Tt=await Os(l," > ",1,q.length,Pe);yt=q[Tt-1],console.log(` ${B(">")} TTS voice: ${x(yt)}`)}else console.log(` ${b("Voice responses disabled.")}`)}let si=t.codeSandboxEnabled?"Y/n":"y/N";console.log(`
561
+ ${x("Code Sandbox (execute Python/JavaScript in a sandboxed environment)?")}`),console.log(`${b("Enables code execution for calculations, data processing, PDF generation, charts, etc.")}`);let zs=(await l.question(`${G}> ${M}${b(`[${si}] `)}`)).trim().toLowerCase(),Xs=zs===""?t.codeSandboxEnabled:zs==="y"||zs==="yes";console.log(Xs?` ${B(">")} Code Sandbox ${x("enabled")} (JavaScript + Python)`:` ${b("Code Sandbox disabled \u2014 you can enable it later in config/default.yml.")}`),console.log(`
562
+ ${x("Security configuration:")}`);let Yr=t.config.security?.ownerUserId??t.env.ALFRED_OWNER_USER_ID??"",Q;if(Yr)Q=await W(l,"Owner user ID (for elevated permissions)",Yr);else{let w=(await l.question(`${ht}Owner user ID${M} ${b("(optional, for elevated permissions)")}: ${G}`)).trim();process.stdout.write(M),Q=w}let wt=!1;if(Q){let w=t.shellEnabled?"Y/n":"y/N";console.log(""),console.log(` ${x("Enable shell access (admin commands) for the owner?")}`),console.log(` ${b("Allows Alfred to execute shell commands. Only for the owner.")}`);let S=(await l.question(` ${G}> ${M}${b(`[${w}] `)}`)).trim().toLowerCase();S===""?wt=t.shellEnabled:wt=S==="y"||S==="yes",console.log(wt?` ${B(">")} Shell access ${x("enabled")} for owner ${b(Q)}`:` ${b("Shell access disabled.")}`)}let ri=t.writeInGroups?"Y/n":"y/N";console.log(""),console.log(` ${x("Allow write actions (notes, reminders, memory) in group chats?")}`),console.log(` ${b("By default, write actions are only allowed in DMs.")}`);let Hs=(await l.question(` ${G}> ${M}${b(`[${ri}] `)}`)).trim().toLowerCase(),Et;Hs===""?Et=t.writeInGroups:Et=Hs==="y"||Hs==="yes",console.log(Et?` ${B(">")} Write actions ${x("enabled")} in groups`:` ${b("Write actions only in DMs (default).")}`);let ni=t.rateLimit??30;console.log("");let oi=await W(l," Rate limit (max write actions per hour per user)",String(ni)),ps=Math.max(1,parseInt(oi,10)||30);console.log(` ${B(">")} Rate limit: ${x(String(ps))} per hour`),console.log(`
563
+ ${x("Writing configuration files...")}`);let L=["# Alfred Environment Variables","# Generated by `alfred setup`","","# === LLM ===","",`ALFRED_LLM_PROVIDER=${a.name}`];if(c){let w=a.envKeyName||"ALFRED_OLLAMA_API_KEY";L.push(`${w}=${c}`)}if(E!==a.defaultModel&&L.push(`ALFRED_LLM_MODEL=${E}`),p&&L.push(`ALFRED_LLM_BASE_URL=${p}`),Object.keys(v).length>0){L.push("","# === Additional Model Tiers ===");for(let[w,S]of Object.entries(v)){let $=`ALFRED_LLM_${w.toUpperCase()}`;L.push(""),L.push(`${$}_PROVIDER=${S.provider}`),L.push(`${$}_MODEL=${S.model}`),S.apiKey&&L.push(`${$}_API_KEY=${S.apiKey}`),S.baseUrl&&L.push(`${$}_BASE_URL=${S.baseUrl}`)}}L.push("","# === Messaging Platforms ===","");for(let[w,S]of Object.entries(ce))L.push(`${w}=${S}`);L.push("","# === Web Search ===",""),H?(L.push(`ALFRED_SEARCH_PROVIDER=${H}`),R&&L.push(`ALFRED_SEARCH_API_KEY=${R}`),F&&L.push(`ALFRED_SEARCH_BASE_URL=${F}`)):(L.push("# ALFRED_SEARCH_PROVIDER=brave"),L.push("# ALFRED_SEARCH_API_KEY=")),L.push("","# === Email ===",""),as?(L.push(`ALFRED_EMAIL_USER=${me}`),L.push(`ALFRED_EMAIL_PASS=${cs}`)):(L.push("# ALFRED_EMAIL_USER="),L.push("# ALFRED_EMAIL_PASS=")),L.push("","# === Speech ===",""),ae?(L.push(`ALFRED_SPEECH_PROVIDER=${ae}`),L.push(`ALFRED_SPEECH_API_KEY=${he}`),ft&&L.push(`ALFRED_SPEECH_BASE_URL=${ft}`),gt&&(L.push("ALFRED_TTS_ENABLED=true"),L.push(`ALFRED_TTS_VOICE=${yt}`))):(L.push("# ALFRED_SPEECH_PROVIDER=groq"),L.push("# ALFRED_SPEECH_API_KEY=")),L.push("","# === Security ===",""),Q?L.push(`ALFRED_OWNER_USER_ID=${Q}`):L.push("# ALFRED_OWNER_USER_ID="),L.push("");let ii=ue.join(e,".env");Y.writeFileSync(ii,L.join(`
564
+ `),"utf-8"),console.log(` ${B("+")} ${b(".env")} written`);let ms=ue.join(e,"config");Y.existsSync(ms)||Y.mkdirSync(ms,{recursive:!0});let Jr={name:r,telegram:{token:Z.telegram?.token??"",enabled:U.some(w=>w.name==="telegram")},discord:{token:Z.discord?.token??"",enabled:U.some(w=>w.name==="discord")},whatsapp:{enabled:U.some(w=>w.name==="whatsapp"),dataPath:"./data/whatsapp"},matrix:{homeserverUrl:Z.matrix?.homeserverUrl??"https://matrix.org",accessToken:Z.matrix?.accessToken??"",userId:Z.matrix?.userId??"",enabled:U.some(w=>w.name==="matrix")},signal:{apiUrl:Z.signal?.apiUrl??"http://localhost:8080",phoneNumber:Z.signal?.phoneNumber??"",enabled:U.some(w=>w.name==="signal")},llm:Object.keys(v).length>0?{default:{provider:a.name,model:E,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...v}:{provider:a.name,model:E,...p?{baseUrl:p}:{},temperature:.7,maxTokens:4096},...H?{search:{provider:H,...R?{apiKey:R}:{},...F?{baseUrl:F}:{}}}:{},...as?{email:{imap:{host:ls,port:js,secure:js===993},smtp:{host:Vr,port:Bs,secure:Bs===465},auth:{user:me,pass:cs}}}:{},...ae?{speech:{provider:ae,apiKey:he,...ft?{baseUrl:ft}:{},...gt?{ttsEnabled:!0,ttsVoice:yt}:{}}}:{},...Xs?{codeSandbox:{enabled:!0,allowedLanguages:["javascript","python"]}}:{},storage:{path:"./data/alfred.db"},logger:{level:"info",pretty:!0,auditLogPath:"./data/audit.log"},security:{rulesPath:"./config/rules",defaultEffect:"deny"}};Q&&(Jr.security.ownerUserId=Q);let ai="# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n"+zr.dump(Jr,{lineWidth:120,noRefs:!0,sortKeys:!1}),ci=ue.join(ms,"default.yml");Y.writeFileSync(ci,ai,"utf-8"),console.log(` ${B("+")} ${b("config/default.yml")} written`);let qs=ue.join(ms,"rules");Y.existsSync(qs)||Y.mkdirSync(qs,{recursive:!0});let li=wt&&Q?`
565
565
  # Allow admin actions (shell, etc.) for the owner only
566
566
  - id: allow-owner-admin
567
567
  effect: allow
@@ -637,14 +637,14 @@ ${li}
637
637
  scope: global
638
638
  actions: ["*"]
639
639
  riskLevels: [read, write, destructive, admin]
640
- `,ui=ue.join(qs,"default-rules.yml");Y.writeFileSync(ui,di,"utf-8"),console.log(` ${j("+")} ${b("config/rules/default-rules.yml")} written`);let Zr=ue.join(e,"data");Y.existsSync(Zr)||(Y.mkdirSync(Zr,{recursive:!0}),console.log(` ${j("+")} ${b("data/")} directory created`)),console.log(""),console.log(`${Cs}${"=".repeat(52)}${L}`),console.log(`${Cs}${ht} Setup complete!${L}`),console.log(`${Cs}${"=".repeat(52)}${L}`),console.log(""),console.log(` ${x("Bot name:")} ${r}`),console.log(` ${x("LLM default:")} ${a.name} (${E})`),c&&console.log(` ${x("API key:")} ${Ce(c)}`);for(let[w,S]of Object.entries(v)){let $=w.charAt(0).toUpperCase()+w.slice(1);console.log(` ${x(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${S.provider} (${S.model})`)}if(U.length>0?console.log(` ${x("Platforms:")} ${U.map(w=>w.label).join(", ")}`):console.log(` ${x("Platforms:")} none (configure later)`),H){let w={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${B})`};console.log(` ${x("Web search:")} ${w[H]}`)}else console.log(` ${x("Web search:")} ${b("disabled")}`);if(console.log(as?` ${x("Email:")} ${me} (${ls})`:` ${x("Email:")} ${b("disabled")}`),ae){let w={openai:"OpenAI Whisper",groq:"Groq Whisper"},S=gt?`, TTS: ${yt}`:"";console.log(` ${x("Voice:")} ${w[ae]}${S}`)}else console.log(` ${x("Voice:")} ${b("disabled")}`);console.log(` ${x("Code Sandbox:")} ${Xs?j("enabled"):b("disabled")}`),Q&&(console.log(` ${x("Owner ID:")} ${Q}`),console.log(` ${x("Shell access:")} ${wt?j("enabled"):b("disabled")}`)),console.log(` ${x("Write scope:")} ${Et?"DMs + Groups":"DMs only"}`),console.log(` ${x("Rate limit:")} ${ps}/hour per user`),console.log(""),console.log(`${Us}Next steps:${L}`),console.log(` ${x("alfred start")} Start Alfred`),console.log(` ${x("alfred status")} Check configuration`),console.log(` ${x("alfred --help")} Show all commands`),console.log(""),console.log(`${be}Edit ${x(".env")}${be} or ${x("config/default.yml")}${be} for manual configuration.${L}`),console.log("")}finally{l.close()}}async function W(l,e,t){let s=(await l.question(`${ht}${e}${L} ${b(`[${t}]`)}: ${G}`)).trim();return process.stdout.write(L),s||t}async function de(l,e){for(;;){let t=(await l.question(`${ht}${e}${L}: ${G}`)).trim();if(process.stdout.write(L),t)return t;console.log(` ${Fo("!")} This field is required. Please enter a value.`)}}async function Os(l,e,t,s,r){for(;;){let n=(await l.question(`${G}${e}${L}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Fo("!")} Please enter a number between ${t} and ${s}.`)}}function Ua(){console.log(`
640
+ `,ui=ue.join(qs,"default-rules.yml");Y.writeFileSync(ui,di,"utf-8"),console.log(` ${B("+")} ${b("config/rules/default-rules.yml")} written`);let Zr=ue.join(e,"data");Y.existsSync(Zr)||(Y.mkdirSync(Zr,{recursive:!0}),console.log(` ${B("+")} ${b("data/")} directory created`)),console.log(""),console.log(`${Cs}${"=".repeat(52)}${M}`),console.log(`${Cs}${ht} Setup complete!${M}`),console.log(`${Cs}${"=".repeat(52)}${M}`),console.log(""),console.log(` ${x("Bot name:")} ${r}`),console.log(` ${x("LLM default:")} ${a.name} (${E})`),c&&console.log(` ${x("API key:")} ${Ce(c)}`);for(let[w,S]of Object.entries(v)){let $=w.charAt(0).toUpperCase()+w.slice(1);console.log(` ${x(`LLM ${$}:`)}${" ".repeat(Math.max(1,10-$.length))}${S.provider} (${S.model})`)}if(U.length>0?console.log(` ${x("Platforms:")} ${U.map(w=>w.label).join(", ")}`):console.log(` ${x("Platforms:")} none (configure later)`),H){let w={brave:"Brave Search",tavily:"Tavily",duckduckgo:"DuckDuckGo",searxng:`SearXNG (${F})`};console.log(` ${x("Web search:")} ${w[H]}`)}else console.log(` ${x("Web search:")} ${b("disabled")}`);if(console.log(as?` ${x("Email:")} ${me} (${ls})`:` ${x("Email:")} ${b("disabled")}`),ae){let w={openai:"OpenAI Whisper",groq:"Groq Whisper"},S=gt?`, TTS: ${yt}`:"";console.log(` ${x("Voice:")} ${w[ae]}${S}`)}else console.log(` ${x("Voice:")} ${b("disabled")}`);console.log(` ${x("Code Sandbox:")} ${Xs?B("enabled"):b("disabled")}`),Q&&(console.log(` ${x("Owner ID:")} ${Q}`),console.log(` ${x("Shell access:")} ${wt?B("enabled"):b("disabled")}`)),console.log(` ${x("Write scope:")} ${Et?"DMs + Groups":"DMs only"}`),console.log(` ${x("Rate limit:")} ${ps}/hour per user`),console.log(""),console.log(`${Us}Next steps:${M}`),console.log(` ${x("alfred start")} Start Alfred`),console.log(` ${x("alfred status")} Check configuration`),console.log(` ${x("alfred --help")} Show all commands`),console.log(""),console.log(`${be}Edit ${x(".env")}${be} or ${x("config/default.yml")}${be} for manual configuration.${M}`),console.log("")}finally{l.close()}}async function W(l,e,t){let s=(await l.question(`${ht}${e}${M} ${b(`[${t}]`)}: ${G}`)).trim();return process.stdout.write(M),s||t}async function de(l,e){for(;;){let t=(await l.question(`${ht}${e}${M}: ${G}`)).trim();if(process.stdout.write(M),t)return t;console.log(` ${Fo("!")} This field is required. Please enter a value.`)}}async function Os(l,e,t,s,r){for(;;){let n=(await l.question(`${G}${e}${M}`)).trim();if(!n)return r;let o=parseInt(n,10);if(!Number.isNaN(o)&&o>=t&&o<=s)return o;console.log(` ${Fo("!")} Please enter a number between ${t} and ${s}.`)}}function Ua(){console.log(`
641
641
  ${Na}${ht} _ _ _____ ____ _____ ____
642
642
  / \\ | | | ___| _ \\| ____| _ \\
643
643
  / _ \\ | | | |_ | |_) | _| | | | |
644
644
  / ___ \\| |___| _| | _ <| |___| |_| |
645
- /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${L}
646
- ${be} Personal AI Assistant \u2014 Setup Wizard${L}
647
- `)}var L,ht,be,Cs,G,Us,Ma,Na,Te,mt,Bo=g(()=>{"use strict";L="\x1B[0m",ht="\x1B[1m",be="\x1B[2m",Cs="\x1B[32m",G="\x1B[33m",Us="\x1B[36m",Ma="\x1B[31m",Na="\x1B[35m";d(j,"green");d(Da,"yellow");d(Ee,"cyan");d(Fo,"red");d(x,"bold");d(b,"dim");d(Ce,"maskKey");Te=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0}],mt=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];d(Oa,"loadExistingConfig");d(Ca,"setupCommand");d(W,"askWithDefault");d(de,"askRequired");d(Os,"askNumber");d(Ua,"printBanner")});var zo={};se(zo,{configCommand:()=>Ba});function Fa(l){let e=l.toLowerCase();return Pa.some(t=>e.includes(t))}function ja(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Wo(l){let e={};for(let[t,s]of Object.entries(l))Fa(t)?e[t]=ja(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Wo(s):e[t]=s;return e}async function Ba(){let l=new V,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Wo(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Pa,Xo=g(()=>{"use strict";Se();Pa=["token","apikey","api_key","accesstoken","secret","password"];d(Fa,"isSensitiveKey");d(ja,"redactValue");d(Wo,"redactObject");d(Ba,"configCommand")});var qo={};se(qo,{rulesCommand:()=>za});import Ps from"node:fs";import Ho from"node:path";import Wa from"js-yaml";async function za(){let l=new V,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ho.resolve(e.security.rulesPath);if(!Ps.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Ps.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Ps.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 Ie,o=[],i=[];for(let a of r){let c=Ho.join(t,a);try{let u=Ps.readFileSync(c,"utf-8"),p=Wa.load(u),m=n.loadFromObject(p);o.push(...m)}catch(u){i.push(` ${a}: ${u.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Ko=g(()=>{"use strict";Se();Ts();d(za,"rulesCommand")});var Vo={};se(Vo,{statusCommand:()=>Ha});import is from"node:fs";import Xr from"node:path";import Xa from"js-yaml";async function Ha(){let l=new V,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let u=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",p=c.enabled?"+":"-";console.log(` [${p}] ${c.name}: ${u}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let u=e.llm[c];u&&console.log(` ${c}: ${u.provider}/${u.model}`)}console.log(""),console.log("Storage:");let r=Xr.resolve(e.storage.path),n=is.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Xr.resolve(e.security.rulesPath),i=0,a=0;if(is.existsSync(o)&&is.statSync(o).isDirectory()){let c=is.readdirSync(o).filter(p=>p.endsWith(".yml")||p.endsWith(".yaml"));a=c.length;let u=new Ie;for(let p of c){let m=Xr.join(o,p);try{let h=is.readFileSync(m,"utf-8"),E=Xa.load(h),f=u.loadFromObject(E);i+=f.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 Go=g(()=>{"use strict";Se();Ts();d(Ha,"statusCommand")});var Yo={};se(Yo,{logsCommand:()=>Va});import qa from"node:fs";import Ka from"node:path";async function Va(l){let e=new V,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=Ka.resolve(t.storage.path);if(!qa.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 ke(s);let n=new ve(r.getDb()),o=n.count({}),i=n.query({limit:l});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(l,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let c=a.timestamp.toISOString(),u=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${c} [${u}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var Jo=g(()=>{"use strict";Se();sr();d(Va,"logsCommand")});import{readFileSync as Ga}from"node:fs";import{fileURLToPath as Ya}from"node:url";import{dirname as Ja,join as Za}from"node:path";function Qa(){try{let l=Ja(Ya(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Ga(Za(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}d(Qa,"getVersion");var Zo=Qa(),Hr=`
645
+ /_/ \\_\\_____|_| |_| \\_\\_____|____/ ${M}
646
+ ${be} Personal AI Assistant \u2014 Setup Wizard${M}
647
+ `)}var M,ht,be,Cs,G,Us,Ma,Na,Te,mt,Bo=g(()=>{"use strict";M="\x1B[0m",ht="\x1B[1m",be="\x1B[2m",Cs="\x1B[32m",G="\x1B[33m",Us="\x1B[36m",Ma="\x1B[31m",Na="\x1B[35m";d(B,"green");d(Da,"yellow");d(Ee,"cyan");d(Fo,"red");d(x,"bold");d(b,"dim");d(Ce,"maskKey");Te=[{name:"anthropic",label:"Anthropic (Claude) \u2014 recommended",defaultModel:"claude-sonnet-4-20250514",envKeyName:"ALFRED_ANTHROPIC_API_KEY",needsApiKey:!0},{name:"openai",label:"OpenAI (GPT)",defaultModel:"gpt-4o",envKeyName:"ALFRED_OPENAI_API_KEY",needsApiKey:!0},{name:"openrouter",label:"OpenRouter (multiple providers)",defaultModel:"anthropic/claude-sonnet-4-20250514",envKeyName:"ALFRED_OPENROUTER_API_KEY",needsApiKey:!0,baseUrl:"https://openrouter.ai/api/v1"},{name:"ollama",label:"Ollama (local, no API key needed)",defaultModel:"llama3.2",envKeyName:"",needsApiKey:!1,baseUrl:"http://localhost:11434"},{name:"openwebui",label:"OpenWebUI (local OpenAI-compatible UI)",defaultModel:"llama3.2",envKeyName:"ALFRED_OPENWEBUI_API_KEY",needsApiKey:!0,baseUrl:"http://localhost:3000/api/v1"},{name:"google",label:"Google (Gemini)",defaultModel:"gemini-2.0-flash",envKeyName:"ALFRED_GOOGLE_API_KEY",needsApiKey:!0}],mt=[{name:"telegram",label:"Telegram",configKey:"telegram",credentials:[{envKey:"ALFRED_TELEGRAM_TOKEN",configField:"token",prompt:"Enter your Telegram Bot token (from @BotFather)",required:!0}]},{name:"discord",label:"Discord",configKey:"discord",credentials:[{envKey:"ALFRED_DISCORD_TOKEN",configField:"token",prompt:"Enter your Discord Bot token",required:!0}]},{name:"whatsapp",label:"WhatsApp",configKey:"whatsapp",credentials:[]},{name:"matrix",label:"Matrix",configKey:"matrix",credentials:[{envKey:"ALFRED_MATRIX_HOMESERVER_URL",configField:"homeserverUrl",prompt:"Enter your Matrix homeserver URL",defaultValue:"https://matrix.org",required:!0},{envKey:"ALFRED_MATRIX_ACCESS_TOKEN",configField:"accessToken",prompt:"Enter your Matrix access token",required:!0},{envKey:"ALFRED_MATRIX_USER_ID",configField:"userId",prompt:"Enter your Matrix user ID (e.g. @bot:matrix.org)",required:!0}]},{name:"signal",label:"Signal",configKey:"signal",credentials:[{envKey:"ALFRED_SIGNAL_API_URL",configField:"apiUrl",prompt:"Enter the Signal REST API URL",defaultValue:"http://localhost:8080",required:!0},{envKey:"ALFRED_SIGNAL_PHONE_NUMBER",configField:"phoneNumber",prompt:"Enter the Signal phone number (e.g. +15551234567)",required:!0}]}];d(Oa,"loadExistingConfig");d(Ca,"setupCommand");d(W,"askWithDefault");d(de,"askRequired");d(Os,"askNumber");d(Ua,"printBanner")});var zo={};se(zo,{configCommand:()=>Ba});function Fa(l){let e=l.toLowerCase();return Pa.some(t=>e.includes(t))}function ja(l){return typeof l!="string"||l.length===0?"(empty)":l.length<=8?"***":l.slice(0,4)+"..."+l.slice(-4)}function Wo(l){let e={};for(let[t,s]of Object.entries(l))Fa(t)?e[t]=ja(s):s!=null&&typeof s=="object"&&!Array.isArray(s)?e[t]=Wo(s):e[t]=s;return e}async function Ba(){let l=new V,e;try{e=l.loadConfig()}catch(s){console.error("Failed to load configuration:",s.message),process.exit(1)}let t=Wo(e);console.log("Alfred \u2014 Resolved Configuration"),console.log("================================"),console.log(JSON.stringify(t,null,2))}var Pa,Xo=g(()=>{"use strict";Se();Pa=["token","apikey","api_key","accesstoken","secret","password"];d(Fa,"isSensitiveKey");d(ja,"redactValue");d(Wo,"redactObject");d(Ba,"configCommand")});var qo={};se(qo,{rulesCommand:()=>za});import Ps from"node:fs";import Ho from"node:path";import Wa from"js-yaml";async function za(){let l=new V,e;try{e=l.loadConfig()}catch(a){console.error("Failed to load configuration:",a.message),process.exit(1)}let t=Ho.resolve(e.security.rulesPath);if(!Ps.existsSync(t)){console.log(`Rules directory not found: ${t}`),console.log("No security rules loaded.");return}Ps.statSync(t).isDirectory()||(console.error(`Rules path is not a directory: ${t}`),process.exit(1));let r=Ps.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 Ie,o=[],i=[];for(let a of r){let c=Ho.join(t,a);try{let u=Ps.readFileSync(c,"utf-8"),p=Wa.load(u),m=n.loadFromObject(p);o.push(...m)}catch(u){i.push(` ${a}: ${u.message}`)}}if(console.log("Alfred \u2014 Security Rules"),console.log("======================="),console.log(`Rules directory: ${t}`),console.log(`Rule files found: ${r.length}`),console.log(`Total rules loaded: ${o.length}`),console.log(""),i.length>0){console.log("Errors:");for(let a of i)console.log(a);console.log("")}if(o.length!==0){o.sort((a,c)=>a.priority-c.priority),console.log("Loaded rules (sorted by priority):"),console.log("");for(let a of o){let c=a.rateLimit?` | rate-limit: ${a.rateLimit.maxInvocations}/${a.rateLimit.windowSeconds}s`:"";console.log(` [${a.priority}] ${a.id}`),console.log(` effect: ${a.effect} | scope: ${a.scope}`),console.log(` actions: ${a.actions.join(", ")}`),console.log(` risk levels: ${a.riskLevels.join(", ")}${c}`),a.conditions&&console.log(` conditions: ${JSON.stringify(a.conditions)}`),console.log("")}}}var Ko=g(()=>{"use strict";Se();Ts();d(za,"rulesCommand")});var Vo={};se(Vo,{statusCommand:()=>Ha});import is from"node:fs";import Xr from"node:path";import Xa from"js-yaml";async function Ha(){let l=new V,e;try{e=l.loadConfig()}catch(c){console.error("Failed to load configuration:",c.message),process.exit(1)}console.log("Alfred \u2014 Status"),console.log("================"),console.log("");let t=[{name:"Telegram",enabled:e.telegram.enabled,configured:!!e.telegram.token},{name:"Discord",enabled:!!e.discord?.enabled,configured:!!e.discord?.token},{name:"WhatsApp",enabled:!!e.whatsapp?.enabled,configured:!!e.whatsapp?.dataPath},{name:"Matrix",enabled:!!e.matrix?.enabled,configured:!!e.matrix?.accessToken},{name:"Signal",enabled:!!e.signal?.enabled,configured:!!e.signal?.phoneNumber}];console.log("Messaging Adapters:");for(let c of t){let u=c.enabled?"enabled":c.configured?"configured (disabled)":"not configured",p=c.enabled?"+":"-";console.log(` [${p}] ${c.name}: ${u}`)}console.log(""),console.log("LLM Provider:");let s=e.llm.default;console.log(` Provider: ${s.provider}`),console.log(` Model: ${s.model}`),console.log(` API Key: ${s.apiKey?"set":"not set"}`),s.baseUrl&&console.log(` Base URL: ${s.baseUrl}`);for(let c of["strong","fast","embeddings","local"]){let u=e.llm[c];u&&console.log(` ${c}: ${u.provider}/${u.model}`)}console.log(""),console.log("Storage:");let r=Xr.resolve(e.storage.path),n=is.existsSync(r);console.log(` Database: ${r}`),console.log(` Status: ${n?"exists":"not yet created"}`),console.log("");let o=Xr.resolve(e.security.rulesPath),i=0,a=0;if(is.existsSync(o)&&is.statSync(o).isDirectory()){let c=is.readdirSync(o).filter(p=>p.endsWith(".yml")||p.endsWith(".yaml"));a=c.length;let u=new Ie;for(let p of c){let m=Xr.join(o,p);try{let h=is.readFileSync(m,"utf-8"),E=Xa.load(h),f=u.loadFromObject(E);i+=f.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 Go=g(()=>{"use strict";Se();Ts();d(Ha,"statusCommand")});var Yo={};se(Yo,{logsCommand:()=>Va});import qa from"node:fs";import Ka from"node:path";async function Va(l){let e=new V,t;try{t=e.loadConfig()}catch(n){console.error("Failed to load configuration:",n.message),process.exit(1)}let s=Ka.resolve(t.storage.path);if(!qa.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 ke(s);let n=new ve(r.getDb()),o=n.count({}),i=n.query({limit:l});if(console.log("Alfred \u2014 Audit Log"),console.log("==================="),console.log(`Total entries: ${o}`),console.log(`Showing last ${Math.min(l,o)} entries:`),console.log(""),i.length===0){console.log("No audit log entries found.");return}for(let a of i){let c=a.timestamp.toISOString(),u=a.effect==="allow"?"ALLOW":"DENY ";console.log(` ${c} [${u}] ${a.action}`),console.log(` user: ${a.userId} | platform: ${a.platform} | risk: ${a.riskLevel}`),a.ruleId&&console.log(` rule: ${a.ruleId}`),a.chatId&&console.log(` chat: ${a.chatId}`),a.context&&console.log(` context: ${JSON.stringify(a.context)}`),console.log("")}}catch(n){console.error("Failed to read audit log:",n.message),process.exit(1)}finally{r&&r.close()}}var Jo=g(()=>{"use strict";Se();sr();d(Va,"logsCommand")});import{readFileSync as Ga}from"node:fs";import{fileURLToPath as Ya}from"node:url";import{dirname as Ja,join as Za}from"node:path";function Qa(){try{let l=Ja(Ya(import.meta.url));for(let e of["../package.json","../../package.json"])try{let t=JSON.parse(Ga(Za(l,e),"utf-8"));if(t.version)return t.version}catch{}}catch{}return"0.0.0"}d(Qa,"getVersion");var Zo=Qa(),Hr=`
648
648
  Alfred CLI v${Zo}
649
649
  Personal AI Assistant
650
650
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madh-io/alfred-ai",
3
- "version": "0.9.32",
3
+ "version": "0.9.34",
4
4
  "description": "Alfred — Personal AI Assistant across Telegram, Discord, WhatsApp, Matrix & Signal",
5
5
  "type": "module",
6
6
  "bin": {