agent-afk 4.8.2 → 4.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1068,7 +1068,7 @@ ${o}`;return s.includes("already checked out")||s.includes("is already used by w
1068
1068
  Effective base URL: ${r}`)),r}return t}function yB(){if(uf!==void 0)return uf;if(!YS){let o=[Yi(process.cwd(),".env"),at(),Wb()];for(let s of o)df(s)&&gB({path:s,override:!1});YS=!0}let e={},t=k.AFK_MODEL??k.CLAUDE_MODEL;if(t){let o=t.toLowerCase();e.model=Tm(o)?o:t}if(re(t)==="anthropic-direct"){let o=pf();o!==void 0&&(e.apiKey=o)}let r=k.AFK_LOCAL_BASE_URL;if(r&&r.length>0&&(e.baseUrl=r,e.apiKey=k.AFK_LOCAL_API_KEY||"local"),k.AFK_MAX_TOKENS&&(e.maxTokens=parseInt(k.AFK_MAX_TOKENS,10)),k.AFK_TEMPERATURE&&(e.temperature=parseFloat(k.AFK_TEMPERATURE)),k.AFK_SYSTEM_PROMPT&&(e.systemPrompt=k.AFK_SYSTEM_PROMPT),k.AFK_AUTO_ROUTING){let o=k.AFK_AUTO_ROUTING.toLowerCase()==="true";e.autoRouting={interactive:o,chat:o,telegram:o,daemon:o}}return k.AFK_OPENAI_BASE_URL&&(e.openaiBaseUrl=hB(k.AFK_OPENAI_BASE_URL)),uf=e,e}function QS(){if(bs!==void 0)return bs;let e=[Yi(process.cwd(),"afk.config.json"),Ct(),Al()];for(let t of e)if(df(t))try{let n=ZS(t,"utf-8"),r=JSON.parse(n),o={},s=Cw(r.models);if(typeof r.model=="string"&&r.model.length>0){let i=r.model.toLowerCase();o.model=Tm(i)?i:r.model}if(typeof r.maxTokens=="number"&&(o.maxTokens=r.maxTokens),typeof r.temperature=="number"&&(o.temperature=r.temperature),r.systemPrompt&&(o.systemPrompt=r.systemPrompt),r.autoRouting&&typeof r.autoRouting=="object"){let i={};typeof r.autoRouting.interactive=="boolean"&&(i.interactive=r.autoRouting.interactive),typeof r.autoRouting.chat=="boolean"&&(i.chat=r.autoRouting.chat),typeof r.autoRouting.telegram=="boolean"&&(i.telegram=r.autoRouting.telegram),typeof r.autoRouting.daemon=="boolean"&&(i.daemon=r.autoRouting.daemon),o.autoRouting=i}if(r.daemon&&typeof r.daemon=="object"){let i={};typeof r.daemon.task=="string"&&(i.task=r.daemon.task),typeof r.daemon.taskId=="string"&&(i.taskId=r.daemon.taskId);let a=r.daemon.worktreePrune;a&&typeof a=="object"&&(i.worktreePrune={enabled:typeof a.enabled=="boolean"?a.enabled:!0,cron:typeof a.cron=="string"?a.cron:"0 4 * * *",maxAgeDaysClean:typeof a.maxAgeDaysClean=="number"?a.maxAgeDaysClean:14,maxAgeDaysDirty:typeof a.maxAgeDaysDirty=="number"?a.maxAgeDaysDirty:30,scope:typeof a.scope=="string"?a.scope:"all"}),o.daemon=i}if(r.telegram&&typeof r.telegram=="object"){let i={},a=r.telegram.notify;if(a&&typeof a=="object"){let l={};if((a.mode==="primary"||a.mode==="broadcast"||a.mode==="custom")&&(l.mode=a.mode),typeof a.primaryChatId=="number"&&Number.isFinite(a.primaryChatId)&&(l.primaryChatId=a.primaryChatId),Array.isArray(a.targets)){let c=a.targets.filter(u=>typeof u=="number"&&Number.isFinite(u));c.length>0&&(l.targets=c)}i.notify=l}o.telegram=i}if(r.updatePolicy&&["notify","auto","off"].includes(r.updatePolicy)&&(o.updatePolicy=r.updatePolicy),typeof r.autoResumeOnUsageLimit=="boolean"&&(o.autoResumeOnUsageLimit=r.autoResumeOnUsageLimit),typeof r.bgSummaries=="boolean"&&(o.bgSummaries=r.bgSummaries),typeof r.maxSummaryCallsPerSession=="number"&&(o.maxSummaryCallsPerSession=Math.min(500,Math.max(1,r.maxSummaryCallsPerSession))),r.hooks!==null&&typeof r.hooks=="object"&&!Array.isArray(r.hooks)&&(o.hooks=r.hooks),typeof r.enableShellHooks=="boolean"&&(o.enableShellHooks=r.enableShellHooks),t!==Yi(process.cwd(),"afk.config.json")){let i=Ji(r.importFrom);i!==void 0&&(o.importFrom=i)}if(r.interactive&&typeof r.interactive=="object"){let i={};typeof r.interactive.worktreeAutoname=="boolean"&&(i.worktreeAutoname=r.interactive.worktreeAutoname),typeof r.interactive.worktreeBranchPrefix=="string"&&(i.worktreeBranchPrefix=sf(r.interactive.worktreeBranchPrefix,`${t}#/interactive/worktreeBranchPrefix`)),typeof r.interactive.worktreeBase=="string"&&r.interactive.worktreeBase.trim().length>0&&(af(r.interactive.worktreeBase,`${t}#/interactive/worktreeBase`),i.worktreeBase=r.interactive.worktreeBase),typeof r.interactive.suggestGhost=="boolean"&&(i.suggestGhost=r.interactive.suggestGhost),Object.keys(i).length>0&&(o.interactive=i)}return bs={config:o,sourcePath:t,modelsPartial:s},bs}catch(n){console.error(`Warning: Failed to parse ${t}:`,n)}return bs={config:{},sourcePath:void 0,modelsPartial:{}},bs}function bB(){if(ws!==void 0)return ws.value;let e=[Yi(process.cwd(),"AFK.md"),Yi(Ae(),"AFK.md")];for(let t of e)if(df(t))try{let n=ZS(t,"utf-8").trim();if(n.length>0)return ws={value:{content:n,path:t}},ws.value}catch{}return ws={value:null},ws.value}function ev(){return QS().config.telegram??{}}function yt(e){let t=yB(),{config:n,sourcePath:r,modelsPartial:o}=QS(),s={...Vi,...t,...n,...e},i;if(t.systemPrompt!==void 0)i="env:AFK_SYSTEM_PROMPT";else if(n.systemPrompt!==void 0&&r!==void 0)i=`file:${r}`;else if(s.systemPrompt===void 0){let c=bB();c!==null&&(s.systemPrompt=c.content,i=`afk-md:${c.path}`)}let a={model:s.model??Vi.model,maxTokens:s.maxTokens??Vi.maxTokens,temperature:s.temperature??Vi.temperature,updatePolicy:s.updatePolicy??Vi.updatePolicy,...s.apiKey!==void 0?{apiKey:s.apiKey}:{},...s.baseUrl!==void 0?{baseUrl:s.baseUrl}:{},...s.openaiBaseUrl!==void 0?{openaiBaseUrl:s.openaiBaseUrl}:{},...s.systemPrompt!==void 0?{systemPrompt:s.systemPrompt}:{},...i!==void 0?{systemPromptSource:i}:{},...s.autoRouting!==void 0?{autoRouting:s.autoRouting}:{},...s.daemon!==void 0?{daemon:s.daemon}:{},...s.telegram!==void 0?{telegram:s.telegram}:{},...s.bgSummaries!==void 0?{bgSummaries:s.bgSummaries}:{},...s.maxSummaryCallsPerSession!==void 0?{maxSummaryCallsPerSession:s.maxSummaryCallsPerSession}:{},...s.interactive!==void 0?{interactive:s.interactive}:{},...s.hooks!==void 0?{hooks:s.hooks}:{},...s.enableShellHooks!==void 0?{enableShellHooks:s.enableShellHooks}:{},...s.importFrom!==void 0?{importFrom:s.importFrom}:{}},l=e?.models??km(o);if(Wl(l),a.models=l,typeof a.model=="string"&&a.model.toLowerCase().startsWith("local-")&&(a.baseUrl===void 0||a.baseUrl.length===0))throw new Error(`Model '${a.model}' requires AFK_LOCAL_BASE_URL to be set (e.g. AFK_LOCAL_BASE_URL=http://127.0.0.1:8080). Point it at your local Anthropic-Messages-compatible server.`);return a}var Vi,YS,uf,XS,bs,ws,Hn=_(()=>{"use strict";Pn();Ht();Je();K();hs();qi();G();no();Vi={model:"sonnet",maxTokens:4096,temperature:1,updatePolicy:"notify"},YS=!1;XS=new Set});function wB(e,t){return t!==void 0&&Number.isFinite(t)&&t!==0?t:e.find(r=>r>0)??e[0]}function SB(e,t={}){let n=[...e],r=t.mode??"primary";if(r==="broadcast")return n;if(r==="custom"){let s=(t.targets??[]).filter(i=>typeof i=="number"&&Number.isFinite(i)&&i!==0);if(s.length>0)return[...new Set(s)]}let o=wB(n,t.primaryChatId);return o!==void 0?[o]:[]}function vB(e){if(!e)return;let t=e.trim();if(!/^-?\d+$/.test(t))return;let n=Number(t);return Number.isFinite(n)&&n!==0?n:void 0}function kB(e){if(!e)return;let t=e.trim().toLowerCase();return t==="primary"||t==="broadcast"||t==="custom"?t:void 0}function xB(){let e=ev().notify??{},t=e.mode??kB(k.AFK_TELEGRAM_NOTIFY_MODE),n=e.primaryChatId??vB(k.AFK_TELEGRAM_PRIMARY_CHAT_ID);return{...t!==void 0?{mode:t}:{},...n!==void 0?{primaryChatId:n}:{},...e.targets!==void 0?{targets:e.targets}:{}}}function kc(){let e=MS(k.AFK_TELEGRAM_ALLOWED_CHAT_IDS);return SB(e,xB())}var mf=_(()=>{"use strict";OS();Hn();G()});function tv(e,t=4096){if(e.length<=t)return[e];let n=[],r=e;for(;r.length>0;){if(r.length<=t){n.push(r);break}let o=t,s=r.lastIndexOf(`
1069
1069
  `,t);if(s>t-500&&s>0)o=s+1;else{let i=r.slice(0,t).match(/[.!?]\s+(?=[A-Z])/g);if(i&&i.length>0){let a=i[i.length-1];if(a){let l=r.lastIndexOf(a,t);l>t-200&&l>0&&(o=l+2)}}else{let a=r.lastIndexOf(" ",t);a>t-100&&a>0&&(o=a+1)}}n.push(r.slice(0,o).trim()),r=r.slice(o).trim()}return n}var nv=_(()=>{"use strict"});var ff={};vl(ff,{push:()=>xc,pushIfConfigured:()=>Ss});async function xc(e){if(!e.token)throw new Error("push: token is required");if(e.chatId===""||e.chatId==null||e.chatId===0)throw new Error("push: chatId is required");let t=e.fetchImpl??fetch,r=`${e.apiBase??EB}/bot${e.token}/sendMessage`,o={chat_id:e.chatId,text:e.text.slice(0,4096)};e.parseMode&&(o.parse_mode=e.parseMode),e.replyMarkup&&(o.reply_markup=e.replyMarkup);let s=new AbortController,i=setTimeout(()=>s.abort(),1e4);try{let a=await t(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),signal:s.signal});if(a.ok)return{ok:!0,status:a.status};let l;try{l=(await a.json()).description}catch{l=`HTTP ${a.status}`}return{ok:!1,status:a.status,...l!==void 0?{errorMessage:l}:{}}}catch(a){return{ok:!1,status:0,errorMessage:a instanceof Error?a.message:String(a)}}finally{clearTimeout(i)}}async function Ss(e,t={}){let n=k.TELEGRAM_BOT_TOKEN;if(!n)return null;let r=kc();if(r.length===0)return null;let o=tv(e),s=[];for(let i of r)for(let a=0;a<o.length;a++)s.push(await xc({token:n,chatId:i,text:o[a]??"",...t.parseMode!==void 0?{parseMode:t.parseMode}:{},...t.replyMarkup!==void 0&&a===0?{replyMarkup:t.replyMarkup}:{},...t.fetchImpl!==void 0?{fetchImpl:t.fetchImpl}:{}}));return s}var EB,vs=_(()=>{"use strict";mf();nv();G();EB="https://api.telegram.org"});function TB(e=xc){return async(t,n)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let o=t.message;if(typeof o!="string")return{content:"Invalid input: message must be a string",isError:!0};if(o.length===0)return{content:"Invalid input: message must be non-empty",isError:!0};if(o.length>rv)return{content:`Invalid input: message exceeds Telegram's ${rv}-character limit (got ${o.length}). Split into multiple sends or trim before calling.`,isError:!0};let s=k.TELEGRAM_BOT_TOKEN;if(!s)return{content:"Telegram is not configured: TELEGRAM_BOT_TOKEN is not set. Run the bot setup wizard or export the env var before using send_telegram.",isError:!0};let i=kc();if(i.length===0)return{content:"Telegram is not configured: AFK_TELEGRAM_ALLOWED_CHAT_IDS is empty or unset. Add the operator chat ID(s) before using send_telegram.",isError:!0};let a=[];for(let l of i){let c=await e({token:s,chatId:l,text:o});c.ok||a.push(`chat ${l}: ${c.errorMessage??`HTTP ${c.status}`}`)}return a.length===i.length?{content:`Failed to send Telegram message to any chat. ${a.join("; ")}`,isError:!0}:a.length>0?{content:`Sent Telegram message to ${i.length-a.length}/${i.length} chat(s); ${a.length} failed: ${a.join("; ")}`}:{content:i.length===1?`Sent Telegram message to chat ${i[0]}.`:`Sent Telegram message to ${i.length} chats.`}}}var rv,ov,sv=_(()=>{"use strict";G();vs();mf();rv=4096;ov=TB()});import{JSDOM as RB}from"jsdom";import{Readability as CB}from"@mozilla/readability";import _B from"turndown";function iv(e){return e.replace(/\n{3,}/g,`
1070
1070
 
1071
- `).trim()}function AB(e){return(e?.textContent??"").replace(/\s+/g," ").trim().length}function lv(e,t){let r=new RB(e,{url:t}).window.document,o=(r.title??"").trim(),s=null;try{let c=r.cloneNode(!0);s=new CB(c).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let c=iv(gf.turndown(s.content)),u=(s.title??"").trim()||o,d=typeof s.length=="number"&&s.length>0?s.length:(s.textContent??"").replace(/\s+/g," ").trim().length;return{title:u,markdown:c,textLength:d,usedFallback:!1}}let i=r.body,a=i?.innerHTML??"",l=iv(gf.turndown(a));return{title:o,markdown:l,textLength:AB(i),usedFallback:!0}}var av,gf,cv=_(()=>{"use strict";av=200,gf=new _B({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});gf.remove(["script","style","noscript","iframe"])});import{readFileSync as IB}from"node:fs";import{join as PB}from"path";function MB(e){let n=e.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function uv(e,t){return MB(t).test(e)}function DB(e,t){if(e!==void 0){let n=e.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(t!==void 0){if(OB.has(t))return!0;if($B.has(t))return!1}return!1}function dv(e){return e===void 0||e.trim()===""?[]:e.split(",").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0)}function LB(e){if(e===void 0||e===""||e==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${e}`)}function FB(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t==="1"||t==="true"||t==="yes"}function NB(e){try{return IB(e,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}}function BB(e,t){let n={...e};if(typeof t.headless=="boolean"&&(n.headless=t.headless),Array.isArray(t.allowedDomains)&&(n.allowedDomains=t.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(t.blockedDomains)&&(n.blockedDomains=t.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof t.domSnapshots=="boolean"&&(n.domSnapshots=t.domSnapshots),t.backend==="playwright")n.backend="playwright";else if(t.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(t.backend)}`);return n}function pv(e){let t=e?.env??k,n=e?.readFileSync??NB,r=e?.surface??t.AGENT_SURFACE,o=DB(t.AFK_BROWSER_HEADLESS,r),s=dv(t.AFK_BROWSER_ALLOWED_DOMAINS),i=dv(t.AFK_BROWSER_BLOCKED_DOMAINS),a=FB(t.AFK_BROWSER_DOM_SNAPSHOTS),l=LB(t.AFK_BROWSER_BACKEND),c={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:l,configPath:null},u=t.AFK_BROWSER_CONFIG,d=u!==void 0&&u.trim()!==""?u.trim():PB(tn(),"browser.json"),m=n(d);if(m===void 0)return c;let f;try{f=JSON.parse(m)}catch(h){throw new Error(`Failed to parse browser config at ${d}: ${String(h)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${d} must be a JSON object`);let g=BB(c,f);return g.configPath=d,g}function hf(e,t){let n;try{n=new URL(e).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${e}`}}for(let r of t.blockedDomains)if(uv(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return t.allowedDomains.length>0&&!t.allowedDomains.some(o=>uv(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var OB,$B,yf=_(()=>{"use strict";G();K();OB=new Set(["daemon","subagent","telegram"]),$B=new Set(["repl","interactive","cli"])});import UB from"node:fs";import jB from"node:path";import{chromium as HB}from"playwright";function WB(){try{return"4.8.2"}catch{}try{let e=jB.resolve(import.meta.dirname,"../../../package.json"),t=UB.readFileSync(e,"utf8"),n=JSON.parse(t);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var KB,Ec,mv=_(()=>{"use strict";KB=WB(),Ec=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(t){this.config=t}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=HB.launch({headless:this.config.headless}).then(t=>(this.browser=t,this.launchPromise=void 0,t)).catch(t=>{throw this.launchPromise=void 0,t}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(t){let n=this.sessions.get(t);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(t,s),o}async ensurePage(t){let n=this.sessions.get(t);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(t);let r=this.sessions.get(t);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${t}`);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(t){return this.sessions.get(t)?.page}async renderHtml(t,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(t,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),l=await i.content(),c=i.url(),u=a!==null?a.status():null;return{html:l,finalUrl:c,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(t){return this.sessions.get(t)?.consoleErrors??0}getLastHttpStatus(t){return this.sessions.get(t)?.lastHttpStatus??null}hasOpenDialog(t){return this.sessions.get(t)?.openDialog!==void 0}async dismissDialog(t,n=!0){let r=this.sessions.get(t);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(t){let n=this.sessions.get(t);n!==void 0&&(this.sessions.delete(t),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let t=[...this.sessions.keys()];if(await Promise.all(t.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/${KB}`}}}});import{createHash as GB}from"crypto";function bf(e){if(e.length===0)return e;let t=e;for(let{regex:n,name:r}of zB)r==="form-password"?t=t.replace(n,"password=[redacted]"):t=t.replace(n,"[redacted]");return t}function fv(e){return!!(e.role==="textbox"&&e.kind==="password"||e.label&&qB.test(e.label))}function gv(e){return GB("sha256").update(e,"utf8").digest("hex").slice(0,8)}function hv(e){let t=e.replace(/\s+/g," ").trim();return t.length<=80?t:t.slice(0,77)+"..."}var zB,qB,Xi=_(()=>{"use strict";zB=[{name:"aws-access-key",regex:/AKIA[0-9A-Z]{16}/g},{name:"github-pat",regex:/ghp_[a-zA-Z0-9]{36}/g},{name:"openai-bearer",regex:/sk-[a-zA-Z0-9_-]{20,}/g},{name:"slack-token",regex:/xox[abp]-[a-zA-Z0-9-]{10,}/g},{name:"jwt",regex:/eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/g},{name:"form-password",regex:/password=[^&\s]+/gi}];qB=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as JB}from"node:crypto";function VB(e){return e?e.replace(/\s+/g," ").trim().slice(0,200):""}function YB(e,t,n){return`el_${JB("sha256").update(`${e}:${t}:${n}`).digest("hex").slice(0,6)}`}function XB(e){let t=e.replace(/\s+/g," ").trim(),n=4e3;return t.length<=n?t:t.slice(0,n)+"\u2026[truncated]"}function yv(e){return e.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function wv(e,t){let n=e.role??"",r=e.name??"";bv.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&t.push(e);for(let s of e.children??[])wv(s,t)}async function ZB(e){return e.evaluate(t=>{let n=Array.from(document.querySelectorAll(t)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let u=window.getComputedStyle(i);if(u.display==="none"||u.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),l=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),c=a==="input"?o.type||null:o.getAttribute("type");r.push({name:l,tagName:a,type:c,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},Sv).catch(()=>[])}async function QB(e){return e.evaluate(t=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(t)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",l=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),c=a||(n[i]??"");if(i==="input"){let h=s.type;h==="checkbox"?c="checkbox":h==="radio"?c="radio":h==="button"||h==="submit"||h==="reset"?c="button":h==="search"?c="searchbox":c="textbox"}if(!c)continue;let u="value"in s?s.value:void 0,d=u!==void 0?String(u):void 0,m=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:c,name:l,disabled:m};d!==void 0&&(g.value=d),f!==void 0&&(g.checked=f),o.push(g)}return o},Sv).catch(()=>[])}function eU(e){let n=e.accessibility;return n!==null&&typeof n=="object"?n:null}async function Tc(e,t){let n=t.maxElements??80,r=t.includeHidden??!1,o=[],s=eU(e),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=ZB(e),l=e.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(e.url()),u=e.title().catch(()=>""),[d,m,f,g,h]=await Promise.all([i,a,l,c,u]),b,y=!1;d!==null?(b=[],wv(d,b)):(o.push("observation skipped accessibility tree (returned null)"),y=!0,b=(await QB(e)).filter($=>bv.has($.role??"")));let v=new Map;for(let M of m){let $=yv(M.name),L=v.get($);(!L||L.bbox.w===0&&M.bbox.w>0)&&v.set($,M)}let w=b.map(M=>({ax:M,dom:v.get(yv(M.name??""))})),T=r?w:w.filter(M=>M.dom?M.dom.bbox.w>0||M.dom.bbox.h>0:!0);T.sort((M,$)=>{let L=M.dom?.bbox.y??0,B=$.dom?.bbox.y??0;if(L!==B)return L-B;let U=M.dom?.bbox.x??0,D=$.dom?.bbox.x??0;return U-D}),T.length>200&&o.push("page has 200+ interactive elements; consider scoping");let R=T.slice(0,n).map((M,$)=>{let L=M.ax.role??"generic",B=M.ax.name??"",U=YB(L,B,$),D=M.dom?.bbox??{x:0,y:0,w:0,h:0},F=M.dom?.type??null,j=null;M.ax.value!==void 0&&M.ax.value!==null&&(j=String(M.ax.value)),M.ax.checked!==void 0&&(j=String(M.ax.checked)),fv({role:L,kind:F})&&(j="[redacted]");let N={disabled:M.ax.disabled??!1};M.ax.checked!==void 0&&(N.checked=M.ax.checked===!0||M.ax.checked==="mixed"),M.ax.selected!==void 0&&(N.selected=M.ax.selected),M.ax.expanded!==void 0&&(N.expanded=M.ax.expanded);let O;M.dom?.testId?O=`[data-testid="${M.dom.testId}"]`:M.dom?.id&&(O=`#${M.dom.id}`);let J={id:U,role:L,label:VB(B),kind:F,value:j,state:N,bbox:D};return O!==void 0&&(J.selector=O),J}),C="idle";try{let M=await e.evaluate(()=>document.readyState);M==="loading"?C="loading":M==="interactive"?C="navigating":C="idle"}catch{C="navigating"}C!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),y&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let S=XB(f),P=`obs_${t.observationCounter.toString(36)}`,A=new Date().toISOString();return{observationId:P,url:g,title:h,textSummary:S,interactive:R,status:{httpStatus:t.httpStatus??null,loadingState:C,hasDialog:t.hasDialog??!1,consoleErrors:t.consoleErrors??0},warnings:o,screenshotPath:t.screenshotPath??null,capturedAt:A}}var bv,Sv,vv=_(()=>{"use strict";Xi();bv=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Sv="a[href], button, input, select, textarea, [role], [tabindex], label"});async function kv(e,t){try{let n=await e.nth(t).evaluate(i=>{let a=i,l=a.getAttribute("role")??a.tagName.toLowerCase(),c=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",u=a.getBoundingClientRect();return{role:l,label:c,x:Math.round(u.x),y:Math.round(u.y),w:Math.round(u.width),h:Math.round(u.height)}}),r=`${n.role}:${n.label}:${t}`,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 wf(e,t){let n=Math.min(t,5);return(await Promise.all(Array.from({length:n},(o,s)=>kv(e,s)))).filter(o=>o!==null)}async function tU(e){let t=new Set,n=[];for(let{loc:r,count:o}of e)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let l=a,c=l.getBoundingClientRect();return`${l.tagName}@${Math.round(c.x)},${Math.round(c.y)}`})}catch{continue}t.has(i)||(t.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Sf(e,t,n){switch(t.kind){case"element_id":return nU(e,t,n);case"selector":return rU(e,t);case"semantic":return oU(e,t)}}async function nU(e,t,n){let r=n.get(t.elementId);if(r===void 0)return{outcome:"not_found",query:t};if(r.selector!==void 0){let l=e.locator(r.selector);if(await l.count()===1)return{outcome:"resolved",locator:l}}let o=e.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:t};if(s===1)return{outcome:"resolved",locator:o};let i=await wf(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function rU(e,t){let n=e.locator(t.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:t};if(r===1)return{outcome:"resolved",locator:n};let o=await wf(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${t.selector}]`},candidates:o}}async function oU(e,t){return t.role!==void 0?sU(e,t.text,t.role):iU(e,t.text,t)}async function sU(e,t,n){let r=e.getByRole(n,{name:t}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:t,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await wf(r,o);return{outcome:"ambiguous_target",query:{text:t,role:n},candidates:s}}async function iU(e,t,n){let r=e.getByRole("button",{name:t}),o=e.getByRole("link",{name:t}),s=e.getByLabel(t,{exact:!1}),[i,a,l]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+l===0)return{outcome:"not_found",query:n};let u=[];i>0&&u.push({loc:r,count:i}),a>0&&u.push({loc:o,count:a}),l>0&&u.push({loc:s,count:l});let d=await tU(u);if(d.length===0)return{outcome:"not_found",query:n};if(d.length===1){let h=d[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let m=d.slice(0,5),f=[];for(let h=0;h<m.length;h++){let b=m[h];if(b===void 0)continue;let y=await kv(b.locator,b.index);if(y!==null){let v=`${y.role}:${y.label}:${h}`,w=0;for(let T=0;T<v.length;T++)w=w*31+v.charCodeAt(T)>>>0;f.push({...y,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:t},candidates:f}}var xv=_(()=>{"use strict"});import{randomBytes as aU}from"crypto";import{mkdir as lU,stat as cU,writeFile as uU}from"fs/promises";import{join as vf}from"path";import{gzip as dU}from"zlib";import{promisify as pU}from"util";function mU(e){return vf(Yo(e),"browser")}function fU(e){return vf(mU(e),"screenshots")}function gU(){return new Date().toISOString().replace(/[:.]/g,"-")}function hU(){return aU(3).toString("hex")}async function kf(e,t,n){if(t.length>Ev)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Ev} byte cap (received ${t.length} bytes). Refusing to write oversized screenshot.`);let r=fU(e);await lU(r,{recursive:!0});let o=`${gU()}-${hU()}-${n}.png`,s=vf(r,o);await uU(s,t);let{size:i}=await cU(s);return{path:s,bytes:i}}var qoe,Ev,Tv=_(()=>{"use strict";K();Xi();qoe=pU(dU);Ev=5*1024*1024});var Cv={};vl(Cv,{PlaywrightProvider:()=>xf});function Rv(e){switch(e.kind){case"semantic":return e.role!==void 0?`semantic('${e.text}', role='${e.role}')`:`semantic('${e.text}')`;case"element_id":return`element_id(${e.elementId})`;case"selector":return`selector(${e.selector})`}}var xf,_v=_(()=>{"use strict";mv();vv();xv();yf();Xi();Tv();xf=class{name="playwright";config;launcher;sessions=new Map;constructor(t){this.config=t,this.launcher=new Ec(t)}async open(t){let n=hf(t.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:t.url,reason:n.reason};let{sessionId:r}=t,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(t.url,{timeout:t.timeoutMs??3e4,waitUntil:t.waitFor??"load"})}catch(c){a=c}(t.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let l=await Tc(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,l.interactive,l.url,l.title,"browser_open"),a!==null)throw a;return l}async observe(t){let{sessionId:n}=t,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;t.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Tc(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:t.includeHidden,maxElements:t.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(t){let{sessionId:n}=t,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=t.timeoutMs??3e4,a=await Sf(r,t.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${Rv(t.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:l}=a,c=null,u=async()=>{switch(t.action){case"click":await l.click({timeout:i});break;case"fill":{let h=bf(t.value??"");await l.fill(t.value??"");break}case"press":await l.press(t.value??"");break;case"select":await l.selectOption(t.value??"");break;case"hover":await l.hover({timeout:i});break;case"scroll_to":await l.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await l.waitFor({timeout:i,state:"visible"});break}};try{await u()}catch(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await u()}catch(b){c=b}else c=h}let d=r.url();if(d!==s){let h=hf(d,this.config);if(!h.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:d,reason:h.reason}}let m=null;(t.screenshot===!0||c!==null)&&(m=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Tc(r,{observationCounter:o.observationCounter,screenshotPath:m,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),g=`browser_act:${t.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,g),c!==null)throw c;return f}async render(t){return this.launcher.renderHtml(t.url,{timeoutMs:t.timeoutMs??3e4,waitUntil:t.waitFor??"load",signal:t.signal})}async screenshot(t){let{sessionId:n}=t,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(t.target!==void 0){let u=await Sf(r,t.target,o.knownElements);if(u.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${Rv(t.target)}`);if(u.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await u.locator.screenshot()}else s=await r.screenshot({fullPage:t.fullPage??!1});let{path:i,bytes:a}=await kf(n,s,"browser_screenshot"),l=0,c=0;if(t.fullPage===!0)try{let u=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));l=u.w,c=u.h}catch{let u=r.viewportSize();l=u?.width??0,c=u?.height??0}else{let u=r.viewportSize();l=u?.width??0,c=u?.height??0}return{path:i,bytes:a,width:l,height:c,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(t){throw new Error("browser_extract not implemented in Phase 1")}async close(t){await this.launcher.closeSession(t.sessionId),this.sessions.delete(t.sessionId)}describe(t){let n=this.sessions.get(t);if(n===void 0)return null;let r=this.launcher.getPage(t);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(t){let n=this.sessions.get(t);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(t,r),r}updateSessionFromObservation(t,n,r,o,s){t.knownElements=new Map(n.map(i=>[i.id,i])),t.currentUrl=r,t.currentTitle=o,t.lastAction=s,t.lastActionAt=new Date().toISOString()}async captureScreenshot(t,n,r){try{let o=await t.screenshot({fullPage:!1}),{path:s}=await kf(n,o,r);return s}catch{return null}}}});var oo={};vl(oo,{__resetBrowserRegistryForTests:()=>vU,browserProviderActive:()=>wU,closeBrowserProvider:()=>Ef,getBrowserProvider:()=>bU,peekBrowserProvider:()=>SU});function Av(){Promise.resolve(Ef()).then(()=>{process.exit(130)})}function Iv(){Promise.resolve(Ef()).then(()=>{process.exit(143)})}function Pv(){ln=null}function yU(){Rc||(process.on("SIGINT",Av),process.on("SIGTERM",Iv),process.on("exit",Pv),Rc=!0)}function Mv(){Rc&&(process.removeListener("SIGINT",Av),process.removeListener("SIGTERM",Iv),process.removeListener("exit",Pv),Rc=!1)}async function bU(e){return ln!==null?ln:(ro!==null||(ro=(async()=>{let{PlaywrightProvider:t}=await Promise.resolve().then(()=>(_v(),Cv)),n=pv(e),r=new t(n);return yU(),ln=r,ro=null,r})()),ro)}async function Ef(){if(ln===null)return;let e=ln;ln=null,ro=null,Mv(),await e.shutdown()}function wU(){return ln!==null}function SU(){return ln}function vU(){ln=null,ro=null,Mv()}var ln,ro,Rc,so=_(()=>{"use strict";yf();ln=null,ro=null,Rc=!1});function Ov(e,t){try{return lv(e,t)}catch(n){return V("[web/scrape] extraction failed",{url:t,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function RU(e,t){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(so(),oo));return(await n()).render({url:e,timeoutMs:t.timeoutMs,signal:t.signal})}async function $v(e,t){let n=t.fetchFn??globalThis.fetch,r=t.renderFn??RU,o=null,s=e,i=null,a=null;try{let c=await n(e,{headers:TU,redirect:"follow",signal:t.signal});i=c.status,s=c.url||e;let u=c.headers.get("content-type")??"";if(c.ok){if(EU.test(u))throw new Error(`web_scrape markdown mode received binary content (${u.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let d=await c.text();if(xU.test(u)&&!kU.test(u))return{title:"",markdown:d.trim(),finalUrl:s,usedRender:!1};o=Ov(d,s)}}catch(c){if(t.signal.aborted||c instanceof Error&&c.message.startsWith("web_scrape markdown mode received binary"))throw c;a=c}if(!(o===null||o.textLength<av)&&o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};try{let c=await r(e,{timeoutMs:t.timeoutMs,signal:t.signal}),u=Ov(c.html,c.finalUrl);if(o===null||u.textLength>=o.textLength)return{title:u.title,markdown:u.markdown,finalUrl:c.finalUrl,usedRender:!0}}catch(c){if(t.signal.aborted)throw c;if(o===null){let u=c instanceof Error?c.message:String(c),d=a instanceof Error?a.message:`HTTP ${i??"error"}`,m=new Error(`web_scrape could not retrieve ${e}: fetch failed (${d}) and render failed (${u}).`);throw m.cause=c,m}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${e} (HTTP ${i??"error"}).`)}var kU,xU,EU,TU,Dv=_(()=>{"use strict";cv();Pe();kU=/(text\/html|application\/xhtml\+xml)/i,xU=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,EU=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,TU={"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 AU(e){let t=e.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await t(CU,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":e.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),_U),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let l="";try{let u=await s.text(),d=pc(u);d&&(l=`: ${d.length>200?d.slice(0,200)+"\u2026":d}`)}catch{}let c=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${c}${l}`)}let i;try{i=await s.json()}catch(l){throw new Error(`Exa Search response was not JSON: ${l instanceof Error?l.message:String(l)}`)}return(i.results??[]).slice(0,r).map(l=>({title:(l.title??"").trim()||"(untitled)",url:l.url??"",description:(l.highlights?.[0]??"").trim()})).filter(l=>l.url.length>0)}}}function Lv(e){return e.exaApiKey!==void 0&&e.exaApiKey.trim()!==""?AU({apiKey:e.exaApiKey,fetchFn:e.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 Fv(e,t){if(t.length===0)return`# Search results for "${e}"
1071
+ `).trim()}function AB(e){return(e?.textContent??"").replace(/\s+/g," ").trim().length}function lv(e,t){let r=new RB(e,{url:t}).window.document,o=(r.title??"").trim(),s=null;try{let c=r.cloneNode(!0);s=new CB(c).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let c=iv(gf.turndown(s.content)),u=(s.title??"").trim()||o,d=typeof s.length=="number"&&s.length>0?s.length:(s.textContent??"").replace(/\s+/g," ").trim().length;return{title:u,markdown:c,textLength:d,usedFallback:!1}}let i=r.body,a=i?.innerHTML??"",l=iv(gf.turndown(a));return{title:o,markdown:l,textLength:AB(i),usedFallback:!0}}var av,gf,cv=_(()=>{"use strict";av=200,gf=new _B({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});gf.remove(["script","style","noscript","iframe"])});import{readFileSync as IB}from"node:fs";import{join as PB}from"path";function MB(e){let n=e.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function uv(e,t){return MB(t).test(e)}function DB(e,t){if(e!==void 0){let n=e.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(t!==void 0){if(OB.has(t))return!0;if($B.has(t))return!1}return!1}function dv(e){return e===void 0||e.trim()===""?[]:e.split(",").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0)}function LB(e){if(e===void 0||e===""||e==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${e}`)}function FB(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t==="1"||t==="true"||t==="yes"}function NB(e){try{return IB(e,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}}function BB(e,t){let n={...e};if(typeof t.headless=="boolean"&&(n.headless=t.headless),Array.isArray(t.allowedDomains)&&(n.allowedDomains=t.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(t.blockedDomains)&&(n.blockedDomains=t.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof t.domSnapshots=="boolean"&&(n.domSnapshots=t.domSnapshots),t.backend==="playwright")n.backend="playwright";else if(t.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(t.backend)}`);return n}function pv(e){let t=e?.env??k,n=e?.readFileSync??NB,r=e?.surface??t.AGENT_SURFACE,o=DB(t.AFK_BROWSER_HEADLESS,r),s=dv(t.AFK_BROWSER_ALLOWED_DOMAINS),i=dv(t.AFK_BROWSER_BLOCKED_DOMAINS),a=FB(t.AFK_BROWSER_DOM_SNAPSHOTS),l=LB(t.AFK_BROWSER_BACKEND),c={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:l,configPath:null},u=t.AFK_BROWSER_CONFIG,d=u!==void 0&&u.trim()!==""?u.trim():PB(tn(),"browser.json"),m=n(d);if(m===void 0)return c;let f;try{f=JSON.parse(m)}catch(h){throw new Error(`Failed to parse browser config at ${d}: ${String(h)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${d} must be a JSON object`);let g=BB(c,f);return g.configPath=d,g}function hf(e,t){let n;try{n=new URL(e).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${e}`}}for(let r of t.blockedDomains)if(uv(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return t.allowedDomains.length>0&&!t.allowedDomains.some(o=>uv(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var OB,$B,yf=_(()=>{"use strict";G();K();OB=new Set(["daemon","subagent","telegram"]),$B=new Set(["repl","interactive","cli"])});import UB from"node:fs";import jB from"node:path";import{chromium as HB}from"playwright";function WB(){try{return"4.8.3"}catch{}try{let e=jB.resolve(import.meta.dirname,"../../../package.json"),t=UB.readFileSync(e,"utf8"),n=JSON.parse(t);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var KB,Ec,mv=_(()=>{"use strict";KB=WB(),Ec=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(t){this.config=t}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=HB.launch({headless:this.config.headless}).then(t=>(this.browser=t,this.launchPromise=void 0,t)).catch(t=>{throw this.launchPromise=void 0,t}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(t){let n=this.sessions.get(t);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(t,s),o}async ensurePage(t){let n=this.sessions.get(t);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(t);let r=this.sessions.get(t);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${t}`);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(t){return this.sessions.get(t)?.page}async renderHtml(t,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(t,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),l=await i.content(),c=i.url(),u=a!==null?a.status():null;return{html:l,finalUrl:c,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(t){return this.sessions.get(t)?.consoleErrors??0}getLastHttpStatus(t){return this.sessions.get(t)?.lastHttpStatus??null}hasOpenDialog(t){return this.sessions.get(t)?.openDialog!==void 0}async dismissDialog(t,n=!0){let r=this.sessions.get(t);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(t){let n=this.sessions.get(t);n!==void 0&&(this.sessions.delete(t),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let t=[...this.sessions.keys()];if(await Promise.all(t.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/${KB}`}}}});import{createHash as GB}from"crypto";function bf(e){if(e.length===0)return e;let t=e;for(let{regex:n,name:r}of zB)r==="form-password"?t=t.replace(n,"password=[redacted]"):t=t.replace(n,"[redacted]");return t}function fv(e){return!!(e.role==="textbox"&&e.kind==="password"||e.label&&qB.test(e.label))}function gv(e){return GB("sha256").update(e,"utf8").digest("hex").slice(0,8)}function hv(e){let t=e.replace(/\s+/g," ").trim();return t.length<=80?t:t.slice(0,77)+"..."}var zB,qB,Xi=_(()=>{"use strict";zB=[{name:"aws-access-key",regex:/AKIA[0-9A-Z]{16}/g},{name:"github-pat",regex:/ghp_[a-zA-Z0-9]{36}/g},{name:"openai-bearer",regex:/sk-[a-zA-Z0-9_-]{20,}/g},{name:"slack-token",regex:/xox[abp]-[a-zA-Z0-9-]{10,}/g},{name:"jwt",regex:/eyJ[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}\.[a-zA-Z0-9_-]{20,}/g},{name:"form-password",regex:/password=[^&\s]+/gi}];qB=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as JB}from"node:crypto";function VB(e){return e?e.replace(/\s+/g," ").trim().slice(0,200):""}function YB(e,t,n){return`el_${JB("sha256").update(`${e}:${t}:${n}`).digest("hex").slice(0,6)}`}function XB(e){let t=e.replace(/\s+/g," ").trim(),n=4e3;return t.length<=n?t:t.slice(0,n)+"\u2026[truncated]"}function yv(e){return e.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function wv(e,t){let n=e.role??"",r=e.name??"";bv.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&t.push(e);for(let s of e.children??[])wv(s,t)}async function ZB(e){return e.evaluate(t=>{let n=Array.from(document.querySelectorAll(t)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let u=window.getComputedStyle(i);if(u.display==="none"||u.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),l=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),c=a==="input"?o.type||null:o.getAttribute("type");r.push({name:l,tagName:a,type:c,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},Sv).catch(()=>[])}async function QB(e){return e.evaluate(t=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(t)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",l=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),c=a||(n[i]??"");if(i==="input"){let h=s.type;h==="checkbox"?c="checkbox":h==="radio"?c="radio":h==="button"||h==="submit"||h==="reset"?c="button":h==="search"?c="searchbox":c="textbox"}if(!c)continue;let u="value"in s?s.value:void 0,d=u!==void 0?String(u):void 0,m=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:c,name:l,disabled:m};d!==void 0&&(g.value=d),f!==void 0&&(g.checked=f),o.push(g)}return o},Sv).catch(()=>[])}function eU(e){let n=e.accessibility;return n!==null&&typeof n=="object"?n:null}async function Tc(e,t){let n=t.maxElements??80,r=t.includeHidden??!1,o=[],s=eU(e),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=ZB(e),l=e.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(e.url()),u=e.title().catch(()=>""),[d,m,f,g,h]=await Promise.all([i,a,l,c,u]),b,y=!1;d!==null?(b=[],wv(d,b)):(o.push("observation skipped accessibility tree (returned null)"),y=!0,b=(await QB(e)).filter($=>bv.has($.role??"")));let v=new Map;for(let M of m){let $=yv(M.name),L=v.get($);(!L||L.bbox.w===0&&M.bbox.w>0)&&v.set($,M)}let w=b.map(M=>({ax:M,dom:v.get(yv(M.name??""))})),T=r?w:w.filter(M=>M.dom?M.dom.bbox.w>0||M.dom.bbox.h>0:!0);T.sort((M,$)=>{let L=M.dom?.bbox.y??0,B=$.dom?.bbox.y??0;if(L!==B)return L-B;let U=M.dom?.bbox.x??0,D=$.dom?.bbox.x??0;return U-D}),T.length>200&&o.push("page has 200+ interactive elements; consider scoping");let R=T.slice(0,n).map((M,$)=>{let L=M.ax.role??"generic",B=M.ax.name??"",U=YB(L,B,$),D=M.dom?.bbox??{x:0,y:0,w:0,h:0},F=M.dom?.type??null,j=null;M.ax.value!==void 0&&M.ax.value!==null&&(j=String(M.ax.value)),M.ax.checked!==void 0&&(j=String(M.ax.checked)),fv({role:L,kind:F})&&(j="[redacted]");let N={disabled:M.ax.disabled??!1};M.ax.checked!==void 0&&(N.checked=M.ax.checked===!0||M.ax.checked==="mixed"),M.ax.selected!==void 0&&(N.selected=M.ax.selected),M.ax.expanded!==void 0&&(N.expanded=M.ax.expanded);let O;M.dom?.testId?O=`[data-testid="${M.dom.testId}"]`:M.dom?.id&&(O=`#${M.dom.id}`);let J={id:U,role:L,label:VB(B),kind:F,value:j,state:N,bbox:D};return O!==void 0&&(J.selector=O),J}),C="idle";try{let M=await e.evaluate(()=>document.readyState);M==="loading"?C="loading":M==="interactive"?C="navigating":C="idle"}catch{C="navigating"}C!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),y&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let S=XB(f),P=`obs_${t.observationCounter.toString(36)}`,A=new Date().toISOString();return{observationId:P,url:g,title:h,textSummary:S,interactive:R,status:{httpStatus:t.httpStatus??null,loadingState:C,hasDialog:t.hasDialog??!1,consoleErrors:t.consoleErrors??0},warnings:o,screenshotPath:t.screenshotPath??null,capturedAt:A}}var bv,Sv,vv=_(()=>{"use strict";Xi();bv=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Sv="a[href], button, input, select, textarea, [role], [tabindex], label"});async function kv(e,t){try{let n=await e.nth(t).evaluate(i=>{let a=i,l=a.getAttribute("role")??a.tagName.toLowerCase(),c=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",u=a.getBoundingClientRect();return{role:l,label:c,x:Math.round(u.x),y:Math.round(u.y),w:Math.round(u.width),h:Math.round(u.height)}}),r=`${n.role}:${n.label}:${t}`,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 wf(e,t){let n=Math.min(t,5);return(await Promise.all(Array.from({length:n},(o,s)=>kv(e,s)))).filter(o=>o!==null)}async function tU(e){let t=new Set,n=[];for(let{loc:r,count:o}of e)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let l=a,c=l.getBoundingClientRect();return`${l.tagName}@${Math.round(c.x)},${Math.round(c.y)}`})}catch{continue}t.has(i)||(t.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Sf(e,t,n){switch(t.kind){case"element_id":return nU(e,t,n);case"selector":return rU(e,t);case"semantic":return oU(e,t)}}async function nU(e,t,n){let r=n.get(t.elementId);if(r===void 0)return{outcome:"not_found",query:t};if(r.selector!==void 0){let l=e.locator(r.selector);if(await l.count()===1)return{outcome:"resolved",locator:l}}let o=e.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:t};if(s===1)return{outcome:"resolved",locator:o};let i=await wf(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function rU(e,t){let n=e.locator(t.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:t};if(r===1)return{outcome:"resolved",locator:n};let o=await wf(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${t.selector}]`},candidates:o}}async function oU(e,t){return t.role!==void 0?sU(e,t.text,t.role):iU(e,t.text,t)}async function sU(e,t,n){let r=e.getByRole(n,{name:t}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:t,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await wf(r,o);return{outcome:"ambiguous_target",query:{text:t,role:n},candidates:s}}async function iU(e,t,n){let r=e.getByRole("button",{name:t}),o=e.getByRole("link",{name:t}),s=e.getByLabel(t,{exact:!1}),[i,a,l]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+l===0)return{outcome:"not_found",query:n};let u=[];i>0&&u.push({loc:r,count:i}),a>0&&u.push({loc:o,count:a}),l>0&&u.push({loc:s,count:l});let d=await tU(u);if(d.length===0)return{outcome:"not_found",query:n};if(d.length===1){let h=d[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let m=d.slice(0,5),f=[];for(let h=0;h<m.length;h++){let b=m[h];if(b===void 0)continue;let y=await kv(b.locator,b.index);if(y!==null){let v=`${y.role}:${y.label}:${h}`,w=0;for(let T=0;T<v.length;T++)w=w*31+v.charCodeAt(T)>>>0;f.push({...y,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:t},candidates:f}}var xv=_(()=>{"use strict"});import{randomBytes as aU}from"crypto";import{mkdir as lU,stat as cU,writeFile as uU}from"fs/promises";import{join as vf}from"path";import{gzip as dU}from"zlib";import{promisify as pU}from"util";function mU(e){return vf(Yo(e),"browser")}function fU(e){return vf(mU(e),"screenshots")}function gU(){return new Date().toISOString().replace(/[:.]/g,"-")}function hU(){return aU(3).toString("hex")}async function kf(e,t,n){if(t.length>Ev)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Ev} byte cap (received ${t.length} bytes). Refusing to write oversized screenshot.`);let r=fU(e);await lU(r,{recursive:!0});let o=`${gU()}-${hU()}-${n}.png`,s=vf(r,o);await uU(s,t);let{size:i}=await cU(s);return{path:s,bytes:i}}var qoe,Ev,Tv=_(()=>{"use strict";K();Xi();qoe=pU(dU);Ev=5*1024*1024});var Cv={};vl(Cv,{PlaywrightProvider:()=>xf});function Rv(e){switch(e.kind){case"semantic":return e.role!==void 0?`semantic('${e.text}', role='${e.role}')`:`semantic('${e.text}')`;case"element_id":return`element_id(${e.elementId})`;case"selector":return`selector(${e.selector})`}}var xf,_v=_(()=>{"use strict";mv();vv();xv();yf();Xi();Tv();xf=class{name="playwright";config;launcher;sessions=new Map;constructor(t){this.config=t,this.launcher=new Ec(t)}async open(t){let n=hf(t.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:t.url,reason:n.reason};let{sessionId:r}=t,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(t.url,{timeout:t.timeoutMs??3e4,waitUntil:t.waitFor??"load"})}catch(c){a=c}(t.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let l=await Tc(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,l.interactive,l.url,l.title,"browser_open"),a!==null)throw a;return l}async observe(t){let{sessionId:n}=t,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;t.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Tc(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:t.includeHidden,maxElements:t.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(t){let{sessionId:n}=t,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=t.timeoutMs??3e4,a=await Sf(r,t.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${Rv(t.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:l}=a,c=null,u=async()=>{switch(t.action){case"click":await l.click({timeout:i});break;case"fill":{let h=bf(t.value??"");await l.fill(t.value??"");break}case"press":await l.press(t.value??"");break;case"select":await l.selectOption(t.value??"");break;case"hover":await l.hover({timeout:i});break;case"scroll_to":await l.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await l.waitFor({timeout:i,state:"visible"});break}};try{await u()}catch(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await u()}catch(b){c=b}else c=h}let d=r.url();if(d!==s){let h=hf(d,this.config);if(!h.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:d,reason:h.reason}}let m=null;(t.screenshot===!0||c!==null)&&(m=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Tc(r,{observationCounter:o.observationCounter,screenshotPath:m,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),g=`browser_act:${t.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,g),c!==null)throw c;return f}async render(t){return this.launcher.renderHtml(t.url,{timeoutMs:t.timeoutMs??3e4,waitUntil:t.waitFor??"load",signal:t.signal})}async screenshot(t){let{sessionId:n}=t,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(t.target!==void 0){let u=await Sf(r,t.target,o.knownElements);if(u.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${Rv(t.target)}`);if(u.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await u.locator.screenshot()}else s=await r.screenshot({fullPage:t.fullPage??!1});let{path:i,bytes:a}=await kf(n,s,"browser_screenshot"),l=0,c=0;if(t.fullPage===!0)try{let u=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));l=u.w,c=u.h}catch{let u=r.viewportSize();l=u?.width??0,c=u?.height??0}else{let u=r.viewportSize();l=u?.width??0,c=u?.height??0}return{path:i,bytes:a,width:l,height:c,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(t){throw new Error("browser_extract not implemented in Phase 1")}async close(t){await this.launcher.closeSession(t.sessionId),this.sessions.delete(t.sessionId)}describe(t){let n=this.sessions.get(t);if(n===void 0)return null;let r=this.launcher.getPage(t);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(t){let n=this.sessions.get(t);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(t,r),r}updateSessionFromObservation(t,n,r,o,s){t.knownElements=new Map(n.map(i=>[i.id,i])),t.currentUrl=r,t.currentTitle=o,t.lastAction=s,t.lastActionAt=new Date().toISOString()}async captureScreenshot(t,n,r){try{let o=await t.screenshot({fullPage:!1}),{path:s}=await kf(n,o,r);return s}catch{return null}}}});var oo={};vl(oo,{__resetBrowserRegistryForTests:()=>vU,browserProviderActive:()=>wU,closeBrowserProvider:()=>Ef,getBrowserProvider:()=>bU,peekBrowserProvider:()=>SU});function Av(){Promise.resolve(Ef()).then(()=>{process.exit(130)})}function Iv(){Promise.resolve(Ef()).then(()=>{process.exit(143)})}function Pv(){ln=null}function yU(){Rc||(process.on("SIGINT",Av),process.on("SIGTERM",Iv),process.on("exit",Pv),Rc=!0)}function Mv(){Rc&&(process.removeListener("SIGINT",Av),process.removeListener("SIGTERM",Iv),process.removeListener("exit",Pv),Rc=!1)}async function bU(e){return ln!==null?ln:(ro!==null||(ro=(async()=>{let{PlaywrightProvider:t}=await Promise.resolve().then(()=>(_v(),Cv)),n=pv(e),r=new t(n);return yU(),ln=r,ro=null,r})()),ro)}async function Ef(){if(ln===null)return;let e=ln;ln=null,ro=null,Mv(),await e.shutdown()}function wU(){return ln!==null}function SU(){return ln}function vU(){ln=null,ro=null,Mv()}var ln,ro,Rc,so=_(()=>{"use strict";yf();ln=null,ro=null,Rc=!1});function Ov(e,t){try{return lv(e,t)}catch(n){return V("[web/scrape] extraction failed",{url:t,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function RU(e,t){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(so(),oo));return(await n()).render({url:e,timeoutMs:t.timeoutMs,signal:t.signal})}async function $v(e,t){let n=t.fetchFn??globalThis.fetch,r=t.renderFn??RU,o=null,s=e,i=null,a=null;try{let c=await n(e,{headers:TU,redirect:"follow",signal:t.signal});i=c.status,s=c.url||e;let u=c.headers.get("content-type")??"";if(c.ok){if(EU.test(u))throw new Error(`web_scrape markdown mode received binary content (${u.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let d=await c.text();if(xU.test(u)&&!kU.test(u))return{title:"",markdown:d.trim(),finalUrl:s,usedRender:!1};o=Ov(d,s)}}catch(c){if(t.signal.aborted||c instanceof Error&&c.message.startsWith("web_scrape markdown mode received binary"))throw c;a=c}if(!(o===null||o.textLength<av)&&o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};try{let c=await r(e,{timeoutMs:t.timeoutMs,signal:t.signal}),u=Ov(c.html,c.finalUrl);if(o===null||u.textLength>=o.textLength)return{title:u.title,markdown:u.markdown,finalUrl:c.finalUrl,usedRender:!0}}catch(c){if(t.signal.aborted)throw c;if(o===null){let u=c instanceof Error?c.message:String(c),d=a instanceof Error?a.message:`HTTP ${i??"error"}`,m=new Error(`web_scrape could not retrieve ${e}: fetch failed (${d}) and render failed (${u}).`);throw m.cause=c,m}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${e} (HTTP ${i??"error"}).`)}var kU,xU,EU,TU,Dv=_(()=>{"use strict";cv();Pe();kU=/(text\/html|application\/xhtml\+xml)/i,xU=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,EU=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,TU={"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 AU(e){let t=e.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await t(CU,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":e.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),_U),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let l="";try{let u=await s.text(),d=pc(u);d&&(l=`: ${d.length>200?d.slice(0,200)+"\u2026":d}`)}catch{}let c=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${c}${l}`)}let i;try{i=await s.json()}catch(l){throw new Error(`Exa Search response was not JSON: ${l instanceof Error?l.message:String(l)}`)}return(i.results??[]).slice(0,r).map(l=>({title:(l.title??"").trim()||"(untitled)",url:l.url??"",description:(l.highlights?.[0]??"").trim()})).filter(l=>l.url.length>0)}}}function Lv(e){return e.exaApiKey!==void 0&&e.exaApiKey.trim()!==""?AU({apiKey:e.exaApiKey,fetchFn:e.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 Fv(e,t){if(t.length===0)return`# Search results for "${e}"
1072
1072
 
1073
1073
  (no results)`;let n=[`# Search results for "${e}"`,""];return t.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(`
1074
1074
  `).trimEnd()}var CU,_U,Nv=_(()=>{"use strict";fs();CU="https://api.exa.ai/search",_U=10});function FU(e){if(!e||typeof e!="object")return{error:"Invalid input: expected an object"};let t=e,n=t.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 t.query!="string"||t.query.length===0)return{error:'Invalid input: search mode requires a non-empty "query" string'};s=t.query}else{if(typeof t.url!="string"||t.url.length===0)return{error:`Invalid input: ${r} mode requires a non-empty "url" string`};let l;try{l=new URL(t.url)}catch{return{error:`Invalid input: "${t.url}" is not a valid absolute URL`}}if(l.protocol!=="http:"&&l.protocol!=="https:")return{error:`Invalid input: protocol "${l.protocol}" not supported (http/https only)`};o=l.toString()}let i=IU;if(t.timeout_ms!==void 0){if(typeof t.timeout_ms!="number"||!Number.isFinite(t.timeout_ms)||t.timeout_ms<=0)return{error:"Invalid input: timeout_ms must be a positive finite number"};i=Math.min(t.timeout_ms,PU)}let a=MU;if(t.max_bytes!==void 0){if(typeof t.max_bytes!="number"||!Number.isFinite(t.max_bytes)||t.max_bytes<=0)return{error:"Invalid input: max_bytes must be a positive finite number"};a=Math.min(t.max_bytes,OU)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Tf(e,t){let n=Buffer.from(e,"utf8");return n.byteLength<=t?e:n.subarray(0,t).toString("utf8")+$U}function NU(e){let t=[],n=e;for(let o=0;o<4&&n instanceof Error;o++)t.push(n.message),n=n.cause;let r=t.join(" | ");return LU.some(o=>r.includes(o))}function BU(e={}){let t=e.fetchFn??globalThis.fetch,n=e.env??process.env;return async(r,o)=>{if(typeof t!="function")return{content:"web_scrape unavailable: global fetch() is not present in this runtime (agent-afk requires Node 20+).",isError:!0};let s=FU(r);if("error"in s)return{content:s.error,isError:!0};if(o.aborted){let u=o.reason;return{content:`web_scrape aborted: ${u instanceof Error?u.message:String(u??"aborted")}`,isError:!0}}let i=new AbortController,a=()=>{i.abort(o.reason)},l,c=()=>{let u=i.signal.reason;return u instanceof Error?u.message:String(u??"aborted")};try{if(o.addEventListener("abort",a,{once:!0}),l=setTimeout(()=>{i.abort(new Error(`web_scrape timeout after ${s.timeoutMs}ms`))},s.timeoutMs),s.mode==="raw"){let d;try{d=await t(s.url,{method:"GET",headers:{"User-Agent":"agent-afk/web_scrape",Accept:"*/*"},signal:i.signal})}catch(f){return i.signal.aborted?{content:`web_scrape aborted: ${c()}`,isError:!0}:{content:`web_scrape network error: ${f instanceof Error?f.message:String(f)}`,isError:!0}}if(!d.ok)return{content:`web_scrape HTTP ${d.status} ${d.statusText||""}`.trimEnd()+` for ${s.url}`,isError:!0};let m;try{m=await d.text()}catch(f){return{content:`web_scrape read error: ${f instanceof Error?f.message:String(f)}`,isError:!0}}return{content:Tf(m,s.maxBytes)}}if(s.mode==="markdown")try{let d=await $v(s.url,{fetchFn:t,renderFn:e.renderFn,timeoutMs:s.timeoutMs,signal:i.signal});return d.markdown.trim().length===0?{content:`web_scrape extracted no readable content from ${s.url}.`,isError:!0}:{content:Tf(d.markdown,s.maxBytes)}}catch(d){if(i.signal.aborted)return{content:`web_scrape aborted: ${c()}`,isError:!0};let m=d instanceof Error?d.message:String(d),f=NU(d)?" (the render fallback needs the optional Playwright browser \u2014 run `pnpm exec playwright install chromium`)":"";return{content:`web_scrape markdown error: ${m}${f}`,isError:!0}}let u=Lv({exaApiKey:n.EXA_API_KEY,fetchFn:t});if("error"in u)return{content:u.error,isError:!0};try{let d=await u.search(s.query,{limit:DU,timeoutMs:s.timeoutMs,signal:i.signal});return{content:Tf(Fv(s.query,d),s.maxBytes)}}catch(d){return i.signal.aborted?{content:`web_scrape aborted: ${c()}`,isError:!0}:{content:`web_scrape search error (${u.name}): ${d instanceof Error?d.message:String(d)}`,isError:!0}}}finally{l!==void 0&&clearTimeout(l),o.removeEventListener("abort",a)}}}var IU,PU,MU,OU,$U,DU,LU,Bv,Uv=_(()=>{"use strict";Dv();Nv();IU=3e4,PU=12e4,MU=1e6,OU=1e7,$U=`
@@ -1086,7 +1086,7 @@ ${o}`;return s.includes("already checked out")||s.includes("is already used by w
1086
1086
  ?`,"m");if(!r.test(n))return!1;let o=n.replace(r,"");return Mc(e,o,384),!0}function Qv(e,t){if(!Qi(e))return;let r=Pc(e,"utf-8").match(new RegExp(`^${Ic(t)}=(.*)$`,"m"));return r?r[1]:void 0}function ek(e){let t={};if(!Qi(e))return t;let n=Pc(e,"utf-8");for(let r of n.split(`
1087
1087
  `)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf("=");if(s<=0)continue;let i=o.slice(0,s).trim(),a=o.slice(s+1);t[i]=a}return t}var Oc=_(()=>{"use strict"});function ks(e){let t=kl(e);return t?mj.has(e)?"non-config":t.secret?"secret":fj.has(e)||e.endsWith("_BASE_URL")?"protected":"settable":"unknown"}function tk(e,t){if(t.includes(`
1088
1088
  `))return{ok:!1,error:`value for ${e.name} must not contain newlines`};switch(e.type){case"number":{let n=Number(t);return Number.isFinite(n)?{ok:!0,value:t.trim()}:{ok:!1,error:`${e.name} expects a number, got ${JSON.stringify(t)}`}}case"boolean":{let n=t.trim().toLowerCase();return["true","false","1","0","yes","no","on","off"].includes(n)?{ok:!0,value:n}:{ok:!1,error:`${e.name} expects a boolean (true/false/1/0/yes/no/on/off), got ${JSON.stringify(t)}`}}case"json":{try{JSON.parse(t)}catch{return{ok:!1,error:`${e.name} expects valid JSON`}}return{ok:!0,value:t}}default:return{ok:!0,value:t}}}function rk(e){return nk.get(e)}function Of(e){let t=nk.get(e);return t?t.tier:"unknown"}function ok(e,t){switch(e.type){case"boolean":{if(typeof t=="boolean")return{ok:!0,value:t};if(typeof t=="string"){let n=t.trim().toLowerCase();if(["true","1","yes","on"].includes(n))return{ok:!0,value:!0};if(["false","0","no","off"].includes(n))return{ok:!0,value:!1}}return{ok:!1,error:`${e.path} expects a boolean`}}case"number":{let n=typeof t=="number"?t:typeof t=="string"?Number(t):NaN;return Number.isFinite(n)?e.clamp?e.clamp.integer&&!Number.isInteger(n)?{ok:!1,error:`${e.path} expects an integer`}:{ok:!0,value:Math.min(e.clamp.max,Math.max(e.clamp.min,n))}:{ok:!0,value:n}:{ok:!1,error:`${e.path} expects a number`}}case"enum":return typeof t=="string"&&e.enumValues?.includes(t)?{ok:!0,value:t}:{ok:!1,error:`${e.path} expects one of: ${e.enumValues?.join(", ")}`};case"number-array":{let n;if(Array.isArray(t))n=t;else if(typeof t=="string")n=t.split(",").map(o=>o.trim()).filter(o=>o.length>0).map(o=>Number(o));else return{ok:!1,error:`${e.path} expects an array of numbers`};let r=[];for(let o of n){let s=typeof o=="number"?o:Number(o);if(!Number.isFinite(s))return{ok:!1,error:`${e.path} contains a non-number`};r.push(s)}return{ok:!0,value:r}}default:return typeof t!="string"?{ok:!1,error:`${e.path} expects a string`}:t.trim().length===0?{ok:!1,error:`${e.path} must not be empty`}:{ok:!0,value:t}}}function sk(e,t){let n=e;for(let r of t.split(".")){if(n===null||typeof n!="object")return;n=n[r]}return n}function ik(e,t,n){let r=t.split("."),o=e;for(let s=0;s<r.length-1;s++){let i=r[s],a=o[i];(a===null||typeof a!="object"||Array.isArray(a))&&(o[i]={}),o=o[i]}o[r[r.length-1]]=n}function ak(e,t){let n=t.split("."),r=[e],o=e;for(let i=0;i<n.length-1;i++){let a=n[i],l=o[a];if(l===null||typeof l!="object"||Array.isArray(l))return!1;o=l,r.push(o)}let s=n[n.length-1];if(!(s in o))return!1;delete o[s];for(let i=r.length-1;i>=1;i--){let a=r[i];if(Object.keys(a).length===0){let l=n[i-1];delete r[i-1][l]}else break}return!0}var mj,fj,gj,nk,$f=_(()=>{"use strict";G();mj=new Set(["HOME","PATH","SHELL","PAGER","NODE_ENV","CI","VITEST","DEBUG","FORCE_COLOR","NO_COLOR","AGENT_SURFACE","AFK_SESSION_ID","NO_UPDATE_NOTIFIER","SCRIPT","ASCIINEMA_REC"]),fj=new Set(["AFK_MODEL_SMALL_BASE_URL","AFK_MODEL_MEDIUM_BASE_URL","AFK_MODEL_LARGE_BASE_URL","AFK_LOCAL_BASE_URL","AFK_OPENAI_BASE_URL","AFK_SYSTEM_PROMPT","AFK_DAEMON_TASK","AFK_DAEMON_TASK_ID","AFK_DAEMON_CWD","AFK_DAEMON_HOST","AFK_BROWSER_ALLOWED_DOMAINS","AFK_BROWSER_BLOCKED_DOMAINS","AFK_BROWSER_CONFIG","AFK_ALLOW_PROJECT_MCP","AFK_INTERNAL","AFK_WORKTREE_BASE","AFK_WORKTREE_BRANCH_PREFIX","AFK_TELEGRAM_ALLOWED_CHAT_IDS","AFK_TELEGRAM_NOTIFY_MODE","AFK_TELEGRAM_PRIMARY_CHAT_ID","AFK_HOME","AFK_STATE_DIR","AFK_FRAMEWORK_DIR","TELEGRAM_DATA_DIR","AFK_TELEGRAM_CWD"]);gj=[{path:"model",tier:"agent",type:"string",description:"Default model id / alias."},{path:"models.local",tier:"agent",type:"string",description:"Local-tier model id (OpenAI-compatible shim: Ollama, LM Studio, vLLM, MLX)."},{path:"models.small",tier:"agent",type:"string",description:"Small-tier model id."},{path:"models.medium",tier:"agent",type:"string",description:"Medium-tier model id."},{path:"models.large",tier:"agent",type:"string",description:"Large-tier model id."},{path:"maxTokens",tier:"agent",type:"number",clamp:{min:1,max:1e6,integer:!0},description:"Max tokens per turn."},{path:"temperature",tier:"agent",type:"number",clamp:{min:0,max:2},description:"Sampling temperature."},{path:"autoRouting.interactive",tier:"agent",type:"boolean",description:"Auto-route model in the REPL."},{path:"autoRouting.chat",tier:"agent",type:"boolean",description:"Auto-route model for chat."},{path:"autoRouting.telegram",tier:"agent",type:"boolean",description:"Auto-route model for Telegram."},{path:"autoRouting.daemon",tier:"agent",type:"boolean",description:"Auto-route model for the daemon."},{path:"telegram.notify.mode",tier:"human",type:"enum",enumValues:["primary","broadcast","custom"],description:"Telegram notify routing mode (human-tier: notification-redirect vector)."},{path:"telegram.notify.primaryChatId",tier:"human",type:"number",clamp:{min:-1e15,max:1e15,integer:!0},description:"Primary Telegram chat id (human-tier: notification-redirect vector)."},{path:"telegram.notify.targets",tier:"human",type:"number-array",description:"Custom Telegram target chat ids (human-tier: notification-redirect vector)."},{path:"interactive.worktreeAutoname",tier:"agent",type:"boolean",description:"Auto-name worktrees."},{path:"interactive.suggestGhost",tier:"agent",type:"boolean",description:"Ghost-text suggestions in the REPL."},{path:"updatePolicy",tier:"human",type:"enum",enumValues:["notify","auto","off"],description:"Self-update policy (human-tier: auto self-update is scope-widening)."},{path:"autoResumeOnUsageLimit",tier:"agent",type:"boolean",description:"Auto-resume after a usage-limit pause."},{path:"bgSummaries",tier:"agent",type:"boolean",description:"Background summarisation."},{path:"maxSummaryCallsPerSession",tier:"agent",type:"number",clamp:{min:1,max:500,integer:!0},description:"Cap on summary calls per session."},{path:"systemPrompt",tier:"human",type:"string",description:"Operator system-prompt overlay."},{path:"enableShellHooks",tier:"human",type:"boolean",description:"Enable shell hooks (trust gate)."},{path:"interactive.worktreeBranchPrefix",tier:"human",type:"string",description:"Worktree branch prefix (git-flag sensitive)."},{path:"interactive.worktreeBase",tier:"human",type:"string",description:"Worktree base ref (git-flag sensitive)."},{path:"daemon.task",tier:"human",type:"string",description:"Daemon task prompt."},{path:"daemon.taskId",tier:"human",type:"string",description:"Daemon task id."}],nk=new Map(gj.map(e=>[e.path,e]))});import{existsSync as lk,readFileSync as hj,copyFileSync as yj,chmodSync as bj}from"fs";function Bf(e){return e===void 0||e.length===0?"<unset>":e.length<=4?"set (****)":`set (****${e.slice(-4)})`}function Lc(e){return e?.filePath??at()}function ck(e,t,n){let r=ks(e);if(r==="unknown")throw new ea(e);if(r==="non-config")throw new Df(e);if(r==="secret"&&!t)throw new Lf(e);if(r==="protected"&&!n)throw new Ff(e);return r}function Fc(e,t,n){let r=ck(e,n?.allowSecret,n?.allowProtected),o=kl(e),s=tk(o,t);if(!s.ok)throw new $c(s.error);let i=Lc(n);return qt(i,e,s.value),{key:e,class:r,persistedTo:i,display:r==="secret"?Bf(s.value):s.value}}function Nc(e,t){let n=ck(e,t?.allowSecret,t?.allowProtected),r=Lc(t),o=Zv(r,e);return{key:e,class:n,removed:o,persistedTo:r}}function Bc(e,t){let n=ks(e);if(n==="unknown")throw new ea(e);let r=Lc(t),o=Qv(r,e),s=Jp(e),i=n==="secret"?o!==void 0?Bf(o):void 0:o;return{key:e,class:n,persisted:i,activeInProcess:s}}function Uc(e){let t=Lc(e),n=ek(t),r=[];for(let o of Mi){let s=o.name,i=ks(s),a=n[s],l=Jp(s);if(!e?.all&&a===void 0&&!l)continue;let c=i==="secret"?a!==void 0?Bf(a):void 0:a;r.push({key:s,class:i,persisted:c,activeInProcess:l})}return r}function jc(e){return e?.filePath??Ct()}function Hc(e){if(!lk(e))return{};let t;try{t=JSON.parse(hj(e,"utf-8"))}catch{throw new Dc(e)}if(t===null||typeof t!="object"||Array.isArray(t))throw new Dc(e);return t}function uk(e,t){if(lk(e))try{yj(e,`${e}.bak`),bj(`${e}.bak`,384)}catch{}Mc(e,JSON.stringify(t,null,2)+`
1089
- `,384)}function dk(e,t){let n=Of(e);if(n==="unknown")throw new ea(e);if(n==="human"&&!t)throw new Nf(e);return n}function Wc(e,t,n){let r=dk(e,n?.allowHumanOnly),o=rk(e),s=ok(o,t);if(!s.ok)throw new $c(s.error);let i=jc(n),a=Hc(i);return ik(a,e,s.value),uk(i,a),{path:e,class:r,value:s.value,persistedTo:i}}function Kc(e,t){let n=dk(e,t?.allowHumanOnly),r=jc(t),o=Hc(r),s=ak(o,e);return s&&uk(r,o),{path:e,class:n,removed:s,persistedTo:r}}function Gc(e,t){let n=Of(e),r=jc(t),o=Hc(r);return{path:e,class:n,value:sk(o,e)}}function zc(e){return Hc(jc(e))}var gr,ea,Df,Lf,Ff,Nf,$c,Dc,Uf=_(()=>{"use strict";K();G();Oc();$f();gr="effective on the next session/daemon restart; the current session is unchanged",ea=class extends Error{constructor(t){super(`unknown config key: ${t}`),this.name="UnknownKeyError"}},Df=class extends Error{constructor(t){super(`${t} is a process/inherited env var and is not afk-configurable`),this.name="NonConfigKeyError"}},Lf=class extends Error{constructor(t){super(`${t} holds a credential; the agent cannot set it. A human must run \`afk config env set ${t}\` (the value is entered masked and never enters the model context).`),this.name="SecretWriteRefused"}},Ff=class extends Error{constructor(t){super(`${t} controls identity, safety, capability, autonomous runs, request routing, or where AFK's own state lives; the agent cannot set it. A human must run \`afk config env set ${t}\`.`),this.name="ProtectedEnvKeyRefused"}},Nf=class extends Error{constructor(t){super(`${t} is human-gated (prompt/hooks/identity); the agent cannot set it. A human must run \`afk config set ${t}\`.`),this.name="HumanOnlyKeyRefused"}},$c=class extends Error{constructor(t){super(t),this.name="ConfigValidationError"}},Dc=class extends Error{constructor(t){super(`refusing to write: existing ${t} is not valid JSON (fix or remove it by hand first)`),this.name="MalformedConfigError"}}});function pk(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function mk(e){return e==="env"||e==="config"?e:void 0}function Wn(e){return{content:e,isError:!0}}var fk,gk,hk=_(()=>{"use strict";Uf();fk=async e=>{let t=pk(e);if(!t)return Wn("config_get: expected an object input");let n=mk(t.target);if(!n)return Wn("config_get: `target` must be 'env' or 'config'");let r=typeof t.key=="string"?t.key:void 0,o=t.all===!0;try{if(n==="env"){if(r){let s=Bc(r);return{content:JSON.stringify(s,null,2)}}return{content:JSON.stringify(Uc({all:o}),null,2)}}if(r){let s=Gc(r);return{content:JSON.stringify(s,null,2)}}return{content:JSON.stringify(zc(),null,2)}}catch(s){return Wn(`config_get: ${s.message}`)}},gk=async e=>{let t=pk(e);if(!t)return Wn("config_set: expected an object input");let n=mk(t.target);if(!n)return Wn("config_set: `target` must be 'env' or 'config'");let r=typeof t.key=="string"?t.key:void 0;if(!r)return Wn("config_set: `key` is required");let o=t.action==="unset"?"unset":"set",s=t.value;try{if(o==="unset"){if(n==="env"){let l=Nc(r);return{content:l.removed?`Removed ${l.key} from afk.env (${l.persistedTo}). ${gr}.`:`${l.key} was not set in afk.env; nothing to remove.`}}let a=Kc(r);return{content:a.removed?`Removed ${a.path} from afk.config.json (${a.persistedTo}). ${gr}.`:`${a.path} was not set in afk.config.json; nothing to remove.`}}if(s==null)return Wn(`config_set: \`value\` is required to set ${r}`);if(n==="env"){if(typeof s!="string"&&typeof s!="number"&&typeof s!="boolean")return Wn("config_set: env values must be a string, number, or boolean");let a=Fc(r,String(s));return{content:`Set ${a.key} = ${a.display} in afk.env (${a.persistedTo}). ${gr}.`}}let i=Wc(r,s);return{content:`Set ${i.path} = ${JSON.stringify(i.value)} in afk.config.json (${i.persistedTo}). ${gr}.`}}catch(i){return Wn(`config_set: ${i.message}`)}}});var xs,jf,cn,ta=_(()=>{"use strict";xs={action:"decline"},jf=class{handler=null;queue=Promise.resolve();queueDepth=0;install(t){this.handler=t}uninstall(){this.handler=null}pendingCount(){return this.queueDepth}route(t,n){if(n.signal.aborted)return Promise.resolve(xs);this.queueDepth+=1;let r,o=new Promise(i=>{r=i}),s=this.handler;return this.queue=this.queue.then(async()=>{try{if(n.signal.aborted){r(xs);return}if(!s){r(xs);return}let i,a=new Promise(l=>{i=()=>l(xs),n.signal.addEventListener("abort",i,{once:!0})});try{let l=await Promise.race([s(t,n).catch(()=>xs),a]);r(l)}finally{n.signal.removeEventListener("abort",i)}}finally{this.queueDepth-=1,r(xs)}}).catch(()=>{}),o}},cn=new jf});var yk,bk=_(()=>{"use strict";ta();yk=async(e,t)=>{if(!e||typeof e!="object")return{content:"Invalid input: expected an object",isError:!0};let n=e,r=n.question;if(typeof r!="string"||r.trim()==="")return{content:"Invalid input: question must be a non-empty string",isError:!0};let o=new Set(["text","confirm","choice","multi_choice","number"]),s=n.type??"text";if(typeof s!="string"||!o.has(s))return{content:"Invalid input: type must be one of: text, confirm, choice, multi_choice, number",isError:!0};if(s==="choice"||s==="multi_choice"){let f=n.choices;if(!Array.isArray(f)||f.length===0)return{content:`Invalid input: choices array is required and must be non-empty for type "${s}"`,isError:!0};if(f.length>100)return{content:`Invalid input: choices array must not exceed 100 items, got ${f.length}`,isError:!0};for(let g of f)if(typeof g!="string")return{content:"Invalid input: all choices must be strings",isError:!0}}let i=n.min,a=n.max;if(i!==void 0&&(typeof i!="number"||!Number.isFinite(i)))return{content:"Invalid input: min must be a finite number",isError:!0};if(a!==void 0&&(typeof a!="number"||!Number.isFinite(a)))return{content:"Invalid input: max must be a finite number",isError:!0};if(i!==void 0&&a!==void 0&&i>a)return{content:`Invalid input: min (${i}) must be \u2264 max (${a})`,isError:!0};let l=n.min_length,c=n.max_length;if(l!==void 0&&typeof l!="number")return{content:"Invalid input: min_length must be a number",isError:!0};if(c!==void 0&&typeof c!="number")return{content:"Invalid input: max_length must be a number",isError:!0};if((l!==void 0||c!==void 0)&&s!=="text")return{content:`Invalid input: min_length/max_length are only valid for type "text", got "${s}"`,isError:!0};if(n.allow_custom!==void 0&&s!=="choice"&&s!=="multi_choice")return{content:`Invalid input: allow_custom is only valid for type "choice" or "multi_choice", got "${s}"`,isError:!0};let u={serverName:"agent",message:r.trim(),origin:"agent",type:s,...n.choices!==void 0&&{choices:n.choices},...n.context!==void 0&&typeof n.context=="string"&&{context:n.context},...n.default!==void 0&&{questionDefault:n.default},...l!==void 0&&{minLength:l},...c!==void 0&&{maxLength:c},...i!==void 0&&{min:i},...a!==void 0&&{max:a},...n.allow_skip!==void 0&&{allowSkip:!!n.allow_skip},...n.allow_custom!==void 0&&{allowCustom:!!n.allow_custom}},d=await cn.route(u,{signal:t}),m=d.action==="decline"||d.action==="cancel";return{content:JSON.stringify(d),...m&&{isError:!0}}}});function qc(e){if(e instanceof Error&&e.name==="TimeoutError")return"timeout";let t=e instanceof Error?e.message:String(e);return/Timeout\s+\d+\s*ms exceeded/i.test(t)?"timeout":void 0}function un(e){return wj.some(t=>e.includes(t))}function dn(e){return e.includes("Executable doesn't exist")?"browser tools require the Playwright chromium binary. Install via: pnpm exec playwright install chromium.":"browser tools require the optional `playwright` peer dependency. Install via: pnpm add playwright (then pnpm exec playwright install chromium). Or pick a different tool."}var wj,Es=_(()=>{"use strict";wj=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"]});function Sj(e){if(!e||typeof e!="object")return{error:"browser_open: input must be an object"};let t=e,n=t.url;if(typeof n!="string"||n.length===0)return{error:'browser_open: "url" is required and must be a non-empty string'};let r;try{r=new URL(n)}catch{return{error:`browser_open: "${n}" is not a valid absolute URL`}}if(r.protocol!=="http:"&&r.protocol!=="https:")return{error:`browser_open: protocol "${r.protocol}" is not supported (http/https only)`};let o;if(t.wait_for!==void 0){if(!wk.includes(t.wait_for))return{error:`browser_open: "wait_for" must be one of ${wk.map(a=>`"${a}"`).join(", ")} (got ${JSON.stringify(t.wait_for)})`};o=t.wait_for}let s;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_open: "screenshot" must be a boolean'};s=t.screenshot}let i;if(t.timeout_ms!==void 0){if(typeof t.timeout_ms!="number"||!Number.isFinite(t.timeout_ms)||t.timeout_ms<=0)return{error:'browser_open: "timeout_ms" must be a positive finite number'};i=t.timeout_ms}return{url:r.toString(),waitFor:o,screenshot:s,timeoutMs:i}}function vj(e={}){return async(t,n)=>{if(n.aborted){let i=n.reason;return{content:`browser_open aborted: ${i instanceof Error?i.message:String(i??"aborted")}`,isError:!0,failureClass:"abort"}}let r=Sj(t);if("error"in r)return{content:r.error,isError:!0};let o=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(o))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(o)}`,isError:!0};let s;try{if(e.getBrowserProvider)s=await e.getBrowserProvider();else{let{getBrowserProvider:i}=await Promise.resolve().then(()=>(so(),oo));s=await i()}}catch(i){let a=i instanceof Error?i.message:String(i);return un(a)?{content:dn(a),isError:!0}:{content:`browser_open failed to get provider: ${a}`,isError:!0}}try{let i=await s.open({sessionId:o,url:r.url,waitFor:r.waitFor,screenshot:r.screenshot,timeoutMs:r.timeoutMs});return"outcome"in i&&i.outcome==="blocked_by_policy"?{content:`browser_open blocked: ${i.reason}`,isError:!0,failureClass:"policy-refusal"}:{content:JSON.stringify(i,null,2)}}catch(i){let a=i instanceof Error?i.message:String(i),l=qc(i);return{content:`browser_open failed: ${a}`,isError:!0,...l?{failureClass:l}:{}}}}}var wk,Sk,vk=_(()=>{"use strict";G();Es();wk=["load","domcontentloaded","networkidle"];Sk=vj()});function kj(e){if(e!=null&&typeof e!="object")return{error:"browser_observe: input must be an object or omitted"};if(!e)return{};let t=e,n;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_observe: "screenshot" must be a boolean'};n=t.screenshot}let r;if(t.include_hidden!==void 0){if(typeof t.include_hidden!="boolean")return{error:'browser_observe: "include_hidden" must be a boolean'};r=t.include_hidden}let o;if(t.max_elements!==void 0){if(typeof t.max_elements!="number"||!Number.isFinite(t.max_elements)||t.max_elements<=0||!Number.isInteger(t.max_elements))return{error:'browser_observe: "max_elements" must be a positive integer'};o=t.max_elements}return{screenshot:n,includeHidden:r,maxElements:o}}function xj(e={}){return async(t,n)=>{if(n.aborted){let i=n.reason;return{content:`browser_observe aborted: ${i instanceof Error?i.message:String(i??"aborted")}`,isError:!0}}let r=kj(t);if("error"in r)return{content:r.error,isError:!0};let o=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(o))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(o)}`,isError:!0};let s;try{if(e.getBrowserProvider)s=await e.getBrowserProvider();else{let{getBrowserProvider:i}=await Promise.resolve().then(()=>(so(),oo));s=await i()}}catch(i){let a=i instanceof Error?i.message:String(i);return un(a)?{content:dn(a),isError:!0}:{content:`browser_observe failed to get provider: ${a}`,isError:!0}}try{let i=await s.observe({sessionId:o,screenshot:r.screenshot,includeHidden:r.includeHidden,maxElements:r.maxElements});return{content:JSON.stringify(i,null,2)}}catch(i){return{content:`browser_observe failed: ${i instanceof Error?i.message:String(i)}`,isError:!0}}}}var kk,xk=_(()=>{"use strict";G();Es();kk=xj()});function Ej(e){if(!e||typeof e!="object")return{error:"browser_act: input must be an object"};let t=e;if(typeof t.action!="string")return{error:'browser_act: "action" is required and must be a string'};if(!Ek.includes(t.action))return{error:`browser_act: "action" must be one of ${Ek.map(u=>`"${u}"`).join(", ")} (got ${JSON.stringify(t.action)})`};let n=t.action,r=t.target;if(!r||typeof r!="object")return{error:'browser_act: "target" is required and must be an object'};let o=r;if(typeof o.kind!="string"||!Tk.includes(o.kind))return{error:`browser_act: "target.kind" must be one of ${Tk.map(u=>`"${u}"`).join(", ")} (got ${JSON.stringify(o.kind)})`};let s,i=o.kind;if(i==="semantic"){if(typeof o.text!="string"||o.text.length===0)return{error:'browser_act: target.kind=semantic requires "target.text" (non-empty string)'};s={kind:"semantic",text:o.text,...typeof o.role=="string"&&o.role.length>0?{role:o.role}:{}}}else if(i==="element_id"){if(typeof o.element_id!="string"||o.element_id.length===0)return{error:'browser_act: target.kind=element_id requires "target.element_id" (non-empty string)'};s={kind:"element_id",elementId:o.element_id}}else{if(typeof o.selector!="string"||o.selector.length===0)return{error:'browser_act: target.kind=selector requires "target.selector" (non-empty string)'};s={kind:"selector",selector:o.selector}}let a;if(t.value!==void 0){if(typeof t.value!="string")return{error:'browser_act: "value" must be a string when provided'};a=t.value}let l;if(t.timeout_ms!==void 0){if(typeof t.timeout_ms!="number"||!Number.isFinite(t.timeout_ms)||t.timeout_ms<=0)return{error:'browser_act: "timeout_ms" must be a positive finite number'};l=t.timeout_ms}let c;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_act: "screenshot" must be a boolean'};c=t.screenshot}return{action:n,target:s,value:a,timeoutMs:l,screenshot:c}}function Tj(e,t){let n=e.role?`"${e.text}" (role: ${e.role})`:`"${e.text}"`;return[`browser_act: ambiguous target \u2014 ${t.length} elements matched ${n}.`,'Retry with target.kind="element_id" using one of the following:',...t.map(o=>` id=${o.id} role=${o.role} label=${o.label}`)].join(`
1089
+ `,384)}function dk(e,t){let n=Of(e);if(n==="unknown")throw new ea(e);if(n==="human"&&!t)throw new Nf(e);return n}function Wc(e,t,n){let r=dk(e,n?.allowHumanOnly),o=rk(e),s=ok(o,t);if(!s.ok)throw new $c(s.error);let i=jc(n),a=Hc(i);return ik(a,e,s.value),uk(i,a),{path:e,class:r,value:s.value,persistedTo:i}}function Kc(e,t){let n=dk(e,t?.allowHumanOnly),r=jc(t),o=Hc(r),s=ak(o,e);return s&&uk(r,o),{path:e,class:n,removed:s,persistedTo:r}}function Gc(e,t){let n=Of(e),r=jc(t),o=Hc(r);return{path:e,class:n,value:sk(o,e)}}function zc(e){return Hc(jc(e))}var gr,ea,Df,Lf,Ff,Nf,$c,Dc,Uf=_(()=>{"use strict";K();G();Oc();$f();gr="effective on the next session/daemon restart; the current session is unchanged",ea=class extends Error{constructor(t){super(`unknown config key: ${t}`),this.name="UnknownKeyError"}},Df=class extends Error{constructor(t){super(`${t} is a process/inherited env var and is not afk-configurable`),this.name="NonConfigKeyError"}},Lf=class extends Error{constructor(t){super(`${t} holds a credential; the agent cannot set it. A human must run \`afk config env set ${t}\` (the value is entered masked and never enters the model context).`),this.name="SecretWriteRefused"}},Ff=class extends Error{constructor(t){super(`${t} controls identity, safety, capability, autonomous runs, request routing, or where AFK's own state lives; the agent cannot set it. A human must run \`afk config env set ${t}\`.`),this.name="ProtectedEnvKeyRefused"}},Nf=class extends Error{constructor(t){super(`${t} is human-gated (prompt/hooks/identity); the agent cannot set it. A human must run \`afk config set ${t}\`.`),this.name="HumanOnlyKeyRefused"}},$c=class extends Error{constructor(t){super(t),this.name="ConfigValidationError"}},Dc=class extends Error{constructor(t){super(`refusing to write: existing ${t} is not valid JSON (fix or remove it by hand first)`),this.name="MalformedConfigError"}}});function pk(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function mk(e){return e==="env"||e==="config"?e:void 0}function Wn(e){return{content:e,isError:!0}}var fk,gk,hk=_(()=>{"use strict";Uf();fk=async e=>{let t=pk(e);if(!t)return Wn("config_get: expected an object input");let n=mk(t.target);if(!n)return Wn("config_get: `target` must be 'env' or 'config'");let r=typeof t.key=="string"?t.key:void 0,o=t.all===!0;try{if(n==="env"){if(r){let s=Bc(r);return{content:JSON.stringify(s,null,2)}}return{content:JSON.stringify(Uc({all:o}),null,2)}}if(r){let s=Gc(r);return{content:JSON.stringify(s,null,2)}}return{content:JSON.stringify(zc(),null,2)}}catch(s){return Wn(`config_get: ${s.message}`)}},gk=async e=>{let t=pk(e);if(!t)return Wn("config_set: expected an object input");let n=mk(t.target);if(!n)return Wn("config_set: `target` must be 'env' or 'config'");let r=typeof t.key=="string"?t.key:void 0;if(!r)return Wn("config_set: `key` is required");let o=t.action==="unset"?"unset":"set",s=t.value;try{if(o==="unset"){if(n==="env"){let l=Nc(r);return{content:l.removed?`Removed ${l.key} from afk.env (${l.persistedTo}). ${gr}.`:`${l.key} was not set in afk.env; nothing to remove.`}}let a=Kc(r);return{content:a.removed?`Removed ${a.path} from afk.config.json (${a.persistedTo}). ${gr}.`:`${a.path} was not set in afk.config.json; nothing to remove.`}}if(s==null)return Wn(`config_set: \`value\` is required to set ${r}`);if(n==="env"){if(typeof s!="string"&&typeof s!="number"&&typeof s!="boolean")return Wn("config_set: env values must be a string, number, or boolean");let a=Fc(r,String(s));return{content:`Set ${a.key} = ${a.display} in afk.env (${a.persistedTo}). ${gr}.`}}let i=Wc(r,s);return{content:`Set ${i.path} = ${JSON.stringify(i.value)} in afk.config.json (${i.persistedTo}). ${gr}.`}}catch(i){return Wn(`config_set: ${i.message}`)}}});var xs,jf,cn,ta=_(()=>{"use strict";xs={action:"decline"},jf=class{handler=null;queue=Promise.resolve();queueDepth=0;install(t){this.handler=t}uninstall(){this.handler=null}pendingCount(){return this.queueDepth}route(t,n){if(n.signal.aborted)return Promise.resolve(xs);this.queueDepth+=1;let r,o=new Promise(i=>{r=i}),s=this.handler;return this.queue=this.queue.then(async()=>{try{if(n.signal.aborted){r(xs);return}if(!s){r(xs);return}let i,a=new Promise(l=>{i=()=>l(xs),n.signal.addEventListener("abort",i,{once:!0})});try{let l=await Promise.race([s(t,n).catch(()=>xs),a]);r(l)}finally{n.signal.removeEventListener("abort",i)}}finally{this.queueDepth-=1,r(xs)}}).catch(()=>{}),o}},cn=new jf});var yk,bk=_(()=>{"use strict";ta();yk=async(e,t)=>{if(!e||typeof e!="object")return{content:"Invalid input: expected an object",isError:!0};let n=e,r=n.question;if(typeof r!="string"||r.trim()==="")return{content:"Invalid input: question must be a non-empty string",isError:!0};let o=new Set(["text","confirm","choice","multi_choice","number"]),s=n.type??"text";if(typeof s!="string"||!o.has(s))return{content:"Invalid input: type must be one of: text, confirm, choice, multi_choice, number",isError:!0};if(s==="choice"||s==="multi_choice"){let f=n.choices;if(!Array.isArray(f)||f.length===0)return{content:`Invalid input: choices array is required and must be non-empty for type "${s}"`,isError:!0};if(f.length>100)return{content:`Invalid input: choices array must not exceed 100 items, got ${f.length}`,isError:!0};for(let g of f)if(typeof g!="string")return{content:"Invalid input: all choices must be strings",isError:!0}}let i=n.min,a=n.max;if(i!==void 0&&(typeof i!="number"||!Number.isFinite(i)))return{content:"Invalid input: min must be a finite number",isError:!0};if(a!==void 0&&(typeof a!="number"||!Number.isFinite(a)))return{content:"Invalid input: max must be a finite number",isError:!0};if(i!==void 0&&a!==void 0&&i>a)return{content:`Invalid input: min (${i}) must be \u2264 max (${a})`,isError:!0};let l=n.min_length,c=n.max_length;if(l!==void 0&&typeof l!="number")return{content:"Invalid input: min_length must be a number",isError:!0};if(c!==void 0&&typeof c!="number")return{content:"Invalid input: max_length must be a number",isError:!0};if((l!==void 0||c!==void 0)&&s!=="text")return{content:`Invalid input: min_length/max_length are only valid for type "text", got "${s}"`,isError:!0};if(n.allow_custom!==void 0&&s!=="choice"&&s!=="multi_choice")return{content:`Invalid input: allow_custom is only valid for type "choice" or "multi_choice", got "${s}"`,isError:!0};let u={serverName:"agent",message:r.trim(),origin:"agent",type:s,...n.choices!==void 0&&{choices:n.choices},...n.context!==void 0&&typeof n.context=="string"&&{context:n.context},...n.default!==void 0&&{questionDefault:n.default},...l!==void 0&&{minLength:l},...c!==void 0&&{maxLength:c},...i!==void 0&&{min:i},...a!==void 0&&{max:a},...n.allow_skip!==void 0&&{allowSkip:!!n.allow_skip},...n.allow_custom!==void 0&&{allowCustom:!!n.allow_custom}},d=await cn.route(u,{signal:t}),m=d.action==="decline"||d.action==="cancel";return{content:JSON.stringify(d),...m&&{isError:!0,failureClass:"elicitation-declined"}}}});function qc(e){if(e instanceof Error&&e.name==="TimeoutError")return"timeout";let t=e instanceof Error?e.message:String(e);return/Timeout\s+\d+\s*ms exceeded/i.test(t)?"timeout":void 0}function un(e){return wj.some(t=>e.includes(t))}function dn(e){return e.includes("Executable doesn't exist")?"browser tools require the Playwright chromium binary. Install via: pnpm exec playwright install chromium.":"browser tools require the optional `playwright` peer dependency. Install via: pnpm add playwright (then pnpm exec playwright install chromium). Or pick a different tool."}var wj,Es=_(()=>{"use strict";wj=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"]});function Sj(e){if(!e||typeof e!="object")return{error:"browser_open: input must be an object"};let t=e,n=t.url;if(typeof n!="string"||n.length===0)return{error:'browser_open: "url" is required and must be a non-empty string'};let r;try{r=new URL(n)}catch{return{error:`browser_open: "${n}" is not a valid absolute URL`}}if(r.protocol!=="http:"&&r.protocol!=="https:")return{error:`browser_open: protocol "${r.protocol}" is not supported (http/https only)`};let o;if(t.wait_for!==void 0){if(!wk.includes(t.wait_for))return{error:`browser_open: "wait_for" must be one of ${wk.map(a=>`"${a}"`).join(", ")} (got ${JSON.stringify(t.wait_for)})`};o=t.wait_for}let s;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_open: "screenshot" must be a boolean'};s=t.screenshot}let i;if(t.timeout_ms!==void 0){if(typeof t.timeout_ms!="number"||!Number.isFinite(t.timeout_ms)||t.timeout_ms<=0)return{error:'browser_open: "timeout_ms" must be a positive finite number'};i=t.timeout_ms}return{url:r.toString(),waitFor:o,screenshot:s,timeoutMs:i}}function vj(e={}){return async(t,n)=>{if(n.aborted){let i=n.reason;return{content:`browser_open aborted: ${i instanceof Error?i.message:String(i??"aborted")}`,isError:!0,failureClass:"abort"}}let r=Sj(t);if("error"in r)return{content:r.error,isError:!0};let o=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(o))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(o)}`,isError:!0};let s;try{if(e.getBrowserProvider)s=await e.getBrowserProvider();else{let{getBrowserProvider:i}=await Promise.resolve().then(()=>(so(),oo));s=await i()}}catch(i){let a=i instanceof Error?i.message:String(i);return un(a)?{content:dn(a),isError:!0}:{content:`browser_open failed to get provider: ${a}`,isError:!0}}try{let i=await s.open({sessionId:o,url:r.url,waitFor:r.waitFor,screenshot:r.screenshot,timeoutMs:r.timeoutMs});return"outcome"in i&&i.outcome==="blocked_by_policy"?{content:`browser_open blocked: ${i.reason}`,isError:!0,failureClass:"policy-refusal"}:{content:JSON.stringify(i,null,2)}}catch(i){let a=i instanceof Error?i.message:String(i),l=qc(i);return{content:`browser_open failed: ${a}`,isError:!0,...l?{failureClass:l}:{}}}}}var wk,Sk,vk=_(()=>{"use strict";G();Es();wk=["load","domcontentloaded","networkidle"];Sk=vj()});function kj(e){if(e!=null&&typeof e!="object")return{error:"browser_observe: input must be an object or omitted"};if(!e)return{};let t=e,n;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_observe: "screenshot" must be a boolean'};n=t.screenshot}let r;if(t.include_hidden!==void 0){if(typeof t.include_hidden!="boolean")return{error:'browser_observe: "include_hidden" must be a boolean'};r=t.include_hidden}let o;if(t.max_elements!==void 0){if(typeof t.max_elements!="number"||!Number.isFinite(t.max_elements)||t.max_elements<=0||!Number.isInteger(t.max_elements))return{error:'browser_observe: "max_elements" must be a positive integer'};o=t.max_elements}return{screenshot:n,includeHidden:r,maxElements:o}}function xj(e={}){return async(t,n)=>{if(n.aborted){let i=n.reason;return{content:`browser_observe aborted: ${i instanceof Error?i.message:String(i??"aborted")}`,isError:!0}}let r=kj(t);if("error"in r)return{content:r.error,isError:!0};let o=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(o))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(o)}`,isError:!0};let s;try{if(e.getBrowserProvider)s=await e.getBrowserProvider();else{let{getBrowserProvider:i}=await Promise.resolve().then(()=>(so(),oo));s=await i()}}catch(i){let a=i instanceof Error?i.message:String(i);return un(a)?{content:dn(a),isError:!0}:{content:`browser_observe failed to get provider: ${a}`,isError:!0}}try{let i=await s.observe({sessionId:o,screenshot:r.screenshot,includeHidden:r.includeHidden,maxElements:r.maxElements});return{content:JSON.stringify(i,null,2)}}catch(i){return{content:`browser_observe failed: ${i instanceof Error?i.message:String(i)}`,isError:!0}}}}var kk,xk=_(()=>{"use strict";G();Es();kk=xj()});function Ej(e){if(!e||typeof e!="object")return{error:"browser_act: input must be an object"};let t=e;if(typeof t.action!="string")return{error:'browser_act: "action" is required and must be a string'};if(!Ek.includes(t.action))return{error:`browser_act: "action" must be one of ${Ek.map(u=>`"${u}"`).join(", ")} (got ${JSON.stringify(t.action)})`};let n=t.action,r=t.target;if(!r||typeof r!="object")return{error:'browser_act: "target" is required and must be an object'};let o=r;if(typeof o.kind!="string"||!Tk.includes(o.kind))return{error:`browser_act: "target.kind" must be one of ${Tk.map(u=>`"${u}"`).join(", ")} (got ${JSON.stringify(o.kind)})`};let s,i=o.kind;if(i==="semantic"){if(typeof o.text!="string"||o.text.length===0)return{error:'browser_act: target.kind=semantic requires "target.text" (non-empty string)'};s={kind:"semantic",text:o.text,...typeof o.role=="string"&&o.role.length>0?{role:o.role}:{}}}else if(i==="element_id"){if(typeof o.element_id!="string"||o.element_id.length===0)return{error:'browser_act: target.kind=element_id requires "target.element_id" (non-empty string)'};s={kind:"element_id",elementId:o.element_id}}else{if(typeof o.selector!="string"||o.selector.length===0)return{error:'browser_act: target.kind=selector requires "target.selector" (non-empty string)'};s={kind:"selector",selector:o.selector}}let a;if(t.value!==void 0){if(typeof t.value!="string")return{error:'browser_act: "value" must be a string when provided'};a=t.value}let l;if(t.timeout_ms!==void 0){if(typeof t.timeout_ms!="number"||!Number.isFinite(t.timeout_ms)||t.timeout_ms<=0)return{error:'browser_act: "timeout_ms" must be a positive finite number'};l=t.timeout_ms}let c;if(t.screenshot!==void 0){if(typeof t.screenshot!="boolean")return{error:'browser_act: "screenshot" must be a boolean'};c=t.screenshot}return{action:n,target:s,value:a,timeoutMs:l,screenshot:c}}function Tj(e,t){let n=e.role?`"${e.text}" (role: ${e.role})`:`"${e.text}"`;return[`browser_act: ambiguous target \u2014 ${t.length} elements matched ${n}.`,'Retry with target.kind="element_id" using one of the following:',...t.map(o=>` id=${o.id} role=${o.role} label=${o.label}`)].join(`
1090
1090
  `)}function Rj(e){return e.kind==="semantic"?`semantic:${hv(e.text)}`:e.kind==="element_id"?`element_id:${e.elementId}`:`selector:${gv(e.selector)}`}function Cj(e={}){return async(t,n)=>{if(n.aborted){let a=n.reason;return{content:`browser_act aborted: ${a instanceof Error?a.message:String(a??"aborted")}`,isError:!0,failureClass:"abort"}}let r=Ej(t);if("error"in r)return{content:r.error,isError:!0};let o=Rj(r.target),s=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(s))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(s)}`,isError:!0};let i;try{if(e.getBrowserProvider)i=await e.getBrowserProvider();else{let{getBrowserProvider:a}=await Promise.resolve().then(()=>(so(),oo));i=await a()}}catch(a){let l=a instanceof Error?a.message:String(a);return un(l)?{content:dn(l),isError:!0}:{content:`browser_act failed to get provider: ${l}`,isError:!0}}try{let a=await i.act({sessionId:s,action:r.action,target:r.target,value:r.value,timeoutMs:r.timeoutMs,screenshot:r.screenshot});if("outcome"in a){if(a.outcome==="ambiguous_target")return{content:Tj(a.query,a.candidates),isError:!0};if(a.outcome==="blocked_by_policy")return{content:`browser_act blocked: ${a.reason}`,isError:!0,failureClass:"policy-refusal"}}return{content:JSON.stringify(a,null,2)}}catch(a){let l=a instanceof Error?a.message:String(a),c=qc(a);return{content:`browser_act failed: ${l}`,isError:!0,...c?{failureClass:c}:{}}}}}var Ek,Tk,Rk,Ck=_(()=>{"use strict";Xi();G();Es();Ek=["click","fill","press","select","hover","scroll_to","wait_for"],Tk=["semantic","element_id","selector"];Rk=Cj()});function _j(e){if(typeof e.kind!="string"||!_k.includes(e.kind))return{error:`browser_screenshot: "target.kind" must be one of ${_k.map(n=>`"${n}"`).join(", ")} (got ${JSON.stringify(e.kind)})`};let t=e.kind;return t==="semantic"?typeof e.text!="string"||e.text.length===0?{error:'browser_screenshot: target.kind=semantic requires "target.text" (non-empty string)'}:{kind:"semantic",text:e.text,...typeof e.role=="string"&&e.role.length>0?{role:e.role}:{}}:t==="element_id"?typeof e.element_id!="string"||e.element_id.length===0?{error:'browser_screenshot: target.kind=element_id requires "target.element_id" (non-empty string)'}:{kind:"element_id",elementId:e.element_id}:typeof e.selector!="string"||e.selector.length===0?{error:'browser_screenshot: target.kind=selector requires "target.selector" (non-empty string)'}:{kind:"selector",selector:e.selector}}function Aj(e){if(e!=null&&typeof e!="object")return{error:"browser_screenshot: input must be an object or omitted"};if(!e)return{};let t=e,n;if(t.target!==void 0){if(!t.target||typeof t.target!="object")return{error:'browser_screenshot: "target" must be an object when provided'};let o=_j(t.target);if("error"in o)return o;n=o}let r;if(t.full_page!==void 0){if(typeof t.full_page!="boolean")return{error:'browser_screenshot: "full_page" must be a boolean'};r=t.full_page}return{target:n,fullPage:r}}function Ij(e={}){return async(t,n)=>{if(n.aborted){let i=n.reason;return{content:`browser_screenshot aborted: ${i instanceof Error?i.message:String(i??"aborted")}`,isError:!0}}let r=Aj(t);if("error"in r)return{content:r.error,isError:!0};let o=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(o))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(o)}`,isError:!0};let s;try{if(e.getBrowserProvider)s=await e.getBrowserProvider();else{let{getBrowserProvider:i}=await Promise.resolve().then(()=>(so(),oo));s=await i()}}catch(i){let a=i instanceof Error?i.message:String(i);return un(a)?{content:dn(a),isError:!0}:{content:`browser_screenshot failed to get provider: ${a}`,isError:!0}}try{let i=await s.screenshot({sessionId:o,target:r.target,fullPage:r.fullPage}),{dataBase64:a,mediaType:l,...c}=i;return c.width>Hf||c.height>Hf?{content:JSON.stringify({...c,imageOmitted:`dimensions ${c.width}x${c.height}px exceed the ${Hf}px model-vision limit; the PNG was saved to the sidecar path but not attached. Use full_page:false (viewport) or target a specific element for a model-visible image.`},null,2)}:{content:JSON.stringify(c,null,2),image:{mediaType:l,data:a}}}catch(i){return{content:`browser_screenshot failed: ${i instanceof Error?i.message:String(i)}`,isError:!0}}}}var _k,Hf,Ak,Ik=_(()=>{"use strict";G();Es();_k=["semantic","element_id","selector"],Hf=8e3;Ak=Ij()});function Pj(e={}){return async(t,n)=>{if(n.aborted){let s=n.reason;return{content:`browser_close aborted: ${s instanceof Error?s.message:String(s??"aborted")}`,isError:!0}}let r=k.AFK_SESSION_ID??"default";if(!/^[a-zA-Z0-9_-]+$/.test(r))return{content:`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(r)}`,isError:!0};let o;try{if(e.getBrowserProvider)o=await e.getBrowserProvider();else{let{getBrowserProvider:s}=await Promise.resolve().then(()=>(so(),oo));o=await s()}}catch(s){let i=s instanceof Error?s.message:String(s);return un(i)?{content:dn(i),isError:!0}:{content:`browser_close failed to get provider: ${i}`,isError:!0}}try{return await o.close({sessionId:r}),{content:"Browser session closed."}}catch(s){return{content:`browser_close failed: ${s instanceof Error?s.message:String(s)}`,isError:!0}}}}var Pk,Mk=_(()=>{"use strict";G();Es();Pk=Pj()});function Jc(e,t){let n=e!==void 0?mc(e,t):t!==void 0?mc("default",t):fS,r=t!==void 0?Xm(t):RS,o=t!==void 0?Zm(t):_S,s=If();return new Map([["bash",n],["read_file",hS],["write_file",SS],["edit_file",kS],["glob",r],["grep",o],["list_directory",IS],["send_telegram",ov],["web_scrape",Bv],["create_schedule",Kv],["list_schedules",Gv],["get_schedule_history",zv],["cancel_schedule",qv],["terminal_font_size",s],["config_get",fk],["config_set",gk],["ask_question",yk],["browser_open",Sk],["browser_observe",kk],["browser_act",Rk],["browser_screenshot",Ak],["browser_close",Pk]])}var Wf=_(()=>{"use strict";gS();yS();vS();xS();CS();AS();PS();sv();Uv();Jv();Mf();hk();bk();vk();xk();Ck();Ik();Mk()});import{existsSync as Mj,readFileSync as Oj}from"fs";import{join as $j}from"path";function Ok(){let e=$j(Cl(),"HOT.md");if(!Mj(e))return null;try{let t=Oj(e,"utf-8");return t.trim().length>0?t:null}catch{return null}}function Kn(e){let t=Ok();if(!t)return e;let r=`<cross-session-memory>
1091
1091
  ${t.replace(/<\/?cross-session-memory\b[^>]*>/gi,"")}
1092
1092
  </cross-session-memory>`,o=e.systemPrompt;if(typeof o=="string")return{...e,systemPrompt:`${r}
@@ -1691,7 +1691,7 @@ ${r} skill ${o} from \`/forge-friction\` awaiting generation in \`${t}/\`: ${s}
1691
1691
 
1692
1692
  Run \`/forge\` to process (it will pick up the pending briefs automatically). Ignore if the user is mid-task on something else.`}function Mu(e,t,n="one-shot",r){if(!e)return e;let o=[e];return t&&o.push(hG),bG.has(n)&&(r!==void 0&&o.push(r),o.push(yG)),o.join(`
1693
1693
 
1694
- `)}import Yn from"chalk";Qc();var wG={read:Yn.hex("#C9B584"),write:Yn.hex("#E8A33D"),shell:Yn.hex("#A8E060"),subagent:p.plan,skill:Yn.hex("#F08AC4"),dag:Yn.hex("#4EC9B0"),mcp:Yn.hex("#5FE0C0"),web:Yn.hex("#A0C4C0"),browser:Yn.hex("#FF8A65"),planning:p.meta,schedule:Yn.hex("#D4A84B"),other:p.meta},SG={read:"\u25CF",write:"\u270E",shell:"$",subagent:"\u2192",skill:"\u25C6",dag:"\u2B21",mcp:"\u22A1",web:"\u2316",browser:"\u25C9",planning:"\u25B1",schedule:"\u23F2",other:"\u25CF"};function qg(e){return{color:wG[e],glyph:SG[e]}}function qs(e){return qg(br(e))}function Ou(e,t){let n=t??process.stdout.columns??80;return!Number.isFinite(n)||n<=0?e:ie(e,n)}function $u(e,t){let{description:n,summary:r,lastToolName:o,totalTokens:s,toolUses:i,durationMs:a}=e,l=[];if(o){let{color:u,glyph:d}=qs(o);l.push(`via ${u(`${d} ${o}`)}`)}i&&l.push(`${i} tool${i===1?"":"s"}`),s&&l.push(`${ae(s)} tok`),a&&l.push(ge(a)),l.push("esc to interrupt \xB7 ctrl+b background");let c=l.length>0?` (${l.join(" \xB7 ")})`:"";return r?[Ou(p.dim(` \u25E6 ${n}`),t),Ou(p.dim(` ${r}${c}`),t)]:[Ou(p.dim(` \u25E6 ${n}${c}`),t)]}function Du(e,t){let n=e.status==="succeeded"?"\u2713":e.status==="failed"?"\u2717":"\u2298",r=e.agentType??e.subagentId,o=[n,r];return e.durationMs!==void 0&&o.push(`\xB7 ${ge(e.durationMs)}`),Ou(p.dim(` ${o.join(" ")}`),t)}Ke();ma();fa();Sr();uo();on();Jt();an();G();K();import{randomUUID as YG}from"node:crypto";import{createHash as KG}from"crypto";import{appendFileSync as GG}from"fs";import{mkdir as zG,open as qG,writeFile as JG}from"fs/promises";import{join as DR}from"path";import{z as x}from"zod";var vR=["policy-refusal","timeout","permission-denied","hook-block","abort"];var vG=x.object({phase:x.literal("started"),toolUseId:x.string(),name:x.string(),inputBytes:x.number().int().nonnegative(),subagentId:x.string().optional()}),kG=x.enum(vR),xG=x.object({phase:x.literal("completed"),toolUseId:x.string(),name:x.string(),resultBytes:x.number().int().nonnegative(),isError:x.boolean(),truncated:x.boolean(),durationMs:x.number().nonnegative(),circuitBreaker:x.boolean().optional(),failureClass:kG.optional(),subagentId:x.string().optional()}),kR=x.discriminatedUnion("phase",[vG,xG]),EG=x.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),xR=x.object({hookEvent:EG,decision:x.union([x.literal("block"),x.literal("approve"),x.undefined()]),reason:x.string().optional(),blockedTool:x.string().optional(),injectedContextBytes:x.number().int().nonnegative().optional()}),TG=x.object({transition:x.literal("started"),subagentId:x.string(),parentId:x.string(),model:x.string(),allowedTools:x.array(x.string()).readonly().optional(),systemPromptHash:x.string().optional()}),RG=x.object({transition:x.literal("succeeded"),subagentId:x.string(),durationMs:x.number().nonnegative(),turnCount:x.number().int().nonnegative(),totalCostUsd:x.number().nonnegative().optional(),outputBytes:x.number().int().nonnegative()}),CG=x.object({transition:x.literal("failed"),subagentId:x.string(),errorClass:x.string(),errorMessage:x.string(),partialOutputBytes:x.number().int().nonnegative()}),_G=x.object({transition:x.literal("cancelled"),subagentId:x.string(),source:x.enum(["cascade","explicit"])}),ER=x.discriminatedUnion("transition",[TG,RG,CG,_G]),AG=x.object({transition:x.literal("started"),jobId:x.string(),subagentId:x.string(),label:x.string(),model:x.string()}),IG=x.object({transition:x.literal("completed"),jobId:x.string(),subagentId:x.string(),durationMs:x.number().nonnegative(),outputBytes:x.number().int().nonnegative()}),PG=x.object({transition:x.literal("failed"),jobId:x.string(),subagentId:x.string(),durationMs:x.number().nonnegative(),errorClass:x.string(),errorMessage:x.string()}),MG=x.object({transition:x.literal("cancelled"),jobId:x.string(),subagentId:x.string(),source:x.enum(["explicit","cascade"])}),OG=x.object({transition:x.literal("joined"),jobId:x.string(),subagentId:x.string(),jobStatus:x.enum(["completed","failed","cancelled"])}),TR=x.discriminatedUnion("transition",[AG,IG,PG,MG,OG]),RR=x.object({kind:x.literal("monetary"),runningCostUsd:x.number().nonnegative(),maxBudgetUsd:x.number().nonnegative(),lastTurnCostUsd:x.number().nonnegative()}),$G=x.enum(["user_signal","cascade","timeout","budget","hook_block"]),CR=x.object({origin:$G,cascadedTo:x.array(x.string()).readonly(),reason:x.string().optional()}),_R=x.enum(["manual","token_threshold","turn_count"]),DG=x.object({path:x.string(),sizeBytes:x.number().int().nonnegative(),sha256:x.string().regex(/^[0-9a-f]{64}$/)}),LG=x.object({trigger:_R,preCompactionMessages:x.array(x.unknown()),summary:x.string(),keptTailCount:x.number().int().nonnegative(),keepLastNConfig:x.number().int().nonnegative(),messagesBefore:x.number().int().nonnegative(),messagesAfter:x.number().int().nonnegative(),tokensSavedEstimate:x.number().nonnegative().optional(),summarizationTokens:x.object({input:x.number().int().nonnegative(),output:x.number().int().nonnegative()}).optional()}),FG=x.object({trigger:_R,preCompactionMessagesRef:DG,summary:x.string(),keptTailCount:x.number().int().nonnegative(),keepLastNConfig:x.number().int().nonnegative(),messagesBefore:x.number().int().nonnegative(),messagesAfter:x.number().int().nonnegative(),tokensSavedEstimate:x.number().nonnegative().optional(),summarizationTokens:x.object({input:x.number().int().nonnegative(),output:x.number().int().nonnegative()}).optional()}),NG=x.enum(["model_end_turn","truncated","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),AR=x.object({reason:NG,finalTurnCount:x.number().int().nonnegative(),finalCostUsd:x.number().nonnegative(),finalTokens:x.object({input:x.number().int().nonnegative().optional(),output:x.number().int().nonnegative().optional(),cacheRead:x.number().int().nonnegative().optional(),cacheCreation:x.number().int().nonnegative().optional()}),lastStopReason:x.string().optional(),guidance:x.string().optional()}),IR=x.object({source:x.string(),assertion:x.string(),evidence:x.array(x.string()).readonly(),confidence:x.number().min(0).max(1),dissent:x.string().optional()}),BG=x.enum(["browser_open","browser_observe","browser_act","browser_screenshot","browser_extract","browser_close"]),UG=x.enum(["click","fill","press","select","hover","scroll_to","wait_for"]),jG=x.object({kind:x.enum(["semantic","element_id","selector"]),text:x.string().max(80).optional(),role:x.string().optional(),elementId:x.string().optional(),selectorHash:x.string().regex(/^[0-9a-f]{8}$/).optional()}),PR=x.object({tool:BG,action:UG.optional(),toolUseId:x.string(),target:jG.optional(),urlBefore:x.string().nullable(),urlAfter:x.string().nullable(),status:x.enum(["ok","error","ambiguous_target","blocked_by_policy"]),screenshotPath:x.string().optional(),observationSummary:x.string().max(500).optional(),error:x.object({reason:x.string(),recoverable:x.boolean()}).optional(),durationMs:x.number().nonnegative()}),HG=x.enum(["bootstrap_start","bootstrap_done","session_init_start","session_init_done","mcp_connect_start","mcp_connect_done","mcp_server_start","mcp_server_done","loop_start","loop_end","model_ttfb"]),MR=x.object({phase:HG,durationMs:x.number().nonnegative().optional(),metadata:x.record(x.string(),x.union([x.string(),x.number(),x.boolean()])).optional(),model:x.string().optional(),resolvedModel:x.string().optional()}),WG=x.object({status:x.enum(["succeeded","failed","cancelled"]),finalCostUsd:x.number().nonnegative(),finalTurnCount:x.number().int().nonnegative(),closedAt:x.string().datetime(),incomplete:x.boolean().optional(),subagentCount:x.number().int().nonnegative().optional(),subagentTokens:x.object({input:x.number().int().nonnegative().optional(),output:x.number().int().nonnegative().optional(),cacheRead:x.number().int().nonnegative().optional(),cacheCreation:x.number().int().nonnegative().optional()}).optional(),subagentCostUsd:x.number().nonnegative().optional()}),OR=x.discriminatedUnion("kind",[x.object({kind:x.literal("tool_call"),payload:kR}),x.object({kind:x.literal("hook_decision"),payload:xR}),x.object({kind:x.literal("subagent_lifecycle"),payload:ER}),x.object({kind:x.literal("background_agent"),payload:TR}),x.object({kind:x.literal("budget"),payload:RR}),x.object({kind:x.literal("abort"),payload:CR}),x.object({kind:x.literal("compaction"),payload:LG}),x.object({kind:x.literal("closure"),payload:AR}),x.object({kind:x.literal("claim"),payload:IR}),x.object({kind:x.literal("browser_event"),payload:PR}),x.object({kind:x.literal("session_phase"),payload:MR})]),$R=x.discriminatedUnion("kind",[x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("tool_call"),payload:kR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("hook_decision"),payload:xR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("subagent_lifecycle"),payload:ER}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("background_agent"),payload:TR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("budget"),payload:RR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("abort"),payload:CR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("compaction"),payload:FG}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("closure"),payload:AR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("claim"),payload:IR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("browser_event"),payload:PR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("session_phase"),payload:MR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("session_sealed"),payload:WG})]);var Lu=new Set,LR=!1;function VG(){LR||(LR=!0,process.on("exit",()=>{for(let e of Lu)e.sealOnProcessExit()}))}var Fu=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(t){this.traceDir=t.traceDir,this.tracePath=DR(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(t){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return OR.parse(t),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(t);await this.appendLine(n)})}async seal(t){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:t};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(t){let n=this.writeQueue.then(t,t);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await zG(this.traceDir,{recursive:!0}),this.fh=await qG(this.tracePath,"a"),Lu.add(this),VG())}async closeHandle(){if(Lu.delete(this),!this.fh)return;let t=this.fh;this.fh=null,await t.close()}sealOnProcessExit(){if(this.sealed||this.seq===0)return;this.sealed=!0,Lu.delete(this);try{let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:{status:"failed",finalCostUsd:0,finalTurnCount:0,closedAt:new Date().toISOString(),incomplete:!0}};GG(this.tracePath,`${JSON.stringify(n)}
1694
+ `)}import Yn from"chalk";Qc();var wG={read:Yn.hex("#C9B584"),write:Yn.hex("#E8A33D"),shell:Yn.hex("#A8E060"),subagent:p.plan,skill:Yn.hex("#F08AC4"),dag:Yn.hex("#4EC9B0"),mcp:Yn.hex("#5FE0C0"),web:Yn.hex("#A0C4C0"),browser:Yn.hex("#FF8A65"),planning:p.meta,schedule:Yn.hex("#D4A84B"),other:p.meta},SG={read:"\u25CF",write:"\u270E",shell:"$",subagent:"\u2192",skill:"\u25C6",dag:"\u2B21",mcp:"\u22A1",web:"\u2316",browser:"\u25C9",planning:"\u25B1",schedule:"\u23F2",other:"\u25CF"};function qg(e){return{color:wG[e],glyph:SG[e]}}function qs(e){return qg(br(e))}function Ou(e,t){let n=t??process.stdout.columns??80;return!Number.isFinite(n)||n<=0?e:ie(e,n)}function $u(e,t){let{description:n,summary:r,lastToolName:o,totalTokens:s,toolUses:i,durationMs:a}=e,l=[];if(o){let{color:u,glyph:d}=qs(o);l.push(`via ${u(`${d} ${o}`)}`)}i&&l.push(`${i} tool${i===1?"":"s"}`),s&&l.push(`${ae(s)} tok`),a&&l.push(ge(a)),l.push("esc to interrupt \xB7 ctrl+b background");let c=l.length>0?` (${l.join(" \xB7 ")})`:"";return r?[Ou(p.dim(` \u25E6 ${n}`),t),Ou(p.dim(` ${r}${c}`),t)]:[Ou(p.dim(` \u25E6 ${n}${c}`),t)]}function Du(e,t){let n=e.status==="succeeded"?"\u2713":e.status==="failed"?"\u2717":"\u2298",r=e.agentType??e.subagentId,o=[n,r];return e.durationMs!==void 0&&o.push(`\xB7 ${ge(e.durationMs)}`),Ou(p.dim(` ${o.join(" ")}`),t)}Ke();ma();fa();Sr();uo();on();Jt();an();G();K();import{randomUUID as YG}from"node:crypto";import{createHash as KG}from"crypto";import{appendFileSync as GG}from"fs";import{mkdir as zG,open as qG,writeFile as JG}from"fs/promises";import{join as DR}from"path";import{z as x}from"zod";var vR=["policy-refusal","timeout","permission-denied","hook-block","abort","elicitation-declined"];var vG=x.object({phase:x.literal("started"),toolUseId:x.string(),name:x.string(),inputBytes:x.number().int().nonnegative(),subagentId:x.string().optional()}),kG=x.enum(vR),xG=x.object({phase:x.literal("completed"),toolUseId:x.string(),name:x.string(),resultBytes:x.number().int().nonnegative(),isError:x.boolean(),truncated:x.boolean(),durationMs:x.number().nonnegative(),circuitBreaker:x.boolean().optional(),failureClass:kG.optional(),subagentId:x.string().optional()}),kR=x.discriminatedUnion("phase",[vG,xG]),EG=x.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),xR=x.object({hookEvent:EG,decision:x.union([x.literal("block"),x.literal("approve"),x.undefined()]),reason:x.string().optional(),blockedTool:x.string().optional(),injectedContextBytes:x.number().int().nonnegative().optional()}),TG=x.object({transition:x.literal("started"),subagentId:x.string(),parentId:x.string(),model:x.string(),allowedTools:x.array(x.string()).readonly().optional(),systemPromptHash:x.string().optional()}),RG=x.object({transition:x.literal("succeeded"),subagentId:x.string(),durationMs:x.number().nonnegative(),turnCount:x.number().int().nonnegative(),totalCostUsd:x.number().nonnegative().optional(),outputBytes:x.number().int().nonnegative()}),CG=x.object({transition:x.literal("failed"),subagentId:x.string(),errorClass:x.string(),errorMessage:x.string(),partialOutputBytes:x.number().int().nonnegative()}),_G=x.object({transition:x.literal("cancelled"),subagentId:x.string(),source:x.enum(["cascade","explicit"])}),ER=x.discriminatedUnion("transition",[TG,RG,CG,_G]),AG=x.object({transition:x.literal("started"),jobId:x.string(),subagentId:x.string(),label:x.string(),model:x.string()}),IG=x.object({transition:x.literal("completed"),jobId:x.string(),subagentId:x.string(),durationMs:x.number().nonnegative(),outputBytes:x.number().int().nonnegative()}),PG=x.object({transition:x.literal("failed"),jobId:x.string(),subagentId:x.string(),durationMs:x.number().nonnegative(),errorClass:x.string(),errorMessage:x.string()}),MG=x.object({transition:x.literal("cancelled"),jobId:x.string(),subagentId:x.string(),source:x.enum(["explicit","cascade"])}),OG=x.object({transition:x.literal("joined"),jobId:x.string(),subagentId:x.string(),jobStatus:x.enum(["completed","failed","cancelled"])}),TR=x.discriminatedUnion("transition",[AG,IG,PG,MG,OG]),RR=x.object({kind:x.literal("monetary"),runningCostUsd:x.number().nonnegative(),maxBudgetUsd:x.number().nonnegative(),lastTurnCostUsd:x.number().nonnegative()}),$G=x.enum(["user_signal","cascade","timeout","budget","hook_block"]),CR=x.object({origin:$G,cascadedTo:x.array(x.string()).readonly(),reason:x.string().optional()}),_R=x.enum(["manual","token_threshold","turn_count"]),DG=x.object({path:x.string(),sizeBytes:x.number().int().nonnegative(),sha256:x.string().regex(/^[0-9a-f]{64}$/)}),LG=x.object({trigger:_R,preCompactionMessages:x.array(x.unknown()),summary:x.string(),keptTailCount:x.number().int().nonnegative(),keepLastNConfig:x.number().int().nonnegative(),messagesBefore:x.number().int().nonnegative(),messagesAfter:x.number().int().nonnegative(),tokensSavedEstimate:x.number().nonnegative().optional(),summarizationTokens:x.object({input:x.number().int().nonnegative(),output:x.number().int().nonnegative()}).optional()}),FG=x.object({trigger:_R,preCompactionMessagesRef:DG,summary:x.string(),keptTailCount:x.number().int().nonnegative(),keepLastNConfig:x.number().int().nonnegative(),messagesBefore:x.number().int().nonnegative(),messagesAfter:x.number().int().nonnegative(),tokensSavedEstimate:x.number().nonnegative().optional(),summarizationTokens:x.object({input:x.number().int().nonnegative(),output:x.number().int().nonnegative()}).optional()}),NG=x.enum(["model_end_turn","truncated","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),AR=x.object({reason:NG,finalTurnCount:x.number().int().nonnegative(),finalCostUsd:x.number().nonnegative(),finalTokens:x.object({input:x.number().int().nonnegative().optional(),output:x.number().int().nonnegative().optional(),cacheRead:x.number().int().nonnegative().optional(),cacheCreation:x.number().int().nonnegative().optional()}),lastStopReason:x.string().optional(),guidance:x.string().optional()}),IR=x.object({source:x.string(),assertion:x.string(),evidence:x.array(x.string()).readonly(),confidence:x.number().min(0).max(1),dissent:x.string().optional()}),BG=x.enum(["browser_open","browser_observe","browser_act","browser_screenshot","browser_extract","browser_close"]),UG=x.enum(["click","fill","press","select","hover","scroll_to","wait_for"]),jG=x.object({kind:x.enum(["semantic","element_id","selector"]),text:x.string().max(80).optional(),role:x.string().optional(),elementId:x.string().optional(),selectorHash:x.string().regex(/^[0-9a-f]{8}$/).optional()}),PR=x.object({tool:BG,action:UG.optional(),toolUseId:x.string(),target:jG.optional(),urlBefore:x.string().nullable(),urlAfter:x.string().nullable(),status:x.enum(["ok","error","ambiguous_target","blocked_by_policy"]),screenshotPath:x.string().optional(),observationSummary:x.string().max(500).optional(),error:x.object({reason:x.string(),recoverable:x.boolean()}).optional(),durationMs:x.number().nonnegative()}),HG=x.enum(["bootstrap_start","bootstrap_done","session_init_start","session_init_done","mcp_connect_start","mcp_connect_done","mcp_server_start","mcp_server_done","loop_start","loop_end","model_ttfb"]),MR=x.object({phase:HG,durationMs:x.number().nonnegative().optional(),metadata:x.record(x.string(),x.union([x.string(),x.number(),x.boolean()])).optional(),model:x.string().optional(),resolvedModel:x.string().optional()}),WG=x.object({status:x.enum(["succeeded","failed","cancelled"]),finalCostUsd:x.number().nonnegative(),finalTurnCount:x.number().int().nonnegative(),closedAt:x.string().datetime(),incomplete:x.boolean().optional(),subagentCount:x.number().int().nonnegative().optional(),subagentTokens:x.object({input:x.number().int().nonnegative().optional(),output:x.number().int().nonnegative().optional(),cacheRead:x.number().int().nonnegative().optional(),cacheCreation:x.number().int().nonnegative().optional()}).optional(),subagentCostUsd:x.number().nonnegative().optional()}),OR=x.discriminatedUnion("kind",[x.object({kind:x.literal("tool_call"),payload:kR}),x.object({kind:x.literal("hook_decision"),payload:xR}),x.object({kind:x.literal("subagent_lifecycle"),payload:ER}),x.object({kind:x.literal("background_agent"),payload:TR}),x.object({kind:x.literal("budget"),payload:RR}),x.object({kind:x.literal("abort"),payload:CR}),x.object({kind:x.literal("compaction"),payload:LG}),x.object({kind:x.literal("closure"),payload:AR}),x.object({kind:x.literal("claim"),payload:IR}),x.object({kind:x.literal("browser_event"),payload:PR}),x.object({kind:x.literal("session_phase"),payload:MR})]),$R=x.discriminatedUnion("kind",[x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("tool_call"),payload:kR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("hook_decision"),payload:xR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("subagent_lifecycle"),payload:ER}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("background_agent"),payload:TR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("budget"),payload:RR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("abort"),payload:CR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("compaction"),payload:FG}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("closure"),payload:AR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("claim"),payload:IR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("browser_event"),payload:PR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("session_phase"),payload:MR}),x.object({ts:x.string().datetime(),seq:x.number().int().nonnegative(),kind:x.literal("session_sealed"),payload:WG})]);var Lu=new Set,LR=!1;function VG(){LR||(LR=!0,process.on("exit",()=>{for(let e of Lu)e.sealOnProcessExit()}))}var Fu=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(t){this.traceDir=t.traceDir,this.tracePath=DR(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(t){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return OR.parse(t),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(t);await this.appendLine(n)})}async seal(t){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:t};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(t){let n=this.writeQueue.then(t,t);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await zG(this.traceDir,{recursive:!0}),this.fh=await qG(this.tracePath,"a"),Lu.add(this),VG())}async closeHandle(){if(Lu.delete(this),!this.fh)return;let t=this.fh;this.fh=null,await t.close()}sealOnProcessExit(){if(this.sealed||this.seq===0)return;this.sealed=!0,Lu.delete(this);try{let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:{status:"failed",finalCostUsd:0,finalTurnCount:0,closedAt:new Date().toISOString(),incomplete:!0}};GG(this.tracePath,`${JSON.stringify(n)}
1695
1695
  `)}catch{}let t=this.fh;this.fh=null,t&&t.close().catch(()=>{})}async appendLine(t){if(!this.fh)throw new Error("NdjsonTraceWriter: file handle missing");await this.fh.appendFile(`${JSON.stringify(t)}
1696
1696
  `)}async materializePersistedEvent(t){let n=new Date().toISOString(),r=this.seq++;if(t.kind==="compaction"){let o=await this.persistCompactionSidecar(t.payload,r,n);return{ts:n,seq:r,kind:"compaction",payload:o}}return{ts:n,seq:r,kind:t.kind,payload:t.payload}}async persistCompactionSidecar(t,n,r){let o=r.replace(/[:.]/g,"-"),s=DR(this.traceDir,`${String(n).padStart(6,"0")}-${o}-pre-compaction.json`),i=JSON.stringify(t.preCompactionMessages),a=Buffer.byteLength(i,"utf8"),l=KG("sha256").update(i).digest("hex");await JG(s,i,{encoding:"utf8",flag:"w"});let c={path:s,sizeBytes:a,sha256:l};return{trigger:t.trigger,preCompactionMessagesRef:c,summary:t.summary,keptTailCount:t.keptTailCount,keepLastNConfig:t.keepLastNConfig,messagesBefore:t.messagesBefore,messagesAfter:t.messagesAfter,...t.tokensSavedEstimate!==void 0?{tokensSavedEstimate:t.tokensSavedEstimate}:{},...t.summarizationTokens!==void 0?{summarizationTokens:t.summarizationTokens}:{}}}};function Js(e={}){if(k.AFK_TRACE_DISABLED==="1")return null;let t=e.sessionLabel??YG(),n=Yo(t),r=new Fu({traceDir:n});return{writer:r,tracePath:r.getTracePath(),sessionLabel:t}}qi();K();import{readFileSync as XG,writeFileSync as BR,existsSync as Ea,mkdirSync as UR,readdirSync as ZG,statSync as QG,realpathSync as FR}from"fs";import{join as jR,basename as HR,resolve as NR,sep as e2}from"path";import{randomUUID as t2}from"node:crypto";function Ys(){return Kb(),Cn()}function n2(e){return jR(Ys(),`${e}.json`)}function Nu(e,{write:t=!1}={}){let n=e.includes("/")?e:n2(e),r,o;if(!t&&Ea(n)?(r=FR(n),o=FR(Ys())):(r=NR(n),o=NR(Ys())),!r.startsWith(o+e2)&&r!==o)throw new Error(`Session path escapes sessions directory: ${e}`);return r}function hn(e,t){let n=Ys();Ea(n)||UR(n,{recursive:!0});let r=t??e.sessionId??`session-${Date.now()}`,o={sessionId:e.sessionId,...e.name?{name:e.name}:{},...e.source?{source:e.source}:{},...e.telegramChatId!==void 0?{telegramChatId:e.telegramChatId}:{},model:e.model,startedAt:e.sessionStartTime,savedAt:Date.now(),totalTurns:e.totalTurns,totalCostUsd:e.totalCostUsd,totalTokens:e.totalTokens,totalDurationMs:e.totalDurationMs,turns:e.turns},s=Nu(r,{write:!0});return BR(s,JSON.stringify(o,null,2)),s}function WR(e,t={}){let n=Ys();Ea(n)||UR(n,{recursive:!0});let r=t.newId??t2(),o={sessionId:r,model:e.model,startedAt:e.sessionStartTime,savedAt:Date.now(),totalTurns:e.totalTurns,totalCostUsd:e.totalCostUsd,totalTokens:e.totalTokens,totalDurationMs:e.totalDurationMs,turns:[...e.turns],...e.sessionId?{forkedFrom:e.sessionId}:{},forkedAt:Date.now()},s=Nu(r,{write:!0});return BR(s,JSON.stringify(o,null,2)),{id:r,path:s}}function Vs(e){let t;try{t=Nu(e)}catch{return}if(Ea(t))try{let n=XG(t,"utf-8");return JSON.parse(n)}catch{return}}function Xs(e){let t;try{t=Nu(e)}catch{return}let n=Vs(t);if(n)return{path:t,id:HR(t,".json"),data:n};let r=Ta();for(let s of r){if(s.id!==e&&s.sessionId!==e&&s.name!==e)continue;let i=Vs(s.path);if(i)return{path:s.path,id:s.id,data:i}}if(e.length>=3){let s=r.filter(i=>i.name!==void 0&&i.name.startsWith(e));if(s.length===1){let i=s[0];if(i){let a=Vs(i.path);if(a)return{path:i.path,id:i.id,data:a}}}}}function Ta(){let e=Ys();if(!Ea(e))return[];let t=[];for(let n of ZG(e)){if(!n.endsWith(".json"))continue;let r=jR(e,n);try{if(!QG(r).isFile())continue;let s=Vs(r);if(!s||typeof s.savedAt!="number"||typeof s.model!="string")continue;t.push({path:r,id:HR(n,".json"),sessionId:s.sessionId,name:s.name,source:s.source,model:s.model,startedAt:s.startedAt,savedAt:s.savedAt,totalTurns:s.totalTurns,totalCostUsd:s.totalCostUsd})}catch{}}return t.sort((n,r)=>r.savedAt-n.savedAt),t}function Zs(e){if(e.resume&&e.continue)throw new Error("Use either --resume <id> or --continue, not both.");if(e.resume){let t=Xs(e.resume);return t?{id:t.id,resumeId:t.data.sessionId??t.id,stored:t.data}:{id:e.resume,resumeId:e.resume}}if(e.continue){let t=Ta()[0];if(!t)throw new Error("No saved sessions found for --continue. Run a session first or use /save.");let n=Vs(t.path);if(!n)throw new Error(`Could not load latest saved session: ${t.id}`);return{id:t.id,resumeId:n.sessionId??t.id,stored:n}}}function Qs(e){return e?{resume:e.resumeId,sessionId:e.resumeId,...e.stored?{resumeHistory:e.stored.turns.map(t=>({user:t.user,assistant:t.assistant}))}:{}}:{}}function ei(e){let t=e.toLowerCase().replace(/[`*_~]/g," ").replace(/[^\w\s-]/g," ").replace(/[\s_]+/g," ").trim();return t?t.split(" ").filter(Boolean).slice(0,6).join("-").slice(0,48).replace(/-+$/g,""):""}function Bu(e){return{totalTurns:0,totalCostUsd:0,totalTokens:0,totalDurationMs:0,sessionStartTime:Date.now(),turnCosts:[],turnTokens:[],turns:[],model:e,planMode:!1}}function KR(e){e.totalTurns=0,e.totalCostUsd=0,e.totalTokens=0,e.totalDurationMs=0,e.sessionStartTime=Date.now(),e.turnCosts.length=0,e.turnTokens.length=0,e.turns.length=0,delete e.sessionId,delete e.name}function po(e,t,n,r,o){let s=r?.totalCostUsd??0,i=r?.durationMs??0,a=Number(r?.usage?.input_tokens??0),l=Number(r?.usage?.output_tokens??0),c=a,u=l,d=Number(r?.usage?.cache_read_input_tokens??0)+Number(r?.usage?.cache_creation_input_tokens??0),m=r?.usage?.iterations;if(Array.isArray(m)&&m.length>0){let y=m[m.length-1];if(y&&typeof y=="object"){let v=y;c=Number(v.input_tokens??0),u=Number(v.output_tokens??0),d=Number(v.cache_read_input_tokens??0)+Number(v.cache_creation_input_tokens??0)}}e.totalTurns+=1,e.totalCostUsd+=s,e.totalDurationMs+=i,e.totalTokens+=a+l,e.turnCosts.push(s);let f=Number(r?.usage?.context_window_tokens??NaN),g=Array.isArray(m)&&m.length>0,h=Number.isFinite(f)?f:g?c+u+d:void 0;if(e.turnTokens.push({input:c,output:u,cache:d,...h!==void 0?{footprint:h}:{}}),r?.sessionId&&!e.sessionId&&(e.sessionId=String(r.sessionId)),!e.name){let y=ei(t);y&&(e.name=y)}let b={user:t,assistant:n,timestamp:Date.now(),costUsd:s,durationMs:i,inputTokens:a,outputTokens:l,...o&&o.length>0?{toolEvents:o}:{}};return e.turns.push(b),b}import{execFile as r2,spawn as o2}from"node:child_process";import{promisify as s2}from"node:util";var i2=s2(r2),GR=2e4,Jg=class extends Error{kind;exitCode;stderr;constructor(t,n,r,o){super(t),this.name="GhError",this.kind=n,this.exitCode=r,this.stderr=o}},Uu=null,Ra=null;function a2(e,t,n){return n===!0?"timeout":t==="ENOENT"?"not-found":/already exists/i.test(e)?"already-exists":/authentication|please log in|HTTP 40[13]|bad credentials|token|scope/i.test(e)?"unauthed":/ETIMEDOUT|ECONNRESET|ECONNREFUSED/i.test(e+(t??""))?"network":"unknown"}function zR(e,t){return i2(e,t,{timeout:GR,killSignal:"SIGTERM"}).then(n=>({stdout:n.stdout,stderr:n.stderr}))}async function qR(e={}){let t=(e._now??(()=>Date.now()))(),n=e.ttlMs??6e4,r=e.execFn??zR,o=e.log??(()=>{});return Uu&&Uu.expiresAt>t?(o("[gh] checkGhReady cache hit"),Uu.result):(o("[gh] checkGhReady cache miss \u2014 probing"),Ra||(Ra=(async()=>{try{await r("gh",["--version"])}catch(a){let l=a;return l.killed?{ok:!1,hint:"`gh` timed out \u2014 check connectivity"}:l.code==="ENOENT"?{ok:!1,hint:"`gh` CLI not found \u2014 install with: brew install gh"}:{ok:!1,hint:"`gh --version` failed unexpectedly \u2014 check gh installation"}}try{await r("gh",["auth","status"])}catch(a){let l=a;return l.killed||/ETIMEDOUT|ECONNRESET|ENOTFOUND/i.test(String(l.code??""))?{ok:!1,hint:"check network \u2014 cannot reach GitHub"}:{ok:!1,hint:"`gh` is not authenticated \u2014 run: gh auth login"}}let i={ok:!0};return n>0&&(Uu={result:i,expiresAt:t+n}),i})().finally(()=>{Ra=null}),Ra))}function l2(e,t,n){return new Promise((r,o)=>{let s=o2(e,t,{stdio:["pipe","pipe","pipe"]}),i="",a="",l=!1,c=setTimeout(()=>{l=!0,s.kill("SIGTERM")},GR);s.stdout?.on("data",u=>{i+=u.toString()}),s.stderr?.on("data",u=>{a+=u.toString()}),s.on("error",u=>{clearTimeout(c),o(Object.assign(new Error(u.message),{...u.code!==void 0?{code:u.code}:{},stderr:a}))}),s.on("close",u=>{if(clearTimeout(c),l){o(Object.assign(new Error(`${e} timed out`),{killed:!0,stderr:a}));return}if(u===0){r({stdout:i,stderr:a});return}o(Object.assign(new Error(`${e} exited ${u??"null"}`),{exitCode:u??1,stderr:a}))}),s.stdin?.on("error",()=>{}),s.stdin?.end(n)})}async function JR(e,t){let n=t??l2,r=["pr","comment"],o=e.pr.trim();o&&r.push(o),r.push("--body-file","-");try{let{stdout:s}=await n("gh",r,e.body);return s.trim()}catch(s){let i=s,a=i.stderr??"",l=a2(a,i.code,i.killed);throw new Jg(`gh pr comment failed (${l}): ${a.trim()}`,l,i.exitCode??1,a)}}async function VR(e){let t=e??zR;try{let{stdout:n}=await t("gh",["pr","view","--json","number","--jq",".number"]),r=n.trim();return/^\d+$/.test(r)?r:null}catch{return null}}vs();var c2=4096,u2="<!-- agent-afk-review -->",d2=new Set(["github","telegram"]),YR=/--post(?:=|\s+)([^\s]+)/g;function XR(e){if(!/--post\b/.test(e))return{targets:[],cleanedArgs:e,unknown:[]};let t=[],n=[];for(let o of e.matchAll(YR))ZR(o[1]??"",t,n);let r=e.replace(YR," ").replace(/(^|\s)--post(?=\s|$)/g," ").replace(/\s+/g," ").trim();return{targets:t,cleanedArgs:r,unknown:n}}function ZR(e,t,n){for(let r of e.split(",").map(o=>o.trim()).filter(Boolean))if(d2.has(r)){let o=r;t.includes(o)||t.push(o)}else n.push(r)}function QR(e){let t=[],n=[];return ZR(e,t,n),{targets:t,unknown:n}}function p2(e,t){if(t<=0||e.length<=t)return[e];let n=[],r="";for(let o of e.split(`
1697
1697
  `)){if(o.length>t){r&&(n.push(r),r="");for(let s=0;s<o.length;s+=t)n.push(o.slice(s,s+t));continue}r.length+o.length+1>t?(r&&n.push(r),r=o):r=r?`${r}
@@ -1964,7 +1964,7 @@ _ended: ${new Date().toISOString()}_
1964
1964
  ${T}${v}
1965
1965
  ${w}
1966
1966
  ${T}`})}return{fileBlocks:a,warnings:l}}async function nM(e,t,n,r,o="summary",s,i){let a=B_(e.text,e.attachments);r.onUserMessage&&await Promise.resolve(r.onUserMessage(a)).catch(()=>{}),r.setInFlight(!0);let l="",c=0,u=!1,d=!1,m=!1,f=!1,g,h=!1,b=0,y=15e3,v=[],w=new Map,T=e.text.startsWith("/")?e.text.split(/[\s:]/)[0]?.slice(1):void 0,E=()=>{let M=r.subagentControl;M?.hasPromotableForeground()&&M.promoteActiveForeground().then($=>{for(let L of $)(s??{fn:console.log}).fn(p.dim(` \u2192 subagent backgrounded as ${L.jobId}: ${L.label}`))}).catch(()=>{})},R=r.getCompositor?r.getCompositor():null,C=()=>new mi({out:fi(s),thinkingMode:o,...T?{activeSkillName:T}:{},onCancel:()=>{t.interrupt().catch(M=>{Ze()&&console.error(" "+p.error("session.interrupt() failed:"),M)})},...r.subagentControl?{onBackground:E}:{},...i?.history?{history:i.history}:{},...i?.autocompleteState?{autocompleteState:i.autocompleteState}:{},...i?.promptText!==void 0?{promptText:i.promptText}:{},...r.scrollRegion?{scrollRegion:r.scrollRegion}:{},...R?{compositor:R}:{},...r.onStageChange?{onStageChange:r.onStageChange}:{}}),S=C(),P=async()=>{if(!m){m=!0;try{await S.dispose()}catch{}}},A=async()=>{await S.arm();let M=S.getCompositor();if(s&&M){let $=M;s.fn=L=>$.commitAbove(L)}r.setActiveCompositor?.(M),r.setInterruptNotifier?.($=>S.setInterrupting($)),r.rearmStatus?.()};try{R?R.commitAbove(""):console.log(),r.setSoftStopHandler&&r.setSoftStopHandler(()=>{h=!0,t.interrupt().catch(D=>{Ze()&&console.error(" "+p.error("soft-stop session.interrupt() failed:"),D)})}),await A(),r.setBackgroundHandler&&r.subagentControl&&r.setBackgroundHandler(E);let{fileBlocks:M,warnings:$}=tM(e.text,{rootDir:process.cwd()});for(let D of $)(s??{fn:console.log}).fn(p.dim(` @-file: ${D}`));let L=M.length>0||e.attachments.length>0?QP(e.text,e.attachments,void 0,M):e.text,B=t.sendMessageStream(L);if(await us((D,F)=>{S.process(D,F)},async()=>{for await(let D of B){if(h)break;if(D.type==="chunk"&&D.chunk.type==="content"?(l+=D.chunk.content,u=!0):D.type==="message"&&!u&&(l=D.message.content),D.type==="stream_retry"&&(l=l.slice(0,c)),D.type==="chunk"&&D.chunk.type==="tool_use_detail"){let F=D.chunk,j={toolName:F.toolName,toolUseId:F.toolUseId,input:F.toolInput,...F.toolInputRaw!==void 0&&{inputRaw:F.toolInputRaw}};w.set(F.toolUseId,j),v.push(j)}else if(D.type==="chunk"&&D.chunk.type==="tool_result"){let F=D.chunk;c=l.length;let j=w.get(F.toolUseId);if(j&&(j.result=F.content,j.isError=F.isError,w.delete(F.toolUseId)),r.onContextProgress){let N=Date.now();if(N-b>=y){b=N;try{let O=r.onContextProgress();O instanceof Promise&&await O}catch(O){Ze()&&console.error(" "+p.error("onContextProgress (status refresh) failed:"),O)}}}}if(D.type==="paused"){await P(),(s??{fn:console.log}).fn(fw({reason:D.reason,...D.resetsAt!==void 0?{resetsAt:D.resetsAt}:{},...D.accountId!==void 0?{accountId:D.accountId}:{},...D.autoResume!==void 0?{autoResume:D.autoResume}:{}}));continue}if(D.type==="resumed"){let F=D.hotSwapped&&D.accountId?`\u25B6 Resumed on ${D.accountId}`:"\u25B6 Resumed";l="",c=0,u=!1,v.length=0,w.clear(),f=!1,g=void 0,d=!1,S=C(),m=!1,await A(),(s??{fn:console.log}).fn(p.success(F));continue}if(D.type==="error"){await P(),ts(Xo(D.error)),d=!0;continue}S.process(D),D.type==="done"&&(f=!0,g=D.metadata)}}),await P(),h){let D=s?s.fn:console.log;D(p.warning("\u23F8 Stopped \u2014 work so far kept.")+p.dim(" Send a message to continue.")),D("")}if(f&&!h){po(n,a,l,g,v),r.onTurnComplete&&await r.onTurnComplete(a,l).catch(()=>{}),Ku(process.stdout);let D=j=>{s?s.fn(j):console.log(j)},F=XP(l);if(F&&(D(ZP(F)),D(""),r.onTerminalState))try{r.onTerminalState(F)}catch{}if(r5(g,n,D),r.onAfterTurn){let j=r.onAfterTurn();j instanceof Promise&&await j.catch(()=>{})}}}catch(M){await P(),d||ts(Xo(M))}finally{await P(),s&&(s.fn=s.idleFn),r.setActiveCompositor?.(null),r.setInterruptNotifier?.(null),r.setBackgroundHandler?.(null),r.setSoftStopHandler?.(null),r.setInFlight(!1),r.rearmStatus?.()}}function r5(e,t,n=console.log){if(!e)return;let r=[];e.durationMs&&r.push(ge(e.durationMs)),e.totalCostUsd!==void 0&&r.push(Ye(e.totalCostUsd));let o=Number(e.usage?.input_tokens??0),s=Number(e.usage?.output_tokens??0);o+s>0&&r.push(ae(o+s)+" tok"),r.length>0&&n(p.dim(" \u25E6 "+r.join(" \xB7 ")));let i=Qg(t),a=vt(t.model);if(i>=1){let l=Math.round((i-1)*a),c=Math.round(a/1e3);console.log(p.error(` context OVER ${c}k tok by ~${ae(l)} tok \u2014 model output may be silently truncated`))}else if(i>.5){let l=i>.8?p.error:p.warning;n(l(` context ${Math.round(i*100)}% used of ${ae(a)}`))}n("")}async function o5(e,t){if(e.firstTurnHook&&e.stats.totalTurns===0){let n=e.firstTurnHook;e.firstTurnHook=void 0;try{await n(t)}catch(r){e.completionWriter.fn(p.warning("\u26A0 ")+"first-turn hook failed: "+(r instanceof Error?r.message:String(r)))}}}async function rM(e,t,n,r,o,s,i,a){let{contextPane:l,loopStageBar:c,verdictLedger:u,shellPassthrough:d}=i,m=null,f=[];e.session.current.waitForInitialization().then(async y=>{Ze()&&(m=Xu(y)),await jd(e.session.current),Ze()&&(f=UI())}).catch(()=>{});let g,h=!1,b=!1;for(;;){if(m&&(e.replRenderer.writeLine(m),e.replRenderer.writeLine(""),m=null),f.length>0){for(let S of f)e.replRenderer.writeLine(S);e.replRenderer.writeLine(""),f=[]}let y=d.drainNotifications();for(let{job:S,result:P}of y){let A=P.errorReason===void 0?"\u2713":"\u2717",M=P.errorReason==="abort"?"killed":P.errorReason==="timeout"?"timed out":P.errorReason==="signal-killed"?"killed by signal":`exit ${P.exitCode??0}`,$=Math.max(0,Math.round(P.durationMs/100)/10);e.replRenderer.writeLine(p.dim(` ${A} [${S.id}] ${M} \xB7 ${$}s \xB7 `)+S.command)}let v=l.renderIfChanged(e.stats.sessionId);if(v.length>0){for(let S of v)e.replRenderer.writeLine(S);e.replRenderer.writeLine("")}let w,T;if(g!==void 0){let S=g;g=void 0;let P=Si(e.stats.model,e.stats.planMode),A=bo({buffer:S.text,promptText:P,isTTY:!!process.stdout.isTTY,attachmentSummary:ii([...S.attachments])});e.replRenderer.writeLine(A),w=S.text.trim(),T=S.attachments}else{let S=await o.readLine({promptFn:()=>Si(e.stats.model,e.stats.planMode),onSigint:r,onShiftTab:()=>{Zn(e.slashCtx).catch(()=>{}),e.statusLine.rearm()}});w=S.text.trim(),T=S.attachments}if(!w&&T.length===0)continue;if(w.startsWith("!")){let S=/^(0|false|off|no)$/i.test(k.AFK_SHELL_PASSTHROUGH??"");if(e.options.shellPassthrough!==!1&&!S&&(h||(h=!0,e.replRenderer.writeLine(p.dim(" \u2139 ! prefix shells out. Pass --no-shell-passthrough (or set AFK_SHELL_PASSTHROUGH=0) to send ! text to the model instead."))),await d.dispatch(w))){e.statusLine.rearm();continue}}let E=!1;if(w.startsWith("/")){let S=await fC(w,e.slashCtx,T);if(S.handled){if(S.result==="exit"){e.rl.close();return}if((w==="/clear"||w.startsWith("/clear "))&&(await t.rotateOnClear(),e.replRenderer.writeLine(p.dim(` transcript: ${t.path()}`)),u.reset()),S.result!==null&&typeof S.result=="object"&&"kind"in S.result&&S.result.kind==="submit"){g={text:S.result.message,attachments:T??[]},e.statusLine.rearm();continue}e.statusLine.rearm();continue}E=!0}a.push(w),await o5(e,w);let R=w;if(E){let S=Zg(w);if(S){let P=S.name.replace(/^\//,"").split(":").pop()??"";if(P&&oy(P)){let A={skillName:P,rawArgs:S.args,source:"plugin",capabilities:{compose:!0,subagents:!0}},M=e.session.current.sessionId,$=Co(M),L=Date.now();V(`[afk trace] preflight.start commandName=${P}`);let B=!1,U=await Ro(A,{cwd:e.stats.cwd??process.cwd(),artifactDir:$},D=>{Ze()&&e.replRenderer.writeLine(p.warning(`\u26A0 preflight(${P}) failed: `)+(D instanceof Error?D.message:String(D)))});B=U!==null,V(`[afk trace] preflight.end commandName=${P} durationMs=${Date.now()-L} success=${B}`),R=iy(U?.manifestBlock,w)}}}let C=d.drainInjections();C.length>0&&(R=C+R),await nM({text:R,attachments:T},e.session.current,e.stats,{setInFlight(S){n.turnInFlight=S},...e.subagentControl?{subagentControl:e.subagentControl}:{},async onUserMessage(S){await t.appendUser(S)},async onTurnComplete(S,P){if(await t.appendTurn(S,P),e.stats.sessionId)try{hn(e.stats)}catch(A){b||(b=!0,e.replRenderer.writeLine(p.warning("\u26A0 ")+"session autosave failed \u2014 this conversation may not be resumable: "+(A instanceof Error?A.message:String(A))))}},async onAfterTurn(){await e.contextSampler.onTurn(e.stats.totalTurns),e.statusLine.rearm(),c?.repaint("observing")},rearmStatus:()=>e.statusLine.rearm(),onTerminalState:S=>u?.push(S),setActiveCompositor:S=>{n.activeCompositor=S},setInterruptNotifier:S=>{n.notifyInterrupting=S},scrollRegion:e.statusLine,getCompositor:()=>o.getCompositor(),setBackgroundHandler:S=>o.setBackgroundHandler(S),setSoftStopHandler:s,async onContextProgress(){await e.contextSampler.refresh(),e.statusLine.repaint(Xn(e.stats,e.contextSampler))},...c?{onStageChange:S=>c.repaint(S)}:{}},e.options.thinkingUi,e.completionWriter,o.toRunTurnRefs(Si(e.stats.model,e.stats.planMode)))}}function s5(e,t){if(e!==void 0){let n=e.toLowerCase();return!(n==="0"||n==="false"||n==="off"||n==="no")}return typeof t=="boolean"?t:!0}async function oM(e,t,n,r){let o=await $P(),s=new up({rl:e.rl,history:o,statusLine:e.statusLine}),i=s5(k.AFK_SUGGEST_GHOST,e.suggestGhostConfig),a;try{let{installSoftStop:l}=await jP(e,s,n,t,r,i,{getLoopStageBar:()=>a?.loopStageBar});a=YP(e,n),await rM(e,t,n,r,s,l,a,o)}finally{n.tryAbortShellForeground=null,a?.shellPassthrough.drainOnExit(),a?.loopStageBar.stop(),a?.bgStatusBar.stop(),a?.verdictLedger.stop(),a?.contextPane.dispose();let l=c=>console.log(c);e.completionWriter.fn=l,e.completionWriter.idleFn=l,await s.dispose(),e.inputSurfaceRef&&(e.inputSurfaceRef.current=null)}}qi();import{execFile as i5}from"node:child_process";import{dirname as a5,isAbsolute as l5,resolve as c5}from"node:path";import{promisify as u5}from"node:util";var sM=u5(i5),d5=3e3,p5=new Set(["empty","orphaned-dir","orphaned-registration","dead-owner"]);async function m5(){let t=(await sM("git",["rev-parse","--git-common-dir"])).stdout.trim();if(!t)throw new Error("Not in a git repository.");let n=l5(t)?t:c5(process.cwd(),t);return a5(n)}async function iM(e){if(e?.disabled)return{ran:!1,removedCount:0,skippedReason:"disabled"};let t;try{t=await m5()}catch{return{ran:!1,removedCount:0,skippedReason:"not-in-repo"}}let n,r=new Promise(o=>{n=setTimeout(()=>o("timeout"),d5)});try{let o=Sn({execFile:sM,repoRoot:t,dryRun:!1,scope:"interactive",bypassSoftLaunch:!0}),s=await Promise.race([o,r]);if(s==="timeout")return{ran:!1,removedCount:0,skippedReason:"timeout"};let i=s;return i.warnings.some(c=>c.toLowerCase().includes("contested"))?{ran:!1,removedCount:0,skippedReason:"lock-contested"}:{ran:!0,removedCount:i.candidates.filter(c=>p5.has(c.verdict)&&i.removed.includes(c.path)).length}}catch{return{ran:!1,removedCount:0,skippedReason:"error"}}finally{n&&clearTimeout(n)}}Kl();qi();import{promises as f5}from"node:fs";import{dirname as g5,join as cM}from"node:path";import{randomBytes as h5}from"node:crypto";var y5=["Generate a 2-4 word kebab-case slug describing this work request.","Rules:","- ASCII lowercase letters and digits only, separated by single hyphens","- 2 to 4 hyphen-separated words","- Maximum 30 characters total","- No prefix, no quotes, no punctuation other than hyphens","- Output ONLY the slug \u2014 no explanation, no preamble","Examples: fix-cleanup-race, add-telegram-allowlist, refactor-prompt-loader, debug-flaky-test"].join(`
1967
- `),aM=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,Oy=30,b5=1024,w5=8e3,S5="haiku";async function v5(e,t){let n=e.trim();if(n.length===0)return t.onSkip?.("empty-message"),null;if(n.startsWith("/"))return t.onSkip?.("slash-command"),null;let r=T5(n,b5),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??w5),i=t.signal?R5([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await ls({token:t.token,model:t.model??S5,system:y5,user:r,maxTokens:32,signal:i})}catch(d){let m=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",m.slice(0,200)),null}finally{clearTimeout(s)}let l=k5(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=g5(t.worktreePath);return await x5(l,c)}function k5(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if(aM.test(t)&&t.length<=Oy)return t;let n=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(n.length===0)return null;let r=n.split("-").filter(s=>s.length>0).slice(0,4);if(r.length<2)return null;let o=r[0];for(let s=1;s<r.length;s++){let i=`${o}-${r[s]}`;if(i.length>Oy)break;o=i}return aM.test(o)?o:null}async function x5(e,t){if(!await E5(cM(t,e)))return e;let n=h5(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,Oy-5)}-${n}`}async function E5(e){try{return await f5.access(e),!0}catch{return!1}}function T5(e,t){let n=Buffer.from(e,"utf8");if(n.length<=t)return e;let r=t;for(;r>0&&n[r]!==void 0&&(n[r]&192)===128;)r--;return n.slice(0,r).toString("utf8")}function R5(e){let t=AbortSignal.any;if(typeof t=="function")return t.call(AbortSignal,e);let n=new AbortController;for(let r of e){if(r.aborted)return n.abort(r.reason),n.signal;r.addEventListener("abort",()=>n.abort(r.reason),{once:!0})}return n.signal}async function uM(e){let t,n,r=cM(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await v5(e.message,{token:e.token,...e.model!==void 0?{model:e.model}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},worktreePath:r,...e.signal!==void 0?{signal:e.signal}:{},...e.slugGenerator!==void 0?{slugGenerator:e.slugGenerator}:{},onSkip:(a,l)=>{t=a,n=l}}),s=t??"unknown",i=n;if(o!==null){let l=`${bc(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return lM(e.session,c.path),{status:"created",path:c.path,branch:c.branch,slug:o}}catch(c){s="create-failed",i=(c instanceof Error?c.message:String(c)).slice(0,200)}}try{let a=await e.deferred.create(!0);return lM(e.session,a.path),{status:"created-fallback",path:a.path,branch:a.branch,reason:s,...i!==void 0?{detail:i}:{}}}catch(a){return{status:"failed",reason:a instanceof Error?a.message:String(a)}}}function lM(e,t){e&&e.setCwd(t),C5(t)}function C5(e){try{process.chdir(e)}catch{}}je();Hn();K();import{spawn as pM}from"child_process";import{existsSync as mM,mkdirSync as M5,readFileSync as fM,unlinkSync as dM,writeFileSync as O5}from"fs";import{get as $5}from"https";import{join as gM}from"path";import{readFileSync as _5}from"fs";import{dirname as A5,join as I5}from"path";import{fileURLToPath as P5}from"url";function or(){try{return"4.8.2"}catch{}try{let e=A5(P5(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(_5(I5(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}G();var D5=64*1024,L5=1440*60*1e3,F5=3600*1e3,N5="update-check.json",B5="pending-update.json";function hM(){return gM(Tl(),N5)}function il(){return gM(Tl(),B5)}function yM(){let e=Tl();mM(e)||M5(e,{recursive:!0})}function U5(e,t){let n=a=>a.split(/[-+]/,1)[0]??a,r=a=>a.includes("-"),o=n(e).split(".").map(Number),s=n(t).split(".").map(Number),i=Math.max(o.length,s.length);for(let a=0;a<i;a++){let l=o[a]??0,c=s[a]??0;if(c>l)return!0;if(c<l)return!1}return r(e)&&!r(t)}function j5(){try{let e=fM(hM(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function H5(){try{yM();let e=`
1967
+ `),aM=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,Oy=30,b5=1024,w5=8e3,S5="haiku";async function v5(e,t){let n=e.trim();if(n.length===0)return t.onSkip?.("empty-message"),null;if(n.startsWith("/"))return t.onSkip?.("slash-command"),null;let r=T5(n,b5),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??w5),i=t.signal?R5([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await ls({token:t.token,model:t.model??S5,system:y5,user:r,maxTokens:32,signal:i})}catch(d){let m=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",m.slice(0,200)),null}finally{clearTimeout(s)}let l=k5(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=g5(t.worktreePath);return await x5(l,c)}function k5(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if(aM.test(t)&&t.length<=Oy)return t;let n=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(n.length===0)return null;let r=n.split("-").filter(s=>s.length>0).slice(0,4);if(r.length<2)return null;let o=r[0];for(let s=1;s<r.length;s++){let i=`${o}-${r[s]}`;if(i.length>Oy)break;o=i}return aM.test(o)?o:null}async function x5(e,t){if(!await E5(cM(t,e)))return e;let n=h5(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,Oy-5)}-${n}`}async function E5(e){try{return await f5.access(e),!0}catch{return!1}}function T5(e,t){let n=Buffer.from(e,"utf8");if(n.length<=t)return e;let r=t;for(;r>0&&n[r]!==void 0&&(n[r]&192)===128;)r--;return n.slice(0,r).toString("utf8")}function R5(e){let t=AbortSignal.any;if(typeof t=="function")return t.call(AbortSignal,e);let n=new AbortController;for(let r of e){if(r.aborted)return n.abort(r.reason),n.signal;r.addEventListener("abort",()=>n.abort(r.reason),{once:!0})}return n.signal}async function uM(e){let t,n,r=cM(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await v5(e.message,{token:e.token,...e.model!==void 0?{model:e.model}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},worktreePath:r,...e.signal!==void 0?{signal:e.signal}:{},...e.slugGenerator!==void 0?{slugGenerator:e.slugGenerator}:{},onSkip:(a,l)=>{t=a,n=l}}),s=t??"unknown",i=n;if(o!==null){let l=`${bc(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return lM(e.session,c.path),{status:"created",path:c.path,branch:c.branch,slug:o}}catch(c){s="create-failed",i=(c instanceof Error?c.message:String(c)).slice(0,200)}}try{let a=await e.deferred.create(!0);return lM(e.session,a.path),{status:"created-fallback",path:a.path,branch:a.branch,reason:s,...i!==void 0?{detail:i}:{}}}catch(a){return{status:"failed",reason:a instanceof Error?a.message:String(a)}}}function lM(e,t){e&&e.setCwd(t),C5(t)}function C5(e){try{process.chdir(e)}catch{}}je();Hn();K();import{spawn as pM}from"child_process";import{existsSync as mM,mkdirSync as M5,readFileSync as fM,unlinkSync as dM,writeFileSync as O5}from"fs";import{get as $5}from"https";import{join as gM}from"path";import{readFileSync as _5}from"fs";import{dirname as A5,join as I5}from"path";import{fileURLToPath as P5}from"url";function or(){try{return"4.8.3"}catch{}try{let e=A5(P5(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(_5(I5(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}G();var D5=64*1024,L5=1440*60*1e3,F5=3600*1e3,N5="update-check.json",B5="pending-update.json";function hM(){return gM(Tl(),N5)}function il(){return gM(Tl(),B5)}function yM(){let e=Tl();mM(e)||M5(e,{recursive:!0})}function U5(e,t){let n=a=>a.split(/[-+]/,1)[0]??a,r=a=>a.includes("-"),o=n(e).split(".").map(Number),s=n(t).split(".").map(Number),i=Math.max(o.length,s.length);for(let a=0;a<i;a++){let l=o[a]??0,c=s[a]??0;if(c>l)return!0;if(c<l)return!1}return r(e)&&!r(t)}function j5(){try{let e=fM(hM(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function H5(){try{yM();let e=`
1968
1968
  const https = require('https');
1969
1969
  const fs = require('fs');
1970
1970
  const url = 'https://registry.npmjs.org/agent-afk/latest';
@@ -2164,7 +2164,7 @@ or "latest" (the default) \u2014 the most recently written trace.`).option("--al
2164
2164
  `)){let o=r.split(" "),s=o.length>=3?o:r.trim().split(/\s+/);if(s.length<3||s[2]?.trim()!==t)continue;let i=s[0]?.trim()??"-",a=s[1]?.trim()??"0",l={};if(i!=="-"&&i!==""){let u=Number.parseInt(i,10);Number.isFinite(u)&&(l.pid=u)}let c=Number.parseInt(a,10);return Number.isFinite(c)&&(l.lastExitStatus=c),l}}function cb(e){let t=Nr(e),n={name:e,label:ot(e),installed:jX(t),plistPath:t,logFile:_i(e)};if(!n.installed)return n;try{let r=UX("launchctl",["list"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:Fo}),o=HX(r,n.label);o&&(o.pid!==void 0&&(n.pid=o.pid),o.lastExitStatus!==void 0&&(n.lastExitStatus=o.lastExitStatus))}catch{}return n}import{execFileSync as Cp}from"child_process";import{existsSync as nO,mkdirSync as tO,readFileSync as ELe,renameSync as WX,rmSync as KX,unlinkSync as GX,writeFileSync as zX}from"fs";import{homedir as qX}from"os";import{dirname as JX}from"path";function rO(e,t={}){let n=Nr(e);if(nO(n))return{kind:"already-installed",plistPath:n,label:ot(e)};let r;try{r=lb(e,t._entrypointExistsCheck)}catch(u){return{kind:"failed",reason:u.message}}let o=t.noWatch?void 0:eO(e,t._entrypointExistsCheck),s=_i(e);tO(ab(),{recursive:!0}),tO(JX(s),{recursive:!0});let i={PATH:Z0(),...t.environment??{}},a={label:ot(e),programArguments:r,workingDirectory:qX(),standardOutPath:s,standardErrorPath:s,...o?{watchPaths:o}:{},environmentVariables:i},l=X0(a),c=`${n}.tmp`;try{zX(c,l,{encoding:"utf-8",flag:"wx",mode:384})}catch(u){return{kind:"failed",reason:`Failed to write plist (tmp ${c}): ${u.message}`}}try{WX(c,n)}catch(u){try{GX(c)}catch{}return{kind:"failed",reason:`Failed to install plist (rename ${c} \u2192 ${n}): ${u.message}`}}if(t.skipBootstrap)return{kind:"installed",plistPath:n,label:ot(e),watchPathsActive:!!o};try{Cp("launchctl",["bootstrap",dl(),n],{stdio:["ignore","pipe","pipe"],timeout:Fo})}catch(u){let d=u.message;if(u.code==="EALREADY"||/\b37\b/.test(d))return{kind:"failed",reason:`Service already loaded \u2014 run 'afk service restart ${e}' to reload with the new plist.`};if(/already bootstrapped|already loaded/i.test(d)){let m="";try{Cp("launchctl",["bootout",`${dl()}/${ot(e)}`],{stdio:["ignore","pipe","pipe"],timeout:Fo})}catch(f){m=f.message}try{Cp("launchctl",["bootstrap",dl(),n],{stdio:["ignore","pipe","pipe"],timeout:Fo})}catch(f){let g=f.message;return{kind:"failed",reason:`Bootstrap failed: ${m?`${g} (prior bootout: ${m})`:g}`}}}else return{kind:"failed",reason:`Bootstrap failed: ${d}`}}return{kind:"installed",plistPath:n,label:ot(e),watchPathsActive:!!o}}function oO(e,t={}){let n=Nr(e);if(!nO(n))return{kind:"not-installed",plistPath:n};if(!t.skipBootout)try{Cp("launchctl",["bootout",`${dl()}/${ot(e)}`],{stdio:"ignore",timeout:Fo})}catch{}try{KX(n,{force:!0})}catch(r){return{kind:"failed",reason:`Failed to remove plist: ${r.message}`}}return{kind:"uninstalled",plistPath:n}}function pl(){if(process.platform!=="darwin")throw new Error(`'afk service' uses macOS launchd and is only supported on darwin. Detected: ${process.platform}.`)}function _p(e){let t=e.toLowerCase();if(Ci.includes(t))return t;throw new Error(`Unknown service '${e}'. Supported: ${Ci.join(", ")}.`)}function aO(e){let t=e.command("service").description("Manage AFK background services via macOS launchd (always-on, auto-restart)");t.command("install <name>").description(`Install <${Ci.join("|")}> as a LaunchAgent that starts on login and relaunches on crash`).option("--no-watch","Disable WatchPaths (no auto-restart on rebuild)").option("--dry-run","Write the plist but do not call launchctl",!1).action((n,r)=>{try{pl();let o=_p(n),s=rO(o,{noWatch:r.watch===!1,skipBootstrap:!!r.dryRun});if(s.kind==="already-installed"&&(console.log(st.yellow(`\u26A0 ${s.label} already installed at ${s.plistPath}`)),console.log(p.meta(` Run 'afk service uninstall ${o}' first to reinstall.`)),process.exit(1)),s.kind==="failed"&&(console.error(st.red(`\u2717 Install failed: ${s.reason}`)),process.exit(1)),console.log(st.green(`\u2713 Installed ${s.label}`)),console.log(p.meta(` Plist: ${s.plistPath}`)),console.log(p.meta(` Log: ${_i(o)}`)),s.watchPathsActive?console.log(p.meta(" WatchPaths: active \u2014 service auto-restarts on rebuild.")):console.log(p.meta(" WatchPaths: off \u2014 manual 'afk service restart' needed after updates.")),r.dryRun){let i=process.getuid?.()??501;console.log(p.info(" (dry-run) launchctl bootstrap was skipped; service is NOT yet running.")),console.log(p.meta(` Load manually: launchctl bootstrap gui/${i} ${s.plistPath}`))}else console.log(p.meta(` Status: afk service status ${o}`))}catch(o){z(o)}}),t.command("uninstall <name>").description("Stop the service and remove its LaunchAgent plist").action(n=>{try{pl();let r=_p(n),o=oO(r);if(o.kind==="not-installed"){console.log(st.yellow(`\u26A0 ${ot(r)} is not installed (no plist at ${o.plistPath})`));return}o.kind==="failed"&&(console.error(st.red(`\u2717 Uninstall failed: ${o.reason}`)),process.exit(1)),console.log(st.green(`\u2713 Uninstalled ${ot(r)}`)),console.log(p.meta(` Removed: ${o.plistPath}`))}catch(r){z(r)}}),t.command("status [name]").description("Show running PID, last exit status, and log file for one or all services").action(n=>{try{if(pl(),n){let r=cb(_p(n));iO(r);return}for(let r of Ci)iO(cb(r)),console.log("")}catch(r){z(r)}}),t.command("list").description("List recognised service names and whether each is installed").action(()=>{try{pl(),console.log(st.bold("AFK services:"));for(let n of Ci){let r=Nr(n),o=sO(r),s=o?st.green("\u25CF"):st.dim("\u25CB"),i=o?p.meta("installed"):p.meta("not installed");console.log(` ${s} ${n.padEnd(10)} ${i} ${p.meta(r)}`)}}catch(n){z(n)}}),t.command("restart <name>").description("Restart the service (launchctl kickstart -k)").action(n=>{try{pl();let r=_p(n),o=Nr(r);if(sO(o)||(console.error(st.red(`\u2717 ${ot(r)} is not installed. Run 'afk service install ${r}' first.`)),process.exit(1)),typeof process.getuid!="function")throw new Error("process.getuid is unavailable \u2014 afk service restart requires a POSIX system.");let s=process.getuid();try{VX("launchctl",["kickstart","-k",`gui/${s}/${ot(r)}`],{stdio:["ignore","pipe","pipe"],timeout:8e3}),console.log(st.green(`\u2713 Restarted ${ot(r)}`))}catch(i){console.error(st.red(`\u2717 Restart failed: ${i.message}`)),process.exit(1)}}catch(r){z(r)}})}function iO(e){if(console.log(st.bold(`${e.label}`)),!e.installed){console.log(` ${st.dim("\u25CB")} Not installed`),console.log(p.meta(` Plist: ${e.plistPath}`)),console.log(p.meta(` Install: afk service install ${e.name}`));return}e.pid!==void 0?console.log(` ${st.green("\u25CF")} Running (PID ${e.pid})`):(console.log(` ${st.yellow("\u25CF")} Installed but not running`),e.lastExitStatus!==void 0&&e.lastExitStatus!==0&&console.log(p.meta(` Last exit status: ${e.lastExitStatus}`))),console.log(p.meta(` Plist: ${e.plistPath}`)),console.log(p.meta(` Log: ${e.logFile}`))}import No from"chalk";import{execFileSync as YX}from"child_process";import{existsSync as dO,mkdirSync as XX,readFileSync as ZX,renameSync as QX,writeFileSync as e9}from"fs";import{dirname as lO,join as t9}from"path";import{randomBytes as n9}from"crypto";var Ur="chrome-devtools",ub=["stable","beta","canary","dev"];function r9(e="stable"){let t=["chrome-devtools-mcp@latest","--autoConnect"];return e!=="stable"&&t.push("--channel",e),{command:"npx",args:t}}function cO(e){if(!dO(e))return{mcpServers:{}};let t;try{t=ZX(e,"utf-8")}catch(o){throw new Error(`Failed to read MCP config at ${e}: ${o.message}`)}let n;try{n=JSON.parse(t)}catch{throw new Error(`MCP config at ${e} is not valid JSON. Fix or remove it, then retry.`)}if(typeof n!="object"||n===null||Array.isArray(n))throw new Error(`MCP config at ${e} must be a JSON object.`);let r=n;if(Array.isArray(r.mcpServers))throw new Error(`MCP config at ${e} has an invalid "mcpServers" (must be a JSON object, not an array).`);return(r.mcpServers===void 0||typeof r.mcpServers!="object"||r.mcpServers===null)&&(r.mcpServers={}),r}function uO(e,t){XX(lO(e),{recursive:!0});let n=t9(lO(e),`.mcp.json.${process.pid}.${n9(4).toString("hex")}.tmp`);e9(n,`${JSON.stringify(t,null,2)}
2165
2165
  `,"utf-8"),QX(n,e)}function o9(){let e=process.platform==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta","/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"]:["google-chrome","google-chrome-stable","chromium","chromium-browser"];for(let t of e)try{let r=YX(t,["--version"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5e3}).match(/(\d+)\.\d+\.\d+/);if(r!==null&&r[1]!==void 0)return parseInt(r[1],10)}catch{}return null}function s9(){let e=o9();console.log(""),console.log(No.bold("Drive your real Chrome \u2014 one-time setup:")),e===null?console.log(p.meta(" \u2022 Chrome not detected. autoConnect requires Chrome \u2265 144.")):e<144?console.log(No.yellow(` \u2022 Detected Chrome ${e} \u2014 autoConnect requires \u2265 144. Please update Chrome.`)):console.log(p.meta(` \u2022 Detected Chrome ${e} \u2713 (autoConnect needs \u2265 144)`)),console.log(p.meta(" 1. In Chrome, open chrome://inspect/#remote-debugging and enable it (one time).")),console.log(p.meta(' 2. The first time the agent drives Chrome, click "Allow" on the prompt.')),console.log(p.meta(' 3. Chrome shows a "being controlled by automated test software" banner while active.')),console.log(""),console.log(p.meta("The agent gains mcp__chrome-devtools__* tools (navigate, click, fill, take_snapshot, \u2026)")),console.log(p.meta("driving your REAL, logged-in profile. Run `/mcp` in the REPL to confirm it connected.")),console.log(p.meta("Undo anytime with `afk browser disconnect`."))}function pO(e){let t=e.command("browser").description("Connect the agent to your real Chrome browser (via Chrome DevTools MCP)");t.command("connect").description("Wire chrome-devtools-mcp (--autoConnect) so the agent can drive your real, logged-in Chrome").option("--channel <channel>",`Chrome channel autoConnect targets (${ub.join("|")})`,"stable").action(n=>{try{let r=(n.channel??"stable").toLowerCase();if(!ub.includes(r))throw new Error(`--channel must be one of ${ub.join(", ")} (got "${n.channel}")`);let o=Mo(),s=cO(o);s.mcpServers===void 0&&(s.mcpServers={});let i=r9(r),a=s.mcpServers[Ur];if(a!==void 0&&JSON.stringify(a)===JSON.stringify(i))console.log(No.green(`\u2713 "${Ur}" already configured`)),console.log(p.meta(` Config: ${o}`));else{s.mcpServers[Ur]=i,uO(o,s);let l=a===void 0?"Added":"Updated";console.log(No.green(`\u2713 ${l} "${Ur}" MCP server`)),console.log(p.meta(` Config: ${o}`)),console.log(p.meta(` Runs: npx ${i.args?.join(" ")??""}`))}s9()}catch(r){z(r)}}),t.command("disconnect").description("Remove the chrome-devtools server from your MCP config").action(()=>{try{let n=Mo();if(!dO(n)){console.log(No.yellow(`\u26A0 No MCP config at ${n} \u2014 nothing to remove.`));return}let r=cO(n);if(r.mcpServers===void 0||r.mcpServers[Ur]===void 0){console.log(No.yellow(`\u26A0 "${Ur}" is not configured \u2014 nothing to remove.`));return}delete r.mcpServers[Ur],uO(n,r),console.log(No.green(`\u2713 Removed "${Ur}" from ${n}`))}catch(n){z(n)}})}import{readFileSync as i9,readdirSync as a9,statSync as l9}from"fs";import{join as fb}from"path";K();import{join as Ge}from"path";function Ap(){return Ge(en(),"improve")}function Bo(){return Ge(Ap(),"failure-cards")}function mO(){return Ge(Bo(),".index.jsonl")}function ml(e){return Ge(Bo(),`${e}.json`)}function Ip(e){return Ge(Bo(),`${e}.md`)}function fO(){return Ge(Te(),"witness")}function Uo(){return Ge(Ap(),"proposals")}function gO(){return Ge(Uo(),".index.jsonl")}function db(e){return Ge(Uo(),`${e}.json`)}function hO(e){return Ge(Uo(),`${e}.md`)}function jr(){return Ge(Ap(),"eval-cases")}function yO(){return Ge(jr(),".index.jsonl")}function pb(e){return Ge(jr(),`${e}.json`)}function mb(e){return Ge(jr(),`${e}.fixture.jsonl`)}function bO(e){return Ge(jr(),`${e}.md`)}function Ai(){return Ge(Ap(),"eval-runs")}function wO(){return Ge(Ai(),".index.jsonl")}function SO(e){return Ge(Ai(),`${e}.json`)}function vO(e){return Ge(Ai(),`${e}.md`)}G();function kO(e){let t=e.trim(),n=/^(\d+)\s*([smhd])$/i.exec(t);if(!n)return;let r=Number.parseInt(n[1]??"0",10),o=(n[2]??"").toLowerCase();if(!(!Number.isFinite(r)||r<=0))switch(o){case"s":return r*1e3;case"m":return r*60*1e3;case"h":return r*60*60*1e3;case"d":return r*24*60*60*1e3;default:return}}function xO(e={}){let t=e.witnessRoot??fO(),n=e.afkHome??k.AFK_HOME??u9(),r=e.sinceMs,o={sessionsScanned:0,sessionsSkippedOld:0,sessionsSkippedEmpty:0,invalidLineCount:0,sessions:[]},s;try{s=a9(t)}catch{return o}for(let i of s){if(i.startsWith("."))continue;let a=fb(t,i),l;try{l=l9(a)}catch{continue}if(!l.isDirectory())continue;if(r!==void 0&&l.mtimeMs<r){o.sessionsSkippedOld+=1;continue}let c=fb(a,"trace.jsonl"),u;try{u=i9(c,"utf-8")}catch{o.sessionsSkippedEmpty+=1;continue}let d=d9(c,n),m=c9({sessionId:i,tracePath:c,relativeTracePath:d,content:u,sessionMtimeMs:l.mtimeMs});o.sessions.push(m),o.sessionsScanned+=1,o.invalidLineCount+=m.invalidLineCount}return o}function c9(e){let{sessionId:t,tracePath:n,relativeTracePath:r,content:o,sessionMtimeMs:s}=e,i=[],a=0,l=o.split(`
2166
2166
  `);for(let c=0;c<l.length;c+=1){let u=l[c]??"";if(u.trim()==="")continue;let d;try{d=JSON.parse(u)}catch{a+=1;continue}let m=$R.safeParse(d);if(!m.success){a+=1;continue}i.push({sessionId:t,tracePath:n,relativeTracePath:r,lineNumber:c+1,rawLine:u,event:m.data})}return{sessionId:t,tracePath:n,relativeTracePath:r,sessionMtimeMs:s,events:i,invalidLineCount:a}}function u9(){let e=k.AFK_HOME;return e&&e.length>0?e:fb(k.HOME??"",".afk")}function d9(e,t){if(!t)return e;if(e.startsWith(t)){let n=e.slice(t.length);return n.startsWith("/")&&(n=n.slice(1)),n}return e}import{createHash as p9}from"crypto";var jo=4,m9=8,f9="v1-bytes-tuple";function EO(e,t={}){let n=t.minRepeats??jo;if(n<2)throw new Error(`minRepeats must be >= 2 (got ${n})`);let r=[];for(let o of e){let s=g9(o,n);r.push(...s)}return r}function g9(e,t){let n=h9(e.events),r=y9(n),o=[];for(let[s,i]of r.entries()){let a=b9(i,t);for(let l of a)o.push(S9(e,l,s))}return o}function h9(e){let t=new Map,n=[];for(let r of e){let o=r.event;if(o.kind!=="tool_call")continue;if(o.payload.phase==="started"){t.set(o.payload.toolUseId,{seq:o.seq,name:o.payload.name,inputBytes:o.payload.inputBytes,subagentId:o.payload.subagentId});continue}let s=t.get(o.payload.toolUseId);if(!s)continue;t.delete(o.payload.toolUseId);let i=w9({name:o.payload.name,inputBytes:s.inputBytes,resultBytes:o.payload.resultBytes,isError:o.payload.isError,subagentId:s.subagentId});n.push({toolUseId:o.payload.toolUseId,startedSeq:s.seq,completedSeq:o.seq,completedLineNumber:r.lineNumber,name:o.payload.name,inputBytes:s.inputBytes,resultBytes:o.payload.resultBytes,isError:o.payload.isError,subagentId:s.subagentId,rawLine:r.rawLine,fingerprint:i})}return n}function y9(e){let t=new Map;for(let n of e){let r=n.subagentId??"root",o=t.get(r);o?o.push(n):t.set(r,[n])}return t}function b9(e,t){let n=[],r=0;for(;r<e.length;){let o=e[r];if(!o){r+=1;continue}let s=r+1;for(;s<e.length;){let a=e[s];if(!a||a.fingerprint!==o.fingerprint)break;s+=1}s-r>=t&&n.push(e.slice(r,s)),r=s>r?s:r+1}return n}function w9(e){let t=[e.name,String(e.inputBytes),String(e.resultBytes),e.isError?"1":"0",e.subagentId??""].join("|");return p9("sha256").update(t).digest("hex")}function S9(e,t,n){let r=t[0];if(!r)throw new Error("repeated-tool-use: empty run");let o=T9(r.name,r.fingerprint),s=new Date().toISOString(),i=t.slice(0,m9),a=[{sessionId:e.sessionId,tracePath:e.relativeTracePath,eventIndices:i.map(l=>l.completedSeq),excerpt:v9(i),annotation:k9(t,n)}];return{slug:o,title:x9(r.name,t.length),pattern:"repeated-tool-use",severity:E9(t.length),observedAt:s,evidence:a,detail:{detector:"repeated-tool-use@v1",fingerprintAlgorithm:f9,fingerprint:r.fingerprint,toolName:r.name,runLength:t.length,agentContext:n,inputBytes:r.inputBytes,resultBytes:r.resultBytes,isError:r.isError,toolUseIds:t.map(l=>l.toolUseId),completedSeqs:t.map(l=>l.completedSeq)}}}function v9(e){let t=e.map(n=>n.rawLine).join(`
2167
- `);return t.length<=2e3?t:t.slice(0,1997)+"..."}function k9(e,t){let n=e[0],r=e[e.length-1];return!n||!r?"":[`${e.length}\xD7 consecutive '${n.name}' calls in ${t} context`,`(seq ${n.completedSeq}\u2026${r.completedSeq},`,`inputBytes=${n.inputBytes}, resultBytes=${n.resultBytes},`,`isError=${n.isError})`].join(" ")}function x9(e,t){return`'${e}' tool repeated ${t}\xD7 with identical fingerprint`}function E9(e){return e>=10?"high":e>=4?"medium":"low"}function T9(e,t){let n=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=t.slice(0,12);return`repeated-tool-${n.length>0?n:"tool"}-${r}`}var R9=new Set(["budget_exceeded","timeout","hook_blocked","abort","iteration_cap","max_turns_exceeded"]);function RO(e,t={}){let n=t.minOccurrences??1;if(n<1)throw new Error(`minOccurrences must be >= 1 (got ${n})`);let r=new Map;for(let s of e)for(let i of s.events){let a=i.event;if(a.kind!=="closure")continue;let l=a.payload.reason;if(!R9.has(l))continue;let c={sessionId:s.sessionId,relativeTracePath:s.relativeTracePath,seq:a.seq,rawLine:i.rawLine,reason:l,finalCostUsd:a.payload.finalCostUsd,finalTurnCount:a.payload.finalTurnCount},u=r.get(l);u?u.push(c):r.set(l,[c])}let o=[];for(let[s,i]of r.entries())i.length<n||o.push(_9(s,i));return o}var C9=8;function _9(e,t){let n=I9(e),r=new Date().toISOString(),s=t.slice(0,C9).map(l=>({sessionId:l.sessionId,tracePath:l.relativeTracePath,eventIndices:[l.seq],excerpt:P9(l.rawLine),annotation:`closure.reason='${l.reason}' \xB7 cost=${M9(l.finalCostUsd)} \xB7 turns=${l.finalTurnCount}`})),i=t.reduce((l,c)=>l+c.finalCostUsd,0),a=t.reduce((l,c)=>l+c.finalTurnCount,0)/t.length;return{slug:n,title:`Session closure reason '${e}' across ${t.length} session${t.length===1?"":"s"}`,pattern:"closure-anomaly",severity:A9(e,t.length),observedAt:r,evidence:s,detail:{detector:"closure-anomaly@v1",closureReason:e,affectedSessions:t.length,totalCostUsd:TO(i),avgTurnCount:O9(a),maxCostUsd:TO(Math.max(...t.map(l=>l.finalCostUsd))),sessionIds:t.map(l=>l.sessionId),seqs:t.map(l=>l.seq)}}}function A9(e,t){switch(e){case"budget_exceeded":case"timeout":return"high";case"hook_blocked":case"iteration_cap":case"max_turns_exceeded":return t>=3?"high":"medium";case"abort":return t>=3?"medium":"low";default:return"low"}}function I9(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`closure-anomaly-${t.length>0?t:"unknown"}`}function P9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}function M9(e){return`$${e.toFixed(4)}`}function TO(e){return Math.round(e*1e4)/1e4}function O9(e){return Math.round(e*100)/100}import{createHash as $9}from"crypto";var Ho=2,D9="v1-hook-reason-tuple",L9=8;function CO(e,t={}){let n=t.minOccurrences??Ho;if(n<1)throw new Error(`minOccurrences must be >= 1 (got ${n})`);let r=new Map;for(let s of e)for(let i of s.events){let a=i.event;if(a.kind!=="hook_decision"||a.payload.hookEvent!=="SubagentStart"||a.payload.decision!=="block")continue;let l=a.payload.reason??"",c=a.payload.blockedTool,u=F9({hookEvent:a.payload.hookEvent,reason:l,blockedTool:c}),d={sessionId:s.sessionId,relativeTracePath:s.relativeTracePath,seq:a.seq,rawLine:i.rawLine,reason:l,blockedTool:c,injectedContextBytes:a.payload.injectedContextBytes},m=r.get(u);m?m.push(d):r.set(u,[d])}let o=[];for(let[s,i]of r.entries())i.length<n||o.push(B9(s,i));return o}function F9(e){let t=[e.hookEvent,e.reason,e.blockedTool??""].join("|");return $9("sha256").update(t).digest("hex")}function N9(e){return`subagent-block-${e.slice(0,12)}`}function B9(e,t){let n=t[0];if(!n)throw new Error("subagent-block: empty sighting bucket");let r=N9(e),o=new Date().toISOString(),i=t.slice(0,L9).map(l=>({sessionId:l.sessionId,tracePath:l.relativeTracePath,eventIndices:[l.seq],excerpt:W9(l.rawLine),annotation:H9(l)})),a=new Set(t.map(l=>l.sessionId)).size;return{slug:r,title:j9(n.reason,t.length,a),pattern:"subagent-block",severity:U9(t.length,a),observedAt:o,evidence:i,detail:{detector:"subagent-block@v1",fingerprintAlgorithm:D9,fingerprint:e,hookEvent:"SubagentStart",reason:n.reason,blockedTool:n.blockedTool??null,blockCount:t.length,distinctSessions:a,sessionIds:t.map(l=>l.sessionId),seqs:t.map(l=>l.seq)}}}function U9(e,t){return e>=6||t>=3?"high":e>=3?"medium":"low"}function j9(e,t,n){let r=e.length>80?e.slice(0,77)+"...":e,o=r.length>0?`: "${r}"`:"";return`SubagentStart hook blocked ${t}\xD7 across ${n} session${n===1?"":"s"}${o}`}function H9(e){let t=[`seq ${e.seq}`];return e.reason&&t.push(`reason="${e.reason.slice(0,200)}"`),e.blockedTool&&t.push(`blockedTool=${e.blockedTool}`),typeof e.injectedContextBytes=="number"&&t.push(`injectedContextBytes=${e.injectedContextBytes}`),t.join(" \xB7 ")}function W9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}var K9=new Set(["policy-refusal","permission-denied","hook-block","abort"]),Wo=3,Ko=.25,G9=8;function _O(e,t={}){let n=t.minFailures??Wo,r=t.minFailureRate??Ko;if(n<1)throw new Error(`minFailures must be >= 1 (got ${n})`);if(r<=0||r>1)throw new Error(`minFailureRate must be in (0, 1] (got ${r})`);let o=new Map;for(let i of e)for(let a of i.events){let l=a.event;if(l.kind!=="tool_call"||l.payload.phase!=="completed"||l.payload.circuitBreaker===!0)continue;let c=z9(o,l.payload.name),u=l.payload.failureClass;if(u!==void 0&&K9.has(u)){c.excludedByClass.set(u,(c.excludedByClass.get(u)??0)+1);continue}c.totalCalls+=1,l.payload.isError&&(c.failures.push({sessionId:i.sessionId,relativeTracePath:i.relativeTracePath,seq:l.seq,rawLine:a.rawLine,resultBytes:l.payload.resultBytes,durationMs:l.payload.durationMs,truncated:l.payload.truncated,...u!==void 0?{failureClass:u}:{}}),c.affectedSessions.add(i.sessionId),l.payload.truncated&&(c.truncatedFailureCount+=1))}let s=[];for(let i of o.values()){if(i.failures.length<n)continue;let a=i.failures.length/i.totalCalls;a<r||s.push(q9(i,a))}return s.sort((i,a)=>i.slug.localeCompare(a.slug)),s}function z9(e,t){let n=e.get(t);return n||(n={toolName:t,totalCalls:0,failures:[],affectedSessions:new Set,truncatedFailureCount:0,excludedByClass:new Map},e.set(t,n)),n}function q9(e,t){let n=Y9(e.toolName),r=new Date().toISOString(),s=e.failures.slice(0,G9).map(u=>({sessionId:u.sessionId,tracePath:u.relativeTracePath,eventIndices:[u.seq],excerpt:X9(u.rawLine),annotation:`isError=true${u.failureClass?` \xB7 class=${u.failureClass}`:""} \xB7 resultBytes=${u.resultBytes} \xB7 durationMs=${u.durationMs}${u.truncated?" \xB7 truncated":""}`})),a=e.failures.reduce((u,d)=>u+d.durationMs,0)/e.failures.length,l={};for(let u of e.failures){let d=u.failureClass??"unclassified";l[d]=(l[d]??0)+1}let c={};for(let[u,d]of e.excludedByClass)c[u]=d;return{slug:n,title:V9(e.toolName,e.failures.length,e.totalCalls,t),pattern:"tool-failure-density",severity:J9(e.failures.length,t),observedAt:r,evidence:s,detail:{detector:"tool-failure-density@v2",toolName:e.toolName,totalCalls:e.totalCalls,failureCount:e.failures.length,failureRate:Z9(t),affectedSessionCount:e.affectedSessions.size,truncatedFailureCount:e.truncatedFailureCount,avgFailureDurationMs:Q9(a),failureClassBreakdown:l,excludedByClass:c,sessionIds:Array.from(e.affectedSessions),seqs:e.failures.map(u=>u.seq)}}}function J9(e,t){return t>=1||t>=.5?"high":t>=.25?e>=10?"high":"medium":e>=10?"medium":"low"}function V9(e,t,n,r){let o=(r*100).toFixed(1);return`'${e}' tool failed ${t}/${n} calls (${o}%)`}function Y9(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`tool-failure-${t.length>0?t:"unknown"}`}function X9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}function Z9(e){return Math.round(e*1e4)/1e4}function Q9(e){return Math.round(e*100)/100}var Pp=Object.freeze([{name:"repeated-tool-use",description:`Tool fired \u2265N consecutive times with identical fingerprint (default ${jo})`,run:(e,t)=>EO(e,{minRepeats:t.minRepeats??jo})},{name:"closure-anomaly",description:`Session closure reason \u2208 {budget_exceeded,timeout,hook_blocked,abort,iteration_cap,max_turns_exceeded} (default \u2265${1})`,enabledByDefault:!1,run:(e,t)=>RO(e,{minOccurrences:t.closureAnomalyMinOccurrences??1})},{name:"subagent-block",description:`Same SubagentStart hook block reason recurring across \u2265N events (default ${Ho})`,enabledByDefault:!1,run:(e,t)=>CO(e,{minOccurrences:t.subagentBlockMinOccurrences??Ho})},{name:"tool-failure-density",description:`Tool with \u2265N failures (isError: true) AND failure rate \u2265R (defaults: ${Wo} failures, ${Ko} rate)`,enabledByDefault:!0,run:(e,t)=>_O(e,{minFailures:t.toolFailureMinFailures??Wo,minFailureRate:t.toolFailureMinRate??Ko})}]);function AO(e,t,n,r){let o=[];for(let s of Pp){if(n!==void 0){if(!n.has(s.name))continue}else if(r!==!0&&s.enabledByDefault===!1)continue;let i=s.run(e,t);o.push(...i)}return o}function Mp(){return Pp.map(e=>e.name)}function IO(){return Pp.filter(e=>e.enabledByDefault!==!1).map(e=>e.name)}function Ii(){return Pp.filter(e=>e.enabledByDefault===!1).map(e=>e.name)}import{existsSync as Lp,mkdirSync as BO,readFileSync as y7,readdirSync as b7,renameSync as UO,writeFileSync as yb}from"fs";import{join as w7}from"path";import{z as I}from"zod";var Pi=I.enum(["repeated-tool-use","subagent-block","closure-anomaly","tool-failure-density"]),Op=I.enum(["low","medium","high"]),e7=I.enum(["open","deferred","resolved"]),PO=I.object({sessionId:I.string().min(1),tracePath:I.string().min(1),eventIndices:I.array(I.number().int().nonnegative()).min(1),excerpt:I.string().max(2e3),annotation:I.string().optional()}),$p=I.object({at:I.string().datetime(),text:I.string()}),gl=I.object({schemaVersion:I.literal(1),slug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"slug must be lowercase alphanumeric with hyphens"),title:I.string().min(1).max(200),pattern:Pi,severity:Op,status:e7,firstSeen:I.string().datetime(),lastSeen:I.string().datetime(),occurrenceCount:I.number().int().nonnegative(),evidence:I.array(PO).min(1),detail:I.record(I.string(),I.unknown()),notes:I.array($p).default([])}),bFe=I.object({slug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),title:I.string().min(1).max(200),pattern:Pi,severity:Op,observedAt:I.string().datetime(),evidence:I.array(PO).min(1),detail:I.record(I.string(),I.unknown())}),MO=I.object({timestamp:I.string().datetime(),event:I.enum(["created","updated","merged-noop"]),slug:I.string(),pattern:Pi,occurrenceCount:I.number().int().nonnegative(),evidenceAdded:I.number().int().nonnegative()}),t7=I.enum(["prompt-defect","schema-too-strict","schema-too-loose","tool-output-shape","hook-overreach","retry-policy","timeout-too-low","cost-control","dispatcher-bug","detector-needs-tuning","unknown"]),n7=I.enum(["safe","moderate","high","forbidden"]),r7=I.enum(["low","medium","high"]),o7=I.object({cardSlug:I.string(),eventIndices:I.array(I.number().int().nonnegative()).min(1),annotation:I.string().optional()}),s7=I.object({path:I.string().min(1),rationale:I.string(),riskTier:n7,confidence:r7}),i7=I.object({unitTests:I.array(I.string()),evalCases:I.array(I.string()),smokeChecks:I.array(I.string()),manualChecks:I.array(I.string())}),a7=I.object({forbiddenPaths:I.array(I.string()),requiresExplicitApproval:I.boolean()}),l7=I.enum(["draft","approved","rejected","superseded"]),gb=I.object({schemaVersion:I.literal(1),proposalId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),cardSlug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),title:I.string().min(1).max(200),hypothesis:I.string().min(1),rootCauseClass:t7,evidenceRefs:I.array(o7).min(1),fixSketch:I.string().min(1),likelyFiles:I.array(s7),riskLevel:Op,validationPlan:i7,scopeFreeze:a7,generatedBy:I.enum(["template","llm"]),createdAt:I.string().datetime(),status:l7,notes:I.array($p).default([])}),OO=I.object({timestamp:I.string().datetime(),event:I.enum(["created","triaged","superseded"]),proposalId:I.string(),cardSlug:I.string(),generatedBy:I.enum(["template","llm"]),riskLevel:Op}),c7=I.object({sourceSessionId:I.string().min(1),sourceTracePath:I.string().min(1),fixturePath:I.string().min(1),evidenceRowIndex:I.number().int().nonnegative(),evidenceEventIndices:I.array(I.number().int().nonnegative()).min(1),sliceLineRange:I.object({startLine:I.number().int().positive(),endLine:I.number().int().positive()}),sliceLineCount:I.number().int().positive(),sliceSha256:I.string().regex(/^[0-9a-f]{64}$/,"sliceSha256 must be 64 lowercase hex chars")}),u7=I.object({kind:I.literal("pattern-absent"),patternId:Pi,detectorVersion:I.string().min(1),rationale:I.string().min(1)}),d7=I.object({detectorAtGeneration:I.string().min(1),fingerprintAtGeneration:I.string().nullable(),cardOccurrenceCountAtGeneration:I.number().int().nonnegative(),cardLastSeenAtGeneration:I.string().datetime(),generatedBy:I.literal("replay-fixture")}),p7=I.enum(["draft","approved","rejected","superseded"]),Dp=I.object({schemaVersion:I.literal(1),evalCaseId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"evalCaseId must be lowercase alphanumeric with hyphens"),cardSlug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),proposalId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/).nullable(),title:I.string().min(1).max(200),createdAt:I.string().datetime(),kind:I.literal("replay"),replay:c7,assertion:u7,provenance:d7,status:p7,notes:I.array($p).default([])}),$O=I.object({timestamp:I.string().datetime(),event:I.enum(["created","triaged","superseded"]),evalCaseId:I.string(),cardSlug:I.string(),proposalId:I.string().nullable(),kind:I.literal("replay")}),m7=I.enum(["pass","fail","skipped"]),f7=I.object({name:I.string().min(1),description:I.string().min(1),status:m7,expected:I.string(),actual:I.string()}),g7=I.enum(["config-value","observed-behavior","source-symbol","fixture"]),h7=I.object({kind:g7,ref:I.string().min(1),detail:I.string()}),DO=I.enum(["pass","fail","unsupported","error"]),hb=I.object({schemaVersion:I.literal(1),evalRunId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"evalRunId must be lowercase alphanumeric with hyphens"),evalCaseId:I.string().min(1),cardSlug:I.string().min(1),patternId:Pi,contract:I.string().min(1).nullable(),status:DO,createdAt:I.string().datetime(),durationMs:I.number().int().nonnegative(),checks:I.array(f7),evidence:I.array(h7),runner:I.object({version:I.string().min(1),mode:I.literal("deterministic")}),notes:I.array($p).default([])}),LO=I.object({timestamp:I.string().datetime(),event:I.literal("created"),evalRunId:I.string(),evalCaseId:I.string(),cardSlug:I.string(),patternId:Pi,contract:I.string().nullable(),status:DO}),FO=Object.freeze(["**/auth/**","**/billing/**","**/secrets/**","**/credentials*",".env",".env.*","pnpm-lock.yaml","package-lock.json","yarn.lock",".github/workflows/**","dist/**","build/**","node_modules/**",".git/**","**/.afk/config/**","**/.afk/state/**"]);function jO(e){let t=Bo();Lp(t)||BO(t,{recursive:!0});let n=ml(e.slug),r=Ip(e.slug),o=hl(n),s=S7(o,e),i=o===void 0,a=s.evidence.length-(o?.evidence.length??0),l=i?"created":a>0?"updated":"merged-noop",c=gl.parse(s);return x7(n,c),E7(r,yl(c)),k7({timestamp:T7(),event:l,slug:c.slug,pattern:c.pattern,occurrenceCount:c.occurrenceCount,evidenceAdded:Math.max(0,a)}),{slug:c.slug,event:l,occurrenceCount:c.occurrenceCount,evidenceAdded:Math.max(0,a),jsonPath:n,markdownPath:r}}function hl(e){if(Lp(e))try{let t=y7(e,"utf-8"),n=JSON.parse(t),r=gl.safeParse(n);return r.success?r.data:void 0}catch{return}}function S7(e,t){if(!e)return{schemaVersion:1,slug:t.slug,title:t.title,pattern:t.pattern,severity:t.severity,status:"open",firstSeen:t.observedAt,lastSeen:t.observedAt,occurrenceCount:t.evidence.length,evidence:t.evidence,detail:t.detail,notes:[]};if(e.slug!==t.slug)throw new Error(`card-writer: slug mismatch on merge (existing='${e.slug}', detection='${t.slug}')`);let n=v7(e.evidence,t.evidence),r=R7(e.firstSeen,t.observedAt),o=C7(e.lastSeen,t.observedAt),s=_7(e.severity,t.severity);return{schemaVersion:1,slug:e.slug,title:t.title,pattern:e.pattern,severity:s,status:e.status,firstSeen:r,lastSeen:o,occurrenceCount:n.length,evidence:n,detail:t.detail,notes:e.notes}}function v7(e,t){let n=s=>`${s.sessionId}::${s.eventIndices[0]??"NA"}`,r=new Set(e.map(n)),o=[...e];for(let s of t){let i=n(s);r.has(i)||(r.add(i),o.push(s))}return o}function yl(e){let t=[];t.push(`# ${e.slug} \u2014 \`${e.severity}\` \u2014 \`${e.status}\``),t.push(""),t.push(e.title),t.push(""),t.push(`**Pattern:** \`${e.pattern}\` \xB7 **Occurrences:** ${e.occurrenceCount} \xB7 **First seen:** ${e.firstSeen} \xB7 **Last seen:** ${e.lastSeen}`),t.push(""),t.push("## Evidence"),t.push("");for(let n of e.evidence)t.push(`### Session \`${n.sessionId}\``),t.push(""),t.push(`- Trace: \`${n.tracePath}\``),t.push(`- Event seqs: ${n.eventIndices.join(", ")}`),n.annotation&&t.push(`- Note: ${n.annotation}`),t.push(""),t.push("```jsonl"),t.push(n.excerpt),t.push("```"),t.push("");if(t.push("## Detail"),t.push(""),t.push("```json"),t.push(JSON.stringify(e.detail,null,2)),t.push("```"),t.push(""),t.push("## Triage notes"),t.push(""),e.notes.length>0){for(let n of e.notes)t.push(`- _${n.at}_ \u2014 ${n.text}`);t.push("")}else t.push('_(none \u2014 add one with `afk improve cards triage <slug> --note "\u2026"`)_'),t.push("");return t.join(`
2167
+ `);return t.length<=2e3?t:t.slice(0,1997)+"..."}function k9(e,t){let n=e[0],r=e[e.length-1];return!n||!r?"":[`${e.length}\xD7 consecutive '${n.name}' calls in ${t} context`,`(seq ${n.completedSeq}\u2026${r.completedSeq},`,`inputBytes=${n.inputBytes}, resultBytes=${n.resultBytes},`,`isError=${n.isError})`].join(" ")}function x9(e,t){return`'${e}' tool repeated ${t}\xD7 with identical fingerprint`}function E9(e){return e>=10?"high":e>=4?"medium":"low"}function T9(e,t){let n=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=t.slice(0,12);return`repeated-tool-${n.length>0?n:"tool"}-${r}`}var R9=new Set(["budget_exceeded","timeout","hook_blocked","abort","iteration_cap","max_turns_exceeded"]);function RO(e,t={}){let n=t.minOccurrences??1;if(n<1)throw new Error(`minOccurrences must be >= 1 (got ${n})`);let r=new Map;for(let s of e)for(let i of s.events){let a=i.event;if(a.kind!=="closure")continue;let l=a.payload.reason;if(!R9.has(l))continue;let c={sessionId:s.sessionId,relativeTracePath:s.relativeTracePath,seq:a.seq,rawLine:i.rawLine,reason:l,finalCostUsd:a.payload.finalCostUsd,finalTurnCount:a.payload.finalTurnCount},u=r.get(l);u?u.push(c):r.set(l,[c])}let o=[];for(let[s,i]of r.entries())i.length<n||o.push(_9(s,i));return o}var C9=8;function _9(e,t){let n=I9(e),r=new Date().toISOString(),s=t.slice(0,C9).map(l=>({sessionId:l.sessionId,tracePath:l.relativeTracePath,eventIndices:[l.seq],excerpt:P9(l.rawLine),annotation:`closure.reason='${l.reason}' \xB7 cost=${M9(l.finalCostUsd)} \xB7 turns=${l.finalTurnCount}`})),i=t.reduce((l,c)=>l+c.finalCostUsd,0),a=t.reduce((l,c)=>l+c.finalTurnCount,0)/t.length;return{slug:n,title:`Session closure reason '${e}' across ${t.length} session${t.length===1?"":"s"}`,pattern:"closure-anomaly",severity:A9(e,t.length),observedAt:r,evidence:s,detail:{detector:"closure-anomaly@v1",closureReason:e,affectedSessions:t.length,totalCostUsd:TO(i),avgTurnCount:O9(a),maxCostUsd:TO(Math.max(...t.map(l=>l.finalCostUsd))),sessionIds:t.map(l=>l.sessionId),seqs:t.map(l=>l.seq)}}}function A9(e,t){switch(e){case"budget_exceeded":case"timeout":return"high";case"hook_blocked":case"iteration_cap":case"max_turns_exceeded":return t>=3?"high":"medium";case"abort":return t>=3?"medium":"low";default:return"low"}}function I9(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`closure-anomaly-${t.length>0?t:"unknown"}`}function P9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}function M9(e){return`$${e.toFixed(4)}`}function TO(e){return Math.round(e*1e4)/1e4}function O9(e){return Math.round(e*100)/100}import{createHash as $9}from"crypto";var Ho=2,D9="v1-hook-reason-tuple",L9=8;function CO(e,t={}){let n=t.minOccurrences??Ho;if(n<1)throw new Error(`minOccurrences must be >= 1 (got ${n})`);let r=new Map;for(let s of e)for(let i of s.events){let a=i.event;if(a.kind!=="hook_decision"||a.payload.hookEvent!=="SubagentStart"||a.payload.decision!=="block")continue;let l=a.payload.reason??"",c=a.payload.blockedTool,u=F9({hookEvent:a.payload.hookEvent,reason:l,blockedTool:c}),d={sessionId:s.sessionId,relativeTracePath:s.relativeTracePath,seq:a.seq,rawLine:i.rawLine,reason:l,blockedTool:c,injectedContextBytes:a.payload.injectedContextBytes},m=r.get(u);m?m.push(d):r.set(u,[d])}let o=[];for(let[s,i]of r.entries())i.length<n||o.push(B9(s,i));return o}function F9(e){let t=[e.hookEvent,e.reason,e.blockedTool??""].join("|");return $9("sha256").update(t).digest("hex")}function N9(e){return`subagent-block-${e.slice(0,12)}`}function B9(e,t){let n=t[0];if(!n)throw new Error("subagent-block: empty sighting bucket");let r=N9(e),o=new Date().toISOString(),i=t.slice(0,L9).map(l=>({sessionId:l.sessionId,tracePath:l.relativeTracePath,eventIndices:[l.seq],excerpt:W9(l.rawLine),annotation:H9(l)})),a=new Set(t.map(l=>l.sessionId)).size;return{slug:r,title:j9(n.reason,t.length,a),pattern:"subagent-block",severity:U9(t.length,a),observedAt:o,evidence:i,detail:{detector:"subagent-block@v1",fingerprintAlgorithm:D9,fingerprint:e,hookEvent:"SubagentStart",reason:n.reason,blockedTool:n.blockedTool??null,blockCount:t.length,distinctSessions:a,sessionIds:t.map(l=>l.sessionId),seqs:t.map(l=>l.seq)}}}function U9(e,t){return e>=6||t>=3?"high":e>=3?"medium":"low"}function j9(e,t,n){let r=e.length>80?e.slice(0,77)+"...":e,o=r.length>0?`: "${r}"`:"";return`SubagentStart hook blocked ${t}\xD7 across ${n} session${n===1?"":"s"}${o}`}function H9(e){let t=[`seq ${e.seq}`];return e.reason&&t.push(`reason="${e.reason.slice(0,200)}"`),e.blockedTool&&t.push(`blockedTool=${e.blockedTool}`),typeof e.injectedContextBytes=="number"&&t.push(`injectedContextBytes=${e.injectedContextBytes}`),t.join(" \xB7 ")}function W9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}var K9=new Set(["policy-refusal","permission-denied","hook-block","abort","elicitation-declined"]),Wo=3,Ko=.25,G9=8;function _O(e,t={}){let n=t.minFailures??Wo,r=t.minFailureRate??Ko;if(n<1)throw new Error(`minFailures must be >= 1 (got ${n})`);if(r<=0||r>1)throw new Error(`minFailureRate must be in (0, 1] (got ${r})`);let o=new Map;for(let i of e)for(let a of i.events){let l=a.event;if(l.kind!=="tool_call"||l.payload.phase!=="completed"||l.payload.circuitBreaker===!0)continue;let c=z9(o,l.payload.name),u=l.payload.failureClass;if(u!==void 0&&K9.has(u)){c.excludedByClass.set(u,(c.excludedByClass.get(u)??0)+1);continue}c.totalCalls+=1,l.payload.isError&&(c.failures.push({sessionId:i.sessionId,relativeTracePath:i.relativeTracePath,seq:l.seq,rawLine:a.rawLine,resultBytes:l.payload.resultBytes,durationMs:l.payload.durationMs,truncated:l.payload.truncated,...u!==void 0?{failureClass:u}:{}}),c.affectedSessions.add(i.sessionId),l.payload.truncated&&(c.truncatedFailureCount+=1))}let s=[];for(let i of o.values()){if(i.failures.length<n)continue;let a=i.failures.length/i.totalCalls;a<r||s.push(q9(i,a))}return s.sort((i,a)=>i.slug.localeCompare(a.slug)),s}function z9(e,t){let n=e.get(t);return n||(n={toolName:t,totalCalls:0,failures:[],affectedSessions:new Set,truncatedFailureCount:0,excludedByClass:new Map},e.set(t,n)),n}function q9(e,t){let n=Y9(e.toolName),r=new Date().toISOString(),s=e.failures.slice(0,G9).map(u=>({sessionId:u.sessionId,tracePath:u.relativeTracePath,eventIndices:[u.seq],excerpt:X9(u.rawLine),annotation:`isError=true${u.failureClass?` \xB7 class=${u.failureClass}`:""} \xB7 resultBytes=${u.resultBytes} \xB7 durationMs=${u.durationMs}${u.truncated?" \xB7 truncated":""}`})),a=e.failures.reduce((u,d)=>u+d.durationMs,0)/e.failures.length,l={};for(let u of e.failures){let d=u.failureClass??"unclassified";l[d]=(l[d]??0)+1}let c={};for(let[u,d]of e.excludedByClass)c[u]=d;return{slug:n,title:V9(e.toolName,e.failures.length,e.totalCalls,t),pattern:"tool-failure-density",severity:J9(e.failures.length,t),observedAt:r,evidence:s,detail:{detector:"tool-failure-density@v2",toolName:e.toolName,totalCalls:e.totalCalls,failureCount:e.failures.length,failureRate:Z9(t),affectedSessionCount:e.affectedSessions.size,truncatedFailureCount:e.truncatedFailureCount,avgFailureDurationMs:Q9(a),failureClassBreakdown:l,excludedByClass:c,sessionIds:Array.from(e.affectedSessions),seqs:e.failures.map(u=>u.seq)}}}function J9(e,t){return t>=1||t>=.5?"high":t>=.25?e>=10?"high":"medium":e>=10?"medium":"low"}function V9(e,t,n,r){let o=(r*100).toFixed(1);return`'${e}' tool failed ${t}/${n} calls (${o}%)`}function Y9(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`tool-failure-${t.length>0?t:"unknown"}`}function X9(e){return e.length<=2e3?e:e.slice(0,1997)+"..."}function Z9(e){return Math.round(e*1e4)/1e4}function Q9(e){return Math.round(e*100)/100}var Pp=Object.freeze([{name:"repeated-tool-use",description:`Tool fired \u2265N consecutive times with identical fingerprint (default ${jo})`,run:(e,t)=>EO(e,{minRepeats:t.minRepeats??jo})},{name:"closure-anomaly",description:`Session closure reason \u2208 {budget_exceeded,timeout,hook_blocked,abort,iteration_cap,max_turns_exceeded} (default \u2265${1})`,enabledByDefault:!1,run:(e,t)=>RO(e,{minOccurrences:t.closureAnomalyMinOccurrences??1})},{name:"subagent-block",description:`Same SubagentStart hook block reason recurring across \u2265N events (default ${Ho})`,enabledByDefault:!1,run:(e,t)=>CO(e,{minOccurrences:t.subagentBlockMinOccurrences??Ho})},{name:"tool-failure-density",description:`Tool with \u2265N failures (isError: true) AND failure rate \u2265R (defaults: ${Wo} failures, ${Ko} rate)`,enabledByDefault:!0,run:(e,t)=>_O(e,{minFailures:t.toolFailureMinFailures??Wo,minFailureRate:t.toolFailureMinRate??Ko})}]);function AO(e,t,n,r){let o=[];for(let s of Pp){if(n!==void 0){if(!n.has(s.name))continue}else if(r!==!0&&s.enabledByDefault===!1)continue;let i=s.run(e,t);o.push(...i)}return o}function Mp(){return Pp.map(e=>e.name)}function IO(){return Pp.filter(e=>e.enabledByDefault!==!1).map(e=>e.name)}function Ii(){return Pp.filter(e=>e.enabledByDefault===!1).map(e=>e.name)}import{existsSync as Lp,mkdirSync as BO,readFileSync as y7,readdirSync as b7,renameSync as UO,writeFileSync as yb}from"fs";import{join as w7}from"path";import{z as I}from"zod";var Pi=I.enum(["repeated-tool-use","subagent-block","closure-anomaly","tool-failure-density"]),Op=I.enum(["low","medium","high"]),e7=I.enum(["open","deferred","resolved"]),PO=I.object({sessionId:I.string().min(1),tracePath:I.string().min(1),eventIndices:I.array(I.number().int().nonnegative()).min(1),excerpt:I.string().max(2e3),annotation:I.string().optional()}),$p=I.object({at:I.string().datetime(),text:I.string()}),gl=I.object({schemaVersion:I.literal(1),slug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"slug must be lowercase alphanumeric with hyphens"),title:I.string().min(1).max(200),pattern:Pi,severity:Op,status:e7,firstSeen:I.string().datetime(),lastSeen:I.string().datetime(),occurrenceCount:I.number().int().nonnegative(),evidence:I.array(PO).min(1),detail:I.record(I.string(),I.unknown()),notes:I.array($p).default([])}),bFe=I.object({slug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),title:I.string().min(1).max(200),pattern:Pi,severity:Op,observedAt:I.string().datetime(),evidence:I.array(PO).min(1),detail:I.record(I.string(),I.unknown())}),MO=I.object({timestamp:I.string().datetime(),event:I.enum(["created","updated","merged-noop"]),slug:I.string(),pattern:Pi,occurrenceCount:I.number().int().nonnegative(),evidenceAdded:I.number().int().nonnegative()}),t7=I.enum(["prompt-defect","schema-too-strict","schema-too-loose","tool-output-shape","hook-overreach","retry-policy","timeout-too-low","cost-control","dispatcher-bug","detector-needs-tuning","unknown"]),n7=I.enum(["safe","moderate","high","forbidden"]),r7=I.enum(["low","medium","high"]),o7=I.object({cardSlug:I.string(),eventIndices:I.array(I.number().int().nonnegative()).min(1),annotation:I.string().optional()}),s7=I.object({path:I.string().min(1),rationale:I.string(),riskTier:n7,confidence:r7}),i7=I.object({unitTests:I.array(I.string()),evalCases:I.array(I.string()),smokeChecks:I.array(I.string()),manualChecks:I.array(I.string())}),a7=I.object({forbiddenPaths:I.array(I.string()),requiresExplicitApproval:I.boolean()}),l7=I.enum(["draft","approved","rejected","superseded"]),gb=I.object({schemaVersion:I.literal(1),proposalId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),cardSlug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),title:I.string().min(1).max(200),hypothesis:I.string().min(1),rootCauseClass:t7,evidenceRefs:I.array(o7).min(1),fixSketch:I.string().min(1),likelyFiles:I.array(s7),riskLevel:Op,validationPlan:i7,scopeFreeze:a7,generatedBy:I.enum(["template","llm"]),createdAt:I.string().datetime(),status:l7,notes:I.array($p).default([])}),OO=I.object({timestamp:I.string().datetime(),event:I.enum(["created","triaged","superseded"]),proposalId:I.string(),cardSlug:I.string(),generatedBy:I.enum(["template","llm"]),riskLevel:Op}),c7=I.object({sourceSessionId:I.string().min(1),sourceTracePath:I.string().min(1),fixturePath:I.string().min(1),evidenceRowIndex:I.number().int().nonnegative(),evidenceEventIndices:I.array(I.number().int().nonnegative()).min(1),sliceLineRange:I.object({startLine:I.number().int().positive(),endLine:I.number().int().positive()}),sliceLineCount:I.number().int().positive(),sliceSha256:I.string().regex(/^[0-9a-f]{64}$/,"sliceSha256 must be 64 lowercase hex chars")}),u7=I.object({kind:I.literal("pattern-absent"),patternId:Pi,detectorVersion:I.string().min(1),rationale:I.string().min(1)}),d7=I.object({detectorAtGeneration:I.string().min(1),fingerprintAtGeneration:I.string().nullable(),cardOccurrenceCountAtGeneration:I.number().int().nonnegative(),cardLastSeenAtGeneration:I.string().datetime(),generatedBy:I.literal("replay-fixture")}),p7=I.enum(["draft","approved","rejected","superseded"]),Dp=I.object({schemaVersion:I.literal(1),evalCaseId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"evalCaseId must be lowercase alphanumeric with hyphens"),cardSlug:I.string().regex(/^[a-z0-9][a-z0-9-]*$/),proposalId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/).nullable(),title:I.string().min(1).max(200),createdAt:I.string().datetime(),kind:I.literal("replay"),replay:c7,assertion:u7,provenance:d7,status:p7,notes:I.array($p).default([])}),$O=I.object({timestamp:I.string().datetime(),event:I.enum(["created","triaged","superseded"]),evalCaseId:I.string(),cardSlug:I.string(),proposalId:I.string().nullable(),kind:I.literal("replay")}),m7=I.enum(["pass","fail","skipped"]),f7=I.object({name:I.string().min(1),description:I.string().min(1),status:m7,expected:I.string(),actual:I.string()}),g7=I.enum(["config-value","observed-behavior","source-symbol","fixture"]),h7=I.object({kind:g7,ref:I.string().min(1),detail:I.string()}),DO=I.enum(["pass","fail","unsupported","error"]),hb=I.object({schemaVersion:I.literal(1),evalRunId:I.string().regex(/^[a-z0-9][a-z0-9-]*$/,"evalRunId must be lowercase alphanumeric with hyphens"),evalCaseId:I.string().min(1),cardSlug:I.string().min(1),patternId:Pi,contract:I.string().min(1).nullable(),status:DO,createdAt:I.string().datetime(),durationMs:I.number().int().nonnegative(),checks:I.array(f7),evidence:I.array(h7),runner:I.object({version:I.string().min(1),mode:I.literal("deterministic")}),notes:I.array($p).default([])}),LO=I.object({timestamp:I.string().datetime(),event:I.literal("created"),evalRunId:I.string(),evalCaseId:I.string(),cardSlug:I.string(),patternId:Pi,contract:I.string().nullable(),status:DO}),FO=Object.freeze(["**/auth/**","**/billing/**","**/secrets/**","**/credentials*",".env",".env.*","pnpm-lock.yaml","package-lock.json","yarn.lock",".github/workflows/**","dist/**","build/**","node_modules/**",".git/**","**/.afk/config/**","**/.afk/state/**"]);function jO(e){let t=Bo();Lp(t)||BO(t,{recursive:!0});let n=ml(e.slug),r=Ip(e.slug),o=hl(n),s=S7(o,e),i=o===void 0,a=s.evidence.length-(o?.evidence.length??0),l=i?"created":a>0?"updated":"merged-noop",c=gl.parse(s);return x7(n,c),E7(r,yl(c)),k7({timestamp:T7(),event:l,slug:c.slug,pattern:c.pattern,occurrenceCount:c.occurrenceCount,evidenceAdded:Math.max(0,a)}),{slug:c.slug,event:l,occurrenceCount:c.occurrenceCount,evidenceAdded:Math.max(0,a),jsonPath:n,markdownPath:r}}function hl(e){if(Lp(e))try{let t=y7(e,"utf-8"),n=JSON.parse(t),r=gl.safeParse(n);return r.success?r.data:void 0}catch{return}}function S7(e,t){if(!e)return{schemaVersion:1,slug:t.slug,title:t.title,pattern:t.pattern,severity:t.severity,status:"open",firstSeen:t.observedAt,lastSeen:t.observedAt,occurrenceCount:t.evidence.length,evidence:t.evidence,detail:t.detail,notes:[]};if(e.slug!==t.slug)throw new Error(`card-writer: slug mismatch on merge (existing='${e.slug}', detection='${t.slug}')`);let n=v7(e.evidence,t.evidence),r=R7(e.firstSeen,t.observedAt),o=C7(e.lastSeen,t.observedAt),s=_7(e.severity,t.severity);return{schemaVersion:1,slug:e.slug,title:t.title,pattern:e.pattern,severity:s,status:e.status,firstSeen:r,lastSeen:o,occurrenceCount:n.length,evidence:n,detail:t.detail,notes:e.notes}}function v7(e,t){let n=s=>`${s.sessionId}::${s.eventIndices[0]??"NA"}`,r=new Set(e.map(n)),o=[...e];for(let s of t){let i=n(s);r.has(i)||(r.add(i),o.push(s))}return o}function yl(e){let t=[];t.push(`# ${e.slug} \u2014 \`${e.severity}\` \u2014 \`${e.status}\``),t.push(""),t.push(e.title),t.push(""),t.push(`**Pattern:** \`${e.pattern}\` \xB7 **Occurrences:** ${e.occurrenceCount} \xB7 **First seen:** ${e.firstSeen} \xB7 **Last seen:** ${e.lastSeen}`),t.push(""),t.push("## Evidence"),t.push("");for(let n of e.evidence)t.push(`### Session \`${n.sessionId}\``),t.push(""),t.push(`- Trace: \`${n.tracePath}\``),t.push(`- Event seqs: ${n.eventIndices.join(", ")}`),n.annotation&&t.push(`- Note: ${n.annotation}`),t.push(""),t.push("```jsonl"),t.push(n.excerpt),t.push("```"),t.push("");if(t.push("## Detail"),t.push(""),t.push("```json"),t.push(JSON.stringify(e.detail,null,2)),t.push("```"),t.push(""),t.push("## Triage notes"),t.push(""),e.notes.length>0){for(let n of e.notes)t.push(`- _${n.at}_ \u2014 ${n.text}`);t.push("")}else t.push('_(none \u2014 add one with `afk improve cards triage <slug> --note "\u2026"`)_'),t.push("");return t.join(`
2168
2168
  `)}function k7(e){let t=MO.parse(e),n=mO(),r=Bo();Lp(r)||BO(r,{recursive:!0});try{yb(n,JSON.stringify(t)+`
2169
2169
  `,{flag:"a"})}catch{}}function x7(e,t){let n=`${e}.tmp-${process.pid}-${Date.now()}`;yb(n,JSON.stringify(t,null,2)),UO(n,e)}function E7(e,t){let n=`${e}.tmp-${process.pid}-${Date.now()}`;yb(n,t),UO(n,e)}function T7(){return new Date().toISOString()}function R7(e,t){return e<=t?e:t}function C7(e,t){return e>=t?e:t}var NO={low:0,medium:1,high:2};function _7(e,t){return NO[e]>=NO[t]?e:t}function HO(){let e=Bo();if(!Lp(e))return[];let t=[];for(let n of b7(e)){if(!n.endsWith(".json")||n.startsWith("."))continue;let r=hl(w7(e,n));r&&t.push({slug:r.slug,title:r.title,pattern:r.pattern,severity:r.severity,status:r.status,occurrenceCount:r.occurrenceCount,firstSeen:r.firstSeen,lastSeen:r.lastSeen})}return t.sort((n,r)=>n.lastSeen!==r.lastSeen?n.lastSeen<r.lastSeen?1:-1:n.slug<r.slug?-1:1),t}function Fp(e){return hl(ml(e))}import{existsSync as A7,mkdirSync as I7,renameSync as WO,writeFileSync as KO}from"fs";import{dirname as P7}from"path";var Go=class extends Error{constructor(n,r){super(r);this.code=n;this.name="TriageError"}code};function GO(e,t){let n=ml(e),r=Ip(e),o=hl(n);if(!o)throw new Go("card-not-found",`No failure card found for slug '${e}'`);if(t.note!==void 0&&t.note.trim().length===0)throw new Go("invalid-note","triage note must be non-empty after trim");let s=t.note?.trim(),i=s!==void 0&&s.length>0,a=t.status!==void 0&&t.status!==o.status;if(!i&&!a)throw new Go("no-change","triage requires at least --note or --status to differ from current");let l=(t.now??(()=>new Date))().toISOString(),c=i?[...o.notes,{at:l,text:s}]:o.notes,u=a?t.status:o.status,d={...o,status:u,notes:c},m=gl.parse(d);return M7(n),O7(n,m),$7(r,yl(m)),{slug:e,card:m,noteAdded:i,statusChanged:a?{from:o.status,to:u}:void 0,jsonPath:n,markdownPath:r}}function M7(e){let t=P7(e);A7(t)||I7(t,{recursive:!0})}function O7(e,t){let n=`${e}.tmp-${process.pid}-${Date.now()}`;KO(n,JSON.stringify(t,null,2)),WO(n,e)}function $7(e,t){let n=`${e}.tmp-${process.pid}-${Date.now()}`;KO(n,t),WO(n,e)}var D7={"repeated-tool-use":{rootCauseClass:"dispatcher-bug",hypothesis:e=>{let t=typeof e.detail.toolName=="string"?e.detail.toolName:"<unknown>",n=typeof e.detail.runLength=="number"?e.detail.runLength:"?";return`The '${t}' tool was dispatched ${n} times in a row with an identical input/output byte fingerprint. This is either (a) the model is stuck retrying the same call without responding to its result, (b) the tool's result shape is too uninformative for the model to make progress, or (c) a productive recursion that happens to share byte counts (rare; the fingerprint caveat is documented on the detector).`},fixSketch:e=>["## Candidate fixes (human picks)","",`**Option A \u2014 make the loop visible.** Surface a clear "no-progress" signal to the model when '${typeof e.detail.toolName=="string"?e.detail.toolName:"<the tool>"}' returns the same result N times in a row. Today the dispatcher just executes the call.`,"",`**Option B \u2014 improve the tool's result shape.** If the model can't distinguish "no results" from "same results," its result is information-poor. Inspect the tool's response and verify it carries enough signal for the model to change its query.`,"","**Option C \u2014 confirm productive recursion.** Open the source trace at the seq values listed in the evidence and inspect the model's reasoning between repeats. If each call's args genuinely differ (and the byte-count collision is the issue), no code change is needed; tune the detector instead.","","_Option C first \u2014 the byte-fingerprint detector has a documented collision caveat. Confirm there is a real loop before changing dispatcher behavior._"].join(`
2170
2170
  `),likelyFiles:[{path:"src/agent/providers/anthropic-direct/loop.ts",rationale:"Main tool dispatch loop. If a no-progress detector is added at the dispatch boundary, it lives here.",riskTier:"moderate",confidence:"medium"},{path:"src/agent/tools/",rationale:"Tool implementations. If the result shape is information-poor, the specific tool implementation needs the change.",riskTier:"safe",confidence:"low"},{path:"src/improve/scan/detectors/repeated-tool-use.ts",rationale:"If this turns out to be detector noise rather than a real bug, tune here.",riskTier:"safe",confidence:"medium"}],riskFloor:"medium",validationPlan:{unitTests:["pnpm test -- src/improve/scan/detectors/repeated-tool-use","pnpm test -- src/agent/providers/anthropic-direct"],evalCases:[],smokeChecks:["pnpm lint","afk improve scan --since 7d # after fix lands, this pattern should NOT recur"],manualChecks:["Open the trace at the evidence seqs and confirm the calls are truly identical (not just byte-coincident)."]}},"subagent-block":{rootCauseClass:"hook-overreach",hypothesis:e=>{let t=typeof e.detail.reason=="string"?e.detail.reason:"",n=typeof e.detail.blockCount=="number"?e.detail.blockCount:"?",r=typeof e.detail.distinctSessions=="number"?e.detail.distinctSessions:"?",o=t?` with reason "${t.slice(0,200)}"`:" (no reason field on the block events)";return`A SubagentStart hook returned decision:'block' ${n} times across ${r} session(s)${o}. Recurring blocks suggest either (a) the guard is over-broad and trips on legitimate dispatches, (b) the legitimate use case actually needs a refactor to satisfy the guard, or (c) the user has no signal explaining the block and keeps retrying.`},fixSketch:e=>{let t=typeof e.detail.reason=="string"?e.detail.reason:"<not in payload>";return["## Candidate fixes (human picks)","",`**Identify the hook owner first.** The trace's hook_decision event carries the \`reason\` field ("${t}"). Grep the codebase for that literal string \u2014 that locates the hook handler.`,"","```sh","# Replace the quoted string below with the actual reason text from the evidence.",`grep -rn -- "${t.slice(0,60).replace(/"/g,'\\"')}" src/`,"```","","**Option A \u2014 tighten the guard.** If the block fires on dispatches it should not, narrow the predicate. Confirm by adding a unit test that exercises the false-positive case.","","**Option B \u2014 make the refusal legible.** Instead of `decision: 'block'`, return a hook decision that injects a context message via `injectContext`. The parent session then sees a clear no-op message instead of a silent block.","",'**Option C \u2014 accept the block as correct.** If the guard is doing its job, mark the card resolved via `afk improve cards triage <slug> --status resolved --note "..."`. No code change.'].join(`