agent-afk 4.33.0 → 4.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +401 -400
- package/dist/index.mjs +1 -1
- package/dist/telegram.mjs +2 -2
- package/package.json +1 -1
package/dist/telegram.mjs
CHANGED
|
@@ -1050,7 +1050,7 @@ Note: this search ran in basic-regex (BRE) mode, where '|' is a literal pipe \u2
|
|
|
1050
1050
|
`)}}catch(i){if(i instanceof Error){let a=i;return a.code==="ENOENT"?{content:`Directory not found: ${s}`,isError:!0}:a.code==="ENOTDIR"?{content:`Not a directory: ${s}`,isError:!0}:a.code==="EACCES"?{content:`Permission denied: ${s}`,isError:!0}:{content:`Error listing directory: ${i.message}`,isError:!0}}return{content:"Unknown error listing directory",isError:!0}}}});function Mo(t,e=()=>{}){let n=new Set;if(!t)return n;for(let r of t.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){e("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}function np(t,e=()=>{}){return async(n,r)=>{let o=n.chat?.id;if(o===void 0||!t.has(o)){e("[allowlist] Rejecting update from chat:",o??"<unknown>");return}await r()}}var Oo=y(()=>{"use strict"});var fa=y(()=>{"use strict";$();B()});var rp=y(()=>{"use strict";$();fa()});import{execFile as M_}from"node:child_process";import{promisify as O_}from"node:util";function sp(t,e){if(t.length>op)throw new Error(`Invalid branch prefix from ${e}: length ${t.length} exceeds ${op}.`);if(!D_.test(t))throw new Error(`Invalid branch prefix from ${e}: '${t}' \u2014 only [A-Za-z0-9_-./] are allowed.`);if(t.startsWith("-"))throw new Error(`Invalid branch prefix from ${e}: '${t}' \u2014 must not start with '-' (would be parsed by git as a flag).`);return t}function ip(t,e){if(t.trim().length===0)throw new Error(`Invalid worktree base ref from ${e}: '' \u2014 base ref cannot be empty.`);if(t.startsWith("-"))throw new Error(`Invalid worktree base ref from ${e}: '${t}' \u2014 must not start with '-' (would be parsed by git as a flag).`);if(t.includes("\0"))throw new Error(`Invalid worktree base ref from ${e}: contains a NUL byte.`);if(/\s/.test(t))throw new Error(`Invalid worktree base ref from ${e}: '${t}' \u2014 must not contain whitespace.`)}var JL,D_,op,ap=y(()=>{"use strict";$();fa();rp();JL=O_(M_),D_=/^[A-Za-z0-9_\-./]*$/,op=64});import{existsSync as Do,readdirSync as QL,readFileSync as F_,realpathSync as ZL,statSync as eN}from"fs";import{homedir as L_}from"os";import{join as ut}from"path";function ga(t){if(t===null||typeof t!="object"||Array.isArray(t))return;let e={};for(let n of cp){let r=t[n];if(r!==void 0){if(r===!0){e[n]={plugins:!0,skills:!0,mcp:!0};continue}if(r!==!1&&typeof r=="object"&&r!==null&&!Array.isArray(r)){let o=r;e[n]={plugins:o.plugins===!0,skills:o.skills===!0,mcp:o.mcp===!0}}}}return Object.keys(e).length>0?e:void 0}function N_(){return[et(),Cr()]}function Un(t=N_()){for(let e of t)if(Do(e))try{let n=JSON.parse(F_(e,"utf-8")),r=ga(n.importFrom);if(r!==void 0)return r}catch{}}function Bn(t,e=L_()){let n={pluginRoots:[],skillRoots:[],mcpConfigs:[]};if(!t)return n;for(let r of cp){let o=t[r];if(!o)continue;let s=ma[r];if(o.plugins)for(let i of s.pluginRoots(e))Do(i)&&n.pluginRoots.push(i);if(o.skills){let i=`imported:${r}`;for(let a of s.skillRoots(e))Do(a)&&n.skillRoots.push({dir:a,origin:i})}if(o.mcp){let i=$_(s.mcpConfigCandidates(e));i&&n.mcpConfigs.push({source:i,format:s.mcpFormat})}}return n}function $_(t){for(let e of t)if(Do(e))return e;return null}var cp,ma,oN,Fo=y(()=>{"use strict";B();cp=["claude-code","codex"],ma={"claude-code":{label:"Claude Code",pluginRoots:t=>[ut(t,".claude","plugins")],skillRoots:t=>[ut(t,".claude","skills")],mcpConfigCandidates:t=>[ut(t,".claude","mcp.json"),ut(t,".claude",".mcp.json"),ut(t,".claude","claude-code","mcp.json")],mcpFormat:"json"},codex:{label:"Codex",pluginRoots:t=>[ut(t,".codex","plugins")],skillRoots:t=>[ut(t,".codex","skills")],mcpConfigCandidates:t=>[ut(t,".codex","config.toml")],mcpFormat:"toml"}},oN={"claude-code":ma["claude-code"].label,codex:ma.codex.label}});import{readFileSync as up,existsSync as ya}from"fs";import{join as jn}from"path";import{config as U_}from"dotenv";function ba(){return ji()}function H_(t){let e=t.trim();if(!e)return e;let n="/chat/completions";if(e.endsWith(n)){let r=e.slice(0,-n.length);return dp.has(e)||(dp.add(e),console.warn(`[afk] AFK_OPENAI_BASE_URL: stripped trailing "/chat/completions" \u2014 the OpenAI SDK appends it automatically.
|
|
1051
1051
|
Effective base URL: ${r}`)),r}return e}function j_(){if(ha!==void 0)return ha;if(!lp){let o=[jn(process.cwd(),".env"),yt(),$l()];for(let s of o)ya(s)&&U_({path:s,override:!1});lp=!0}let t={},e=k.AFK_MODEL??k.CLAUDE_MODEL;if(e){let o=e.toLowerCase();t.model=Ci(o)?o:e}if(G(e)==="anthropic-direct"){let o=ba();o!==void 0&&(t.apiKey=o)}let r=k.AFK_LOCAL_BASE_URL;if(r&&r.length>0&&(t.baseUrl=r,t.apiKey=k.AFK_LOCAL_API_KEY||"local"),k.AFK_MAX_TOKENS&&(t.maxTokens=parseInt(k.AFK_MAX_TOKENS,10)),k.AFK_TEMPERATURE&&(t.temperature=parseFloat(k.AFK_TEMPERATURE)),k.AFK_SYSTEM_PROMPT&&(t.systemPrompt=k.AFK_SYSTEM_PROMPT),k.AFK_AUTO_ROUTING){let o=k.AFK_AUTO_ROUTING.toLowerCase()==="true";t.autoRouting={interactive:o,chat:o,telegram:o,daemon:o}}return k.AFK_OPENAI_BASE_URL&&(t.openaiBaseUrl=H_(k.AFK_OPENAI_BASE_URL)),ha=t,t}function pp(){if(rn!==void 0)return rn;let t=[jn(process.cwd(),"afk.config.json"),et(),Cr()];for(let e of t)if(ya(e))try{let n=up(e,"utf-8"),r=JSON.parse(n),o={},s=xd(r.models);if(typeof r.model=="string"&&r.model.length>0){let i=r.model.toLowerCase();o.model=Ci(i)?i:r.model}if(typeof r.maxTokens=="number"&&(o.maxTokens=r.maxTokens),typeof r.temperature=="number"&&(o.temperature=r.temperature),r.systemPrompt&&(o.systemPrompt=r.systemPrompt),typeof r.permissionMode=="string"){let i=r.permissionMode;(i==="default"||i==="plan"||i==="autonomous"||i==="bypassPermissions")&&(o.permissionMode=i)}if(r.autoRouting&&typeof r.autoRouting=="object"){let i={};typeof r.autoRouting.interactive=="boolean"&&(i.interactive=r.autoRouting.interactive),typeof r.autoRouting.chat=="boolean"&&(i.chat=r.autoRouting.chat),typeof r.autoRouting.telegram=="boolean"&&(i.telegram=r.autoRouting.telegram),typeof r.autoRouting.daemon=="boolean"&&(i.daemon=r.autoRouting.daemon),o.autoRouting=i}if(r.daemon&&typeof r.daemon=="object"){let i={};typeof r.daemon.task=="string"&&(i.task=r.daemon.task),typeof r.daemon.taskId=="string"&&(i.taskId=r.daemon.taskId);let a=r.daemon.worktreePrune;a&&typeof a=="object"&&(i.worktreePrune={enabled:typeof a.enabled=="boolean"?a.enabled:!0,cron:typeof a.cron=="string"?a.cron:"0 4 * * *",maxAgeDaysClean:typeof a.maxAgeDaysClean=="number"?a.maxAgeDaysClean:14,maxAgeDaysDirty:typeof a.maxAgeDaysDirty=="number"?a.maxAgeDaysDirty:30,scope:typeof a.scope=="string"?a.scope:"all"}),o.daemon=i}if(r.telegram&&typeof r.telegram=="object"){let i={},a=r.telegram.notify;if(a&&typeof a=="object"){let c={};if((a.mode==="primary"||a.mode==="broadcast"||a.mode==="custom")&&(c.mode=a.mode),typeof a.primaryChatId=="number"&&Number.isFinite(a.primaryChatId)&&(c.primaryChatId=a.primaryChatId),Array.isArray(a.targets)){let l=a.targets.filter(d=>typeof d=="number"&&Number.isFinite(d));l.length>0&&(c.targets=l)}i.notify=c}typeof r.telegram.verifyDone=="boolean"&&(i.verifyDone=r.telegram.verifyDone),o.telegram=i}if(r.updatePolicy&&["notify","auto","off"].includes(r.updatePolicy)&&(o.updatePolicy=r.updatePolicy),typeof r.autoResumeOnUsageLimit=="boolean"&&(o.autoResumeOnUsageLimit=r.autoResumeOnUsageLimit),typeof r.bgSummaries=="boolean"&&(o.bgSummaries=r.bgSummaries),typeof r.maxSummaryCallsPerSession=="number"&&(o.maxSummaryCallsPerSession=Math.min(500,Math.max(1,r.maxSummaryCallsPerSession))),r.hooks!==null&&typeof r.hooks=="object"&&!Array.isArray(r.hooks)&&(o.hooks=r.hooks),typeof r.enableShellHooks=="boolean"&&(o.enableShellHooks=r.enableShellHooks),e!==jn(process.cwd(),"afk.config.json")){let i=ga(r.importFrom);i!==void 0&&(o.importFrom=i)}if(r.interactive&&typeof r.interactive=="object"){let i={};typeof r.interactive.worktreeAutoname=="boolean"&&(i.worktreeAutoname=r.interactive.worktreeAutoname),typeof r.interactive.worktreeBranchPrefix=="string"&&(i.worktreeBranchPrefix=sp(r.interactive.worktreeBranchPrefix,`${e}#/interactive/worktreeBranchPrefix`)),typeof r.interactive.worktreeBase=="string"&&r.interactive.worktreeBase.trim().length>0&&(ip(r.interactive.worktreeBase,`${e}#/interactive/worktreeBase`),i.worktreeBase=r.interactive.worktreeBase),typeof r.interactive.suggestGhost=="boolean"&&(i.suggestGhost=r.interactive.suggestGhost),Object.keys(i).length>0&&(o.interactive=i)}return rn={config:o,sourcePath:e,modelsPartial:s},rn}catch(n){console.error(`Warning: Failed to parse ${e}:`,n)}return rn={config:{},sourcePath:void 0,modelsPartial:{}},rn}function K_(){if(on!==void 0)return on.value;let t=[jn(process.cwd(),"AFK.md"),jn(se(),"AFK.md")];for(let e of t)if(ya(e))try{let n=up(e,"utf-8").trim();if(n.length>0)return on={value:{content:n,path:e}},on.value}catch{}return on={value:null},on.value}function fp(){return pp().config.telegram??{}}function wa(t){let e=j_(),{config:n,sourcePath:r,modelsPartial:o}=pp(),s={...Hn,...e,...n,...t},i;if(e.systemPrompt!==void 0)i="env:AFK_SYSTEM_PROMPT";else if(n.systemPrompt!==void 0&&r!==void 0)i=`file:${r}`;else if(s.systemPrompt===void 0){let l=K_();l!==null&&(s.systemPrompt=l.content,i=`afk-md:${l.path}`)}let a={model:s.model??Hn.model,maxTokens:s.maxTokens??Hn.maxTokens,temperature:s.temperature??Hn.temperature,updatePolicy:s.updatePolicy??Hn.updatePolicy,...s.apiKey!==void 0?{apiKey:s.apiKey}:{},...s.baseUrl!==void 0?{baseUrl:s.baseUrl}:{},...s.openaiBaseUrl!==void 0?{openaiBaseUrl:s.openaiBaseUrl}:{},...s.systemPrompt!==void 0?{systemPrompt:s.systemPrompt}:{},...i!==void 0?{systemPromptSource:i}:{},permissionMode:s.permissionMode??B_,...s.autoRouting!==void 0?{autoRouting:s.autoRouting}:{},...s.daemon!==void 0?{daemon:s.daemon}:{},...s.telegram!==void 0?{telegram:s.telegram}:{},...s.bgSummaries!==void 0?{bgSummaries:s.bgSummaries}:{},...s.maxSummaryCallsPerSession!==void 0?{maxSummaryCallsPerSession:s.maxSummaryCallsPerSession}:{},...s.interactive!==void 0?{interactive:s.interactive}:{},...s.hooks!==void 0?{hooks:s.hooks}:{},...s.enableShellHooks!==void 0?{enableShellHooks:s.enableShellHooks}:{},...s.importFrom!==void 0?{importFrom:s.importFrom}:{}},c=t?.models??Ri(o);if(to(c),a.models=c,typeof a.model=="string"&&a.model.toLowerCase().startsWith("local-")&&(a.baseUrl===void 0||a.baseUrl.length===0))throw new Error(`Model '${a.model}' requires AFK_LOCAL_BASE_URL to be set (e.g. AFK_LOCAL_BASE_URL=http://127.0.0.1:8080). Point it at your local Anthropic-Messages-compatible server.`);return a}var Hn,B_,lp,ha,dp,rn,on,Lo=y(()=>{"use strict";Re();je();ge();B();Jt();ap();$();Fo();Hn={model:"sonnet",maxTokens:4096,temperature:1,updatePolicy:"notify"},B_="bypassPermissions",lp=!1;dp=new Set});function W_(t,e){return e!==void 0&&Number.isFinite(e)&&e!==0?e:t.find(r=>r>0)??t[0]}function G_(t,e={}){let n=[...t],r=e.mode??"primary";if(r==="broadcast")return n;if(r==="custom"){let s=(e.targets??[]).filter(i=>typeof i=="number"&&Number.isFinite(i)&&i!==0);if(s.length>0)return[...new Set(s)]}let o=W_(n,e.primaryChatId);return o!==void 0?[o]:[]}function q_(t){if(!t)return;let e=t.trim();if(!/^-?\d+$/.test(e))return;let n=Number(e);return Number.isFinite(n)&&n!==0?n:void 0}function V_(t){if(!t)return;let e=t.trim().toLowerCase();return e==="primary"||e==="broadcast"||e==="custom"?e:void 0}function z_(){let t=fp().notify??{},e=t.mode??V_(k.AFK_TELEGRAM_NOTIFY_MODE),n=t.primaryChatId??q_(k.AFK_TELEGRAM_PRIMARY_CHAT_ID);return{...e!==void 0?{mode:e}:{},...n!==void 0?{primaryChatId:n}:{},...t.targets!==void 0?{targets:t.targets}:{}}}function No(){let t=Mo(k.AFK_TELEGRAM_ALLOWED_CHAT_IDS);return G_(t,z_())}var Sa=y(()=>{"use strict";Oo();Lo();$()});var mp={};si(mp,{push:()=>$o,pushIfConfigured:()=>Y_});async function $o(t){if(!t.token)throw new Error("push: token is required");if(t.chatId===""||t.chatId==null||t.chatId===0)throw new Error("push: chatId is required");let e=t.fetchImpl??fetch,r=`${t.apiBase??J_}/bot${t.token}/sendMessage`,o={chat_id:t.chatId,text:t.text.slice(0,4096)};t.parseMode&&(o.parse_mode=t.parseMode),t.replyMarkup&&(o.reply_markup=t.replyMarkup);let s=new AbortController,i=setTimeout(()=>s.abort(),1e4);try{let a=await e(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),signal:s.signal});if(a.ok)return{ok:!0,status:a.status};let c;try{c=(await a.json()).description}catch{c=`HTTP ${a.status}`}return{ok:!1,status:a.status,...c!==void 0?{errorMessage:c}:{}}}catch(a){return{ok:!1,status:0,errorMessage:a instanceof Error?a.message:String(a)}}finally{clearTimeout(i)}}async function Y_(t,e={}){let n=k.TELEGRAM_BOT_TOKEN;if(!n)return null;let r=No();if(r.length===0)return null;let o=Se(t),s=[];for(let i of r)for(let a=0;a<o.length;a++)s.push(await $o({token:n,chatId:i,text:o[a]??"",...e.parseMode!==void 0?{parseMode:e.parseMode}:{},...e.replyMarkup!==void 0&&a===0?{replyMarkup:e.replyMarkup}:{},...e.fetchImpl!==void 0?{fetchImpl:e.fetchImpl}:{}}));return s}var J_,va=y(()=>{"use strict";Sa();Te();$();J_="https://api.telegram.org"});function X_(t=$o){return async(e,n)=>{if(!e||typeof e!="object")return{content:"Invalid input: expected an object",isError:!0};let o=e.message;if(typeof o!="string")return{content:"Invalid input: message must be a string",isError:!0};if(o.length===0)return{content:"Invalid input: message must be non-empty",isError:!0};if(o.length>gp)return{content:`Invalid input: message exceeds Telegram's ${gp}-character limit (got ${o.length}). Split into multiple sends or trim before calling.`,isError:!0};let s=k.TELEGRAM_BOT_TOKEN;if(!s)return{content:"Telegram is not configured: TELEGRAM_BOT_TOKEN is not set. Run the bot setup wizard or export the env var before using send_telegram.",isError:!0};let i=No();if(i.length===0)return{content:"Telegram is not configured: AFK_TELEGRAM_ALLOWED_CHAT_IDS is empty or unset. Add the operator chat ID(s) before using send_telegram.",isError:!0};let a=[];for(let c of i){let l=await t({token:s,chatId:c,text:o});l.ok||a.push(`chat ${c}: ${l.errorMessage??`HTTP ${l.status}`}`)}return a.length===i.length?{content:`Failed to send Telegram message to any chat. ${a.join("; ")}`,isError:!0}:a.length>0?{content:`Sent Telegram message to ${i.length-a.length}/${i.length} chat(s); ${a.length} failed: ${a.join("; ")}`}:{content:i.length===1?`Sent Telegram message to chat ${i[0]}.`:`Sent Telegram message to ${i.length} chats.`}}}var gp,hp,yp=y(()=>{"use strict";$();va();Sa();gp=4096;hp=X_()});import{JSDOM as Q_}from"jsdom";import{Readability as Z_}from"@mozilla/readability";import eE from"turndown";function bp(t){return t.replace(/\n{3,}/g,`
|
|
1052
1052
|
|
|
1053
|
-
`).trim()}function tE(t){return(t?.textContent??"").replace(/\s+/g," ").trim().length}function Sp(t,e){let r=new Q_(t,{url:e}).window.document,o=(r.title??"").trim(),s=null;try{let l=r.cloneNode(!0);s=new Z_(l).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let l=bp(ka.turndown(s.content)),d=(s.title??"").trim()||o,u=typeof s.length=="number"&&s.length>0?s.length:(s.textContent??"").replace(/\s+/g," ").trim().length;return{title:d,markdown:l,textLength:u,usedFallback:!1}}let i=r.body,a=i?.innerHTML??"",c=bp(ka.turndown(a));return{title:o,markdown:c,textLength:tE(i),usedFallback:!0}}var wp,ka,vp=y(()=>{"use strict";wp=200,ka=new eE({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});ka.remove(["script","style","noscript","iframe"])});import{readFileSync as nE}from"node:fs";import{join as rE}from"path";function oE(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function kp(t,e){return oE(e).test(t)}function aE(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(sE.has(e))return!0;if(iE.has(e))return!1}return!1}function _p(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function cE(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function lE(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function dE(t){try{return nE(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function uE(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function Ep(t){let e=t?.env??k,n=t?.readFileSync??dE,r=t?.surface??e.AGENT_SURFACE,o=aE(e.AFK_BROWSER_HEADLESS,r),s=_p(e.AFK_BROWSER_ALLOWED_DOMAINS),i=_p(e.AFK_BROWSER_BLOCKED_DOMAINS),a=lE(e.AFK_BROWSER_DOM_SNAPSHOTS),c=cE(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():rE(Ue(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(g){throw new Error(`Failed to parse browser config at ${u}: ${String(g)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let h=uE(l,f);return h.configPath=u,h}function _a(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(kp(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>kp(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var sE,iE,Ea=y(()=>{"use strict";$();B();sE=new Set(["daemon","subagent","telegram","afk"]),iE=new Set(["repl","interactive","cli"])});import pE from"node:fs";import fE from"node:path";import{chromium as mE}from"playwright";function gE(){try{return"4.33.0"}catch{}try{let t=fE.resolve(import.meta.dirname,"../../../package.json"),e=pE.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var hE,Uo,Ap=y(()=>{"use strict";hE=gE(),Uo=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=mE.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${hE}`}}}});import{createHash as yE}from"crypto";function Aa(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of bE)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function Tp(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&wE.test(t.label))}function xp(t){return yE("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Rp(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var bE,wE,Kn=y(()=>{"use strict";bE=[{name:"aws-access-key",regex:/AKIA[0-9A-Z]{16}/g},{name:"github-pat",regex:/ghp_[a-zA-Z0-9]{36}/g},{name:"openai-bearer",regex:/sk-[a-zA-Z0-9_-]{20,}/g},{name:"slack-token",regex:/xox[abp]-[a-zA-Z0-9-]{10,}/g},{name:"jwt",regex:/eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/g},{name:"form-password",regex:/password=[^&\s]+/gi}];wE=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as SE}from"node:crypto";function vE(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function kE(t,e,n){return`el_${SE("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function _E(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Pp(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Cp(t,e){let n=t.role??"",r=t.name??"";Ip.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Cp(s,e)}async function EE(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},Mp).catch(()=>[])}async function AE(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let g=s.type;g==="checkbox"?l="checkbox":g==="radio"?l="radio":g==="button"||g==="submit"||g==="reset"?l="button":g==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,h={role:l,name:c,disabled:p};u!==void 0&&(h.value=u),f!==void 0&&(h.checked=f),o.push(h)}return o},Mp).catch(()=>[])}function TE(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Bo(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=TE(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=EE(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,h,g]=await Promise.all([i,a,c,l,d]),S,b=!1;u!==null?(S=[],Cp(u,S)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,S=(await AE(t)).filter(R=>Ip.has(R.role??"")));let _=new Map;for(let T of p){let R=Pp(T.name),P=_.get(R);(!P||P.bbox.w===0&&T.bbox.w>0)&&_.set(R,T)}let w=S.map(T=>({ax:T,dom:_.get(Pp(T.name??""))})),v=r?w:w.filter(T=>T.dom?T.dom.bbox.w>0||T.dom.bbox.h>0:!0);v.sort((T,R)=>{let P=T.dom?.bbox.y??0,M=R.dom?.bbox.y??0;if(P!==M)return P-M;let D=T.dom?.bbox.x??0,O=R.dom?.bbox.x??0;return D-O}),v.length>200&&o.push("page has 200+ interactive elements; consider scoping");let A=v.slice(0,n).map((T,R)=>{let P=T.ax.role??"generic",M=T.ax.name??"",D=kE(P,M,R),O=T.dom?.bbox??{x:0,y:0,w:0,h:0},L=T.dom?.type??null,H=null;T.ax.value!==void 0&&T.ax.value!==null&&(H=String(T.ax.value)),T.ax.checked!==void 0&&(H=String(T.ax.checked)),Tp({role:P,kind:L})&&(H="[redacted]");let q={disabled:T.ax.disabled??!1};T.ax.checked!==void 0&&(q.checked=T.ax.checked===!0||T.ax.checked==="mixed"),T.ax.selected!==void 0&&(q.selected=T.ax.selected),T.ax.expanded!==void 0&&(q.expanded=T.ax.expanded);let z;T.dom?.testId?z=`[data-testid="${T.dom.testId}"]`:T.dom?.id&&(z=`#${T.dom.id}`);let Y={id:D,role:P,label:vE(M),kind:L,value:H,state:q,bbox:O};return z!==void 0&&(Y.selector=z),Y}),E="idle";try{let T=await t.evaluate(()=>document.readyState);T==="loading"?E="loading":T==="interactive"?E="navigating":E="idle"}catch{E="navigating"}E!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),b&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let I=_E(f),C=`obs_${e.observationCounter.toString(36)}`,F=new Date().toISOString();return{observationId:C,url:h,title:g,textSummary:I,interactive:A,status:{httpStatus:e.httpStatus??null,loadingState:E,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:F}}var Ip,Mp,Op=y(()=>{"use strict";Kn();Ip=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Mp="a[href], button, input, select, textarea, [role], [tabindex], label"});async function Dp(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function Ta(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>Dp(t,s)))).filter(o=>o!==null)}async function xE(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function xa(t,e,n){switch(e.kind){case"element_id":return RE(t,e,n);case"selector":return PE(t,e);case"semantic":return IE(t,e)}}async function RE(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await Ta(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function PE(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await Ta(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function IE(t,e){return e.role!==void 0?CE(t,e.text,e.role):ME(t,e.text,e)}async function CE(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await Ta(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function ME(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await xE(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let g=u[0];return g===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:g.locator.nth(g.index)}}let p=u.slice(0,5),f=[];for(let g=0;g<p.length;g++){let S=p[g];if(S===void 0)continue;let b=await Dp(S.locator,S.index);if(b!==null){let _=`${b.role}:${b.label}:${g}`,w=0;for(let v=0;v<_.length;v++)w=w*31+_.charCodeAt(v)>>>0;f.push({...b,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var Fp=y(()=>{"use strict"});import{randomBytes as OE}from"crypto";import{mkdir as DE,stat as FE,writeFile as LE}from"fs/promises";import{join as Ra}from"path";import{gzip as NE}from"zlib";import{promisify as $E}from"util";function UE(t){return Ra(Ir(t),"browser")}function BE(t){return Ra(UE(t),"screenshots")}function HE(){return new Date().toISOString().replace(/[:.]/g,"-")}function jE(){return OE(3).toString("hex")}async function Pa(t,e,n){if(e.length>Lp)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Lp} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=BE(t);await DE(r,{recursive:!0});let o=`${HE()}-${jE()}-${n}.png`,s=Ra(r,o);await LE(s,e);let{size:i}=await FE(s);return{path:s,bytes:i}}var n$,Lp,Np=y(()=>{"use strict";B();Kn();n$=$E(NE);Lp=5*1024*1024});var Up={};si(Up,{PlaywrightProvider:()=>Ia});function $p(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var Ia,Bp=y(()=>{"use strict";Ap();Op();Fp();Ea();Kn();Np();Ia=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Uo(e)}async open(e){let n=_a(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await Bo(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Bo(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await xa(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${$p(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let g=Aa(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(S){l=S}else l=g}let u=r.url();if(u!==s){let g=_a(u,this.config);if(!g.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:g.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Bo(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),h=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,h),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await xa(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${$p(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await Pa(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await Pa(n,o,r);return s}catch{return null}}}});var Ot={};si(Ot,{__resetBrowserRegistryForTests:()=>VE,browserProviderActive:()=>GE,closeBrowserProvider:()=>Ca,getBrowserProvider:()=>WE,peekBrowserProvider:()=>qE});function Hp(){Promise.resolve(Ca()).then(()=>{process.exit(130)})}function jp(){Promise.resolve(Ca()).then(()=>{process.exit(143)})}function Kp(){Oe=null}function KE(){Ho||(process.on("SIGINT",Hp),process.on("SIGTERM",jp),process.on("exit",Kp),Ho=!0)}function Wp(){Ho&&(process.removeListener("SIGINT",Hp),process.removeListener("SIGTERM",jp),process.removeListener("exit",Kp),Ho=!1)}async function WE(t){return Oe!==null?Oe:(Mt!==null||(Mt=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(Bp(),Up)),n=Ep(t),r=new e(n);return KE(),Oe=r,Mt=null,r})()),Mt)}async function Ca(){if(Oe===null)return;let t=Oe;Oe=null,Mt=null,Wp(),await t.shutdown()}function GE(){return Oe!==null}function qE(){return Oe}function VE(){Oe=null,Mt=null,Wp()}var Oe,Mt,Ho,Dt=y(()=>{"use strict";Ea();Oe=null,Mt=null,Ho=!1});function Gp(t,e){try{return Sp(t,e)}catch(n){return N("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function QE(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Dt(),Ot));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal})}async function qp(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??QE,o=null,s=t,i=null,a=null;try{let l=await n(t,{headers:XE,redirect:"follow",signal:e.signal});i=l.status,s=l.url||t;let d=l.headers.get("content-type")??"";if(l.ok){if(YE.test(d))throw new Error(`web_scrape markdown mode received binary content (${d.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let u=await l.text();if(JE.test(d)&&!zE.test(d))return{title:"",markdown:u.trim(),finalUrl:s,usedRender:!1};o=Gp(u,s)}}catch(l){if(e.signal.aborted||l instanceof Error&&l.message.startsWith("web_scrape markdown mode received binary"))throw l;a=l}if(!(o===null||o.textLength<wp)&&o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};try{let l=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal}),d=Gp(l.html,l.finalUrl);if(o===null||d.textLength>=o.textLength)return{title:d.title,markdown:d.markdown,finalUrl:l.finalUrl,usedRender:!0}}catch(l){if(e.signal.aborted)throw l;if(o===null){let d=l instanceof Error?l.message:String(l),u=a instanceof Error?a.message:`HTTP ${i??"error"}`,p=new Error(`web_scrape could not retrieve ${t}: fetch failed (${u}) and render failed (${d}).`);throw p.cause=l,p}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${i??"error"}).`)}var zE,JE,YE,XE,Vp=y(()=>{"use strict";vp();le();zE=/(text\/html|application\/xhtml\+xml)/i,JE=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,YE=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,XE={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/web_scrape",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}});function tA(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(ZE,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":t.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),eA),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=yo(d);u&&(c=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let l=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${l}${c}`)}let i;try{i=await s.json()}catch(c){throw new Error(`Exa Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(i.results??[]).slice(0,r).map(c=>({title:(c.title??"").trim()||"(untitled)",url:c.url??"",description:(c.highlights?.[0]??"").trim()})).filter(c=>c.url.length>0)}}}function zp(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?tA({apiKey:t.exaApiKey,fetchFn:t.fetchFn}):{error:'web_scrape search mode requires a search backend. Set EXA_API_KEY (free tier at https://exa.ai) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function Jp(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
1053
|
+
`).trim()}function tE(t){return(t?.textContent??"").replace(/\s+/g," ").trim().length}function Sp(t,e){let r=new Q_(t,{url:e}).window.document,o=(r.title??"").trim(),s=null;try{let l=r.cloneNode(!0);s=new Z_(l).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let l=bp(ka.turndown(s.content)),d=(s.title??"").trim()||o,u=typeof s.length=="number"&&s.length>0?s.length:(s.textContent??"").replace(/\s+/g," ").trim().length;return{title:d,markdown:l,textLength:u,usedFallback:!1}}let i=r.body,a=i?.innerHTML??"",c=bp(ka.turndown(a));return{title:o,markdown:c,textLength:tE(i),usedFallback:!0}}var wp,ka,vp=y(()=>{"use strict";wp=200,ka=new eE({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});ka.remove(["script","style","noscript","iframe"])});import{readFileSync as nE}from"node:fs";import{join as rE}from"path";function oE(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function kp(t,e){return oE(e).test(t)}function aE(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(sE.has(e))return!0;if(iE.has(e))return!1}return!1}function _p(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function cE(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function lE(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function dE(t){try{return nE(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function uE(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function Ep(t){let e=t?.env??k,n=t?.readFileSync??dE,r=t?.surface??e.AGENT_SURFACE,o=aE(e.AFK_BROWSER_HEADLESS,r),s=_p(e.AFK_BROWSER_ALLOWED_DOMAINS),i=_p(e.AFK_BROWSER_BLOCKED_DOMAINS),a=lE(e.AFK_BROWSER_DOM_SNAPSHOTS),c=cE(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():rE(Ue(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(g){throw new Error(`Failed to parse browser config at ${u}: ${String(g)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let h=uE(l,f);return h.configPath=u,h}function _a(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(kp(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>kp(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var sE,iE,Ea=y(()=>{"use strict";$();B();sE=new Set(["daemon","subagent","telegram","afk"]),iE=new Set(["repl","interactive","cli"])});import pE from"node:fs";import fE from"node:path";import{chromium as mE}from"playwright";function gE(){try{return"4.33.2"}catch{}try{let t=fE.resolve(import.meta.dirname,"../../../package.json"),e=pE.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var hE,Uo,Ap=y(()=>{"use strict";hE=gE(),Uo=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=mE.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${hE}`}}}});import{createHash as yE}from"crypto";function Aa(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of bE)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function Tp(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&wE.test(t.label))}function xp(t){return yE("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Rp(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var bE,wE,Kn=y(()=>{"use strict";bE=[{name:"aws-access-key",regex:/AKIA[0-9A-Z]{16}/g},{name:"github-pat",regex:/ghp_[a-zA-Z0-9]{36}/g},{name:"openai-bearer",regex:/sk-[a-zA-Z0-9_-]{20,}/g},{name:"slack-token",regex:/xox[abp]-[a-zA-Z0-9-]{10,}/g},{name:"jwt",regex:/eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/g},{name:"form-password",regex:/password=[^&\s]+/gi}];wE=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as SE}from"node:crypto";function vE(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function kE(t,e,n){return`el_${SE("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function _E(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Pp(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Cp(t,e){let n=t.role??"",r=t.name??"";Ip.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Cp(s,e)}async function EE(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},Mp).catch(()=>[])}async function AE(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let g=s.type;g==="checkbox"?l="checkbox":g==="radio"?l="radio":g==="button"||g==="submit"||g==="reset"?l="button":g==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,h={role:l,name:c,disabled:p};u!==void 0&&(h.value=u),f!==void 0&&(h.checked=f),o.push(h)}return o},Mp).catch(()=>[])}function TE(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Bo(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=TE(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=EE(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,h,g]=await Promise.all([i,a,c,l,d]),S,b=!1;u!==null?(S=[],Cp(u,S)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,S=(await AE(t)).filter(R=>Ip.has(R.role??"")));let _=new Map;for(let T of p){let R=Pp(T.name),P=_.get(R);(!P||P.bbox.w===0&&T.bbox.w>0)&&_.set(R,T)}let w=S.map(T=>({ax:T,dom:_.get(Pp(T.name??""))})),v=r?w:w.filter(T=>T.dom?T.dom.bbox.w>0||T.dom.bbox.h>0:!0);v.sort((T,R)=>{let P=T.dom?.bbox.y??0,M=R.dom?.bbox.y??0;if(P!==M)return P-M;let D=T.dom?.bbox.x??0,O=R.dom?.bbox.x??0;return D-O}),v.length>200&&o.push("page has 200+ interactive elements; consider scoping");let A=v.slice(0,n).map((T,R)=>{let P=T.ax.role??"generic",M=T.ax.name??"",D=kE(P,M,R),O=T.dom?.bbox??{x:0,y:0,w:0,h:0},L=T.dom?.type??null,H=null;T.ax.value!==void 0&&T.ax.value!==null&&(H=String(T.ax.value)),T.ax.checked!==void 0&&(H=String(T.ax.checked)),Tp({role:P,kind:L})&&(H="[redacted]");let q={disabled:T.ax.disabled??!1};T.ax.checked!==void 0&&(q.checked=T.ax.checked===!0||T.ax.checked==="mixed"),T.ax.selected!==void 0&&(q.selected=T.ax.selected),T.ax.expanded!==void 0&&(q.expanded=T.ax.expanded);let z;T.dom?.testId?z=`[data-testid="${T.dom.testId}"]`:T.dom?.id&&(z=`#${T.dom.id}`);let Y={id:D,role:P,label:vE(M),kind:L,value:H,state:q,bbox:O};return z!==void 0&&(Y.selector=z),Y}),E="idle";try{let T=await t.evaluate(()=>document.readyState);T==="loading"?E="loading":T==="interactive"?E="navigating":E="idle"}catch{E="navigating"}E!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),b&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let I=_E(f),C=`obs_${e.observationCounter.toString(36)}`,F=new Date().toISOString();return{observationId:C,url:h,title:g,textSummary:I,interactive:A,status:{httpStatus:e.httpStatus??null,loadingState:E,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:F}}var Ip,Mp,Op=y(()=>{"use strict";Kn();Ip=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Mp="a[href], button, input, select, textarea, [role], [tabindex], label"});async function Dp(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function Ta(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>Dp(t,s)))).filter(o=>o!==null)}async function xE(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function xa(t,e,n){switch(e.kind){case"element_id":return RE(t,e,n);case"selector":return PE(t,e);case"semantic":return IE(t,e)}}async function RE(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await Ta(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function PE(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await Ta(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function IE(t,e){return e.role!==void 0?CE(t,e.text,e.role):ME(t,e.text,e)}async function CE(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await Ta(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function ME(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await xE(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let g=u[0];return g===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:g.locator.nth(g.index)}}let p=u.slice(0,5),f=[];for(let g=0;g<p.length;g++){let S=p[g];if(S===void 0)continue;let b=await Dp(S.locator,S.index);if(b!==null){let _=`${b.role}:${b.label}:${g}`,w=0;for(let v=0;v<_.length;v++)w=w*31+_.charCodeAt(v)>>>0;f.push({...b,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var Fp=y(()=>{"use strict"});import{randomBytes as OE}from"crypto";import{mkdir as DE,stat as FE,writeFile as LE}from"fs/promises";import{join as Ra}from"path";import{gzip as NE}from"zlib";import{promisify as $E}from"util";function UE(t){return Ra(Ir(t),"browser")}function BE(t){return Ra(UE(t),"screenshots")}function HE(){return new Date().toISOString().replace(/[:.]/g,"-")}function jE(){return OE(3).toString("hex")}async function Pa(t,e,n){if(e.length>Lp)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Lp} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=BE(t);await DE(r,{recursive:!0});let o=`${HE()}-${jE()}-${n}.png`,s=Ra(r,o);await LE(s,e);let{size:i}=await FE(s);return{path:s,bytes:i}}var n$,Lp,Np=y(()=>{"use strict";B();Kn();n$=$E(NE);Lp=5*1024*1024});var Up={};si(Up,{PlaywrightProvider:()=>Ia});function $p(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var Ia,Bp=y(()=>{"use strict";Ap();Op();Fp();Ea();Kn();Np();Ia=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Uo(e)}async open(e){let n=_a(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await Bo(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Bo(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await xa(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${$p(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let g=Aa(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(S){l=S}else l=g}let u=r.url();if(u!==s){let g=_a(u,this.config);if(!g.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:g.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Bo(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),h=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,h),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await xa(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${$p(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await Pa(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await Pa(n,o,r);return s}catch{return null}}}});var Ot={};si(Ot,{__resetBrowserRegistryForTests:()=>VE,browserProviderActive:()=>GE,closeBrowserProvider:()=>Ca,getBrowserProvider:()=>WE,peekBrowserProvider:()=>qE});function Hp(){Promise.resolve(Ca()).then(()=>{process.exit(130)})}function jp(){Promise.resolve(Ca()).then(()=>{process.exit(143)})}function Kp(){Oe=null}function KE(){Ho||(process.on("SIGINT",Hp),process.on("SIGTERM",jp),process.on("exit",Kp),Ho=!0)}function Wp(){Ho&&(process.removeListener("SIGINT",Hp),process.removeListener("SIGTERM",jp),process.removeListener("exit",Kp),Ho=!1)}async function WE(t){return Oe!==null?Oe:(Mt!==null||(Mt=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(Bp(),Up)),n=Ep(t),r=new e(n);return KE(),Oe=r,Mt=null,r})()),Mt)}async function Ca(){if(Oe===null)return;let t=Oe;Oe=null,Mt=null,Wp(),await t.shutdown()}function GE(){return Oe!==null}function qE(){return Oe}function VE(){Oe=null,Mt=null,Wp()}var Oe,Mt,Ho,Dt=y(()=>{"use strict";Ea();Oe=null,Mt=null,Ho=!1});function Gp(t,e){try{return Sp(t,e)}catch(n){return N("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function QE(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Dt(),Ot));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal})}async function qp(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??QE,o=null,s=t,i=null,a=null;try{let l=await n(t,{headers:XE,redirect:"follow",signal:e.signal});i=l.status,s=l.url||t;let d=l.headers.get("content-type")??"";if(l.ok){if(YE.test(d))throw new Error(`web_scrape markdown mode received binary content (${d.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let u=await l.text();if(JE.test(d)&&!zE.test(d))return{title:"",markdown:u.trim(),finalUrl:s,usedRender:!1};o=Gp(u,s)}}catch(l){if(e.signal.aborted||l instanceof Error&&l.message.startsWith("web_scrape markdown mode received binary"))throw l;a=l}if(!(o===null||o.textLength<wp)&&o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};try{let l=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal}),d=Gp(l.html,l.finalUrl);if(o===null||d.textLength>=o.textLength)return{title:d.title,markdown:d.markdown,finalUrl:l.finalUrl,usedRender:!0}}catch(l){if(e.signal.aborted)throw l;if(o===null){let d=l instanceof Error?l.message:String(l),u=a instanceof Error?a.message:`HTTP ${i??"error"}`,p=new Error(`web_scrape could not retrieve ${t}: fetch failed (${u}) and render failed (${d}).`);throw p.cause=l,p}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${i??"error"}).`)}var zE,JE,YE,XE,Vp=y(()=>{"use strict";vp();le();zE=/(text\/html|application\/xhtml\+xml)/i,JE=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,YE=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,XE={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/web_scrape",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}});function tA(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(ZE,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":t.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),eA),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=yo(d);u&&(c=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let l=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${l}${c}`)}let i;try{i=await s.json()}catch(c){throw new Error(`Exa Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(i.results??[]).slice(0,r).map(c=>({title:(c.title??"").trim()||"(untitled)",url:c.url??"",description:(c.highlights?.[0]??"").trim()})).filter(c=>c.url.length>0)}}}function zp(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?tA({apiKey:t.exaApiKey,fetchFn:t.fetchFn}):{error:'web_scrape search mode requires a search backend. Set EXA_API_KEY (free tier at https://exa.ai) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function Jp(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
1054
1054
|
|
|
1055
1055
|
(no results)`;let n=[`# Search results for "${t}"`,""];return e.forEach((r,o)=>{n.push(`## ${o+1}. ${r.title}`),r.url&&n.push(r.url),r.description&&n.push(r.description),n.push("")}),n.join(`
|
|
1056
1056
|
`).trimEnd()}var ZE,eA,Yp=y(()=>{"use strict";Qt();ZE="https://api.exa.ai/search",eA=10});function lA(t){if(!t||typeof t!="object")return{error:"Invalid input: expected an object"};let e=t,n=e.mode??"markdown";if(n!=="markdown"&&n!=="raw"&&n!=="search")return{error:`Invalid input: mode must be one of "markdown", "raw", "search" (got ${JSON.stringify(n)})`};let r=n,o,s;if(r==="search"){if(typeof e.query!="string"||e.query.length===0)return{error:'Invalid input: search mode requires a non-empty "query" string'};s=e.query}else{if(typeof e.url!="string"||e.url.length===0)return{error:`Invalid input: ${r} mode requires a non-empty "url" string`};let c;try{c=new URL(e.url)}catch{return{error:`Invalid input: "${e.url}" is not a valid absolute URL`}}if(c.protocol!=="http:"&&c.protocol!=="https:")return{error:`Invalid input: protocol "${c.protocol}" not supported (http/https only)`};o=c.toString()}let i=nA;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number"||!Number.isFinite(e.timeout_ms)||e.timeout_ms<=0)return{error:"Invalid input: timeout_ms must be a positive finite number"};i=Math.min(e.timeout_ms,rA)}let a=oA;if(e.max_bytes!==void 0){if(typeof e.max_bytes!="number"||!Number.isFinite(e.max_bytes)||e.max_bytes<=0)return{error:"Invalid input: max_bytes must be a positive finite number"};a=Math.min(e.max_bytes,sA)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Ma(t,e){let n=Buffer.from(t,"utf8");return n.byteLength<=e?t:n.subarray(0,e).toString("utf8")+iA}function dA(t){let e=[],n=t;for(let o=0;o<4&&n instanceof Error;o++)e.push(n.message),n=n.cause;let r=e.join(" | ");return cA.some(o=>r.includes(o))}function uA(t={}){let e=t.fetchFn??globalThis.fetch,n=t.env??process.env;return async(r,o)=>{if(typeof e!="function")return{content:"web_scrape unavailable: global fetch() is not present in this runtime (agent-afk requires Node 20+).",isError:!0};let s=lA(r);if("error"in s)return{content:s.error,isError:!0};if(o.aborted){let d=o.reason;return{content:`web_scrape aborted: ${d instanceof Error?d.message:String(d??"aborted")}`,isError:!0}}let i=new AbortController,a=()=>{i.abort(o.reason)},c,l=()=>{let d=i.signal.reason;return d instanceof Error?d.message:String(d??"aborted")};try{if(o.addEventListener("abort",a,{once:!0}),c=setTimeout(()=>{i.abort(new Error(`web_scrape timeout after ${s.timeoutMs}ms`))},s.timeoutMs),s.mode==="raw"){let u;try{u=await e(s.url,{method:"GET",headers:{"User-Agent":"agent-afk/web_scrape",Accept:"*/*"},signal:i.signal})}catch(f){return i.signal.aborted?{content:`web_scrape aborted: ${l()}`,isError:!0}:{content:`web_scrape network error: ${f instanceof Error?f.message:String(f)}`,isError:!0}}if(!u.ok)return{content:`web_scrape HTTP ${u.status} ${u.statusText||""}`.trimEnd()+` for ${s.url}`,isError:!0};let p;try{p=await u.text()}catch(f){return{content:`web_scrape read error: ${f instanceof Error?f.message:String(f)}`,isError:!0}}return{content:Ma(p,s.maxBytes)}}if(s.mode==="markdown")try{let u=await qp(s.url,{fetchFn:e,renderFn:t.renderFn,timeoutMs:s.timeoutMs,signal:i.signal});return u.markdown.trim().length===0?{content:`web_scrape extracted no readable content from ${s.url}.`,isError:!0}:{content:Ma(u.markdown,s.maxBytes)}}catch(u){if(i.signal.aborted)return{content:`web_scrape aborted: ${l()}`,isError:!0};let p=u instanceof Error?u.message:String(u),f=dA(u)?" (the render fallback needs the optional Playwright browser \u2014 run `pnpm exec playwright install chromium`)":"";return{content:`web_scrape markdown error: ${p}${f}`,isError:!0}}let d=zp({exaApiKey:n.EXA_API_KEY,fetchFn:e});if("error"in d)return{content:d.error,isError:!0};try{let u=await d.search(s.query,{limit:aA,timeoutMs:s.timeoutMs,signal:i.signal});return{content:Ma(Jp(s.query,u),s.maxBytes)}}catch(u){return i.signal.aborted?{content:`web_scrape aborted: ${l()}`,isError:!0}:{content:`web_scrape search error (${d.name}): ${u instanceof Error?u.message:String(u)}`,isError:!0}}}finally{c!==void 0&&clearTimeout(c),o.removeEventListener("abort",a)}}}var nA,rA,oA,sA,iA,aA,cA,Xp,Qp=y(()=>{"use strict";Vp();Yp();nA=3e4,rA=12e4,oA=1e6,sA=1e7,iA=`
|
|
@@ -1607,7 +1607,7 @@ Enter a number${x}`}_&&(d.allowSkip?v+=`
|
|
|
1607
1607
|
model: ${t.model}${t.cwd?`
|
|
1608
1608
|
cwd: ${t.cwd}`:""}`;case"user":return`\u{1F464} ${gr(t.text,fb)}`;case"assistant":return`\u{1F916} ${gr(t.text,fb)}`;case"tool":return`\u{1F527} ${t.toolName}(${gr(t.input,il)})`;case"tool_error":return`\u26A0\uFE0F tool failed: ${gr(t.content,il)}`;case"done":{let e=[];return typeof t.durationMs=="number"&&e.push(`${(t.durationMs/1e3).toFixed(1)}s`),typeof t.costUsd=="number"&&e.push(`$${t.costUsd.toFixed(4)}`),`\u2705 turn done${e.length?` (${e.join(", ")})`:""}`}case"error":return`\u274C error: ${gr(t.message,il)}`;case"paused":return`\u23F8\uFE0F paused on usage limit${t.resetsAt?` (resets ${t.resetsAt})`:""}`;case"resumed":return"\u25B6\uFE0F resumed";case"closed":return`\u{1F3C1} session closed${t.reason?` (${t.reason})`:""} \u2014 watch ended`;default:return null}}async function mb(t){let e=gd(t);return e?.data.sessionId&&await mo(e.data.sessionId)?e.data.sessionId:await mo(t)?t:null}async function gb(){let t=[],n=(await Fn()).filter(s=>s.surface!=="telegram");if(n.length>0){t.push("\u{1F7E2} Live sessions:");for(let s of n)t.push(` ${s.sessionId} (${s.surface}, ${s.cwd})`)}let r=Si().filter(s=>s.source!=="telegram").slice(0,8),o=[];for(let s of r)s.sessionId&&await mo(s.sessionId)&&o.push(` ${s.name??s.id} (${s.model})`);return o.length>0&&(t.length>0&&t.push(""),t.push("\u{1F4BE} Recent sessions with activity logs:",...o)),t.length===0?"No watchable sessions found. Start one with `afk i` on your machine, then /watch <session-id-or-name>.":(t.push("","Watch one with /watch <session-id-or-name>."),t.join(`
|
|
1609
1609
|
`))}var Vs=class{watches=new Map;log;bot;messageHandler;constructor(e=()=>{},n,r){this.log=e,this.bot=n,this.messageHandler=r}watching(e){return this.watches.get(e)?.sessionId}getWatched(e){return this.watches.get(e)?.sessionId}start(e,n,r){this.stop(e);let o=new AbortController,s=this._run(e,n,r,o.signal).catch(i=>{this.log("watch loop error:",i)});this.watches.set(e,{sessionId:n,abort:o,finished:s})}stop(e){let n=this.watches.get(e);if(n)return this.watches.delete(e),n.abort.abort(),n.sessionId}async stopAll(){let e=[...this.watches.values()];this.watches.clear();for(let n of e)n.abort.abort();await Promise.allSettled(e.map(n=>n.finished))}async _run(e,n,r,o){let s=[],i=null,a=Promise.resolve(),c=this.bot!==void 0&&this.messageHandler!==void 0?Ws(this.messageHandler,this.bot,e,{ledgerOriginated:!0}):void 0,l=()=>{if(i=null,s.length===0)return;let d=s.join(`
|
|
1610
|
-
`);s=[],a=a.then(()=>r(d)).catch(u=>this.log("watch send error:",u))};try{for await(let d of iu(n,{signal:o})){if(d.kind==="elicitation"&&c!==void 0){i&&clearTimeout(i),l(),await a;let p=await c(d.request,{signal:o}),f=qs(n);if(f!==null){let h=db(f,n,d.reqId,p);new st(n).record({kind:"elicitation_response",reqId:d.reqId,result:p,hmac:h})}else this.log("[watch] no session key for",n,"\u2014 skipping elicitation write-back");continue}let u=nC(d);if(u){if(s.push(u),d.kind==="closed"){l();break}i||(i=setTimeout(l,tC),i.unref?.())}}i&&clearTimeout(i),l(),await a}finally{i&&clearTimeout(i);let d=this.watches.get(e);d&&d.sessionId===n&&d.abort.signal===o&&this.watches.delete(e)}}};Ln();go();Te();var zs=class t{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;watchManager;autoSubscribeInterval=null;static AUTO_SUBSCRIBE_INTERVAL_MS=5e3;constructor(e){this.options=e,this.bot=new rC(e.botToken),this.sessionManager=new qr(e),this.messageHandler=new Hs(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.watchManager=new Vs(this.log.bind(this),this.bot,this.messageHandler),this.setupHandlers()}setupHandlers(){this.bot.use(np(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",n=>ki(n)),this.bot.command("help",n=>_i(n,this.sessionManager)),this.bot.command("clear",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}(await this.sessionManager.getSession(r)).state!=="idle"?(this.messageHandler.enqueueClear(r,n),await n.reply("Clear queued.")):await Xc(n,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}if((await this.sessionManager.getSession(r)).state!=="idle")this.messageHandler.enqueueCompact(r,n),await n.reply("Compact queued.");else try{await My(n,this.sessionManager,this.log.bind(this))}finally{this.messageHandler.drainQueue(r).catch(s=>this.log("Drain error:",s))}}),this.bot.command("model",n=>Qc(n,this.sessionManager,this.log.bind(this))),this.bot.command(["cd","cwd"],n=>Oy(n,this.sessionManager,this.log.bind(this))),this.bot.command("name",n=>Dy(n,this.sessionManager,this.log.bind(this))),this.bot.command("watch",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let s=((n.message&&"text"in n.message?n.message.text:"")??"").split(/\s+/).slice(1).join(" ").trim();try{if(!s){await n.reply(await gb());return}let i=await mb(s);if(!i){await n.reply(`No session ledger found for "${s}". Use /watch with no argument to list watchable sessions.`);return}let a=async c=>{for(let l of Se(c))await n.telegram.sendMessage(r,l)};this.watchManager.start(r,i,a),await n.reply(`\u{1F4E1} Watching ${i} \u2014 new activity will stream here. /unwatch to stop.`)}catch(i){this.log("Watch error:",i),await n.reply(W(i))}}),this.bot.command("unwatch",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let o=this.watchManager.stop(r);await n.reply(o?`Stopped watching ${o}.`:"Not watching anything.")}),this.bot.command("abort",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let o=this.watchManager.getWatched(r);if(!o){await n.reply("Not watching any session. Use /watch <session-id> to watch a REPL session first, then /abort to stop it.");return}let s=qs(o);if(s===null){await n.reply("Session key not found \u2014 the REPL may not have enabled AFK mode (/afk on). Cannot send a verified abort.");return}let i=pb(),a=ub(s,o,i);new st(o).record({kind:"abort_request",nonce:i,hmac:a}),await n.reply(`\u270B Abort sent to session ${o}.`)}),this.bot.on("text",n=>this.messageHandler.handle(n)),this.bot.on("photo",n=>this.messageHandler.handlePhoto(n));let e=new RegExp(`^${oC(Bs)}`);this.bot.action(e,n=>zy(n,{log:this.log.bind(this)})),this.bot.action(/^afk:m:/,async n=>{if(await n.answerCbQuery().catch(()=>{}),n.chat?.id!==void 0&&!this.options.allowedChatIds.has(n.chat.id))return;let o=(typeof n.callbackQuery=="object"&&"data"in n.callbackQuery?n.callbackQuery.data:"").replace("afk:m:",""),s=n.chat?.id;if(!(!s||!o)&&sr.includes(o))try{await this.sessionManager.switchModel(s,o);let i=Jr(o);await n.editMessageText(i).catch(()=>n.reply(i))}catch(i){this.log("Model action error:",i)}}),this.bot.catch((n,r)=>{this.log("Bot error:",n),r.reply(W("An unexpected error occurred. Please try again.")).catch(o=>this.log("Failed to send error message:",o))})}async start(){if(this.running)throw new Error("Bot is already running");this.log("Loading sessions..."),await this.sessionManager.loadSessions();let e=[...this.options.allowedChatIds];if(e.length>0){let r=e[0],o=Ws(this.messageHandler,this.bot,r),s=ib(this.bot,new Set(this.options.allowedChatIds),(...i)=>this.log("[elicitation]",...i));Ft.install(ab(o,s))}this.log("Starting bot..."),await this.bot.launch(),this.log("Registering bot commands..."),await this.bot.telegram.setMyCommands([{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"},{command:"cd",description:"Show or change session working directory"},{command:"name",description:"Show or set the session name"},{command:"watch",description:"Live-tail a CLI session from this chat"},{command:"unwatch",description:"Stop watching a session"}]),this.running=!0,this.log("Bot started successfully"),this.startAutoSubscribe();let n=async r=>{this.log(`Received ${r}, shutting down...`),await this.stop(),process.exit(0)};process.once("SIGINT",()=>n("SIGINT")),process.once("SIGTERM",()=>n("SIGTERM"))}async stop(){if(this.running){this.log("Stopping bot..."),this.running=!1,this.log("Stopping auto-subscribe loop..."),this.stopAutoSubscribe(),this.log("Uninstalling elicitation handler..."),Ft.uninstall(),this.log("Stopping session watches..."),await this.watchManager.stopAll(),this.log("Closing sessions..."),await this.sessionManager.closeAll(),this.log("Stopping bot polling...");try{this.bot.stop()}catch(e){this.log("Error stopping bot (may not have been started):",e)}this.log("Bot stopped")}}getStats(){return{running:this.running,activeSessions:this.sessionManager.getSessionCount(),totalChats:this.sessionManager.getChatCount()}}getBusySessionCount(){return this.sessionManager.getBusySessionCount()}async handleStart(e){return ki(e)}async handleHelp(e){return _i(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(W("Could not identify chat"));return}if((await this.sessionManager.getSession(n)).state!=="idle")this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.");else return Xc(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handlePhoto(e){return this.messageHandler.handlePhoto(e)}async handleModelSwitch(e){return Qc(e,this.sessionManager,this.log.bind(this))}startAutoSubscribe(){if(this.autoSubscribeInterval!==null)return;let e=()=>{this.runAutoSubscribeTick().catch(n=>this.log("auto-subscribe tick error:",n))};this.autoSubscribeInterval=setInterval(e,t.AUTO_SUBSCRIBE_INTERVAL_MS),this.autoSubscribeInterval.unref?.(),e()}stopAutoSubscribe(){this.autoSubscribeInterval!==null&&(clearInterval(this.autoSubscribeInterval),this.autoSubscribeInterval=null)}async runAutoSubscribeTick(){let e=[...this.options.allowedChatIds];if(e.length===0)return;let n;try{n=await Fn()}catch{return}let r=new Set(n.filter(o=>o.surface==="cli"&&o.afk===!0&&o.sessionId).map(o=>o.sessionId));for(let o of e){let s=this.watchManager.getWatched(o);s!==void 0&&!r.has(s)&&(this.watchManager.stop(o),this.log(`[auto-subscribe] stopped watch for ${s} (afk cleared)`));for(let i of r){if(this.watchManager.watching(o)===i)continue;let a=async c=>{for(let l of Se(c))await this.bot.telegram.sendMessage(o,l)};this.watchManager.start(o,i,a),this.log(`[auto-subscribe] started watch for ${i} on chat ${o}`);break}}}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function oC(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Oo();Ua();B();$();import hV from"chalk";var sC="https://api.telegram.org";async function hb(t){try{let e=await fetch(`${sC}/bot${t}/getMe`);if(!e.ok)return null;let n=await e.json();return!n.ok||!n.result?.id||!n.result?.first_name?null:{id:n.result.id,...n.result.username!==void 0?{username:n.result.username}:{},firstName:n.result.first_name}}catch{return null}}Vi();$();B();import{randomUUID as FC}from"node:crypto";import{createHash as PC}from"crypto";import{appendFileSync as IC}from"fs";import{mkdir as CC,open as MC,writeFile as OC}from"fs/promises";import{join as Ib}from"path";import{z as m}from"zod";var yb=["policy-refusal","timeout","permission-denied","hook-block","abort","elicitation-declined"];var iC=m.object({phase:m.literal("started"),toolUseId:m.string(),name:m.string(),inputBytes:m.number().int().nonnegative(),subagentId:m.string().optional()}),aC=m.enum(yb),cC=m.object({phase:m.literal("completed"),toolUseId:m.string(),name:m.string(),resultBytes:m.number().int().nonnegative(),isError:m.boolean(),truncated:m.boolean(),durationMs:m.number().nonnegative(),circuitBreaker:m.boolean().optional(),failureClass:aC.optional(),subagentId:m.string().optional()}),bb=m.discriminatedUnion("phase",[iC,cC]),lC=m.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),wb=m.object({hookEvent:lC,decision:m.union([m.literal("block"),m.literal("approve"),m.undefined()]),reason:m.string().optional(),blockedTool:m.string().optional(),injectedContextBytes:m.number().int().nonnegative().optional()}),dC=m.object({transition:m.literal("started"),subagentId:m.string(),parentId:m.string(),model:m.string(),allowedTools:m.array(m.string()).readonly().optional(),systemPromptHash:m.string().optional()}),uC=m.object({transition:m.literal("succeeded"),subagentId:m.string(),durationMs:m.number().nonnegative(),turnCount:m.number().int().nonnegative(),totalCostUsd:m.number().nonnegative().optional(),outputBytes:m.number().int().nonnegative()}),pC=m.object({transition:m.literal("failed"),subagentId:m.string(),errorClass:m.string(),errorMessage:m.string(),partialOutputBytes:m.number().int().nonnegative()}),fC=m.object({transition:m.literal("cancelled"),subagentId:m.string(),source:m.enum(["cascade","explicit"])}),Sb=m.discriminatedUnion("transition",[dC,uC,pC,fC]),mC=m.object({transition:m.literal("started"),jobId:m.string(),subagentId:m.string(),label:m.string(),model:m.string()}),gC=m.object({transition:m.literal("completed"),jobId:m.string(),subagentId:m.string(),durationMs:m.number().nonnegative(),outputBytes:m.number().int().nonnegative()}),hC=m.object({transition:m.literal("failed"),jobId:m.string(),subagentId:m.string(),durationMs:m.number().nonnegative(),errorClass:m.string(),errorMessage:m.string()}),yC=m.object({transition:m.literal("cancelled"),jobId:m.string(),subagentId:m.string(),source:m.enum(["explicit","cascade"])}),bC=m.object({transition:m.literal("joined"),jobId:m.string(),subagentId:m.string(),jobStatus:m.enum(["completed","failed","cancelled"])}),vb=m.discriminatedUnion("transition",[mC,gC,hC,yC,bC]),kb=m.object({kind:m.literal("monetary"),runningCostUsd:m.number().nonnegative(),maxBudgetUsd:m.number().nonnegative(),lastTurnCostUsd:m.number().nonnegative()}),wC=m.enum(["user_signal","cascade","timeout","budget","hook_block"]),_b=m.object({origin:wC,cascadedTo:m.array(m.string()).readonly(),reason:m.string().optional()}),Eb=m.enum(["manual","token_threshold","turn_count"]),SC=m.object({path:m.string(),sizeBytes:m.number().int().nonnegative(),sha256:m.string().regex(/^[0-9a-f]{64}$/)}),vC=m.object({trigger:Eb,preCompactionMessages:m.array(m.unknown()),summary:m.string(),keptTailCount:m.number().int().nonnegative(),keepLastNConfig:m.number().int().nonnegative(),messagesBefore:m.number().int().nonnegative(),messagesAfter:m.number().int().nonnegative(),tokensSavedEstimate:m.number().nonnegative().optional(),summarizationTokens:m.object({input:m.number().int().nonnegative(),output:m.number().int().nonnegative()}).optional()}),kC=m.object({trigger:Eb,preCompactionMessagesRef:SC,summary:m.string(),keptTailCount:m.number().int().nonnegative(),keepLastNConfig:m.number().int().nonnegative(),messagesBefore:m.number().int().nonnegative(),messagesAfter:m.number().int().nonnegative(),tokensSavedEstimate:m.number().nonnegative().optional(),summarizationTokens:m.object({input:m.number().int().nonnegative(),output:m.number().int().nonnegative()}).optional()}),_C=m.enum(["model_end_turn","truncated","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),Ab=m.object({reason:_C,finalTurnCount:m.number().int().nonnegative(),finalCostUsd:m.number().nonnegative(),finalTokens:m.object({input:m.number().int().nonnegative().optional(),output:m.number().int().nonnegative().optional(),cacheRead:m.number().int().nonnegative().optional(),cacheCreation:m.number().int().nonnegative().optional()}),lastStopReason:m.string().optional(),guidance:m.string().optional()}),Tb=m.object({source:m.string(),assertion:m.string(),evidence:m.array(m.string()).readonly(),confidence:m.number().min(0).max(1),dissent:m.string().optional()}),EC=m.enum(["browser_open","browser_observe","browser_act","browser_screenshot","browser_extract","browser_close"]),AC=m.enum(["click","fill","press","select","hover","scroll_to","wait_for"]),TC=m.object({kind:m.enum(["semantic","element_id","selector"]),text:m.string().max(80).optional(),role:m.string().optional(),elementId:m.string().optional(),selectorHash:m.string().regex(/^[0-9a-f]{8}$/).optional()}),xb=m.object({tool:EC,action:AC.optional(),toolUseId:m.string(),target:TC.optional(),urlBefore:m.string().nullable(),urlAfter:m.string().nullable(),status:m.enum(["ok","error","ambiguous_target","blocked_by_policy"]),screenshotPath:m.string().optional(),observationSummary:m.string().max(500).optional(),error:m.object({reason:m.string(),recoverable:m.boolean()}).optional(),durationMs:m.number().nonnegative()}),xC=m.enum(["bootstrap_start","bootstrap_done","session_init_start","session_init_done","mcp_connect_start","mcp_connect_done","mcp_server_start","mcp_server_done","loop_start","loop_end","model_ttfb"]),Rb=m.object({phase:xC,durationMs:m.number().nonnegative().optional(),metadata:m.record(m.string(),m.union([m.string(),m.number(),m.boolean()])).optional(),model:m.string().optional(),resolvedModel:m.string().optional(),origin:m.enum(["cli","telegram","daemon","unknown"]).optional(),actor:m.enum(["main","subagent"]).optional()}),RC=m.object({status:m.enum(["succeeded","failed","cancelled"]),finalCostUsd:m.number().nonnegative(),finalTurnCount:m.number().int().nonnegative(),closedAt:m.string().datetime(),incomplete:m.boolean().optional(),subagentCount:m.number().int().nonnegative().optional(),subagentTokens:m.object({input:m.number().int().nonnegative().optional(),output:m.number().int().nonnegative().optional(),cacheRead:m.number().int().nonnegative().optional(),cacheCreation:m.number().int().nonnegative().optional()}).optional(),subagentCostUsd:m.number().nonnegative().optional()}),Pb=m.discriminatedUnion("kind",[m.object({kind:m.literal("tool_call"),payload:bb}),m.object({kind:m.literal("hook_decision"),payload:wb}),m.object({kind:m.literal("subagent_lifecycle"),payload:Sb}),m.object({kind:m.literal("background_agent"),payload:vb}),m.object({kind:m.literal("budget"),payload:kb}),m.object({kind:m.literal("abort"),payload:_b}),m.object({kind:m.literal("compaction"),payload:vC}),m.object({kind:m.literal("closure"),payload:Ab}),m.object({kind:m.literal("claim"),payload:Tb}),m.object({kind:m.literal("browser_event"),payload:xb}),m.object({kind:m.literal("session_phase"),payload:Rb})]),AV=m.discriminatedUnion("kind",[m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("tool_call"),payload:bb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("hook_decision"),payload:wb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("subagent_lifecycle"),payload:Sb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("background_agent"),payload:vb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("budget"),payload:kb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("abort"),payload:_b}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("compaction"),payload:kC}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("closure"),payload:Ab}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("claim"),payload:Tb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("browser_event"),payload:xb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("session_phase"),payload:Rb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("session_sealed"),payload:RC})]);var Js=new Set,Cb=!1;function DC(){Cb||(Cb=!0,process.on("exit",()=>{for(let t of Js)t.sealOnProcessExit()}))}var Ys=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(e){this.traceDir=e.traceDir,this.tracePath=Ib(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(e){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return Pb.parse(e),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(e);await this.appendLine(n)})}async seal(e){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:e};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(e){let n=this.writeQueue.then(e,e);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await CC(this.traceDir,{recursive:!0}),this.fh=await MC(this.tracePath,"a"),Js.add(this),DC())}async closeHandle(){if(Js.delete(this),!this.fh)return;let e=this.fh;this.fh=null,await e.close()}sealOnProcessExit(){if(this.sealed||this.seq===0)return;this.sealed=!0,Js.delete(this);try{let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:{status:"failed",finalCostUsd:0,finalTurnCount:0,closedAt:new Date().toISOString(),incomplete:!0}};IC(this.tracePath,`${JSON.stringify(n)}
|
|
1610
|
+
`);s=[],a=a.then(()=>r(d)).catch(u=>this.log("watch send error:",u))};try{for await(let d of iu(n,{signal:o})){if(d.kind==="elicitation"&&c!==void 0){i&&clearTimeout(i),l(),await a;let p=await c(d.request,{signal:o}),f=qs(n);if(f!==null){let h=db(f,n,d.reqId,p);new st(n).record({kind:"elicitation_response",reqId:d.reqId,result:p,hmac:h})}else this.log("[watch] no session key for",n,"\u2014 skipping elicitation write-back");continue}let u=nC(d);if(u){if(s.push(u),d.kind==="closed"){l();break}i||(i=setTimeout(l,tC),i.unref?.())}}i&&clearTimeout(i),l(),await a}finally{i&&clearTimeout(i);let d=this.watches.get(e);d&&d.sessionId===n&&d.abort.signal===o&&this.watches.delete(e)}}};Ln();go();Te();var zs=class t{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;watchManager;autoSubscribeInterval=null;static AUTO_SUBSCRIBE_INTERVAL_MS=5e3;constructor(e){this.options=e,this.bot=new rC(e.botToken),this.sessionManager=new qr(e),this.messageHandler=new Hs(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.watchManager=new Vs(this.log.bind(this),this.bot,this.messageHandler),this.setupHandlers()}setupHandlers(){this.bot.use(np(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",n=>ki(n)),this.bot.command("help",n=>_i(n,this.sessionManager)),this.bot.command("clear",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}(await this.sessionManager.getSession(r)).state!=="idle"?(this.messageHandler.enqueueClear(r,n),await n.reply("Clear queued.")):await Xc(n,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}if((await this.sessionManager.getSession(r)).state!=="idle")this.messageHandler.enqueueCompact(r,n),await n.reply("Compact queued.");else try{await My(n,this.sessionManager,this.log.bind(this))}finally{this.messageHandler.drainQueue(r).catch(s=>this.log("Drain error:",s))}}),this.bot.command("model",n=>Qc(n,this.sessionManager,this.log.bind(this))),this.bot.command(["cd","cwd"],n=>Oy(n,this.sessionManager,this.log.bind(this))),this.bot.command("name",n=>Dy(n,this.sessionManager,this.log.bind(this))),this.bot.command("watch",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let s=((n.message&&"text"in n.message?n.message.text:"")??"").split(/\s+/).slice(1).join(" ").trim();try{if(!s){await n.reply(await gb());return}let i=await mb(s);if(!i){await n.reply(`No session ledger found for "${s}". Use /watch with no argument to list watchable sessions.`);return}let a=async c=>{for(let l of Se(c))await n.telegram.sendMessage(r,l)};this.watchManager.start(r,i,a),await n.reply(`\u{1F4E1} Watching ${i} \u2014 new activity will stream here. /unwatch to stop.`)}catch(i){this.log("Watch error:",i),await n.reply(W(i))}}),this.bot.command("unwatch",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let o=this.watchManager.stop(r);await n.reply(o?`Stopped watching ${o}.`:"Not watching anything.")}),this.bot.command("abort",async n=>{let r=n.chat?.id;if(!r){await n.reply(W("Could not identify chat"));return}let o=this.watchManager.getWatched(r);if(!o){await n.reply("Not watching any session. Use /watch <session-id> to watch a REPL session first, then /abort to stop it.");return}let s=qs(o);if(s===null){await n.reply("Session key not found \u2014 the REPL may not have enabled AFK mode (/afk on). Cannot send a verified abort.");return}let i=pb(),a=ub(s,o,i);new st(o).record({kind:"abort_request",nonce:i,hmac:a}),await n.reply(`\u270B Abort sent to session ${o}.`)}),this.bot.on("text",n=>this.messageHandler.handle(n)),this.bot.on("photo",n=>this.messageHandler.handlePhoto(n));let e=new RegExp(`^${oC(Bs)}`);this.bot.action(e,n=>zy(n,{log:this.log.bind(this)})),this.bot.action(/^afk:m:/,async n=>{if(await n.answerCbQuery().catch(()=>{}),n.chat?.id!==void 0&&!this.options.allowedChatIds.has(n.chat.id))return;let o=(typeof n.callbackQuery=="object"&&"data"in n.callbackQuery?n.callbackQuery.data:"").replace("afk:m:",""),s=n.chat?.id;if(!(!s||!o)&&sr.includes(o))try{await this.sessionManager.switchModel(s,o);let i=Jr(o);await n.editMessageText(i).catch(()=>n.reply(i))}catch(i){this.log("Model action error:",i)}}),this.bot.catch((n,r)=>{this.log("Bot error:",n),r.reply(W("An unexpected error occurred. Please try again.")).catch(o=>this.log("Failed to send error message:",o))})}async start(){if(this.running)throw new Error("Bot is already running");this.log("Loading sessions..."),await this.sessionManager.loadSessions();let e=[...this.options.allowedChatIds];if(e.length>0){let r=e[0],o=Ws(this.messageHandler,this.bot,r),s=ib(this.bot,new Set(this.options.allowedChatIds),(...i)=>this.log("[elicitation]",...i));Ft.install(ab(o,s))}this.log("Starting bot..."),await this.bot.launch(),this.log("Registering bot commands..."),await this.bot.telegram.setMyCommands([{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"},{command:"cd",description:"Show or change session working directory"},{command:"name",description:"Show or set the session name"},{command:"watch",description:"Live-tail a CLI session from this chat"},{command:"unwatch",description:"Stop watching a session"}]),this.running=!0,this.log("Bot started successfully"),this.startAutoSubscribe();let n=async r=>{this.log(`Received ${r}, shutting down...`),await this.stop(),process.exit(0)};process.once("SIGINT",()=>n("SIGINT")),process.once("SIGTERM",()=>n("SIGTERM"))}async stop(){if(this.running){this.log("Stopping bot..."),this.running=!1,this.log("Stopping auto-subscribe loop..."),this.stopAutoSubscribe(),this.log("Uninstalling elicitation handler..."),Ft.uninstall(),this.log("Stopping session watches..."),await this.watchManager.stopAll(),this.log("Closing sessions..."),await this.sessionManager.closeAll(),this.log("Stopping bot polling...");try{this.bot.stop()}catch(e){this.log("Error stopping bot (may not have been started):",e)}this.log("Bot stopped")}}getStats(){return{running:this.running,activeSessions:this.sessionManager.getSessionCount(),totalChats:this.sessionManager.getChatCount()}}getBusySessionCount(){return this.sessionManager.getBusySessionCount()}async handleStart(e){return ki(e)}async handleHelp(e){return _i(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(W("Could not identify chat"));return}if((await this.sessionManager.getSession(n)).state!=="idle")this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.");else return Xc(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handlePhoto(e){return this.messageHandler.handlePhoto(e)}async handleModelSwitch(e){return Qc(e,this.sessionManager,this.log.bind(this))}startAutoSubscribe(){if(this.autoSubscribeInterval!==null)return;let e=()=>{this.runAutoSubscribeTick().catch(n=>this.log("auto-subscribe tick error:",n))};this.autoSubscribeInterval=setInterval(e,t.AUTO_SUBSCRIBE_INTERVAL_MS),this.autoSubscribeInterval.unref?.(),e()}stopAutoSubscribe(){this.autoSubscribeInterval!==null&&(clearInterval(this.autoSubscribeInterval),this.autoSubscribeInterval=null)}async runAutoSubscribeTick(){let e=[...this.options.allowedChatIds];if(e.length===0)return;let n;try{n=await Fn()}catch{return}let r=new Set(n.filter(o=>o.surface==="cli"&&o.afk===!0&&o.sessionId).map(o=>o.sessionId));for(let o of e){let s=this.watchManager.getWatched(o);s!==void 0&&!r.has(s)&&(this.watchManager.stop(o),this.log(`[auto-subscribe] stopped watch for ${s} (afk cleared)`));for(let i of r){if(this.watchManager.watching(o)===i)continue;let a=async c=>{for(let l of Se(c))await this.bot.telegram.sendMessage(o,l)};this.watchManager.start(o,i,a),this.log(`[auto-subscribe] started watch for ${i} on chat ${o}`);break}}}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function oC(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Oo();Ua();B();$();import hV from"chalk";var sC="https://api.telegram.org";async function hb(t){try{let e=await fetch(`${sC}/bot${t}/getMe`);if(!e.ok)return null;let n=await e.json();return!n.ok||!n.result?.id||!n.result?.first_name?null:{id:n.result.id,...n.result.username!==void 0?{username:n.result.username}:{},firstName:n.result.first_name}}catch{return null}}Vi();$();B();import{randomUUID as FC}from"node:crypto";import{createHash as PC}from"crypto";import{appendFileSync as IC}from"fs";import{mkdir as CC,open as MC,writeFile as OC}from"fs/promises";import{join as Ib}from"path";import{z as m}from"zod";var yb=["policy-refusal","timeout","permission-denied","hook-block","abort","elicitation-declined"];var iC=m.object({phase:m.literal("started"),toolUseId:m.string(),name:m.string(),inputBytes:m.number().int().nonnegative(),subagentId:m.string().optional()}),aC=m.enum(yb),cC=m.object({phase:m.literal("completed"),toolUseId:m.string(),name:m.string(),resultBytes:m.number().int().nonnegative(),isError:m.boolean(),truncated:m.boolean(),durationMs:m.number().nonnegative(),circuitBreaker:m.boolean().optional(),failureClass:aC.optional(),subagentId:m.string().optional()}),bb=m.discriminatedUnion("phase",[iC,cC]),lC=m.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),wb=m.object({hookEvent:lC,decision:m.union([m.literal("block"),m.literal("approve")]).optional(),reason:m.string().optional(),blockedTool:m.string().optional(),injectedContextBytes:m.number().int().nonnegative().optional()}),dC=m.object({transition:m.literal("started"),subagentId:m.string(),parentId:m.string(),model:m.string(),allowedTools:m.array(m.string()).readonly().optional(),systemPromptHash:m.string().optional()}),uC=m.object({transition:m.literal("succeeded"),subagentId:m.string(),durationMs:m.number().nonnegative(),turnCount:m.number().int().nonnegative(),totalCostUsd:m.number().nonnegative().optional(),outputBytes:m.number().int().nonnegative()}),pC=m.object({transition:m.literal("failed"),subagentId:m.string(),errorClass:m.string(),errorMessage:m.string(),partialOutputBytes:m.number().int().nonnegative()}),fC=m.object({transition:m.literal("cancelled"),subagentId:m.string(),source:m.enum(["cascade","explicit"])}),Sb=m.discriminatedUnion("transition",[dC,uC,pC,fC]),mC=m.object({transition:m.literal("started"),jobId:m.string(),subagentId:m.string(),label:m.string(),model:m.string()}),gC=m.object({transition:m.literal("completed"),jobId:m.string(),subagentId:m.string(),durationMs:m.number().nonnegative(),outputBytes:m.number().int().nonnegative()}),hC=m.object({transition:m.literal("failed"),jobId:m.string(),subagentId:m.string(),durationMs:m.number().nonnegative(),errorClass:m.string(),errorMessage:m.string()}),yC=m.object({transition:m.literal("cancelled"),jobId:m.string(),subagentId:m.string(),source:m.enum(["explicit","cascade"])}),bC=m.object({transition:m.literal("joined"),jobId:m.string(),subagentId:m.string(),jobStatus:m.enum(["completed","failed","cancelled"])}),vb=m.discriminatedUnion("transition",[mC,gC,hC,yC,bC]),kb=m.object({kind:m.literal("monetary"),runningCostUsd:m.number().nonnegative(),maxBudgetUsd:m.number().nonnegative(),lastTurnCostUsd:m.number().nonnegative()}),wC=m.enum(["user_signal","cascade","timeout","budget","hook_block"]),_b=m.object({origin:wC,cascadedTo:m.array(m.string()).readonly(),reason:m.string().optional()}),Eb=m.enum(["manual","token_threshold","turn_count"]),SC=m.object({path:m.string(),sizeBytes:m.number().int().nonnegative(),sha256:m.string().regex(/^[0-9a-f]{64}$/)}),vC=m.object({trigger:Eb,preCompactionMessages:m.array(m.unknown()),summary:m.string(),keptTailCount:m.number().int().nonnegative(),keepLastNConfig:m.number().int().nonnegative(),messagesBefore:m.number().int().nonnegative(),messagesAfter:m.number().int().nonnegative(),tokensSavedEstimate:m.number().nonnegative().optional(),summarizationTokens:m.object({input:m.number().int().nonnegative(),output:m.number().int().nonnegative()}).optional()}),kC=m.object({trigger:Eb,preCompactionMessagesRef:SC,summary:m.string(),keptTailCount:m.number().int().nonnegative(),keepLastNConfig:m.number().int().nonnegative(),messagesBefore:m.number().int().nonnegative(),messagesAfter:m.number().int().nonnegative(),tokensSavedEstimate:m.number().nonnegative().optional(),summarizationTokens:m.object({input:m.number().int().nonnegative(),output:m.number().int().nonnegative()}).optional()}),_C=m.enum(["model_end_turn","truncated","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),Ab=m.object({reason:_C,finalTurnCount:m.number().int().nonnegative(),finalCostUsd:m.number().nonnegative(),finalTokens:m.object({input:m.number().int().nonnegative().optional(),output:m.number().int().nonnegative().optional(),cacheRead:m.number().int().nonnegative().optional(),cacheCreation:m.number().int().nonnegative().optional()}),lastStopReason:m.string().optional(),guidance:m.string().optional()}),Tb=m.object({source:m.string(),assertion:m.string(),evidence:m.array(m.string()).readonly(),confidence:m.number().min(0).max(1),dissent:m.string().optional()}),EC=m.enum(["browser_open","browser_observe","browser_act","browser_screenshot","browser_extract","browser_close"]),AC=m.enum(["click","fill","press","select","hover","scroll_to","wait_for"]),TC=m.object({kind:m.enum(["semantic","element_id","selector"]),text:m.string().max(80).optional(),role:m.string().optional(),elementId:m.string().optional(),selectorHash:m.string().regex(/^[0-9a-f]{8}$/).optional()}),xb=m.object({tool:EC,action:AC.optional(),toolUseId:m.string(),target:TC.optional(),urlBefore:m.string().nullable(),urlAfter:m.string().nullable(),status:m.enum(["ok","error","ambiguous_target","blocked_by_policy"]),screenshotPath:m.string().optional(),observationSummary:m.string().max(500).optional(),error:m.object({reason:m.string(),recoverable:m.boolean()}).optional(),durationMs:m.number().nonnegative()}),xC=m.enum(["bootstrap_start","bootstrap_done","session_init_start","session_init_done","mcp_connect_start","mcp_connect_done","mcp_server_start","mcp_server_done","loop_start","loop_end","model_ttfb"]),Rb=m.object({phase:xC,durationMs:m.number().nonnegative().optional(),metadata:m.record(m.string(),m.union([m.string(),m.number(),m.boolean()])).optional(),model:m.string().optional(),resolvedModel:m.string().optional(),origin:m.enum(["cli","telegram","daemon","unknown"]).optional(),actor:m.enum(["main","subagent"]).optional()}),RC=m.object({status:m.enum(["succeeded","failed","cancelled"]),finalCostUsd:m.number().nonnegative(),finalTurnCount:m.number().int().nonnegative(),closedAt:m.string().datetime(),incomplete:m.boolean().optional(),subagentCount:m.number().int().nonnegative().optional(),subagentTokens:m.object({input:m.number().int().nonnegative().optional(),output:m.number().int().nonnegative().optional(),cacheRead:m.number().int().nonnegative().optional(),cacheCreation:m.number().int().nonnegative().optional()}).optional(),subagentCostUsd:m.number().nonnegative().optional()}),Pb=m.discriminatedUnion("kind",[m.object({kind:m.literal("tool_call"),payload:bb}),m.object({kind:m.literal("hook_decision"),payload:wb}),m.object({kind:m.literal("subagent_lifecycle"),payload:Sb}),m.object({kind:m.literal("background_agent"),payload:vb}),m.object({kind:m.literal("budget"),payload:kb}),m.object({kind:m.literal("abort"),payload:_b}),m.object({kind:m.literal("compaction"),payload:vC}),m.object({kind:m.literal("closure"),payload:Ab}),m.object({kind:m.literal("claim"),payload:Tb}),m.object({kind:m.literal("browser_event"),payload:xb}),m.object({kind:m.literal("session_phase"),payload:Rb})]),AV=m.discriminatedUnion("kind",[m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("tool_call"),payload:bb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("hook_decision"),payload:wb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("subagent_lifecycle"),payload:Sb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("background_agent"),payload:vb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("budget"),payload:kb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("abort"),payload:_b}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("compaction"),payload:kC}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("closure"),payload:Ab}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("claim"),payload:Tb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("browser_event"),payload:xb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("session_phase"),payload:Rb}),m.object({ts:m.string().datetime(),seq:m.number().int().nonnegative(),kind:m.literal("session_sealed"),payload:RC})]);var Js=new Set,Cb=!1;function DC(){Cb||(Cb=!0,process.on("exit",()=>{for(let t of Js)t.sealOnProcessExit()}))}var Ys=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(e){this.traceDir=e.traceDir,this.tracePath=Ib(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(e){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return Pb.parse(e),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(e);await this.appendLine(n)})}async seal(e){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:e};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(e){let n=this.writeQueue.then(e,e);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await CC(this.traceDir,{recursive:!0}),this.fh=await MC(this.tracePath,"a"),Js.add(this),DC())}async closeHandle(){if(Js.delete(this),!this.fh)return;let e=this.fh;this.fh=null,await e.close()}sealOnProcessExit(){if(this.sealed||this.seq===0)return;this.sealed=!0,Js.delete(this);try{let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:{status:"failed",finalCostUsd:0,finalTurnCount:0,closedAt:new Date().toISOString(),incomplete:!0}};IC(this.tracePath,`${JSON.stringify(n)}
|
|
1611
1611
|
`)}catch{}let e=this.fh;this.fh=null,e&&e.close().catch(()=>{})}async appendLine(e){if(!this.fh)throw new Error("NdjsonTraceWriter: file handle missing");await this.fh.appendFile(`${JSON.stringify(e)}
|
|
1612
1612
|
`)}async materializePersistedEvent(e){let n=new Date().toISOString(),r=this.seq++;if(e.kind==="compaction"){let o=await this.persistCompactionSidecar(e.payload,r,n);return{ts:n,seq:r,kind:"compaction",payload:o}}return{ts:n,seq:r,kind:e.kind,payload:e.payload}}async persistCompactionSidecar(e,n,r){let o=r.replace(/[:.]/g,"-"),s=Ib(this.traceDir,`${String(n).padStart(6,"0")}-${o}-pre-compaction.json`),i=JSON.stringify(e.preCompactionMessages),a=Buffer.byteLength(i,"utf8"),c=PC("sha256").update(i).digest("hex");await OC(s,i,{encoding:"utf8",flag:"w"});let l={path:s,sizeBytes:a,sha256:c};return{trigger:e.trigger,preCompactionMessagesRef:l,summary:e.summary,keptTailCount:e.keptTailCount,keepLastNConfig:e.keepLastNConfig,messagesBefore:e.messagesBefore,messagesAfter:e.messagesAfter,...e.tokensSavedEstimate!==void 0?{tokensSavedEstimate:e.tokensSavedEstimate}:{},...e.summarizationTokens!==void 0?{summarizationTokens:e.summarizationTokens}:{}}}};function Mb(t={}){if(k.AFK_TRACE_DISABLED==="1")return null;let e=t.sessionLabel??FC(),n=Ir(e),r=new Ys({traceDir:n});return{writer:r,tracePath:r.getTracePath(),sessionLabel:e}}function al(t,e={}){let n=(e.createTraceWriter??Mb)(),r=n?{traceWriter:n.writer,...t,surface:"telegram"}:{...t,surface:"telegram"};return(e.newSession??(s=>new Et(s)))(r)}vo();var LC=["shadow-verify","shadow_verify","resolve","diagnose","appmap","mint","review"],NC=[/\bverdict(s)?\b/i,/\brecommend(ation)?s?\b/i,/\bshould\s+(delete|remove|rewrite|refactor|rename|reject|merge|revert|disable)\b/i,/\b(USELESS|KEEP|REJECT|APPROVE|SALVAGE|BLOCK|FAIL)\b/,/\b(redundant|duplicated|superseded|obsolete)\b/i,/\bvulnerab\w*\b/i,/\bunused\b/i,/\bbroken\b/i,/\bregress\w*\b/i,/\|\s*(status|verdict|decision|severity|risk|finding|priority|holds\??)\s*\|/i,/\bfound\s+\d+\s*(issue|problem|bug|error|finding|vulnerabilit)/i,/\b(critical|high|medium|low)\s+(severity|priority|risk)\b/i,/\bclaim(s)?\b[^\n]{0,80}\b(holds?|refuted|verified|partial|confirmed|disputed)\b/i,/\b(root\s*cause|incident)\b/i,/\brecommend\s+(removing|deleting|rewriting|refactoring|merging|reverting)\b/i,/\bI\s+(applied|committed|pushed|edited|wrote|fixed|patched|reset|restored|staged)\b/i,/\b(applied|committed|pushed|fixed|patched)\s+(the|these|those)\s+(change|commit|fix|patch|edit)/i],$C=[/\bverifier_verdict\b/i,/"\s*claim\s*"\s*:/i,/\bre-derived\b[^.\n]{0,80}\bindependent/i,/\bindependently\s+(re-derived|re-verified|verified|checked)\b/i,/\bverifier\s+(agrees|disagrees|confirms|refutes)\b/i],UC=`[framework-generated context: shadow-verify nudge]
|
|
1613
1613
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-afk",
|
|
3
|
-
"version": "4.33.
|
|
3
|
+
"version": "4.33.2",
|
|
4
4
|
"description": "Open-source coding-agent harness you can actually change — own the loop (prompts, gates, routing, skills, terminal states), use any model, run long tasks while you're away.",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"type": "module",
|