tg-agent 1.2.7 → 1.2.9

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 +48 -25
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,40 +1,63 @@
1
1
  #!/usr/bin/env node
2
- var H=(e,t)=>()=>(e&&(t=e(e=0)),t);import Ce from"node:fs/promises";import gn from"node:os";import me from"node:path";import{randomUUID as Je}from"node:crypto";function N(){return Date.now()}function B(e){return e.startsWith("~")?me.join(gn.homedir(),e.slice(1)):e}async function z(e){await Ce.mkdir(e,{recursive:!0})}async function Ge(e,t){let n=me.dirname(e),o=`${me.basename(e)}.${Je()}.tmp`,r=me.join(n,o),s=JSON.stringify(t,null,2);await Ce.writeFile(r,s,"utf8"),await Ce.rename(r,e)}function ie(){return Je().split("-")[0]}function Ve(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 Xe(){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 Qe(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(i=>{n.push(i),o()});try{return await s()}finally{t=Math.max(0,t-1),o()}}}var Y=H(()=>{"use strict"});import Ye from"node:fs";import pe from"node:path";import*as fe from"@iarna/toml";function tt(){let e=B(Ze);return pe.join(e,pn)}function j(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function O(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 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 fn(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 yn(e){return new Set(fn(e))}function hn(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,pe.resolve(B(o.trim())));return t}function ae(){let e=tt();try{let t=Ye.readFileSync(e,"utf8"),n=fe.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Re(e,t){await z(pe.dirname(e));let n=fe.stringify(t);await Ye.promises.writeFile(e,n,"utf8")}function nt(){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:et},tls:{extra_ca_certs:"",reject_unauthorized:""}}}function ge(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function ot(e,t){let n=!1,o=(r,s)=>{for(let[i,l]of Object.entries(s)){if(!(i in r)){r[i]=l,n=!0;continue}let a=r[i];ge(a)&&ge(l)&&o(a,l)}};return ge(e)&&ge(t)&&o(e,t),n}function rt(e){let t=j(e,"telegram");return O(t.bot_token,"").trim()}function st(e,t){let n=j(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function it(e){let t=j(e,"telegram"),n=j(e,"model"),o=j(e,"paths"),r=j(e,"limits"),s=j(e,"timeouts"),i=j(e,"fetch"),l=j(e,"proxy"),a=j(e,"auth"),u=j(e,"logging"),c=j(e,"system"),d=j(e,"tls"),g=j(e,"workspace_mappings"),p=O(o.workspace_dir,process.cwd()),h=O(o.session_dir,"~/.tg-agent/tg-sessions"),v=hn(g),M=O(d.reject_unauthorized,""),_=M===""?null:Ae(M,!0);return{telegramToken:O(t.bot_token,"").trim(),telegramAllowedUsers:yn(t.allowed_user_ids),telegramParseMode:O(t.parse_mode,"").trim(),modelProvider:O(n.provider,"openai-codex").trim(),modelRef:O(n.model,"gpt-5.2").trim(),openaiApiKey:O(n.openai_api_key,"").trim(),sessionDir:B(h),agentDir:B(Ze),workspaceDir:pe.resolve(B(p)),workspaceMappings:v,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(i.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:O(c.prompt,et),proxyUrl:O(l.url,"").trim(),fetchProxyUrl:O(i.proxy_url,"").trim(),codexHome:B(O(a.codex_home,"~/.codex")),logAgentEvents:Ae(u.agent_events,!0),logAgentStream:Ae(u.agent_stream,!0),tlsExtraCaCerts:O(d.extra_ca_certs,"").trim(),tlsRejectUnauthorized:_}}function at(){let{data:e}=ae();return m=it(e),m}function ct(){let e=[];if(m.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${tt()})`)}var Ze,pn,et,wn,m,V=H(()=>{"use strict";Y();Ze="~/.tg-agent",pn="config.toml",et="You are running in user's personal computer or VPS, using telegram bot to interact with user. Be concise and practical.";({data:wn}=ae()),m=it(wn)});import{createHash as bn}from"node:crypto";import lt from"node:fs";import xn from"node:path";import{execSync as Sn}from"node:child_process";function kn(){return xn.join(m.codexHome,Mn)}function _n(e){return`cli|${bn("sha256").update(e).digest("hex").slice(0,16)}`}function $n(){if(process.platform!=="darwin")return null;let e=m.codexHome,t=_n(e);try{let n=Sn(`security find-generic-password -s "${vn}" -a "${t}" -w`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim(),o=JSON.parse(n),r=o.tokens,s=r?.access_token,i=r?.refresh_token;if(typeof s!="string"||!s||typeof i!="string"||!i)return null;let l=o.last_refresh,a=typeof l=="string"||typeof l=="number"?new Date(l).getTime():Date.now(),u=Number.isFinite(a)?a+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:i,expiresAt:u,source:"keychain"}}catch{return null}}function Tn(){let e=kn();try{let t=lt.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 i=Date.now()+3600*1e3;try{i=lt.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:i,source:"file"}}catch{return null}}function Z(){return $n()??Tn()}var Mn,vn,ye=H(()=>{"use strict";V();Mn="auth.json",vn="Codex Auth"});function ut(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=Z();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 Pn(){return m.proxyUrl?{url:m.proxyUrl,source:"config.proxy.url"}:m.fetchProxyUrl?{url:m.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function dt(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function mt(){let e=Pn();return e?{url:e.url,kind:dt(e.url),source:e.source}:null}function gt(){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=dt(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var De=H(()=>{"use strict";V();ye()});import{ProxyAgent as Cn,setGlobalDispatcher as An}from"undici";function ft(){if(pt)return Ee;pt=!0;let e=gt();if(!e)return Ee=null,null;let t=new Cn(e.url);return An(t),Ee=e,e}var pt,Ee,yt=H(()=>{"use strict";De();pt=!1,Ee=null});import Rn from"node:fs";import Dn from"node:fs/promises";import En from"node:path";import On from"node:readline";import{spawn as jn}from"node:child_process";import*as wt from"@iarna/toml";function St(e){return En.join(e,"config.toml")}function he(e){let t=St(e);try{let n=Rn.readFileSync(t,"utf8");return _t(n)}catch{return[]}}async function ce(e){let t=St(e);try{let n=await Dn.readFile(t,"utf8");return _t(n)}catch{return[]}}async function le(e,t={}){if(ee)return ee;let n=await ce(e);if(n.length===0)return ee="","";let o=t.maxTools??zn,r=t.maxChars??Nn,s=t.timeoutMs??4e3,i=t.maxBytes??bt,l=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let c=await Ln(u,{timeoutMs:s,maxBytes:i});if(l.push(`${u.name} (${u.type})`),c.length===0){l.push(" - tools unavailable");continue}let d=c.slice(0,o);for(let g of d){let p=g.description?`: ${g.description}`:"";l.push(` - ${g.name}${p}`)}c.length>d.length&&l.push(` - ...and ${c.length-d.length} more`)}let a=l.join(`
4
- `);return a.length>r&&(a=`${a.slice(0,r-20)}...
5
- (truncated)`),ee=a,a}function je(){ee&&(xt=!0)}function Mt(){ee=null,xt=!1,I.clear()}function Q(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 vt(e,t=5e3){let n=Date.now();try{return await we(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 we(e,t,n,o={}){let r=ht(o.timeoutMs??Fn,1e3,12e4),s=ht(o.maxBytes??bt,1024,5e6),i=new AbortController,l=()=>i.abort();o.signal?.addEventListener("abort",l,{once:!0});let a=setTimeout(()=>i.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await Wn(e,s,i.signal),await Bn(e,t,n,s,i.signal)):await Kn(e,t,n,s,i.signal)}finally{clearTimeout(a),o.signal?.removeEventListener("abort",l)}}function ht(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function Ln(e,t){try{let n=await we(e,"tools/list",{},t);return Un(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 Un(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 i of r){if(!i||typeof i!="object")continue;let l=i,a=typeof l.name=="string"?l.name:"";if(!a)continue;let u=typeof l.description=="string"?l.description:void 0,c=l.inputSchema;s.push({name:a,description:u,inputSchema:c})}return s}async function Bn(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),i=await Oe(e,t,n,o,r),l=kt(i.parsed);if(l)throw new Error(l);let a=i.bodyText;return i.parsed&&(a=JSON.stringify(i.parsed,null,2)),{ok:i.statusCode>=200&&i.statusCode<300,output:a,durationMs:Date.now()-s,bytes:i.bytes,truncated:i.truncated,statusCode:i.statusCode,statusText:i.statusText,contentType:i.contentType}}async function Oe(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=I.get(e.name),i={jsonrpc:"2.0",id:`tg-agent-${Date.now()}`,method:t,params:n??{}},l={"content-type":"application/json"};e.auth&&(l.authorization=e.auth.startsWith("Bearer ")?e.auth:`Bearer ${e.auth}`),s?.cookie&&(l.cookie=s.cookie),s?.sessionId&&(l["mcp-session-id"]=s.sessionId);let a=await fetch(e.url,{method:"POST",headers:l,body:JSON.stringify(i),signal:r});Hn(e.name,a);let u=await Jn(a,o,r),c;try{c=JSON.parse(u.text)}catch{c=void 0}return qn(e.name,c),{statusCode:a.status,statusText:a.statusText,contentType:a.headers.get("content-type"),bodyText:u.text,parsed:c,bytes:u.bytes,truncated:u.truncated}}function kt(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 Wn(e,t,n){let o=I.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let s=await Oe(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),i=kt(s.parsed);if(i){let u=i.toLowerCase();if(u.includes("method")&&u.includes("not"))return;throw new Error(i)}let l=new AbortController,a=setTimeout(()=>l.abort(),In);try{await Oe(e,"notifications/initialized",{},t,l.signal)}catch{}finally{clearTimeout(a)}})();I.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let s=I.get(e.name);I.set(e.name,{initializedAt:Date.now(),cookie:s?.cookie,sessionId:s?.sessionId})}catch(s){throw I.delete(e.name),s}}function Hn(e,t){let o=I.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),s=t.headers.getSetCookie?.(),i=s&&s.length>0?s.join("; "):r;i&&I.set(e,{...o,cookie:i});let l=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");l&&I.set(e,{...o,sessionId:l})}function qn(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=I.get(e)??{initializedAt:0};I.set(e,{...s,sessionId:r})}async function Kn(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),i=jn(e.command,e.args??[],{stdio:["pipe","pipe","pipe"]}),l=()=>{i.killed||i.kill("SIGTERM")};if(r.aborted)throw l(),new Error("MCP request aborted.");let a=new Map,u=!1,c="",d=new Error("MCP request aborted."),g=On.createInterface({input:i.stdout,terminal:!1});g.on("line",b=>{if(b.length>o){u=!0;return}let S=null;try{S=JSON.parse(b)}catch{return}let k=typeof S.id=="string"?S.id:typeof S.id=="number"?String(S.id):"";if(!k)return;let P=a.get(k);P&&(a.delete(k),P.resolve(S))}),i.stderr?.on("data",b=>{let S=b.toString();if(c.length+S.length>o){u=!0;return}c+=S});let p=()=>{for(let b of a.values())b.reject(d);a.clear(),l()};r.addEventListener("abort",p,{once:!0});let h=b=>{let S=b===0?"MCP stdio exited.":c.trim()||"MCP stdio exited with error.";for(let k of a.values())k.reject(new Error(S));a.clear()};i.once("exit",b=>h(b));let v=async(b,S)=>{let k=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,P={jsonrpc:"2.0",id:k,method:b,params:S??{}};return await new Promise((y,w)=>{a.set(k,{resolve:y,reject:w}),i.stdin?.write(`${JSON.stringify(P)}
6
- `)})};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 M=await v("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:!!M.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),M.error&&typeof M.error=="object"){let b=M.error.message??"MCP initialize failed.";throw l(),new Error(String(b))}let _={jsonrpc:"2.0",method:"notifications/initialized"};i.stdin?.write(`${JSON.stringify(_)}
7
- `),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 E=await v(t,n);r.removeEventListener("abort",p),g.close(),i.stdin?.end(),l();let T=new Promise(b=>{i.once("exit",()=>b())});if(await Promise.race([T,new Promise(b=>setTimeout(b,500))]),E.error&&typeof E.error=="object"){let b=E.error.message??"MCP request failed.";throw new Error(String(b))}let $=JSON.stringify(E,null,2),W=$.length>o?$.slice(0,o):$;return $.length>o&&(u=!0),{ok:!0,output:W,durationMs:Date.now()-s,bytes:Math.min($.length,o),truncated:u}}async function Jn(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=[],i=0,l=!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=i+g.byteLength;if(p>t){let h=Math.max(0,t-i);h>0&&(s.push(g.slice(0,h)),i+=h),l=!0;try{await o.cancel()}catch{}break}s.push(g),i=p}let a=new Uint8Array(i),u=0;for(let d of s)a.set(d,u),u+=d.byteLength;return{text:r.decode(a),bytes:i,truncated:l}}function _t(e){let t=[],n;try{n=wt.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 i=s,l=typeof i.type=="string"?i.type.toLowerCase():void 0,a=typeof i.url=="string"?i.url:void 0,u=typeof i.command=="string"?i.command:void 0,c=l==="http"||l==="stdio"?l:a?"http":u?"stdio":void 0;if(!c||c==="http"&&!a||c==="stdio"&&!u)continue;let d;Array.isArray(i.args)&&(d=i.args.filter(p=>typeof p=="string").map(p=>p.trim()));let g=typeof i.auth=="string"?i.auth:typeof i.authorization=="string"?i.authorization:typeof i.token=="string"?i.token:void 0;t.push({name:r,type:c,url:a,command:u,args:d,auth:g})}return t}var Fn,bt,zn,Nn,ee,xt,I,In,be=H(()=>{"use strict";Fn=6e4,bt=2e5,zn=40,Nn=3500,ee=null,xt=!1,I=new Map,In=1500});import J from"node:path";import Gn from"node:fs/promises";import{Type as x}from"@sinclair/typebox";function xe(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function Qn(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 $t(e){let t=m.fetchTimeoutMs>0?m.fetchTimeoutMs:Xn;return xe(e||t,1e3,12e4)}function Tt(e){let t=m.fetchMaxBytes>0?m.fetchMaxBytes:Vn;return xe(e||t,1024,5e6)}function Pt(e,t,n){let o=e.trim();if(!o)return null;let r=B(o),s=J.isAbsolute(r)?r:J.join(n,r),i=J.resolve(s);for(let l of t){let a=J.resolve(l);if(i===a||i.startsWith(`${a}${J.sep}`))return i}return null}async function Ct(e){try{let t=await Gn.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function Yn(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function Zn(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 eo(e,t,n){let o=e.body?.getReader?.();if(!o){let c=await e.text?.()??"",d=Math.min(c.length,t),g=c.length>t;return{text:c.slice(0,t),bytes:d,truncated:g}}let r=new TextDecoder("utf-8"),s=[],i=0,l=!1;for(;;){if(n?.aborted){try{await o.cancel?.()}catch{}throw new Error("Fetch aborted")}let{done:c,value:d}=await o.read();if(c)break;if(!d)continue;let g=i+d.byteLength;if(g>t){let p=Math.max(0,t-i);p>0&&(s.push(d.slice(0,p)),i+=p),l=!0;try{await o.cancel?.()}catch{}break}s.push(d),i=g}let a=Zn(s,i);return{text:r.decode(a),bytes:i,truncated:l}}function to(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}
2
+ var W=(e,t)=>()=>(e&&(t=e(e=0)),t);import Oe from"node:fs/promises";import $n from"node:os";import ye from"node:path";import{randomUUID as Qe}from"node:crypto";function F(){return Date.now()}function H(e){return e.startsWith("~")?ye.join($n.homedir(),e.slice(1)):e}async function D(e){await Oe.mkdir(e,{recursive:!0})}async function Ze(e,t){let n=ye.dirname(e),o=`${ye.basename(e)}.${Qe()}.tmp`,r=ye.join(n,o),s=JSON.stringify(t,null,2);await Oe.writeFile(r,s,"utf8"),await Oe.rename(r,e)}function ce(){return Qe().split("-")[0]}function et(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 tt(){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 nt(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 Z=W(()=>{"use strict"});import ot from"node:fs";import be from"node:path";import*as ve from"@iarna/toml";function it(){let e=H(rt);return be.join(e,_n)}function O(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function T(e,t){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):t}function K(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 he(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 at(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 An(e){return new Set(at(e))}function Pn(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,be.resolve(H(o.trim())));return t}function le(){let e=it();try{let t=ot.readFileSync(e,"utf8"),n=ve.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Ie(e,t){await D(be.dirname(e));let n=ve.stringify(t);await ot.promises.writeFile(e,n,"utf8")}function ct(){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:st},tls:{extra_ca_certs:"",reject_unauthorized:""},security_audit:{enabled:!1,model_provider:"",model_id:"",whitelist_patterns:[],confirm_timeout_ms:12e4}}}function we(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function lt(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 i=r[l];we(i)&&we(a)&&o(i,a)}};return we(e)&&we(t)&&o(e,t),n}function ut(e){let t=O(e,"telegram");return T(t.bot_token,"").trim()}function dt(e,t){let n=O(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function mt(e){let t=O(e,"telegram"),n=O(e,"model"),o=O(e,"paths"),r=O(e,"limits"),s=O(e,"timeouts"),l=O(e,"fetch"),a=O(e,"proxy"),i=O(e,"auth"),u=O(e,"logging"),c=O(e,"system"),m=O(e,"tls"),g=O(e,"workspace_mappings"),p=O(e,"security_audit"),h=T(o.workspace_dir,process.cwd()),k=T(o.session_dir,"~/.tg-agent/tg-sessions"),P=Pn(g),S=T(m.reject_unauthorized,""),I=S===""?null:he(S,!0);return{telegramToken:T(t.bot_token,"").trim(),telegramAllowedUsers:An(t.allowed_user_ids),telegramParseMode:T(t.parse_mode,"").trim(),modelProvider:T(n.provider,"openai-codex").trim(),modelRef:T(n.model,"gpt-5.2").trim(),openaiApiKey:T(n.openai_api_key,"").trim(),sessionDir:H(k),agentDir:H(rt),workspaceDir:be.resolve(H(h)),workspaceMappings:P,maxSessions:K(r.max_sessions,5),maxConcurrent:K(r.max_concurrent,5),maxHistoryMessages:K(r.max_history_messages,40),maxOutputTokens:K(r.max_output_tokens,0),fetchMaxBytes:K(l.max_bytes,2e5),fetchTimeoutMs:K(s.fetch_timeout_ms,6e4),modelTimeoutMs:K(s.model_timeout_ms,6e4),modelTimeoutStreamingMs:K(s.model_timeout_stream_ms,3e5),systemPrompt:T(c.prompt,st),proxyUrl:T(a.url,"").trim(),fetchProxyUrl:T(l.proxy_url,"").trim(),codexHome:H(T(i.codex_home,"~/.codex")),logAgentEvents:he(u.agent_events,!0),logAgentStream:he(u.agent_stream,!0),tlsExtraCaCerts:T(m.extra_ca_certs,"").trim(),tlsRejectUnauthorized:I,audit:{enabled:he(p.enabled,!1),modelProvider:T(p.model_provider,"").trim(),modelId:T(p.model_id,"").trim(),whitelistPatterns:at(p.whitelist_patterns),confirmTimeoutMs:K(p.confirm_timeout_ms,6e4)}}}function gt(){let{data:e}=le();return d=mt(e),d}function pt(){let e=[];if(d.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${it()})`)}var rt,_n,st,Tn,d,G=W(()=>{"use strict";Z();rt="~/.tg-agent",_n="config.toml",st=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
4
+
5
+ Important behavioral rules:
6
+ - Do NOT mention the name of your underlying framework, technical implementation, or any package names
7
+ - Do NOT refer to yourself as "pi", "pi-coding-agent", or any other framework/tool name
8
+ - When users ask about your identity or implementation, simply say you are a coding assistant
9
+ - Focus on helping with tasks rather than discussing your technical stack or architecture
10
+ - Do not mention documentation paths or framework-specific resources unless directly relevant to the task
11
+
12
+ Be concise and practical in all responses.`;({data:Tn}=le()),d=mt(Tn)});import{createHash as Cn}from"node:crypto";import ft from"node:fs";import Rn from"node:path";import{execSync as En}from"node:child_process";function In(){return Rn.join(d.codexHome,Dn)}function Ln(e){return`cli|${Cn("sha256").update(e).digest("hex").slice(0,16)}`}function jn(){if(process.platform!=="darwin")return null;let e=d.codexHome,t=Ln(e);try{let n=En(`security find-generic-password -s "${On}" -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,i=typeof a=="string"||typeof a=="number"?new Date(a).getTime():Date.now(),u=Number.isFinite(i)?i+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:l,expiresAt:u,source:"keychain"}}catch{return null}}function Nn(){let e=In();try{let t=ft.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=ft.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function oe(){return jn()??Nn()}var Dn,On,xe=W(()=>{"use strict";G();Dn="auth.json",On="Codex Auth"});function yt(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=oe();if(n)return{apiKey:n.accessToken,source:`codex:${n.source}`};throw new Error("No Codex OAuth credentials found. Run `codex login`.")}if(d.openaiApiKey)return{apiKey:d.openaiApiKey,source:"config.model.openai_api_key"};throw new Error(`No API key for provider: ${e}`)}function Fn(){return d.proxyUrl?{url:d.proxyUrl,source:"config.proxy.url"}:d.fetchProxyUrl?{url:d.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function ht(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function wt(){let e=Fn();return e?{url:e.url,kind:ht(e.url),source:e.source}:null}function bt(){let e=[{key:"config.fetch.proxy_url",value:d.fetchProxyUrl},{key:"config.proxy.url",value:d.proxyUrl}];for(let t of e){let n=t.value?.trim();if(!n)continue;let o=ht(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var Le=W(()=>{"use strict";G();xe()});import{ProxyAgent as zn,setGlobalDispatcher as Un}from"undici";function xt(){if(vt)return je;vt=!0;let e=bt();if(!e)return je=null,null;let t=new zn(e.url);return Un(t),je=e,e}var vt,je,St=W(()=>{"use strict";Le();vt=!1,je=null});import Bn from"node:fs";import Wn from"node:fs/promises";import Hn from"node:path";import qn from"node:readline";import{spawn as Jn}from"node:child_process";import*as Mt from"@iarna/toml";function At(e){return Hn.join(e,"config.toml")}function Se(e){let t=At(e);try{let n=Bn.readFileSync(t,"utf8");return Rt(n)}catch{return[]}}async function ue(e){let t=At(e);try{let n=await Wn.readFile(t,"utf8");return Rt(n)}catch{return[]}}async function de(e,t={}){if(re)return re;let n=await ue(e);if(n.length===0)return re="","";let o=t.maxTools??Gn,r=t.maxChars??Vn,s=t.timeoutMs??4e3,l=t.maxBytes??$t,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let c=await Xn(u,{timeoutMs:s,maxBytes:l});if(a.push(`${u.name} (${u.type})`),c.length===0){a.push(" - tools unavailable");continue}let m=c.slice(0,o);for(let g of m){let p=g.description?`: ${g.description}`:"";a.push(` - ${g.name}${p}`)}c.length>m.length&&a.push(` - ...and ${c.length-m.length} more`)}let i=a.join(`
13
+ `);return i.length>r&&(i=`${i.slice(0,r-20)}...
14
+ (truncated)`),re=i,i}function Fe(){re&&(_t=!0)}function Pt(){re=null,_t=!1,z.clear()}function ee(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 Tt(e,t=5e3){let n=Date.now();try{return await ke(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 ke(e,t,n,o={}){let r=kt(o.timeoutMs??Kn,1e3,12e4),s=kt(o.maxBytes??$t,1024,5e6),l=new AbortController,a=()=>l.abort();o.signal?.addEventListener("abort",a,{once:!0});let i=setTimeout(()=>l.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await eo(e,s,l.signal),await Zn(e,t,n,s,l.signal)):await oo(e,t,n,s,l.signal)}finally{clearTimeout(i),o.signal?.removeEventListener("abort",a)}}function kt(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function Xn(e,t){try{let n=await ke(e,"tools/list",{},t);return Qn(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 Qn(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,i=typeof a.name=="string"?a.name:"";if(!i)continue;let u=typeof a.description=="string"?a.description:void 0,c=a.inputSchema;s.push({name:i,description:u,inputSchema:c})}return s}async function Zn(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await Ne(e,t,n,o,r),a=Ct(l.parsed);if(a)throw new Error(a);let i=l.bodyText;return l.parsed&&(i=JSON.stringify(l.parsed,null,2)),{ok:l.statusCode>=200&&l.statusCode<300,output:i,durationMs:Date.now()-s,bytes:l.bytes,truncated:l.truncated,statusCode:l.statusCode,statusText:l.statusText,contentType:l.contentType}}async function Ne(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 i=await fetch(e.url,{method:"POST",headers:a,body:JSON.stringify(l),signal:r});to(e.name,i);let u=await ro(i,o,r),c;try{c=JSON.parse(u.text)}catch{c=void 0}return no(e.name,c),{statusCode:i.status,statusText:i.statusText,contentType:i.headers.get("content-type"),bodyText:u.text,parsed:c,bytes:u.bytes,truncated:u.truncated}}function Ct(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 eo(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 Ne(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=Ct(s.parsed);if(l){let u=l.toLowerCase();if(u.includes("method")&&u.includes("not"))return;throw new Error(l)}let a=new AbortController,i=setTimeout(()=>a.abort(),Yn);try{await Ne(e,"notifications/initialized",{},t,a.signal)}catch{}finally{clearTimeout(i)}})();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 to(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 no(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 oo(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=Jn(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 i=new Map,u=!1,c="",m=new Error("MCP request aborted."),g=qn.createInterface({input:l.stdout,terminal:!1});g.on("line",w=>{if(w.length>o){u=!0;return}let v=null;try{v=JSON.parse(w)}catch{return}let $=typeof v.id=="string"?v.id:typeof v.id=="number"?String(v.id):"";if(!$)return;let Q=i.get($);Q&&(i.delete($),Q.resolve(v))}),l.stderr?.on("data",w=>{let v=w.toString();if(c.length+v.length>o){u=!0;return}c+=v});let p=()=>{for(let w of i.values())w.reject(m);i.clear(),a()};r.addEventListener("abort",p,{once:!0});let h=w=>{let v=w===0?"MCP stdio exited.":c.trim()||"MCP stdio exited with error.";for(let $ of i.values())$.reject(new Error(v));i.clear()};l.once("exit",w=>h(w));let k=async(w,v)=>{let $=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,Q={jsonrpc:"2.0",id:$,method:w,params:v??{}};return await new Promise((ne,y)=>{i.set($,{resolve:ne,reject:y}),l.stdin?.write(`${JSON.stringify(Q)}
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 P=await k("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:!!P.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),P.error&&typeof P.error=="object"){let w=P.error.message??"MCP initialize failed.";throw a(),new Error(String(w))}let S={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify(S)}
16
+ `),fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeMethod",message:"sending method request",data:{method:t,elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"C"})}).catch(()=>{});let I=await k(t,n);r.removeEventListener("abort",p),g.close(),l.stdin?.end(),a();let M=new Promise(w=>{l.once("exit",()=>w())});if(await Promise.race([M,new Promise(w=>setTimeout(w,500))]),I.error&&typeof I.error=="object"){let w=I.error.message??"MCP request failed.";throw new Error(String(w))}let L=JSON.stringify(I,null,2),N=L.length>o?L.slice(0,o):L;return L.length>o&&(u=!0),{ok:!0,output:N,durationMs:Date.now()-s,bytes:Math.min(L.length,o),truncated:u}}async function ro(e,t,n){let o=e.body?.getReader?.();if(!o){let m=await e.text(),g=Math.min(m.length,t);return{text:m.slice(0,t),bytes:g,truncated:m.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:m,value:g}=await o.read();if(m)break;if(!g)continue;let p=l+g.byteLength;if(p>t){let h=Math.max(0,t-l);h>0&&(s.push(g.slice(0,h)),l+=h),a=!0;try{await o.cancel()}catch{}break}s.push(g),l=p}let i=new Uint8Array(l),u=0;for(let m of s)i.set(m,u),u+=m.byteLength;return{text:r.decode(i),bytes:l,truncated:a}}function Rt(e){let t=[],n;try{n=Mt.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,i=typeof l.url=="string"?l.url:void 0,u=typeof l.command=="string"?l.command:void 0,c=a==="http"||a==="stdio"?a:i?"http":u?"stdio":void 0;if(!c||c==="http"&&!i||c==="stdio"&&!u)continue;let m;Array.isArray(l.args)&&(m=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:c,url:i,command:u,args:m,auth:g})}return t}var Kn,$t,Gn,Vn,re,_t,z,Yn,Me=W(()=>{"use strict";Kn=6e4,$t=2e5,Gn=40,Vn=3500,re=null,_t=!1,z=new Map,Yn=1500});import V from"node:path";import so from"node:fs/promises";import{Type as x}from"@sinclair/typebox";function $e(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function co(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 Et(e){let t=d.fetchTimeoutMs>0?d.fetchTimeoutMs:ao;return $e(e||t,1e3,12e4)}function Dt(e){let t=d.fetchMaxBytes>0?d.fetchMaxBytes:io;return $e(e||t,1024,5e6)}function Ot(e,t,n){let o=e.trim();if(!o)return null;let r=H(o),s=V.isAbsolute(r)?r:V.join(n,r),l=V.resolve(s);for(let a of t){let i=V.resolve(a);if(l===i||l.startsWith(`${i}${V.sep}`))return l}return null}async function It(e){try{let t=await so.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function lo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function uo(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 c=await e.text?.()??"",m=Math.min(c.length,t),g=c.length>t;return{text:c.slice(0,t),bytes:m,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:c,value:m}=await o.read();if(c)break;if(!m)continue;let g=l+m.byteLength;if(g>t){let p=Math.max(0,t-l);p>0&&(s.push(m.slice(0,p)),l+=p),a=!0;try{await o.cancel?.()}catch{}break}s.push(m),l=g}let i=uo(s,l);return{text:r.decode(i),bytes:l,truncated:a}}function go(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}
8
17
  ${o.join(`
9
18
  `)}
10
19
 
11
- ${t}`}function oo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:no,execute:async(e,t,n,o,r)=>{if(!Yn(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=$t(t.timeoutMs),i=Tt(t.maxBytes),l=new AbortController,a=()=>l.abort();r?.addEventListener("abort",a,{once:!0});let u=setTimeout(()=>l.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 c=await fetch(t.url,{method:t.method?.toUpperCase()??"GET",headers:Qn(t.headers),body:t.body,signal:l.signal}),d=await eo(c,i,r),g=c.headers.get("content-type");return{content:[{type:"text",text:to({url:c.url,status:c.status,statusText:c.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g},d.text)}],details:{url:c.url,status:c.status,statusText:c.statusText,bytes:d.bytes,truncated:d.truncated,contentType:g}}}catch(c){return{content:[{type:"text",text:`Fetch failed: ${c instanceof Error?c.message:String(c)}`}],details:{url:t.url,status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}finally{clearTimeout(u),r?.removeEventListener("abort",a)}}}}function so(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 fo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:po,execute:async(e,t,n,o,r)=>{if(!lo(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=Et(t.timeoutMs),l=Dt(t.maxBytes),a=new AbortController,i=()=>a.abort();r?.addEventListener("abort",i,{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 c=await fetch(t.url,{method:t.method?.toUpperCase()??"GET",headers:co(t.headers),body:t.body,signal:a.signal}),m=await mo(c,l,r),g=c.headers.get("content-type");return{content:[{type:"text",text:go({url:c.url,status:c.status,statusText:c.statusText,bytes:m.bytes,truncated:m.truncated,contentType:g},m.text)}],details:{url:c.url,status:c.status,statusText:c.statusText,bytes:m.bytes,truncated:m.truncated,contentType:g}}}catch(c){return{content:[{type:"text",text:`Fetch failed: ${c instanceof Error?c.message:String(c)}`}],details:{url:t.url,status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}finally{clearTimeout(u),r?.removeEventListener("abort",i)}}}}function ho(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}
12
21
  ${r.join(`
13
22
  `)}
14
23
 
15
- ${n}`}function io(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:ro,execute:async(t,n,o,r,s)=>{let i=await e();if(i.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 l=n.server?.trim()??"";if(!l)if(i.length===1)l=i[0]?.name??"";else return{content:[{type:"text",text:`Multiple MCP servers configured. Provide server name. Available: ${i.map(u=>u.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let a=i.find(u=>u.name===l);if(!a)return{content:[{type:"text",text:`MCP server not found: ${l}. Available: ${i.map(u=>u.name).join(", ")}`}],details:{server:l,type:"http",target:"",status:0,statusText:"server_not_found",bytes:0,truncated:!1,contentType:null}};try{o?.({content:[{type:"text",text:`Calling MCP ${a.name} ${n.method}...`}],details:{server:a.name,type:a.type,target:Q(a),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let u=await we(a,n.method,n.params??{},{timeoutMs:$t(void 0),maxBytes:Tt(void 0),signal:s});return{content:[{type:"text",text:so(a,{server:a.name,type:a.type,target:Q(a),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:a.name,type:a.type,target:Q(a),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:a.name,type:a.type,target:Q(a),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function lo(e){let t=[m.workspaceDir,J.join(m.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:ao,execute:async(n,o)=>{let r=Pt(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 Ct(r);return s?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${J.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function uo(e){let t=[m.workspaceDir,J.join(m.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:co,execute:async(n,o)=>{let r=Pt(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 Ct(r);return s?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${J.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function At(e){let t=[oo()];return e?.telegram&&(t.push(lo(e.telegram)),t.push(uo(e.telegram))),he(m.agentDir).length>0&&t.push(io(()=>ce(m.agentDir))),t}var Vn,Xn,no,ro,ao,co,Rt=H(()=>{"use strict";V();be();Y();Vn=2e5,Xn=6e4;no=x.Object({url:x.String({description:"HTTP or HTTPS URL"}),method:x.Optional(x.String({description:"HTTP method (default: GET)"})),headers:x.Optional(x.Array(x.Object({name:x.String({description:"Header name"}),value:x.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:x.Optional(x.String({description:"Request body (string)"})),timeoutMs:x.Optional(x.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:x.Optional(x.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});ro=x.Object({server:x.Optional(x.String({description:"MCP server name"})),method:x.String({description:"MCP method name"}),params:x.Optional(x.Any({description:"MCP params payload"}))});ao=x.Object({path:x.String({description:"Image file path (relative to workspace or uploads)."}),caption:x.Optional(x.String({description:"Caption text (plain text)."}))}),co=x.Object({path:x.String({description:"File path (relative to workspace or uploads)."}),caption:x.Optional(x.String({description:"Caption text (plain text)."}))})});import Ot from"node:fs/promises";import jt from"node:path";function Ft(e){return jt.join(m.sessionDir,`${e}.json`)}function Dt(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function Fe(e,t){let n=Dt(e),o=Dt(t);return jt.join(m.sessionDir,`${n}-${o}.jsonl`)}async function te(e,t){let n=Fe(e,t);try{await Ot.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function Et(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 Me(e){await z(m.sessionDir);let t=Se.get(e);if(t)return t;let n=Ft(e);try{let o=await Ot.readFile(n,"utf8"),r=JSON.parse(o),s=Et(e,r);return Se.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=Et(e,{});return Se.set(e,r),r}throw o}}async function C(e){await z(m.sessionDir);let t=Ft(e.chatId);await Ge(t,e),Se.set(e.chatId,e)}function ze(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function Ne(e){return[]}function ve(e,t){if(Object.keys(e.sessions).length>=m.maxSessions)throw new Error("Max sessions reached");let o=ie(),r=N(),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 zt(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function ne(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function Ie(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function Nt(e){e.messages=[],e.updatedAt=N()}function Le(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=N()}function It(e,t){e.workspaceDir=t}var Se,Ue=H(()=>{"use strict";V();Y();Se=new Map});import{createAgentSession as mo,discoverAuthStorage as go,discoverModels as po,SessionManager as fo,SettingsManager as yo}from"@mariozechner/pi-coding-agent";import ke from"node:fs/promises";import Lt from"node:path";function Ut(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function wo(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 bo(e,t){return e!=="openai-codex"?t:ho[t]??t}function xo(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 So(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=Ut(t?.provider||m.modelProvider||"openai-codex"),s=n||o?"":m.modelRef||"",{provider:i,modelId:l}=wo(s,r),a=t?.provider?r:Ut(i),u=o?t?.modelId?.trim()||"":l;if(!u){let g=xo(e,a);return g?{model:g,provider:a,modelId:g.id}:{model:void 0,provider:a,modelId:""}}let c=bo(a,u);return{model:e.find(a,c),provider:a,modelId:c}}function Mo(e){let t=Z();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function vo(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(`
24
+ ${n}`}function wo(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:yo,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 i=l.find(u=>u.name===a);if(!i)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 ${i.name} ${n.method}...`}],details:{server:i.name,type:i.type,target:ee(i),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let u=await ke(i,n.method,n.params??{},{timeoutMs:Et(void 0),maxBytes:Dt(void 0),signal:s});return{content:[{type:"text",text:ho(i,{server:i.name,type:i.type,target:ee(i),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:i.name,type:i.type,target:ee(i),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:i.name,type:i.type,target:ee(i),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function xo(e){let t=[d.workspaceDir,V.join(d.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:bo,execute:async(n,o)=>{let r=Ot(o.path,t,d.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 It(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 So(e){let t=[d.workspaceDir,V.join(d.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:vo,execute:async(n,o)=>{let r=Ot(o.path,t,d.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 It(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 Lt(e){let t=[fo()];return e?.telegram&&(t.push(xo(e.telegram)),t.push(So(e.telegram))),Se(d.agentDir).length>0&&t.push(wo(()=>ue(d.agentDir))),t}var io,ao,po,yo,bo,vo,jt=W(()=>{"use strict";G();Me();Z();io=2e5,ao=6e4;po=x.Object({url:x.String({description:"HTTP or HTTPS URL"}),method:x.Optional(x.String({description:"HTTP method (default: GET)"})),headers:x.Optional(x.Array(x.Object({name:x.String({description:"Header name"}),value:x.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:x.Optional(x.String({description:"Request body (string)"})),timeoutMs:x.Optional(x.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:x.Optional(x.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});yo=x.Object({server:x.Optional(x.String({description:"MCP server name"})),method:x.String({description:"MCP method name"}),params:x.Optional(x.Any({description:"MCP params payload"}))});bo=x.Object({path:x.String({description:"Image file path (relative to workspace or uploads)."}),caption:x.Optional(x.String({description:"Caption text (plain text)."}))}),vo=x.Object({path:x.String({description:"File path (relative to workspace or uploads)."}),caption:x.Optional(x.String({description:"Caption text (plain text)."}))})});import zt from"node:fs/promises";import Ut from"node:path";function Bt(e){return Ut.join(d.sessionDir,`${e}.json`)}function Nt(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function ze(e,t){let n=Nt(e),o=Nt(t);return Ut.join(d.sessionDir,`${n}-${o}.jsonl`)}async function se(e,t){let n=ze(e,t);try{await zt.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function Ft(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 Ae(e){await D(d.sessionDir);let t=_e.get(e);if(t)return t;let n=Bt(e);try{let o=await zt.readFile(n,"utf8"),r=JSON.parse(o),s=Ft(e,r);return _e.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=Ft(e,{});return _e.set(e,r),r}throw o}}async function C(e){await D(d.sessionDir);let t=Bt(e.chatId);await Ze(t,e),_e.set(e.chatId,e)}function Ue(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function Be(e){return[]}function Pe(e,t){if(Object.keys(e.sessions).length>=d.maxSessions)throw new Error("Max sessions reached");let o=ce(),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 Wt(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function te(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function We(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function Ht(e){e.messages=[],e.updatedAt=F()}function He(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=F()}function qt(e,t){e.workspaceDir=t}var _e,qe=W(()=>{"use strict";G();Z();_e=new Map});import ko from"node:fs/promises";import Kt from"node:path";import{completeSimple as Mo}from"@mariozechner/pi-ai";function Po(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return Ao.replace("{{command}}",n)}function To(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 Co(e,t,n,o){let r=Po(n,o);try{let l=(await Mo(e,{messages:[{role:"user",content:r,timestamp:Date.now()}]},{apiKey:t,maxTokens:500,temperature:0})).content.find(i=>i.type==="text"),a=l?.type==="text"?l.text:"";return To(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 Ro(e,t){let n=e.trim();return t.some(o=>o.test(n))}function Eo(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 Y(e,t,n){try{await D(Jt);let o=Kt.join(Jt,`${e}-${t}.log`),r=JSON.stringify(n)+`
25
+ `;await ko.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 Do(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 Gt(e,t){let n=d.audit,o=Eo(n.whitelistPatterns);return r=>{r.on("tool_call",async(s,l)=>{let{toolName:a,toolCallId:i,input:u}=s,c={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:a,toolCallId:i,input:u,riskLevel:"none",analysis:"",action:"passed"};if($o.has(a)){c.analysis="Read-only tool",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=passed (read-only)`);return}if(!_o.has(a)){c.analysis="Tool not in analysis scope",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=passed (not analyzed)`);return}if(a==="bash"){let g=u.command??"";if(Ro(g,o)){c.analysis="Whitelisted bash command",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=passed (whitelisted)`);return}}if(!t){c.analysis="No audit model configured",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=passed (no audit model)`);return}console.log(`[audit] analyzing tool=${a} id=${i}`);let m=await Co(t.model,t.apiKey,a,u);if(c.riskLevel=m.riskLevel,c.analysis=m.reason,m.riskLevel==="none"||m.riskLevel==="low"){c.action="passed",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} risk=${m.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${a} id=${i} reason=${m.reason}`);try{let g=Do(c);if(await e.requestConfirmation(g,n.confirmTimeoutMs)){c.action="approved",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=approved`);return}return c.action="blocked",await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} 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 c.action="blocked",c.analysis=`${m.reason} (confirmation failed: ${p})`,await Y(e.chatId,e.sessionId,c),console.log(`[audit] tool=${a} id=${i} action=blocked (${p})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${p}`}}})}}var $o,_o,Ao,Jt,Vt=W(()=>{"use strict";G();Z();$o=new Set(["read","ls","find","grep"]),_o=new Set(["bash"]),Ao=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
27
+
28
+ Command: {{command}}
29
+
30
+ Risk levels:
31
+ - "none": Safe (read-only, standard dev tools)
32
+ - "low": Minor risk (file writes, package installs)
33
+ - "critical": High risk (secrets exposure, destructive ops, network attacks, privilege escalation)
34
+
35
+ Reply format (ONLY this JSON, nothing else):
36
+ {"riskLevel":"none|low|critical","reason":"brief explanation"}`;Jt=Kt.join(d.sessionDir,"audit-logs")});import{createAgentSession as Oo,discoverAuthStorage as Io,discoverModels as Lo,SessionManager as jo,SettingsManager as No}from"@mariozechner/pi-coding-agent";import Te from"node:fs/promises";import Yt from"node:path";function Xt(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function zo(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 Uo(e,t){return e!=="openai-codex"?t:Fo[t]??t}function Bo(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 Wo(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=Xt(t?.provider||d.modelProvider||"openai-codex"),s=n||o?"":d.modelRef||"",{provider:l,modelId:a}=zo(s,r),i=t?.provider?r:Xt(l),u=o?t?.modelId?.trim()||"":a;if(!u){let g=Bo(e,i);return g?{model:g,provider:i,modelId:g.id}:{model:void 0,provider:i,modelId:""}}let c=Uo(i,u);return{model:e.find(i,c),provider:i,modelId:c}}function Ho(e){let t=oe();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function qo(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(`
16
37
 
17
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(`
18
39
 
19
- `):""}function ko(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,i=n?.errorMessage;if(typeof r=="string")return`${o}(text:${r.length}${s?`,stop=${s}`:""})`;if(Array.isArray(r)){let a=[`blocks:${r.map(u=>typeof u=="object"&&u&&"type"in u?String(u.type||"unknown"):typeof u).join(",")||"none"}`,s?`stop=${s}`:null,i?"error=1":null].filter(Boolean).join(",");return`${o}(${a})`}if(r==null){let l=["empty",s?`stop=${s}`:null,i?"error=1":null].filter(Boolean).join(",");return`${o}(${l})`}return`${o}(${typeof r}${s?`,stop=${s}`:""})`});return`messages=${e.length} last=[${t.join(" ")}]`}function _o(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
40
+ `):""}function Jo(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 i=[`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}(${i})`}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 Ko(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
41
+
42
+ Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function Go(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=qo(e[o]);if(r)return r}return""}function Vo(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function Qt(e){let t=e.workspaceDir||d.workspaceDir;await D(d.sessionDir),await D(d.agentDir),await D(t);let n=ze(e.chatId,e.sessionId),o=Io(d.agentDir),r=Ho(o);r&&console.log(`[tg-agent] codex oauth source=${r.source} expiresAt=${new Date(r.expiresAt).toISOString()}`);let s=Lo(o,d.agentDir),{model:l,provider:a,modelId:i}=Wo(s,{provider:e.modelProvider,modelId:e.modelId});i&&!l&&console.warn(`[tg-agent] model not found: ${a}/${i}`);let u=jo.open(n),c=No.create(t,d.agentDir);try{let y=Yt.join(d.agentDir,"skills"),b=Yt.join(t,".pi","skills"),_=await Te.access(y).then(()=>!0).catch(()=>!1),A=await Te.access(b).then(()=>!0).catch(()=>!1);if(_){let J=(await Te.readdir(y,{withFileTypes:!0})).filter(B=>B.isDirectory()).map(B=>B.name);console.log(`[tg-agent] skills directory found at ${y} with ${J.length} skill(s): ${J.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${y}`);if(A){let J=(await Te.readdir(b,{withFileTypes:!0})).filter(B=>B.isDirectory()).map(B=>B.name);console.log(`[tg-agent] workspace skills directory found at ${b} with ${J.length} skill(s): ${J.join(", ")}`)}let U=c.getSettings?.();if(U){let J=U.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${J}`)}}catch(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] skills check failed: ${b}`)}let m="";try{m=await de(d.agentDir,{timeoutMs:4e3,maxBytes:d.fetchMaxBytes,maxChars:3e3})}catch(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] mcp catalog error: ${b}`)}let g=[];if(d.audit.enabled&&e.auditContext){let y={...e.auditContext,sessionId:e.sessionId},b;if(d.audit.modelProvider&&d.audit.modelId){let _=s.find(d.audit.modelProvider,d.audit.modelId);if(_){let A=await o.getApiKey(d.audit.modelProvider);b={provider:d.audit.modelProvider,model:_,apiKey:A??void 0},console.log(`[tg-agent] audit model: ${d.audit.modelProvider}/${d.audit.modelId} apiKey=${A?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${d.audit.modelProvider}/${d.audit.modelId}`)}g.push(Gt(y,b)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let{session:p,modelFallbackMessage:h}=await Oo({cwd:t,agentDir:d.agentDir,authStorage:o,modelRegistry:s,model:l??void 0,sessionManager:u,settingsManager:c,customTools:Lt({telegram:e.telegram}),extensions:g.length>0?g:void 0,systemPrompt:y=>{let b=e.systemPrompt?.trim(),_=[y];return b&&_.push(b),m&&_.push(m),_.join(`
20
43
 
21
- Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function $o(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=vo(e[o]);if(r)return r}return""}function To(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function Bt(e){let t=e.workspaceDir||m.workspaceDir;await z(m.sessionDir),await z(m.agentDir),await z(t);let n=Fe(e.chatId,e.sessionId),o=go(m.agentDir),r=Mo(o);r&&console.log(`[tg-agent] codex oauth source=${r.source} expiresAt=${new Date(r.expiresAt).toISOString()}`);let s=po(o,m.agentDir),{model:i,provider:l,modelId:a}=So(s,{provider:e.modelProvider,modelId:e.modelId});a&&!i&&console.warn(`[tg-agent] model not found: ${l}/${a}`);let u=fo.open(n),c=yo.create(t,m.agentDir);try{let y=Lt.join(m.agentDir,"skills"),w=Lt.join(t,".pi","skills"),A=await ke.access(y).then(()=>!0).catch(()=>!1),R=await ke.access(w).then(()=>!0).catch(()=>!1);if(A){let K=(await ke.readdir(y,{withFileTypes:!0})).filter(U=>U.isDirectory()).map(U=>U.name);console.log(`[tg-agent] skills directory found at ${y} with ${K.length} skill(s): ${K.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${y}`);if(R){let K=(await ke.readdir(w,{withFileTypes:!0})).filter(U=>U.isDirectory()).map(U=>U.name);console.log(`[tg-agent] workspace skills directory found at ${w} with ${K.length} skill(s): ${K.join(", ")}`)}let L=c.getSettings?.();if(L){let K=L.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${K}`)}}catch(y){let w=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] skills check failed: ${w}`)}let d="";try{d=await le(m.agentDir,{timeoutMs:4e3,maxBytes:m.fetchMaxBytes,maxChars:3e3})}catch(y){let w=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] mcp catalog error: ${w}`)}let{session:g,modelFallbackMessage:p}=await mo({cwd:t,agentDir:m.agentDir,authStorage:o,modelRegistry:s,model:i??void 0,sessionManager:u,settingsManager:c,customTools:At({telegram:e.telegram}),systemPrompt:y=>{let w=e.systemPrompt?.trim(),A=[y];return w&&A.push(w),d&&A.push(d),A.join(`
44
+ `)}});try{let y=p.messages,b=y.some(E=>{let J=E.role,B=E.content;return J==="system"&&typeof B=="string"?B.toLowerCase().includes("compaction")||B.toLowerCase().includes("compact"):E.type==="compaction"||E.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof u}`),console.log(`[tg-agent] session messages count: ${y.length}`),console.log(`[tg-agent] compacting support detected: ${b||"unknown (will be detected during runtime)"}`);let A=typeof u.compact=="function",U=typeof u.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${A}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${U}`)}catch(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] compacting check failed: ${b}`)}h&&console.warn(`[tg-agent] modelFallback=${h}`);let k=!1,P=()=>{k=!0,p.abort()};e.onAbortReady?.(P);let S=d.logAgentEvents,I=d.logAgentStream,M=new Map,L=p.subscribe(y=>{switch(y.type){case"agent_start":S&&console.log(`[tg-agent] agent start session=${e.sessionId}`),j=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}`),j=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":S&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${y.toolResults.length}`),j=Date.now(),e.onStatus?.({type:"turn_end",toolResults:y.toolResults.length});break;case"message_start":{if(S){let b=y.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${b}`)}j=Date.now();{let b=y.message.role??"unknown";e.onStatus?.({type:"message_start",role:b})}break}case"message_end":{if(S){let b=y.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${b}`)}j=Date.now();{let b=y.message.role??"unknown";e.onStatus?.({type:"message_end",role:b})}break}case"message_update":{if(!I)break;if(y.assistantMessageEvent.type==="text_delta"){let _=(y.assistantMessageEvent.delta??"").length;_>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${_}`),j=Date.now()}y.assistantMessageEvent.type==="thinking_delta"&&(j=Date.now());break}case"tool_execution_start":{M.set(y.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${y.toolName} id=${y.toolCallId}`),ne+=1,j=Date.now(),e.onStatus?.({type:"tool_start",name:y.toolName,id:y.toolCallId,args:y.args});break}case"tool_execution_end":{let b=M.get(y.toolCallId),_=b?Date.now()-b:0;console.log(`[tg-agent] tool end name=${y.toolName} id=${y.toolCallId} ok=${!y.isError} durationMs=${_}`),M.delete(y.toolCallId),ne=Math.max(0,ne-1),j=Date.now(),e.onStatus?.({type:"tool_end",name:y.toolName,id:y.toolCallId,ok:!y.isError,durationMs:_});break}case"auto_compaction_start":{let b=y.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${b}`),j=Date.now();break}case"auto_compaction_end":{let b=y.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${b}`),j=Date.now();break}default:break}}),N=null,w=null,v=!1,$=0,Q=!1,j=Date.now(),ne=0;try{let y=Date.now();N=setInterval(()=>{let A=Date.now()-y;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${A} streaming=${p.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:A,streaming:p.isStreaming})},15e3),w=setInterval(()=>{if(v||ne>0)return;let A=Date.now()-j,U=p.isStreaming?d.modelTimeoutStreamingMs:d.modelTimeoutMs,E=Math.max(1e3,U);A>=E&&(v=!0,$=E,Q=p.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${A}`),p.abort())},2e3);try{if(await p.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),v)throw new Error(`Model request timed out after ${d.modelTimeoutMs}ms`)}catch(A){if(k)throw new Error("Cancelled by user.");if(v){let U=Q?" (streaming)":"",E=$||d.modelTimeoutMs;throw new Error(`Model request timed out after ${E}ms${U}`)}throw A}N&&clearInterval(N);let b=Vo(p.messages);if(b){let A=b?.stopReason,U=b?.errorMessage;if(A==="error"){let E=U?Ko(U):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${E}`),new Error(E)}}let _=Go(p.messages,p);if(!_){let A=Jo(p.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${A}`),new Error("No assistant response.")}return{text:_,sessionFile:n,sessionId:p.sessionId,modelProvider:p.model?.provider??a,modelId:p.model?.id??i,modelFallbackMessage:h}}finally{N&&clearInterval(N),w&&clearInterval(w),L(),u.flushPendingToolResults?.(),p.dispose()}}var Fo,Zt=W(()=>{"use strict";G();xe();jt();Me();Z();qe();Vt();Fo={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var Wr={};import Re from"node:path";import en from"node:fs/promises";import Yo from"node-telegram-bot-api";import{discoverAuthStorage as Xo,discoverModels as Qo}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Zo}from"@mariozechner/pi-ai";function tr(e,t){fe.set(e,t)}function Ve(e){fe.delete(e)}function nr(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 rr(){return Re.join(d.agentDir,"uploads")}function sr(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 ir(e){return!!e?.startsWith("image/")}function ar(e){switch(Re.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 cr(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 lr(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(cr(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
45
+ `)}function ur(e){let t=[];if(e.photo&&e.photo.length>0){let n=sr(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=rr();await D(t);let n=[],o=[];for(let r of e)try{let s=await R.downloadFile(r.fileId,t),l=await en.stat(s),a=r.fileName??Re.basename(s),i=r.mimeType??ar(s),u=r.kind==="photo"||ir(i),c={path:s,name:a,mimeType:i,bytes:l.size,isImage:u};if(n.push(c),u){let m=await en.readFile(s);o.push({type:"image",data:m.toString("base64"),mimeType:i??or})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function me(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 gr(e){if(me(e,"*")%2!==0||me(e,"_")%2!==0||me(e,"`")%2!==0)return!1;let r=me(e,"["),s=me(e,"]");return r===s}function pr(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(mr.has(n))return!1}return!0}function ln(e){let t=nr(d.telegramParseMode);return t?[t]:pr(e)?["MarkdownV2","Markdown"]:gr(e)?["Markdown"]:[]}function pe(e,t){let n=ge.get(e);return n?(clearTimeout(n.timeoutId),ge.delete(e),n.messageId&&R.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function tn(e,t,n,o,r){if(ge.has(e))throw new Error("Audit confirmation already pending.");let s=bn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await vn(t,n,s,r);return await new Promise((a,i)=>{let u=setTimeout(()=>{ge.delete(e),R.editMessageText(`${n}
22
46
 
23
- `)}});try{let y=g.messages,w=y.some(D=>{let K=D.role,U=D.content;return K==="system"&&typeof U=="string"?U.toLowerCase().includes("compaction")||U.toLowerCase().includes("compact"):D.type==="compaction"||D.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof u}`),console.log(`[tg-agent] session messages count: ${y.length}`),console.log(`[tg-agent] compacting support detected: ${w||"unknown (will be detected during runtime)"}`);let R=typeof u.compact=="function",L=typeof u.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${R}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${L}`)}catch(y){let w=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] compacting check failed: ${w}`)}p&&console.warn(`[tg-agent] modelFallback=${p}`);let h=!1,v=()=>{h=!0,g.abort()};e.onAbortReady?.(v);let M=m.logAgentEvents,_=m.logAgentStream,E=new Map,T=g.subscribe(y=>{switch(y.type){case"agent_start":M&&console.log(`[tg-agent] agent start session=${e.sessionId}`),P=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":M&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":M&&console.log(`[tg-agent] turn start session=${e.sessionId}`),P=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":M&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${y.toolResults.length}`),P=Date.now(),e.onStatus?.({type:"turn_end",toolResults:y.toolResults.length});break;case"message_start":{if(M){let w=y.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${w}`)}P=Date.now();{let w=y.message.role??"unknown";e.onStatus?.({type:"message_start",role:w})}break}case"message_end":{if(M){let w=y.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${w}`)}P=Date.now();{let w=y.message.role??"unknown";e.onStatus?.({type:"message_end",role:w})}break}case"message_update":{if(!_)break;if(y.assistantMessageEvent.type==="text_delta"){let A=(y.assistantMessageEvent.delta??"").length;A>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${A}`),P=Date.now()}y.assistantMessageEvent.type==="thinking_delta"&&(P=Date.now());break}case"tool_execution_start":{E.set(y.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${y.toolName} id=${y.toolCallId}`),se+=1,P=Date.now(),e.onStatus?.({type:"tool_start",name:y.toolName,id:y.toolCallId,args:y.args});break}case"tool_execution_end":{let w=E.get(y.toolCallId),A=w?Date.now()-w:0;console.log(`[tg-agent] tool end name=${y.toolName} id=${y.toolCallId} ok=${!y.isError} durationMs=${A}`),E.delete(y.toolCallId),se=Math.max(0,se-1),P=Date.now(),e.onStatus?.({type:"tool_end",name:y.toolName,id:y.toolCallId,ok:!y.isError,durationMs:A});break}case"auto_compaction_start":{let w=y.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${w}`),P=Date.now();break}case"auto_compaction_end":{let w=y.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${w}`),P=Date.now();break}default:break}}),$=null,W=null,b=!1,S=0,k=!1,P=Date.now(),se=0;try{let y=Date.now();$=setInterval(()=>{let R=Date.now()-y;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${R} streaming=${g.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:R,streaming:g.isStreaming})},15e3),W=setInterval(()=>{if(b||se>0)return;let R=Date.now()-P,L=g.isStreaming?m.modelTimeoutStreamingMs:m.modelTimeoutMs,D=Math.max(1e3,L);R>=D&&(b=!0,S=D,k=g.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${R}`),g.abort())},2e3);try{if(await g.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),b)throw new Error(`Model request timed out after ${m.modelTimeoutMs}ms`)}catch(R){if(h)throw new Error("Cancelled by user.");if(b){let L=k?" (streaming)":"",D=S||m.modelTimeoutMs;throw new Error(`Model request timed out after ${D}ms${L}`)}throw R}$&&clearInterval($);let w=To(g.messages);if(w){let R=w?.stopReason,L=w?.errorMessage;if(R==="error"){let D=L?_o(L):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${D}`),new Error(D)}}let A=$o(g.messages,g);if(!A){let R=ko(g.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${R}`),new Error("No assistant response.")}return{text:A,sessionFile:n,sessionId:g.sessionId,modelProvider:g.model?.provider??l,modelId:g.model?.id??a,modelFallbackMessage:p}}finally{$&&clearInterval($),W&&clearInterval(W),T(),u.flushPendingToolResults?.(),g.dispose()}}var ho,Wt=H(()=>{"use strict";V();ye();Rt();be();Y();Ue();ho={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var Mr={};import $e from"node:path";import Ht from"node:fs/promises";import Po from"node-telegram-bot-api";import{discoverAuthStorage as Co,discoverModels as Ao}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Ro}from"@mariozechner/pi-ai";function Eo(e,t){de.set(e,t)}function qe(e){de.delete(e)}function Oo(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 Fo(){return $e.join(m.agentDir,"uploads")}function zo(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 No(e){return!!e?.startsWith("image/")}function Io(e){switch($e.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 Lo(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 Uo(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(Lo(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
24
- `)}function Bo(e){let t=[];if(e.photo&&e.photo.length>0){let n=zo(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 Wo(e){if(e.length===0)return{resolved:[],images:[]};let t=Fo();await z(t);let n=[],o=[];for(let r of e)try{let s=await F.downloadFile(r.fileId,t),i=await Ht.stat(s),l=r.fileName??$e.basename(s),a=r.mimeType??Io(s),u=r.kind==="photo"||No(a),c={path:s,name:l,mimeType:a,bytes:i.size,isImage:u};if(n.push(c),u){let d=await Ht.readFile(s);o.push({type:"image",data:d.toString("base64"),mimeType:a??jo})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function ue(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 qo(e){if(ue(e,"*")%2!==0||ue(e,"_")%2!==0||ue(e,"`")%2!==0)return!1;let r=ue(e,"["),s=ue(e,"]");return r===s}function Ko(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Ho.has(n))return!1}return!0}function Qt(e){let t=Oo(m.telegramParseMode);return t?[t]:Ko(e)?["MarkdownV2","Markdown"]:qo(e)?["Markdown"]:[]}function re(e){let t=e.trim().toLowerCase();return Go.get(t)??t}function Xo(e,t){return e!=="openai-codex"?t:Vo[t]??t}async function oe(){await z(m.agentDir);let e=Co(m.agentDir),t=Z();t&&e.setRuntimeApiKey("openai-codex",t.accessToken);let n=Ao(e,m.agentDir);return{authStorage:e,modelRegistry:n}}function Yt(e){let t=X.get(e);t&&(clearTimeout(t.timeoutId),X.delete(e))}function Qo(e,t){let n=X.get(e);n&&(clearTimeout(n.timeoutId),X.delete(e),n.reject(new Error(t)))}async function qt(e,t,n,o){if(X.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,i)=>{let l=setTimeout(()=>{X.delete(e),i(new Error("Login prompt timed out."))},Jo);X.set(e,{resolve:s,reject:i,timeoutId:l,chatId:t})})}async function Zt(e,t,n){let o=de.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 en(e,t,n,o){let r=await Me(t),s=n||r.activeSessionId;if(!s){await f(e,"No active session to close.",o);return}let i=de.get(t);if(i){if(i.cancelRequested=!0,i.abortRequested=!0,i.status&&i.status.update("Cancelled by user.",!0),i.abort)try{i.abort()}catch(u){console.warn("[tg-agent] abort callback failed during force close",u)}qe(t)}if(!Ie(r,s)){await f(e,`Session not found: ${s}`,o);return}await C(r),await te(t,s).catch(u=>{console.warn(`[tg-agent] delete session file failed id=${s}`,u)});let a=i?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await f(e,a,o)}function Yo(){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=he(m.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${m.fetchMaxBytes} fetchTimeoutMs=${m.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${m.proxyUrl||"(none)"} fetchProxy=${m.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${m.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${m.tlsRejectUnauthorized===null?"(unset)":String(m.tlsRejectUnauthorized)}`);try{let{source:o}=ut(m.modelProvider);console.log(`[tg-agent] authSource=${o}`)}catch(o){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] authSource=missing (${r})`)}let n=mt();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function Ke(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 Kt(e,t,n){let o=ne(e);return o||(o=ve(e,""),await C(e),await f(t,`Created session ${o.id}.`,n)),o}function Zo(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()).sort((r,s)=>r[0].localeCompare(s[0])).map(([r,s])=>({label:`${r} (${s.count}, ${s.auth?"ok":"no auth"})`,command:`/provider ${r}`}))}function er(e,t,n=[]){let o=e.getAll().filter(l=>l.provider===t).sort((l,a)=>l.id.localeCompare(a.id));if(n.length===0)return o.map(l=>({label:l.id,command:`/model ${t}/${l.id}`}));let r=new Map(o.map(l=>[l.id,l])),s=new Set,i=[];for(let l of n){let a=r.get(l);!a||s.has(a.id)||(s.add(a.id),i.push(a))}for(let l of o)s.has(l.id)||i.push(l);return i.map(l=>({label:l.id,command:`/model ${t}/${l.id}`}))}function tr(e,t,n=3){let o=new Set,r=[],s=ze(e);for(let i of s){if(i.modelProvider!==t)continue;let l=i.modelId;if(!(!l||o.has(l))&&(o.add(l),r.push(l),r.length>=n))break}return r}function nr(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:re(n),modelId:o.trim()}}return{modelId:t}}function tn(e,t){let n=Date.now(),o=Jt.get(e)??0;n-o<or||(Jt.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function nn(e){let t=m.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function rr(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(`
25
- `)}function Te(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function He(e,t){if(t.workspaceDir)return t.workspaceDir;let n=m.workspaceMappings.get(e);return n||m.workspaceDir}async function on(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await F.sendMessage(e,t,r)}async function rn(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 F.editMessageText(n,s)}async function sn(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 sr(e,t,n){return await sn(o=>on(e,t,o,n),Qt(t))}async function ir(e,t,n,o){await sn(r=>rn(e,t,n,r,o),Qt(n))}async function f(e,t,n){let o=Ve(t,3900);for(let r of o)await sr(e,r,n)}function cr(){let e=N()-an;for(let[o,r]of q)r.createdAt<e&&q.delete(o);if(q.size<=Gt)return;let t=Array.from(q.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=q.size-Gt;for(let o=0;o<n;o+=1)q.delete(t[o][0])}function lr(e){cr();let t=ie();for(;q.has(t);)t=ie();return q.set(t,{command:e,createdAt:N()}),t}function ur(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=q.get(t);return n?N()-n.createdAt>an?(q.delete(t),null):n.command:null}function dr(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 mr(e,t){let n=[],o=[];for(let r of e){let s=lr(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 gr(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await F.sendMessage(e,t,r)}async function Vt(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??ar,i=o?.footer,l=o?.messageThreadId,a=dr(n,s);for(let u=0;u<a.length;u+=1){let c=a[u],d=a.length>1?` (page ${u+1}/${a.length})`:"",g=[`${t}${d}`];i&&g.push(i);let p=mr(c,r);await gr(e,g.join(`
26
- `),p,l)}}function We(e,t=pr){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
47
+ [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),i(new Error("Audit confirmation timed out."))},o);ge.set(e,{resolve:a,reject:i,timeoutId:u,chatId:t,messageThreadId:r,messageId:l.message_id})})}function ae(e){let t=e.trim().toLowerCase();return yr.get(t)??t}function wr(e,t){return e!=="openai-codex"?t:hr[t]??t}async function ie(){await D(d.agentDir);let e=Xo(d.agentDir),t=oe();t&&e.setRuntimeApiKey("openai-codex",t.accessToken);let n=Qo(e,d.agentDir);return{authStorage:e,modelRegistry:n}}function un(e){let t=X.get(e);t&&(clearTimeout(t.timeoutId),X.delete(e))}function br(e,t){let n=X.get(e);n&&(clearTimeout(n.timeoutId),X.delete(e),n.reject(new Error(t)))}async function nn(e,t,n,o){if(X.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(()=>{X.delete(e),l(new Error("Login prompt timed out."))},fr);X.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function dn(e,t,n){let o=fe.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 Ae(t),s=n||r.activeSessionId;if(!s){await f(e,"No active session to close.",o);return}let l=fe.get(t);if(l){if(l.cancelRequested=!0,l.abortRequested=!0,l.status&&l.status.update("Cancelled by user.",!0),l.abort)try{l.abort()}catch(u){console.warn("[tg-agent] abort callback failed during force close",u)}Ve(t)}if(!We(r,s)){await f(e,`Session not found: ${s}`,o);return}await C(r),await se(t,s).catch(u=>{console.warn(`[tg-agent] delete session file failed id=${s}`,u)});let i=l?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await f(e,i,o)}function vr(){console.log(`[tg-agent] modelProvider=${d.modelProvider} modelRef=${d.modelRef} sessionDir=${d.sessionDir} maxConcurrent=${d.maxConcurrent}`),console.log(`[tg-agent] agentDir=${d.agentDir} workspaceDir=${d.workspaceDir}`);let e=Se(d.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${d.fetchMaxBytes} fetchTimeoutMs=${d.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${d.proxyUrl||"(none)"} fetchProxy=${d.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${d.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${d.tlsRejectUnauthorized===null?"(unset)":String(d.tlsRejectUnauthorized)}`);try{let{source:o}=yt(d.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=wt();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function Ye(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 on(e,t,n){let o=te(e);return o||(o=Pe(e,""),await C(e),await f(t,`Created session ${o.id}.`,n)),o}function Sr(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])=>xr.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 kr(e,t,n=[]){let o=e.getAll().filter(a=>a.provider===t).sort((a,i)=>a.id.localeCompare(i.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 i=r.get(a);!i||s.has(i.id)||(s.add(i.id),l.push(i))}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 Mr(e,t,n=3){let o=new Set,r=[],s=Ue(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 $r(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:ae(n),modelId:o.trim()}}return{modelId:t}}function gn(e,t){let n=Date.now(),o=rn.get(e)??0;n-o<_r||(rn.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function pn(e){let t=d.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function Ar(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(`
48
+ `)}function Ee(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function Ge(e,t){if(t.workspaceDir)return t.workspaceDir;let n=d.workspaceMappings.get(e);return n||d.workspaceDir}async function fn(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await R.sendMessage(e,t,r)}async function yn(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 R.editMessageText(n,s)}async function hn(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 Pr(e,t,n){return await hn(o=>fn(e,t,o,n),ln(t))}async function Tr(e,t,n,o){await hn(r=>yn(e,t,n,r,o),ln(n))}async function f(e,t,n){let o=et(t,3900);for(let r of o)await Pr(e,r,n)}function Rr(){let e=F()-wn;for(let[o,r]of q)r.createdAt<e&&q.delete(o);if(q.size<=sn)return;let t=Array.from(q.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=q.size-sn;for(let o=0;o<n;o+=1)q.delete(t[o][0])}function Er(e){Rr();let t=ce();for(;q.has(t);)t=ce();return q.set(t,{command:e,createdAt:F()}),t}function Dr(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=q.get(t);return n?F()-n.createdAt>wn?(q.delete(t),null):n.command:null}function Or(e,t){if(e.length<=t)return[e];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}function bn(e,t){let n=[],o=[];for(let r of e){let s=Er(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 vn(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await R.sendMessage(e,t,r)}async function an(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??Cr,l=o?.footer,a=o?.messageThreadId,i=Or(n,s);for(let u=0;u<i.length;u+=1){let c=i[u],m=i.length>1?` (page ${u+1}/${i.length})`:"",g=[`${t}${m}`];l&&g.push(l);let p=bn(c,r);await vn(e,g.join(`
49
+ `),p,a)}}function Ke(e,t=Ir){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
27
50
 
28
- [truncated]`,truncated:!0}}async function yr(e,t){let n="Working...",r=(await on(e,n,void 0,t)).message_id,s=n,i=0,l=Promise.resolve(),a=(c,d=!1)=>{let g=Date.now();!d&&g-i<fr||c!==s&&(s=c,i=g,l=l.then(async()=>{await rn(e,r,c,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},u=c=>{s=c,i=Date.now(),l=l.then(async()=>{await ir(e,r,c,t)}).catch(d=>{console.warn("[tg-agent] status edit failed",d)})};return{update:(c,d=!1)=>{let g=We(c).text;a(g,d)},finalize:async c=>{let d=We(c).text;u(d),await l},fail:async c=>{let d=We(c).text;u(d),await l}}}function hr(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
29
- args: ${wr(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 wr(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,i=(u,c)=>{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(c>=s)return"[truncated]";if(t.add(u),Array.isArray(u)){let p=u.slice(0,r).map(h=>i(h,c+1));return u.length>r&&p.push("[truncated]"),p}let d=Object.entries(u),g={};for(let[p,h]of d.slice(0,o))g[p]=i(h,c+1);return d.length>o&&(g._truncated=!0),g},l=i(e,0),a=JSON.stringify(l);return a?a.length>700?`${a.slice(0,700)}...`:a:"null"}catch{return"[unavailable]"}}function Pe(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 br(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function xr(){let e=await ce(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=>vt(o))),n=["MCP servers:"];for(let o=0;o<e.length;o+=1){let r=e[o],s=t[o],i=s.ok?"ok":`error: ${br(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${Q(r)} status=${i} (${s.durationMs}ms)`)}return n.join(`
30
- `)}async function cn(e,t,n,o,r){let s=r,l=Te(e,s,s!==void 0);if(!l)return;let a=await Me(l),u=Ne(a);switch(u.length>0&&(await C(a),await Promise.all(u.map(c=>te(l,c).catch(d=>{console.warn(`[tg-agent] cleanup session file failed id=${c}`,d)})))),n){case"start":case"help":{let c=["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","","Tips:","Send images or files to attach them to the prompt."].join(`
31
- `);await f(e,c,r);return}case"new":{try{let d=ve(a,o||"");await C(a),await f(e,`Created session ${d.id} (${d.title}).`,r)}catch(c){await f(e,c.message,r)}return}case"list":{await C(a),await f(e,rr(ze(a)),r);return}case"use":{if(!o){await f(e,"Usage: /use <id>",r);return}if(!zt(a,o)){await f(e,`Session not found: ${o}`,r);return}await C(a),await f(e,`Active session set to ${o}.`,r);return}case"close":{let c=o||a.activeSessionId;if(!c){await f(e,"No active session to close.",r);return}let d=de.get(l);if(d){if(d.cancelRequested=!0,d.abortRequested=!0,d.status&&d.status.update("Cancelled by user.",!0),d.abort)try{d.abort()}catch(h){console.warn("[tg-agent] abort callback failed during force close",h)}qe(l)}if(!Ie(a,c)){await f(e,`Session not found: ${c}`,r);return}await C(a),await te(l,c).catch(h=>{console.warn(`[tg-agent] delete session file failed id=${c}`,h)});let p=d?`Force-closed session ${c} (interrupted running task).`:`Closed session ${c}.`;await f(e,p,r);return}case"reset":{let c=ne(a);if(!c){await f(e,"No active session.",r);return}Nt(c),await C(a),await te(l,c.id).catch(d=>{console.warn(`[tg-agent] reset session file failed id=${c.id}`,d)}),await f(e,`Reset session ${c.id}.`,r);return}case"workspace":{if(!o){let d=He(l,a),g=a.workspaceDir?"chat":m.workspaceMappings.has(l)?"config":"default";await f(e,`Workspace: ${d} (source: ${g})`,r);return}let c=$e.resolve(B(o.trim()));It(a,c),await C(a),await f(e,`Workspace set to: ${c}`,r);return}case"providers":{let{authStorage:c,modelRegistry:d}=await oe(),g=d.getError(),p=Zo(d,c);if(p.length===0){let v=g?`Warning: ${g}
51
+ [truncated]`,truncated:!0}}async function jr(e,t){let n="Working...",r=(await fn(e,n,void 0,t)).message_id,s=n,l=0,a=Promise.resolve(),i=(c,m=!1)=>{let g=Date.now();!m&&g-l<Lr||c!==s&&(s=c,l=g,a=a.then(async()=>{await yn(e,r,c,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},u=c=>{s=c,l=Date.now(),a=a.then(async()=>{await Tr(e,r,c,t)}).catch(m=>{console.warn("[tg-agent] status edit failed",m)})};return{update:(c,m=!1)=>{let g=Ke(c).text;i(g,m)},finalize:async c=>{let m=Ke(c).text;u(m),await a},fail:async c=>{let m=Ke(c).text;u(m),await a}}}function Nr(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
52
+ args: ${Fr(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 Fr(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,l=(u,c)=>{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(c>=s)return"[truncated]";if(t.add(u),Array.isArray(u)){let p=u.slice(0,r).map(h=>l(h,c+1));return u.length>r&&p.push("[truncated]"),p}let m=Object.entries(u),g={};for(let[p,h]of m.slice(0,o))g[p]=l(h,c+1);return m.length>o&&(g._truncated=!0),g},a=l(e,0),i=JSON.stringify(a);return i?i.length>700?`${i.slice(0,700)}...`:i:"null"}catch{return"[unavailable]"}}function De(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 zr(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function Ur(){let e=await ue(d.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=>Tt(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: ${zr(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${ee(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
53
+ `)}async function Xe(e,t,n,o,r){let s=r,a=Ee(e,s,s!==void 0);if(!a)return;let i=await Ae(a),u=Be(i);switch(u.length>0&&(await C(i),await Promise.all(u.map(c=>se(a,c).catch(m=>{console.warn(`[tg-agent] cleanup session file failed id=${c}`,m)})))),n){case"start":case"help":{let c=["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(`
54
+ `);await f(e,c,r);return}case"new":{try{let c=o||"",m=te(i),g=m?.modelProvider,p=m?.modelId,h=Pe(i,c);g&&(h.modelProvider=g,p&&(h.modelId=p)),await C(i),await f(e,`Created session ${h.id} (${h.title}).`,r)}catch(c){await f(e,c.message,r)}return}case"list":{await C(i),await f(e,Ar(Ue(i)),r);return}case"use":{if(!o){await f(e,"Usage: /use <id>",r);return}if(!Wt(i,o)){await f(e,`Session not found: ${o}`,r);return}await C(i),await f(e,`Active session set to ${o}.`,r);return}case"close":{let c=o||i.activeSessionId;if(!c){await f(e,"No active session to close.",r);return}let m=fe.get(a);if(m){if(m.cancelRequested=!0,m.abortRequested=!0,m.status&&m.status.update("Cancelled by user.",!0),m.abort)try{m.abort()}catch(h){console.warn("[tg-agent] abort callback failed during force close",h)}Ve(a)}if(!We(i,c)){await f(e,`Session not found: ${c}`,r);return}await C(i),await se(a,c).catch(h=>{console.warn(`[tg-agent] delete session file failed id=${c}`,h)});let p=m?`Force-closed session ${c} (interrupted running task).`:`Closed session ${c}.`;await f(e,p,r);return}case"reset":{let c=te(i);if(!c){await f(e,"No active session.",r);return}Ht(c),await C(i),await se(a,c.id).catch(m=>{console.warn(`[tg-agent] reset session file failed id=${c.id}`,m)}),await f(e,`Reset session ${c.id}.`,r);return}case"workspace":{if(!o){let m=Ge(a,i),g=i.workspaceDir?"chat":d.workspaceMappings.has(a)?"config":"default";await f(e,`Workspace: ${m} (source: ${g})`,r);return}let c=Re.resolve(H(o.trim()));qt(i,c),await C(i),await f(e,`Workspace set to: ${c}`,r);return}case"providers":{let{authStorage:c,modelRegistry:m}=await ie(),g=m.getError(),p=Sr(m,c);if(p.length===0){let k=g?`Warning: ${g}
32
55
 
33
- No providers found.`:"No providers found.";await f(e,v,r);return}let h=[];g&&h.push(`Warning: ${g}`),h.push("Providers:"),await Vt(e,h.join(`
34
- `),p,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:c,modelRegistry:d}=await oe(),g=o?re(o):"";if(!g){let M=ne(a);if(!M?.modelProvider){await f(e,"Usage: /models <provider>",r);return}g=M.modelProvider}let p=c.hasAuth(g),h=tr(a,g),v=er(d,g,h);if(v.length===0){await f(e,`No models found for provider ${g}.`,r);return}await Vt(e,`Models for ${g} (auth: ${p?"ok":"missing"}):`,v,{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 c=re(o),{modelRegistry:d}=await oe();if(!d.getAll().some(h=>h.provider===c)){await f(e,`Unknown provider: ${c}`,r);return}let p=await Kt(a,e,r);p.modelProvider=c,p.modelId=void 0,p.updatedAt=N(),await C(a),await f(e,`Session ${p.id} provider set to ${c}.`,r);return}case"model":{let c=nr(o);if(!c){await f(e,"Usage: /model <provider>/<model>",r);return}let d=await Kt(a,e,r),g=re(c.provider??d.modelProvider??"");if(!g){await f(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await oe(),h=Xo(g,c.modelId);if(!p.find(g,h)){await f(e,`Model not found: ${g}/${h}`,r);return}d.modelProvider=g,d.modelId=h,d.updatedAt=N(),await C(a),await f(e,`Session ${d.id} model set to ${g}/${h}.`,r);return}case"status":{let c=ne(a);if(!c){await f(e,"No active session.",r);return}let d=m.modelRef.includes("/")?m.modelRef:`${m.modelProvider}/${m.modelRef}`,g=c.modelProvider||c.modelId?`Model: ${c.modelProvider??"?"}/${c.modelId??"?"}`:`Model: ${d} (default)`,p=He(l,a),h=a.workspaceDir?"chat":m.workspaceMappings.has(l)?"config":"default",v=[`Session: ${c.id} (${c.title})`,g,`Workspace: ${p} (${h})`].join(`
35
- `);await f(e,v,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Mt(),await le(m.agentDir,{timeoutMs:5e3,maxBytes:m.fetchMaxBytes,maxChars:3e3}),je(),await f(e,"MCP catalog refreshed.",r);return}let c=await xr();await f(e,c,r);return}case"login":{let c=Ro();if(!o){let p=c.map(h=>`- ${h.id} (${h.name})`);await f(e,["OAuth providers:",...p].join(`
36
- `),r);return}let d=re(o);if(Be.has(t)){await f(e,"Login already in progress.",r);return}let g=c.find(p=>p.id===d);if(!g){await f(e,`Unknown OAuth provider: ${d}`,r);return}Be.add(t);try{let{authStorage:p}=await oe();await f(e,`Starting login for ${g.id}...`,r),await p.login(g.id,{onAuth:({url:h,instructions:v})=>{let M=["Open this URL in your browser:",h];v&&M.push("",v),f(e,M.join(`
37
- `),r)},onPrompt:h=>qt(t,e,h,r),onProgress:h=>{f(e,h,r)},onManualCodeInput:()=>qt(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let h=Pe(p);await f(e,`Login failed: ${h}`,r)}finally{Be.delete(t),Yt(t)}return}case"logout":{if(!o){await f(e,"Usage: /logout <provider>",r);return}let c=re(o),{authStorage:d}=await oe();d.logout(c),await f(e,`Logged out from ${c}.`,r);return}default:await f(e,`Unknown command: ${n}`,r)}}async function Sr(e,t,n,o=[],r){let s=Ke(n);if(s){await cn(e,t,s.command,s.args,r);return}let l=Te(e,r,r!==void 0);if(!l)return;let a=await Me(l),u=Ne(a);u.length>0&&(await C(a),await Promise.all(u.map(T=>te(l,T).catch($=>{console.warn(`[tg-agent] cleanup session file failed id=${T}`,$)}))));let c=ne(a);if(!c)try{c=ve(a,""),await C(a),await f(e,`Created session ${c.id}.`,r)}catch(T){await f(e,T.message,r);return}let{resolved:d,images:g}=await Wo(o);if(o.length>0&&d.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=Uo(d),h=[];n.trim()&&h.push(n.trim()),p&&h.push(p);let v=h.join(`
56
+ No providers found.`:"No providers found.";await f(e,k,r);return}let h=[];g&&h.push(`Warning: ${g}`),h.push("Providers:"),await an(e,h.join(`
57
+ `),p,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:c,modelRegistry:m}=await ie(),g=o?ae(o):"";if(!g){let P=te(i);if(!P?.modelProvider){await f(e,"Usage: /models <provider>",r);return}g=P.modelProvider}let p=c.hasAuth(g),h=Mr(i,g),k=kr(m,g,h);if(k.length===0){await f(e,`No models found for provider ${g}.`,r);return}await an(e,`Models for ${g} (auth: ${p?"ok":"missing"}):`,k,{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 c=ae(o),{modelRegistry:m}=await ie();if(!m.getAll().some(h=>h.provider===c)){await f(e,`Unknown provider: ${c}`,r);return}let p=await on(i,e,r);p.modelProvider=c,p.modelId=void 0,p.updatedAt=F(),await C(i),await f(e,`Session ${p.id} provider set to ${c}.`,r),await Xe(e,t,"models",c,r);return}case"model":{let c=$r(o);if(!c){await f(e,"Usage: /model <provider>/<model>",r);return}let m=await on(i,e,r),g=ae(c.provider??m.modelProvider??"");if(!g){await f(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await ie(),h=wr(g,c.modelId);if(!p.find(g,h)){await f(e,`Model not found: ${g}/${h}`,r);return}m.modelProvider=g,m.modelId=h,m.updatedAt=F(),await C(i),await f(e,`Session ${m.id} model set to ${g}/${h}.`,r);return}case"status":{let c=te(i);if(!c){await f(e,"No active session.",r);return}let m=d.modelRef.includes("/")?d.modelRef:`${d.modelProvider}/${d.modelRef}`,g=c.modelProvider||c.modelId?`Model: ${c.modelProvider??"?"}/${c.modelId??"?"}`:`Model: ${m} (default)`,p=Ge(a,i),h=i.workspaceDir?"chat":d.workspaceMappings.has(a)?"config":"default",k=[`Session: ${c.id} (${c.title})`,g,`Workspace: ${p} (${h})`].join(`
58
+ `);await f(e,k,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Pt(),await de(d.agentDir,{timeoutMs:5e3,maxBytes:d.fetchMaxBytes,maxChars:3e3}),Fe(),await f(e,"MCP catalog refreshed.",r);return}let c=await Ur();await f(e,c,r);return}case"login":{let c=Zo();if(!o){let p=c.map(h=>`- ${h.id} (${h.name})`);await f(e,["OAuth providers:",...p].join(`
59
+ `),r);return}let m=ae(o);if(Je.has(t)){await f(e,"Login already in progress.",r);return}let g=c.find(p=>p.id===m);if(!g){await f(e,`Unknown OAuth provider: ${m}`,r);return}Je.add(t);try{let{authStorage:p}=await ie();await f(e,`Starting login for ${g.id}...`,r),await p.login(g.id,{onAuth:({url:h,instructions:k})=>{let P=["Open this URL in your browser:",h];k&&P.push("",k),f(e,P.join(`
60
+ `),r)},onPrompt:h=>nn(t,e,h,r),onProgress:h=>{f(e,h,r)},onManualCodeInput:()=>nn(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let h=De(p);await f(e,`Login failed: ${h}`,r)}finally{Je.delete(t),un(t)}return}case"logout":{if(!o){await f(e,"Usage: /logout <provider>",r);return}let c=ae(o),{authStorage:m}=await ie();m.logout(c),await f(e,`Logged out from ${c}.`,r);return}default:await f(e,`Unknown command: ${n}`,r)}}async function Br(e,t,n,o=[],r){let s=Ye(n);if(s){await Xe(e,t,s.command,s.args,r);return}let a=Ee(e,r,r!==void 0);if(!a)return;let i=await Ae(a),u=Be(i);u.length>0&&(await C(i),await Promise.all(u.map(M=>se(a,M).catch(L=>{console.warn(`[tg-agent] cleanup session file failed id=${M}`,L)}))));let c=te(i);if(!c)try{c=Pe(i,""),await C(i),await f(e,`Created session ${c.id}.`,r)}catch(M){await f(e,M.message,r);return}let{resolved:m,images:g}=await dr(o);if(o.length>0&&m.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=lr(m),h=[];n.trim()&&h.push(n.trim()),p&&h.push(p);let k=h.join(`
38
61
 
39
- `)||"Attachment received.",M={role:"user",content:v,ts:N()};Le(c,M,m.maxHistoryMessages),await C(a),console.log(`[tg-agent] request user=${t} chat=${l} session=${c.id} messages=${c.messages.length} textLen=${v.length} attachments=${d.length} provider=${c.modelProvider??"-"} model=${c.modelId??"-"}`);let _=null;try{_=await yr(e,r)}catch(T){console.warn("[tg-agent] status message failed",T)}let E={sessionId:c.id,chatId:e,messageThreadId:r,status:_,abortRequested:!1,cancelRequested:!1};Eo(l,E);try{let T=await Do(async()=>{let W=await Bt({chatId:l,sessionId:c.id,prompt:v,images:g,systemPrompt:m.systemPrompt,modelProvider:c.modelProvider,modelId:c.modelId,workspaceDir:He(l,a),telegram:{chatId:e,sendPhoto:async(b,S)=>{let k={};S&&(k.caption=S),r!==void 0&&(k.message_thread_id=r),await F.sendPhoto(e,b,k)},sendDocument:async(b,S)=>{let k={};S&&(k.caption=S),r!==void 0&&(k.message_thread_id=r),await F.sendDocument(e,b,k)}},onAbortReady:b=>{E.abort=b,E.abortRequested&&b()},onStatus:_?b=>{let S=hr(b);S&&_?.update(S)}:void 0});return console.log(`[tg-agent] response session=${c.id} model=${W.modelProvider}/${W.modelId} file=${W.sessionFile}`),W.text});if(E.cancelRequested){_?await _.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let $={role:"assistant",content:T,ts:N()};Le(c,$,m.maxHistoryMessages),await C(a),_?await _.finalize(T):await f(e,T,r)}catch(T){if(console.error("[tg-agent] runModel error",T),E.cancelRequested){_?await _.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let $=Pe(T);_?await _.fail(`Error: ${$}`):await f(e,`Error: ${$}`,r)}finally{qe(l)}}var F,Xt,Do,de,jo,Ho,Jo,X,Be,Go,Vo,_e,or,Jt,an,Gt,ar,q,pr,fr,ln=H(()=>{"use strict";V();De();yt();Wt();ye();be();Ue();Y();ct();F=new Po(m.telegramToken,{polling:!0}),Xt=Xe(),Do=Qe(m.maxConcurrent),de=new Map;jo="image/jpeg";Ho=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);Jo=600*1e3,X=new Map,Be=new Set,Go=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),Vo={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};Yo();z(m.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await le(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}`)}})();_e=ft();console.log(_e?`[tg-agent] fetchProxy=${_e.url} kind=${_e.kind} source=${_e.source}`:"[tg-agent] fetchProxy=(none)");or=6e4,Jt=new Map;an=1800*1e3,Gt=2e3,ar=60,q=new Map;pr=3900,fr=1200;F.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){F.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!nn(o)){tn(o,n),F.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){F.answerCallbackQuery(e.id);return}let r=ur(t);if(!r){F.answerCallbackQuery(e.id,{text:"Command expired."});return}F.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,i=e.message?.is_topic_message??!1,l=Te(n,s,i);if(!l)return;let a=Ke(r);if(a?.command==="stop"){Zt(n,l,s);return}if(a?.command==="close"){en(n,l,a.args,s);return}Xt(l,async()=>{if(!a){await f(n,"Invalid command.",s);return}await cn(n,o,a.command,a.args,s)}).catch(async u=>{console.error("[tg-agent] runModel error",u);let c=Pe(u);await f(n,`Error: ${c}`,s)})});F.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!nn(t)){tn(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=Te(n,o,r);if(!s)return;let i=(e.text??e.caption??"").trim(),l=Bo(e);if(!i&&l.length===0)return;let a=X.get(t);if(a){if(i==="/stop"||i==="/cancel"){Qo(t,"Login cancelled by user."),f(n,"Login cancelled.",o);return}if(!i){f(n,"Login expects a text response.",o);return}Yt(t),a.resolve(i);return}let u=Ke(i);if(u?.command==="stop"){Zt(n,s,o);return}if(u?.command==="close"){en(n,s,u.args,o);return}Xt(s,()=>Sr(n,t,i,l,o)).catch(async c=>{console.error("[tg-agent] runModel error",c);let d=Pe(c);await f(n,`Error: ${d}`,o)})});F.on("polling_error",e=>{console.error("Polling error",e)});console.log("tg-agent started")});V();import vr from"node:fs";import un from"node:path";import kr from"node:readline/promises";import{fileURLToPath as _r}from"node:url";var dn=process.argv.slice(2),mn=(e,t)=>dn.includes(e)||(t?dn.includes(t):!1),$r=mn("--help","-h"),Tr=mn("--version","-v"),Pr=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
40
- `),Cr=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=_r(import.meta.url),t=un.dirname(e),n=un.join(t,"..","package.json"),o=vr.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};$r&&(console.log(Pr),process.exit(0));Tr&&(console.log(Cr()),process.exit(0));async function Ar(){let e=kr.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function Rr(){let{configPath:e,data:t,exists:n}=ae(),o=nt(),r=n?t:o,s=ot(r,o);if(rt(r)){s&&await Re(e,r);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${e}.`),process.exit(1));let l=await Ar();l||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),st(r,l),await Re(e,r),console.log(`Saved config to ${e}.`)}async function Dr(){let{data:e}=ae(),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 Rr();await Dr();at();Promise.resolve().then(()=>ln());
62
+ `)||"Attachment received.",P={role:"user",content:k,ts:F()};He(c,P,d.maxHistoryMessages),await C(i),console.log(`[tg-agent] request user=${t} chat=${a} session=${c.id} messages=${c.messages.length} textLen=${k.length} attachments=${m.length} provider=${c.modelProvider??"-"} model=${c.modelId??"-"}`);let S=null;try{S=await jr(e,r)}catch(M){console.warn("[tg-agent] status message failed",M)}let I={sessionId:c.id,chatId:e,messageThreadId:r,status:S,abortRequested:!1,cancelRequested:!1};tr(a,I);try{let M=await er(async()=>{let N=await Qt({chatId:a,sessionId:c.id,prompt:k,images:g,systemPrompt:d.systemPrompt,modelProvider:c.modelProvider,modelId:c.modelId,workspaceDir:Ge(a,i),telegram:{chatId:e,sendPhoto:async(w,v)=>{let $={};v&&($.caption=v),r!==void 0&&($.message_thread_id=r),await R.sendPhoto(e,w,$)},sendDocument:async(w,v)=>{let $={};v&&($.caption=v),r!==void 0&&($.message_thread_id=r),await R.sendDocument(e,w,$)},sendMessage:async w=>{await f(e,w,r)},requestConfirmation:async(w,v)=>await tn(a,e,w,v,r)},auditContext:d.audit.enabled?{chatId:a,requestConfirmation:async(w,v)=>await tn(a,e,w,v,r),sendNotification:async w=>{await f(e,w,r)}}:void 0,onAbortReady:w=>{I.abort=w,I.abortRequested&&w()},onStatus:S?w=>{let v=Nr(w);v&&S?.update(v)}:void 0});return console.log(`[tg-agent] response session=${c.id} model=${N.modelProvider}/${N.modelId} file=${N.sessionFile}`),N.text});if(I.cancelRequested){S?await S.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let L={role:"assistant",content:M,ts:F()};He(c,L,d.maxHistoryMessages),await C(i),S?await S.finalize(M):await f(e,M,r)}catch(M){if(console.error("[tg-agent] runModel error",M),I.cancelRequested){S?await S.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let L=De(M);S?await S.fail(`Error: ${L}`):await f(e,`Error: ${L}`,r)}finally{Ve(a)}}var R,cn,er,fe,or,mr,fr,X,Je,ge,yr,hr,Ce,xr,_r,rn,wn,sn,Cr,q,Ir,Lr,xn=W(()=>{"use strict";G();Le();St();Zt();xe();Me();qe();Z();pt();R=new Yo(d.telegramToken,{polling:!0}),cn=tt(),er=nt(d.maxConcurrent),fe=new Map;or="image/jpeg";mr=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);fr=600*1e3,X=new Map,Je=new Set,ge=new Map;yr=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),hr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};vr();D(d.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await de(d.agentDir,{timeoutMs:3e3,maxBytes:d.fetchMaxBytes,maxChars:2e3}),Fe()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Ce=xt();console.log(Ce?`[tg-agent] fetchProxy=${Ce.url} kind=${Ce.kind} source=${Ce.source}`:"[tg-agent] fetchProxy=(none)");xr=new Set(["openai-codex","google-antigravity","anthropic"]);_r=6e4,rn=new Map;wn=1800*1e3,sn=2e3,Cr=60,q=new Map;Ir=3900,Lr=1200;R.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){R.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!pn(o)){gn(o,n),R.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){R.answerCallbackQuery(e.id);return}let r=Dr(t);if(!r){R.answerCallbackQuery(e.id,{text:"Command expired."});return}R.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,l=e.message?.is_topic_message??!1,a=Ee(n,s,l);if(!a)return;let i=Ye(r);if(i?.command==="stop"){pe(a,!1)?f(n,"Operation blocked.",s):dn(n,a,s);return}if(i?.command==="close"){mn(n,a,i.args,s);return}if(i?.command==="approve"){pe(a,!0)?f(n,"Operation approved.",s):f(n,"No pending audit confirmation.",s);return}cn(a,async()=>{if(!i){await f(n,"Invalid command.",s);return}await Xe(n,o,i.command,i.args,s)}).catch(async u=>{console.error("[tg-agent] runModel error",u);let c=De(u);await f(n,`Error: ${c}`,s)})});R.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!pn(t)){gn(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=Ee(n,o,r);if(!s)return;let l=(e.text??e.caption??"").trim(),a=ur(e);if(!l&&a.length===0)return;let i=X.get(t);if(i){if(l==="/stop"||l==="/cancel"){br(t,"Login cancelled by user."),f(n,"Login cancelled.",o);return}if(!l){f(n,"Login expects a text response.",o);return}un(t),i.resolve(l);return}let u=Ye(l);if(u?.command==="stop"){pe(s,!1),dn(n,s,o);return}if(u?.command==="close"){pe(s,!1),mn(n,s,u.args,o);return}if(u?.command==="approve"){pe(s,!0)?f(n,"Operation approved.",o):f(n,"No pending audit confirmation.",o);return}cn(s,()=>Br(n,t,l,a,o)).catch(async c=>{console.error("[tg-agent] runModel error",c);let m=De(c);await f(n,`Error: ${m}`,o)})});R.on("polling_error",e=>{console.error("Polling error",e)});console.log("tg-agent started")});G();import Hr from"node:fs";import Sn from"node:path";import qr from"node:readline/promises";import{fileURLToPath as Jr}from"node:url";var kn=process.argv.slice(2),Mn=(e,t)=>kn.includes(e)||(t?kn.includes(t):!1),Kr=Mn("--help","-h"),Gr=Mn("--version","-v"),Vr=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
63
+ `),Yr=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Jr(import.meta.url),t=Sn.dirname(e),n=Sn.join(t,"..","package.json"),o=Hr.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Kr&&(console.log(Vr),process.exit(0));Gr&&(console.log(Yr()),process.exit(0));async function Xr(){let e=qr.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function Qr(){let{configPath:e,data:t,exists:n}=le(),o=ct(),r=n?t:o,s=lt(r,o);if(ut(r)){s&&await Ie(e,r);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${e}.`),process.exit(1));let a=await Xr();a||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),dt(r,a),await Ie(e,r),console.log(`Saved config to ${e}.`)}async function Zr(){let{data:e}=le(),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 Qr();await Zr();gt();Promise.resolve().then(()=>xn());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tg-agent",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "Telegram Agent Bot",
5
5
  "type": "module",
6
6
  "bin": {