tg-agent 1.2.9 → 1.2.11
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.
- package/dist/cli.js +53 -30
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
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
|
|
2
|
+
var F=(e,t)=>()=>(e&&(t=e(e=0)),t);import Oe from"node:fs/promises";import Cn 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(Cn.homedir(),e.slice(1)):e}async function R(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,Rn)}function j(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 En(e){return new Set(lt(e))}function Dn(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 R(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=j(e,"telegram");return D(t.bot_token,"").trim()}function gt(e,t){let n=j(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function pt(e){let t=j(e,"telegram"),n=j(e,"model"),o=j(e,"paths"),r=j(e,"limits"),s=j(e,"timeouts"),l=j(e,"fetch"),c=j(e,"proxy"),a=j(e,"auth"),u=j(e,"logging"),i=j(e,"system"),m=j(e,"tls"),g=j(e,"workspace_mappings"),p=j(e,"security_audit"),h=D(o.workspace_dir,process.cwd()),v=D(o.session_dir,"~/.tg-agent/tg-sessions"),k=Dn(g),S=D(m.reject_unauthorized,""),P=S===""?null:we(S,!0);return{telegramToken:D(t.bot_token,"").trim(),telegramAllowedUsers:En(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(h)),workspaceMappings:k,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:P,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,Rn,at,On,d,K=F(()=>{"use strict";V();it="~/.tg-agent",Rn="config.toml",at=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
|
|
4
4
|
|
|
5
5
|
Important behavioral rules:
|
|
6
6
|
- Do NOT mention the name of your underlying framework, technical implementation, or any package names
|
|
@@ -9,21 +9,21 @@ Important behavioral rules:
|
|
|
9
9
|
- Focus on helping with tasks rather than discussing your technical stack or architecture
|
|
10
10
|
- Do not mention documentation paths or framework-specific resources unless directly relevant to the task
|
|
11
11
|
|
|
12
|
-
Be concise and practical in all responses.`;({data:
|
|
13
|
-
`);return
|
|
14
|
-
(truncated)`),
|
|
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
|
|
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
|
|
12
|
+
Be concise and practical in all responses.`;({data:On}=ue()),d=pt(On)});import{createHash as In}from"node:crypto";import ht from"node:fs";import Ln from"node:path";import{execSync as jn}from"node:child_process";function zn(){return Ln.join(d.codexHome,Nn)}function Un(e){return`cli|${In("sha256").update(e).digest("hex").slice(0,16)}`}function Bn(){if(process.platform!=="darwin")return null;let e=d.codexHome,t=Un(e);try{let n=jn(`security find-generic-password -s "${Fn}" -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 Wn(){let e=zn();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 Bn()??Wn()}var Nn,Fn,xe=F(()=>{"use strict";K();Nn="auth.json",Fn="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 Hn(){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=Hn();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 Le=F(()=>{"use strict";K();xe()});import{ProxyAgent as Kn,setGlobalDispatcher as qn}from"undici";function Mt(){if(xt)return je;xt=!0;let e=St();if(!e)return je=null,null;let t=new Kn(e.url);return qn(t),je=e,e}var xt,je,kt=F(()=>{"use strict";Le();xt=!1,je=null});import Jn from"node:fs";import Yn from"node:fs/promises";import Gn from"node:path";import Vn from"node:readline";import{spawn as Xn}from"node:child_process";import*as _t from"@iarna/toml";function Tt(e){return Gn.join(e,"config.toml")}function Me(e){let t=Tt(e);try{let n=Jn.readFileSync(t,"utf8");return Dt(n)}catch{return[]}}async function de(e){let t=Tt(e);try{let n=await Yn.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??Zn,r=t.maxChars??eo,s=t.timeoutMs??4e3,l=t.maxBytes??At,c=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let u of n){let i=await no(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??Qn,1e3,12e4),s=$t(o.maxBytes??At,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 so(e,s,l.signal),await ro(e,t,n,s,l.signal)):await co(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 no(e,t){try{let n=await ke(e,"tools/list",{},t);return oo(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 oo(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 ro(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});io(e.name,a);let u=await lo(a,o,r),i;try{i=JSON.parse(u.text)}catch{i=void 0}return ao(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 so(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(),to);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 io(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 ao(e,t){if(!t||typeof t!="object")return;let o=t.result;if(!o)return;let r=typeof o.sessionId=="string"&&o.sessionId||typeof o.session_id=="string"&&o.session_id;if(!r)return;let s=U.get(e)??{initializedAt:0};U.set(e,{...s,sessionId:r})}async function co(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let s=Date.now(),l=Xn(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=Vn.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 A=typeof x.id=="string"?x.id:typeof x.id=="number"?String(x.id):"";if(!A)return;let ee=a.get(A);ee&&(a.delete(A),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 h=w=>{let x=w===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let A of a.values())A.reject(new Error(x));a.clear()};l.once("exit",w=>h(w));let v=async(w,x)=>{let A=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,ee={jsonrpc:"2.0",id:A,method:w,params:x??{}};return await new Promise((oe,y)=>{a.set(A,{resolve:oe,reject:y}),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 k=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:!!k.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),k.error&&typeof k.error=="object"){let w=k.error.message??"MCP initialize failed.";throw c(),new Error(String(w))}let S={jsonrpc:"2.0",method:"notifications/initialized"};l.stdin?.write(`${JSON.stringify(S)}
|
|
16
|
+
`),fetch("http://127.0.0.1:7243/ingest/9e452bb4-cc67-4519-89fa-8fb51d810231",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({location:"mcp.ts:callStdioMcp:beforeMethod",message:"sending method request",data:{method:t,elapsed:Date.now()-s},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"C"})}).catch(()=>{});let P=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))]),P.error&&typeof P.error=="object"){let w=P.error.message??"MCP request failed.";throw new Error(String(w))}let _=JSON.stringify(P,null,2),E=_.length>o?_.slice(0,o):_;return _.length>o&&(u=!0),{ok:!0,output:E,durationMs:Date.now()-s,bytes:Math.min(_.length,o),truncated:u}}async function lo(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 h=Math.max(0,t-l);h>0&&(s.push(g.slice(0,h)),l+=h),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=_t.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 Qn,At,Zn,eo,se,Pt,U,to,$e=F(()=>{"use strict";Qn=6e4,At=2e5,Zn=40,eo=3500,se=null,Pt=!1,U=new Map,to=1500});import G from"node:path";import uo from"node:fs/promises";import{Type as M}from"@sinclair/typebox";function _e(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function po(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:go;return _e(e||t,1e3,12e4)}function It(e){let t=d.fetchMaxBytes>0?d.fetchMaxBytes:mo;return _e(e||t,1024,5e6)}function Lt(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 jt(e){try{let t=await uo.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function fo(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function yo(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 ho(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=yo(s,l);return{text:r.decode(a),bytes:l,truncated:c}}function wo(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
|
|
20
|
+
${t}`}function vo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:bo,execute:async(e,t,n,o,r)=>{if(!fo(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:po(t.headers),body:t.body,signal:c.signal}),m=await ho(i,l,r),g=i.headers.get("content-type");return{content:[{type:"text",text:wo({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 xo(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
|
|
25
|
-
`;await
|
|
26
|
-
`)}function
|
|
24
|
+
${n}`}function Mo(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:So,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:xo(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:ko,execute:async(n,o)=>{let r=Lt(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 jt(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 Ao(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:$o,execute:async(n,o)=>{let r=Lt(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 jt(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=[vo()];return e?.telegram&&(t.push(_o(e.telegram)),t.push(Ao(e.telegram))),Me(d.agentDir).length>0&&t.push(Mo(()=>de(d.agentDir))),t}var mo,go,bo,So,ko,$o,Ft=F(()=>{"use strict";K();$e();V();mo=2e5,go=6e4;bo=M.Object({url:M.String({description:"HTTP or HTTPS URL"}),method:M.Optional(M.String({description:"HTTP method (default: GET)"})),headers:M.Optional(M.Array(M.Object({name:M.String({description:"Header name"}),value:M.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:M.Optional(M.String({description:"Request body (string)"})),timeoutMs:M.Optional(M.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:M.Optional(M.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});So=M.Object({server:M.Optional(M.String({description:"MCP server name"})),method:M.String({description:"MCP method name"}),params:M.Optional(M.Any({description:"MCP params payload"}))});ko=M.Object({path:M.String({description:"Image file path (relative to workspace or uploads)."}),caption:M.Optional(M.String({description:"Caption text (plain text)."}))}),$o=M.Object({path:M.String({description:"File path (relative to workspace or uploads)."}),caption:M.Optional(M.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 R(d.sessionDir);let t=Ae.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 Ae.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=Ut(e,{});return Ae.set(e,r),r}throw o}}async function O(e){await R(d.sessionDir);let t=Ht(e.chatId);await tt(t,e),Ae.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 Ae,Ke=F(()=>{"use strict";K();V();Ae=new Map});import Po from"node:fs/promises";import Gt from"node:path";import{completeSimple as To}from"@mariozechner/pi-ai";function Do(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return Eo.replace("{{command}}",n)}function Oo(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 Io(e,t,n,o){let r=Do(n,o);try{let l=(await To(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 Oo(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 jo(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 R(Yt);let o=Gt.join(Yt,`${e}-${t}.log`),r=JSON.stringify(n)+`
|
|
25
|
+
`;await Po.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 No(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=jo(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(Co.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(!Ro.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 Io(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=No(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 Co,Ro,Eo,Yt,Xt=F(()=>{"use strict";K();V();Co=new Set(["read","ls","find","grep"]),Ro=new Set(["bash"]),Eo=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
|
|
27
27
|
|
|
28
28
|
Command: {{command}}
|
|
29
29
|
|
|
@@ -33,31 +33,54 @@ 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"}`;
|
|
36
|
+
{"riskLevel":"none|low|critical","reason":"brief explanation"}`;Yt=Gt.join(d.sessionDir,"audit-logs")});import{createAgentSession as Fo,discoverAuthStorage as zo,discoverModels as Uo,SessionManager as Bo,SettingsManager as Wo}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 Ko(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 qo(e,t){return e!=="openai-codex"?t:Ho[t]??t}function Jo(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=Zt(t?.provider||d.modelProvider||"openai-codex"),s=n||o?"":d.modelRef||"",{provider:l,modelId:c}=Ko(s,r),a=t?.provider?r:Zt(l),u=o?t?.modelId?.trim()||"":c;if(!u){let g=Jo(e,a);return g?{model:g,provider:a,modelId:g.id}:{model:void 0,provider:a,modelId:""}}let i=qo(a,u);return{model:e.find(a,i),provider:a,modelId:i}}function Go(e){let t=re();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function Vo(e){if(e?.role!=="assistant")return"";let n=e.content;if(typeof n=="string")return n.trim();if(!Array.isArray(n))return"";let o=n.filter(s=>typeof s=="object"&&s&&s.type==="text").map(s=>s.text??"").map(s=>s.trim()).filter(Boolean);if(o.length>0)return o.join(`
|
|
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
|
|
40
|
+
`):""}function Xo(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 Qo(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
|
|
42
|
+
Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function Zo(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=Vo(e[o]);if(r)return r}return""}function er(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 R(d.sessionDir),await R(d.agentDir),await R(t);let n=ze(e.chatId,e.sessionId),o=zo(d.agentDir),r=Go(o);r&&console.log(`[tg-agent] codex oauth source=${r.source} expiresAt=${new Date(r.expiresAt).toISOString()}`);let s=Uo(o,d.agentDir),{model:l,provider:c,modelId:a}=Yo(s,{provider:e.modelProvider,modelId:e.modelId});a&&!l&&console.warn(`[tg-agent] model not found: ${c}/${a}`);let u=Bo.open(n),i=Wo.create(t,d.agentDir);try{let y=Qt.join(d.agentDir,"skills"),b=Qt.join(t,".pi","skills"),T=await Ce.access(y).then(()=>!0).catch(()=>!1),C=await Ce.access(b).then(()=>!0).catch(()=>!1);if(T){let J=(await Ce.readdir(y,{withFileTypes:!0})).filter(W=>W.isDirectory()).map(W=>W.name);console.log(`[tg-agent] skills directory found at ${y} with ${J.length} skill(s): ${J.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${y}`);if(C){let J=(await Ce.readdir(b,{withFileTypes:!0})).filter(W=>W.isDirectory()).map(W=>W.name);console.log(`[tg-agent] workspace skills directory found at ${b} 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(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] skills check failed: ${b}`)}let m="";try{m=await me(d.agentDir,{timeoutMs:4e3,maxBytes:d.fetchMaxBytes,maxChars:3e3})}catch(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] mcp catalog error: ${b}`)}let g=[];if(d.audit.enabled&&e.auditContext){let y={...e.auditContext,sessionId:e.sessionId},b;if(d.audit.modelProvider&&d.audit.modelId){let T=s.find(d.audit.modelProvider,d.audit.modelId);if(T){let C=await o.getApiKey(d.audit.modelProvider);b={provider:d.audit.modelProvider,model:T,apiKey:C??void 0},console.log(`[tg-agent] audit model: ${d.audit.modelProvider}/${d.audit.modelId} apiKey=${C?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${d.audit.modelProvider}/${d.audit.modelId}`)}g.push(Vt(y,b)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let{session:p,modelFallbackMessage:h}=await Fo({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:y=>{let b=e.systemPrompt?.trim(),T=[y];return b&&T.push(b),m&&T.push(m),T.join(`
|
|
43
43
|
|
|
44
|
-
`)}});try{let y=p.messages,b=y.some(
|
|
45
|
-
`)}function ur(e){let t=[];if(e.photo&&e.photo.length>0){let n=sr(e.photo);n&&t.push({kind:"photo",fileId:n.file_id,fileSize:n.file_size})}if(e.document&&t.push({kind:"document",fileId:e.document.file_id,fileName:e.document.file_name,mimeType:e.document.mime_type,fileSize:e.document.file_size}),e.audio){let n=e.audio.mime_type?.split("/")[1]??"mp3",o=e.audio.title??e.audio.performer??"audio";t.push({kind:"document",fileId:e.audio.file_id,fileName:`${o}.${n}`,mimeType:e.audio.mime_type,fileSize:e.audio.file_size})}if(e.voice&&t.push({kind:"document",fileId:e.voice.file_id,fileName:`voice.${e.voice.mime_type?.split("/")[1]??"ogg"}`,mimeType:e.voice.mime_type,fileSize:e.voice.file_size}),e.video){let n=e.video.mime_type?.split("/")[1]??"mp4";t.push({kind:"document",fileId:e.video.file_id,fileName:`video.${n}`,mimeType:e.video.mime_type,fileSize:e.video.file_size})}return e.video_note&&t.push({kind:"document",fileId:e.video_note.file_id,fileName:"video_note.mp4",mimeType:"video/mp4",fileSize:e.video_note.file_size}),t}async function dr(e){if(e.length===0)return{resolved:[],images:[]};let t=rr();await D(t);let n=[],o=[];for(let r of e)try{let s=await R.downloadFile(r.fileId,t),l=await en.stat(s),a=r.fileName??Re.basename(s),i=r.mimeType??ar(s),u=r.kind==="photo"||ir(i),c={path:s,name:a,mimeType:i,bytes:l.size,isImage:u};if(n.push(c),u){let m=await en.readFile(s);o.push({type:"image",data:m.toString("base64"),mimeType:i??or})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function me(e,t){let n=0;for(let o=0;o<e.length;o+=1){let r=e[o];if(r==="\\"){o+=1;continue}r===t&&(n+=1)}return n}function gr(e){if(me(e,"*")%2!==0||me(e,"_")%2!==0||me(e,"`")%2!==0)return!1;let r=me(e,"["),s=me(e,"]");return r===s}function pr(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(mr.has(n))return!1}return!0}function ln(e){let t=nr(d.telegramParseMode);return t?[t]:pr(e)?["MarkdownV2","Markdown"]:gr(e)?["Markdown"]:[]}function pe(e,t){let n=ge.get(e);return n?(clearTimeout(n.timeoutId),ge.delete(e),n.messageId&&R.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function tn(e,t,n,o,r){if(ge.has(e))throw new Error("Audit confirmation already pending.");let s=bn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await vn(t,n,s,r);return await new Promise((a,i)=>{let u=setTimeout(()=>{ge.delete(e),R.editMessageText(`${n}
|
|
44
|
+
`)}});try{let y=p.messages,b=y.some(L=>{let J=L.role,W=L.content;return J==="system"&&typeof W=="string"?W.toLowerCase().includes("compaction")||W.toLowerCase().includes("compact"):L.type==="compaction"||L.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof u}`),console.log(`[tg-agent] session messages count: ${y.length}`),console.log(`[tg-agent] compacting support detected: ${b||"unknown (will be detected during runtime)"}`);let C=typeof u.compact=="function",B=typeof u.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${C}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${B}`)}catch(y){let b=y instanceof Error?y.message:String(y);console.warn(`[tg-agent] compacting check failed: ${b}`)}h&&console.warn(`[tg-agent] modelFallback=${h}`);let v=!1,k=()=>{v=!0,p.abort()};e.onAbortReady?.(k);let S=d.logAgentEvents,P=d.logAgentStream,$=new Map,_=p.subscribe(y=>{switch(y.type){case"agent_start":S&&console.log(`[tg-agent] agent start session=${e.sessionId}`),N=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":S&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":S&&console.log(`[tg-agent] turn start session=${e.sessionId}`),N=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":S&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${y.toolResults.length}`),N=Date.now(),e.onStatus?.({type:"turn_end",toolResults:y.toolResults.length});break;case"message_start":{if(S){let b=y.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${b}`)}N=Date.now();{let b=y.message.role??"unknown";e.onStatus?.({type:"message_start",role:b})}break}case"message_end":{if(S){let b=y.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${b}`)}N=Date.now();{let b=y.message.role??"unknown";e.onStatus?.({type:"message_end",role:b})}break}case"message_update":{if(!P)break;if(y.assistantMessageEvent.type==="text_delta"){let T=(y.assistantMessageEvent.delta??"").length;T>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${T}`),N=Date.now()}y.assistantMessageEvent.type==="thinking_delta"&&(N=Date.now());break}case"tool_execution_start":{$.set(y.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${y.toolName} id=${y.toolCallId}`),oe+=1,N=Date.now(),e.onStatus?.({type:"tool_start",name:y.toolName,id:y.toolCallId,args:y.args});break}case"tool_execution_end":{let b=$.get(y.toolCallId),T=b?Date.now()-b:0;console.log(`[tg-agent] tool end name=${y.toolName} id=${y.toolCallId} ok=${!y.isError} durationMs=${T}`),$.delete(y.toolCallId),oe=Math.max(0,oe-1),N=Date.now(),e.onStatus?.({type:"tool_end",name:y.toolName,id:y.toolCallId,ok:!y.isError,durationMs:T});break}case"auto_compaction_start":{let b=y.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${b}`),N=Date.now();break}case"auto_compaction_end":{let b=y.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${b}`),N=Date.now();break}default:break}}),E=null,w=null,x=!1,A=0,ee=!1,N=Date.now(),oe=0;try{let y=Date.now();E=setInterval(()=>{let C=Date.now()-y;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${C} streaming=${p.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:C,streaming:p.isStreaming})},15e3),w=setInterval(()=>{if(x||oe>0)return;let C=Date.now()-N,B=p.isStreaming?d.modelTimeoutStreamingMs:d.modelTimeoutMs,L=Math.max(1e3,B);C>=L&&(x=!0,A=L,ee=p.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${C}`),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(C){if(v)throw new Error("Cancelled by user.");if(x){let B=ee?" (streaming)":"",L=A||d.modelTimeoutMs;throw new Error(`Model request timed out after ${L}ms${B}`)}throw C}E&&clearInterval(E);let b=er(p.messages);if(b){let C=b?.stopReason,B=b?.errorMessage;if(C==="error"){let L=B?Qo(B):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${L}`),new Error(L)}}let T=Zo(p.messages,p);if(!T){let C=Xo(p.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${C}`),new Error("No assistant response.")}return{text:T,sessionFile:n,sessionId:p.sessionId,modelProvider:p.model?.provider??c,modelId:p.model?.id??a,modelFallbackMessage:h}}finally{E&&clearInterval(E),w&&clearInterval(w),_(),u.flushPendingToolResults?.(),p.dispose()}}var Ho,tn=F(()=>{"use strict";K();xe();Ft();$e();V();Ke();Xt();Ho={"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 tr}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(`
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
`)}function Ee(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function Ge(e,t){if(t.workspaceDir)return t.workspaceDir;let n=d.workspaceMappings.get(e);return n||d.workspaceDir}async function fn(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await R.sendMessage(e,t,r)}async function yn(e,t,n,o,r){let s={chat_id:e,message_id:t};o&&(s.parse_mode=o),r!==void 0&&(s.message_thread_id=r),await R.editMessageText(n,s)}async function hn(e,t){let n;for(let o of t)try{return await e(o)}catch(r){n=r;let s=r instanceof Error?r.message:String(r);console.warn(`[tg-agent] parse_mode ${o} failed, trying fallback: ${s}`)}try{return await e(void 0)}catch(o){if(n){let r=o instanceof Error?o.message:String(o);console.warn(`[tg-agent] parse_mode fallback to plain failed: ${r}`)}throw o}}async function Pr(e,t,n){return await hn(o=>fn(e,t,o,n),ln(t))}async function Tr(e,t,n,o){await hn(r=>yn(e,t,n,r,o),ln(n))}async function f(e,t,n){let o=et(t,3900);for(let r of o)await Pr(e,r,n)}function Rr(){let e=F()-wn;for(let[o,r]of q)r.createdAt<e&&q.delete(o);if(q.size<=sn)return;let t=Array.from(q.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=q.size-sn;for(let o=0;o<n;o+=1)q.delete(t[o][0])}function Er(e){Rr();let t=ce();for(;q.has(t);)t=ce();return q.set(t,{command:e,createdAt:F()}),t}function Dr(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=q.get(t);return n?F()-n.createdAt>wn?(q.delete(t),null):n.command:null}function Or(e,t){if(e.length<=t)return[e];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}function bn(e,t){let n=[],o=[];for(let r of e){let s=Er(r.command);o.push({text:r.label,callback_data:`cmd:${s}`}),o.length>=t&&(n.push(o),o=[])}return o.length>0&&n.push(o),n}async function vn(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await R.sendMessage(e,t,r)}async function an(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??Cr,l=o?.footer,a=o?.messageThreadId,i=Or(n,s);for(let u=0;u<i.length;u+=1){let c=i[u],m=i.length>1?` (page ${u+1}/${i.length})`:"",g=[`${t}${m}`];l&&g.push(l);let p=bn(c,r);await vn(e,g.join(`
|
|
49
|
-
`),p,a)}}function Ke(e,t=Ir){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
|
|
46
|
+
`);try{let i=(await tr(t,{messages:[{role:"system",content:nr},{role:"user",content:`Here is the conversation transcript:
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
`);await
|
|
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 R(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 R(qe),await nn.writeFile(c,i,"utf8")}}var qe,nr,rn=F(()=>{"use strict";K();V();qe=on.join(d.agentDir,"tg-memory"),nr=`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.
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
`);await f(e,k,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){Pt(),await de(d.agentDir,{timeoutMs:5e3,maxBytes:d.fetchMaxBytes,maxChars:3e3}),Fe(),await f(e,"MCP catalog refreshed.",r);return}let c=await Ur();await f(e,c,r);return}case"login":{let c=Zo();if(!o){let p=c.map(h=>`- ${h.id} (${h.name})`);await f(e,["OAuth providers:",...p].join(`
|
|
59
|
-
`),r);return}let m=ae(o);if(Je.has(t)){await f(e,"Login already in progress.",r);return}let g=c.find(p=>p.id===m);if(!g){await f(e,`Unknown OAuth provider: ${m}`,r);return}Je.add(t);try{let{authStorage:p}=await ie();await f(e,`Starting login for ${g.id}...`,r),await p.login(g.id,{onAuth:({url:h,instructions:k})=>{let P=["Open this URL in your browser:",h];k&&P.push("",k),f(e,P.join(`
|
|
60
|
-
`),r)},onPrompt:h=>nn(t,e,h,r),onProgress:h=>{f(e,h,r)},onManualCodeInput:()=>nn(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let h=De(p);await f(e,`Login failed: ${h}`,r)}finally{Je.delete(t),un(t)}return}case"logout":{if(!o){await f(e,"Usage: /logout <provider>",r);return}let c=ae(o),{authStorage:m}=await ie();m.logout(c),await f(e,`Logged out from ${c}.`,r);return}default:await f(e,`Unknown command: ${n}`,r)}}async function Br(e,t,n,o=[],r){let s=Ye(n);if(s){await Xe(e,t,s.command,s.args,r);return}let a=Ee(e,r,r!==void 0);if(!a)return;let i=await Ae(a),u=Be(i);u.length>0&&(await C(i),await Promise.all(u.map(M=>se(a,M).catch(L=>{console.warn(`[tg-agent] cleanup session file failed id=${M}`,L)}))));let c=te(i);if(!c)try{c=Pe(i,""),await C(i),await f(e,`Created session ${c.id}.`,r)}catch(M){await f(e,M.message,r);return}let{resolved:m,images:g}=await dr(o);if(o.length>0&&m.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=lr(m),h=[];n.trim()&&h.push(n.trim()),p&&h.push(p);let k=h.join(`
|
|
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.
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
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?
|
|
66
|
+
|
|
67
|
+
Be warm, empathetic, and encouraging. Write as if you are writing a private journal entry about your beloved family member.`});var Vr={};import Ee from"node:path";import sn from"node:fs/promises";import or from"node-telegram-bot-api";import{discoverAuthStorage as rr,discoverModels as sr}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as ir}from"@mariozechner/pi-ai";function cr(e,t){ye.set(e,t)}function Xe(e){ye.delete(e)}function lr(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 dr(){return Ee.join(d.agentDir,"uploads")}function mr(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 gr(e){return!!e?.startsWith("image/")}function pr(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 fr(e){if(!Number.isFinite(e)||e<=0)return"0 B";let t=["B","KB","MB","GB"],n=e,o=0;for(;n>=1024&&o<t.length-1;)n/=1024,o+=1;return`${n.toFixed(n>=10||o===0?0:1)} ${t[o]}`}function yr(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(fr(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
|
|
68
|
+
`)}function hr(e){let t=[];if(e.photo&&e.photo.length>0){let n=mr(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 wr(e){if(e.length===0)return{resolved:[],images:[]};let t=dr();await R(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??pr(s),u=r.kind==="photo"||gr(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??ur})}}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 vr(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 Sr(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(br.has(n))return!1}return!0}function pn(e){let t=lr(d.telegramParseMode);return t?[t]:Sr(e)?["MarkdownV2","Markdown"]:vr(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 an(e,t,n,o,r){if(pe.has(e))throw new Error("Audit confirmation already pending.");let s=kn([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await $n(t,n,s,r);return await new Promise((c,a)=>{let u=setTimeout(()=>{pe.delete(e),I.editMessageText(`${n}
|
|
69
|
+
|
|
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 Mr.get(t)??t}function $r(e,t){return e!=="openai-codex"?t:kr[t]??t}async function Q(){await R(d.agentDir);let e=rr(d.agentDir),t=re();t&&e.setRuntimeApiKey("openai-codex",t.accessToken);let n=sr(e,d.agentDir);return{authStorage:e,modelRegistry:n}}function fn(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 cn(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."))},xr);Z.set(e,{resolve:s,reject:l,timeoutId:c,chatId:t})})}async function yn(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 hn(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 Ar(){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 ln(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 Tr(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])=>Pr.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 Cr(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 Rr(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 Er(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 wn(e,t){let n=Date.now(),o=un.get(e)??0;n-o<Dr||(un.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function bn(e){let t=d.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function Or(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 vn(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 Sn(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 xn(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 Ir(e,t,n){return await xn(o=>vn(e,t,o,n),pn(t))}async function Lr(e,t,n,o){await xn(r=>Sn(e,t,n,r,o),pn(n))}async function f(e,t,n){let o=nt(t,3900);for(let r of o)await Ir(e,r,n)}function Nr(){let e=z()-Mn;for(let[o,r]of q)r.createdAt<e&&q.delete(o);if(q.size<=dn)return;let t=Array.from(q.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=q.size-dn;for(let o=0;o<n;o+=1)q.delete(t[o][0])}function Fr(e){Nr();let t=le();for(;q.has(t);)t=le();return q.set(t,{command:e,createdAt:z()}),t}function zr(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=q.get(t);return n?z()-n.createdAt>Mn?(q.delete(t),null):n.command:null}function Ur(e,t){if(e.length<=t)return[e];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}function kn(e,t){let n=[],o=[];for(let r of e){let s=Fr(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 $n(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 mn(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??jr,l=o?.footer,c=o?.messageThreadId,a=Ur(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=kn(i,r);await $n(e,g.join(`
|
|
72
|
+
`),p,c)}}function Ge(e,t=Br){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
|
|
73
|
+
|
|
74
|
+
[truncated]`,truncated:!0}}async function Hr(e,t){let n="Working...",r=(await vn(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<Wr||i!==s&&(s=i,l=g,c=c.then(async()=>{await Sn(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 Kr(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
|
|
75
|
+
args: ${qr(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 qr(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(h=>l(h,i+1));return u.length>r&&p.push("[truncated]"),p}let m=Object.entries(u),g={};for(let[p,h]of m.slice(0,o))g[p]=l(h,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 Jr(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function Yr(){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: ${Jr(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,h=Te(a,i);g&&(h.modelProvider=g,p&&(h.modelId=p)),await O(a),await f(e,`Created session ${h.id} (${h.title}).`,r)}catch(i){await f(e,i.message,r)}return}case"list":{await O(a),await f(e,Or(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:k}=await Q(),S=m.modelProvider||d.modelProvider,P=m.modelId||(d.modelRef.includes("/")?d.modelRef.split("/")[1]:d.modelRef),$=S||d.modelProvider,_=k.find($,P);if(!_){let E=k.getAll().filter(w=>w.provider===$);E.length>0&&(_=E[0])}if(_){let E=await v.getApiKey($);await Je(m,_.model,E),await f(e,"Memory archived successfully.",r)}else console.warn(`[tg-agent] could not find model for reflection: ${$}`)}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 h=g?`Force-closed session ${i} (interrupted running task).`:`Closed session ${i}.`;await f(e,h,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,h=i.modelId||(d.modelRef.includes("/")?d.modelRef.split("/")[1]:d.modelRef),v=p||d.modelProvider,k=g.find(v,h);if(!k){let S=g.getAll().filter(P=>P.provider===v);S.length>0&&(k=S[0])}if(k){let S=await m.getApiKey(v);await Je(i,k.model,S),await f(e,"Memory archived successfully.",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=Tr(m,i);if(p.length===0){let v=g?`Warning: ${g}
|
|
78
|
+
|
|
79
|
+
No providers found.`:"No providers found.";await f(e,v,r);return}let h=[];g&&h.push(`Warning: ${g}`),h.push("Providers:"),await mn(e,h.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 k=ne(a);if(!k?.modelProvider){await f(e,"Usage: /models <provider>",r);return}g=k.modelProvider}let p=i.hasAuth(g),h=Rr(a,g),v=Cr(m,g,h);if(v.length===0){await f(e,`No models found for provider ${g}.`,r);return}await mn(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(h=>h.provider===i)){await f(e,`Unknown provider: ${i}`,r);return}let p=await ln(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=Er(o);if(!i){await f(e,"Usage: /model <provider>/<model>",r);return}let m=await ln(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(),h=$r(g,i.modelId);if(!p.find(g,h)){await f(e,`Model not found: ${g}/${h}`,r);return}m.modelProvider=g,m.modelId=h,m.updatedAt=z(),await O(a),await f(e,`Session ${m.id} model set to ${g}/${h}.`,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),h=a.workspaceDir?"chat":d.workspaceMappings.has(c)?"config":"default",v=[`Session: ${i.id} (${i.title})`,g,`Workspace: ${p} (${h})`].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 Yr();await f(e,i,r);return}case"login":{let i=ir();if(!o){let p=i.map(h=>`- ${h.id} (${h.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:h,instructions:v})=>{let k=["Open this URL in your browser:",h];v&&k.push("",v),f(e,k.join(`
|
|
83
|
+
`),r)},onPrompt:h=>cn(t,e,h,r),onProgress:h=>{f(e,h,r)},onManualCodeInput:()=>cn(t,e,{message:"Paste the authorization code:"},r)}),await f(e,`Login completed for ${g.id}.`,r)}catch(p){let h=ce(p);await f(e,`Login failed: ${h}`,r)}finally{Ye.delete(t),fn(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 Gr(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(_=>{console.warn(`[tg-agent] cleanup session file failed id=${$}`,_)}))));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 wr(o);if(o.length>0&&m.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=yr(m),h=[];n.trim()&&h.push(n.trim()),p&&h.push(p);let v=h.join(`
|
|
84
|
+
|
|
85
|
+
`)||"Attachment received.",k={role:"user",content:v,ts:z()};He(i,k,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 S=null;try{S=await Hr(e,r)}catch($){console.warn("[tg-agent] status message failed",$)}let P={sessionId:i.id,chatId:e,messageThreadId:r,status:S,abortRequested:!1,cancelRequested:!1};cr(c,P);try{let $=await ar(async()=>{let E=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 A={};x&&(A.caption=x),r!==void 0&&(A.message_thread_id=r),await I.sendPhoto(e,w,A)},sendDocument:async(w,x)=>{let A={};x&&(A.caption=x),r!==void 0&&(A.message_thread_id=r),await I.sendDocument(e,w,A)},sendMessage:async w=>{await f(e,w,r)},requestConfirmation:async(w,x)=>await an(c,e,w,x,r)},auditContext:d.audit.enabled?{chatId:c,requestConfirmation:async(w,x)=>await an(c,e,w,x,r),sendNotification:async w=>{await f(e,w,r)}}:void 0,onAbortReady:w=>{P.abort=w,P.abortRequested&&w()},onStatus:S?w=>{let x=Kr(w);x&&S?.update(x)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${E.modelProvider}/${E.modelId} file=${E.sessionFile}`),E.text});if(P.cancelRequested){S?await S.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let _={role:"assistant",content:$,ts:z()};He(i,_,d.maxHistoryMessages),await O(a),S?await S.finalize($):await f(e,$,r)}catch($){if(console.error("[tg-agent] runModel error",$),P.cancelRequested){S?await S.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let _=ce($);S?await S.fail(`Error: ${_}`):await f(e,`Error: ${_}`,r)}finally{Xe(c)}}var I,gn,ar,ye,ur,br,xr,Z,Ye,pe,Mr,kr,Re,Pr,Dr,un,Mn,dn,jr,q,Br,Wr,_n=F(()=>{"use strict";K();Le();kt();tn();xe();$e();Ke();rn();V();yt();I=new or(d.telegramToken,{polling:!0}),gn=ot(),ar=rt(d.maxConcurrent),ye=new Map;ur="image/jpeg";br=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);xr=600*1e3,Z=new Map,Ye=new Set,pe=new Map;Mr=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),kr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};Ar();R(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)");Pr=new Set(["openai-codex","google-antigravity","anthropic"]);Dr=6e4,un=new Map;Mn=1800*1e3,dn=2e3,jr=60,q=new Map;Br=3900,Wr=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(!bn(o)){wn(o,n),I.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){I.answerCallbackQuery(e.id);return}let r=zr(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):yn(n,c,s);return}if(a?.command==="close"){hn(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}gn(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(!bn(t)){wn(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=hr(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}fn(t),a.resolve(l);return}let u=Qe(l);if(u?.command==="stop"){fe(s,!1),yn(n,s,o);return}if(u?.command==="close"){fe(s,!1),hn(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}gn(s,()=>Gr(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 Xr from"node:fs";import An from"node:path";import Qr from"node:readline/promises";import{fileURLToPath as Zr}from"node:url";var Pn=process.argv.slice(2),Tn=(e,t)=>Pn.includes(e)||(t?Pn.includes(t):!1),es=Tn("--help","-h"),ts=Tn("--version","-v"),ns=["Usage: tg-agent [options]","","Options:"," -h, --help Show help"," -v, --version Show version"].join(`
|
|
86
|
+
`),os=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Zr(import.meta.url),t=An.dirname(e),n=An.join(t,"..","package.json"),o=Xr.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};es&&(console.log(ns),process.exit(0));ts&&(console.log(os()),process.exit(0));async function rs(){let e=Qr.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}async function ss(){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 rs();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 is(){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 ss();await is();ft();Promise.resolve().then(()=>_n());
|