agent-afk 5.152.4 → 5.153.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/code-block-register.d.ts +2 -0
- package/dist/cli.mjs +501 -493
- package/dist/index.mjs +1 -1
- package/dist/telegram.mjs +11 -3
- package/package.json +1 -1
package/dist/telegram.mjs
CHANGED
|
@@ -281,7 +281,7 @@ ${o}`,paths:[e,n]}:o!==null?s={content:o,paths:[n]}:r!==null?s={content:r,paths:
|
|
|
281
281
|
|
|
282
282
|
${e}`}var O1,mg=g(()=>{"use strict";O1=new Set(["script","style","noscript","template","svg"])});function L1(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 K_(t,e,n){let r=Math.min(e*2**t,n);return Math.round(Math.random()*r)}function N1(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 G_(t,e,n={},r={}){let o=r.retries??3,s=r.baseDelayMs??500,i=r.maxDelayMs??1e4,a=r.sleep??L1,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(!F1.has(u.status)||d===o)return u;let p=N1(u,i)??K_(d,s,i);M("[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=K_(d,s,i);M("[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 F1,q_=g(()=>{"use strict";oe();F1=new Set([429,502,503,504])});import{BlockList as U1,isIP as hg}from"node:net";import{lookup as $1}from"node:dns/promises";import{Agent as B1}from"undici";function z_(){let t=S.AFK_WEB_ALLOW_PRIVATE_HOSTS?.trim().toLowerCase();return t==="1"||t==="true"}function K1(t){return t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t}function gg(t){let e=hg(t);return e===0?!1:W1.check(t,e===4?"ipv4":"ipv6")}async function V_(t){return $1(t,{all:!0,verbatim:!0})}async function yg(t,e={}){if(e.allowPrivateHosts??z_())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=K1(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(hg(r)!==0)return gg(r)?{allowed:!1,reason:o(r,r)}:{allowed:!0};let s=e.lookupFn??V_,i;try{i=await s(r)}catch{return{allowed:!0}}for(let a of i)if(gg(a.address))return{allowed:!1,reason:o(a.address,`${r} (resolved)`)};return{allowed:!0}}async function fi(t,e={}){let n=await yg(t,e);if(!n.allowed)throw new St(n.reason)}async function Ml(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<=X_;i++){await fi(s,o);let a={...n,redirect:"manual",...t===globalThis.fetch&&!(r.allowPrivateHosts??z_())?{dispatcher:G1}:{}},c=await G_(t,s,a,r.retry??{});if(!q1.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 St(`too many redirects (>${X_}) starting from ${e}`)}var j1,H1,W1,St,G1,X_,q1,bg=g(()=>{"use strict";U();q_();j1=[["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]],H1=[["::",96],["64:ff9b::",96],["fc00::",7],["fe80::",10]],W1=(()=>{let t=new U1;for(let[e,n]of j1)t.addSubnet(e,n,"ipv4");for(let[e,n]of H1)t.addSubnet(e,n,"ipv6");return t})(),St=class extends Error{constructor(e){super(e),this.name="EgressBlockedError"}};G1=new B1({connect:{lookup(t,e,n){V_(t).then(r=>{let o=r.find(i=>gg(i.address));if(o!==void 0){n(new St(`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,hg(s.address))},r=>n(r,"",0))}}});X_=20,q1=new Set([301,302,303,307,308])});import{readFileSync as X1}from"node:fs";import{join as z1}from"path";function V1(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function J_(t,e){return V1(e).test(t)}function Q1(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(J1.has(e))return!0;if(Y1.has(e))return!1}return!1}function Y_(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function Z1(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function Q_(t){let e=t===void 0||t.trim()===""?"default":t.trim();return bf(e),e}function eG(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function tG(t){try{return X1(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function nG(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return typeof e.defaultProfile=="string"&&(n.defaultProfile=Q_(e.defaultProfile)),n}function Z_(t){let e=t?.env??S,n=t?.readFileSync??tG,r=t?.surface??e.AGENT_SURFACE,o=Q1(e.AFK_BROWSER_HEADLESS,r),s=Y_(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Y_(e.AFK_BROWSER_BLOCKED_DOMAINS),a=eG(e.AFK_BROWSER_DOM_SNAPSHOTS),c=Z1(e.AFK_BROWSER_BACKEND),l=Q_(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():z1(Gt(),"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=nG(d,m);return h.configPath=p,h}function Ol(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(J_(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>J_(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var J1,Y1,Dl=g(()=>{"use strict";U();j();J1=new Set(["daemon","subagent","telegram","afk"]),Y1=new Set(["repl","interactive","cli"])});import{existsSync as rG,readFileSync as oG}from"node:fs";import{createRequire as sG}from"node:module";import{dirname as iG,join as aG}from"node:path";function nE(t){if(typeof t=="string")return t;let e=[],n=t;for(let r=0;r<lG&&n instanceof Error;r++)e.push(n.message),n=n.cause;return e.length>0?e.join(" | "):String(t)}function He(t){let e=nE(t);return tE.some(n=>e.includes(n))}function dG(){try{let e=sG(import.meta.url).resolve("playwright/package.json"),n=JSON.parse(oG(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=aG(iG(e),o);return rG(s)?`node ${/\s/.test(s)?`"${s}"`:s} install chromium`:void 0}catch{return}}function mi(){return eE??=dG()??cG,eE}function wg(t){return t.includes("install chromium")}function at(t,e){let n=nE(t),r=e?.latched===!0?` ${uG}`:"";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: ${mi()}.${o}${r}`}return`browser tools require the optional \`playwright\` peer dependency. Install via: pnpm add playwright (then ${mi()}). Or pick a different tool.${r}`}function Sg(t,e,n=!1){if(!He(t))return t;let r=t instanceof Error?t.message:String(t);return new Error(`${r}
|
|
283
283
|
|
|
284
|
-
${at(t,{headless:e,latched:n})}`,{cause:t})}var tE,cG,lG,eE,uG,vg=g(()=>{"use strict";tE=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],cG="pnpm exec playwright install chromium",lG=4;uG="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 ur from"node:fs";import Fl from"node:path";import{randomBytes as pG}from"node:crypto";import{chromium as fG}from"playwright";function mG(){try{return"5.152.4"}catch{}try{let t=Fl.resolve(import.meta.dirname,"../../../package.json"),e=ur.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var gG,Ll,rE=g(()=>{"use strict";vg();j();oe();gG=mG(),Ll=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=fG.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=Sg(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/${gG}`}}loadStorageState(e){let n=wf(e);try{if(!ur.existsSync(n))return;let r=JSON.parse(ur.readFileSync(n,"utf8"));return M("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){M("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=wf(e);if(!ur.existsSync(r))return;let o=await n.storageState(),s=Fl.join(Fl.dirname(r),`.${Fl.basename(r)}.${process.pid}.${pG(4).toString("hex")}.tmp`);ur.writeFileSync(s,JSON.stringify(o),{mode:384}),ur.chmodSync(s,384),ur.renameSync(s,r),M("[browser/vault] saved session",{profile:e,file:r})}catch(r){M("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as hG}from"crypto";function oE(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&yG.test(t.label))}function sE(t){return hG("sha256").update(t,"utf8").digest("hex").slice(0,8)}function iE(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var yG,Nl=g(()=>{"use strict";yG=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as bG}from"node:crypto";function wG(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function SG(t,e,n){return`el_${bG("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function vG(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function aE(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function lE(t,e){let n=t.role??"",r=t.name??"";cE.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])lE(s,e)}async function kG(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},dE).catch(()=>[])}async function AG(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},dE).catch(()=>[])}function _G(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Ul(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=_G(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=kG(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=[],lE(u,y)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,y=(await AG(t)).filter(O=>cE.has(O.role??"")));let k=new Map;for(let C of p){let O=aE(C.name),q=k.get(O);(!q||q.bbox.w===0&&C.bbox.w>0)&&k.set(O,C)}let A=y.map(C=>({ax:C,dom:k.get(aE(C.name??""))})),E=r?A:A.filter(C=>C.dom?C.dom.bbox.w>0||C.dom.bbox.h>0:!0);E.sort((C,O)=>{let q=C.dom?.bbox.y??0,P=O.dom?.bbox.y??0;if(q!==P)return q-P;let $=C.dom?.bbox.x??0,D=O.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,O)=>{let q=C.ax.role??"generic",P=C.ax.name??"",$=SG(q,P,O),D=C.dom?.bbox??{x:0,y:0,w:0,h:0},L=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)),oE({role:q,kind:L})&&(B="[redacted]");let W={disabled:C.ax.disabled??!1};C.ax.checked!==void 0&&(W.checked=C.ax.checked===!0||C.ax.checked==="mixed"),C.ax.selected!==void 0&&(W.selected=C.ax.selected),C.ax.expanded!==void 0&&(W.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:wG(P),kind:L,value:B,state:W,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 R=vG(f),v=`obs_${e.observationCounter.toString(36)}`,_=new Date().toISOString();return{observationId:v,url:m,title:h,textSummary:R,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:_}}var cE,dE,uE=g(()=>{"use strict";Nl();cE=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);dE="a[href], button, input, select, textarea, [role], [tabindex], label"});async function pE(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 kg(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>pE(t,s)))).filter(o=>o!==null)}async function EG(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 Ag(t,e,n){switch(e.kind){case"element_id":return TG(t,e,n);case"selector":return xG(t,e);case"semantic":return RG(t,e)}}async function TG(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 kg(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function xG(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 kg(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function RG(t,e){return e.role!==void 0?IG(t,e.text,e.role):CG(t,e.text,e)}async function IG(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 kg(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function CG(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 EG(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 pE(y.locator,y.index);if(b!==null){let k=`${b.role}:${b.label}:${h}`,A=0;for(let E=0;E<k.length;E++)A=A*31+k.charCodeAt(E)>>>0;f.push({...b,id:`el_${A.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var fE=g(()=>{"use strict"});async function _g(t,e,n,r){let o=t.url();if(o===n)return null;let s=Ol(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 mE=g(()=>{"use strict";Dl()});import{randomBytes as PG}from"crypto";import{mkdir as MG,stat as OG,writeFile as DG}from"fs/promises";import{join as Eg}from"path";import{gzip as FG}from"zlib";import{promisify as LG}from"util";function NG(t){return Eg(xt(t),"browser")}function UG(t){return Eg(NG(t),"screenshots")}function $G(){return new Date().toISOString().replace(/[:.]/g,"-")}function BG(){return PG(3).toString("hex")}async function Tg(t,e,n){if(e.length>gE)throw new Error(`writeScreenshotSidecar: buffer exceeds ${gE} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=UG(t);await MG(r,{recursive:!0});let o=`${$G()}-${BG()}-${n}.png`,s=Eg(r,o);await DG(s,e);let{size:i}=await OG(s);return{path:s,bytes:i}}var Xce,gE,hE=g(()=>{"use strict";j();Nl();Xce=LG(FG);gE=5*1024*1024});var bE={};uf(bE,{PlaywrightProvider:()=>xg});function yE(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 xg,wE=g(()=>{"use strict";rE();uE();fE();Dl();mE();hE();xg=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Ll(e)}async open(e){let n=Ol(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 _g(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 Ul(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 Ul(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 Ag(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${yE(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 _g(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 Ul(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 Ag(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${yE(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 Tg(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 Tg(n,o,r);return s}catch{return null}}}});var fr={};uf(fr,{__resetBrowserRegistryForTests:()=>GG,browserProviderActive:()=>WG,closeBrowserProvider:()=>Rg,getBrowserProvider:()=>HG,peekBrowserProvider:()=>KG});function SE(){Promise.resolve(Rg()).then(()=>{process.exit(130)})}function vE(){Promise.resolve(Rg()).then(()=>{process.exit(143)})}function kE(){Nt=null}function jG(){$l||(process.on("SIGINT",SE),process.on("SIGTERM",vE),process.on("exit",kE),$l=!0)}function AE(){$l&&(process.removeListener("SIGINT",SE),process.removeListener("SIGTERM",vE),process.removeListener("exit",kE),$l=!1)}async function HG(t){return Nt!==null?Nt:(pr!==null||(pr=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(wE(),bE)),n=Z_(t),r=new e(n);return jG(),Nt=r,pr=null,r})()),pr)}async function Rg(){if(Nt===null)return;let t=Nt;Nt=null,pr=null,AE(),await t.shutdown()}function WG(){return Nt!==null}function KG(){return Nt}function GG(){Nt=null,pr=null,AE()}var Nt,pr,$l,mr=g(()=>{"use strict";Dl();Nt=null,pr=null,$l=!1});async function _E(t,e){try{return await j_(t,e)}catch(n){return M("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function YG(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(mr(),fr));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function EE(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??YG,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await Ml(n,t,{headers:JG,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(VG.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(zG.test(p)&&!XG.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await _E(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof St||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=fg({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await fi(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>fi(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await fi(u.finalUrl,o);let p=await _E(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=fg({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 St)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 XG,zG,VG,JG,TE=g(()=>{"use strict";H_();mg();bg();oe();XG=/(text\/html|application\/xhtml\+xml)/i,zG=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,VG=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,JG={"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 eq(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(QG,{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),ZG),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 xE(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?eq({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 RE(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
284
|
+
${at(t,{headless:e,latched:n})}`,{cause:t})}var tE,cG,lG,eE,uG,vg=g(()=>{"use strict";tE=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],cG="pnpm exec playwright install chromium",lG=4;uG="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 ur from"node:fs";import Fl from"node:path";import{randomBytes as pG}from"node:crypto";import{chromium as fG}from"playwright";function mG(){try{return"5.153.0"}catch{}try{let t=Fl.resolve(import.meta.dirname,"../../../package.json"),e=ur.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var gG,Ll,rE=g(()=>{"use strict";vg();j();oe();gG=mG(),Ll=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=fG.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=Sg(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/${gG}`}}loadStorageState(e){let n=wf(e);try{if(!ur.existsSync(n))return;let r=JSON.parse(ur.readFileSync(n,"utf8"));return M("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){M("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=wf(e);if(!ur.existsSync(r))return;let o=await n.storageState(),s=Fl.join(Fl.dirname(r),`.${Fl.basename(r)}.${process.pid}.${pG(4).toString("hex")}.tmp`);ur.writeFileSync(s,JSON.stringify(o),{mode:384}),ur.chmodSync(s,384),ur.renameSync(s,r),M("[browser/vault] saved session",{profile:e,file:r})}catch(r){M("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as hG}from"crypto";function oE(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&yG.test(t.label))}function sE(t){return hG("sha256").update(t,"utf8").digest("hex").slice(0,8)}function iE(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var yG,Nl=g(()=>{"use strict";yG=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as bG}from"node:crypto";function wG(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function SG(t,e,n){return`el_${bG("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function vG(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function aE(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function lE(t,e){let n=t.role??"",r=t.name??"";cE.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])lE(s,e)}async function kG(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},dE).catch(()=>[])}async function AG(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},dE).catch(()=>[])}function _G(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Ul(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=_G(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=kG(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=[],lE(u,y)):(o.push("observation skipped accessibility tree (returned null)"),b=!0,y=(await AG(t)).filter(O=>cE.has(O.role??"")));let k=new Map;for(let C of p){let O=aE(C.name),q=k.get(O);(!q||q.bbox.w===0&&C.bbox.w>0)&&k.set(O,C)}let A=y.map(C=>({ax:C,dom:k.get(aE(C.name??""))})),E=r?A:A.filter(C=>C.dom?C.dom.bbox.w>0||C.dom.bbox.h>0:!0);E.sort((C,O)=>{let q=C.dom?.bbox.y??0,P=O.dom?.bbox.y??0;if(q!==P)return q-P;let $=C.dom?.bbox.x??0,D=O.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,O)=>{let q=C.ax.role??"generic",P=C.ax.name??"",$=SG(q,P,O),D=C.dom?.bbox??{x:0,y:0,w:0,h:0},L=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)),oE({role:q,kind:L})&&(B="[redacted]");let W={disabled:C.ax.disabled??!1};C.ax.checked!==void 0&&(W.checked=C.ax.checked===!0||C.ax.checked==="mixed"),C.ax.selected!==void 0&&(W.selected=C.ax.selected),C.ax.expanded!==void 0&&(W.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:wG(P),kind:L,value:B,state:W,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 R=vG(f),v=`obs_${e.observationCounter.toString(36)}`,_=new Date().toISOString();return{observationId:v,url:m,title:h,textSummary:R,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:_}}var cE,dE,uE=g(()=>{"use strict";Nl();cE=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);dE="a[href], button, input, select, textarea, [role], [tabindex], label"});async function pE(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 kg(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>pE(t,s)))).filter(o=>o!==null)}async function EG(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 Ag(t,e,n){switch(e.kind){case"element_id":return TG(t,e,n);case"selector":return xG(t,e);case"semantic":return RG(t,e)}}async function TG(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 kg(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function xG(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 kg(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function RG(t,e){return e.role!==void 0?IG(t,e.text,e.role):CG(t,e.text,e)}async function IG(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 kg(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function CG(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 EG(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 pE(y.locator,y.index);if(b!==null){let k=`${b.role}:${b.label}:${h}`,A=0;for(let E=0;E<k.length;E++)A=A*31+k.charCodeAt(E)>>>0;f.push({...b,id:`el_${A.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var fE=g(()=>{"use strict"});async function _g(t,e,n,r){let o=t.url();if(o===n)return null;let s=Ol(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 mE=g(()=>{"use strict";Dl()});import{randomBytes as PG}from"crypto";import{mkdir as MG,stat as OG,writeFile as DG}from"fs/promises";import{join as Eg}from"path";import{gzip as FG}from"zlib";import{promisify as LG}from"util";function NG(t){return Eg(xt(t),"browser")}function UG(t){return Eg(NG(t),"screenshots")}function $G(){return new Date().toISOString().replace(/[:.]/g,"-")}function BG(){return PG(3).toString("hex")}async function Tg(t,e,n){if(e.length>gE)throw new Error(`writeScreenshotSidecar: buffer exceeds ${gE} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=UG(t);await MG(r,{recursive:!0});let o=`${$G()}-${BG()}-${n}.png`,s=Eg(r,o);await DG(s,e);let{size:i}=await OG(s);return{path:s,bytes:i}}var Xce,gE,hE=g(()=>{"use strict";j();Nl();Xce=LG(FG);gE=5*1024*1024});var bE={};uf(bE,{PlaywrightProvider:()=>xg});function yE(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 xg,wE=g(()=>{"use strict";rE();uE();fE();Dl();mE();hE();xg=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Ll(e)}async open(e){let n=Ol(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 _g(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 Ul(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 Ul(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 Ag(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${yE(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 _g(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 Ul(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 Ag(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${yE(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 Tg(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 Tg(n,o,r);return s}catch{return null}}}});var fr={};uf(fr,{__resetBrowserRegistryForTests:()=>GG,browserProviderActive:()=>WG,closeBrowserProvider:()=>Rg,getBrowserProvider:()=>HG,peekBrowserProvider:()=>KG});function SE(){Promise.resolve(Rg()).then(()=>{process.exit(130)})}function vE(){Promise.resolve(Rg()).then(()=>{process.exit(143)})}function kE(){Nt=null}function jG(){$l||(process.on("SIGINT",SE),process.on("SIGTERM",vE),process.on("exit",kE),$l=!0)}function AE(){$l&&(process.removeListener("SIGINT",SE),process.removeListener("SIGTERM",vE),process.removeListener("exit",kE),$l=!1)}async function HG(t){return Nt!==null?Nt:(pr!==null||(pr=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(wE(),bE)),n=Z_(t),r=new e(n);return jG(),Nt=r,pr=null,r})()),pr)}async function Rg(){if(Nt===null)return;let t=Nt;Nt=null,pr=null,AE(),await t.shutdown()}function WG(){return Nt!==null}function KG(){return Nt}function GG(){Nt=null,pr=null,AE()}var Nt,pr,$l,mr=g(()=>{"use strict";Dl();Nt=null,pr=null,$l=!1});async function _E(t,e){try{return await j_(t,e)}catch(n){return M("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function YG(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(mr(),fr));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function EE(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??YG,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await Ml(n,t,{headers:JG,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(VG.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(zG.test(p)&&!XG.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await _E(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof St||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=fg({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await fi(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>fi(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await fi(u.finalUrl,o);let p=await _E(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=fg({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 St)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 XG,zG,VG,JG,TE=g(()=>{"use strict";H_();mg();bg();oe();XG=/(text\/html|application\/xhtml\+xml)/i,zG=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,VG=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,JG={"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 eq(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(QG,{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),ZG),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 xE(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?eq({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 RE(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
285
285
|
|
|
286
286
|
(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(`
|
|
287
287
|
`).trimEnd()}var QG,ZG,IE=g(()=>{"use strict";mt();QG="https://api.exa.ai/search",ZG=10});function Bl(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 gr=g(()=>{"use strict";vg()});function iq(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=tq;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,nq)}let a=rq;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,oq)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Ig(t,e){return Buffer.byteLength(t,"utf8")<=e?{content:t,truncated:!1}:{content:er(t,e),truncated:!0}}function aq(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=iq(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 yg(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 Ml(e,i.url,h,r)}catch(h){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:h instanceof St?{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=Ig(f,i.maxBytes);return{content:m.content,...m.truncated?{truncated:!0}:{}}}if(i.mode==="markdown")try{let p=await EE(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=Ig(W_(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 St)return{content:`web_scrape blocked: ${p.message}`,isError:!0};let f=p instanceof Error?p.message:String(p),m=He(p)&&!wg(f)?` (the render fallback needs the optional Playwright browser \u2014 run \`${mi()}\`)`:"";return{content:`web_scrape markdown error: ${f}${m}`,isError:!0}}let u=xE({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:sq,timeoutMs:i.timeoutMs,signal:a.signal}),f=Ig(RE(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 tq,nq,rq,oq,sq,CE,PE=g(()=>{"use strict";TE();IE();bg();yn();mg();gr();tq=3e4,nq=12e4,rq=1e5,oq=1e6,sq=10;CE=aq()});import{existsSync as OE,mkdirSync as cq,readFileSync as lq,renameSync as dq,unlinkSync as uq,writeFileSync as pq}from"node:fs";import{dirname as ME,join as fq}from"node:path";import{randomBytes as mq}from"node:crypto";function hr(t){let e=t??gf();if(!OE(e))return[];try{let n=lq(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 gi(t,e){let n=e??gf();cq(ME(n),{recursive:!0});let r=fq(ME(n),`.schedules.json.${process.pid}.${mq(4).toString("hex")}.tmp`),o=JSON.stringify(t,null,2);try{pq(r,o,"utf-8"),dq(r,n)}catch(s){try{OE(r)&&uq(r)}catch{}throw s}}function DE(t,e){let n=hr(e),r=n.map(c=>c.id),o=gq(t.name),s=hq(o,r),i=new Date().toISOString(),a={...t,notifyOn:t.notifyOn??"failure",id:s,createdAt:i,updatedAt:i};return n.push(a),gi(n,e),a}function FE(t,e){let n=hr(e),r=n.length,o=n.filter(s=>s.id!==t);return o.length===r?!1:(gi(o,e),!0)}function LE(t,e){return hr(e).find(n=>n.id===t)}function gq(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}function hq(t,e){if(!e.includes(t))return t;let n=2;for(;e.includes(`${t}-${n}`);)n+=1;return`${t}-${n}`}function NE(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 UE=g(()=>{"use strict";j()});import{existsSync as yq,readFileSync as bq}from"node:fs";import{join as wq}from"node:path";async function ho(t,e,n){let r,o;try{let s=wq(Zw("default"),"port");if(!yq(s))return{synced:!1,detail:"daemon-not-detected (no port file)"};let i=bq(s,"utf-8").trim(),a=Sq(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 Sq(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 Cg,$E=g(()=>{"use strict";j();Cg="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 vq}from"node:fs";import{readFile as kq}from"node:fs/promises";var BE,jE,HE,WE,KE=g(()=>{"use strict";UE();j();$E();BE=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=DE({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 ho("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 ho("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:Cg}})}},jE=async(t,e)=>{let n=hr();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})))}},HE=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=Ga();if(!vq(s))return{content:JSON.stringify([])};let i;try{let l=await kq(s);i=(l.length>1048576?l.subarray(l.length-1048576):l).toString("utf-8")}catch{return{content:JSON.stringify([])}}let a=i.split(`
|
|
@@ -1432,7 +1432,15 @@ The transcript is not a user channel. AFK users see bridge messages, files, comm
|
|
|
1432
1432
|
|
|
1433
1433
|
## Constraints
|
|
1434
1434
|
|
|
1435
|
-
- **Irreversible actions require explicit recent intent.** Examples: deleting files
|
|
1435
|
+
- **Irreversible actions require explicit recent intent.** Examples: deleting files
|
|
1436
|
+
or branches, force-pushing, dropping data, messaging third parties, calling paid
|
|
1437
|
+
APIs, modifying shared systems, installing OS services or persistent daemons
|
|
1438
|
+
(launchctl, systemctl \u2014 use \`/service-setup\`), or making HTTP requests with
|
|
1439
|
+
side-effects to production APIs (including through localhost proxies).
|
|
1440
|
+
- **Never invoke \`launchctl\`, \`systemctl\`, or write to \`~/Library/LaunchAgents/\`
|
|
1441
|
+
or \`~/.config/systemd/user/\` directly.** Use \`afk service install\` or invoke
|
|
1442
|
+
\`/service-setup\`. Direct invocation produces untracked persistent processes that
|
|
1443
|
+
survive reboots and are not recorded in agent state.
|
|
1436
1444
|
- **Tool schemas are authoritative.** Required fields are required. If a value is unknown, fetch it or ask. Do not guess.
|
|
1437
1445
|
- **Do not skip Observe or Update to save tokens.** Stale-state errors cost more than the tokens saved.
|
|
1438
1446
|
- **Parallelize independent calls; sequence dependent ones.**
|
|
@@ -1621,7 +1629,7 @@ The sub-agent that just finished returned output that reads like **decision-driv
|
|
|
1621
1629
|
Single-pass sub-agent reports are prone to confident hallucination \u2014 polished output that falls apart on re-derivation. Before acting on these conclusions, consider dispatching \`/shadow-verify\`. Independent verifiers will re-derive the 2\u20133 most load-bearing claims from scratch (without seeing the original reasoning) and flag any that don't hold up.
|
|
1622
1630
|
|
|
1623
1631
|
Skip when: the findings are purely exploratory, the sub-agent ran inside an already-verifying orchestrator, the user is about to dismiss the report, or the stakes are low (read-only Q&A).`,S7=h7.map(t=>new RegExp(`(?:^|-)${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?:-|$)`,"i"));function v7(t){return t?S7.some(e=>e.test(t)):!1}function k7(t){return b7.some(e=>e.test(t))}function A7(t){let e=0;for(let n of y7)n.test(t)&&e++;return e}function jN(){let t=!1,e=new Set;return n=>{if(n.event==="Stop")return t=!1,{};if(n.event!=="SubagentStop")return{};let r=n.lastMessage??"";return r.length<600?{}:v7(n.agentType)?{}:k7(r)?{}:A7(r)<2?{}:t||e.has(n.subagentId)?{}:(t=!0,e.add(n.subagentId),{injectContext:w7})}}br();go();var HN=300,_7="ask_question gate: no interactive operator is attached to this surface (no elicitation handler \u2014 daemon/scheduled/one-shot run), so the question cannot be answered now. The operator has been notified asynchronously. Do not re-ask or wait. Choose the most reasonable interpretation, state the assumption explicitly in your final report for async review, and proceed. If no safe assumption exists and the next action would be irreversible, end the turn with a Blocked terminal state naming exactly what the operator must supply.";function E7(t){dr(t).catch(()=>{})}function WN(t={}){let e=t.hasHandler??(()=>Qe.hasHandler()),n=t.notify??E7;return function(o){if(o.event!=="PreToolUse")return{};if(o.toolName!=="ask_question")return{};if(e())return{};try{let i=(typeof o.input=="object"&&o.input!==null?String(o.input.question??""):"").trim(),a=i.length<=HN?i:`${i.slice(0,HN)}\u2026(truncated)`;n(`\u{1F514} AFK question (auto-gated; agent proceeds on a stated assumption):
|
|
1624
|
-
`+(a!==""?a:"(question text unavailable)"))}catch{}return{decision:"block",reason:_7}}}var Pw=[{id:"rm-recursive-force",re:/\brm\s+-(?=[a-z]*r)(?=[a-z]*f)[a-z]+/i,tier:"observe"},{id:"rm-recursive-force-split",re:/\brm\s+-[a-z]*r[a-z]*\s+-[a-z]*f|\brm\s+-[a-z]*f[a-z]*\s+-[a-z]*r/i,tier:"observe"},{id:"rm-recursive-force-long",re:/\brm\s+[^|&;\n]*--recursive\b[^|&;\n]*--force\b|\brm\s+[^|&;\n]*--force\b[^|&;\n]*--recursive\b/i,tier:"observe"},{id:"rm-no-preserve-root",re:/\brm\b[^|&;\n]*--no-preserve-root\b/i,tier:"block",blockReason:"safe-destruct: blocked [rm-no-preserve-root] \u2014 explicit root-wipe flag, irrecoverable; remove the --no-preserve-root flag, or target a non-root path instead."},{id:"git-reset-hard",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*reset\s+--hard\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-reset-hard] \u2014 discards all uncommitted changes irrecoverably; commit or run "git stash" first. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"git-clean-force",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*clean\s+-[a-z]*f|\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*clean\s+[^|&;\n]*--force\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-clean-force] \u2014 deletes untracked files irrecoverably; use "git clean -n" (dry-run) to preview. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"git-push-force",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*push\b[^|&;\n]*--force(?!-)|\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*push\b[^|&;\n]*(?<![\w-])-f\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-push-force] \u2014 rewrites remote history, permanently destructive for all branch consumers; prefer "--force-with-lease" or coordinate with collaborators first.'},{id:"git-branch-force-delete",re:/\bgit\s+branch\s+[^|&;\n]*-D\b/,tier:"observe"},{id:"dd-to-device",re:/\bof=\/dev\/(?!null\b|zero\b|random\b|urandom\b|stdout\b|stderr\b|tty\b)\S/i,tier:"block",blockReason:"safe-destruct: blocked [dd-to-device] \u2014 writing directly to a block device is irrecoverable; verify the target path is a file, not a device node."},{id:"mkfs",re:/\bmkfs(\.\w+)?\b/i,tier:"block",blockReason:"safe-destruct: blocked [mkfs] \u2014 formats a filesystem, irrecoverably destroying all data on the target device; confirm the device path. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it."},{id:"redirect-to-block-device",re:/>\s*\/dev\/(sd|nvme|hd|disk|mmcblk|vd)\w*/i,tier:"block",blockReason:"safe-destruct: blocked [redirect-to-block-device] \u2014 shell redirect to a block device overwrites raw sectors irrecoverably; redirect to a file path instead."},{id:"find-delete",re:/\bfind\b[^|&;\n]*-delete\b|\bfind\b[^|&;\n]*-exec\s+rm\b/i,tier:"observe"},{id:"shred",re:/\bshred\b/i,tier:"block",blockReason:'safe-destruct: blocked [shred] \u2014 overwrites file data irrecoverably, bypassing the filesystem; use "rm" if secure deletion is not required. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"sql-drop-truncate",re:/\b(drop\s+(table|database|schema|index)\b|truncate\s+table\b)/i,tier:"block",blockReason:"safe-destruct: blocked [sql-drop-truncate] \u2014 DDL destructor removes schema objects or all rows without a transaction rollback path; back up or use a migration with a down step. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it."},{id:"sql-delete-from",re:/\bdelete\s+from\b/i,tier:"observe"},{id:"docker-destructive",re:/\bdocker\s+(system\s+prune|volume\s+(rm|prune)|image\s+prune|container\s+prune|network\s+prune)\b|\bdocker\b[^|&;\n]*\brmi?\s+[^|&;\n]*-f/i,tier:"observe"},{id:"kubectl-delete",re:/\bkubectl\s+delete\b/i,tier:"observe"},{id:"terraform-destroy",re:/\bterraform\s+destroy\b/i,tier:"block",blockReason:'safe-destruct: blocked [terraform-destroy] \u2014 tears down live external infrastructure irrecoverably (new apply creates new resources, not the same ones); run "terraform plan -destroy" to preview. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'}];var T7="safe-destruct observe-only: destructive-command attempt",x7="This command was blocked by the safe-destruct hook because it matches an irrecoverable or externally-irreversible operation pattern. The block cannot be self-bypassed. If the destructive action is genuinely required, stop and ask the operator to run it manually, or use a safer alternative named in the block reason above.";function R7(t){if(!t)return[];let e=[];for(let{id:n,re:r}of Pw)r.test(t)&&e.push(n);return e}function KN(){return function(e){if(e.event!=="PreToolUse")return{};if(e.toolName!=="bash")return{};let n=e.input,r=typeof n?.command=="string"?n.command:"";if(!r)return{};let o=R7(r);if(o.length===0)return{};let s=new Map(Pw.map(i=>[i.id,i]));for(let i of o){let a=s.get(i);if(a?.tier==="block")return{decision:"block",reason:a.blockReason,injectContext:x7}}return{decision:"approve",reason:`${T7} [${o.join(", ")}]`}}}var Mw=[{id:"npm-publish",re:/\bnpm\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [npm-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"pnpm-publish",re:/\bpnpm\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [pnpm-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"yarn-publish",re:/\byarn\s+(?:npm\s+)?publish\b/i,tier:"block",blockReason:"release-boundary: blocked [yarn-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"cargo-publish",re:/\bcargo\s+(?:--[\w-]+\s+)*publish\b/i,tier:"block",blockReason:"release-boundary: blocked [cargo-publish] \u2014 publishes a crate to crates.io, externally irreversible (crates.io does not allow un-publishing); verify Cargo.toml version and changelog."},{id:"pypi-twine-upload",re:/\btwine\s+upload\b/i,tier:"block",blockReason:"release-boundary: blocked [pypi-twine-upload] \u2014 uploads a package to PyPI, externally irreversible once consumed; verify setup.py/pyproject.toml version and changelog."},{id:"poetry-publish",re:/\bpoetry\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [poetry-publish] \u2014 publishes a package to PyPI, externally irreversible once consumed; verify pyproject.toml version and changelog."},{id:"gem-push",re:/\bgem\s+push\b/i,tier:"block",blockReason:"release-boundary: blocked [gem-push] \u2014 pushes a gem to RubyGems, externally irreversible once consumed; verify gemspec version and changelog."},{id:"docker-push",re:/\bdocker\s+(?:image\s+)?push\b/i,tier:"block",blockReason:"release-boundary: blocked [docker-push] \u2014 pushes a container image to a registry, externally irreversible once pulled by consumers; verify image tag and contents."},{id:"gh-release-create",re:/\bgh\s+release\s+create\b/i,tier:"block",blockReason:"release-boundary: blocked [gh-release-create] \u2014 creates a GitHub release, externally visible and triggering downstream workflows; verify release notes and tag."},{id:"terraform-apply",re:/\bterraform\s+apply\b/i,tier:"block",blockReason:'release-boundary: blocked [terraform-apply] \u2014 applies infrastructure changes to live systems, externally irreversible (new apply creates different resources); run "terraform plan" to preview first.'},{id:"kubectl-apply",re:/\bkubectl\s+apply\b/i,tier:"block",blockReason:"release-boundary: blocked [kubectl-apply] \u2014 applies resources to a live Kubernetes cluster, externally irreversible for stateful workloads; verify manifests and target namespace."},{id:"git-push-mirror",re:/\bgit\s+push\b[^|&;\n]*--mirror\b/i,tier:"observe"},{id:"git-push-tags",re:/\bgit\s+push\b[^|&;\n]*--(?:tags|follow-tags)\b/i,tier:"observe"}];var GN="release-boundary observe-only: sync-boundary command",I7="This command was blocked by the release-boundary hook because it crosses an externally-irreversible publish or deploy boundary. Once a package is published, a container pushed, a release cut, or infrastructure applied, the external state change cannot be undone by the agent. Verify that all living artifacts (changelog, version, generated docs, lock files) are up-to-date before proceeding, and ask the operator to confirm publication.";function C7(t){return/--dry-run\b/i.test(t)||/-refresh-only\b/i.test(t)}function P7(t){let e=t.replace(/'[^']*'/g,"");return e=e.replace(/#[^\n]*/g,""),e}function M7(t){if(!t)return[];let e=P7(t),n=[];for(let{id:r,re:o}of Mw)o.test(e)&&n.push(r);return n}function O7(t){return Mw.find(e=>e.id===t)}function qN(){return function(e){if(e.event!=="PreToolUse")return{};if(e.toolName!=="bash")return{};let n=e.input,r=typeof n?.command=="string"?n.command:"";if(!r)return{};let o=M7(r);if(o.length===0)return{};if(C7(r))return{decision:"approve",reason:`${GN} [${o.join(", ")}] (dry-run: not blocked)`};for(let s of o){let i=O7(s);if(i?.tier==="block")return{decision:"block",reason:i.blockReason,injectContext:I7}}return{decision:"approve",reason:`${GN} [${o.join(", ")}]`}}}Rt();Ki();cm();function XN(t){return function(n){if(n.event!=="PreToolUse")return{};if(n.parentSessionId)return{};if(t()!=="plan")return{};let{toolName:r}=n;if(uu(r)==="write")return{decision:"block",reason:`plan mode: ${r} is refused. Use /plan off to exit plan mode.`};if(r==="worktree"){let o=typeof n.input=="object"&&n.input!==null?String(n.input.action??""):"";if(o!=="list")return{decision:"block",reason:`plan mode: worktree "${o}" is refused (mutates the worktree registry). Only action "list" is allowed in plan mode. Use /plan off to act.`}}if(r==="bash"){let o=typeof n.input=="object"&&n.input!==null?String(n.input.command??""):"",s=Zc(o);if(s.mutating)return{decision:"block",reason:`plan mode: bash refused \u2014 command looks state-mutating (${s.reason??"mutation detected"}). Read-only investigation (git status/log/diff, ls, cat, grep, find) is allowed. Use /plan off to act.`}}return{}}}import ms from"path";no();Ki();import zN from"path";var D7=["rm -rf","rm ","sudo","eval ","chmod","chown","git push --force","git push -f","git reset --hard","mkfs","fdisk","diskutil eraseDisk","dd if=","dd of=","| sh","| bash","|sh","|bash"],F7=["git push","git reset","git commit","git stash drop","git stash clear","npm install","pnpm install","yarn","pip install","apt ","apt-get ","brew install","tee "," > "," >> ","mv ","cp ","mkdir","touch","pnpm build","tsc ","eslint --fix"],L7=["pnpm test","vitest","jest","pytest","cargo test","go test","git status","git log","git diff","git show","ls ","cat ","head ","tail ","find ","grep ","echo ","printf "];function N7(t){return typeof t=="object"&&t!==null&&"command"in t?String(t.command??""):typeof t=="string"?t:""}function U7(t){if(typeof t!="object"||t===null)return"";let e=t;return typeof e.file_path=="string"?e.file_path:typeof e.path=="string"?e.path:""}function $7(t){for(let e of D7)if(t.includes(e))return"high";for(let e of F7)if(t.includes(e))return"medium";for(let e of L7)if(t.includes(e))return"safe";return"medium"}function B7(t,e){if(!t)return"safe";let n=De(zN.resolve(e.cwd,t)),r=Om();for(let o of r)if(n===o||n.startsWith(o+"/"))return"high";if(n.includes("/.git/"))return"high";if(e.workspaceRoot!==void 0){let o=De(e.workspaceRoot);if(zN.relative(o,n).startsWith(".."))return"high"}return n.includes("/node_modules/")?"medium":"safe"}var j7=new Set(["delete","drop","remove","destroy","truncate","purge","wipe","write","create","update","insert","upsert","patch","rename","exec","execute","run","eval","send","push","publish","deploy","post","merge","rollback","reset","terminate","provision","scale","disable","charge","refund","revoke"]);function H7(t){return t.split("__").slice(1).join("__").split(/[_-]+/).filter(Boolean)}function VN(t,e,n){let r=t.toLowerCase();if(r==="bash"){let o=N7(e);return $7(o)}if(r==="write_file"||r==="edit_file"){let o=U7(e);return B7(o,n)}if(uu(t)==="read")return"safe";if(r==="send_telegram")return"medium";if(r.startsWith("mcp__"))return H7(r).some(s=>j7.has(s))?"high":"medium";if(r==="create_schedule"||r==="cancel_schedule")return"high";if(r==="worktree"){let o=typeof e=="object"&&e!==null?e:{},s=typeof o.action=="string"?o.action:"";return s==="list"?"safe":s==="remove"&&o.force===!0?"high":"medium"}return r==="browser_act"||r==="browser_open"||r==="web_scrape"?"medium":"safe"}br();V();Ti();Ph();no();import Ow from"path";import{lstatSync as W7}from"fs";import{spawnSync as K7}from"child_process";var G7=new Set(["node_modules","dist","build",".next","coverage",".cache","__pycache__",".turbo",".parcel-cache","out","target"]),q7=/[*?$`(){};|&<>'"\\\r\n]/;function X7(t){return t==="--recursive"?!0:t.startsWith("--")?!1:/^-[A-Za-z]+$/.test(t)&&/[rR]/.test(t)}function z7(t){if(!/^rm\b/.test(t)||q7.test(t))return null;let e=t.trim().split(/\s+/),n=[],r=!1,o=!1;for(let s of e.slice(1)){if(!o&&s==="--"){o=!0;continue}if(!o&&s.startsWith("-")){X7(s)&&(r=!0);continue}n.push(s)}return n.length===0?null:{targets:n,recursive:r}}function V7(t,e){try{return W7(t).isDirectory()?K7("git",["check-ignore","--quiet","--",t],{cwd:e,stdio:"ignore"}).status===0:!1}catch(n){return n.code==="ENOENT"}}function JN(t,e,n){let r=z7(t);if(r===null||!r.recursive)return!1;let o=De(n);for(let s of r.targets){if(s==="/"||s==="."||s===".."||s==="~"||s.startsWith("~/")||s==="$HOME"||s.startsWith("$HOME/")||s===".git"||s.startsWith(".git/"))return!1;let i=De(Ow.resolve(e,s));if(i===o||!i.startsWith(o+Ow.sep)||!G7.has(Ow.basename(i))||!V7(i,o))return!1}return!0}var J7=3e5,YN=300;function QN(t,e,n,r){let o=r?.approvalTimeoutMs??J7,s=r?.promptForApproval??!0,i=r?.traceWriter,a=r?.sessionId,c=r?.route??((d,u)=>Qe.route(d,u));async function l(d,u,p,f){let m=Date.now(),h=Y7(d,u),y=new AbortController,b=()=>y.abort();p&&(p.aborted?y.abort():p.addEventListener("abort",b,{once:!0}));let k=Symbol("afk-approval-timeout"),A,E,x=new Promise(v=>{E=()=>{A||(A=setTimeout(()=>{y.abort(),v(k)},o),A.unref?.())}});function T(v,_){let C=Date.now()-m,O=v.decision==="block";return ot(i,{hookEvent:"PreToolUse",...O?{decision:"block"}:{},...O&&v.reason!==void 0?{reason:v.reason}:{},...O?{blockedTool:d}:{},durationMs:C,approvalOutcome:_}),v}let I;try{let v=f??a;I=await Promise.race([c(h,{signal:y.signal,onActive:E,...v!==void 0?{sessionId:v}:{}}),x])}finally{A&&clearTimeout(A),p&&p.removeEventListener("abort",b)}if(I===k)return T(Wa(d,`no approval arrived within ${Math.round(o/1e3)}s`),"timeout");if(I.action!=="accept")return T(Wa(d,I.action==="cancel"?"the operator cancelled the approval prompt":"no operator approval was available"),I.action==="cancel"?"cancel":"decline");let R=String(I.content?.choice??"").toLowerCase();return R==="approve"?T({},"approved"):R==="deny"?T(Wa(d,"the operator denied it"),"denied"):T(Wa(d,"the approval prompt returned an unrecognised choice"),"unrecognised")}return function(u,p){if(u.event!=="PreToolUse")return{};if(t()!=="autonomous")return{};let{toolName:f}=u,m=Date.now();if(f==="send_telegram")return{};let h=n?.()??e??process.cwd(),y=u.cwd,b=y??h,A=(y!==void 0?Z7(y,h):void 0)??h,E=VN(f,u.input,{cwd:b,workspaceRoot:A});if(E==="high"&&f==="bash"){let x=typeof u.input=="object"&&u.input!==null&&"command"in u.input?String(u.input.command??""):"";if(x&&JN(x,b,A))return ot(i,{hookEvent:"PreToolUse",blockedTool:f,durationMs:Date.now()-m,approvalOutcome:"carve-out"}),{}}if(E!=="high")return{};if(u.parentSessionId!==void 0||!s){let x=Wa(f,"AFK mode runs autonomously without a human watching");return ot(i,{hookEvent:"PreToolUse",decision:"block",...x.reason!==void 0?{reason:x.reason}:{},blockedTool:f,durationMs:Date.now()-m,approvalOutcome:"hard-block"}),x}return l(f,u.input,p,u.sessionId)}}function Y7(t,e){let n=Q7(e);return{serverName:"agent-afk",message:`AFK: \`${t}\` is high-risk / irreversible and AFK mode runs unattended. Approve this single call?`+(n?`
|
|
1632
|
+
`+(a!==""?a:"(question text unavailable)"))}catch{}return{decision:"block",reason:_7}}}var Pw=[{id:"rm-recursive-force",re:/\brm\s+-(?=[a-z]*r)(?=[a-z]*f)[a-z]+/i,tier:"observe"},{id:"rm-recursive-force-split",re:/\brm\s+-[a-z]*r[a-z]*\s+-[a-z]*f|\brm\s+-[a-z]*f[a-z]*\s+-[a-z]*r/i,tier:"observe"},{id:"rm-recursive-force-long",re:/\brm\s+[^|&;\n]*--recursive\b[^|&;\n]*--force\b|\brm\s+[^|&;\n]*--force\b[^|&;\n]*--recursive\b/i,tier:"observe"},{id:"rm-no-preserve-root",re:/\brm\b[^|&;\n]*--no-preserve-root\b/i,tier:"block",blockReason:"safe-destruct: blocked [rm-no-preserve-root] \u2014 explicit root-wipe flag, irrecoverable; remove the --no-preserve-root flag, or target a non-root path instead."},{id:"git-reset-hard",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*reset\s+--hard\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-reset-hard] \u2014 discards all uncommitted changes irrecoverably; commit or run "git stash" first. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"git-clean-force",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*clean\s+-[a-z]*f|\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*clean\s+[^|&;\n]*--force\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-clean-force] \u2014 deletes untracked files irrecoverably; use "git clean -n" (dry-run) to preview. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"git-push-force",re:/\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*push\b[^|&;\n]*--force(?!-)|\bgit\s+(?:(?:-{2}[\w-]+(?:=\S+)?|-[A-Za-z](?:\s+\S+)?)\s+)*push\b[^|&;\n]*(?<![\w-])-f\b/i,tier:"block",blockReason:'safe-destruct: blocked [git-push-force] \u2014 rewrites remote history, permanently destructive for all branch consumers; prefer "--force-with-lease" or coordinate with collaborators first.'},{id:"git-branch-force-delete",re:/\bgit\s+branch\s+[^|&;\n]*-D\b/,tier:"observe"},{id:"dd-to-device",re:/\bof=\/dev\/(?!null\b|zero\b|random\b|urandom\b|stdout\b|stderr\b|tty\b)\S/i,tier:"block",blockReason:"safe-destruct: blocked [dd-to-device] \u2014 writing directly to a block device is irrecoverable; verify the target path is a file, not a device node."},{id:"mkfs",re:/\bmkfs(\.\w+)?\b/i,tier:"block",blockReason:"safe-destruct: blocked [mkfs] \u2014 formats a filesystem, irrecoverably destroying all data on the target device; confirm the device path. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it."},{id:"redirect-to-block-device",re:/>\s*\/dev\/(sd|nvme|hd|disk|mmcblk|vd)\w*/i,tier:"block",blockReason:"safe-destruct: blocked [redirect-to-block-device] \u2014 shell redirect to a block device overwrites raw sectors irrecoverably; redirect to a file path instead."},{id:"find-delete",re:/\bfind\b[^|&;\n]*-delete\b|\bfind\b[^|&;\n]*-exec\s+rm\b/i,tier:"observe"},{id:"shred",re:/\bshred\b/i,tier:"block",blockReason:'safe-destruct: blocked [shred] \u2014 overwrites file data irrecoverably, bypassing the filesystem; use "rm" if secure deletion is not required. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'},{id:"sql-drop-truncate",re:/\b(drop\s+(table|database|schema|index)\b|truncate\s+table\b)/i,tier:"block",blockReason:"safe-destruct: blocked [sql-drop-truncate] \u2014 DDL destructor removes schema objects or all rows without a transaction rollback path; back up or use a migration with a down step. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it."},{id:"sql-delete-from",re:/\bdelete\s+from\b/i,tier:"observe"},{id:"curl-write-method",re:/\bcurl\b[^|;&]*\s(-X\s*|--request\s+)(POST|PUT|PATCH|DELETE)\b/i,tier:"observe"},{id:"curl-data-flag",re:/\bcurl\b[^|;&]*\s(-d\b|--data\b|-F\b|--form\b)|\bwget\b[^|;&]*\s(--post-data\b|--post-file\b)/i,tier:"observe"},{id:"docker-destructive",re:/\bdocker\s+(system\s+prune|volume\s+(rm|prune)|image\s+prune|container\s+prune|network\s+prune)\b|\bdocker\b[^|&;\n]*\brmi?\s+[^|&;\n]*-f/i,tier:"observe"},{id:"kubectl-delete",re:/\bkubectl\s+delete\b/i,tier:"observe"},{id:"terraform-destroy",re:/\bterraform\s+destroy\b/i,tier:"block",blockReason:'safe-destruct: blocked [terraform-destroy] \u2014 tears down live external infrastructure irrecoverably (new apply creates new resources, not the same ones); run "terraform plan -destroy" to preview. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.'}];var T7="safe-destruct observe-only: destructive-command attempt",x7="This command was blocked by the safe-destruct hook because it matches an irrecoverable or externally-irreversible operation pattern. The block cannot be self-bypassed. If the destructive action is genuinely required, stop and ask the operator to run it manually, or use a safer alternative named in the block reason above.";function R7(t){if(!t)return[];let e=[];for(let{id:n,re:r}of Pw)r.test(t)&&e.push(n);return e}function KN(){return function(e){if(e.event!=="PreToolUse")return{};if(e.toolName!=="bash")return{};let n=e.input,r=typeof n?.command=="string"?n.command:"";if(!r)return{};let o=R7(r);if(o.length===0)return{};let s=new Map(Pw.map(i=>[i.id,i]));for(let i of o){let a=s.get(i);if(a?.tier==="block")return{decision:"block",reason:a.blockReason,injectContext:x7}}return{decision:"approve",reason:`${T7} [${o.join(", ")}]`}}}var Mw=[{id:"npm-publish",re:/\bnpm\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [npm-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"pnpm-publish",re:/\bpnpm\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [pnpm-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"yarn-publish",re:/\byarn\s+(?:npm\s+)?publish\b/i,tier:"block",blockReason:"release-boundary: blocked [yarn-publish] \u2014 publishes a package to the npm registry, externally irreversible once consumed by dependents; verify changelog, version, and generated docs are current before publishing."},{id:"cargo-publish",re:/\bcargo\s+(?:--[\w-]+\s+)*publish\b/i,tier:"block",blockReason:"release-boundary: blocked [cargo-publish] \u2014 publishes a crate to crates.io, externally irreversible (crates.io does not allow un-publishing); verify Cargo.toml version and changelog."},{id:"pypi-twine-upload",re:/\btwine\s+upload\b/i,tier:"block",blockReason:"release-boundary: blocked [pypi-twine-upload] \u2014 uploads a package to PyPI, externally irreversible once consumed; verify setup.py/pyproject.toml version and changelog."},{id:"poetry-publish",re:/\bpoetry\s+publish\b/i,tier:"block",blockReason:"release-boundary: blocked [poetry-publish] \u2014 publishes a package to PyPI, externally irreversible once consumed; verify pyproject.toml version and changelog."},{id:"gem-push",re:/\bgem\s+push\b/i,tier:"block",blockReason:"release-boundary: blocked [gem-push] \u2014 pushes a gem to RubyGems, externally irreversible once consumed; verify gemspec version and changelog."},{id:"docker-push",re:/\bdocker\s+(?:image\s+)?push\b/i,tier:"block",blockReason:"release-boundary: blocked [docker-push] \u2014 pushes a container image to a registry, externally irreversible once pulled by consumers; verify image tag and contents."},{id:"gh-release-create",re:/\bgh\s+release\s+create\b/i,tier:"block",blockReason:"release-boundary: blocked [gh-release-create] \u2014 creates a GitHub release, externally visible and triggering downstream workflows; verify release notes and tag."},{id:"terraform-apply",re:/\bterraform\s+apply\b/i,tier:"block",blockReason:'release-boundary: blocked [terraform-apply] \u2014 applies infrastructure changes to live systems, externally irreversible (new apply creates different resources); run "terraform plan" to preview first.'},{id:"kubectl-apply",re:/\bkubectl\s+apply\b/i,tier:"block",blockReason:"release-boundary: blocked [kubectl-apply] \u2014 applies resources to a live Kubernetes cluster, externally irreversible for stateful workloads; verify manifests and target namespace."},{id:"git-push-mirror",re:/\bgit\s+push\b[^|&;\n]*--mirror\b/i,tier:"observe"},{id:"git-push-tags",re:/\bgit\s+push\b[^|&;\n]*--(?:tags|follow-tags)\b/i,tier:"observe"}];var GN="release-boundary observe-only: sync-boundary command",I7="This command was blocked by the release-boundary hook because it crosses an externally-irreversible publish or deploy boundary. Once a package is published, a container pushed, a release cut, or infrastructure applied, the external state change cannot be undone by the agent. Verify that all living artifacts (changelog, version, generated docs, lock files) are up-to-date before proceeding, and ask the operator to confirm publication.";function C7(t){return/--dry-run\b/i.test(t)||/-refresh-only\b/i.test(t)}function P7(t){let e=t.replace(/'[^']*'/g,"");return e=e.replace(/#[^\n]*/g,""),e}function M7(t){if(!t)return[];let e=P7(t),n=[];for(let{id:r,re:o}of Mw)o.test(e)&&n.push(r);return n}function O7(t){return Mw.find(e=>e.id===t)}function qN(){return function(e){if(e.event!=="PreToolUse")return{};if(e.toolName!=="bash")return{};let n=e.input,r=typeof n?.command=="string"?n.command:"";if(!r)return{};let o=M7(r);if(o.length===0)return{};if(C7(r))return{decision:"approve",reason:`${GN} [${o.join(", ")}] (dry-run: not blocked)`};for(let s of o){let i=O7(s);if(i?.tier==="block")return{decision:"block",reason:i.blockReason,injectContext:I7}}return{decision:"approve",reason:`${GN} [${o.join(", ")}]`}}}Rt();Ki();cm();function XN(t){return function(n){if(n.event!=="PreToolUse")return{};if(n.parentSessionId)return{};if(t()!=="plan")return{};let{toolName:r}=n;if(uu(r)==="write")return{decision:"block",reason:`plan mode: ${r} is refused. Use /plan off to exit plan mode.`};if(r==="worktree"){let o=typeof n.input=="object"&&n.input!==null?String(n.input.action??""):"";if(o!=="list")return{decision:"block",reason:`plan mode: worktree "${o}" is refused (mutates the worktree registry). Only action "list" is allowed in plan mode. Use /plan off to act.`}}if(r==="bash"){let o=typeof n.input=="object"&&n.input!==null?String(n.input.command??""):"",s=Zc(o);if(s.mutating)return{decision:"block",reason:`plan mode: bash refused \u2014 command looks state-mutating (${s.reason??"mutation detected"}). Read-only investigation (git status/log/diff, ls, cat, grep, find) is allowed. Use /plan off to act.`}}return{}}}import ms from"path";no();Ki();import zN from"path";var D7=["rm -rf","rm ","sudo","eval ","chmod","chown","git push --force","git push -f","git reset --hard","mkfs","fdisk","diskutil eraseDisk","dd if=","dd of=","| sh","| bash","|sh","|bash","-X POST","-X PUT","-X PATCH","-X DELETE","-XPOST","-XPUT","-XPATCH","-XDELETE","--request POST","--request PUT","--request PATCH","--request DELETE","curl --data","curl -d","curl -F","wget --post-data","wget --post-file"],F7=["git push","git reset","git commit","git stash drop","git stash clear","npm install","pnpm install","yarn","pip install","apt ","apt-get ","brew install","tee "," > "," >> ","mv ","cp ","mkdir","touch","pnpm build","tsc ","eslint --fix"],L7=["pnpm test","vitest","jest","pytest","cargo test","go test","git status","git log","git diff","git show","ls ","cat ","head ","tail ","find ","grep ","echo ","printf "];function N7(t){return typeof t=="object"&&t!==null&&"command"in t?String(t.command??""):typeof t=="string"?t:""}function U7(t){if(typeof t!="object"||t===null)return"";let e=t;return typeof e.file_path=="string"?e.file_path:typeof e.path=="string"?e.path:""}function $7(t){for(let e of D7)if(t.includes(e))return"high";for(let e of F7)if(t.includes(e))return"medium";for(let e of L7)if(t.includes(e))return"safe";return"medium"}function B7(t,e){if(!t)return"safe";let n=De(zN.resolve(e.cwd,t)),r=Om();for(let o of r)if(n===o||n.startsWith(o+"/"))return"high";if(n.includes("/.git/"))return"high";if(e.workspaceRoot!==void 0){let o=De(e.workspaceRoot);if(zN.relative(o,n).startsWith(".."))return"high"}return n.includes("/node_modules/")?"medium":"safe"}var j7=new Set(["delete","drop","remove","destroy","truncate","purge","wipe","write","create","update","insert","upsert","patch","rename","exec","execute","run","eval","send","push","publish","deploy","post","merge","rollback","reset","terminate","provision","scale","disable","charge","refund","revoke"]);function H7(t){return t.split("__").slice(1).join("__").split(/[_-]+/).filter(Boolean)}function VN(t,e,n){let r=t.toLowerCase();if(r==="bash"){let o=N7(e);return $7(o)}if(r==="write_file"||r==="edit_file"){let o=U7(e);return B7(o,n)}if(uu(t)==="read")return"safe";if(r==="send_telegram")return"medium";if(r.startsWith("mcp__"))return H7(r).some(s=>j7.has(s))?"high":"medium";if(r==="create_schedule"||r==="cancel_schedule")return"high";if(r==="worktree"){let o=typeof e=="object"&&e!==null?e:{},s=typeof o.action=="string"?o.action:"";return s==="list"?"safe":s==="remove"&&o.force===!0?"high":"medium"}return r==="browser_act"||r==="browser_open"||r==="web_scrape"?"medium":"safe"}br();V();Ti();Ph();no();import Ow from"path";import{lstatSync as W7}from"fs";import{spawnSync as K7}from"child_process";var G7=new Set(["node_modules","dist","build",".next","coverage",".cache","__pycache__",".turbo",".parcel-cache","out","target"]),q7=/[*?$`(){};|&<>'"\\\r\n]/;function X7(t){return t==="--recursive"?!0:t.startsWith("--")?!1:/^-[A-Za-z]+$/.test(t)&&/[rR]/.test(t)}function z7(t){if(!/^rm\b/.test(t)||q7.test(t))return null;let e=t.trim().split(/\s+/),n=[],r=!1,o=!1;for(let s of e.slice(1)){if(!o&&s==="--"){o=!0;continue}if(!o&&s.startsWith("-")){X7(s)&&(r=!0);continue}n.push(s)}return n.length===0?null:{targets:n,recursive:r}}function V7(t,e){try{return W7(t).isDirectory()?K7("git",["check-ignore","--quiet","--",t],{cwd:e,stdio:"ignore"}).status===0:!1}catch(n){return n.code==="ENOENT"}}function JN(t,e,n){let r=z7(t);if(r===null||!r.recursive)return!1;let o=De(n);for(let s of r.targets){if(s==="/"||s==="."||s===".."||s==="~"||s.startsWith("~/")||s==="$HOME"||s.startsWith("$HOME/")||s===".git"||s.startsWith(".git/"))return!1;let i=De(Ow.resolve(e,s));if(i===o||!i.startsWith(o+Ow.sep)||!G7.has(Ow.basename(i))||!V7(i,o))return!1}return!0}var J7=3e5,YN=300;function QN(t,e,n,r){let o=r?.approvalTimeoutMs??J7,s=r?.promptForApproval??!0,i=r?.traceWriter,a=r?.sessionId,c=r?.route??((d,u)=>Qe.route(d,u));async function l(d,u,p,f){let m=Date.now(),h=Y7(d,u),y=new AbortController,b=()=>y.abort();p&&(p.aborted?y.abort():p.addEventListener("abort",b,{once:!0}));let k=Symbol("afk-approval-timeout"),A,E,x=new Promise(v=>{E=()=>{A||(A=setTimeout(()=>{y.abort(),v(k)},o),A.unref?.())}});function T(v,_){let C=Date.now()-m,O=v.decision==="block";return ot(i,{hookEvent:"PreToolUse",...O?{decision:"block"}:{},...O&&v.reason!==void 0?{reason:v.reason}:{},...O?{blockedTool:d}:{},durationMs:C,approvalOutcome:_}),v}let I;try{let v=f??a;I=await Promise.race([c(h,{signal:y.signal,onActive:E,...v!==void 0?{sessionId:v}:{}}),x])}finally{A&&clearTimeout(A),p&&p.removeEventListener("abort",b)}if(I===k)return T(Wa(d,`no approval arrived within ${Math.round(o/1e3)}s`),"timeout");if(I.action!=="accept")return T(Wa(d,I.action==="cancel"?"the operator cancelled the approval prompt":"no operator approval was available"),I.action==="cancel"?"cancel":"decline");let R=String(I.content?.choice??"").toLowerCase();return R==="approve"?T({},"approved"):R==="deny"?T(Wa(d,"the operator denied it"),"denied"):T(Wa(d,"the approval prompt returned an unrecognised choice"),"unrecognised")}return function(u,p){if(u.event!=="PreToolUse")return{};if(t()!=="autonomous")return{};let{toolName:f}=u,m=Date.now();if(f==="send_telegram")return{};let h=n?.()??e??process.cwd(),y=u.cwd,b=y??h,A=(y!==void 0?Z7(y,h):void 0)??h,E=VN(f,u.input,{cwd:b,workspaceRoot:A});if(E==="high"&&f==="bash"){let x=typeof u.input=="object"&&u.input!==null&&"command"in u.input?String(u.input.command??""):"";if(x&&JN(x,b,A))return ot(i,{hookEvent:"PreToolUse",blockedTool:f,durationMs:Date.now()-m,approvalOutcome:"carve-out"}),{}}if(E!=="high")return{};if(u.parentSessionId!==void 0||!s){let x=Wa(f,"AFK mode runs autonomously without a human watching");return ot(i,{hookEvent:"PreToolUse",decision:"block",...x.reason!==void 0?{reason:x.reason}:{},blockedTool:f,durationMs:Date.now()-m,approvalOutcome:"hard-block"}),x}return l(f,u.input,p,u.sessionId)}}function Y7(t,e){let n=Q7(e);return{serverName:"agent-afk",message:`AFK: \`${t}\` is high-risk / irreversible and AFK mode runs unattended. Approve this single call?`+(n?`
|
|
1625
1633
|
|
|
1626
1634
|
Input: ${n}`:""),mode:"form",title:"AFK high-risk approval",requestedSchema:{type:"object",properties:{choice:{type:"string",title:"Approve this high-risk operation?",enum:["approve","deny"],description:"'approve' runs this single call. 'deny' refuses it (the model gets an error and should push an Asking summary or take a safe path)."}},required:["choice"]}}}function Q7(t){let e;try{e=typeof t=="string"?t:JSON.stringify(t)}catch{e=String(t)}return e?(e=Sr(e),e.length>YN?`${e.slice(0,YN)}\u2026 [truncated]`:e):""}function Wa(t,e){return{decision:"block",reason:`AFK mode: ${t} is refused \u2014 this op is high-risk or irreversible, and ${e}. Push an Asking summary to Telegram (send_telegram) and stop, or have the operator run /afk off and take over.`}}function Z7(t,e){let n=ms.resolve(t),r=ms.resolve(e);if(n===r)return r;let o=ms.relative(r,n);if(o!==""&&!o.startsWith("..")&&!ms.isAbsolute(o))return Eo(n)??n;let s=Eo(r),i=Eo(n);if(s!==void 0&&i!==void 0&&ms.dirname(s)===ms.dirname(i))return i}j();U();nc();import{mkdir as eZ,readFile as tZ,writeFile as ZN}from"fs/promises";import{basename as nZ,dirname as rZ,join as eU}from"path";var oZ=1,sZ=["permission-denied","hook-block","policy-refusal"];function iZ(t){return Bn(t,{guard:aZ})}function aZ(t){if(typeof t!="object"||t===null)return!1;let e=t;return typeof e.kind=="string"&&typeof e.ts=="string"&&"payload"in e}function cZ(t){let e=nZ(rZ(t)),n=hf();return{label:e,jsonPath:eU(n,`${e}.json`),mdPath:eU(n,`${e}.md`)}}function lZ(t,e){let n={},r={},o={},s=[],i=0,a=0,c=0,l=0,d={started:0,succeeded:0,failed:0,cancelled:0},u,p,f,m,h,y,b,k,A,E,x=!1;for(let L of t)switch(n[L.kind]=(n[L.kind]??0)+1,L.kind){case"tool_call":{let B=L.payload;if(B.phase!=="completed")break;if(B.circuitBreaker===!0){l++;break}i++;let W=r[B.name]??{total:0,errored:0};if(W.total++,B.isError===!0){c++,W.errored++;let Q=B.failureClass,Ne=Q??"unclassified";o[Ne]=(o[Ne]??0)+1,s.push({toolUseId:B.toolUseId,name:B.name,...Q!==void 0?{failureClass:Q}:{},durationMs:B.durationMs,ts:L.ts,truncated:B.truncated===!0,exempt:Q!==void 0&&GL.has(Q),...B.subagentId!==void 0?{subagentId:B.subagentId}:{}})}else a++;r[B.name]=W;break}case"subagent_lifecycle":{let B=L.payload.transition;B==="started"?d.started++:B==="succeeded"?d.succeeded++:B==="failed"?d.failed++:B==="cancelled"&&d.cancelled++;break}case"closure":{let B=L.payload;u=B.reason,p=B.lastStopReason,f=B.guidance,h=B.finalCostUsd,y=B.finalTurnCount,B.finalTokens!==void 0&&(m=B.finalTokens);break}case"session_sealed":{let B=L.payload;b=B.status,k=B.finalCostUsd,A=B.finalTurnCount,E=B.closedAt,B.incomplete===!0&&(x=!0);break}default:break}let T=s.filter(L=>!L.exempt).length,I=sZ.reduce((L,B)=>L+(o[B]??0),0),R=b??"unknown",v=t[0]?.ts,_=E??(t.length>0?t[t.length-1]?.ts:void 0),C;if(v!==void 0&&_!==void 0){let L=Date.parse(_)-Date.parse(v);Number.isFinite(L)&&L>=0&&(C=L)}let O=k??h,q=A??y,P=[];R==="failed"?P.push('Session sealed with status "failed".'):R==="cancelled"?P.push("Session was cancelled."):R==="unknown"&&P.push("No terminal session_sealed record found \u2014 the trace may be truncated or was read before the session sealed."),x&&P.push("Trace was sealed by the process-exit backstop, indicating an abnormal exit (crash, early EOF, or process.exit())."),u!==void 0&&u!=="model_end_turn"&&P.push(`Closure reason "${u}" is not a clean completion.`),T>0&&P.push(`${T} tool call(s) returned an error (excluding benign outcomes).`),l>0&&P.push(`Repeat-loop circuit breaker fired ${l} time(s).`),d.failed>0&&P.push(`${d.failed} subagent(s) failed.`);let $=["Sourced from witness-trace metadata only: raw tool output (stdout/stderr, file contents, error messages) is NOT recorded in the trace and is therefore absent here.","Failure entries list tool name, failure class, duration, and timestamp; inspect the trace at the path above for full per-call detail."];R==="unknown"&&$.push("No session_sealed record was present when this receipt was generated.");let D={...O!==void 0?{finalCostUsd:O}:{},...q!==void 0?{turnCount:q}:{},...m!==void 0?{tokens:m}:{}};return{schemaVersion:oZ,generatedAt:(e.now??new Date).toISOString(),witnessLabel:e.witnessLabel,tracePath:e.tracePath,...e.sessionId!==void 0?{sessionId:e.sessionId}:{},...e.endReason!==void 0?{endReason:e.endReason}:{},status:R,...u!==void 0?{closureReason:u}:{},...p!==void 0?{lastStopReason:p}:{},...f!==void 0?{guidance:f}:{},incomplete:x,...v!==void 0?{startedAt:v}:{},..._!==void 0?{endedAt:_}:{},...C!==void 0?{durationMs:C}:{},toolCalls:{total:i,succeeded:a,errored:c,erroredNotable:T,refused:I,circuitBreakerHits:l,byTool:r,byFailureClass:o},events:{total:t.length,byKind:n},subagents:d,cost:D,failures:s,humanReviewRequired:P.length>0,humanReviewReasons:P,limitations:$}}function dZ(t){if(t<1e3)return`${t}ms`;let e=t/1e3;if(e<60)return`${e.toFixed(1)}s`;let n=Math.floor(e/60),r=Math.round(e%60);return`${n}m${r}s`}function uZ(t){let e=[];e.push(`# Run receipt \u2014 ${t.witnessLabel}`),e.push(""),e.push(`**Status:** ${t.status} \xB7 **Review required:** ${t.humanReviewRequired?"\u26A0\uFE0F YES":"\u2713 no"}`);let n=[];if(t.sessionId!==void 0&&n.push(`**Session:** ${t.sessionId}`),t.endedAt!==void 0&&n.push(`**Ended:** ${t.endedAt}`),t.durationMs!==void 0&&n.push(`**Duration:** ${dZ(t.durationMs)}`),n.length>0&&e.push(n.join(" \xB7 ")),e.push(`**Trace:** \`${t.tracePath}\``),e.push(""),t.humanReviewRequired){e.push("## Why review is required");for(let o of t.humanReviewReasons)e.push(`- ${o}`);e.push("")}if(e.push("## Summary"),e.push(""),e.push("| Metric | Value |"),e.push("| --- | --- |"),e.push(`| Tool calls | ${t.toolCalls.total} |`),e.push(`| Errored | ${t.toolCalls.errored} (${t.toolCalls.erroredNotable} notable) |`),t.toolCalls.refused>0){let o=t.toolCalls.total>0?(t.toolCalls.refused/t.toolCalls.total*100).toFixed(1):"0.0";e.push(`| Refused (denylisted) | ${t.toolCalls.refused} (${o}% of calls) |`)}t.toolCalls.circuitBreakerHits>0&&e.push(`| Circuit-breaker hits | ${t.toolCalls.circuitBreakerHits} |`),t.cost.turnCount!==void 0&&e.push(`| Turns | ${t.cost.turnCount} |`),t.cost.finalCostUsd!==void 0&&e.push(`| Cost (USD) | ${t.cost.finalCostUsd.toFixed(4)} |`),t.subagents.started>0&&e.push(`| Subagents | ${t.subagents.started} started \xB7 ${t.subagents.succeeded} ok \xB7 ${t.subagents.failed} failed \xB7 ${t.subagents.cancelled} cancelled |`),t.closureReason!==void 0&&e.push(`| Closure | ${t.closureReason} |`),e.push("");let r=Object.keys(t.toolCalls.byTool).sort();if(r.length>0){e.push("## Tool calls by name"),e.push(""),e.push("| Tool | Calls | Errored |"),e.push("| --- | --- | --- |");for(let o of r){let s=t.toolCalls.byTool[o];s!==void 0&&e.push(`| ${o} | ${s.total} | ${s.errored} |`)}e.push("")}if(t.failures.length>0){e.push("## Failures"),e.push(""),e.push("| Tool | Class | Duration | When | Exempt |"),e.push("| --- | --- | --- | --- | --- |");for(let o of t.failures)e.push(`| ${o.name} | ${o.failureClass??"unclassified"} | ${o.durationMs}ms | ${o.ts} | ${o.exempt?"yes":"no"} |`);e.push("")}else e.push("No tool failures recorded."),e.push("");e.push("## Limitations"),e.push("");for(let o of t.limitations)e.push(`- ${o}`);return e.push(""),e.push("---"),e.push(`_Generated ${t.generatedAt} by the AFK run-receipt writer (read-only; no agent behavior was modified)._`),e.push(""),e.join(`
|
|
1627
1635
|
`)}async function pZ(t){let e;try{e=await tZ(t.tracePath,"utf8")}catch{return null}let n=iZ(e);if(n.length===0)return null;let r=cZ(t.tracePath),o=lZ(n,{tracePath:t.tracePath,witnessLabel:r.label,...t.sessionId!==void 0?{sessionId:t.sessionId}:{},...t.reason!==void 0?{endReason:t.reason}:{},...t.now!==void 0?{now:t.now}:{}});return await eZ(hf(),{recursive:!0}),await ZN(r.jsonPath,JSON.stringify(o,null,2)+`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-afk",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.153.0",
|
|
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",
|