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.
- package/dist/cli.js +50 -48
- package/package.json +3 -3
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 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:
|
|
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 M=await
|
|
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: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:
|
|
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
|
|
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
|
|
26
|
-
`)}function
|
|
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"}`;
|
|
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
|
|
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
|
|
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
|
|
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
|
-
`);
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
`)}function
|
|
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
|
-
[
|
|
75
|
-
|
|
76
|
-
`)}
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
`)
|
|
82
|
-
`),r);return}let
|
|
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
|
-
|
|
86
|
-
`),
|
|
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.
|
|
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.
|
|
25
|
-
"@mariozechner/pi-coding-agent": "^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",
|