tg-agent 1.4.1 → 1.4.2

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/dist/cli.js +67 -67
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,14 +1,55 @@
1
1
  #!/usr/bin/env node
2
- var j=(e,t)=>()=>(e&&(t=e(e=0)),t);import We from"node:fs/promises";import Vn from"node:os";import _e from"node:path";import{randomUUID as wt}from"node:crypto";function z(){return Date.now()}function J(e){return e.startsWith("~")?_e.join(Vn.homedir(),e.slice(1)):e}async function R(e){await We.mkdir(e,{recursive:!0})}async function bt(e,t){let n=_e.dirname(e),o=`${_e.basename(e)}.${wt()}.tmp`,r=_e.join(n,o),s=JSON.stringify(t,null,2);await We.writeFile(r,s,"utf8"),await We.rename(r,e)}function he(){return wt().split("-")[0]}function xt(e,t){if(e.length<=t)return[e];let n=[],o=e;for(;o.length>t;){let r=o.slice(0,t),s=r.lastIndexOf(`
3
- `);s>t*.6&&(r=r.slice(0,s)),n.push(r),o=o.slice(r.length)}return o.length>0&&n.push(o),n}function vt(){let e=new Map;return async function(n,o){let s=(e.get(n)??Promise.resolve()).then(o,o);e.set(n,s);try{return await s}finally{e.get(n)===s&&e.delete(n)}}}function St(e){let t=0,n=[],o=()=>{if(t>=e)return;let r=n.shift();r&&(t+=1,r())};return async function(s){await new Promise(l=>{n.push(l),o()});try{return await s()}finally{t=Math.max(0,t-1),o()}}}var Y=j(()=>{"use strict"});import{createHash as Xn}from"node:crypto";import Mt from"node:fs";import Yn from"node:path";import{execSync as Qn}from"node:child_process";function to(){return Yn.join(m.codexHome,Zn)}function no(e){return`cli|${Xn("sha256").update(e).digest("hex").slice(0,16)}`}function oo(){if(process.platform!=="darwin")return null;let e=m.codexHome,t=no(e);try{let n=Qn(`security find-generic-password -s "${eo}" -a "${t}" -w`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim(),o=JSON.parse(n),r=o.tokens,s=r?.access_token,l=r?.refresh_token;if(typeof s!="string"||!s||typeof l!="string"||!l)return null;let a=o.last_refresh,c=typeof a=="string"||typeof a=="number"?new Date(a).getTime():Date.now(),u=Number.isFinite(c)?c+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:l,expiresAt:u,source:"keychain"}}catch{return null}}function ro(){let e=to();try{let t=Mt.readFileSync(e,"utf8"),o=JSON.parse(t).tokens,r=o?.access_token,s=o?.refresh_token;if(typeof r!="string"||!r||typeof s!="string"||!s)return null;let l=Date.now()+3600*1e3;try{l=Mt.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function q(){return oo()??ro()}var Zn,eo,ce=j(()=>{"use strict";W();Zn="auth.json",eo="Codex Auth"});import so from"node:path";import*as $t from"@lancedb/lancedb";import He from"openai";function ao(){if(Z)return Z;let e=m.memory.rag;if(e.embeddingApiKey){let n={apiKey:e.embeddingApiKey};return e.embeddingBaseUrl&&(n.baseURL=e.embeddingBaseUrl),Z=new He(n),console.log(`[memory-rag] using embedding API key${e.embeddingBaseUrl?` (baseURL: ${e.embeddingBaseUrl})`:""}`),Z}if(m.openaiApiKey)return Z=new He({apiKey:m.openaiApiKey}),console.log("[memory-rag] using OpenAI API key from config"),Z;let t=q();if(t)return Z=new He({apiKey:t.accessToken}),console.log("[memory-rag] using Codex OAuth token"),Z;throw new Error("No API key for embeddings. Set memory.rag.embedding_api_key or run `codex login`.")}async function Ge(e){let t=ao(),n=m.memory.rag.embeddingModel;console.log(`[memory-rag] embedding ${e.length} chars using ${n}`);let o=3e4,r=new Promise((s,l)=>{setTimeout(()=>l(new Error(`Embedding timeout after ${o}ms`)),o)});try{let s=await Promise.race([t.embeddings.create({model:n,input:e,encoding_format:"float"}),r]);if(!s?.data?.[0]?.embedding)throw new Error(`Invalid embedding response: ${JSON.stringify(s).slice(0,200)}`);let l=s.data[0].embedding;return console.log(`[memory-rag] got ${l.length}D embedding`),l}catch(s){throw s instanceof Error&&console.error(`[memory-rag] embedding error: ${s.message}`),s}}async function le(){return Pe||(await R(qe),Pe=await $t.connect(qe),console.log(`[memory-rag] connected to DB at ${qe}`),Pe)}async function Re(e,t,n,o,r){let s={sessionSaved:!1,memoriesIndexed:0,errors:[]};if(!m.memory.rag.enabled)return console.log("[memory-rag] RAG disabled, skipping save"),s;console.log(`[memory-rag] saving session ${e}`);try{let l=await le(),a=await l.tableNames(),c={sessionId:e,date:t,title:n,transcript:o,reflection:JSON.stringify(r),memoryCount:r.memories?.length??0,timestamp:Date.now()};if(a.includes(ee)?await(await l.openTable(ee)).add([c]):await l.createTable(ee,[c]),s.sessionSaved=!0,console.log("[memory-rag] session saved to DB"),r.memories&&r.memories.length>0){let u=await lo(e,t,r.memories);s.memoriesIndexed=u.indexed,s.errors=u.errors}return s}catch(l){let a=l instanceof Error?l.message:String(l);return console.error(`[memory-rag] saveSession failed: ${a}`),s.errors.push(a),s}}async function co(){try{let e=await le();return(await e.tableNames()).includes(ee)?(await(await e.openTable(ee)).query().toArray()).map(r=>({sessionId:r.sessionId,date:r.date,title:r.title,transcript:r.transcript,reflection:r.reflection,memoryCount:r.memoryCount,timestamp:r.timestamp})):[]}catch(e){return console.error(`[memory-rag] getAllSessions failed: ${e}`),[]}}async function lo(e,t,n){let o={indexed:0,errors:[]};if(!m.memory.rag.enabled||n.length===0)return o;console.log(`[memory-rag] indexing ${n.length} memories for session ${e}`);try{let r=await le(),s=await r.tableNames(),l,a=!1;s.includes(G)?l=await r.openTable(G):a=!0;for(let c=0;c<n.length;c++){let u=n[c];try{let i=await Ge(u.content),d={id:`${e}-${c}`,sessionId:e,date:t,type:u.type,content:u.content,vector:i,timestamp:Date.now()};a?(l=await r.createTable(G,[d]),a=!1,console.log("[memory-rag] created memories table")):await l.add([d]),o.indexed++,console.log(`[memory-rag] indexed [${c+1}/${n.length}]: ${u.type}`)}catch(i){let d=i instanceof Error?i.message:String(i);o.errors.push(`${u.type}: ${d}`),console.error(`[memory-rag] failed to index item ${c}: ${d}`)}c<n.length-1&&await new Promise(i=>setTimeout(i,200))}return console.log(`[memory-rag] indexed ${o.indexed}/${n.length} memories`),o}catch(r){let s=r instanceof Error?r.message:String(r);return console.error(`[memory-rag] indexMemoryItems failed: ${s}`),o.errors.push(s),o}}async function kt(e,t=m.memory.rag.maxResults,n=m.memory.rag.similarityThreshold){if(!m.memory.rag.enabled)return[];console.log(`[memory-rag] searching: "${e.slice(0,50)}..."`);try{let o=await le();if(!(await o.tableNames()).includes(G))return console.log("[memory-rag] memories table not found"),[];let s=await o.openTable(G),l=await s.countRows();console.log(`[memory-rag] memories table has ${l} rows`);let a=await Ge(e),c=await s.vectorSearch(a).column(io).limit(t*2).toArray();if(console.log(`[memory-rag] search returned ${c.length} results`),c.length>0){let d=c.map(g=>g._distance?.toFixed(4)??"N/A");console.log(`[memory-rag] distances: [${d.join(", ")}]`)}let u=(1-n)*2;console.log(`[memory-rag] threshold=${n}, maxDistance=${u.toFixed(4)}`);let i=c.filter(d=>{let g=d._distance;return g===void 0||g<=u}).slice(0,t).map(d=>({id:d.id,sessionId:d.sessionId,date:d.date,type:d.type,content:d.content,timestamp:d.timestamp,_distance:d._distance}));return console.log(`[memory-rag] filtered: ${i.length} memories`),i.length>0&&i.forEach((d,g)=>{console.log(`[memory-rag] ${g+1}. [${d.type}] "${d.content.slice(0,50)}..." (dist=${d._distance?.toFixed(4)??"N/A"})`)}),i}catch(o){let r=o instanceof Error?o.message:String(o);return console.warn(`[memory-rag] search failed: ${r}`),[]}}async function At(){try{let e=await le(),t=await e.tableNames(),n=0,o=0;return t.includes(ee)&&(n=await(await e.openTable(ee)).countRows()),t.includes(G)&&(o=await(await e.openTable(G)).countRows()),{sessionsCount:n,memoriesCount:o,embeddingModel:m.memory.rag.embeddingModel}}catch{return{sessionsCount:0,memoriesCount:0,embeddingModel:m.memory.rag.embeddingModel}}}async function _t(e){let t={success:!1,totalSessions:0,totalMemories:0,indexedMemories:0,errors:[],embeddingModel:m.memory.rag.embeddingModel,vectorDimension:null};console.log("[reindex] ========================================"),console.log("[reindex] Rebuilding memories from sessions table"),console.log(`[reindex] Embedding model: ${m.memory.rag.embeddingModel}`),console.log("[reindex] ========================================");try{let n=await le(),o=await n.tableNames();if(!o.includes(ee))return console.log("[reindex] No sessions table found, nothing to reindex"),t.success=!0,t;let r=await co();if(t.totalSessions=r.length,r.length===0)return console.log("[reindex] No sessions found"),t.success=!0,t;console.log(`[reindex] Found ${r.length} sessions`);let s=[];for(let a of r)try{let c=JSON.parse(a.reflection);if(c.memories&&c.memories.length>0)for(let u of c.memories)s.push({sessionId:a.sessionId,date:a.date,item:u})}catch(c){console.warn(`[reindex] Failed to parse reflection for session ${a.sessionId}: ${c}`)}if(t.totalMemories=s.length,console.log(`[reindex] Found ${s.length} memories to reindex`),s.length===0)return console.log("[reindex] No memories to reindex"),t.success=!0,t;o.includes(G)&&(await n.dropTable(G),console.log("[reindex] Dropped old memories table"));let l=null;for(let a=0;a<s.length;a++){let{sessionId:c,date:u,item:i}=s[a],d=`[${a+1}/${s.length}]`;try{e?.(a+1,s.length,`Indexing: ${i.content.slice(0,30)}...`);let g=await Ge(i.content);t.vectorDimension===null&&(t.vectorDimension=g.length);let f={id:`${c}-${a}`,sessionId:c,date:u,type:i.type,content:i.content,vector:g,timestamp:Date.now()};l===null?(l=await n.createTable(G,[f]),console.log(`[reindex] ${d} Created new memories table`)):await l.add([f]),t.indexedMemories++,console.log(`[reindex] ${d} Indexed: [${i.type}] ${i.content.slice(0,40)}...`)}catch(g){let f=g instanceof Error?g.message:String(g);t.errors.push(`${i.content.slice(0,30)}: ${f}`),console.error(`[reindex] ${d} Failed: ${f}`)}a<s.length-1&&await new Promise(g=>setTimeout(g,200))}return console.log("[reindex] ========================================"),console.log("[reindex] Reindex complete!"),console.log(`[reindex] Sessions: ${t.totalSessions}`),console.log(`[reindex] Total memories: ${t.totalMemories}`),console.log(`[reindex] Indexed: ${t.indexedMemories}`),console.log(`[reindex] Errors: ${t.errors.length}`),console.log("[reindex] ========================================"),t.success=!0,t}catch(n){let o=n instanceof Error?n.message:String(n);return console.error(`[reindex] Failed: ${o}`),t.errors.push(o),t}}var qe,ee,G,io,Pe,Z,Ve=j(()=>{"use strict";W();Y();ce();qe=so.join(m.agentDir,"tg-memory-db"),ee="sessions",G="memories",io="vector",Pe=null,Z=null});import Pt from"node:path";import{AuthStorage as uo,ModelRegistry as mo}from"@mariozechner/pi-coding-agent";import{completeSimple as go,getModel as po}from"@mariozechner/pi-ai";function fo(){return m.memory.systemPrompt||Xe}function ho(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function wo(e,t){return e!=="openai-codex"?t:yo[t]??t}async function bo(e,t){await R(m.agentDir);let n=Pt.join(m.agentDir,"auth.json"),o=new uo(n),r=q();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let s=Pt.join(m.agentDir,"models.json"),l=new mo(o,s),a=async(d,g,f)=>{let y=ho(d),w=wo(y,g),k=l.find(y,w);if(!k)try{k=po(y,w)}catch{}if(k){let A=await o.getApiKey(y);return{model:k,provider:y,modelId:w,apiKey:A??void 0,source:f}}return null};if(e&&t){let d=await a(e,t,"session");if(d)return console.log(`[memory] using session model: ${d.provider}/${d.modelId}`),d}if(m.memory.modelProvider&&m.memory.modelId){let d=await a(m.memory.modelProvider,m.memory.modelId,"memory-config");if(d)return console.log(`[memory] using configured memory model: ${d.provider}/${d.modelId}`),d}let c=m.modelProvider,u=m.modelRef.includes("/")?m.modelRef.split("/")[1]:m.modelRef;if(c&&u){let d=await a(c,u,"system-default");if(d)return console.log(`[memory] using system default model: ${d.provider}/${d.modelId}`),d}let i=l.getAll();if(i.length>0){let d=i[0],g=await o.getApiKey(d.provider);return console.log(`[memory] using first available model: ${d.provider}/${d.id}`),{model:d,provider:d.provider,modelId:d.id,apiKey:g??void 0,source:"first-available"}}return console.warn("[memory] no model available for reflection"),null}function xo(e){let t={emotional:"",insights:"",advice:"",memories:[]};if(!e.trim())return t;try{let n=e.trim(),o=n.match(/```(?:json)?\s*([\s\S]*?)```/);o&&(n=o[1].trim());let r=JSON.parse(n),s={emotional:typeof r.emotional=="string"?r.emotional:"",insights:typeof r.insights=="string"?r.insights:"",advice:typeof r.advice=="string"?r.advice:"",memories:[]};if(Array.isArray(r.memories))for(let l of r.memories)typeof l=="object"&&typeof l.type=="string"&&typeof l.content=="string"&&s.memories.push({type:l.type,content:l.content});return console.log(`[memory] parsed ${s.memories.length} memories from reflection`),s}catch(n){return console.warn(`[memory] failed to parse JSON response: ${n}`),console.warn(`[memory] raw response: ${e.slice(0,500)}...`),{emotional:"",insights:e.slice(0,500),advice:"",memories:[{type:"insight",content:`Session summary: ${e.slice(0,200)}`}]}}}async function Ce(e,t,n){if(!m.memory.enabled)return{success:!0,reflected:!1,memoriesIndexed:0};if(e.messages.length===0)return{success:!0,reflected:!1,memoriesIndexed:0};let r=new Date().toISOString().split("T")[0],s=e.messages.map(a=>`[${a.role.toUpperCase()}]: ${a.content}`).join(`
2
+ var j=(e,t)=>()=>(e&&(t=e(e=0)),t);import We from"node:fs/promises";import Gn from"node:os";import _e from"node:path";import{randomUUID as yt}from"node:crypto";function z(){return Date.now()}function J(e){return e.startsWith("~")?_e.join(Gn.homedir(),e.slice(1)):e}async function R(e){await We.mkdir(e,{recursive:!0})}async function ht(e,t){let n=_e.dirname(e),o=`${_e.basename(e)}.${yt()}.tmp`,r=_e.join(n,o),s=JSON.stringify(t,null,2);await We.writeFile(r,s,"utf8"),await We.rename(r,e)}function he(){return yt().split("-")[0]}function wt(e,t){if(e.length<=t)return[e];let n=[],o=e;for(;o.length>t;){let r=o.slice(0,t),s=r.lastIndexOf(`
3
+ `);s>t*.6&&(r=r.slice(0,s)),n.push(r),o=o.slice(r.length)}return o.length>0&&n.push(o),n}function bt(){let e=new Map;return async function(n,o){let s=(e.get(n)??Promise.resolve()).then(o,o);e.set(n,s);try{return await s}finally{e.get(n)===s&&e.delete(n)}}}function xt(e){let t=0,n=[],o=()=>{if(t>=e)return;let r=n.shift();r&&(t+=1,r())};return async function(s){await new Promise(l=>{n.push(l),o()});try{return await s()}finally{t=Math.max(0,t-1),o()}}}var Y=j(()=>{"use strict"});import vt from"node:fs";import Re from"node:path";import*as Ce from"@iarna/toml";function $t(){let e=J(St);return Re.join(e,Vn)}function T(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function _(e,t){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):t}function W(e,t){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"){let n=Number.parseInt(e,10);return Number.isNaN(n)?t:n}return t}function ce(e,t){if(typeof e=="boolean")return e;if(typeof e=="string"){let n=e.trim().toLowerCase();if(n==="true"||n==="1"||n==="yes")return!0;if(n==="false"||n==="0"||n==="no")return!1}return t}function kt(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?t:String(t)).map(t=>t.trim()).filter(Boolean):typeof e=="string"?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Xn(e){return new Set(kt(e))}function Yn(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,Re.resolve(J(o.trim())));return t}function we(){let e=$t();try{let t=vt.readFileSync(e,"utf8"),n=Ce.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function He(e,t){await R(Re.dirname(e));let n=Ce.stringify(t);await vt.promises.writeFile(e,n,"utf8")}function At(){return{telegram:{bot_token:"",allowed_user_ids:[],parse_mode:""},model:{provider:"openai-codex",model:"gpt-5.2",openai_api_key:""},paths:{workspace_dir:"",session_dir:"~/.tg-agent/tg-sessions"},workspace_mappings:{},limits:{max_sessions:5,max_concurrent:5,max_history_messages:40,max_output_tokens:0},timeouts:{model_timeout_ms:6e4,model_timeout_stream_ms:3e5,fetch_timeout_ms:6e4},fetch:{max_bytes:2e5,proxy_url:""},proxy:{url:""},auth:{codex_home:"~/.codex"},logging:{agent_events:!0,agent_stream:!0},system:{prompt:Mt},tls:{extra_ca_certs:"",reject_unauthorized:""},security_audit:{enabled:!1,model_provider:"",model_id:"",whitelist_patterns:[],confirm_timeout_ms:12e4},memory:{enabled:!0,model_provider:"",model_id:"",system_prompt:"",rag:{enabled:!0,embedding_model:"openai/text-embedding-3-small",embedding_base_url:"",embedding_api_key:"",similarity_threshold:.5,max_results:5}}}}function Pe(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function _t(e,t){let n=!1,o=(r,s)=>{for(let[l,a]of Object.entries(s)){if(!(l in r)){r[l]=a,n=!0;continue}let c=r[l];Pe(c)&&Pe(a)&&o(c,a)}};return Pe(e)&&Pe(t)&&o(e,t),n}function Pt(e){let t=T(e,"telegram");return _(t.bot_token,"").trim()}function Rt(e,t){let n=T(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function Ct(e){let t=T(e,"telegram"),n=T(e,"model"),o=T(e,"paths"),r=T(e,"limits"),s=T(e,"timeouts"),l=T(e,"fetch"),a=T(e,"proxy"),c=T(e,"auth"),u=T(e,"logging"),i=T(e,"system"),d=T(e,"tls"),g=T(e,"workspace_mappings"),f=T(e,"security_audit"),y=T(e,"memory"),w=T(y,"rag"),k=_(o.workspace_dir,process.cwd()),A=_(o.session_dir,"~/.tg-agent/tg-sessions"),I=Yn(g),x=_(d.reject_unauthorized,""),P=x===""?null:ce(x,!0);return{telegramToken:_(t.bot_token,"").trim(),telegramAllowedUsers:Xn(t.allowed_user_ids),telegramParseMode:_(t.parse_mode,"").trim(),modelProvider:_(n.provider,"openai-codex").trim(),modelRef:_(n.model,"gpt-5.2").trim(),openaiApiKey:_(n.openai_api_key,"").trim(),sessionDir:J(A),agentDir:J(St),workspaceDir:Re.resolve(J(k)),workspaceMappings:I,maxSessions:W(r.max_sessions,5),maxConcurrent:W(r.max_concurrent,5),maxHistoryMessages:W(r.max_history_messages,40),maxOutputTokens:W(r.max_output_tokens,0),fetchMaxBytes:W(l.max_bytes,2e5),fetchTimeoutMs:W(s.fetch_timeout_ms,6e4),modelTimeoutMs:W(s.model_timeout_ms,6e4),modelTimeoutStreamingMs:W(s.model_timeout_stream_ms,3e5),systemPrompt:_(i.prompt,Mt),proxyUrl:_(a.url,"").trim(),fetchProxyUrl:_(l.proxy_url,"").trim(),codexHome:J(_(c.codex_home,"~/.codex")),logAgentEvents:ce(u.agent_events,!0),logAgentStream:ce(u.agent_stream,!0),tlsExtraCaCerts:_(d.extra_ca_certs,"").trim(),tlsRejectUnauthorized:P,audit:{enabled:ce(f.enabled,!1),modelProvider:_(f.model_provider,"").trim(),modelId:_(f.model_id,"").trim(),whitelistPatterns:kt(f.whitelist_patterns),confirmTimeoutMs:W(f.confirm_timeout_ms,6e4)},memory:{enabled:ce(y.enabled,!0),modelProvider:_(y.model_provider,"").trim(),modelId:_(y.model_id,"").trim(),systemPrompt:_(y.system_prompt,"").trim(),rag:{enabled:ce(w.enabled,!0),embeddingModel:_(w.embedding_model,"openai/text-embedding-3-small").trim(),embeddingBaseUrl:_(w.embedding_base_url,"").trim(),embeddingApiKey:_(w.embedding_api_key,"").trim(),similarityThreshold:W(w.similarity_threshold,.5),maxResults:W(w.max_results,5)}}}}function Tt(){let{data:e}=we();return m=Ct(e),m}function Et(){let e=[];if(m.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${$t()})`)}var St,Vn,Mt,Qn,m,H=j(()=>{"use strict";Y();St="~/.tg-agent",Vn="config.toml",Mt=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
4
4
 
5
- `),l=await bo(t,n);if(!l){console.log("[memory] no model available, saving raw session");let a={emotional:"",insights:"No model available for reflection",advice:"",memories:[]};return{success:(await Re(e.id,r,e.title,s,a)).sessionSaved,reflected:!1,memoriesIndexed:0}}console.log(`[memory] reflecting on session ${e.id} using ${l.provider}/${l.modelId}`);try{let c=`${fo()}
5
+ Important behavioral rules:
6
+ - Do NOT mention the name of your underlying framework, technical implementation, or any package names
7
+ - Do NOT refer to yourself as "pi", "pi-coding-agent", or any other framework/tool name
8
+ - When users ask about your identity or implementation, simply say you are a coding assistant
9
+ - Focus on helping with tasks rather than discussing your technical stack or architecture
10
+ - Do not mention documentation paths or framework-specific resources unless directly relevant to the task
11
+
12
+ Be concise and practical in all responses.`;({data:Qn}=we()),m=Ct(Qn)});import{createHash as Zn}from"node:crypto";import Dt from"node:fs";import eo from"node:path";import{execSync as to}from"node:child_process";function ro(){return eo.join(m.codexHome,no)}function so(e){return`cli|${Zn("sha256").update(e).digest("hex").slice(0,16)}`}function io(){if(process.platform!=="darwin")return null;let e=m.codexHome,t=so(e);try{let n=to(`security find-generic-password -s "${oo}" -a "${t}" -w`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim(),o=JSON.parse(n),r=o.tokens,s=r?.access_token,l=r?.refresh_token;if(typeof s!="string"||!s||typeof l!="string"||!l)return null;let a=o.last_refresh,c=typeof a=="string"||typeof a=="number"?new Date(a).getTime():Date.now(),u=Number.isFinite(c)?c+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:l,expiresAt:u,source:"keychain"}}catch{return null}}function ao(){let e=ro();try{let t=Dt.readFileSync(e,"utf8"),o=JSON.parse(t).tokens,r=o?.access_token,s=o?.refresh_token;if(typeof r!="string"||!r||typeof s!="string"||!s)return null;let l=Date.now()+3600*1e3;try{l=Dt.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function q(){return io()??ao()}var no,oo,le=j(()=>{"use strict";H();no="auth.json",oo="Codex Auth"});function Ot(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=q();if(n)return{apiKey:n.accessToken,source:`codex:${n.source}`};throw new Error("No Codex OAuth credentials found. Run `codex login`.")}if(m.openaiApiKey)return{apiKey:m.openaiApiKey,source:"config.model.openai_api_key"};throw new Error(`No API key for provider: ${e}`)}function co(){return m.proxyUrl?{url:m.proxyUrl,source:"config.proxy.url"}:m.fetchProxyUrl?{url:m.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function It(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function Nt(){let e=co();return e?{url:e.url,kind:It(e.url),source:e.source}:null}function Lt(){let e=[{key:"config.fetch.proxy_url",value:m.fetchProxyUrl},{key:"config.proxy.url",value:m.proxyUrl}];for(let t of e){let n=t.value?.trim();if(!n)continue;let o=It(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var qe=j(()=>{"use strict";H();le()});import{ProxyAgent as lo,setGlobalDispatcher as uo}from"undici";function Ft(){if(jt)return Ge;jt=!0;let e=Lt();if(!e)return Ge=null,null;let t=new lo(e.url);return uo(t),Ge=e,e}var jt,Ge,zt=j(()=>{"use strict";qe();jt=!1,Ge=null});import mo from"node:fs";import go from"node:fs/promises";import po from"node:path";import fo from"node:readline";import{spawn as yo}from"node:child_process";import*as Bt from"@iarna/toml";function Wt(e){return po.join(e,"config.toml")}function Te(e){let t=Wt(e);try{let n=mo.readFileSync(t,"utf8");return Vt(n)}catch{return[]}}async function be(e){let t=Wt(e);try{let n=await go.readFile(t,"utf8");return Vt(n)}catch{return[]}}async function xe(e,t={}){if(de)return de;let n=await be(e);if(n.length===0)return de="","";let o=t.maxTools??wo,r=t.maxChars??bo,s=t.timeoutMs??4e3,l=t.maxBytes??Kt,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let i=await vo(u,{timeoutMs:s,maxBytes:l});if(a.push(`${u.name} (${u.type})`),i.length===0){a.push(" - tools unavailable");continue}let d=i.slice(0,o);for(let g of d){let f=g.description?`: ${g.description}`:"";a.push(` - ${g.name}${f}`)}i.length>d.length&&a.push(` - ...and ${i.length-d.length} more`)}let c=a.join(`
13
+ `);return c.length>r&&(c=`${c.slice(0,r-20)}...
14
+ (truncated)`),de=c,c}function Xe(){de&&(Jt=!0)}function Ht(){de=null,Jt=!1,U.clear()}function re(e){if(e.type==="http")return e.url?`url=${e.url}`:"url=(missing)";let t=e.args&&e.args.length>0?` ${e.args.join(" ")}`:"";return e.command?`command=${e.command}${t}`:"command=(missing)"}async function qt(e,t=5e3){let n=Date.now();try{return await Ee(e,"tools/list",{},{timeoutMs:t}),{ok:!0,durationMs:Date.now()-n}}catch(o){let r=o instanceof Error?o.message:String(o);return{ok:!1,durationMs:Date.now()-n,error:r}}}async function Ee(e,t,n,o={}){let r=Ut(o.timeoutMs??ho,1e3,12e4),s=Ut(o.maxBytes??Kt,1024,5e6),l=new AbortController,a=()=>l.abort();o.signal?.addEventListener("abort",a,{once:!0});let c=setTimeout(()=>l.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await $o(e,s,l.signal),await Mo(e,t,n,s,l.signal)):await _o(e,t,n,s,l.signal)}finally{clearTimeout(c),o.signal?.removeEventListener("abort",a)}}function Ut(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function vo(e,t){try{let n=await Ee(e,"tools/list",{},t);return So(n.output)}catch(n){let o=n instanceof Error?n.message:String(n);return console.warn(`[tg-agent] mcp tools/list failed server=${e.name} error=${o}`),[]}}function So(e){let t;try{t=JSON.parse(e)}catch{return[]}if(!t||typeof t!="object")return[];let n=t,r=(n.result??n).tools??n.tools;if(!Array.isArray(r))return[];let s=[];for(let l of r){if(!l||typeof l!="object")continue;let a=l,c=typeof a.name=="string"?a.name:"";if(!c)continue;let u=typeof a.description=="string"?a.description:void 0,i=a.inputSchema;s.push({name:c,description:u,inputSchema:i})}return s}async function Mo(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await Ve(e,t,n,o,r),a=Gt(l.parsed);if(a)throw new Error(a);let c=l.bodyText;return l.parsed&&(c=JSON.stringify(l.parsed,null,2)),{ok:l.statusCode>=200&&l.statusCode<300,output:c,durationMs:Date.now()-s,bytes:l.bytes,truncated:l.truncated,statusCode:l.statusCode,statusText:l.statusText,contentType:l.contentType}}async function Ve(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=U.get(e.name),l={jsonrpc:"2.0",id:`tg-agent-${Date.now()}`,method:t,params:n??{}},a={"content-type":"application/json"};e.auth&&(a.authorization=e.auth.startsWith("Bearer ")?e.auth:`Bearer ${e.auth}`),s?.cookie&&(a.cookie=s.cookie),s?.sessionId&&(a["mcp-session-id"]=s.sessionId);let c=await fetch(e.url,{method:"POST",headers:a,body:JSON.stringify(l),signal:r});ko(e.name,c);let u=await Po(c,o,r),i;try{i=JSON.parse(u.text)}catch{i=void 0}return Ao(e.name,i),{statusCode:c.status,statusText:c.statusText,contentType:c.headers.get("content-type"),bodyText:u.text,parsed:i,bytes:u.bytes,truncated:u.truncated}}function Gt(e){if(!e||typeof e!="object")return null;let t=e;if(t.error&&typeof t.error=="object"){let n=t.error;if(typeof n.message=="string")return n.message}return typeof t.error_description=="string"?t.error_description:typeof t.error=="string"?t.error:null}async function $o(e,t,n){let o=U.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let s=await Ve(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=Gt(s.parsed);if(l){let u=l.toLowerCase();if(u.includes("method")&&u.includes("not"))return;throw new Error(l)}let a=new AbortController,c=setTimeout(()=>a.abort(),xo);try{await Ve(e,"notifications/initialized",{},t,a.signal)}catch{}finally{clearTimeout(c)}})();U.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let s=U.get(e.name);U.set(e.name,{initializedAt:Date.now(),cookie:s?.cookie,sessionId:s?.sessionId})}catch(s){throw U.delete(e.name),s}}function ko(e,t){let o=U.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),s=t.headers.getSetCookie?.(),l=s&&s.length>0?s.join("; "):r;l&&U.set(e,{...o,cookie:l});let a=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");a&&U.set(e,{...o,sessionId:a})}function Ao(e,t){if(!t||typeof t!="object")return;let o=t.result;if(!o)return;let r=typeof o.sessionId=="string"&&o.sessionId||typeof o.session_id=="string"&&o.session_id;if(!r)return;let s=U.get(e)??{initializedAt:0};U.set(e,{...s,sessionId:r})}async function _o(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=yo(e.command,e.args??[],{stdio:["pipe","pipe","pipe"]}),a=()=>{l.killed||l.kill("SIGTERM")};if(r.aborted)throw a(),new Error("MCP request aborted.");let c=new Map,u=!1,i="",d=new Error("MCP request aborted."),g=fo.createInterface({input:l.stdout,terminal:!1});g.on("line",S=>{if(S.length>o){u=!0;return}let b=null;try{b=JSON.parse(S)}catch{return}let $=typeof b.id=="string"?b.id:typeof b.id=="number"?String(b.id):"";if(!$)return;let D=c.get($);D&&(c.delete($),D.resolve(b))}),l.stderr?.on("data",S=>{let b=S.toString();if(i.length+b.length>o){u=!0;return}i+=b});let f=()=>{for(let S of c.values())S.reject(d);c.clear(),a()};r.addEventListener("abort",f,{once:!0});let y=S=>{let b=S===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let $ of c.values())$.reject(new Error(b));c.clear()};l.once("exit",S=>y(S));let w=async(S,b)=>{let $=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,D={jsonrpc:"2.0",id:$,method:S,params:b??{}};return await new Promise((oe,ye)=>{c.set($,{resolve:oe,reject:ye}),l.stdin?.write(`${JSON.stringify(D)}
15
+ `)})};fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeInit",message:"sending initialize request",data:{elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{});let k=await w("initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}});if(fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:afterInit",message:"initialize response received",data:{elapsed:Date.now()-s,hasError:!!k.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),k.error&&typeof k.error=="object"){let S=k.error.message??"MCP initialize failed.";throw a(),new Error(String(S))}let A={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify(A)}
16
+ `),fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeMethod",message:"sending method request",data:{method:t,elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"C"})}).catch(()=>{});let I=await w(t,n);r.removeEventListener("abort",f),g.close(),l.stdin?.end(),a();let x=new Promise(S=>{l.once("exit",()=>S())});if(await Promise.race([x,new Promise(S=>setTimeout(S,500))]),I.error&&typeof I.error=="object"){let S=I.error.message??"MCP request failed.";throw new Error(String(S))}let P=JSON.stringify(I,null,2),ae=P.length>o?P.slice(0,o):P;return P.length>o&&(u=!0),{ok:!0,output:ae,durationMs:Date.now()-s,bytes:Math.min(P.length,o),truncated:u}}async function Po(e,t,n){let o=e.body?.getReader?.();if(!o){let d=await e.text(),g=Math.min(d.length,t);return{text:d.slice(0,t),bytes:g,truncated:d.length>t}}let r=new TextDecoder("utf-8"),s=[],l=0,a=!1;for(;;){if(n.aborted){try{await o.cancel()}catch{}throw new Error("MCP request aborted.")}let{done:d,value:g}=await o.read();if(d)break;if(!g)continue;let f=l+g.byteLength;if(f>t){let y=Math.max(0,t-l);y>0&&(s.push(g.slice(0,y)),l+=y),a=!0;try{await o.cancel()}catch{}break}s.push(g),l=f}let c=new Uint8Array(l),u=0;for(let d of s)c.set(d,u),u+=d.byteLength;return{text:r.decode(c),bytes:l,truncated:a}}function Vt(e){let t=[],n;try{n=Bt.parse(e)}catch{return t}let o=n.mcp_servers;if(!o||typeof o!="object")return t;for(let[r,s]of Object.entries(o)){if(!s||typeof s!="object")continue;let l=s,a=typeof l.type=="string"?l.type.toLowerCase():void 0,c=typeof l.url=="string"?l.url:void 0,u=typeof l.command=="string"?l.command:void 0,i=a==="http"||a==="stdio"?a:c?"http":u?"stdio":void 0;if(!i||i==="http"&&!c||i==="stdio"&&!u)continue;let d;Array.isArray(l.args)&&(d=l.args.filter(f=>typeof f=="string").map(f=>f.trim()));let g=typeof l.auth=="string"?l.auth:typeof l.authorization=="string"?l.authorization:typeof l.token=="string"?l.token:void 0;t.push({name:r,type:i,url:c,command:u,args:d,auth:g})}return t}var ho,Kt,wo,bo,de,Jt,U,xo,De=j(()=>{"use strict";ho=6e4,Kt=2e5,wo=40,bo=3500,de=null,Jt=!1,U=new Map,xo=1500});import Q from"node:path";import Ro from"node:fs/promises";import{Type as M}from"@sinclair/typebox";function Oe(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function Eo(e){if(!e)return{};let t={};if(Array.isArray(e)){for(let n of e)n?.name&&(t[n.name]=n.value??"");return t}for(let[n,o]of Object.entries(e))n&&(t[n]=o);return t}function Xt(e){let t=m.fetchTimeoutMs>0?m.fetchTimeoutMs:To;return Oe(e||t,1e3,12e4)}function Yt(e){let t=m.fetchMaxBytes>0?m.fetchMaxBytes:Co;return Oe(e||t,1024,5e6)}function Qt(e,t,n){let o=e.trim();if(!o)return null;let r=J(o),s=Q.isAbsolute(r)?r:Q.join(n,r),l=Q.resolve(s);for(let a of t){let c=Q.resolve(a);if(l===c||l.startsWith(`${c}${Q.sep}`))return l}return null}async function Zt(e){try{let t=await Ro.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function Do(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Oo(e,t){let n=new Uint8Array(t),o=0;for(let r of e)n.set(r,o),o+=r.byteLength;return n}async function Io(e,t,n){let o=e.body?.getReader?.();if(!o){let i=await e.text?.()??"",d=Math.min(i.length,t),g=i.length>t;return{text:i.slice(0,t),bytes:d,truncated:g}}let r=new TextDecoder("utf-8"),s=[],l=0,a=!1;for(;;){if(n?.aborted){try{await o.cancel?.()}catch{}throw new Error("Fetch aborted")}let{done:i,value:d}=await o.read();if(i)break;if(!d)continue;let g=l+d.byteLength;if(g>t){let f=Math.max(0,t-l);f>0&&(s.push(d.slice(0,f)),l+=f),a=!0;try{await o.cancel?.()}catch{}break}s.push(d),l=g}let c=Oo(s,l);return{text:r.decode(c),bytes:l,truncated:a}}function No(e,t){let n=`HTTP ${e.status} ${e.statusText}`.trim(),o=[`url: ${e.url}`,`bytes: ${e.bytes}${e.truncated?" (truncated)":""}`,`content-type: ${e.contentType??"unknown"}`];return`${n}
17
+ ${o.join(`
18
+ `)}
19
+
20
+ ${t}`}function jo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:Lo,execute:async(e,t,n,o,r)=>{if(!Do(t.url))return{content:[{type:"text",text:"Invalid URL. Only http(s) is allowed."}],details:{url:t.url,status:0,statusText:"invalid_url",bytes:0,truncated:!1,contentType:null}};let s=Xt(t.timeoutMs),l=Yt(t.maxBytes),a=new AbortController,c=()=>a.abort();r?.addEventListener("abort",c,{once:!0});let u=setTimeout(()=>a.abort(),s);try{n?.({content:[{type:"text",text:`Fetching ${t.url}...`}],details:{url:t.url,status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let i=await fetch(t.url,{method:t.method?.toUpperCase()??"GET",headers:Eo(t.headers),body:t.body,signal:a.signal}),d=await Io(i,l,r),g=i.headers.get("content-type");return{content:[{type:"text",text:No({url:i.url,status:i.status,statusText:i.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g},d.text)}],details:{url:i.url,status:i.status,statusText:i.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g}}}catch(i){return{content:[{type:"text",text:`Fetch failed: ${i instanceof Error?i.message:String(i)}`}],details:{url:t.url,status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}finally{clearTimeout(u),r?.removeEventListener("abort",c)}}}}function zo(e,t,n){let o=t.status>0?`HTTP ${t.status} ${t.statusText}`.trim():t.statusText,r=[`server: ${e.name}`,`type: ${e.type}`,`target: ${t.target}`,`bytes: ${t.bytes}${t.truncated?" (truncated)":""}`,`content-type: ${t.contentType??"unknown"}`];return`${o}
21
+ ${r.join(`
22
+ `)}
23
+
24
+ ${n}`}function Uo(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:Fo,execute:async(t,n,o,r,s)=>{let l=await e();if(l.length===0)return{content:[{type:"text",text:"MCP is not configured. Add [mcp_servers.*] to ~/.tg-agent/config.toml."}],details:{server:"",type:"http",target:"",status:0,statusText:"not_configured",bytes:0,truncated:!1,contentType:null}};let a=n.server?.trim()??"";if(!a)if(l.length===1)a=l[0]?.name??"";else return{content:[{type:"text",text:`Multiple MCP servers configured. Provide server name. Available: ${l.map(u=>u.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let c=l.find(u=>u.name===a);if(!c)return{content:[{type:"text",text:`MCP server not found: ${a}. Available: ${l.map(u=>u.name).join(", ")}`}],details:{server:a,type:"http",target:"",status:0,statusText:"server_not_found",bytes:0,truncated:!1,contentType:null}};try{o?.({content:[{type:"text",text:`Calling MCP ${c.name} ${n.method}...`}],details:{server:c.name,type:c.type,target:re(c),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let u=await Ee(c,n.method,n.params??{},{timeoutMs:Xt(void 0),maxBytes:Yt(void 0),signal:s});return{content:[{type:"text",text:zo(c,{server:c.name,type:c.type,target:re(c),status:u.statusCode??0,statusText:u.statusText??(u.ok?"ok":"error"),bytes:u.bytes,truncated:u.truncated,contentType:u.contentType??null},u.output)}],details:{server:c.name,type:c.type,target:re(c),status:u.statusCode??0,statusText:u.statusText??(u.ok?"ok":"error"),bytes:u.bytes,truncated:u.truncated,contentType:u.contentType??null}}}catch(u){return{content:[{type:"text",text:`MCP failed: ${u instanceof Error?u.message:String(u)}`}],details:{server:c.name,type:c.type,target:re(c),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function Jo(e){let t=[m.workspaceDir,Q.join(m.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:Bo,execute:async(n,o)=>{let r=Qt(o.path,t,m.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let s=await Zt(r);return s?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${Q.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function Wo(e){let t=[m.workspaceDir,Q.join(m.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:Ko,execute:async(n,o)=>{let r=Qt(o.path,t,m.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let s=await Zt(r);return s?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${Q.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function en(e){let t=[jo()];return e?.telegram&&(t.push(Jo(e.telegram)),t.push(Wo(e.telegram))),Te(m.agentDir).length>0&&t.push(Uo(()=>be(m.agentDir))),t}var Co,To,Lo,Fo,Bo,Ko,tn=j(()=>{"use strict";H();De();Y();Co=2e5,To=6e4;Lo=M.Object({url:M.String({description:"HTTP or HTTPS URL"}),method:M.Optional(M.String({description:"HTTP method (default: GET)"})),headers:M.Optional(M.Array(M.Object({name:M.String({description:"Header name"}),value:M.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:M.Optional(M.String({description:"Request body (string)"})),timeoutMs:M.Optional(M.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:M.Optional(M.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});Fo=M.Object({server:M.Optional(M.String({description:"MCP server name"})),method:M.String({description:"MCP method name"}),params:M.Optional(M.Any({description:"MCP params payload"}))});Bo=M.Object({path:M.String({description:"Image file path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))}),Ko=M.Object({path:M.String({description:"File path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))})});import rn from"node:fs/promises";import sn from"node:path";function an(e){return sn.join(m.sessionDir,`${e}.json`)}function nn(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function Ye(e,t){let n=nn(e),o=nn(t);return sn.join(m.sessionDir,`${n}-${o}.jsonl`)}async function ue(e,t){let n=Ye(e,t);try{await rn.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function on(e,t){let n=t?.sessions??{},o=t?.activeSessionId??null,r=t?.workspaceDir,s={chatId:e,workspaceDir:r,activeSessionId:o,sessions:n};return(!o||!n[o])&&(s.activeSessionId=null),s}async function Ne(e){await R(m.sessionDir);let t=Ie.get(e);if(t)return t;let n=an(e);try{let o=await rn.readFile(n,"utf8"),r=JSON.parse(o),s=on(e,r);return Ie.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=on(e,{});return Ie.set(e,r),r}throw o}}async function O(e){await R(m.sessionDir);let t=an(e.chatId);await ht(t,e),Ie.set(e.chatId,e)}function Qe(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function Ze(e){return[]}function Le(e,t){if(Object.keys(e.sessions).length>=m.maxSessions)throw new Error("Max sessions reached");let o=he(),r=z(),s={id:o,title:t&&t.length>0?t:`session-${o}`,messages:[],createdAt:r,updatedAt:r};return e.sessions[o]=s,e.activeSessionId=o,s}function cn(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function se(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function et(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function ln(e){e.messages=[],e.updatedAt=z()}function tt(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=z()}function dn(e,t){e.workspaceDir=t}var Ie,nt=j(()=>{"use strict";H();Y();Ie=new Map});import Ho from"node:fs/promises";import mn from"node:path";import{completeSimple as qo}from"@mariozechner/pi-ai";function Yo(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return Xo.replace("{{command}}",n)}function Qo(e){let t=e.trim();console.log(`[audit] AI response: ${t.slice(0,200)}`);try{let n=JSON.parse(t),o=n.riskLevel?.toLowerCase();if(o==="none"||o==="low"||o==="critical")return{riskLevel:o,reason:n.reason??"No reason"}}catch{}try{let n=t.match(/\{[^{}]*"riskLevel"\s*:\s*"[^"]*"[^{}]*\}/);if(n){let r=JSON.parse(n[0]),s=r.riskLevel?.toLowerCase();if(s==="none"||s==="low"||s==="critical")return{riskLevel:s,reason:r.reason??"No reason"}}let o=t.toLowerCase();return o.includes('"critical"')||o.includes("critical risk")?{riskLevel:"critical",reason:"AI indicated critical risk"}:o.includes('"none"')||o.includes("no risk")?{riskLevel:"none",reason:"AI indicated no risk"}:(console.warn("[audit] could not parse response, defaulting to low"),{riskLevel:"low",reason:"Could not parse AI response"})}catch(n){return console.warn("[audit] parse error:",n),{riskLevel:"low",reason:"Failed to parse AI response"}}}async function Zo(e,t,n,o){let r=Yo(n,o);try{let l=(await qo(e,{messages:[{role:"user",content:r,timestamp:Date.now()}]},{apiKey:t,maxTokens:500,temperature:0})).content.find(c=>c.type==="text"),a=l?.type==="text"?l.text:"";return Qo(a)}catch(s){let l=s instanceof Error?s.message:String(s);return console.error("[audit] AI analysis failed:",l),{riskLevel:"low",reason:`AI analysis failed: ${l}`}}}function er(e,t){let n=e.trim();return t.some(o=>o.test(n))}function tr(e){let t=[];for(let n of e)try{t.push(new RegExp(n,"i"))}catch{console.warn(`[audit] invalid whitelist pattern: ${n}`)}return t}async function Z(e,t,n){try{await R(un);let o=mn.join(un,`${e}-${t}.log`),r=JSON.stringify(n)+`
25
+ `;await Ho.appendFile(o,r,"utf8")}catch(o){let r=o instanceof Error?o.message:String(o);console.error(`[audit] failed to write audit log: ${r}`)}}function nr(e){let t=e.toolName==="bash"?e.input.command??JSON.stringify(e.input):JSON.stringify(e.input,null,2);return["[Security Alert]",`Tool: ${e.toolName}`,`Command: ${t.slice(0,300)}`,`Risk: ${e.riskLevel.toUpperCase()} - ${e.analysis}`,"",'Press "Approve" to continue or "Stop" to block.'].join(`
26
+ `)}function gn(e,t){let n=m.audit,o=tr(n.whitelistPatterns);return r=>{r.on("tool_call",async(s,l)=>{let{toolName:a,toolCallId:c,input:u}=s,i={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:a,toolCallId:c,input:u,riskLevel:"none",analysis:"",action:"passed"};if(Go.has(a)){i.analysis="Read-only tool",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (read-only)`);return}if(!Vo.has(a)){i.analysis="Tool not in analysis scope",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (not analyzed)`);return}if(a==="bash"){let g=u.command??"";if(er(g,o)){i.analysis="Whitelisted bash command",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (whitelisted)`);return}}if(!t){i.analysis="No audit model configured",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (no audit model)`);return}console.log(`[audit] analyzing tool=${a} id=${c}`);let d=await Zo(t.model,t.apiKey,a,u);if(i.riskLevel=d.riskLevel,i.analysis=d.reason,d.riskLevel==="none"||d.riskLevel==="low"){i.action="passed",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} risk=${d.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${a} id=${c} reason=${d.reason}`);try{let g=nr(i);if(await e.requestConfirmation(g,n.confirmTimeoutMs)){i.action="approved",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=approved`);return}return i.action="blocked",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (user rejected)`),l.abort(),{block:!0,reason:"Operation blocked by user due to security risk."}}catch(g){let f=g instanceof Error?g.message:String(g);return i.action="blocked",i.analysis=`${d.reason} (confirmation failed: ${f})`,await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (${f})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${f}`}}})}}var Go,Vo,Xo,un,pn=j(()=>{"use strict";H();Y();Go=new Set(["read","ls","find","grep"]),Vo=new Set(["bash"]),Xo=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
27
+
28
+ Command: {{command}}
29
+
30
+ Risk levels:
31
+ - "none": Safe (read-only, standard dev tools)
32
+ - "low": Minor risk (file writes, package installs)
33
+ - "critical": High risk (secrets exposure, destructive ops, network attacks, privilege escalation)
34
+
35
+ Reply format (ONLY this JSON, nothing else):
36
+ {"riskLevel":"none|low|critical","reason":"brief explanation"}`;un=mn.join(m.sessionDir,"audit-logs")});import{createAgentSession as or,AuthStorage as rr,ModelRegistry as sr,SessionManager as ir,SettingsManager as ar,DefaultResourceLoader as cr}from"@mariozechner/pi-coding-agent";import je from"node:fs/promises";import Fe from"node:path";function fn(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function dr(e,t){let n=e.trim();if(!n)return{provider:t,modelId:""};if(n.includes("/")){let[o,r]=n.split("/",2);return{provider:o.trim()||t,modelId:r.trim()}}return{provider:t,modelId:n}}function ur(e,t){return e!=="openai-codex"?t:lr[t]??t}function mr(e,t){let n=e.getAvailable().filter(r=>r.provider===t);return n.length>0?n[0]:e.getAll().filter(r=>r.provider===t)[0]}function gr(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=fn(t?.provider||m.modelProvider||"openai-codex"),s=n||o?"":m.modelRef||"",{provider:l,modelId:a}=dr(s,r),c=t?.provider?r:fn(l),u=o?t?.modelId?.trim()||"":a;if(!u){let g=mr(e,c);return g?{model:g,provider:c,modelId:g.id}:{model:void 0,provider:c,modelId:""}}let i=ur(c,u);return{model:e.find(c,i),provider:c,modelId:i}}function pr(e){let t=q();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function fr(e){if(e?.role!=="assistant")return"";let n=e.content;if(typeof n=="string")return n.trim();if(!Array.isArray(n))return"";let o=n.filter(s=>typeof s=="object"&&s&&s.type==="text").map(s=>s.text??"").map(s=>s.trim()).filter(Boolean);if(o.length>0)return o.join(`
37
+
38
+ `);let r=n.filter(s=>typeof s=="object"&&s&&s.type==="thinking").map(s=>s.thinking??"").map(s=>s.trim()).filter(Boolean);return r.length>0?r.join(`
39
+
40
+ `):""}function yr(e){if(e.length===0)return"messages=0";let t=e.slice(-6).map(n=>{let o=n?.role??"unknown",r=n.content,s=n?.stopReason,l=n?.errorMessage;if(typeof r=="string")return`${o}(text:${r.length}${s?`,stop=${s}`:""})`;if(Array.isArray(r)){let c=[`blocks:${r.map(u=>typeof u=="object"&&u&&"type"in u?String(u.type||"unknown"):typeof u).join(",")||"none"}`,s?`stop=${s}`:null,l?"error=1":null].filter(Boolean).join(",");return`${o}(${c})`}if(r==null){let a=["empty",s?`stop=${s}`:null,l?"error=1":null].filter(Boolean).join(",");return`${o}(${a})`}return`${o}(${typeof r}${s?`,stop=${s}`:""})`});return`messages=${e.length} last=[${t.join(" ")}]`}function hr(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
41
+
42
+ Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function wr(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=fr(e[o]);if(r)return r}return""}function br(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function yn(e){let t=e.workspaceDir||m.workspaceDir;await R(m.sessionDir),await R(m.agentDir),await R(t);let n=Ye(e.chatId,e.sessionId),o=Fe.join(m.agentDir,"auth.json"),r=new rr(o),s=pr(r);s&&console.log(`[tg-agent] codex oauth source=${s.source} expiresAt=${new Date(s.expiresAt).toISOString()}`);let l=Fe.join(m.agentDir,"models.json"),a=new sr(r,l),{model:c,provider:u,modelId:i}=gr(a,{provider:e.modelProvider,modelId:e.modelId});i&&!c&&console.warn(`[tg-agent] model not found: ${u}/${i}`);let d=ir.open(n),g=ar.create(t,m.agentDir);try{let h=Fe.join(m.agentDir,"skills"),v=Fe.join(t,".pi","skills"),L=await je.access(h).then(()=>!0).catch(()=>!1),C=await je.access(v).then(()=>!0).catch(()=>!1);if(L){let X=(await je.readdir(h,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] skills directory found at ${h} with ${X.length} skill(s): ${X.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${h}`);if(C){let X=(await je.readdir(v,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] workspace skills directory found at ${v} with ${X.length} skill(s): ${X.join(", ")}`)}let B=g.getSettings?.();if(B){let X=B.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${X}`)}}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] skills check failed: ${v}`)}let f="";try{f=await xe(m.agentDir,{timeoutMs:4e3,maxBytes:m.fetchMaxBytes,maxChars:3e3})}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] mcp catalog error: ${v}`)}let y=[];if(m.audit.enabled&&e.auditContext){let h={...e.auditContext,sessionId:e.sessionId},v;if(m.audit.modelProvider&&m.audit.modelId){let L=a.find(m.audit.modelProvider,m.audit.modelId);if(L){let C=await r.getApiKey(m.audit.modelProvider);v={provider:m.audit.modelProvider,model:L,apiKey:C??void 0},console.log(`[tg-agent] audit model: ${m.audit.modelProvider}/${m.audit.modelId} apiKey=${C?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${m.audit.modelProvider}/${m.audit.modelId}`)}y.push(gn(h,v)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let w=e.systemPrompt?.trim(),k=[];w&&k.push(w),f&&k.push(f);let A=k.length>0?k.join(`
43
+
44
+ `):void 0;console.log(`[tg-agent] systemPrompt append=${A?A.slice(0,80)+"...":"(none)"}`);let I=new cr({cwd:t,agentDir:m.agentDir,settingsManager:g,extensionFactories:y.length>0?y:void 0,appendSystemPrompt:A});await I.reload();let{session:x,modelFallbackMessage:P}=await or({cwd:t,agentDir:m.agentDir,authStorage:r,modelRegistry:a,model:c??void 0,sessionManager:d,settingsManager:g,resourceLoader:I,customTools:en({telegram:e.telegram})});try{let h=x.messages,v=h.some(N=>{let X=N.role,K=N.content;return X==="system"&&typeof K=="string"?K.toLowerCase().includes("compaction")||K.toLowerCase().includes("compact"):N.type==="compaction"||N.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof d}`),console.log(`[tg-agent] session messages count: ${h.length}`),console.log(`[tg-agent] compacting support detected: ${v||"unknown (will be detected during runtime)"}`);let C=typeof d.compact=="function",B=typeof d.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${C}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${B}`)}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] compacting check failed: ${v}`)}P&&console.warn(`[tg-agent] modelFallback=${P}`);let ae=!1,S=()=>{ae=!0,x.abort()};e.onAbortReady?.(S);let b=m.logAgentEvents,$=m.logAgentStream,D=new Map,gt=x.subscribe(h=>{switch(h.type){case"agent_start":b&&console.log(`[tg-agent] agent start session=${e.sessionId}`),F=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":b&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":b&&console.log(`[tg-agent] turn start session=${e.sessionId}`),F=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":b&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${h.toolResults.length}`),F=Date.now(),e.onStatus?.({type:"turn_end",toolResults:h.toolResults.length});break;case"message_start":{if(b){let v=h.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${v}`)}F=Date.now();{let v=h.message.role??"unknown";e.onStatus?.({type:"message_start",role:v})}break}case"message_end":{if(b){let v=h.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${v}`)}F=Date.now();{let v=h.message.role??"unknown";e.onStatus?.({type:"message_end",role:v})}break}case"message_update":{if(!$)break;if(h.assistantMessageEvent.type==="text_delta"){let L=(h.assistantMessageEvent.delta??"").length;L>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${L}`),F=Date.now()}h.assistantMessageEvent.type==="thinking_delta"&&(F=Date.now());break}case"tool_execution_start":{D.set(h.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${h.toolName} id=${h.toolCallId}`),Ae+=1,F=Date.now(),e.onStatus?.({type:"tool_start",name:h.toolName,id:h.toolCallId,args:h.args});break}case"tool_execution_end":{let v=D.get(h.toolCallId),L=v?Date.now()-v:0;console.log(`[tg-agent] tool end name=${h.toolName} id=${h.toolCallId} ok=${!h.isError} durationMs=${L}`),D.delete(h.toolCallId),Ae=Math.max(0,Ae-1),F=Date.now(),e.onStatus?.({type:"tool_end",name:h.toolName,id:h.toolCallId,ok:!h.isError,durationMs:L});break}case"auto_compaction_start":{let v=h.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${v}`),F=Date.now();break}case"auto_compaction_end":{let v=h.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${v}`),F=Date.now();break}default:break}}),oe=null,ye=null,ke=!1,pt=0,ft=!1,F=Date.now(),Ae=0;try{let h=Date.now();oe=setInterval(()=>{let C=Date.now()-h;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${C} streaming=${x.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:C,streaming:x.isStreaming})},15e3),ye=setInterval(()=>{if(ke||Ae>0)return;let C=Date.now()-F,B=x.isStreaming?m.modelTimeoutStreamingMs:m.modelTimeoutMs,N=Math.max(1e3,B);C>=N&&(ke=!0,pt=N,ft=x.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${C}`),x.abort())},2e3);try{if(await x.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),ke)throw new Error(`Model request timed out after ${m.modelTimeoutMs}ms`)}catch(C){if(ae)throw new Error("Cancelled by user.");if(ke){let B=ft?" (streaming)":"",N=pt||m.modelTimeoutMs;throw new Error(`Model request timed out after ${N}ms${B}`)}throw C}oe&&clearInterval(oe);let v=br(x.messages);if(v){let C=v?.stopReason,B=v?.errorMessage;if(C==="error"){let N=B?hr(B):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${N}`),new Error(N)}}let L=wr(x.messages,x);if(!L){let C=yr(x.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${C}`),new Error("No assistant response.")}return{text:L,sessionFile:n,sessionId:x.sessionId,modelProvider:x.model?.provider??u,modelId:x.model?.id??i,modelFallbackMessage:P}}finally{oe&&clearInterval(oe),ye&&clearInterval(ye),gt(),d.flushPendingToolResults?.(),x.dispose()}}var lr,hn=j(()=>{"use strict";H();le();tn();De();Y();nt();pn();lr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import xr from"node:path";import*as wn from"@lancedb/lancedb";import ot from"openai";function Sr(){if(ee)return ee;let e=m.memory.rag;if(e.embeddingApiKey){let n={apiKey:e.embeddingApiKey};return e.embeddingBaseUrl&&(n.baseURL=e.embeddingBaseUrl),ee=new ot(n),console.log(`[memory-rag] using embedding API key${e.embeddingBaseUrl?` (baseURL: ${e.embeddingBaseUrl})`:""}`),ee}if(m.openaiApiKey)return ee=new ot({apiKey:m.openaiApiKey}),console.log("[memory-rag] using OpenAI API key from config"),ee;let t=q();if(t)return ee=new ot({apiKey:t.accessToken}),console.log("[memory-rag] using Codex OAuth token"),ee;throw new Error("No API key for embeddings. Set memory.rag.embedding_api_key or run `codex login`.")}async function st(e){let t=Sr(),n=m.memory.rag.embeddingModel;console.log(`[memory-rag] embedding ${e.length} chars using ${n}`);let o=3e4,r=new Promise((s,l)=>{setTimeout(()=>l(new Error(`Embedding timeout after ${o}ms`)),o)});try{let s=await Promise.race([t.embeddings.create({model:n,input:e,encoding_format:"float"}),r]);if(!s?.data?.[0]?.embedding)throw new Error(`Invalid embedding response: ${JSON.stringify(s).slice(0,200)}`);let l=s.data[0].embedding;return console.log(`[memory-rag] got ${l.length}D embedding`),l}catch(s){throw s instanceof Error&&console.error(`[memory-rag] embedding error: ${s.message}`),s}}async function me(){return ze||(await R(rt),ze=await wn.connect(rt),console.log(`[memory-rag] connected to DB at ${rt}`),ze)}async function Ue(e,t,n,o,r){let s={sessionSaved:!1,memoriesIndexed:0,errors:[]};if(!m.memory.rag.enabled)return console.log("[memory-rag] RAG disabled, skipping save"),s;console.log(`[memory-rag] saving session ${e}`);try{let l=await me(),a=await l.tableNames(),c={sessionId:e,date:t,title:n,transcript:o,reflection:JSON.stringify(r),memoryCount:r.memories?.length??0,timestamp:Date.now()};if(a.includes(te)?await(await l.openTable(te)).add([c]):await l.createTable(te,[c]),s.sessionSaved=!0,console.log("[memory-rag] session saved to DB"),r.memories&&r.memories.length>0){let u=await $r(e,t,r.memories);s.memoriesIndexed=u.indexed,s.errors=u.errors}return s}catch(l){let a=l instanceof Error?l.message:String(l);return console.error(`[memory-rag] saveSession failed: ${a}`),s.errors.push(a),s}}async function Mr(){try{let e=await me();return(await e.tableNames()).includes(te)?(await(await e.openTable(te)).query().toArray()).map(r=>({sessionId:r.sessionId,date:r.date,title:r.title,transcript:r.transcript,reflection:r.reflection,memoryCount:r.memoryCount,timestamp:r.timestamp})):[]}catch(e){return console.error(`[memory-rag] getAllSessions failed: ${e}`),[]}}async function $r(e,t,n){let o={indexed:0,errors:[]};if(!m.memory.rag.enabled||n.length===0)return o;console.log(`[memory-rag] indexing ${n.length} memories for session ${e}`);try{let r=await me(),s=await r.tableNames(),l,a=!1;s.includes(G)?l=await r.openTable(G):a=!0;for(let c=0;c<n.length;c++){let u=n[c];try{let i=await st(u.content),d={id:`${e}-${c}`,sessionId:e,date:t,type:u.type,content:u.content,vector:i,timestamp:Date.now()};a?(l=await r.createTable(G,[d]),a=!1,console.log("[memory-rag] created memories table")):await l.add([d]),o.indexed++,console.log(`[memory-rag] indexed [${c+1}/${n.length}]: ${u.type}`)}catch(i){let d=i instanceof Error?i.message:String(i);o.errors.push(`${u.type}: ${d}`),console.error(`[memory-rag] failed to index item ${c}: ${d}`)}c<n.length-1&&await new Promise(i=>setTimeout(i,200))}return console.log(`[memory-rag] indexed ${o.indexed}/${n.length} memories`),o}catch(r){let s=r instanceof Error?r.message:String(r);return console.error(`[memory-rag] indexMemoryItems failed: ${s}`),o.errors.push(s),o}}async function bn(e,t=m.memory.rag.maxResults,n=m.memory.rag.similarityThreshold){if(!m.memory.rag.enabled)return[];console.log(`[memory-rag] searching: "${e.slice(0,50)}..."`);try{let o=await me();if(!(await o.tableNames()).includes(G))return console.log("[memory-rag] memories table not found"),[];let s=await o.openTable(G),l=await s.countRows();console.log(`[memory-rag] memories table has ${l} rows`);let a=await st(e),c=await s.vectorSearch(a).column(vr).limit(t*2).toArray();if(console.log(`[memory-rag] search returned ${c.length} results`),c.length>0){let d=c.map(g=>g._distance?.toFixed(4)??"N/A");console.log(`[memory-rag] distances: [${d.join(", ")}]`)}let u=(1-n)*2;console.log(`[memory-rag] threshold=${n}, maxDistance=${u.toFixed(4)}`);let i=c.filter(d=>{let g=d._distance;return g===void 0||g<=u}).slice(0,t).map(d=>({id:d.id,sessionId:d.sessionId,date:d.date,type:d.type,content:d.content,timestamp:d.timestamp,_distance:d._distance}));return console.log(`[memory-rag] filtered: ${i.length} memories`),i.length>0&&i.forEach((d,g)=>{console.log(`[memory-rag] ${g+1}. [${d.type}] "${d.content.slice(0,50)}..." (dist=${d._distance?.toFixed(4)??"N/A"})`)}),i}catch(o){let r=o instanceof Error?o.message:String(o);return console.warn(`[memory-rag] search failed: ${r}`),[]}}async function xn(){try{let e=await me(),t=await e.tableNames(),n=0,o=0;return t.includes(te)&&(n=await(await e.openTable(te)).countRows()),t.includes(G)&&(o=await(await e.openTable(G)).countRows()),{sessionsCount:n,memoriesCount:o,embeddingModel:m.memory.rag.embeddingModel}}catch{return{sessionsCount:0,memoriesCount:0,embeddingModel:m.memory.rag.embeddingModel}}}async function vn(e){let t={success:!1,totalSessions:0,totalMemories:0,indexedMemories:0,errors:[],embeddingModel:m.memory.rag.embeddingModel,vectorDimension:null};console.log("[reindex] ========================================"),console.log("[reindex] Rebuilding memories from sessions table"),console.log(`[reindex] Embedding model: ${m.memory.rag.embeddingModel}`),console.log("[reindex] ========================================");try{let n=await me(),o=await n.tableNames();if(!o.includes(te))return console.log("[reindex] No sessions table found, nothing to reindex"),t.success=!0,t;let r=await Mr();if(t.totalSessions=r.length,r.length===0)return console.log("[reindex] No sessions found"),t.success=!0,t;console.log(`[reindex] Found ${r.length} sessions`);let s=[];for(let a of r)try{let c=JSON.parse(a.reflection);if(c.memories&&c.memories.length>0)for(let u of c.memories)s.push({sessionId:a.sessionId,date:a.date,item:u})}catch(c){console.warn(`[reindex] Failed to parse reflection for session ${a.sessionId}: ${c}`)}if(t.totalMemories=s.length,console.log(`[reindex] Found ${s.length} memories to reindex`),s.length===0)return console.log("[reindex] No memories to reindex"),t.success=!0,t;o.includes(G)&&(await n.dropTable(G),console.log("[reindex] Dropped old memories table"));let l=null;for(let a=0;a<s.length;a++){let{sessionId:c,date:u,item:i}=s[a],d=`[${a+1}/${s.length}]`;try{e?.(a+1,s.length,`Indexing: ${i.content.slice(0,30)}...`);let g=await st(i.content);t.vectorDimension===null&&(t.vectorDimension=g.length);let f={id:`${c}-${a}`,sessionId:c,date:u,type:i.type,content:i.content,vector:g,timestamp:Date.now()};l===null?(l=await n.createTable(G,[f]),console.log(`[reindex] ${d} Created new memories table`)):await l.add([f]),t.indexedMemories++,console.log(`[reindex] ${d} Indexed: [${i.type}] ${i.content.slice(0,40)}...`)}catch(g){let f=g instanceof Error?g.message:String(g);t.errors.push(`${i.content.slice(0,30)}: ${f}`),console.error(`[reindex] ${d} Failed: ${f}`)}a<s.length-1&&await new Promise(g=>setTimeout(g,200))}return console.log("[reindex] ========================================"),console.log("[reindex] Reindex complete!"),console.log(`[reindex] Sessions: ${t.totalSessions}`),console.log(`[reindex] Total memories: ${t.totalMemories}`),console.log(`[reindex] Indexed: ${t.indexedMemories}`),console.log(`[reindex] Errors: ${t.errors.length}`),console.log("[reindex] ========================================"),t.success=!0,t}catch(n){let o=n instanceof Error?n.message:String(n);return console.error(`[reindex] Failed: ${o}`),t.errors.push(o),t}}var rt,te,G,vr,ze,ee,it=j(()=>{"use strict";H();Y();le();rt=xr.join(m.agentDir,"tg-memory-db"),te="sessions",G="memories",vr="vector",ze=null,ee=null});import Sn from"node:path";import{AuthStorage as kr,ModelRegistry as Ar}from"@mariozechner/pi-coding-agent";import{completeSimple as _r,getModel as Pr}from"@mariozechner/pi-ai";function Cr(){return m.memory.systemPrompt||Rr}function Er(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Dr(e,t){return e!=="openai-codex"?t:Tr[t]??t}async function Or(e,t){await R(m.agentDir);let n=Sn.join(m.agentDir,"auth.json"),o=new kr(n),r=q();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let s=Sn.join(m.agentDir,"models.json"),l=new Ar(o,s),a=async(d,g,f)=>{let y=Er(d),w=Dr(y,g),k=l.find(y,w);if(!k)try{k=Pr(y,w)}catch{}if(k){let A=await o.getApiKey(y);return{model:k,provider:y,modelId:w,apiKey:A??void 0,source:f}}return null};if(e&&t){let d=await a(e,t,"session");if(d)return console.log(`[memory] using session model: ${d.provider}/${d.modelId}`),d}if(m.memory.modelProvider&&m.memory.modelId){let d=await a(m.memory.modelProvider,m.memory.modelId,"memory-config");if(d)return console.log(`[memory] using configured memory model: ${d.provider}/${d.modelId}`),d}let c=m.modelProvider,u=m.modelRef.includes("/")?m.modelRef.split("/")[1]:m.modelRef;if(c&&u){let d=await a(c,u,"system-default");if(d)return console.log(`[memory] using system default model: ${d.provider}/${d.modelId}`),d}let i=l.getAll();if(i.length>0){let d=i[0],g=await o.getApiKey(d.provider);return console.log(`[memory] using first available model: ${d.provider}/${d.id}`),{model:d,provider:d.provider,modelId:d.id,apiKey:g??void 0,source:"first-available"}}return console.warn("[memory] no model available for reflection"),null}function Ir(e){let t={emotional:"",insights:"",advice:"",memories:[]};if(!e.trim())return t;try{let n=e.trim(),o=n.match(/```(?:json)?\s*([\s\S]*?)```/);o&&(n=o[1].trim());let r=JSON.parse(n),s={emotional:typeof r.emotional=="string"?r.emotional:"",insights:typeof r.insights=="string"?r.insights:"",advice:typeof r.advice=="string"?r.advice:"",memories:[]};if(Array.isArray(r.memories))for(let l of r.memories)typeof l=="object"&&typeof l.type=="string"&&typeof l.content=="string"&&s.memories.push({type:l.type,content:l.content});return console.log(`[memory] parsed ${s.memories.length} memories from reflection`),s}catch(n){return console.warn(`[memory] failed to parse JSON response: ${n}`),console.warn(`[memory] raw response: ${e.slice(0,500)}...`),{emotional:"",insights:e.slice(0,500),advice:"",memories:[{type:"insight",content:`Session summary: ${e.slice(0,200)}`}]}}}async function Be(e,t,n){if(!m.memory.enabled)return{success:!0,reflected:!1,memoriesIndexed:0};if(e.messages.length===0)return{success:!0,reflected:!1,memoriesIndexed:0};let r=new Date().toISOString().split("T")[0],s=e.messages.map(a=>`[${a.role.toUpperCase()}]: ${a.content}`).join(`
45
+
46
+ `),l=await Or(t,n);if(!l){console.log("[memory] no model available, saving raw session");let a={emotional:"",insights:"No model available for reflection",advice:"",memories:[]};return{success:(await Ue(e.id,r,e.title,s,a)).sessionSaved,reflected:!1,memoriesIndexed:0}}console.log(`[memory] reflecting on session ${e.id} using ${l.provider}/${l.modelId}`);try{let c=`${Cr()}
6
47
 
7
48
  ---
8
49
 
9
50
  Conversation transcript:
10
51
 
11
- ${s}`,i=(await go(l.model,{messages:[{role:"user",content:c,timestamp:Date.now()}]},{apiKey:l.apiKey,maxTokens:2e3,temperature:.7})).content.find(y=>y.type==="text"),d=i?.type==="text"?i.text:"",g=xo(d);console.log(`[memory] reflection generated: ${g.memories.length} memories`);let f=await Re(e.id,r,e.title,s,g);return f.errors.length>0&&console.warn(`[memory] some errors during save: ${f.errors.join(", ")}`),console.log(`[memory] session archived, ${f.memoriesIndexed} memories indexed`),{success:f.sessionSaved,reflected:!0,memoriesIndexed:f.memoriesIndexed}}catch(a){let c=a instanceof Error?a.message:String(a);console.error(`[memory] reflection failed: ${c}`);let u={emotional:"",insights:`Reflection failed: ${c}`,advice:"",memories:[]};return{success:(await Re(e.id,r,e.title,s,u)).sessionSaved,reflected:!1,memoriesIndexed:0,error:c}}}var Xe,yo,Ye=j(()=>{"use strict";W();Y();ce();Ve();Xe=`You are a caring AI companion summarizing a conversation with Shawn.
52
+ ${s}`,i=(await _r(l.model,{messages:[{role:"user",content:c,timestamp:Date.now()}]},{apiKey:l.apiKey,maxTokens:2e3,temperature:.7})).content.find(y=>y.type==="text"),d=i?.type==="text"?i.text:"",g=Ir(d);console.log(`[memory] reflection generated: ${g.memories.length} memories`);let f=await Ue(e.id,r,e.title,s,g);return f.errors.length>0&&console.warn(`[memory] some errors during save: ${f.errors.join(", ")}`),console.log(`[memory] session archived, ${f.memoriesIndexed} memories indexed`),{success:f.sessionSaved,reflected:!0,memoriesIndexed:f.memoriesIndexed}}catch(a){let c=a instanceof Error?a.message:String(a);console.error(`[memory] reflection failed: ${c}`);let u={emotional:"",insights:`Reflection failed: ${c}`,advice:"",memories:[]};return{success:(await Ue(e.id,r,e.title,s,u)).sessionSaved,reflected:!1,memoriesIndexed:0,error:c}}}var Rr,Tr,Mn=j(()=>{"use strict";H();Y();le();it();Rr=`You are a caring AI companion summarizing a conversation with Shawn.
12
53
 
13
54
  Your task is to:
14
55
  1. Understand Shawn's emotional state and what's important to them
@@ -41,74 +82,33 @@ Guidelines:
41
82
  - Each memory should be self-contained and specific
42
83
  - Focus on information that would help Shawn in the future
43
84
  - Keep each memory concise (one sentence)
44
- - Prioritize what matters for Shawn's growth and wellbeing`;yo={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import Rt from"node:fs";import Ee from"node:path";import*as De from"@iarna/toml";function Et(){let e=J(Ct);return Ee.join(e,vo)}function T(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function _(e,t){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):t}function H(e,t){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"){let n=Number.parseInt(e,10);return Number.isNaN(n)?t:n}return t}function de(e,t){if(typeof e=="boolean")return e;if(typeof e=="string"){let n=e.trim().toLowerCase();if(n==="true"||n==="1"||n==="yes")return!0;if(n==="false"||n==="0"||n==="no")return!1}return t}function Dt(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?t:String(t)).map(t=>t.trim()).filter(Boolean):typeof e=="string"?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function So(e){return new Set(Dt(e))}function Mo(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,Ee.resolve(J(o.trim())));return t}function we(){let e=Et();try{let t=Rt.readFileSync(e,"utf8"),n=De.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Qe(e,t){await R(Ee.dirname(e));let n=De.stringify(t);await Rt.promises.writeFile(e,n,"utf8")}function Ot(){return{telegram:{bot_token:"",allowed_user_ids:[],parse_mode:""},model:{provider:"openai-codex",model:"gpt-5.2",openai_api_key:""},paths:{workspace_dir:"",session_dir:"~/.tg-agent/tg-sessions"},workspace_mappings:{},limits:{max_sessions:5,max_concurrent:5,max_history_messages:40,max_output_tokens:0},timeouts:{model_timeout_ms:6e4,model_timeout_stream_ms:3e5,fetch_timeout_ms:6e4},fetch:{max_bytes:2e5,proxy_url:""},proxy:{url:""},auth:{codex_home:"~/.codex"},logging:{agent_events:!0,agent_stream:!0},system:{prompt:Tt},tls:{extra_ca_certs:"",reject_unauthorized:""},security_audit:{enabled:!1,model_provider:"",model_id:"",whitelist_patterns:[],confirm_timeout_ms:12e4},memory:{enabled:!0,model_provider:"",model_id:"",system_prompt:"",rag:{enabled:!0,embedding_model:"openai/text-embedding-3-small",embedding_base_url:"",embedding_api_key:"",similarity_threshold:.5,max_results:5}}}}function Te(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function It(e,t){let n=!1,o=(r,s)=>{for(let[l,a]of Object.entries(s)){if(!(l in r)){r[l]=a,n=!0;continue}let c=r[l];Te(c)&&Te(a)&&o(c,a)}};return Te(e)&&Te(t)&&o(e,t),n}function Nt(e){let t=T(e,"telegram");return _(t.bot_token,"").trim()}function Lt(e,t){let n=T(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function jt(e){let t=T(e,"telegram"),n=T(e,"model"),o=T(e,"paths"),r=T(e,"limits"),s=T(e,"timeouts"),l=T(e,"fetch"),a=T(e,"proxy"),c=T(e,"auth"),u=T(e,"logging"),i=T(e,"system"),d=T(e,"tls"),g=T(e,"workspace_mappings"),f=T(e,"security_audit"),y=T(e,"memory"),w=T(y,"rag"),k=_(o.workspace_dir,process.cwd()),A=_(o.session_dir,"~/.tg-agent/tg-sessions"),I=Mo(g),x=_(d.reject_unauthorized,""),P=x===""?null:de(x,!0);return{telegramToken:_(t.bot_token,"").trim(),telegramAllowedUsers:So(t.allowed_user_ids),telegramParseMode:_(t.parse_mode,"").trim(),modelProvider:_(n.provider,"openai-codex").trim(),modelRef:_(n.model,"gpt-5.2").trim(),openaiApiKey:_(n.openai_api_key,"").trim(),sessionDir:J(A),agentDir:J(Ct),workspaceDir:Ee.resolve(J(k)),workspaceMappings:I,maxSessions:H(r.max_sessions,5),maxConcurrent:H(r.max_concurrent,5),maxHistoryMessages:H(r.max_history_messages,40),maxOutputTokens:H(r.max_output_tokens,0),fetchMaxBytes:H(l.max_bytes,2e5),fetchTimeoutMs:H(s.fetch_timeout_ms,6e4),modelTimeoutMs:H(s.model_timeout_ms,6e4),modelTimeoutStreamingMs:H(s.model_timeout_stream_ms,3e5),systemPrompt:_(i.prompt,Tt),proxyUrl:_(a.url,"").trim(),fetchProxyUrl:_(l.proxy_url,"").trim(),codexHome:J(_(c.codex_home,"~/.codex")),logAgentEvents:de(u.agent_events,!0),logAgentStream:de(u.agent_stream,!0),tlsExtraCaCerts:_(d.extra_ca_certs,"").trim(),tlsRejectUnauthorized:P,audit:{enabled:de(f.enabled,!1),modelProvider:_(f.model_provider,"").trim(),modelId:_(f.model_id,"").trim(),whitelistPatterns:Dt(f.whitelist_patterns),confirmTimeoutMs:H(f.confirm_timeout_ms,6e4)},memory:{enabled:de(y.enabled,!0),modelProvider:_(y.model_provider,"").trim(),modelId:_(y.model_id,"").trim(),systemPrompt:_(y.system_prompt,Xe).trim(),rag:{enabled:de(w.enabled,!0),embeddingModel:_(w.embedding_model,"openai/text-embedding-3-small").trim(),embeddingBaseUrl:_(w.embedding_base_url,"").trim(),embeddingApiKey:_(w.embedding_api_key,"").trim(),similarityThreshold:H(w.similarity_threshold,.5),maxResults:H(w.max_results,5)}}}}function Ft(){let{data:e}=we();return m=jt(e),m}function zt(){let e=[];if(m.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${Et()})`)}var Ct,vo,Tt,$o,m,W=j(()=>{"use strict";Y();Ye();Ct="~/.tg-agent",vo="config.toml",Tt=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
45
-
46
- Important behavioral rules:
47
- - Do NOT mention the name of your underlying framework, technical implementation, or any package names
48
- - Do NOT refer to yourself as "pi", "pi-coding-agent", or any other framework/tool name
49
- - When users ask about your identity or implementation, simply say you are a coding assistant
50
- - Focus on helping with tasks rather than discussing your technical stack or architecture
51
- - Do not mention documentation paths or framework-specific resources unless directly relevant to the task
52
-
53
- Be concise and practical in all responses.`;({data:$o}=we()),m=jt($o)});function Ut(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=q();if(n)return{apiKey:n.accessToken,source:`codex:${n.source}`};throw new Error("No Codex OAuth credentials found. Run `codex login`.")}if(m.openaiApiKey)return{apiKey:m.openaiApiKey,source:"config.model.openai_api_key"};throw new Error(`No API key for provider: ${e}`)}function ko(){return m.proxyUrl?{url:m.proxyUrl,source:"config.proxy.url"}:m.fetchProxyUrl?{url:m.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function Bt(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function Kt(){let e=ko();return e?{url:e.url,kind:Bt(e.url),source:e.source}:null}function Jt(){let e=[{key:"config.fetch.proxy_url",value:m.fetchProxyUrl},{key:"config.proxy.url",value:m.proxyUrl}];for(let t of e){let n=t.value?.trim();if(!n)continue;let o=Bt(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var Ze=j(()=>{"use strict";W();ce()});import{ProxyAgent as Ao,setGlobalDispatcher as _o}from"undici";function Ht(){if(Wt)return et;Wt=!0;let e=Jt();if(!e)return et=null,null;let t=new Ao(e.url);return _o(t),et=e,e}var Wt,et,qt=j(()=>{"use strict";Ze();Wt=!1,et=null});import Po from"node:fs";import Ro from"node:fs/promises";import Co from"node:path";import To from"node:readline";import{spawn as Eo}from"node:child_process";import*as Vt from"@iarna/toml";function Qt(e){return Co.join(e,"config.toml")}function Oe(e){let t=Qt(e);try{let n=Po.readFileSync(t,"utf8");return nn(n)}catch{return[]}}async function be(e){let t=Qt(e);try{let n=await Ro.readFile(t,"utf8");return nn(n)}catch{return[]}}async function xe(e,t={}){if(ue)return ue;let n=await be(e);if(n.length===0)return ue="","";let o=t.maxTools??Oo,r=t.maxChars??Io,s=t.timeoutMs??4e3,l=t.maxBytes??Xt,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let i=await Lo(u,{timeoutMs:s,maxBytes:l});if(a.push(`${u.name} (${u.type})`),i.length===0){a.push(" - tools unavailable");continue}let d=i.slice(0,o);for(let g of d){let f=g.description?`: ${g.description}`:"";a.push(` - ${g.name}${f}`)}i.length>d.length&&a.push(` - ...and ${i.length-d.length} more`)}let c=a.join(`
54
- `);return c.length>r&&(c=`${c.slice(0,r-20)}...
55
- (truncated)`),ue=c,c}function nt(){ue&&(Yt=!0)}function Zt(){ue=null,Yt=!1,U.clear()}function re(e){if(e.type==="http")return e.url?`url=${e.url}`:"url=(missing)";let t=e.args&&e.args.length>0?` ${e.args.join(" ")}`:"";return e.command?`command=${e.command}${t}`:"command=(missing)"}async function en(e,t=5e3){let n=Date.now();try{return await Ie(e,"tools/list",{},{timeoutMs:t}),{ok:!0,durationMs:Date.now()-n}}catch(o){let r=o instanceof Error?o.message:String(o);return{ok:!1,durationMs:Date.now()-n,error:r}}}async function Ie(e,t,n,o={}){let r=Gt(o.timeoutMs??Do,1e3,12e4),s=Gt(o.maxBytes??Xt,1024,5e6),l=new AbortController,a=()=>l.abort();o.signal?.addEventListener("abort",a,{once:!0});let c=setTimeout(()=>l.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await zo(e,s,l.signal),await Fo(e,t,n,s,l.signal)):await Ko(e,t,n,s,l.signal)}finally{clearTimeout(c),o.signal?.removeEventListener("abort",a)}}function Gt(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function Lo(e,t){try{let n=await Ie(e,"tools/list",{},t);return jo(n.output)}catch(n){let o=n instanceof Error?n.message:String(n);return console.warn(`[tg-agent] mcp tools/list failed server=${e.name} error=${o}`),[]}}function jo(e){let t;try{t=JSON.parse(e)}catch{return[]}if(!t||typeof t!="object")return[];let n=t,r=(n.result??n).tools??n.tools;if(!Array.isArray(r))return[];let s=[];for(let l of r){if(!l||typeof l!="object")continue;let a=l,c=typeof a.name=="string"?a.name:"";if(!c)continue;let u=typeof a.description=="string"?a.description:void 0,i=a.inputSchema;s.push({name:c,description:u,inputSchema:i})}return s}async function Fo(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await tt(e,t,n,o,r),a=tn(l.parsed);if(a)throw new Error(a);let c=l.bodyText;return l.parsed&&(c=JSON.stringify(l.parsed,null,2)),{ok:l.statusCode>=200&&l.statusCode<300,output:c,durationMs:Date.now()-s,bytes:l.bytes,truncated:l.truncated,statusCode:l.statusCode,statusText:l.statusText,contentType:l.contentType}}async function tt(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=U.get(e.name),l={jsonrpc:"2.0",id:`tg-agent-${Date.now()}`,method:t,params:n??{}},a={"content-type":"application/json"};e.auth&&(a.authorization=e.auth.startsWith("Bearer ")?e.auth:`Bearer ${e.auth}`),s?.cookie&&(a.cookie=s.cookie),s?.sessionId&&(a["mcp-session-id"]=s.sessionId);let c=await fetch(e.url,{method:"POST",headers:a,body:JSON.stringify(l),signal:r});Uo(e.name,c);let u=await Jo(c,o,r),i;try{i=JSON.parse(u.text)}catch{i=void 0}return Bo(e.name,i),{statusCode:c.status,statusText:c.statusText,contentType:c.headers.get("content-type"),bodyText:u.text,parsed:i,bytes:u.bytes,truncated:u.truncated}}function tn(e){if(!e||typeof e!="object")return null;let t=e;if(t.error&&typeof t.error=="object"){let n=t.error;if(typeof n.message=="string")return n.message}return typeof t.error_description=="string"?t.error_description:typeof t.error=="string"?t.error:null}async function zo(e,t,n){let o=U.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let s=await tt(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=tn(s.parsed);if(l){let u=l.toLowerCase();if(u.includes("method")&&u.includes("not"))return;throw new Error(l)}let a=new AbortController,c=setTimeout(()=>a.abort(),No);try{await tt(e,"notifications/initialized",{},t,a.signal)}catch{}finally{clearTimeout(c)}})();U.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let s=U.get(e.name);U.set(e.name,{initializedAt:Date.now(),cookie:s?.cookie,sessionId:s?.sessionId})}catch(s){throw U.delete(e.name),s}}function Uo(e,t){let o=U.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),s=t.headers.getSetCookie?.(),l=s&&s.length>0?s.join("; "):r;l&&U.set(e,{...o,cookie:l});let a=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");a&&U.set(e,{...o,sessionId:a})}function Bo(e,t){if(!t||typeof t!="object")return;let o=t.result;if(!o)return;let r=typeof o.sessionId=="string"&&o.sessionId||typeof o.session_id=="string"&&o.session_id;if(!r)return;let s=U.get(e)??{initializedAt:0};U.set(e,{...s,sessionId:r})}async function Ko(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=Eo(e.command,e.args??[],{stdio:["pipe","pipe","pipe"]}),a=()=>{l.killed||l.kill("SIGTERM")};if(r.aborted)throw a(),new Error("MCP request aborted.");let c=new Map,u=!1,i="",d=new Error("MCP request aborted."),g=To.createInterface({input:l.stdout,terminal:!1});g.on("line",S=>{if(S.length>o){u=!0;return}let b=null;try{b=JSON.parse(S)}catch{return}let $=typeof b.id=="string"?b.id:typeof b.id=="number"?String(b.id):"";if(!$)return;let D=c.get($);D&&(c.delete($),D.resolve(b))}),l.stderr?.on("data",S=>{let b=S.toString();if(i.length+b.length>o){u=!0;return}i+=b});let f=()=>{for(let S of c.values())S.reject(d);c.clear(),a()};r.addEventListener("abort",f,{once:!0});let y=S=>{let b=S===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let $ of c.values())$.reject(new Error(b));c.clear()};l.once("exit",S=>y(S));let w=async(S,b)=>{let $=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,D={jsonrpc:"2.0",id:$,method:S,params:b??{}};return await new Promise((oe,ye)=>{c.set($,{resolve:oe,reject:ye}),l.stdin?.write(`${JSON.stringify(D)}
56
- `)})};fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeInit",message:"sending initialize request",data:{elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{});let k=await w("initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}});if(fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:afterInit",message:"initialize response received",data:{elapsed:Date.now()-s,hasError:!!k.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),k.error&&typeof k.error=="object"){let S=k.error.message??"MCP initialize failed.";throw a(),new Error(String(S))}let A={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify(A)}
57
- `),fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeMethod",message:"sending method request",data:{method:t,elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"C"})}).catch(()=>{});let I=await w(t,n);r.removeEventListener("abort",f),g.close(),l.stdin?.end(),a();let x=new Promise(S=>{l.once("exit",()=>S())});if(await Promise.race([x,new Promise(S=>setTimeout(S,500))]),I.error&&typeof I.error=="object"){let S=I.error.message??"MCP request failed.";throw new Error(String(S))}let P=JSON.stringify(I,null,2),ae=P.length>o?P.slice(0,o):P;return P.length>o&&(u=!0),{ok:!0,output:ae,durationMs:Date.now()-s,bytes:Math.min(P.length,o),truncated:u}}async function Jo(e,t,n){let o=e.body?.getReader?.();if(!o){let d=await e.text(),g=Math.min(d.length,t);return{text:d.slice(0,t),bytes:g,truncated:d.length>t}}let r=new TextDecoder("utf-8"),s=[],l=0,a=!1;for(;;){if(n.aborted){try{await o.cancel()}catch{}throw new Error("MCP request aborted.")}let{done:d,value:g}=await o.read();if(d)break;if(!g)continue;let f=l+g.byteLength;if(f>t){let y=Math.max(0,t-l);y>0&&(s.push(g.slice(0,y)),l+=y),a=!0;try{await o.cancel()}catch{}break}s.push(g),l=f}let c=new Uint8Array(l),u=0;for(let d of s)c.set(d,u),u+=d.byteLength;return{text:r.decode(c),bytes:l,truncated:a}}function nn(e){let t=[],n;try{n=Vt.parse(e)}catch{return t}let o=n.mcp_servers;if(!o||typeof o!="object")return t;for(let[r,s]of Object.entries(o)){if(!s||typeof s!="object")continue;let l=s,a=typeof l.type=="string"?l.type.toLowerCase():void 0,c=typeof l.url=="string"?l.url:void 0,u=typeof l.command=="string"?l.command:void 0,i=a==="http"||a==="stdio"?a:c?"http":u?"stdio":void 0;if(!i||i==="http"&&!c||i==="stdio"&&!u)continue;let d;Array.isArray(l.args)&&(d=l.args.filter(f=>typeof f=="string").map(f=>f.trim()));let g=typeof l.auth=="string"?l.auth:typeof l.authorization=="string"?l.authorization:typeof l.token=="string"?l.token:void 0;t.push({name:r,type:i,url:c,command:u,args:d,auth:g})}return t}var Do,Xt,Oo,Io,ue,Yt,U,No,Ne=j(()=>{"use strict";Do=6e4,Xt=2e5,Oo=40,Io=3500,ue=null,Yt=!1,U=new Map,No=1500});import Q from"node:path";import Wo from"node:fs/promises";import{Type as M}from"@sinclair/typebox";function Le(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function Go(e){if(!e)return{};let t={};if(Array.isArray(e)){for(let n of e)n?.name&&(t[n.name]=n.value??"");return t}for(let[n,o]of Object.entries(e))n&&(t[n]=o);return t}function on(e){let t=m.fetchTimeoutMs>0?m.fetchTimeoutMs:qo;return Le(e||t,1e3,12e4)}function rn(e){let t=m.fetchMaxBytes>0?m.fetchMaxBytes:Ho;return Le(e||t,1024,5e6)}function sn(e,t,n){let o=e.trim();if(!o)return null;let r=J(o),s=Q.isAbsolute(r)?r:Q.join(n,r),l=Q.resolve(s);for(let a of t){let c=Q.resolve(a);if(l===c||l.startsWith(`${c}${Q.sep}`))return l}return null}async function an(e){try{let t=await Wo.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function Vo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Xo(e,t){let n=new Uint8Array(t),o=0;for(let r of e)n.set(r,o),o+=r.byteLength;return n}async function Yo(e,t,n){let o=e.body?.getReader?.();if(!o){let i=await e.text?.()??"",d=Math.min(i.length,t),g=i.length>t;return{text:i.slice(0,t),bytes:d,truncated:g}}let r=new TextDecoder("utf-8"),s=[],l=0,a=!1;for(;;){if(n?.aborted){try{await o.cancel?.()}catch{}throw new Error("Fetch aborted")}let{done:i,value:d}=await o.read();if(i)break;if(!d)continue;let g=l+d.byteLength;if(g>t){let f=Math.max(0,t-l);f>0&&(s.push(d.slice(0,f)),l+=f),a=!0;try{await o.cancel?.()}catch{}break}s.push(d),l=g}let c=Xo(s,l);return{text:r.decode(c),bytes:l,truncated:a}}function Qo(e,t){let n=`HTTP ${e.status} ${e.statusText}`.trim(),o=[`url: ${e.url}`,`bytes: ${e.bytes}${e.truncated?" (truncated)":""}`,`content-type: ${e.contentType??"unknown"}`];return`${n}
58
- ${o.join(`
59
- `)}
60
-
61
- ${t}`}function er(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:Zo,execute:async(e,t,n,o,r)=>{if(!Vo(t.url))return{content:[{type:"text",text:"Invalid URL. Only http(s) is allowed."}],details:{url:t.url,status:0,statusText:"invalid_url",bytes:0,truncated:!1,contentType:null}};let s=on(t.timeoutMs),l=rn(t.maxBytes),a=new AbortController,c=()=>a.abort();r?.addEventListener("abort",c,{once:!0});let u=setTimeout(()=>a.abort(),s);try{n?.({content:[{type:"text",text:`Fetching ${t.url}...`}],details:{url:t.url,status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let i=await fetch(t.url,{method:t.method?.toUpperCase()??"GET",headers:Go(t.headers),body:t.body,signal:a.signal}),d=await Yo(i,l,r),g=i.headers.get("content-type");return{content:[{type:"text",text:Qo({url:i.url,status:i.status,statusText:i.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g},d.text)}],details:{url:i.url,status:i.status,statusText:i.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g}}}catch(i){return{content:[{type:"text",text:`Fetch failed: ${i instanceof Error?i.message:String(i)}`}],details:{url:t.url,status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}finally{clearTimeout(u),r?.removeEventListener("abort",c)}}}}function nr(e,t,n){let o=t.status>0?`HTTP ${t.status} ${t.statusText}`.trim():t.statusText,r=[`server: ${e.name}`,`type: ${e.type}`,`target: ${t.target}`,`bytes: ${t.bytes}${t.truncated?" (truncated)":""}`,`content-type: ${t.contentType??"unknown"}`];return`${o}
62
- ${r.join(`
63
- `)}
64
-
65
- ${n}`}function or(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:tr,execute:async(t,n,o,r,s)=>{let l=await e();if(l.length===0)return{content:[{type:"text",text:"MCP is not configured. Add [mcp_servers.*] to ~/.tg-agent/config.toml."}],details:{server:"",type:"http",target:"",status:0,statusText:"not_configured",bytes:0,truncated:!1,contentType:null}};let a=n.server?.trim()??"";if(!a)if(l.length===1)a=l[0]?.name??"";else return{content:[{type:"text",text:`Multiple MCP servers configured. Provide server name. Available: ${l.map(u=>u.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let c=l.find(u=>u.name===a);if(!c)return{content:[{type:"text",text:`MCP server not found: ${a}. Available: ${l.map(u=>u.name).join(", ")}`}],details:{server:a,type:"http",target:"",status:0,statusText:"server_not_found",bytes:0,truncated:!1,contentType:null}};try{o?.({content:[{type:"text",text:`Calling MCP ${c.name} ${n.method}...`}],details:{server:c.name,type:c.type,target:re(c),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let u=await Ie(c,n.method,n.params??{},{timeoutMs:on(void 0),maxBytes:rn(void 0),signal:s});return{content:[{type:"text",text:nr(c,{server:c.name,type:c.type,target:re(c),status:u.statusCode??0,statusText:u.statusText??(u.ok?"ok":"error"),bytes:u.bytes,truncated:u.truncated,contentType:u.contentType??null},u.output)}],details:{server:c.name,type:c.type,target:re(c),status:u.statusCode??0,statusText:u.statusText??(u.ok?"ok":"error"),bytes:u.bytes,truncated:u.truncated,contentType:u.contentType??null}}}catch(u){return{content:[{type:"text",text:`MCP failed: ${u instanceof Error?u.message:String(u)}`}],details:{server:c.name,type:c.type,target:re(c),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function ir(e){let t=[m.workspaceDir,Q.join(m.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:rr,execute:async(n,o)=>{let r=sn(o.path,t,m.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let s=await an(r);return s?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${Q.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function ar(e){let t=[m.workspaceDir,Q.join(m.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:sr,execute:async(n,o)=>{let r=sn(o.path,t,m.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let s=await an(r);return s?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${Q.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function cn(e){let t=[er()];return e?.telegram&&(t.push(ir(e.telegram)),t.push(ar(e.telegram))),Oe(m.agentDir).length>0&&t.push(or(()=>be(m.agentDir))),t}var Ho,qo,Zo,tr,rr,sr,ln=j(()=>{"use strict";W();Ne();Y();Ho=2e5,qo=6e4;Zo=M.Object({url:M.String({description:"HTTP or HTTPS URL"}),method:M.Optional(M.String({description:"HTTP method (default: GET)"})),headers:M.Optional(M.Array(M.Object({name:M.String({description:"Header name"}),value:M.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:M.Optional(M.String({description:"Request body (string)"})),timeoutMs:M.Optional(M.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:M.Optional(M.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});tr=M.Object({server:M.Optional(M.String({description:"MCP server name"})),method:M.String({description:"MCP method name"}),params:M.Optional(M.Any({description:"MCP params payload"}))});rr=M.Object({path:M.String({description:"Image file path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))}),sr=M.Object({path:M.String({description:"File path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))})});import mn from"node:fs/promises";import gn from"node:path";function pn(e){return gn.join(m.sessionDir,`${e}.json`)}function dn(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function ot(e,t){let n=dn(e),o=dn(t);return gn.join(m.sessionDir,`${n}-${o}.jsonl`)}async function me(e,t){let n=ot(e,t);try{await mn.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function un(e,t){let n=t?.sessions??{},o=t?.activeSessionId??null,r=t?.workspaceDir,s={chatId:e,workspaceDir:r,activeSessionId:o,sessions:n};return(!o||!n[o])&&(s.activeSessionId=null),s}async function Fe(e){await R(m.sessionDir);let t=je.get(e);if(t)return t;let n=pn(e);try{let o=await mn.readFile(n,"utf8"),r=JSON.parse(o),s=un(e,r);return je.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=un(e,{});return je.set(e,r),r}throw o}}async function O(e){await R(m.sessionDir);let t=pn(e.chatId);await bt(t,e),je.set(e.chatId,e)}function rt(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function st(e){return[]}function ze(e,t){if(Object.keys(e.sessions).length>=m.maxSessions)throw new Error("Max sessions reached");let o=he(),r=z(),s={id:o,title:t&&t.length>0?t:`session-${o}`,messages:[],createdAt:r,updatedAt:r};return e.sessions[o]=s,e.activeSessionId=o,s}function fn(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function se(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function it(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function yn(e){e.messages=[],e.updatedAt=z()}function at(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=z()}function hn(e,t){e.workspaceDir=t}var je,ct=j(()=>{"use strict";W();Y();je=new Map});import cr from"node:fs/promises";import bn from"node:path";import{completeSimple as lr}from"@mariozechner/pi-ai";function gr(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return mr.replace("{{command}}",n)}function pr(e){let t=e.trim();console.log(`[audit] AI response: ${t.slice(0,200)}`);try{let n=JSON.parse(t),o=n.riskLevel?.toLowerCase();if(o==="none"||o==="low"||o==="critical")return{riskLevel:o,reason:n.reason??"No reason"}}catch{}try{let n=t.match(/\{[^{}]*"riskLevel"\s*:\s*"[^"]*"[^{}]*\}/);if(n){let r=JSON.parse(n[0]),s=r.riskLevel?.toLowerCase();if(s==="none"||s==="low"||s==="critical")return{riskLevel:s,reason:r.reason??"No reason"}}let o=t.toLowerCase();return o.includes('"critical"')||o.includes("critical risk")?{riskLevel:"critical",reason:"AI indicated critical risk"}:o.includes('"none"')||o.includes("no risk")?{riskLevel:"none",reason:"AI indicated no risk"}:(console.warn("[audit] could not parse response, defaulting to low"),{riskLevel:"low",reason:"Could not parse AI response"})}catch(n){return console.warn("[audit] parse error:",n),{riskLevel:"low",reason:"Failed to parse AI response"}}}async function fr(e,t,n,o){let r=gr(n,o);try{let l=(await lr(e,{messages:[{role:"user",content:r,timestamp:Date.now()}]},{apiKey:t,maxTokens:500,temperature:0})).content.find(c=>c.type==="text"),a=l?.type==="text"?l.text:"";return pr(a)}catch(s){let l=s instanceof Error?s.message:String(s);return console.error("[audit] AI analysis failed:",l),{riskLevel:"low",reason:`AI analysis failed: ${l}`}}}function yr(e,t){let n=e.trim();return t.some(o=>o.test(n))}function hr(e){let t=[];for(let n of e)try{t.push(new RegExp(n,"i"))}catch{console.warn(`[audit] invalid whitelist pattern: ${n}`)}return t}async function te(e,t,n){try{await R(wn);let o=bn.join(wn,`${e}-${t}.log`),r=JSON.stringify(n)+`
66
- `;await cr.appendFile(o,r,"utf8")}catch(o){let r=o instanceof Error?o.message:String(o);console.error(`[audit] failed to write audit log: ${r}`)}}function wr(e){let t=e.toolName==="bash"?e.input.command??JSON.stringify(e.input):JSON.stringify(e.input,null,2);return["[Security Alert]",`Tool: ${e.toolName}`,`Command: ${t.slice(0,300)}`,`Risk: ${e.riskLevel.toUpperCase()} - ${e.analysis}`,"",'Press "Approve" to continue or "Stop" to block.'].join(`
67
- `)}function xn(e,t){let n=m.audit,o=hr(n.whitelistPatterns);return r=>{r.on("tool_call",async(s,l)=>{let{toolName:a,toolCallId:c,input:u}=s,i={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:a,toolCallId:c,input:u,riskLevel:"none",analysis:"",action:"passed"};if(dr.has(a)){i.analysis="Read-only tool",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (read-only)`);return}if(!ur.has(a)){i.analysis="Tool not in analysis scope",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (not analyzed)`);return}if(a==="bash"){let g=u.command??"";if(yr(g,o)){i.analysis="Whitelisted bash command",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (whitelisted)`);return}}if(!t){i.analysis="No audit model configured",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=passed (no audit model)`);return}console.log(`[audit] analyzing tool=${a} id=${c}`);let d=await fr(t.model,t.apiKey,a,u);if(i.riskLevel=d.riskLevel,i.analysis=d.reason,d.riskLevel==="none"||d.riskLevel==="low"){i.action="passed",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} risk=${d.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${a} id=${c} reason=${d.reason}`);try{let g=wr(i);if(await e.requestConfirmation(g,n.confirmTimeoutMs)){i.action="approved",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=approved`);return}return i.action="blocked",await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (user rejected)`),l.abort(),{block:!0,reason:"Operation blocked by user due to security risk."}}catch(g){let f=g instanceof Error?g.message:String(g);return i.action="blocked",i.analysis=`${d.reason} (confirmation failed: ${f})`,await te(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (${f})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${f}`}}})}}var dr,ur,mr,wn,vn=j(()=>{"use strict";W();Y();dr=new Set(["read","ls","find","grep"]),ur=new Set(["bash"]),mr=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
68
-
69
- Command: {{command}}
70
-
71
- Risk levels:
72
- - "none": Safe (read-only, standard dev tools)
73
- - "low": Minor risk (file writes, package installs)
74
- - "critical": High risk (secrets exposure, destructive ops, network attacks, privilege escalation)
75
-
76
- Reply format (ONLY this JSON, nothing else):
77
- {"riskLevel":"none|low|critical","reason":"brief explanation"}`;wn=bn.join(m.sessionDir,"audit-logs")});import{createAgentSession as br,AuthStorage as xr,ModelRegistry as vr,SessionManager as Sr,SettingsManager as Mr,DefaultResourceLoader as $r}from"@mariozechner/pi-coding-agent";import Ue from"node:fs/promises";import Be from"node:path";function Sn(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Ar(e,t){let n=e.trim();if(!n)return{provider:t,modelId:""};if(n.includes("/")){let[o,r]=n.split("/",2);return{provider:o.trim()||t,modelId:r.trim()}}return{provider:t,modelId:n}}function _r(e,t){return e!=="openai-codex"?t:kr[t]??t}function Pr(e,t){let n=e.getAvailable().filter(r=>r.provider===t);return n.length>0?n[0]:e.getAll().filter(r=>r.provider===t)[0]}function Rr(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=Sn(t?.provider||m.modelProvider||"openai-codex"),s=n||o?"":m.modelRef||"",{provider:l,modelId:a}=Ar(s,r),c=t?.provider?r:Sn(l),u=o?t?.modelId?.trim()||"":a;if(!u){let g=Pr(e,c);return g?{model:g,provider:c,modelId:g.id}:{model:void 0,provider:c,modelId:""}}let i=_r(c,u);return{model:e.find(c,i),provider:c,modelId:i}}function Cr(e){let t=q();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function Tr(e){if(e?.role!=="assistant")return"";let n=e.content;if(typeof n=="string")return n.trim();if(!Array.isArray(n))return"";let o=n.filter(s=>typeof s=="object"&&s&&s.type==="text").map(s=>s.text??"").map(s=>s.trim()).filter(Boolean);if(o.length>0)return o.join(`
78
-
79
- `);let r=n.filter(s=>typeof s=="object"&&s&&s.type==="thinking").map(s=>s.thinking??"").map(s=>s.trim()).filter(Boolean);return r.length>0?r.join(`
80
-
81
- `):""}function Er(e){if(e.length===0)return"messages=0";let t=e.slice(-6).map(n=>{let o=n?.role??"unknown",r=n.content,s=n?.stopReason,l=n?.errorMessage;if(typeof r=="string")return`${o}(text:${r.length}${s?`,stop=${s}`:""})`;if(Array.isArray(r)){let c=[`blocks:${r.map(u=>typeof u=="object"&&u&&"type"in u?String(u.type||"unknown"):typeof u).join(",")||"none"}`,s?`stop=${s}`:null,l?"error=1":null].filter(Boolean).join(",");return`${o}(${c})`}if(r==null){let a=["empty",s?`stop=${s}`:null,l?"error=1":null].filter(Boolean).join(",");return`${o}(${a})`}return`${o}(${typeof r}${s?`,stop=${s}`:""})`});return`messages=${e.length} last=[${t.join(" ")}]`}function Dr(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
82
-
83
- Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function Or(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=Tr(e[o]);if(r)return r}return""}function Ir(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function Mn(e){let t=e.workspaceDir||m.workspaceDir;await R(m.sessionDir),await R(m.agentDir),await R(t);let n=ot(e.chatId,e.sessionId),o=Be.join(m.agentDir,"auth.json"),r=new xr(o),s=Cr(r);s&&console.log(`[tg-agent] codex oauth source=${s.source} expiresAt=${new Date(s.expiresAt).toISOString()}`);let l=Be.join(m.agentDir,"models.json"),a=new vr(r,l),{model:c,provider:u,modelId:i}=Rr(a,{provider:e.modelProvider,modelId:e.modelId});i&&!c&&console.warn(`[tg-agent] model not found: ${u}/${i}`);let d=Sr.open(n),g=Mr.create(t,m.agentDir);try{let h=Be.join(m.agentDir,"skills"),v=Be.join(t,".pi","skills"),L=await Ue.access(h).then(()=>!0).catch(()=>!1),C=await Ue.access(v).then(()=>!0).catch(()=>!1);if(L){let X=(await Ue.readdir(h,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] skills directory found at ${h} with ${X.length} skill(s): ${X.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${h}`);if(C){let X=(await Ue.readdir(v,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] workspace skills directory found at ${v} with ${X.length} skill(s): ${X.join(", ")}`)}let B=g.getSettings?.();if(B){let X=B.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${X}`)}}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] skills check failed: ${v}`)}let f="";try{f=await xe(m.agentDir,{timeoutMs:4e3,maxBytes:m.fetchMaxBytes,maxChars:3e3})}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] mcp catalog error: ${v}`)}let y=[];if(m.audit.enabled&&e.auditContext){let h={...e.auditContext,sessionId:e.sessionId},v;if(m.audit.modelProvider&&m.audit.modelId){let L=a.find(m.audit.modelProvider,m.audit.modelId);if(L){let C=await r.getApiKey(m.audit.modelProvider);v={provider:m.audit.modelProvider,model:L,apiKey:C??void 0},console.log(`[tg-agent] audit model: ${m.audit.modelProvider}/${m.audit.modelId} apiKey=${C?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${m.audit.modelProvider}/${m.audit.modelId}`)}y.push(xn(h,v)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let w=e.systemPrompt?.trim(),k=[];w&&k.push(w),f&&k.push(f);let A=k.length>0?k.join(`
84
-
85
- `):void 0;console.log(`[tg-agent] systemPrompt append=${A?A.slice(0,80)+"...":"(none)"}`);let I=new $r({cwd:t,agentDir:m.agentDir,settingsManager:g,extensionFactories:y.length>0?y:void 0,appendSystemPrompt:A});await I.reload();let{session:x,modelFallbackMessage:P}=await br({cwd:t,agentDir:m.agentDir,authStorage:r,modelRegistry:a,model:c??void 0,sessionManager:d,settingsManager:g,resourceLoader:I,customTools:cn({telegram:e.telegram})});try{let h=x.messages,v=h.some(N=>{let X=N.role,K=N.content;return X==="system"&&typeof K=="string"?K.toLowerCase().includes("compaction")||K.toLowerCase().includes("compact"):N.type==="compaction"||N.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof d}`),console.log(`[tg-agent] session messages count: ${h.length}`),console.log(`[tg-agent] compacting support detected: ${v||"unknown (will be detected during runtime)"}`);let C=typeof d.compact=="function",B=typeof d.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${C}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${B}`)}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] compacting check failed: ${v}`)}P&&console.warn(`[tg-agent] modelFallback=${P}`);let ae=!1,S=()=>{ae=!0,x.abort()};e.onAbortReady?.(S);let b=m.logAgentEvents,$=m.logAgentStream,D=new Map,ft=x.subscribe(h=>{switch(h.type){case"agent_start":b&&console.log(`[tg-agent] agent start session=${e.sessionId}`),F=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":b&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":b&&console.log(`[tg-agent] turn start session=${e.sessionId}`),F=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":b&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${h.toolResults.length}`),F=Date.now(),e.onStatus?.({type:"turn_end",toolResults:h.toolResults.length});break;case"message_start":{if(b){let v=h.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${v}`)}F=Date.now();{let v=h.message.role??"unknown";e.onStatus?.({type:"message_start",role:v})}break}case"message_end":{if(b){let v=h.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${v}`)}F=Date.now();{let v=h.message.role??"unknown";e.onStatus?.({type:"message_end",role:v})}break}case"message_update":{if(!$)break;if(h.assistantMessageEvent.type==="text_delta"){let L=(h.assistantMessageEvent.delta??"").length;L>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${L}`),F=Date.now()}h.assistantMessageEvent.type==="thinking_delta"&&(F=Date.now());break}case"tool_execution_start":{D.set(h.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${h.toolName} id=${h.toolCallId}`),Ae+=1,F=Date.now(),e.onStatus?.({type:"tool_start",name:h.toolName,id:h.toolCallId,args:h.args});break}case"tool_execution_end":{let v=D.get(h.toolCallId),L=v?Date.now()-v:0;console.log(`[tg-agent] tool end name=${h.toolName} id=${h.toolCallId} ok=${!h.isError} durationMs=${L}`),D.delete(h.toolCallId),Ae=Math.max(0,Ae-1),F=Date.now(),e.onStatus?.({type:"tool_end",name:h.toolName,id:h.toolCallId,ok:!h.isError,durationMs:L});break}case"auto_compaction_start":{let v=h.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${v}`),F=Date.now();break}case"auto_compaction_end":{let v=h.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${v}`),F=Date.now();break}default:break}}),oe=null,ye=null,ke=!1,yt=0,ht=!1,F=Date.now(),Ae=0;try{let h=Date.now();oe=setInterval(()=>{let C=Date.now()-h;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${C} streaming=${x.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:C,streaming:x.isStreaming})},15e3),ye=setInterval(()=>{if(ke||Ae>0)return;let C=Date.now()-F,B=x.isStreaming?m.modelTimeoutStreamingMs:m.modelTimeoutMs,N=Math.max(1e3,B);C>=N&&(ke=!0,yt=N,ht=x.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${C}`),x.abort())},2e3);try{if(await x.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),ke)throw new Error(`Model request timed out after ${m.modelTimeoutMs}ms`)}catch(C){if(ae)throw new Error("Cancelled by user.");if(ke){let B=ht?" (streaming)":"",N=yt||m.modelTimeoutMs;throw new Error(`Model request timed out after ${N}ms${B}`)}throw C}oe&&clearInterval(oe);let v=Ir(x.messages);if(v){let C=v?.stopReason,B=v?.errorMessage;if(C==="error"){let N=B?Dr(B):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${N}`),new Error(N)}}let L=Or(x.messages,x);if(!L){let C=Er(x.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${C}`),new Error("No assistant response.")}return{text:L,sessionFile:n,sessionId:x.sessionId,modelProvider:x.model?.provider??u,modelId:x.model?.id??i,modelFallbackMessage:P}}finally{oe&&clearInterval(oe),ye&&clearInterval(ye),ft(),d.flushPendingToolResults?.(),x.dispose()}}var kr,$n=j(()=>{"use strict";W();ce();ln();Ne();Y();ct();vn();kr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var Rs={};import fe from"node:path";import kn from"node:fs/promises";import Nr from"node-telegram-bot-api";import{AuthStorage as Lr,ModelRegistry as jr}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Fr}from"@mariozechner/pi-ai";function Ur(e,t){$e.set(e,t)}function mt(e){$e.delete(e)}function Br(e){let t=e.trim();if(t){if(t==="Markdown"||t==="MarkdownV2"||t==="HTML")return t;console.warn(`[tg-agent] invalid TELEGRAM_PARSE_MODE=${t}, ignoring`)}}function Jr(){return fe.join(m.agentDir,"uploads")}function Wr(e){return e.length===0?null:e.reduce((t,n)=>{let o=t.file_size??t.width*t.height;return(n.file_size??n.width*n.height)>o?n:t})}function Hr(e){return!!e?.startsWith("image/")}function qr(e){switch(fe.extname(e).toLowerCase()){case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".webp":return"image/webp";case".gif":return"image/gif";default:return}}function Gr(e){if(!Number.isFinite(e)||e<=0)return"0 B";let t=["B","KB","MB","GB"],n=e,o=0;for(;n>=1024&&o<t.length-1;)n/=1024,o+=1;return`${n.toFixed(n>=10||o===0?0:1)} ${t[o]}`}function Vr(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(Gr(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
86
- `)}function Xr(e){let t=[];if(e.photo&&e.photo.length>0){let n=Wr(e.photo);n&&t.push({kind:"photo",fileId:n.file_id,fileSize:n.file_size})}if(e.document&&t.push({kind:"document",fileId:e.document.file_id,fileName:e.document.file_name,mimeType:e.document.mime_type,fileSize:e.document.file_size}),e.audio){let n=e.audio.mime_type?.split("/")[1]??"mp3",o=e.audio.title??e.audio.performer??"audio";t.push({kind:"document",fileId:e.audio.file_id,fileName:`${o}.${n}`,mimeType:e.audio.mime_type,fileSize:e.audio.file_size})}if(e.voice&&t.push({kind:"document",fileId:e.voice.file_id,fileName:`voice.${e.voice.mime_type?.split("/")[1]??"ogg"}`,mimeType:e.voice.mime_type,fileSize:e.voice.file_size}),e.video){let n=e.video.mime_type?.split("/")[1]??"mp4";t.push({kind:"document",fileId:e.video.file_id,fileName:`video.${n}`,mimeType:e.video.mime_type,fileSize:e.video.file_size})}return e.video_note&&t.push({kind:"document",fileId:e.video_note.file_id,fileName:"video_note.mp4",mimeType:"video/mp4",fileSize:e.video_note.file_size}),t}async function Yr(e){if(e.length===0)return{resolved:[],images:[]};let t=Jr();await R(t);let n=[],o=[];for(let r of e)try{let s=await E.downloadFile(r.fileId,t),l=await kn.stat(s),a=r.fileName??fe.basename(s),c=r.mimeType??qr(s),u=r.kind==="photo"||Hr(c),i={path:s,name:a,mimeType:c,bytes:l.size,isImage:u};if(n.push(i),u){let d=await kn.readFile(s);o.push({type:"image",data:d.toString("base64"),mimeType:c??Kr})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function ve(e,t){let n=0;for(let o=0;o<e.length;o+=1){let r=e[o];if(r==="\\"){o+=1;continue}r===t&&(n+=1)}return n}function Zr(e){if(ve(e,"*")%2!==0||ve(e,"_")%2!==0||ve(e,"`")%2!==0)return!1;let r=ve(e,"["),s=ve(e,"]");return r===s}function es(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Qr.has(n))return!1}return!0}function Dn(e){let t=Br(m.telegramParseMode);return t?[t]:es(e)?["MarkdownV2","Markdown"]:Zr(e)?["Markdown"]:[]}function Me(e,t){let n=Se.get(e);return n?(clearTimeout(n.timeoutId),Se.delete(e),n.messageId&&E.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function An(e,t,n,o,r){if(Se.has(e))throw new Error("Audit confirmation already pending.");let s=Kn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await Jn(t,n,s,r);return await new Promise((a,c)=>{let u=setTimeout(()=>{Se.delete(e),E.editMessageText(`${n}
87
-
88
- [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),c(new Error("Audit confirmation timed out."))},o);Se.set(e,{resolve:a,reject:c,timeoutId:u,chatId:t,messageThreadId:r,messageId:l.message_id})})}function pe(e){let t=e.trim().toLowerCase();return ns.get(t)??t}function rs(e,t){return e!=="openai-codex"?t:os[t]??t}async function ge(){await R(m.agentDir);let e=fe.join(m.agentDir,"auth.json"),t=new Lr(e),n=q();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=fe.join(m.agentDir,"models.json"),r=new jr(t,o);return{authStorage:t,modelRegistry:r}}function On(e){let t=ne.get(e);t&&(clearTimeout(t.timeoutId),ne.delete(e))}function ss(e,t){let n=ne.get(e);n&&(clearTimeout(n.timeoutId),ne.delete(e),n.reject(new Error(t)))}async function _n(e,t,n,o){if(ne.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await p(t,r,o),await new Promise((s,l)=>{let a=setTimeout(()=>{ne.delete(e),l(new Error("Login prompt timed out."))},ts);ne.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function In(e,t,n){let o=$e.get(t);if(!o){await p(e,"No active request to stop.",n);return}o.cancelRequested=!0,o.abortRequested=!0,o.status&&o.status.update("Cancelled by user.",!0),o.abort&&o.abort(),(!o.status||o.chatId!==e)&&await p(e,"Stopping current request...",n)}async function Nn(e,t,n,o){let r=await Fe(t),s=n||r.activeSessionId;if(!s){await p(e,"No active session to close.",o);return}let l=r.sessions[s];if(l&&l.messages.length>0)try{await p(e,"Reflecting on session memory...",o);let i=await Ce(l,l.modelProvider,l.modelId);i.reflected?await p(e,"Memory archived successfully.",o):i.error?await p(e,`Memory saved (reflection failed: ${i.error})`,o):await p(e,"Memory saved (no reflection).",o)}catch(i){console.warn("[tg-agent] memory archival failed",i),await p(e,`Memory archival failed: ${ie(i)}`,o)}let a=$e.get(t);if(a){if(a.cancelRequested=!0,a.abortRequested=!0,a.status&&a.status.update("Cancelled by user.",!0),a.abort)try{a.abort()}catch(i){console.warn("[tg-agent] abort callback failed during force close",i)}mt(t)}if(!it(r,s)){await p(e,`Session not found: ${s}`,o);return}await O(r),await me(t,s).catch(i=>{console.warn(`[tg-agent] delete session file failed id=${s}`,i)});let u=a?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await p(e,u,o)}function is(){console.log(`[tg-agent] modelProvider=${m.modelProvider} modelRef=${m.modelRef} sessionDir=${m.sessionDir} maxConcurrent=${m.maxConcurrent}`),console.log(`[tg-agent] agentDir=${m.agentDir} workspaceDir=${m.workspaceDir}`);let e=Oe(m.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${m.fetchMaxBytes} fetchTimeoutMs=${m.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${m.proxyUrl||"(none)"} fetchProxy=${m.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${m.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${m.tlsRejectUnauthorized===null?"(unset)":String(m.tlsRejectUnauthorized)}`);try{let{source:o}=Ut(m.modelProvider);console.log(`[tg-agent] authSource=${o}`)}catch(o){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] authSource=missing (${r})`)}let n=Kt();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function gt(e){if(!e.startsWith("/"))return null;let t=e.trim(),[n,...o]=t.split(" ");return{command:n.split("@")[0].slice(1).toLowerCase(),args:o.join(" ").trim()}}async function Pn(e,t,n){let o=se(e);return o||(o=ze(e,""),await O(e),await p(t,`Created session ${o.id}.`,n)),o}function cs(e,t){let n=e.getAll(),o=new Map;for(let r of n){let s=o.get(r.provider)??{count:0,auth:t.hasAuth(r.provider)};s.count+=1,o.set(r.provider,s)}return Array.from(o.entries()).filter(([r])=>as.has(r)).sort((r,s)=>r[0].localeCompare(s[0])).map(([r,s])=>({label:`${r} (${s.count}, ${s.auth?"ok":"no auth"})`,command:`/provider ${r}`}))}function ls(e,t,n=[]){let o=e.getAll().filter(a=>a.provider===t).sort((a,c)=>a.id.localeCompare(c.id));if(n.length===0)return o.map(a=>({label:a.id,command:`/model ${t}/${a.id}`}));let r=new Map(o.map(a=>[a.id,a])),s=new Set,l=[];for(let a of n){let c=r.get(a);!c||s.has(c.id)||(s.add(c.id),l.push(c))}for(let a of o)s.has(a.id)||l.push(a);return l.map(a=>({label:a.id,command:`/model ${t}/${a.id}`}))}function ds(e,t,n=3){let o=new Set,r=[],s=rt(e);for(let l of s){if(l.modelProvider!==t)continue;let a=l.modelId;if(!(!a||o.has(a))&&(o.add(a),r.push(a),r.length>=n))break}return r}function us(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:pe(n),modelId:o.trim()}}return{modelId:t}}function Ln(e,t){let n=Date.now(),o=Rn.get(e)??0;n-o<ms||(Rn.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function jn(e){let t=m.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function gs(e){return e.length===0?"No sessions found.":["Sessions:",...e.map(n=>{let o=new Date(n.updatedAt).toISOString();return`- ${n.id} | ${n.title} | updated ${o}`})].join(`
89
- `)}function Je(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function ut(e,t){if(t.workspaceDir)return t.workspaceDir;let n=m.workspaceMappings.get(e);return n||m.workspaceDir}async function Fn(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await E.sendMessage(e,t,r)}async function zn(e,t,n,o,r){let s={chat_id:e,message_id:t};o&&(s.parse_mode=o),r!==void 0&&(s.message_thread_id=r),await E.editMessageText(n,s)}async function Un(e,t){let n;for(let o of t)try{return await e(o)}catch(r){n=r;let s=r instanceof Error?r.message:String(r);console.warn(`[tg-agent] parse_mode ${o} failed, trying fallback: ${s}`)}try{return await e(void 0)}catch(o){if(n){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] parse_mode fallback to plain failed: ${r}`)}throw o}}async function ps(e,t,n){return await Un(o=>Fn(e,t,o,n),Dn(t))}async function fs(e,t,n,o){await Un(r=>zn(e,t,n,r,o),Dn(n))}async function p(e,t,n){let o=xt(t,3900);for(let r of o)await ps(e,r,n)}function hs(){let e=z()-Bn;for(let[o,r]of V)r.createdAt<e&&V.delete(o);if(V.size<=Cn)return;let t=Array.from(V.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=V.size-Cn;for(let o=0;o<n;o+=1)V.delete(t[o][0])}function ws(e){hs();let t=he();for(;V.has(t);)t=he();return V.set(t,{command:e,createdAt:z()}),t}function bs(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=V.get(t);return n?z()-n.createdAt>Bn?(V.delete(t),null):n.command:null}function xs(e,t){if(e.length<=t)return[e];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}function Kn(e,t){let n=[],o=[];for(let r of e){let s=ws(r.command);o.push({text:r.label,callback_data:`cmd:${s}`}),o.length>=t&&(n.push(o),o=[])}return o.length>0&&n.push(o),n}async function Jn(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await E.sendMessage(e,t,r)}async function Tn(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??ys,l=o?.footer,a=o?.messageThreadId,c=xs(n,s);for(let u=0;u<c.length;u+=1){let i=c[u],d=c.length>1?` (page ${u+1}/${c.length})`:"",g=[`${t}${d}`];l&&g.push(l);let f=Kn(i,r);await Jn(e,g.join(`
90
- `),f,a)}}function dt(e,t=vs){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
91
-
92
- [truncated]`,truncated:!0}}async function Ms(e,t){let n="Working...",r=(await Fn(e,n,void 0,t)).message_id,s=n,l=0,a=Promise.resolve(),c=(i,d=!1)=>{let g=Date.now();!d&&g-l<Ss||i!==s&&(s=i,l=g,a=a.then(async()=>{await zn(e,r,i,void 0,t)}).catch(f=>{console.warn("[tg-agent] status edit failed",f)}))},u=i=>{s=i,l=Date.now(),a=a.then(async()=>{await fs(e,r,i,t)}).catch(d=>{console.warn("[tg-agent] status edit failed",d)})};return{update:(i,d=!1)=>{let g=dt(i).text;c(g,d)},finalize:async i=>{let d=dt(i).text;u(d),await a},fail:async i=>{let d=dt(i).text;u(d),await a}}}function $s(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
93
- args: ${ks(e.args)}`;case"tool_end":return e.ok?`Tool finished: ${e.name} (${e.durationMs}ms)`:`Tool failed: ${e.name} (${e.durationMs}ms)`;case"message_start":return e.role==="assistant"?"Generating reply...":null;case"message_end":return e.role==="assistant"?"Finalizing reply...":null;case"heartbeat":return`Working... ${Math.max(1,Math.round(e.elapsedMs/1e3))}s`;default:return null}}function ks(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,l=(u,i)=>{if(u==null)return u;if(typeof u=="string")return u.length>n?`${u.slice(0,n)}...`:u;if(typeof u=="number"||typeof u=="boolean")return u;if(typeof u=="bigint")return u.toString();if(typeof u=="function")return"[function]";if(typeof u!="object")return String(u);if(t.has(u))return"[circular]";if(i>=s)return"[truncated]";if(t.add(u),Array.isArray(u)){let f=u.slice(0,r).map(y=>l(y,i+1));return u.length>r&&f.push("[truncated]"),f}let d=Object.entries(u),g={};for(let[f,y]of d.slice(0,o))g[f]=l(y,i+1);return d.length>o&&(g._truncated=!0),g},a=l(e,0),c=JSON.stringify(a);return c?c.length>700?`${c.slice(0,700)}...`:c:"null"}catch{return"[unavailable]"}}function ie(e){let t=e instanceof Error?e.message:String(e),n=e?.cause;return n instanceof Error?`${t} (${n.message})`:n?`${t} (${String(n)})`:t}function As(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function _s(){let e=await be(m.agentDir);if(e.length===0)return"No MCP servers configured. Add [mcp_servers.*] to ~/.tg-agent/config.toml.";let t=await Promise.all(e.map(o=>en(o))),n=["MCP servers:"];for(let o=0;o<e.length;o+=1){let r=e[o],s=t[o],l=s.ok?"ok":`error: ${As(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${re(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
94
- `)}async function pt(e,t,n,o,r){let s=r,a=Je(e,s,s!==void 0);if(!a)return;let c=await Fe(a),u=st(c);switch(u.length>0&&(await O(c),await Promise.all(u.map(i=>me(a,i).catch(d=>{console.warn(`[tg-agent] cleanup session file failed id=${i}`,d)})))),n){case"start":case"help":{let i=["Commands:","/new [title] - create a new session","/list - list sessions","/use <id> - switch active session","/close [id] - close a session (default: active)","/reset - clear active session history","/workspace [path] - view or set workspace directory","/providers - list available providers","/models [provider] - list models for provider","/provider <name> - set provider for current session","/model <provider>/<model> - set model for current session","/mcp - list configured MCP servers","/mcp refresh - reload MCP catalog","/status - show session and workspace settings","/login <provider> - login to OAuth provider","/logout <provider> - logout from provider","/stop - stop the current running request","/approve - approve a pending security audit confirmation","/memory - show memory RAG status","/reindex - rebuild vector index for all memories","","Tips:","Send images or files to attach them to the prompt."].join(`
95
- `);await p(e,i,r);return}case"new":{try{let i=o||"",d=se(c),g=d?.modelProvider,f=d?.modelId,y=ze(c,i);g&&(y.modelProvider=g,f&&(y.modelId=f)),await O(c),await p(e,`Created session ${y.id} (${y.title}).`,r)}catch(i){await p(e,i.message,r)}return}case"list":{await O(c),await p(e,gs(rt(c)),r);return}case"use":{if(!o){await p(e,"Usage: /use <id>",r);return}if(!fn(c,o)){await p(e,`Session not found: ${o}`,r);return}await O(c),await p(e,`Active session set to ${o}.`,r);return}case"close":{let i=o||c.activeSessionId;if(!i){await p(e,"No active session to close.",r);return}let d=c.sessions[i];if(d&&d.messages.length>0)try{await p(e,"Reflecting on session memory...",r);let w=await Ce(d,d.modelProvider,d.modelId);w.reflected?await p(e,"Memory archived successfully.",r):w.error?await p(e,`Memory saved (reflection failed: ${w.error})`,r):await p(e,"Memory saved (no reflection).",r)}catch(w){console.warn("[tg-agent] memory archival failed",w),await p(e,`Memory archival failed: ${ie(w)}`,r)}let g=$e.get(a);if(g){if(g.cancelRequested=!0,g.abortRequested=!0,g.status&&g.status.update("Cancelled by user.",!0),g.abort)try{g.abort()}catch(w){console.warn("[tg-agent] abort callback failed during force close",w)}mt(a)}if(!it(c,i)){await p(e,`Session not found: ${i}`,r);return}await O(c),await me(a,i).catch(w=>{console.warn(`[tg-agent] delete session file failed id=${i}`,w)});let y=g?`Force-closed session ${i} (interrupted running task).`:`Closed session ${i}.`;await p(e,y,r);return}case"reset":{let i=se(c);if(!i){await p(e,"No active session.",r);return}if(i.messages.length>0)try{await p(e,"Reflecting on session memory...",r);let d=await Ce(i,i.modelProvider,i.modelId);d.reflected?await p(e,"Memory archived successfully.",r):d.error?await p(e,`Memory saved (reflection failed: ${d.error})`,r):await p(e,"Memory saved (no reflection).",r)}catch(d){console.warn("[tg-agent] memory archival failed",d),await p(e,`Memory archival failed: ${ie(d)}`,r)}yn(i),await O(c),await me(a,i.id).catch(d=>{console.warn(`[tg-agent] reset session file failed id=${i.id}`,d)}),await p(e,`Reset session ${i.id}.`,r);return}case"workspace":{if(!o){let d=ut(a,c),g=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default";await p(e,`Workspace: ${d} (source: ${g})`,r);return}let i=fe.resolve(J(o.trim()));hn(c,i),await O(c),await p(e,`Workspace set to: ${i}`,r);return}case"providers":{let{authStorage:i,modelRegistry:d}=await ge(),g=d.getError(),f=cs(d,i);if(f.length===0){let w=g?`Warning: ${g}
96
-
97
- No providers found.`:"No providers found.";await p(e,w,r);return}let y=[];g&&y.push(`Warning: ${g}`),y.push("Providers:"),await Tn(e,y.join(`
98
- `),f,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:i,modelRegistry:d}=await ge(),g=o?pe(o):"";if(!g){let k=se(c);if(!k?.modelProvider){await p(e,"Usage: /models <provider>",r);return}g=k.modelProvider}let f=i.hasAuth(g),y=ds(c,g),w=ls(d,g,y);if(w.length===0){await p(e,`No models found for provider ${g}.`,r);return}await Tn(e,`Models for ${g} (auth: ${f?"ok":"missing"}):`,w,{perRow:1,footer:"Tap a model to set it.",messageThreadId:r});return}case"provider":{if(!o){await p(e,"Usage: /provider <name>",r);return}let i=pe(o),{modelRegistry:d}=await ge();if(!d.getAll().some(y=>y.provider===i)){await p(e,`Unknown provider: ${i}`,r);return}let f=await Pn(c,e,r);f.modelProvider=i,f.modelId=void 0,f.updatedAt=z(),await O(c),await p(e,`Session ${f.id} provider set to ${i}.`,r),await pt(e,t,"models",i,r);return}case"model":{let i=us(o);if(!i){await p(e,"Usage: /model <provider>/<model>",r);return}let d=await Pn(c,e,r),g=pe(i.provider??d.modelProvider??"");if(!g){await p(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:f}=await ge(),y=rs(g,i.modelId);if(!f.find(g,y)){await p(e,`Model not found: ${g}/${y}`,r);return}d.modelProvider=g,d.modelId=y,d.updatedAt=z(),await O(c),await p(e,`Session ${d.id} model set to ${g}/${y}.`,r);return}case"status":{let i=se(c);if(!i){await p(e,"No active session.",r);return}let d=m.modelRef.includes("/")?m.modelRef:`${m.modelProvider}/${m.modelRef}`,g=i.modelProvider||i.modelId?`Model: ${i.modelProvider??"?"}/${i.modelId??"?"}`:`Model: ${d} (default)`,f=ut(a,c),y=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default",w=[`Session: ${i.id} (${i.title})`,g,`Workspace: ${f} (${y})`].join(`
99
- `);await p(e,w,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Zt(),await xe(m.agentDir,{timeoutMs:5e3,maxBytes:m.fetchMaxBytes,maxChars:3e3}),nt(),await p(e,"MCP catalog refreshed.",r);return}let i=await _s();await p(e,i,r);return}case"login":{let i=Fr();if(!o){let f=i.map(y=>`- ${y.id} (${y.name})`);await p(e,["OAuth providers:",...f].join(`
100
- `),r);return}let d=pe(o);if(lt.has(t)){await p(e,"Login already in progress.",r);return}let g=i.find(f=>f.id===d);if(!g){await p(e,`Unknown OAuth provider: ${d}`,r);return}lt.add(t);try{let{authStorage:f}=await ge();await p(e,`Starting login for ${g.id}...`,r),await f.login(g.id,{onAuth:({url:y,instructions:w})=>{let k=["Open this URL in your browser:",y];w&&k.push("",w),p(e,k.join(`
101
- `),r)},onPrompt:y=>_n(t,e,y,r),onProgress:y=>{p(e,y,r)},onManualCodeInput:()=>_n(t,e,{message:"Paste the authorization code:"},r)}),await p(e,`Login completed for ${g.id}.`,r)}catch(f){let y=ie(f);await p(e,`Login failed: ${y}`,r)}finally{lt.delete(t),On(t)}return}case"logout":{if(!o){await p(e,"Usage: /logout <provider>",r);return}let i=pe(o),{authStorage:d}=await ge();d.logout(i),await p(e,`Logged out from ${i}.`,r);return}case"memory":{let i=m.memory.rag,d=await At(),g=["Memory System Status:","",`RAG Enabled: ${i.enabled?"Yes":"No"}`,`Embedding Model: ${i.embeddingModel}`,`Embedding Base URL: ${i.embeddingBaseUrl||"(default)"}`,`Similarity Threshold: ${i.similarityThreshold}`,`Max Results: ${i.maxResults}`,"","Database:",` Sessions: ${d.sessionsCount}`,` Memories: ${d.memoriesCount}`,"","Tip: Use /reindex to rebuild memory vectors after changing embedding model."];await p(e,g.join(`
85
+ - Prioritize what matters for Shawn's growth and wellbeing`;Tr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var Rs={};import fe from"node:path";import $n from"node:fs/promises";import Nr from"node-telegram-bot-api";import{AuthStorage as Lr,ModelRegistry as jr}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Fr}from"@mariozechner/pi-ai";function Ur(e,t){$e.set(e,t)}function dt(e){$e.delete(e)}function Br(e){let t=e.trim();if(t){if(t==="Markdown"||t==="MarkdownV2"||t==="HTML")return t;console.warn(`[tg-agent] invalid TELEGRAM_PARSE_MODE=${t}, ignoring`)}}function Jr(){return fe.join(m.agentDir,"uploads")}function Wr(e){return e.length===0?null:e.reduce((t,n)=>{let o=t.file_size??t.width*t.height;return(n.file_size??n.width*n.height)>o?n:t})}function Hr(e){return!!e?.startsWith("image/")}function qr(e){switch(fe.extname(e).toLowerCase()){case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".webp":return"image/webp";case".gif":return"image/gif";default:return}}function Gr(e){if(!Number.isFinite(e)||e<=0)return"0 B";let t=["B","KB","MB","GB"],n=e,o=0;for(;n>=1024&&o<t.length-1;)n/=1024,o+=1;return`${n.toFixed(n>=10||o===0?0:1)} ${t[o]}`}function Vr(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(Gr(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
86
+ `)}function Xr(e){let t=[];if(e.photo&&e.photo.length>0){let n=Wr(e.photo);n&&t.push({kind:"photo",fileId:n.file_id,fileSize:n.file_size})}if(e.document&&t.push({kind:"document",fileId:e.document.file_id,fileName:e.document.file_name,mimeType:e.document.mime_type,fileSize:e.document.file_size}),e.audio){let n=e.audio.mime_type?.split("/")[1]??"mp3",o=e.audio.title??e.audio.performer??"audio";t.push({kind:"document",fileId:e.audio.file_id,fileName:`${o}.${n}`,mimeType:e.audio.mime_type,fileSize:e.audio.file_size})}if(e.voice&&t.push({kind:"document",fileId:e.voice.file_id,fileName:`voice.${e.voice.mime_type?.split("/")[1]??"ogg"}`,mimeType:e.voice.mime_type,fileSize:e.voice.file_size}),e.video){let n=e.video.mime_type?.split("/")[1]??"mp4";t.push({kind:"document",fileId:e.video.file_id,fileName:`video.${n}`,mimeType:e.video.mime_type,fileSize:e.video.file_size})}return e.video_note&&t.push({kind:"document",fileId:e.video_note.file_id,fileName:"video_note.mp4",mimeType:"video/mp4",fileSize:e.video_note.file_size}),t}async function Yr(e){if(e.length===0)return{resolved:[],images:[]};let t=Jr();await R(t);let n=[],o=[];for(let r of e)try{let s=await E.downloadFile(r.fileId,t),l=await $n.stat(s),a=r.fileName??fe.basename(s),c=r.mimeType??qr(s),u=r.kind==="photo"||Hr(c),i={path:s,name:a,mimeType:c,bytes:l.size,isImage:u};if(n.push(i),u){let d=await $n.readFile(s);o.push({type:"image",data:d.toString("base64"),mimeType:c??Kr})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function ve(e,t){let n=0;for(let o=0;o<e.length;o+=1){let r=e[o];if(r==="\\"){o+=1;continue}r===t&&(n+=1)}return n}function Zr(e){if(ve(e,"*")%2!==0||ve(e,"_")%2!==0||ve(e,"`")%2!==0)return!1;let r=ve(e,"["),s=ve(e,"]");return r===s}function es(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Qr.has(n))return!1}return!0}function En(e){let t=Br(m.telegramParseMode);return t?[t]:es(e)?["MarkdownV2","Markdown"]:Zr(e)?["Markdown"]:[]}function Me(e,t){let n=Se.get(e);return n?(clearTimeout(n.timeoutId),Se.delete(e),n.messageId&&E.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function kn(e,t,n,o,r){if(Se.has(e))throw new Error("Audit confirmation already pending.");let s=Bn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await Kn(t,n,s,r);return await new Promise((a,c)=>{let u=setTimeout(()=>{Se.delete(e),E.editMessageText(`${n}
87
+
88
+ [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),c(new Error("Audit confirmation timed out."))},o);Se.set(e,{resolve:a,reject:c,timeoutId:u,chatId:t,messageThreadId:r,messageId:l.message_id})})}function pe(e){let t=e.trim().toLowerCase();return ns.get(t)??t}function rs(e,t){return e!=="openai-codex"?t:os[t]??t}async function ge(){await R(m.agentDir);let e=fe.join(m.agentDir,"auth.json"),t=new Lr(e),n=q();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=fe.join(m.agentDir,"models.json"),r=new jr(t,o);return{authStorage:t,modelRegistry:r}}function Dn(e){let t=ne.get(e);t&&(clearTimeout(t.timeoutId),ne.delete(e))}function ss(e,t){let n=ne.get(e);n&&(clearTimeout(n.timeoutId),ne.delete(e),n.reject(new Error(t)))}async function An(e,t,n,o){if(ne.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await p(t,r,o),await new Promise((s,l)=>{let a=setTimeout(()=>{ne.delete(e),l(new Error("Login prompt timed out."))},ts);ne.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function On(e,t,n){let o=$e.get(t);if(!o){await p(e,"No active request to stop.",n);return}o.cancelRequested=!0,o.abortRequested=!0,o.status&&o.status.update("Cancelled by user.",!0),o.abort&&o.abort(),(!o.status||o.chatId!==e)&&await p(e,"Stopping current request...",n)}async function In(e,t,n,o){let r=await Ne(t),s=n||r.activeSessionId;if(!s){await p(e,"No active session to close.",o);return}let l=r.sessions[s];if(l&&l.messages.length>0)try{await p(e,"Reflecting on session memory...",o);let i=await Be(l,l.modelProvider,l.modelId);i.reflected?await p(e,"Memory archived successfully.",o):i.error?await p(e,`Memory saved (reflection failed: ${i.error})`,o):await p(e,"Memory saved (no reflection).",o)}catch(i){console.warn("[tg-agent] memory archival failed",i),await p(e,`Memory archival failed: ${ie(i)}`,o)}let a=$e.get(t);if(a){if(a.cancelRequested=!0,a.abortRequested=!0,a.status&&a.status.update("Cancelled by user.",!0),a.abort)try{a.abort()}catch(i){console.warn("[tg-agent] abort callback failed during force close",i)}dt(t)}if(!et(r,s)){await p(e,`Session not found: ${s}`,o);return}await O(r),await ue(t,s).catch(i=>{console.warn(`[tg-agent] delete session file failed id=${s}`,i)});let u=a?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await p(e,u,o)}function is(){console.log(`[tg-agent] modelProvider=${m.modelProvider} modelRef=${m.modelRef} sessionDir=${m.sessionDir} maxConcurrent=${m.maxConcurrent}`),console.log(`[tg-agent] agentDir=${m.agentDir} workspaceDir=${m.workspaceDir}`);let e=Te(m.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${m.fetchMaxBytes} fetchTimeoutMs=${m.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${m.proxyUrl||"(none)"} fetchProxy=${m.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${m.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${m.tlsRejectUnauthorized===null?"(unset)":String(m.tlsRejectUnauthorized)}`);try{let{source:o}=Ot(m.modelProvider);console.log(`[tg-agent] authSource=${o}`)}catch(o){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] authSource=missing (${r})`)}let n=Nt();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function ut(e){if(!e.startsWith("/"))return null;let t=e.trim(),[n,...o]=t.split(" ");return{command:n.split("@")[0].slice(1).toLowerCase(),args:o.join(" ").trim()}}async function _n(e,t,n){let o=se(e);return o||(o=Le(e,""),await O(e),await p(t,`Created session ${o.id}.`,n)),o}function cs(e,t){let n=e.getAll(),o=new Map;for(let r of n){let s=o.get(r.provider)??{count:0,auth:t.hasAuth(r.provider)};s.count+=1,o.set(r.provider,s)}return Array.from(o.entries()).filter(([r])=>as.has(r)).sort((r,s)=>r[0].localeCompare(s[0])).map(([r,s])=>({label:`${r} (${s.count}, ${s.auth?"ok":"no auth"})`,command:`/provider ${r}`}))}function ls(e,t,n=[]){let o=e.getAll().filter(a=>a.provider===t).sort((a,c)=>a.id.localeCompare(c.id));if(n.length===0)return o.map(a=>({label:a.id,command:`/model ${t}/${a.id}`}));let r=new Map(o.map(a=>[a.id,a])),s=new Set,l=[];for(let a of n){let c=r.get(a);!c||s.has(c.id)||(s.add(c.id),l.push(c))}for(let a of o)s.has(a.id)||l.push(a);return l.map(a=>({label:a.id,command:`/model ${t}/${a.id}`}))}function ds(e,t,n=3){let o=new Set,r=[],s=Qe(e);for(let l of s){if(l.modelProvider!==t)continue;let a=l.modelId;if(!(!a||o.has(a))&&(o.add(a),r.push(a),r.length>=n))break}return r}function us(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:pe(n),modelId:o.trim()}}return{modelId:t}}function Nn(e,t){let n=Date.now(),o=Pn.get(e)??0;n-o<ms||(Pn.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function Ln(e){let t=m.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function gs(e){return e.length===0?"No sessions found.":["Sessions:",...e.map(n=>{let o=new Date(n.updatedAt).toISOString();return`- ${n.id} | ${n.title} | updated ${o}`})].join(`
89
+ `)}function Je(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function lt(e,t){if(t.workspaceDir)return t.workspaceDir;let n=m.workspaceMappings.get(e);return n||m.workspaceDir}async function jn(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await E.sendMessage(e,t,r)}async function Fn(e,t,n,o,r){let s={chat_id:e,message_id:t};o&&(s.parse_mode=o),r!==void 0&&(s.message_thread_id=r),await E.editMessageText(n,s)}async function zn(e,t){let n;for(let o of t)try{return await e(o)}catch(r){n=r;let s=r instanceof Error?r.message:String(r);console.warn(`[tg-agent] parse_mode ${o} failed, trying fallback: ${s}`)}try{return await e(void 0)}catch(o){if(n){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] parse_mode fallback to plain failed: ${r}`)}throw o}}async function ps(e,t,n){return await zn(o=>jn(e,t,o,n),En(t))}async function fs(e,t,n,o){await zn(r=>Fn(e,t,n,r,o),En(n))}async function p(e,t,n){let o=wt(t,3900);for(let r of o)await ps(e,r,n)}function hs(){let e=z()-Un;for(let[o,r]of V)r.createdAt<e&&V.delete(o);if(V.size<=Rn)return;let t=Array.from(V.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=V.size-Rn;for(let o=0;o<n;o+=1)V.delete(t[o][0])}function ws(e){hs();let t=he();for(;V.has(t);)t=he();return V.set(t,{command:e,createdAt:z()}),t}function bs(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=V.get(t);return n?z()-n.createdAt>Un?(V.delete(t),null):n.command:null}function xs(e,t){if(e.length<=t)return[e];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}function Bn(e,t){let n=[],o=[];for(let r of e){let s=ws(r.command);o.push({text:r.label,callback_data:`cmd:${s}`}),o.length>=t&&(n.push(o),o=[])}return o.length>0&&n.push(o),n}async function Kn(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await E.sendMessage(e,t,r)}async function Cn(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??ys,l=o?.footer,a=o?.messageThreadId,c=xs(n,s);for(let u=0;u<c.length;u+=1){let i=c[u],d=c.length>1?` (page ${u+1}/${c.length})`:"",g=[`${t}${d}`];l&&g.push(l);let f=Bn(i,r);await Kn(e,g.join(`
90
+ `),f,a)}}function ct(e,t=vs){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
91
+
92
+ [truncated]`,truncated:!0}}async function Ms(e,t){let n="Working...",r=(await jn(e,n,void 0,t)).message_id,s=n,l=0,a=Promise.resolve(),c=(i,d=!1)=>{let g=Date.now();!d&&g-l<Ss||i!==s&&(s=i,l=g,a=a.then(async()=>{await Fn(e,r,i,void 0,t)}).catch(f=>{console.warn("[tg-agent] status edit failed",f)}))},u=i=>{s=i,l=Date.now(),a=a.then(async()=>{await fs(e,r,i,t)}).catch(d=>{console.warn("[tg-agent] status edit failed",d)})};return{update:(i,d=!1)=>{let g=ct(i).text;c(g,d)},finalize:async i=>{let d=ct(i).text;u(d),await a},fail:async i=>{let d=ct(i).text;u(d),await a}}}function $s(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
93
+ args: ${ks(e.args)}`;case"tool_end":return e.ok?`Tool finished: ${e.name} (${e.durationMs}ms)`:`Tool failed: ${e.name} (${e.durationMs}ms)`;case"message_start":return e.role==="assistant"?"Generating reply...":null;case"message_end":return e.role==="assistant"?"Finalizing reply...":null;case"heartbeat":return`Working... ${Math.max(1,Math.round(e.elapsedMs/1e3))}s`;default:return null}}function ks(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,l=(u,i)=>{if(u==null)return u;if(typeof u=="string")return u.length>n?`${u.slice(0,n)}...`:u;if(typeof u=="number"||typeof u=="boolean")return u;if(typeof u=="bigint")return u.toString();if(typeof u=="function")return"[function]";if(typeof u!="object")return String(u);if(t.has(u))return"[circular]";if(i>=s)return"[truncated]";if(t.add(u),Array.isArray(u)){let f=u.slice(0,r).map(y=>l(y,i+1));return u.length>r&&f.push("[truncated]"),f}let d=Object.entries(u),g={};for(let[f,y]of d.slice(0,o))g[f]=l(y,i+1);return d.length>o&&(g._truncated=!0),g},a=l(e,0),c=JSON.stringify(a);return c?c.length>700?`${c.slice(0,700)}...`:c:"null"}catch{return"[unavailable]"}}function ie(e){let t=e instanceof Error?e.message:String(e),n=e?.cause;return n instanceof Error?`${t} (${n.message})`:n?`${t} (${String(n)})`:t}function As(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function _s(){let e=await be(m.agentDir);if(e.length===0)return"No MCP servers configured. Add [mcp_servers.*] to ~/.tg-agent/config.toml.";let t=await Promise.all(e.map(o=>qt(o))),n=["MCP servers:"];for(let o=0;o<e.length;o+=1){let r=e[o],s=t[o],l=s.ok?"ok":`error: ${As(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${re(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
94
+ `)}async function mt(e,t,n,o,r){let s=r,a=Je(e,s,s!==void 0);if(!a)return;let c=await Ne(a),u=Ze(c);switch(u.length>0&&(await O(c),await Promise.all(u.map(i=>ue(a,i).catch(d=>{console.warn(`[tg-agent] cleanup session file failed id=${i}`,d)})))),n){case"start":case"help":{let i=["Commands:","/new [title] - create a new session","/list - list sessions","/use <id> - switch active session","/close [id] - close a session (default: active)","/reset - clear active session history","/workspace [path] - view or set workspace directory","/providers - list available providers","/models [provider] - list models for provider","/provider <name> - set provider for current session","/model <provider>/<model> - set model for current session","/mcp - list configured MCP servers","/mcp refresh - reload MCP catalog","/status - show session and workspace settings","/login <provider> - login to OAuth provider","/logout <provider> - logout from provider","/stop - stop the current running request","/approve - approve a pending security audit confirmation","/memory - show memory RAG status","/reindex - rebuild vector index for all memories","","Tips:","Send images or files to attach them to the prompt."].join(`
95
+ `);await p(e,i,r);return}case"new":{try{let i=o||"",d=se(c),g=d?.modelProvider,f=d?.modelId,y=Le(c,i);g&&(y.modelProvider=g,f&&(y.modelId=f)),await O(c),await p(e,`Created session ${y.id} (${y.title}).`,r)}catch(i){await p(e,i.message,r)}return}case"list":{await O(c),await p(e,gs(Qe(c)),r);return}case"use":{if(!o){await p(e,"Usage: /use <id>",r);return}if(!cn(c,o)){await p(e,`Session not found: ${o}`,r);return}await O(c),await p(e,`Active session set to ${o}.`,r);return}case"close":{let i=o||c.activeSessionId;if(!i){await p(e,"No active session to close.",r);return}let d=c.sessions[i];if(d&&d.messages.length>0)try{await p(e,"Reflecting on session memory...",r);let w=await Be(d,d.modelProvider,d.modelId);w.reflected?await p(e,"Memory archived successfully.",r):w.error?await p(e,`Memory saved (reflection failed: ${w.error})`,r):await p(e,"Memory saved (no reflection).",r)}catch(w){console.warn("[tg-agent] memory archival failed",w),await p(e,`Memory archival failed: ${ie(w)}`,r)}let g=$e.get(a);if(g){if(g.cancelRequested=!0,g.abortRequested=!0,g.status&&g.status.update("Cancelled by user.",!0),g.abort)try{g.abort()}catch(w){console.warn("[tg-agent] abort callback failed during force close",w)}dt(a)}if(!et(c,i)){await p(e,`Session not found: ${i}`,r);return}await O(c),await ue(a,i).catch(w=>{console.warn(`[tg-agent] delete session file failed id=${i}`,w)});let y=g?`Force-closed session ${i} (interrupted running task).`:`Closed session ${i}.`;await p(e,y,r);return}case"reset":{let i=se(c);if(!i){await p(e,"No active session.",r);return}if(i.messages.length>0)try{await p(e,"Reflecting on session memory...",r);let d=await Be(i,i.modelProvider,i.modelId);d.reflected?await p(e,"Memory archived successfully.",r):d.error?await p(e,`Memory saved (reflection failed: ${d.error})`,r):await p(e,"Memory saved (no reflection).",r)}catch(d){console.warn("[tg-agent] memory archival failed",d),await p(e,`Memory archival failed: ${ie(d)}`,r)}ln(i),await O(c),await ue(a,i.id).catch(d=>{console.warn(`[tg-agent] reset session file failed id=${i.id}`,d)}),await p(e,`Reset session ${i.id}.`,r);return}case"workspace":{if(!o){let d=lt(a,c),g=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default";await p(e,`Workspace: ${d} (source: ${g})`,r);return}let i=fe.resolve(J(o.trim()));dn(c,i),await O(c),await p(e,`Workspace set to: ${i}`,r);return}case"providers":{let{authStorage:i,modelRegistry:d}=await ge(),g=d.getError(),f=cs(d,i);if(f.length===0){let w=g?`Warning: ${g}
96
+
97
+ No providers found.`:"No providers found.";await p(e,w,r);return}let y=[];g&&y.push(`Warning: ${g}`),y.push("Providers:"),await Cn(e,y.join(`
98
+ `),f,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:i,modelRegistry:d}=await ge(),g=o?pe(o):"";if(!g){let k=se(c);if(!k?.modelProvider){await p(e,"Usage: /models <provider>",r);return}g=k.modelProvider}let f=i.hasAuth(g),y=ds(c,g),w=ls(d,g,y);if(w.length===0){await p(e,`No models found for provider ${g}.`,r);return}await Cn(e,`Models for ${g} (auth: ${f?"ok":"missing"}):`,w,{perRow:1,footer:"Tap a model to set it.",messageThreadId:r});return}case"provider":{if(!o){await p(e,"Usage: /provider <name>",r);return}let i=pe(o),{modelRegistry:d}=await ge();if(!d.getAll().some(y=>y.provider===i)){await p(e,`Unknown provider: ${i}`,r);return}let f=await _n(c,e,r);f.modelProvider=i,f.modelId=void 0,f.updatedAt=z(),await O(c),await p(e,`Session ${f.id} provider set to ${i}.`,r),await mt(e,t,"models",i,r);return}case"model":{let i=us(o);if(!i){await p(e,"Usage: /model <provider>/<model>",r);return}let d=await _n(c,e,r),g=pe(i.provider??d.modelProvider??"");if(!g){await p(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:f}=await ge(),y=rs(g,i.modelId);if(!f.find(g,y)){await p(e,`Model not found: ${g}/${y}`,r);return}d.modelProvider=g,d.modelId=y,d.updatedAt=z(),await O(c),await p(e,`Session ${d.id} model set to ${g}/${y}.`,r);return}case"status":{let i=se(c);if(!i){await p(e,"No active session.",r);return}let d=m.modelRef.includes("/")?m.modelRef:`${m.modelProvider}/${m.modelRef}`,g=i.modelProvider||i.modelId?`Model: ${i.modelProvider??"?"}/${i.modelId??"?"}`:`Model: ${d} (default)`,f=lt(a,c),y=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default",w=[`Session: ${i.id} (${i.title})`,g,`Workspace: ${f} (${y})`].join(`
99
+ `);await p(e,w,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Ht(),await xe(m.agentDir,{timeoutMs:5e3,maxBytes:m.fetchMaxBytes,maxChars:3e3}),Xe(),await p(e,"MCP catalog refreshed.",r);return}let i=await _s();await p(e,i,r);return}case"login":{let i=Fr();if(!o){let f=i.map(y=>`- ${y.id} (${y.name})`);await p(e,["OAuth providers:",...f].join(`
100
+ `),r);return}let d=pe(o);if(at.has(t)){await p(e,"Login already in progress.",r);return}let g=i.find(f=>f.id===d);if(!g){await p(e,`Unknown OAuth provider: ${d}`,r);return}at.add(t);try{let{authStorage:f}=await ge();await p(e,`Starting login for ${g.id}...`,r),await f.login(g.id,{onAuth:({url:y,instructions:w})=>{let k=["Open this URL in your browser:",y];w&&k.push("",w),p(e,k.join(`
101
+ `),r)},onPrompt:y=>An(t,e,y,r),onProgress:y=>{p(e,y,r)},onManualCodeInput:()=>An(t,e,{message:"Paste the authorization code:"},r)}),await p(e,`Login completed for ${g.id}.`,r)}catch(f){let y=ie(f);await p(e,`Login failed: ${y}`,r)}finally{at.delete(t),Dn(t)}return}case"logout":{if(!o){await p(e,"Usage: /logout <provider>",r);return}let i=pe(o),{authStorage:d}=await ge();d.logout(i),await p(e,`Logged out from ${i}.`,r);return}case"memory":{let i=m.memory.rag,d=await xn(),g=["Memory System Status:","",`RAG Enabled: ${i.enabled?"Yes":"No"}`,`Embedding Model: ${i.embeddingModel}`,`Embedding Base URL: ${i.embeddingBaseUrl||"(default)"}`,`Similarity Threshold: ${i.similarityThreshold}`,`Max Results: ${i.maxResults}`,"","Database:",` Sessions: ${d.sessionsCount}`,` Memories: ${d.memoriesCount}`,"","Tip: Use /reindex to rebuild memory vectors after changing embedding model."];await p(e,g.join(`
102
102
  `),r);return}case"reindex":{if(!m.memory.rag.enabled){await p(e,"Memory RAG is disabled. Enable it in config.toml first.",r);return}await p(e,["Starting memory reindex...","",`Embedding Model: ${m.memory.rag.embeddingModel}`,"","Reading sessions and rebuilding memories table..."].join(`
103
- `),r);try{let i=await _t((d,g,f)=>{(d%5===0||d===g)&&console.log(`[reindex] Progress: ${d}/${g} - ${f}`)});if(i.success){let d=["Reindex completed!","",`Sessions: ${i.totalSessions}`,`Total memories: ${i.totalMemories}`,`Indexed: ${i.indexedMemories}`,`Errors: ${i.errors.length}`,"",`Embedding Model: ${i.embeddingModel}`,`Vector Dimension: ${i.vectorDimension??"N/A"}`];i.errors.length>0&&(d.push("","Errors:"),i.errors.slice(0,5).forEach(g=>d.push(` - ${g}`)),i.errors.length>5&&d.push(` ... and ${i.errors.length-5} more`)),await p(e,d.join(`
104
- `),r)}else await p(e,`Reindex failed: ${i.errors.join(", ")}`,r)}catch(i){let d=i instanceof Error?i.message:String(i);await p(e,`Reindex failed: ${d}`,r)}return}default:await p(e,`Unknown command: ${n}`,r)}}async function Ps(e,t,n,o=[],r){let s=gt(n);if(s){await pt(e,t,s.command,s.args,r);return}let a=Je(e,r,r!==void 0);if(!a)return;let c=await Fe(a),u=st(c);u.length>0&&(await O(c),await Promise.all(u.map(x=>me(a,x).catch(P=>{console.warn(`[tg-agent] cleanup session file failed id=${x}`,P)}))));let i=se(c);if(!i)try{i=ze(c,""),await O(c),await p(e,`Created session ${i.id}.`,r)}catch(x){await p(e,x.message,r);return}let{resolved:d,images:g}=await Yr(o);if(o.length>0&&d.length===0&&!n.trim()){await p(e,"Failed to download attachments.",r);return}let f=Vr(d),y=[];n.trim()&&y.push(n.trim()),f&&y.push(f);let w=y.join(`
103
+ `),r);try{let i=await vn((d,g,f)=>{(d%5===0||d===g)&&console.log(`[reindex] Progress: ${d}/${g} - ${f}`)});if(i.success){let d=["Reindex completed!","",`Sessions: ${i.totalSessions}`,`Total memories: ${i.totalMemories}`,`Indexed: ${i.indexedMemories}`,`Errors: ${i.errors.length}`,"",`Embedding Model: ${i.embeddingModel}`,`Vector Dimension: ${i.vectorDimension??"N/A"}`];i.errors.length>0&&(d.push("","Errors:"),i.errors.slice(0,5).forEach(g=>d.push(` - ${g}`)),i.errors.length>5&&d.push(` ... and ${i.errors.length-5} more`)),await p(e,d.join(`
104
+ `),r)}else await p(e,`Reindex failed: ${i.errors.join(", ")}`,r)}catch(i){let d=i instanceof Error?i.message:String(i);await p(e,`Reindex failed: ${d}`,r)}return}default:await p(e,`Unknown command: ${n}`,r)}}async function Ps(e,t,n,o=[],r){let s=ut(n);if(s){await mt(e,t,s.command,s.args,r);return}let a=Je(e,r,r!==void 0);if(!a)return;let c=await Ne(a),u=Ze(c);u.length>0&&(await O(c),await Promise.all(u.map(x=>ue(a,x).catch(P=>{console.warn(`[tg-agent] cleanup session file failed id=${x}`,P)}))));let i=se(c);if(!i)try{i=Le(c,""),await O(c),await p(e,`Created session ${i.id}.`,r)}catch(x){await p(e,x.message,r);return}let{resolved:d,images:g}=await Yr(o);if(o.length>0&&d.length===0&&!n.trim()){await p(e,"Failed to download attachments.",r);return}let f=Vr(d),y=[];n.trim()&&y.push(n.trim()),f&&y.push(f);let w=y.join(`
105
105
 
106
- `)||"Attachment received.",k={role:"user",content:w,ts:z()};at(i,k,m.maxHistoryMessages),await O(c),console.log(`[tg-agent] request user=${t} chat=${a} session=${i.id} messages=${i.messages.length} textLen=${w.length} attachments=${d.length} provider=${i.modelProvider??"-"} model=${i.modelId??"-"}`);let A=null;try{A=await Ms(e,r)}catch(x){console.warn("[tg-agent] status message failed",x)}let I={sessionId:i.id,chatId:e,messageThreadId:r,status:A,abortRequested:!1,cancelRequested:!1};Ur(a,I);try{let x=m.systemPrompt;if(m.memory.rag.enabled&&w.trim())try{let S=await kt(w);if(S.length>0){let b=S.map($=>`- [${$.type}] ${$.content} (${$.date})`).join(`
106
+ `)||"Attachment received.",k={role:"user",content:w,ts:z()};tt(i,k,m.maxHistoryMessages),await O(c),console.log(`[tg-agent] request user=${t} chat=${a} session=${i.id} messages=${i.messages.length} textLen=${w.length} attachments=${d.length} provider=${i.modelProvider??"-"} model=${i.modelId??"-"}`);let A=null;try{A=await Ms(e,r)}catch(x){console.warn("[tg-agent] status message failed",x)}let I={sessionId:i.id,chatId:e,messageThreadId:r,status:A,abortRequested:!1,cancelRequested:!1};Ur(a,I);try{let x=m.systemPrompt;if(m.memory.rag.enabled&&w.trim())try{let S=await bn(w);if(S.length>0){let b=S.map($=>`- [${$.type}] ${$.content} (${$.date})`).join(`
107
107
  `);x+=`
108
108
 
109
109
  <relevant_memories>
110
110
  Relevant facts about Shawn from past conversations:
111
111
 
112
112
  ${b}
113
- </relevant_memories>`,console.log(`[memory-rag] injected ${S.length} memories into context`)}}catch(S){console.warn(`[memory-rag] retrieval failed: ${S}`)}let P=await zr(async()=>{let S=await Mn({chatId:a,sessionId:i.id,prompt:w,images:g,systemPrompt:x,modelProvider:i.modelProvider,modelId:i.modelId,workspaceDir:ut(a,c),telegram:{chatId:e,sendPhoto:async(b,$)=>{let D={};$&&(D.caption=$),r!==void 0&&(D.message_thread_id=r),await E.sendPhoto(e,b,D)},sendDocument:async(b,$)=>{let D={};$&&(D.caption=$),r!==void 0&&(D.message_thread_id=r),await E.sendDocument(e,b,D)},sendMessage:async b=>{await p(e,b,r)},requestConfirmation:async(b,$)=>await An(a,e,b,$,r)},auditContext:m.audit.enabled?{chatId:a,requestConfirmation:async(b,$)=>await An(a,e,b,$,r),sendNotification:async b=>{await p(e,b,r)}}:void 0,onAbortReady:b=>{I.abort=b,I.abortRequested&&b()},onStatus:A?b=>{let $=$s(b);$&&A?.update($)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${S.modelProvider}/${S.modelId} file=${S.sessionFile}`),S.text});if(I.cancelRequested){A?await A.finalize("Cancelled by user."):await p(e,"Cancelled by user.",r);return}let ae={role:"assistant",content:P,ts:z()};at(i,ae,m.maxHistoryMessages),await O(c),A?await A.finalize(P):await p(e,P,r)}catch(x){if(console.error("[tg-agent] runModel error",x),I.cancelRequested){A?await A.fail("Cancelled by user."):await p(e,"Cancelled by user.",r);return}let P=ie(x);A?await A.fail(`Error: ${P}`):await p(e,`Error: ${P}`,r)}finally{mt(a)}}var E,En,zr,$e,Kr,Qr,ts,ne,lt,Se,ns,os,Ke,as,ms,Rn,Bn,Cn,ys,V,vs,Ss,Wn=j(()=>{"use strict";W();Ze();qt();$n();ce();Ne();ct();Ye();Ve();Y();zt();E=new Nr(m.telegramToken,{polling:!0}),En=vt(),zr=St(m.maxConcurrent),$e=new Map;Kr="image/jpeg";Qr=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);ts=600*1e3,ne=new Map,lt=new Set,Se=new Map;ns=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),os={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};is();R(m.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await xe(m.agentDir,{timeoutMs:3e3,maxBytes:m.fetchMaxBytes,maxChars:2e3}),nt()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Ke=Ht();console.log(Ke?`[tg-agent] fetchProxy=${Ke.url} kind=${Ke.kind} source=${Ke.source}`:"[tg-agent] fetchProxy=(none)");as=new Set(["openai-codex","google-antigravity","anthropic"]);ms=6e4,Rn=new Map;Bn=1800*1e3,Cn=2e3,ys=60,V=new Map;vs=3900,Ss=1200;E.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){E.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!jn(o)){Ln(o,n),E.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){E.answerCallbackQuery(e.id);return}let r=bs(t);if(!r){E.answerCallbackQuery(e.id,{text:"Command expired."});return}E.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,l=e.message?.is_topic_message??!1,a=Je(n,s,l);if(!a)return;let c=gt(r);if(c?.command==="stop"){Me(a,!1)?p(n,"Operation blocked.",s):In(n,a,s);return}if(c?.command==="close"){Nn(n,a,c.args,s);return}if(c?.command==="approve"){Me(a,!0)?p(n,"Operation approved.",s):p(n,"No pending audit confirmation.",s);return}En(a,async()=>{if(!c){await p(n,"Invalid command.",s);return}await pt(n,o,c.command,c.args,s)}).catch(async u=>{console.error("[tg-agent] runModel error",u);let i=ie(u);await p(n,`Error: ${i}`,s)})});E.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!jn(t)){Ln(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=Je(n,o,r);if(!s)return;let l=(e.text??e.caption??"").trim(),a=Xr(e);if(!l&&a.length===0)return;let c=ne.get(t);if(c){if(l==="/stop"||l==="/cancel"){ss(t,"Login cancelled by user."),p(n,"Login cancelled.",o);return}if(!l){p(n,"Login expects a text response.",o);return}On(t),c.resolve(l);return}let u=gt(l);if(u?.command==="stop"){Me(s,!1),In(n,s,o);return}if(u?.command==="close"){Me(s,!1),Nn(n,s,u.args,o);return}if(u?.command==="approve"){Me(s,!0)?p(n,"Operation approved.",o):p(n,"No pending audit confirmation.",o);return}En(s,()=>Ps(n,t,l,a,o)).catch(async i=>{console.error("[tg-agent] runModel error",i);let d=ie(i);await p(n,`Error: ${d}`,o)})});E.on("polling_error",e=>{console.error("Polling error",e)});E.setMyCommands([{command:"new",description:"Create a new session"},{command:"list",description:"List all sessions"},{command:"use",description:"Switch to a session"},{command:"close",description:"Close current session"},{command:"reset",description:"Clear session history"},{command:"stop",description:"Stop current request"},{command:"workspace",description:"View/set workspace directory"},{command:"status",description:"Show session status"},{command:"providers",description:"List available providers"},{command:"models",description:"List models for provider"},{command:"provider",description:"Set provider for session"},{command:"model",description:"Set model for session"},{command:"mcp",description:"List MCP servers"},{command:"memory",description:"Show memory RAG status"},{command:"reindex",description:"Rebuild memory vector index"},{command:"login",description:"Login to OAuth provider"},{command:"logout",description:"Logout from provider"},{command:"approve",description:"Approve security audit"},{command:"help",description:"Show all commands"}]).then(()=>{console.log("[tg-agent] bot commands menu registered")}).catch(e=>{console.warn("[tg-agent] failed to set bot commands:",e.message)});console.log("tg-agent started")});W();import Cs from"node:fs";import Hn from"node:path";import Ts from"node:readline/promises";import{fileURLToPath as Es}from"node:url";var qn=process.argv.slice(2),Gn=(e,t)=>qn.includes(e)||(t?qn.includes(t):!1),Ds=Gn("--help","-h"),Os=Gn("--version","-v"),Is=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
114
- `),Ns=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Es(import.meta.url),t=Hn.dirname(e),n=Hn.join(t,"..","package.json"),o=Cs.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Ds&&(console.log(Is),process.exit(0));Os&&(console.log(Ns()),process.exit(0));async function Ls(){let e=Ts.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function js(){let{configPath:e,data:t,exists:n}=we(),o=Ot(),r=n?t:o,s=It(r,o);if(Nt(r)){s&&await Qe(e,r);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${e}.`),process.exit(1));let a=await Ls();a||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),Lt(r,a),await Qe(e,r),console.log(`Saved config to ${e}.`)}async function Fs(){let{data:e}=we(),t=typeof e.tls=="object"&&e.tls?e.tls:{},n=typeof t.extra_ca_certs=="string"?t.extra_ca_certs.trim():"";if(n&&(process.env.NODE_EXTRA_CA_CERTS=n),typeof t.reject_unauthorized=="boolean"){process.env.NODE_TLS_REJECT_UNAUTHORIZED=t.reject_unauthorized?"1":"0";return}let o=typeof t.reject_unauthorized=="string"?t.reject_unauthorized.trim():"";o&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}await js();await Fs();Ft();Promise.resolve().then(()=>Wn());
113
+ </relevant_memories>`,console.log(`[memory-rag] injected ${S.length} memories into context`)}}catch(S){console.warn(`[memory-rag] retrieval failed: ${S}`)}let P=await zr(async()=>{let S=await yn({chatId:a,sessionId:i.id,prompt:w,images:g,systemPrompt:x,modelProvider:i.modelProvider,modelId:i.modelId,workspaceDir:lt(a,c),telegram:{chatId:e,sendPhoto:async(b,$)=>{let D={};$&&(D.caption=$),r!==void 0&&(D.message_thread_id=r),await E.sendPhoto(e,b,D)},sendDocument:async(b,$)=>{let D={};$&&(D.caption=$),r!==void 0&&(D.message_thread_id=r),await E.sendDocument(e,b,D)},sendMessage:async b=>{await p(e,b,r)},requestConfirmation:async(b,$)=>await kn(a,e,b,$,r)},auditContext:m.audit.enabled?{chatId:a,requestConfirmation:async(b,$)=>await kn(a,e,b,$,r),sendNotification:async b=>{await p(e,b,r)}}:void 0,onAbortReady:b=>{I.abort=b,I.abortRequested&&b()},onStatus:A?b=>{let $=$s(b);$&&A?.update($)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${S.modelProvider}/${S.modelId} file=${S.sessionFile}`),S.text});if(I.cancelRequested){A?await A.finalize("Cancelled by user."):await p(e,"Cancelled by user.",r);return}let ae={role:"assistant",content:P,ts:z()};tt(i,ae,m.maxHistoryMessages),await O(c),A?await A.finalize(P):await p(e,P,r)}catch(x){if(console.error("[tg-agent] runModel error",x),I.cancelRequested){A?await A.fail("Cancelled by user."):await p(e,"Cancelled by user.",r);return}let P=ie(x);A?await A.fail(`Error: ${P}`):await p(e,`Error: ${P}`,r)}finally{dt(a)}}var E,Tn,zr,$e,Kr,Qr,ts,ne,at,Se,ns,os,Ke,as,ms,Pn,Un,Rn,ys,V,vs,Ss,Jn=j(()=>{"use strict";H();qe();zt();hn();le();De();nt();Mn();it();Y();Et();E=new Nr(m.telegramToken,{polling:!0}),Tn=bt(),zr=xt(m.maxConcurrent),$e=new Map;Kr="image/jpeg";Qr=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);ts=600*1e3,ne=new Map,at=new Set,Se=new Map;ns=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),os={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};is();R(m.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await xe(m.agentDir,{timeoutMs:3e3,maxBytes:m.fetchMaxBytes,maxChars:2e3}),Xe()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Ke=Ft();console.log(Ke?`[tg-agent] fetchProxy=${Ke.url} kind=${Ke.kind} source=${Ke.source}`:"[tg-agent] fetchProxy=(none)");as=new Set(["openai-codex","google-antigravity","anthropic"]);ms=6e4,Pn=new Map;Un=1800*1e3,Rn=2e3,ys=60,V=new Map;vs=3900,Ss=1200;E.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){E.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!Ln(o)){Nn(o,n),E.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){E.answerCallbackQuery(e.id);return}let r=bs(t);if(!r){E.answerCallbackQuery(e.id,{text:"Command expired."});return}E.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,l=e.message?.is_topic_message??!1,a=Je(n,s,l);if(!a)return;let c=ut(r);if(c?.command==="stop"){Me(a,!1)?p(n,"Operation blocked.",s):On(n,a,s);return}if(c?.command==="close"){In(n,a,c.args,s);return}if(c?.command==="approve"){Me(a,!0)?p(n,"Operation approved.",s):p(n,"No pending audit confirmation.",s);return}Tn(a,async()=>{if(!c){await p(n,"Invalid command.",s);return}await mt(n,o,c.command,c.args,s)}).catch(async u=>{console.error("[tg-agent] runModel error",u);let i=ie(u);await p(n,`Error: ${i}`,s)})});E.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!Ln(t)){Nn(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=Je(n,o,r);if(!s)return;let l=(e.text??e.caption??"").trim(),a=Xr(e);if(!l&&a.length===0)return;let c=ne.get(t);if(c){if(l==="/stop"||l==="/cancel"){ss(t,"Login cancelled by user."),p(n,"Login cancelled.",o);return}if(!l){p(n,"Login expects a text response.",o);return}Dn(t),c.resolve(l);return}let u=ut(l);if(u?.command==="stop"){Me(s,!1),On(n,s,o);return}if(u?.command==="close"){Me(s,!1),In(n,s,u.args,o);return}if(u?.command==="approve"){Me(s,!0)?p(n,"Operation approved.",o):p(n,"No pending audit confirmation.",o);return}Tn(s,()=>Ps(n,t,l,a,o)).catch(async i=>{console.error("[tg-agent] runModel error",i);let d=ie(i);await p(n,`Error: ${d}`,o)})});E.on("polling_error",e=>{console.error("Polling error",e)});E.setMyCommands([{command:"new",description:"Create a new session"},{command:"list",description:"List all sessions"},{command:"use",description:"Switch to a session"},{command:"close",description:"Close current session"},{command:"reset",description:"Clear session history"},{command:"stop",description:"Stop current request"},{command:"workspace",description:"View/set workspace directory"},{command:"status",description:"Show session status"},{command:"providers",description:"List available providers"},{command:"models",description:"List models for provider"},{command:"provider",description:"Set provider for session"},{command:"model",description:"Set model for session"},{command:"mcp",description:"List MCP servers"},{command:"memory",description:"Show memory RAG status"},{command:"reindex",description:"Rebuild memory vector index"},{command:"login",description:"Login to OAuth provider"},{command:"logout",description:"Logout from provider"},{command:"approve",description:"Approve security audit"},{command:"help",description:"Show all commands"}]).then(()=>{console.log("[tg-agent] bot commands menu registered")}).catch(e=>{console.warn("[tg-agent] failed to set bot commands:",e.message)});console.log("tg-agent started")});H();import Cs from"node:fs";import Wn from"node:path";import Ts from"node:readline/promises";import{fileURLToPath as Es}from"node:url";var Hn=process.argv.slice(2),qn=(e,t)=>Hn.includes(e)||(t?Hn.includes(t):!1),Ds=qn("--help","-h"),Os=qn("--version","-v"),Is=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
114
+ `),Ns=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Es(import.meta.url),t=Wn.dirname(e),n=Wn.join(t,"..","package.json"),o=Cs.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Ds&&(console.log(Is),process.exit(0));Os&&(console.log(Ns()),process.exit(0));async function Ls(){let e=Ts.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function js(){let{configPath:e,data:t,exists:n}=we(),o=At(),r=n?t:o,s=_t(r,o);if(Pt(r)){s&&await He(e,r);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${e}.`),process.exit(1));let a=await Ls();a||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),Rt(r,a),await He(e,r),console.log(`Saved config to ${e}.`)}async function Fs(){let{data:e}=we(),t=typeof e.tls=="object"&&e.tls?e.tls:{},n=typeof t.extra_ca_certs=="string"?t.extra_ca_certs.trim():"";if(n&&(process.env.NODE_EXTRA_CA_CERTS=n),typeof t.reject_unauthorized=="boolean"){process.env.NODE_TLS_REJECT_UNAUTHORIZED=t.reject_unauthorized?"1":"0";return}let o=typeof t.reject_unauthorized=="string"?t.reject_unauthorized.trim():"";o&&(process.env.NODE_TLS_REJECT_UNAUTHORIZED=o)}await js();await Fs();Tt();Promise.resolve().then(()=>Jn());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tg-agent",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Telegram Agent Bot",
5
5
  "type": "module",
6
6
  "bin": {