tg-agent 1.2.13 → 1.2.15

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