agent-afk 5.167.1 → 5.167.3
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/agent/provider.d.ts +1 -0
- package/dist/cli/slash/plugin-skills/state.d.ts +1 -0
- package/dist/cli.mjs +21 -7
- package/dist/index.mjs +2 -2
- package/dist/telegram.mjs +18 -4
- package/package.json +1 -1
package/dist/telegram.mjs
CHANGED
|
@@ -169,18 +169,32 @@ CREATE TABLE IF NOT EXISTS workspace_entries (
|
|
|
169
169
|
|
|
170
170
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_ws_session_seq ON workspace_entries(session_id, seq);
|
|
171
171
|
|
|
172
|
+
-- FTS5 options are fixed when the virtual table is created. If WorkspaceStore
|
|
173
|
+
-- gains persistent-database callers, option changes require a migration that
|
|
174
|
+
-- drops and recreates workspace_fts rather than relying on IF NOT EXISTS.
|
|
172
175
|
CREATE VIRTUAL TABLE IF NOT EXISTS workspace_fts USING fts5(
|
|
173
176
|
subject,
|
|
174
177
|
content,
|
|
175
178
|
content=workspace_entries,
|
|
176
179
|
content_rowid=id,
|
|
177
|
-
tokenize='porter'
|
|
178
|
-
columnsize=0
|
|
180
|
+
tokenize='porter'
|
|
179
181
|
);
|
|
180
182
|
|
|
181
183
|
CREATE TRIGGER IF NOT EXISTS ws_fts_ai AFTER INSERT ON workspace_entries BEGIN
|
|
182
184
|
INSERT INTO workspace_fts(rowid, subject, content) VALUES (new.id, new.subject, new.content);
|
|
183
185
|
END;
|
|
186
|
+
|
|
187
|
+
CREATE TRIGGER IF NOT EXISTS ws_fts_ad AFTER DELETE ON workspace_entries BEGIN
|
|
188
|
+
INSERT INTO workspace_fts(workspace_fts, rowid, subject, content)
|
|
189
|
+
VALUES ('delete', old.id, old.subject, old.content);
|
|
190
|
+
END;
|
|
191
|
+
|
|
192
|
+
CREATE TRIGGER IF NOT EXISTS ws_fts_au AFTER UPDATE ON workspace_entries BEGIN
|
|
193
|
+
INSERT INTO workspace_fts(workspace_fts, rowid, subject, content)
|
|
194
|
+
VALUES ('delete', old.id, old.subject, old.content);
|
|
195
|
+
INSERT INTO workspace_fts(rowid, subject, content)
|
|
196
|
+
VALUES (new.id, new.subject, new.content);
|
|
197
|
+
END;
|
|
184
198
|
`,Vs=class{db;constructor(e){this.db=new Sj(e??":memory:"),this.db.pragma("busy_timeout = 5000"),this.enableWalMode(),this.db.exec(vj)}enableWalMode(){for(let r=1;;r++)try{if(this.db.pragma("journal_mode",{simple:!0})==="wal")return;this.db.pragma("journal_mode = WAL");return}catch(o){if(!(o?.code==="SQLITE_BUSY")||r>=50)throw o;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,20)}}publish(e){return this.db.transaction(()=>{let r=this.nextSeq(e.session_id),s=this.db.prepare(`
|
|
185
199
|
INSERT INTO workspace_entries
|
|
186
200
|
(session_id, type, subject, content, evidence, confidence, agent_id, relates_to, relation_type, seq)
|
|
@@ -297,7 +311,7 @@ ${o}`,paths:[e,n]}:o!==null?s={content:o,paths:[n]}:r!==null?s={content:r,paths:
|
|
|
297
311
|
|
|
298
312
|
${e}`}var CG,Ag=g(()=>{"use strict";CG=new Set(["script","style","noscript","template","svg"])});function OG(t,e){return new Promise((n,r)=>{if(e?.aborted){r(e.reason??new Error("aborted"));return}let o=()=>{clearTimeout(s),r(e?.reason??new Error("aborted"))},s=setTimeout(()=>{e?.removeEventListener("abort",o),n()},t);e?.addEventListener("abort",o,{once:!0})})}function gE(t,e,n){let r=Math.min(e*2**t,n);return Math.round(Math.random()*r)}function DG(t,e){let n=t.headers.get("retry-after");if(n===null)return null;let r=Number(n.trim());return!Number.isFinite(r)||r<0?null:Math.min(r*1e3,e)}async function hE(t,e,n={},r={}){let o=r.retries??3,s=r.baseDelayMs??500,i=r.maxDelayMs??1e4,a=r.sleep??OG,c=n.signal??void 0,l;for(let d=0;d<=o;d++){if(c?.aborted)throw c.reason??new Error("aborted");try{let u=await t(e,n);if(!MG.has(u.status)||d===o)return u;let p=DG(u,i)??gE(d,s,i);O("[web/retryFetch] retrying",{url:e,attempt:d,status:u.status,waitMs:p}),await u.body?.cancel().catch(()=>{}),await a(p,c)}catch(u){if(c?.aborted||(l=u,d===o))throw u;let p=gE(d,s,i);O("[web/retryFetch] retrying after error",{url:e,attempt:d,waitMs:p}),await a(p,c)}}throw l??new Error("retryFetch: exhausted without a result")}var MG,yE=g(()=>{"use strict";se();MG=new Set([429,502,503,504])});import{BlockList as FG,isIP as Tg}from"node:net";import{lookup as LG}from"node:dns/promises";import{Agent as NG}from"undici";function wE(){let t=S.AFK_WEB_ALLOW_PRIVATE_HOSTS?.trim().toLowerCase();return t==="1"||t==="true"}function jG(t){return t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t}function Eg(t){let e=Tg(t);return e===0?!1:BG.check(t,e===4?"ipv4":"ipv6")}async function SE(t){return LG(t,{all:!0,verbatim:!0})}async function Rg(t,e={}){if(e.allowPrivateHosts??wE())return{allowed:!0};let n;try{n=new URL(t)}catch{return{allowed:!1,reason:`"${t}" is not a valid absolute URL`}}if(n.protocol!=="http:"&&n.protocol!=="https:")return{allowed:!1,reason:`protocol "${n.protocol}" not supported (http/https only)`};let r=jG(n.hostname),o=(a,c)=>`refusing to fetch ${c} \u2014 internal/private address ${a} (loopback, link-local, cloud metadata, or RFC1918 space). Set AFK_WEB_ALLOW_PRIVATE_HOSTS=1 to allow private-host access.`;if(Tg(r)!==0)return Eg(r)?{allowed:!1,reason:o(r,r)}:{allowed:!0};let s=e.lookupFn??SE,i;try{i=await s(r)}catch{return{allowed:!0}}for(let a of i)if(Eg(a.address))return{allowed:!1,reason:o(a.address,`${r} (resolved)`)};return{allowed:!0}}async function ki(t,e={}){let n=await Rg(t,e);if(!n.allowed)throw new kt(n.reason)}async function Bl(t,e,n={},r={}){let o={...r.lookupFn!==void 0?{lookupFn:r.lookupFn}:{},...r.allowPrivateHosts!==void 0?{allowPrivateHosts:r.allowPrivateHosts}:{}},s=e;for(let i=0;i<=bE;i++){await ki(s,o);let a={...n,redirect:"manual",...t===globalThis.fetch&&!(r.allowPrivateHosts??wE())?{dispatcher:HG}:{}},c=await hE(t,s,a,r.retry??{});if(!WG.has(c.status))return c;let l=c.headers.get("location");if(l===null||l.trim()==="")return c;let d;try{d=new URL(l,c.url||s).toString()}catch{return c}await c.body?.cancel().catch(()=>{}),s=d}throw new kt(`too many redirects (>${bE}) starting from ${e}`)}var UG,$G,BG,kt,HG,bE,WG,xg=g(()=>{"use strict";L();yE();UG=[["0.0.0.0",8],["10.0.0.0",8],["100.64.0.0",10],["127.0.0.0",8],["169.254.0.0",16],["172.16.0.0",12],["192.168.0.0",16]],$G=[["::",96],["64:ff9b::",96],["fc00::",7],["fe80::",10]],BG=(()=>{let t=new FG;for(let[e,n]of UG)t.addSubnet(e,n,"ipv4");for(let[e,n]of $G)t.addSubnet(e,n,"ipv6");return t})(),kt=class extends Error{constructor(e){super(e),this.name="EgressBlockedError"}};HG=new NG({connect:{lookup(t,e,n){SE(t).then(r=>{let o=r.find(i=>Eg(i.address));if(o!==void 0){n(new kt(`refusing to connect to ${t} (resolved) \u2014 internal/private address ${o.address} (loopback, link-local, cloud metadata, or RFC1918 space). Set AFK_WEB_ALLOW_PRIVATE_HOSTS=1 to allow private-host access.`),"",0);return}let s=r[0];if(s===void 0){n(new Error(`DNS lookup returned no addresses for ${t}`),"",0);return}n(null,s.address,Tg(s.address))},r=>n(r,"",0))}}});bE=20,WG=new Set([301,302,303,307,308])});var AE={};As(AE,{enforceDomainPolicy:()=>_t,loadBrowserConfig:()=>Ig});import{readFileSync as KG}from"node:fs";import{join as GG}from"path";function qG(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function vE(t,e){return qG(e).test(t)}function VG(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(XG.has(e))return!0;if(zG.has(e))return!1}return!1}function kE(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function JG(t){if(t===void 0||t==="")return"auto";if(t==="playwright"||t==="agent-browser"||t==="auto")return t;throw new Error(`AFK_BROWSER_BACKEND: must be "playwright", "agent-browser", or "auto", got: ${t}`)}function _E(t){let e=t===void 0||t.trim()===""?"default":t.trim();return If(e),e}function YG(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function QG(t){try{return KG(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function ZG(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"||e.backend==="agent-browser"||e.backend==="auto")n.backend=e.backend;else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: must be "playwright", "agent-browser", or "auto", got: ${String(e.backend)}`);return typeof e.defaultProfile=="string"&&(n.defaultProfile=_E(e.defaultProfile)),n}function Ig(t){let e=t?.env??S,n=t?.readFileSync??QG,r=t?.surface??e.AGENT_SURFACE,o=VG(e.AFK_BROWSER_HEADLESS,r),s=kE(e.AFK_BROWSER_ALLOWED_DOMAINS),i=kE(e.AFK_BROWSER_BLOCKED_DOMAINS),a=YG(e.AFK_BROWSER_DOM_SNAPSHOTS),c=JG(e.AFK_BROWSER_BACKEND),l=_E(e.AFK_BROWSER_DEFAULT_PROFILE),d={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null,defaultProfile:l},u=e.AFK_BROWSER_CONFIG,p=u!==void 0&&u.trim()!==""?u.trim():GG(Vt(),"browser.json"),f=n(p);if(f===void 0)return d;let m;try{m=JSON.parse(f)}catch(y){throw new Error(`Failed to parse browser config at ${p}: ${String(y)}`)}if(typeof m!="object"||m===null||Array.isArray(m))throw new Error(`Browser config at ${p} must be a JSON object`);let h=ZG(d,m);return h.configPath=p,h}function _t(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(vE(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>vE(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var XG,zG,pr=g(()=>{"use strict";L();j();XG=new Set(["daemon","subagent","telegram","afk"]),zG=new Set(["repl","interactive","cli"])});import{readFileSync as eq}from"node:fs";import{join as tq}from"node:path";import{homedir as nq}from"node:os";function oq(t){let e=t??rq,n;try{n=eq(e,"utf8")}catch{return null}let r;try{r=JSON.parse(n)}catch{return null}if(typeof r!="object"||r===null||Array.isArray(r))return null;let o=r;if(typeof o.url!="string"||typeof o.token!="string"||typeof o.pid!="number")return null;let s;try{s=new URL(o.url)}catch{return null}let{hostname:i,protocol:a}=s;if(!(i==="127.0.0.1"||i==="localhost"||i==="::1")||a!=="http:")throw new Error(`Agent Browser connection file contains an untrusted URL: ${o.url}. Only http://127.0.0.1 or http://localhost is permitted.`);return{url:o.url,token:o.token,pid:o.pid,version:typeof o.version=="string"?o.version:"unknown"}}function sq(t){try{return process.kill(t,0),!0}catch{return!1}}async function iq(t,e,n=2e3){try{let r=new AbortController,o=setTimeout(()=>r.abort(),n),s=await fetch(`${t}/health`,{method:"GET",headers:{Authorization:`Bearer ${e}`,Host:"127.0.0.1:8833"},signal:r.signal});return clearTimeout(o),s.ok}catch{return!1}}async function Cg(t){let e=oq(t);return e===null?{available:!1,connection:null,reason:"connection file missing or invalid"}:sq(e.pid)?await iq(e.url,e.token)?{available:!0,connection:e,reason:null}:{available:!1,connection:e,reason:`health probe failed at ${e.url}`}:{available:!1,connection:e,reason:`stale connection file: PID ${e.pid} not alive`}}var rq,EE=g(()=>{"use strict";rq=tq(nq(),".config","agent-browser","connection.json")});async function TE(t){let{config:e,surface:n}=t;if(e.backend==="playwright")return{backend:"playwright",reason:"explicit config: backend=playwright",probeMs:0,availability:null};if(e.backend==="agent-browser"){let i=Date.now(),a=await Cg(),c=Date.now()-i;if(!a.available)throw new Error(`AFK_BROWSER_BACKEND=agent-browser but Agent Browser is not available: ${a.reason}`);return{backend:"agent-browser",reason:"explicit config: backend=agent-browser",probeMs:c,availability:a}}if(n&&aq.has(n))return{backend:"playwright",reason:`auto: surface "${n}" excluded from Agent Browser`,probeMs:0,availability:null};if(e.headless)return{backend:"playwright",reason:"auto: headless mode requires Playwright",probeMs:0,availability:null};let r=Date.now(),o=await Cg(),s=Date.now()-r;return o.available?{backend:"agent-browser",reason:"auto: Agent Browser available and preferred",probeMs:s,availability:o}:{backend:"playwright",reason:`auto: Agent Browser unavailable (${o.reason})`,probeMs:s,availability:o}}var aq,RE=g(()=>{"use strict";EE();aq=new Set(["daemon","subagent"])});import{createHash as cq}from"crypto";function xE(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&lq.test(t.label))}function IE(t){return cq("sha256").update(t,"utf8").digest("hex").slice(0,8)}function CE(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var lq,jl=g(()=>{"use strict";lq=/password|secret|token|api[_-]?key|otp|2fa/i});import{randomBytes as dq}from"crypto";import{mkdir as uq,stat as pq,writeFile as fq}from"fs/promises";import{join as Pg}from"path";import{gzip as mq}from"zlib";import{promisify as gq}from"util";function hq(t){return Pg(Ct(t),"browser")}function yq(t){return Pg(hq(t),"screenshots")}function bq(){return new Date().toISOString().replace(/[:.]/g,"-")}function wq(){return dq(3).toString("hex")}async function So(t,e,n){if(e.length>PE)throw new Error(`writeScreenshotSidecar: buffer exceeds ${PE} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=yq(t);await uq(r,{recursive:!0});let o=`${bq()}-${wq()}-${n}.png`,s=Pg(r,o);await fq(s,e);let{size:i}=await pq(s);return{path:s,bytes:i}}var Qle,PE,Mg=g(()=>{"use strict";j();jl();Qle=gq(mq);PE=5*1024*1024});var Hl,ME=g(()=>{"use strict";Hl=class{baseUrl;token;constructor(e){this.baseUrl=e.url,this.token=e.token}async call(e,n,r=3e4){let o={version:1,method:e,params:n},s=new AbortController,i=setTimeout(()=>s.abort(),r);try{let a=await fetch(`${this.baseUrl}/agent`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`,Host:new URL(this.baseUrl).host},body:JSON.stringify(o),signal:s.signal});if(!a.ok){let c=await a.text().catch(()=>"");throw new Error(`Agent Browser ${e} failed (HTTP ${a.status}): ${c}`)}return await a.json()}finally{clearTimeout(i)}}async listTabs(){return(await this.call("tabs.list",null)).tabs}async openTab(e){return{tabId:(await this.call("tabs.open",{url:e},6e4)).tab_id}}async closeTab(e){await this.call("tabs.close",{tab_id:e})}async read(e,n){return this.call("page.read",{tab_id:e,mode:n?.mode??"main",...n?.query?{query:n.query}:{},...n?.budget?{budget:n.budget}:{}})}async inspect(e,n){return this.call("page.inspect",{tab_id:e,mode:n?.mode??"interactive",...n?.query?{query:n.query}:{},...n?.limit?{limit:n.limit}:{}})}async click(e,n){await this.call("page.click",{tab_id:e,element_id:n})}async fill(e,n,r){await this.call("page.fill",{tab_id:e,element_id:n,value:r})}async press(e,n,r){await this.call("page.press",{tab_id:e,key:n,...r?{element_id:r}:{}})}async select(e,n,r){await this.call("page.select",{tab_id:e,element_id:n,value:r})}async waitFor(e,n,r){await this.call("page.wait",{tab_id:e,condition:n,...r?.value?{value:r.value}:{},...r?.timeout?{timeout:r.timeout}:{}},(r?.timeout??3e4)+5e3)}async evalScript(e,n){return this.call("page.eval",{tab_id:e,script:n})}async screenshot(e){return this.call("page.screenshot",{tab_id:e})}}});function Og(t){return{id:t.id,role:t.role,label:t.label,kind:t.kind,value:t.value,state:{disabled:t.disabled,...t.checked!==void 0?{checked:t.checked}:{},...t.selected!==void 0?{selected:t.selected}:{},...t.expanded!==void 0?{expanded:t.expanded}:{}},bbox:t.bbox,...t.selector?{selector:t.selector}:{}}}function OE(t,e){switch(e.kind){case"element_id":if(t.has(e.elementId))return e.elementId;throw new Error(`Element ${e.elementId} not found in current observation. Call browser_observe to refresh.`);case"selector":return null;case"semantic":return null}}async function Dg(t,e,n,r,o,s){switch(n){case"click":await t.click(e,r);break;case"fill":if(o===void 0)throw new Error("fill requires a value");await t.fill(e,r,o);break;case"press":if(o===void 0)throw new Error("press requires a value (key combo)");await t.press(e,o,r);break;case"select":if(o===void 0)throw new Error("select requires a value");await t.select(e,r,o);break;case"hover":throw new Error("hover is not supported by Agent Browser; use element_id from a prior observation to target clicks instead");case"scroll_to":{let i=r.replace(/\\/g,"\\\\").replace(/"/g,'\\"');await t.evalScript(e,`document.querySelector('[data-element-id="${i}"]')?.scrollIntoView({behavior:'smooth',block:'center'})`);break}case"wait_for":await t.waitFor(e,"element",{value:r,timeout:s??1e4});break;default:throw new Error(`Unknown action: ${n}`)}}async function DE(t,e){if(e.target.kind!=="semantic")throw new Error("resolveSemanticAndAct called with non-semantic target");let{elements:n}=await t.client.inspect(t.tabId,{mode:"interactive",query:e.target.text,limit:10}),r=n;if(e.target.role){let c=e.target.role.toLowerCase();r=n.filter(l=>l.role.toLowerCase()===c)}if(r.length===0)throw new Error(`No element found matching semantic target: text="${e.target.text}"`+(e.target.role?`, role="${e.target.role}"`:""));if(r.length>1)return{outcome:"ambiguous_target",query:{text:e.target.text,...e.target.role?{role:e.target.role}:{}},candidates:r.slice(0,5).map(Og)};let s=r[0].id;await Dg(t.client,t.tabId,e.action,s,e.value,e.timeoutMs);let i=await t.client.read(t.tabId,{mode:"main"}),a=_t(i.url,t.config);return a.allowed?{elementId:s}:{outcome:"blocked_by_policy",url:i.url,reason:`action navigated to blocked domain: ${a.reason}`}}var FE=g(()=>{"use strict";pr()});var LE={};As(LE,{AgentBrowserProvider:()=>Fg});var Fg,NE=g(()=>{"use strict";pr();Mg();ME();FE();Fg=class{name="agent-browser";config;client;sessions=new Map;constructor(e,n){this.config=e,this.client=new Hl(n)}async open(e){let n=_t(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let r=this.sessions.get(e.sessionId);if(r)await this.client.evalScript(r.tabId,`window.location.href = ${JSON.stringify(e.url)}`),await this.client.waitFor(r.tabId,"load",{timeout:e.timeoutMs??3e4});else{let{tabId:i}=await this.client.openTab(e.url);await this.client.waitFor(i,"load",{timeout:e.timeoutMs??3e4}),r={tabId:i,observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null},this.sessions.set(e.sessionId,r)}let o=await this.client.read(r.tabId,{mode:"main"}),s=_t(o.url,this.config);return s.allowed?this.buildObservation(r,e.sessionId,e.screenshot,void 0,"browser_open"):(await this.client.evalScript(r.tabId,"window.location.href = 'about:blank'").catch(()=>{}),{outcome:"blocked_by_policy",url:o.url,reason:`redirected to blocked domain: ${s.reason}`})}async observe(e){let n=this.sessions.get(e.sessionId);if(!n)throw new Error(`No Agent Browser tab open for session ${e.sessionId}. Call browser_open first.`);return this.buildObservation(n,e.sessionId,e.screenshot,e.maxElements,"browser_observe")}async act(e){let n=this.sessions.get(e.sessionId);if(!n)throw new Error(`No Agent Browser tab open for session ${e.sessionId}. Call browser_open first.`);let r=OE(n.knownElements,e.target);if(r===null){if(e.target.kind==="semantic"){let i=await DE({client:this.client,config:this.config,tabId:n.tabId},e);return"outcome"in i?i:(n.lastAction=`browser_act:${e.action}`,n.lastActionAt=new Date().toISOString(),this.buildObservation(n,e.sessionId,e.screenshot,void 0,"browser_act"))}throw e.target.kind==="selector"?new Error("selector targets are not supported by Agent Browser; use element_id or semantic targets"):new Error(`Cannot resolve target: ${JSON.stringify(e.target)}`)}await Dg(this.client,n.tabId,e.action,r,e.value,e.timeoutMs),n.lastAction=`browser_act:${e.action}`,n.lastActionAt=new Date().toISOString();let o=await this.client.read(n.tabId,{mode:"main"}),s=_t(o.url,this.config);return s.allowed?this.buildObservation(n,e.sessionId,e.screenshot,void 0,"browser_act"):(await this.client.evalScript(n.tabId,"window.location.href = 'about:blank'").catch(()=>{}),{outcome:"blocked_by_policy",url:o.url,reason:`action navigated to blocked domain: ${s.reason}`})}async render(e){throw new Error("AgentBrowserProvider does not support render(). Use PlaywrightProvider for one-shot content fetches.")}async screenshot(e){let n=this.sessions.get(e.sessionId);if(!n)throw new Error(`No Agent Browser tab open for session ${e.sessionId}. Call browser_open first.`);if(e.target!==void 0||e.fullPage)throw new Error("Agent Browser does not support element or full-page screenshots; omit target and fullPage.");let r=await this.client.screenshot(n.tabId),o=Buffer.from(r.data,"base64"),s=o.length>=24?o.readUInt32BE(16):0,i=o.length>=24?o.readUInt32BE(20):0;return{path:(await So(e.sessionId,o,"browser_screenshot")).path,bytes:o.length,width:s,height:i,dataBase64:r.data,mediaType:"image/png"}}async extract(e){throw new Error("AgentBrowserProvider does not support extract() yet.")}async close(e){let n=this.sessions.get(e.sessionId);if(n){try{await this.client.closeTab(n.tabId)}catch{}this.sessions.delete(e.sessionId)}}describe(e){let n=this.sessions.get(e);return n?{active:!0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:1}:null}async shutdown(){let e=Array.from(this.sessions.entries()).map(async([,n])=>{try{await this.client.closeTab(n.tabId)}catch{}});await Promise.all(e),this.sessions.clear()}async buildObservation(e,n,r,o,s="browser_open"){let[i,a]=await Promise.all([this.client.read(e.tabId,{mode:"main",budget:4e3}),this.client.inspect(e.tabId,{mode:"interactive",limit:o??80})]),c=a.elements.map(Og),l=o??80,d=c.slice(0,l);e.observationCounter+=1,e.knownElements=new Map(d.map(h=>[h.id,h])),e.currentUrl=i.url,e.currentTitle=i.title;let u=[];c.length>l&&u.push(`page has ${c.length} interactive elements; showing first ${l}`);let p=null;if(r)try{let h=await this.client.screenshot(e.tabId),y=Buffer.from(h.data,"base64");p=(await So(n,y,s)).path}catch{u.push("screenshot capture failed")}let f=`obs_${e.observationCounter.toString(36)}`,m={httpStatus:null,loadingState:"idle",hasDialog:!1,consoleErrors:0};return{observationId:f,url:i.url,title:i.title,textSummary:i.content.slice(0,4e3),interactive:d,status:m,warnings:u,screenshotPath:p,capturedAt:new Date().toISOString()}}}});import{existsSync as Sq,readFileSync as vq}from"node:fs";import{createRequire as kq}from"node:module";import{dirname as _q,join as Aq}from"node:path";function BE(t){if(typeof t=="string")return t;let e=[],n=t;for(let r=0;r<Tq&&n instanceof Error;r++)e.push(n.message),n=n.cause;return e.length>0?e.join(" | "):String(t)}function He(t){let e=BE(t);return $E.some(n=>e.includes(n))}function Rq(){try{let e=kq(import.meta.url).resolve("playwright/package.json"),n=JSON.parse(vq(e,"utf8"));if(typeof n!="object"||n===null)return;let r=n.bin,o=typeof r=="string"?r:typeof r=="object"&&r!==null?r.playwright:void 0;if(typeof o!="string"||o.length===0)return;let s=Aq(_q(e),o);return Sq(s)?`node ${/\s/.test(s)?`"${s}"`:s} install chromium`:void 0}catch{return}}function _i(){return UE??=Rq()??Eq,UE}function Lg(t){return t.includes("install chromium")}function ct(t,e){let n=BE(t),r=e?.latched===!0?` ${xq}`:"";if(n.includes("Executable doesn't exist")){let o="";return e?.headless===!0?o=" This launch was headless, which needs the `chromium_headless_shell-*` build.":e?.headless===!1&&(o=" This launch was headed, which needs the full `chromium-*` build \u2014 the headless shell alone does not satisfy it."),`browser tools require the Playwright chromium binary. Install via: ${_i()}.${o}${r}`}return`browser tools require the optional \`playwright\` peer dependency. Install via: pnpm add playwright (then ${_i()}). Or pick a different tool.${r}`}function Ng(t,e,n=!1){if(!He(t))return t;let r=t instanceof Error?t.message:String(t);return new Error(`${r}
|
|
299
313
|
|
|
300
|
-
${ct(t,{headless:e,latched:n})}`,{cause:t})}var $E,Eq,Tq,UE,xq,Ug=g(()=>{"use strict";$E=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],Eq="pnpm exec playwright install chromium",Tq=4;xq="This session already latched the failure, so browser tools keep fast-failing with this same error \u2014 after installing, call browser_close once to retry."});import fr from"node:fs";import Wl from"node:path";import{randomBytes as Iq}from"node:crypto";import{chromium as Cq}from"playwright";function Pq(){try{return"5.167.1"}catch{}try{let t=Wl.resolve(import.meta.dirname,"../../../package.json"),e=fr.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Mq,Kl,jE=g(()=>{"use strict";Ug();j();se();Mq=Pq(),Kl=class{config;browser;sessions=new Map;launchPromise;launchFailure;shutdownComplete=!1;constructor(e){this.config=e}clearLaunchFailure(){this.launchFailure=void 0}latchLaunchFailure(e){this.launchFailure={error:e}}async ensureBrowser(){if(this.browser!==void 0&&this.browser.isConnected())return this.browser;if(this.launchFailure!==void 0)throw this.launchFailure.error;return this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Cq.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,this.clearLaunchFailure(),e)).catch(e=>{this.launchPromise=void 0;let n=Ng(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),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 r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}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;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(c){s=c,await a.abort("blockedbyclient")}});let i=()=>{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",i,{once:!0});try{let a=await o.newPage(),c;try{c=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let l=await a.content();if(s!==void 0)throw s;let d=a.url(),u=c!==null?c.status():null;return{html:l,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),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){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),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/${Mq}`}}loadStorageState(e){let n=Cf(e);try{if(!fr.existsSync(n))return;let r=JSON.parse(fr.readFileSync(n,"utf8"));return O("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){O("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=Cf(e);if(!fr.existsSync(r))return;let o=await n.storageState(),s=Wl.join(Wl.dirname(r),`.${Wl.basename(r)}.${process.pid}.${Iq(4).toString("hex")}.tmp`);fr.writeFileSync(s,JSON.stringify(o),{mode:384}),fr.chmodSync(s,384),fr.renameSync(s,r),O("[browser/vault] saved session",{profile:e,file:r})}catch(r){O("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as Oq}from"node:crypto";function Dq(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Fq(t,e,n){return`el_${Oq("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Lq(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function HE(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function KE(t,e){let n=t.role??"",r=t.name??"";WE.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])KE(s,e)}async function Nq(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},GE).catch(()=>[])}async function Uq(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 h=s.type;h==="checkbox"?l="checkbox":h==="radio"?l="radio":h==="button"||h==="submit"||h==="reset"?l="button":h==="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,m={role:l,name:c,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},GE).catch(()=>[])}function $q(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Gl(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=$q(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=Nq(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,h]=await Promise.all([i,a,c,l,d]),y,b=!1;u!==null?(y=[],KE(u,y)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,y=(await Uq(t)).filter(M=>WE.has(M.role??"")));let k=new Map;for(let C of p){let M=HE(C.name),q=k.get(M);(!q||q.bbox.w===0&&C.bbox.w>0)&&k.set(M,C)}let _=y.map(C=>({ax:C,dom:k.get(HE(C.name??""))})),E=r?_:_.filter(C=>C.dom?C.dom.bbox.w>0||C.dom.bbox.h>0:!0);E.sort((C,M)=>{let q=C.dom?.bbox.y??0,P=M.dom?.bbox.y??0;if(q!==P)return q-P;let $=C.dom?.bbox.x??0,D=M.dom?.bbox.x??0;return $-D}),E.length>200&&o.push("page has 200+ interactive elements; consider scoping");let T=E.slice(0,n).map((C,M)=>{let q=C.ax.role??"generic",P=C.ax.name??"",$=Fq(q,P,M),D=C.dom?.bbox??{x:0,y:0,w:0,h:0},N=C.dom?.type??null,B=null;C.ax.value!==void 0&&C.ax.value!==null&&(B=String(C.ax.value)),C.ax.checked!==void 0&&(B=String(C.ax.checked)),xE({role:q,kind:N})&&(B="[redacted]");let K={disabled:C.ax.disabled??!1};C.ax.checked!==void 0&&(K.checked=C.ax.checked===!0||C.ax.checked==="mixed"),C.ax.selected!==void 0&&(K.selected=C.ax.selected),C.ax.expanded!==void 0&&(K.expanded=C.ax.expanded);let Q;C.dom?.testId?Q=`[data-testid="${C.dom.testId}"]`:C.dom?.id&&(Q=`#${C.dom.id}`);let Ne={id:$,role:q,label:Dq(P),kind:N,value:B,state:K,bbox:D};return Q!==void 0&&(Ne.selector=Q),Ne}),I="idle";try{let C=await t.evaluate(()=>document.readyState);C==="loading"?I="loading":C==="interactive"?I="navigating":I="idle"}catch{I="navigating"}I!=="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 x=Lq(f),v=`obs_${e.observationCounter.toString(36)}`,A=new Date().toISOString();return{observationId:v,url:m,title:h,textSummary:x,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:A}}var WE,GE,qE=g(()=>{"use strict";jl();WE=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);GE="a[href], button, input, select, textarea, [role], [tabindex], label"});async function XE(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 $g(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>XE(t,s)))).filter(o=>o!==null)}async function Bq(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 Bg(t,e,n){switch(e.kind){case"element_id":return jq(t,e,n);case"selector":return Hq(t,e);case"semantic":return Wq(t,e)}}async function jq(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 $g(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Hq(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 $g(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Wq(t,e){return e.role!==void 0?Kq(t,e.text,e.role):Gq(t,e.text,e)}async function Kq(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 $g(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function Gq(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 Bq(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let h=u[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let p=u.slice(0,5),f=[];for(let h=0;h<p.length;h++){let y=p[h];if(y===void 0)continue;let b=await XE(y.locator,y.index);if(b!==null){let k=`${b.role}:${b.label}:${h}`,_=0;for(let E=0;E<k.length;E++)_=_*31+k.charCodeAt(E)>>>0;f.push({...b,id:`el_${_.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var zE=g(()=>{"use strict"});async function jg(t,e,n,r){let o=t.url();if(o===n)return null;let s=_t(o,e);if(s.allowed)return null;try{await t.goBack()}catch{await r()}return{outcome:"blocked_by_policy",url:o,reason:s.reason}}var VE=g(()=>{"use strict";pr()});var Wg={};As(Wg,{PlaywrightProvider:()=>Hg});function JE(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 Hg,Kg=g(()=>{"use strict";jE();qE();zE();pr();VE();Mg();Hg=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Kl(e)}async open(e){let n=_t(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(u){a=u}let c=o.url();if(!(a!==null&&(c===""||c==="about:blank"))){let u=await jg(o,this.config,e.url,()=>this.close({sessionId:r}));if(u!==null)return u}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let d=await Gl(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,d.interactive,d.url,d.title,"browser_open"),a!==null)throw a;return d}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 Gl(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 Bg(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${JE(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":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(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await d()}catch(y){l=y}else l=h}let u=await jg(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Gl(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),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,requestGuard:e.requestGuard})}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 Bg(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${JE(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 So(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 So(n,o,r);return s}catch{return null}}}});var gr={};As(gr,{__resetBrowserRegistryForTests:()=>Yq,browserProviderActive:()=>zq,closeBrowserProvider:()=>qg,getBrowserProvider:()=>Xq,getLastRoutingDecision:()=>Jq,peekBrowserProvider:()=>Vq});function YE(){Promise.resolve(qg()).then(()=>{process.exit(130)})}function QE(){Promise.resolve(qg()).then(()=>{process.exit(143)})}function ZE(){jt=null}function qq(){ql||(process.on("SIGINT",YE),process.on("SIGTERM",QE),process.on("exit",ZE),ql=!0)}function eT(){ql&&(process.removeListener("SIGINT",YE),process.removeListener("SIGTERM",QE),process.removeListener("exit",ZE),ql=!1)}async function Xq(t){return jt!==null?jt:(mr!==null||(mr=(async()=>{let e=Ig(t),n=t?.surface??(t?.env??{}).AGENT_SURFACE??S.AGENT_SURFACE,r=await TE({config:e,surface:n});Gg=r;let o;if(r.backend==="agent-browser"){let{AgentBrowserProvider:s}=await Promise.resolve().then(()=>(NE(),LE)),i=r.availability.connection;o=new s(e,i)}else{let{PlaywrightProvider:s}=await Promise.resolve().then(()=>(Kg(),Wg));o=new s(e)}return qq(),jt=o,mr=null,o})()),mr)}async function qg(){if(jt===null)return;let t=jt;jt=null,mr=null,eT(),await t.shutdown()}function zq(){return jt!==null}function Vq(){return jt}function Jq(){return Gg}function Yq(){jt=null,mr=null,Gg=null,eT()}var jt,mr,ql,Gg,hr=g(()=>{"use strict";pr();RE();L();jt=null,mr=null,ql=!1,Gg=null});async function tT(t,e){try{return await pE(t,e)}catch(n){return O("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function r2(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(hr(),gr)),r=await n();try{return await r.render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}catch(o){if(r.name==="agent-browser"){let{PlaywrightProvider:s}=await Promise.resolve().then(()=>(Kg(),Wg)),{loadBrowserConfig:i}=await Promise.resolve().then(()=>(pr(),AE)),a=i(),c=new s(a);try{return await c.render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}finally{await c.shutdown()}}throw o}}async function nT(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??r2,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await Bl(n,t,{headers:n2,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(t2.test(p))throw new Error(`web_scrape markdown mode received binary content (${p.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let f=await u.text();if(e2.test(p)&&!Zq.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await tT(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof kt||u instanceof Error&&u.message.startsWith("web_scrape markdown mode received binary"))throw u;l=u}if(!(s===null||s.textLength<200)&&s!==null){let u=_g({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await ki(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>ki(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await ki(u.finalUrl,o);let p=await tT(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=_g({html:u.html,extractedTextLength:p.textLength});return{title:p.title,markdown:p.markdown,finalUrl:u.finalUrl,usedRender:!0,...f!==void 0?{advisory:f}:{}}}}catch(u){if(e.signal.aborted||u instanceof kt)throw u;if(s===null){let p=u instanceof Error?u.message:String(u),f=l instanceof Error?l.message:`HTTP ${c??"error"}`,m=new Error(`web_scrape could not retrieve ${t}: fetch failed (${f}) and render failed (${p}).`);throw m.cause=u,m}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${c??"error"}).`)}var Zq,e2,t2,n2,rT=g(()=>{"use strict";fE();Ag();xg();se();Zq=/(text\/html|application\/xhtml\+xml)/i,e2=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,t2=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,n2={"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 i2(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(o2,{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),s2),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=Z(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 oT(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?i2({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 sT(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
314
|
+
${ct(t,{headless:e,latched:n})}`,{cause:t})}var $E,Eq,Tq,UE,xq,Ug=g(()=>{"use strict";$E=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],Eq="pnpm exec playwright install chromium",Tq=4;xq="This session already latched the failure, so browser tools keep fast-failing with this same error \u2014 after installing, call browser_close once to retry."});import fr from"node:fs";import Wl from"node:path";import{randomBytes as Iq}from"node:crypto";import{chromium as Cq}from"playwright";function Pq(){try{return"5.167.3"}catch{}try{let t=Wl.resolve(import.meta.dirname,"../../../package.json"),e=fr.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Mq,Kl,jE=g(()=>{"use strict";Ug();j();se();Mq=Pq(),Kl=class{config;browser;sessions=new Map;launchPromise;launchFailure;shutdownComplete=!1;constructor(e){this.config=e}clearLaunchFailure(){this.launchFailure=void 0}latchLaunchFailure(e){this.launchFailure={error:e}}async ensureBrowser(){if(this.browser!==void 0&&this.browser.isConnected())return this.browser;if(this.launchFailure!==void 0)throw this.launchFailure.error;return this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Cq.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,this.clearLaunchFailure(),e)).catch(e=>{this.launchPromise=void 0;let n=Ng(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),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 r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}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;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(c){s=c,await a.abort("blockedbyclient")}});let i=()=>{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",i,{once:!0});try{let a=await o.newPage(),c;try{c=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let l=await a.content();if(s!==void 0)throw s;let d=a.url(),u=c!==null?c.status():null;return{html:l,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),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){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),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/${Mq}`}}loadStorageState(e){let n=Cf(e);try{if(!fr.existsSync(n))return;let r=JSON.parse(fr.readFileSync(n,"utf8"));return O("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){O("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=Cf(e);if(!fr.existsSync(r))return;let o=await n.storageState(),s=Wl.join(Wl.dirname(r),`.${Wl.basename(r)}.${process.pid}.${Iq(4).toString("hex")}.tmp`);fr.writeFileSync(s,JSON.stringify(o),{mode:384}),fr.chmodSync(s,384),fr.renameSync(s,r),O("[browser/vault] saved session",{profile:e,file:r})}catch(r){O("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as Oq}from"node:crypto";function Dq(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Fq(t,e,n){return`el_${Oq("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Lq(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function HE(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function KE(t,e){let n=t.role??"",r=t.name??"";WE.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])KE(s,e)}async function Nq(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},GE).catch(()=>[])}async function Uq(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 h=s.type;h==="checkbox"?l="checkbox":h==="radio"?l="radio":h==="button"||h==="submit"||h==="reset"?l="button":h==="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,m={role:l,name:c,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},GE).catch(()=>[])}function $q(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Gl(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=$q(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=Nq(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,h]=await Promise.all([i,a,c,l,d]),y,b=!1;u!==null?(y=[],KE(u,y)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,y=(await Uq(t)).filter(M=>WE.has(M.role??"")));let k=new Map;for(let C of p){let M=HE(C.name),q=k.get(M);(!q||q.bbox.w===0&&C.bbox.w>0)&&k.set(M,C)}let _=y.map(C=>({ax:C,dom:k.get(HE(C.name??""))})),E=r?_:_.filter(C=>C.dom?C.dom.bbox.w>0||C.dom.bbox.h>0:!0);E.sort((C,M)=>{let q=C.dom?.bbox.y??0,P=M.dom?.bbox.y??0;if(q!==P)return q-P;let $=C.dom?.bbox.x??0,D=M.dom?.bbox.x??0;return $-D}),E.length>200&&o.push("page has 200+ interactive elements; consider scoping");let T=E.slice(0,n).map((C,M)=>{let q=C.ax.role??"generic",P=C.ax.name??"",$=Fq(q,P,M),D=C.dom?.bbox??{x:0,y:0,w:0,h:0},N=C.dom?.type??null,B=null;C.ax.value!==void 0&&C.ax.value!==null&&(B=String(C.ax.value)),C.ax.checked!==void 0&&(B=String(C.ax.checked)),xE({role:q,kind:N})&&(B="[redacted]");let K={disabled:C.ax.disabled??!1};C.ax.checked!==void 0&&(K.checked=C.ax.checked===!0||C.ax.checked==="mixed"),C.ax.selected!==void 0&&(K.selected=C.ax.selected),C.ax.expanded!==void 0&&(K.expanded=C.ax.expanded);let Q;C.dom?.testId?Q=`[data-testid="${C.dom.testId}"]`:C.dom?.id&&(Q=`#${C.dom.id}`);let Ne={id:$,role:q,label:Dq(P),kind:N,value:B,state:K,bbox:D};return Q!==void 0&&(Ne.selector=Q),Ne}),I="idle";try{let C=await t.evaluate(()=>document.readyState);C==="loading"?I="loading":C==="interactive"?I="navigating":I="idle"}catch{I="navigating"}I!=="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 x=Lq(f),v=`obs_${e.observationCounter.toString(36)}`,A=new Date().toISOString();return{observationId:v,url:m,title:h,textSummary:x,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:A}}var WE,GE,qE=g(()=>{"use strict";jl();WE=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);GE="a[href], button, input, select, textarea, [role], [tabindex], label"});async function XE(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 $g(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>XE(t,s)))).filter(o=>o!==null)}async function Bq(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 Bg(t,e,n){switch(e.kind){case"element_id":return jq(t,e,n);case"selector":return Hq(t,e);case"semantic":return Wq(t,e)}}async function jq(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 $g(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Hq(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 $g(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Wq(t,e){return e.role!==void 0?Kq(t,e.text,e.role):Gq(t,e.text,e)}async function Kq(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 $g(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function Gq(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 Bq(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let h=u[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let p=u.slice(0,5),f=[];for(let h=0;h<p.length;h++){let y=p[h];if(y===void 0)continue;let b=await XE(y.locator,y.index);if(b!==null){let k=`${b.role}:${b.label}:${h}`,_=0;for(let E=0;E<k.length;E++)_=_*31+k.charCodeAt(E)>>>0;f.push({...b,id:`el_${_.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var zE=g(()=>{"use strict"});async function jg(t,e,n,r){let o=t.url();if(o===n)return null;let s=_t(o,e);if(s.allowed)return null;try{await t.goBack()}catch{await r()}return{outcome:"blocked_by_policy",url:o,reason:s.reason}}var VE=g(()=>{"use strict";pr()});var Wg={};As(Wg,{PlaywrightProvider:()=>Hg});function JE(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 Hg,Kg=g(()=>{"use strict";jE();qE();zE();pr();VE();Mg();Hg=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Kl(e)}async open(e){let n=_t(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(u){a=u}let c=o.url();if(!(a!==null&&(c===""||c==="about:blank"))){let u=await jg(o,this.config,e.url,()=>this.close({sessionId:r}));if(u!==null)return u}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let d=await Gl(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,d.interactive,d.url,d.title,"browser_open"),a!==null)throw a;return d}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 Gl(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 Bg(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${JE(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":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(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await d()}catch(y){l=y}else l=h}let u=await jg(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Gl(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),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,requestGuard:e.requestGuard})}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 Bg(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${JE(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 So(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 So(n,o,r);return s}catch{return null}}}});var gr={};As(gr,{__resetBrowserRegistryForTests:()=>Yq,browserProviderActive:()=>zq,closeBrowserProvider:()=>qg,getBrowserProvider:()=>Xq,getLastRoutingDecision:()=>Jq,peekBrowserProvider:()=>Vq});function YE(){Promise.resolve(qg()).then(()=>{process.exit(130)})}function QE(){Promise.resolve(qg()).then(()=>{process.exit(143)})}function ZE(){jt=null}function qq(){ql||(process.on("SIGINT",YE),process.on("SIGTERM",QE),process.on("exit",ZE),ql=!0)}function eT(){ql&&(process.removeListener("SIGINT",YE),process.removeListener("SIGTERM",QE),process.removeListener("exit",ZE),ql=!1)}async function Xq(t){return jt!==null?jt:(mr!==null||(mr=(async()=>{let e=Ig(t),n=t?.surface??(t?.env??{}).AGENT_SURFACE??S.AGENT_SURFACE,r=await TE({config:e,surface:n});Gg=r;let o;if(r.backend==="agent-browser"){let{AgentBrowserProvider:s}=await Promise.resolve().then(()=>(NE(),LE)),i=r.availability.connection;o=new s(e,i)}else{let{PlaywrightProvider:s}=await Promise.resolve().then(()=>(Kg(),Wg));o=new s(e)}return qq(),jt=o,mr=null,o})()),mr)}async function qg(){if(jt===null)return;let t=jt;jt=null,mr=null,eT(),await t.shutdown()}function zq(){return jt!==null}function Vq(){return jt}function Jq(){return Gg}function Yq(){jt=null,mr=null,Gg=null,eT()}var jt,mr,ql,Gg,hr=g(()=>{"use strict";pr();RE();L();jt=null,mr=null,ql=!1,Gg=null});async function tT(t,e){try{return await pE(t,e)}catch(n){return O("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function r2(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(hr(),gr)),r=await n();try{return await r.render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}catch(o){if(r.name==="agent-browser"){let{PlaywrightProvider:s}=await Promise.resolve().then(()=>(Kg(),Wg)),{loadBrowserConfig:i}=await Promise.resolve().then(()=>(pr(),AE)),a=i(),c=new s(a);try{return await c.render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}finally{await c.shutdown()}}throw o}}async function nT(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??r2,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await Bl(n,t,{headers:n2,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(t2.test(p))throw new Error(`web_scrape markdown mode received binary content (${p.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let f=await u.text();if(e2.test(p)&&!Zq.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await tT(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof kt||u instanceof Error&&u.message.startsWith("web_scrape markdown mode received binary"))throw u;l=u}if(!(s===null||s.textLength<200)&&s!==null){let u=_g({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await ki(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>ki(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await ki(u.finalUrl,o);let p=await tT(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=_g({html:u.html,extractedTextLength:p.textLength});return{title:p.title,markdown:p.markdown,finalUrl:u.finalUrl,usedRender:!0,...f!==void 0?{advisory:f}:{}}}}catch(u){if(e.signal.aborted||u instanceof kt)throw u;if(s===null){let p=u instanceof Error?u.message:String(u),f=l instanceof Error?l.message:`HTTP ${c??"error"}`,m=new Error(`web_scrape could not retrieve ${t}: fetch failed (${f}) and render failed (${p}).`);throw m.cause=u,m}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${c??"error"}).`)}var Zq,e2,t2,n2,rT=g(()=>{"use strict";fE();Ag();xg();se();Zq=/(text\/html|application\/xhtml\+xml)/i,e2=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,t2=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,n2={"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 i2(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(o2,{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),s2),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=Z(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 oT(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?i2({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 sT(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
301
315
|
|
|
302
316
|
(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(`
|
|
303
317
|
`).trimEnd()}var o2,s2,iT=g(()=>{"use strict";ht();o2="https://api.exa.ai/search",s2=10});function Xl(t){if(t instanceof Error&&t.name==="TimeoutError")return"timeout";let e=t instanceof Error?t.message:String(t);return/Timeout\s+\d+\s*ms exceeded/i.test(e)?"timeout":void 0}var yr=g(()=>{"use strict";Ug()});function p2(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=a2;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,c2)}let a=l2;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,d2)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Xg(t,e){return Buffer.byteLength(t,"utf8")<=e?{content:t,truncated:!1}:{content:tr(t,e),truncated:!0}}function f2(t={}){let e=t.fetchFn??globalThis.fetch,n=t.env??process.env,r=t.lookupFn!==void 0?{lookupFn:t.lookupFn}:{};return async(o,s)=>{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 i=p2(o);if("error"in i)return{content:i.error,isError:!0};if(s.aborted){let u=s.reason;return{content:`web_scrape aborted: ${u instanceof Error?u.message:String(u??"aborted")}`,isError:!0}}let a=new AbortController,c=()=>{a.abort(s.reason)},l,d=()=>{let u=a.signal.reason;return u instanceof Error?u.message:String(u??"aborted")};try{if(s.addEventListener("abort",c,{once:!0}),l=setTimeout(()=>{a.abort(new Error(`web_scrape timeout after ${i.timeoutMs}ms`))},i.timeoutMs),i.url!==void 0){let p=await Rg(i.url,r);if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(!p.allowed)return{content:`web_scrape blocked: ${p.reason}`,isError:!0}}if(i.mode==="raw"){let p;try{let h={method:"GET",headers:{"User-Agent":"agent-afk/web_scrape",Accept:"*/*"},signal:a.signal};p=await Bl(e,i.url,h,r)}catch(h){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:h instanceof kt?{content:`web_scrape blocked: ${h.message}`,isError:!0}:{content:`web_scrape network error: ${h instanceof Error?h.message:String(h)}`,isError:!0}}if(!p.ok)return{content:`web_scrape HTTP ${p.status} ${p.statusText||""}`.trimEnd()+` for ${i.url}`,isError:!0};let f;try{f=await p.text()}catch(h){return{content:`web_scrape read error: ${h instanceof Error?h.message:String(h)}`,isError:!0}}let m=Xg(f,i.maxBytes);return{content:m.content,...m.truncated?{truncated:!0}:{}}}if(i.mode==="markdown")try{let p=await nT(i.url,{fetchFn:e,renderFn:t.renderFn,timeoutMs:i.timeoutMs,signal:a.signal,...t.lookupFn!==void 0?{lookupFn:t.lookupFn}:{}});if(p.markdown.trim().length===0)return{content:`web_scrape extracted no readable content from ${i.url}.`,isError:!0};let f=Xg(mE(p.markdown,p.advisory),i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(p instanceof kt)return{content:`web_scrape blocked: ${p.message}`,isError:!0};let f=p instanceof Error?p.message:String(p),m=He(p)&&!Lg(f)?` (the render fallback needs the optional Playwright browser \u2014 run \`${_i()}\`)`:"";return{content:`web_scrape markdown error: ${f}${m}`,isError:!0}}let u=oT({exaApiKey:n.EXA_API_KEY,fetchFn:e});if("error"in u)return{content:u.error,isError:!0};try{let p=await u.search(i.query,{limit:u2,timeoutMs:i.timeoutMs,signal:a.signal}),f=Xg(sT(i.query,p),i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:{content:`web_scrape search error (${u.name}): ${p instanceof Error?p.message:String(p)}`,isError:!0}}}finally{l!==void 0&&clearTimeout(l),s.removeEventListener("abort",c)}}}var a2,c2,l2,d2,u2,aT,cT=g(()=>{"use strict";rT();iT();xg();wn();Ag();yr();a2=3e4,c2=12e4,l2=1e5,d2=1e6,u2=10;aT=f2()});import{existsSync as dT,mkdirSync as m2,readFileSync as g2,renameSync as h2,unlinkSync as y2,writeFileSync as b2}from"node:fs";import{dirname as lT,join as w2}from"node:path";import{randomBytes as S2}from"node:crypto";function br(t){let e=t??_f();if(!dT(e))return[];try{let n=g2(e,"utf-8");return JSON.parse(n)}catch(n){let r=n instanceof Error?n.message:String(n);return console.error(`[schedule-store] failed to parse ${e}: ${r}`),[]}}function Ai(t,e){let n=e??_f();m2(lT(n),{recursive:!0});let r=w2(lT(n),`.schedules.json.${process.pid}.${S2(4).toString("hex")}.tmp`),o=JSON.stringify(t,null,2);try{b2(r,o,"utf-8"),h2(r,n)}catch(s){try{dT(r)&&y2(r)}catch{}throw s}}function uT(t,e){let n=br(e),r=n.map(c=>c.id),o=v2(t.name),s=k2(o,r),i=new Date().toISOString(),a={...t,notifyOn:t.notifyOn??"failure",id:s,createdAt:i,updatedAt:i};return n.push(a),Ai(n,e),a}function pT(t,e){let n=br(e),r=n.length,o=n.filter(s=>s.id!==t);return o.length===r?!1:(Ai(o,e),!0)}function fT(t,e){return br(e).find(n=>n.id===t)}function v2(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}function k2(t,e){if(!e.includes(t))return t;let n=2;for(;e.includes(`${t}-${n}`);)n+=1;return`${t}-${n}`}function mT(t){return{taskId:t.id,command:t.command,trigger:t.trigger??"cron",...t.cron!==void 0?{cronExpression:t.cron}:{},...t.notifyOn!==void 0?{notifyOn:t.notifyOn}:{},...t.notifyChat!==void 0?{notifyChat:t.notifyChat}:{}}}var gT=g(()=>{"use strict";j()});import{existsSync as _2,readFileSync as A2}from"node:fs";import{join as E2}from"node:path";async function vo(t,e,n){let r,o;try{let s=E2(vS("default"),"port");if(!_2(s))return{synced:!1,detail:"daemon-not-detected (no port file)"};let i=A2(s,"utf-8").trim(),a=T2(i);if(!a)return{synced:!1,detail:"daemon-not-detected (invalid port file)"};({host:r,port:o}=a)}catch{return{synced:!1,detail:"daemon-not-detected (unreadable port file)"}}try{let s=r.includes(":")?`[${r}]`:r,i=await fetch(`http://${s}:${o}${e}`,{method:t,headers:{"Content-Type":"application/json"},body:n!==void 0?JSON.stringify(n):void 0,signal:AbortSignal.timeout(2e3)});return i.ok?{synced:!0,detail:"synced"}:t==="POST"&&i.status===409?{synced:!0,detail:"already-registered"}:t==="DELETE"&&i.status===404?{synced:!0,detail:"not-registered"}:{synced:!1,detail:`daemon-rejected (HTTP ${i.status})`}}catch{return{synced:!1,detail:"daemon-unreachable (stale port file or network error)"}}}function T2(t){let e=parseInt(t,10);if(String(e)===t&&!Number.isNaN(e))return e<1||e>65535?null:{host:"localhost",port:e};let n=t.lastIndexOf(":");if(n<1)return null;let r=t.slice(0,n),o=t.slice(n+1);if(!/^\d+$/.test(o))return null;let s=parseInt(o,10);return Number.isNaN(s)||s<1||s>65535||/^:+$/.test(r)?null:{host:r.startsWith("[")&&r.endsWith("]")?r.slice(1,-1):r,port:s}}var zg,hT=g(()=>{"use strict";j();zg="Change saved to schedules.json, but a running daemon (if any) did not pick it up \u2014 it will apply on the next daemon (re)start."});import{existsSync as R2}from"node:fs";import{readFile as x2}from"node:fs/promises";var yT,bT,wT,ST,vT=g(()=>{"use strict";gT();j();hT();yT=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected object",isError:!0};let n=t;if(typeof n.name!="string"||!n.name)return{content:"Invalid input: name required",isError:!0};if(typeof n.command!="string"||!n.command)return{content:"Invalid input: command required",isError:!0};if(typeof n.cron!="string"||!n.cron)return{content:"Invalid input: cron required",isError:!0};let r=n.cron.trim().split(/\s+/);if(r.length!==5&&r.length!==6)return{content:"Invalid input: cron must be a 5 or 6-field expression",isError:!0};let o=n.notifyChat;if(o!==void 0&&typeof o!="number"&&typeof o!="string")return{content:"Invalid input: notifyChat must be a number (chat id) or string (chat id or alias name)",isError:!0};let s=uT({name:n.name,command:n.command,cron:n.cron,trigger:n.trigger??"cron",notifyOn:n.notifyOn,...o!==void 0?{notifyChat:o}:{},enabled:typeof n.enabled=="boolean"?n.enabled:!0}),i=s.enabled?await vo("POST","/tasks",{taskId:s.id,command:s.command,cron:s.cron,trigger:s.trigger,notifyOn:s.notifyOn,...s.notifyChat!==void 0?{notifyChat:s.notifyChat}:{}}):await vo("DELETE",`/tasks/${s.id}`);return{content:JSON.stringify({id:s.id,name:s.name,cron:s.cron,enabled:s.enabled,daemonSynced:i.synced,syncDetail:i.detail,...i.synced?{}:{syncNote:zg}})}},bT=async(t,e)=>{let n=br();return{content:JSON.stringify(n.map(r=>({id:r.id,name:r.name,cron:r.cron,trigger:r.trigger,enabled:r.enabled,notifyOn:r.notifyOn})))}},wT=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected object",isError:!0};let n=t;if(typeof n.taskId!="string"||!n.taskId)return{content:"Invalid input: taskId required",isError:!0};let r=n.taskId,o=typeof n.limit=="number"?Math.min(Math.max(1,n.limit),50):10,s=tc();if(!R2(s))return{content:JSON.stringify([])};let i;try{let l=await x2(s);i=(l.length>1048576?l.subarray(l.length-1048576):l).toString("utf-8")}catch{return{content:JSON.stringify([])}}let a=i.split(`
|
|
@@ -1058,7 +1072,7 @@ On your first turn, decide whether to call memory_search based on the request:
|
|
|
1058
1072
|
- If hot memory (shown in <cross-session-memory> tags above) already covers the relevant context, skip the search.
|
|
1059
1073
|
- Search at most once per session for general context. Search again only if new information surfaces a specific topic worth querying.
|
|
1060
1074
|
|
|
1061
|
-
Use FTS5 syntax: "exact phrase", term1 AND term2, prefix*.`});function Bi(t,e){let n=(u,p)=>{if(!(u==null&&p==null))return(u??0)+(p??0)},r=(u,p)=>p!==void 0?p:u,o={stopReason:e.stopReason??t.stopReason??null,...e.raw!==void 0?{raw:e.raw}:t.raw!==void 0?{raw:t.raw}:{}},s=n(t.inputTokens,e.inputTokens);s!==void 0&&(o.inputTokens=s);let i=n(t.outputTokens,e.outputTokens);i!==void 0&&(o.outputTokens=i);let a=r(t.cachedInputTokens,e.cachedInputTokens);a!==void 0&&(o.cachedInputTokens=a);let c=r(t.cacheCreationTokens,e.cacheCreationTokens);c!==void 0&&(o.cacheCreationTokens=c);let l=n(t.totalTokens,e.totalTokens);l!==void 0&&(o.totalTokens=l);let d=n(t.totalCostUsd,e.totalCostUsd);return d!==void 0&&(o.totalCostUsd=d),o}var Zh=g(()=>{"use strict"});function Wd(){try{let t=ji();return Promise.resolve(t.map(e=>{let n={name:e.name,description:e.description};return e.argumentHint&&(n.argumentHint=e.argumentHint),e.source&&(n.source=e.source),n}))}catch{return Promise.resolve([])}}var ey=g(()=>{"use strict";xn()});var Po,ty=g(()=>{"use strict";V();Po=class{constructor(e,n,r){this.signal=e;this.traceWriter=n;this.provider=r;W(n,{phase:"loop_start"}),this.interruptedAt=e.aborted?Date.now():null,n&&!e.aborted&&e.addEventListener("abort",this.onInterrupt,{once:!0})}signal;traceWriter;provider;interruptedAt;onInterrupt=()=>{this.interruptedAt===null&&(this.interruptedAt=Date.now())};finish(e){this.signal.removeEventListener("abort",this.onInterrupt),this.interruptedAt!==null&&this.signal.reason==="interrupted"&&W(this.traceWriter,{phase:"interrupt_halt",durationMs:Date.now()-this.interruptedAt,metadata:{provider:this.provider}}),W(this.traceWriter,{phase:"loop_end",durationMs:e})}}});import{readFileSync as CJ}from"node:fs";import{homedir as PJ}from"node:os";import{join as lC}from"node:path";function MJ(t){try{return CJ(t,"utf-8")}catch{return null}}function In(t,e={},n=!1){let r=e.readEnv??(d=>process.env[d]),o=(e.homedir??PJ)(),s=e.readFile??MJ;if(n){let d=lC(o,".codex","auth.json"),u=s(d);if(u!==null){let p=dC(u);if(p.kind==="chatgpt"&&p.accessToken){let f={apiKey:p.accessToken,source:"chatgpt-oauth",last4:Mo(p.accessToken)};return p.accountId!==void 0&&(f.accountId=p.accountId),p.expiresAt!==void 0&&(f.expiresAt=p.expiresAt),f}}return{apiKey:null,source:"no-usable-auth-forced-chatgpt-oauth"}}if(t&&t.length>0)return{apiKey:t,source:"config",last4:Mo(t)};let i=r("OPENAI_API_KEY");if(i&&i.length>0)return{apiKey:i,source:"env",last4:Mo(i),envVar:"OPENAI_API_KEY"};let a=r("CODEX_API_KEY");if(a&&a.length>0)return{apiKey:a,source:"env",last4:Mo(a),envVar:"CODEX_API_KEY"};let c=lC(o,".codex","auth.json"),l=s(c);if(l!==null){let d=dC(l);if(d.kind==="apikey")return{apiKey:d.apiKey,source:"codex-cli",last4:Mo(d.apiKey)};if(d.kind==="chatgpt"){if(OJ(r)&&d.accessToken){let u={apiKey:d.accessToken,source:"chatgpt-oauth",last4:Mo(d.accessToken)};return d.accountId!==void 0&&(u.accountId=d.accountId),d.expiresAt!==void 0&&(u.expiresAt=d.expiresAt),u}return{apiKey:null,source:"no-usable-auth-codex-oauth"}}}return{apiKey:null,source:"no-usable-auth"}}function dC(t){let e;try{e=JSON.parse(t)}catch{return{kind:"invalid"}}if(typeof e!="object"||e===null)return{kind:"invalid"};let n=e,r=n.OPENAI_API_KEY;if(typeof r=="string"&&r.length>0)return{kind:"apikey",apiKey:r};let o=n.tokens,s=typeof o=="object"&&o!==null?o:null,i=s&&typeof s.access_token=="string"?s.access_token:void 0;if(n.auth_mode==="chatgpt"||i){let a={kind:"chatgpt"};if(i&&(a.accessToken=i),s){let c=DJ(s);c!==void 0&&(a.accountId=c);let l=FJ(s);l!==void 0&&(a.expiresAt=l)}return a}return{kind:"no-key"}}function Mo(t){return t.length<=4?t:t.slice(-4)}function OJ(t){let e=t("AFK_OPENAI_CHATGPT_OAUTH");if(!e)return!1;let n=e.trim().toLowerCase();return n==="1"||n==="true"||n==="yes"||n==="on"}function uC(t){let e=t.split(".");if(e.length<2||!e[1])return null;try{let n=Buffer.from(e[1],"base64url").toString("utf-8"),r=JSON.parse(n);return typeof r=="object"&&r!==null?r:null}catch{return null}}function DJ(t){let e=t.account_id;if(typeof e=="string"&&e.length>0)return e;for(let n of["access_token","id_token"]){let r=t[n];if(typeof r!="string")continue;let o=uC(r);if(!o)continue;let s=o["https://api.openai.com/auth"];if(typeof s=="object"&&s!==null){let a=s.chatgpt_account_id;if(typeof a=="string"&&a.length>0)return a}let i=o.chatgpt_account_id;if(typeof i=="string"&&i.length>0)return i}}function FJ(t){let e=t.access_token;if(typeof e!="string")return;let n=uC(e)?.exp;return typeof n=="number"?n:void 0}function LJ(t){if(typeof t!="number")return"";let e=t-Math.floor(Date.now()/1e3);if(e<=0)return", EXPIRED \u2014 re-run `codex` to refresh";let n=Math.floor(e/3600),r=Math.floor(e%3600/60);return`, expires in ${n>0?`${n}h `:""}${r}m`}function ny(t){switch(t.source){case"config":return`using explicit AFK config API key (\u2026${t.last4??"????"})`;case"env":return`using ${t.envVar??"OPENAI_API_KEY"} env var (\u2026${t.last4??"????"})`;case"codex-cli":return`using Codex CLI API key from ~/.codex/auth.json (\u2026${t.last4??"????"})`;case"chatgpt-oauth":{let e=t.accountId?`\u2026${t.accountId.slice(-4)}`:"unknown",n=LJ(t.expiresAt);return`using ChatGPT subscription OAuth from ~/.codex/auth.json (account ${e}${n})`}case"no-usable-auth-codex-oauth":return"Found ChatGPT/OAuth credentials in ~/.codex/auth.json but the OpenAI provider is in API-key mode. To use your ChatGPT subscription, set AFK_OPENAI_CHATGPT_OAUTH=1 (read-only; AFK will not refresh the token \u2014 re-run `codex` when it expires). Otherwise run `codex login --api-key` or set OPENAI_API_KEY.";case"no-usable-auth-forced-chatgpt-oauth":return"This model's slot is configured provider: 'chatgpt-oauth' but no ChatGPT-subscription token was found in ~/.codex/auth.json. Sign in with `codex` using ChatGPT (not API-key mode), or change the slot to provider: 'openai' with a key. (read-only; AFK will not refresh the token \u2014 re-run `codex` when it expires).";default:return"No OpenAI auth found. Set OPENAI_API_KEY, pass an explicit apiKey in AFK config, or run `codex login --api-key`."}}var Hi=g(()=>{"use strict"});function Kd(t,e,n){let r=t.lastIndexOf(pC);if(r===-1)return t;let o=t.indexOf(`
|
|
1075
|
+
Use FTS5 syntax: "exact phrase", term1 AND term2, prefix*.`});function Bi(t,e){let n=(u,p)=>{if(!(u==null&&p==null))return(u??0)+(p??0)},r=(u,p)=>p!==void 0?p:u,o={stopReason:e.stopReason??t.stopReason??null,...e.raw!==void 0?{raw:e.raw}:t.raw!==void 0?{raw:t.raw}:{}},s=n(t.inputTokens,e.inputTokens);s!==void 0&&(o.inputTokens=s);let i=n(t.outputTokens,e.outputTokens);i!==void 0&&(o.outputTokens=i);let a=r(t.cachedInputTokens,e.cachedInputTokens);a!==void 0&&(o.cachedInputTokens=a);let c=r(t.cacheCreationTokens,e.cacheCreationTokens);c!==void 0&&(o.cacheCreationTokens=c);let l=n(t.totalTokens,e.totalTokens);l!==void 0&&(o.totalTokens=l);let d=n(t.totalCostUsd,e.totalCostUsd);return d!==void 0&&(o.totalCostUsd=d),o}var Zh=g(()=>{"use strict"});function Wd(){try{let t=ji();return Promise.resolve(t.map(e=>{let n={name:e.name,description:e.description};return e.argumentHint&&(n.argumentHint=e.argumentHint),e.whenToUse&&(n.whenToUse=e.whenToUse),e.source&&(n.source=e.source),n}))}catch{return Promise.resolve([])}}var ey=g(()=>{"use strict";xn()});var Po,ty=g(()=>{"use strict";V();Po=class{constructor(e,n,r){this.signal=e;this.traceWriter=n;this.provider=r;W(n,{phase:"loop_start"}),this.interruptedAt=e.aborted?Date.now():null,n&&!e.aborted&&e.addEventListener("abort",this.onInterrupt,{once:!0})}signal;traceWriter;provider;interruptedAt;onInterrupt=()=>{this.interruptedAt===null&&(this.interruptedAt=Date.now())};finish(e){this.signal.removeEventListener("abort",this.onInterrupt),this.interruptedAt!==null&&this.signal.reason==="interrupted"&&W(this.traceWriter,{phase:"interrupt_halt",durationMs:Date.now()-this.interruptedAt,metadata:{provider:this.provider}}),W(this.traceWriter,{phase:"loop_end",durationMs:e})}}});import{readFileSync as CJ}from"node:fs";import{homedir as PJ}from"node:os";import{join as lC}from"node:path";function MJ(t){try{return CJ(t,"utf-8")}catch{return null}}function In(t,e={},n=!1){let r=e.readEnv??(d=>process.env[d]),o=(e.homedir??PJ)(),s=e.readFile??MJ;if(n){let d=lC(o,".codex","auth.json"),u=s(d);if(u!==null){let p=dC(u);if(p.kind==="chatgpt"&&p.accessToken){let f={apiKey:p.accessToken,source:"chatgpt-oauth",last4:Mo(p.accessToken)};return p.accountId!==void 0&&(f.accountId=p.accountId),p.expiresAt!==void 0&&(f.expiresAt=p.expiresAt),f}}return{apiKey:null,source:"no-usable-auth-forced-chatgpt-oauth"}}if(t&&t.length>0)return{apiKey:t,source:"config",last4:Mo(t)};let i=r("OPENAI_API_KEY");if(i&&i.length>0)return{apiKey:i,source:"env",last4:Mo(i),envVar:"OPENAI_API_KEY"};let a=r("CODEX_API_KEY");if(a&&a.length>0)return{apiKey:a,source:"env",last4:Mo(a),envVar:"CODEX_API_KEY"};let c=lC(o,".codex","auth.json"),l=s(c);if(l!==null){let d=dC(l);if(d.kind==="apikey")return{apiKey:d.apiKey,source:"codex-cli",last4:Mo(d.apiKey)};if(d.kind==="chatgpt"){if(OJ(r)&&d.accessToken){let u={apiKey:d.accessToken,source:"chatgpt-oauth",last4:Mo(d.accessToken)};return d.accountId!==void 0&&(u.accountId=d.accountId),d.expiresAt!==void 0&&(u.expiresAt=d.expiresAt),u}return{apiKey:null,source:"no-usable-auth-codex-oauth"}}}return{apiKey:null,source:"no-usable-auth"}}function dC(t){let e;try{e=JSON.parse(t)}catch{return{kind:"invalid"}}if(typeof e!="object"||e===null)return{kind:"invalid"};let n=e,r=n.OPENAI_API_KEY;if(typeof r=="string"&&r.length>0)return{kind:"apikey",apiKey:r};let o=n.tokens,s=typeof o=="object"&&o!==null?o:null,i=s&&typeof s.access_token=="string"?s.access_token:void 0;if(n.auth_mode==="chatgpt"||i){let a={kind:"chatgpt"};if(i&&(a.accessToken=i),s){let c=DJ(s);c!==void 0&&(a.accountId=c);let l=FJ(s);l!==void 0&&(a.expiresAt=l)}return a}return{kind:"no-key"}}function Mo(t){return t.length<=4?t:t.slice(-4)}function OJ(t){let e=t("AFK_OPENAI_CHATGPT_OAUTH");if(!e)return!1;let n=e.trim().toLowerCase();return n==="1"||n==="true"||n==="yes"||n==="on"}function uC(t){let e=t.split(".");if(e.length<2||!e[1])return null;try{let n=Buffer.from(e[1],"base64url").toString("utf-8"),r=JSON.parse(n);return typeof r=="object"&&r!==null?r:null}catch{return null}}function DJ(t){let e=t.account_id;if(typeof e=="string"&&e.length>0)return e;for(let n of["access_token","id_token"]){let r=t[n];if(typeof r!="string")continue;let o=uC(r);if(!o)continue;let s=o["https://api.openai.com/auth"];if(typeof s=="object"&&s!==null){let a=s.chatgpt_account_id;if(typeof a=="string"&&a.length>0)return a}let i=o.chatgpt_account_id;if(typeof i=="string"&&i.length>0)return i}}function FJ(t){let e=t.access_token;if(typeof e!="string")return;let n=uC(e)?.exp;return typeof n=="number"?n:void 0}function LJ(t){if(typeof t!="number")return"";let e=t-Math.floor(Date.now()/1e3);if(e<=0)return", EXPIRED \u2014 re-run `codex` to refresh";let n=Math.floor(e/3600),r=Math.floor(e%3600/60);return`, expires in ${n>0?`${n}h `:""}${r}m`}function ny(t){switch(t.source){case"config":return`using explicit AFK config API key (\u2026${t.last4??"????"})`;case"env":return`using ${t.envVar??"OPENAI_API_KEY"} env var (\u2026${t.last4??"????"})`;case"codex-cli":return`using Codex CLI API key from ~/.codex/auth.json (\u2026${t.last4??"????"})`;case"chatgpt-oauth":{let e=t.accountId?`\u2026${t.accountId.slice(-4)}`:"unknown",n=LJ(t.expiresAt);return`using ChatGPT subscription OAuth from ~/.codex/auth.json (account ${e}${n})`}case"no-usable-auth-codex-oauth":return"Found ChatGPT/OAuth credentials in ~/.codex/auth.json but the OpenAI provider is in API-key mode. To use your ChatGPT subscription, set AFK_OPENAI_CHATGPT_OAUTH=1 (read-only; AFK will not refresh the token \u2014 re-run `codex` when it expires). Otherwise run `codex login --api-key` or set OPENAI_API_KEY.";case"no-usable-auth-forced-chatgpt-oauth":return"This model's slot is configured provider: 'chatgpt-oauth' but no ChatGPT-subscription token was found in ~/.codex/auth.json. Sign in with `codex` using ChatGPT (not API-key mode), or change the slot to provider: 'openai' with a key. (read-only; AFK will not refresh the token \u2014 re-run `codex` when it expires).";default:return"No OpenAI auth found. Set OPENAI_API_KEY, pass an explicit apiKey in AFK config, or run `codex login --api-key`."}}var Hi=g(()=>{"use strict"});function Kd(t,e,n){let r=t.lastIndexOf(pC);if(r===-1)return t;let o=t.indexOf(`
|
|
1062
1076
|
`,r+pC.length);if(o===-1)return t;let s=o+1;if(!t.startsWith(ry,s))return t;let i=t.indexOf(`
|
|
1063
1077
|
`,s),a=i===-1?t.length:i,c=t.slice(s+ry.length,a),l=cl(e??new Date,n);return c===l?t:t.slice(0,s+ry.length)+l+t.slice(a)}var pC,ry,oy=g(()=>{"use strict";Oe();pC=`# Environment
|
|
1064
1078
|
- Working directory: `,ry="- Date: "});function NJ(t,e){let n=e===1?"An image was":`${e} images were`,r=e===1?"an image":"images",o=e===1?"it":"them",s=t&&t.trim().length>0?`the current model ("${t.trim()}")`:"the current model";return`[${n} attached to this message, but ${s} cannot view images. Acknowledge to the user that you received ${r} but are unable to see ${o}, and suggest switching to a vision-capable model (e.g. gpt-4o or a Claude model).]`}function UJ(t){let e=t.source;return e.type==="base64"?`data:${e.media_type};base64,${e.data}`:e.type==="url"?e.url:null}function fC(t,e){if(typeof t=="string")return t;let n=[],r=0;for(let i of t)if(typeof i=="object"&&i&&"type"in i){if(i.type==="text")n.push(i.text);else if(i.type==="image")r+=1;else if(i.type==="document"){let a=i,c=a.title??"document",l=a.source;if(l&&l.type==="text")n.push(`[Document: ${c}]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-afk",
|
|
3
|
-
"version": "5.167.
|
|
3
|
+
"version": "5.167.3",
|
|
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
|
"types": "dist/index.d.ts",
|