tg-agent 1.2.19 → 1.3.0

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 +47 -35
  2. package/package.json +6 -2
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- var N=(e,t)=>()=>(e&&(t=e(e=0)),t);import Ue from"node:fs/promises";import jn from"node:os";import Me from"node:path";import{randomUUID as lt}from"node:crypto";function F(){return Date.now()}function W(e){return e.startsWith("~")?Me.join(jn.homedir(),e.slice(1)):e}async function _(e){await Ue.mkdir(e,{recursive:!0})}async function ut(e,t){let n=Me.dirname(e),o=`${Me.basename(e)}.${lt()}.tmp`,r=Me.join(n,o),s=JSON.stringify(t,null,2);await Ue.writeFile(r,s,"utf8"),await Ue.rename(r,e)}function de(){return lt().split("-")[0]}function dt(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 mt(){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 gt(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 X=N(()=>{"use strict"});import ft from"node:fs";import $e from"node:path";import*as _e from"@iarna/toml";function ht(){let e=W(pt);return $e.join(e,Ln)}function E(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function A(e,t){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):t}function G(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 me(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 wt(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 Nn(e){return new Set(wt(e))}function Fn(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,$e.resolve(W(o.trim())));return t}function ge(){let e=ht();try{let t=ft.readFileSync(e,"utf8"),n=_e.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Be(e,t){await _($e.dirname(e));let n=_e.stringify(t);await ft.promises.writeFile(e,n,"utf8")}function bt(){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:yt},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:""}}}function ke(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function vt(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];ke(c)&&ke(a)&&o(c,a)}};return ke(e)&&ke(t)&&o(e,t),n}function xt(e){let t=E(e,"telegram");return A(t.bot_token,"").trim()}function St(e,t){let n=E(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function Mt(e){let t=E(e,"telegram"),n=E(e,"model"),o=E(e,"paths"),r=E(e,"limits"),s=E(e,"timeouts"),l=E(e,"fetch"),a=E(e,"proxy"),c=E(e,"auth"),d=E(e,"logging"),i=E(e,"system"),u=E(e,"tls"),g=E(e,"workspace_mappings"),p=E(e,"security_audit"),y=E(e,"memory"),w=A(o.workspace_dir,process.cwd()),k=A(o.session_dir,"~/.tg-agent/tg-sessions"),$=Fn(g),T=A(u.reject_unauthorized,""),v=T===""?null:me(T,!0);return{telegramToken:A(t.bot_token,"").trim(),telegramAllowedUsers:Nn(t.allowed_user_ids),telegramParseMode:A(t.parse_mode,"").trim(),modelProvider:A(n.provider,"openai-codex").trim(),modelRef:A(n.model,"gpt-5.2").trim(),openaiApiKey:A(n.openai_api_key,"").trim(),sessionDir:W(k),agentDir:W(pt),workspaceDir:$e.resolve(W(w)),workspaceMappings:$,maxSessions:G(r.max_sessions,5),maxConcurrent:G(r.max_concurrent,5),maxHistoryMessages:G(r.max_history_messages,40),maxOutputTokens:G(r.max_output_tokens,0),fetchMaxBytes:G(l.max_bytes,2e5),fetchTimeoutMs:G(s.fetch_timeout_ms,6e4),modelTimeoutMs:G(s.model_timeout_ms,6e4),modelTimeoutStreamingMs:G(s.model_timeout_stream_ms,3e5),systemPrompt:A(i.prompt,yt),proxyUrl:A(a.url,"").trim(),fetchProxyUrl:A(l.proxy_url,"").trim(),codexHome:W(A(c.codex_home,"~/.codex")),logAgentEvents:me(d.agent_events,!0),logAgentStream:me(d.agent_stream,!0),tlsExtraCaCerts:A(u.extra_ca_certs,"").trim(),tlsRejectUnauthorized:v,audit:{enabled:me(p.enabled,!1),modelProvider:A(p.model_provider,"").trim(),modelId:A(p.model_id,"").trim(),whitelistPatterns:wt(p.whitelist_patterns),confirmTimeoutMs:G(p.confirm_timeout_ms,6e4)},memory:{enabled:me(y.enabled,!0),modelProvider:A(y.model_provider,"").trim(),modelId:A(y.model_id,"").trim(),systemPrompt:A(y.system_prompt,"").trim()}}}function kt(){let{data:e}=ge();return m=Mt(e),m}function $t(){let e=[];if(m.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${ht()})`)}var pt,Ln,yt,zn,m,K=N(()=>{"use strict";X();pt="~/.tg-agent",Ln="config.toml",yt=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
2
+ var L=(e,t)=>()=>(e&&(t=e(e=0)),t);import qe from"node:fs/promises";import Qn from"node:os";import ke from"node:path";import{randomUUID as xt}from"node:crypto";function z(){return Date.now()}function W(e){return e.startsWith("~")?ke.join(Qn.homedir(),e.slice(1)):e}async function A(e){await qe.mkdir(e,{recursive:!0})}async function vt(e,t){let n=ke.dirname(e),o=`${ke.basename(e)}.${xt()}.tmp`,r=ke.join(n,o),s=JSON.stringify(t,null,2);await qe.writeFile(r,s,"utf8"),await qe.rename(r,e)}function pe(){return xt().split("-")[0]}function Mt(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 St(){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 $t(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 X=L(()=>{"use strict"});import kt from"node:fs";import Ae from"node:path";import*as Pe from"@iarna/toml";function Pt(){let e=W(_t);return Ae.join(e,Zn)}function T(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function P(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 ae(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 Ct(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 eo(e){return new Set(Ct(e))}function to(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,Ae.resolve(W(o.trim())));return t}function ye(){let e=Pt();try{let t=kt.readFileSync(e,"utf8"),n=Pe.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Ve(e,t){await A(Ae.dirname(e));let n=Pe.stringify(t);await kt.promises.writeFile(e,n,"utf8")}function Rt(){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:At},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 _e(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function Tt(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];_e(c)&&_e(a)&&o(c,a)}};return _e(e)&&_e(t)&&o(e,t),n}function Et(e){let t=T(e,"telegram");return P(t.bot_token,"").trim()}function Dt(e,t){let n=T(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function Ot(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"),p=T(e,"security_audit"),y=T(e,"memory"),w=T(y,"rag"),$=P(o.workspace_dir,process.cwd()),_=P(o.session_dir,"~/.tg-agent/tg-sessions"),j=to(g),x=P(d.reject_unauthorized,""),C=x===""?null:ae(x,!0);return{telegramToken:P(t.bot_token,"").trim(),telegramAllowedUsers:eo(t.allowed_user_ids),telegramParseMode:P(t.parse_mode,"").trim(),modelProvider:P(n.provider,"openai-codex").trim(),modelRef:P(n.model,"gpt-5.2").trim(),openaiApiKey:P(n.openai_api_key,"").trim(),sessionDir:W(_),agentDir:W(_t),workspaceDir:Ae.resolve(W($)),workspaceMappings:j,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:P(i.prompt,At),proxyUrl:P(a.url,"").trim(),fetchProxyUrl:P(l.proxy_url,"").trim(),codexHome:W(P(c.codex_home,"~/.codex")),logAgentEvents:ae(u.agent_events,!0),logAgentStream:ae(u.agent_stream,!0),tlsExtraCaCerts:P(d.extra_ca_certs,"").trim(),tlsRejectUnauthorized:C,audit:{enabled:ae(p.enabled,!1),modelProvider:P(p.model_provider,"").trim(),modelId:P(p.model_id,"").trim(),whitelistPatterns:Ct(p.whitelist_patterns),confirmTimeoutMs:H(p.confirm_timeout_ms,6e4)},memory:{enabled:ae(y.enabled,!0),modelProvider:P(y.model_provider,"").trim(),modelId:P(y.model_id,"").trim(),systemPrompt:P(y.system_prompt,"").trim(),rag:{enabled:ae(w.enabled,!0),embeddingModel:P(w.embedding_model,"openai/text-embedding-3-small").trim(),embeddingBaseUrl:P(w.embedding_base_url,"").trim(),embeddingApiKey:P(w.embedding_api_key,"").trim(),similarityThreshold:H(w.similarity_threshold,.5),maxResults:H(w.max_results,5)}}}}function jt(){let{data:e}=ye();return m=Ot(e),m}function Nt(){let e=[];if(m.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${Pt()})`)}var _t,Zn,At,no,m,J=L(()=>{"use strict";X();_t="~/.tg-agent",Zn="config.toml",At=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
4
4
 
5
5
  Important behavioral rules:
6
6
  - Do NOT mention the name of your underlying framework, technical implementation, or any package names
@@ -9,21 +9,21 @@ Important behavioral rules:
9
9
  - Focus on helping with tasks rather than discussing your technical stack or architecture
10
10
  - Do not mention documentation paths or framework-specific resources unless directly relevant to the task
11
11
 
12
- Be concise and practical in all responses.`;({data:zn}=ge()),m=Mt(zn)});import{createHash as Un}from"node:crypto";import _t from"node:fs";import Bn from"node:path";import{execSync as Wn}from"node:child_process";function Jn(){return Bn.join(m.codexHome,Kn)}function qn(e){return`cli|${Un("sha256").update(e).digest("hex").slice(0,16)}`}function Gn(){if(process.platform!=="darwin")return null;let e=m.codexHome,t=qn(e);try{let n=Wn(`security find-generic-password -s "${Hn}" -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(),d=Number.isFinite(c)?c+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:l,expiresAt:d,source:"keychain"}}catch{return null}}function Vn(){let e=Jn();try{let t=_t.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=_t.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function Q(){return Gn()??Vn()}var Kn,Hn,fe=N(()=>{"use strict";K();Kn="auth.json",Hn="Codex Auth"});function At(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 Yn(){return m.proxyUrl?{url:m.proxyUrl,source:"config.proxy.url"}:m.fetchProxyUrl?{url:m.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function Pt(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function Ct(){let e=Yn();return e?{url:e.url,kind:Pt(e.url),source:e.source}:null}function Tt(){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=Pt(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var We=N(()=>{"use strict";K();fe()});import{ProxyAgent as Xn,setGlobalDispatcher as Qn}from"undici";function Et(){if(Rt)return Ke;Rt=!0;let e=Tt();if(!e)return Ke=null,null;let t=new Xn(e.url);return Qn(t),Ke=e,e}var Rt,Ke,Dt=N(()=>{"use strict";We();Rt=!1,Ke=null});import Zn from"node:fs";import eo from"node:fs/promises";import to from"node:path";import no from"node:readline";import{spawn as oo}from"node:child_process";import*as It from"@iarna/toml";function Nt(e){return to.join(e,"config.toml")}function Ae(e){let t=Nt(e);try{let n=Zn.readFileSync(t,"utf8");return Bt(n)}catch{return[]}}async function pe(e){let t=Nt(e);try{let n=await eo.readFile(t,"utf8");return Bt(n)}catch{return[]}}async function ye(e,t={}){if(se)return se;let n=await pe(e);if(n.length===0)return se="","";let o=t.maxTools??so,r=t.maxChars??io,s=t.timeoutMs??4e3,l=t.maxBytes??jt,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let d of n){let i=await co(d,{timeoutMs:s,maxBytes:l});if(a.push(`${d.name} (${d.type})`),i.length===0){a.push(" - tools unavailable");continue}let u=i.slice(0,o);for(let g of u){let p=g.description?`: ${g.description}`:"";a.push(` - ${g.name}${p}`)}i.length>u.length&&a.push(` - ...and ${i.length-u.length} more`)}let c=a.join(`
12
+ Be concise and practical in all responses.`;({data:no}=ye()),m=Ot(no)});import{createHash as oo}from"node:crypto";import It from"node:fs";import ro from"node:path";import{execSync as so}from"node:child_process";function co(){return ro.join(m.codexHome,io)}function lo(e){return`cli|${oo("sha256").update(e).digest("hex").slice(0,16)}`}function uo(){if(process.platform!=="darwin")return null;let e=m.codexHome,t=lo(e);try{let n=so(`security find-generic-password -s "${ao}" -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 mo(){let e=co();try{let t=It.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=It.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function q(){return uo()??mo()}var io,ao,ce=L(()=>{"use strict";J();io="auth.json",ao="Codex Auth"});function Lt(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 go(){return m.proxyUrl?{url:m.proxyUrl,source:"config.proxy.url"}:m.fetchProxyUrl?{url:m.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function Ft(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function zt(){let e=go();return e?{url:e.url,kind:Ft(e.url),source:e.source}:null}function Ut(){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=Ft(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var Ge=L(()=>{"use strict";J();ce()});import{ProxyAgent as fo,setGlobalDispatcher as po}from"undici";function Kt(){if(Bt)return Ye;Bt=!0;let e=Ut();if(!e)return Ye=null,null;let t=new fo(e.url);return po(t),Ye=e,e}var Bt,Ye,Wt=L(()=>{"use strict";Ge();Bt=!1,Ye=null});import yo from"node:fs";import ho from"node:fs/promises";import wo from"node:path";import bo from"node:readline";import{spawn as xo}from"node:child_process";import*as Jt from"@iarna/toml";function Gt(e){return wo.join(e,"config.toml")}function Ce(e){let t=Gt(e);try{let n=yo.readFileSync(t,"utf8");return Zt(n)}catch{return[]}}async function he(e){let t=Gt(e);try{let n=await ho.readFile(t,"utf8");return Zt(n)}catch{return[]}}async function we(e,t={}){if(le)return le;let n=await he(e);if(n.length===0)return le="","";let o=t.maxTools??Mo,r=t.maxChars??So,s=t.timeoutMs??4e3,l=t.maxBytes??qt,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let i=await ko(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 p=g.description?`: ${g.description}`:"";a.push(` - ${g.name}${p}`)}i.length>d.length&&a.push(` - ...and ${i.length-d.length} more`)}let c=a.join(`
13
13
  `);return c.length>r&&(c=`${c.slice(0,r-20)}...
14
- (truncated)`),se=c,c}function Je(){se&&(Lt=!0)}function Ft(){se=null,Lt=!1,z.clear()}function ne(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 zt(e,t=5e3){let n=Date.now();try{return await Pe(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 Pe(e,t,n,o={}){let r=Ot(o.timeoutMs??ro,1e3,12e4),s=Ot(o.maxBytes??jt,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 mo(e,s,l.signal),await uo(e,t,n,s,l.signal)):await po(e,t,n,s,l.signal)}finally{clearTimeout(c),o.signal?.removeEventListener("abort",a)}}function Ot(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function co(e,t){try{let n=await Pe(e,"tools/list",{},t);return lo(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 lo(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 d=typeof a.description=="string"?a.description:void 0,i=a.inputSchema;s.push({name:c,description:d,inputSchema:i})}return s}async function uo(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await He(e,t,n,o,r),a=Ut(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 He(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=z.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});go(e.name,c);let d=await yo(c,o,r),i;try{i=JSON.parse(d.text)}catch{i=void 0}return fo(e.name,i),{statusCode:c.status,statusText:c.statusText,contentType:c.headers.get("content-type"),bodyText:d.text,parsed:i,bytes:d.bytes,truncated:d.truncated}}function Ut(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 mo(e,t,n){let o=z.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let s=await He(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=Ut(s.parsed);if(l){let d=l.toLowerCase();if(d.includes("method")&&d.includes("not"))return;throw new Error(l)}let a=new AbortController,c=setTimeout(()=>a.abort(),ao);try{await He(e,"notifications/initialized",{},t,a.signal)}catch{}finally{clearTimeout(c)}})();z.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let s=z.get(e.name);z.set(e.name,{initializedAt:Date.now(),cookie:s?.cookie,sessionId:s?.sessionId})}catch(s){throw z.delete(e.name),s}}function go(e,t){let o=z.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),s=t.headers.getSetCookie?.(),l=s&&s.length>0?s.join("; "):r;l&&z.set(e,{...o,cookie:l});let a=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");a&&z.set(e,{...o,sessionId:a})}function fo(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=z.get(e)??{initializedAt:0};z.set(e,{...s,sessionId:r})}async function po(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=oo(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,d=!1,i="",u=new Error("MCP request aborted."),g=no.createInterface({input:l.stdout,terminal:!1});g.on("line",b=>{if(b.length>o){d=!0;return}let S=null;try{S=JSON.parse(b)}catch{return}let P=typeof S.id=="string"?S.id:typeof S.id=="number"?String(S.id):"";if(!P)return;let Y=c.get(P);Y&&(c.delete(P),Y.resolve(S))}),l.stderr?.on("data",b=>{let S=b.toString();if(i.length+S.length>o){d=!0;return}i+=S});let p=()=>{for(let b of c.values())b.reject(u);c.clear(),a()};r.addEventListener("abort",p,{once:!0});let y=b=>{let S=b===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let P of c.values())P.reject(new Error(S));c.clear()};l.once("exit",b=>y(b));let w=async(b,S)=>{let P=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,Y={jsonrpc:"2.0",id:P,method:b,params:S??{}};return await new Promise((te,ue)=>{c.set(P,{resolve:te,reject:ue}),l.stdin?.write(`${JSON.stringify(Y)}
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 b=k.error.message??"MCP initialize failed.";throw a(),new Error(String(b))}let $={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify($)}
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 T=await w(t,n);r.removeEventListener("abort",p),g.close(),l.stdin?.end(),a();let v=new Promise(b=>{l.once("exit",()=>b())});if(await Promise.race([v,new Promise(b=>setTimeout(b,500))]),T.error&&typeof T.error=="object"){let b=T.error.message??"MCP request failed.";throw new Error(String(b))}let R=JSON.stringify(T,null,2),J=R.length>o?R.slice(0,o):R;return R.length>o&&(d=!0),{ok:!0,output:J,durationMs:Date.now()-s,bytes:Math.min(R.length,o),truncated:d}}async function yo(e,t,n){let o=e.body?.getReader?.();if(!o){let u=await e.text(),g=Math.min(u.length,t);return{text:u.slice(0,t),bytes:g,truncated:u.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:u,value:g}=await o.read();if(u)break;if(!g)continue;let p=l+g.byteLength;if(p>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=p}let c=new Uint8Array(l),d=0;for(let u of s)c.set(u,d),d+=u.byteLength;return{text:r.decode(c),bytes:l,truncated:a}}function Bt(e){let t=[],n;try{n=It.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,d=typeof l.command=="string"?l.command:void 0,i=a==="http"||a==="stdio"?a:c?"http":d?"stdio":void 0;if(!i||i==="http"&&!c||i==="stdio"&&!d)continue;let u;Array.isArray(l.args)&&(u=l.args.filter(p=>typeof p=="string").map(p=>p.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:d,args:u,auth:g})}return t}var ro,jt,so,io,se,Lt,z,ao,Ce=N(()=>{"use strict";ro=6e4,jt=2e5,so=40,io=3500,se=null,Lt=!1,z=new Map,ao=1500});import V from"node:path";import ho from"node:fs/promises";import{Type as M}from"@sinclair/typebox";function Te(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function vo(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 Wt(e){let t=m.fetchTimeoutMs>0?m.fetchTimeoutMs:bo;return Te(e||t,1e3,12e4)}function Kt(e){let t=m.fetchMaxBytes>0?m.fetchMaxBytes:wo;return Te(e||t,1024,5e6)}function Ht(e,t,n){let o=e.trim();if(!o)return null;let r=W(o),s=V.isAbsolute(r)?r:V.join(n,r),l=V.resolve(s);for(let a of t){let c=V.resolve(a);if(l===c||l.startsWith(`${c}${V.sep}`))return l}return null}async function Jt(e){try{let t=await ho.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function xo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function So(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 Mo(e,t,n){let o=e.body?.getReader?.();if(!o){let i=await e.text?.()??"",u=Math.min(i.length,t),g=i.length>t;return{text:i.slice(0,t),bytes:u,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:u}=await o.read();if(i)break;if(!u)continue;let g=l+u.byteLength;if(g>t){let p=Math.max(0,t-l);p>0&&(s.push(u.slice(0,p)),l+=p),a=!0;try{await o.cancel?.()}catch{}break}s.push(u),l=g}let c=So(s,l);return{text:r.decode(c),bytes:l,truncated:a}}function ko(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}
14
+ (truncated)`),le=c,c}function Qe(){le&&(Vt=!0)}function Yt(){le=null,Vt=!1,U.clear()}function oe(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 Xt(e,t=5e3){let n=Date.now();try{return await Re(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 Re(e,t,n,o={}){let r=Ht(o.timeoutMs??vo,1e3,12e4),s=Ht(o.maxBytes??qt,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 Po(e,s,l.signal),await Ao(e,t,n,s,l.signal)):await To(e,t,n,s,l.signal)}finally{clearTimeout(c),o.signal?.removeEventListener("abort",a)}}function Ht(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function ko(e,t){try{let n=await Re(e,"tools/list",{},t);return _o(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 _o(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 Ao(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await Xe(e,t,n,o,r),a=Qt(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 Xe(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});Co(e.name,c);let u=await Eo(c,o,r),i;try{i=JSON.parse(u.text)}catch{i=void 0}return Ro(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 Qt(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 Po(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 Xe(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=Qt(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(),$o);try{await Xe(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 Co(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 Ro(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 To(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=xo(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=bo.createInterface({input:l.stdout,terminal:!1});g.on("line",M=>{if(M.length>o){u=!0;return}let b=null;try{b=JSON.parse(M)}catch{return}let k=typeof b.id=="string"?b.id:typeof b.id=="number"?String(b.id):"";if(!k)return;let D=c.get(k);D&&(c.delete(k),D.resolve(b))}),l.stderr?.on("data",M=>{let b=M.toString();if(i.length+b.length>o){u=!0;return}i+=b});let p=()=>{for(let M of c.values())M.reject(d);c.clear(),a()};r.addEventListener("abort",p,{once:!0});let y=M=>{let b=M===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let k of c.values())k.reject(new Error(b));c.clear()};l.once("exit",M=>y(M));let w=async(M,b)=>{let k=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,D={jsonrpc:"2.0",id:k,method:M,params:b??{}};return await new Promise((ne,fe)=>{c.set(k,{resolve:ne,reject:fe}),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 $=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:!!$.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),$.error&&typeof $.error=="object"){let M=$.error.message??"MCP initialize failed.";throw a(),new Error(String(M))}let _={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify(_)}
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 j=await w(t,n);r.removeEventListener("abort",p),g.close(),l.stdin?.end(),a();let x=new Promise(M=>{l.once("exit",()=>M())});if(await Promise.race([x,new Promise(M=>setTimeout(M,500))]),j.error&&typeof j.error=="object"){let M=j.error.message??"MCP request failed.";throw new Error(String(M))}let C=JSON.stringify(j,null,2),ie=C.length>o?C.slice(0,o):C;return C.length>o&&(u=!0),{ok:!0,output:ie,durationMs:Date.now()-s,bytes:Math.min(C.length,o),truncated:u}}async function Eo(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 p=l+g.byteLength;if(p>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=p}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 Zt(e){let t=[],n;try{n=Jt.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(p=>typeof p=="string").map(p=>p.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 vo,qt,Mo,So,le,Vt,U,$o,Te=L(()=>{"use strict";vo=6e4,qt=2e5,Mo=40,So=3500,le=null,Vt=!1,U=new Map,$o=1500});import Q from"node:path";import Do from"node:fs/promises";import{Type as S}from"@sinclair/typebox";function Ee(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function No(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 en(e){let t=m.fetchTimeoutMs>0?m.fetchTimeoutMs:jo;return Ee(e||t,1e3,12e4)}function tn(e){let t=m.fetchMaxBytes>0?m.fetchMaxBytes:Oo;return Ee(e||t,1024,5e6)}function nn(e,t,n){let o=e.trim();if(!o)return null;let r=W(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 on(e){try{let t=await Do.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function Io(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Lo(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 Fo(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 p=Math.max(0,t-l);p>0&&(s.push(d.slice(0,p)),l+=p),a=!0;try{await o.cancel?.()}catch{}break}s.push(d),l=g}let c=Lo(s,l);return{text:r.decode(c),bytes:l,truncated:a}}function zo(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
17
  ${o.join(`
18
18
  `)}
19
19
 
20
- ${t}`}function _o(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:$o,execute:async(e,t,n,o,r)=>{if(!xo(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=Wt(t.timeoutMs),l=Kt(t.maxBytes),a=new AbortController,c=()=>a.abort();r?.addEventListener("abort",c,{once:!0});let d=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:vo(t.headers),body:t.body,signal:a.signal}),u=await Mo(i,l,r),g=i.headers.get("content-type");return{content:[{type:"text",text:ko({url:i.url,status:i.status,statusText:i.statusText,bytes:u.bytes,truncated:u.truncated,contentType:g},u.text)}],details:{url:i.url,status:i.status,statusText:i.statusText,bytes:u.bytes,truncated:u.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(d),r?.removeEventListener("abort",c)}}}}function Po(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}
20
+ ${t}`}function Bo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:Uo,execute:async(e,t,n,o,r)=>{if(!Io(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=en(t.timeoutMs),l=tn(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:No(t.headers),body:t.body,signal:a.signal}),d=await Fo(i,l,r),g=i.headers.get("content-type");return{content:[{type:"text",text:zo({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 Wo(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
21
  ${r.join(`
22
22
  `)}
23
23
 
24
- ${n}`}function Co(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:Ao,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(d=>d.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let c=l.find(d=>d.name===a);if(!c)return{content:[{type:"text",text:`MCP server not found: ${a}. Available: ${l.map(d=>d.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:ne(c),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let d=await Pe(c,n.method,n.params??{},{timeoutMs:Wt(void 0),maxBytes:Kt(void 0),signal:s});return{content:[{type:"text",text:Po(c,{server:c.name,type:c.type,target:ne(c),status:d.statusCode??0,statusText:d.statusText??(d.ok?"ok":"error"),bytes:d.bytes,truncated:d.truncated,contentType:d.contentType??null},d.output)}],details:{server:c.name,type:c.type,target:ne(c),status:d.statusCode??0,statusText:d.statusText??(d.ok?"ok":"error"),bytes:d.bytes,truncated:d.truncated,contentType:d.contentType??null}}}catch(d){return{content:[{type:"text",text:`MCP failed: ${d instanceof Error?d.message:String(d)}`}],details:{server:c.name,type:c.type,target:ne(c),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function Eo(e){let t=[m.workspaceDir,V.join(m.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:To,execute:async(n,o)=>{let r=Ht(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 Jt(r);return s?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${V.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function Do(e){let t=[m.workspaceDir,V.join(m.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:Ro,execute:async(n,o)=>{let r=Ht(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 Jt(r);return s?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${V.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function qt(e){let t=[_o()];return e?.telegram&&(t.push(Eo(e.telegram)),t.push(Do(e.telegram))),Ae(m.agentDir).length>0&&t.push(Co(()=>pe(m.agentDir))),t}var wo,bo,$o,Ao,To,Ro,Gt=N(()=>{"use strict";K();Ce();X();wo=2e5,bo=6e4;$o=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}))});Ao=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"}))});To=M.Object({path:M.String({description:"Image file path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))}),Ro=M.Object({path:M.String({description:"File path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))})});import Xt from"node:fs/promises";import Qt from"node:path";function Zt(e){return Qt.join(m.sessionDir,`${e}.json`)}function Vt(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function qe(e,t){let n=Vt(e),o=Vt(t);return Qt.join(m.sessionDir,`${n}-${o}.jsonl`)}async function ie(e,t){let n=qe(e,t);try{await Xt.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function Yt(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 Ee(e){await _(m.sessionDir);let t=Re.get(e);if(t)return t;let n=Zt(e);try{let o=await Xt.readFile(n,"utf8"),r=JSON.parse(o),s=Yt(e,r);return Re.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=Yt(e,{});return Re.set(e,r),r}throw o}}async function D(e){await _(m.sessionDir);let t=Zt(e.chatId);await ut(t,e),Re.set(e.chatId,e)}function Ge(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function Ve(e){return[]}function De(e,t){if(Object.keys(e.sessions).length>=m.maxSessions)throw new Error("Max sessions reached");let o=de(),r=F(),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 en(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function oe(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function Ye(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function tn(e){e.messages=[],e.updatedAt=F()}function Xe(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=F()}function nn(e,t){e.workspaceDir=t}var Re,Qe=N(()=>{"use strict";K();X();Re=new Map});import Oo from"node:fs/promises";import rn from"node:path";import{completeSimple as Io}from"@mariozechner/pi-ai";function Fo(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return No.replace("{{command}}",n)}function zo(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 Uo(e,t,n,o){let r=Fo(n,o);try{let l=(await Io(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 zo(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 Bo(e,t){let n=e.trim();return t.some(o=>o.test(n))}function Wo(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 _(on);let o=rn.join(on,`${e}-${t}.log`),r=JSON.stringify(n)+`
25
- `;await Oo.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 Ko(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 sn(e,t){let n=m.audit,o=Wo(n.whitelistPatterns);return r=>{r.on("tool_call",async(s,l)=>{let{toolName:a,toolCallId:c,input:d}=s,i={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:a,toolCallId:c,input:d,riskLevel:"none",analysis:"",action:"passed"};if(jo.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(!Lo.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=d.command??"";if(Bo(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 u=await Uo(t.model,t.apiKey,a,d);if(i.riskLevel=u.riskLevel,i.analysis=u.reason,u.riskLevel==="none"||u.riskLevel==="low"){i.action="passed",await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} risk=${u.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${a} id=${c} reason=${u.reason}`);try{let g=Ko(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 p=g instanceof Error?g.message:String(g);return i.action="blocked",i.analysis=`${u.reason} (confirmation failed: ${p})`,await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (${p})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${p}`}}})}}var jo,Lo,No,on,an=N(()=>{"use strict";K();X();jo=new Set(["read","ls","find","grep"]),Lo=new Set(["bash"]),No=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
24
+ ${n}`}function Ho(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:Ko,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:oe(c),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let u=await Re(c,n.method,n.params??{},{timeoutMs:en(void 0),maxBytes:tn(void 0),signal:s});return{content:[{type:"text",text:Wo(c,{server:c.name,type:c.type,target:oe(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:oe(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:oe(c),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function Vo(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:Jo,execute:async(n,o)=>{let r=nn(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 on(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 Go(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:qo,execute:async(n,o)=>{let r=nn(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 on(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 rn(e){let t=[Bo()];return e?.telegram&&(t.push(Vo(e.telegram)),t.push(Go(e.telegram))),Ce(m.agentDir).length>0&&t.push(Ho(()=>he(m.agentDir))),t}var Oo,jo,Uo,Ko,Jo,qo,sn=L(()=>{"use strict";J();Te();X();Oo=2e5,jo=6e4;Uo=S.Object({url:S.String({description:"HTTP or HTTPS URL"}),method:S.Optional(S.String({description:"HTTP method (default: GET)"})),headers:S.Optional(S.Array(S.Object({name:S.String({description:"Header name"}),value:S.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:S.Optional(S.String({description:"Request body (string)"})),timeoutMs:S.Optional(S.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:S.Optional(S.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});Ko=S.Object({server:S.Optional(S.String({description:"MCP server name"})),method:S.String({description:"MCP method name"}),params:S.Optional(S.Any({description:"MCP params payload"}))});Jo=S.Object({path:S.String({description:"Image file path (relative to workspace or uploads)."}),caption:S.Optional(S.String({description:"Caption text (plain text)."}))}),qo=S.Object({path:S.String({description:"File path (relative to workspace or uploads)."}),caption:S.Optional(S.String({description:"Caption text (plain text)."}))})});import ln from"node:fs/promises";import dn from"node:path";function un(e){return dn.join(m.sessionDir,`${e}.json`)}function an(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function Ze(e,t){let n=an(e),o=an(t);return dn.join(m.sessionDir,`${n}-${o}.jsonl`)}async function de(e,t){let n=Ze(e,t);try{await ln.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function cn(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 Oe(e){await A(m.sessionDir);let t=De.get(e);if(t)return t;let n=un(e);try{let o=await ln.readFile(n,"utf8"),r=JSON.parse(o),s=cn(e,r);return De.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=cn(e,{});return De.set(e,r),r}throw o}}async function O(e){await A(m.sessionDir);let t=un(e.chatId);await vt(t,e),De.set(e.chatId,e)}function et(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function tt(e){return[]}function je(e,t){if(Object.keys(e.sessions).length>=m.maxSessions)throw new Error("Max sessions reached");let o=pe(),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 mn(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function re(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function nt(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function gn(e){e.messages=[],e.updatedAt=z()}function ot(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=z()}function fn(e,t){e.workspaceDir=t}var De,rt=L(()=>{"use strict";J();X();De=new Map});import Yo from"node:fs/promises";import yn from"node:path";import{completeSimple as Xo}from"@mariozechner/pi-ai";function tr(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return er.replace("{{command}}",n)}function nr(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 or(e,t,n,o){let r=tr(n,o);try{let l=(await Xo(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 nr(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 rr(e,t){let n=e.trim();return t.some(o=>o.test(n))}function sr(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 A(pn);let o=yn.join(pn,`${e}-${t}.log`),r=JSON.stringify(n)+`
25
+ `;await Yo.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 ir(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 hn(e,t){let n=m.audit,o=sr(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(Qo.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(!Zo.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(rr(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 or(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=ir(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 p=g instanceof Error?g.message:String(g);return i.action="blocked",i.analysis=`${d.reason} (confirmation failed: ${p})`,await Z(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${c} action=blocked (${p})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${p}`}}})}}var Qo,Zo,er,pn,wn=L(()=>{"use strict";J();X();Qo=new Set(["read","ls","find","grep"]),Zo=new Set(["bash"]),er=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
27
27
 
28
28
  Command: {{command}}
29
29
 
@@ -33,30 +33,30 @@ Risk levels:
33
33
  - "critical": High risk (secrets exposure, destructive ops, network attacks, privilege escalation)
34
34
 
35
35
  Reply format (ONLY this JSON, nothing else):
36
- {"riskLevel":"none|low|critical","reason":"brief explanation"}`;on=rn.join(m.sessionDir,"audit-logs")});import{createAgentSession as Ho,AuthStorage as Jo,ModelRegistry as qo,SessionManager as Go,SettingsManager as Vo,DefaultResourceLoader as Yo}from"@mariozechner/pi-coding-agent";import Oe from"node:fs/promises";import Ie from"node:path";function cn(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Qo(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 Zo(e,t){return e!=="openai-codex"?t:Xo[t]??t}function er(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 tr(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=cn(t?.provider||m.modelProvider||"openai-codex"),s=n||o?"":m.modelRef||"",{provider:l,modelId:a}=Qo(s,r),c=t?.provider?r:cn(l),d=o?t?.modelId?.trim()||"":a;if(!d){let g=er(e,c);return g?{model:g,provider:c,modelId:g.id}:{model:void 0,provider:c,modelId:""}}let i=Zo(c,d);return{model:e.find(c,i),provider:c,modelId:i}}function nr(e){let t=Q();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function or(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(`
36
+ {"riskLevel":"none|low|critical","reason":"brief explanation"}`;pn=yn.join(m.sessionDir,"audit-logs")});import{createAgentSession as ar,AuthStorage as cr,ModelRegistry as lr,SessionManager as dr,SettingsManager as ur,DefaultResourceLoader as mr}from"@mariozechner/pi-coding-agent";import Ne from"node:fs/promises";import Ie from"node:path";function bn(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function fr(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 pr(e,t){return e!=="openai-codex"?t:gr[t]??t}function yr(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 hr(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=bn(t?.provider||m.modelProvider||"openai-codex"),s=n||o?"":m.modelRef||"",{provider:l,modelId:a}=fr(s,r),c=t?.provider?r:bn(l),u=o?t?.modelId?.trim()||"":a;if(!u){let g=yr(e,c);return g?{model:g,provider:c,modelId:g.id}:{model:void 0,provider:c,modelId:""}}let i=pr(c,u);return{model:e.find(c,i),provider:c,modelId:i}}function wr(e){let t=q();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function br(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
37
 
38
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
39
 
40
- `):""}function rr(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(d=>typeof d=="object"&&d&&"type"in d?String(d.type||"unknown"):typeof d).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 sr(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
40
+ `):""}function xr(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 vr(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
41
41
 
42
- Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function ir(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=or(e[o]);if(r)return r}return""}function ar(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function ln(e){let t=e.workspaceDir||m.workspaceDir;await _(m.sessionDir),await _(m.agentDir),await _(t);let n=qe(e.chatId,e.sessionId),o=Ie.join(m.agentDir,"auth.json"),r=new Jo(o),s=nr(r);s&&console.log(`[tg-agent] codex oauth source=${s.source} expiresAt=${new Date(s.expiresAt).toISOString()}`);let l=Ie.join(m.agentDir,"models.json"),a=new qo(r,l),{model:c,provider:d,modelId:i}=tr(a,{provider:e.modelProvider,modelId:e.modelId});i&&!c&&console.warn(`[tg-agent] model not found: ${d}/${i}`);let u=Go.open(n),g=Vo.create(t,m.agentDir);try{let h=Ie.join(m.agentDir,"skills"),x=Ie.join(t,".pi","skills"),j=await Oe.access(h).then(()=>!0).catch(()=>!1),C=await Oe.access(x).then(()=>!0).catch(()=>!1);if(j){let q=(await Oe.readdir(h,{withFileTypes:!0})).filter(B=>B.isDirectory()).map(B=>B.name);console.log(`[tg-agent] skills directory found at ${h} with ${q.length} skill(s): ${q.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${h}`);if(C){let q=(await Oe.readdir(x,{withFileTypes:!0})).filter(B=>B.isDirectory()).map(B=>B.name);console.log(`[tg-agent] workspace skills directory found at ${x} with ${q.length} skill(s): ${q.join(", ")}`)}let U=g.getSettings?.();if(U){let q=U.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${q}`)}}catch(h){let x=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] skills check failed: ${x}`)}let p="";try{p=await ye(m.agentDir,{timeoutMs:4e3,maxBytes:m.fetchMaxBytes,maxChars:3e3})}catch(h){let x=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] mcp catalog error: ${x}`)}let y=[];if(m.audit.enabled&&e.auditContext){let h={...e.auditContext,sessionId:e.sessionId},x;if(m.audit.modelProvider&&m.audit.modelId){let j=a.find(m.audit.modelProvider,m.audit.modelId);if(j){let C=await r.getApiKey(m.audit.modelProvider);x={provider:m.audit.modelProvider,model:j,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(sn(h,x)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let w=e.systemPrompt?.trim(),k=[];w&&k.push(w),p&&k.push(p);let $=k.length>0?k.join(`
42
+ Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function Mr(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=br(e[o]);if(r)return r}return""}function Sr(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function xn(e){let t=e.workspaceDir||m.workspaceDir;await A(m.sessionDir),await A(m.agentDir),await A(t);let n=Ze(e.chatId,e.sessionId),o=Ie.join(m.agentDir,"auth.json"),r=new cr(o),s=wr(r);s&&console.log(`[tg-agent] codex oauth source=${s.source} expiresAt=${new Date(s.expiresAt).toISOString()}`);let l=Ie.join(m.agentDir,"models.json"),a=new lr(r,l),{model:c,provider:u,modelId:i}=hr(a,{provider:e.modelProvider,modelId:e.modelId});i&&!c&&console.warn(`[tg-agent] model not found: ${u}/${i}`);let d=dr.open(n),g=ur.create(t,m.agentDir);try{let h=Ie.join(m.agentDir,"skills"),v=Ie.join(t,".pi","skills"),I=await Ne.access(h).then(()=>!0).catch(()=>!1),R=await Ne.access(v).then(()=>!0).catch(()=>!1);if(I){let Y=(await Ne.readdir(h,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] skills directory found at ${h} with ${Y.length} skill(s): ${Y.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${h}`);if(R){let Y=(await Ne.readdir(v,{withFileTypes:!0})).filter(K=>K.isDirectory()).map(K=>K.name);console.log(`[tg-agent] workspace skills directory found at ${v} with ${Y.length} skill(s): ${Y.join(", ")}`)}let B=g.getSettings?.();if(B){let Y=B.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${Y}`)}}catch(h){let v=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] skills check failed: ${v}`)}let p="";try{p=await we(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 I=a.find(m.audit.modelProvider,m.audit.modelId);if(I){let R=await r.getApiKey(m.audit.modelProvider);v={provider:m.audit.modelProvider,model:I,apiKey:R??void 0},console.log(`[tg-agent] audit model: ${m.audit.modelProvider}/${m.audit.modelId} apiKey=${R?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${m.audit.modelProvider}/${m.audit.modelId}`)}y.push(hn(h,v)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let w=e.systemPrompt?.trim(),$=[];w&&$.push(w),p&&$.push(p);let _=$.length>0?$.join(`
43
43
 
44
- `):void 0;console.log(`[tg-agent] systemPrompt append=${$?$.slice(0,80)+"...":"(none)"}`);let T=new Yo({cwd:t,agentDir:m.agentDir,settingsManager:g,extensionFactories:y.length>0?y:void 0,appendSystemPrompt:$});await T.reload();let{session:v,modelFallbackMessage:R}=await Ho({cwd:t,agentDir:m.agentDir,authStorage:r,modelRegistry:a,model:c??void 0,sessionManager:u,settingsManager:g,resourceLoader:T,customTools:qt({telegram:e.telegram})});try{let h=v.messages,x=h.some(I=>{let q=I.role,B=I.content;return q==="system"&&typeof B=="string"?B.toLowerCase().includes("compaction")||B.toLowerCase().includes("compact"):I.type==="compaction"||I.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof u}`),console.log(`[tg-agent] session messages count: ${h.length}`),console.log(`[tg-agent] compacting support detected: ${x||"unknown (will be detected during runtime)"}`);let C=typeof u.compact=="function",U=typeof u.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${C}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${U}`)}catch(h){let x=h instanceof Error?h.message:String(h);console.warn(`[tg-agent] compacting check failed: ${x}`)}R&&console.warn(`[tg-agent] modelFallback=${R}`);let J=!1,b=()=>{J=!0,v.abort()};e.onAbortReady?.(b);let S=m.logAgentEvents,P=m.logAgentStream,Y=new Map,it=v.subscribe(h=>{switch(h.type){case"agent_start":S&&console.log(`[tg-agent] agent start session=${e.sessionId}`),L=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":S&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":S&&console.log(`[tg-agent] turn start session=${e.sessionId}`),L=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":S&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${h.toolResults.length}`),L=Date.now(),e.onStatus?.({type:"turn_end",toolResults:h.toolResults.length});break;case"message_start":{if(S){let x=h.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${x}`)}L=Date.now();{let x=h.message.role??"unknown";e.onStatus?.({type:"message_start",role:x})}break}case"message_end":{if(S){let x=h.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${x}`)}L=Date.now();{let x=h.message.role??"unknown";e.onStatus?.({type:"message_end",role:x})}break}case"message_update":{if(!P)break;if(h.assistantMessageEvent.type==="text_delta"){let j=(h.assistantMessageEvent.delta??"").length;j>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${j}`),L=Date.now()}h.assistantMessageEvent.type==="thinking_delta"&&(L=Date.now());break}case"tool_execution_start":{Y.set(h.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${h.toolName} id=${h.toolCallId}`),Se+=1,L=Date.now(),e.onStatus?.({type:"tool_start",name:h.toolName,id:h.toolCallId,args:h.args});break}case"tool_execution_end":{let x=Y.get(h.toolCallId),j=x?Date.now()-x:0;console.log(`[tg-agent] tool end name=${h.toolName} id=${h.toolCallId} ok=${!h.isError} durationMs=${j}`),Y.delete(h.toolCallId),Se=Math.max(0,Se-1),L=Date.now(),e.onStatus?.({type:"tool_end",name:h.toolName,id:h.toolCallId,ok:!h.isError,durationMs:j});break}case"auto_compaction_start":{let x=h.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${x}`),L=Date.now();break}case"auto_compaction_end":{let x=h.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${x}`),L=Date.now();break}default:break}}),te=null,ue=null,xe=!1,at=0,ct=!1,L=Date.now(),Se=0;try{let h=Date.now();te=setInterval(()=>{let C=Date.now()-h;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${C} streaming=${v.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:C,streaming:v.isStreaming})},15e3),ue=setInterval(()=>{if(xe||Se>0)return;let C=Date.now()-L,U=v.isStreaming?m.modelTimeoutStreamingMs:m.modelTimeoutMs,I=Math.max(1e3,U);C>=I&&(xe=!0,at=I,ct=v.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${C}`),v.abort())},2e3);try{if(await v.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),xe)throw new Error(`Model request timed out after ${m.modelTimeoutMs}ms`)}catch(C){if(J)throw new Error("Cancelled by user.");if(xe){let U=ct?" (streaming)":"",I=at||m.modelTimeoutMs;throw new Error(`Model request timed out after ${I}ms${U}`)}throw C}te&&clearInterval(te);let x=ar(v.messages);if(x){let C=x?.stopReason,U=x?.errorMessage;if(C==="error"){let I=U?sr(U):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${I}`),new Error(I)}}let j=ir(v.messages,v);if(!j){let C=rr(v.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${C}`),new Error("No assistant response.")}return{text:j,sessionFile:n,sessionId:v.sessionId,modelProvider:v.model?.provider??d,modelId:v.model?.id??i,modelFallbackMessage:R}}finally{te&&clearInterval(te),ue&&clearInterval(ue),it(),u.flushPendingToolResults?.(),v.dispose()}}var Xo,un=N(()=>{"use strict";K();fe();Gt();Ce();X();Qe();an();Xo={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import Ze from"node:fs/promises";import Le from"node:path";import{AuthStorage as cr,ModelRegistry as lr}from"@mariozechner/pi-coding-agent";import{completeSimple as ur,getModel as dr}from"@mariozechner/pi-ai";function gr(){return m.memory.systemPrompt||mr}function pr(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function yr(e,t){return e!=="openai-codex"?t:fr[t]??t}async function hr(e,t){await _(m.agentDir);let n=Le.join(m.agentDir,"auth.json"),o=new cr(n),r=Q();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let s=Le.join(m.agentDir,"models.json"),l=new lr(o,s),a=async(u,g,p)=>{let y=pr(u),w=yr(y,g),k=l.find(y,w);if(!k)try{k=dr(y,w)}catch{}if(k){let $=await o.getApiKey(y);return{model:k,provider:y,modelId:w,apiKey:$??void 0,source:p}}return null};if(e&&t){let u=await a(e,t,"session");if(u)return console.log(`[memory] using session model: ${u.provider}/${u.modelId}`),u}if(m.memory.modelProvider&&m.memory.modelId){let u=await a(m.memory.modelProvider,m.memory.modelId,"memory-config");if(u)return console.log(`[memory] using configured memory model: ${u.provider}/${u.modelId}`),u;console.warn(`[memory] configured memory model not found: ${m.memory.modelProvider}/${m.memory.modelId}`)}let c=m.modelProvider,d=m.modelRef.includes("/")?m.modelRef.split("/")[1]:m.modelRef;if(c&&d){let u=await a(c,d,"system-default");if(u)return console.log(`[memory] using system default model: ${u.provider}/${u.modelId}`),u}let i=l.getAll();if(i.length>0){let u=i[0],g=await o.getApiKey(u.provider);return console.log(`[memory] using first available model: ${u.provider}/${u.id}`),{model:u,provider:u.provider,modelId:u.id,apiKey:g??void 0,source:"first-available"}}return console.warn("[memory] no model available for reflection"),null}async function Ne(e,t,n){if(!m.memory.enabled)return{success:!0,reflected:!1};if(e.messages.length===0)return{success:!0,reflected:!1};let o=new Date,r=o.toISOString().split("T")[0],s=e.title.replace(/[^a-zA-Z0-9_-]/g,"_"),l=`${r}-${e.id}-${s}.md`,a=Le.join(je,l),c=e.messages.map(i=>`[${i.role.toUpperCase()}]: ${i.content}`).join(`
44
+ `):void 0;console.log(`[tg-agent] systemPrompt append=${_?_.slice(0,80)+"...":"(none)"}`);let j=new mr({cwd:t,agentDir:m.agentDir,settingsManager:g,extensionFactories:y.length>0?y:void 0,appendSystemPrompt:_});await j.reload();let{session:x,modelFallbackMessage:C}=await ar({cwd:t,agentDir:m.agentDir,authStorage:r,modelRegistry:a,model:c??void 0,sessionManager:d,settingsManager:g,resourceLoader:j,customTools:rn({telegram:e.telegram})});try{let h=x.messages,v=h.some(N=>{let Y=N.role,K=N.content;return Y==="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 R=typeof d.compact=="function",B=typeof d.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${R}`),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}`)}C&&console.warn(`[tg-agent] modelFallback=${C}`);let ie=!1,M=()=>{ie=!0,x.abort()};e.onAbortReady?.(M);let b=m.logAgentEvents,k=m.logAgentStream,D=new Map,ht=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(!k)break;if(h.assistantMessageEvent.type==="text_delta"){let I=(h.assistantMessageEvent.delta??"").length;I>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${I}`),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}`),$e+=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),I=v?Date.now()-v:0;console.log(`[tg-agent] tool end name=${h.toolName} id=${h.toolCallId} ok=${!h.isError} durationMs=${I}`),D.delete(h.toolCallId),$e=Math.max(0,$e-1),F=Date.now(),e.onStatus?.({type:"tool_end",name:h.toolName,id:h.toolCallId,ok:!h.isError,durationMs:I});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}}),ne=null,fe=null,Se=!1,wt=0,bt=!1,F=Date.now(),$e=0;try{let h=Date.now();ne=setInterval(()=>{let R=Date.now()-h;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${R} streaming=${x.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:R,streaming:x.isStreaming})},15e3),fe=setInterval(()=>{if(Se||$e>0)return;let R=Date.now()-F,B=x.isStreaming?m.modelTimeoutStreamingMs:m.modelTimeoutMs,N=Math.max(1e3,B);R>=N&&(Se=!0,wt=N,bt=x.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${R}`),x.abort())},2e3);try{if(await x.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),Se)throw new Error(`Model request timed out after ${m.modelTimeoutMs}ms`)}catch(R){if(ie)throw new Error("Cancelled by user.");if(Se){let B=bt?" (streaming)":"",N=wt||m.modelTimeoutMs;throw new Error(`Model request timed out after ${N}ms${B}`)}throw R}ne&&clearInterval(ne);let v=Sr(x.messages);if(v){let R=v?.stopReason,B=v?.errorMessage;if(R==="error"){let N=B?vr(B):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${N}`),new Error(N)}}let I=Mr(x.messages,x);if(!I){let R=xr(x.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${R}`),new Error("No assistant response.")}return{text:I,sessionFile:n,sessionId:x.sessionId,modelProvider:x.model?.provider??u,modelId:x.model?.id??i,modelFallbackMessage:C}}finally{ne&&clearInterval(ne),fe&&clearInterval(fe),ht(),d.flushPendingToolResults?.(),x.dispose()}}var gr,vn=L(()=>{"use strict";J();ce();sn();Te();X();rt();wn();gr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import it from"node:fs/promises";import ze from"node:path";import*as Mn from"@lancedb/lancedb";import st from"openai";function kr(){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 st(n),console.log(`[memory-rag] using dedicated embedding API key${e.embeddingBaseUrl?` (baseURL: ${e.embeddingBaseUrl})`:""}`),ee}if(m.openaiApiKey)return ee=new st({apiKey:m.openaiApiKey}),console.log("[memory-rag] using OpenAI API key from config"),ee;let t=q();if(t)return ee=new st({apiKey:t.accessToken}),console.log("[memory-rag] using Codex OAuth token for embeddings"),ee;throw new Error("No API key available for embeddings. Set memory.rag.embedding_api_key, model.openai_api_key, or run `codex login`.")}async function ct(e){let t=kr(),n=m.memory.rag.embeddingModel;console.log(`[memory-rag] requesting embedding for ${e.length} chars using model=${n}`);let o=3e4,r=new Promise((s,l)=>{setTimeout(()=>l(new Error(`Embedding request timeout after ${o}ms`)),o)});try{let s=await Promise.race([t.embeddings.create({model:n,input:e,encoding_format:"float"}),r]);if(!s)throw new Error("Empty response from embedding API");if(!s.data)throw new Error(`Unexpected response structure: ${JSON.stringify(s).slice(0,200)}`);if(!Array.isArray(s.data)||s.data.length===0)throw new Error(`Empty data array in response: ${JSON.stringify(s).slice(0,200)}`);if(!s.data[0].embedding)throw new Error(`No embedding in response: ${JSON.stringify(s.data[0]).slice(0,200)}`);let l=s.data[0].embedding;return console.log(`[memory-rag] received embedding with ${l.length} dimensions`),l}catch(s){if(s instanceof Error){if(console.error(`[memory-rag] embedding error: ${s.message}`),"response"in s){let l=s.response;console.error(`[memory-rag] response status: ${l?.status}, body: ${JSON.stringify(l?.data)?.slice(0,500)}`)}"status"in s&&console.error(`[memory-rag] HTTP status: ${s.status}`)}throw s}}async function Ue(){return Fe||(await A(at),Fe=await Mn.connect(at),Fe)}async function Sn(e,t,n,o,r){if(!m.memory.rag.enabled){console.log("[memory-rag] RAG disabled, skipping indexing");return}console.log(`[memory-rag] indexing session ${e}, reflection length=${o.length}`);try{let s=await Ue(),l=await s.tableNames();console.log(`[memory-rag] existing tables: ${l.join(", ")||"(none)"}`);let a=await ct(o);console.log(`[memory-rag] embedding generated, vector length=${a.length}`);let c={sessionId:e,date:t,title:n,content:o,filePath:r,vector:a,timestamp:Date.now()},u;l.includes(V)?(u=await s.openTable(V),await u.add([c]),console.log("[memory-rag] added to existing table")):(u=await s.createTable(V,[c]),console.log("[memory-rag] created new table with first record")),console.log(`[memory-rag] successfully indexed session ${e}`)}catch(s){let l=s instanceof Error?s.message:String(s),a=s instanceof Error?s.stack:void 0;console.error(`[memory-rag] failed to index session ${e}: ${l}`),a&&console.error(`[memory-rag] stack: ${a}`)}}async function $n(e,t=m.memory.rag.maxResults,n=m.memory.rag.similarityThreshold){if(!m.memory.rag.enabled)return[];console.log(`[memory-rag] searching memories for query: "${e.slice(0,50)}..."`);try{let o=await Ue();if(!(await o.tableNames()).includes(V))return console.log("[memory-rag] no reflections table yet, skipping search"),[];let s=await o.openTable(V),l=await s.countRows();console.log(`[memory-rag] table has ${l} rows`);let a=await ct(e),c=await s.vectorSearch(a).column($r).limit(t*2).toArray();if(console.log(`[memory-rag] vectorSearch 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=>({sessionId:d.sessionId,date:d.date,title:d.title,content:d.content,filePath:d.filePath,timestamp:d.timestamp,_distance:d._distance}));return console.log(`[memory-rag] after filtering: ${i.length} memories`),i.length>0?(console.log(`[memory-rag] found ${i.length} relevant memories (threshold=${n})`),i.forEach((d,g)=>{console.log(`[memory-rag] ${g+1}. "${d.title}" (dist=${d._distance?.toFixed(4)??"N/A"})`)})):console.log("[memory-rag] no memories passed the threshold filter"),i}catch(o){let r=o instanceof Error?o.message:String(o),s=o instanceof Error?o.stack:void 0;return console.warn(`[memory-rag] search failed: ${r}`),s&&console.warn(`[memory-rag] stack: ${s}`),[]}}async function _r(e){try{let t=await it.readFile(e,"utf8"),n=ze.basename(e),o=n.match(/^(\d{4}-\d{2}-\d{2})-([a-f0-9]+)-(.+)\.md$/);if(!o)return console.warn(`[reindex] \u65E0\u6CD5\u89E3\u6790\u6587\u4EF6\u540D\u683C\u5F0F: ${n}`),null;let[,r,s,l]=o,a=l.replace(/_/g," "),c=t.match(/## Reflection\s*\n([\s\S]*?)(?=\n## Original Transcript|\n## |\Z)/);if(!c||!c[1]?.trim())return console.warn(`[reindex] \u6587\u4EF6\u4E2D\u6CA1\u6709\u627E\u5230 Reflection \u90E8\u5206: ${n}`),null;let u=c[1].trim();return u==="No reflection generated."||u.toLowerCase().includes("reflection failed")?(console.warn(`[reindex] Reflection \u65E0\u6548\uFF0C\u8DF3\u8FC7: ${n}`),null):{sessionId:s,date:r,title:a,reflection:u}}catch(t){let n=t instanceof Error?t.message:String(t);return console.error(`[reindex] \u8BFB\u53D6\u6587\u4EF6\u5931\u8D25 ${e}: ${n}`),null}}async function kn(e){let t={success:!1,totalFiles:0,indexedCount:0,skippedCount:0,errorCount:0,errors:[],embeddingModel:m.memory.rag.embeddingModel,vectorDimension:null};console.log("[reindex] ========================================"),console.log("[reindex] \u5F00\u59CB\u91CD\u65B0\u7D22\u5F15\u6240\u6709\u5386\u53F2\u8BB0\u5FC6"),console.log(`[reindex] Embedding \u6A21\u578B: ${m.memory.rag.embeddingModel}`),console.log(`[reindex] \u8BB0\u5FC6\u76EE\u5F55: ${Le}`),console.log(`[reindex] \u5411\u91CF\u6570\u636E\u5E93\u76EE\u5F55: ${at}`),console.log("[reindex] ========================================");try{try{await it.access(Le)}catch{return console.log("[reindex] \u8BB0\u5FC6\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u65E0\u9700\u7D22\u5F15"),t.success=!0,t}let o=(await it.readdir(Le)).filter(c=>c.endsWith(".md"));if(t.totalFiles=o.length,o.length===0)return console.log("[reindex] \u6CA1\u6709\u627E\u5230\u4EFB\u4F55\u8BB0\u5FC6\u6587\u4EF6"),t.success=!0,t;console.log(`[reindex] \u627E\u5230 ${o.length} \u4E2A\u8BB0\u5FC6\u6587\u4EF6`),e?.(0,o.length,"\u626B\u63CF\u5B8C\u6210\uFF0C\u51C6\u5907\u7D22\u5F15...");let r=[];for(let c of o){let u=ze.join(Le,c),i=await _r(u);i?r.push({...i,filePath:u}):t.skippedCount++}if(r.length===0)return console.log("[reindex] \u6CA1\u6709\u6709\u6548\u7684\u8BB0\u5FC6\u53EF\u4EE5\u7D22\u5F15"),t.success=!0,t;console.log(`[reindex] \u89E3\u6790\u6210\u529F ${r.length} \u4E2A\uFF0C\u8DF3\u8FC7 ${t.skippedCount} \u4E2A`),console.log("[reindex] \u6B63\u5728\u5220\u9664\u65E7\u7684\u5411\u91CF\u7D22\u5F15...");let s=await Ue();(await s.tableNames()).includes(V)&&(await s.dropTable(V),console.log("[reindex] \u65E7\u7684\u5411\u91CF\u7D22\u5F15\u5DF2\u5220\u9664")),console.log("[reindex] \u5F00\u59CB\u751F\u6210\u65B0\u7684\u5411\u91CF\u7D22\u5F15...");let a=null;for(let c=0;c<r.length;c++){let u=r[c],i=`[${c+1}/${r.length}]`;try{e?.(c+1,r.length,`\u6B63\u5728\u7D22\u5F15: ${u.title}`),console.log(`[reindex] ${i} \u6B63\u5728\u5904\u7406: ${u.sessionId} - ${u.title}`);let d=await ct(u.reflection);t.vectorDimension===null&&(t.vectorDimension=d.length,console.log(`[reindex] \u5411\u91CF\u7EF4\u5EA6: ${d.length}`));let g={sessionId:u.sessionId,date:u.date,title:u.title,content:u.reflection,filePath:u.filePath,vector:d,timestamp:Date.now()};a===null?(a=await s.createTable(V,[g]),console.log(`[reindex] ${i} \u521B\u5EFA\u65B0\u8868\u5E76\u6DFB\u52A0\u7B2C\u4E00\u6761\u8BB0\u5F55`)):(await a.add([g]),console.log(`[reindex] ${i} \u6DFB\u52A0\u8BB0\u5F55\u6210\u529F`)),t.indexedCount++}catch(d){let g=d instanceof Error?d.message:String(d);console.error(`[reindex] ${i} \u7D22\u5F15\u5931\u8D25: ${g}`),t.errors.push(`${u.sessionId}: ${g}`),t.errorCount++}c<r.length-1&&await new Promise(d=>setTimeout(d,200))}return console.log("[reindex] ========================================"),console.log("[reindex] \u91CD\u65B0\u7D22\u5F15\u5B8C\u6210\uFF01"),console.log(`[reindex] \u603B\u6587\u4EF6\u6570: ${t.totalFiles}`),console.log(`[reindex] \u6210\u529F\u7D22\u5F15: ${t.indexedCount}`),console.log(`[reindex] \u8DF3\u8FC7: ${t.skippedCount}`),console.log(`[reindex] \u9519\u8BEF: ${t.errorCount}`),console.log(`[reindex] \u5411\u91CF\u7EF4\u5EA6: ${t.vectorDimension}`),console.log("[reindex] ========================================"),t.success=!0,t}catch(n){let o=n instanceof Error?n.message:String(n);return console.error(`[reindex] \u91CD\u65B0\u7D22\u5F15\u5931\u8D25: ${o}`),t.errors.push(o),t}}async function _n(){try{let e=await Ue();return(await e.tableNames()).includes(V)?{exists:!0,rowCount:await(await e.openTable(V)).countRows(),embeddingModel:m.memory.rag.embeddingModel}:{exists:!1,rowCount:0,embeddingModel:m.memory.rag.embeddingModel}}catch{return{exists:!1,rowCount:0,embeddingModel:m.memory.rag.embeddingModel}}}var at,Le,V,$r,Fe,ee,lt=L(()=>{"use strict";J();X();ce();at=ze.join(m.agentDir,"tg-memory-vectors"),Le=ze.join(m.agentDir,"tg-memory"),V="reflections",$r="vector",Fe=null,ee=null});import dt from"node:fs/promises";import Ke from"node:path";import{AuthStorage as Ar,ModelRegistry as Pr}from"@mariozechner/pi-coding-agent";import{completeSimple as Cr,getModel as Rr}from"@mariozechner/pi-ai";function Er(){return m.memory.systemPrompt||Tr}function Or(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function jr(e,t){return e!=="openai-codex"?t:Dr[t]??t}async function Nr(e,t){await A(m.agentDir);let n=Ke.join(m.agentDir,"auth.json"),o=new Ar(n),r=q();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let s=Ke.join(m.agentDir,"models.json"),l=new Pr(o,s),a=async(d,g,p)=>{let y=Or(d),w=jr(y,g),$=l.find(y,w);if(!$)try{$=Rr(y,w)}catch{}if($){let _=await o.getApiKey(y);return{model:$,provider:y,modelId:w,apiKey:_??void 0,source:p}}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;console.warn(`[memory] configured memory model not found: ${m.memory.modelProvider}/${m.memory.modelId}`)}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}async function We(e,t,n){if(!m.memory.enabled)return{success:!0,reflected:!1};if(e.messages.length===0)return{success:!0,reflected:!1};let o=new Date,r=o.toISOString().split("T")[0],s=e.title.replace(/[^a-zA-Z0-9_-]/g,"_"),l=`${r}-${e.id}-${s}.md`,a=Ke.join(Be,l),c=e.messages.map(i=>`[${i.role.toUpperCase()}]: ${i.content}`).join(`
45
45
 
46
- `),d=await hr(t,n);if(!d){console.log(`[memory] no model available, saving raw transcript to ${a}`);let i=[`# Memory Archive (No Model): ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,"**Note**: No model available for reflection",`
46
+ `),u=await Nr(t,n);if(!u){console.log(`[memory] no model available, saving raw transcript to ${a}`);let i=[`# Memory Archive (No Model): ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,"**Note**: No model available for reflection",`
47
47
  ## Original Transcript`,c].join(`
48
- `);return await _(je),await Ze.writeFile(a,i,"utf8"),{success:!0,reflected:!1,filePath:a}}console.log(`[memory] reflecting on session ${e.id} using ${d.provider}/${d.modelId}`);try{let u=`${gr()}
48
+ `);return await A(Be),await dt.writeFile(a,i,"utf8"),{success:!0,reflected:!1,filePath:a}}console.log(`[memory] reflecting on session ${e.id} using ${u.provider}/${u.modelId}`);try{let d=`${Er()}
49
49
 
50
50
  ---
51
51
 
52
52
  Here is the conversation transcript:
53
53
 
54
- ${c}`,p=(await ur(d.model,{messages:[{role:"user",content:u,timestamp:Date.now()}]},{apiKey:d.apiKey,maxTokens:2e3,temperature:.7})).content.find(k=>k.type==="text"),y=p?.type==="text"?p.text:"No reflection generated.",w=[`# Memory Archive: ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,`**Model**: ${d.provider}/${d.modelId} (${d.source})`,`
54
+ ${c}`,p=(await Cr(u.model,{messages:[{role:"user",content:d,timestamp:Date.now()}]},{apiKey:u.apiKey,maxTokens:2e3,temperature:.7})).content.find($=>$.type==="text"),y=p?.type==="text"?p.text:"No reflection generated.",w=[`# Memory Archive: ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,`**Model**: ${u.provider}/${u.modelId} (${u.source})`,`
55
55
  ## Reflection`,y,`
56
56
  ## Original Transcript`,c].join(`
57
- `);return await _(je),await Ze.writeFile(a,w,"utf8"),console.log(`[memory] archived memory to ${a}`),{success:!0,reflected:!0,filePath:a}}catch(i){let u=i instanceof Error?i.message:String(i);console.error(`[memory] reflection failed: ${u}`);let g=[`# Memory Archive (Reflection Failed): ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,`**Model**: ${d.provider}/${d.modelId} (${d.source})`,`**Error**: ${u}`,`
57
+ `);return await A(Be),await dt.writeFile(a,w,"utf8"),console.log(`[memory] archived memory to ${a}`),y&&y!=="No reflection generated."&&Sn(e.id,r,e.title,y,a).catch($=>console.warn(`[memory] indexing background failed: ${$}`)),{success:!0,reflected:!0,filePath:a}}catch(i){let d=i instanceof Error?i.message:String(i);console.error(`[memory] reflection failed: ${d}`);let g=[`# Memory Archive (Reflection Failed): ${e.title}`,`**Date**: ${o.toISOString()}`,`**Session ID**: ${e.id}`,`**Model**: ${u.provider}/${u.modelId} (${u.source})`,`**Error**: ${d}`,`
58
58
  ## Original Transcript`,c].join(`
59
- `);return await _(je),await Ze.writeFile(a,g,"utf8"),{success:!0,reflected:!1,filePath:a,error:u}}}var je,mr,fr,dn=N(()=>{"use strict";K();X();fe();je=Le.join(m.agentDir,"tg-memory"),mr=`You are summarizing a conversation session that is about to be closed.
59
+ `);return await A(Be),await dt.writeFile(a,g,"utf8"),{success:!0,reflected:!1,filePath:a,error:d}}}var Be,Tr,Dr,An=L(()=>{"use strict";J();X();ce();lt();Be=Ke.join(m.agentDir,"tg-memory"),Tr=`You are summarizing a conversation session that is about to be closed.
60
60
  Your task is to extract and preserve important information from this conversation.
61
61
 
62
62
  Output your summary in Markdown format. Focus on:
@@ -66,23 +66,35 @@ Output your summary in Markdown format. Focus on:
66
66
  4. **Important Details**: Names, dates, numbers, links, or technical details worth remembering.
67
67
  5. **Context**: Background information that might be useful for future conversations.
68
68
 
69
- Be concise and factual. Prioritize information that would be valuable to recall later.`;fr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var ds={};import le from"node:path";import mn from"node:fs/promises";import wr from"node-telegram-bot-api";import{AuthStorage as br,ModelRegistry as vr}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as xr}from"@mariozechner/pi-ai";function Mr(e,t){ve.set(e,t)}function ot(e){ve.delete(e)}function kr(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 _r(){return le.join(m.agentDir,"uploads")}function Ar(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 Pr(e){return!!e?.startsWith("image/")}function Cr(e){switch(le.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 Tr(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 Rr(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(Tr(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
70
- `)}function Er(e){let t=[];if(e.photo&&e.photo.length>0){let n=Ar(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 Dr(e){if(e.length===0)return{resolved:[],images:[]};let t=_r();await _(t);let n=[],o=[];for(let r of e)try{let s=await O.downloadFile(r.fileId,t),l=await mn.stat(s),a=r.fileName??le.basename(s),c=r.mimeType??Cr(s),d=r.kind==="photo"||Pr(c),i={path:s,name:a,mimeType:c,bytes:l.size,isImage:d};if(n.push(i),d){let u=await mn.readFile(s);o.push({type:"image",data:u.toString("base64"),mimeType:c??$r})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function he(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 Ir(e){if(he(e,"*")%2!==0||he(e,"_")%2!==0||he(e,"`")%2!==0)return!1;let r=he(e,"["),s=he(e,"]");return r===s}function jr(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Or.has(n))return!1}return!0}function vn(e){let t=kr(m.telegramParseMode);return t?[t]:jr(e)?["MarkdownV2","Markdown"]:Ir(e)?["Markdown"]:[]}function be(e,t){let n=we.get(e);return n?(clearTimeout(n.timeoutId),we.delete(e),n.messageId&&O.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function gn(e,t,n,o,r){if(we.has(e))throw new Error("Audit confirmation already pending.");let s=Tn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await Rn(t,n,s,r);return await new Promise((a,c)=>{let d=setTimeout(()=>{we.delete(e),O.editMessageText(`${n}
69
+ Be concise and factual. Prioritize information that would be valuable to recall later.`;Dr={"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 ge from"node:path";import Pn from"node:fs/promises";import Ir from"node-telegram-bot-api";import{AuthStorage as Lr,ModelRegistry as Fr}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as zr}from"@mariozechner/pi-ai";function Br(e,t){Me.set(e,t)}function ft(e){Me.delete(e)}function Kr(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 Hr(){return ge.join(m.agentDir,"uploads")}function Jr(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 qr(e){return!!e?.startsWith("image/")}function Vr(e){switch(ge.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 Yr(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(`
70
+ `)}function Xr(e){let t=[];if(e.photo&&e.photo.length>0){let n=Jr(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 Qr(e){if(e.length===0)return{resolved:[],images:[]};let t=Hr();await A(t);let n=[],o=[];for(let r of e)try{let s=await E.downloadFile(r.fileId,t),l=await Pn.stat(s),a=r.fileName??ge.basename(s),c=r.mimeType??Vr(s),u=r.kind==="photo"||qr(c),i={path:s,name:a,mimeType:c,bytes:l.size,isImage:u};if(n.push(i),u){let d=await Pn.readFile(s);o.push({type:"image",data:d.toString("base64"),mimeType:c??Wr})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function be(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 es(e){if(be(e,"*")%2!==0||be(e,"_")%2!==0||be(e,"`")%2!==0)return!1;let r=be(e,"["),s=be(e,"]");return r===s}function ts(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Zr.has(n))return!1}return!0}function Nn(e){let t=Kr(m.telegramParseMode);return t?[t]:ts(e)?["MarkdownV2","Markdown"]:es(e)?["Markdown"]:[]}function ve(e,t){let n=xe.get(e);return n?(clearTimeout(n.timeoutId),xe.delete(e),n.messageId&&E.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function Cn(e,t,n,o,r){if(xe.has(e))throw new Error("Audit confirmation already pending.");let s=Jn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await qn(t,n,s,r);return await new Promise((a,c)=>{let u=setTimeout(()=>{xe.delete(e),E.editMessageText(`${n}
71
71
 
72
- [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),c(new Error("Audit confirmation timed out."))},o);we.set(e,{resolve:a,reject:c,timeoutId:d,chatId:t,messageThreadId:r,messageId:l.message_id})})}function ce(e){let t=e.trim().toLowerCase();return Nr.get(t)??t}function zr(e,t){return e!=="openai-codex"?t:Fr[t]??t}async function ae(){await _(m.agentDir);let e=le.join(m.agentDir,"auth.json"),t=new br(e),n=Q();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=le.join(m.agentDir,"models.json"),r=new vr(t,o);return{authStorage:t,modelRegistry:r}}function xn(e){let t=ee.get(e);t&&(clearTimeout(t.timeoutId),ee.delete(e))}function Ur(e,t){let n=ee.get(e);n&&(clearTimeout(n.timeoutId),ee.delete(e),n.reject(new Error(t)))}async function fn(e,t,n,o){if(ee.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await f(t,r,o),await new Promise((s,l)=>{let a=setTimeout(()=>{ee.delete(e),l(new Error("Login prompt timed out."))},Lr);ee.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function Sn(e,t,n){let o=ve.get(t);if(!o){await f(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 f(e,"Stopping current request...",n)}async function Mn(e,t,n,o){let r=await Ee(t),s=n||r.activeSessionId;if(!s){await f(e,"No active session to close.",o);return}let l=r.sessions[s];if(l&&l.messages.length>0)try{await f(e,"Reflecting on session memory...",o);let i=await Ne(l,l.modelProvider,l.modelId);i.reflected?await f(e,"Memory archived successfully.",o):i.error?await f(e,`Memory saved (reflection failed: ${i.error})`,o):await f(e,"Memory saved (no reflection).",o)}catch(i){console.warn("[tg-agent] memory archival failed",i),await f(e,`Memory archival failed: ${re(i)}`,o)}let a=ve.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)}ot(t)}if(!Ye(r,s)){await f(e,`Session not found: ${s}`,o);return}await D(r),await ie(t,s).catch(i=>{console.warn(`[tg-agent] delete session file failed id=${s}`,i)});let d=a?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await f(e,d,o)}function Br(){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=Ae(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}=At(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=Ct();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function rt(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=oe(e);return o||(o=De(e,""),await D(e),await f(t,`Created session ${o.id}.`,n)),o}function Kr(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])=>Wr.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 Hr(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 Jr(e,t,n=3){let o=new Set,r=[],s=Ge(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 qr(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:ce(n),modelId:o.trim()}}return{modelId:t}}function kn(e,t){let n=Date.now(),o=yn.get(e)??0;n-o<Gr||(yn.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function $n(e){let t=m.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function Vr(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(`
73
- `)}function ze(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function nt(e,t){if(t.workspaceDir)return t.workspaceDir;let n=m.workspaceMappings.get(e);return n||m.workspaceDir}async function _n(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await O.sendMessage(e,t,r)}async function An(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 O.editMessageText(n,s)}async function Pn(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 Yr(e,t,n){return await Pn(o=>_n(e,t,o,n),vn(t))}async function Xr(e,t,n,o){await Pn(r=>An(e,t,n,r,o),vn(n))}async function f(e,t,n){let o=dt(t,3900);for(let r of o)await Yr(e,r,n)}function Zr(){let e=F()-Cn;for(let[o,r]of H)r.createdAt<e&&H.delete(o);if(H.size<=hn)return;let t=Array.from(H.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=H.size-hn;for(let o=0;o<n;o+=1)H.delete(t[o][0])}function es(e){Zr();let t=de();for(;H.has(t);)t=de();return H.set(t,{command:e,createdAt:F()}),t}function ts(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=H.get(t);return n?F()-n.createdAt>Cn?(H.delete(t),null):n.command:null}function ns(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 Tn(e,t){let n=[],o=[];for(let r of e){let s=es(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 Rn(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await O.sendMessage(e,t,r)}async function wn(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??Qr,l=o?.footer,a=o?.messageThreadId,c=ns(n,s);for(let d=0;d<c.length;d+=1){let i=c[d],u=c.length>1?` (page ${d+1}/${c.length})`:"",g=[`${t}${u}`];l&&g.push(l);let p=Tn(i,r);await Rn(e,g.join(`
74
- `),p,a)}}function tt(e,t=os){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
72
+ [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),c(new Error("Audit confirmation timed out."))},o);xe.set(e,{resolve:a,reject:c,timeoutId:u,chatId:t,messageThreadId:r,messageId:l.message_id})})}function me(e){let t=e.trim().toLowerCase();return os.get(t)??t}function ss(e,t){return e!=="openai-codex"?t:rs[t]??t}async function ue(){await A(m.agentDir);let e=ge.join(m.agentDir,"auth.json"),t=new Lr(e),n=q();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=ge.join(m.agentDir,"models.json"),r=new Fr(t,o);return{authStorage:t,modelRegistry:r}}function In(e){let t=te.get(e);t&&(clearTimeout(t.timeoutId),te.delete(e))}function is(e,t){let n=te.get(e);n&&(clearTimeout(n.timeoutId),te.delete(e),n.reject(new Error(t)))}async function Rn(e,t,n,o){if(te.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await f(t,r,o),await new Promise((s,l)=>{let a=setTimeout(()=>{te.delete(e),l(new Error("Login prompt timed out."))},ns);te.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function Ln(e,t,n){let o=Me.get(t);if(!o){await f(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 f(e,"Stopping current request...",n)}async function Fn(e,t,n,o){let r=await Oe(t),s=n||r.activeSessionId;if(!s){await f(e,"No active session to close.",o);return}let l=r.sessions[s];if(l&&l.messages.length>0)try{await f(e,"Reflecting on session memory...",o);let i=await We(l,l.modelProvider,l.modelId);i.reflected?await f(e,"Memory archived successfully.",o):i.error?await f(e,`Memory saved (reflection failed: ${i.error})`,o):await f(e,"Memory saved (no reflection).",o)}catch(i){console.warn("[tg-agent] memory archival failed",i),await f(e,`Memory archival failed: ${se(i)}`,o)}let a=Me.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)}ft(t)}if(!nt(r,s)){await f(e,`Session not found: ${s}`,o);return}await O(r),await de(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 f(e,u,o)}function as(){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=Ce(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}=Lt(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=zt();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function pt(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 Tn(e,t,n){let o=re(e);return o||(o=je(e,""),await O(e),await f(t,`Created session ${o.id}.`,n)),o}function ls(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])=>cs.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 ds(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 us(e,t,n=3){let o=new Set,r=[],s=et(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 ms(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:me(n),modelId:o.trim()}}return{modelId:t}}function zn(e,t){let n=Date.now(),o=En.get(e)??0;n-o<gs||(En.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function Un(e){let t=m.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function fs(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(`
73
+ `)}function Je(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function gt(e,t){if(t.workspaceDir)return t.workspaceDir;let n=m.workspaceMappings.get(e);return n||m.workspaceDir}async function Bn(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 Kn(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 Wn(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 Wn(o=>Bn(e,t,o,n),Nn(t))}async function ys(e,t,n,o){await Wn(r=>Kn(e,t,n,r,o),Nn(n))}async function f(e,t,n){let o=Mt(t,3900);for(let r of o)await ps(e,r,n)}function ws(){let e=z()-Hn;for(let[o,r]of G)r.createdAt<e&&G.delete(o);if(G.size<=Dn)return;let t=Array.from(G.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=G.size-Dn;for(let o=0;o<n;o+=1)G.delete(t[o][0])}function bs(e){ws();let t=pe();for(;G.has(t);)t=pe();return G.set(t,{command:e,createdAt:z()}),t}function xs(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=G.get(t);return n?z()-n.createdAt>Hn?(G.delete(t),null):n.command:null}function vs(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 Jn(e,t){let n=[],o=[];for(let r of e){let s=bs(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 qn(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 On(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??hs,l=o?.footer,a=o?.messageThreadId,c=vs(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 p=Jn(i,r);await qn(e,g.join(`
74
+ `),p,a)}}function mt(e,t=Ms){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
75
75
 
76
- [truncated]`,truncated:!0}}async function ss(e,t){let n="Working...",r=(await _n(e,n,void 0,t)).message_id,s=n,l=0,a=Promise.resolve(),c=(i,u=!1)=>{let g=Date.now();!u&&g-l<rs||i!==s&&(s=i,l=g,a=a.then(async()=>{await An(e,r,i,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},d=i=>{s=i,l=Date.now(),a=a.then(async()=>{await Xr(e,r,i,t)}).catch(u=>{console.warn("[tg-agent] status edit failed",u)})};return{update:(i,u=!1)=>{let g=tt(i).text;c(g,u)},finalize:async i=>{let u=tt(i).text;d(u),await a},fail:async i=>{let u=tt(i).text;d(u),await a}}}function is(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
77
- args: ${as(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 as(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,l=(d,i)=>{if(d==null)return d;if(typeof d=="string")return d.length>n?`${d.slice(0,n)}...`:d;if(typeof d=="number"||typeof d=="boolean")return d;if(typeof d=="bigint")return d.toString();if(typeof d=="function")return"[function]";if(typeof d!="object")return String(d);if(t.has(d))return"[circular]";if(i>=s)return"[truncated]";if(t.add(d),Array.isArray(d)){let p=d.slice(0,r).map(y=>l(y,i+1));return d.length>r&&p.push("[truncated]"),p}let u=Object.entries(d),g={};for(let[p,y]of u.slice(0,o))g[p]=l(y,i+1);return u.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 re(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 cs(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function ls(){let e=await pe(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=>zt(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: ${cs(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${ne(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
78
- `)}async function st(e,t,n,o,r){let s=r,a=ze(e,s,s!==void 0);if(!a)return;let c=await Ee(a),d=Ve(c);switch(d.length>0&&(await D(c),await Promise.all(d.map(i=>ie(a,i).catch(u=>{console.warn(`[tg-agent] cleanup session file failed id=${i}`,u)})))),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","","Tips:","Send images or files to attach them to the prompt."].join(`
79
- `);await f(e,i,r);return}case"new":{try{let i=o||"",u=oe(c),g=u?.modelProvider,p=u?.modelId,y=De(c,i);g&&(y.modelProvider=g,p&&(y.modelId=p)),await D(c),await f(e,`Created session ${y.id} (${y.title}).`,r)}catch(i){await f(e,i.message,r)}return}case"list":{await D(c),await f(e,Vr(Ge(c)),r);return}case"use":{if(!o){await f(e,"Usage: /use <id>",r);return}if(!en(c,o)){await f(e,`Session not found: ${o}`,r);return}await D(c),await f(e,`Active session set to ${o}.`,r);return}case"close":{let i=o||c.activeSessionId;if(!i){await f(e,"No active session to close.",r);return}let u=c.sessions[i];if(u&&u.messages.length>0)try{await f(e,"Reflecting on session memory...",r);let w=await Ne(u,u.modelProvider,u.modelId);w.reflected?await f(e,"Memory archived successfully.",r):w.error?await f(e,`Memory saved (reflection failed: ${w.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(w){console.warn("[tg-agent] memory archival failed",w),await f(e,`Memory archival failed: ${re(w)}`,r)}let g=ve.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)}ot(a)}if(!Ye(c,i)){await f(e,`Session not found: ${i}`,r);return}await D(c),await ie(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 f(e,y,r);return}case"reset":{let i=oe(c);if(!i){await f(e,"No active session.",r);return}if(i.messages.length>0)try{await f(e,"Reflecting on session memory...",r);let u=await Ne(i,i.modelProvider,i.modelId);u.reflected?await f(e,"Memory archived successfully.",r):u.error?await f(e,`Memory saved (reflection failed: ${u.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(u){console.warn("[tg-agent] memory archival failed",u),await f(e,`Memory archival failed: ${re(u)}`,r)}tn(i),await D(c),await ie(a,i.id).catch(u=>{console.warn(`[tg-agent] reset session file failed id=${i.id}`,u)}),await f(e,`Reset session ${i.id}.`,r);return}case"workspace":{if(!o){let u=nt(a,c),g=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default";await f(e,`Workspace: ${u} (source: ${g})`,r);return}let i=le.resolve(W(o.trim()));nn(c,i),await D(c),await f(e,`Workspace set to: ${i}`,r);return}case"providers":{let{authStorage:i,modelRegistry:u}=await ae(),g=u.getError(),p=Kr(u,i);if(p.length===0){let w=g?`Warning: ${g}
76
+ [truncated]`,truncated:!0}}async function $s(e,t){let n="Working...",r=(await Bn(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 Kn(e,r,i,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},u=i=>{s=i,l=Date.now(),a=a.then(async()=>{await ys(e,r,i,t)}).catch(d=>{console.warn("[tg-agent] status edit failed",d)})};return{update:(i,d=!1)=>{let g=mt(i).text;c(g,d)},finalize:async i=>{let d=mt(i).text;u(d),await a},fail:async i=>{let d=mt(i).text;u(d),await a}}}function ks(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
77
+ args: ${_s(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 _s(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 p=u.slice(0,r).map(y=>l(y,i+1));return u.length>r&&p.push("[truncated]"),p}let d=Object.entries(u),g={};for(let[p,y]of d.slice(0,o))g[p]=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 se(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 Ps(){let e=await he(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=>Xt(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}) ${oe(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
78
+ `)}async function yt(e,t,n,o,r){let s=r,a=Je(e,s,s!==void 0);if(!a)return;let c=await Oe(a),u=tt(c);switch(u.length>0&&(await O(c),await Promise.all(u.map(i=>de(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(`
79
+ `);await f(e,i,r);return}case"new":{try{let i=o||"",d=re(c),g=d?.modelProvider,p=d?.modelId,y=je(c,i);g&&(y.modelProvider=g,p&&(y.modelId=p)),await O(c),await f(e,`Created session ${y.id} (${y.title}).`,r)}catch(i){await f(e,i.message,r)}return}case"list":{await O(c),await f(e,fs(et(c)),r);return}case"use":{if(!o){await f(e,"Usage: /use <id>",r);return}if(!mn(c,o)){await f(e,`Session not found: ${o}`,r);return}await O(c),await f(e,`Active session set to ${o}.`,r);return}case"close":{let i=o||c.activeSessionId;if(!i){await f(e,"No active session to close.",r);return}let d=c.sessions[i];if(d&&d.messages.length>0)try{await f(e,"Reflecting on session memory...",r);let w=await We(d,d.modelProvider,d.modelId);w.reflected?await f(e,"Memory archived successfully.",r):w.error?await f(e,`Memory saved (reflection failed: ${w.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(w){console.warn("[tg-agent] memory archival failed",w),await f(e,`Memory archival failed: ${se(w)}`,r)}let g=Me.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)}ft(a)}if(!nt(c,i)){await f(e,`Session not found: ${i}`,r);return}await O(c),await de(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 f(e,y,r);return}case"reset":{let i=re(c);if(!i){await f(e,"No active session.",r);return}if(i.messages.length>0)try{await f(e,"Reflecting on session memory...",r);let d=await We(i,i.modelProvider,i.modelId);d.reflected?await f(e,"Memory archived successfully.",r):d.error?await f(e,`Memory saved (reflection failed: ${d.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(d){console.warn("[tg-agent] memory archival failed",d),await f(e,`Memory archival failed: ${se(d)}`,r)}gn(i),await O(c),await de(a,i.id).catch(d=>{console.warn(`[tg-agent] reset session file failed id=${i.id}`,d)}),await f(e,`Reset session ${i.id}.`,r);return}case"workspace":{if(!o){let d=gt(a,c),g=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default";await f(e,`Workspace: ${d} (source: ${g})`,r);return}let i=ge.resolve(W(o.trim()));fn(c,i),await O(c),await f(e,`Workspace set to: ${i}`,r);return}case"providers":{let{authStorage:i,modelRegistry:d}=await ue(),g=d.getError(),p=ls(d,i);if(p.length===0){let w=g?`Warning: ${g}
80
80
 
81
- No providers found.`:"No providers found.";await f(e,w,r);return}let y=[];g&&y.push(`Warning: ${g}`),y.push("Providers:"),await wn(e,y.join(`
82
- `),p,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:i,modelRegistry:u}=await ae(),g=o?ce(o):"";if(!g){let k=oe(c);if(!k?.modelProvider){await f(e,"Usage: /models <provider>",r);return}g=k.modelProvider}let p=i.hasAuth(g),y=Jr(c,g),w=Hr(u,g,y);if(w.length===0){await f(e,`No models found for provider ${g}.`,r);return}await wn(e,`Models for ${g} (auth: ${p?"ok":"missing"}):`,w,{perRow:1,footer:"Tap a model to set it.",messageThreadId:r});return}case"provider":{if(!o){await f(e,"Usage: /provider <name>",r);return}let i=ce(o),{modelRegistry:u}=await ae();if(!u.getAll().some(y=>y.provider===i)){await f(e,`Unknown provider: ${i}`,r);return}let p=await pn(c,e,r);p.modelProvider=i,p.modelId=void 0,p.updatedAt=F(),await D(c),await f(e,`Session ${p.id} provider set to ${i}.`,r),await st(e,t,"models",i,r);return}case"model":{let i=qr(o);if(!i){await f(e,"Usage: /model <provider>/<model>",r);return}let u=await pn(c,e,r),g=ce(i.provider??u.modelProvider??"");if(!g){await f(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await ae(),y=zr(g,i.modelId);if(!p.find(g,y)){await f(e,`Model not found: ${g}/${y}`,r);return}u.modelProvider=g,u.modelId=y,u.updatedAt=F(),await D(c),await f(e,`Session ${u.id} model set to ${g}/${y}.`,r);return}case"status":{let i=oe(c);if(!i){await f(e,"No active session.",r);return}let u=m.modelRef.includes("/")?m.modelRef:`${m.modelProvider}/${m.modelRef}`,g=i.modelProvider||i.modelId?`Model: ${i.modelProvider??"?"}/${i.modelId??"?"}`:`Model: ${u} (default)`,p=nt(a,c),y=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default",w=[`Session: ${i.id} (${i.title})`,g,`Workspace: ${p} (${y})`].join(`
83
- `);await f(e,w,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Ft(),await ye(m.agentDir,{timeoutMs:5e3,maxBytes:m.fetchMaxBytes,maxChars:3e3}),Je(),await f(e,"MCP catalog refreshed.",r);return}let i=await ls();await f(e,i,r);return}case"login":{let i=xr();if(!o){let p=i.map(y=>`- ${y.id} (${y.name})`);await f(e,["OAuth providers:",...p].join(`
84
- `),r);return}let u=ce(o);if(et.has(t)){await f(e,"Login already in progress.",r);return}let g=i.find(p=>p.id===u);if(!g){await f(e,`Unknown OAuth provider: ${u}`,r);return}et.add(t);try{let{authStorage:p}=await ae();await f(e,`Starting login for ${g.id}...`,r),await p.login(g.id,{onAuth:({url:y,instructions:w})=>{let k=["Open this URL in your browser:",y];w&&k.push("",w),f(e,k.join(`
85
- `),r)},onPrompt:y=>fn(t,e,y,r),onProgress:y=>{f(e,y,r)},onManualCodeInput:()=>fn(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let y=re(p);await f(e,`Login failed: ${y}`,r)}finally{et.delete(t),xn(t)}return}case"logout":{if(!o){await f(e,"Usage: /logout <provider>",r);return}let i=ce(o),{authStorage:u}=await ae();u.logout(i),await f(e,`Logged out from ${i}.`,r);return}default:await f(e,`Unknown command: ${n}`,r)}}async function us(e,t,n,o=[],r){let s=rt(n);if(s){await st(e,t,s.command,s.args,r);return}let a=ze(e,r,r!==void 0);if(!a)return;let c=await Ee(a),d=Ve(c);d.length>0&&(await D(c),await Promise.all(d.map(v=>ie(a,v).catch(R=>{console.warn(`[tg-agent] cleanup session file failed id=${v}`,R)}))));let i=oe(c);if(!i)try{i=De(c,""),await D(c),await f(e,`Created session ${i.id}.`,r)}catch(v){await f(e,v.message,r);return}let{resolved:u,images:g}=await Dr(o);if(o.length>0&&u.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=Rr(u),y=[];n.trim()&&y.push(n.trim()),p&&y.push(p);let w=y.join(`
81
+ No providers found.`:"No providers found.";await f(e,w,r);return}let y=[];g&&y.push(`Warning: ${g}`),y.push("Providers:"),await On(e,y.join(`
82
+ `),p,{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 ue(),g=o?me(o):"";if(!g){let $=re(c);if(!$?.modelProvider){await f(e,"Usage: /models <provider>",r);return}g=$.modelProvider}let p=i.hasAuth(g),y=us(c,g),w=ds(d,g,y);if(w.length===0){await f(e,`No models found for provider ${g}.`,r);return}await On(e,`Models for ${g} (auth: ${p?"ok":"missing"}):`,w,{perRow:1,footer:"Tap a model to set it.",messageThreadId:r});return}case"provider":{if(!o){await f(e,"Usage: /provider <name>",r);return}let i=me(o),{modelRegistry:d}=await ue();if(!d.getAll().some(y=>y.provider===i)){await f(e,`Unknown provider: ${i}`,r);return}let p=await Tn(c,e,r);p.modelProvider=i,p.modelId=void 0,p.updatedAt=z(),await O(c),await f(e,`Session ${p.id} provider set to ${i}.`,r),await yt(e,t,"models",i,r);return}case"model":{let i=ms(o);if(!i){await f(e,"Usage: /model <provider>/<model>",r);return}let d=await Tn(c,e,r),g=me(i.provider??d.modelProvider??"");if(!g){await f(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await ue(),y=ss(g,i.modelId);if(!p.find(g,y)){await f(e,`Model not found: ${g}/${y}`,r);return}d.modelProvider=g,d.modelId=y,d.updatedAt=z(),await O(c),await f(e,`Session ${d.id} model set to ${g}/${y}.`,r);return}case"status":{let i=re(c);if(!i){await f(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)`,p=gt(a,c),y=c.workspaceDir?"chat":m.workspaceMappings.has(a)?"config":"default",w=[`Session: ${i.id} (${i.title})`,g,`Workspace: ${p} (${y})`].join(`
83
+ `);await f(e,w,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Yt(),await we(m.agentDir,{timeoutMs:5e3,maxBytes:m.fetchMaxBytes,maxChars:3e3}),Qe(),await f(e,"MCP catalog refreshed.",r);return}let i=await Ps();await f(e,i,r);return}case"login":{let i=zr();if(!o){let p=i.map(y=>`- ${y.id} (${y.name})`);await f(e,["OAuth providers:",...p].join(`
84
+ `),r);return}let d=me(o);if(ut.has(t)){await f(e,"Login already in progress.",r);return}let g=i.find(p=>p.id===d);if(!g){await f(e,`Unknown OAuth provider: ${d}`,r);return}ut.add(t);try{let{authStorage:p}=await ue();await f(e,`Starting login for ${g.id}...`,r),await p.login(g.id,{onAuth:({url:y,instructions:w})=>{let $=["Open this URL in your browser:",y];w&&$.push("",w),f(e,$.join(`
85
+ `),r)},onPrompt:y=>Rn(t,e,y,r),onProgress:y=>{f(e,y,r)},onManualCodeInput:()=>Rn(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let y=se(p);await f(e,`Login failed: ${y}`,r)}finally{ut.delete(t),In(t)}return}case"logout":{if(!o){await f(e,"Usage: /logout <provider>",r);return}let i=me(o),{authStorage:d}=await ue();d.logout(i),await f(e,`Logged out from ${i}.`,r);return}case"memory":{let i=m.memory.rag,d=await _n(),g=["Memory RAG Status:","",`Enabled: ${i.enabled?"Yes":"No"}`,`Embedding Model: ${i.embeddingModel}`,`Embedding Base URL: ${i.embeddingBaseUrl||"(default)"}`,`Similarity Threshold: ${i.similarityThreshold}`,`Max Results: ${i.maxResults}`,"","Vector Database:",` Status: ${d.exists?"Initialized":"Not initialized"}`,` Records: ${d.rowCount}`,"","Tip: Use /reindex to rebuild the vector index after changing embedding model."];await f(e,g.join(`
86
+ `),r);return}case"reindex":{if(!m.memory.rag.enabled){await f(e,"Memory RAG is disabled. Enable it in config.toml first.",r);return}await f(e,["Starting memory reindex...","",`Embedding Model: ${m.memory.rag.embeddingModel}`,"","This may take a few minutes. Please wait..."].join(`
87
+ `),r);try{let i=await kn((d,g,p)=>{(d%5===0||d===g)&&console.log(`[reindex] Progress: ${d}/${g} - ${p}`)});if(i.success){let d=["Reindex completed!","",`Total files: ${i.totalFiles}`,`Successfully indexed: ${i.indexedCount}`,`Skipped: ${i.skippedCount}`,`Errors: ${i.errorCount}`,"",`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 f(e,d.join(`
88
+ `),r)}else await f(e,`Reindex failed: ${i.errors.join(", ")}`,r)}catch(i){let d=i instanceof Error?i.message:String(i);await f(e,`Reindex failed: ${d}`,r)}return}default:await f(e,`Unknown command: ${n}`,r)}}async function Cs(e,t,n,o=[],r){let s=pt(n);if(s){await yt(e,t,s.command,s.args,r);return}let a=Je(e,r,r!==void 0);if(!a)return;let c=await Oe(a),u=tt(c);u.length>0&&(await O(c),await Promise.all(u.map(x=>de(a,x).catch(C=>{console.warn(`[tg-agent] cleanup session file failed id=${x}`,C)}))));let i=re(c);if(!i)try{i=je(c,""),await O(c),await f(e,`Created session ${i.id}.`,r)}catch(x){await f(e,x.message,r);return}let{resolved:d,images:g}=await Qr(o);if(o.length>0&&d.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=Yr(d),y=[];n.trim()&&y.push(n.trim()),p&&y.push(p);let w=y.join(`
86
89
 
87
- `)||"Attachment received.",k={role:"user",content:w,ts:F()};Xe(i,k,m.maxHistoryMessages),await D(c),console.log(`[tg-agent] request user=${t} chat=${a} session=${i.id} messages=${i.messages.length} textLen=${w.length} attachments=${u.length} provider=${i.modelProvider??"-"} model=${i.modelId??"-"}`);let $=null;try{$=await ss(e,r)}catch(v){console.warn("[tg-agent] status message failed",v)}let T={sessionId:i.id,chatId:e,messageThreadId:r,status:$,abortRequested:!1,cancelRequested:!1};Mr(a,T);try{let v=await Sr(async()=>{let J=await ln({chatId:a,sessionId:i.id,prompt:w,images:g,systemPrompt:m.systemPrompt,modelProvider:i.modelProvider,modelId:i.modelId,workspaceDir:nt(a,c),telegram:{chatId:e,sendPhoto:async(b,S)=>{let P={};S&&(P.caption=S),r!==void 0&&(P.message_thread_id=r),await O.sendPhoto(e,b,P)},sendDocument:async(b,S)=>{let P={};S&&(P.caption=S),r!==void 0&&(P.message_thread_id=r),await O.sendDocument(e,b,P)},sendMessage:async b=>{await f(e,b,r)},requestConfirmation:async(b,S)=>await gn(a,e,b,S,r)},auditContext:m.audit.enabled?{chatId:a,requestConfirmation:async(b,S)=>await gn(a,e,b,S,r),sendNotification:async b=>{await f(e,b,r)}}:void 0,onAbortReady:b=>{T.abort=b,T.abortRequested&&b()},onStatus:$?b=>{let S=is(b);S&&$?.update(S)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${J.modelProvider}/${J.modelId} file=${J.sessionFile}`),J.text});if(T.cancelRequested){$?await $.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let R={role:"assistant",content:v,ts:F()};Xe(i,R,m.maxHistoryMessages),await D(c),$?await $.finalize(v):await f(e,v,r)}catch(v){if(console.error("[tg-agent] runModel error",v),T.cancelRequested){$?await $.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let R=re(v);$?await $.fail(`Error: ${R}`):await f(e,`Error: ${R}`,r)}finally{ot(a)}}var O,bn,Sr,ve,$r,Or,Lr,ee,et,we,Nr,Fr,Fe,Wr,Gr,yn,Cn,hn,Qr,H,os,rs,En=N(()=>{"use strict";K();We();Dt();un();fe();Ce();Qe();dn();X();$t();O=new wr(m.telegramToken,{polling:!0}),bn=mt(),Sr=gt(m.maxConcurrent),ve=new Map;$r="image/jpeg";Or=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);Lr=600*1e3,ee=new Map,et=new Set,we=new Map;Nr=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),Fr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};Br();_(m.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await ye(m.agentDir,{timeoutMs:3e3,maxBytes:m.fetchMaxBytes,maxChars:2e3}),Je()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Fe=Et();console.log(Fe?`[tg-agent] fetchProxy=${Fe.url} kind=${Fe.kind} source=${Fe.source}`:"[tg-agent] fetchProxy=(none)");Wr=new Set(["openai-codex","google-antigravity","anthropic"]);Gr=6e4,yn=new Map;Cn=1800*1e3,hn=2e3,Qr=60,H=new Map;os=3900,rs=1200;O.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){O.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!$n(o)){kn(o,n),O.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){O.answerCallbackQuery(e.id);return}let r=ts(t);if(!r){O.answerCallbackQuery(e.id,{text:"Command expired."});return}O.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,l=e.message?.is_topic_message??!1,a=ze(n,s,l);if(!a)return;let c=rt(r);if(c?.command==="stop"){be(a,!1)?f(n,"Operation blocked.",s):Sn(n,a,s);return}if(c?.command==="close"){Mn(n,a,c.args,s);return}if(c?.command==="approve"){be(a,!0)?f(n,"Operation approved.",s):f(n,"No pending audit confirmation.",s);return}bn(a,async()=>{if(!c){await f(n,"Invalid command.",s);return}await st(n,o,c.command,c.args,s)}).catch(async d=>{console.error("[tg-agent] runModel error",d);let i=re(d);await f(n,`Error: ${i}`,s)})});O.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!$n(t)){kn(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=ze(n,o,r);if(!s)return;let l=(e.text??e.caption??"").trim(),a=Er(e);if(!l&&a.length===0)return;let c=ee.get(t);if(c){if(l==="/stop"||l==="/cancel"){Ur(t,"Login cancelled by user."),f(n,"Login cancelled.",o);return}if(!l){f(n,"Login expects a text response.",o);return}xn(t),c.resolve(l);return}let d=rt(l);if(d?.command==="stop"){be(s,!1),Sn(n,s,o);return}if(d?.command==="close"){be(s,!1),Mn(n,s,d.args,o);return}if(d?.command==="approve"){be(s,!0)?f(n,"Operation approved.",o):f(n,"No pending audit confirmation.",o);return}bn(s,()=>us(n,t,l,a,o)).catch(async i=>{console.error("[tg-agent] runModel error",i);let u=re(i);await f(n,`Error: ${u}`,o)})});O.on("polling_error",e=>{console.error("Polling error",e)});console.log("tg-agent started")});K();import ms from"node:fs";import Dn from"node:path";import gs from"node:readline/promises";import{fileURLToPath as fs}from"node:url";var On=process.argv.slice(2),In=(e,t)=>On.includes(e)||(t?On.includes(t):!1),ps=In("--help","-h"),ys=In("--version","-v"),hs=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
88
- `),ws=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=fs(import.meta.url),t=Dn.dirname(e),n=Dn.join(t,"..","package.json"),o=ms.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};ps&&(console.log(hs),process.exit(0));ys&&(console.log(ws()),process.exit(0));async function bs(){let e=gs.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function vs(){let{configPath:e,data:t,exists:n}=ge(),o=bt(),r=n?t:o,s=vt(r,o);if(xt(r)){s&&await Be(e,r);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${e}.`),process.exit(1));let a=await bs();a||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),St(r,a),await Be(e,r),console.log(`Saved config to ${e}.`)}async function xs(){let{data:e}=ge(),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 vs();await xs();kt();Promise.resolve().then(()=>En());
90
+ `)||"Attachment received.",$={role:"user",content:w,ts:z()};ot(i,$,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 _=null;try{_=await $s(e,r)}catch(x){console.warn("[tg-agent] status message failed",x)}let j={sessionId:i.id,chatId:e,messageThreadId:r,status:_,abortRequested:!1,cancelRequested:!1};Br(a,j);try{let x=m.systemPrompt;if(m.memory.rag.enabled&&w.trim())try{let M=await $n(w);if(M.length>0){let b=M.map(k=>`[${k.date}] Session: ${k.title}
91
+ Summary: ${k.content}`).join(`
92
+
93
+ `);x+=`
94
+
95
+ <relevant_memories>
96
+ The following are summaries from your past conversations that may be relevant:
97
+
98
+ ${b}
99
+ </relevant_memories>`,console.log(`[memory-rag] injected ${M.length} memories into context`)}}catch(M){console.warn(`[memory-rag] retrieval failed: ${M}`)}let C=await Ur(async()=>{let M=await xn({chatId:a,sessionId:i.id,prompt:w,images:g,systemPrompt:x,modelProvider:i.modelProvider,modelId:i.modelId,workspaceDir:gt(a,c),telegram:{chatId:e,sendPhoto:async(b,k)=>{let D={};k&&(D.caption=k),r!==void 0&&(D.message_thread_id=r),await E.sendPhoto(e,b,D)},sendDocument:async(b,k)=>{let D={};k&&(D.caption=k),r!==void 0&&(D.message_thread_id=r),await E.sendDocument(e,b,D)},sendMessage:async b=>{await f(e,b,r)},requestConfirmation:async(b,k)=>await Cn(a,e,b,k,r)},auditContext:m.audit.enabled?{chatId:a,requestConfirmation:async(b,k)=>await Cn(a,e,b,k,r),sendNotification:async b=>{await f(e,b,r)}}:void 0,onAbortReady:b=>{j.abort=b,j.abortRequested&&b()},onStatus:_?b=>{let k=ks(b);k&&_?.update(k)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${M.modelProvider}/${M.modelId} file=${M.sessionFile}`),M.text});if(j.cancelRequested){_?await _.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let ie={role:"assistant",content:C,ts:z()};ot(i,ie,m.maxHistoryMessages),await O(c),_?await _.finalize(C):await f(e,C,r)}catch(x){if(console.error("[tg-agent] runModel error",x),j.cancelRequested){_?await _.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let C=se(x);_?await _.fail(`Error: ${C}`):await f(e,`Error: ${C}`,r)}finally{ft(a)}}var E,jn,Ur,Me,Wr,Zr,ns,te,ut,xe,os,rs,He,cs,gs,En,Hn,Dn,hs,G,Ms,Ss,Vn=L(()=>{"use strict";J();Ge();Wt();vn();ce();Te();rt();An();lt();X();Nt();E=new Ir(m.telegramToken,{polling:!0}),jn=St(),Ur=$t(m.maxConcurrent),Me=new Map;Wr="image/jpeg";Zr=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);ns=600*1e3,te=new Map,ut=new Set,xe=new Map;os=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),rs={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};as();A(m.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await we(m.agentDir,{timeoutMs:3e3,maxBytes:m.fetchMaxBytes,maxChars:2e3}),Qe()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();He=Kt();console.log(He?`[tg-agent] fetchProxy=${He.url} kind=${He.kind} source=${He.source}`:"[tg-agent] fetchProxy=(none)");cs=new Set(["openai-codex","google-antigravity","anthropic"]);gs=6e4,En=new Map;Hn=1800*1e3,Dn=2e3,hs=60,G=new Map;Ms=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(!Un(o)){zn(o,n),E.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){E.answerCallbackQuery(e.id);return}let r=xs(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=pt(r);if(c?.command==="stop"){ve(a,!1)?f(n,"Operation blocked.",s):Ln(n,a,s);return}if(c?.command==="close"){Fn(n,a,c.args,s);return}if(c?.command==="approve"){ve(a,!0)?f(n,"Operation approved.",s):f(n,"No pending audit confirmation.",s);return}jn(a,async()=>{if(!c){await f(n,"Invalid command.",s);return}await yt(n,o,c.command,c.args,s)}).catch(async u=>{console.error("[tg-agent] runModel error",u);let i=se(u);await f(n,`Error: ${i}`,s)})});E.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!Un(t)){zn(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=te.get(t);if(c){if(l==="/stop"||l==="/cancel"){is(t,"Login cancelled by user."),f(n,"Login cancelled.",o);return}if(!l){f(n,"Login expects a text response.",o);return}In(t),c.resolve(l);return}let u=pt(l);if(u?.command==="stop"){ve(s,!1),Ln(n,s,o);return}if(u?.command==="close"){ve(s,!1),Fn(n,s,u.args,o);return}if(u?.command==="approve"){ve(s,!0)?f(n,"Operation approved.",o):f(n,"No pending audit confirmation.",o);return}jn(s,()=>Cs(n,t,l,a,o)).catch(async i=>{console.error("[tg-agent] runModel error",i);let d=se(i);await f(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")});J();import Ts from"node:fs";import Gn from"node:path";import Es from"node:readline/promises";import{fileURLToPath as Ds}from"node:url";var Yn=process.argv.slice(2),Xn=(e,t)=>Yn.includes(e)||(t?Yn.includes(t):!1),Os=Xn("--help","-h"),js=Xn("--version","-v"),Ns=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
100
+ `),Is=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Ds(import.meta.url),t=Gn.dirname(e),n=Gn.join(t,"..","package.json"),o=Ts.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Os&&(console.log(Ns),process.exit(0));js&&(console.log(Is()),process.exit(0));async function Ls(){let e=Es.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function Fs(){let{configPath:e,data:t,exists:n}=ye(),o=Rt(),r=n?t:o,s=Tt(r,o);if(Et(r)){s&&await Ve(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)),Dt(r,a),await Ve(e,r),console.log(`Saved config to ${e}.`)}async function zs(){let{data:e}=ye(),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 Fs();await zs();jt();Promise.resolve().then(()=>Vn());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tg-agent",
3
- "version": "1.2.19",
3
+ "version": "1.3.0",
4
4
  "description": "Telegram Agent Bot",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@iarna/toml": "^2.2.5",
24
+ "@lancedb/lancedb": "^0.22.3",
24
25
  "@mariozechner/pi-ai": "^0.50.1",
25
26
  "@mariozechner/pi-coding-agent": "^0.50.1",
26
27
  "@sinclair/typebox": "^0.32.35",
@@ -31,13 +32,16 @@
31
32
  "undici": "^7.18.2"
32
33
  },
33
34
  "devDependencies": {
34
- "esbuild": "^0.25.0",
35
35
  "@types/node": "^20.14.10",
36
36
  "@types/node-telegram-bot-api": "^0.64.7",
37
+ "esbuild": "^0.25.0",
37
38
  "tsx": "^4.19.1",
38
39
  "typescript": "^5.6.3"
39
40
  },
40
41
  "engines": {
41
42
  "node": ">=18"
43
+ },
44
+ "optionalDependencies": {
45
+ "@lancedb/lancedb-darwin-arm64": "^0.22.3"
42
46
  }
43
47
  }