tg-agent 1.8.9 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.cn.md CHANGED
@@ -10,7 +10,8 @@
10
10
  - 运行中可取消:/stop
11
11
  - 自动 Markdown 渲染:优先 MarkdownV2,失败回退 Markdown,再回退纯文本
12
12
  - 多 Provider / 多 Model 选择(支持 Codex / antigravity / Gemini CLI 等)
13
- - OAuth 登录与注销(/login, /logout
13
+ - OAuth 登录与注销(/login, /logout),支持多账号切换
14
+ - API Key + 自定义 Endpoint 模式(/apikey, /endpoint, /useapikey)
14
15
  - 工具调用:内置 `fetch`,可选 MCP(HTTP/stdio)
15
16
  - 多媒体文件支持:图片、文档、音频、视频、语音、视频笔记
16
17
  - 代理支持:模型与工具请求可分别配置
@@ -60,6 +61,7 @@ bot_token = "YOUR_BOT_TOKEN"
60
61
  - `/models [provider]` - 列出指定 Provider 的模型(不指定则显示当前会话的 Provider)
61
62
  - `/provider <name>` - 设置当前会话的 Provider
62
63
  - `/model <provider>/<model>` - 设置当前会话的模型
64
+ - `/modelraw <provider> <model>` - 设置自定义模型 ID(跳过注册表校验;也兼容 `/modelraw <provider>/<model>`)
63
65
 
64
66
  ### 工作区与工具
65
67
 
@@ -72,6 +74,12 @@ bot_token = "YOUR_BOT_TOKEN"
72
74
 
73
75
  - `/login <provider>` - OAuth 登录到指定 Provider
74
76
  - `/logout <provider>` - 退出指定 Provider 的登录
77
+ - `/accounts [provider]` - 列出 OAuth 账号并切换
78
+ - `/setdefault <provider>/<accountId>` - 设置默认 OAuth 账号
79
+ - `/apikey <provider> <key>` - 设置 Provider 的 API Key
80
+ - `/endpoint <provider> <url>` - 设置 Provider 的自定义 Endpoint
81
+ - `/useapikey <provider>` - 当前会话强制使用 API Key 模式
82
+ - `/useoauth <provider>[/accountId]` - 当前会话强制使用 OAuth 模式
75
83
 
76
84
  ### 帮助
77
85
 
@@ -166,6 +174,15 @@ reject_unauthorized = ""
166
174
  codex login
167
175
  ```
168
176
 
177
+ ## API Key + Endpoint 模式
178
+
179
+ - API Key 与自定义 Endpoint 存储在 `~/.tg-agent/api-key-auth.json`
180
+ - 该模式不会覆盖你的 OAuth 多账号数据(`~/.tg-agent/multi-auth.json`)
181
+ - Claude 常见用法:
182
+ - `/apikey anthropic <your-key>`
183
+ - `/endpoint anthropic https://your-proxy-or-gateway`
184
+ - `/useapikey anthropic`
185
+
169
186
  ## MCP 配置
170
187
 
171
188
  在同一个 `~/.tg-agent/config.toml` 中添加 MCP 服务器:
package/README.md CHANGED
@@ -10,7 +10,8 @@ A locally running Telegram bot that supports multiple LLM providers (Codex, Clau
10
10
  - Cancellable during execution: /stop
11
11
  - Automatic Markdown rendering: prefers MarkdownV2, falls back to Markdown, then plain text
12
12
  - Multiple Provider / Model selection (supports Codex / antigravity / Gemini CLI, etc.)
13
- - OAuth login and logout (/login, /logout)
13
+ - OAuth login/logout with multi-account switching (/login, /logout, /accounts, /setdefault)
14
+ - API key + custom endpoint mode (/apikey, /endpoint, /useapikey)
14
15
  - Tool calls: built-in `fetch`, optional MCP (HTTP/stdio)
15
16
  - Multimedia file support: images, documents, audio, video, voice, video notes
16
17
  - Proxy support: model and tool requests can be configured separately
@@ -60,6 +61,7 @@ Send the following commands in Telegram:
60
61
  - `/models [provider]` - List models for a provider (shows current session's provider if not specified)
61
62
  - `/provider <name>` - Set the provider for current session
62
63
  - `/model <provider>/<model>` - Set the model for current session
64
+ - `/modelraw <provider> <model>` - Set a custom model id (skip registry check; `/modelraw <provider>/<model>` is also supported)
63
65
 
64
66
  ### Workspace and Tools
65
67
 
@@ -72,6 +74,12 @@ Send the following commands in Telegram:
72
74
 
73
75
  - `/login <provider>` - OAuth login to a provider
74
76
  - `/logout <provider>` - Logout from a provider
77
+ - `/accounts [provider]` - List OAuth accounts and switch
78
+ - `/setdefault <provider>/<accountId>` - Set default OAuth account
79
+ - `/apikey <provider> <key>` - Set API key for a provider
80
+ - `/endpoint <provider> <url>` - Set custom endpoint for a provider
81
+ - `/useapikey <provider>` - Force API key mode for current session
82
+ - `/useoauth <provider>[/accountId]` - Force OAuth mode for current session
75
83
 
76
84
  ### Help
77
85
 
@@ -166,6 +174,15 @@ If you see missing permissions or cannot find credentials at runtime, re-run:
166
174
  codex login
167
175
  ```
168
176
 
177
+ ## API Key + Endpoint Mode
178
+
179
+ - API keys and custom endpoints are stored in `~/.tg-agent/api-key-auth.json`
180
+ - This mode does not overwrite OAuth multi-account data in `~/.tg-agent/multi-auth.json`
181
+ - Common Claude flow:
182
+ - `/apikey anthropic <your-key>`
183
+ - `/endpoint anthropic https://your-proxy-or-gateway`
184
+ - `/useapikey anthropic`
185
+
169
186
  ## MCP Configuration
170
187
 
171
188
  Add MCP servers in the same `~/.tg-agent/config.toml`:
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- var F=(e,t)=>()=>(e&&(t=e(e=0)),t);import tt from"node:fs/promises";import ao from"node:os";import Ee from"node:path";import{randomUUID as Lt}from"node:crypto";function U(){return Date.now()}function B(e){return e.startsWith("~")?Ee.join(ao.homedir(),e.slice(1)):e}async function T(e){await tt.mkdir(e,{recursive:!0})}async function De(e,t){let n=Ee.dirname(e),o=`${Ee.basename(e)}.${Lt()}.tmp`,r=Ee.join(n,o),s=JSON.stringify(t,null,2);await tt.writeFile(r,s,"utf8"),await tt.rename(r,e)}function ee(){return Lt().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 jt(){let e=new Map;return async function(n,o){let s=(e.get(n)??Promise.resolve()).then(o,o);e.set(n,s);try{return await s}finally{e.get(n)===s&&e.delete(n)}}}function Nt(e){let t=0,n=[],o=()=>{if(t>=e)return;let r=n.shift();r&&(t+=1,r())};return async function(s){await new Promise(l=>{n.push(l),o()});try{return await s()}finally{t=Math.max(0,t-1),o()}}}var q=F(()=>{"use strict"});import Ft from"node:fs";import xe from"node:path";import*as Ie from"@iarna/toml";function Bt(){let e=B(Ut);return xe.join(e,co)}function O(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function R(e,t){return typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):t}function G(e,t){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"){let n=Number.parseInt(e,10);return Number.isNaN(n)?t:n}return t}function ge(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 Kt(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 lo(e){return new Set(Kt(e))}function uo(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,xe.resolve(B(o.trim())));return t}function Se(){let e=Bt();try{let t=Ft.readFileSync(e,"utf8"),n=Ie.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Le(e,t){await T(xe.dirname(e));let n=Ie.stringify(t);await Ft.promises.writeFile(e,n,"utf8")}function Wt(){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",restart_script_path:""},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:zt},tls:{extra_ca_certs:"",reject_unauthorized:""},security_audit:{enabled:!1,model_provider:"",model_id:"",whitelist_patterns:[],confirm_timeout_ms:12e4},memory:{enabled:!0,model_provider:"",model_id:"",system_prompt:"",rag:{enabled:!0,embedding_model:"openai/text-embedding-3-small",embedding_base_url:"",embedding_api_key:"",similarity_threshold:.5,max_results:5}}}}function Oe(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function Jt(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 u=r[l];Oe(u)&&Oe(a)&&o(u,a)}};return Oe(e)&&Oe(t)&&o(e,t),n}function Ht(e){let t=O(e,"telegram");return R(t.bot_token,"").trim()}function qt(e,t){let n=O(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function Gt(e){let t=O(e,"telegram"),n=O(e,"model"),o=O(e,"paths"),r=O(e,"limits"),s=O(e,"timeouts"),l=O(e,"fetch"),a=O(e,"proxy"),u=O(e,"auth"),m=O(e,"logging"),i=O(e,"system"),c=O(e,"tls"),d=O(e,"workspace_mappings"),p=O(e,"security_audit"),y=O(e,"memory"),h=O(y,"rag"),b=R(o.workspace_dir,process.cwd()),$=R(o.session_dir,"~/.tg-agent/tg-sessions"),A=uo(d),M=R(c.reject_unauthorized,""),C=M===""?null:ge(M,!0);return{telegramToken:R(t.bot_token,"").trim(),telegramAllowedUsers:lo(t.allowed_user_ids),telegramParseMode:R(t.parse_mode,"").trim(),modelProvider:R(n.provider,"openai-codex").trim(),modelRef:R(n.model,"gpt-5.2").trim(),openaiApiKey:R(n.openai_api_key,"").trim(),sessionDir:B($),agentDir:B(Ut),restartScriptPath:(()=>{let _=R(o.restart_script_path,"").trim();return _?xe.resolve(B(_)):""})(),workspaceDir:xe.resolve(B(b)),workspaceMappings:A,maxSessions:G(r.max_sessions,5),maxConcurrent:G(r.max_concurrent,5),maxHistoryMessages:G(r.max_history_messages,40),maxOutputTokens:G(r.max_output_tokens,0),fetchMaxBytes:G(l.max_bytes,2e5),fetchTimeoutMs:G(s.fetch_timeout_ms,6e4),modelTimeoutMs:G(s.model_timeout_ms,6e4),modelTimeoutStreamingMs:G(s.model_timeout_stream_ms,3e5),systemPrompt:R(i.prompt,zt),proxyUrl:R(a.url,"").trim(),fetchProxyUrl:R(l.proxy_url,"").trim(),codexHome:B(R(u.codex_home,"~/.codex")),logAgentEvents:ge(m.agent_events,!0),logAgentStream:ge(m.agent_stream,!0),tlsExtraCaCerts:R(c.extra_ca_certs,"").trim(),tlsRejectUnauthorized:C,audit:{enabled:ge(p.enabled,!1),modelProvider:R(p.model_provider,"").trim(),modelId:R(p.model_id,"").trim(),whitelistPatterns:Kt(p.whitelist_patterns),confirmTimeoutMs:G(p.confirm_timeout_ms,6e4)},memory:{enabled:ge(y.enabled,!0),modelProvider:R(y.model_provider,"").trim(),modelId:R(y.model_id,"").trim(),systemPrompt:R(y.system_prompt,"").trim(),rag:{enabled:ge(h.enabled,!0),embeddingModel:R(h.embedding_model,"openai/text-embedding-3-small").trim(),embeddingBaseUrl:R(h.embedding_base_url,"").trim(),embeddingApiKey:R(h.embedding_api_key,"").trim(),similarityThreshold:G(h.similarity_threshold,.5),maxResults:G(h.max_results,5)}}}}function Vt(){let{data:e}=Se();return g=Gt(e),g}function Yt(){let e=[];if(g.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${Bt()})`)}var Ut,co,zt,mo,g,K=F(()=>{"use strict";q();Ut="~/.tg-agent",co="config.toml",zt=`You are running in user's personal computer or VPS, using telegram bot to interact with user.
2
+ var z=(e,t)=>()=>(e&&(t=e(e=0)),t);import rt from"node:fs/promises";import Po from"node:os";import Ne from"node:path";import{randomUUID as Jt}from"node:crypto";function D(){return Date.now()}function W(e){return e.startsWith("~")?Ne.join(Po.homedir(),e.slice(1)):e}async function C(e){await rt.mkdir(e,{recursive:!0})}async function he(e,t){let n=Ne.dirname(e),o=`${Ne.basename(e)}.${Jt()}.tmp`,r=Ne.join(n,o),i=JSON.stringify(t,null,2);await rt.writeFile(r,i,"utf8"),await rt.rename(r,e)}function ne(){return Jt().split("-")[0]}function st(e,t){if(e.length<=t)return[e];let n=[],o=e;for(;o.length>t;){let r=o.slice(0,t),i=r.lastIndexOf(`
3
+ `);i>t*.6&&(r=r.slice(0,i)),n.push(r),o=o.slice(r.length)}return o.length>0&&n.push(o),n}function Ht(){let e=new Map;return async function(n,o){let i=(e.get(n)??Promise.resolve()).then(o,o);e.set(n,i);try{return await i}finally{e.get(n)===i&&e.delete(n)}}}function qt(e){let t=0,n=[],o=()=>{if(t>=e)return;let r=n.shift();r&&(t+=1,r())};return async function(i){await new Promise(c=>{n.push(c),o()});try{return await i()}finally{t=Math.max(0,t-1),o()}}}var J=z(()=>{"use strict"});import Gt from"node:fs";import Ae from"node:path";import*as Le from"@iarna/toml";function Xt(){let e=W(Vt);return Ae.join(e,_o)}function N(e,t){let n=e[t];return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function R(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 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 Qt(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 Co(e){return new Set(Qt(e))}function Ro(e){let t=new Map;for(let[n,o]of Object.entries(e))typeof o=="string"&&o.trim()&&t.set(n,Ae.resolve(W(o.trim())));return t}function Me(){let e=Xt();try{let t=Gt.readFileSync(e,"utf8"),n=Le.parse(t);return{configPath:e,data:n,exists:!0}}catch{return{configPath:e,data:{},exists:!1}}}async function Ue(e,t){await C(Ae.dirname(e));let n=Le.stringify(t);await Gt.promises.writeFile(e,n,"utf8")}function Zt(){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",restart_script_path:""},workspace_mappings:{},limits:{max_sessions:5,max_concurrent:5,max_history_messages:40,max_output_tokens:0},timeouts:{model_timeout_ms:6e4,model_timeout_stream_ms:3e5,fetch_timeout_ms:6e4},fetch:{max_bytes:2e5,proxy_url:""},proxy:{url:""},auth:{codex_home:"~/.codex"},logging:{agent_events:!0,agent_stream:!0},system:{prompt:Yt},tls:{extra_ca_certs:"",reject_unauthorized:""},security_audit:{enabled:!1,model_provider:"",model_id:"",whitelist_patterns:[],confirm_timeout_ms:12e4},memory:{enabled:!0,model_provider:"",model_id:"",system_prompt:"",rag:{enabled:!0,embedding_model:"openai/text-embedding-3-small",embedding_base_url:"",embedding_api_key:"",similarity_threshold:.5,max_results:5}}}}function je(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}function en(e,t){let n=!1,o=(r,i)=>{for(let[c,u]of Object.entries(i)){if(!(c in r)){r[c]=u,n=!0;continue}let l=r[c];je(l)&&je(u)&&o(l,u)}};return je(e)&&je(t)&&o(e,t),n}function tn(e){let t=N(e,"telegram");return R(t.bot_token,"").trim()}function nn(e,t){let n=N(e,"telegram");n.bot_token=t.trim(),e.telegram=n}function on(e){let t=N(e,"telegram"),n=N(e,"model"),o=N(e,"paths"),r=N(e,"limits"),i=N(e,"timeouts"),c=N(e,"fetch"),u=N(e,"proxy"),l=N(e,"auth"),m=N(e,"logging"),s=N(e,"system"),a=N(e,"tls"),d=N(e,"workspace_mappings"),p=N(e,"security_audit"),h=N(e,"memory"),y=N(h,"rag"),w=R(o.workspace_dir,process.cwd()),x=R(o.session_dir,"~/.tg-agent/tg-sessions"),M=Ro(d),$=R(a.reject_unauthorized,""),P=$===""?null:we($,!0);return{telegramToken:R(t.bot_token,"").trim(),telegramAllowedUsers:Co(t.allowed_user_ids),telegramParseMode:R(t.parse_mode,"").trim(),modelProvider:R(n.provider,"openai-codex").trim(),modelRef:R(n.model,"gpt-5.2").trim(),openaiApiKey:R(n.openai_api_key,"").trim(),sessionDir:W(x),agentDir:W(Vt),restartScriptPath:(()=>{let U=R(o.restart_script_path,"").trim();return U?Ae.resolve(W(U)):""})(),workspaceDir:Ae.resolve(W(w)),workspaceMappings:M,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(c.max_bytes,2e5),fetchTimeoutMs:V(i.fetch_timeout_ms,6e4),modelTimeoutMs:V(i.model_timeout_ms,6e4),modelTimeoutStreamingMs:V(i.model_timeout_stream_ms,3e5),systemPrompt:R(s.prompt,Yt),proxyUrl:R(u.url,"").trim(),fetchProxyUrl:R(c.proxy_url,"").trim(),codexHome:W(R(l.codex_home,"~/.codex")),logAgentEvents:we(m.agent_events,!0),logAgentStream:we(m.agent_stream,!0),tlsExtraCaCerts:R(a.extra_ca_certs,"").trim(),tlsRejectUnauthorized:P,audit:{enabled:we(p.enabled,!1),modelProvider:R(p.model_provider,"").trim(),modelId:R(p.model_id,"").trim(),whitelistPatterns:Qt(p.whitelist_patterns),confirmTimeoutMs:V(p.confirm_timeout_ms,6e4)},memory:{enabled:we(h.enabled,!0),modelProvider:R(h.model_provider,"").trim(),modelId:R(h.model_id,"").trim(),systemPrompt:R(h.system_prompt,"").trim(),rag:{enabled:we(y.enabled,!0),embeddingModel:R(y.embedding_model,"openai/text-embedding-3-small").trim(),embeddingBaseUrl:R(y.embedding_base_url,"").trim(),embeddingApiKey:R(y.embedding_api_key,"").trim(),similarityThreshold:V(y.similarity_threshold,.5),maxResults:V(y.max_results,5)}}}}function rn(){let{data:e}=Me();return f=on(e),f}function sn(){let e=[];if(f.telegramToken||e.push("telegram.bot_token"),e.length>0)throw new Error(`Missing config values: ${e.join(", ")} (edit ${Xt()})`)}var Vt,_o,Yt,To,f,K=z(()=>{"use strict";J();Vt="~/.tg-agent",_o="config.toml",Yt=`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,23 +9,23 @@ 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:mo}=Se()),g=Gt(mo)});import{createHash as go}from"node:crypto";import Xt from"node:fs";import po from"node:path";import{execSync as fo}from"node:child_process";function wo(){return po.join(g.codexHome,yo)}function bo(e){return`cli|${go("sha256").update(e).digest("hex").slice(0,16)}`}function vo(){if(process.platform!=="darwin")return null;let e=g.codexHome,t=bo(e);try{let n=fo(`security find-generic-password -s "${ho}" -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,u=typeof a=="string"||typeof a=="number"?new Date(a).getTime():Date.now(),m=Number.isFinite(u)?u+3600*1e3:Date.now()+3600*1e3;return{accessToken:s,refreshToken:l,expiresAt:m,source:"keychain"}}catch{return null}}function xo(){let e=wo();try{let t=Xt.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=Xt.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:s,expiresAt:l,source:"file"}}catch{return null}}function V(){return vo()??xo()}var yo,ho,pe=F(()=>{"use strict";K();yo="auth.json",ho="Codex Auth"});function Qt(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=V();if(n)return{apiKey:n.accessToken,source:`codex:${n.source}`};throw new Error("No Codex OAuth credentials found. Run `codex login`.")}if(g.openaiApiKey)return{apiKey:g.openaiApiKey,source:"config.model.openai_api_key"};throw new Error(`No API key for provider: ${e}`)}function So(){return g.proxyUrl?{url:g.proxyUrl,source:"config.proxy.url"}:g.fetchProxyUrl?{url:g.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function Zt(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function en(){let e=So();return e?{url:e.url,kind:Zt(e.url),source:e.source}:null}function tn(){let e=[{key:"config.fetch.proxy_url",value:g.fetchProxyUrl},{key:"config.proxy.url",value:g.proxyUrl}];for(let t of e){let n=t.value?.trim();if(!n)continue;let o=Zt(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var ot=F(()=>{"use strict";K();pe()});import{ProxyAgent as Mo,setGlobalDispatcher as $o}from"undici";function je(){if(nn)return rt;nn=!0;let e=tn();if(!e)return rt=null,null;let t=new Mo(e.url);return $o(t),rt=e,e}var nn,rt,st=F(()=>{"use strict";ot();nn=!1,rt=null});import Ao from"node:fs";import ko from"node:fs/promises";import Po from"node:path";import _o from"node:readline";import{spawn as Co}from"node:child_process";import*as rn from"@iarna/toml";function cn(e){return Po.join(e,"config.toml")}function Ne(e){let t=cn(e);try{let n=Ao.readFileSync(t,"utf8");return mn(n)}catch{return[]}}async function Me(e){let t=cn(e);try{let n=await ko.readFile(t,"utf8");return mn(n)}catch{return[]}}async function le(e,t={}){if(fe)return fe;let n=await Me(e);if(n.length===0)return fe="","";let o=t.maxTools??To,r=t.maxChars??Eo,s=t.timeoutMs??4e3,l=t.maxBytes??sn,a=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let m of n){let i=await Oo(m,{timeoutMs:s,maxBytes:l});if(a.push(`${m.name} (${m.type})`),i.length===0){a.push(" - tools unavailable");continue}let c=i.slice(0,o);for(let d of c){let p=d.description?`: ${d.description}`:"";a.push(` - ${d.name}${p}`)}i.length>c.length&&a.push(` - ...and ${i.length-c.length} more`)}let u=a.join(`
13
- `);return u.length>r&&(u=`${u.slice(0,r-20)}...
14
- (truncated)`),fe=u,u}function $e(){fe&&(an=!0)}function ln(){fe=null,an=!1,W.clear()}function ue(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 un(e,t=5e3){let n=Date.now();try{return await Fe(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 Fe(e,t,n,o={}){let r=on(o.timeoutMs??Ro,1e3,12e4),s=on(o.maxBytes??sn,1024,5e6),l=new AbortController,a=()=>l.abort();o.signal?.addEventListener("abort",a,{once:!0});let u=setTimeout(()=>l.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await jo(e,s,l.signal),await Lo(e,t,n,s,l.signal)):await Uo(e,t,n,s,l.signal)}finally{clearTimeout(u),o.signal?.removeEventListener("abort",a)}}function on(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function Oo(e,t){try{let n=await Fe(e,"tools/list",{},t);return Io(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 Io(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,u=typeof a.name=="string"?a.name:"";if(!u)continue;let m=typeof a.description=="string"?a.description:void 0,i=a.inputSchema;s.push({name:u,description:m,inputSchema:i})}return s}async function Lo(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=Date.now(),l=await it(e,t,n,o,r),a=dn(l.parsed);if(a)throw new Error(a);let u=l.bodyText;return l.parsed&&(u=JSON.stringify(l.parsed,null,2)),{ok:l.statusCode>=200&&l.statusCode<300,output:u,durationMs:Date.now()-s,bytes:l.bytes,truncated:l.truncated,statusCode:l.statusCode,statusText:l.statusText,contentType:l.contentType}}async function it(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let s=W.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 u=await fetch(e.url,{method:"POST",headers:a,body:JSON.stringify(l),signal:r});No(e.name,u);let m=await zo(u,o,r),i;try{i=JSON.parse(m.text)}catch{i=void 0}return Fo(e.name,i),{statusCode:u.status,statusText:u.statusText,contentType:u.headers.get("content-type"),bodyText:m.text,parsed:i,bytes:m.bytes,truncated:m.truncated}}function dn(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 jo(e,t,n){let o=W.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let s=await it(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),l=dn(s.parsed);if(l){let m=l.toLowerCase();if(m.includes("method")&&m.includes("not"))return;throw new Error(l)}let a=new AbortController,u=setTimeout(()=>a.abort(),Do);try{await it(e,"notifications/initialized",{},t,a.signal)}catch{}finally{clearTimeout(u)}})();W.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let s=W.get(e.name);W.set(e.name,{initializedAt:Date.now(),cookie:s?.cookie,sessionId:s?.sessionId})}catch(s){throw W.delete(e.name),s}}function No(e,t){let o=W.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),s=t.headers.getSetCookie?.(),l=s&&s.length>0?s.join("; "):r;l&&W.set(e,{...o,cookie:l});let a=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");a&&W.set(e,{...o,sessionId:a})}function Fo(e,t){if(!t||typeof t!="object")return;let o=t.result;if(!o)return;let r=typeof o.sessionId=="string"&&o.sessionId||typeof o.session_id=="string"&&o.session_id;if(!r)return;let s=W.get(e)??{initializedAt:0};W.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=Co(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 u=new Map,m=!1,i="",c=new Error("MCP request aborted."),d=_o.createInterface({input:l.stdout,terminal:!1});d.on("line",v=>{if(v.length>o){m=!0;return}let x=null;try{x=JSON.parse(v)}catch{return}let k=typeof x.id=="string"?x.id:typeof x.id=="number"?String(x.id):"";if(!k)return;let E=u.get(k);E&&(u.delete(k),E.resolve(x))}),l.stderr?.on("data",v=>{let x=v.toString();if(i.length+x.length>o){m=!0;return}i+=x});let p=()=>{for(let v of u.values())v.reject(c);u.clear(),a()};r.addEventListener("abort",p,{once:!0});let y=v=>{let x=v===0?"MCP stdio exited.":i.trim()||"MCP stdio exited with error.";for(let k of u.values())k.reject(new Error(x));u.clear()};l.once("exit",v=>y(v));let h=async(v,x)=>{let k=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,E={jsonrpc:"2.0",id:k,method:v,params:x??{}};return await new Promise((be,Ze)=>{u.set(k,{resolve:be,reject:Ze}),l.stdin?.write(`${JSON.stringify(E)}
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 b=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:!!b.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),b.error&&typeof b.error=="object"){let v=b.error.message??"MCP initialize failed.";throw a(),new Error(String(v))}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 A=await h(t,n);r.removeEventListener("abort",p),d.close(),l.stdin?.end(),a();let M=new Promise(v=>{l.once("exit",()=>v())});if(await Promise.race([M,new Promise(v=>setTimeout(v,500))]),A.error&&typeof A.error=="object"){let v=A.error.message??"MCP request failed.";throw new Error(String(v))}let C=JSON.stringify(A,null,2),_=C.length>o?C.slice(0,o):C;return C.length>o&&(m=!0),{ok:!0,output:_,durationMs:Date.now()-s,bytes:Math.min(C.length,o),truncated:m}}async function zo(e,t,n){let o=e.body?.getReader?.();if(!o){let c=await e.text(),d=Math.min(c.length,t);return{text:c.slice(0,t),bytes:d,truncated:c.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:c,value:d}=await o.read();if(c)break;if(!d)continue;let p=l+d.byteLength;if(p>t){let y=Math.max(0,t-l);y>0&&(s.push(d.slice(0,y)),l+=y),a=!0;try{await o.cancel()}catch{}break}s.push(d),l=p}let u=new Uint8Array(l),m=0;for(let c of s)u.set(c,m),m+=c.byteLength;return{text:r.decode(u),bytes:l,truncated:a}}function mn(e){let t=[],n;try{n=rn.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,u=typeof l.url=="string"?l.url:void 0,m=typeof l.command=="string"?l.command:void 0,i=a==="http"||a==="stdio"?a:u?"http":m?"stdio":void 0;if(!i||i==="http"&&!u||i==="stdio"&&!m)continue;let c;Array.isArray(l.args)&&(c=l.args.filter(p=>typeof p=="string").map(p=>p.trim()));let d=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:u,command:m,args:c,auth:d})}return t}var Ro,sn,To,Eo,fe,an,W,Do,Ae=F(()=>{"use strict";Ro=6e4,sn=2e5,To=40,Eo=3500,fe=null,an=!1,W=new Map,Do=1500});import te from"node:path";import Bo from"node:fs/promises";import{Type as P}from"@sinclair/typebox";function Ue(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function Jo(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 gn(e){let t=g.fetchTimeoutMs>0?g.fetchTimeoutMs:Wo;return Ue(e||t,1e3,12e4)}function pn(e){let t=g.fetchMaxBytes>0?g.fetchMaxBytes:Ko;return Ue(e||t,1024,5e6)}function fn(e,t,n){let o=e.trim();if(!o)return null;let r=B(o),s=te.isAbsolute(r)?r:te.join(n,r),l=te.resolve(s);for(let a of t){let u=te.resolve(a);if(l===u||l.startsWith(`${u}${te.sep}`))return l}return null}async function yn(e){try{let t=await Bo.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 qo(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 Go(e,t,n){let o=e.body?.getReader?.();if(!o){let i=await e.text?.()??"",c=Math.min(i.length,t),d=i.length>t;return{text:i.slice(0,t),bytes:c,truncated:d}}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:c}=await o.read();if(i)break;if(!c)continue;let d=l+c.byteLength;if(d>t){let p=Math.max(0,t-l);p>0&&(s.push(c.slice(0,p)),l+=p),a=!0;try{await o.cancel?.()}catch{}break}s.push(c),l=d}let u=qo(s,l);return{text:r.decode(u),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}
12
+ Be concise and practical in all responses.`;({data:To}=Me()),f=on(To)});import{createHash as Eo}from"node:crypto";import an from"node:fs";import Do from"node:path";import{execSync as Oo}from"node:child_process";function Lo(){return Do.join(f.codexHome,No)}function Uo(e){return`cli|${Eo("sha256").update(e).digest("hex").slice(0,16)}`}function Io(){if(process.platform!=="darwin")return null;let e=f.codexHome,t=Uo(e);try{let n=Oo(`security find-generic-password -s "${jo}" -a "${t}" -w`,{encoding:"utf8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim(),o=JSON.parse(n),r=o.tokens,i=r?.access_token,c=r?.refresh_token;if(typeof i!="string"||!i||typeof c!="string"||!c)return null;let u=o.last_refresh,l=typeof u=="string"||typeof u=="number"?new Date(u).getTime():Date.now(),m=Number.isFinite(l)?l+3600*1e3:Date.now()+3600*1e3;return{accessToken:i,refreshToken:c,expiresAt:m,source:"keychain"}}catch{return null}}function Fo(){let e=Lo();try{let t=an.readFileSync(e,"utf8"),o=JSON.parse(t).tokens,r=o?.access_token,i=o?.refresh_token;if(typeof r!="string"||!r||typeof i!="string"||!i)return null;let c=Date.now()+3600*1e3;try{c=an.statSync(e).mtimeMs+3600*1e3}catch{}return{accessToken:r,refreshToken:i,expiresAt:c,source:"file"}}catch{return null}}function X(){return Io()??Fo()}var No,jo,be=z(()=>{"use strict";K();No="auth.json",jo="Codex Auth"});function cn(e){let t=e.trim().toLowerCase();if(t==="openai-codex"||t==="codex"){let n=X();if(n)return{apiKey:n.accessToken,source:`codex:${n.source}`};throw new Error("No Codex OAuth credentials found. Run `codex login`.")}if(f.openaiApiKey)return{apiKey:f.openaiApiKey,source:"config.model.openai_api_key"};throw new Error(`No API key for provider: ${e}`)}function zo(){return f.proxyUrl?{url:f.proxyUrl,source:"config.proxy.url"}:f.fetchProxyUrl?{url:f.fetchProxyUrl,source:"config.fetch.proxy_url"}:null}function ln(e){let t=e.toLowerCase();return t.startsWith("socks5://")||t.startsWith("socks4://")||t.startsWith("socks://")?"socks":t.startsWith("https://")?"https":"http"}function un(){let e=zo();return e?{url:e.url,kind:ln(e.url),source:e.source}:null}function dn(){let e=[{key:"config.fetch.proxy_url",value:f.fetchProxyUrl},{key:"config.proxy.url",value:f.proxyUrl}];for(let t of e){let n=t.value?.trim();if(!n)continue;let o=ln(n);if(o!=="socks")return{url:n,kind:o,source:t.key}}return null}var it=z(()=>{"use strict";K();be()});import{ProxyAgent as Ko,setGlobalDispatcher as Bo}from"undici";function Ie(){if(mn)return at;mn=!0;let e=dn();if(!e)return at=null,null;let t=new Ko(e.url);return Bo(t),at=e,e}var mn,at,ct=z(()=>{"use strict";it();mn=!1,at=null});import Wo from"node:fs";import Jo from"node:fs/promises";import Ho from"node:path";import qo from"node:readline";import{spawn as Go}from"node:child_process";import*as fn from"@iarna/toml";function hn(e){return Ho.join(e,"config.toml")}function Fe(e){let t=hn(e);try{let n=Wo.readFileSync(t,"utf8");return xn(n)}catch{return[]}}async function ke(e){let t=hn(e);try{let n=await Jo.readFile(t,"utf8");return xn(n)}catch{return[]}}async function pe(e,t={}){if(ve)return ve;let n=await ke(e);if(n.length===0)return ve="","";let o=t.maxTools??Yo,r=t.maxChars??Xo,i=t.timeoutMs??4e3,c=t.maxBytes??gn,u=["MCP catalog (auto-discovered):","Use tool 'mcp' with server=<name> method=<tool> params=<object>."];for(let m of n){let s=await Zo(m,{timeoutMs:i,maxBytes:c});if(u.push(`${m.name} (${m.type})`),s.length===0){u.push(" - tools unavailable");continue}let a=s.slice(0,o);for(let d of a){let p=d.description?`: ${d.description}`:"";u.push(` - ${d.name}${p}`)}s.length>a.length&&u.push(` - ...and ${s.length-a.length} more`)}let l=u.join(`
13
+ `);return l.length>r&&(l=`${l.slice(0,r-20)}...
14
+ (truncated)`),ve=l,l}function Pe(){ve&&(yn=!0)}function wn(){ve=null,yn=!1,H.clear()}function fe(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 bn(e,t=5e3){let n=Date.now();try{return await ze(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 ze(e,t,n,o={}){let r=pn(o.timeoutMs??Vo,1e3,12e4),i=pn(o.maxBytes??gn,1024,5e6),c=new AbortController,u=()=>c.abort();o.signal?.addEventListener("abort",u,{once:!0});let l=setTimeout(()=>c.abort(),r);try{return e.type==="http"?(t!=="initialize"&&t!=="notifications/initialized"&&await nr(e,i,c.signal),await tr(e,t,n,i,c.signal)):await sr(e,t,n,i,c.signal)}finally{clearTimeout(l),o.signal?.removeEventListener("abort",u)}}function pn(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}async function Zo(e,t){try{let n=await ze(e,"tools/list",{},t);return er(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 er(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 i=[];for(let c of r){if(!c||typeof c!="object")continue;let u=c,l=typeof u.name=="string"?u.name:"";if(!l)continue;let m=typeof u.description=="string"?u.description:void 0,s=u.inputSchema;i.push({name:l,description:m,inputSchema:s})}return i}async function tr(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let i=Date.now(),c=await lt(e,t,n,o,r),u=vn(c.parsed);if(u)throw new Error(u);let l=c.bodyText;return c.parsed&&(l=JSON.stringify(c.parsed,null,2)),{ok:c.statusCode>=200&&c.statusCode<300,output:l,durationMs:Date.now()-i,bytes:c.bytes,truncated:c.truncated,statusCode:c.statusCode,statusText:c.statusText,contentType:c.contentType}}async function lt(e,t,n,o,r){if(!e.url)throw new Error("MCP server url is missing.");let i=H.get(e.name),c={jsonrpc:"2.0",id:`tg-agent-${Date.now()}`,method:t,params:n??{}},u={"content-type":"application/json"};e.auth&&(u.authorization=e.auth.startsWith("Bearer ")?e.auth:`Bearer ${e.auth}`),i?.cookie&&(u.cookie=i.cookie),i?.sessionId&&(u["mcp-session-id"]=i.sessionId);let l=await fetch(e.url,{method:"POST",headers:u,body:JSON.stringify(c),signal:r});or(e.name,l);let m=await ir(l,o,r),s;try{s=JSON.parse(m.text)}catch{s=void 0}return rr(e.name,s),{statusCode:l.status,statusText:l.statusText,contentType:l.headers.get("content-type"),bodyText:m.text,parsed:s,bytes:m.bytes,truncated:m.truncated}}function vn(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 nr(e,t,n){let o=H.get(e.name);if(o?.initializedAt)return;if(o?.inFlight){await o.inFlight;return}let r=(async()=>{let i=await lt(e,"initialize",{protocolVersion:"2024-11-05",clientInfo:{name:"tg-agent",version:process.env.npm_package_version??"dev"},capabilities:{}},t,n),c=vn(i.parsed);if(c){let m=c.toLowerCase();if(m.includes("method")&&m.includes("not"))return;throw new Error(c)}let u=new AbortController,l=setTimeout(()=>u.abort(),Qo);try{await lt(e,"notifications/initialized",{},t,u.signal)}catch{}finally{clearTimeout(l)}})();H.set(e.name,{initializedAt:Date.now(),inFlight:r});try{await r;let i=H.get(e.name);H.set(e.name,{initializedAt:Date.now(),cookie:i?.cookie,sessionId:i?.sessionId})}catch(i){throw H.delete(e.name),i}}function or(e,t){let o=H.get(e)??{initializedAt:0},r=t.headers.get("set-cookie"),i=t.headers.getSetCookie?.(),c=i&&i.length>0?i.join("; "):r;c&&H.set(e,{...o,cookie:c});let u=t.headers.get("mcp-session-id")??t.headers.get("x-mcp-session-id");u&&H.set(e,{...o,sessionId:u})}function rr(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 i=H.get(e)??{initializedAt:0};H.set(e,{...i,sessionId:r})}async function sr(e,t,n,o,r){if(!e.command)throw new Error("MCP server command is missing.");let i=Date.now(),c=Go(e.command,e.args??[],{stdio:["pipe","pipe","pipe"]}),u=()=>{c.killed||c.kill("SIGTERM")};if(r.aborted)throw u(),new Error("MCP request aborted.");let l=new Map,m=!1,s="",a=new Error("MCP request aborted."),d=qo.createInterface({input:c.stdout,terminal:!1});d.on("line",S=>{if(S.length>o){m=!0;return}let b=null;try{b=JSON.parse(S)}catch{return}let k=typeof b.id=="string"?b.id:typeof b.id=="number"?String(b.id):"";if(!k)return;let I=l.get(k);I&&(l.delete(k),I.resolve(b))}),c.stderr?.on("data",S=>{let b=S.toString();if(s.length+b.length>o){m=!0;return}s+=b});let p=()=>{for(let S of l.values())S.reject(a);l.clear(),u()};r.addEventListener("abort",p,{once:!0});let h=S=>{let b=S===0?"MCP stdio exited.":s.trim()||"MCP stdio exited with error.";for(let k of l.values())k.reject(new Error(b));l.clear()};c.once("exit",S=>h(S));let y=async(S,b)=>{let k=`tg-agent-${Date.now()}-${Math.random().toString(16).slice(2,8)}`,I={jsonrpc:"2.0",id:k,method:S,params:b??{}};return await new Promise((ie,tt)=>{l.set(k,{resolve:ie,reject:tt}),c.stdin?.write(`${JSON.stringify(I)}
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()-i},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{});let w=await y("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()-i,hasError:!!w.error},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"B,C"})}).catch(()=>{}),w.error&&typeof w.error=="object"){let S=w.error.message??"MCP initialize failed.";throw u(),new Error(String(S))}let x={jsonrpc:"2.0",method:"notifications/initialized"};c.stdin?.write(`${JSON.stringify(x)}
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()-i},timestamp:Date.now(),sessionId:"debug-session",hypothesisId:"C"})}).catch(()=>{});let M=await y(t,n);r.removeEventListener("abort",p),d.close(),c.stdin?.end(),u();let $=new Promise(S=>{c.once("exit",()=>S())});if(await Promise.race([$,new Promise(S=>setTimeout(S,500))]),M.error&&typeof M.error=="object"){let S=M.error.message??"MCP request failed.";throw new Error(String(S))}let P=JSON.stringify(M,null,2),U=P.length>o?P.slice(0,o):P;return P.length>o&&(m=!0),{ok:!0,output:U,durationMs:Date.now()-i,bytes:Math.min(P.length,o),truncated:m}}async function ir(e,t,n){let o=e.body?.getReader?.();if(!o){let a=await e.text(),d=Math.min(a.length,t);return{text:a.slice(0,t),bytes:d,truncated:a.length>t}}let r=new TextDecoder("utf-8"),i=[],c=0,u=!1;for(;;){if(n.aborted){try{await o.cancel()}catch{}throw new Error("MCP request aborted.")}let{done:a,value:d}=await o.read();if(a)break;if(!d)continue;let p=c+d.byteLength;if(p>t){let h=Math.max(0,t-c);h>0&&(i.push(d.slice(0,h)),c+=h),u=!0;try{await o.cancel()}catch{}break}i.push(d),c=p}let l=new Uint8Array(c),m=0;for(let a of i)l.set(a,m),m+=a.byteLength;return{text:r.decode(l),bytes:c,truncated:u}}function xn(e){let t=[],n;try{n=fn.parse(e)}catch{return t}let o=n.mcp_servers;if(!o||typeof o!="object")return t;for(let[r,i]of Object.entries(o)){if(!i||typeof i!="object")continue;let c=i,u=typeof c.type=="string"?c.type.toLowerCase():void 0,l=typeof c.url=="string"?c.url:void 0,m=typeof c.command=="string"?c.command:void 0,s=u==="http"||u==="stdio"?u:l?"http":m?"stdio":void 0;if(!s||s==="http"&&!l||s==="stdio"&&!m)continue;let a;Array.isArray(c.args)&&(a=c.args.filter(p=>typeof p=="string").map(p=>p.trim()));let d=typeof c.auth=="string"?c.auth:typeof c.authorization=="string"?c.authorization:typeof c.token=="string"?c.token:void 0;t.push({name:r,type:s,url:l,command:m,args:a,auth:d})}return t}var Vo,gn,Yo,Xo,ve,yn,H,Qo,_e=z(()=>{"use strict";Vo=6e4,gn=2e5,Yo=40,Xo=3500,ve=null,yn=!1,H=new Map,Qo=1500});import oe from"node:path";import ar from"node:fs/promises";import{Type as _}from"@sinclair/typebox";function Ke(e,t,n){return Number.isNaN(e)?t:Math.min(n,Math.max(t,e))}function ur(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 $n(e){let t=f.fetchTimeoutMs>0?f.fetchTimeoutMs:lr;return Ke(e||t,1e3,12e4)}function Sn(e){let t=f.fetchMaxBytes>0?f.fetchMaxBytes:cr;return Ke(e||t,1024,5e6)}function An(e,t,n){let o=e.trim();if(!o)return null;let r=W(o),i=oe.isAbsolute(r)?r:oe.join(n,r),c=oe.resolve(i);for(let u of t){let l=oe.resolve(u);if(c===l||c.startsWith(`${l}${oe.sep}`))return c}return null}async function Mn(e){try{let t=await ar.stat(e);return t.isFile()?{bytes:t.size}:null}catch{return null}}function dr(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function mr(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 pr(e,t,n){let o=e.body?.getReader?.();if(!o){let s=await e.text?.()??"",a=Math.min(s.length,t),d=s.length>t;return{text:s.slice(0,t),bytes:a,truncated:d}}let r=new TextDecoder("utf-8"),i=[],c=0,u=!1;for(;;){if(n?.aborted){try{await o.cancel?.()}catch{}throw new Error("Fetch aborted")}let{done:s,value:a}=await o.read();if(s)break;if(!a)continue;let d=c+a.byteLength;if(d>t){let p=Math.max(0,t-c);p>0&&(i.push(a.slice(0,p)),c+=p),u=!0;try{await o.cancel?.()}catch{}break}i.push(a),c=d}let l=mr(i,c);return{text:r.decode(l),bytes:c,truncated:u}}function fr(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 Xo(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:Yo,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=gn(t.timeoutMs),l=pn(t.maxBytes),a=new AbortController,u=()=>a.abort();r?.addEventListener("abort",u,{once:!0});let m=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:Jo(t.headers),body:t.body,signal:a.signal}),c=await Go(i,l,r),d=i.headers.get("content-type");return{content:[{type:"text",text:Vo({url:i.url,status:i.status,statusText:i.statusText,bytes:c.bytes,truncated:c.truncated,contentType:d},c.text)}],details:{url:i.url,status:i.status,statusText:i.statusText,bytes:c.bytes,truncated:c.truncated,contentType:d}}}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(m),r?.removeEventListener("abort",u)}}}}function Zo(e,t,n){let o=t.status>0?`HTTP ${t.status} ${t.statusText}`.trim():t.statusText,r=[`server: ${e.name}`,`type: ${e.type}`,`target: ${t.target}`,`bytes: ${t.bytes}${t.truncated?" (truncated)":""}`,`content-type: ${t.contentType??"unknown"}`];return`${o}
20
+ ${t}`}function yr(){return{name:"fetch",label:"fetch",description:"Fetch a URL via HTTP(S) and return the response body.",parameters:gr,execute:async(e,t,n,o,r)=>{if(!dr(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 i=$n(t.timeoutMs),c=Sn(t.maxBytes),u=new AbortController,l=()=>u.abort();r?.addEventListener("abort",l,{once:!0});let m=setTimeout(()=>u.abort(),i);try{n?.({content:[{type:"text",text:`Fetching ${t.url}...`}],details:{url:t.url,status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let s=await fetch(t.url,{method:t.method?.toUpperCase()??"GET",headers:ur(t.headers),body:t.body,signal:u.signal}),a=await pr(s,c,r),d=s.headers.get("content-type");return{content:[{type:"text",text:fr({url:s.url,status:s.status,statusText:s.statusText,bytes:a.bytes,truncated:a.truncated,contentType:d},a.text)}],details:{url:s.url,status:s.status,statusText:s.statusText,bytes:a.bytes,truncated:a.truncated,contentType:d}}}catch(s){return{content:[{type:"text",text:`Fetch failed: ${s instanceof Error?s.message:String(s)}`}],details:{url:t.url,status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}finally{clearTimeout(m),r?.removeEventListener("abort",l)}}}}function wr(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 er(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:Qo,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(m=>m.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let u=l.find(m=>m.name===a);if(!u)return{content:[{type:"text",text:`MCP server not found: ${a}. Available: ${l.map(m=>m.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 ${u.name} ${n.method}...`}],details:{server:u.name,type:u.type,target:ue(u),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let m=await Fe(u,n.method,n.params??{},{timeoutMs:gn(void 0),maxBytes:pn(void 0),signal:s});return{content:[{type:"text",text:Zo(u,{server:u.name,type:u.type,target:ue(u),status:m.statusCode??0,statusText:m.statusText??(m.ok?"ok":"error"),bytes:m.bytes,truncated:m.truncated,contentType:m.contentType??null},m.output)}],details:{server:u.name,type:u.type,target:ue(u),status:m.statusCode??0,statusText:m.statusText??(m.ok?"ok":"error"),bytes:m.bytes,truncated:m.truncated,contentType:m.contentType??null}}}catch(m){return{content:[{type:"text",text:`MCP failed: ${m instanceof Error?m.message:String(m)}`}],details:{server:u.name,type:u.type,target:ue(u),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function or(e){let t=[g.workspaceDir,te.join(g.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:tr,execute:async(n,o)=>{let r=fn(o.path,t,g.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 yn(r);return s?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${te.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function rr(e){let t=[g.workspaceDir,te.join(g.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:nr,execute:async(n,o)=>{let r=fn(o.path,t,g.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 yn(r);return s?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${te.basename(r)}`}],details:{path:r,bytes:s.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function hn(e){let t=[Xo()];return e?.telegram&&(t.push(or(e.telegram)),t.push(rr(e.telegram))),Ne(g.agentDir).length>0&&t.push(er(()=>Me(g.agentDir))),t}var Ko,Wo,Yo,Qo,tr,nr,wn=F(()=>{"use strict";K();Ae();q();Ko=2e5,Wo=6e4;Yo=P.Object({url:P.String({description:"HTTP or HTTPS URL"}),method:P.Optional(P.String({description:"HTTP method (default: GET)"})),headers:P.Optional(P.Array(P.Object({name:P.String({description:"Header name"}),value:P.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:P.Optional(P.String({description:"Request body (string)"})),timeoutMs:P.Optional(P.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:P.Optional(P.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});Qo=P.Object({server:P.Optional(P.String({description:"MCP server name"})),method:P.String({description:"MCP method name"}),params:P.Optional(P.Any({description:"MCP params payload"}))});tr=P.Object({path:P.String({description:"Image file path (relative to workspace or uploads)."}),caption:P.Optional(P.String({description:"Caption text (plain text)."}))}),nr=P.Object({path:P.String({description:"File path (relative to workspace or uploads)."}),caption:P.Optional(P.String({description:"Caption text (plain text)."}))})});import xn from"node:fs/promises";import Sn from"node:path";function Mn(e){return Sn.join(g.sessionDir,`${e}.json`)}function bn(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function at(e,t){let n=bn(e),o=bn(t);return Sn.join(g.sessionDir,`${n}-${o}.jsonl`)}async function ye(e,t){let n=at(e,t);try{await xn.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function vn(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 Be(e){await T(g.sessionDir);let t=ze.get(e);if(t)return t;let n=Mn(e);try{let o=await xn.readFile(n,"utf8"),r=JSON.parse(o),s=vn(e,r);return ze.set(e,s),s}catch(o){if(o.code==="ENOENT"){let r=vn(e,{});return ze.set(e,r),r}throw o}}async function I(e){await T(g.sessionDir);let t=Mn(e.chatId);await De(t,e),ze.set(e.chatId,e)}function ct(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function lt(e){return[]}function Ke(e,t){if(Object.keys(e.sessions).length>=g.maxSessions)throw new Error("Max sessions reached");let o=ee(),r=U(),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 $n(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function de(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function ut(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function An(e){e.messages=[],e.updatedAt=U()}function dt(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=U()}function kn(e,t){e.workspaceDir=t}var ze,mt=F(()=>{"use strict";K();q();ze=new Map});import sr from"node:fs/promises";import _n from"node:path";import{completeSimple as ir}from"@mariozechner/pi-ai";function ur(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return lr.replace("{{command}}",n)}function dr(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 mr(e,t,n,o,r){let s=ur(n,o);try{let a={systemPrompt:'You are a security analyst. Reply with ONLY valid JSON: {"riskLevel":"none|low|critical","reason":"brief explanation"}.',messages:[{role:"user",content:s,timestamp:Date.now()}]},u=await ir(e,a,{apiKey:t,maxTokens:500,temperature:0,...r&&{sessionId:r}}),m=u.content.find(c=>c.type==="text"),i=m?.type==="text"?m.text:"";return i.trim()||(i=u.content.filter(d=>d.type==="thinking").map(d=>d.type==="thinking"?d.thinking:"").filter(Boolean).join(`
24
+ ${n}`}function br(e){return{name:"mcp",label:"mcp",description:"Call an MCP endpoint via JSON-RPC.",parameters:hr,execute:async(t,n,o,r,i)=>{let c=await e();if(c.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 u=n.server?.trim()??"";if(!u)if(c.length===1)u=c[0]?.name??"";else return{content:[{type:"text",text:`Multiple MCP servers configured. Provide server name. Available: ${c.map(m=>m.name).join(", ")}`}],details:{server:"",type:"http",target:"",status:0,statusText:"server_required",bytes:0,truncated:!1,contentType:null}};let l=c.find(m=>m.name===u);if(!l)return{content:[{type:"text",text:`MCP server not found: ${u}. Available: ${c.map(m=>m.name).join(", ")}`}],details:{server:u,type:"http",target:"",status:0,statusText:"server_not_found",bytes:0,truncated:!1,contentType:null}};try{o?.({content:[{type:"text",text:`Calling MCP ${l.name} ${n.method}...`}],details:{server:l.name,type:l.type,target:fe(l),status:0,statusText:"pending",bytes:0,truncated:!1,contentType:null}});let m=await ze(l,n.method,n.params??{},{timeoutMs:$n(void 0),maxBytes:Sn(void 0),signal:i});return{content:[{type:"text",text:wr(l,{server:l.name,type:l.type,target:fe(l),status:m.statusCode??0,statusText:m.statusText??(m.ok?"ok":"error"),bytes:m.bytes,truncated:m.truncated,contentType:m.contentType??null},m.output)}],details:{server:l.name,type:l.type,target:fe(l),status:m.statusCode??0,statusText:m.statusText??(m.ok?"ok":"error"),bytes:m.bytes,truncated:m.truncated,contentType:m.contentType??null}}}catch(m){return{content:[{type:"text",text:`MCP failed: ${m instanceof Error?m.message:String(m)}`}],details:{server:l.name,type:l.type,target:fe(l),status:0,statusText:"error",bytes:0,truncated:!1,contentType:null}}}}}}function $r(e){let t=[f.workspaceDir,oe.join(f.agentDir,"uploads")];return{name:"send_photo",label:"send_photo",description:"Send an image file to the current Telegram chat.",parameters:vr,execute:async(n,o)=>{let r=An(o.path,t,f.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let i=await Mn(r);return i?(await e.sendPhoto(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`Photo sent: ${oe.basename(r)}`}],details:{path:r,bytes:i.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function Sr(e){let t=[f.workspaceDir,oe.join(f.agentDir,"uploads")];return{name:"send_file",label:"send_file",description:"Send a file to the current Telegram chat.",parameters:xr,execute:async(n,o)=>{let r=An(o.path,t,f.workspaceDir);if(!r)return{content:[{type:"text",text:"Invalid path. Only workspace or uploads are allowed."}],details:{path:o.path,bytes:0}};let i=await Mn(r);return i?(await e.sendDocument(r,o.caption?.trim()||void 0),{content:[{type:"text",text:`File sent: ${oe.basename(r)}`}],details:{path:r,bytes:i.bytes}}):{content:[{type:"text",text:`File not found: ${r}`}],details:{path:r,bytes:0}}}}}function kn(e){let t=[yr()];return e?.telegram&&(t.push($r(e.telegram)),t.push(Sr(e.telegram))),Fe(f.agentDir).length>0&&t.push(br(()=>ke(f.agentDir))),t}var cr,lr,gr,hr,vr,xr,Pn=z(()=>{"use strict";K();_e();J();cr=2e5,lr=6e4;gr=_.Object({url:_.String({description:"HTTP or HTTPS URL"}),method:_.Optional(_.String({description:"HTTP method (default: GET)"})),headers:_.Optional(_.Array(_.Object({name:_.String({description:"Header name"}),value:_.String({description:"Header value"})}),{description:"Request headers as name/value pairs"})),body:_.Optional(_.String({description:"Request body (string)"})),timeoutMs:_.Optional(_.Integer({description:"Timeout in milliseconds",minimum:1e3,maximum:12e4})),maxBytes:_.Optional(_.Integer({description:"Max response bytes",minimum:1024,maximum:5e6}))});hr=_.Object({server:_.Optional(_.String({description:"MCP server name"})),method:_.String({description:"MCP method name"}),params:_.Optional(_.Any({description:"MCP params payload"}))});vr=_.Object({path:_.String({description:"Image file path (relative to workspace or uploads)."}),caption:_.Optional(_.String({description:"Caption text (plain text)."}))}),xr=_.Object({path:_.String({description:"File path (relative to workspace or uploads)."}),caption:_.Optional(_.String({description:"Caption text (plain text)."}))})});import Rn from"node:fs/promises";import Tn from"node:path";function En(e){return Tn.join(f.sessionDir,`${e}.json`)}function _n(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_")}function ut(e,t){let n=_n(e),o=_n(t);return Tn.join(f.sessionDir,`${n}-${o}.jsonl`)}async function xe(e,t){let n=ut(e,t);try{await Rn.unlink(n)}catch(o){if(o.code==="ENOENT")return;throw o}}function Cn(e,t){let n=t?.sessions??{},o=t?.activeSessionId??null,r=t?.workspaceDir,i={chatId:e,workspaceDir:r,activeSessionId:o,sessions:n};return(!o||!n[o])&&(i.activeSessionId=null),i}async function We(e){await C(f.sessionDir);let t=Be.get(e);if(t)return t;let n=En(e);try{let o=await Rn.readFile(n,"utf8"),r=JSON.parse(o),i=Cn(e,r);return Be.set(e,i),i}catch(o){if(o.code==="ENOENT"){let r=Cn(e,{});return Be.set(e,r),r}throw o}}async function T(e){await C(f.sessionDir);let t=En(e.chatId);await he(t,e),Be.set(e.chatId,e)}function dt(e){return Object.values(e.sessions).sort((t,n)=>n.updatedAt-t.updatedAt)}function mt(e){return[]}function Je(e,t){if(Object.keys(e.sessions).length>=f.maxSessions)throw new Error("Max sessions reached");let o=ne(),r=D(),i={id:o,title:t&&t.length>0?t:`session-${o}`,messages:[],createdAt:r,updatedAt:r};return e.sessions[o]=i,e.activeSessionId=o,i}function Dn(e,t){return e.sessions[t]?(e.activeSessionId=t,!0):!1}function ge(e){return e.activeSessionId?e.sessions[e.activeSessionId]??null:null}function pt(e,t){return e.sessions[t]?(delete e.sessions[t],e.activeSessionId===t&&(e.activeSessionId=null),!0):!1}function On(e){e.messages=[],e.updatedAt=D()}function ft(e,t,n){e.messages.push(t),e.messages.length>n&&(e.messages=e.messages.slice(-n)),e.updatedAt=D()}function Nn(e,t){e.workspaceDir=t}var Be,gt=z(()=>{"use strict";K();J();Be=new Map});import Ar from"node:fs/promises";import Ln from"node:path";import{completeSimple as Mr}from"@mariozechner/pi-ai";function Cr(e,t){let n=e==="bash"&&typeof t.command=="string"?t.command:`${e}: ${JSON.stringify(t)}`;return _r.replace("{{command}}",n)}function Rr(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]),i=r.riskLevel?.toLowerCase();if(i==="none"||i==="low"||i==="critical")return{riskLevel:i,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 Tr(e,t,n,o,r){let i=Cr(n,o);try{let u={systemPrompt:'You are a security analyst. Reply with ONLY valid JSON: {"riskLevel":"none|low|critical","reason":"brief explanation"}.',messages:[{role:"user",content:i,timestamp:Date.now()}]},l=await Mr(e,u,{apiKey:t,maxTokens:500,temperature:0,...r&&{sessionId:r}}),m=l.content.find(a=>a.type==="text"),s=m?.type==="text"?m.text:"";return s.trim()||(s=l.content.filter(d=>d.type==="thinking").map(d=>d.type==="thinking"?d.thinking:"").filter(Boolean).join(`
25
25
 
26
- `)),dr(i)}catch(l){let a=l instanceof Error?l.message:String(l);return console.error("[audit] AI analysis failed:",a),{riskLevel:"low",reason:`AI analysis failed: ${a}`}}}function gr(e,t){let n=e.trim();return t.some(o=>o.test(n))}function pr(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 oe(e,t,n){try{await T(Pn);let o=_n.join(Pn,`${e}-${t}.log`),r=JSON.stringify(n)+`
27
- `;await sr.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 fr(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(`
28
- `)}function Cn(e,t){let n=g.audit,o=pr(n.whitelistPatterns);return r=>{r.on("tool_call",async(s,l)=>{let{toolName:a,toolCallId:u,input:m}=s,i={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:a,toolCallId:u,input:m,riskLevel:"none",analysis:"",action:"passed"};if(ar.has(a)){i.analysis="Read-only tool",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=passed (read-only)`);return}if(!cr.has(a)){i.analysis="Tool not in analysis scope",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=passed (not analyzed)`);return}if(a==="bash"){let d=m.command??"";if(gr(d,o)){i.analysis="Whitelisted bash command",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=passed (whitelisted)`);return}}if(!t){i.analysis="No audit model configured",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=passed (no audit model)`);return}console.log(`[audit] analyzing tool=${a} id=${u}`);let c=await mr(t.model,t.apiKey,a,m,e.sessionId);if(i.riskLevel=c.riskLevel,i.analysis=c.reason,c.riskLevel==="none"||c.riskLevel==="low"){i.action="passed",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} risk=${c.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${a} id=${u} reason=${c.reason}`);try{let d=fr(i);if(await e.requestConfirmation(d,n.confirmTimeoutMs)){i.action="approved",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=approved`);return}return i.action="blocked",await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=blocked (user rejected)`),l.abort(),{block:!0,reason:"Operation blocked by user due to security risk."}}catch(d){let p=d instanceof Error?d.message:String(d);return i.action="blocked",i.analysis=`${c.reason} (confirmation failed: ${p})`,await oe(e.chatId,e.sessionId,i),console.log(`[audit] tool=${a} id=${u} action=blocked (${p})`),l.abort(),{block:!0,reason:`Security confirmation failed: ${p}`}}})}}var ar,cr,lr,Pn,Rn=F(()=>{"use strict";K();q();ar=new Set(["read","ls","find","grep"]),cr=new Set(["bash"]),lr=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
26
+ `)),Rr(s)}catch(c){let u=c instanceof Error?c.message:String(c);return console.error("[audit] AI analysis failed:",u),{riskLevel:"low",reason:`AI analysis failed: ${u}`}}}function Er(e,t){let n=e.trim();return t.some(o=>o.test(n))}function Dr(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 ae(e,t,n){try{await C(jn);let o=Ln.join(jn,`${e}-${t}.log`),r=JSON.stringify(n)+`
27
+ `;await Ar.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 Or(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(`
28
+ `)}function Un(e,t){let n=f.audit,o=Dr(n.whitelistPatterns);return r=>{r.on("tool_call",async(i,c)=>{let{toolName:u,toolCallId:l,input:m}=i,s={timestamp:new Date().toISOString(),sessionId:e.sessionId,toolName:u,toolCallId:l,input:m,riskLevel:"none",analysis:"",action:"passed"};if(kr.has(u)){s.analysis="Read-only tool",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=passed (read-only)`);return}if(!Pr.has(u)){s.analysis="Tool not in analysis scope",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=passed (not analyzed)`);return}if(u==="bash"){let d=m.command??"";if(Er(d,o)){s.analysis="Whitelisted bash command",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=passed (whitelisted)`);return}}if(!t){s.analysis="No audit model configured",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=passed (no audit model)`);return}console.log(`[audit] analyzing tool=${u} id=${l}`);let a=await Tr(t.model,t.apiKey,u,m,e.sessionId);if(s.riskLevel=a.riskLevel,s.analysis=a.reason,a.riskLevel==="none"||a.riskLevel==="low"){s.action="passed",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} risk=${a.riskLevel} action=passed`);return}console.log(`[audit] CRITICAL tool=${u} id=${l} reason=${a.reason}`);try{let d=Or(s);if(await e.requestConfirmation(d,n.confirmTimeoutMs)){s.action="approved",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=approved`);return}return s.action="blocked",await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=blocked (user rejected)`),c.abort(),{block:!0,reason:"Operation blocked by user due to security risk."}}catch(d){let p=d instanceof Error?d.message:String(d);return s.action="blocked",s.analysis=`${a.reason} (confirmation failed: ${p})`,await ae(e.chatId,e.sessionId,s),console.log(`[audit] tool=${u} id=${l} action=blocked (${p})`),c.abort(),{block:!0,reason:`Security confirmation failed: ${p}`}}})}}var kr,Pr,_r,jn,In=z(()=>{"use strict";K();J();kr=new Set(["read","ls","find","grep"]),Pr=new Set(["bash"]),_r=`Analyze this command for security risks. Reply with ONLY a JSON object, no other text.
29
29
 
30
30
  Command: {{command}}
31
31
 
@@ -35,21 +35,21 @@ Risk levels:
35
35
  - "critical": High risk (secrets exposure, destructive ops, network attacks, privilege escalation)
36
36
 
37
37
  Reply format (ONLY this JSON, nothing else):
38
- {"riskLevel":"none|low|critical","reason":"brief explanation"}`;Pn=_n.join(g.sessionDir,"audit-logs")});import{readFileSync as yr,existsSync as hr,chmodSync as wr}from"node:fs";import Tn from"node:path";import{getOAuthProvider as br}from"@mariozechner/pi-ai";function ne(){return gt||(gt=new pt),gt}var pt,gt,ft=F(()=>{"use strict";K();q();pt=class{filePath;data={};constructor(t){this.filePath=t??Tn.join(g.agentDir,"multi-auth.json"),this.reload()}reload(){if(!hr(this.filePath)){this.data={};return}try{let t=yr(this.filePath,"utf8");this.data=JSON.parse(t)}catch{this.data={}}}async save(){let t=Tn.dirname(this.filePath);await T(t),await De(this.filePath,this.data);try{wr(this.filePath,384)}catch{}}listAccounts(t){let n=this.data[t];return n?Object.entries(n.accounts).map(([o,r])=>({id:o,email:r.email,isDefault:n.defaultAccountId===o,lastUsedAt:r.lastUsedAt})):[]}async addAccount(t,n,o){this.data[t]||(this.data[t]={accounts:{}});let r=`acc_${ee()}`,s=n;return this.data[t].accounts[r]={type:"oauth",refresh:n.refresh,access:n.access,expires:n.expires,email:o?.email??s.email,projectId:s.projectId,createdAt:Date.now(),lastUsedAt:Date.now()},this.data[t].defaultAccountId||(this.data[t].defaultAccountId=r),await this.save(),r}getAccount(t,n){return this.data[t]?.accounts[n]??null}getDefaultAccount(t){let n=this.data[t];if(!n?.defaultAccountId)return null;let o=n.accounts[n.defaultAccountId];return o?{id:n.defaultAccountId,credential:o}:null}async setDefaultAccount(t,n){let o=this.data[t];return o?.accounts[n]?(o.defaultAccountId=n,await this.save(),!0):!1}async removeAccount(t,n){let o=this.data[t];if(!o?.accounts[n])return!1;if(delete o.accounts[n],o.defaultAccountId===n){let r=Object.keys(o.accounts);o.defaultAccountId=r[0]}return Object.keys(o.accounts).length===0&&delete this.data[t],await this.save(),!0}async removeAllAccounts(t){let n=this.data[t];if(!n)return 0;let o=Object.keys(n.accounts).length;return delete this.data[t],await this.save(),o}async updateCredential(t,n,o){let r=this.data[t]?.accounts[n];if(!r)return;r.refresh=o.refresh,r.access=o.access,r.expires=o.expires,r.lastUsedAt=Date.now();let s=o;s.projectId!==void 0&&(r.projectId=s.projectId),await this.save()}async getApiKey(t,n){let o=this.data[t]?.accounts[n];if(!o)return null;let r=br(t);if(!r)return null;let s=Date.now(),l=300*1e3;if(o.expires-s<l)try{let a={refresh:o.refresh,access:o.access,expires:o.expires,...o.projectId!==void 0&&{projectId:o.projectId}},u=await r.refreshToken(a);return await this.updateCredential(t,n,u),r.getApiKey(u)}catch(a){return console.warn(`[multi-auth] token refresh failed for ${t}/${n}:`,a),o.expires>s?r.getApiKey(o):null}return r.getApiKey(o)}hasMultipleAccounts(t){let n=this.data[t]?.accounts;return n?Object.keys(n).length>1:!1}hasAccounts(t){let n=this.data[t]?.accounts;return n?Object.keys(n).length>0:!1}},gt=null});import{createAgentSession as vr,AuthStorage as xr,ModelRegistry as Sr,SessionManager as Mr,SettingsManager as $r,DefaultResourceLoader as Ar}from"@mariozechner/pi-coding-agent";import We from"node:fs/promises";import Je from"node:path";function En(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Pr(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 _r(e,t){return e!=="openai-codex"?t:kr[t]??t}function Cr(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 Rr(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=En(t?.provider||g.modelProvider||"openai-codex"),s=n||o?"":g.modelRef||"",{provider:l,modelId:a}=Pr(s,r),u=t?.provider?r:En(l),m=o?t?.modelId?.trim()||"":a;if(!m){let d=Cr(e,u);return d?{model:d,provider:u,modelId:d.id}:{model:void 0,provider:u,modelId:""}}let i=_r(u,m);return{model:e.find(u,i),provider:u,modelId:i}}function Tr(e){let t=V();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function Er(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(`
38
+ {"riskLevel":"none|low|critical","reason":"brief explanation"}`;jn=Ln.join(f.sessionDir,"audit-logs")});import{readFileSync as Nr,existsSync as jr,chmodSync as Lr}from"node:fs";import Fn from"node:path";import{getOAuthProvider as Ur}from"@mariozechner/pi-ai";function Q(){return yt||(yt=new ht),yt}var ht,yt,wt=z(()=>{"use strict";K();J();ht=class{filePath;data={};constructor(t){this.filePath=t??Fn.join(f.agentDir,"multi-auth.json"),this.reload()}reload(){if(!jr(this.filePath)){this.data={};return}try{let t=Nr(this.filePath,"utf8");this.data=JSON.parse(t)}catch{this.data={}}}async save(){let t=Fn.dirname(this.filePath);await C(t),await he(this.filePath,this.data);try{Lr(this.filePath,384)}catch{}}listAccounts(t){let n=this.data[t];return n?Object.entries(n.accounts).map(([o,r])=>({id:o,email:r.email,isDefault:n.defaultAccountId===o,lastUsedAt:r.lastUsedAt})):[]}async addAccount(t,n,o){this.data[t]||(this.data[t]={accounts:{}});let r=`acc_${ne()}`,i=n,c=typeof o?.email=="string"?o.email:typeof i.email=="string"?i.email:void 0;return this.data[t].accounts[r]={type:"oauth",refresh:n.refresh,access:n.access,expires:n.expires,email:c,projectId:i.projectId,createdAt:Date.now(),lastUsedAt:Date.now()},this.data[t].defaultAccountId||(this.data[t].defaultAccountId=r),await this.save(),r}getAccount(t,n){return this.data[t]?.accounts[n]??null}getDefaultAccount(t){let n=this.data[t];if(!n?.defaultAccountId)return null;let o=n.accounts[n.defaultAccountId];return o?{id:n.defaultAccountId,credential:o}:null}async setDefaultAccount(t,n){let o=this.data[t];return o?.accounts[n]?(o.defaultAccountId=n,await this.save(),!0):!1}async removeAccount(t,n){let o=this.data[t];if(!o?.accounts[n])return!1;if(delete o.accounts[n],o.defaultAccountId===n){let r=Object.keys(o.accounts);o.defaultAccountId=r[0]}return Object.keys(o.accounts).length===0&&delete this.data[t],await this.save(),!0}async removeAllAccounts(t){let n=this.data[t];if(!n)return 0;let o=Object.keys(n.accounts).length;return delete this.data[t],await this.save(),o}async updateCredential(t,n,o){let r=this.data[t]?.accounts[n];if(!r)return;r.refresh=o.refresh,r.access=o.access,r.expires=o.expires,r.lastUsedAt=Date.now();let i=o;i.projectId!==void 0&&(r.projectId=i.projectId),await this.save()}async getApiKey(t,n){let o=this.data[t]?.accounts[n];if(!o)return null;let r=Ur(t);if(!r)return null;let i=Date.now(),c=300*1e3;if(o.expires-i<c)try{let u={refresh:o.refresh,access:o.access,expires:o.expires,...o.projectId!==void 0&&{projectId:o.projectId}},l=await r.refreshToken(u);return await this.updateCredential(t,n,l),r.getApiKey(l)}catch(u){return console.warn(`[multi-auth] token refresh failed for ${t}/${n}:`,u),o.expires>i?r.getApiKey(o):null}return r.getApiKey(o)}hasMultipleAccounts(t){let n=this.data[t]?.accounts;return n?Object.keys(n).length>1:!1}hasAccounts(t){let n=this.data[t]?.accounts;return n?Object.keys(n).length>0:!1}},yt=null});import{chmodSync as Ir,existsSync as Fr,readFileSync as zr}from"node:fs";import zn from"node:path";function Kr(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e,n=typeof t.apiKey=="string"?t.apiKey.trim():"",o=typeof t.baseUrl=="string"?t.baseUrl.trim():"",r=typeof t.updatedAt=="number"?t.updatedAt:Date.now();return!n&&!o?null:{...n?{apiKey:n}:{},...o?{baseUrl:o}:{},updatedAt:r}}function re(){return bt||(bt=new vt),bt}var vt,bt,xt=z(()=>{"use strict";K();J();vt=class{filePath;data={};constructor(t){this.filePath=t??zn.join(f.agentDir,"api-key-auth.json"),this.reload()}reload(){if(!Fr(this.filePath)){this.data={};return}try{let t=JSON.parse(zr(this.filePath,"utf8"));if(!t||typeof t!="object"||Array.isArray(t)){this.data={};return}let n={};for(let[o,r]of Object.entries(t)){let i=Kr(r);i&&(n[o]=i)}this.data=n}catch{this.data={}}}async save(){await C(zn.dirname(this.filePath)),await he(this.filePath,this.data);try{Ir(this.filePath,384)}catch{}}upsert(t){let n=this.data[t];if(n)return n;let o={updatedAt:Date.now()};return this.data[t]=o,o}cleanup(t){let n=this.data[t];n&&!n.apiKey&&!n.baseUrl&&delete this.data[t]}listProviders(){return Object.keys(this.data).sort((t,n)=>t.localeCompare(n))}getProviderConfig(t){let n=this.data[t];return n?{...n}:null}hasApiKey(t){return!!this.data[t]?.apiKey}async setApiKey(t,n){let o=this.upsert(t);o.apiKey=n.trim(),o.updatedAt=Date.now(),this.cleanup(t),await this.save()}async clearApiKey(t){let n=this.data[t];return n?.apiKey?(delete n.apiKey,n.updatedAt=Date.now(),this.cleanup(t),await this.save(),!0):!1}async setBaseUrl(t,n){let o=this.upsert(t);o.baseUrl=n.trim(),o.updatedAt=Date.now(),this.cleanup(t),await this.save()}async clearBaseUrl(t){let n=this.data[t];return n?.baseUrl?(delete n.baseUrl,n.updatedAt=Date.now(),this.cleanup(t),await this.save(),!0):!1}},bt=null});import{createAgentSession as Br,AuthStorage as Wr,ModelRegistry as Jr,SessionManager as Hr,SettingsManager as qr,DefaultResourceLoader as Gr}from"@mariozechner/pi-coding-agent";import He from"node:fs/promises";import qe from"node:path";function Kn(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Yr(e){if(!e)return;let t=e.trim().toLowerCase();if(t==="oauth")return"oauth";if(t==="api_key"||t==="apikey")return"api_key"}function Xr(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 Qr(e,t){return e!=="openai-codex"?t:Vr[t]??t}function Bn(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 Zr(e,t,n){let o=Bn(e,t);if(o)return{...o,id:n,name:n}}function es(e,t){let n=!!t?.provider?.trim(),o=!!t?.modelId?.trim(),r=Kn(t?.provider||f.modelProvider||"openai-codex"),i=n||o?"":f.modelRef||"",{provider:c,modelId:u}=Xr(i,r),l=t?.provider?r:Kn(c),m=o?t?.modelId?.trim()||"":u;if(!m){let p=Bn(e,l);return p?{model:p,provider:l,modelId:p.id,syntheticModel:!1}:{model:void 0,provider:l,modelId:"",syntheticModel:!1}}let s=Qr(l,m),a=e.find(l,s);if(a)return{model:a,provider:l,modelId:s,syntheticModel:!1};let d=Zr(e,l,s);return d?{model:d,provider:l,modelId:s,syntheticModel:!0}:{model:void 0,provider:l,modelId:s,syntheticModel:!1}}function ts(e){let t=X();return t?(e.setRuntimeApiKey("openai-codex",t.accessToken),{source:t.source,expiresAt:t.expiresAt}):null}function ns(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(i=>typeof i=="object"&&i&&i.type==="text").map(i=>i.text??"").map(i=>i.trim()).filter(Boolean);if(o.length>0)return o.join(`
39
39
 
40
- `);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(`
40
+ `);let r=n.filter(i=>typeof i=="object"&&i&&i.type==="thinking").map(i=>i.thinking??"").map(i=>i.trim()).filter(Boolean);return r.length>0?r.join(`
41
41
 
42
- `):""}function Dr(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 u=[`blocks:${r.map(m=>typeof m=="object"&&m&&"type"in m?String(m.type||"unknown"):typeof m).join(",")||"none"}`,s?`stop=${s}`:null,l?"error=1":null].filter(Boolean).join(",");return`${o}(${u})`}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 Or(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
42
+ `):""}function os(e){if(e.length===0)return"messages=0";let t=e.slice(-6).map(n=>{let o=n?.role??"unknown",r=n.content,i=n?.stopReason,c=n?.errorMessage;if(typeof r=="string")return`${o}(text:${r.length}${i?`,stop=${i}`:""})`;if(Array.isArray(r)){let l=[`blocks:${r.map(m=>typeof m=="object"&&m&&"type"in m?String(m.type||"unknown"):typeof m).join(",")||"none"}`,i?`stop=${i}`:null,c?"error=1":null].filter(Boolean).join(",");return`${o}(${l})`}if(r==null){let u=["empty",i?`stop=${i}`:null,c?"error=1":null].filter(Boolean).join(",");return`${o}(${u})`}return`${o}(${typeof r}${i?`,stop=${i}`:""})`});return`messages=${e.length} last=[${t.join(" ")}]`}function rs(e){let t=e.trim();return t.toLowerCase().includes("usage limit")?`${t}
43
43
 
44
- Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function Ir(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=Er(e[o]);if(r)return r}return""}function Lr(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function He(e){let t=e.workspaceDir||g.workspaceDir;await T(g.sessionDir),await T(g.agentDir),await T(t);let n=at(e.chatId,e.sessionId),o=Je.join(g.agentDir,"auth.json"),r=new xr(o),s=Tr(r);s&&console.log(`[tg-agent] codex oauth source=${s.source} expiresAt=${new Date(s.expiresAt).toISOString()}`);let l=e.modelProvider||g.modelProvider,a=ne();if(e.accountId){let w=await a.getApiKey(l,e.accountId);w?(r.setRuntimeApiKey(l,w),console.log(`[tg-agent] multi-auth: using account=${e.accountId} for ${l}`)):console.warn(`[tg-agent] multi-auth: account not found ${l}/${e.accountId}`)}else if(a.hasAccounts(l)){let w=a.getDefaultAccount(l);if(w){let S=await a.getApiKey(l,w.id);S&&(r.setRuntimeApiKey(l,S),console.log(`[tg-agent] multi-auth: using default account=${w.id} for ${l}`))}}let u=Je.join(g.agentDir,"models.json"),m=new Sr(r,u),{model:i,provider:c,modelId:d}=Rr(m,{provider:e.modelProvider,modelId:e.modelId});d&&!i&&console.warn(`[tg-agent] model not found: ${c}/${d}`);let p=Mr.open(n),y=$r.create(t,g.agentDir);try{let w=Je.join(g.agentDir,"skills"),S=Je.join(t,".pi","skills"),N=await We.access(w).then(()=>!0).catch(()=>!1),D=await We.access(S).then(()=>!0).catch(()=>!1);if(N){let Z=(await We.readdir(w,{withFileTypes:!0})).filter(H=>H.isDirectory()).map(H=>H.name);console.log(`[tg-agent] skills directory found at ${w} with ${Z.length} skill(s): ${Z.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${w}`);if(D){let Z=(await We.readdir(S,{withFileTypes:!0})).filter(H=>H.isDirectory()).map(H=>H.name);console.log(`[tg-agent] workspace skills directory found at ${S} with ${Z.length} skill(s): ${Z.join(", ")}`)}let J=y.getSettings?.();if(J){let Z=J.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${Z}`)}}catch(w){let S=w instanceof Error?w.message:String(w);console.warn(`[tg-agent] skills check failed: ${S}`)}let h="";try{h=await le(g.agentDir,{timeoutMs:4e3,maxBytes:g.fetchMaxBytes,maxChars:3e3})}catch(w){let S=w instanceof Error?w.message:String(w);console.warn(`[tg-agent] mcp catalog error: ${S}`)}let b=[];if(g.audit.enabled&&e.auditContext){let w={...e.auditContext,sessionId:e.sessionId},S;if(g.audit.modelProvider&&g.audit.modelId){let N=m.find(g.audit.modelProvider,g.audit.modelId);if(N){let D=await r.getApiKey(g.audit.modelProvider);S={provider:g.audit.modelProvider,model:N,apiKey:D??void 0},console.log(`[tg-agent] audit model: ${g.audit.modelProvider}/${g.audit.modelId} apiKey=${D?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${g.audit.modelProvider}/${g.audit.modelId}`)}b.push(Cn(w,S)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let $=e.systemPrompt?.trim(),A=[];$&&A.push($),h&&A.push(h);let M=A.length>0?A.join(`
44
+ Suggestion: wait for the limit to reset or switch to another provider/model.`:t}function ss(e,t){let n=t?.getLastAssistantText?.();if(n?.trim())return n.trim();for(let o=e.length-1;o>=0;o-=1){let r=ns(e[o]);if(r)return r}return""}function is(e){for(let t=e.length-1;t>=0;t-=1)if(e[t]?.role==="assistant")return e[t]}async function Ge(e){let t=e.workspaceDir||f.workspaceDir;await C(f.sessionDir),await C(f.agentDir),await C(t);let n=ut(e.chatId,e.sessionId),o=qe.join(f.agentDir,"auth.json"),r=new Wr(o),i=ts(r);i&&console.log(`[tg-agent] codex oauth source=${i.source} expiresAt=${new Date(i.expiresAt).toISOString()}`);let c=e.modelProvider||f.modelProvider,u=Yr(e.authMode),l=qe.join(f.agentDir,"models.json"),m=new Jr(r,l);if(u==="api_key"){let A=re().getProviderConfig(c),O=A?.apiKey?.trim();if(!O)throw new Error(`API key mode selected for ${c}, but no key is configured. Use /apikey ${c} <key>.`);r.setRuntimeApiKey(c,O),A?.baseUrl&&(m.registerProvider(c,{baseUrl:A.baseUrl}),console.log(`[tg-agent] api-key-auth: using endpoint=${A.baseUrl} for ${c}`)),console.log(`[tg-agent] api-key-auth: enabled for ${c}`)}let s=Q();if(u!=="api_key"&&e.accountId){let v=await s.getApiKey(c,e.accountId);v?(r.setRuntimeApiKey(c,v),console.log(`[tg-agent] multi-auth: using account=${e.accountId} for ${c}`)):console.warn(`[tg-agent] multi-auth: account not found ${c}/${e.accountId}`)}else if(u!=="api_key"&&s.hasAccounts(c)){let v=s.getDefaultAccount(c);if(v){let A=await s.getApiKey(c,v.id);A&&(r.setRuntimeApiKey(c,A),console.log(`[tg-agent] multi-auth: using default account=${v.id} for ${c}`))}}let{model:a,provider:d,modelId:p,syntheticModel:h}=es(m,{provider:e.modelProvider,modelId:e.modelId});p&&!a?console.warn(`[tg-agent] model not found: ${d}/${p}`):h&&console.log(`[tg-agent] model override: using custom model id ${d}/${p} via provider template`);let y=Hr.open(n),w=qr.create(t,f.agentDir);try{let v=qe.join(f.agentDir,"skills"),A=qe.join(t,".pi","skills"),O=await He.access(v).then(()=>!0).catch(()=>!1),E=await He.access(A).then(()=>!0).catch(()=>!1);if(O){let te=(await He.readdir(v,{withFileTypes:!0})).filter(G=>G.isDirectory()).map(G=>G.name);console.log(`[tg-agent] skills directory found at ${v} with ${te.length} skill(s): ${te.join(", ")}`)}else console.log(`[tg-agent] skills directory not found at ${v}`);if(E){let te=(await He.readdir(A,{withFileTypes:!0})).filter(G=>G.isDirectory()).map(G=>G.name);console.log(`[tg-agent] workspace skills directory found at ${A} with ${te.length} skill(s): ${te.join(", ")}`)}let q=w.getSettings?.();if(q){let te=q.skills?.enabled!==!1;console.log(`[tg-agent] skills enabled in settings: ${te}`)}}catch(v){let A=v instanceof Error?v.message:String(v);console.warn(`[tg-agent] skills check failed: ${A}`)}let x="";try{x=await pe(f.agentDir,{timeoutMs:4e3,maxBytes:f.fetchMaxBytes,maxChars:3e3})}catch(v){let A=v instanceof Error?v.message:String(v);console.warn(`[tg-agent] mcp catalog error: ${A}`)}let M=[];if(f.audit.enabled&&e.auditContext){let v={...e.auditContext,sessionId:e.sessionId},A;if(f.audit.modelProvider&&f.audit.modelId){let O=m.find(f.audit.modelProvider,f.audit.modelId);if(O){let E=await r.getApiKey(f.audit.modelProvider);A={provider:f.audit.modelProvider,model:O,apiKey:E??void 0},console.log(`[tg-agent] audit model: ${f.audit.modelProvider}/${f.audit.modelId} apiKey=${E?"present":"missing"}`)}else console.warn(`[tg-agent] audit model not found: ${f.audit.modelProvider}/${f.audit.modelId}`)}M.push(Un(v,A)),console.log(`[tg-agent] security audit enabled for session ${e.sessionId}`)}let $=e.systemPrompt?.trim(),P=[];$&&P.push($),x&&P.push(x);let U=P.length>0?P.join(`
45
45
 
46
- `):void 0;console.log(`[tg-agent] systemPrompt append=${M?M.slice(0,80)+"...":"(none)"}`);let C=new Ar({cwd:t,agentDir:g.agentDir,settingsManager:y,extensionFactories:b.length>0?b:void 0,appendSystemPrompt:M});await C.reload();let{session:_,modelFallbackMessage:v}=await vr({cwd:t,agentDir:g.agentDir,authStorage:r,modelRegistry:m,model:i??void 0,sessionManager:p,settingsManager:y,resourceLoader:C,customTools:hn({telegram:e.telegram})});try{let w=_.messages,S=w.some(j=>{let Z=j.role,H=j.content;return Z==="system"&&typeof H=="string"?H.toLowerCase().includes("compaction")||H.toLowerCase().includes("compact"):j.type==="compaction"||j.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof p}`),console.log(`[tg-agent] session messages count: ${w.length}`),console.log(`[tg-agent] compacting support detected: ${S||"unknown (will be detected during runtime)"}`);let D=typeof p.compact=="function",J=typeof p.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${D}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${J}`)}catch(w){let S=w instanceof Error?w.message:String(w);console.warn(`[tg-agent] compacting check failed: ${S}`)}v&&console.warn(`[tg-agent] modelFallback=${v}`);let x=!1,k=()=>{x=!0,_.abort()};e.onAbortReady?.(k);let E=g.logAgentEvents,Dt=g.logAgentStream,be=new Map,Ze=_.subscribe(w=>{switch(w.type){case"agent_start":E&&console.log(`[tg-agent] agent start session=${e.sessionId}`),z=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":E&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":E&&console.log(`[tg-agent] turn start session=${e.sessionId}`),z=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":E&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${w.toolResults.length}`),z=Date.now(),e.onStatus?.({type:"turn_end",toolResults:w.toolResults.length});break;case"message_start":{if(E){let S=w.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${S}`)}z=Date.now();{let S=w.message.role??"unknown";e.onStatus?.({type:"message_start",role:S})}break}case"message_end":{if(E){let S=w.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${S}`)}z=Date.now();{let S=w.message.role??"unknown";e.onStatus?.({type:"message_end",role:S})}break}case"message_update":{if(!Dt)break;if(w.assistantMessageEvent.type==="text_delta"){let N=(w.assistantMessageEvent.delta??"").length;N>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${N}`),z=Date.now()}w.assistantMessageEvent.type==="thinking_delta"&&(z=Date.now());break}case"tool_execution_start":{be.set(w.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${w.toolName} id=${w.toolCallId}`),Te+=1,z=Date.now(),e.onStatus?.({type:"tool_start",name:w.toolName,id:w.toolCallId,args:w.args});break}case"tool_execution_end":{let S=be.get(w.toolCallId),N=S?Date.now()-S:0;console.log(`[tg-agent] tool end name=${w.toolName} id=${w.toolCallId} ok=${!w.isError} durationMs=${N}`),be.delete(w.toolCallId),Te=Math.max(0,Te-1),z=Date.now(),e.onStatus?.({type:"tool_end",name:w.toolName,id:w.toolCallId,ok:!w.isError,durationMs:N});break}case"auto_compaction_start":{let S=w.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${S}`),z=Date.now();break}case"auto_compaction_end":{let S=w.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${S}`),z=Date.now();break}default:break}}),ve=null,et=null,Re=!1,Ot=0,It=!1,z=Date.now(),Te=0;try{let w=Date.now();ve=setInterval(()=>{let D=Date.now()-w;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${D} streaming=${_.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:D,streaming:_.isStreaming})},15e3),et=setInterval(()=>{if(Re||Te>0)return;let D=Date.now()-z,J=_.isStreaming?g.modelTimeoutStreamingMs:g.modelTimeoutMs,j=Math.max(1e3,J);D>=j&&(Re=!0,Ot=j,It=_.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${D}`),_.abort())},2e3);try{if(await _.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),Re)throw new Error(`Model request timed out after ${g.modelTimeoutMs}ms`)}catch(D){if(x)throw new Error("Cancelled by user.");if(Re){let J=It?" (streaming)":"",j=Ot||g.modelTimeoutMs;throw new Error(`Model request timed out after ${j}ms${J}`)}throw D}ve&&clearInterval(ve);let S=Lr(_.messages);if(S){let D=S?.stopReason,J=S?.errorMessage;if(D==="error"){let j=J?Or(J):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${j}`),new Error(j)}}let N=Ir(_.messages,_);if(!N){let D=Dr(_.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${D}`),new Error("No assistant response.")}return{text:N,sessionFile:n,sessionId:_.sessionId,modelProvider:_.model?.provider??c,modelId:_.model?.id??d,modelFallbackMessage:v}}finally{ve&&clearInterval(ve),et&&clearInterval(et),Ze(),p.flushPendingToolResults?.(),_.dispose()}}var kr,yt=F(()=>{"use strict";K();pe();wn();Ae();q();mt();Rn();ft();kr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import jr from"node:path";import*as Dn from"@lancedb/lancedb";import ht from"openai";function Fr(){if(re)return re;let e=g.memory.rag;if(e.embeddingApiKey){let n={apiKey:e.embeddingApiKey};return e.embeddingBaseUrl&&(n.baseURL=e.embeddingBaseUrl),re=new ht(n),console.log(`[memory-rag] using embedding API key${e.embeddingBaseUrl?` (baseURL: ${e.embeddingBaseUrl})`:""}`),re}if(g.openaiApiKey)return re=new ht({apiKey:g.openaiApiKey}),console.log("[memory-rag] using OpenAI API key from config"),re;let t=V();if(t)return re=new ht({apiKey:t.accessToken}),console.log("[memory-rag] using Codex OAuth token"),re;throw new Error("No API key for embeddings. Set memory.rag.embedding_api_key or run `codex login`.")}async function bt(e){let t=Fr(),n=g.memory.rag.embeddingModel;console.log(`[memory-rag] embedding ${e.length} chars using ${n}`);let o=3e4,r=new Promise((s,l)=>{setTimeout(()=>l(new Error(`Embedding timeout after ${o}ms`)),o)});try{let s=await Promise.race([t.embeddings.create({model:n,input:e,encoding_format:"float"}),r]);if(!s?.data?.[0]?.embedding)throw new Error(`Invalid embedding response: ${JSON.stringify(s).slice(0,200)}`);let l=s.data[0].embedding;return console.log(`[memory-rag] got ${l.length}D embedding`),l}catch(s){throw s instanceof Error&&console.error(`[memory-rag] embedding error: ${s.message}`),s}}async function he(){return qe||(await T(wt),qe=await Dn.connect(wt),console.log(`[memory-rag] connected to DB at ${wt}`),qe)}async function Ge(e,t,n,o,r){let s={sessionSaved:!1,memoriesIndexed:0,errors:[]};if(!g.memory.rag.enabled)return console.log("[memory-rag] RAG disabled, skipping save"),s;console.log(`[memory-rag] saving session ${e}`);try{let l=await he(),a=await l.tableNames(),u={sessionId:e,date:t,title:n,transcript:o,reflection:JSON.stringify(r),memoryCount:r.memories?.length??0,timestamp:Date.now()};if(a.includes(se)?await(await l.openTable(se)).add([u]):await l.createTable(se,[u]),s.sessionSaved=!0,console.log("[memory-rag] session saved to DB"),r.memories&&r.memories.length>0){let m=await zr(e,t,r.memories);s.memoriesIndexed=m.indexed,s.errors=m.errors}return s}catch(l){let a=l instanceof Error?l.message:String(l);return console.error(`[memory-rag] saveSession failed: ${a}`),s.errors.push(a),s}}async function Ur(){try{let e=await he();return(await e.tableNames()).includes(se)?(await(await e.openTable(se)).query().toArray()).map(r=>({sessionId:r.sessionId,date:r.date,title:r.title,transcript:r.transcript,reflection:r.reflection,memoryCount:r.memoryCount,timestamp:r.timestamp})):[]}catch(e){return console.error(`[memory-rag] getAllSessions failed: ${e}`),[]}}async function zr(e,t,n){let o={indexed:0,errors:[]};if(!g.memory.rag.enabled||n.length===0)return o;console.log(`[memory-rag] indexing ${n.length} memories for session ${e}`);try{let r=await he(),s=await r.tableNames(),l,a=!1;s.includes(Y)?l=await r.openTable(Y):a=!0;for(let u=0;u<n.length;u++){let m=n[u];try{let i=await bt(m.content),c={id:`${e}-${u}`,sessionId:e,date:t,type:m.type,content:m.content,vector:i,timestamp:Date.now()};a?(l=await r.createTable(Y,[c]),a=!1,console.log("[memory-rag] created memories table")):await l.add([c]),o.indexed++,console.log(`[memory-rag] indexed [${u+1}/${n.length}]: ${m.type}`)}catch(i){let c=i instanceof Error?i.message:String(i);o.errors.push(`${m.type}: ${c}`),console.error(`[memory-rag] failed to index item ${u}: ${c}`)}u<n.length-1&&await new Promise(i=>setTimeout(i,200))}return console.log(`[memory-rag] indexed ${o.indexed}/${n.length} memories`),o}catch(r){let s=r instanceof Error?r.message:String(r);return console.error(`[memory-rag] indexMemoryItems failed: ${s}`),o.errors.push(s),o}}async function On(e,t=g.memory.rag.maxResults,n=g.memory.rag.similarityThreshold){if(!g.memory.rag.enabled)return[];console.log(`[memory-rag] searching: "${e.slice(0,50)}..."`);try{let o=await he();if(!(await o.tableNames()).includes(Y))return console.log("[memory-rag] memories table not found"),[];let s=await o.openTable(Y),l=await s.countRows();console.log(`[memory-rag] memories table has ${l} rows`);let a=await bt(e),u=await s.vectorSearch(a).column(Nr).limit(t*2).toArray();if(console.log(`[memory-rag] search returned ${u.length} results`),u.length>0){let c=u.map(d=>d._distance?.toFixed(4)??"N/A");console.log(`[memory-rag] distances: [${c.join(", ")}]`)}let m=(1-n)*2;console.log(`[memory-rag] threshold=${n}, maxDistance=${m.toFixed(4)}`);let i=u.filter(c=>{let d=c._distance;return d===void 0||d<=m}).slice(0,t).map(c=>({id:c.id,sessionId:c.sessionId,date:c.date,type:c.type,content:c.content,timestamp:c.timestamp,_distance:c._distance}));return console.log(`[memory-rag] filtered: ${i.length} memories`),i.length>0&&i.forEach((c,d)=>{console.log(`[memory-rag] ${d+1}. [${c.type}] "${c.content.slice(0,50)}..." (dist=${c._distance?.toFixed(4)??"N/A"})`)}),i}catch(o){let r=o instanceof Error?o.message:String(o);return console.warn(`[memory-rag] search failed: ${r}`),[]}}async function In(){try{let e=await he(),t=await e.tableNames(),n=0,o=0;return t.includes(se)&&(n=await(await e.openTable(se)).countRows()),t.includes(Y)&&(o=await(await e.openTable(Y)).countRows()),{sessionsCount:n,memoriesCount:o,embeddingModel:g.memory.rag.embeddingModel}}catch{return{sessionsCount:0,memoriesCount:0,embeddingModel:g.memory.rag.embeddingModel}}}async function Ln(e){let t={success:!1,totalSessions:0,totalMemories:0,indexedMemories:0,errors:[],embeddingModel:g.memory.rag.embeddingModel,vectorDimension:null};console.log("[reindex] ========================================"),console.log("[reindex] Rebuilding memories from sessions table"),console.log(`[reindex] Embedding model: ${g.memory.rag.embeddingModel}`),console.log("[reindex] ========================================");try{let n=await he(),o=await n.tableNames();if(!o.includes(se))return console.log("[reindex] No sessions table found, nothing to reindex"),t.success=!0,t;let r=await Ur();if(t.totalSessions=r.length,r.length===0)return console.log("[reindex] No sessions found"),t.success=!0,t;console.log(`[reindex] Found ${r.length} sessions`);let s=[];for(let a of r)try{let u=JSON.parse(a.reflection);if(u.memories&&u.memories.length>0)for(let m of u.memories)s.push({sessionId:a.sessionId,date:a.date,item:m})}catch(u){console.warn(`[reindex] Failed to parse reflection for session ${a.sessionId}: ${u}`)}if(t.totalMemories=s.length,console.log(`[reindex] Found ${s.length} memories to reindex`),s.length===0)return console.log("[reindex] No memories to reindex"),t.success=!0,t;o.includes(Y)&&(await n.dropTable(Y),console.log("[reindex] Dropped old memories table"));let l=null;for(let a=0;a<s.length;a++){let{sessionId:u,date:m,item:i}=s[a],c=`[${a+1}/${s.length}]`;try{e?.(a+1,s.length,`Indexing: ${i.content.slice(0,30)}...`);let d=await bt(i.content);t.vectorDimension===null&&(t.vectorDimension=d.length);let p={id:`${u}-${a}`,sessionId:u,date:m,type:i.type,content:i.content,vector:d,timestamp:Date.now()};l===null?(l=await n.createTable(Y,[p]),console.log(`[reindex] ${c} Created new memories table`)):await l.add([p]),t.indexedMemories++,console.log(`[reindex] ${c} Indexed: [${i.type}] ${i.content.slice(0,40)}...`)}catch(d){let p=d instanceof Error?d.message:String(d);t.errors.push(`${i.content.slice(0,30)}: ${p}`),console.error(`[reindex] ${c} Failed: ${p}`)}a<s.length-1&&await new Promise(d=>setTimeout(d,200))}return console.log("[reindex] ========================================"),console.log("[reindex] Reindex complete!"),console.log(`[reindex] Sessions: ${t.totalSessions}`),console.log(`[reindex] Total memories: ${t.totalMemories}`),console.log(`[reindex] Indexed: ${t.indexedMemories}`),console.log(`[reindex] Errors: ${t.errors.length}`),console.log("[reindex] ========================================"),t.success=!0,t}catch(n){let o=n instanceof Error?n.message:String(n);return console.error(`[reindex] Failed: ${o}`),t.errors.push(o),t}}var wt,se,Y,Nr,qe,re,vt=F(()=>{"use strict";K();q();pe();wt=jr.join(g.agentDir,"tg-memory-db"),se="sessions",Y="memories",Nr="vector",qe=null,re=null});import jn from"node:path";import{AuthStorage as Br,ModelRegistry as Kr}from"@mariozechner/pi-coding-agent";import{completeSimple as Wr,getModel as Jr}from"@mariozechner/pi-ai";function qr(){return g.memory.systemPrompt||Hr}function Vr(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function Yr(e,t){return e!=="openai-codex"?t:Gr[t]??t}async function Xr(e,t){await T(g.agentDir);let n=jn.join(g.agentDir,"auth.json"),o=new Br(n),r=V();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let s=jn.join(g.agentDir,"models.json"),l=new Kr(o,s),a=async(c,d,p)=>{let y=Vr(c),h=Yr(y,d),b=l.find(y,h);if(!b)try{b=Jr(y,h)}catch{}if(b){let $=await o.getApiKey(y);return{model:b,provider:y,modelId:h,apiKey:$??void 0,source:p}}return null};if(e&&t){let c=await a(e,t,"session");if(c)return console.log(`[memory] using session model: ${c.provider}/${c.modelId}`),c}if(g.memory.modelProvider&&g.memory.modelId){let c=await a(g.memory.modelProvider,g.memory.modelId,"memory-config");if(c)return console.log(`[memory] using configured memory model: ${c.provider}/${c.modelId}`),c}let u=g.modelProvider,m=g.modelRef.includes("/")?g.modelRef.split("/")[1]:g.modelRef;if(u&&m){let c=await a(u,m,"system-default");if(c)return console.log(`[memory] using system default model: ${c.provider}/${c.modelId}`),c}let i=l.getAll();if(i.length>0){let c=i[0],d=await o.getApiKey(c.provider);return console.log(`[memory] using first available model: ${c.provider}/${c.id}`),{model:c,provider:c.provider,modelId:c.id,apiKey:d??void 0,source:"first-available"}}return console.warn("[memory] no model available for reflection"),null}function Qr(e){let t={emotional:"",insights:"",advice:"",memories:[]};if(!e.trim())return t;try{let n=e.trim(),o=n.match(/```(?:json)?\s*([\s\S]*?)```/);o&&(n=o[1].trim());let r=JSON.parse(n),s={emotional:typeof r.emotional=="string"?r.emotional:"",insights:typeof r.insights=="string"?r.insights:"",advice:typeof r.advice=="string"?r.advice:"",memories:[]};if(Array.isArray(r.memories))for(let l of r.memories)l&&typeof l=="object"&&typeof l.type=="string"&&typeof l.content=="string"&&s.memories.push({type:l.type,content:l.content});return s}catch(n){return console.warn(`[memory] failed to parse reflection JSON: ${n}`),{emotional:"",insights:e.slice(0,500),advice:"",memories:[{type:"insight",content:`Session summary: ${e.slice(0,200)}`}]}}}async function Ve(e,t,n){if(!g.memory.enabled)return{success:!0,reflected:!1,memoriesIndexed:0};if(e.messages.length===0)return{success:!0,reflected:!1,memoriesIndexed:0};let r=new Date().toISOString().split("T")[0],s=e.messages.map(a=>`[${a.role.toUpperCase()}]: ${a.content}`).join(`
46
+ `):void 0;console.log(`[tg-agent] systemPrompt append=${U?U.slice(0,80)+"...":"(none)"}`);let S=new Gr({cwd:t,agentDir:f.agentDir,settingsManager:w,extensionFactories:M.length>0?M:void 0,appendSystemPrompt:U});await S.reload();let{session:b,modelFallbackMessage:k}=await Br({cwd:t,agentDir:f.agentDir,authStorage:r,modelRegistry:m,model:a??void 0,sessionManager:y,settingsManager:w,resourceLoader:S,customTools:kn({telegram:e.telegram})});try{let v=b.messages,A=v.some(F=>{let te=F.role,G=F.content;return te==="system"&&typeof G=="string"?G.toLowerCase().includes("compaction")||G.toLowerCase().includes("compact"):F.type==="compaction"||F.compaction!==void 0});console.log(`[tg-agent] session manager type: ${typeof y}`),console.log(`[tg-agent] session messages count: ${v.length}`),console.log(`[tg-agent] compacting support detected: ${A||"unknown (will be detected during runtime)"}`);let E=typeof y.compact=="function",q=typeof y.appendCompaction=="function";console.log(`[tg-agent] SessionManager.compact method: ${E}`),console.log(`[tg-agent] SessionManager.appendCompaction method: ${q}`)}catch(v){let A=v instanceof Error?v.message:String(v);console.warn(`[tg-agent] compacting check failed: ${A}`)}k&&console.warn(`[tg-agent] modelFallback=${k}`);let I=!1,Kt=()=>{I=!0,b.abort()};e.onAbortReady?.(Kt);let ie=f.logAgentEvents,tt=f.logAgentStream,nt=new Map,ko=b.subscribe(v=>{switch(v.type){case"agent_start":ie&&console.log(`[tg-agent] agent start session=${e.sessionId}`),B=Date.now(),e.onStatus?.({type:"agent_start"});break;case"agent_end":ie&&console.log(`[tg-agent] agent end session=${e.sessionId}`),e.onStatus?.({type:"agent_end"});break;case"turn_start":ie&&console.log(`[tg-agent] turn start session=${e.sessionId}`),B=Date.now(),e.onStatus?.({type:"turn_start"});break;case"turn_end":ie&&console.log(`[tg-agent] turn end session=${e.sessionId} toolResults=${v.toolResults.length}`),B=Date.now(),e.onStatus?.({type:"turn_end",toolResults:v.toolResults.length});break;case"message_start":{if(ie){let A=v.message.role??"unknown";console.log(`[tg-agent] message start session=${e.sessionId} role=${A}`)}B=Date.now();{let A=v.message.role??"unknown";e.onStatus?.({type:"message_start",role:A})}break}case"message_end":{if(ie){let A=v.message.role??"unknown";console.log(`[tg-agent] message end session=${e.sessionId} role=${A}`)}B=Date.now();{let A=v.message.role??"unknown";e.onStatus?.({type:"message_end",role:A})}break}case"message_update":{if(!tt)break;if(v.assistantMessageEvent.type==="text_delta"){let O=(v.assistantMessageEvent.delta??"").length;O>0&&console.log(`[tg-agent] stream delta session=${e.sessionId} chars=${O}`),B=Date.now()}v.assistantMessageEvent.type==="thinking_delta"&&(B=Date.now());break}case"tool_execution_start":{nt.set(v.toolCallId,Date.now()),console.log(`[tg-agent] tool start name=${v.toolName} id=${v.toolCallId}`),Oe+=1,B=Date.now(),e.onStatus?.({type:"tool_start",name:v.toolName,id:v.toolCallId,args:v.args});break}case"tool_execution_end":{let A=nt.get(v.toolCallId),O=A?Date.now()-A:0;console.log(`[tg-agent] tool end name=${v.toolName} id=${v.toolCallId} ok=${!v.isError} durationMs=${O}`),nt.delete(v.toolCallId),Oe=Math.max(0,Oe-1),B=Date.now(),e.onStatus?.({type:"tool_end",name:v.toolName,id:v.toolCallId,ok:!v.isError,durationMs:O});break}case"auto_compaction_start":{let A=v.reason??"unknown";console.log(`[tg-agent] auto compaction started session=${e.sessionId} reason=${A}`),B=Date.now();break}case"auto_compaction_end":{let A=v.willRetry??!1;console.log(`[tg-agent] auto compaction ended session=${e.sessionId} willRetry=${A}`),B=Date.now();break}default:break}}),Se=null,ot=null,De=!1,Bt=0,Wt=!1,B=Date.now(),Oe=0;try{let v=Date.now();Se=setInterval(()=>{let E=Date.now()-v;console.log(`[tg-agent] prompt running session=${e.sessionId} elapsedMs=${E} streaming=${b.isStreaming}`),e.onStatus?.({type:"heartbeat",elapsedMs:E,streaming:b.isStreaming})},15e3),ot=setInterval(()=>{if(De||Oe>0)return;let E=Date.now()-B,q=b.isStreaming?f.modelTimeoutStreamingMs:f.modelTimeoutMs,F=Math.max(1e3,q);E>=F&&(De=!0,Bt=F,Wt=b.isStreaming,console.warn(`[tg-agent] model timeout session=${e.sessionId} elapsedMs=${E}`),b.abort())},2e3);try{if(await b.prompt(e.prompt,e.images&&e.images.length>0?{images:e.images}:void 0),De)throw new Error(`Model request timed out after ${f.modelTimeoutMs}ms`)}catch(E){if(I)throw new Error("Cancelled by user.");if(De){let q=Wt?" (streaming)":"",F=Bt||f.modelTimeoutMs;throw new Error(`Model request timed out after ${F}ms${q}`)}throw E}Se&&clearInterval(Se);let A=is(b.messages);if(A){let E=A?.stopReason,q=A?.errorMessage;if(E==="error"){let F=q?rs(q):"Model error without details.";throw console.warn(`[tg-agent] model error session=${e.sessionId} error=${F}`),new Error(F)}}let O=ss(b.messages,b);if(!O){let E=os(b.messages);throw console.warn(`[tg-agent] empty response session=${e.sessionId} ${E}`),new Error("No assistant response.")}return{text:O,sessionFile:n,sessionId:b.sessionId,modelProvider:b.model?.provider??d,modelId:b.model?.id??p,modelFallbackMessage:k}}finally{Se&&clearInterval(Se),ot&&clearInterval(ot),ko(),y.flushPendingToolResults?.(),b.dispose()}}var Vr,$t=z(()=>{"use strict";K();be();Pn();_e();J();gt();In();wt();xt();Vr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});import as from"node:path";import*as Wn from"@lancedb/lancedb";import St from"openai";function ls(){if(ce)return ce;let e=f.memory.rag;if(e.embeddingApiKey){let n={apiKey:e.embeddingApiKey};return e.embeddingBaseUrl&&(n.baseURL=e.embeddingBaseUrl),ce=new St(n),console.log(`[memory-rag] using embedding API key${e.embeddingBaseUrl?` (baseURL: ${e.embeddingBaseUrl})`:""}`),ce}if(f.openaiApiKey)return ce=new St({apiKey:f.openaiApiKey}),console.log("[memory-rag] using OpenAI API key from config"),ce;let t=X();if(t)return ce=new St({apiKey:t.accessToken}),console.log("[memory-rag] using Codex OAuth token"),ce;throw new Error("No API key for embeddings. Set memory.rag.embedding_api_key or run `codex login`.")}async function Mt(e){let t=ls(),n=f.memory.rag.embeddingModel;console.log(`[memory-rag] embedding ${e.length} chars using ${n}`);let o=3e4,r=new Promise((i,c)=>{setTimeout(()=>c(new Error(`Embedding timeout after ${o}ms`)),o)});try{let i=await Promise.race([t.embeddings.create({model:n,input:e,encoding_format:"float"}),r]);if(!i?.data?.[0]?.embedding)throw new Error(`Invalid embedding response: ${JSON.stringify(i).slice(0,200)}`);let c=i.data[0].embedding;return console.log(`[memory-rag] got ${c.length}D embedding`),c}catch(i){throw i instanceof Error&&console.error(`[memory-rag] embedding error: ${i.message}`),i}}async function $e(){return Ve||(await C(At),Ve=await Wn.connect(At),console.log(`[memory-rag] connected to DB at ${At}`),Ve)}async function Ye(e,t,n,o,r){let i={sessionSaved:!1,memoriesIndexed:0,errors:[]};if(!f.memory.rag.enabled)return console.log("[memory-rag] RAG disabled, skipping save"),i;console.log(`[memory-rag] saving session ${e}`);try{let c=await $e(),u=await c.tableNames(),l={sessionId:e,date:t,title:n,transcript:o,reflection:JSON.stringify(r),memoryCount:r.memories?.length??0,timestamp:Date.now()};if(u.includes(le)?await(await c.openTable(le)).add([l]):await c.createTable(le,[l]),i.sessionSaved=!0,console.log("[memory-rag] session saved to DB"),r.memories&&r.memories.length>0){let m=await ds(e,t,r.memories);i.memoriesIndexed=m.indexed,i.errors=m.errors}return i}catch(c){let u=c instanceof Error?c.message:String(c);return console.error(`[memory-rag] saveSession failed: ${u}`),i.errors.push(u),i}}async function us(){try{let e=await $e();return(await e.tableNames()).includes(le)?(await(await e.openTable(le)).query().toArray()).map(r=>({sessionId:r.sessionId,date:r.date,title:r.title,transcript:r.transcript,reflection:r.reflection,memoryCount:r.memoryCount,timestamp:r.timestamp})):[]}catch(e){return console.error(`[memory-rag] getAllSessions failed: ${e}`),[]}}async function ds(e,t,n){let o={indexed:0,errors:[]};if(!f.memory.rag.enabled||n.length===0)return o;console.log(`[memory-rag] indexing ${n.length} memories for session ${e}`);try{let r=await $e(),i=await r.tableNames(),c,u=!1;i.includes(Z)?c=await r.openTable(Z):u=!0;for(let l=0;l<n.length;l++){let m=n[l];try{let s=await Mt(m.content),a={id:`${e}-${l}`,sessionId:e,date:t,type:m.type,content:m.content,vector:s,timestamp:Date.now()};u?(c=await r.createTable(Z,[a]),u=!1,console.log("[memory-rag] created memories table")):await c.add([a]),o.indexed++,console.log(`[memory-rag] indexed [${l+1}/${n.length}]: ${m.type}`)}catch(s){let a=s instanceof Error?s.message:String(s);o.errors.push(`${m.type}: ${a}`),console.error(`[memory-rag] failed to index item ${l}: ${a}`)}l<n.length-1&&await new Promise(s=>setTimeout(s,200))}return console.log(`[memory-rag] indexed ${o.indexed}/${n.length} memories`),o}catch(r){let i=r instanceof Error?r.message:String(r);return console.error(`[memory-rag] indexMemoryItems failed: ${i}`),o.errors.push(i),o}}async function Jn(e,t=f.memory.rag.maxResults,n=f.memory.rag.similarityThreshold){if(!f.memory.rag.enabled)return[];console.log(`[memory-rag] searching: "${e.slice(0,50)}..."`);try{let o=await $e();if(!(await o.tableNames()).includes(Z))return console.log("[memory-rag] memories table not found"),[];let i=await o.openTable(Z),c=await i.countRows();console.log(`[memory-rag] memories table has ${c} rows`);let u=await Mt(e),l=await i.vectorSearch(u).column(cs).limit(t*2).toArray();if(console.log(`[memory-rag] search returned ${l.length} results`),l.length>0){let a=l.map(d=>d._distance?.toFixed(4)??"N/A");console.log(`[memory-rag] distances: [${a.join(", ")}]`)}let m=(1-n)*2;console.log(`[memory-rag] threshold=${n}, maxDistance=${m.toFixed(4)}`);let s=l.filter(a=>{let d=a._distance;return d===void 0||d<=m}).slice(0,t).map(a=>({id:a.id,sessionId:a.sessionId,date:a.date,type:a.type,content:a.content,timestamp:a.timestamp,_distance:a._distance}));return console.log(`[memory-rag] filtered: ${s.length} memories`),s.length>0&&s.forEach((a,d)=>{console.log(`[memory-rag] ${d+1}. [${a.type}] "${a.content.slice(0,50)}..." (dist=${a._distance?.toFixed(4)??"N/A"})`)}),s}catch(o){let r=o instanceof Error?o.message:String(o);return console.warn(`[memory-rag] search failed: ${r}`),[]}}async function Hn(){try{let e=await $e(),t=await e.tableNames(),n=0,o=0;return t.includes(le)&&(n=await(await e.openTable(le)).countRows()),t.includes(Z)&&(o=await(await e.openTable(Z)).countRows()),{sessionsCount:n,memoriesCount:o,embeddingModel:f.memory.rag.embeddingModel}}catch{return{sessionsCount:0,memoriesCount:0,embeddingModel:f.memory.rag.embeddingModel}}}async function qn(e){let t={success:!1,totalSessions:0,totalMemories:0,indexedMemories:0,errors:[],embeddingModel:f.memory.rag.embeddingModel,vectorDimension:null};console.log("[reindex] ========================================"),console.log("[reindex] Rebuilding memories from sessions table"),console.log(`[reindex] Embedding model: ${f.memory.rag.embeddingModel}`),console.log("[reindex] ========================================");try{let n=await $e(),o=await n.tableNames();if(!o.includes(le))return console.log("[reindex] No sessions table found, nothing to reindex"),t.success=!0,t;let r=await us();if(t.totalSessions=r.length,r.length===0)return console.log("[reindex] No sessions found"),t.success=!0,t;console.log(`[reindex] Found ${r.length} sessions`);let i=[];for(let u of r)try{let l=JSON.parse(u.reflection);if(l.memories&&l.memories.length>0)for(let m of l.memories)i.push({sessionId:u.sessionId,date:u.date,item:m})}catch(l){console.warn(`[reindex] Failed to parse reflection for session ${u.sessionId}: ${l}`)}if(t.totalMemories=i.length,console.log(`[reindex] Found ${i.length} memories to reindex`),i.length===0)return console.log("[reindex] No memories to reindex"),t.success=!0,t;o.includes(Z)&&(await n.dropTable(Z),console.log("[reindex] Dropped old memories table"));let c=null;for(let u=0;u<i.length;u++){let{sessionId:l,date:m,item:s}=i[u],a=`[${u+1}/${i.length}]`;try{e?.(u+1,i.length,`Indexing: ${s.content.slice(0,30)}...`);let d=await Mt(s.content);t.vectorDimension===null&&(t.vectorDimension=d.length);let p={id:`${l}-${u}`,sessionId:l,date:m,type:s.type,content:s.content,vector:d,timestamp:Date.now()};c===null?(c=await n.createTable(Z,[p]),console.log(`[reindex] ${a} Created new memories table`)):await c.add([p]),t.indexedMemories++,console.log(`[reindex] ${a} Indexed: [${s.type}] ${s.content.slice(0,40)}...`)}catch(d){let p=d instanceof Error?d.message:String(d);t.errors.push(`${s.content.slice(0,30)}: ${p}`),console.error(`[reindex] ${a} Failed: ${p}`)}u<i.length-1&&await new Promise(d=>setTimeout(d,200))}return console.log("[reindex] ========================================"),console.log("[reindex] Reindex complete!"),console.log(`[reindex] Sessions: ${t.totalSessions}`),console.log(`[reindex] Total memories: ${t.totalMemories}`),console.log(`[reindex] Indexed: ${t.indexedMemories}`),console.log(`[reindex] Errors: ${t.errors.length}`),console.log("[reindex] ========================================"),t.success=!0,t}catch(n){let o=n instanceof Error?n.message:String(n);return console.error(`[reindex] Failed: ${o}`),t.errors.push(o),t}}var At,le,Z,cs,Ve,ce,kt=z(()=>{"use strict";K();J();be();At=as.join(f.agentDir,"tg-memory-db"),le="sessions",Z="memories",cs="vector",Ve=null,ce=null});import Gn from"node:path";import{AuthStorage as ms,ModelRegistry as ps}from"@mariozechner/pi-coding-agent";import{completeSimple as fs,getModel as gs}from"@mariozechner/pi-ai";function hs(){return f.memory.systemPrompt||ys}function bs(e){let t=e.trim().toLowerCase();return t==="codex"?"openai-codex":t}function vs(e,t){return e!=="openai-codex"?t:ws[t]??t}async function xs(e,t){await C(f.agentDir);let n=Gn.join(f.agentDir,"auth.json"),o=new ms(n),r=X();r&&o.setRuntimeApiKey("openai-codex",r.accessToken);let i=Gn.join(f.agentDir,"models.json"),c=new ps(o,i),u=async(a,d,p)=>{let h=bs(a),y=vs(h,d),w=c.find(h,y);if(!w)try{w=gs(h,y)}catch{}if(w){let x=await o.getApiKey(h);return{model:w,provider:h,modelId:y,apiKey:x??void 0,source:p}}return null};if(e&&t){let a=await u(e,t,"session");if(a)return console.log(`[memory] using session model: ${a.provider}/${a.modelId}`),a}if(f.memory.modelProvider&&f.memory.modelId){let a=await u(f.memory.modelProvider,f.memory.modelId,"memory-config");if(a)return console.log(`[memory] using configured memory model: ${a.provider}/${a.modelId}`),a}let l=f.modelProvider,m=f.modelRef.includes("/")?f.modelRef.split("/")[1]:f.modelRef;if(l&&m){let a=await u(l,m,"system-default");if(a)return console.log(`[memory] using system default model: ${a.provider}/${a.modelId}`),a}let s=c.getAll();if(s.length>0){let a=s[0],d=await o.getApiKey(a.provider);return console.log(`[memory] using first available model: ${a.provider}/${a.id}`),{model:a,provider:a.provider,modelId:a.id,apiKey:d??void 0,source:"first-available"}}return console.warn("[memory] no model available for reflection"),null}function $s(e){let t={emotional:"",insights:"",advice:"",memories:[]};if(!e.trim())return t;try{let n=e.trim(),o=n.match(/```(?:json)?\s*([\s\S]*?)```/);o&&(n=o[1].trim());let r=JSON.parse(n),i={emotional:typeof r.emotional=="string"?r.emotional:"",insights:typeof r.insights=="string"?r.insights:"",advice:typeof r.advice=="string"?r.advice:"",memories:[]};if(Array.isArray(r.memories))for(let c of r.memories)c&&typeof c=="object"&&typeof c.type=="string"&&typeof c.content=="string"&&i.memories.push({type:c.type,content:c.content});return i}catch(n){return console.warn(`[memory] failed to parse reflection JSON: ${n}`),{emotional:"",insights:e.slice(0,500),advice:"",memories:[{type:"insight",content:`Session summary: ${e.slice(0,200)}`}]}}}async function Xe(e,t,n){if(!f.memory.enabled)return{success:!0,reflected:!1,memoriesIndexed:0};if(e.messages.length===0)return{success:!0,reflected:!1,memoriesIndexed:0};let r=new Date().toISOString().split("T")[0],i=e.messages.map(u=>`[${u.role.toUpperCase()}]: ${u.content}`).join(`
47
47
 
48
- `),l=await Xr(t,n);if(!l){console.log("[memory] no model available, saving raw session");let a={emotional:"",insights:"No model available for reflection",advice:"",memories:[]};return{success:(await Ge(e.id,r,e.title,s,a)).sessionSaved,reflected:!1,memoriesIndexed:0}}console.log(`[memory] reflecting on session ${e.id} using ${l.provider}/${l.modelId}`);try{let u={systemPrompt:qr(),messages:[{role:"user",content:`Conversation transcript:
48
+ `),c=await xs(t,n);if(!c){console.log("[memory] no model available, saving raw session");let u={emotional:"",insights:"No model available for reflection",advice:"",memories:[]};return{success:(await Ye(e.id,r,e.title,i,u)).sessionSaved,reflected:!1,memoriesIndexed:0}}console.log(`[memory] reflecting on session ${e.id} using ${c.provider}/${c.modelId}`);try{let l={systemPrompt:hs(),messages:[{role:"user",content:`Conversation transcript:
49
49
 
50
- ${s}`,timestamp:Date.now()}]},m=await Wr(l.model,u,{apiKey:l.apiKey,maxTokens:2e3,sessionId:e.id});if(m.stopReason==="error")throw new Error(m.errorMessage||"Unknown API error");let i=m.content.find(y=>y.type==="text"),c=i?.type==="text"?i.text:"";c.trim()||(c=m.content.filter(h=>h.type==="thinking").map(h=>h.type==="thinking"?h.thinking:"").filter(Boolean).join(`
50
+ ${i}`,timestamp:Date.now()}]},m=await fs(c.model,l,{apiKey:c.apiKey,maxTokens:2e3,sessionId:e.id});if(m.stopReason==="error")throw new Error(m.errorMessage||"Unknown API error");let s=m.content.find(h=>h.type==="text"),a=s?.type==="text"?s.text:"";a.trim()||(a=m.content.filter(y=>y.type==="thinking").map(y=>y.type==="thinking"?y.thinking:"").filter(Boolean).join(`
51
51
 
52
- `));let d=Qr(c);console.log(`[memory] reflection generated: ${d.memories.length} memories`);let p=await Ge(e.id,r,e.title,s,d);return p.errors.length>0&&console.warn(`[memory] some errors during save: ${p.errors.join(", ")}`),console.log(`[memory] session archived, ${p.memoriesIndexed} memories indexed`),{success:p.sessionSaved,reflected:!0,memoriesIndexed:p.memoriesIndexed}}catch(a){let u=a instanceof Error?a.message:String(a);console.error(`[memory] reflection failed: ${u}`);let m={emotional:"",insights:`Reflection failed: ${u}`,advice:"",memories:[]};return{success:(await Ge(e.id,r,e.title,s,m)).sessionSaved,reflected:!1,memoriesIndexed:0,error:u}}}var Hr,Gr,Nn=F(()=>{"use strict";K();q();pe();vt();Hr=`You are a caring AI companion summarizing a conversation with Shawn.
52
+ `));let d=$s(a);console.log(`[memory] reflection generated: ${d.memories.length} memories`);let p=await Ye(e.id,r,e.title,i,d);return p.errors.length>0&&console.warn(`[memory] some errors during save: ${p.errors.join(", ")}`),console.log(`[memory] session archived, ${p.memoriesIndexed} memories indexed`),{success:p.sessionSaved,reflected:!0,memoriesIndexed:p.memoriesIndexed}}catch(u){let l=u instanceof Error?u.message:String(u);console.error(`[memory] reflection failed: ${l}`);let m={emotional:"",insights:`Reflection failed: ${l}`,advice:"",memories:[]};return{success:(await Ye(e.id,r,e.title,i,m)).sessionSaved,reflected:!1,memoriesIndexed:0,error:l}}}var ys,ws,Vn=z(()=>{"use strict";K();J();be();kt();ys=`You are a caring AI companion summarizing a conversation with Shawn.
53
53
 
54
54
  Your task is to:
55
55
  1. Understand Shawn's emotional state and what's important to them
@@ -82,50 +82,76 @@ Guidelines:
82
82
  - Each memory should be self-contained and specific
83
83
  - Focus on information that would help Shawn in the future
84
84
  - Keep each memory concise (one sentence)
85
- - Prioritize what matters for Shawn's growth and wellbeing`;Gr={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var Vs={};import we from"node:path";import{spawn as Zr}from"node:child_process";import Fn from"node:fs/promises";import es from"node-telegram-bot-api";import{AuthStorage as ts,ModelRegistry as ns}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Un,getOAuthProvider as os}from"@mariozechner/pi-ai";function ss(e,t){Ce.set(e,t)}function At(e){Ce.delete(e)}function is(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 cs(){return we.join(g.agentDir,"uploads")}function ls(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 us(e){return!!e?.startsWith("image/")}function ds(e){switch(we.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 ms(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 gs(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(ms(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
86
- `)}function ps(e){let t=[];if(e.photo&&e.photo.length>0){let n=ls(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 fs(e){if(e.length===0)return{resolved:[],images:[]};let t=cs();await T(t);let n=[],o=[];for(let r of e)try{let s=await L.downloadFile(r.fileId,t),l=await Fn.stat(s),a=r.fileName??we.basename(s),u=r.mimeType??ds(s),m=r.kind==="photo"||us(u),i={path:s,name:a,mimeType:u,bytes:l.size,isImage:m};if(n.push(i),m){let c=await Fn.readFile(s);o.push({type:"image",data:c.toString("base64"),mimeType:u??as})}}catch(s){console.warn("[tg-agent] attachment download failed",s)}return{resolved:n,images:o}}function ke(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 hs(e){if(ke(e,"*")%2!==0||ke(e,"_")%2!==0||ke(e,"`")%2!==0)return!1;let r=ke(e,"["),s=ke(e,"]");return r===s}function ws(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(ys.has(n))return!1}return!0}function qn(e){let t=is(g.telegramParseMode);return t?[t]:ws(e)?["MarkdownV2","Markdown"]:hs(e)?["Markdown"]:[]}function _e(e,t){let n=Pe.get(e);return n?(clearTimeout(n.timeoutId),Pe.delete(e),n.messageId&&L.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function zn(e,t,n,o,r){if(Pe.has(e))throw new Error("Audit confirmation already pending.");let s=_t([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),l=await Ct(t,n,s,r);return await new Promise((a,u)=>{let m=setTimeout(()=>{Pe.delete(e),L.editMessageText(`${n}
87
-
88
- [Timed out - Operation blocked]`,{chat_id:t,message_id:l.message_id}).catch(()=>{}),u(new Error("Audit confirmation timed out."))},o);Pe.set(e,{resolve:a,reject:u,timeoutId:m,chatId:t,messageThreadId:r,messageId:l.message_id})})}function X(e){let t=e.trim().toLowerCase();return vs.get(t)??t}function Ss(e,t){return e!=="openai-codex"?t:xs[t]??t}async function ie(){await T(g.agentDir);let e=we.join(g.agentDir,"auth.json"),t=new ts(e),n=V();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=we.join(g.agentDir,"models.json"),r=new ns(t,o);return{authStorage:t,modelRegistry:r}}function Gn(e){let t=ae.get(e);t&&(clearTimeout(t.timeoutId),ae.delete(e))}function Ms(e,t){let n=ae.get(e);n&&(clearTimeout(n.timeoutId),ae.delete(e),n.reject(new Error(t)))}async function Bn(e,t,n,o){if(ae.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await f(t,r,o),await new Promise((s,l)=>{let a=setTimeout(()=>{ae.delete(e),l(new Error("Login prompt timed out."))},bs);ae.set(e,{resolve:s,reject:l,timeoutId:a,chatId:t})})}async function Vn(e,t,n){let o=Ce.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 Yn(e,t,n,o){let r=await Be(t),s=n||r.activeSessionId;if(!s){await f(e,"No active session to close.",o);return}let l=r.sessions[s];if(l&&l.messages.length>0)try{await f(e,"Reflecting on session memory...",o);let i=await Ve(l,l.modelProvider,l.modelId);i.reflected?await f(e,"Memory archived successfully.",o):i.error?await f(e,`Memory saved (reflection failed: ${i.error})`,o):await f(e,"Memory saved (no reflection).",o)}catch(i){console.warn("[tg-agent] memory archival failed",i),await f(e,`Memory archival failed: ${me(i)}`,o)}let a=Ce.get(t);if(a){if(a.cancelRequested=!0,a.abortRequested=!0,a.status&&a.status.update("Cancelled by user.",!0),a.abort)try{a.abort()}catch(i){console.warn("[tg-agent] abort callback failed during force close",i)}At(t)}if(!ut(r,s)){await f(e,`Session not found: ${s}`,o);return}await I(r),await ye(t,s).catch(i=>{console.warn(`[tg-agent] delete session file failed id=${s}`,i)});let m=a?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await f(e,m,o)}function $s(){console.log(`[tg-agent] modelProvider=${g.modelProvider} modelRef=${g.modelRef} sessionDir=${g.sessionDir} maxConcurrent=${g.maxConcurrent}`),console.log(`[tg-agent] agentDir=${g.agentDir} workspaceDir=${g.workspaceDir}`);let e=Ne(g.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${g.fetchMaxBytes} fetchTimeoutMs=${g.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${g.proxyUrl||"(none)"} fetchProxy=${g.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${g.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${g.tlsRejectUnauthorized===null?"(unset)":String(g.tlsRejectUnauthorized)}`);try{let{source:o}=Qt(g.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=en();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function kt(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 St(e,t,n){let o=de(e);return o||(o=Ke(e,""),await I(e),await f(t,`Created session ${o.id}.`,n)),o}function ks(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])=>As.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 Ps(e,t,n=[]){let o=e.getAll().filter(a=>a.provider===t).sort((a,u)=>a.id.localeCompare(u.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 u=r.get(a);!u||s.has(u.id)||(s.add(u.id),l.push(u))}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 _s(e,t,n=3){let o=new Set,r=[],s=ct(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 Cs(e){let t=e.trim();if(!t)return null;if(t.includes("/")){let[n,o]=t.split("/",2);return!n||!o?null:{provider:X(n),modelId:o.trim()}}return{modelId:t}}function Xn(e,t){let n=Date.now(),o=Kn.get(e)??0;n-o<Rs||(Kn.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function Qn(e){let t=g.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function Ts(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(`
89
- `)}function Qe(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function $t(e,t){if(t.workspaceDir)return t.workspaceDir;let n=g.workspaceMappings.get(e);return n||g.workspaceDir}async function Pt(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await L.sendMessage(e,t,r)}async function Zn(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 L.editMessageText(n,s)}async function eo(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 Es(e,t,n){return await eo(o=>Pt(e,t,o,n),qn(t))}async function Ds(e,t,n,o){await eo(r=>Zn(e,t,n,r,o),qn(n))}async function f(e,t,n){let o=nt(t,3900);for(let r of o)await Es(e,r,n)}async function Os(e,t,n){let o=nt(t,3900);for(let r of o)await Pt(e,r,void 0,n)}function Ls(){let e=U()-to;for(let[o,r]of Q)r.createdAt<e&&Q.delete(o);if(Q.size<=Wn)return;let t=Array.from(Q.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=Q.size-Wn;for(let o=0;o<n;o+=1)Q.delete(t[o][0])}function js(e){Ls();let t=ee();for(;Q.has(t);)t=ee();return Q.set(t,{command:e,createdAt:U()}),t}function Ns(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=Q.get(t);return n?U()-n.createdAt>to?(Q.delete(t),null):n.command:null}function Fs(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 _t(e,t){let n=[],o=[];for(let r of e){let s=js(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 Ct(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await L.sendMessage(e,t,r)}async function Xe(e,t,n,o){let r=o?.perRow??1,s=o?.pageSize??Is,l=o?.footer,a=o?.messageThreadId,u=Fs(n,s);for(let m=0;m<u.length;m+=1){let i=u[m],c=u.length>1?` (page ${m+1}/${u.length})`:"",d=[`${t}${c}`];l&&d.push(l);let p=_t(i,r);await Ct(e,d.join(`
90
- `),p,a)}}function Mt(e,t=Us){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
91
-
92
- [truncated]`,truncated:!0}}async function Bs(e,t){let n="Working...",r=(await Pt(e,n,void 0,t)).message_id,s=n,l=0,a=Promise.resolve(),u=(i,c=!1)=>{let d=Date.now();!c&&d-l<zs||i!==s&&(s=i,l=d,a=a.then(async()=>{await Zn(e,r,i,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},m=i=>{s=i,l=Date.now(),a=a.then(async()=>{await Ds(e,r,i,t)}).catch(c=>{console.warn("[tg-agent] status edit failed",c)})};return{update:(i,c=!1)=>{let d=Mt(i).text;u(d,c)},finalize:async i=>{let c=Mt(i).text;m(c),await a},fail:async i=>{let c=Mt(i).text;m(c),await a}}}function Ks(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
93
- args: ${Ws(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 Ws(e){try{let t=new WeakSet,n=200,o=12,r=12,s=3,l=(m,i)=>{if(m==null)return m;if(typeof m=="string")return m.length>n?`${m.slice(0,n)}...`:m;if(typeof m=="number"||typeof m=="boolean")return m;if(typeof m=="bigint")return m.toString();if(typeof m=="function")return"[function]";if(typeof m!="object")return String(m);if(t.has(m))return"[circular]";if(i>=s)return"[truncated]";if(t.add(m),Array.isArray(m)){let p=m.slice(0,r).map(y=>l(y,i+1));return m.length>r&&p.push("[truncated]"),p}let c=Object.entries(m),d={};for(let[p,y]of c.slice(0,o))d[p]=l(y,i+1);return c.length>o&&(d._truncated=!0),d},a=l(e,0),u=JSON.stringify(a);return u?u.length>700?`${u.slice(0,700)}...`:u:"null"}catch{return"[unavailable]"}}function me(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 Js(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function Hs(){let e=await Me(g.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=>un(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: ${Js(s.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${ue(r)} status=${l} (${s.durationMs}ms)`)}return n.join(`
94
- `)}async function Rt(e,t,n,o,r){let s=r,a=Qe(e,s,s!==void 0);if(!a)return;let u=await Be(a),m=lt(u);switch(m.length>0&&(await I(u),await Promise.all(m.map(i=>ye(a,i).catch(c=>{console.warn(`[tg-agent] cleanup session file failed id=${i}`,c)})))),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 (lists accountIds if multiple)","/accounts [provider] - list OAuth accounts, tap to switch","/setdefault <provider>/<accountId> - set default OAuth account","/restart - run restart script (paths.restart_script_path in config)","/stop - stop the current running request","/approve - approve a pending security audit confirmation","/memory - show memory RAG status","/reindex - rebuild vector index for all memories","","Tips:","Send images or files to attach them to the prompt."].join(`
95
- `);await f(e,i,r);return}case"new":{try{let i=o||"",c=de(u),d=c?.modelProvider,p=c?.modelId,y=Ke(u,i);d&&(y.modelProvider=d,p&&(y.modelId=p)),await I(u),await f(e,`Created session ${y.id} (${y.title}).`,r)}catch(i){await f(e,i.message,r)}return}case"list":{await I(u),await f(e,Ts(ct(u)),r);return}case"use":{if(!o){await f(e,"Usage: /use <id>",r);return}if(!$n(u,o)){await f(e,`Session not found: ${o}`,r);return}await I(u),await f(e,`Active session set to ${o}.`,r);return}case"close":{let i=o||u.activeSessionId;if(!i){await f(e,"No active session to close.",r);return}let c=u.sessions[i];if(c&&c.messages.length>0)try{await f(e,"Reflecting on session memory...",r);let h=await Ve(c,c.modelProvider,c.modelId);h.reflected?await f(e,"Memory archived successfully.",r):h.error?await f(e,`Memory saved (reflection failed: ${h.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(h){console.warn("[tg-agent] memory archival failed",h),await f(e,`Memory archival failed: ${me(h)}`,r)}let d=Ce.get(a);if(d){if(d.cancelRequested=!0,d.abortRequested=!0,d.status&&d.status.update("Cancelled by user.",!0),d.abort)try{d.abort()}catch(h){console.warn("[tg-agent] abort callback failed during force close",h)}At(a)}if(!ut(u,i)){await f(e,`Session not found: ${i}`,r);return}await I(u),await ye(a,i).catch(h=>{console.warn(`[tg-agent] delete session file failed id=${i}`,h)});let y=d?`Force-closed session ${i} (interrupted running task).`:`Closed session ${i}.`;await f(e,y,r);return}case"reset":{let i=de(u);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 c=await Ve(i,i.modelProvider,i.modelId);c.reflected?await f(e,"Memory archived successfully.",r):c.error?await f(e,`Memory saved (reflection failed: ${c.error})`,r):await f(e,"Memory saved (no reflection).",r)}catch(c){console.warn("[tg-agent] memory archival failed",c),await f(e,`Memory archival failed: ${me(c)}`,r)}An(i),await I(u),await ye(a,i.id).catch(c=>{console.warn(`[tg-agent] reset session file failed id=${i.id}`,c)}),await f(e,`Reset session ${i.id}.`,r);return}case"workspace":{if(!o){let c=$t(a,u),d=u.workspaceDir?"chat":g.workspaceMappings.has(a)?"config":"default";await f(e,`Workspace: ${c} (source: ${d})`,r);return}let i=we.resolve(B(o.trim()));kn(u,i),await I(u),await f(e,`Workspace set to: ${i}`,r);return}case"providers":{let{authStorage:i,modelRegistry:c}=await ie(),d=c.getError(),p=ks(c,i);if(p.length===0){let h=d?`Warning: ${d}
96
-
97
- No providers found.`:"No providers found.";await f(e,h,r);return}let y=[];d&&y.push(`Warning: ${d}`),y.push("Providers:"),await Xe(e,y.join(`
98
- `),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:c}=await ie(),d=o?X(o):"";if(!d){let b=de(u);if(!b?.modelProvider){await f(e,"Usage: /models <provider>",r);return}d=b.modelProvider}let p=i.hasAuth(d),y=_s(u,d),h=Ps(c,d,y);if(h.length===0){await f(e,`No models found for provider ${d}.`,r);return}await Xe(e,`Models for ${d} (auth: ${p?"ok":"missing"}):`,h,{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=X(o),{modelRegistry:c}=await ie();if(!c.getAll().some(y=>y.provider===i)){await f(e,`Unknown provider: ${i}`,r);return}let p=await St(u,e,r);p.modelProvider=i,p.modelId=void 0,p.updatedAt=U(),await I(u),await f(e,`Session ${p.id} provider set to ${i}.`,r),await Rt(e,t,"models",i,r);return}case"model":{let i=Cs(o);if(!i){await f(e,"Usage: /model <provider>/<model>",r);return}let c=await St(u,e,r),d=X(i.provider??c.modelProvider??"");if(!d){await f(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await ie(),y=Ss(d,i.modelId);if(!p.find(d,y)){await f(e,`Model not found: ${d}/${y}`,r);return}c.modelProvider=d,c.modelId=y,c.updatedAt=U(),await I(u),await f(e,`Session ${c.id} model set to ${d}/${y}.`,r);return}case"status":{let i=de(u);if(!i){await f(e,"No active session.",r);return}let c=g.modelRef.includes("/")?g.modelRef:`${g.modelProvider}/${g.modelRef}`,d=i.modelProvider||i.modelId?`Model: ${i.modelProvider??"?"}/${i.modelId??"?"}`:`Model: ${c} (default)`,p="";if(i.accountId){let A=ne().getAccount(i.modelProvider||"",i.accountId);A?p=`
99
- Account: ${A.email||i.accountId}`:p=`
100
- Account: ${i.accountId} (not found)`}let y=$t(a,u),h=u.workspaceDir?"chat":g.workspaceMappings.has(a)?"config":"default",b=[`Session: ${i.id} (${i.title})`,d+p,`Workspace: ${y} (${h})`].join(`
101
- `);await f(e,b,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){ln(),await le(g.agentDir,{timeoutMs:5e3,maxBytes:g.fetchMaxBytes,maxChars:3e3}),$e(),await f(e,"MCP catalog refreshed.",r);return}let i=await Hs();await f(e,i,r);return}case"login":{let i=Un();if(!o){let p=i.map(y=>`- ${y.id} (${y.name})`);await f(e,["OAuth providers:",...p].join(`
102
- `),r);return}let c=X(o);if(xt.has(t)){await f(e,"Login already in progress.",r);return}let d=i.find(p=>p.id===c);if(!d){await f(e,`Unknown OAuth provider: ${c}`,r);return}xt.add(t);try{let{authStorage:p}=await ie(),y=ne(),h=y.listAccounts(c);h.length>0&&await f(e,`You have ${h.length} account(s) for ${c}. Adding a new one...`,r),await f(e,`Starting login for ${d.id}...`,r);let b=os(c);if(!b)throw new Error(`OAuth provider not found: ${c}`);let $=await b.login({onAuth:({url:v,instructions:x})=>{let k=["Open this URL in your browser:",v];x&&k.push("",x),Os(e,k.join(`
103
- `),r)},onPrompt:v=>Bn(t,e,v,r),onProgress:v=>{f(e,v,r)},onManualCodeInput:()=>Bn(t,e,{message:"Paste the authorization code:"},r)}),A=$.email,M=await y.addAccount(c,$,{email:A});p.set(c,{type:"oauth",...$});let C=y.listAccounts(c),_=A||M;await f(e,`Login completed for ${d.id}.
104
- Account: ${_}
105
- Account ID: ${M}
106
- Total accounts: ${C.length}
107
- Use /accounts ${c} to see all accounts.`,r)}catch(p){let y=me(p);await f(e,`Login failed: ${y}`,r)}finally{xt.delete(t),Gn(t)}return}case"logout":{if(!o){await f(e,`Usage: /logout <provider> \u2014 lists accountIds if multiple.
85
+ - Prioritize what matters for Shawn's growth and wellbeing`;ws={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"}});var xi={};import de from"node:path";import{spawn as Ss}from"node:child_process";import Rt from"node:fs/promises";import As from"node-telegram-bot-api";import{AuthStorage as Ms,ModelRegistry as ks}from"@mariozechner/pi-coding-agent";import{getOAuthProviders as Yn,getOAuthProvider as Ps}from"@mariozechner/pi-ai";function Cs(e,t){Ee.set(e,t)}function Ot(e){Ee.delete(e)}function Rs(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 Es(){return de.join(f.agentDir,"uploads")}function Ds(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 Os(e){return!!e?.startsWith("image/")}function Ns(e){switch(de.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 js(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 Ls(e){return e.length===0?"":e.map(t=>{let n=[];t.mimeType&&n.push(t.mimeType),t.bytes>0&&n.push(js(t.bytes));let o=n.length>0?` (${n.join(", ")})`:"";return`Attachment saved: ${t.path}${o}`}).join(`
86
+ `)}function Us(e){let t=[];if(e.photo&&e.photo.length>0){let n=Ds(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 Is(e){if(e.length===0)return{resolved:[],images:[]};let t=Es();await C(t);let n=[],o=[];for(let r of e)try{let i=await L.downloadFile(r.fileId,t),c=await Rt.stat(i),u=r.fileName??de.basename(i),l=r.mimeType??Ns(i),m=r.kind==="photo"||Os(l),s={path:i,name:u,mimeType:l,bytes:c.size,isImage:m};if(n.push(s),m){let a=await Rt.readFile(i);o.push({type:"image",data:a.toString("base64"),mimeType:l??Ts})}}catch(i){console.warn("[tg-agent] attachment download failed",i)}return{resolved:n,images:o}}function Ce(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 zs(e){if(Ce(e,"*")%2!==0||Ce(e,"_")%2!==0||Ce(e,"`")%2!==0)return!1;let r=Ce(e,"["),i=Ce(e,"]");return r===i}function Ks(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n==="\\"){t+=1;continue}if(Fs.has(n))return!1}return!0}function co(e){let t=Rs(f.telegramParseMode);return t?[t]:Ks(e)?["MarkdownV2","Markdown"]:zs(e)?["Markdown"]:[]}function Te(e,t){let n=Re.get(e);return n?(clearTimeout(n.timeoutId),Re.delete(e),n.messageId&&L.editMessageReplyMarkup({inline_keyboard:[]},{chat_id:n.chatId,message_id:n.messageId}).catch(()=>{}),n.resolve(t),!0):!1}async function Xn(e,t,n,o,r){if(Re.has(e))throw new Error("Audit confirmation already pending.");let i=Lt([{label:"Approve",command:"/approve"},{label:"Stop",command:"/stop"}],2),c=await Ut(t,n,i,r);return await new Promise((u,l)=>{let m=setTimeout(()=>{Re.delete(e),L.editMessageText(`${n}
87
+
88
+ [Timed out - Operation blocked]`,{chat_id:t,message_id:c.message_id}).catch(()=>{}),l(new Error("Audit confirmation timed out."))},o);Re.set(e,{resolve:u,reject:l,timeoutId:m,chatId:t,messageThreadId:r,messageId:c.message_id})})}function lo(e){return Hs.test(e)}function uo(){return de.join(f.agentDir,"souls")}function Tt(e){return de.join(uo(),`${e}.md`)}async function mo(e){if(!lo(e))throw new Error(`Invalid soul name: ${e}. Use only letters, numbers, "_" and "-".`);let t=Tt(e),o=(await Rt.readFile(t,"utf8")).trim();if(!o)throw new Error(`Soul file is empty: ${t}`);if(o.length>Qn)throw new Error(`Soul file too large (${o.length} chars). Max ${Qn}.`);return o}function Gs(e,t){return[qs,"",`<session_soul name="${e}">`,t,"</session_soul>"].join(`
89
+ `)}function j(e){let t=e.trim().toLowerCase();return Ws.get(t)??t}function Zn(e,t){return e!=="openai-codex"?t:Js[t]??t}async function Y(){await C(f.agentDir);let e=de.join(f.agentDir,"auth.json"),t=new Ms(e),n=X();n&&t.setRuntimeApiKey("openai-codex",n.accessToken);let o=de.join(f.agentDir,"models.json"),r=new ks(t,o);return{authStorage:t,modelRegistry:r}}function po(e){let t=ue.get(e);t&&(clearTimeout(t.timeoutId),ue.delete(e))}function Vs(e,t){let n=ue.get(e);n&&(clearTimeout(n.timeoutId),ue.delete(e),n.reject(new Error(t)))}async function eo(e,t,n,o){if(ue.has(e))throw new Error("Login is already awaiting input.");let r=n.placeholder?`${n.message} (${n.placeholder})`:n.message;return await g(t,r,o),await new Promise((i,c)=>{let u=setTimeout(()=>{ue.delete(e),c(new Error("Login prompt timed out."))},Bs);ue.set(e,{resolve:i,reject:c,timeoutId:u,chatId:t})})}async function fo(e,t,n){let o=Ee.get(t);if(!o){await g(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 g(e,"Stopping current request...",n)}async function go(e,t,n,o){let r=await We(t),i=n||r.activeSessionId;if(!i){await g(e,"No active session to close.",o);return}let c=r.sessions[i];if(c&&c.messages.length>0)try{await g(e,"Reflecting on session memory...",o);let s=await Xe(c,c.modelProvider,c.modelId);s.reflected?await g(e,"Memory archived successfully.",o):s.error?await g(e,`Memory saved (reflection failed: ${s.error})`,o):await g(e,"Memory saved (no reflection).",o)}catch(s){console.warn("[tg-agent] memory archival failed",s),await g(e,`Memory archival failed: ${se(s)}`,o)}let u=Ee.get(t);if(u){if(u.cancelRequested=!0,u.abortRequested=!0,u.status&&u.status.update("Cancelled by user.",!0),u.abort)try{u.abort()}catch(s){console.warn("[tg-agent] abort callback failed during force close",s)}Ot(t)}if(!pt(r,i)){await g(e,`Session not found: ${i}`,o);return}await T(r),await xe(t,i).catch(s=>{console.warn(`[tg-agent] delete session file failed id=${i}`,s)});let m=u?`Force-closed session ${i} (interrupted running task).`:`Closed session ${i}.`;await g(e,m,o)}function Ys(){console.log(`[tg-agent] modelProvider=${f.modelProvider} modelRef=${f.modelRef} sessionDir=${f.sessionDir} maxConcurrent=${f.maxConcurrent}`),console.log(`[tg-agent] agentDir=${f.agentDir} workspaceDir=${f.workspaceDir}`);let e=Fe(f.agentDir),t=e.length>0?`on (${e.length})`:"off";console.log(`[tg-agent] tools fetchMaxBytes=${f.fetchMaxBytes} fetchTimeoutMs=${f.fetchTimeoutMs} mcp=${t}`),console.log(`[tg-agent] proxy url=${f.proxyUrl||"(none)"} fetchProxy=${f.fetchProxyUrl||"(none)"}`),console.log(`[tg-agent] tls extra_ca=${f.tlsExtraCaCerts||"(empty)"} reject_unauthorized=${f.tlsRejectUnauthorized===null?"(unset)":String(f.tlsRejectUnauthorized)}`);try{let{source:o}=cn(f.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=un();console.log(n?`[tg-agent] proxyUrl=${n.url} kind=${n.kind} source=${n.source}`:"[tg-agent] proxyUrl=(none)")}function Nt(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 ye(e,t,n){let o=ge(e);return o||(o=Je(e,""),await T(e),await g(t,`Created session ${o.id}.`,n)),o}function Qs(e,t){let n=re(),o=e.getAll(),r=new Map;for(let i of o){let c=r.get(i.provider)??{count:0,auth:t.hasAuth(i.provider)||n.hasApiKey(i.provider)};c.count+=1,r.set(i.provider,c)}return Array.from(r.entries()).filter(([i])=>Xs.has(i)).sort((i,c)=>i[0].localeCompare(c[0])).map(([i,c])=>({label:`${i} (${c.count}, ${c.auth?"ok":"no auth"})`,command:`/provider ${i}`}))}function Zs(e,t,n=[]){let o=e.getAll().filter(u=>u.provider===t).sort((u,l)=>u.id.localeCompare(l.id));if(n.length===0)return o.map(u=>({label:u.id,command:`/model ${t}/${u.id}`}));let r=new Map(o.map(u=>[u.id,u])),i=new Set,c=[];for(let u of n){let l=r.get(u);!l||i.has(l.id)||(i.add(l.id),c.push(l))}for(let u of o)i.has(u.id)||c.push(u);return c.map(u=>({label:u.id,command:`/model ${t}/${u.id}`}))}function ei(e,t,n=3){let o=new Set,r=[],i=dt(e);for(let c of i){if(c.modelProvider!==t)continue;let u=c.modelId;if(!(!u||o.has(u))&&(o.add(u),r.push(u),r.length>=n))break}return r}function to(e){let t=e.trim();if(!t)return null;let n=t.indexOf(" ");if(n>0){let o=t.slice(0,n).trim(),r=t.slice(n+1).trim();return!o||!r?null:{provider:j(o),modelId:r}}if(t.includes("/")){let o=t.indexOf("/"),r=t.slice(0,o).trim(),i=t.slice(o+1).trim();return!r||!i?null:{provider:j(r),modelId:i}}return{modelId:t}}function Et(e){if(!e)return;let t=e.trim().toLowerCase();if(t==="oauth")return"oauth";if(t==="api_key"||t==="apikey")return"api_key"}function _t(e){let t=e.trim();return t?t.startsWith("!")?"command(...)":/^[A-Z][A-Z0-9_]{2,}$/.test(t)?`env:${t}`:t.length<=8?`${"*".repeat(Math.max(0,t.length-2))}${t.slice(-2)}`:`${t.slice(0,4)}...${t.slice(-4)}`:"(empty)"}function no(e){let t=e.trim().toLowerCase();return t==="clear"||t==="remove"||t==="unset"}function oo(e){let t=e.trim();if(!t)return null;let n=t.indexOf(" ");if(n<=0)return null;let o=j(t.slice(0,n)),r=t.slice(n+1).trim();return!o||!r?null:{provider:o,value:r}}function ti(e){try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return!1}}function yo(e,t){let n=Date.now(),o=ro.get(e)??0;n-o<ni||(ro.set(e,n),console.warn(`[tg-agent] unauthorized user=${e} chat=${t}`))}function ho(e){let t=f.telegramAllowedUsers;return!t||t.size===0?!0:t.has(e)}function oi(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(`
90
+ `)}function et(e,t,n){let o=String(e);return t!==void 0&&!n?null:t!==void 0&&n?`${o}_${t}`:o}function Dt(e,t){if(t.workspaceDir)return t.workspaceDir;let n=f.workspaceMappings.get(e);return n||f.workspaceDir}async function jt(e,t,n,o){let r={};return n&&(r.parse_mode=n),o!==void 0&&(r.message_thread_id=o),await L.sendMessage(e,t,r)}async function wo(e,t,n,o,r){let i={chat_id:e,message_id:t};o&&(i.parse_mode=o),r!==void 0&&(i.message_thread_id=r),await L.editMessageText(n,i)}async function bo(e,t){let n;for(let o of t)try{return await e(o)}catch(r){n=r;let i=r instanceof Error?r.message:String(r);console.warn(`[tg-agent] parse_mode ${o} failed, trying fallback: ${i}`)}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 ri(e,t,n){return await bo(o=>jt(e,t,o,n),co(t))}async function si(e,t,n,o){await bo(r=>wo(e,t,n,r,o),co(n))}async function g(e,t,n){let o=st(t,3900);for(let r of o)await ri(e,r,n)}async function ii(e,t,n){let o=st(t,3900);for(let r of o)await jt(e,r,void 0,n)}function ci(){let e=D()-vo;for(let[o,r]of ee)r.createdAt<e&&ee.delete(o);if(ee.size<=so)return;let t=Array.from(ee.entries()).sort((o,r)=>o[1].createdAt-r[1].createdAt),n=ee.size-so;for(let o=0;o<n;o+=1)ee.delete(t[o][0])}function li(e){ci();let t=ne();for(;ee.has(t);)t=ne();return ee.set(t,{command:e,createdAt:D()}),t}function ui(e){if(!e.startsWith("cmd:"))return null;let t=e.slice(4),n=ee.get(t);return n?D()-n.createdAt>vo?(ee.delete(t),null):n.command:null}function di(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 Lt(e,t){let n=[],o=[];for(let r of e){let i=li(r.command);o.push({text:r.label,callback_data:`cmd:${i}`}),o.length>=t&&(n.push(o),o=[])}return o.length>0&&n.push(o),n}async function Ut(e,t,n,o){let r={reply_markup:{inline_keyboard:n}};return o!==void 0&&(r.message_thread_id=o),await L.sendMessage(e,t,r)}async function Ze(e,t,n,o){let r=o?.perRow??1,i=o?.pageSize??ai,c=o?.footer,u=o?.messageThreadId,l=di(n,i);for(let m=0;m<l.length;m+=1){let s=l[m],a=l.length>1?` (page ${m+1}/${l.length})`:"",d=[`${t}${a}`];c&&d.push(c);let p=Lt(s,r);await Ut(e,d.join(`
91
+ `),p,u)}}function Ct(e,t=mi){return e.length<=t?{text:e,truncated:!1}:{text:`${e.slice(0,Math.max(0,t-15))}...
92
+
93
+ [truncated]`,truncated:!0}}async function fi(e,t){let n="Working...",r=(await jt(e,n,void 0,t)).message_id,i=n,c=0,u=Promise.resolve(),l=(s,a=!1)=>{let d=Date.now();!a&&d-c<pi||s!==i&&(i=s,c=d,u=u.then(async()=>{await wo(e,r,s,void 0,t)}).catch(p=>{console.warn("[tg-agent] status edit failed",p)}))},m=s=>{i=s,c=Date.now(),u=u.then(async()=>{await si(e,r,s,t)}).catch(a=>{console.warn("[tg-agent] status edit failed",a)})};return{update:(s,a=!1)=>{let d=Ct(s).text;l(d,a)},finalize:async s=>{let a=Ct(s).text;m(a),await u},fail:async s=>{let a=Ct(s).text;m(a),await u}}}function gi(e){switch(e.type){case"agent_start":return"Working...";case"tool_start":return`Running tool: ${e.name}
94
+ args: ${yi(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 yi(e){try{let t=new WeakSet,n=200,o=12,r=12,i=3,c=(m,s)=>{if(m==null)return m;if(typeof m=="string")return m.length>n?`${m.slice(0,n)}...`:m;if(typeof m=="number"||typeof m=="boolean")return m;if(typeof m=="bigint")return m.toString();if(typeof m=="function")return"[function]";if(typeof m!="object")return String(m);if(t.has(m))return"[circular]";if(s>=i)return"[truncated]";if(t.add(m),Array.isArray(m)){let p=m.slice(0,r).map(h=>c(h,s+1));return m.length>r&&p.push("[truncated]"),p}let a=Object.entries(m),d={};for(let[p,h]of a.slice(0,o))d[p]=c(h,s+1);return a.length>o&&(d._truncated=!0),d},u=c(e,0),l=JSON.stringify(u);return l?l.length>700?`${l.slice(0,700)}...`:l:"null"}catch{return"[unavailable]"}}function se(e){let t=e instanceof Error?e.message:String(e),n=e?.cause;return n instanceof Error?`${t} (${n.message})`:n?`${t} (${String(n)})`:t}function hi(e,t=140){return e.length<=t?e:`${e.slice(0,t-3)}...`}async function wi(){let e=await ke(f.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=>bn(o))),n=["MCP servers:"];for(let o=0;o<e.length;o+=1){let r=e[o],i=t[o],c=i.ok?"ok":`error: ${hi(i.error??"unknown")}`;n.push(`- ${r.name} (${r.type}) ${fe(r)} status=${c} (${i.durationMs}ms)`)}return n.join(`
95
+ `)}async function It(e,t,n,o,r){let i=r,u=et(e,i,i!==void 0);if(!u)return;let l=await We(u),m=mt(l);switch(m.length>0&&(await T(l),await Promise.all(m.map(s=>xe(u,s).catch(a=>{console.warn(`[tg-agent] cleanup session file failed id=${s}`,a)})))),n){case"start":case"help":{let s=["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","/modelraw <provider> <model> - set custom model id for current session","/mcp - list configured MCP servers","/mcp refresh - reload MCP catalog","/status - show session and workspace settings","/soul [name|off] - bind or clear session soul from ~/.tg-agent/souls/<name>.md","/login <provider> - login to OAuth provider","/logout <provider> - logout from provider (lists accountIds if multiple)","/accounts [provider] - list OAuth accounts, tap to switch","/setdefault <provider>/<accountId> - set default OAuth account","/apikey [provider] | /apikey <provider> <key> - manage API keys","/endpoint [provider] | /endpoint <provider> <url> - manage custom endpoints","/useapikey <provider> - force current session to API key mode","/useoauth <provider>[/accountId] - force current session to OAuth mode","/restart - run restart script (paths.restart_script_path in config)","/stop - stop the current running request","/approve - approve a pending security audit confirmation","/memory - show memory RAG status","/reindex - rebuild vector index for all memories","","Tips:","Send images or files to attach them to the prompt."].join(`
96
+ `);await g(e,s,r);return}case"new":{try{let s=o||"",a=ge(l),d=a?.modelProvider,p=a?.modelId,h=a?.accountId,y=Et(a?.authMode),w=Je(l,s);d&&(w.modelProvider=d,p&&(w.modelId=p)),h&&(w.accountId=h),y&&(w.authMode=y),await T(l),await g(e,`Created session ${w.id} (${w.title}).`,r)}catch(s){await g(e,s.message,r)}return}case"list":{await T(l),await g(e,oi(dt(l)),r);return}case"use":{if(!o){await g(e,"Usage: /use <id>",r);return}if(!Dn(l,o)){await g(e,`Session not found: ${o}`,r);return}await T(l),await g(e,`Active session set to ${o}.`,r);return}case"close":{let s=o||l.activeSessionId;if(!s){await g(e,"No active session to close.",r);return}let a=l.sessions[s];if(a&&a.messages.length>0)try{await g(e,"Reflecting on session memory...",r);let y=await Xe(a,a.modelProvider,a.modelId);y.reflected?await g(e,"Memory archived successfully.",r):y.error?await g(e,`Memory saved (reflection failed: ${y.error})`,r):await g(e,"Memory saved (no reflection).",r)}catch(y){console.warn("[tg-agent] memory archival failed",y),await g(e,`Memory archival failed: ${se(y)}`,r)}let d=Ee.get(u);if(d){if(d.cancelRequested=!0,d.abortRequested=!0,d.status&&d.status.update("Cancelled by user.",!0),d.abort)try{d.abort()}catch(y){console.warn("[tg-agent] abort callback failed during force close",y)}Ot(u)}if(!pt(l,s)){await g(e,`Session not found: ${s}`,r);return}await T(l),await xe(u,s).catch(y=>{console.warn(`[tg-agent] delete session file failed id=${s}`,y)});let h=d?`Force-closed session ${s} (interrupted running task).`:`Closed session ${s}.`;await g(e,h,r);return}case"reset":{let s=ge(l);if(!s){await g(e,"No active session.",r);return}if(s.messages.length>0)try{await g(e,"Reflecting on session memory...",r);let a=await Xe(s,s.modelProvider,s.modelId);a.reflected?await g(e,"Memory archived successfully.",r):a.error?await g(e,`Memory saved (reflection failed: ${a.error})`,r):await g(e,"Memory saved (no reflection).",r)}catch(a){console.warn("[tg-agent] memory archival failed",a),await g(e,`Memory archival failed: ${se(a)}`,r)}On(s),await T(l),await xe(u,s.id).catch(a=>{console.warn(`[tg-agent] reset session file failed id=${s.id}`,a)}),await g(e,`Reset session ${s.id}.`,r);return}case"workspace":{if(!o){let a=Dt(u,l),d=l.workspaceDir?"chat":f.workspaceMappings.has(u)?"config":"default";await g(e,`Workspace: ${a} (source: ${d})`,r);return}let s=de.resolve(W(o.trim()));Nn(l,s),await T(l),await g(e,`Workspace set to: ${s}`,r);return}case"providers":{let{authStorage:s,modelRegistry:a}=await Y(),d=a.getError(),p=Qs(a,s);if(p.length===0){let y=d?`Warning: ${d}
97
+
98
+ No providers found.`:"No providers found.";await g(e,y,r);return}let h=[];d&&h.push(`Warning: ${d}`),h.push("Providers:"),await Ze(e,h.join(`
99
+ `),p,{perRow:1,footer:"Tap a provider to set it. Use /models <provider> to list models.",messageThreadId:r});return}case"models":{let{authStorage:s,modelRegistry:a}=await Y(),d=o?j(o):"";if(!d){let x=ge(l);if(!x?.modelProvider){await g(e,"Usage: /models <provider>",r);return}d=x.modelProvider}let p=re(),h=s.hasAuth(d)||p.hasApiKey(d),y=ei(l,d),w=Zs(a,d,y);if(w.length===0){await g(e,`No models found for provider ${d}.`,r);return}await Ze(e,`Models for ${d} (auth: ${h?"ok":"missing"}):`,w,{perRow:1,footer:"Tap a model to set it.",messageThreadId:r});return}case"provider":{if(!o){await g(e,"Usage: /provider <name>",r);return}let s=j(o),{modelRegistry:a}=await Y();if(!a.getAll().some(y=>y.provider===s)){await g(e,`Unknown provider: ${s}`,r);return}let p=await ye(l,e,r),h=p.modelProvider!==s;p.modelProvider=s,p.modelId=void 0,h&&(p.accountId=void 0),p.updatedAt=D(),await T(l),await g(e,`Session ${p.id} provider set to ${s}.`,r),await It(e,t,"models",s,r);return}case"model":{let s=to(o);if(!s){await g(e,"Usage: /model <provider>/<model>",r);return}let a=await ye(l,e,r),d=j(s.provider??a.modelProvider??"");if(!d){await g(e,"Usage: /model <provider>/<model>",r);return}let{modelRegistry:p}=await Y(),h=Zn(d,s.modelId);if(!p.find(d,h)){await g(e,`Model not found: ${d}/${h}
100
+ Use /models ${d} to list available models.
101
+ To force a custom id, use: /modelraw ${d} ${h}`,r);return}a.modelProvider=d,a.modelId=h,a.updatedAt=D(),await T(l),await g(e,`Session ${a.id} model set to ${d}/${h}.`,r);return}case"modelraw":{let s=to(o);if(!s){await g(e,`Usage: /modelraw <provider> <model>
102
+ Also supported: /modelraw <provider>/<model>`,r);return}let a=await ye(l,e,r),d=j(s.provider??a.modelProvider??"");if(!d){await g(e,`Usage: /modelraw <provider> <model>
103
+ Also supported: /modelraw <provider>/<model>`,r);return}let{modelRegistry:p}=await Y();if(!p.getAll().some(M=>M.provider===d)){await g(e,`Unknown provider: ${d}`,r);return}let y=Zn(d,s.modelId),w=!!p.find(d,y);a.modelProvider=d,a.modelId=y,a.updatedAt=D(),await T(l);let x=w?"registered":"custom";await g(e,`Session ${a.id} model set to ${d}/${y} (${x}).`,r);return}case"status":{let s=ge(l);if(!s){await g(e,"No active session.",r);return}let a=f.modelRef.includes("/")?f.modelRef:`${f.modelProvider}/${f.modelRef}`,d=s.modelProvider||s.modelId?`Model: ${s.modelProvider??"?"}/${s.modelId??"?"}`:`Model: ${a} (default)`,p="",h=Et(s.authMode);if(h==="api_key"){let M=re(),$=s.modelProvider||"",P=$?M.getProviderConfig($):null,U=P?.baseUrl?`, endpoint=${P.baseUrl}`:"";p=`
104
+ Auth: api_key (${P?.apiKey?"key=present":"key=missing"}${U})`}else if(s.accountId){let $=Q().getAccount(s.modelProvider||"",s.accountId);$?p=`
105
+ Auth: oauth (${$.email||s.accountId})`:p=`
106
+ Auth: oauth (${s.accountId}, not found)`}else h==="oauth"&&(p=`
107
+ Auth: oauth (default account)`);let y=Dt(u,l),w=l.workspaceDir?"chat":f.workspaceMappings.has(u)?"config":"default",x=[`Session: ${s.id} (${s.title})`,d+p,`Soul: ${s.soulName??"(none)"}`,`Workspace: ${y} (${w})`].join(`
108
+ `);await g(e,x,r);return}case"soul":{let s=await ye(l,e,r),a=o.trim();if(!a){if(!s.soulName){await g(e,[`Session ${s.id} soul: (none)`,"Set one with: /soul <name>",`File location: ${uo()}/<name>.md`].join(`
109
+ `),r);return}let p=Tt(s.soulName);await g(e,`Session ${s.id} soul: ${s.soulName}
110
+ Path: ${p}`,r);return}let d=a.toLowerCase();if(d==="off"||d==="none"){s.soulName=void 0,s.updatedAt=D(),await T(l),await g(e,`Session ${s.id} soul cleared.`,r);return}if(!lo(a)){await g(e,["Invalid soul name.","Use only letters, numbers, '_' and '-'.","Example: /soul girlfriend"].join(`
111
+ `),r);return}try{let p=await mo(a);s.soulName=a,s.updatedAt=D(),await T(l),await g(e,[`Session ${s.id} soul set to ${a}.`,`Path: ${Tt(a)}`,`Loaded chars: ${p.length}`].join(`
112
+ `),r)}catch(p){await g(e,`Failed to load soul "${a}": ${se(p)}`,r)}return}case"apikey":{let s=re(),a=o.trim();if(!a){let p=s.listProviders().filter(y=>!!s.getProviderConfig(y)?.apiKey);if(p.length===0){await g(e,`No API keys configured.
113
+ Usage: /apikey <provider> <key>
114
+ Clear: /apikey <provider> clear`,r);return}let h=p.map(y=>{let w=s.getProviderConfig(y),x=w?.baseUrl?` | endpoint=${w.baseUrl}`:"";return`- ${y}: ${_t(w?.apiKey??"")}${x}`});await g(e,["API key providers:",...h,"","Set: /apikey <provider> <key>","Clear: /apikey <provider> clear"].join(`
115
+ `),r);return}let d=oo(a);if(!d){let p=j(a),h=s.getProviderConfig(p);if(!h?.apiKey){await g(e,`No API key for ${p}.
116
+ Set one with: /apikey ${p} <key>`,r);return}let y=h.baseUrl?`
117
+ Endpoint: ${h.baseUrl}`:"";await g(e,`API key for ${p}: ${_t(h.apiKey)}${y}`,r);return}if(no(d.value)){if(!await s.clearApiKey(d.provider)){await g(e,`No API key to clear for ${d.provider}.`,r);return}await g(e,`Cleared API key for ${d.provider}.`,r);return}await s.setApiKey(d.provider,d.value),await g(e,`Saved API key for ${d.provider} (${_t(d.value)}).
118
+ Use /useapikey ${d.provider} to force API key mode in this session.`,r);return}case"endpoint":{let s=re(),a=o.trim();if(!a){let p=s.listProviders().filter(y=>!!s.getProviderConfig(y)?.baseUrl);if(p.length===0){await g(e,`No custom endpoints configured.
119
+ Usage: /endpoint <provider> <url>
120
+ Clear: /endpoint <provider> clear`,r);return}let h=p.map(y=>{let w=s.getProviderConfig(y);return`- ${y}: ${w?.baseUrl}`});await g(e,["Custom endpoints:",...h,"","Set: /endpoint <provider> <url>","Clear: /endpoint <provider> clear"].join(`
121
+ `),r);return}let d=oo(a);if(!d){let p=j(a),h=s.getProviderConfig(p);if(!h?.baseUrl){await g(e,`No custom endpoint for ${p}.
122
+ Set one with: /endpoint ${p} <url>`,r);return}await g(e,`Endpoint for ${p}: ${h.baseUrl}`,r);return}if(no(d.value)){if(!await s.clearBaseUrl(d.provider)){await g(e,`No endpoint to clear for ${d.provider}.`,r);return}await g(e,`Cleared custom endpoint for ${d.provider}.`,r);return}if(!ti(d.value)){await g(e,`Invalid endpoint URL: ${d.value}`,r);return}await s.setBaseUrl(d.provider,d.value),await g(e,`Saved endpoint for ${d.provider}: ${d.value}
123
+ This endpoint is used when session auth mode is API key.`,r);return}case"useapikey":{if(!o){await g(e,"Usage: /useapikey <provider>",r);return}let s=j(o),{modelRegistry:a}=await Y();if(!a.getAll().some(M=>M.provider===s)){await g(e,`Unknown provider: ${s}`,r);return}let h=re().getProviderConfig(s);if(!h?.apiKey){await g(e,`No API key for ${s}. Set one with: /apikey ${s} <key>`,r);return}let y=await ye(l,e,r),w=y.modelProvider!==s;y.modelProvider=s,w&&(y.modelId=void 0),y.accountId=void 0,y.authMode="api_key",y.updatedAt=D(),await T(l);let x=h.baseUrl?`
124
+ Endpoint: ${h.baseUrl}`:"";await g(e,`Session ${y.id} now uses API key mode for ${s}.${x}`,r);return}case"useoauth":{if(!o){await g(e,"Usage: /useoauth <provider>[/accountId]",r);return}let s=o.trim(),a=s,d;if(s.includes("/")){let[b,k]=s.split("/",2);if(a=b.trim(),d=k?.trim(),!a||!d){await g(e,"Usage: /useoauth <provider>[/accountId]",r);return}}let p=j(a),{modelRegistry:h}=await Y();if(!h.getAll().some(b=>b.provider===p)){await g(e,`Unknown provider: ${p}`,r);return}let w=Q(),x=w.listAccounts(p);if(x.length===0){await g(e,`No OAuth account for ${p}. Login first: /login ${p}`,r);return}let M=d?x.find(b=>b.id===d):void 0;if(d&&!M){await g(e,`Account not found: ${p}/${d}`,r);return}if(!M){let b=w.getDefaultAccount(p);M=x.find(k=>k.id===b?.id)||x[0]}let $=await ye(l,e,r),P=$.modelProvider!==p;$.modelProvider=p,P&&($.modelId=void 0),$.accountId=M.id,$.authMode="oauth",$.updatedAt=D(),await T(l);let U=M.email||M.id,S=d?"":" [default]";await g(e,`Session ${$.id} now uses OAuth mode for ${p} (${U}${S}).`,r);return}case"mcp":{if(o.trim().toLowerCase()==="refresh"){wn(),await pe(f.agentDir,{timeoutMs:5e3,maxBytes:f.fetchMaxBytes,maxChars:3e3}),Pe(),await g(e,"MCP catalog refreshed.",r);return}let s=await wi();await g(e,s,r);return}case"login":{let s=Yn();if(!o){let p=s.map(h=>`- ${h.id} (${h.name})`);await g(e,["OAuth providers:",...p].join(`
125
+ `),r);return}let a=j(o);if(Pt.has(t)){await g(e,"Login already in progress.",r);return}let d=s.find(p=>p.id===a);if(!d){await g(e,`Unknown OAuth provider: ${a}`,r);return}Pt.add(t);try{let{authStorage:p}=await Y(),h=Q(),y=h.listAccounts(a);y.length>0&&await g(e,`You have ${y.length} account(s) for ${a}. Adding a new one...`,r),await g(e,`Starting login for ${d.id}...`,r);let w=Ps(a);if(!w)throw new Error(`OAuth provider not found: ${a}`);let x=await w.login({onAuth:({url:S,instructions:b})=>{let k=["Open this URL in your browser:",S];b&&k.push("",b),ii(e,k.join(`
126
+ `),r)},onPrompt:S=>eo(t,e,S,r),onProgress:S=>{g(e,S,r)},onManualCodeInput:()=>eo(t,e,{message:"Paste the authorization code:"},r)}),M=x.email,$=await h.addAccount(a,x,{email:M});p.set(a,{type:"oauth",...x});let P=h.listAccounts(a),U=M||$;await g(e,`Login completed for ${d.id}.
127
+ Account: ${U}
128
+ Account ID: ${$}
129
+ Total accounts: ${P.length}
130
+ Use /accounts ${a} to see all accounts.`,r)}catch(p){let h=se(p);await g(e,`Login failed: ${h}`,r)}finally{Pt.delete(t),po(t)}return}case"logout":{if(!o){await g(e,`Usage: /logout <provider> \u2014 lists accountIds if multiple.
108
131
  /logout <provider>/<accountId> \u2014 logout one account.
109
- /logout <provider>/all \u2014 logout all accounts for that provider.`,r);return}let i=ne();if(o.includes("/")){let[c,d]=o.split("/",2),p=X(c);if(d==="all"){let b=await i.removeAllAccounts(p),{authStorage:$}=await ie();$.logout(p),await f(e,`Logged out from ${p} (${b} account(s)).`,r);return}let y=i.getAccount(p,d);if(!y){await f(e,`Account not found: ${p}/${d}`,r);return}let h=y.email||d;if(await i.removeAccount(p,d),!i.hasAccounts(p)){let{authStorage:b}=await ie();b.logout(p)}await f(e,`Logged out: ${h} (${p})`,r)}else{let c=X(o),d=i.listAccounts(c);if(d.length===0){await f(e,`No accounts for ${c}.`,r);return}if(d.length>1){let h=d.map(M=>` ${M.id}${M.email?` (${M.email})`:""}${M.isDefault?" [default]":""}`),b=[...d.map(M=>({label:M.email?`Logout ${M.email}`:`Logout ${M.id}`,command:`/logout ${c}/${M.id}`})),{label:"Logout all",command:`/logout ${c}/all`}],$=_t(b,1),A=`You have ${d.length} account(s) for ${c}:
110
- ${h.join(`
132
+ /logout <provider>/all \u2014 logout all accounts for that provider.`,r);return}let s=Q();if(o.includes("/")){let[a,d]=o.split("/",2),p=j(a);if(d==="all"){let w=await s.removeAllAccounts(p),{authStorage:x}=await Y();x.logout(p),await g(e,`Logged out from ${p} (${w} account(s)).`,r);return}let h=s.getAccount(p,d);if(!h){await g(e,`Account not found: ${p}/${d}`,r);return}let y=h.email||d;if(await s.removeAccount(p,d),!s.hasAccounts(p)){let{authStorage:w}=await Y();w.logout(p)}await g(e,`Logged out: ${y} (${p})`,r)}else{let a=j(o),d=s.listAccounts(a);if(d.length===0){await g(e,`No accounts for ${a}.`,r);return}if(d.length>1){let y=d.map($=>` ${$.id}${$.email?` (${$.email})`:""}${$.isDefault?" [default]":""}`),w=[...d.map($=>({label:$.email?`Logout ${$.email}`:`Logout ${$.id}`,command:`/logout ${a}/${$.id}`})),{label:"Logout all",command:`/logout ${a}/all`}],x=Lt(w,1),M=`You have ${d.length} account(s) for ${a}:
133
+ ${y.join(`
111
134
  `)}
112
135
 
113
- Tap to logout:`;await Ct(e,A,$,r);return}let p=await i.removeAllAccounts(c),{authStorage:y}=await ie();y.logout(c),p>0?await f(e,`Logged out from ${c} (${p} account(s)).`,r):await f(e,`Logged out from ${c}.`,r)}return}case"accounts":{let i=ne();if(!o){let y=Un(),h=[];for(let b of y){let $=i.listAccounts(b.id);for(let A of $){let M=A.email||A.id,C=A.isDefault?" *":"";h.push({label:`${b.id}: ${M}${C}`,command:`/useaccount ${b.id}/${A.id}`})}}if(h.length===0){await f(e,"No accounts found. Use /login <provider> to add one.",r);return}await Xe(e,"All accounts (tap to switch session to this account):",h,{perRow:1,footer:"Tap to switch provider and account. * = default for that provider.",messageThreadId:r});return}let c=X(o),d=i.listAccounts(c);if(d.length===0){await f(e,`No accounts for ${c}. Use /login ${c} to add one.`,r);return}let p=d.map(y=>{let h=y.email||y.id,b=y.isDefault?" *":"";return{label:`${h}${b}`,command:`/useaccount ${c}/${y.id}`}});await Xe(e,`Accounts for ${c}:`,p,{perRow:1,footer:"Tap to use this account for current session. * = default",messageThreadId:r});return}case"useaccount":{if(!o||!o.includes("/")){await f(e,"Usage: /useaccount <provider>/<accountId>",r);return}let[i,c]=o.split("/",2),d=X(i),y=ne().getAccount(d,c);if(!y){await f(e,`Account not found: ${d}/${c}`,r);return}let h=await St(u,e,r);h.modelProvider=d,h.accountId=c,h.updatedAt=U(),await I(u);let b=y.email||c;await f(e,`Session "${h.title||h.id}" now using: ${b} (${d})`,r);return}case"setdefault":{if(!o||!o.includes("/")){await f(e,"Usage: /setdefault <provider>/<accountId>",r);return}let[i,c]=o.split("/",2),d=X(i),p=ne(),y=p.getAccount(d,c);if(!y){await f(e,`Account not found: ${d}/${c}`,r);return}if(!await p.setDefaultAccount(d,c)){await f(e,"Failed to set default account.",r);return}let b=y.email||c;await f(e,`Default account for ${d} set to: ${b}`,r);return}case"restart":{let i=g.restartScriptPath;if(!i){await f(e,'restart_script_path not configured. Set [paths] restart_script_path = "path/to/script.sh" in config.toml.',r);return}try{Zr("bash",[i],{stdio:"ignore",detached:!0}).unref(),await f(e,`Restart script started: ${i}`,r)}catch(c){let d=c instanceof Error?c.message:String(c);await f(e,`Restart failed: ${d}`,r)}return}case"memory":{let i=g.memory.rag,c=await In(),d=["Memory System Status:","",`RAG Enabled: ${i.enabled?"Yes":"No"}`,`Embedding Model: ${i.embeddingModel}`,`Embedding Base URL: ${i.embeddingBaseUrl||"(default)"}`,`Similarity Threshold: ${i.similarityThreshold}`,`Max Results: ${i.maxResults}`,"","Database:",` Sessions: ${c.sessionsCount}`,` Memories: ${c.memoriesCount}`,"","Tip: Use /reindex to rebuild memory vectors after changing embedding model."];await f(e,d.join(`
114
- `),r);return}case"reindex":{if(!g.memory.rag.enabled){await f(e,"Memory RAG is disabled. Enable it in config.toml first.",r);return}await f(e,["Starting memory reindex...","",`Embedding Model: ${g.memory.rag.embeddingModel}`,"","Reading sessions and rebuilding memories table..."].join(`
115
- `),r);try{let i=await Ln((c,d,p)=>{(c%5===0||c===d)&&console.log(`[reindex] Progress: ${c}/${d} - ${p}`)});if(i.success){let c=["Reindex completed!","",`Sessions: ${i.totalSessions}`,`Total memories: ${i.totalMemories}`,`Indexed: ${i.indexedMemories}`,`Errors: ${i.errors.length}`,"",`Embedding Model: ${i.embeddingModel}`,`Vector Dimension: ${i.vectorDimension??"N/A"}`];i.errors.length>0&&(c.push("","Errors:"),i.errors.slice(0,5).forEach(d=>c.push(` - ${d}`)),i.errors.length>5&&c.push(` ... and ${i.errors.length-5} more`)),await f(e,c.join(`
116
- `),r)}else await f(e,`Reindex failed: ${i.errors.join(", ")}`,r)}catch(i){let c=i instanceof Error?i.message:String(i);await f(e,`Reindex failed: ${c}`,r)}return}default:await f(e,`Unknown command: ${n}`,r)}}async function qs(e,t,n,o=[],r){let s=kt(n);if(s){await Rt(e,t,s.command,s.args,r);return}let a=Qe(e,r,r!==void 0);if(!a)return;let u=await Be(a),m=lt(u);m.length>0&&(await I(u),await Promise.all(m.map(M=>ye(a,M).catch(C=>{console.warn(`[tg-agent] cleanup session file failed id=${M}`,C)}))));let i=de(u);if(!i)try{i=Ke(u,""),await I(u),await f(e,`Created session ${i.id}.`,r)}catch(M){await f(e,M.message,r);return}let{resolved:c,images:d}=await fs(o);if(o.length>0&&c.length===0&&!n.trim()){await f(e,"Failed to download attachments.",r);return}let p=gs(c),y=[];n.trim()&&y.push(n.trim()),p&&y.push(p);let h=y.join(`
136
+ Tap to logout:`;await Ut(e,M,x,r);return}let p=await s.removeAllAccounts(a),{authStorage:h}=await Y();h.logout(a),p>0?await g(e,`Logged out from ${a} (${p} account(s)).`,r):await g(e,`Logged out from ${a}.`,r)}return}case"accounts":{let s=Q();if(!o){let h=Yn(),y=[];for(let w of h){let x=s.listAccounts(w.id);for(let M of x){let $=M.email||M.id,P=M.isDefault?" *":"";y.push({label:`${w.id}: ${$}${P}`,command:`/useaccount ${w.id}/${M.id}`})}}if(y.length===0){await g(e,"No accounts found. Use /login <provider> to add one.",r);return}await Ze(e,"All accounts (tap to switch session to this account):",y,{perRow:1,footer:"Tap to switch provider and account. * = default for that provider.",messageThreadId:r});return}let a=j(o),d=s.listAccounts(a);if(d.length===0){await g(e,`No accounts for ${a}. Use /login ${a} to add one.`,r);return}let p=d.map(h=>{let y=h.email||h.id,w=h.isDefault?" *":"";return{label:`${y}${w}`,command:`/useaccount ${a}/${h.id}`}});await Ze(e,`Accounts for ${a}:`,p,{perRow:1,footer:"Tap to use this account for current session. * = default",messageThreadId:r});return}case"useaccount":{if(!o||!o.includes("/")){await g(e,"Usage: /useaccount <provider>/<accountId>",r);return}let[s,a]=o.split("/",2),d=j(s),h=Q().getAccount(d,a);if(!h){await g(e,`Account not found: ${d}/${a}`,r);return}let y=await ye(l,e,r),w=y.modelProvider!==d;y.modelProvider=d,w&&(y.modelId=void 0),y.accountId=a,y.authMode="oauth",y.updatedAt=D(),await T(l);let x=h.email||a;await g(e,`Session "${y.title||y.id}" now using: ${x} (${d})`,r);return}case"setdefault":{if(!o||!o.includes("/")){await g(e,"Usage: /setdefault <provider>/<accountId>",r);return}let[s,a]=o.split("/",2),d=j(s),p=Q(),h=p.getAccount(d,a);if(!h){await g(e,`Account not found: ${d}/${a}`,r);return}if(!await p.setDefaultAccount(d,a)){await g(e,"Failed to set default account.",r);return}let w=h.email||a;await g(e,`Default account for ${d} set to: ${w}`,r);return}case"restart":{let s=f.restartScriptPath;if(!s){await g(e,'restart_script_path not configured. Set [paths] restart_script_path = "path/to/script.sh" in config.toml.',r);return}try{Ss("bash",[s],{stdio:"ignore",detached:!0}).unref(),await g(e,`Restart script started: ${s}`,r)}catch(a){let d=a instanceof Error?a.message:String(a);await g(e,`Restart failed: ${d}`,r)}return}case"memory":{let s=f.memory.rag,a=await Hn(),d=["Memory System Status:","",`RAG Enabled: ${s.enabled?"Yes":"No"}`,`Embedding Model: ${s.embeddingModel}`,`Embedding Base URL: ${s.embeddingBaseUrl||"(default)"}`,`Similarity Threshold: ${s.similarityThreshold}`,`Max Results: ${s.maxResults}`,"","Database:",` Sessions: ${a.sessionsCount}`,` Memories: ${a.memoriesCount}`,"","Tip: Use /reindex to rebuild memory vectors after changing embedding model."];await g(e,d.join(`
137
+ `),r);return}case"reindex":{if(!f.memory.rag.enabled){await g(e,"Memory RAG is disabled. Enable it in config.toml first.",r);return}await g(e,["Starting memory reindex...","",`Embedding Model: ${f.memory.rag.embeddingModel}`,"","Reading sessions and rebuilding memories table..."].join(`
138
+ `),r);try{let s=await qn((a,d,p)=>{(a%5===0||a===d)&&console.log(`[reindex] Progress: ${a}/${d} - ${p}`)});if(s.success){let a=["Reindex completed!","",`Sessions: ${s.totalSessions}`,`Total memories: ${s.totalMemories}`,`Indexed: ${s.indexedMemories}`,`Errors: ${s.errors.length}`,"",`Embedding Model: ${s.embeddingModel}`,`Vector Dimension: ${s.vectorDimension??"N/A"}`];s.errors.length>0&&(a.push("","Errors:"),s.errors.slice(0,5).forEach(d=>a.push(` - ${d}`)),s.errors.length>5&&a.push(` ... and ${s.errors.length-5} more`)),await g(e,a.join(`
139
+ `),r)}else await g(e,`Reindex failed: ${s.errors.join(", ")}`,r)}catch(s){let a=s instanceof Error?s.message:String(s);await g(e,`Reindex failed: ${a}`,r)}return}default:await g(e,`Unknown command: ${n}`,r)}}async function bi(e,t,n,o=[],r){let i=Nt(n);if(i){await It(e,t,i.command,i.args,r);return}let u=et(e,r,r!==void 0);if(!u)return;let l=await We(u),m=mt(l);m.length>0&&(await T(l),await Promise.all(m.map($=>xe(u,$).catch(P=>{console.warn(`[tg-agent] cleanup session file failed id=${$}`,P)}))));let s=ge(l);if(!s)try{s=Je(l,""),await T(l),await g(e,`Created session ${s.id}.`,r)}catch($){await g(e,$.message,r);return}let{resolved:a,images:d}=await Is(o);if(o.length>0&&a.length===0&&!n.trim()){await g(e,"Failed to download attachments.",r);return}let p=Ls(a),h=[];n.trim()&&h.push(n.trim()),p&&h.push(p);let y=h.join(`
117
140
 
118
- `)||"Attachment received.",b={role:"user",content:h,ts:U()};dt(i,b,g.maxHistoryMessages),await I(u),console.log(`[tg-agent] request user=${t} chat=${a} session=${i.id} messages=${i.messages.length} textLen=${h.length} attachments=${c.length} provider=${i.modelProvider??"-"} model=${i.modelId??"-"}`);let $=null;try{$=await Bs(e,r)}catch(M){console.warn("[tg-agent] status message failed",M)}let A={sessionId:i.id,chatId:e,messageThreadId:r,status:$,abortRequested:!1,cancelRequested:!1};ss(a,A);try{let M=g.systemPrompt;if(g.memory.rag.enabled&&h.trim())try{let v=await On(h);if(v.length>0){let x=v.map(k=>`- [${k.type}] ${k.content} (${k.date})`).join(`
119
- `);M+=`
141
+ `)||"Attachment received.",w={role:"user",content:y,ts:D()};ft(s,w,f.maxHistoryMessages),await T(l),console.log(`[tg-agent] request user=${t} chat=${u} session=${s.id} messages=${s.messages.length} textLen=${y.length} attachments=${a.length} provider=${s.modelProvider??"-"} model=${s.modelId??"-"}`);let x=null;try{x=await fi(e,r)}catch($){console.warn("[tg-agent] status message failed",$)}let M={sessionId:s.id,chatId:e,messageThreadId:r,status:x,abortRequested:!1,cancelRequested:!1};Cs(u,M);try{let $=f.systemPrompt;if(s.soulName)try{let S=await mo(s.soulName);$+=`
142
+
143
+ ${Gs(s.soulName,S)}`,console.log(`[tg-agent] injected soul name=${s.soulName} chars=${S.length}`)}catch(S){console.warn(`[tg-agent] failed to load soul name=${s.soulName}: ${se(S)}`)}if(f.memory.rag.enabled&&y.trim())try{let S=await Jn(y);if(S.length>0){let b=S.map(k=>`- [${k.type}] ${k.content} (${k.date})`).join(`
144
+ `);$+=`
120
145
 
121
146
  <relevant_memories>
122
147
  Relevant facts about Shawn from past conversations:
123
148
 
124
- ${x}
125
- </relevant_memories>`,console.log(`[memory-rag] injected ${v.length} memories into context`)}}catch(v){console.warn(`[memory-rag] retrieval failed: ${v}`)}let C=await rs(async()=>{let v=await He({chatId:a,sessionId:i.id,prompt:h,images:d,systemPrompt:M,modelProvider:i.modelProvider,modelId:i.modelId,accountId:i.accountId,workspaceDir:$t(a,u),telegram:{chatId:e,sendPhoto:async(x,k)=>{let E={};k&&(E.caption=k),r!==void 0&&(E.message_thread_id=r),await L.sendPhoto(e,x,E)},sendDocument:async(x,k)=>{let E={};k&&(E.caption=k),r!==void 0&&(E.message_thread_id=r),await L.sendDocument(e,x,E)},sendMessage:async x=>{await f(e,x,r)},requestConfirmation:async(x,k)=>await zn(a,e,x,k,r)},auditContext:g.audit.enabled?{chatId:a,requestConfirmation:async(x,k)=>await zn(a,e,x,k,r),sendNotification:async x=>{await f(e,x,r)}}:void 0,onAbortReady:x=>{A.abort=x,A.abortRequested&&x()},onStatus:$?x=>{let k=Ks(x);k&&$?.update(k)}:void 0});return console.log(`[tg-agent] response session=${i.id} model=${v.modelProvider}/${v.modelId} file=${v.sessionFile}`),v.text});if(A.cancelRequested){$?await $.finalize("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let _={role:"assistant",content:C,ts:U()};dt(i,_,g.maxHistoryMessages),await I(u),$?await $.finalize(C):await f(e,C,r)}catch(M){if(console.error("[tg-agent] runModel error",M),A.cancelRequested){$?await $.fail("Cancelled by user."):await f(e,"Cancelled by user.",r);return}let C=me(M);$?await $.fail(`Error: ${C}`):await f(e,`Error: ${C}`,r)}finally{At(a)}}async function Gs(){let e=[{type:"default"},{type:"all_private_chats"},{type:"all_group_chats"}];for(let t of e)try{await L.setMyCommands(Jn,{scope:t}),console.log(`[tg-agent] bot commands registered scope=${t.type} count=${Jn.length}`)}catch(n){let o=n instanceof Error?n.message:String(n);console.warn(`[tg-agent] setMyCommands failed scope=${t.type}:`,o)}}var L,Hn,rs,Ce,as,ys,bs,ae,xt,Pe,vs,xs,Ye,As,Rs,Kn,to,Wn,Is,Q,Us,zs,Jn,no=F(()=>{"use strict";K();ot();st();yt();pe();ft();Ae();mt();Nn();vt();q();Yt();L=new es(g.telegramToken,{polling:!0}),Hn=jt(),rs=Nt(g.maxConcurrent),Ce=new Map;as="image/jpeg";ys=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);bs=600*1e3,ae=new Map,xt=new Set,Pe=new Map;vs=new Map([["codex","openai-codex"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),xs={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"};$s();T(g.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await le(g.agentDir,{timeoutMs:3e3,maxBytes:g.fetchMaxBytes,maxChars:2e3}),$e()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Ye=je();console.log(Ye?`[tg-agent] fetchProxy=${Ye.url} kind=${Ye.kind} source=${Ye.source}`:"[tg-agent] fetchProxy=(none)");As=new Set(["openai-codex","google-antigravity","anthropic"]);Rs=6e4,Kn=new Map;to=1800*1e3,Wn=2e3,Is=60,Q=new Map;Us=3900,zs=1200;L.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){L.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!Qn(o)){Xn(o,n),L.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){L.answerCallbackQuery(e.id);return}let r=Ns(t);if(!r){L.answerCallbackQuery(e.id,{text:"Command expired."});return}L.answerCallbackQuery(e.id);let s=e.message?.message_thread_id,l=e.message?.is_topic_message??!1,a=Qe(n,s,l);if(!a)return;let u=kt(r);if(u?.command==="stop"){_e(a,!1)?f(n,"Operation blocked.",s):Vn(n,a,s);return}if(u?.command==="close"){Yn(n,a,u.args,s);return}if(u?.command==="approve"){_e(a,!0)?f(n,"Operation approved.",s):f(n,"No pending audit confirmation.",s);return}Hn(a,async()=>{if(!u){await f(n,"Invalid command.",s);return}await Rt(n,o,u.command,u.args,s)}).catch(async m=>{console.error("[tg-agent] runModel error",m);let i=me(m);await f(n,`Error: ${i}`,s)})});L.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!Qn(t)){Xn(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,s=Qe(n,o,r);if(!s)return;let l=(e.text??e.caption??"").trim(),a=ps(e);if(!l&&a.length===0)return;let u=ae.get(t);if(u){if(l==="/stop"||l==="/cancel"){Ms(t,"Login cancelled by user."),f(n,"Login cancelled.",o);return}if(!l){f(n,"Login expects a text response.",o);return}Gn(t),u.resolve(l);return}let m=kt(l);if(m?.command==="stop"){_e(s,!1),Vn(n,s,o);return}if(m?.command==="close"){_e(s,!1),Yn(n,s,m.args,o);return}if(m?.command==="approve"){_e(s,!0)?f(n,"Operation approved.",o):f(n,"No pending audit confirmation.",o);return}Hn(s,()=>qs(n,t,l,a,o)).catch(async i=>{console.error("[tg-agent] runModel error",i);let c=me(i);await f(n,`Error: ${c}`,o)})});L.on("polling_error",e=>{console.error("Polling error",e)});Jn=[{command:"new",description:"Create a new session"},{command:"list",description:"List all sessions"},{command:"use",description:"Switch to a session"},{command:"close",description:"Close current session"},{command:"reset",description:"Clear session history"},{command:"stop",description:"Stop current request"},{command:"workspace",description:"View/set workspace directory"},{command:"status",description:"Show session status"},{command:"providers",description:"List available providers"},{command:"models",description:"List models for provider"},{command:"provider",description:"Set provider for session"},{command:"model",description:"Set model for session"},{command:"mcp",description:"List MCP servers"},{command:"memory",description:"Show memory RAG status"},{command:"reindex",description:"Rebuild memory vector index"},{command:"login",description:"Login to OAuth provider"},{command:"logout",description:"Logout from provider"},{command:"accounts",description:"List OAuth accounts (tap to switch)"},{command:"setdefault",description:"Set default OAuth account"},{command:"restart",description:"Run restart script (config)"},{command:"approve",description:"Approve security audit"},{command:"help",description:"Show all commands"}];Gs();console.log("tg-agent started")});K();st();Ae();yt();q();import Ys from"node:fs";import oo from"node:path";import Xs from"node:readline/promises";import{fileURLToPath as Qs}from"node:url";var ce=process.argv.slice(2),so=(e,t)=>ce.includes(e)||(t?ce.includes(t):!1),Zs=so("--help","-h"),ei=so("--version","-v"),ti=["Usage: tg-agent [options] [ -c | --cli <prompt> ]","","Options:"," -h, --help Show help"," -v, --version Show version"," -c, --cli <cmd> Run a one-shot CLI task (no Telegram). Task must complete within TG_AGENT_CLI_TIMEOUT_MS (default 30m)."," -p, --provider <name> Model provider for CLI task (e.g. openai-codex)."," -m, --model <id> Model id for CLI task (e.g. gpt-4 or provider/modelId)."].join(`
126
- `),ni=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Qs(import.meta.url),t=oo.dirname(e),n=oo.join(t,"..","package.json"),o=Ys.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Zs&&(console.log(ti),process.exit(0));ei&&(console.log(ni()),process.exit(0));async function oi(){let e=Xs.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}function ri(){for(let e=0;e<ce.length;e+=1){let t=ce[e];if(t==="-c"||t==="--cli"){let n=ce[e+1];return n!==void 0&&!n.startsWith("-")?n:null}if(t.startsWith("--cli="))return t.slice(6);if(t.startsWith("-c="))return t.slice(3)}return null}function io(e,t=!0){for(let n=0;n<ce.length;n+=1){let o=ce[n];if(e.includes(o)){let r=ce[n+1];return r!==void 0&&!r.startsWith("-")&&r.trim()||null}if(t&&o.startsWith("--")){for(let r of e)if(r.startsWith("--")&&o.startsWith(r+"="))return o.slice(r.length+1).trim()||null}}return null}function si(){return io(["--provider","-p"])??null}function ii(){return io(["--model","-m"])??null}async function ai(e=!1){let{configPath:t,data:n,exists:o}=Se(),r=Wt(),s=o?n:r,l=Jt(s,r);if(Ht(s)){l&&await Le(t,s);return}if(e){l&&await Le(t,s);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${t}.`),process.exit(1));let u=await oi();u||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),qt(s,u),await Le(t,s),console.log(`Saved config to ${t}.`)}var Et="[TG-AGENT-CLI-DONE]",ci=`This is a one-shot CLI task. Do not reply to the user until the entire task is complete.
149
+ ${b}
150
+ </relevant_memories>`,console.log(`[memory-rag] injected ${S.length} memories into context`)}}catch(S){console.warn(`[memory-rag] retrieval failed: ${S}`)}let P=await _s(async()=>{let S=await Ge({chatId:u,sessionId:s.id,prompt:y,images:d,systemPrompt:$,modelProvider:s.modelProvider,modelId:s.modelId,accountId:s.accountId,authMode:Et(s.authMode),workspaceDir:Dt(u,l),telegram:{chatId:e,sendPhoto:async(b,k)=>{let I={};k&&(I.caption=k),r!==void 0&&(I.message_thread_id=r),await L.sendPhoto(e,b,I)},sendDocument:async(b,k)=>{let I={};k&&(I.caption=k),r!==void 0&&(I.message_thread_id=r),await L.sendDocument(e,b,I)},sendMessage:async b=>{await g(e,b,r)},requestConfirmation:async(b,k)=>await Xn(u,e,b,k,r)},auditContext:f.audit.enabled?{chatId:u,requestConfirmation:async(b,k)=>await Xn(u,e,b,k,r),sendNotification:async b=>{await g(e,b,r)}}:void 0,onAbortReady:b=>{M.abort=b,M.abortRequested&&b()},onStatus:x?b=>{let k=gi(b);k&&x?.update(k)}:void 0});return console.log(`[tg-agent] response session=${s.id} model=${S.modelProvider}/${S.modelId} file=${S.sessionFile}`),S.text});if(M.cancelRequested){x?await x.finalize("Cancelled by user."):await g(e,"Cancelled by user.",r);return}let U={role:"assistant",content:P,ts:D()};ft(s,U,f.maxHistoryMessages),await T(l),x?await x.finalize(P):await g(e,P,r)}catch($){if(console.error("[tg-agent] runModel error",$),M.cancelRequested){x?await x.fail("Cancelled by user."):await g(e,"Cancelled by user.",r);return}let P=se($);x?await x.fail(`Error: ${P}`):await g(e,`Error: ${P}`,r)}finally{Ot(u)}}async function vi(){let e=[{type:"default"},{type:"all_private_chats"},{type:"all_group_chats"}];for(let t of e)try{await L.setMyCommands(io,{scope:t}),console.log(`[tg-agent] bot commands registered scope=${t.type} count=${io.length}`)}catch(n){let o=n instanceof Error?n.message:String(n);console.warn(`[tg-agent] setMyCommands failed scope=${t.type}:`,o)}}var L,ao,_s,Ee,Ts,Fs,Bs,ue,Pt,Re,Ws,Js,Hs,Qn,qs,Qe,Xs,ni,ro,vo,so,ai,ee,mi,pi,io,xo=z(()=>{"use strict";K();it();ct();$t();be();wt();xt();_e();gt();Vn();kt();J();sn();L=new As(f.telegramToken,{polling:!0}),ao=Ht(),_s=qt(f.maxConcurrent),Ee=new Map;Ts="image/jpeg";Fs=new Set(["_","*","[","]","(",")","~","`",">","#","+","-","=","|","{","}",".","!"]);Bs=600*1e3,ue=new Map,Pt=new Set,Re=new Map;Ws=new Map([["codex","openai-codex"],["claude","anthropic"],["antigravity","google-antigravity"],["gemini","google-gemini-cli"],["gemini-cli","google-gemini-cli"]]),Js={"codex-mini-latest":"gpt-5.1-codex-mini","codex-max-latest":"gpt-5.1-codex-max","codex-latest":"gpt-5.2-codex"},Hs=/^[a-zA-Z0-9_-]+$/,Qn=16e3,qs=["<session_soul_protocol>",'You may receive an optional block: <session_soul name="...">...</session_soul>.',"Treat it as session-level behavioral guidance (tone, style, default strategy).","Priority order:","1) Safety and non-overridable policy constraints","2) Core system instructions","3) Explicit user instructions in this conversation","4) session_soul guidance (default behavior only)","If conflicts exist, follow higher-priority rules and ignore conflicting soul parts.","Do not mention this protocol unless asked.","</session_soul_protocol>"].join(`
151
+ `);Ys();C(f.agentDir).catch(e=>{console.warn(`[tg-agent] ensure agentDir failed: ${e instanceof Error?e.message:String(e)}`)});(async()=>{try{await pe(f.agentDir,{timeoutMs:3e3,maxBytes:f.fetchMaxBytes,maxChars:2e3}),Pe()}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[tg-agent] mcp catalog warmup failed: ${t}`)}})();Qe=Ie();console.log(Qe?`[tg-agent] fetchProxy=${Qe.url} kind=${Qe.kind} source=${Qe.source}`:"[tg-agent] fetchProxy=(none)");Xs=new Set(["openai-codex","google-antigravity","anthropic"]);ni=6e4,ro=new Map;vo=1800*1e3,so=2e3,ai=60,ee=new Map;mi=3900,pi=1200;L.on("callback_query",e=>{let t=e.data??"",n=e.message?.chat.id;if(!e.from?.id||!n){L.answerCallbackQuery(e.id);return}let o=String(e.from.id);if(!ho(o)){yo(o,n),L.answerCallbackQuery(e.id);return}if(!t.startsWith("cmd:")){L.answerCallbackQuery(e.id);return}let r=ui(t);if(!r){L.answerCallbackQuery(e.id,{text:"Command expired."});return}L.answerCallbackQuery(e.id);let i=e.message?.message_thread_id,c=e.message?.is_topic_message??!1,u=et(n,i,c);if(!u)return;let l=Nt(r);if(l?.command==="stop"){Te(u,!1)?g(n,"Operation blocked.",i):fo(n,u,i);return}if(l?.command==="close"){go(n,u,l.args,i);return}if(l?.command==="approve"){Te(u,!0)?g(n,"Operation approved.",i):g(n,"No pending audit confirmation.",i);return}ao(u,async()=>{if(!l){await g(n,"Invalid command.",i);return}await It(n,o,l.command,l.args,i)}).catch(async m=>{console.error("[tg-agent] runModel error",m);let s=se(m);await g(n,`Error: ${s}`,i)})});L.on("message",e=>{if(!e.from?.id)return;let t=String(e.from.id),n=e.chat.id;if(!ho(t)){yo(t,n);return}let o=e.message_thread_id,r=e.is_topic_message??!1,i=et(n,o,r);if(!i)return;let c=(e.text??e.caption??"").trim(),u=Us(e);if(!c&&u.length===0)return;let l=ue.get(t);if(l){if(c==="/stop"||c==="/cancel"){Vs(t,"Login cancelled by user."),g(n,"Login cancelled.",o);return}if(!c){g(n,"Login expects a text response.",o);return}po(t),l.resolve(c);return}let m=Nt(c);if(m?.command==="stop"){Te(i,!1),fo(n,i,o);return}if(m?.command==="close"){Te(i,!1),go(n,i,m.args,o);return}if(m?.command==="approve"){Te(i,!0)?g(n,"Operation approved.",o):g(n,"No pending audit confirmation.",o);return}ao(i,()=>bi(n,t,c,u,o)).catch(async s=>{console.error("[tg-agent] runModel error",s);let a=se(s);await g(n,`Error: ${a}`,o)})});L.on("polling_error",e=>{console.error("Polling error",e)});io=[{command:"new",description:"Create a new session"},{command:"list",description:"List all sessions"},{command:"use",description:"Switch to a session"},{command:"close",description:"Close current session"},{command:"reset",description:"Clear session history"},{command:"stop",description:"Stop current request"},{command:"workspace",description:"View/set workspace directory"},{command:"status",description:"Show session status"},{command:"providers",description:"List available providers"},{command:"models",description:"List models for provider"},{command:"provider",description:"Set provider for session"},{command:"model",description:"Set model for session"},{command:"modelraw",description:"Set custom model id for session"},{command:"mcp",description:"List MCP servers"},{command:"soul",description:"Bind/clear session soul profile"},{command:"memory",description:"Show memory RAG status"},{command:"reindex",description:"Rebuild memory vector index"},{command:"login",description:"Login to OAuth provider"},{command:"logout",description:"Logout from provider"},{command:"accounts",description:"List OAuth accounts (tap to switch)"},{command:"setdefault",description:"Set default OAuth account"},{command:"apikey",description:"Set/list API key for provider"},{command:"endpoint",description:"Set/list custom endpoint"},{command:"useapikey",description:"Use API key mode in session"},{command:"useoauth",description:"Use OAuth mode in session"},{command:"restart",description:"Run restart script (config)"},{command:"approve",description:"Approve security audit"},{command:"help",description:"Show all commands"}];vi();console.log("tg-agent started")});K();ct();_e();$t();J();import $i from"node:fs";import $o from"node:path";import Si from"node:readline/promises";import{fileURLToPath as Ai}from"node:url";var me=process.argv.slice(2),Ao=(e,t)=>me.includes(e)||(t?me.includes(t):!1),Mi=Ao("--help","-h"),ki=Ao("--version","-v"),Pi=["Usage: tg-agent [options] [ -c | --cli <prompt> ]","","Options:"," -h, --help Show help"," -v, --version Show version"," -c, --cli <cmd> Run a one-shot CLI task (no Telegram). Task must complete within TG_AGENT_CLI_TIMEOUT_MS (default 30m)."," -p, --provider <name> Model provider for CLI task (e.g. openai-codex)."," -m, --model <id> Model id for CLI task (e.g. gpt-4 or provider/modelId)."].join(`
152
+ `),_i=()=>{if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=Ai(import.meta.url),t=$o.dirname(e),n=$o.join(t,"..","package.json"),o=$i.readFileSync(n,"utf8"),r=JSON.parse(o);if(r.version)return r.version}catch{}return"dev"};Mi&&(console.log(Pi),process.exit(0));ki&&(console.log(_i()),process.exit(0));async function Ci(){let e=Si.createInterface({input:process.stdin,output:process.stdout});try{return(await e.question("Enter TELEGRAM_BOT_TOKEN: ")).trim()}finally{e.close()}}function Ri(){for(let e=0;e<me.length;e+=1){let t=me[e];if(t==="-c"||t==="--cli"){let n=me[e+1];return n!==void 0&&!n.startsWith("-")?n:null}if(t.startsWith("--cli="))return t.slice(6);if(t.startsWith("-c="))return t.slice(3)}return null}function Mo(e,t=!0){for(let n=0;n<me.length;n+=1){let o=me[n];if(e.includes(o)){let r=me[n+1];return r!==void 0&&!r.startsWith("-")&&r.trim()||null}if(t&&o.startsWith("--")){for(let r of e)if(r.startsWith("--")&&o.startsWith(r+"="))return o.slice(r.length+1).trim()||null}}return null}function Ti(){return Mo(["--provider","-p"])??null}function Ei(){return Mo(["--model","-m"])??null}async function Di(e=!1){let{configPath:t,data:n,exists:o}=Me(),r=Zt(),i=o?n:r,c=en(i,r);if(tn(i)){c&&await Ue(t,i);return}if(e){c&&await Ue(t,i);return}process.stdin.isTTY||(console.error(`Missing telegram.bot_token in ${t}.`),process.exit(1));let l=await Ci();l||(console.error("Empty TELEGRAM_BOT_TOKEN."),process.exit(1)),nn(i,l),await Ue(t,i),console.log(`Saved config to ${t}.`)}var zt="[TG-AGENT-CLI-DONE]",Oi=`This is a one-shot CLI task. Do not reply to the user until the entire task is complete.
127
153
  When you have fully completed the task, end your final reply with exactly the following line (and nothing after it):
128
- ${Et}`,ro=1800*1e3,li=6e4,ui=1440*60*1e3;function di(){let e=process.env.TG_AGENT_CLI_TIMEOUT_MS;if(!e?.trim())return ro;let t=Number.parseInt(e.trim(),10);return Number.isFinite(t)?Math.min(ui,Math.max(li,t)):ro}function mi(e){let t=e.trim(),n=Et.trim();if(t.endsWith(n))return{stripped:t.slice(0,t.length-n.length).trimEnd(),found:!0};if((t.split(/\r?\n/).pop()?.trim()??"")===n){let r=t.split(/\r?\n/);return r.pop(),{stripped:r.join(`
129
- `).trimEnd(),found:!0}}return{stripped:e,found:!1}}function gi(e,t){if(!e?.trim())return{};let n=e.trim();if(n.includes("/")){let[o,r]=n.split("/",2);if(o?.trim()&&r?.trim())return{modelProvider:o.trim(),modelId:r.trim()}}return{modelProvider:t?.trim()||void 0,modelId:n}}async function pi(e){let t=di(),n=[g.systemPrompt,ci].join(`
154
+ ${zt}`,So=1800*1e3,Ni=6e4,ji=1440*60*1e3;function Li(){let e=process.env.TG_AGENT_CLI_TIMEOUT_MS;if(!e?.trim())return So;let t=Number.parseInt(e.trim(),10);return Number.isFinite(t)?Math.min(ji,Math.max(Ni,t)):So}function Ui(e){let t=e.trim(),n=zt.trim();if(t.endsWith(n))return{stripped:t.slice(0,t.length-n.length).trimEnd(),found:!0};if((t.split(/\r?\n/).pop()?.trim()??"")===n){let r=t.split(/\r?\n/);return r.pop(),{stripped:r.join(`
155
+ `).trimEnd(),found:!0}}return{stripped:e,found:!1}}function Ii(e,t){if(!e?.trim())return{};let n=e.trim();if(n.includes("/")){let[o,r]=n.split("/",2);if(o?.trim()&&r?.trim())return{modelProvider:o.trim(),modelId:r.trim()}}return{modelProvider:t?.trim()||void 0,modelId:n}}async function Fi(e){let t=Li(),n=[f.systemPrompt,Oi].join(`
130
156
 
131
- `),{modelProvider:o,modelId:r}=gi(ii(),si());try{await le(g.agentDir,{timeoutMs:3e3,maxBytes:g.fetchMaxBytes,maxChars:2e3}),$e()}catch(d){let p=d instanceof Error?d.message:String(d);console.warn(`[tg-agent] mcp catalog warmup failed: ${p}`)}let s=g.audit.enabled?{chatId:"cli",requestConfirmation:async(d,p)=>process.env.TG_AGENT_AUTO_APPROVE==="1",sendNotification:async d=>{console.error(`[tg-agent] ${d}`)}}:void 0,l=()=>{},a=He({chatId:"cli",sessionId:ee(),prompt:e,systemPrompt:n,workspaceDir:g.workspaceDir,telegram:void 0,auditContext:s,modelProvider:o||void 0,modelId:r||void 0,onAbortReady:d=>{l=d}}),u=new Promise((d,p)=>{setTimeout(()=>{l(),p(new Error(`CLI timeout (${Math.round(t/6e4)} minutes)`))},t)}),m;try{m=await Promise.race([a,u])}catch(d){let p=d instanceof Error?d.message:String(d);return console.error(`[tg-agent] ${p}`),1}let{stripped:i,found:c}=mi(m.text);return i.length>0&&console.log(i),c?0:(console.error(`[tg-agent] Task did not end with ${Et} (incomplete).`),1)}async function fi(){let{data:e}=Se(),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)}var Tt=ri();await ai(Tt!==null);await fi();Vt();if(Tt!==null){je();let e=await pi(Tt);process.exit(e)}Promise.resolve().then(()=>no());
157
+ `),{modelProvider:o,modelId:r}=Ii(Ei(),Ti());try{await pe(f.agentDir,{timeoutMs:3e3,maxBytes:f.fetchMaxBytes,maxChars:2e3}),Pe()}catch(d){let p=d instanceof Error?d.message:String(d);console.warn(`[tg-agent] mcp catalog warmup failed: ${p}`)}let i=f.audit.enabled?{chatId:"cli",requestConfirmation:async(d,p)=>process.env.TG_AGENT_AUTO_APPROVE==="1",sendNotification:async d=>{console.error(`[tg-agent] ${d}`)}}:void 0,c=()=>{},u=Ge({chatId:"cli",sessionId:ne(),prompt:e,systemPrompt:n,workspaceDir:f.workspaceDir,telegram:void 0,auditContext:i,modelProvider:o||void 0,modelId:r||void 0,onAbortReady:d=>{c=d}}),l=new Promise((d,p)=>{setTimeout(()=>{c(),p(new Error(`CLI timeout (${Math.round(t/6e4)} minutes)`))},t)}),m;try{m=await Promise.race([u,l])}catch(d){let p=d instanceof Error?d.message:String(d);return console.error(`[tg-agent] ${p}`),1}let{stripped:s,found:a}=Ui(m.text);return s.length>0&&console.log(s),a?0:(console.error(`[tg-agent] Task did not end with ${zt} (incomplete).`),1)}async function zi(){let{data:e}=Me(),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)}var Ft=Ri();await Di(Ft!==null);await zi();rn();if(Ft!==null){Ie();let e=await Fi(Ft);process.exit(e)}Promise.resolve().then(()=>xo());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tg-agent",
3
- "version": "1.8.9",
3
+ "version": "1.9.0",
4
4
  "description": "Telegram Agent Bot",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,8 +22,8 @@
22
22
  "dependencies": {
23
23
  "@iarna/toml": "^2.2.5",
24
24
  "@lancedb/lancedb": "^0.22.3",
25
- "@mariozechner/pi-ai": "^0.52.8",
26
- "@mariozechner/pi-coding-agent": "^0.52.8",
25
+ "@mariozechner/pi-ai": "^0.52.9",
26
+ "@mariozechner/pi-coding-agent": "^0.52.9",
27
27
  "@sinclair/typebox": "^0.32.35",
28
28
  "https-proxy-agent": "^7.0.5",
29
29
  "node-telegram-bot-api": "^0.64.0",