agent-afk 3.92.1 → 3.92.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: shadow-verify
3
- description: "Dispatch a parallel adversarial verifier wave after any high-stakes sub-agent investigation (code reviews, audits, findings reports, large refactors). Shadow verifiers independently re-derive 2–3 key claims from scratch and flag disagreements before the user acts. Use when sub-agent output will drive decisions, file changes, commits, or external side-effects."
3
+ description: "Dispatch a parallel adversarial verifier wave after any high-stakes sub-agent investigation (code reviews, audits, findings reports, large refactors) — or whenever a sub-agent asserts a claim with high-confidence language (confident, certain, clearly, ≥80%), since confidence is a trigger, not a verdict. Shadow verifiers independently re-derive 2–3 key claims from scratch using tool calls only, returning CONFIRMED/REFUTED/UNVERIFIABLE, and flag disagreements before the user acts. Use when sub-agent output will drive decisions, file changes, commits, or external side-effects."
4
4
  context: fork
5
5
  ---
6
6
 
@@ -12,14 +12,17 @@ When a sub-agent (or wave) returns investigation findings, code-review conclusio
12
12
  **Wave 2 — Adversarial verifiers (parallel, independent):**
13
13
  1. Extract 2–3 concrete, re-checkable claims from the returned report (e.g., "X function is unused", "file Y exceeds 300 lines", "PR targets main", "no tests cover Z").
14
14
  2. Dispatch one shadow sub-agent per claim, in parallel. Each receives ONLY the claim + the user's original goal — never the original agent's reasoning or cited evidence. **Default to `subagent_type: "research-agent"` (mechanically locked to Read/Grep/Glob/WebFetch/WebSearch — cannot Edit/commit/push).** If the claim requires Bash to verify (running a failing test, `gh pr view`, `git log origin/...`), fall back to a Bash-capable subagent type with `isolation: "worktree"` and prepend this prefix to the prompt: *"Verifier sub-agent — do not Edit, Write, commit, push, `gh pr create`, or `curl`. Return findings only."*
15
- 3. Each verifier re-derives the verdict independently. Returns `{claim, verifier_verdict, evidence_pointer}`.
15
+ 3. Each verifier re-derives the verdict independently using tool calls only — never re-reading the original report's reasoning. Returns `{claim, verifier_verdict, evidence_pointer}`, where `verifier_verdict` is one of `CONFIRMED`, `REFUTED`, or `UNVERIFIABLE`. On `REFUTED`, the verifier also emits a corrected finding.
16
16
 
17
17
  **Merge:**
18
- - All verifiers confirm → surface the original report as validated.
19
- - Any verifier disagrees show the original claim alongside the verifier's counter-claim with evidence. Do not act until the conflict is resolved.
18
+ - `CONFIRMED` → surface the claim as validated.
19
+ - `REFUTED`replace the claim with the verifier's corrected finding, annotated `[was: confident, now: refuted]`, and show it alongside the original with evidence. Do not act until the conflict is resolved.
20
+ - `UNVERIFIABLE` → surface with a `[needs-human-review]` tag rather than passing it through silently.
21
+
22
+ Bound the loop: at most 3 verification rounds per session. Claims still unresolved after 3 rounds are escalated to the user, never silently dropped.
20
23
 
21
24
  **When to invoke:**
22
- Any time sub-agent output will drive user decisions, file edits, commits, external side-effects, or is the basis of a user-facing summary.
25
+ Any time sub-agent output will drive user decisions, file edits, commits, external side-effects, or is the basis of a user-facing summary. Treat **high-confidence language as a trigger in its own right**: when a review/audit sub-agent asserts a claim with markers like "confident", "certain", "clearly", "obviously", "must be", or a stated probability ≥ 80%, verify it as if it were decision-driving regardless of stakes. Confidence is a trigger, not a verdict.
23
26
 
24
27
  **Skip when:**
25
28
  Sub-agent ran inside an orchestrator skill that already verifies (`resolve`, `diagnose`, `appmap`); sub-agent returned explicit failure; work was purely exploratory and no decision follows; or the session is **text-terminal** — a pure explanation, architecture walkthrough, onboarding Q&A, or capability map that names no mutated artifact (file/PR/commit/test), where there are no re-checkable state claims for adversarial verifiers to re-derive (assess coverage, coherence, and citation density instead of dispatching re-derivation sub-agents).
package/dist/cli.mjs CHANGED
@@ -1054,7 +1054,7 @@ ${o}`;return s.includes("already checked out")||s.includes("is already used by w
1054
1054
  Effective base URL: ${r}`)),r}return t}function sL(){if(zp!==void 0)return zp;if(!uw){let o=[Cl(process.cwd(),".env"),ut(),cy()];for(let s of o)qp(s)&&rL({path:s,override:!1});uw=!0}let e={},t=T.AFK_MODEL??T.CLAUDE_MODEL;if(t){let o=t.toLowerCase();e.model=pp(o)?o:t}if(se(t)==="anthropic-direct"){let o=Jp();o!==void 0&&(e.apiKey=o)}let r=T.AFK_LOCAL_BASE_URL;if(r&&r.length>0&&(e.baseUrl=r,e.apiKey=T.AFK_LOCAL_API_KEY||"local"),T.AFK_MAX_TOKENS&&(e.maxTokens=parseInt(T.AFK_MAX_TOKENS,10)),T.AFK_TEMPERATURE&&(e.temperature=parseFloat(T.AFK_TEMPERATURE)),T.AFK_SYSTEM_PROMPT&&(e.systemPrompt=T.AFK_SYSTEM_PROMPT),T.AFK_AUTO_ROUTING){let o=T.AFK_AUTO_ROUTING.toLowerCase()==="true";e.autoRouting={interactive:o,chat:o,telegram:o,daemon:o}}return T.AFK_OPENAI_BASE_URL&&(e.openaiBaseUrl=oL(T.AFK_OPENAI_BASE_URL)),zp=e,e}function mw(){if(Wo!==void 0)return Wo;let e=[Cl(process.cwd(),"afk.config.json"),Ro(),uy()];for(let t of e)if(qp(t))try{let n=pw(t,"utf-8"),r=JSON.parse(n),o={},s=zy(r.models);if(typeof r.model=="string"&&r.model.length>0){let i=r.model.toLowerCase();o.model=pp(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),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=Kp(r.interactive.worktreeBranchPrefix,`${t}#/interactive/worktreeBranchPrefix`)),typeof r.interactive.worktreeBase=="string"&&r.interactive.worktreeBase.trim().length>0&&(Gp(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 Wo={config:o,sourcePath:t,modelsPartial:s},Wo}catch(n){console.error(`Warning: Failed to parse ${t}:`,n)}return Wo={config:{},sourcePath:void 0,modelsPartial:{}},Wo}function iL(){if(Ko!==void 0)return Ko.value;let e=[Cl(process.cwd(),"AFK.md"),Cl(Me(),"AFK.md")];for(let t of e)if(qp(t))try{let n=pw(t,"utf-8").trim();if(n.length>0)return Ko={value:{content:n,path:t}},Ko.value}catch{}return Ko={value:null},Ko.value}function fw(){return mw().config.telegram??{}}function ct(e){let t=sL(),{config:n,sourcePath:r,modelsPartial:o}=mw(),s={...bi,...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=iL();c!==null&&(s.systemPrompt=c.content,i=`afk-md:${c.path}`)}let a={model:s.model??bi.model,maxTokens:s.maxTokens??bi.maxTokens,temperature:s.temperature??bi.temperature,updatePolicy:s.updatePolicy??bi.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}:{}},l=e?.models??cp(o);if(rl(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 bi,uw,zp,dw,Wo,Ko,Rn=A(()=>{"use strict";Jn();qn();Je();W();Ho();yi();K();bi={model:"sonnet",maxTokens:4096,temperature:1,updatePolicy:"notify"},uw=!1;dw=new Set});function aL(e,t){return t!==void 0&&Number.isFinite(t)&&t!==0?t:e.find(r=>r>0)??e[0]}function lL(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=aL(n,t.primaryChatId);return o!==void 0?[o]:[]}function cL(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 uL(e){if(!e)return;let t=e.trim().toLowerCase();return t==="primary"||t==="broadcast"||t==="custom"?t:void 0}function dL(){let e=fw().notify??{},t=e.mode??uL(T.AFK_TELEGRAM_NOTIFY_MODE),n=e.primaryChatId??cL(T.AFK_TELEGRAM_PRIMARY_CHAT_ID);return{...t!==void 0?{mode:t}:{},...n!==void 0?{primaryChatId:n}:{},...e.targets!==void 0?{targets:e.targets}:{}}}function Il(){let e=Xb(T.AFK_TELEGRAM_ALLOWED_CHAT_IDS);return lL(e,dL())}var Yp=A(()=>{"use strict";Zb();Rn();K()});function gw(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(`
1055
1055
  `,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 hw=A(()=>{"use strict"});var Vp={};Ba(Vp,{push:()=>Pl,pushIfConfigured:()=>Go});async function Pl(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??pL}/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 Go(e,t={}){let n=T.TELEGRAM_BOT_TOKEN;if(!n)return null;let r=Il();if(r.length===0)return null;let o=gw(e),s=[];for(let i of r)for(let a=0;a<o.length;a++)s.push(await Pl({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 pL,zo=A(()=>{"use strict";Yp();hw();K();pL="https://api.telegram.org"});function mL(e=Pl){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>yw)return{content:`Invalid input: message exceeds Telegram's ${yw}-character limit (got ${o.length}). Split into multiple sends or trim before calling.`,isError:!0};let s=T.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=Il();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 yw,bw,ww=A(()=>{"use strict";K();zo();Yp();yw=4096;bw=mL()});import{JSDOM as fL}from"jsdom";import{Readability as gL}from"@mozilla/readability";import hL from"turndown";function Sw(e){return e.replace(/\n{3,}/g,`
1056
1056
 
1057
- `).trim()}function yL(e){return(e?.textContent??"").replace(/\s+/g," ").trim().length}function vw(e,t){let r=new fL(e,{url:t}).window.document,o=(r.title??"").trim(),s=null;try{let c=r.cloneNode(!0);s=new gL(c).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let c=Sw(Xp.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=Sw(Xp.turndown(a));return{title:o,markdown:l,textLength:yL(i),usedFallback:!0}}var kw,Xp,Tw=A(()=>{"use strict";kw=200,Xp=new hL({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});Xp.remove(["script","style","noscript","iframe"])});import{readFileSync as bL}from"node:fs";import{join as wL}from"path";function SL(e){let n=e.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Ew(e,t){return SL(t).test(e)}function TL(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(kL.has(t))return!0;if(vL.has(t))return!1}return!1}function xw(e){return e===void 0||e.trim()===""?[]:e.split(",").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0)}function EL(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 xL(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t==="1"||t==="true"||t==="yes"}function RL(e){try{return bL(e,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}}function _L(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 Rw(e){let t=e?.env??T,n=e?.readFileSync??RL,r=e?.surface??t.AGENT_SURFACE,o=TL(t.AFK_BROWSER_HEADLESS,r),s=xw(t.AFK_BROWSER_ALLOWED_DOMAINS),i=xw(t.AFK_BROWSER_BLOCKED_DOMAINS),a=xL(t.AFK_BROWSER_DOM_SNAPSHOTS),l=EL(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():wL(Wt(),"browser.json"),p=n(d);if(p===void 0)return c;let f;try{f=JSON.parse(p)}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=_L(c,f);return g.configPath=d,g}function Zp(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(Ew(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return t.allowedDomains.length>0&&!t.allowedDomains.some(o=>Ew(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var kL,vL,Qp=A(()=>{"use strict";K();W();kL=new Set(["daemon","subagent","telegram"]),vL=new Set(["repl","interactive","cli"])});import AL from"node:fs";import CL from"node:path";import{chromium as IL}from"playwright";function PL(){try{return"3.92.1"}catch{}try{let e=CL.resolve(import.meta.dirname,"../../../package.json"),t=AL.readFileSync(e,"utf8"),n=JSON.parse(t);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var ML,Ml,_w=A(()=>{"use strict";ML=PL(),Ml=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=IL.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/${ML}`}}}});import{createHash as OL}from"crypto";function em(e){if(e.length===0)return e;let t=e;for(let{regex:n,name:r}of $L)r==="form-password"?t=t.replace(n,"password=[redacted]"):t=t.replace(n,"[redacted]");return t}function Aw(e){return!!(e.role==="textbox"&&e.kind==="password"||e.label&&DL.test(e.label))}function Cw(e){return OL("sha256").update(e,"utf8").digest("hex").slice(0,8)}function Iw(e){let t=e.replace(/\s+/g," ").trim();return t.length<=80?t:t.slice(0,77)+"..."}var $L,DL,wi=A(()=>{"use strict";$L=[{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}];DL=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as LL}from"node:crypto";function FL(e){return e?e.replace(/\s+/g," ").trim().slice(0,200):""}function NL(e,t,n){return`el_${LL("sha256").update(`${e}:${t}:${n}`).digest("hex").slice(0,6)}`}function BL(e){let t=e.replace(/\s+/g," ").trim(),n=4e3;return t.length<=n?t:t.slice(0,n)+"\u2026[truncated]"}function Pw(e){return e.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Ow(e,t){let n=e.role??"",r=e.name??"";Mw.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&t.push(e);for(let s of e.children??[])Ow(s,t)}async function UL(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},$w).catch(()=>[])}async function jL(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,p=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:c,name:l,disabled:p};d!==void 0&&(g.value=d),f!==void 0&&(g.checked=f),o.push(g)}return o},$w).catch(()=>[])}function HL(e){let n=e.accessibility;return n!==null&&typeof n=="object"?n:null}async function Ol(e,t){let n=t.maxElements??80,r=t.includeHidden??!1,o=[],s=HL(e),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=UL(e),l=e.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(e.url()),u=e.title().catch(()=>""),[d,p,f,g,h]=await Promise.all([i,a,l,c,u]),b,y=!1;d!==null?(b=[],Ow(d,b)):(o.push("observation skipped accessibility tree (returned null)"),y=!0,b=(await jL(e)).filter(M=>Mw.has(M.role??"")));let w=new Map;for(let I of p){let M=Pw(I.name),F=w.get(M);(!F||F.bbox.w===0&&I.bbox.w>0)&&w.set(M,I)}let S=b.map(I=>({ax:I,dom:w.get(Pw(I.name??""))})),E=r?S:S.filter(I=>I.dom?I.dom.bbox.w>0||I.dom.bbox.h>0:!0);E.sort((I,M)=>{let F=I.dom?.bbox.y??0,H=M.dom?.bbox.y??0;if(F!==H)return F-H;let B=I.dom?.bbox.x??0,z=M.dom?.bbox.x??0;return B-z}),E.length>200&&o.push("page has 200+ interactive elements; consider scoping");let x=E.slice(0,n).map((I,M)=>{let F=I.ax.role??"generic",H=I.ax.name??"",B=NL(F,H,M),z=I.dom?.bbox??{x:0,y:0,w:0,h:0},L=I.dom?.type??null,$=null;I.ax.value!==void 0&&I.ax.value!==null&&($=String(I.ax.value)),I.ax.checked!==void 0&&($=String(I.ax.checked)),Aw({role:F,kind:L})&&($="[redacted]");let O={disabled:I.ax.disabled??!1};I.ax.checked!==void 0&&(O.checked=I.ax.checked===!0||I.ax.checked==="mixed"),I.ax.selected!==void 0&&(O.selected=I.ax.selected),I.ax.expanded!==void 0&&(O.expanded=I.ax.expanded);let C;I.dom?.testId?C=`[data-testid="${I.dom.testId}"]`:I.dom?.id&&(C=`#${I.dom.id}`);let V={id:B,role:F,label:FL(H),kind:L,value:$,state:O,bbox:z};return C!==void 0&&(V.selector=C),V}),R="idle";try{let I=await e.evaluate(()=>document.readyState);I==="loading"?R="loading":I==="interactive"?R="navigating":R="idle"}catch{R="navigating"}R!=="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 _=BL(f),P=`obs_${t.observationCounter.toString(36)}`,N=new Date().toISOString();return{observationId:P,url:g,title:h,textSummary:_,interactive:x,status:{httpStatus:t.httpStatus??null,loadingState:R,hasDialog:t.hasDialog??!1,consoleErrors:t.consoleErrors??0},warnings:o,screenshotPath:t.screenshotPath??null,capturedAt:N}}var Mw,$w,Dw=A(()=>{"use strict";wi();Mw=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);$w="a[href], button, input, select, textarea, [role], [tabindex], label"});async function Lw(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 tm(e,t){let n=Math.min(t,5);return(await Promise.all(Array.from({length:n},(o,s)=>Lw(e,s)))).filter(o=>o!==null)}async function WL(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 nm(e,t,n){switch(t.kind){case"element_id":return KL(e,t,n);case"selector":return GL(e,t);case"semantic":return zL(e,t)}}async function KL(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 tm(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function GL(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 tm(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${t.selector}]`},candidates:o}}async function zL(e,t){return t.role!==void 0?qL(e,t.text,t.role):JL(e,t.text,t)}async function qL(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 tm(r,o);return{outcome:"ambiguous_target",query:{text:t,role:n},candidates:s}}async function JL(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 WL(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 p=d.slice(0,5),f=[];for(let h=0;h<p.length;h++){let b=p[h];if(b===void 0)continue;let y=await Lw(b.locator,b.index);if(y!==null){let w=`${y.role}:${y.label}:${h}`,S=0;for(let E=0;E<w.length;E++)S=S*31+w.charCodeAt(E)>>>0;f.push({...y,id:`el_${S.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:t},candidates:f}}var Fw=A(()=>{"use strict"});import{randomBytes as YL}from"crypto";import{mkdir as VL,stat as XL,writeFile as ZL}from"fs/promises";import{join as rm}from"path";import{gzip as QL}from"zlib";import{promisify as eF}from"util";function tF(e){return rm(Eo(e),"browser")}function nF(e){return rm(tF(e),"screenshots")}function rF(){return new Date().toISOString().replace(/[:.]/g,"-")}function oF(){return YL(3).toString("hex")}async function om(e,t,n){if(t.length>Nw)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Nw} byte cap (received ${t.length} bytes). Refusing to write oversized screenshot.`);let r=nF(e);await VL(r,{recursive:!0});let o=`${rF()}-${oF()}-${n}.png`,s=rm(r,o);await ZL(s,t);let{size:i}=await XL(s);return{path:s,bytes:i}}var KQ,Nw,Bw=A(()=>{"use strict";W();wi();KQ=eF(QL);Nw=5*1024*1024});var jw={};Ba(jw,{PlaywrightProvider:()=>sm});function Uw(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 sm,Hw=A(()=>{"use strict";_w();Dw();Fw();Qp();wi();Bw();sm=class{name="playwright";config;launcher;sessions=new Map;constructor(t){this.config=t,this.launcher=new Ml(t)}async open(t){let n=Zp(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 Ol(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 Ol(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 nm(r,t.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${Uw(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=em(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=Zp(d,this.config);if(!h.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:d,reason:h.reason}}let p=null;(t.screenshot===!0||c!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Ol(r,{observationCounter:o.observationCounter,screenshotPath:p,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 nm(r,t.target,o.knownElements);if(u.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${Uw(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 om(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}}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 om(n,o,r);return s}catch{return null}}}});var Fr={};Ba(Fr,{__resetBrowserRegistryForTests:()=>cF,browserProviderActive:()=>aF,closeBrowserProvider:()=>im,getBrowserProvider:()=>iF,peekBrowserProvider:()=>lF});function Ww(){Promise.resolve(im()).then(()=>{process.exit(130)})}function Kw(){Promise.resolve(im()).then(()=>{process.exit(143)})}function Gw(){Jt=null}function sF(){$l||(process.on("SIGINT",Ww),process.on("SIGTERM",Kw),process.on("exit",Gw),$l=!0)}function zw(){$l&&(process.removeListener("SIGINT",Ww),process.removeListener("SIGTERM",Kw),process.removeListener("exit",Gw),$l=!1)}async function iF(e){return Jt!==null?Jt:(Lr!==null||(Lr=(async()=>{let{PlaywrightProvider:t}=await Promise.resolve().then(()=>(Hw(),jw)),n=Rw(e),r=new t(n);return sF(),Jt=r,Lr=null,r})()),Lr)}async function im(){if(Jt===null)return;let e=Jt;Jt=null,Lr=null,zw(),await e.shutdown()}function aF(){return Jt!==null}function lF(){return Jt}function cF(){Jt=null,Lr=null,zw()}var Jt,Lr,$l,Nr=A(()=>{"use strict";Qp();Jt=null,Lr=null,$l=!1});function qw(e,t){try{return vw(e,t)}catch{return{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function fF(e,t){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Nr(),Fr));return(await n()).render({url:e,timeoutMs:t.timeoutMs,signal:t.signal})}async function Jw(e,t){let n=t.fetchFn??globalThis.fetch,r=t.renderFn??fF,o=null,s=e,i=null,a=null;try{let c=await n(e,{headers:mF,redirect:"follow",signal:t.signal});i=c.status,s=c.url||e;let u=c.headers.get("content-type")??"";if(c.ok){if(pF.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(dF.test(u)&&!uF.test(u))return{title:"",markdown:d.trim(),finalUrl:s,usedRender:!1};o=qw(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<kw)&&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=qw(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"}`,p=new Error(`web_scrape could not retrieve ${e}: fetch failed (${d}) and render failed (${u}).`);throw p.cause=c,p}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${e} (HTTP ${i??"error"}).`)}var uF,dF,pF,mF,Yw=A(()=>{"use strict";Tw();uF=/(text\/html|application\/xhtml\+xml)/i,dF=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,pF=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,mF={"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 Vw(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\s+/g," ").trim()}function yF(e){let t=e.fetchFn??globalThis.fetch;return{name:"brave",async search(n,{limit:r,signal:o}){let s=new URL(gF);s.searchParams.set("q",n),s.searchParams.set("count",String(Math.min(Math.max(r,1),hF)));let i=await t(s.toString(),{method:"GET",headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":e.apiKey,"User-Agent":"agent-afk/web_scrape"},signal:o});if(!i.ok){let c="";try{let d=await i.text(),p=kl(d);p&&(c=`: ${p.length>200?p.slice(0,200)+"\u2026":p}`)}catch{}let u=i.statusText?` ${i.statusText}`:"";throw new Error(`Brave Search HTTP ${i.status}${u}${c}`)}let a;try{a=await i.json()}catch(c){throw new Error(`Brave Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(a.web?.results??[]).slice(0,r).map(c=>({title:Vw(c.title??"")||"(untitled)",url:c.url??"",description:Vw(c.description??"")})).filter(c=>c.url.length>0)}}}function Xw(e){return e.braveApiKey!==void 0&&e.braveApiKey.trim()!==""?yF({apiKey:e.braveApiKey,fetchFn:e.fetchFn}):{error:'web_scrape search mode requires a search backend. Set BRAVE_SEARCH_API_KEY (free tier at https://brave.com/search/api/) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function Zw(e,t){if(t.length===0)return`# Search results for "${e}"
1057
+ `).trim()}function yL(e){return(e?.textContent??"").replace(/\s+/g," ").trim().length}function vw(e,t){let r=new fL(e,{url:t}).window.document,o=(r.title??"").trim(),s=null;try{let c=r.cloneNode(!0);s=new gL(c).parse()}catch{s=null}if(s&&typeof s.content=="string"&&s.content.trim().length>0){let c=Sw(Xp.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=Sw(Xp.turndown(a));return{title:o,markdown:l,textLength:yL(i),usedFallback:!0}}var kw,Xp,Tw=A(()=>{"use strict";kw=200,Xp=new hL({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});Xp.remove(["script","style","noscript","iframe"])});import{readFileSync as bL}from"node:fs";import{join as wL}from"path";function SL(e){let n=e.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Ew(e,t){return SL(t).test(e)}function TL(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(kL.has(t))return!0;if(vL.has(t))return!1}return!1}function xw(e){return e===void 0||e.trim()===""?[]:e.split(",").map(t=>t.trim().toLowerCase()).filter(t=>t.length>0)}function EL(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 xL(e){if(e===void 0)return!1;let t=e.trim().toLowerCase();return t==="1"||t==="true"||t==="yes"}function RL(e){try{return bL(e,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}}function _L(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 Rw(e){let t=e?.env??T,n=e?.readFileSync??RL,r=e?.surface??t.AGENT_SURFACE,o=TL(t.AFK_BROWSER_HEADLESS,r),s=xw(t.AFK_BROWSER_ALLOWED_DOMAINS),i=xw(t.AFK_BROWSER_BLOCKED_DOMAINS),a=xL(t.AFK_BROWSER_DOM_SNAPSHOTS),l=EL(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():wL(Wt(),"browser.json"),p=n(d);if(p===void 0)return c;let f;try{f=JSON.parse(p)}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=_L(c,f);return g.configPath=d,g}function Zp(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(Ew(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return t.allowedDomains.length>0&&!t.allowedDomains.some(o=>Ew(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var kL,vL,Qp=A(()=>{"use strict";K();W();kL=new Set(["daemon","subagent","telegram"]),vL=new Set(["repl","interactive","cli"])});import AL from"node:fs";import CL from"node:path";import{chromium as IL}from"playwright";function PL(){try{return"3.92.2"}catch{}try{let e=CL.resolve(import.meta.dirname,"../../../package.json"),t=AL.readFileSync(e,"utf8"),n=JSON.parse(t);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var ML,Ml,_w=A(()=>{"use strict";ML=PL(),Ml=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=IL.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/${ML}`}}}});import{createHash as OL}from"crypto";function em(e){if(e.length===0)return e;let t=e;for(let{regex:n,name:r}of $L)r==="form-password"?t=t.replace(n,"password=[redacted]"):t=t.replace(n,"[redacted]");return t}function Aw(e){return!!(e.role==="textbox"&&e.kind==="password"||e.label&&DL.test(e.label))}function Cw(e){return OL("sha256").update(e,"utf8").digest("hex").slice(0,8)}function Iw(e){let t=e.replace(/\s+/g," ").trim();return t.length<=80?t:t.slice(0,77)+"..."}var $L,DL,wi=A(()=>{"use strict";$L=[{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}];DL=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as LL}from"node:crypto";function FL(e){return e?e.replace(/\s+/g," ").trim().slice(0,200):""}function NL(e,t,n){return`el_${LL("sha256").update(`${e}:${t}:${n}`).digest("hex").slice(0,6)}`}function BL(e){let t=e.replace(/\s+/g," ").trim(),n=4e3;return t.length<=n?t:t.slice(0,n)+"\u2026[truncated]"}function Pw(e){return e.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Ow(e,t){let n=e.role??"",r=e.name??"";Mw.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&t.push(e);for(let s of e.children??[])Ow(s,t)}async function UL(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},$w).catch(()=>[])}async function jL(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,p=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:c,name:l,disabled:p};d!==void 0&&(g.value=d),f!==void 0&&(g.checked=f),o.push(g)}return o},$w).catch(()=>[])}function HL(e){let n=e.accessibility;return n!==null&&typeof n=="object"?n:null}async function Ol(e,t){let n=t.maxElements??80,r=t.includeHidden??!1,o=[],s=HL(e),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=UL(e),l=e.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(e.url()),u=e.title().catch(()=>""),[d,p,f,g,h]=await Promise.all([i,a,l,c,u]),b,y=!1;d!==null?(b=[],Ow(d,b)):(o.push("observation skipped accessibility tree (returned null)"),y=!0,b=(await jL(e)).filter(M=>Mw.has(M.role??"")));let w=new Map;for(let I of p){let M=Pw(I.name),F=w.get(M);(!F||F.bbox.w===0&&I.bbox.w>0)&&w.set(M,I)}let S=b.map(I=>({ax:I,dom:w.get(Pw(I.name??""))})),E=r?S:S.filter(I=>I.dom?I.dom.bbox.w>0||I.dom.bbox.h>0:!0);E.sort((I,M)=>{let F=I.dom?.bbox.y??0,H=M.dom?.bbox.y??0;if(F!==H)return F-H;let B=I.dom?.bbox.x??0,z=M.dom?.bbox.x??0;return B-z}),E.length>200&&o.push("page has 200+ interactive elements; consider scoping");let x=E.slice(0,n).map((I,M)=>{let F=I.ax.role??"generic",H=I.ax.name??"",B=NL(F,H,M),z=I.dom?.bbox??{x:0,y:0,w:0,h:0},L=I.dom?.type??null,$=null;I.ax.value!==void 0&&I.ax.value!==null&&($=String(I.ax.value)),I.ax.checked!==void 0&&($=String(I.ax.checked)),Aw({role:F,kind:L})&&($="[redacted]");let O={disabled:I.ax.disabled??!1};I.ax.checked!==void 0&&(O.checked=I.ax.checked===!0||I.ax.checked==="mixed"),I.ax.selected!==void 0&&(O.selected=I.ax.selected),I.ax.expanded!==void 0&&(O.expanded=I.ax.expanded);let C;I.dom?.testId?C=`[data-testid="${I.dom.testId}"]`:I.dom?.id&&(C=`#${I.dom.id}`);let V={id:B,role:F,label:FL(H),kind:L,value:$,state:O,bbox:z};return C!==void 0&&(V.selector=C),V}),R="idle";try{let I=await e.evaluate(()=>document.readyState);I==="loading"?R="loading":I==="interactive"?R="navigating":R="idle"}catch{R="navigating"}R!=="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 _=BL(f),P=`obs_${t.observationCounter.toString(36)}`,N=new Date().toISOString();return{observationId:P,url:g,title:h,textSummary:_,interactive:x,status:{httpStatus:t.httpStatus??null,loadingState:R,hasDialog:t.hasDialog??!1,consoleErrors:t.consoleErrors??0},warnings:o,screenshotPath:t.screenshotPath??null,capturedAt:N}}var Mw,$w,Dw=A(()=>{"use strict";wi();Mw=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);$w="a[href], button, input, select, textarea, [role], [tabindex], label"});async function Lw(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 tm(e,t){let n=Math.min(t,5);return(await Promise.all(Array.from({length:n},(o,s)=>Lw(e,s)))).filter(o=>o!==null)}async function WL(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 nm(e,t,n){switch(t.kind){case"element_id":return KL(e,t,n);case"selector":return GL(e,t);case"semantic":return zL(e,t)}}async function KL(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 tm(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function GL(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 tm(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${t.selector}]`},candidates:o}}async function zL(e,t){return t.role!==void 0?qL(e,t.text,t.role):JL(e,t.text,t)}async function qL(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 tm(r,o);return{outcome:"ambiguous_target",query:{text:t,role:n},candidates:s}}async function JL(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 WL(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 p=d.slice(0,5),f=[];for(let h=0;h<p.length;h++){let b=p[h];if(b===void 0)continue;let y=await Lw(b.locator,b.index);if(y!==null){let w=`${y.role}:${y.label}:${h}`,S=0;for(let E=0;E<w.length;E++)S=S*31+w.charCodeAt(E)>>>0;f.push({...y,id:`el_${S.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:t},candidates:f}}var Fw=A(()=>{"use strict"});import{randomBytes as YL}from"crypto";import{mkdir as VL,stat as XL,writeFile as ZL}from"fs/promises";import{join as rm}from"path";import{gzip as QL}from"zlib";import{promisify as eF}from"util";function tF(e){return rm(Eo(e),"browser")}function nF(e){return rm(tF(e),"screenshots")}function rF(){return new Date().toISOString().replace(/[:.]/g,"-")}function oF(){return YL(3).toString("hex")}async function om(e,t,n){if(t.length>Nw)throw new Error(`writeScreenshotSidecar: buffer exceeds ${Nw} byte cap (received ${t.length} bytes). Refusing to write oversized screenshot.`);let r=nF(e);await VL(r,{recursive:!0});let o=`${rF()}-${oF()}-${n}.png`,s=rm(r,o);await ZL(s,t);let{size:i}=await XL(s);return{path:s,bytes:i}}var KQ,Nw,Bw=A(()=>{"use strict";W();wi();KQ=eF(QL);Nw=5*1024*1024});var jw={};Ba(jw,{PlaywrightProvider:()=>sm});function Uw(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 sm,Hw=A(()=>{"use strict";_w();Dw();Fw();Qp();wi();Bw();sm=class{name="playwright";config;launcher;sessions=new Map;constructor(t){this.config=t,this.launcher=new Ml(t)}async open(t){let n=Zp(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 Ol(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 Ol(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 nm(r,t.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${Uw(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=em(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=Zp(d,this.config);if(!h.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:d,reason:h.reason}}let p=null;(t.screenshot===!0||c!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Ol(r,{observationCounter:o.observationCounter,screenshotPath:p,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 nm(r,t.target,o.knownElements);if(u.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${Uw(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 om(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}}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 om(n,o,r);return s}catch{return null}}}});var Fr={};Ba(Fr,{__resetBrowserRegistryForTests:()=>cF,browserProviderActive:()=>aF,closeBrowserProvider:()=>im,getBrowserProvider:()=>iF,peekBrowserProvider:()=>lF});function Ww(){Promise.resolve(im()).then(()=>{process.exit(130)})}function Kw(){Promise.resolve(im()).then(()=>{process.exit(143)})}function Gw(){Jt=null}function sF(){$l||(process.on("SIGINT",Ww),process.on("SIGTERM",Kw),process.on("exit",Gw),$l=!0)}function zw(){$l&&(process.removeListener("SIGINT",Ww),process.removeListener("SIGTERM",Kw),process.removeListener("exit",Gw),$l=!1)}async function iF(e){return Jt!==null?Jt:(Lr!==null||(Lr=(async()=>{let{PlaywrightProvider:t}=await Promise.resolve().then(()=>(Hw(),jw)),n=Rw(e),r=new t(n);return sF(),Jt=r,Lr=null,r})()),Lr)}async function im(){if(Jt===null)return;let e=Jt;Jt=null,Lr=null,zw(),await e.shutdown()}function aF(){return Jt!==null}function lF(){return Jt}function cF(){Jt=null,Lr=null,zw()}var Jt,Lr,$l,Nr=A(()=>{"use strict";Qp();Jt=null,Lr=null,$l=!1});function qw(e,t){try{return vw(e,t)}catch{return{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function fF(e,t){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Nr(),Fr));return(await n()).render({url:e,timeoutMs:t.timeoutMs,signal:t.signal})}async function Jw(e,t){let n=t.fetchFn??globalThis.fetch,r=t.renderFn??fF,o=null,s=e,i=null,a=null;try{let c=await n(e,{headers:mF,redirect:"follow",signal:t.signal});i=c.status,s=c.url||e;let u=c.headers.get("content-type")??"";if(c.ok){if(pF.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(dF.test(u)&&!uF.test(u))return{title:"",markdown:d.trim(),finalUrl:s,usedRender:!1};o=qw(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<kw)&&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=qw(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"}`,p=new Error(`web_scrape could not retrieve ${e}: fetch failed (${d}) and render failed (${u}).`);throw p.cause=c,p}}if(o!==null)return{title:o.title,markdown:o.markdown,finalUrl:s,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${e} (HTTP ${i??"error"}).`)}var uF,dF,pF,mF,Yw=A(()=>{"use strict";Tw();uF=/(text\/html|application\/xhtml\+xml)/i,dF=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,pF=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,mF={"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 Vw(e){return e.replace(/<[^>]*>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\s+/g," ").trim()}function yF(e){let t=e.fetchFn??globalThis.fetch;return{name:"brave",async search(n,{limit:r,signal:o}){let s=new URL(gF);s.searchParams.set("q",n),s.searchParams.set("count",String(Math.min(Math.max(r,1),hF)));let i=await t(s.toString(),{method:"GET",headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":e.apiKey,"User-Agent":"agent-afk/web_scrape"},signal:o});if(!i.ok){let c="";try{let d=await i.text(),p=kl(d);p&&(c=`: ${p.length>200?p.slice(0,200)+"\u2026":p}`)}catch{}let u=i.statusText?` ${i.statusText}`:"";throw new Error(`Brave Search HTTP ${i.status}${u}${c}`)}let a;try{a=await i.json()}catch(c){throw new Error(`Brave Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(a.web?.results??[]).slice(0,r).map(c=>({title:Vw(c.title??"")||"(untitled)",url:c.url??"",description:Vw(c.description??"")})).filter(c=>c.url.length>0)}}}function Xw(e){return e.braveApiKey!==void 0&&e.braveApiKey.trim()!==""?yF({apiKey:e.braveApiKey,fetchFn:e.fetchFn}):{error:'web_scrape search mode requires a search backend. Set BRAVE_SEARCH_API_KEY (free tier at https://brave.com/search/api/) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function Zw(e,t){if(t.length===0)return`# Search results for "${e}"
1058
1058
 
1059
1059
  (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(`
1060
1060
  `).trimEnd()}var gF,hF,Qw=A(()=>{"use strict";Uo();gF="https://api.search.brave.com/res/v1/web/search",hF=20});function xF(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=bF;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,wF)}let a=SF;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,kF)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function am(e,t){let n=Buffer.from(e,"utf8");return n.byteLength<=t?e:n.subarray(0,t).toString("utf8")+vF}function RF(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 EF.some(o=>r.includes(o))}function _F(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=xF(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 p;try{p=await d.text()}catch(f){return{content:`web_scrape read error: ${f instanceof Error?f.message:String(f)}`,isError:!0}}return{content:am(p,s.maxBytes)}}if(s.mode==="markdown")try{let d=await Jw(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:am(d.markdown,s.maxBytes)}}catch(d){if(i.signal.aborted)return{content:`web_scrape aborted: ${c()}`,isError:!0};let p=d instanceof Error?d.message:String(d),f=RF(d)?" (the render fallback needs the optional Playwright browser \u2014 run `pnpm exec playwright install chromium`)":"";return{content:`web_scrape markdown error: ${p}${f}`,isError:!0}}let u=Xw({braveApiKey:n.BRAVE_SEARCH_API_KEY,fetchFn:t});if("error"in u)return{content:u.error,isError:!0};try{let d=await u.search(s.query,{limit:TF,timeoutMs:s.timeoutMs,signal:i.signal});return{content:am(Zw(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 bF,wF,SF,kF,vF,TF,EF,eS,tS=A(()=>{"use strict";Yw();Qw();bF=3e4,wF=12e4,SF=1e6,kF=1e7,vF=`
@@ -1831,8 +1831,8 @@ ${t}`}var lA=!1;function cA(){lA||(lA=!0,_g("review",nA),oA())}K();var W2=new Se
1831
1831
  `))e.out.line(" "+" ".repeat(n)+m.dim(l))}}function yA(e,t,n){let r=K2(t,n);if(e.out.line(),r.size===0){e.out.line(m.dim(" No skills available. Built-in skills should always load \u2014 check your install.")),e.out.line();return}let o=Array.from(r.values()),s=o.reduce((g,h)=>g+h.alts.length,0),i=o.filter(g=>g.main.source==="builtin").sort(mA),a=o.filter(g=>g.main.source!=="builtin").sort(mA),l=Math.max(20,Z()),c=o.reduce((g,h)=>Math.max(g,q(h.main.display)),0),u=Math.min(c+2,Math.max(10,Math.floor((l-2)*.45))),d=Math.max(12,l-2-u);e.out.line(m.bold("Skills")+m.dim(` (${o.length})`));let p=new Set(o.map(g=>g.main.source)),f=["builtin","user","project","plugin"].filter(g=>p.has(g)).map(Pg).join(" \xB7 ");if(e.out.line(m.dim(` ${f} \u2014 /skills <name> for details`)),i.length>0){e.out.line(),e.out.line(ge("Built-in"));for(let g of i)fA(e,g,u,d)}if(a.length>0){e.out.line(),e.out.line(i.length>0?ge("Plugins & user skills"):ge());for(let g of a)fA(e,g,u,d)}e.out.line(),e.out.line(m.dim(s>0?" Tip: \u21B3 also lines show alternative (shadowed) forms \xB7 /skills <name> for full details":" Tip: /skills <name> for full details on a skill")),e.out.line()}function G2(e,t){try{let n=$e(e);return Ot(n,t)?n:void 0}catch{return}}function z2(e,t){let n=[];for(let r of yp(t))if(r.includes(":")&&ln(r)===e){let o=Mg($e(r).origin);n.push({slash:`/${r}`,source:o})}for(let r of io.collisions)r.bare===e&&n.push({slash:r.altSlash,source:"plugin"});return n}function bA(e,t,n,r){let o=t.replace(/^\//,"").trim(),s=G2(o,r),i=n.find(y=>ln(y.name)===o||y.name===o);if(!s&&!i){e.out.line(),e.out.line(m.dim(` No skill found matching "${o}".`)),e.out.line(m.dim(" Run /skills to see everything available.")),e.out.line();return}let a=s?.name??ln(i.name),l=s?.description??i.description,c=s?.argumentHint??i?.argumentHint,u=c?`/${a} ${c}`:`/${a}`,d=s?Mg(s.origin):"plugin",p=Math.max(20,Z()),f=Math.max(20,Math.min(p-2,100));e.out.line(),e.out.line(` ${m.warning(u)}`),e.out.line();for(let y of ue(l,f).split(`
1832
1832
  `))e.out.line(` ${y}`);let g=s?.whenToUse??hA(l);if(g&&g!==l.trim()){e.out.line(),e.out.line(` ${m.bold("When to use")}`);for(let y of ue(g,f).split(`
1833
1833
  `))e.out.line(` ${m.dim(y)}`)}let h=s?.flags??gA().get(o);h&&h.length>0&&(e.out.line(),e.out.line(` ${m.bold("Flags")} ${m.dim(h.join(", "))}`)),e.out.line(),e.out.line(` ${m.bold("Source")} ${m.dim(Pg(d))}`);let b=z2(a,r);if(b.length>0){e.out.line(),e.out.line(` ${m.bold("Alternatives")}`);for(let y of b)e.out.line(` ${m.dim("\u21B3")} ${m.warning(y.slash)} ${m.dim(`(${Pg(y.source)} \u2014 shadowed by /${a})`)}`)}e.out.line()}var q2={name:"/skills",aliases:["/builtin-skills"],summary:"List all skills available in this session \u2014 vendored, user, and plugin",usage:"/skills [name]",hint:"When you want to browse every skill the session can dispatch \u2014 pass a name for full details on one.",async handler(e,t){let n=T.AFK_INTERNAL==="1",r=t.trim();return r&&!r.startsWith("-")?bA(e,r,[],n):yA(e,[],n),"continue"}};function J2(e){return{name:"/skills",aliases:["/builtin-skills"],summary:"List all skills available in this session \u2014 vendored, user, and plugin",usage:"/skills [name]",hint:"When you want to browse every skill the session can dispatch \u2014 pass a name for full details on one.",async handler(t,n){let r=T.AFK_INTERNAL==="1",o=n.trim();return o&&!o.startsWith("-")?bA(t,o,e,r):yA(t,e,r),"continue"}}}async function wA(e){let t;try{t=await e.supportedCommands()}catch(l){return console.error(m.dim(" \u26A0 Plugin-skill discovery failed: ")+(l instanceof Error?l.message:String(l))),null}let n=t.map(l=>({name:l.name,description:l.description,...l.argumentHint?{argumentHint:l.argumentHint}:{}})),r=gA(),o=T.AFK_INTERNAL==="1",s=new Set(gn().filter(l=>Ot($e(l),o)).map(ln)),i=[],a=new Set;for(let l of n){let c=`/${l.name}`;if(W2.has(c))continue;let u=ln(l.name),d=r.get(u);if(s.has(u)){let p=l.name.includes(":")?l.name:`plugin:${l.name}`,f={...l,name:p};dr(pA(f,d)),i.push({bare:u,altSlash:`/${p}`,altDescription:l.description}),a.add(u);continue}dr(pA(l,d))}return io={discovered:n,collisions:i,shadowedBareNames:a},dr(J2(n)),n.length}function SA(){return io.collisions.length===0?[]:io.collisions.map(e=>m.dim(` /${e.bare}: vendored or user skill wins; plugin form ${e.altSlash} stays reachable.`))}async function Cu(e){let[t,n]=await Promise.all([wA(e),Tg(e)]);return{skillCount:t,agentCount:n}}function Y2(e){let t={builtin:0,plugin:0,user:0,project:0};for(let r of e)t[r.source]++;return[["builtin","built-in"],["plugin","plugin"],["user","user"],["project","project"]].filter(([r])=>t[r]>0).map(([r,o])=>`${t[r]} ${o}`).join(" \xB7 ")}function V2(e,t){return e.size===0?null:{added:[...t].filter(n=>!e.has(n)).sort(),removed:[...e].filter(n=>!t.has(n)).sort()}}function X2(e){let{added:t,removed:n}=e;if(t.length===0&&n.length===0)return"";let r=[];t.length&&r.push(`+${t.length}`),n.length&&r.push(`\u2212${n.length}`);let o=`${r.join(" ")} since last reload`,s=[];return t.length>0&&t.length<=3&&s.push(`new: ${t.map(i=>`/${i}`).join(", ")}`),n.length>0&&n.length<=3&&s.push(`gone: ${n.map(i=>`/${i}`).join(", ")}`),s.length>0&&(o+=` (${s.join("; ")})`),o}function Z2(e){if(e.length===0)return[];let t=8,n=e.slice(0,t),r=Math.min(24,n.reduce((s,i)=>Math.max(s,i.name.length),0)),o=n.map(s=>m.dim(` ${s.name.padEnd(r)} ${G_(s)}`));return e.length>t&&o.push(m.dim(` \u2026and ${e.length-t} more`)),o}var Q2={name:"/reload-plugins",summary:"Reload plugin skills from disk and refresh the slash registry",async handler(e){e.out.line(),e.out.info("Reloading plugins\u2026");let t=new Set(io.discovered.map(a=>a.name));Cn();try{let a=e.session.current.getQuery();typeof a.reloadPlugins=="function"&&await a.reloadPlugins()}catch(a){e.out.warn(`Plugin reload failed: ${a instanceof Error?a.message:String(a)}`)}let[n,r]=await Promise.all([wA(e.session.current),Tg(e.session.current)]);if(n===null&&r===null)return e.out.error("Could not refresh plugin skills or agents."),e.out.line(),"continue";let o=K_(),s=[];n!==null&&s.push(`${n} skill${n===1?"":"s"}`),r!==null&&s.push(`${r} agent${r===1?"":"s"}`);let i=o.length>0?` from ${o.length} plugin${o.length===1?"":"s"}`:"";if(e.out.success(`Reloaded ${s.join(" + ")}${i}.`),n!==null){let a=Y2(An()),l=V2(t,new Set(io.discovered.map(d=>d.name))),c=l?X2(l):"",u=[a,c].filter(d=>d.length>0);u.length>0&&e.out.line(m.dim(` ${u.join(" \xB7 ")}`))}for(let a of Z2(o))e.out.line(a);return e.out.line(),"continue"}};function kA(){de(q2),de(Q2)}at();Qm();W();K();function ez(e){let t=e??"builtin";switch(t){case"builtin":return"builtin";case"user":return"user";case"project":return"project";default:{let n=t;throw new Error(`[afk builtin-skills] Unhandled origin: ${String(n)}`)}}}function tz(e){let t=`/${e.name}`,n=e.argumentHint?`${t} ${e.argumentHint}`:void 0;return{name:t,summary:e.description,acceptsAttachments:!0,...n!==void 0?{usage:n}:{},...e.whenToUse?{hint:e.whenToUse}:{},...e.flags&&e.flags.length>0?{flags:e.flags}:{},async handler(r,o,s){try{await xu(r,{skillName:e.name,skillMeta:e,args:o,attachments:s,preflight:async()=>{let i={skillName:e.name,rawArgs:o,source:ez(e.origin),capabilities:{compose:!0,subagents:!0}},a=r.session.current.sessionId,l=so(a);return(await oo(i,{cwd:r.stats.cwd??process.cwd(),artifactDir:l},u=>{T.AFK_SKILL_STREAM_VERBOSE==="1"&&r.out.warn(`preflight(${e.name}) failed: ${u instanceof Error?u.message:String(u)}`)}))?.manifestBlock}})}catch(i){r.out.line(),r.out.error(`${e.name} failed: ${i instanceof Error?i.message:String(i)}`)}return"continue"}}}function vA(){cA(),Xm(),Kr(Ha(),"project");let e=T.AFK_INTERNAL==="1";for(let t of gn()){let n=$e(t);Ot(n,e)&&dr(tz(n))}}W();import{existsSync as ma,mkdirSync as Lz,renameSync as Fz,rmSync as Nz,symlinkSync as Bz,lstatSync as Uz,unlinkSync as jz}from"fs";import{basename as Hz,join as Ng}from"path";W();import{existsSync as kr,mkdirSync as yz,readFileSync as bz,realpathSync as _A,renameSync as wz,rmSync as Sz,symlinkSync as kz,lstatSync as vz,unlinkSync as Tz}from"fs";import{basename as AA,dirname as Ez,join as lo,resolve as $g,relative as xz}from"path";import{existsSync as TA}from"fs";import{isAbsolute as nz,resolve as RA}from"path";import{homedir as EA}from"os";var rz=/^(?:https?:\/\/|git:\/\/|ssh:\/\/|git\+ssh:\/\/|file:\/\/|git@[^:]+:)/,oz=/^([a-zA-Z0-9][a-zA-Z0-9_.-]*)\/([a-zA-Z0-9][a-zA-Z0-9._-]*?)(?:\.git)?$/,sz=/^([a-zA-Z0-9][a-zA-Z0-9_.-]*):([a-zA-Z0-9][a-zA-Z0-9_.-]*)$/;function iz(e){return e==="~"?EA():e.startsWith("~/")?RA(EA(),e.slice(2)):e}function Iu(e){if(!e.startsWith("https://"))throw new Error(`Plugin source must use https:// (got: ${e}). git://, http://, ssh://, file://, and git@ are rejected to avoid downgrade attacks and unauthenticated clones.`)}function Bs(e){let t=e.trim();if(!t)throw new Error('plugin source is required (examples: "owner/repo", "https://github.com/owner/repo.git", "./my-plugin")');if(az(t)){let o=xA(t);if(!TA(o))throw new Error(`could not resolve plugin source: "${t}" looks like a local path but does not exist on disk`);return{type:"local",path:o}}if(rz.test(t))return{type:"git",url:t};let n=sz.exec(t);if(n&&n[1]&&n[2])return{type:"marketplace-ref",marketplace:n[1],plugin:n[2]};let r=oz.exec(t);if(r&&r[1]&&r[2]){let o=r[1],s=r[2];return{type:"github",owner:o,repo:s,url:`https://github.com/${o}/${s}.git`}}if(TA(t))return{type:"local",path:xA(t)};throw new Error(`could not resolve plugin source: "${t}". Use a git URL (https://\u2026/repo.git), GitHub shorthand (owner/repo), or a local path to a directory that exists on disk.`)}function az(e){return e.startsWith("./")||e.startsWith("../")||e.startsWith("~")||e.startsWith("/")}function xA(e){let t=iz(e);return nz(t)?t:RA(process.cwd(),t)}import{execFile as lz}from"child_process";import{promisify as cz}from"util";var uz=cz(lz),ao=async(e,t,n)=>{try{let{stdout:r,stderr:o}=await uz("git",Array.from(e),{cwd:t,env:n,maxBuffer:20971520});return{stdout:r,stderr:o}}catch(r){throw dz(r)&&r.code==="ENOENT"?new Error("git not found on PATH \u2014 install git first"):r}};function dz(e){return typeof e=="object"&&e!==null&&"code"in e}var pz=Object.freeze(["-c","core.hooksPath=/dev/null","-c","filter.process=","-c","filter.smudge=","-c","filter.clean="]);function Og(e){return[...pz,...e]}async function Pu(e,t,n={}){await(n.runner??ao)(Og(["clone","--",e,t]),void 0,n.env)}async function Mu(e,t={}){await(t.runner??ao)(Og(["fetch","--tags","--prune"]),e,t.env)}async function br(e,t={}){let n=t.runner??ao,{stdout:r}=await n(["tag","--list","--sort=-v:refname"],e,t.env);return r.split(`
1834
- `).map(o=>o.trim()).filter(Boolean)}async function wr(e,t,n={}){await(n.runner??ao)(Og(["checkout","--detach",t]),e,n.env)}async function cn(e,t={}){let n=t.runner??ao,{stdout:r}=await n(["rev-parse","HEAD"],e,t.env);return r.trim()}async function Ou(e,t,n={}){let r=n.runner??ao;try{let{stdout:o}=await r(["rev-parse","--verify","--quiet",t],e,n.env);return o.trim()||null}catch{return null}}async function un(e,t={}){let n=t.runner??ao;try{let{stdout:r}=await n(["symbolic-ref","refs/remotes/origin/HEAD","--short"],e,t.env);return r.trim().replace(/^origin\//,"")||"main"}catch{return"main"}}ft();var mz=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function fz(e){let t=mz.exec(e);if(!t)return null;let[,n,r,o,s]=t;return{raw:e,major:Number(n),minor:Number(r),patch:Number(o),prerelease:s??null}}function gz(e,t){if(e===null&&t===null)return 0;if(e===null)return 1;if(t===null)return-1;let n=e.split("."),r=t.split("."),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let i=n[s],a=r[s];if(i===void 0)return-1;if(a===void 0)return 1;let l=/^\d+$/.test(i),c=/^\d+$/.test(a);if(l&&c){let u=Number(i)-Number(a);if(u!==0)return u}else{if(l)return-1;if(c)return 1;if(i<a)return-1;if(i>a)return 1}}return 0}function hz(e,t){return e.major!==t.major?e.major-t.major:e.minor!==t.minor?e.minor-t.minor:e.patch!==t.patch?e.patch-t.patch:gz(e.prerelease,t.prerelease)}function Sr(e){let t=e.map(n=>fz(n.trim())).filter(n=>n!==null);return t.length===0?null:(t.sort((n,r)=>hz(r,n)),t[0]?.raw??null)}ir();async function Lu(e,t={},n={}){let r=n.pluginsDir??Fe(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},a=n.confirm??!0,l=n.confirmDelayMs??3e3,c=Bs(e);if(yz(r,{recursive:!0}),c.type==="local")return Rz(c,t,r,o,s);if(c.type==="marketplace-ref")throw new Error(`marketplace-ref source "${c.marketplace}:${c.plugin}" must be installed via the marketplace resolver, not installPlugin directly`);return Iu(c.url),_z(c,t,r,o,s,i,{confirm:a,confirmDelayMs:l})}function Rz(e,t,n,r,o){CA(e.path);let s=IA(e.path),i=t.name??s??AA(e.path);Fn(i);let a=lo(n,i);co(a,n),Dg(a,t.force??!1),(kr(a)||Lg(a))&&Du(a),kz(e.path,a,"dir");let l=o().toISOString(),c={source:e.path,sourceType:"local",ref:null,commit:null,enabled:!0,installedAt:l,updatedAt:l,...s&&s!==i?{manifestName:s}:{}};return sr(i,c,r),Cn(),{name:i,dir:a,entry:c}}async function _z(e,t,n,r,o,s,i){let a=t.name??Cz(e);Fn(a);let l=lo(n,a);co(l,n),Dg(l,t.force??!1),kr(l)&&Du(l);let c=e.type==="github"?`${e.owner}/${e.repo}`:e.url;i.confirm&&await Iz(e.url,i.confirmDelayMs),await Pu(e.url,l,s);try{let u;if(t.ref)u=t.ref;else{let y=await br(l,s);u=Sr(y)??await un(l,s)}(t.ref||await Az(l,u,s))&&await wr(l,u,s);let d=await cn(l,s);CA(l);let p=IA(l),f=a,g=l;if(!t.name&&p&&p!==a){Fn(p);let y=lo(n,p);co(y,n),Dg(y,t.force??!1),kr(y)&&Du(y),wz(l,y),f=p,g=y}let h=o().toISOString(),b={source:c,sourceType:e.type,ref:u,commit:d,enabled:!0,installedAt:h,updatedAt:h,...p&&p!==f?{manifestName:p}:{}};return sr(f,b,r),Cn(),{name:f,dir:g,entry:b}}catch(u){try{kr(l)&&Du(l)}catch{}throw u}}async function Az(e,t,n){let r=await un(e,n);return t!==r}function Cz(e){if(e.type==="github")return e.repo;let t=e.url.replace(/\.git$/,""),n=t.lastIndexOf("/"),r=t.lastIndexOf(":"),o=Math.max(n,r);return o>=0?t.slice(o+1):t}async function Iz(e,t){let n="\u2550".repeat(70),r=o=>process.stderr.write(o+`
1835
- `);if(r(""),r(n),r(" \u26A0\uFE0F PLUGIN INSTALL WARNING \u2014 READ BEFORE CONTINUING"),r(n),r(""),r(` Source : ${e}`),r(""),r(" Installing a plugin grants ARBITRARY CODE EXECUTION to whoever controls"),r(" that git ref. The plugin's SKILL.md becomes a system prompt that runs"),r(" inside a subagent with full tool access (bash, write_file, web_scrape,"),r(" and any other tool enabled in your session)."),r(""),r(" \u25BA Audit the repository source code before proceeding."),r(" \u25BA Only install plugins from authors you trust."),r(" \u25BA Run `afk plugin install --yes <source>` to suppress this warning."),r(""),t>0){let o=Math.ceil(t/1e3);r(` Proceeding in ${o} second(s)\u2026 Press Ctrl-C to abort.`),r(""),await new Promise(s=>setTimeout(s,t))}r(n),r("")}function CA(e){let t=lo(e,".claude-plugin","plugin.json");if(kr(t))return;let n=lo(e,".claude-plugin","marketplace.json");if(kr(n))throw new Error(`${e} contains .claude-plugin/marketplace.json instead of plugin.json. Use \`afk marketplace install <source>\` to install a marketplace, then \`afk plugin install <marketplace>:<plugin>\` to install a plugin from it.`)}function IA(e){let t=lo(e,".claude-plugin","plugin.json");if(!kr(t))return null;try{let n=JSON.parse(bz(t,"utf8"));return typeof n.name=="string"&&n.name.trim()?n.name.trim():null}catch{return null}}var Pz=/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;function Fn(e){if(!e||e.length>100||!Pz.test(e))throw new Error(`Invalid plugin name "${e}": must be 1\u2013100 chars, starting with alphanumeric, containing only letters, digits, hyphens, or underscores.`)}function co(e,t){let n;try{n=_A($g(t))}catch{n=$g(t)}let r=$g(e),o;try{o=lo(_A(Ez(r)),AA(r))}catch{o=r}let s=xz(n,o);if(s.startsWith("..")||s==="")throw new Error(`Path traversal detected: resolved path "${e}" escapes plugin dir "${t}"`);if(s.startsWith("/"))throw new Error(`Path traversal detected: resolved path "${e}" escapes plugin dir "${t}"`)}function Dg(e,t){if(!(!kr(e)&&!Lg(e))&&!t)throw new Error(`plugin directory already exists: ${e} (re-run with --force to replace)`)}function Lg(e){try{return vz(e).isSymbolicLink()}catch{return!1}}function Du(e){if(Lg(e)){Tz(e);return}Sz(e,{recursive:!0,force:!0})}ft();import{existsSync as MA,readFileSync as Mz}from"fs";import{join as Oz}from"path";var $z=".claude-plugin/marketplace.json";function OA(e){return Oz(e,$z)}function Fg(e){return MA(OA(e))}function Nn(e){let t=OA(e);if(!MA(t))throw new Error(`marketplace manifest not found: ${t}`);let n;try{n=Mz(t,"utf8")}catch(o){throw new Error(`could not read marketplace manifest at ${t}: ${PA(o)}`)}let r;try{r=JSON.parse(n)}catch(o){throw new Error(`marketplace manifest at ${t} is not valid JSON: ${PA(o)}`)}return Dz(r,t)}function $A(e){try{return Nn(e)}catch{return null}}function Dz(e,t){if(!e||typeof e!="object")throw new Error(`marketplace manifest at ${t} must be a JSON object`);let n=e,r=n.name;if(typeof r!="string"||!r.trim())throw new Error(`marketplace manifest at ${t} is missing required "name" field`);let o=n.plugins;if(!Array.isArray(o))throw new Error(`marketplace manifest at ${t} is missing required "plugins" array`);let s=new Set,i=o.map((u,d)=>{if(!u||typeof u!="object")throw new Error(`marketplace manifest at ${t}: plugins[${d}] must be an object`);let p=u,f=p.name,g=p.source;if(typeof f!="string"||!f.trim())throw new Error(`marketplace manifest at ${t}: plugins[${d}] missing required "name"`);if(typeof g!="string"||!g.trim())throw new Error(`marketplace manifest at ${t}: plugins[${d}] missing required "source"`);let h=f.trim();if(s.has(h))throw new Error(`marketplace manifest at ${t}: duplicate plugin name "${h}"`);s.add(h);let b={name:h,source:g.trim()},y=p.description;return typeof y=="string"&&(b.description=y),b}),a={name:r.trim(),plugins:i},l=n.metadata;if(l&&typeof l=="object"){let u=l,d={};typeof u.description=="string"&&(d.description=u.description),Object.keys(d).length>0&&(a.metadata=d)}let c=n.owner;if(c&&typeof c=="object"){let u=c,d={};typeof u.name=="string"&&(d.name=u.name),typeof u.email=="string"&&(d.email=u.email),Object.keys(d).length>0&&(a.owner=d)}return a}function PA(e){return e instanceof Error?e.message:String(e)}async function Nu(e,t={},n={}){let r=n.cacheDir??dn(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},a=Bs(e);if(a.type==="marketplace-ref")throw new Error(`marketplace source cannot itself be a marketplace reference ("${e}")`);return Lz(r,{recursive:!0}),a.type==="local"?Wz(a,t,r,o,s):Kz(a,t,r,o,s,i)}function Wz(e,t,n,r,o){let s=Nn(e.path),i=t.name??s.name;Fn(i);let a=Ng(n,i);co(a,n),Bg(a,t.force??!1),(ma(a)||Ug(a))&&Fu(a),Bz(e.path,a,"dir");let l=o().toISOString(),c={source:e.path,sourceType:"local",ref:null,commit:null,installedAt:l,updatedAt:l};return Di(i,c,r),{name:i,dir:a,entry:c,plugins:s.plugins.map(DA)}}async function Kz(e,t,n,r,o,s){Iu(e.url);let i=t.name??zz(e);Fn(i);let a=Ng(n,i);co(a,n),Bg(a,t.force??!1),ma(a)&&Fu(a);let l=e.type==="github"?`${e.owner}/${e.repo}`:e.url;await Pu(e.url,a,s);try{let c;if(t.ref)c=t.ref;else{let b=await br(a,s);c=Sr(b)??await un(a,s)}(t.ref||await Gz(a,c,s))&&await wr(a,c,s);let u=await cn(a,s),d=Nn(a),p=i,f=a;if(!t.name&&d.name!==i){Fn(d.name);let b=Ng(n,d.name);co(b,n),Bg(b,t.force??!1),ma(b)&&Fu(b),Fz(a,b),p=d.name,f=b}let g=o().toISOString(),h={source:l,sourceType:e.type,ref:c,commit:u,installedAt:g,updatedAt:g};return Di(p,h,r),{name:p,dir:f,entry:h,plugins:d.plugins.map(DA)}}catch(c){try{ma(a)&&Fu(a)}catch{}throw c}}async function Gz(e,t,n){let r=await un(e,n);return t!==r}function zz(e){if(e.type==="github")return e.repo;let t=e.url.replace(/\.git$/,""),n=t.lastIndexOf("/"),r=t.lastIndexOf(":"),o=Math.max(n,r);return o>=0?t.slice(o+1):Hz(t)}function Bg(e,t){if(!(!ma(e)&&!Ug(e))&&!t)throw new Error(`marketplace directory already exists: ${e} (re-run with --force to replace)`)}function Ug(e){try{return Uz(e).isSymbolicLink()}catch{return!1}}function Fu(e){if(Ug(e)){jz(e);return}Nz(e,{recursive:!0,force:!0})}function DA(e){return e.description?{name:e.name,description:e.description}:{name:e.name}}W();ft();import{existsSync as qz,lstatSync as Jz,rmSync as Yz,unlinkSync as Vz}from"fs";import{join as Xz}from"path";function Bu(e,t={}){let n=t.cacheDir??dn(),r=t.indexPath??ce(),o=Xz(n,e),s=!1;Zz(o)?(Vz(o),s=!0):qz(o)&&(Yz(o,{recursive:!0,force:!0}),s=!0);let i=ye(r),a=Object.prototype.hasOwnProperty.call(i.marketplaces,e),l=Object.entries(i.plugins).filter(([,c])=>c.marketplace===e).map(([c])=>c);return(a||l.length>0)&&Dk(e,r),{name:e,removedDir:s,removedIndexEntry:a,removedPluginEntries:l}}function Zz(e){try{return Jz(e).isSymbolicLink()}catch{return!1}}W();import{existsSync as sq}from"fs";import{join as iq}from"path";ft();K();W();ft();import{existsSync as Uu,statSync as Qz}from"fs";import{isAbsolute as LA,join as eq,resolve as FA}from"path";async function Us(e,t,n={},r={}){let o=r.marketplaceDirFor??ei,s=r.indexPath??ce(),i=r.now??(()=>new Date),a=o(e);if(!Uu(a)||!Fg(a))throw new Error(`marketplace "${e}" is not installed (looked for manifest under ${a})`);let l=Nn(a),c=l.plugins.find(u=>u.name===t);if(!c){let u=l.plugins.map(d=>d.name).join(", ")||"(none)";throw new Error(`marketplace "${e}" does not list a plugin named "${t}". Available: ${u}`)}return tq(c.source)?nq(e,c,a,s,i,n):rq(e,c,n,r)}function ju(e,t={}){let n=t.marketplaceDirFor??ei,r=t.indexPath??ce(),o=n(e);if(!Uu(o)||!Fg(o))throw new Error(`marketplace "${e}" is not installed`);let s=Nn(o),i=ye(r);return s.plugins.map(a=>{let l=`${e}:${a.name}`,c=l in i.plugins||a.name in i.plugins&&i.plugins[a.name]?.marketplace===e,u={name:a.name,installed:c,key:l};return a.description&&(u.description=a.description),u})}function tq(e){return e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.startsWith("~")}function NA(e){return e.startsWith(".")||LA(e)||e.startsWith("~")}function jg(e,t){return LA(t)||t.startsWith("~")?oq(t):FA(e,t)}function nq(e,t,n,r,o,s){let i=t.source,a=jg(n,i);if(!Uu(a))throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but that path does not exist on disk`);if(!Qz(a).isDirectory())throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but that path is not a directory`);let c=eq(a,".claude-plugin","plugin.json");if(!Uu(c))throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but no .claude-plugin/plugin.json was found`);let u=`${e}:${t.name}`,d=ye(r);if(!s.force&&u in d.plugins&&d.plugins[u]?.enabled)throw new Error(`plugin "${u}" is already installed (re-run with --force to overwrite)`);let p=o().toISOString(),f={source:`${e}:${t.name}`,sourceType:"marketplace",ref:null,commit:null,enabled:!0,installedAt:p,updatedAt:p,marketplace:e};return sr(u,f,r),{key:u,name:t.name,dir:a,entry:f}}async function rq(e,t,n,r){let o={name:t.name,...n.ref?{ref:n.ref}:{},...n.force?{force:!0}:{}},s=await Lu(t.source,o,r),i=r.indexPath??ce(),a={...s.entry,marketplace:e};return sr(s.name,a,i),{key:s.name,name:s.name,dir:s.dir,entry:a}}function oq(e){if(e.startsWith("~")){let t=T.HOME??"";if(e==="~")return t;if(e.startsWith("~/"))return FA(t,e.slice(2))}return e}async function fa(e,t={},n={}){let r=n.indexPath??ce(),o=n.now??(()=>new Date),s=n.gitRunner?{runner:n.gitRunner}:{},a=ye(r).marketplaces[e];if(!a)throw new Error(`marketplace "${e}" is not installed`);let l=n.cacheDir?iq(n.cacheDir,e):ei(e);if(!sq(l))return{name:e,status:"missing-dir",dir:l};if(a.sourceType==="local")return{name:e,status:"skipped-local"};let c=new Set(($A(l)?.plugins??[]).map(_=>_.name));await Mu(l,s);let u,d=!1;if(t.ref)u=t.ref;else{let _=await br(l,s),P=Sr(_);P!==null?(u=P,d=!0):u=a.ref??await un(l,s)}let p=`refs/remotes/origin/${u}`,f=d?null:await Ou(l,p,s),g=f!==null,h=await cn(l,s);if(g?f===h:u===a.ref)return{name:e,status:"up-to-date",ref:u,commit:h};await wr(l,g?p:d?`refs/tags/${u}`:u,s);let y=await cn(l,s),w=o().toISOString(),S={...a,ref:u,commit:y,updatedAt:w};Di(e,S,r);let E=Nn(l),k=new Set(E.plugins.map(_=>_.name)),x=[...k].filter(_=>!c.has(_)),R=[...c].filter(_=>!k.has(_));return{name:e,status:"updated",fromRef:a.ref,toRef:u,commit:y,addedPlugins:x,removedPlugins:R,pluginVersions:aq(l,E)}}function aq(e,t){return t.plugins.map(n=>{let r=NA(n.source)?ro(jg(e,n.source)).version:null;return{name:n.name,version:r}})}async function BA(e={}){let t=e.indexPath??ce(),n=ye(t),r=[];for(let o of Object.keys(n.marketplaces))try{r.push(await fa(o,{},e))}catch(s){let i=s instanceof Error?s.message:String(s);r.push({name:o,status:"missing-dir",dir:i})}return r}ft();var UA=["add","plugins","install","remove","update"],lq={name:"/marketplaces",summary:"List installed plugin marketplaces",async handler(e){return uq(e),"continue"}},cq={name:"/marketplace",summary:"Manage plugin marketplaces (add | plugins | install | remove | update)",usage:"/marketplace <add|plugins|install|remove|update> [args]",async handler(e,t){let n=t.trim();if(!n)return dq(e),"continue";let[r,...o]=n.split(/\s+/);if(!r||!UA.includes(r))return e.out.error(`Unknown subcommand "${r??""}". Try one of: ${UA.join(", ")}.`),"continue";switch(r){case"add":return pq(e,o);case"plugins":return mq(e,o);case"install":return fq(e,o);case"remove":return gq(e,o);case"update":return hq(e,o);default:return"continue"}}};function jA(){de(lq),de(cq)}function uq(e){let t=ye(),n=Object.entries(t.marketplaces).sort(([r],[o])=>r.localeCompare(o));if(e.out.line(),n.length===0){e.out.line(m.dim(" No marketplaces installed.")),e.out.line(m.dim(" Try: /marketplace add anthropics/claude-plugins-official")),e.out.line();return}e.out.line(m.bold("Installed marketplaces:"));for(let[r,o]of n){let s=o.ref?m.brand(o.ref):m.dim("(local)");e.out.line(` ${m.bold(r.padEnd(28))} ${s.padEnd(12)} ${m.dim(o.source)}`)}e.out.line()}function dq(e){e.out.line(),e.out.line(m.bold("/marketplace usage:")),e.out.line(` ${m.brand("/marketplace add")} <git-url|owner/repo|local-path>`),e.out.line(` ${m.brand("/marketplace plugins")} <marketplace>`),e.out.line(` ${m.brand("/marketplace install")} <marketplace> <plugin>`),e.out.line(` ${m.brand("/marketplace remove")} <marketplace>`),e.out.line(` ${m.brand("/marketplace update")} [<marketplace>]`),e.out.line()}async function pq(e,t){if(t.length===0)return e.out.error("Usage: /marketplace add <source> [name]"),"continue";let[n,r,...o]=t;if(!n)return e.out.error("Usage: /marketplace add <source> [name]"),"continue";let s=yq(o);e.out.info(`Installing marketplace ${n}\u2026`);try{let i=await Nu(n,{...r&&!r.startsWith("-")?{name:r}:{},...s.ref?{ref:s.ref}:{},...s.force?{force:!0}:{}});e.out.success(`Installed marketplace ${i.name} (${i.plugins.length} plugin(s) available).`),e.out.line(m.dim(` Next: /marketplace plugins ${i.name}`))}catch(i){e.out.error(`Install failed: ${Hu(i)}`)}return"continue"}function mq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace plugins <marketplace>"),"continue";try{let r=ju(n);if(e.out.line(),r.length===0)return e.out.line(m.dim(` Marketplace "${n}" lists no plugins.`)),e.out.line(),"continue";e.out.line(m.bold(`Plugins in ${n}:`)),r.forEach((o,s)=>{let i=o.installed?m.brand("[\u2713]"):m.dim("[ ]"),a=o.description?m.dim(` \u2014 ${o.description}`):"";e.out.line(` ${i} ${m.bold(String(s+1).padStart(2))}. ${m.bold(o.name)}${a}`)}),e.out.line(),e.out.line(m.dim(` Install one: /marketplace install ${n} <plugin>`)),e.out.line()}catch(r){e.out.error(`List failed: ${Hu(r)}`)}return"continue"}async function fq(e,t){let n,r;if(t.length===1&&t[0]?.includes(":")){let o=t[0].split(":");o.length===2&&([n,r]=o)}else[n,r]=t;if(!n||!r)return e.out.error("Usage: /marketplace install <marketplace> <plugin>"),"continue";e.out.info(`Installing ${n}:${r}\u2026`);try{let o=await Us(n,r);e.out.success(`Installed ${o.key}.`),e.out.line(m.dim(" Run /reload-plugins to refresh this session's slash commands."))}catch(o){e.out.error(`Install failed: ${Hu(o)}`)}return"continue"}function gq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace remove <marketplace>"),"continue";let r=Bu(n);if(!r.removedDir&&!r.removedIndexEntry&&r.removedPluginEntries.length===0)return e.out.line(m.dim(` No marketplace named "${n}" to remove.`)),"continue";let o=r.removedPluginEntries.length>0?` + ${r.removedPluginEntries.length} plugin(s)`:"";return e.out.success(`Removed marketplace ${n}${o}.`),"continue"}async function hq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace update <marketplace>"),"continue";e.out.info(`Updating ${n}\u2026`);try{let r=await fa(n);switch(r.status){case"updated":{let o=r.addedPlugins.length>0?` +${r.addedPlugins.join(", ")}`:"",s=r.removedPlugins.length>0?` -${r.removedPlugins.join(", ")}`:"";e.out.success(`Updated ${n}: ${r.fromRef??"(none)"} \u2192 ${r.toRef}${o}${s}`);break}case"up-to-date":e.out.info(`${n} is up-to-date (${r.ref}).`);break;case"skipped-local":e.out.info(`${n} skipped (local source).`);break;case"missing-dir":e.out.warn(`${n}: marketplace dir missing (${r.dir}).`);break}}catch(r){e.out.error(`Update failed: ${Hu(r)}`)}return"continue"}function yq(e){let t={};for(let n=0;n<e.length;n+=1){let r=e[n];r==="-f"||r==="--force"?t.force=!0:(r==="-r"||r==="--ref")&&e[n+1]&&(t.ref=e[n+1],n+=1)}return t}function Hu(e){return e instanceof Error?e.message:String(e)}R_("shadow-verify",{glyph:"\u25C8",color:"#7B5EA7",inFlightVerb:"verifying\u2026"});function HA(){KE();for(let e of VE)de(e);for(let e of sx)de(e);de(ix),de(hx),de(yx),de(bx),de(wx),de(Tx),de(Cx),de(Px);for(let e of Dx)de(e);de(Nx),de(jx),de(Wx),de(E_),de(C_),de(I_),de(M_),de(B_),de(U_),de(W_),vA(),WE($_),kA(),z_(),jA()}function WA(e,t={}){if(!e.isTTY)return{writeLine:o=>{e.write(o+`
1834
+ `).map(o=>o.trim()).filter(Boolean)}async function wr(e,t,n={}){let r=n.runner??ao,o=["checkout","--detach"];n.force&&o.push("--force"),o.push(t),await r(Og(o),e,n.env)}async function cn(e,t={}){let n=t.runner??ao,{stdout:r}=await n(["rev-parse","HEAD"],e,t.env);return r.trim()}async function Ou(e,t,n={}){let r=n.runner??ao;try{let{stdout:o}=await r(["rev-parse","--verify","--quiet",t],e,n.env);return o.trim()||null}catch{return null}}async function un(e,t={}){let n=t.runner??ao;try{let{stdout:r}=await n(["symbolic-ref","refs/remotes/origin/HEAD","--short"],e,t.env);return r.trim().replace(/^origin\//,"")||"main"}catch{return"main"}}ft();var mz=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function fz(e){let t=mz.exec(e);if(!t)return null;let[,n,r,o,s]=t;return{raw:e,major:Number(n),minor:Number(r),patch:Number(o),prerelease:s??null}}function gz(e,t){if(e===null&&t===null)return 0;if(e===null)return 1;if(t===null)return-1;let n=e.split("."),r=t.split("."),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let i=n[s],a=r[s];if(i===void 0)return-1;if(a===void 0)return 1;let l=/^\d+$/.test(i),c=/^\d+$/.test(a);if(l&&c){let u=Number(i)-Number(a);if(u!==0)return u}else{if(l)return-1;if(c)return 1;if(i<a)return-1;if(i>a)return 1}}return 0}function hz(e,t){return e.major!==t.major?e.major-t.major:e.minor!==t.minor?e.minor-t.minor:e.patch!==t.patch?e.patch-t.patch:gz(e.prerelease,t.prerelease)}function Sr(e){let t=e.map(n=>fz(n.trim())).filter(n=>n!==null);return t.length===0?null:(t.sort((n,r)=>hz(r,n)),t[0]?.raw??null)}ir();async function Lu(e,t={},n={}){let r=n.pluginsDir??Fe(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},a=n.confirm??!0,l=n.confirmDelayMs??3e3,c=Bs(e);if(yz(r,{recursive:!0}),c.type==="local")return Rz(c,t,r,o,s);if(c.type==="marketplace-ref")throw new Error(`marketplace-ref source "${c.marketplace}:${c.plugin}" must be installed via the marketplace resolver, not installPlugin directly`);return Iu(c.url),_z(c,t,r,o,s,i,{confirm:a,confirmDelayMs:l})}function Rz(e,t,n,r,o){CA(e.path);let s=IA(e.path),i=t.name??s??AA(e.path);Fn(i);let a=lo(n,i);co(a,n),Dg(a,t.force??!1),(kr(a)||Lg(a))&&Du(a),kz(e.path,a,"dir");let l=o().toISOString(),c={source:e.path,sourceType:"local",ref:null,commit:null,enabled:!0,installedAt:l,updatedAt:l,...s&&s!==i?{manifestName:s}:{}};return sr(i,c,r),Cn(),{name:i,dir:a,entry:c}}async function _z(e,t,n,r,o,s,i){let a=t.name??Cz(e);Fn(a);let l=lo(n,a);co(l,n),Dg(l,t.force??!1),kr(l)&&Du(l);let c=e.type==="github"?`${e.owner}/${e.repo}`:e.url;i.confirm&&await Iz(e.url,i.confirmDelayMs),await Pu(e.url,l,s);try{let u;if(t.ref)u=t.ref;else{let y=await br(l,s);u=Sr(y)??await un(l,s)}(t.ref||await Az(l,u,s))&&await wr(l,u,s);let d=await cn(l,s);CA(l);let p=IA(l),f=a,g=l;if(!t.name&&p&&p!==a){Fn(p);let y=lo(n,p);co(y,n),Dg(y,t.force??!1),kr(y)&&Du(y),wz(l,y),f=p,g=y}let h=o().toISOString(),b={source:c,sourceType:e.type,ref:u,commit:d,enabled:!0,installedAt:h,updatedAt:h,...p&&p!==f?{manifestName:p}:{}};return sr(f,b,r),Cn(),{name:f,dir:g,entry:b}}catch(u){try{kr(l)&&Du(l)}catch{}throw u}}async function Az(e,t,n){let r=await un(e,n);return t!==r}function Cz(e){if(e.type==="github")return e.repo;let t=e.url.replace(/\.git$/,""),n=t.lastIndexOf("/"),r=t.lastIndexOf(":"),o=Math.max(n,r);return o>=0?t.slice(o+1):t}async function Iz(e,t){let n="\u2550".repeat(70),r=o=>process.stderr.write(o+`
1835
+ `);if(r(""),r(n),r(" \u26A0\uFE0F PLUGIN INSTALL WARNING \u2014 READ BEFORE CONTINUING"),r(n),r(""),r(` Source : ${e}`),r(""),r(" Installing a plugin grants ARBITRARY CODE EXECUTION to whoever controls"),r(" that git ref. The plugin's SKILL.md becomes a system prompt that runs"),r(" inside a subagent with full tool access (bash, write_file, web_scrape,"),r(" and any other tool enabled in your session)."),r(""),r(" \u25BA Audit the repository source code before proceeding."),r(" \u25BA Only install plugins from authors you trust."),r(" \u25BA Run `afk plugin install --yes <source>` to suppress this warning."),r(""),t>0){let o=Math.ceil(t/1e3);r(` Proceeding in ${o} second(s)\u2026 Press Ctrl-C to abort.`),r(""),await new Promise(s=>setTimeout(s,t))}r(n),r("")}function CA(e){let t=lo(e,".claude-plugin","plugin.json");if(kr(t))return;let n=lo(e,".claude-plugin","marketplace.json");if(kr(n))throw new Error(`${e} contains .claude-plugin/marketplace.json instead of plugin.json. Use \`afk marketplace install <source>\` to install a marketplace, then \`afk plugin install <marketplace>:<plugin>\` to install a plugin from it.`)}function IA(e){let t=lo(e,".claude-plugin","plugin.json");if(!kr(t))return null;try{let n=JSON.parse(bz(t,"utf8"));return typeof n.name=="string"&&n.name.trim()?n.name.trim():null}catch{return null}}var Pz=/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;function Fn(e){if(!e||e.length>100||!Pz.test(e))throw new Error(`Invalid plugin name "${e}": must be 1\u2013100 chars, starting with alphanumeric, containing only letters, digits, hyphens, or underscores.`)}function co(e,t){let n;try{n=_A($g(t))}catch{n=$g(t)}let r=$g(e),o;try{o=lo(_A(Ez(r)),AA(r))}catch{o=r}let s=xz(n,o);if(s.startsWith("..")||s==="")throw new Error(`Path traversal detected: resolved path "${e}" escapes plugin dir "${t}"`);if(s.startsWith("/"))throw new Error(`Path traversal detected: resolved path "${e}" escapes plugin dir "${t}"`)}function Dg(e,t){if(!(!kr(e)&&!Lg(e))&&!t)throw new Error(`plugin directory already exists: ${e} (re-run with --force to replace)`)}function Lg(e){try{return vz(e).isSymbolicLink()}catch{return!1}}function Du(e){if(Lg(e)){Tz(e);return}Sz(e,{recursive:!0,force:!0})}ft();import{existsSync as MA,readFileSync as Mz}from"fs";import{join as Oz}from"path";var $z=".claude-plugin/marketplace.json";function OA(e){return Oz(e,$z)}function Fg(e){return MA(OA(e))}function Nn(e){let t=OA(e);if(!MA(t))throw new Error(`marketplace manifest not found: ${t}`);let n;try{n=Mz(t,"utf8")}catch(o){throw new Error(`could not read marketplace manifest at ${t}: ${PA(o)}`)}let r;try{r=JSON.parse(n)}catch(o){throw new Error(`marketplace manifest at ${t} is not valid JSON: ${PA(o)}`)}return Dz(r,t)}function $A(e){try{return Nn(e)}catch{return null}}function Dz(e,t){if(!e||typeof e!="object")throw new Error(`marketplace manifest at ${t} must be a JSON object`);let n=e,r=n.name;if(typeof r!="string"||!r.trim())throw new Error(`marketplace manifest at ${t} is missing required "name" field`);let o=n.plugins;if(!Array.isArray(o))throw new Error(`marketplace manifest at ${t} is missing required "plugins" array`);let s=new Set,i=o.map((u,d)=>{if(!u||typeof u!="object")throw new Error(`marketplace manifest at ${t}: plugins[${d}] must be an object`);let p=u,f=p.name,g=p.source;if(typeof f!="string"||!f.trim())throw new Error(`marketplace manifest at ${t}: plugins[${d}] missing required "name"`);if(typeof g!="string"||!g.trim())throw new Error(`marketplace manifest at ${t}: plugins[${d}] missing required "source"`);let h=f.trim();if(s.has(h))throw new Error(`marketplace manifest at ${t}: duplicate plugin name "${h}"`);s.add(h);let b={name:h,source:g.trim()},y=p.description;return typeof y=="string"&&(b.description=y),b}),a={name:r.trim(),plugins:i},l=n.metadata;if(l&&typeof l=="object"){let u=l,d={};typeof u.description=="string"&&(d.description=u.description),Object.keys(d).length>0&&(a.metadata=d)}let c=n.owner;if(c&&typeof c=="object"){let u=c,d={};typeof u.name=="string"&&(d.name=u.name),typeof u.email=="string"&&(d.email=u.email),Object.keys(d).length>0&&(a.owner=d)}return a}function PA(e){return e instanceof Error?e.message:String(e)}async function Nu(e,t={},n={}){let r=n.cacheDir??dn(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},a=Bs(e);if(a.type==="marketplace-ref")throw new Error(`marketplace source cannot itself be a marketplace reference ("${e}")`);return Lz(r,{recursive:!0}),a.type==="local"?Wz(a,t,r,o,s):Kz(a,t,r,o,s,i)}function Wz(e,t,n,r,o){let s=Nn(e.path),i=t.name??s.name;Fn(i);let a=Ng(n,i);co(a,n),Bg(a,t.force??!1),(ma(a)||Ug(a))&&Fu(a),Bz(e.path,a,"dir");let l=o().toISOString(),c={source:e.path,sourceType:"local",ref:null,commit:null,installedAt:l,updatedAt:l};return Di(i,c,r),{name:i,dir:a,entry:c,plugins:s.plugins.map(DA)}}async function Kz(e,t,n,r,o,s){Iu(e.url);let i=t.name??zz(e);Fn(i);let a=Ng(n,i);co(a,n),Bg(a,t.force??!1),ma(a)&&Fu(a);let l=e.type==="github"?`${e.owner}/${e.repo}`:e.url;await Pu(e.url,a,s);try{let c;if(t.ref)c=t.ref;else{let b=await br(a,s);c=Sr(b)??await un(a,s)}(t.ref||await Gz(a,c,s))&&await wr(a,c,s);let u=await cn(a,s),d=Nn(a),p=i,f=a;if(!t.name&&d.name!==i){Fn(d.name);let b=Ng(n,d.name);co(b,n),Bg(b,t.force??!1),ma(b)&&Fu(b),Fz(a,b),p=d.name,f=b}let g=o().toISOString(),h={source:l,sourceType:e.type,ref:c,commit:u,installedAt:g,updatedAt:g};return Di(p,h,r),{name:p,dir:f,entry:h,plugins:d.plugins.map(DA)}}catch(c){try{ma(a)&&Fu(a)}catch{}throw c}}async function Gz(e,t,n){let r=await un(e,n);return t!==r}function zz(e){if(e.type==="github")return e.repo;let t=e.url.replace(/\.git$/,""),n=t.lastIndexOf("/"),r=t.lastIndexOf(":"),o=Math.max(n,r);return o>=0?t.slice(o+1):Hz(t)}function Bg(e,t){if(!(!ma(e)&&!Ug(e))&&!t)throw new Error(`marketplace directory already exists: ${e} (re-run with --force to replace)`)}function Ug(e){try{return Uz(e).isSymbolicLink()}catch{return!1}}function Fu(e){if(Ug(e)){jz(e);return}Nz(e,{recursive:!0,force:!0})}function DA(e){return e.description?{name:e.name,description:e.description}:{name:e.name}}W();ft();import{existsSync as qz,lstatSync as Jz,rmSync as Yz,unlinkSync as Vz}from"fs";import{join as Xz}from"path";function Bu(e,t={}){let n=t.cacheDir??dn(),r=t.indexPath??ce(),o=Xz(n,e),s=!1;Zz(o)?(Vz(o),s=!0):qz(o)&&(Yz(o,{recursive:!0,force:!0}),s=!0);let i=ye(r),a=Object.prototype.hasOwnProperty.call(i.marketplaces,e),l=Object.entries(i.plugins).filter(([,c])=>c.marketplace===e).map(([c])=>c);return(a||l.length>0)&&Dk(e,r),{name:e,removedDir:s,removedIndexEntry:a,removedPluginEntries:l}}function Zz(e){try{return Jz(e).isSymbolicLink()}catch{return!1}}W();import{existsSync as sq}from"fs";import{join as iq}from"path";ft();K();W();ft();import{existsSync as Uu,statSync as Qz}from"fs";import{isAbsolute as LA,join as eq,resolve as FA}from"path";async function Us(e,t,n={},r={}){let o=r.marketplaceDirFor??ei,s=r.indexPath??ce(),i=r.now??(()=>new Date),a=o(e);if(!Uu(a)||!Fg(a))throw new Error(`marketplace "${e}" is not installed (looked for manifest under ${a})`);let l=Nn(a),c=l.plugins.find(u=>u.name===t);if(!c){let u=l.plugins.map(d=>d.name).join(", ")||"(none)";throw new Error(`marketplace "${e}" does not list a plugin named "${t}". Available: ${u}`)}return tq(c.source)?nq(e,c,a,s,i,n):rq(e,c,n,r)}function ju(e,t={}){let n=t.marketplaceDirFor??ei,r=t.indexPath??ce(),o=n(e);if(!Uu(o)||!Fg(o))throw new Error(`marketplace "${e}" is not installed`);let s=Nn(o),i=ye(r);return s.plugins.map(a=>{let l=`${e}:${a.name}`,c=l in i.plugins||a.name in i.plugins&&i.plugins[a.name]?.marketplace===e,u={name:a.name,installed:c,key:l};return a.description&&(u.description=a.description),u})}function tq(e){return e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.startsWith("~")}function NA(e){return e.startsWith(".")||LA(e)||e.startsWith("~")}function jg(e,t){return LA(t)||t.startsWith("~")?oq(t):FA(e,t)}function nq(e,t,n,r,o,s){let i=t.source,a=jg(n,i);if(!Uu(a))throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but that path does not exist on disk`);if(!Qz(a).isDirectory())throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but that path is not a directory`);let c=eq(a,".claude-plugin","plugin.json");if(!Uu(c))throw new Error(`marketplace "${e}" lists plugin "${t.name}" at ${a}, but no .claude-plugin/plugin.json was found`);let u=`${e}:${t.name}`,d=ye(r);if(!s.force&&u in d.plugins&&d.plugins[u]?.enabled)throw new Error(`plugin "${u}" is already installed (re-run with --force to overwrite)`);let p=o().toISOString(),f={source:`${e}:${t.name}`,sourceType:"marketplace",ref:null,commit:null,enabled:!0,installedAt:p,updatedAt:p,marketplace:e};return sr(u,f,r),{key:u,name:t.name,dir:a,entry:f}}async function rq(e,t,n,r){let o={name:t.name,...n.ref?{ref:n.ref}:{},...n.force?{force:!0}:{}},s=await Lu(t.source,o,r),i=r.indexPath??ce(),a={...s.entry,marketplace:e};return sr(s.name,a,i),{key:s.name,name:s.name,dir:s.dir,entry:a}}function oq(e){if(e.startsWith("~")){let t=T.HOME??"";if(e==="~")return t;if(e.startsWith("~/"))return FA(t,e.slice(2))}return e}async function fa(e,t={},n={}){let r=n.indexPath??ce(),o=n.now??(()=>new Date),s=n.gitRunner?{runner:n.gitRunner}:{},a=ye(r).marketplaces[e];if(!a)throw new Error(`marketplace "${e}" is not installed`);let l=n.cacheDir?iq(n.cacheDir,e):ei(e);if(!sq(l))return{name:e,status:"missing-dir",dir:l};if(a.sourceType==="local")return{name:e,status:"skipped-local"};let c=new Set(($A(l)?.plugins??[]).map(_=>_.name));await Mu(l,s);let u,d=!1;if(t.ref)u=t.ref;else{let _=await br(l,s),P=Sr(_);P!==null?(u=P,d=!0):u=a.ref??await un(l,s)}let p=`refs/remotes/origin/${u}`,f=d?null:await Ou(l,p,s),g=f!==null,h=await cn(l,s);if(g?f===h:u===a.ref)return{name:e,status:"up-to-date",ref:u,commit:h};await wr(l,g?p:d?`refs/tags/${u}`:u,{...s,force:!0});let y=await cn(l,s),w=o().toISOString(),S={...a,ref:u,commit:y,updatedAt:w};Di(e,S,r);let E=Nn(l),k=new Set(E.plugins.map(_=>_.name)),x=[...k].filter(_=>!c.has(_)),R=[...c].filter(_=>!k.has(_));return{name:e,status:"updated",fromRef:a.ref,toRef:u,commit:y,addedPlugins:x,removedPlugins:R,pluginVersions:aq(l,E)}}function aq(e,t){return t.plugins.map(n=>{let r=NA(n.source)?ro(jg(e,n.source)).version:null;return{name:n.name,version:r}})}async function BA(e={}){let t=e.indexPath??ce(),n=ye(t),r=[];for(let o of Object.keys(n.marketplaces))try{r.push(await fa(o,{},e))}catch(s){let i=s instanceof Error?s.message:String(s);r.push({name:o,status:"missing-dir",dir:i})}return r}ft();var UA=["add","plugins","install","remove","update"],lq={name:"/marketplaces",summary:"List installed plugin marketplaces",async handler(e){return uq(e),"continue"}},cq={name:"/marketplace",summary:"Manage plugin marketplaces (add | plugins | install | remove | update)",usage:"/marketplace <add|plugins|install|remove|update> [args]",async handler(e,t){let n=t.trim();if(!n)return dq(e),"continue";let[r,...o]=n.split(/\s+/);if(!r||!UA.includes(r))return e.out.error(`Unknown subcommand "${r??""}". Try one of: ${UA.join(", ")}.`),"continue";switch(r){case"add":return pq(e,o);case"plugins":return mq(e,o);case"install":return fq(e,o);case"remove":return gq(e,o);case"update":return hq(e,o);default:return"continue"}}};function jA(){de(lq),de(cq)}function uq(e){let t=ye(),n=Object.entries(t.marketplaces).sort(([r],[o])=>r.localeCompare(o));if(e.out.line(),n.length===0){e.out.line(m.dim(" No marketplaces installed.")),e.out.line(m.dim(" Try: /marketplace add anthropics/claude-plugins-official")),e.out.line();return}e.out.line(m.bold("Installed marketplaces:"));for(let[r,o]of n){let s=o.ref?m.brand(o.ref):m.dim("(local)");e.out.line(` ${m.bold(r.padEnd(28))} ${s.padEnd(12)} ${m.dim(o.source)}`)}e.out.line()}function dq(e){e.out.line(),e.out.line(m.bold("/marketplace usage:")),e.out.line(` ${m.brand("/marketplace add")} <git-url|owner/repo|local-path>`),e.out.line(` ${m.brand("/marketplace plugins")} <marketplace>`),e.out.line(` ${m.brand("/marketplace install")} <marketplace> <plugin>`),e.out.line(` ${m.brand("/marketplace remove")} <marketplace>`),e.out.line(` ${m.brand("/marketplace update")} [<marketplace>]`),e.out.line()}async function pq(e,t){if(t.length===0)return e.out.error("Usage: /marketplace add <source> [name]"),"continue";let[n,r,...o]=t;if(!n)return e.out.error("Usage: /marketplace add <source> [name]"),"continue";let s=yq(o);e.out.info(`Installing marketplace ${n}\u2026`);try{let i=await Nu(n,{...r&&!r.startsWith("-")?{name:r}:{},...s.ref?{ref:s.ref}:{},...s.force?{force:!0}:{}});e.out.success(`Installed marketplace ${i.name} (${i.plugins.length} plugin(s) available).`),e.out.line(m.dim(` Next: /marketplace plugins ${i.name}`))}catch(i){e.out.error(`Install failed: ${Hu(i)}`)}return"continue"}function mq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace plugins <marketplace>"),"continue";try{let r=ju(n);if(e.out.line(),r.length===0)return e.out.line(m.dim(` Marketplace "${n}" lists no plugins.`)),e.out.line(),"continue";e.out.line(m.bold(`Plugins in ${n}:`)),r.forEach((o,s)=>{let i=o.installed?m.brand("[\u2713]"):m.dim("[ ]"),a=o.description?m.dim(` \u2014 ${o.description}`):"";e.out.line(` ${i} ${m.bold(String(s+1).padStart(2))}. ${m.bold(o.name)}${a}`)}),e.out.line(),e.out.line(m.dim(` Install one: /marketplace install ${n} <plugin>`)),e.out.line()}catch(r){e.out.error(`List failed: ${Hu(r)}`)}return"continue"}async function fq(e,t){let n,r;if(t.length===1&&t[0]?.includes(":")){let o=t[0].split(":");o.length===2&&([n,r]=o)}else[n,r]=t;if(!n||!r)return e.out.error("Usage: /marketplace install <marketplace> <plugin>"),"continue";e.out.info(`Installing ${n}:${r}\u2026`);try{let o=await Us(n,r);e.out.success(`Installed ${o.key}.`),e.out.line(m.dim(" Run /reload-plugins to refresh this session's slash commands."))}catch(o){e.out.error(`Install failed: ${Hu(o)}`)}return"continue"}function gq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace remove <marketplace>"),"continue";let r=Bu(n);if(!r.removedDir&&!r.removedIndexEntry&&r.removedPluginEntries.length===0)return e.out.line(m.dim(` No marketplace named "${n}" to remove.`)),"continue";let o=r.removedPluginEntries.length>0?` + ${r.removedPluginEntries.length} plugin(s)`:"";return e.out.success(`Removed marketplace ${n}${o}.`),"continue"}async function hq(e,t){let n=t[0];if(!n)return e.out.error("Usage: /marketplace update <marketplace>"),"continue";e.out.info(`Updating ${n}\u2026`);try{let r=await fa(n);switch(r.status){case"updated":{let o=r.addedPlugins.length>0?` +${r.addedPlugins.join(", ")}`:"",s=r.removedPlugins.length>0?` -${r.removedPlugins.join(", ")}`:"";e.out.success(`Updated ${n}: ${r.fromRef??"(none)"} \u2192 ${r.toRef}${o}${s}`);break}case"up-to-date":e.out.info(`${n} is up-to-date (${r.ref}).`);break;case"skipped-local":e.out.info(`${n} skipped (local source).`);break;case"missing-dir":e.out.warn(`${n}: marketplace dir missing (${r.dir}).`);break}}catch(r){e.out.error(`Update failed: ${Hu(r)}`)}return"continue"}function yq(e){let t={};for(let n=0;n<e.length;n+=1){let r=e[n];r==="-f"||r==="--force"?t.force=!0:(r==="-r"||r==="--ref")&&e[n+1]&&(t.ref=e[n+1],n+=1)}return t}function Hu(e){return e instanceof Error?e.message:String(e)}R_("shadow-verify",{glyph:"\u25C8",color:"#7B5EA7",inFlightVerb:"verifying\u2026"});function HA(){KE();for(let e of VE)de(e);for(let e of sx)de(e);de(ix),de(hx),de(yx),de(bx),de(wx),de(Tx),de(Cx),de(Px);for(let e of Dx)de(e);de(Nx),de(jx),de(Wx),de(E_),de(C_),de(I_),de(M_),de(B_),de(U_),de(W_),vA(),WE($_),kA(),z_(),jA()}function WA(e,t={}){if(!e.isTTY)return{writeLine:o=>{e.write(o+`
1836
1836
  `)},setCompositor:()=>{}};let n=null,r=t.statusLine;return{writeLine(o){if(n?.isArmed()){n.commitAbove(o);return}r?r.withFullScrollRegion(()=>{e.write(o+`
1837
1837
  `)}):e.write(o+`
1838
1838
  `)},setCompositor(o){n=o}}}var Wu=class{entries=new Map;record(t){let n=this.entries.get(t.skillName);n?(n.runs+=1,n.totalDurationMs+=t.durationMs,t.claimsTotal!==void 0&&(n.totalClaims=(n.totalClaims??0)+t.claimsTotal),t.claimsConfirmed!==void 0&&(n.totalConfirmed=(n.totalConfirmed??0)+t.claimsConfirmed),t.claimsRefuted!==void 0&&(n.totalRefuted=(n.totalRefuted??0)+t.claimsRefuted),t.claimsInconclusive!==void 0&&(n.totalInconclusive=(n.totalInconclusive??0)+t.claimsInconclusive)):this.entries.set(t.skillName,{skillName:t.skillName,runs:1,totalDurationMs:t.durationMs,...t.claimsTotal!==void 0?{totalClaims:t.claimsTotal}:{},...t.claimsConfirmed!==void 0?{totalConfirmed:t.claimsConfirmed}:{},...t.claimsRefuted!==void 0?{totalRefuted:t.claimsRefuted}:{},...t.claimsInconclusive!==void 0?{totalInconclusive:t.claimsInconclusive}:{}})}summary(){return this.entries.size===0?null:new Map(this.entries)}clear(){this.entries=new Map}};$m();var Ku=class{source;sampleEveryNTurns;cachedRatio;cachedDetail;inFlight=null;disposed=!1;generation=0;constructor(t,n={}){this.source=t,this.sampleEveryNTurns=n.sampleEveryNTurns??3}attach(t){return this.source=t,this.generation+=1,this.reset(),this}getRatio(){return this.cachedRatio}getDetail(){return this.cachedDetail}async refresh(){if(this.disposed)return;if(this.inFlight)return this.inFlight;let t=this.doFetch().finally(()=>{this.inFlight=null});return this.inFlight=t,t}async onTurn(t){this.disposed||t%this.sampleEveryNTurns===1&&await this.refresh()}reset(){this.cachedRatio=void 0,this.cachedDetail=void 0,this.inFlight=null}dispose(){this.disposed=!0}async doFetch(){let t=this.generation;try{let n=await this.source.getContextUsage();if(this.generation!==t)return;let r=bq(n.apiUsage),o=n.maxTokens??0,s=n.percentage;typeof s=="number"&&(this.cachedRatio=Math.min(1,Math.max(0,s/100)),this.cachedDetail={used:r,limit:o,percentage:s})}catch{}}};function bq(e){return e?e.input_tokens+e.output_tokens+e.cache_creation_input_tokens+e.cache_read_input_tokens:0}Ue();Mi();Cm();Oe();ol();var wq="claude-haiku-4-5",Sq=15e3,kq=1e3,vq=80,Tq=200,Eq=3e3,xq='Summarize what this background subagent is currently doing in \u226480 tokens. Be concrete: name specific tools used, files examined, decisions made. Avoid filler ("appears to be working on\u2026").';function Rq(e){return e.replace(/\bauthorization:\s*bearer\s+\S+/gi,"Authorization: Bearer [REDACTED]").replace(/\bsk-ant-[A-Za-z0-9_-]{20,}/g,"[REDACTED]").replace(/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,"[REDACTED]").replace(/\b(?:AKIA|ASIA|AROA|AIDA|AGPA|AIPA|ANPA|ANVA|APKA|ABIA|ACCA)[A-Z0-9]{16}\b/g,"[REDACTED]").replace(/(?<![/.\w])[A-Za-z0-9+/=_-]{32,}(?![/.\w])/g,"[REDACTED]")}var Gu=class{registry;apiKey;model;intervalMs;maxInputTokens;maxOutputTokens;maxCallsPerSession;callLLM;getTranscriptFn;summaries=new Map;jobIndexMap=new Map;jobIndexCounter=0;callsThisSession=0;lastRefreshedAt=new Map;abortController=new AbortController;tickTimer;tickIntervalMs;constructor(t){this.registry=t.registry,this.apiKey=t.apiKey,this.model=t.model??wq,this.intervalMs=t.intervalMs??Sq,this.maxInputTokens=t.maxInputTokens??kq,this.maxOutputTokens=t.maxOutputTokens??vq,this.maxCallsPerSession=t.maxCallsPerSession??Tq,this.tickIntervalMs=Math.max(1e3,Math.floor(this.intervalMs/10)),t.callLLM!==void 0?this.callLLM=t.callLLM:this.callLLM=(n,r)=>$o({token:this.apiKey,model:this.model,system:xq,user:n,maxTokens:this.maxOutputTokens,signal:r}),this.getTranscriptFn=t.getTranscript??(n=>this.registry.getTranscript(n)),this.registry.on("started",n=>{this.jobIndexMap.set(n.jobId,this.jobIndexCounter++)}),this.registry.on("settled",n=>{this.summaries.delete(n.jobId),this.jobIndexMap.delete(n.jobId),this.lastRefreshedAt.delete(n.jobId)})}start(){this.tickTimer===void 0&&(this.abortController=new AbortController,this.tickTimer=setInterval(()=>{this.tick()},this.tickIntervalMs))}stop(){this.tickTimer!==void 0&&(clearInterval(this.tickTimer),this.tickTimer=void 0),this.abortController.abort()}getSummary(t){return this.summaries.get(t)}async tick(){let t=Date.now(),n=this.registry.list().filter(o=>o.status==="running"),r=[];for(let o of n){let i=(this.jobIndexMap.get(o.jobId)??0)*Eq%this.intervalMs,a=this.intervalMs-1e3-i,l=this.lastRefreshedAt.get(o.jobId)??0;if(!(t-l<a)){if(this.callsThisSession>=this.maxCallsPerSession){Y(`[BackgroundSummarizer] budget cap (${this.callsThisSession}/${this.maxCallsPerSession}) \u2014 skipping ${o.jobId}`);continue}this.callsThisSession++,r.push(o.jobId)}}await Promise.allSettled(r.map(o=>this.refreshJob(o,t)))}async refreshJob(t,n){let r=!1;try{let o=this.getTranscriptFn(t);if(o===void 0||o.trim().length===0)return;let s=this.maxInputTokens*4,i=o.length>s?o.slice(-s):o,l=`Transcript tail:
@@ -1902,7 +1902,7 @@ ${E}`})}return{fileBlocks:a,warnings:l}}async function TC(e,t,n,r,o="summary",s,
1902
1902
  `))!==-1;){let u=n.slice(0,c);n=n.slice(c+1),this.opts.writeLine(u)}},s={command:t,mode:"foreground",onChunk:c=>{r||(n+=c.toString("utf8"),o())}},i=this.opts.getCwd();i!==void 0&&(s.cwd=i);let{job:a,handle:l}=this.registry.start(s);this.activeFgJobId=a.id;try{let c=await l.promise;r=!0,n.length>0&&(this.opts.writeLine(n),n=""),this.opts.writeLine(UJ(a,c)),this.queueInjection({command:t,mode:"foreground",result:c})}finally{this.activeFgJobId=null}}startBackground(t){let n={command:t,mode:"background"},r=this.opts.getCwd();r!==void 0&&(n.cwd=r);let{job:o}=this.registry.start(n);this.opts.writeLine(m.dim(` [${o.id}] background: `)+t)}queueInjection(t){this.pendingInjections.push(t),this.pendingInjections.length>e.MAX_PENDING_INJECTIONS&&this.pendingInjections.shift()}};function HJ(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 WJ(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(m.warning("\u26A0 ")+"first-turn hook failed: "+(r instanceof Error?r.message:String(r)))}}}function rd(e,t){let n=m.brand("afk")+m.dim(` (${e})`),r=t?m.warning(" \u25CF plan"):"";return n+r+m.dim(" \u203A ")}async function PC(e,t,n,r){let o=null,s=[];e.session.current.waitForInitialization().then(async S=>{ze()&&(o=Oc(S)),await Cu(e.session.current),ze()&&(s=SA())}).catch(()=>{});let i=await dC(),a=new ed({rl:e.rl,history:i,statusLine:e.statusLine}),l,c,u,d,p,f,g,h=!1,b=!1,y=gR({onError:S=>Y("[afk suggest] Tier-2 completion failed:",S)}),w=HJ(T.AFK_SUGGEST_GHOST,e.suggestGhostConfig);try{await a.armCompositor({promptFn:()=>rd(e.stats.model,e.stats.planMode),onCancel:r,onShiftTab:()=>{mr(e.slashCtx).catch(()=>{}),e.statusLine.rearm()},scrollRegion:e.statusLine,...e.preArmAnchorRow!==void 0?{anchorRow:e.preArmAnchorRow}:{},...w?{suggest:{engine:y,getContext:()=>({model:e.stats.model,apiKey:e.suggestApiKey,baseUrl:e.suggestBaseUrl,cwd:e.stats.cwd??process.cwd(),getHistory:()=>{let I=a.history;return I.getEntries?[...I.getEntries()]:[]},getDropdownTopCandidate:I=>{let F=a.autocompleteState.candidates[0];return F&&F.value.startsWith(I)&&F.value.length>I.length?F.value:null},getTranscriptTail:()=>"",getRecentCommands:()=>[],llmEnabled:()=>/^(1|true|yes|on)$/i.test(T.AFK_SUGGEST_ENABLED??"")})}}:{}});let S=a.getCompositor();Yt.install(Cc({readLine:I=>a.readLine({promptFn:()=>I}).then(M=>M.text),writer:{line:(I="")=>{let M=a.getCompositor();M?M.commitAbove(I):process.stdout.write(I+`
1903
1903
  `)}},pendingCount:()=>Yt.pendingCount(),...S?{pickFromList:I=>hC(S,I),readTextOverlay:I=>yC(S,I)}:{}})),e.replRenderer.setCompositor(a.getCompositor()),e.slashCtx.getCompositor=()=>a.getCompositor();let E=a.getCompositor();if(E){let I=M=>E.commitAbove(M);e.completionWriter.fn=I,e.completionWriter.idleFn=I}e.slashCtx.setSoftStopHandler=I=>a.setSoftStopHandler(I),e.slashCtx.onStageChange=I=>p?.repaint(I),e.slashCtx.onContextProgress=async()=>{await e.contextSampler.refresh(),e.statusLine.repaint(pr(e.stats,e.contextSampler))},e.slashCtx.transcript=t,e.inputSurfaceRef&&(e.inputSurfaceRef.current=a),c=EC(),g=xC(),e.clearVerdictLedger=()=>g?.reset(),u=new Uc,Ix(u),Bx(u),Hx(u),Ux(e.backgroundRegistry);let k=0,x=0,R=1,_=()=>e.statusLine.setExtraRows(R+k+x);g.setRowCountChangeHandler(I=>{x=I,_(),d?.redraw(),p?.redraw()}),d=new td(u,e.backgroundRegistry,{getAdjacentRows:()=>x}),d.setRowCountChangeHandler(I=>{k=I,_()}),p=new du({getExtraRows:()=>e.statusLine.getExtraRows()}),p.setRowCountChangeHandler(I=>{_()}),e.statusLine.setAfterScrollRestore(()=>{g?.repaint(),d?.redraw(),p?.redraw()}),d.start(),p.start(),g.start({stream:process.stdout});let P=50,N=[];for(u.on("complete",I=>{N.length>=P&&N.shift(),N.push(I)}),f=new nd({writeLine:I=>e.replRenderer.writeLine(I),getCwd:()=>e.stats.cwd}),Fx(f),n.tryAbortShellForeground=()=>f.abortActiveForeground();;){if(o&&(e.replRenderer.writeLine(o),e.replRenderer.writeLine(""),o=null),s.length>0){for(let $ of s)e.replRenderer.writeLine($);e.replRenderer.writeLine(""),s=[]}for(;N.length>0;){let $=N.shift(),O=$.status==="succeeded"?"\u2713":"\u2717",C=[];if($.resultText){let J=$.resultText.trim().split(`
1904
1904
  `)[0]?.slice(0,80)??"";J&&C.push(J)}$.error&&C.push($.error.message);let V=[$.stats.toolUses>0?`${$.stats.toolUses} tools`:"",$.stats.tokens>0?`${Math.round($.stats.tokens/1e3)}k tok`:"",$.stats.durationMs>0?`${Math.round($.stats.durationMs/1e3)}s`:""].filter(Boolean).join(" \xB7 ");V&&C.push(V),e.replRenderer.writeLine(zn({kind:$.status==="succeeded"?"checkpoint":"diagnosis",title:`${O} ${$.id} ${$.label}`,body:C})),e.replRenderer.writeLine("")}let I=f.drainNotifications();for(let{job:$,result:O}of I){let C=O.errorReason===void 0?"\u2713":"\u2717",V=O.errorReason==="abort"?"killed":O.errorReason==="timeout"?"timed out":O.errorReason==="signal-killed"?"killed by signal":`exit ${O.exitCode??0}`,J=Math.max(0,Math.round(O.durationMs/100)/10);e.replRenderer.writeLine(m.dim(` ${C} [${$.id}] ${V} \xB7 ${J}s \xB7 `)+$.command)}let M=c.renderIfChanged(e.stats.sessionId);if(M.length>0){for(let $ of M)e.replRenderer.writeLine($);e.replRenderer.writeLine("")}let F,H;if(l!==void 0){let $=l;l=void 0;let O=rd(e.stats.model,e.stats.planMode),C=Yr({buffer:$.text,promptText:O,isTTY:!!process.stdout.isTTY,attachmentSummary:As([...$.attachments])});e.replRenderer.writeLine(C),F=$.text.trim(),H=$.attachments}else{let $=await a.readLine({promptFn:()=>rd(e.stats.model,e.stats.planMode),onSigint:r,onShiftTab:()=>{mr(e.slashCtx).catch(()=>{}),e.statusLine.rearm()}});F=$.text.trim(),H=$.attachments}if(!F&&H.length===0)continue;if(F.startsWith("!")){let $=/^(0|false|off|no)$/i.test(T.AFK_SHELL_PASSTHROUGH??"");if(e.options.shellPassthrough!==!1&&!$&&(h||(h=!0,e.replRenderer.writeLine(m.dim(" \u2139 ! prefix shells out. Pass --no-shell-passthrough (or set AFK_SHELL_PASSTHROUGH=0) to send ! text to the model instead."))),await f.dispatch(F))){e.statusLine.rearm();continue}}let B=!1;if(F.startsWith("/")){let $=await zE(F,e.slashCtx,H);if($.handled){if($.result==="exit"){e.rl.close();return}if((F==="/clear"||F.startsWith("/clear "))&&(await t.rotateOnClear(),e.replRenderer.writeLine(m.dim(` transcript: ${t.path()}`)),g.reset()),$.result!==null&&typeof $.result=="object"&&"kind"in $.result&&$.result.kind==="submit"){l={text:$.result.message,attachments:H??[]},e.statusLine.rearm();continue}e.statusLine.rearm();continue}B=!0}i.push(F),await WJ(e,F);let z=F;if(B){let $=Tf(F);if($){let O=$.name.replace(/^\//,"").split(":").pop()??"";if(O&&Ag(O)){let C={skillName:O,rawArgs:$.args,source:"plugin",capabilities:{compose:!0,subagents:!0}},V=e.session.current.sessionId,J=so(V),X=Date.now();Y(`[afk trace] preflight.start commandName=${O}`);let te=!1,U=await oo(C,{cwd:e.stats.cwd??process.cwd(),artifactDir:J},Se=>{ze()&&e.replRenderer.writeLine(m.warning(`\u26A0 preflight(${O}) failed: `)+(Se instanceof Error?Se.message:String(Se)))});te=U!==null,Y(`[afk trace] preflight.end commandName=${O} durationMs=${Date.now()-X} success=${te}`),z=Ig(U?.manifestBlock,F)}}}let L=f.drainInjections();L.length>0&&(z=L+z),await TC({text:z,attachments:H},e.session.current,e.stats,{setInFlight($){n.turnInFlight=$},async onTurnComplete($,O){if(await t.appendTurn($,O),e.stats.sessionId)try{nn(e.stats)}catch(C){b||(b=!0,e.replRenderer.writeLine(m.warning("\u26A0 ")+"session autosave failed \u2014 this conversation may not be resumable: "+(C instanceof Error?C.message:String(C))))}},async onAfterTurn(){await e.contextSampler.onTurn(e.stats.totalTurns),e.statusLine.rearm(),p?.repaint("observing")},rearmStatus:()=>e.statusLine.rearm(),onTerminalState:$=>g?.push($),setActiveCompositor:$=>{n.activeCompositor=$},setInterruptNotifier:$=>{n.notifyInterrupting=$},scrollRegion:e.statusLine,getCompositor:()=>a.getCompositor(),setBackgroundHandler:$=>a.setBackgroundHandler($),setSoftStopHandler:$=>a.setSoftStopHandler($),async onContextProgress(){await e.contextSampler.refresh(),e.statusLine.repaint(pr(e.stats,e.contextSampler))},...p?{onStageChange:$=>p.repaint($)}:{}},e.options.thinkingUi,e.completionWriter,u,a.toRunTurnRefs(rd(e.stats.model,e.stats.planMode)))}}finally{if(u!==void 0)for(let E of u.running())u.cancel(E.id);n.tryAbortShellForeground=null,f?.drainOnExit(),p?.stop(),d?.stop(),g?.stop(),c?.dispose();let S=E=>console.log(E);e.completionWriter.fn=S,e.completionWriter.idleFn=S,await a.dispose(),e.inputSurfaceRef&&(e.inputSurfaceRef.current=null)}}yi();import{execFile as KJ}from"node:child_process";import{dirname as GJ,isAbsolute as zJ,resolve as qJ}from"node:path";import{promisify as JJ}from"node:util";var MC=JJ(KJ),YJ=3e3,VJ=new Set(["empty","orphaned-dir","orphaned-registration","dead-owner"]);async function XJ(){let t=(await MC("git",["rev-parse","--git-common-dir"])).stdout.trim();if(!t)throw new Error("Not in a git repository.");let n=zJ(t)?t:qJ(process.cwd(),t);return GJ(n)}async function OC(e){if(e?.disabled)return{ran:!1,removedCount:0,skippedReason:"disabled"};let t;try{t=await XJ()}catch{return{ran:!1,removedCount:0,skippedReason:"not-in-repo"}}let n,r=new Promise(o=>{n=setTimeout(()=>o("timeout"),YJ)});try{let o=an({execFile:MC,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=>VJ.has(c.verdict)&&i.removed.includes(c.path)).length}}catch{return{ran:!1,removedCount:0,skippedReason:"error"}}finally{n&&clearTimeout(n)}}ol();yi();import{promises as ZJ}from"node:fs";import{dirname as QJ,join as LC}from"node:path";import{randomBytes as eY}from"node:crypto";var tY=["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(`
1905
- `),$C=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,rh=30,nY=1024,rY=8e3,oY="haiku";async function sY(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=cY(n,nY),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??rY),i=t.signal?uY([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await $o({token:t.token,model:t.model??oY,system:tY,user:r,maxTokens:32,signal:i})}catch(d){let p=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",p.slice(0,200)),null}finally{clearTimeout(s)}let l=iY(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=QJ(t.worktreePath);return await aY(l,c)}function iY(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if($C.test(t)&&t.length<=rh)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>rh)break;o=i}return $C.test(o)?o:null}async function aY(e,t){if(!await lY(LC(t,e)))return e;let n=eY(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,rh-5)}-${n}`}async function lY(e){try{return await ZJ.access(e),!0}catch{return!1}}function cY(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 uY(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 FC(e){let t,n,r=LC(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await sY(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=`${_l(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return DC(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 DC(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 DC(e,t){e&&e.setCwd(t),dY(t)}function dY(e){try{process.chdir(e)}catch{}}Le();Rn();W();import{spawn as NC}from"child_process";import{existsSync as hY,mkdirSync as yY,readFileSync as BC,unlinkSync as bY,writeFileSync as wY}from"fs";import{get as SY}from"https";import{join as UC}from"path";import{readFileSync as pY}from"fs";import{dirname as mY,join as fY}from"path";import{fileURLToPath as gY}from"url";function Bn(){try{return"3.92.1"}catch{}try{let e=mY(gY(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(pY(fY(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}K();var kY=64*1024,vY=1440*60*1e3,TY="update-check.json",EY="pending-update.json";function jC(){return UC(Wa(),TY)}function oh(){return UC(Wa(),EY)}function HC(){let e=Wa();hY(e)||yY(e,{recursive:!0})}function xY(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let i=n[s]??0,a=r[s]??0;if(a>i)return!0;if(a<i)return!1}return!1}function RY(){try{let e=BC(jC(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function _Y(){try{HC();let e=`
1905
+ `),$C=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,rh=30,nY=1024,rY=8e3,oY="haiku";async function sY(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=cY(n,nY),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??rY),i=t.signal?uY([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await $o({token:t.token,model:t.model??oY,system:tY,user:r,maxTokens:32,signal:i})}catch(d){let p=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",p.slice(0,200)),null}finally{clearTimeout(s)}let l=iY(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=QJ(t.worktreePath);return await aY(l,c)}function iY(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if($C.test(t)&&t.length<=rh)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>rh)break;o=i}return $C.test(o)?o:null}async function aY(e,t){if(!await lY(LC(t,e)))return e;let n=eY(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,rh-5)}-${n}`}async function lY(e){try{return await ZJ.access(e),!0}catch{return!1}}function cY(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 uY(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 FC(e){let t,n,r=LC(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await sY(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=`${_l(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return DC(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 DC(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 DC(e,t){e&&e.setCwd(t),dY(t)}function dY(e){try{process.chdir(e)}catch{}}Le();Rn();W();import{spawn as NC}from"child_process";import{existsSync as hY,mkdirSync as yY,readFileSync as BC,unlinkSync as bY,writeFileSync as wY}from"fs";import{get as SY}from"https";import{join as UC}from"path";import{readFileSync as pY}from"fs";import{dirname as mY,join as fY}from"path";import{fileURLToPath as gY}from"url";function Bn(){try{return"3.92.2"}catch{}try{let e=mY(gY(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(pY(fY(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}K();var kY=64*1024,vY=1440*60*1e3,TY="update-check.json",EY="pending-update.json";function jC(){return UC(Wa(),TY)}function oh(){return UC(Wa(),EY)}function HC(){let e=Wa();hY(e)||yY(e,{recursive:!0})}function xY(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let i=n[s]??0,a=r[s]??0;if(a>i)return!0;if(a<i)return!1}return!1}function RY(){try{let e=BC(jC(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function _Y(){try{HC();let e=`
1906
1906
  const https = require('https');
1907
1907
  const fs = require('fs');
1908
1908
  const url = 'https://registry.npmjs.org/agent-afk/latest';
@@ -1948,7 +1948,7 @@ ${M.slice(0,500)}`).catch(F=>{console.error("[daemon] crash notification push fa
1948
1948
  `),g4(e,o,{mode:384})}import bI from"chalk";function wI(e){return process.stdin.isTTY||(console.error(bI.red(`Cannot securely prompt for secret on a non-TTY stdin: "${e.trim()}"`)),console.error(bI.gray(" Supply the token via environment variable or ~/.afk/config/afk.env instead.")),process.exit(1)),new Promise(t=>{process.stdout.write(e);let n=[];process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf-8");let r=o=>{o==="\r"||o===`
1949
1949
  `||o===""?(process.stdin.setRawMode(!1),process.stdin.pause(),process.stdin.removeListener("data",r),process.stdout.write(`
1950
1950
  `),t(n.join("").trim())):o===""?(process.stdin.setRawMode(!1),process.stdin.pause(),process.stdout.write(`
1951
- `),process.exit(1)):o==="\x7F"?n.pop():n.push(o)};process.stdin.on("data",r)})}function kI(){return wI("Anthropic API key or OAuth token: ")}async function ld(e){let t=e??await kI();t||(console.error(SI.red("No token provided. Nothing saved.")),process.exit(1));let n=ut(),r,o;t.startsWith("sk-ant-oat")?(r="CLAUDE_CODE_OAUTH_TOKEN",o=["ANTHROPIC_API_KEY"]):(r="ANTHROPIC_API_KEY",o=["CLAUDE_CODE_OAUTH_TOKEN"]),Un(n,r,t,o),console.log(SI.green(`\u2713 Saved ${r} to ${n}`)),console.log(m.meta("Restart any running afk daemon to pick up the new token."))}function vI(e){e.command("login [token]").description("Save an Anthropic API key or OAuth token for afk to use").action(async t=>{let n=se(rt());if(n==="openai-compatible"||n==="openai-codex"){console.log(Ws.yellow("`afk login` is Anthropic-only.")),console.log(""),console.log("For OpenAI-backed models (gpt-*, o1*, o3*, o4*, codex-*), authenticate with one of:"),console.log(Ws.cyan(" export OPENAI_API_KEY=sk-proj-...")),console.log(Ws.cyan(" # or: export CODEX_API_KEY=...")),console.log(Ws.cyan(" codex login --api-key sk-proj-...")),console.log(""),console.log(Ws.gray("Run `afk provider auth diagnose` to see which auth source AFK will use.")),console.log(Ws.gray("To save an Anthropic key for Claude models instead, re-run with AFK_MODEL=sonnet (or similar) first."));return}await ld(t)})}import pe from"chalk";import cd from"ora";W();import{existsSync as b4}from"fs";import{join as w4}from"path";ft();ir();async function ph(e,t={},n={}){let r=n.pluginsDir??Fe(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},l=ye(o).plugins[e];if(!l)throw new Error(`plugin "${e}" is not installed`);let c=w4(r,e);if(!b4(c))return{name:e,status:"missing-dir",dir:c};if(Cn(),l.sourceType==="local")return{name:e,status:"skipped-local"};await Mu(c,i);let u,d=!1;if(t.ref)u=t.ref;else{let k=await br(c,i),x=Sr(k);x!==null?(u=x,d=!0):u=l.ref??await un(c,i)}let p=`refs/remotes/origin/${u}`,f=d?null:await Ou(c,p,i),g=f!==null,h=await cn(c,i);if(g?f===h:u===l.ref)return{name:e,status:"up-to-date",ref:u,commit:h,version:ro(c).version};await wr(c,g?p:d?`refs/tags/${u}`:u,i);let y=await cn(c,i),w=ro(c).version,S=s().toISOString(),E={...l,ref:u,commit:y,updatedAt:S};return sr(e,E,o),{name:e,status:"updated",fromRef:l.ref,toRef:u,commit:y,version:w}}async function TI(e={}){let t=e.indexPath??ce(),n=ye(t),r=[];for(let o of Object.keys(n.plugins))try{r.push(await ph(o,{},e))}catch(s){let i=s instanceof Error?s.message:String(s);r.push({name:o,status:"missing-dir",dir:i})}return r}W();ft();import{existsSync as S4,lstatSync as k4,rmSync as v4,unlinkSync as T4}from"fs";import{join as E4}from"path";ir();function EI(e,t={}){Fn(e);let n=t.pluginsDir??Fe(),r=t.indexPath??ce(),o=E4(n,e),s=!1;x4(o)?(T4(o),s=!0):S4(o)&&(v4(o,{recursive:!0,force:!0}),s=!0);let i=ye(r),a=Object.prototype.hasOwnProperty.call(i.plugins,e);return a&&$k(e,r),Cn(),{name:e,removedDir:s,removedIndexEntry:a}}function x4(e){try{return k4(e).isSymbolicLink()}catch{return!1}}ft();W();function xI(e,t={}){let n=t.logger??console,r=t.pluginsDir??Fe(),o=t.indexPath??ce(),s={...t,pluginsDir:r,indexPath:o},i=e.command("plugin").description("Manage AFK plugins (install / update / list / remove / enable / disable)");i.command("install <source> [name]").description("Install a plugin from a git URL, owner/repo shorthand, local path, or <marketplace>:<plugin>").option("-r, --ref <ref>","Install a specific tag, branch, or SHA").option("-f, --force","Replace an existing plugin with the same name").option("-y, --yes","Skip the install warning and countdown (non-interactive / CI)").action(async(a,l,c)=>{let u;try{u=Bs(a)}catch(f){cd(`Installing ${a}\u2026`).start().fail("Failed"),G(f)}let d=process.stderr.isTTY===!0&&!c.yes;if(u.type==="marketplace-ref"){let f=cd(`Installing ${u.marketplace}:${u.plugin}\u2026`).start();try{let g=await Us(u.marketplace,u.plugin,{...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},{...s,confirm:d});f.succeed(pe.green(`Installed ${pe.bold(g.key)}`)+pe.gray(` at ${g.dir}`))}catch(g){f.fail("Failed"),G(g)}return}let p=cd(`Installing ${a}\u2026`).start();try{let f={...l?{name:l}:{},...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},g=await Lu(a,f,{...s,confirm:d});p.succeed(pe.green(`Installed ${pe.bold(g.name)}`)+pe.gray(` at ${g.dir}${g.entry.ref?` (ref: ${g.entry.ref})`:""}`))}catch(f){p.fail("Failed"),G(f)}}),i.command("update [name]").description("Update one plugin, or all if no name is given").option("-r, --ref <ref>","Pin to a specific ref instead of the latest tag").action(async(a,l)=>{try{if(a){let c=cd(`Updating ${a}\u2026`).start(),u=await ph(a,l.ref?{ref:l.ref}:{},s);_4(u,c)}else{n.log(pe.cyan("Updating all plugins\u2026"));let c=await TI(s);if(c.length===0){n.log(pe.gray(" (nothing installed)"));return}for(let u of c)n.log(" "+RI(u))}}catch(c){G(c)}}),i.command("list").description("List installed plugins with their source, version, and enabled state").option("-f, --format <format>","Output format (text|json)","text").action(a=>{let l=ye(o);if(a.format==="json"){let c=Object.entries(l.plugins).map(([u,d])=>({name:u,enabled:d.enabled,...d.ref?{ref:d.ref}:{},source:d.source}));n.log(JSON.stringify({plugins:c},null,2))}else R4(l,n)}),i.command("remove <name>").description("Remove a plugin (directory + index entry)").action(a=>{let l=EI(a,{pluginsDir:r,indexPath:o});if(!l.removedDir&&!l.removedIndexEntry){n.log(pe.gray(`No plugin named "${a}" to remove.`));return}let c=[l.removedDir?"directory":null,l.removedIndexEntry?"index entry":null].filter(Boolean);n.log(pe.green(`Removed ${a}: ${c.join(" + ")}`))}),i.command("enable <name>").description("Re-enable a previously disabled plugin").action(a=>{try{Bm(a,!0,o),n.log(pe.green(`Enabled ${a}`))}catch(l){G(l)}}),i.command("disable <name>").description("Keep the plugin on disk but skip it from SDK init").action(a=>{try{Bm(a,!1,o),n.log(pe.yellow(`Disabled ${a} (dir preserved at ${r}/${a})`))}catch(l){G(l)}})}function R4(e,t){let n=Object.keys(e.plugins).sort();if(n.length===0){t.log(pe.gray("No plugins installed.")),t.log(pe.gray(" Try: afk plugin install anthropics/claude-plugins-official"));return}t.log(pe.cyan.bold(`
1951
+ `),process.exit(1)):o==="\x7F"?n.pop():n.push(o)};process.stdin.on("data",r)})}function kI(){return wI("Anthropic API key or OAuth token: ")}async function ld(e){let t=e??await kI();t||(console.error(SI.red("No token provided. Nothing saved.")),process.exit(1));let n=ut(),r,o;t.startsWith("sk-ant-oat")?(r="CLAUDE_CODE_OAUTH_TOKEN",o=["ANTHROPIC_API_KEY"]):(r="ANTHROPIC_API_KEY",o=["CLAUDE_CODE_OAUTH_TOKEN"]),Un(n,r,t,o),console.log(SI.green(`\u2713 Saved ${r} to ${n}`)),console.log(m.meta("Restart any running afk daemon to pick up the new token."))}function vI(e){e.command("login [token]").description("Save an Anthropic API key or OAuth token for afk to use").action(async t=>{let n=se(rt());if(n==="openai-compatible"||n==="openai-codex"){console.log(Ws.yellow("`afk login` is Anthropic-only.")),console.log(""),console.log("For OpenAI-backed models (gpt-*, o1*, o3*, o4*, codex-*), authenticate with one of:"),console.log(Ws.cyan(" export OPENAI_API_KEY=sk-proj-...")),console.log(Ws.cyan(" # or: export CODEX_API_KEY=...")),console.log(Ws.cyan(" codex login --api-key sk-proj-...")),console.log(""),console.log(Ws.gray("Run `afk provider auth diagnose` to see which auth source AFK will use.")),console.log(Ws.gray("To save an Anthropic key for Claude models instead, re-run with AFK_MODEL=sonnet (or similar) first."));return}await ld(t)})}import pe from"chalk";import cd from"ora";W();import{existsSync as b4}from"fs";import{join as w4}from"path";ft();ir();async function ph(e,t={},n={}){let r=n.pluginsDir??Fe(),o=n.indexPath??ce(),s=n.now??(()=>new Date),i=n.gitRunner?{runner:n.gitRunner}:{},l=ye(o).plugins[e];if(!l)throw new Error(`plugin "${e}" is not installed`);let c=w4(r,e);if(!b4(c))return{name:e,status:"missing-dir",dir:c};if(Cn(),l.sourceType==="local")return{name:e,status:"skipped-local"};await Mu(c,i);let u,d=!1;if(t.ref)u=t.ref;else{let k=await br(c,i),x=Sr(k);x!==null?(u=x,d=!0):u=l.ref??await un(c,i)}let p=`refs/remotes/origin/${u}`,f=d?null:await Ou(c,p,i),g=f!==null,h=await cn(c,i);if(g?f===h:u===l.ref)return{name:e,status:"up-to-date",ref:u,commit:h,version:ro(c).version};await wr(c,g?p:d?`refs/tags/${u}`:u,{...i,force:!0});let y=await cn(c,i),w=ro(c).version,S=s().toISOString(),E={...l,ref:u,commit:y,updatedAt:S};return sr(e,E,o),{name:e,status:"updated",fromRef:l.ref,toRef:u,commit:y,version:w}}async function TI(e={}){let t=e.indexPath??ce(),n=ye(t),r=[];for(let o of Object.keys(n.plugins))try{r.push(await ph(o,{},e))}catch(s){let i=s instanceof Error?s.message:String(s);r.push({name:o,status:"missing-dir",dir:i})}return r}W();ft();import{existsSync as S4,lstatSync as k4,rmSync as v4,unlinkSync as T4}from"fs";import{join as E4}from"path";ir();function EI(e,t={}){Fn(e);let n=t.pluginsDir??Fe(),r=t.indexPath??ce(),o=E4(n,e),s=!1;x4(o)?(T4(o),s=!0):S4(o)&&(v4(o,{recursive:!0,force:!0}),s=!0);let i=ye(r),a=Object.prototype.hasOwnProperty.call(i.plugins,e);return a&&$k(e,r),Cn(),{name:e,removedDir:s,removedIndexEntry:a}}function x4(e){try{return k4(e).isSymbolicLink()}catch{return!1}}ft();W();function xI(e,t={}){let n=t.logger??console,r=t.pluginsDir??Fe(),o=t.indexPath??ce(),s={...t,pluginsDir:r,indexPath:o},i=e.command("plugin").description("Manage AFK plugins (install / update / list / remove / enable / disable)");i.command("install <source> [name]").description("Install a plugin from a git URL, owner/repo shorthand, local path, or <marketplace>:<plugin>").option("-r, --ref <ref>","Install a specific tag, branch, or SHA").option("-f, --force","Replace an existing plugin with the same name").option("-y, --yes","Skip the install warning and countdown (non-interactive / CI)").action(async(a,l,c)=>{let u;try{u=Bs(a)}catch(f){cd(`Installing ${a}\u2026`).start().fail("Failed"),G(f)}let d=process.stderr.isTTY===!0&&!c.yes;if(u.type==="marketplace-ref"){let f=cd(`Installing ${u.marketplace}:${u.plugin}\u2026`).start();try{let g=await Us(u.marketplace,u.plugin,{...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},{...s,confirm:d});f.succeed(pe.green(`Installed ${pe.bold(g.key)}`)+pe.gray(` at ${g.dir}`))}catch(g){f.fail("Failed"),G(g)}return}let p=cd(`Installing ${a}\u2026`).start();try{let f={...l?{name:l}:{},...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},g=await Lu(a,f,{...s,confirm:d});p.succeed(pe.green(`Installed ${pe.bold(g.name)}`)+pe.gray(` at ${g.dir}${g.entry.ref?` (ref: ${g.entry.ref})`:""}`))}catch(f){p.fail("Failed"),G(f)}}),i.command("update [name]").description("Update one plugin, or all if no name is given").option("-r, --ref <ref>","Pin to a specific ref instead of the latest tag").action(async(a,l)=>{try{if(a){let c=cd(`Updating ${a}\u2026`).start(),u=await ph(a,l.ref?{ref:l.ref}:{},s);_4(u,c)}else{n.log(pe.cyan("Updating all plugins\u2026"));let c=await TI(s);if(c.length===0){n.log(pe.gray(" (nothing installed)"));return}for(let u of c)n.log(" "+RI(u))}}catch(c){G(c)}}),i.command("list").description("List installed plugins with their source, version, and enabled state").option("-f, --format <format>","Output format (text|json)","text").action(a=>{let l=ye(o);if(a.format==="json"){let c=Object.entries(l.plugins).map(([u,d])=>({name:u,enabled:d.enabled,...d.ref?{ref:d.ref}:{},source:d.source}));n.log(JSON.stringify({plugins:c},null,2))}else R4(l,n)}),i.command("remove <name>").description("Remove a plugin (directory + index entry)").action(a=>{let l=EI(a,{pluginsDir:r,indexPath:o});if(!l.removedDir&&!l.removedIndexEntry){n.log(pe.gray(`No plugin named "${a}" to remove.`));return}let c=[l.removedDir?"directory":null,l.removedIndexEntry?"index entry":null].filter(Boolean);n.log(pe.green(`Removed ${a}: ${c.join(" + ")}`))}),i.command("enable <name>").description("Re-enable a previously disabled plugin").action(a=>{try{Bm(a,!0,o),n.log(pe.green(`Enabled ${a}`))}catch(l){G(l)}}),i.command("disable <name>").description("Keep the plugin on disk but skip it from SDK init").action(a=>{try{Bm(a,!1,o),n.log(pe.yellow(`Disabled ${a} (dir preserved at ${r}/${a})`))}catch(l){G(l)}})}function R4(e,t){let n=Object.keys(e.plugins).sort();if(n.length===0){t.log(pe.gray("No plugins installed.")),t.log(pe.gray(" Try: afk plugin install anthropics/claude-plugins-official"));return}t.log(pe.cyan.bold(`
1952
1952
  Installed plugins:`));for(let r of n){let o=e.plugins[r];if(!o)continue;let s=o.enabled?pe.green("enabled "):pe.yellow("disabled"),i=o.ref?pe.blue(o.ref):pe.gray("(local)"),a=pe.gray(o.source);t.log(` ${pe.bold(r.padEnd(30))} ${s} ${i.padEnd(12)} ${a}`)}t.log("")}function RI(e){switch(e.status){case"updated":{let t=e.fromRef===e.toRef?`${e.toRef} @ ${e.commit.slice(0,7)}`:`${e.fromRef??"(none)"} \u2192 ${e.toRef}`,n=e.version?pe.gray(` [v${e.version.replace(/^v/i,"")}]`):"";return`${pe.green("\u2713")} ${pe.bold(e.name)}: ${t}${n}`}case"up-to-date":{let t=e.version?pe.gray(` [v${e.version.replace(/^v/i,"")}]`):"";return`${pe.gray("\xB7")} ${pe.bold(e.name)}: up-to-date (${e.ref})${t}`}case"skipped-local":return`${pe.gray("\xB7")} ${pe.bold(e.name)}: skipped (local source)`;case"missing-dir":return`${pe.yellow("!")} ${pe.bold(e.name)}: plugin dir missing (${e.dir})`}}function _4(e,t){let n=RI(e);e.status==="updated"?t.succeed(n):e.status==="up-to-date"||e.status==="skipped-local"?t.info(n):t.warn(n)}import ie from"chalk";import mh from"ora";ft();W();function _I(e,t={}){let n=t.logger??console,r=t.cacheDir??dn(),o=t.indexPath??ce(),s={...t,cacheDir:r,indexPath:o},i=e.command("marketplace").description("Manage AFK plugin marketplaces (install / list / plugins / install-plugin / remove / update)");i.command("install <source> [name]").description("Clone or symlink a marketplace into the local plugin cache").option("-r, --ref <ref>","Install a specific tag, branch, or SHA").option("-f, --force","Replace an existing marketplace with the same name").action(async(a,l,c)=>{let u=mh(`Installing marketplace ${a}\u2026`).start();try{let d={...l?{name:l}:{},...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},p=await Nu(a,d,s),f=p.entry.ref?` (ref: ${p.entry.ref})`:"";u.succeed(ie.green(`Installed marketplace ${ie.bold(p.name)}`)+ie.gray(`${f} at ${p.dir}`)),n.log(ie.gray(` ${p.plugins.length} plugin(s) available \u2014 run \`afk marketplace plugins ${p.name}\` to list.`))}catch(d){u.fail("Failed"),G(d)}}),i.command("list").description("List installed marketplaces with their source and ref").option("-f, --format <format>","Output format (text|json)","text").action(a=>{let l=ye(o),c=Object.entries(l.marketplaces);if(a.format==="json"){n.log(JSON.stringify({marketplaces:c.map(([u,d])=>({name:u,source:d.source,sourceType:d.sourceType,...d.ref?{ref:d.ref}:{}}))},null,2));return}if(c.length===0){n.log(ie.gray("No marketplaces installed.")),n.log(ie.gray(" Try: afk marketplace install <org>/<marketplace>"));return}n.log(ie.cyan.bold(`
1953
1953
  Installed marketplaces:`));for(let[u,d]of c.sort()){let p=d.ref?ie.blue(d.ref):ie.gray("(local)"),f=ie.gray(d.source);n.log(` ${ie.bold(u.padEnd(30))} ${p.padEnd(12)} ${f}`)}n.log("")}),i.command("plugins <name>").description("List plugins inside a marketplace, with [installed] / [available] markers").option("-f, --format <format>","Output format (text|json)","text").action((a,l)=>{try{let c=ju(a,s);if(l.format==="json"){n.log(JSON.stringify({marketplace:a,plugins:c},null,2));return}if(c.length===0){n.log(ie.gray(`Marketplace "${a}" lists no plugins.`));return}n.log(ie.cyan.bold(`
1954
1954
  Plugins in ${a}:`)),c.forEach((u,d)=>{let p=u.installed?ie.green("[\u2713]"):ie.gray("[ ]"),f=u.description?ie.gray(` \u2014 ${u.description}`):"";n.log(` ${p} ${ie.bold((d+1).toString().padStart(2))}. ${ie.bold(u.name)}${f}`)}),n.log(ie.gray(`
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  var Pd=Object.defineProperty;var pe=(t,e)=>()=>(t&&(e=t(t=0)),e);var is=(t,e)=>{for(var n in e)Pd(t,n,{get:e[n],enumerable:!0})};var Id,y,F=pe(()=>{"use strict";Id=[{name:"AFK_COMPACT_KEEP_LAST_TURNS",description:"Number of recent turns the compactor keeps verbatim during /compact. Default tuned in compact-handler.ts.",type:"number",required:!1,example:"6",category:"model"},{name:"AFK_COMPACT_MODEL",description:"Override the model used by the /compact summarizer. Falls back to a cheap default (haiku-class).",type:"string",required:!1,example:"claude-haiku-4-5",category:"model"},{name:"AFK_DEFAULT_SUBAGENT_MODEL",description:"Override the default model used when a subagent is dispatched without an explicit model.",type:"string",required:!1,example:"sonnet",category:"model"},{name:"AFK_DISABLE_PROMPT_CACHE",description:"Disable Anthropic prompt caching when set to 1/true/yes/on. Unset = caching enabled.",type:"boolean",required:!1,default:"0",example:"1",category:"model"},{name:"AFK_EFFORT",description:"Effort hint guiding adaptive-thinking depth, forwarded as Anthropic output_config.effort (model-gated; ignored where unsupported). Accepts low | medium | high | xhigh | max.",type:"string",required:!1,example:"medium",category:"model"},{name:"AFK_MAX_BUDGET_USD",description:"Per-turn USD budget ceiling. Aborts the turn when projected spend would exceed this.",type:"number",required:!1,default:"5.00",example:"10.00",category:"model"},{name:"AFK_MAX_OUTPUT_TOKENS",description:"Cap on output tokens per turn. Falls back to provider default when unset.",type:"number",required:!1,example:"8192",category:"model"},{name:"AFK_MAX_TOKENS",description:"Cap on total tokens per turn (input + output). Default 4096.",type:"number",required:!1,default:"4096",example:"8192",category:"model"},{name:"AFK_MODEL",description:"Default model for agent turns. Accepts slot names (small, medium, large), legacy aliases (opus, sonnet, haiku), the fixed-id fable alias (Claude Fable 5), or full model IDs.",type:"string",required:!1,default:"sonnet",example:"claude-opus-4-5",category:"model"},{name:"AFK_MODEL_LARGE",description:'Bind the "large" capability tier (most capable) to a model id/alias. Overrides afk.config.json models.large.',type:"string",required:!1,example:"claude-opus-4-8",category:"model"},{name:"AFK_MODEL_LARGE_API_KEY",description:'Per-slot API key for the "large" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_LARGE_BASE_URL",description:'Per-slot endpoint base URL for the "large" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_MODEL_MEDIUM",description:'Bind the "medium" capability tier (general-use) to a model id/alias. Overrides afk.config.json models.medium.',type:"string",required:!1,example:"claude-sonnet-4-6",category:"model"},{name:"AFK_MODEL_MEDIUM_API_KEY",description:'Per-slot API key for the "medium" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_MEDIUM_BASE_URL",description:'Per-slot endpoint base URL for the "medium" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_MODEL_SMALL",description:'Bind the "small" capability tier (cheap/fast) to a model id/alias. Overrides afk.config.json models.small.',type:"string",required:!1,example:"gpt-4o-mini",category:"model"},{name:"AFK_MODEL_SMALL_API_KEY",description:'Per-slot API key for the "small" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_SMALL_BASE_URL",description:'Per-slot endpoint base URL for the "small" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_PROMPT_CACHE_TTL",description:"TTL for Anthropic prompt-cache blocks. Accepts 5m or 1h.",type:"string",required:!1,default:"1h",example:"1h",category:"model"},{name:"AFK_SUGGEST_ENABLED",description:"Enable the LLM-backed ghost-text suggestion tier in the interactive REPL. Set to 1/true/yes/on to activate. Off by default.",type:"boolean",required:!1,category:"model"},{name:"AFK_SUGGEST_GHOST",description:"Enable REPL ghost-text inline suggestions (Tier-1 history/dropdown + optional Tier-2 LLM). 1 = on (default), 0 = off. Set 0/false/off/no to disable all ghost text. Tier-2 LLM is separately gated by AFK_SUGGEST_ENABLED.",type:"boolean",required:!1,default:"1",example:"0",category:"model"},{name:"AFK_SUGGEST_MODEL",description:"Override the small model used for REPL ghost-text suggestions. Falls back to AFK_COMPACT_MODEL or haiku-class for anthropic, or the session model for other providers.",type:"string",required:!1,category:"model"},{name:"AFK_TASK_BUDGET",description:"Per-task token budget ceiling. Aborts when cumulative usage would exceed it.",type:"number",required:!1,default:"100000",example:"200000",category:"model"},{name:"AFK_TEMPERATURE",description:"Numeric temperature override for model sampling. Provider default if unset.",type:"number",required:!1,example:"0.7",category:"model"},{name:"AFK_THINKING",description:"Extended-thinking mode. Accepts adaptive | disabled | enabled:<N> | enabled:max. Defaults to the model-appropriate mode when unset (adaptive on current models).",type:"string",required:!1,default:"adaptive",example:"adaptive",category:"model"},{name:"AFK_TIMEOUT_MS",description:"Per-turn timeout in milliseconds. Provider/SDK default if unset.",type:"number",required:!1,example:"120000",category:"model"},{name:"CLAUDE_MODEL",description:"Legacy alias for AFK_MODEL \u2014 supported for back-compat with pre-AFK_* deployments.",type:"string",required:!1,example:"sonnet",category:"model"},{name:"AFK_SYSTEM_PROMPT",description:'Raw operator-overlay prompt. Highest-priority overlay (over afk.config.json and AFK.md). Appended on top of the framework base (prompts/system-prompt.md) under an "# Operator configuration" header \u2014 it augments, never replaces, the base.',type:"string",required:!1,example:"You are a helpful agent.",category:"model"},{name:"AFK_DUMP_PROMPT",description:"Write the resolved system prompt to a file at startup. Accepts a path or 1 for default location.",type:"string",required:!1,example:"/tmp/afk-prompt.txt",category:"debug"},{name:"ANTHROPIC_API_KEY",description:"Anthropic API key. Tier-1 credential \u2014 overrides keychain OAuth and CLAUDE_CODE_OAUTH_TOKEN.",type:"string",required:!1,category:"auth",secret:!0},{name:"CLAUDE_CODE_OAUTH_TOKEN",description:"Claude Code OAuth token. Tier-2 credential \u2014 used when ANTHROPIC_API_KEY is unset; falls back to keychain.",type:"string",required:!1,category:"auth",secret:!0},{name:"OPENAI_API_KEY",description:"OpenAI API key for the openai-compatible provider (gpt-*, o1*, o3*, o4* models).",type:"string",required:!1,category:"auth",secret:!0},{name:"CODEX_API_KEY",description:"Fallback OpenAI API key for the openai-compatible provider, read after OPENAI_API_KEY. Legacy name from the removed @openai/codex-sdk integration \u2014 prefer OPENAI_API_KEY.",type:"string",required:!1,category:"auth",secret:!0},{name:"AFK_LOCAL_API_KEY",description:"Placeholder API key for local Anthropic-compatible servers (vllm-mlx, etc.). Set when AFK_LOCAL_BASE_URL is configured.",type:"string",required:!1,default:"local",example:"local",category:"auth",secret:!0},{name:"AFK_LOCAL_BASE_URL",description:"Base URL for a self-hosted Anthropic-compatible server. When set, routes traffic away from api.anthropic.com.",type:"string",required:!1,example:"http://127.0.0.1:8080",category:"model"},{name:"AFK_OPENAI_BASE_URL",description:"Base URL override for the OpenAI-compatible provider. Used for local shims (mlx_lm.server, Ollama, vLLM, LM Studio). The OpenAI SDK appends `/chat/completions` itself \u2014 a value ending in `/chat/completions` will be stripped at config-load time with a one-shot warning.",type:"string",required:!1,example:"http://127.0.0.1:8000/v1",category:"model"},{name:"AFK_OPENAI_USE_RESPONSES",description:"Opt the OpenAI-compatible provider into the OpenAI Responses API instead of Chat Completions for API-key sessions. Truthy values: 1, true, yes, on. The ChatGPT-subscription OAuth path uses Responses automatically regardless of this flag.",type:"boolean",required:!1,example:"1",category:"model"},{name:"AFK_OPENAI_CHATGPT_OAUTH",description:"Opt into using ChatGPT-subscription OAuth credentials from ~/.codex/auth.json (auth_mode: chatgpt) as OpenAI provider auth. Off by default. READ-ONLY: AFK never refreshes these tokens \u2014 re-run `codex` when the access token expires. Routes requests over the Responses API to the private ChatGPT backend (chatgpt.com/backend-api).",type:"boolean",required:!1,example:"1",category:"model"},{name:"AFK_PROVIDER",description:"Force provider selection (anthropic | anthropic-direct | openai | openai-compatible | openai-codex). Overrides the model-name heuristic. Same surface as the --provider CLI flag; CLI flag wins when both are set.",type:"string",required:!1,example:"openai-compatible",category:"model"},{name:"BRAVE_SEARCH_API_KEY",description:"Brave Search API subscription token, enabling web_scrape search mode. Free tier available at https://brave.com/search/api/. When unset, search mode returns an actionable error; markdown and raw modes are unaffected.",type:"string",required:!1,category:"auth",secret:!0},{name:"TELEGRAM_BOT_TOKEN",description:"Telegram bot token from @BotFather. Required to run the Telegram bot surface.",type:"string",required:!1,category:"telegram",secret:!0},{name:"AFK_TELEGRAM_BOT_TOKEN",description:"Alternative env var name for the Telegram bot token, accepted by the setup wizard.",type:"string",required:!1,category:"telegram",secret:!0},{name:"AFK_TELEGRAM_ALLOWED_CHAT_IDS",description:"Comma-separated list of Telegram chat IDs allowed to interact with the bot. Required when the bot is running.",type:"string",required:!1,example:"123456789,987654321",category:"telegram"},{name:"AFK_TELEGRAM_PRIMARY_CHAT_ID",description:"Default chat ID for outbound notifications (primary-mode routing). When unset, notifications go to the first private/DM chat in AFK_TELEGRAM_ALLOWED_CHAT_IDS. The afk.config.json telegram.notify block takes precedence.",type:"string",required:!1,example:"123456789",category:"telegram"},{name:"AFK_TELEGRAM_NOTIFY_MODE",description:"Outbound notification fan-out: primary (default \u2014 one chat), broadcast (every allowed chat), or custom (afk.config.json telegram.notify.targets). The afk.config.json telegram.notify.mode takes precedence.",type:"string",required:!1,example:"broadcast",category:"telegram"},{name:"TELEGRAM_DATA_DIR",description:"Override the directory where Telegram bot state is stored. Defaults to ~/.afk/state/telegram/.",type:"string",required:!1,category:"telegram"},{name:"TELEGRAM_VERBOSE",description:"Set to 1 to log per-message details from the Telegram bot \u2014 chat IDs, message text, latency.",type:"boolean",required:!1,example:"1",category:"telegram"},{name:"AFK_TELEGRAM_TRACE",description:"Set to 1 to dump raw bridge traffic between the agent and the Telegram bot \u2014 debugging only.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_TELEGRAM_CWD",description:"Override the working directory used by the Telegram bot when spawning agent sessions.",type:"string",required:!1,category:"telegram"},{name:"AFK_HOME",description:"Override the AFK home directory. Default: ~/.afk/.",type:"string",required:!1,default:"~/.afk",example:"/opt/afk",category:"paths"},{name:"AFK_STATE_DIR",description:"Override the AFK state directory. Default: $AFK_HOME/state/.",type:"string",required:!1,category:"paths"},{name:"AFK_FRAMEWORK_DIR",description:"Override the AFK agent-framework directory used for telemetry and briefs. Default: $AFK_HOME/agent-framework/.",type:"string",required:!1,category:"paths"},{name:"HOME",description:"Standard Unix home directory. Used as the fallback when AFK_HOME is unset.",type:"string",required:!1,category:"process"},{name:"PATH",description:"System PATH. Read for executable resolution (git, gh, etc.) in tool handlers.",type:"string",required:!1,category:"process"},{name:"AFK_DAEMON_CWD",description:"Working directory used by the daemon process for spawned agent sessions.",type:"string",required:!1,category:"daemon"},{name:"AFK_DAEMON_TASK",description:"Default task description for the daemon. Falls back to afk.config.json daemon.task.",type:"string",required:!1,category:"daemon"},{name:"AFK_DAEMON_TASK_ID",description:"Task identifier the daemon uses to scope its state directory and telemetry.",type:"string",required:!1,category:"daemon"},{name:"AFK_SESSIONSTART_COOLDOWN_MS",description:"Cooldown in milliseconds between SessionStart trigger fires in the daemon. Prevents thundering-herd on rapid restarts.",type:"number",required:!1,category:"daemon"},{name:"AFK_WORKTREE_AUTONAME",description:"Auto-rename worktree branches based on the first user message in interactive mode. 1 = on (default), 0 = off.",type:"boolean",required:!1,default:"1",example:"0",category:"worktree"},{name:"AFK_WORKTREE_BRANCH_PREFIX",description:"Branch-name prefix for AFK-managed worktrees. Default afk/. Set to empty string to drop the prefix.",type:"string",required:!1,default:"afk/",example:"wt/",category:"worktree"},{name:"AFK_WORKTREE_BASE",description:"Override the base git ref for worktrees created with --worktree. By default AFK bases worktrees on the remote's default branch (e.g. origin/main), fetched fresh. Set this to pin a different ref, or to HEAD to base on the local checkout. Overridden per-session by --worktree-base.",type:"string",required:!1,example:"origin/main",category:"worktree"},{name:"AFK_WORKTREE_BOOT_PRUNE",description:"When set, the daemon prunes stale worktrees at boot in addition to the cron-driven sweep.",type:"boolean",required:!1,category:"worktree"},{name:"AFK_WORKTREE_PRUNE_DISABLE",description:"Disable the worktree prune job entirely. Useful for long-running tests.",type:"boolean",required:!1,category:"worktree"},{name:"AFK_WORKTREE_MAX_AGE_CLEAN",description:"Maximum age (in days) before a clean worktree is auto-pruned. Default 14.",type:"number",required:!1,default:"14",category:"worktree"},{name:"AFK_WORKTREE_MAX_AGE_DIRTY",description:"Maximum age (in days) before a dirty worktree is auto-pruned. Default 30.",type:"number",required:!1,default:"30",category:"worktree"},{name:"AFK_WORKTREE_SWEEP_ROOT",description:"Override the root directory under which AFK worktrees are tracked for pruning.",type:"string",required:!1,category:"worktree"},{name:"AFK_ALLOW_PROJECT_MCP",description:"Allow loading MCP configuration from <cwd>/.mcp.json. Disabled by default \u2014 opt-in to mitigate config-injection risks.",type:"boolean",required:!1,example:"1",category:"mcp"},{name:"AFK_AUTO_ROUTING",description:"Auto-route bare slash inputs to matching skills. Applies to interactive, chat, telegram, and daemon surfaces.",type:"boolean",required:!1,example:"true",category:"routing"},{name:"AFK_INTERNAL",description:'Tier gate. Set to exactly `1` to unlock \u2014 only the literal string "1" unlocks (other truthy values like "true"/"yes" leave the tier locked). When unlocked, skills tagged `audience: \'internal\'` (e.g. /audit-fit, harvest/distill plugins) become visible at end-user surfaces (slash-command list, --help, tab-complete, system-prompt skill manifest). Default unset = public tier \u2014 internal skills are hidden. Not an access-control boundary; it gates surfacing, not the underlying registry.',type:"boolean",required:!1,example:"1",category:"routing"},{name:"AFK_SHELL_PASSTHROUGH",description:"Enable the interactive REPL `!cmd` / `!&cmd` shell-passthrough feature. On by default. Set to 0, false, off, or no (case-insensitive) to disable, so inputs beginning with ! are sent to the model as literal text instead of being executed as shell commands. Equivalent to the --no-shell-passthrough flag.",type:"boolean",required:!1,default:"1",example:"0",category:"misc"},{name:"AFK_BANNER_PLAIN",description:"Suppress the ANSI-colored banner at REPL startup. Useful for non-TTY captures and CI logs.",type:"boolean",required:!1,example:"1",category:"misc"},{name:"AFK_SPINNER_TIPS",description:"Show rotating tips in the loading spinner during long calls. 1 = on, 0 = off.",type:"boolean",required:!1,category:"misc"},{name:"AFK_SHOW_DIFFS",description:"Show inline diffs in the tool-lane output for edit/write tool calls. 1 = on, 0 = off.",type:"boolean",required:!1,category:"misc"},{name:"AFK_SKILL_STREAM_VERBOSE",description:"Verbose streaming output when a skill is dispatched. Logs sub-agent setup, intermediate events, and final result.",type:"boolean",required:!1,category:"debug"},{name:"FORCE_COLOR",description:"Standard Node convention. Force-enable ANSI color output even when stdout is not a TTY.",type:"string",required:!1,example:"1",category:"process"},{name:"NO_COLOR",description:"Standard convention (https://no-color.org). When set to any non-empty value, disables ANSI color output.",type:"string",required:!1,example:"1",category:"process"},{name:"AFK_DEBUG",description:"Enable verbose debug logging across the codebase. Accepts 1 to enable.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_DEBUG_CLIPBOARD",description:"Debug bracketed-paste and image-paste handling in the interactive REPL.",type:"boolean",required:!1,category:"debug"},{name:"AFK_DEBUG_COMPOSITOR",description:"Gate compositor phase-boundary traces to stderr; any truthy value enables.",type:"boolean",required:!1,category:"debug"},{name:"AFK_TRACE_DISABLED",description:"Disable the agent trace subsystem entirely. Set to 1 to skip trace file writes.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_SESSION_LEDGER_DISABLED",description:"Disable the per-session durable event ledger (state/sessions/<id>/events.jsonl). Set to 1 to skip ledger writes; live cross-surface watching (e.g. the Telegram /watch command) will report no activity for sessions started while disabled.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"DEBUG",description:"Standard Node `debug`-package convention. When set to 1, enables verbose logging in several modules alongside AFK_DEBUG.",type:"string",required:!1,category:"debug"},{name:"AGENT_AFK_ASCII",description:"Force the interactive REPL tool-lane renderer to ASCII-only glyphs instead of the default Unicode box-drawing set. Accepts 1/true/yes (case-insensitive). Useful for terminals whose font lacks \u2503\u251C\u2570\u251C glyphs.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AGENT_SURFACE",description:"Internal surface marker propagated to subprocesses. Identifies which AFK surface (cli, telegram, daemon) spawned the process.",type:"string",required:!1,example:"cli",category:"process"},{name:"CI",description:"Standard CI-detection convention. Auto-set by GitHub Actions, CircleCI, etc. Used to switch off TTY-only UX.",type:"string",required:!1,example:"true",category:"process"},{name:"NODE_ENV",description:"Standard Node environment marker. test | development | production. Used by routing-telemetry.ts to suppress test-time writes.",type:"string",required:!1,example:"production",category:"process"},{name:"VITEST",description:"Set automatically by Vitest. Used at runtime to short-circuit code paths that should not fire in tests.",type:"string",required:!1,category:"process"},{name:"NO_UPDATE_NOTIFIER",description:"Disable the update-available notifier on CLI startup. Standard convention shared with many Node CLIs.",type:"boolean",required:!1,category:"process"},{name:"AFK_BROWSER_HEADLESS",description:"Override the default headless mode for native browser-control tools. `1`/`true` forces headless; `0`/`false` forces headed. When unset the default is headless for daemon and subagent surfaces and headed for repl/interactive \u2014 so an operator can watch the agent work in REPL mode.",type:"boolean",required:!1,example:"1",category:"browser"},{name:"AFK_BROWSER_ALLOWED_DOMAINS",description:"Comma-separated allowlist of URL host globs. When set, browser_open and any navigation that targets a host outside the list returns status: blocked_by_policy. Unset means no allowlist (permissive). Patterns use simple `*` glob matching against the URL host. Combines with AFK_BROWSER_BLOCKED_DOMAINS \u2014 block wins.",type:"string",required:!1,example:"github.com,*.atlassian.net",category:"browser"},{name:"AFK_BROWSER_BLOCKED_DOMAINS",description:"Comma-separated blocklist of URL host globs. Browser navigation that matches any entry returns status: blocked_by_policy regardless of the allowlist.",type:"string",required:!1,example:"*.ads.example.com",category:"browser"},{name:"AFK_BROWSER_DOM_SNAPSHOTS",description:"Phase 2 opt-in: when set to 1, every browser_act writes a gzipped DOM snapshot sidecar under ~/.afk/state/witness/<sid>/browser/dom-snapshots/. Off by default because snapshots are large; useful for post-mortem analysis of failed actions.",type:"boolean",required:!1,example:"1",category:"browser"},{name:"AFK_BROWSER_BACKEND",description:"Select the browser provider backend. Phase 1 supports only `playwright`. Reserved for future `cdp` / `mcp` adapters. Unset defaults to `playwright`.",type:"string",required:!1,example:"playwright",category:"browser"},{name:"AFK_BROWSER_CONFIG",description:"Absolute path to an alternate browser config file. Overrides the default ~/.afk/config/browser.json lookup. Useful for per-project overrides in CI.",type:"string",required:!1,example:"/path/to/browser.json",category:"browser"},{name:"AFK_WRITE_DENYLIST",description:"Comma-separated list of additional path globs that the write_file tool refuses to write to.",type:"string",required:!1,example:"**/.env,**/secrets/**",category:"misc"},{name:"AFK_WRITE_DIFF",description:"Show a diff preview before each write_file tool call. Defaults provider-controlled when unset.",type:"boolean",required:!1,category:"misc"},{name:"AFK_DEMO_CLEAN",description:"Explicit opt-in to capture-mode. When set to 1, suppresses high-frequency repaint drivers (spinner ticker, live thinking-preview) so recorded artifacts contain each state once instead of once per timer tick.",type:"boolean",required:!1,example:"1",category:"misc"},{name:"SCRIPT",description:"Set by script(1) on BSD/macOS/Linux to the typescript filename while a terminal session is being recorded. Presence of a non-empty value triggers capture-mode.",type:"string",required:!1,example:"/tmp/typescript",category:"process"},{name:"ASCIINEMA_REC",description:"Set to 1 by asciinema rec while a session is being recorded. Triggers capture-mode.",type:"boolean",required:!1,example:"1",category:"process"},{name:"AFK_SESSION_ID",description:"Override the browser session ID used by the native browser-control tools. Defaults to 'default' for single-session use. Subagents inherit the parent's session by default. Set this when running multiple concurrent AFK processes that should each manage an isolated browser context.",type:"string",required:!1,default:"default",example:"session-abc123",category:"browser"},{name:"SHELL",description:"Standard POSIX env var pointing to the user's login shell binary. Used by shell-init and worktree commands to auto-detect the correct shell syntax for emitted wrapper code.",type:"string",required:!1,example:"/bin/zsh",category:"process"},{name:"PAGER",description:"Standard POSIX env var naming the user's preferred pager (with optional flags). Used by /transcript to render the full session in a scrollable viewer; falls back to `less -R` when unset.",type:"string",required:!1,example:"less -R",category:"process"},{name:"AFK_DIFF_LINES",description:"Maximum number of diff lines shown in the inline diff render during write_file tool calls. Set to 0 for no cap. Non-integer values are silently ignored and the default applies.",type:"number",required:!1,example:"50",category:"misc"},{name:"AFK_SHELL_WRAPPER",description:"Set to 1 or true by the optional afk shell wrapper function (installed via `afk shell-init`). Signals that the parent shell has the wrapper active so the post-exit cd can fire.",type:"boolean",required:!1,example:"1",category:"process"},{name:"AFK_USER_CARD_MAX_ROWS",description:'Maximum number of visual rows emitted by renderUserCard before collapsing the remainder into a dim "\u2026(N lines collapsed)" summary row. Defaults to 24. Non-integer or non-positive values are silently ignored and the default applies.',type:"number",required:!1,example:"24",category:"misc"}],y={get AFK_COMPACT_KEEP_LAST_TURNS(){return process.env.AFK_COMPACT_KEEP_LAST_TURNS},get AFK_COMPACT_MODEL(){return process.env.AFK_COMPACT_MODEL},get AFK_DEFAULT_SUBAGENT_MODEL(){return process.env.AFK_DEFAULT_SUBAGENT_MODEL},get AFK_DISABLE_PROMPT_CACHE(){return process.env.AFK_DISABLE_PROMPT_CACHE},get AFK_EFFORT(){return process.env.AFK_EFFORT},get AFK_MAX_BUDGET_USD(){return process.env.AFK_MAX_BUDGET_USD},get AFK_MAX_OUTPUT_TOKENS(){return process.env.AFK_MAX_OUTPUT_TOKENS},get AFK_MAX_TOKENS(){return process.env.AFK_MAX_TOKENS},get AFK_MODEL(){return process.env.AFK_MODEL},get AFK_MODEL_LARGE(){return process.env.AFK_MODEL_LARGE},get AFK_MODEL_LARGE_API_KEY(){return process.env.AFK_MODEL_LARGE_API_KEY},get AFK_MODEL_LARGE_BASE_URL(){return process.env.AFK_MODEL_LARGE_BASE_URL},get AFK_MODEL_MEDIUM(){return process.env.AFK_MODEL_MEDIUM},get AFK_MODEL_MEDIUM_API_KEY(){return process.env.AFK_MODEL_MEDIUM_API_KEY},get AFK_MODEL_MEDIUM_BASE_URL(){return process.env.AFK_MODEL_MEDIUM_BASE_URL},get AFK_MODEL_SMALL(){return process.env.AFK_MODEL_SMALL},get AFK_MODEL_SMALL_API_KEY(){return process.env.AFK_MODEL_SMALL_API_KEY},get AFK_MODEL_SMALL_BASE_URL(){return process.env.AFK_MODEL_SMALL_BASE_URL},get AFK_PROMPT_CACHE_TTL(){return process.env.AFK_PROMPT_CACHE_TTL},get AFK_SUGGEST_ENABLED(){return process.env.AFK_SUGGEST_ENABLED},get AFK_SUGGEST_GHOST(){return process.env.AFK_SUGGEST_GHOST},get AFK_SUGGEST_MODEL(){return process.env.AFK_SUGGEST_MODEL},get AFK_TASK_BUDGET(){return process.env.AFK_TASK_BUDGET},get AFK_TEMPERATURE(){return process.env.AFK_TEMPERATURE},get AFK_THINKING(){return process.env.AFK_THINKING},get AFK_TIMEOUT_MS(){return process.env.AFK_TIMEOUT_MS},get CLAUDE_MODEL(){return process.env.CLAUDE_MODEL},get AFK_SYSTEM_PROMPT(){return process.env.AFK_SYSTEM_PROMPT},get AFK_DUMP_PROMPT(){return process.env.AFK_DUMP_PROMPT},get ANTHROPIC_API_KEY(){return process.env.ANTHROPIC_API_KEY},get CLAUDE_CODE_OAUTH_TOKEN(){return process.env.CLAUDE_CODE_OAUTH_TOKEN},get OPENAI_API_KEY(){return process.env.OPENAI_API_KEY},get CODEX_API_KEY(){return process.env.CODEX_API_KEY},get AFK_LOCAL_API_KEY(){return process.env.AFK_LOCAL_API_KEY},get AFK_LOCAL_BASE_URL(){return process.env.AFK_LOCAL_BASE_URL},get AFK_OPENAI_BASE_URL(){return process.env.AFK_OPENAI_BASE_URL},get AFK_OPENAI_USE_RESPONSES(){return process.env.AFK_OPENAI_USE_RESPONSES},get AFK_OPENAI_CHATGPT_OAUTH(){return process.env.AFK_OPENAI_CHATGPT_OAUTH},get AFK_PROVIDER(){return process.env.AFK_PROVIDER},get BRAVE_SEARCH_API_KEY(){return process.env.BRAVE_SEARCH_API_KEY},get TELEGRAM_BOT_TOKEN(){return process.env.TELEGRAM_BOT_TOKEN},get AFK_TELEGRAM_BOT_TOKEN(){return process.env.AFK_TELEGRAM_BOT_TOKEN},get AFK_TELEGRAM_ALLOWED_CHAT_IDS(){return process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS},get AFK_TELEGRAM_PRIMARY_CHAT_ID(){return process.env.AFK_TELEGRAM_PRIMARY_CHAT_ID},get AFK_TELEGRAM_NOTIFY_MODE(){return process.env.AFK_TELEGRAM_NOTIFY_MODE},get TELEGRAM_DATA_DIR(){return process.env.TELEGRAM_DATA_DIR},get TELEGRAM_VERBOSE(){return process.env.TELEGRAM_VERBOSE},get AFK_TELEGRAM_TRACE(){return process.env.AFK_TELEGRAM_TRACE},get AFK_TELEGRAM_CWD(){return process.env.AFK_TELEGRAM_CWD},get AFK_HOME(){return process.env.AFK_HOME},get AFK_STATE_DIR(){return process.env.AFK_STATE_DIR},get AFK_FRAMEWORK_DIR(){return process.env.AFK_FRAMEWORK_DIR},get HOME(){return process.env.HOME},get PATH(){return process.env.PATH},get AFK_DAEMON_CWD(){return process.env.AFK_DAEMON_CWD},get AFK_DAEMON_TASK(){return process.env.AFK_DAEMON_TASK},get AFK_DAEMON_TASK_ID(){return process.env.AFK_DAEMON_TASK_ID},get AFK_SESSIONSTART_COOLDOWN_MS(){return process.env.AFK_SESSIONSTART_COOLDOWN_MS},get AFK_WORKTREE_AUTONAME(){return process.env.AFK_WORKTREE_AUTONAME},get AFK_WORKTREE_BRANCH_PREFIX(){return process.env.AFK_WORKTREE_BRANCH_PREFIX},get AFK_WORKTREE_BASE(){return process.env.AFK_WORKTREE_BASE},get AFK_WORKTREE_BOOT_PRUNE(){return process.env.AFK_WORKTREE_BOOT_PRUNE},get AFK_WORKTREE_PRUNE_DISABLE(){return process.env.AFK_WORKTREE_PRUNE_DISABLE},get AFK_WORKTREE_MAX_AGE_CLEAN(){return process.env.AFK_WORKTREE_MAX_AGE_CLEAN},get AFK_WORKTREE_MAX_AGE_DIRTY(){return process.env.AFK_WORKTREE_MAX_AGE_DIRTY},get AFK_WORKTREE_SWEEP_ROOT(){return process.env.AFK_WORKTREE_SWEEP_ROOT},get AFK_ALLOW_PROJECT_MCP(){return process.env.AFK_ALLOW_PROJECT_MCP},get AFK_AUTO_ROUTING(){return process.env.AFK_AUTO_ROUTING},get AFK_INTERNAL(){return process.env.AFK_INTERNAL},get AFK_SHELL_PASSTHROUGH(){return process.env.AFK_SHELL_PASSTHROUGH},get AFK_BANNER_PLAIN(){return process.env.AFK_BANNER_PLAIN},get AFK_SPINNER_TIPS(){return process.env.AFK_SPINNER_TIPS},get AFK_SHOW_DIFFS(){return process.env.AFK_SHOW_DIFFS},get AFK_SKILL_STREAM_VERBOSE(){return process.env.AFK_SKILL_STREAM_VERBOSE},get FORCE_COLOR(){return process.env.FORCE_COLOR},get NO_COLOR(){return process.env.NO_COLOR},get AFK_DEBUG(){return process.env.AFK_DEBUG},get AFK_DEBUG_CLIPBOARD(){return process.env.AFK_DEBUG_CLIPBOARD},get AFK_DEBUG_COMPOSITOR(){return process.env.AFK_DEBUG_COMPOSITOR},get AFK_TRACE_DISABLED(){return process.env.AFK_TRACE_DISABLED},get AFK_SESSION_LEDGER_DISABLED(){return process.env.AFK_SESSION_LEDGER_DISABLED},get DEBUG(){return process.env.DEBUG},get AGENT_AFK_ASCII(){return process.env.AGENT_AFK_ASCII},get AGENT_SURFACE(){return process.env.AGENT_SURFACE},get CI(){return process.env.CI},get NODE_ENV(){return process.env.NODE_ENV},get VITEST(){return process.env.VITEST},get NO_UPDATE_NOTIFIER(){return process.env.NO_UPDATE_NOTIFIER},get AFK_SESSION_ID(){return process.env.AFK_SESSION_ID},get AFK_BROWSER_HEADLESS(){return process.env.AFK_BROWSER_HEADLESS},get AFK_BROWSER_ALLOWED_DOMAINS(){return process.env.AFK_BROWSER_ALLOWED_DOMAINS},get AFK_BROWSER_BLOCKED_DOMAINS(){return process.env.AFK_BROWSER_BLOCKED_DOMAINS},get AFK_BROWSER_DOM_SNAPSHOTS(){return process.env.AFK_BROWSER_DOM_SNAPSHOTS},get AFK_BROWSER_BACKEND(){return process.env.AFK_BROWSER_BACKEND},get AFK_BROWSER_CONFIG(){return process.env.AFK_BROWSER_CONFIG},get AFK_WRITE_DENYLIST(){return process.env.AFK_WRITE_DENYLIST},get AFK_WRITE_DIFF(){return process.env.AFK_WRITE_DIFF},get AFK_DEMO_CLEAN(){return process.env.AFK_DEMO_CLEAN},get SCRIPT(){return process.env.SCRIPT},get ASCIINEMA_REC(){return process.env.ASCIINEMA_REC},get SHELL(){return process.env.SHELL},get PAGER(){return process.env.PAGER},get AFK_DIFF_LINES(){return process.env.AFK_DIFF_LINES},get AFK_SHELL_WRAPPER(){return process.env.AFK_SHELL_WRAPPER},get AFK_USER_CARD_MAX_ROWS(){return process.env.AFK_USER_CARD_MAX_ROWS}};(function(){for(let e of Id){if(!e.secret)continue;let n=Object.getOwnPropertyDescriptor(y,e.name);n&&Object.defineProperty(y,e.name,{...n,enumerable:!1})}})()});import{existsSync as Os,mkdirSync as tu,renameSync as nu,cpSync as ru,rmSync as ou}from"fs";import{join as B,dirname as Ds,isAbsolute as su}from"path";import{homedir as Fs}from"os";import{fileURLToPath as iu}from"url";function Z(){let t=y.AFK_HOME;if(t!==void 0&&t!==""){if(!su(t)||t==="/")throw new Error(`AFK_HOME must be an absolute path that is not /, got: ${t}`);return t}return B(Fs(),".afk")}function Qe(){return B(Z(),"agent-framework")}function Ls(){return B(Qe(),"forge-telemetry.jsonl")}function Ns(){return B(Qe(),"briefs")}function Mr(){return B(Z(),"skills")}function Ze(){return B(Z(),"plugins")}function $s(){return B(process.cwd(),".afk")}function Us(){return B($s(),"skills")}function Or(){return B($s(),"plugins")}function fn(){return B(Ze(),".index.json")}function Dr(){return B(mn(),"schedules.json")}function Fr(){let t=iu(import.meta.url),e=Ds(t);return B(e,"bundled-plugins")}function mn(){return B(Z(),"config")}function He(){return B(Z(),"state")}function et(){return B(He(),"sessions")}function gn(){return B(He(),"presence")}function hn(){return B(He(),"memory")}function tt(){return B(He(),"session-grants.jsonl")}function Bs(){return B(Z(),"farms")}function Hs(t){return B(Bs(),t)}function cu(t){if(!au.test(t))throw new Error(`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(t)}`)}function js(t){return cu(t),B(He(),"witness",t)}function Ks(t="default"){return B(He(),"daemon",`agent-afk@${t}`)}function Ws(){return B(mn(),"afk.config.json")}function Gs(){return B(Fs(),".afk.config.json")}function lu(){return B(Z(),"sessions")}function du(t,e){if(t!==e&&Os(t)&&!Os(e))try{tu(Ds(e),{recursive:!0});try{nu(t,e)}catch(n){if(n.code==="EXDEV")try{ru(t,e,{recursive:!0}),ou(t,{recursive:!0,force:!0})}catch(r){process.stderr.write(`[afk] migrateDirOnce: EXDEV fallback failed for ${t} \u2192 ${e}: ${String(r)}
2
- `)}}}catch{}}function qs(){du(lu(),et())}function Ct(t){return typeof t=="string"&&t.length>0&&t.length<=pu&&uu.test(t)}function yn(t){if(!Ct(t))throw new Error(`Invalid session id for ledger path: ${JSON.stringify(t)}`);return B(et(),t)}function bn(t){return B(yn(t),"events.jsonl")}var au,uu,pu,H=pe(()=>{"use strict";F();au=/^[a-zA-Z0-9_-]+$/;uu=/^[A-Za-z0-9_-]+$/,pu=128});import{readFileSync as hm}from"node:fs";import{join as ym}from"path";function bm(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Wi(t,e){return bm(e).test(t)}function vm(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(wm.has(e))return!0;if(Sm.has(e))return!1}return!1}function Gi(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function km(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function _m(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function Em(t){try{return hm(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function Am(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function qi(t){let e=t?.env??y,n=t?.readFileSync??Em,r=t?.surface??e.AGENT_SURFACE,o=vm(e.AFK_BROWSER_HEADLESS,r),s=Gi(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Gi(e.AFK_BROWSER_BLOCKED_DOMAINS),a=_m(e.AFK_BROWSER_DOM_SNAPSHOTS),c=km(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():ym(mn(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(m){throw new Error(`Failed to parse browser config at ${u}: ${String(m)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let g=Am(l,f);return g.configPath=u,g}function Zr(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(Wi(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>Wi(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var wm,Sm,eo=pe(()=>{"use strict";F();H();wm=new Set(["daemon","subagent","telegram"]),Sm=new Set(["repl","interactive","cli"])});import xm from"node:fs";import Tm from"node:path";import{chromium as Rm}from"playwright";function Pm(){try{return"3.92.1"}catch{}try{let t=Tm.resolve(import.meta.dirname,"../../../package.json"),e=xm.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Im,On,zi=pe(()=>{"use strict";Im=Pm(),On=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Rm.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${Im}`}}}});import{createHash as Cm}from"crypto";function to(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of Mm)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function Ji(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&Om.test(t.label))}function Vi(t){return Cm("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Yi(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Mm,Om,Wt=pe(()=>{"use strict";Mm=[{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}];Om=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Dm}from"node:crypto";function Fm(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Lm(t,e,n){return`el_${Dm("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Nm(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Xi(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Zi(t,e){let n=t.role??"",r=t.name??"";Qi.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Zi(s,e)}async function $m(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},ea).catch(()=>[])}async function Um(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let m=s.type;m==="checkbox"?l="checkbox":m==="radio"?l="radio":m==="button"||m==="submit"||m==="reset"?l="button":m==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:l,name:c,disabled:p};u!==void 0&&(g.value=u),f!==void 0&&(g.checked=f),o.push(g)}return o},ea).catch(()=>[])}function Bm(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Dn(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Bm(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=$m(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,g,m]=await Promise.all([i,a,c,l,d]),k,_=!1;u!==null?(k=[],Zi(u,k)):(o.push("observation skipped accessibility tree (returned null)"),_=!0,k=(await Um(t)).filter(h=>Qi.has(h.role??"")));let b=new Map;for(let v of p){let h=Xi(v.name),x=b.get(h);(!x||x.bbox.w===0&&v.bbox.w>0)&&b.set(h,v)}let S=k.map(v=>({ax:v,dom:b.get(Xi(v.name??""))})),w=r?S:S.filter(v=>v.dom?v.dom.bbox.w>0||v.dom.bbox.h>0:!0);w.sort((v,h)=>{let x=v.dom?.bbox.y??0,I=h.dom?.bbox.y??0;if(x!==I)return x-I;let T=v.dom?.bbox.x??0,O=h.dom?.bbox.x??0;return T-O}),w.length>200&&o.push("page has 200+ interactive elements; consider scoping");let A=w.slice(0,n).map((v,h)=>{let x=v.ax.role??"generic",I=v.ax.name??"",T=Lm(x,I,h),O=v.dom?.bbox??{x:0,y:0,w:0,h:0},K=v.dom?.type??null,W=null;v.ax.value!==void 0&&v.ax.value!==null&&(W=String(v.ax.value)),v.ax.checked!==void 0&&(W=String(v.ax.checked)),Ji({role:x,kind:K})&&(W="[redacted]");let Q={disabled:v.ax.disabled??!1};v.ax.checked!==void 0&&(Q.checked=v.ax.checked===!0||v.ax.checked==="mixed"),v.ax.selected!==void 0&&(Q.selected=v.ax.selected),v.ax.expanded!==void 0&&(Q.expanded=v.ax.expanded);let U;v.dom?.testId?U=`[data-testid="${v.dom.testId}"]`:v.dom?.id&&(U=`#${v.dom.id}`);let ue={id:T,role:x,label:Fm(I),kind:K,value:W,state:Q,bbox:O};return U!==void 0&&(ue.selector=U),ue}),P="idle";try{let v=await t.evaluate(()=>document.readyState);v==="loading"?P="loading":v==="interactive"?P="navigating":P="idle"}catch{P="navigating"}P!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),_&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let C=Nm(f),M=`obs_${e.observationCounter.toString(36)}`,L=new Date().toISOString();return{observationId:M,url:g,title:m,textSummary:C,interactive:A,status:{httpStatus:e.httpStatus??null,loadingState:P,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:L}}var Qi,ea,ta=pe(()=>{"use strict";Wt();Qi=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);ea="a[href], button, input, select, textarea, [role], [tabindex], label"});async function na(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function no(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>na(t,s)))).filter(o=>o!==null)}async function Hm(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function ro(t,e,n){switch(e.kind){case"element_id":return jm(t,e,n);case"selector":return Km(t,e);case"semantic":return Wm(t,e)}}async function jm(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await no(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Km(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await no(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Wm(t,e){return e.role!==void 0?Gm(t,e.text,e.role):qm(t,e.text,e)}async function Gm(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await no(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function qm(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Hm(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let m=u[0];return m===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:m.locator.nth(m.index)}}let p=u.slice(0,5),f=[];for(let m=0;m<p.length;m++){let k=p[m];if(k===void 0)continue;let _=await na(k.locator,k.index);if(_!==null){let b=`${_.role}:${_.label}:${m}`,S=0;for(let w=0;w<b.length;w++)S=S*31+b.charCodeAt(w)>>>0;f.push({..._,id:`el_${S.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var ra=pe(()=>{"use strict"});import{randomBytes as zm}from"crypto";import{mkdir as Jm,stat as Vm,writeFile as Ym}from"fs/promises";import{join as oo}from"path";import{gzip as Xm}from"zlib";import{promisify as Qm}from"util";function Zm(t){return oo(js(t),"browser")}function eg(t){return oo(Zm(t),"screenshots")}function tg(){return new Date().toISOString().replace(/[:.]/g,"-")}function ng(){return zm(3).toString("hex")}async function so(t,e,n){if(e.length>oa)throw new Error(`writeScreenshotSidecar: buffer exceeds ${oa} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=eg(t);await Jm(r,{recursive:!0});let o=`${tg()}-${ng()}-${n}.png`,s=oo(r,o);await Ym(s,e);let{size:i}=await Vm(s);return{path:s,bytes:i}}var CE,oa,sa=pe(()=>{"use strict";H();Wt();CE=Qm(Xm);oa=5*1024*1024});var aa={};is(aa,{PlaywrightProvider:()=>io});function ia(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var io,ca=pe(()=>{"use strict";zi();ta();ra();eo();Wt();sa();io=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new On(e)}async open(e){let n=Zr(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await Dn(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Dn(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await ro(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${ia(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let m=to(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(m){if(m instanceof Error&&/navigation|net::ERR/i.test(m.message))try{await d()}catch(k){l=k}else l=m}let u=r.url();if(u!==s){let m=Zr(u,this.config);if(!m.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:m.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Dn(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),g=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,g),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await ro(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${ia(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await so(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await so(n,o,r);return s}catch{return null}}}});var qe={};is(qe,{__resetBrowserRegistryForTests:()=>ag,browserProviderActive:()=>sg,closeBrowserProvider:()=>ao,getBrowserProvider:()=>og,peekBrowserProvider:()=>ig});function la(){Promise.resolve(ao()).then(()=>{process.exit(130)})}function da(){Promise.resolve(ao()).then(()=>{process.exit(143)})}function ua(){he=null}function rg(){Fn||(process.on("SIGINT",la),process.on("SIGTERM",da),process.on("exit",ua),Fn=!0)}function pa(){Fn&&(process.removeListener("SIGINT",la),process.removeListener("SIGTERM",da),process.removeListener("exit",ua),Fn=!1)}async function og(t){return he!==null?he:(Ge!==null||(Ge=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(ca(),aa)),n=qi(t),r=new e(n);return rg(),he=r,Ge=null,r})()),Ge)}async function ao(){if(he===null)return;let t=he;he=null,Ge=null,pa(),await t.shutdown()}function sg(){return he!==null}function ig(){return he}function ag(){he=null,Ge=null,pa()}var he,Ge,Fn,ze=pe(()=>{"use strict";eo();he=null,Ge=null,Fn=!1});F();function Cd(){return y.AFK_DEBUG==="1"||y.DEBUG==="1"}function D(...t){Cd()&&console.log(...t)}var oe=class extends Error{constructor(e){super(e),this.name="AbortError"}},Te=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},q=class extends Error{constructor(n,r,o,s){super(n);this.event=r;this.reason=o;this.name="HookBlockedError",s?.cause!==void 0&&(this.cause=s.cause)}event;reason;cause};var Ye=class extends Error{constructor(n,r,o){super(o??`Budget ceiling reached: $${n.toFixed(4)} cumulative >= $${r.toFixed(4)} limit`);this.runningCostUsd=n;this.maxBudgetUsd=r;this.name="BudgetExceededError"}runningCostUsd;maxBudgetUsd};async function wr(t,e){if(t)try{await t.write({kind:"tool_call",payload:e})}catch(n){D(`trace.emit tool_call failed: ${Re(n)}`)}}async function Xe(t,e){if(t)try{await t.write({kind:"hook_decision",payload:e})}catch(n){D(`trace.emit hook_decision failed: ${Re(n)}`)}}async function $e(t,e){if(t)try{await t.write({kind:"subagent_lifecycle",payload:e})}catch(n){D(`trace.emit subagent_lifecycle failed: ${Re(n)}`)}}async function as(t,e){if(t)try{await t.write({kind:"budget",payload:e})}catch(n){D(`trace.emit budget failed: ${Re(n)}`)}}async function cs(t,e){if(t)try{await t.write({kind:"abort",payload:e})}catch(n){D(`trace.emit abort failed: ${Re(n)}`)}}async function ls(t,e){if(t)try{await t.write({kind:"compaction",payload:e})}catch(n){D(`trace.emit compaction failed: ${Re(n)}`)}}async function ds(t,e){if(t)try{await t.write({kind:"closure",payload:e})}catch(n){D(`trace.emit closure failed: ${Re(n)}`)}}async function Ue(t,e){if(t)try{await t.write({kind:"session_phase",payload:e})}catch(n){D(`trace.emit session_phase failed: ${Re(n)}`)}}function Re(t){return t instanceof Error?t.message:String(t)}import Ko from"path";import{appendFileSync as ow,mkdirSync as sw}from"fs";import{dirname as iw}from"path";import Rl from"@anthropic-ai/sdk";var us="claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,extended-cache-ttl-2025-04-11",Md="effort-2025-11-24",Od="claude-cli/1.0.0 (external, cli)",Dd="x-anthropic-billing-header: cc_version=1.0.0.test; cc_entrypoint=cli; cch=00000;";function sn(t){return t.startsWith("sk-ant-oat01-")?"oauth":"api-key"}function kt(t,e,n){let r=e==="oauth"?{authToken:t}:{apiKey:t};return typeof n=="string"&&n.length>0?{...r,baseURL:n}:r}function fe(t,e,n,r){return t!=="oauth"?{}:{"anthropic-beta":r?`${us},${Md}`:us,"x-app":"cli","User-Agent":Od,"X-Claude-Code-Session-Id":e,"x-client-request-id":n}}function ps(t){return t!=="oauth"?null:[{type:"text",text:Dd}]}import Hd from"@anthropic-ai/sdk";F();var _r=["small","medium","large"],Be={small:{id:"claude-haiku-4-5-20251001"},medium:{id:"claude-sonnet-4-6"},large:{id:"claude-opus-4-8"}},Fd={haiku:"small",sonnet:"medium",sonnet_1m:"medium",opus:"large",opus_1m:"large"},Ld="auto",Er="claude-fable-5",Nd={fable:Er},kr;function Ar(t){kr=t}function Sr(t){if(t===void 0)return;let e=t.trim();return e.length>0?e:void 0}function vr(t,e,n){let r={},o=Sr(t);o&&(r.id=o);let s=Sr(e);s&&(r.baseUrl=s);let i=Sr(n);return i&&(r.apiKey=i),r}function $d(){return{small:vr(y.AFK_MODEL_SMALL,y.AFK_MODEL_SMALL_BASE_URL,y.AFK_MODEL_SMALL_API_KEY),medium:vr(y.AFK_MODEL_MEDIUM,y.AFK_MODEL_MEDIUM_BASE_URL,y.AFK_MODEL_MEDIUM_API_KEY),large:vr(y.AFK_MODEL_LARGE,y.AFK_MODEL_LARGE_BASE_URL,y.AFK_MODEL_LARGE_API_KEY)}}function fs(t){let e=$d(),n={};for(let r of _r){let o=Be[r],s=t?.[r],i=e[r],a={id:i.id??s?.id??o.id},c=s?.name;c&&(a.name=c);let l=s?.provider;l&&(a.provider=l);let d=i.baseUrl??s?.baseUrl;d&&(a.baseUrl=d);let u=i.apiKey??s?.apiKey;u&&(a.apiKey=u),n[r]=a}return n}function _t(t){return t||kr||fs()}function Et(t,e=_t()){let n=t.trim().toLowerCase();if(!n||n===Ld)return;for(let o of _r){let s=e[o].name;if(s&&s.trim().toLowerCase()===n)return o}return n==="small"||n==="medium"||n==="large"?n:Fd[n]}function xr(t,e=_t()){if(t===void 0)return{id:""};let n=Et(t,e);if(n)return e[n];let r=Nd[t.trim().toLowerCase()];return r?{id:r}:{id:t}}function At(t,e=_t()){if(t!==void 0)return xr(t,e).id}function ms(t){let e={};if(!t||typeof t!="object")return e;let n=t;for(let r of _r){let o=Bd(n[r]);o&&(e[r]=o)}return e}function Ud(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();if(e==="anthropic"||e==="anthropic-direct")return"anthropic";if(e==="openai"||e==="openai-compatible")return"openai"}function an(t){return typeof t=="string"?t.trim():""}function Bd(t){if(typeof t=="string"){let e=t.trim();return e?{id:e}:void 0}if(t&&typeof t=="object"){let e=t,n=an(e.id);if(!n)return;let r={id:n},o=an(e.name);o&&(r.name=o);let s=Ud(e.provider);s&&(r.provider=s);let i=an(e.baseUrl);i&&(r.baseUrl=i);let a=an(e.apiKey);return a&&(r.apiKey=a),r}}var Tr={opus:Be.large.id,opus_1m:Be.large.id,sonnet:Be.medium.id,sonnet_1m:Be.medium.id,haiku:Be.small.id,fable:Er};function gs(t){return t in Tr}function se(t){return At(t)}import{randomUUID as hs}from"node:crypto";async function ys(t){let{token:e,model:n,system:r,user:o,maxTokens:s=64,signal:i,clientFactory:a}=t;if(!e)throw new Error("oneShotCompletion: token required");let c=sn(e),l=kt(e,c),d=a?a(l):new Hd(l),u=hs(),p=hs(),f=fe(c,u,p),g=se(n)??n,m={};Object.keys(f).length>0&&(m.headers=f),i&&(m.signal=i);let k=await d.messages.create({model:g,max_tokens:s,system:r,messages:[{role:"user",content:o}]},Object.keys(m).length>0?m:void 0),_=[];for(let S of k.content)S.type==="text"&&_.push(S.text);let b=_.join("").trim();return b.length===0&&console.warn("oneShotCompletion: response contained no text blocks \u2014 returning empty string"),b}import{execFileSync as bs}from"child_process";import{existsSync as jd,readFileSync as Kd,writeFileSync as Wd}from"fs";import{homedir as ws,userInfo as Ss}from"os";import{join as vs}from"path";var Gd="9d1c250a-e61b-44d9-88ed-5944d1962f5e",qd="https://platform.claude.com/v1/oauth/token",zd=300*1e3;function ie(){let t=ks();if(t===void 0)return;let e=_s(t);if(e!==void 0){if(e.expiresAt!==void 0&&e.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return e.accessToken}}async function Rr(){let t=ks();if(t===void 0)return;let e=_s(t);if(e===void 0)return;if(e.expiresAt!==void 0&&e.expiresAt>Date.now()+zd)return e.accessToken;if(!e.refreshToken){process.stderr.write("agent-afk: OAuth token expired and no refresh token available. Run `claude login` to refresh.\n");return}let n=await Jd(e.refreshToken);if(!n){process.stderr.write("agent-afk: OAuth token refresh failed. Run `claude login` to refresh.\n");return}try{let r={};try{r=JSON.parse(t)}catch{}let o=r.claudeAiOauth??{};r.claudeAiOauth={...o,accessToken:n.accessToken,expiresAt:n.expiresAt,...n.refreshToken!==void 0?{refreshToken:n.refreshToken}:{}},Vd(JSON.stringify(r))}catch{process.stderr.write(`agent-afk: Refreshed OAuth token but failed to write back to credential store.
2
+ `)}}}catch{}}function qs(){du(lu(),et())}function Ct(t){return typeof t=="string"&&t.length>0&&t.length<=pu&&uu.test(t)}function yn(t){if(!Ct(t))throw new Error(`Invalid session id for ledger path: ${JSON.stringify(t)}`);return B(et(),t)}function bn(t){return B(yn(t),"events.jsonl")}var au,uu,pu,H=pe(()=>{"use strict";F();au=/^[a-zA-Z0-9_-]+$/;uu=/^[A-Za-z0-9_-]+$/,pu=128});import{readFileSync as hm}from"node:fs";import{join as ym}from"path";function bm(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Wi(t,e){return bm(e).test(t)}function vm(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(wm.has(e))return!0;if(Sm.has(e))return!1}return!1}function Gi(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function km(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function _m(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function Em(t){try{return hm(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function Am(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function qi(t){let e=t?.env??y,n=t?.readFileSync??Em,r=t?.surface??e.AGENT_SURFACE,o=vm(e.AFK_BROWSER_HEADLESS,r),s=Gi(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Gi(e.AFK_BROWSER_BLOCKED_DOMAINS),a=_m(e.AFK_BROWSER_DOM_SNAPSHOTS),c=km(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():ym(mn(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(m){throw new Error(`Failed to parse browser config at ${u}: ${String(m)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let g=Am(l,f);return g.configPath=u,g}function Zr(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(Wi(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>Wi(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var wm,Sm,eo=pe(()=>{"use strict";F();H();wm=new Set(["daemon","subagent","telegram"]),Sm=new Set(["repl","interactive","cli"])});import xm from"node:fs";import Tm from"node:path";import{chromium as Rm}from"playwright";function Pm(){try{return"3.92.2"}catch{}try{let t=Tm.resolve(import.meta.dirname,"../../../package.json"),e=xm.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Im,On,zi=pe(()=>{"use strict";Im=Pm(),On=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Rm.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${Im}`}}}});import{createHash as Cm}from"crypto";function to(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of Mm)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function Ji(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&Om.test(t.label))}function Vi(t){return Cm("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Yi(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Mm,Om,Wt=pe(()=>{"use strict";Mm=[{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}];Om=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Dm}from"node:crypto";function Fm(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Lm(t,e,n){return`el_${Dm("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Nm(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Xi(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Zi(t,e){let n=t.role??"",r=t.name??"";Qi.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Zi(s,e)}async function $m(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},ea).catch(()=>[])}async function Um(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let m=s.type;m==="checkbox"?l="checkbox":m==="radio"?l="radio":m==="button"||m==="submit"||m==="reset"?l="button":m==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,g={role:l,name:c,disabled:p};u!==void 0&&(g.value=u),f!==void 0&&(g.checked=f),o.push(g)}return o},ea).catch(()=>[])}function Bm(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Dn(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Bm(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=$m(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,g,m]=await Promise.all([i,a,c,l,d]),k,_=!1;u!==null?(k=[],Zi(u,k)):(o.push("observation skipped accessibility tree (returned null)"),_=!0,k=(await Um(t)).filter(h=>Qi.has(h.role??"")));let b=new Map;for(let v of p){let h=Xi(v.name),x=b.get(h);(!x||x.bbox.w===0&&v.bbox.w>0)&&b.set(h,v)}let S=k.map(v=>({ax:v,dom:b.get(Xi(v.name??""))})),w=r?S:S.filter(v=>v.dom?v.dom.bbox.w>0||v.dom.bbox.h>0:!0);w.sort((v,h)=>{let x=v.dom?.bbox.y??0,I=h.dom?.bbox.y??0;if(x!==I)return x-I;let T=v.dom?.bbox.x??0,O=h.dom?.bbox.x??0;return T-O}),w.length>200&&o.push("page has 200+ interactive elements; consider scoping");let A=w.slice(0,n).map((v,h)=>{let x=v.ax.role??"generic",I=v.ax.name??"",T=Lm(x,I,h),O=v.dom?.bbox??{x:0,y:0,w:0,h:0},K=v.dom?.type??null,W=null;v.ax.value!==void 0&&v.ax.value!==null&&(W=String(v.ax.value)),v.ax.checked!==void 0&&(W=String(v.ax.checked)),Ji({role:x,kind:K})&&(W="[redacted]");let Q={disabled:v.ax.disabled??!1};v.ax.checked!==void 0&&(Q.checked=v.ax.checked===!0||v.ax.checked==="mixed"),v.ax.selected!==void 0&&(Q.selected=v.ax.selected),v.ax.expanded!==void 0&&(Q.expanded=v.ax.expanded);let U;v.dom?.testId?U=`[data-testid="${v.dom.testId}"]`:v.dom?.id&&(U=`#${v.dom.id}`);let ue={id:T,role:x,label:Fm(I),kind:K,value:W,state:Q,bbox:O};return U!==void 0&&(ue.selector=U),ue}),P="idle";try{let v=await t.evaluate(()=>document.readyState);v==="loading"?P="loading":v==="interactive"?P="navigating":P="idle"}catch{P="navigating"}P!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),_&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let C=Nm(f),M=`obs_${e.observationCounter.toString(36)}`,L=new Date().toISOString();return{observationId:M,url:g,title:m,textSummary:C,interactive:A,status:{httpStatus:e.httpStatus??null,loadingState:P,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:L}}var Qi,ea,ta=pe(()=>{"use strict";Wt();Qi=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);ea="a[href], button, input, select, textarea, [role], [tabindex], label"});async function na(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function no(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>na(t,s)))).filter(o=>o!==null)}async function Hm(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function ro(t,e,n){switch(e.kind){case"element_id":return jm(t,e,n);case"selector":return Km(t,e);case"semantic":return Wm(t,e)}}async function jm(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await no(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Km(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await no(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Wm(t,e){return e.role!==void 0?Gm(t,e.text,e.role):qm(t,e.text,e)}async function Gm(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await no(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function qm(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Hm(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let m=u[0];return m===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:m.locator.nth(m.index)}}let p=u.slice(0,5),f=[];for(let m=0;m<p.length;m++){let k=p[m];if(k===void 0)continue;let _=await na(k.locator,k.index);if(_!==null){let b=`${_.role}:${_.label}:${m}`,S=0;for(let w=0;w<b.length;w++)S=S*31+b.charCodeAt(w)>>>0;f.push({..._,id:`el_${S.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var ra=pe(()=>{"use strict"});import{randomBytes as zm}from"crypto";import{mkdir as Jm,stat as Vm,writeFile as Ym}from"fs/promises";import{join as oo}from"path";import{gzip as Xm}from"zlib";import{promisify as Qm}from"util";function Zm(t){return oo(js(t),"browser")}function eg(t){return oo(Zm(t),"screenshots")}function tg(){return new Date().toISOString().replace(/[:.]/g,"-")}function ng(){return zm(3).toString("hex")}async function so(t,e,n){if(e.length>oa)throw new Error(`writeScreenshotSidecar: buffer exceeds ${oa} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=eg(t);await Jm(r,{recursive:!0});let o=`${tg()}-${ng()}-${n}.png`,s=oo(r,o);await Ym(s,e);let{size:i}=await Vm(s);return{path:s,bytes:i}}var CE,oa,sa=pe(()=>{"use strict";H();Wt();CE=Qm(Xm);oa=5*1024*1024});var aa={};is(aa,{PlaywrightProvider:()=>io});function ia(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var io,ca=pe(()=>{"use strict";zi();ta();ra();eo();Wt();sa();io=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new On(e)}async open(e){let n=Zr(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await Dn(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Dn(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await ro(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${ia(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let m=to(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(m){if(m instanceof Error&&/navigation|net::ERR/i.test(m.message))try{await d()}catch(k){l=k}else l=m}let u=r.url();if(u!==s){let m=Zr(u,this.config);if(!m.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:m.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Dn(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),g=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,g),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await ro(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${ia(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await so(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await so(n,o,r);return s}catch{return null}}}});var qe={};is(qe,{__resetBrowserRegistryForTests:()=>ag,browserProviderActive:()=>sg,closeBrowserProvider:()=>ao,getBrowserProvider:()=>og,peekBrowserProvider:()=>ig});function la(){Promise.resolve(ao()).then(()=>{process.exit(130)})}function da(){Promise.resolve(ao()).then(()=>{process.exit(143)})}function ua(){he=null}function rg(){Fn||(process.on("SIGINT",la),process.on("SIGTERM",da),process.on("exit",ua),Fn=!0)}function pa(){Fn&&(process.removeListener("SIGINT",la),process.removeListener("SIGTERM",da),process.removeListener("exit",ua),Fn=!1)}async function og(t){return he!==null?he:(Ge!==null||(Ge=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(ca(),aa)),n=qi(t),r=new e(n);return rg(),he=r,Ge=null,r})()),Ge)}async function ao(){if(he===null)return;let t=he;he=null,Ge=null,pa(),await t.shutdown()}function sg(){return he!==null}function ig(){return he}function ag(){he=null,Ge=null,pa()}var he,Ge,Fn,ze=pe(()=>{"use strict";eo();he=null,Ge=null,Fn=!1});F();function Cd(){return y.AFK_DEBUG==="1"||y.DEBUG==="1"}function D(...t){Cd()&&console.log(...t)}var oe=class extends Error{constructor(e){super(e),this.name="AbortError"}},Te=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},q=class extends Error{constructor(n,r,o,s){super(n);this.event=r;this.reason=o;this.name="HookBlockedError",s?.cause!==void 0&&(this.cause=s.cause)}event;reason;cause};var Ye=class extends Error{constructor(n,r,o){super(o??`Budget ceiling reached: $${n.toFixed(4)} cumulative >= $${r.toFixed(4)} limit`);this.runningCostUsd=n;this.maxBudgetUsd=r;this.name="BudgetExceededError"}runningCostUsd;maxBudgetUsd};async function wr(t,e){if(t)try{await t.write({kind:"tool_call",payload:e})}catch(n){D(`trace.emit tool_call failed: ${Re(n)}`)}}async function Xe(t,e){if(t)try{await t.write({kind:"hook_decision",payload:e})}catch(n){D(`trace.emit hook_decision failed: ${Re(n)}`)}}async function $e(t,e){if(t)try{await t.write({kind:"subagent_lifecycle",payload:e})}catch(n){D(`trace.emit subagent_lifecycle failed: ${Re(n)}`)}}async function as(t,e){if(t)try{await t.write({kind:"budget",payload:e})}catch(n){D(`trace.emit budget failed: ${Re(n)}`)}}async function cs(t,e){if(t)try{await t.write({kind:"abort",payload:e})}catch(n){D(`trace.emit abort failed: ${Re(n)}`)}}async function ls(t,e){if(t)try{await t.write({kind:"compaction",payload:e})}catch(n){D(`trace.emit compaction failed: ${Re(n)}`)}}async function ds(t,e){if(t)try{await t.write({kind:"closure",payload:e})}catch(n){D(`trace.emit closure failed: ${Re(n)}`)}}async function Ue(t,e){if(t)try{await t.write({kind:"session_phase",payload:e})}catch(n){D(`trace.emit session_phase failed: ${Re(n)}`)}}function Re(t){return t instanceof Error?t.message:String(t)}import Ko from"path";import{appendFileSync as ow,mkdirSync as sw}from"fs";import{dirname as iw}from"path";import Rl from"@anthropic-ai/sdk";var us="claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,extended-cache-ttl-2025-04-11",Md="effort-2025-11-24",Od="claude-cli/1.0.0 (external, cli)",Dd="x-anthropic-billing-header: cc_version=1.0.0.test; cc_entrypoint=cli; cch=00000;";function sn(t){return t.startsWith("sk-ant-oat01-")?"oauth":"api-key"}function kt(t,e,n){let r=e==="oauth"?{authToken:t}:{apiKey:t};return typeof n=="string"&&n.length>0?{...r,baseURL:n}:r}function fe(t,e,n,r){return t!=="oauth"?{}:{"anthropic-beta":r?`${us},${Md}`:us,"x-app":"cli","User-Agent":Od,"X-Claude-Code-Session-Id":e,"x-client-request-id":n}}function ps(t){return t!=="oauth"?null:[{type:"text",text:Dd}]}import Hd from"@anthropic-ai/sdk";F();var _r=["small","medium","large"],Be={small:{id:"claude-haiku-4-5-20251001"},medium:{id:"claude-sonnet-4-6"},large:{id:"claude-opus-4-8"}},Fd={haiku:"small",sonnet:"medium",sonnet_1m:"medium",opus:"large",opus_1m:"large"},Ld="auto",Er="claude-fable-5",Nd={fable:Er},kr;function Ar(t){kr=t}function Sr(t){if(t===void 0)return;let e=t.trim();return e.length>0?e:void 0}function vr(t,e,n){let r={},o=Sr(t);o&&(r.id=o);let s=Sr(e);s&&(r.baseUrl=s);let i=Sr(n);return i&&(r.apiKey=i),r}function $d(){return{small:vr(y.AFK_MODEL_SMALL,y.AFK_MODEL_SMALL_BASE_URL,y.AFK_MODEL_SMALL_API_KEY),medium:vr(y.AFK_MODEL_MEDIUM,y.AFK_MODEL_MEDIUM_BASE_URL,y.AFK_MODEL_MEDIUM_API_KEY),large:vr(y.AFK_MODEL_LARGE,y.AFK_MODEL_LARGE_BASE_URL,y.AFK_MODEL_LARGE_API_KEY)}}function fs(t){let e=$d(),n={};for(let r of _r){let o=Be[r],s=t?.[r],i=e[r],a={id:i.id??s?.id??o.id},c=s?.name;c&&(a.name=c);let l=s?.provider;l&&(a.provider=l);let d=i.baseUrl??s?.baseUrl;d&&(a.baseUrl=d);let u=i.apiKey??s?.apiKey;u&&(a.apiKey=u),n[r]=a}return n}function _t(t){return t||kr||fs()}function Et(t,e=_t()){let n=t.trim().toLowerCase();if(!n||n===Ld)return;for(let o of _r){let s=e[o].name;if(s&&s.trim().toLowerCase()===n)return o}return n==="small"||n==="medium"||n==="large"?n:Fd[n]}function xr(t,e=_t()){if(t===void 0)return{id:""};let n=Et(t,e);if(n)return e[n];let r=Nd[t.trim().toLowerCase()];return r?{id:r}:{id:t}}function At(t,e=_t()){if(t!==void 0)return xr(t,e).id}function ms(t){let e={};if(!t||typeof t!="object")return e;let n=t;for(let r of _r){let o=Bd(n[r]);o&&(e[r]=o)}return e}function Ud(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();if(e==="anthropic"||e==="anthropic-direct")return"anthropic";if(e==="openai"||e==="openai-compatible")return"openai"}function an(t){return typeof t=="string"?t.trim():""}function Bd(t){if(typeof t=="string"){let e=t.trim();return e?{id:e}:void 0}if(t&&typeof t=="object"){let e=t,n=an(e.id);if(!n)return;let r={id:n},o=an(e.name);o&&(r.name=o);let s=Ud(e.provider);s&&(r.provider=s);let i=an(e.baseUrl);i&&(r.baseUrl=i);let a=an(e.apiKey);return a&&(r.apiKey=a),r}}var Tr={opus:Be.large.id,opus_1m:Be.large.id,sonnet:Be.medium.id,sonnet_1m:Be.medium.id,haiku:Be.small.id,fable:Er};function gs(t){return t in Tr}function se(t){return At(t)}import{randomUUID as hs}from"node:crypto";async function ys(t){let{token:e,model:n,system:r,user:o,maxTokens:s=64,signal:i,clientFactory:a}=t;if(!e)throw new Error("oneShotCompletion: token required");let c=sn(e),l=kt(e,c),d=a?a(l):new Hd(l),u=hs(),p=hs(),f=fe(c,u,p),g=se(n)??n,m={};Object.keys(f).length>0&&(m.headers=f),i&&(m.signal=i);let k=await d.messages.create({model:g,max_tokens:s,system:r,messages:[{role:"user",content:o}]},Object.keys(m).length>0?m:void 0),_=[];for(let S of k.content)S.type==="text"&&_.push(S.text);let b=_.join("").trim();return b.length===0&&console.warn("oneShotCompletion: response contained no text blocks \u2014 returning empty string"),b}import{execFileSync as bs}from"child_process";import{existsSync as jd,readFileSync as Kd,writeFileSync as Wd}from"fs";import{homedir as ws,userInfo as Ss}from"os";import{join as vs}from"path";var Gd="9d1c250a-e61b-44d9-88ed-5944d1962f5e",qd="https://platform.claude.com/v1/oauth/token",zd=300*1e3;function ie(){let t=ks();if(t===void 0)return;let e=_s(t);if(e!==void 0){if(e.expiresAt!==void 0&&e.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return e.accessToken}}async function Rr(){let t=ks();if(t===void 0)return;let e=_s(t);if(e===void 0)return;if(e.expiresAt!==void 0&&e.expiresAt>Date.now()+zd)return e.accessToken;if(!e.refreshToken){process.stderr.write("agent-afk: OAuth token expired and no refresh token available. Run `claude login` to refresh.\n");return}let n=await Jd(e.refreshToken);if(!n){process.stderr.write("agent-afk: OAuth token refresh failed. Run `claude login` to refresh.\n");return}try{let r={};try{r=JSON.parse(t)}catch{}let o=r.claudeAiOauth??{};r.claudeAiOauth={...o,accessToken:n.accessToken,expiresAt:n.expiresAt,...n.refreshToken!==void 0?{refreshToken:n.refreshToken}:{}},Vd(JSON.stringify(r))}catch{process.stderr.write(`agent-afk: Refreshed OAuth token but failed to write back to credential store.
3
3
  `)}return n.accessToken}function ks(){if(process.platform==="darwin")try{return bs("security",["find-generic-password","-s","Claude Code-credentials","-a",Ss().username,"-w"],{stdio:["ignore","pipe","ignore"],encoding:"utf-8"}).trim()}catch{return}if(process.platform==="linux"){let t=vs(ws(),".claude",".credentials.json");if(!jd(t))return;try{return Kd(t,"utf-8")}catch{return}}}function _s(t){let e;try{e=JSON.parse(t)}catch{return}if(typeof e!="object"||e===null)return;let n=e.claudeAiOauth;if(typeof n!="object"||n===null)return;let r=n,o=r.accessToken;if(typeof o!="string"||o.length===0)return;let s={accessToken:o},i=r.refreshToken;typeof i=="string"&&i.length>0&&(s.refreshToken=i);let a=r.expiresAt;return typeof a=="number"&&(s.expiresAt=a),s}async function Jd(t){try{let e=await fetch(qd,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:t,client_id:Gd})});if(!e.ok)return;let n=await e.json(),r=n.access_token,o=n.expires_in;if(typeof r!="string"||typeof o!="number")return;let s=n.refresh_token;return{accessToken:r,expiresAt:Date.now()+o*1e3,...typeof s=="string"&&s.length>0?{refreshToken:s}:{}}}catch{return}}function xt(t){if(!t||t.length<3)return"token:(unknown)";try{let n=t.split(".");if(n.length<2)throw new Error("not a JWT");let r=Buffer.from(n[1],"base64url").toString("utf-8"),o=JSON.parse(r),s=typeof o.email=="string"&&o.email||typeof o.sub=="string"&&o.sub||typeof o.account_id=="string"&&o.account_id||typeof o.preferred_username=="string"&&o.preferred_username;if(s)return s}catch{}return`token:${t.length>=8?t.slice(-8):t}`}function Vd(t){if(process.platform==="darwin")bs("security",["add-generic-password","-U","-s","Claude Code-credentials","-a",Ss().username,"-w",t],{stdio:["ignore","ignore","ignore"]});else if(process.platform==="linux"){let e=vs(ws(),".claude",".credentials.json");Yd(e,t)}}function Yd(t,e){Wd(t,e,{encoding:"utf-8",mode:384})}import{randomUUID as El}from"node:crypto";F();var Xd="1h";function cn(t){if(typeof t?.baseUrl=="string"&&t.baseUrl.length>0)return!1;let e=y.AFK_DISABLE_PROMPT_CACHE;if(e===void 0||e.length===0)return!0;let n=e.toLowerCase();return!(n==="1"||n==="true"||n==="yes"||n==="on")}function ln(){let t=y.AFK_PROMPT_CACHE_TTL;return t==="5m"?"5m":t==="1h"?"1h":Xd}function Es(t,e){if(t.length===0)return t;let n=t[t.length-1],r=xs(n,e);return r===n?t:[...t.slice(0,-1),r]}function As(t,e){if(t.length===0)return t;let n=t[t.length-1],r=Qd(n,e);return r===n?t:[...t.slice(0,-1),r]}function Qd(t,e){let n=t.content;if(typeof n=="string")return n.length===0?t:{...t,content:[{type:"text",text:n,cache_control:{type:"ephemeral",ttl:e}}]};if(!Array.isArray(n)||n.length===0)return t;let r=n[n.length-1],o=xs(r,e);return o===r?t:{...t,content:[...n.slice(0,-1),o]}}function xs(t,e){return t.type==="thinking"||t.type==="redacted_thinking"?t:{...t,cache_control:{type:"ephemeral",ttl:e}}}var Pr=["## Plan mode is active","","Write-class tools (`write_file`, `edit_file`, write-intent `bash`) are refused at the hook layer.","The user has asked you to plan, not yet to act. Treat this turn as planning work.","","Traverse the shape that matches the work \u2014 skip steps the terrain already covers, do not skip steps the terrain hides:",""," unknown field \u2192 ground the current terrain \u2192 gather missing codebase context \u2192"," research missing external context \u2192 reveal chaos / constraints / risks \u2192"," name the failure geometry \u2192 form a candidate plan \u2192 apply adversarial pressure \u2192 embody the final plan","","Reach for these skills (invoke via the `skill` tool) when the cost of skipping exceeds the cost of dispatching:"," - `ground-state` \u2014 survey git, infra, memory before non-trivial work"," - `gather` \u2014 parallel context-gathering for a code area"," - `research` \u2014 parallel external + local context for the current task"," - `devils-advocate` \u2014 generate alternatives and rank them before committing"," - `shadow-verify` \u2014 independently re-derive load-bearing claims","","Do not declare readiness silently. When the plan is ready, state: chosen approach, risks named, and alternatives considered. The user will then exit plan mode with `/plan off`, which has you save this plan to a file and implement it (Shift+Tab exits without implementing) \u2014 so keep the plan concrete and complete enough to act on directly."].join(`
4
4
  `);function Ts(t){return t!=="plan"?null:{type:"text",text:Pr}}import{z as j}from"zod";import{mkdir as Ac,appendFile as xc}from"fs/promises";import{join as Co}from"path";var Rs={"audit-fit":{"01-skill-inspector.md":`# Skill Inspector
5
5
 
package/dist/telegram.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var fp=Object.defineProperty;var me=(t,e)=>()=>(t&&(e=t(t=0)),e);var js=(t,e)=>{for(var n in e)fp(t,n,{get:e[n],enumerable:!0})};var mp,S,N=me(()=>{"use strict";mp=[{name:"AFK_COMPACT_KEEP_LAST_TURNS",description:"Number of recent turns the compactor keeps verbatim during /compact. Default tuned in compact-handler.ts.",type:"number",required:!1,example:"6",category:"model"},{name:"AFK_COMPACT_MODEL",description:"Override the model used by the /compact summarizer. Falls back to a cheap default (haiku-class).",type:"string",required:!1,example:"claude-haiku-4-5",category:"model"},{name:"AFK_DEFAULT_SUBAGENT_MODEL",description:"Override the default model used when a subagent is dispatched without an explicit model.",type:"string",required:!1,example:"sonnet",category:"model"},{name:"AFK_DISABLE_PROMPT_CACHE",description:"Disable Anthropic prompt caching when set to 1/true/yes/on. Unset = caching enabled.",type:"boolean",required:!1,default:"0",example:"1",category:"model"},{name:"AFK_EFFORT",description:"Effort hint guiding adaptive-thinking depth, forwarded as Anthropic output_config.effort (model-gated; ignored where unsupported). Accepts low | medium | high | xhigh | max.",type:"string",required:!1,example:"medium",category:"model"},{name:"AFK_MAX_BUDGET_USD",description:"Per-turn USD budget ceiling. Aborts the turn when projected spend would exceed this.",type:"number",required:!1,default:"5.00",example:"10.00",category:"model"},{name:"AFK_MAX_OUTPUT_TOKENS",description:"Cap on output tokens per turn. Falls back to provider default when unset.",type:"number",required:!1,example:"8192",category:"model"},{name:"AFK_MAX_TOKENS",description:"Cap on total tokens per turn (input + output). Default 4096.",type:"number",required:!1,default:"4096",example:"8192",category:"model"},{name:"AFK_MODEL",description:"Default model for agent turns. Accepts slot names (small, medium, large), legacy aliases (opus, sonnet, haiku), the fixed-id fable alias (Claude Fable 5), or full model IDs.",type:"string",required:!1,default:"sonnet",example:"claude-opus-4-5",category:"model"},{name:"AFK_MODEL_LARGE",description:'Bind the "large" capability tier (most capable) to a model id/alias. Overrides afk.config.json models.large.',type:"string",required:!1,example:"claude-opus-4-8",category:"model"},{name:"AFK_MODEL_LARGE_API_KEY",description:'Per-slot API key for the "large" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_LARGE_BASE_URL",description:'Per-slot endpoint base URL for the "large" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_MODEL_MEDIUM",description:'Bind the "medium" capability tier (general-use) to a model id/alias. Overrides afk.config.json models.medium.',type:"string",required:!1,example:"claude-sonnet-4-6",category:"model"},{name:"AFK_MODEL_MEDIUM_API_KEY",description:'Per-slot API key for the "medium" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_MEDIUM_BASE_URL",description:'Per-slot endpoint base URL for the "medium" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_MODEL_SMALL",description:'Bind the "small" capability tier (cheap/fast) to a model id/alias. Overrides afk.config.json models.small.',type:"string",required:!1,example:"gpt-4o-mini",category:"model"},{name:"AFK_MODEL_SMALL_API_KEY",description:'Per-slot API key for the "small" tier (Stage 2). Overrides global credentials for this tier only.',type:"string",required:!1,category:"model",secret:!0},{name:"AFK_MODEL_SMALL_BASE_URL",description:'Per-slot endpoint base URL for the "small" tier (Stage 2). Anthropic Messages base or OpenAI-compatible base per the tier provider.',type:"string",required:!1,example:"http://localhost:8080/v1",category:"model"},{name:"AFK_PROMPT_CACHE_TTL",description:"TTL for Anthropic prompt-cache blocks. Accepts 5m or 1h.",type:"string",required:!1,default:"1h",example:"1h",category:"model"},{name:"AFK_SUGGEST_ENABLED",description:"Enable the LLM-backed ghost-text suggestion tier in the interactive REPL. Set to 1/true/yes/on to activate. Off by default.",type:"boolean",required:!1,category:"model"},{name:"AFK_SUGGEST_GHOST",description:"Enable REPL ghost-text inline suggestions (Tier-1 history/dropdown + optional Tier-2 LLM). 1 = on (default), 0 = off. Set 0/false/off/no to disable all ghost text. Tier-2 LLM is separately gated by AFK_SUGGEST_ENABLED.",type:"boolean",required:!1,default:"1",example:"0",category:"model"},{name:"AFK_SUGGEST_MODEL",description:"Override the small model used for REPL ghost-text suggestions. Falls back to AFK_COMPACT_MODEL or haiku-class for anthropic, or the session model for other providers.",type:"string",required:!1,category:"model"},{name:"AFK_TASK_BUDGET",description:"Per-task token budget ceiling. Aborts when cumulative usage would exceed it.",type:"number",required:!1,default:"100000",example:"200000",category:"model"},{name:"AFK_TEMPERATURE",description:"Numeric temperature override for model sampling. Provider default if unset.",type:"number",required:!1,example:"0.7",category:"model"},{name:"AFK_THINKING",description:"Extended-thinking mode. Accepts adaptive | disabled | enabled:<N> | enabled:max. Defaults to the model-appropriate mode when unset (adaptive on current models).",type:"string",required:!1,default:"adaptive",example:"adaptive",category:"model"},{name:"AFK_TIMEOUT_MS",description:"Per-turn timeout in milliseconds. Provider/SDK default if unset.",type:"number",required:!1,example:"120000",category:"model"},{name:"CLAUDE_MODEL",description:"Legacy alias for AFK_MODEL \u2014 supported for back-compat with pre-AFK_* deployments.",type:"string",required:!1,example:"sonnet",category:"model"},{name:"AFK_SYSTEM_PROMPT",description:'Raw operator-overlay prompt. Highest-priority overlay (over afk.config.json and AFK.md). Appended on top of the framework base (prompts/system-prompt.md) under an "# Operator configuration" header \u2014 it augments, never replaces, the base.',type:"string",required:!1,example:"You are a helpful agent.",category:"model"},{name:"AFK_DUMP_PROMPT",description:"Write the resolved system prompt to a file at startup. Accepts a path or 1 for default location.",type:"string",required:!1,example:"/tmp/afk-prompt.txt",category:"debug"},{name:"ANTHROPIC_API_KEY",description:"Anthropic API key. Tier-1 credential \u2014 overrides keychain OAuth and CLAUDE_CODE_OAUTH_TOKEN.",type:"string",required:!1,category:"auth",secret:!0},{name:"CLAUDE_CODE_OAUTH_TOKEN",description:"Claude Code OAuth token. Tier-2 credential \u2014 used when ANTHROPIC_API_KEY is unset; falls back to keychain.",type:"string",required:!1,category:"auth",secret:!0},{name:"OPENAI_API_KEY",description:"OpenAI API key for the openai-compatible provider (gpt-*, o1*, o3*, o4* models).",type:"string",required:!1,category:"auth",secret:!0},{name:"CODEX_API_KEY",description:"Fallback OpenAI API key for the openai-compatible provider, read after OPENAI_API_KEY. Legacy name from the removed @openai/codex-sdk integration \u2014 prefer OPENAI_API_KEY.",type:"string",required:!1,category:"auth",secret:!0},{name:"AFK_LOCAL_API_KEY",description:"Placeholder API key for local Anthropic-compatible servers (vllm-mlx, etc.). Set when AFK_LOCAL_BASE_URL is configured.",type:"string",required:!1,default:"local",example:"local",category:"auth",secret:!0},{name:"AFK_LOCAL_BASE_URL",description:"Base URL for a self-hosted Anthropic-compatible server. When set, routes traffic away from api.anthropic.com.",type:"string",required:!1,example:"http://127.0.0.1:8080",category:"model"},{name:"AFK_OPENAI_BASE_URL",description:"Base URL override for the OpenAI-compatible provider. Used for local shims (mlx_lm.server, Ollama, vLLM, LM Studio). The OpenAI SDK appends `/chat/completions` itself \u2014 a value ending in `/chat/completions` will be stripped at config-load time with a one-shot warning.",type:"string",required:!1,example:"http://127.0.0.1:8000/v1",category:"model"},{name:"AFK_OPENAI_USE_RESPONSES",description:"Opt the OpenAI-compatible provider into the OpenAI Responses API instead of Chat Completions for API-key sessions. Truthy values: 1, true, yes, on. The ChatGPT-subscription OAuth path uses Responses automatically regardless of this flag.",type:"boolean",required:!1,example:"1",category:"model"},{name:"AFK_OPENAI_CHATGPT_OAUTH",description:"Opt into using ChatGPT-subscription OAuth credentials from ~/.codex/auth.json (auth_mode: chatgpt) as OpenAI provider auth. Off by default. READ-ONLY: AFK never refreshes these tokens \u2014 re-run `codex` when the access token expires. Routes requests over the Responses API to the private ChatGPT backend (chatgpt.com/backend-api).",type:"boolean",required:!1,example:"1",category:"model"},{name:"AFK_PROVIDER",description:"Force provider selection (anthropic | anthropic-direct | openai | openai-compatible | openai-codex). Overrides the model-name heuristic. Same surface as the --provider CLI flag; CLI flag wins when both are set.",type:"string",required:!1,example:"openai-compatible",category:"model"},{name:"BRAVE_SEARCH_API_KEY",description:"Brave Search API subscription token, enabling web_scrape search mode. Free tier available at https://brave.com/search/api/. When unset, search mode returns an actionable error; markdown and raw modes are unaffected.",type:"string",required:!1,category:"auth",secret:!0},{name:"TELEGRAM_BOT_TOKEN",description:"Telegram bot token from @BotFather. Required to run the Telegram bot surface.",type:"string",required:!1,category:"telegram",secret:!0},{name:"AFK_TELEGRAM_BOT_TOKEN",description:"Alternative env var name for the Telegram bot token, accepted by the setup wizard.",type:"string",required:!1,category:"telegram",secret:!0},{name:"AFK_TELEGRAM_ALLOWED_CHAT_IDS",description:"Comma-separated list of Telegram chat IDs allowed to interact with the bot. Required when the bot is running.",type:"string",required:!1,example:"123456789,987654321",category:"telegram"},{name:"AFK_TELEGRAM_PRIMARY_CHAT_ID",description:"Default chat ID for outbound notifications (primary-mode routing). When unset, notifications go to the first private/DM chat in AFK_TELEGRAM_ALLOWED_CHAT_IDS. The afk.config.json telegram.notify block takes precedence.",type:"string",required:!1,example:"123456789",category:"telegram"},{name:"AFK_TELEGRAM_NOTIFY_MODE",description:"Outbound notification fan-out: primary (default \u2014 one chat), broadcast (every allowed chat), or custom (afk.config.json telegram.notify.targets). The afk.config.json telegram.notify.mode takes precedence.",type:"string",required:!1,example:"broadcast",category:"telegram"},{name:"TELEGRAM_DATA_DIR",description:"Override the directory where Telegram bot state is stored. Defaults to ~/.afk/state/telegram/.",type:"string",required:!1,category:"telegram"},{name:"TELEGRAM_VERBOSE",description:"Set to 1 to log per-message details from the Telegram bot \u2014 chat IDs, message text, latency.",type:"boolean",required:!1,example:"1",category:"telegram"},{name:"AFK_TELEGRAM_TRACE",description:"Set to 1 to dump raw bridge traffic between the agent and the Telegram bot \u2014 debugging only.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_TELEGRAM_CWD",description:"Override the working directory used by the Telegram bot when spawning agent sessions.",type:"string",required:!1,category:"telegram"},{name:"AFK_HOME",description:"Override the AFK home directory. Default: ~/.afk/.",type:"string",required:!1,default:"~/.afk",example:"/opt/afk",category:"paths"},{name:"AFK_STATE_DIR",description:"Override the AFK state directory. Default: $AFK_HOME/state/.",type:"string",required:!1,category:"paths"},{name:"AFK_FRAMEWORK_DIR",description:"Override the AFK agent-framework directory used for telemetry and briefs. Default: $AFK_HOME/agent-framework/.",type:"string",required:!1,category:"paths"},{name:"HOME",description:"Standard Unix home directory. Used as the fallback when AFK_HOME is unset.",type:"string",required:!1,category:"process"},{name:"PATH",description:"System PATH. Read for executable resolution (git, gh, etc.) in tool handlers.",type:"string",required:!1,category:"process"},{name:"AFK_DAEMON_CWD",description:"Working directory used by the daemon process for spawned agent sessions.",type:"string",required:!1,category:"daemon"},{name:"AFK_DAEMON_TASK",description:"Default task description for the daemon. Falls back to afk.config.json daemon.task.",type:"string",required:!1,category:"daemon"},{name:"AFK_DAEMON_TASK_ID",description:"Task identifier the daemon uses to scope its state directory and telemetry.",type:"string",required:!1,category:"daemon"},{name:"AFK_SESSIONSTART_COOLDOWN_MS",description:"Cooldown in milliseconds between SessionStart trigger fires in the daemon. Prevents thundering-herd on rapid restarts.",type:"number",required:!1,category:"daemon"},{name:"AFK_WORKTREE_AUTONAME",description:"Auto-rename worktree branches based on the first user message in interactive mode. 1 = on (default), 0 = off.",type:"boolean",required:!1,default:"1",example:"0",category:"worktree"},{name:"AFK_WORKTREE_BRANCH_PREFIX",description:"Branch-name prefix for AFK-managed worktrees. Default afk/. Set to empty string to drop the prefix.",type:"string",required:!1,default:"afk/",example:"wt/",category:"worktree"},{name:"AFK_WORKTREE_BASE",description:"Override the base git ref for worktrees created with --worktree. By default AFK bases worktrees on the remote's default branch (e.g. origin/main), fetched fresh. Set this to pin a different ref, or to HEAD to base on the local checkout. Overridden per-session by --worktree-base.",type:"string",required:!1,example:"origin/main",category:"worktree"},{name:"AFK_WORKTREE_BOOT_PRUNE",description:"When set, the daemon prunes stale worktrees at boot in addition to the cron-driven sweep.",type:"boolean",required:!1,category:"worktree"},{name:"AFK_WORKTREE_PRUNE_DISABLE",description:"Disable the worktree prune job entirely. Useful for long-running tests.",type:"boolean",required:!1,category:"worktree"},{name:"AFK_WORKTREE_MAX_AGE_CLEAN",description:"Maximum age (in days) before a clean worktree is auto-pruned. Default 14.",type:"number",required:!1,default:"14",category:"worktree"},{name:"AFK_WORKTREE_MAX_AGE_DIRTY",description:"Maximum age (in days) before a dirty worktree is auto-pruned. Default 30.",type:"number",required:!1,default:"30",category:"worktree"},{name:"AFK_WORKTREE_SWEEP_ROOT",description:"Override the root directory under which AFK worktrees are tracked for pruning.",type:"string",required:!1,category:"worktree"},{name:"AFK_ALLOW_PROJECT_MCP",description:"Allow loading MCP configuration from <cwd>/.mcp.json. Disabled by default \u2014 opt-in to mitigate config-injection risks.",type:"boolean",required:!1,example:"1",category:"mcp"},{name:"AFK_AUTO_ROUTING",description:"Auto-route bare slash inputs to matching skills. Applies to interactive, chat, telegram, and daemon surfaces.",type:"boolean",required:!1,example:"true",category:"routing"},{name:"AFK_INTERNAL",description:'Tier gate. Set to exactly `1` to unlock \u2014 only the literal string "1" unlocks (other truthy values like "true"/"yes" leave the tier locked). When unlocked, skills tagged `audience: \'internal\'` (e.g. /audit-fit, harvest/distill plugins) become visible at end-user surfaces (slash-command list, --help, tab-complete, system-prompt skill manifest). Default unset = public tier \u2014 internal skills are hidden. Not an access-control boundary; it gates surfacing, not the underlying registry.',type:"boolean",required:!1,example:"1",category:"routing"},{name:"AFK_SHELL_PASSTHROUGH",description:"Enable the interactive REPL `!cmd` / `!&cmd` shell-passthrough feature. On by default. Set to 0, false, off, or no (case-insensitive) to disable, so inputs beginning with ! are sent to the model as literal text instead of being executed as shell commands. Equivalent to the --no-shell-passthrough flag.",type:"boolean",required:!1,default:"1",example:"0",category:"misc"},{name:"AFK_BANNER_PLAIN",description:"Suppress the ANSI-colored banner at REPL startup. Useful for non-TTY captures and CI logs.",type:"boolean",required:!1,example:"1",category:"misc"},{name:"AFK_SPINNER_TIPS",description:"Show rotating tips in the loading spinner during long calls. 1 = on, 0 = off.",type:"boolean",required:!1,category:"misc"},{name:"AFK_SHOW_DIFFS",description:"Show inline diffs in the tool-lane output for edit/write tool calls. 1 = on, 0 = off.",type:"boolean",required:!1,category:"misc"},{name:"AFK_SKILL_STREAM_VERBOSE",description:"Verbose streaming output when a skill is dispatched. Logs sub-agent setup, intermediate events, and final result.",type:"boolean",required:!1,category:"debug"},{name:"FORCE_COLOR",description:"Standard Node convention. Force-enable ANSI color output even when stdout is not a TTY.",type:"string",required:!1,example:"1",category:"process"},{name:"NO_COLOR",description:"Standard convention (https://no-color.org). When set to any non-empty value, disables ANSI color output.",type:"string",required:!1,example:"1",category:"process"},{name:"AFK_DEBUG",description:"Enable verbose debug logging across the codebase. Accepts 1 to enable.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_DEBUG_CLIPBOARD",description:"Debug bracketed-paste and image-paste handling in the interactive REPL.",type:"boolean",required:!1,category:"debug"},{name:"AFK_DEBUG_COMPOSITOR",description:"Gate compositor phase-boundary traces to stderr; any truthy value enables.",type:"boolean",required:!1,category:"debug"},{name:"AFK_TRACE_DISABLED",description:"Disable the agent trace subsystem entirely. Set to 1 to skip trace file writes.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AFK_SESSION_LEDGER_DISABLED",description:"Disable the per-session durable event ledger (state/sessions/<id>/events.jsonl). Set to 1 to skip ledger writes; live cross-surface watching (e.g. the Telegram /watch command) will report no activity for sessions started while disabled.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"DEBUG",description:"Standard Node `debug`-package convention. When set to 1, enables verbose logging in several modules alongside AFK_DEBUG.",type:"string",required:!1,category:"debug"},{name:"AGENT_AFK_ASCII",description:"Force the interactive REPL tool-lane renderer to ASCII-only glyphs instead of the default Unicode box-drawing set. Accepts 1/true/yes (case-insensitive). Useful for terminals whose font lacks \u2503\u251C\u2570\u251C glyphs.",type:"boolean",required:!1,example:"1",category:"debug"},{name:"AGENT_SURFACE",description:"Internal surface marker propagated to subprocesses. Identifies which AFK surface (cli, telegram, daemon) spawned the process.",type:"string",required:!1,example:"cli",category:"process"},{name:"CI",description:"Standard CI-detection convention. Auto-set by GitHub Actions, CircleCI, etc. Used to switch off TTY-only UX.",type:"string",required:!1,example:"true",category:"process"},{name:"NODE_ENV",description:"Standard Node environment marker. test | development | production. Used by routing-telemetry.ts to suppress test-time writes.",type:"string",required:!1,example:"production",category:"process"},{name:"VITEST",description:"Set automatically by Vitest. Used at runtime to short-circuit code paths that should not fire in tests.",type:"string",required:!1,category:"process"},{name:"NO_UPDATE_NOTIFIER",description:"Disable the update-available notifier on CLI startup. Standard convention shared with many Node CLIs.",type:"boolean",required:!1,category:"process"},{name:"AFK_BROWSER_HEADLESS",description:"Override the default headless mode for native browser-control tools. `1`/`true` forces headless; `0`/`false` forces headed. When unset the default is headless for daemon and subagent surfaces and headed for repl/interactive \u2014 so an operator can watch the agent work in REPL mode.",type:"boolean",required:!1,example:"1",category:"browser"},{name:"AFK_BROWSER_ALLOWED_DOMAINS",description:"Comma-separated allowlist of URL host globs. When set, browser_open and any navigation that targets a host outside the list returns status: blocked_by_policy. Unset means no allowlist (permissive). Patterns use simple `*` glob matching against the URL host. Combines with AFK_BROWSER_BLOCKED_DOMAINS \u2014 block wins.",type:"string",required:!1,example:"github.com,*.atlassian.net",category:"browser"},{name:"AFK_BROWSER_BLOCKED_DOMAINS",description:"Comma-separated blocklist of URL host globs. Browser navigation that matches any entry returns status: blocked_by_policy regardless of the allowlist.",type:"string",required:!1,example:"*.ads.example.com",category:"browser"},{name:"AFK_BROWSER_DOM_SNAPSHOTS",description:"Phase 2 opt-in: when set to 1, every browser_act writes a gzipped DOM snapshot sidecar under ~/.afk/state/witness/<sid>/browser/dom-snapshots/. Off by default because snapshots are large; useful for post-mortem analysis of failed actions.",type:"boolean",required:!1,example:"1",category:"browser"},{name:"AFK_BROWSER_BACKEND",description:"Select the browser provider backend. Phase 1 supports only `playwright`. Reserved for future `cdp` / `mcp` adapters. Unset defaults to `playwright`.",type:"string",required:!1,example:"playwright",category:"browser"},{name:"AFK_BROWSER_CONFIG",description:"Absolute path to an alternate browser config file. Overrides the default ~/.afk/config/browser.json lookup. Useful for per-project overrides in CI.",type:"string",required:!1,example:"/path/to/browser.json",category:"browser"},{name:"AFK_WRITE_DENYLIST",description:"Comma-separated list of additional path globs that the write_file tool refuses to write to.",type:"string",required:!1,example:"**/.env,**/secrets/**",category:"misc"},{name:"AFK_WRITE_DIFF",description:"Show a diff preview before each write_file tool call. Defaults provider-controlled when unset.",type:"boolean",required:!1,category:"misc"},{name:"AFK_DEMO_CLEAN",description:"Explicit opt-in to capture-mode. When set to 1, suppresses high-frequency repaint drivers (spinner ticker, live thinking-preview) so recorded artifacts contain each state once instead of once per timer tick.",type:"boolean",required:!1,example:"1",category:"misc"},{name:"SCRIPT",description:"Set by script(1) on BSD/macOS/Linux to the typescript filename while a terminal session is being recorded. Presence of a non-empty value triggers capture-mode.",type:"string",required:!1,example:"/tmp/typescript",category:"process"},{name:"ASCIINEMA_REC",description:"Set to 1 by asciinema rec while a session is being recorded. Triggers capture-mode.",type:"boolean",required:!1,example:"1",category:"process"},{name:"AFK_SESSION_ID",description:"Override the browser session ID used by the native browser-control tools. Defaults to 'default' for single-session use. Subagents inherit the parent's session by default. Set this when running multiple concurrent AFK processes that should each manage an isolated browser context.",type:"string",required:!1,default:"default",example:"session-abc123",category:"browser"},{name:"SHELL",description:"Standard POSIX env var pointing to the user's login shell binary. Used by shell-init and worktree commands to auto-detect the correct shell syntax for emitted wrapper code.",type:"string",required:!1,example:"/bin/zsh",category:"process"},{name:"PAGER",description:"Standard POSIX env var naming the user's preferred pager (with optional flags). Used by /transcript to render the full session in a scrollable viewer; falls back to `less -R` when unset.",type:"string",required:!1,example:"less -R",category:"process"},{name:"AFK_DIFF_LINES",description:"Maximum number of diff lines shown in the inline diff render during write_file tool calls. Set to 0 for no cap. Non-integer values are silently ignored and the default applies.",type:"number",required:!1,example:"50",category:"misc"},{name:"AFK_SHELL_WRAPPER",description:"Set to 1 or true by the optional afk shell wrapper function (installed via `afk shell-init`). Signals that the parent shell has the wrapper active so the post-exit cd can fire.",type:"boolean",required:!1,example:"1",category:"process"},{name:"AFK_USER_CARD_MAX_ROWS",description:'Maximum number of visual rows emitted by renderUserCard before collapsing the remainder into a dim "\u2026(N lines collapsed)" summary row. Defaults to 24. Non-integer or non-positive values are silently ignored and the default applies.',type:"number",required:!1,example:"24",category:"misc"}],S={get AFK_COMPACT_KEEP_LAST_TURNS(){return process.env.AFK_COMPACT_KEEP_LAST_TURNS},get AFK_COMPACT_MODEL(){return process.env.AFK_COMPACT_MODEL},get AFK_DEFAULT_SUBAGENT_MODEL(){return process.env.AFK_DEFAULT_SUBAGENT_MODEL},get AFK_DISABLE_PROMPT_CACHE(){return process.env.AFK_DISABLE_PROMPT_CACHE},get AFK_EFFORT(){return process.env.AFK_EFFORT},get AFK_MAX_BUDGET_USD(){return process.env.AFK_MAX_BUDGET_USD},get AFK_MAX_OUTPUT_TOKENS(){return process.env.AFK_MAX_OUTPUT_TOKENS},get AFK_MAX_TOKENS(){return process.env.AFK_MAX_TOKENS},get AFK_MODEL(){return process.env.AFK_MODEL},get AFK_MODEL_LARGE(){return process.env.AFK_MODEL_LARGE},get AFK_MODEL_LARGE_API_KEY(){return process.env.AFK_MODEL_LARGE_API_KEY},get AFK_MODEL_LARGE_BASE_URL(){return process.env.AFK_MODEL_LARGE_BASE_URL},get AFK_MODEL_MEDIUM(){return process.env.AFK_MODEL_MEDIUM},get AFK_MODEL_MEDIUM_API_KEY(){return process.env.AFK_MODEL_MEDIUM_API_KEY},get AFK_MODEL_MEDIUM_BASE_URL(){return process.env.AFK_MODEL_MEDIUM_BASE_URL},get AFK_MODEL_SMALL(){return process.env.AFK_MODEL_SMALL},get AFK_MODEL_SMALL_API_KEY(){return process.env.AFK_MODEL_SMALL_API_KEY},get AFK_MODEL_SMALL_BASE_URL(){return process.env.AFK_MODEL_SMALL_BASE_URL},get AFK_PROMPT_CACHE_TTL(){return process.env.AFK_PROMPT_CACHE_TTL},get AFK_SUGGEST_ENABLED(){return process.env.AFK_SUGGEST_ENABLED},get AFK_SUGGEST_GHOST(){return process.env.AFK_SUGGEST_GHOST},get AFK_SUGGEST_MODEL(){return process.env.AFK_SUGGEST_MODEL},get AFK_TASK_BUDGET(){return process.env.AFK_TASK_BUDGET},get AFK_TEMPERATURE(){return process.env.AFK_TEMPERATURE},get AFK_THINKING(){return process.env.AFK_THINKING},get AFK_TIMEOUT_MS(){return process.env.AFK_TIMEOUT_MS},get CLAUDE_MODEL(){return process.env.CLAUDE_MODEL},get AFK_SYSTEM_PROMPT(){return process.env.AFK_SYSTEM_PROMPT},get AFK_DUMP_PROMPT(){return process.env.AFK_DUMP_PROMPT},get ANTHROPIC_API_KEY(){return process.env.ANTHROPIC_API_KEY},get CLAUDE_CODE_OAUTH_TOKEN(){return process.env.CLAUDE_CODE_OAUTH_TOKEN},get OPENAI_API_KEY(){return process.env.OPENAI_API_KEY},get CODEX_API_KEY(){return process.env.CODEX_API_KEY},get AFK_LOCAL_API_KEY(){return process.env.AFK_LOCAL_API_KEY},get AFK_LOCAL_BASE_URL(){return process.env.AFK_LOCAL_BASE_URL},get AFK_OPENAI_BASE_URL(){return process.env.AFK_OPENAI_BASE_URL},get AFK_OPENAI_USE_RESPONSES(){return process.env.AFK_OPENAI_USE_RESPONSES},get AFK_OPENAI_CHATGPT_OAUTH(){return process.env.AFK_OPENAI_CHATGPT_OAUTH},get AFK_PROVIDER(){return process.env.AFK_PROVIDER},get BRAVE_SEARCH_API_KEY(){return process.env.BRAVE_SEARCH_API_KEY},get TELEGRAM_BOT_TOKEN(){return process.env.TELEGRAM_BOT_TOKEN},get AFK_TELEGRAM_BOT_TOKEN(){return process.env.AFK_TELEGRAM_BOT_TOKEN},get AFK_TELEGRAM_ALLOWED_CHAT_IDS(){return process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS},get AFK_TELEGRAM_PRIMARY_CHAT_ID(){return process.env.AFK_TELEGRAM_PRIMARY_CHAT_ID},get AFK_TELEGRAM_NOTIFY_MODE(){return process.env.AFK_TELEGRAM_NOTIFY_MODE},get TELEGRAM_DATA_DIR(){return process.env.TELEGRAM_DATA_DIR},get TELEGRAM_VERBOSE(){return process.env.TELEGRAM_VERBOSE},get AFK_TELEGRAM_TRACE(){return process.env.AFK_TELEGRAM_TRACE},get AFK_TELEGRAM_CWD(){return process.env.AFK_TELEGRAM_CWD},get AFK_HOME(){return process.env.AFK_HOME},get AFK_STATE_DIR(){return process.env.AFK_STATE_DIR},get AFK_FRAMEWORK_DIR(){return process.env.AFK_FRAMEWORK_DIR},get HOME(){return process.env.HOME},get PATH(){return process.env.PATH},get AFK_DAEMON_CWD(){return process.env.AFK_DAEMON_CWD},get AFK_DAEMON_TASK(){return process.env.AFK_DAEMON_TASK},get AFK_DAEMON_TASK_ID(){return process.env.AFK_DAEMON_TASK_ID},get AFK_SESSIONSTART_COOLDOWN_MS(){return process.env.AFK_SESSIONSTART_COOLDOWN_MS},get AFK_WORKTREE_AUTONAME(){return process.env.AFK_WORKTREE_AUTONAME},get AFK_WORKTREE_BRANCH_PREFIX(){return process.env.AFK_WORKTREE_BRANCH_PREFIX},get AFK_WORKTREE_BASE(){return process.env.AFK_WORKTREE_BASE},get AFK_WORKTREE_BOOT_PRUNE(){return process.env.AFK_WORKTREE_BOOT_PRUNE},get AFK_WORKTREE_PRUNE_DISABLE(){return process.env.AFK_WORKTREE_PRUNE_DISABLE},get AFK_WORKTREE_MAX_AGE_CLEAN(){return process.env.AFK_WORKTREE_MAX_AGE_CLEAN},get AFK_WORKTREE_MAX_AGE_DIRTY(){return process.env.AFK_WORKTREE_MAX_AGE_DIRTY},get AFK_WORKTREE_SWEEP_ROOT(){return process.env.AFK_WORKTREE_SWEEP_ROOT},get AFK_ALLOW_PROJECT_MCP(){return process.env.AFK_ALLOW_PROJECT_MCP},get AFK_AUTO_ROUTING(){return process.env.AFK_AUTO_ROUTING},get AFK_INTERNAL(){return process.env.AFK_INTERNAL},get AFK_SHELL_PASSTHROUGH(){return process.env.AFK_SHELL_PASSTHROUGH},get AFK_BANNER_PLAIN(){return process.env.AFK_BANNER_PLAIN},get AFK_SPINNER_TIPS(){return process.env.AFK_SPINNER_TIPS},get AFK_SHOW_DIFFS(){return process.env.AFK_SHOW_DIFFS},get AFK_SKILL_STREAM_VERBOSE(){return process.env.AFK_SKILL_STREAM_VERBOSE},get FORCE_COLOR(){return process.env.FORCE_COLOR},get NO_COLOR(){return process.env.NO_COLOR},get AFK_DEBUG(){return process.env.AFK_DEBUG},get AFK_DEBUG_CLIPBOARD(){return process.env.AFK_DEBUG_CLIPBOARD},get AFK_DEBUG_COMPOSITOR(){return process.env.AFK_DEBUG_COMPOSITOR},get AFK_TRACE_DISABLED(){return process.env.AFK_TRACE_DISABLED},get AFK_SESSION_LEDGER_DISABLED(){return process.env.AFK_SESSION_LEDGER_DISABLED},get DEBUG(){return process.env.DEBUG},get AGENT_AFK_ASCII(){return process.env.AGENT_AFK_ASCII},get AGENT_SURFACE(){return process.env.AGENT_SURFACE},get CI(){return process.env.CI},get NODE_ENV(){return process.env.NODE_ENV},get VITEST(){return process.env.VITEST},get NO_UPDATE_NOTIFIER(){return process.env.NO_UPDATE_NOTIFIER},get AFK_SESSION_ID(){return process.env.AFK_SESSION_ID},get AFK_BROWSER_HEADLESS(){return process.env.AFK_BROWSER_HEADLESS},get AFK_BROWSER_ALLOWED_DOMAINS(){return process.env.AFK_BROWSER_ALLOWED_DOMAINS},get AFK_BROWSER_BLOCKED_DOMAINS(){return process.env.AFK_BROWSER_BLOCKED_DOMAINS},get AFK_BROWSER_DOM_SNAPSHOTS(){return process.env.AFK_BROWSER_DOM_SNAPSHOTS},get AFK_BROWSER_BACKEND(){return process.env.AFK_BROWSER_BACKEND},get AFK_BROWSER_CONFIG(){return process.env.AFK_BROWSER_CONFIG},get AFK_WRITE_DENYLIST(){return process.env.AFK_WRITE_DENYLIST},get AFK_WRITE_DIFF(){return process.env.AFK_WRITE_DIFF},get AFK_DEMO_CLEAN(){return process.env.AFK_DEMO_CLEAN},get SCRIPT(){return process.env.SCRIPT},get ASCIINEMA_REC(){return process.env.ASCIINEMA_REC},get SHELL(){return process.env.SHELL},get PAGER(){return process.env.PAGER},get AFK_DIFF_LINES(){return process.env.AFK_DIFF_LINES},get AFK_SHELL_WRAPPER(){return process.env.AFK_SHELL_WRAPPER},get AFK_USER_CARD_MAX_ROWS(){return process.env.AFK_USER_CARD_MAX_ROWS}};(function(){for(let e of mp){if(!e.secret)continue;let n=Object.getOwnPropertyDescriptor(S,e.name);n&&Object.defineProperty(S,e.name,{...n,enumerable:!1})}})()});import{existsSync as Ws,mkdirSync as gp,renameSync as hp,cpSync as yp,rmSync as bp}from"fs";import{join as U,dirname as Gs,isAbsolute as wp}from"path";import{homedir as Kr}from"os";import{fileURLToPath as Sp}from"url";function te(){let t=S.AFK_HOME;if(t!==void 0&&t!==""){if(!wp(t)||t==="/")throw new Error(`AFK_HOME must be an absolute path that is not /, got: ${t}`);return t}return U(Kr(),".afk")}function rt(){return U(te(),"agent-framework")}function qs(){return U(rt(),"forge-telemetry.jsonl")}function zs(){return U(rt(),"briefs")}function Wr(){return U(te(),"skills")}function ot(){return U(te(),"plugins")}function Js(){return U(process.cwd(),".afk")}function Vs(){return U(Js(),"skills")}function Gr(){return U(Js(),"plugins")}function fn(){return U(ot(),".index.json")}function qr(){return U(st(),"schedules.json")}function zr(){let t=Sp(import.meta.url),e=Gs(t);return U(e,"bundled-plugins")}function st(){return U(te(),"config")}function He(){return U(te(),"state")}function _e(){return U(He(),"sessions")}function mn(){return U(He(),"presence")}function gn(){return U(He(),"memory")}function it(){return U(He(),"session-grants.jsonl")}function Ys(){return U(te(),"farms")}function Xs(t){return U(Ys(),t)}function kp(t){if(!vp.test(t))throw new Error(`Invalid AFK_SESSION_ID: must match /^[a-zA-Z0-9_-]+$/, got: ${JSON.stringify(t)}`)}function hn(t){return kp(t),U(He(),"witness",t)}function Qs(t="default"){return U(He(),"daemon",`agent-afk@${t}`)}function Pt(){return U(st(),"afk.env")}function yn(){return U(st(),"afk.config.json")}function Zs(){return U(st(),"settings.json")}function ei(t=process.cwd()){return U(t,".afk","settings.json")}function ti(){return U(Kr(),".afk.env")}function ni(){return U(Kr(),".afk.config.json")}function _p(){return U(te(),"sessions")}function Ep(t,e){if(t!==e&&Ws(t)&&!Ws(e))try{gp(Gs(e),{recursive:!0});try{hp(t,e)}catch(n){if(n.code==="EXDEV")try{yp(t,e,{recursive:!0}),bp(t,{recursive:!0,force:!0})}catch(r){process.stderr.write(`[afk] migrateDirOnce: EXDEV fallback failed for ${t} \u2192 ${e}: ${String(r)}
3
- `)}}}catch{}}function ri(){Ep(_p(),_e())}function Ct(t){return typeof t=="string"&&t.length>0&&t.length<=xp&&Ap.test(t)}function bn(t){if(!Ct(t))throw new Error(`Invalid session id for ledger path: ${JSON.stringify(t)}`);return U(_e(),t)}function wn(t){return U(bn(t),"events.jsonl")}var vp,Ap,xp,B=me(()=>{"use strict";N();vp=/^[a-zA-Z0-9_-]+$/;Ap=/^[A-Za-z0-9_-]+$/,xp=128});import{readFileSync as Ah}from"node:fs";import{join as xh}from"path";function Th(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Qa(t,e){return Th(e).test(t)}function Ph(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(Rh.has(e))return!0;if(Ih.has(e))return!1}return!1}function Za(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function Ch(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function Mh(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function Oh(t){try{return Ah(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function Dh(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function ec(t){let e=t?.env??S,n=t?.readFileSync??Oh,r=t?.surface??e.AGENT_SURFACE,o=Ph(e.AFK_BROWSER_HEADLESS,r),s=Za(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Za(e.AFK_BROWSER_BLOCKED_DOMAINS),a=Mh(e.AFK_BROWSER_DOM_SNAPSHOTS),c=Ch(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():xh(st(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(g){throw new Error(`Failed to parse browser config at ${u}: ${String(g)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let h=Dh(l,f);return h.configPath=u,h}function Ho(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(Qa(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>Qa(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var Rh,Ih,jo=me(()=>{"use strict";N();B();Rh=new Set(["daemon","subagent","telegram"]),Ih=new Set(["repl","interactive","cli"])});import Fh from"node:fs";import Lh from"node:path";import{chromium as Nh}from"playwright";function $h(){try{return"3.92.1"}catch{}try{let t=Lh.resolve(import.meta.dirname,"../../../package.json"),e=Fh.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Uh,or,tc=me(()=>{"use strict";Uh=$h(),or=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Nh.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${Uh}`}}}});import{createHash as Bh}from"crypto";function Ko(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of Hh)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function nc(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&jh.test(t.label))}function rc(t){return Bh("sha256").update(t,"utf8").digest("hex").slice(0,8)}function oc(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Hh,jh,Jt=me(()=>{"use strict";Hh=[{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}];jh=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Kh}from"node:crypto";function Wh(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Gh(t,e,n){return`el_${Kh("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function qh(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function sc(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function ac(t,e){let n=t.role??"",r=t.name??"";ic.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])ac(s,e)}async function zh(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},cc).catch(()=>[])}async function Jh(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let g=s.type;g==="checkbox"?l="checkbox":g==="radio"?l="radio":g==="button"||g==="submit"||g==="reset"?l="button":g==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,h={role:l,name:c,disabled:p};u!==void 0&&(h.value=u),f!==void 0&&(h.checked=f),o.push(h)}return o},cc).catch(()=>[])}function Vh(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function sr(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Vh(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=zh(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,h,g]=await Promise.all([i,a,c,l,d]),y,v=!1;u!==null?(y=[],ac(u,y)):(o.push("observation skipped accessibility tree (returned null)"),v=!0,y=(await Jh(t)).filter(E=>ic.has(E.role??"")));let b=new Map;for(let A of p){let E=sc(A.name),P=b.get(E);(!P||P.bbox.w===0&&A.bbox.w>0)&&b.set(E,A)}let w=y.map(A=>({ax:A,dom:b.get(sc(A.name??""))})),k=r?w:w.filter(A=>A.dom?A.dom.bbox.w>0||A.dom.bbox.h>0:!0);k.sort((A,E)=>{let P=A.dom?.bbox.y??0,O=E.dom?.bbox.y??0;if(P!==O)return P-O;let C=A.dom?.bbox.x??0,F=E.dom?.bbox.x??0;return C-F}),k.length>200&&o.push("page has 200+ interactive elements; consider scoping");let x=k.slice(0,n).map((A,E)=>{let P=A.ax.role??"generic",O=A.ax.name??"",C=Gh(P,O,E),F=A.dom?.bbox??{x:0,y:0,w:0,h:0},j=A.dom?.type??null,K=null;A.ax.value!==void 0&&A.ax.value!==null&&(K=String(A.ax.value)),A.ax.checked!==void 0&&(K=String(A.ax.checked)),nc({role:P,kind:j})&&(K="[redacted]");let J={disabled:A.ax.disabled??!1};A.ax.checked!==void 0&&(J.checked=A.ax.checked===!0||A.ax.checked==="mixed"),A.ax.selected!==void 0&&(J.selected=A.ax.selected),A.ax.expanded!==void 0&&(J.expanded=A.ax.expanded);let H;A.dom?.testId?H=`[data-testid="${A.dom.testId}"]`:A.dom?.id&&(H=`#${A.dom.id}`);let ne={id:C,role:P,label:Wh(O),kind:j,value:K,state:J,bbox:F};return H!==void 0&&(ne.selector=H),ne}),T="idle";try{let A=await t.evaluate(()=>document.readyState);A==="loading"?T="loading":A==="interactive"?T="navigating":T="idle"}catch{T="navigating"}T!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),v&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let I=qh(f),R=`obs_${e.observationCounter.toString(36)}`,M=new Date().toISOString();return{observationId:R,url:h,title:g,textSummary:I,interactive:x,status:{httpStatus:e.httpStatus??null,loadingState:T,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:M}}var ic,cc,lc=me(()=>{"use strict";Jt();ic=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);cc="a[href], button, input, select, textarea, [role], [tabindex], label"});async function dc(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function Wo(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>dc(t,s)))).filter(o=>o!==null)}async function Yh(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Go(t,e,n){switch(e.kind){case"element_id":return Xh(t,e,n);case"selector":return Qh(t,e);case"semantic":return Zh(t,e)}}async function Xh(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await Wo(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Qh(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await Wo(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Zh(t,e){return e.role!==void 0?ey(t,e.text,e.role):ty(t,e.text,e)}async function ey(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await Wo(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function ty(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Yh(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let g=u[0];return g===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:g.locator.nth(g.index)}}let p=u.slice(0,5),f=[];for(let g=0;g<p.length;g++){let y=p[g];if(y===void 0)continue;let v=await dc(y.locator,y.index);if(v!==null){let b=`${v.role}:${v.label}:${g}`,w=0;for(let k=0;k<b.length;k++)w=w*31+b.charCodeAt(k)>>>0;f.push({...v,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var uc=me(()=>{"use strict"});import{randomBytes as ny}from"crypto";import{mkdir as ry,stat as oy,writeFile as sy}from"fs/promises";import{join as qo}from"path";import{gzip as iy}from"zlib";import{promisify as ay}from"util";function cy(t){return qo(hn(t),"browser")}function ly(t){return qo(cy(t),"screenshots")}function dy(){return new Date().toISOString().replace(/[:.]/g,"-")}function uy(){return ny(3).toString("hex")}async function zo(t,e,n){if(e.length>pc)throw new Error(`writeScreenshotSidecar: buffer exceeds ${pc} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=ly(t);await ry(r,{recursive:!0});let o=`${dy()}-${uy()}-${n}.png`,s=qo(r,o);await sy(s,e);let{size:i}=await oy(s);return{path:s,bytes:i}}var aI,pc,fc=me(()=>{"use strict";B();Jt();aI=ay(iy);pc=5*1024*1024});var gc={};js(gc,{PlaywrightProvider:()=>Jo});function mc(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var Jo,hc=me(()=>{"use strict";tc();lc();uc();jo();Jt();fc();Jo=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new or(e)}async open(e){let n=Ho(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await sr(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await sr(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await Go(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${mc(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let g=Ko(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(y){l=y}else l=g}let u=r.url();if(u!==s){let g=Ho(u,this.config);if(!g.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:g.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await sr(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),h=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,h),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await Go(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${mc(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await zo(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await zo(n,o,r);return s}catch{return null}}}});var Ze={};js(Ze,{__resetBrowserRegistryForTests:()=>hy,browserProviderActive:()=>my,closeBrowserProvider:()=>Vo,getBrowserProvider:()=>fy,peekBrowserProvider:()=>gy});function yc(){Promise.resolve(Vo()).then(()=>{process.exit(130)})}function bc(){Promise.resolve(Vo()).then(()=>{process.exit(143)})}function wc(){we=null}function py(){ir||(process.on("SIGINT",yc),process.on("SIGTERM",bc),process.on("exit",wc),ir=!0)}function Sc(){ir&&(process.removeListener("SIGINT",yc),process.removeListener("SIGTERM",bc),process.removeListener("exit",wc),ir=!1)}async function fy(t){return we!==null?we:(Qe!==null||(Qe=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(hc(),gc)),n=ec(t),r=new e(n);return py(),we=r,Qe=null,r})()),Qe)}async function Vo(){if(we===null)return;let t=we;we=null,Qe=null,Sc(),await t.shutdown()}function my(){return we!==null}function gy(){return we}function hy(){we=null,Qe=null,Sc()}var we,Qe,ir,et=me(()=>{"use strict";jo();we=null,Qe=null,ir=!1});N();import{existsSync as N_,readFileSync as Hs}from"fs";import{fileURLToPath as cp}from"url";import{dirname as lp,join as dp}from"path";function Ks(t,e){return!t||!e||t==="unknown"||e==="unknown"?{drift:!1}:t===e?{drift:!1}:{drift:!0,message:`[daemon] Version mismatch: running ${t} but installed is ${e}. Exiting.`}}import{Telegraf as Mk}from"telegraf";B();import Rp from"better-sqlite3";import{existsSync as Mt,mkdirSync as oi,readFileSync as Sn,writeFileSync as si,readdirSync as Ip,appendFileSync as Pp,unlinkSync as ii,copyFileSync as Cp,renameSync as Mp}from"fs";import{join as re,basename as ai,resolve as vn,relative as Op}from"path";N();function Tp(){return S.AFK_DEBUG==="1"||S.DEBUG==="1"}function L(...t){Tp()&&console.log(...t)}var ci="HOT.md",Dp="HOT.md.bak",li="memory.db",di="memory-wal.jsonl",kn="procedures",Fp="HOT.md.tmp",_n=5250,Lp=Math.ceil(_n/3.5),Np=600,mi=.8,Jr='<!-- HOT TRUNCATED to fit the ~1,500-token cap; move durable detail to the fact archive (memory_update target:"fact"). -->',Ot=2,$p=`
3
+ `)}}}catch{}}function ri(){Ep(_p(),_e())}function Ct(t){return typeof t=="string"&&t.length>0&&t.length<=xp&&Ap.test(t)}function bn(t){if(!Ct(t))throw new Error(`Invalid session id for ledger path: ${JSON.stringify(t)}`);return U(_e(),t)}function wn(t){return U(bn(t),"events.jsonl")}var vp,Ap,xp,B=me(()=>{"use strict";N();vp=/^[a-zA-Z0-9_-]+$/;Ap=/^[A-Za-z0-9_-]+$/,xp=128});import{readFileSync as Ah}from"node:fs";import{join as xh}from"path";function Th(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function Qa(t,e){return Th(e).test(t)}function Ph(t,e){if(t!==void 0){let n=t.trim().toLowerCase();if(n==="1"||n==="true"||n==="yes")return!0;if(n==="0"||n==="false"||n==="no")return!1}if(e!==void 0){if(Rh.has(e))return!0;if(Ih.has(e))return!1}return!1}function Za(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function Ch(t){if(t===void 0||t===""||t==="playwright")return"playwright";throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${t}`)}function Mh(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function Oh(t){try{return Ah(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function Dh(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return n}function ec(t){let e=t?.env??S,n=t?.readFileSync??Oh,r=t?.surface??e.AGENT_SURFACE,o=Ph(e.AFK_BROWSER_HEADLESS,r),s=Za(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Za(e.AFK_BROWSER_BLOCKED_DOMAINS),a=Mh(e.AFK_BROWSER_DOM_SNAPSHOTS),c=Ch(e.AFK_BROWSER_BACKEND),l={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null},d=e.AFK_BROWSER_CONFIG,u=d!==void 0&&d.trim()!==""?d.trim():xh(st(),"browser.json"),p=n(u);if(p===void 0)return l;let f;try{f=JSON.parse(p)}catch(g){throw new Error(`Failed to parse browser config at ${u}: ${String(g)}`)}if(typeof f!="object"||f===null||Array.isArray(f))throw new Error(`Browser config at ${u} must be a JSON object`);let h=Dh(l,f);return h.configPath=u,h}function Ho(t,e){let n;try{n=new URL(t).hostname.toLowerCase()}catch{return{allowed:!1,reason:`invalid URL: ${t}`}}for(let r of e.blockedDomains)if(Qa(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>Qa(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var Rh,Ih,jo=me(()=>{"use strict";N();B();Rh=new Set(["daemon","subagent","telegram"]),Ih=new Set(["repl","interactive","cli"])});import Fh from"node:fs";import Lh from"node:path";import{chromium as Nh}from"playwright";function $h(){try{return"3.92.2"}catch{}try{let t=Lh.resolve(import.meta.dirname,"../../../package.json"),e=Fh.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var Uh,or,tc=me(()=>{"use strict";Uh=$h(),or=class{config;browser;sessions=new Map;launchPromise;shutdownComplete=!1;constructor(e){this.config=e}async ensureBrowser(){return this.browser!==void 0&&this.browser.isConnected()?this.browser:(this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=Nh.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,e)).catch(e=>{throw this.launchPromise=void 0,e}),this.launchPromise))}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s={context:o,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,s),o}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",s,{once:!0});try{let i=await o.newPage(),a=await i.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil}),c=await i.content(),l=i.url(),d=a!==null?a.status():null;return{html:c,finalUrl:l,httpStatus:d}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",s),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${Uh}`}}}});import{createHash as Bh}from"crypto";function Ko(t){if(t.length===0)return t;let e=t;for(let{regex:n,name:r}of Hh)r==="form-password"?e=e.replace(n,"password=[redacted]"):e=e.replace(n,"[redacted]");return e}function nc(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&jh.test(t.label))}function rc(t){return Bh("sha256").update(t,"utf8").digest("hex").slice(0,8)}function oc(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Hh,jh,Jt=me(()=>{"use strict";Hh=[{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}];jh=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Kh}from"node:crypto";function Wh(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Gh(t,e,n){return`el_${Kh("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function qh(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function sc(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function ac(t,e){let n=t.role??"",r=t.name??"";ic.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])ac(s,e)}async function zh(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},cc).catch(()=>[])}async function Jh(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let g=s.type;g==="checkbox"?l="checkbox":g==="radio"?l="radio":g==="button"||g==="submit"||g==="reset"?l="button":g==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,h={role:l,name:c,disabled:p};u!==void 0&&(h.value=u),f!==void 0&&(h.checked=f),o.push(h)}return o},cc).catch(()=>[])}function Vh(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function sr(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Vh(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=zh(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,h,g]=await Promise.all([i,a,c,l,d]),y,v=!1;u!==null?(y=[],ac(u,y)):(o.push("observation skipped accessibility tree (returned null)"),v=!0,y=(await Jh(t)).filter(E=>ic.has(E.role??"")));let b=new Map;for(let A of p){let E=sc(A.name),P=b.get(E);(!P||P.bbox.w===0&&A.bbox.w>0)&&b.set(E,A)}let w=y.map(A=>({ax:A,dom:b.get(sc(A.name??""))})),k=r?w:w.filter(A=>A.dom?A.dom.bbox.w>0||A.dom.bbox.h>0:!0);k.sort((A,E)=>{let P=A.dom?.bbox.y??0,O=E.dom?.bbox.y??0;if(P!==O)return P-O;let C=A.dom?.bbox.x??0,F=E.dom?.bbox.x??0;return C-F}),k.length>200&&o.push("page has 200+ interactive elements; consider scoping");let x=k.slice(0,n).map((A,E)=>{let P=A.ax.role??"generic",O=A.ax.name??"",C=Gh(P,O,E),F=A.dom?.bbox??{x:0,y:0,w:0,h:0},j=A.dom?.type??null,K=null;A.ax.value!==void 0&&A.ax.value!==null&&(K=String(A.ax.value)),A.ax.checked!==void 0&&(K=String(A.ax.checked)),nc({role:P,kind:j})&&(K="[redacted]");let J={disabled:A.ax.disabled??!1};A.ax.checked!==void 0&&(J.checked=A.ax.checked===!0||A.ax.checked==="mixed"),A.ax.selected!==void 0&&(J.selected=A.ax.selected),A.ax.expanded!==void 0&&(J.expanded=A.ax.expanded);let H;A.dom?.testId?H=`[data-testid="${A.dom.testId}"]`:A.dom?.id&&(H=`#${A.dom.id}`);let ne={id:C,role:P,label:Wh(O),kind:j,value:K,state:J,bbox:F};return H!==void 0&&(ne.selector=H),ne}),T="idle";try{let A=await t.evaluate(()=>document.readyState);A==="loading"?T="loading":A==="interactive"?T="navigating":T="idle"}catch{T="navigating"}T!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),v&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let I=qh(f),R=`obs_${e.observationCounter.toString(36)}`,M=new Date().toISOString();return{observationId:R,url:h,title:g,textSummary:I,interactive:x,status:{httpStatus:e.httpStatus??null,loadingState:T,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:M}}var ic,cc,lc=me(()=>{"use strict";Jt();ic=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);cc="a[href], button, input, select, textarea, [role], [tabindex], label"});async function dc(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function Wo(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>dc(t,s)))).filter(o=>o!==null)}async function Yh(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Go(t,e,n){switch(e.kind){case"element_id":return Xh(t,e,n);case"selector":return Qh(t,e);case"semantic":return Zh(t,e)}}async function Xh(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await Wo(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Qh(t,e){let n=t.locator(e.selector),r=await n.count();if(r===0)return{outcome:"not_found",query:e};if(r===1)return{outcome:"resolved",locator:n};let o=await Wo(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Zh(t,e){return e.role!==void 0?ey(t,e.text,e.role):ty(t,e.text,e)}async function ey(t,e,n){let r=t.getByRole(n,{name:e}),o=await r.count();if(o===0)return{outcome:"not_found",query:{kind:"semantic",text:e,role:n}};if(o===1)return{outcome:"resolved",locator:r};let s=await Wo(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function ty(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Yh(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let g=u[0];return g===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:g.locator.nth(g.index)}}let p=u.slice(0,5),f=[];for(let g=0;g<p.length;g++){let y=p[g];if(y===void 0)continue;let v=await dc(y.locator,y.index);if(v!==null){let b=`${v.role}:${v.label}:${g}`,w=0;for(let k=0;k<b.length;k++)w=w*31+b.charCodeAt(k)>>>0;f.push({...v,id:`el_${w.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var uc=me(()=>{"use strict"});import{randomBytes as ny}from"crypto";import{mkdir as ry,stat as oy,writeFile as sy}from"fs/promises";import{join as qo}from"path";import{gzip as iy}from"zlib";import{promisify as ay}from"util";function cy(t){return qo(hn(t),"browser")}function ly(t){return qo(cy(t),"screenshots")}function dy(){return new Date().toISOString().replace(/[:.]/g,"-")}function uy(){return ny(3).toString("hex")}async function zo(t,e,n){if(e.length>pc)throw new Error(`writeScreenshotSidecar: buffer exceeds ${pc} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=ly(t);await ry(r,{recursive:!0});let o=`${dy()}-${uy()}-${n}.png`,s=qo(r,o);await sy(s,e);let{size:i}=await oy(s);return{path:s,bytes:i}}var aI,pc,fc=me(()=>{"use strict";B();Jt();aI=ay(iy);pc=5*1024*1024});var gc={};js(gc,{PlaywrightProvider:()=>Jo});function mc(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var Jo,hc=me(()=>{"use strict";tc();lc();uc();jo();Jt();fc();Jo=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new or(e)}async open(e){let n=Ho(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(l){a=l}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let c=await sr(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,c.interactive,c.url,c.title,"browser_open"),a!==null)throw a;return c}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await sr(r,{observationCounter:o.observationCounter,screenshotPath:s,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n),includeHidden:e.includeHidden,maxElements:e.maxElements});return this.updateSessionFromObservation(o,i.interactive,i.url,i.title,"browser_observe"),i}async act(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_act: no page open for session ${n}`);let o=this.ensureSessionState(n),s=r.url(),i=e.timeoutMs??3e4,a=await Go(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${mc(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":{let g=Ko(e.value??"");await c.fill(e.value??"");break}case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(y){l=y}else l=g}let u=r.url();if(u!==s){let g=Ho(u,this.config);if(!g.allowed)return await r.goBack().catch(()=>{}),{outcome:"blocked_by_policy",url:u,reason:g.reason}}let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await sr(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),h=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,h),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await Go(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${mc(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await zo(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await zo(n,o,r);return s}catch{return null}}}});var Ze={};js(Ze,{__resetBrowserRegistryForTests:()=>hy,browserProviderActive:()=>my,closeBrowserProvider:()=>Vo,getBrowserProvider:()=>fy,peekBrowserProvider:()=>gy});function yc(){Promise.resolve(Vo()).then(()=>{process.exit(130)})}function bc(){Promise.resolve(Vo()).then(()=>{process.exit(143)})}function wc(){we=null}function py(){ir||(process.on("SIGINT",yc),process.on("SIGTERM",bc),process.on("exit",wc),ir=!0)}function Sc(){ir&&(process.removeListener("SIGINT",yc),process.removeListener("SIGTERM",bc),process.removeListener("exit",wc),ir=!1)}async function fy(t){return we!==null?we:(Qe!==null||(Qe=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(hc(),gc)),n=ec(t),r=new e(n);return py(),we=r,Qe=null,r})()),Qe)}async function Vo(){if(we===null)return;let t=we;we=null,Qe=null,Sc(),await t.shutdown()}function my(){return we!==null}function gy(){return we}function hy(){we=null,Qe=null,Sc()}var we,Qe,ir,et=me(()=>{"use strict";jo();we=null,Qe=null,ir=!1});N();import{existsSync as N_,readFileSync as Hs}from"fs";import{fileURLToPath as cp}from"url";import{dirname as lp,join as dp}from"path";function Ks(t,e){return!t||!e||t==="unknown"||e==="unknown"?{drift:!1}:t===e?{drift:!1}:{drift:!0,message:`[daemon] Version mismatch: running ${t} but installed is ${e}. Exiting.`}}import{Telegraf as Mk}from"telegraf";B();import Rp from"better-sqlite3";import{existsSync as Mt,mkdirSync as oi,readFileSync as Sn,writeFileSync as si,readdirSync as Ip,appendFileSync as Pp,unlinkSync as ii,copyFileSync as Cp,renameSync as Mp}from"fs";import{join as re,basename as ai,resolve as vn,relative as Op}from"path";N();function Tp(){return S.AFK_DEBUG==="1"||S.DEBUG==="1"}function L(...t){Tp()&&console.log(...t)}var ci="HOT.md",Dp="HOT.md.bak",li="memory.db",di="memory-wal.jsonl",kn="procedures",Fp="HOT.md.tmp",_n=5250,Lp=Math.ceil(_n/3.5),Np=600,mi=.8,Jr='<!-- HOT TRUNCATED to fit the ~1,500-token cap; move durable detail to the fact archive (memory_update target:"fact"). -->',Ot=2,$p=`
4
4
  CREATE TABLE IF NOT EXISTS sessions (
5
5
  session_id TEXT PRIMARY KEY,
6
6
  surface TEXT NOT NULL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-afk",
3
- "version": "3.92.1",
3
+ "version": "3.92.2",
4
4
  "description": "Local-first control plane for long-running AI agent work — delegation, traces, resumable sessions, verification, and notifications.",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",
@@ -103,6 +103,8 @@
103
103
  "audit:env:list": "tsx scripts/audit-env-access.ts --list",
104
104
  "scan:env": "tsx scripts/render-env-registry.ts",
105
105
  "scan:env:check": "tsx scripts/render-env-registry.ts --check",
106
+ "fix:pins": "tsx scripts/update-hash-pins.ts",
107
+ "fix:pins:check": "tsx scripts/update-hash-pins.ts --check",
106
108
  "stats:tools": "tsx scripts/count-tool-calls.ts",
107
109
  "clean": "rm -rf dist",
108
110
  "build:dist": "node scripts/build-dist.mjs",