agent-afk 5.89.0 → 5.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +4 -4
- package/dist/index.mjs +3 -3
- package/dist/telegram.mjs +3 -3
- package/package.json +1 -1
package/dist/telegram.mjs
CHANGED
|
@@ -842,7 +842,7 @@ ${e}`:[{type:"text",text:n},...e]}getInputStreamRef(){return{pushUserMessage:e=>
|
|
|
842
842
|
|
|
843
843
|
`;return i.toString("utf8")+c+a.toString("utf8")}function Zt(t){return Buffer.byteLength(t,"utf8")<=1e5?{content:t,truncated:!1}:{content:Ft(t,1e5),truncated:!0}}var $D,Ma,Pn=h(()=>{"use strict";$D=160;Ma=`
|
|
844
844
|
[output truncated \u2014 command exceeded the 8000000-byte output cap and was terminated]`});import Xu from"path";import{dirname as UD}from"path";import{appendFileSync as BD,mkdirSync as HD}from"fs";var en,Oa=h(()=>{"use strict";W();en=class{hooks;constructor(e){this.hooks=e}addReadRoot(e,n="slash",r){this.hooks.ensureInitialized?.();let o=this.hooks.getReadRoots();if(!o)return;let s=Xu.resolve(e);o.includes(s)||(o.push(s),this.appendAuditLog({action:"grant-read",path:s,source:n,sessionId:r}))}addWriteRoot(e,n="slash",r){this.hooks.ensureInitialized?.();let o=this.hooks.getReadRoots(),s=this.hooks.getWriteRoots();if(!o||!s)return;let i=Xu.resolve(e);o.includes(i)||o.push(i),s.includes(i)||(s.push(i),this.appendAuditLog({action:"grant-write",path:i,source:n,sessionId:r}))}revokeRoot(e,n="slash",r){let o=this.hooks.getReadRoots();if(!o)return;let s=Xu.resolve(e),i=this.hooks.getProtectedRoot();if(i!==void 0&&s===i)return;let a=o.indexOf(s);a!==-1&&o.splice(a,1);let l=this.hooks.getWriteRoots();if(l){let c=l.indexOf(s);c!==-1&&l.splice(c,1)}this.appendAuditLog({action:"revoke",path:s,source:n,sessionId:r})}getGrants(){return{resolveBase:this.hooks.getProtectedRoot(),readRoots:this.hooks.getReadRoots()?.slice()??[],writeRoots:this.hooks.getWriteRoots()?.slice()??[],allowAll:this.hooks.getAllowAll()}}appendAuditLog(e){try{let n=ai();HD(UD(n),{recursive:!0});let r=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e.sessionId??this.hooks.getDefaultSessionId?.()??null,action:e.action,path:e.path,source:e.source});BD(n,r+`
|
|
845
|
-
`)}catch{}}}});var jD,WD,KD,GD,qD,zD,JD,VD,YD,We,Mn,On,XD,QD,ZD,eF,tF,nF,rF,oF,sF,iF,aF,lF,cF,dF,St,ct,a5,Xe=h(()=>{"use strict";jD={name:"bash",category:"shell",concurrencySafe:!1,description:"Execute a shell command and return its stdout and stderr. Use for running programs, installing packages, git operations, and any task that requires a shell. Commands run in the user's default shell. Long-running commands should use timeout_ms. Output is capped to a ~100KB head+tail view (the start and end are kept, the middle elided with a notice), so the command still runs to completion and you keep the real exit code and the tail (test/build summaries, final errors). For the full body of a verbose command, filter it (`| tail -n`, `--quiet`, narrower flags) or redirect to a file and read slices. Commands emitting extreme output (>8MB) are terminated. For reading or writing files \u2014 especially anything sensitive \u2014 prefer the typed file tools (read_file, write_file, edit_file): they support per-call user approval, and interpreter one-liners (python -c, node -e, sh -c, ...) that reference credential paths (SSH keys, cloud credentials, /etc/shadow) are blocked by the path-approval policy on interactive surfaces.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds (default 120000, max 600000). The command is killed if it exceeds this duration."}},required:["command"]}},WD={name:"read_file",category:"read",concurrencySafe:!0,description:"Read a file from the filesystem. Returns the file content with line numbers. Use offset and limit to read specific sections of large files. When the read returns a partial view, the response ends with a `... (showing lines X-Y of Z [\u2014 pass offset=N to continue])` annotation indicating the full file size and how to continue. Binary files are detected and rejected. Missing files return an error.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to read."},offset:{type:"number",description:"Line number to start reading from (1-based). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to read. Defaults to 2000."}},required:["file_path"]}},KD={name:"write_file",category:"write",concurrencySafe:!1,description:"Write content to a file, creating it if it does not exist or overwriting if it does. Parent directories are created automatically. Prefer edit_file for modifying existing files \u2014 use write_file only for new files or complete rewrites.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to write."},content:{type:"string",description:"The full content to write to the file."}},required:["file_path","content"]}},GD={name:"edit_file",category:"write",concurrencySafe:!1,description:"Perform an exact string replacement in a file. Finds old_string and replaces it with new_string. The edit fails if old_string is not found or matches multiple locations (unless replace_all is true). Always use read_file first to verify the exact content before editing.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to edit."},old_string:{type:"string",description:"The exact string to find and replace. Must match file content exactly."},new_string:{type:"string",description:"The replacement string."},replace_all:{type:"boolean",description:"If true, replace all occurrences. If false (default), fail when multiple matches exist."}},required:["file_path","old_string","new_string"]}},qD={name:"glob",category:"read",concurrencySafe:!0,description:'Find files matching a glob pattern. Returns matching file paths, capped at 500 results. Use for discovering files before reading them. Patterns follow standard glob syntax (e.g., "src/**/*.ts", "*.json"). Skips node_modules/.git/.hg/.svn by default; name such a directory literally in the pattern (e.g. "node_modules/**/*.js") to search it.',input_schema:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern to match (e.g., "src/**/*.ts").'},path:{type:"string",description:"Base directory to search from. Defaults to the current working directory."}},required:["pattern"]}},zD={name:"grep",category:"read",concurrencySafe:!0,description:"Search file contents for lines matching a pattern. Returns matches in file:line:content format. Runs on ripgrep: `|` `+` `?` `(` `)` `{` `}` are regex metacharacters by default (e.g. `foo|bar` alternates, matching either branch) \u2014 escape with a backslash for the literal character. Honors .gitignore (so build/dependency dirs like node_modules are skipped) but DOES search hidden files/dirs like .github and .env; the .git directory and binary files are skipped. Output is capped to a ~100KB head+tail view; if a search is truncated, narrow it (a more specific pattern, an `include` glob, or a subdirectory `path`) rather than re-running the same broad query. Use for finding symbols, strings, or patterns across the codebase.",input_schema:{type:"object",properties:{pattern:{type:"string",description:'Search pattern (ripgrep regex syntax). `|` `+` `?` `(` `)` `{` `}` are metacharacters \u2014 e.g. `foo|bar` matches either "foo" or "bar". Escape with a backslash (e.g. `\\|`) to match the literal character.'},path:{type:"string",description:"Directory or file to search. Defaults to current working directory."},include:{type:"string",description:'File glob to restrict search (e.g., "*.ts"). Passed as -g to ripgrep.'}},required:["pattern"]}},JD={name:"list_directory",category:"read",concurrencySafe:!0,description:"List the contents of a directory. Returns file and subdirectory names with type annotations (directories end with /). Use for exploring project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Absolute path to the directory to list."}},required:["path"]}},VD={name:"send_telegram",category:"web",concurrencySafe:!1,riskClass:"caution",description:'Send a Telegram message to the operator. Use to surface terminal-state notifications, blocking questions, or important status updates when the user is away from keyboard (AFK). The message is delivered through the same Telegram bot the operator uses to drive this session. By default the message goes to your primary chat (the first private chat in `AFK_TELEGRAM_ALLOWED_CHAT_IDS`, or `AFK_TELEGRAM_PRIMARY_CHAT_ID` if set); set `telegram.notify` in afk.config.json to broadcast to all allowed chats or target a custom set.\n\nPlain text only \u2014 Telegram\'s 4096-character limit per message is enforced. Returns an error if Telegram is not configured (missing `TELEGRAM_BOT_TOKEN` or empty allowlist) so the tool is safe to attempt unconditionally.\n\nUse sparingly: this is a real push notification to a human. Reserve for terminal states (Done/Blocked/Asking) and material progress, not running commentary. When running inside the Telegram bot, prefer replying normally \u2014 your response already reaches the operator through the bot. Use this tool only from CLI or daemon sessions.\n\nOptionally set `chat` to route to a SPECIFIC chat instead of the default primary target: pass a numeric chat id (e.g. -1001234567890 for a group) or a chat alias name defined in afk.config.json `telegram.chatAliases` (e.g. "ops"). An explicitly-targeted chat must be in the inbound allowlist (AFK_TELEGRAM_ALLOWED_CHAT_IDS) \u2014 a non-allowlisted target is rejected (fail-closed). Omit `chat` for the default behavior (unchanged).',input_schema:{type:"object",properties:{message:{type:"string",description:"Plain-text message body to send to the operator. Max 4096 characters (Telegram API limit). Must be non-empty."},chat:{type:["number","string"],description:"Optional. Target a specific chat instead of the default primary target. A number (or numeric string) is a raw Telegram chat id; a non-numeric string is looked up as a name in afk.config.json `telegram.chatAliases`. The resolved chat must be allowlisted (AFK_TELEGRAM_ALLOWED_CHAT_IDS) or the send is rejected. Omit to send to the configured default (primary DM chat / notify targets)."}},required:["message"]}},YD={name:"web_scrape",category:"web",concurrencySafe:!0,description:'Scrape a web page or run a web search and return text content suitable for reasoning over. Three modes:\n\n- `markdown` (default): fetches the URL and extracts the main content as clean markdown (Readability + Turndown). Handles JS-rendered pages: if the plain fetch yields thin content, it escalates to a headless-browser render and re-extracts. Use this for articles, docs, blog posts, and most "I want to read this page" cases. No API key required (the render fallback needs the Playwright chromium binary; if it is absent the error names the exact install command for this installation).\n- `raw`: GETs the URL directly and returns the response body as decoded text, with no markdown transformation. Use for JSON APIs, robots.txt, RSS, or plain-text endpoints. Not byte-preserving \u2014 binary payloads are decoded as text, so do not rely on this for exact bytes. No API key required.\n- `search`: runs a web search and returns ranked markdown results. Use when you need to FIND a URL, not read one. Provide `query` instead of `url`. Requires `EXA_API_KEY` (free tier at https://exa.ai); the handler returns a clear error if it is unset.\n\nOutputs are capped at `max_bytes` UTF-8 bytes (default 100KB, ceiling 1MB); content over the cap is reduced to head+tail with a `\u2026 [N bytes truncated: \u2026] \u2026` marker so both ends survive. The request is aborted after `timeout_ms` (default 30000, ceiling 120000).',input_schema:{type:"object",properties:{mode:{type:"string",enum:["markdown","raw","search"],description:'Fetch mode. Defaults to "markdown".'},url:{type:"string",description:"Absolute http(s) URL. Required for markdown and raw modes. Ignored in search mode."},query:{type:"string",description:"Search query string. Required for search mode. Ignored otherwise."},timeout_ms:{type:"number",description:"Request timeout in milliseconds (default 30000, clamped to 120000)."},max_bytes:{type:"number",description:"Maximum UTF-8 bytes returned. Content beyond this is reduced to head+tail with a truncation marker (both ends preserved). Default 100000, clamped to 1000000."}},required:[]}},We={name:"agent",category:"subagent",concurrencySafe:!0,description:`Dispatch an independent subagent with its own context window and tool access. Use for tasks that protect the main session's context: codebase exploration, multi-file inspection, repo search, verification, debugging, failing-test investigation, PR review, parallel hypothesis testing, independent re-derivation of a claim, audit work, stale-path detection, feature-wiring checks, and any research-shaped investigation.
|
|
845
|
+
`)}catch{}}}});var jD,WD,KD,GD,qD,zD,JD,VD,YD,We,Mn,On,XD,QD,ZD,eF,tF,nF,rF,oF,sF,iF,aF,lF,cF,dF,St,ct,a5,Xe=h(()=>{"use strict";jD={name:"bash",category:"shell",concurrencySafe:!1,description:"Execute a shell command and return its stdout and stderr. Use for running programs, installing packages, git operations, and any task that requires a shell. Commands run through /bin/sh (Node spawn with shell:true) \u2014 NOT bash and NOT your $SHELL; /bin/sh is bash-in-POSIX-mode on macOS but dash on Debian/Ubuntu. Only process substitution <(...) reliably fails closed (exit 2, nothing runs). Other bashisms are nonportable and are NOT dependable refusals: [[ ]] runs on macOS but is a not-found command on dash while the rest of the line still executes; {a,b} expands on macOS but passes through literally on dash (silently wrong argument); arrays run on macOS but are a syntax error on dash. So never assume a bashism-containing command was side-effect-free \u2014 prefer a temp file or a POSIX equivalent. Long-running commands should use timeout_ms. Output is capped to a ~100KB head+tail view (the start and end are kept, the middle elided with a notice), so the command still runs to completion and you keep the real exit code and the tail (test/build summaries, final errors). For the full body of a verbose command, filter it (`| tail -n`, `--quiet`, narrower flags) or redirect to a file and read slices. Commands emitting extreme output (>8MB) are terminated. For reading or writing files \u2014 especially anything sensitive \u2014 prefer the typed file tools (read_file, write_file, edit_file): they support per-call user approval, and interpreter one-liners (python -c, node -e, sh -c, ...) that reference credential paths (SSH keys, cloud credentials, /etc/shadow) are blocked by the path-approval policy on interactive surfaces.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds (default 120000, max 600000). The command is killed if it exceeds this duration."}},required:["command"]}},WD={name:"read_file",category:"read",concurrencySafe:!0,description:"Read a file from the filesystem. Returns the file content with line numbers. Use offset and limit to read specific sections of large files. When the read returns a partial view, the response ends with a `... (showing lines X-Y of Z [\u2014 pass offset=N to continue])` annotation indicating the full file size and how to continue. Binary files are detected and rejected. Missing files return an error.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to read."},offset:{type:"number",description:"Line number to start reading from (1-based). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to read. Defaults to 2000."}},required:["file_path"]}},KD={name:"write_file",category:"write",concurrencySafe:!1,description:"Write content to a file, creating it if it does not exist or overwriting if it does. Parent directories are created automatically. Prefer edit_file for modifying existing files \u2014 use write_file only for new files or complete rewrites.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to write."},content:{type:"string",description:"The full content to write to the file."}},required:["file_path","content"]}},GD={name:"edit_file",category:"write",concurrencySafe:!1,description:"Perform an exact string replacement in a file. Finds old_string and replaces it with new_string. The edit fails if old_string is not found or matches multiple locations (unless replace_all is true). Always use read_file first to verify the exact content before editing.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to edit."},old_string:{type:"string",description:"The exact string to find and replace. Must match file content exactly."},new_string:{type:"string",description:"The replacement string."},replace_all:{type:"boolean",description:"If true, replace all occurrences. If false (default), fail when multiple matches exist."}},required:["file_path","old_string","new_string"]}},qD={name:"glob",category:"read",concurrencySafe:!0,description:'Find files matching a glob pattern. Returns matching file paths, capped at 500 results. Use for discovering files before reading them. Patterns follow standard glob syntax (e.g., "src/**/*.ts", "*.json"). Skips node_modules/.git/.hg/.svn by default; name such a directory literally in the pattern (e.g. "node_modules/**/*.js") to search it.',input_schema:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern to match (e.g., "src/**/*.ts").'},path:{type:"string",description:"Base directory to search from. Defaults to the current working directory."}},required:["pattern"]}},zD={name:"grep",category:"read",concurrencySafe:!0,description:"Search file contents for lines matching a pattern. Returns matches in file:line:content format. Runs on ripgrep: `|` `+` `?` `(` `)` `{` `}` are regex metacharacters by default (e.g. `foo|bar` alternates, matching either branch) \u2014 escape with a backslash for the literal character. Honors .gitignore (so build/dependency dirs like node_modules are skipped) but DOES search hidden files/dirs like .github and .env; the .git directory and binary files are skipped. Output is capped to a ~100KB head+tail view; if a search is truncated, narrow it (a more specific pattern, an `include` glob, or a subdirectory `path`) rather than re-running the same broad query. Use for finding symbols, strings, or patterns across the codebase.",input_schema:{type:"object",properties:{pattern:{type:"string",description:'Search pattern (ripgrep regex syntax). `|` `+` `?` `(` `)` `{` `}` are metacharacters \u2014 e.g. `foo|bar` matches either "foo" or "bar". Escape with a backslash (e.g. `\\|`) to match the literal character.'},path:{type:"string",description:"Directory or file to search. Defaults to current working directory."},include:{type:"string",description:'File glob to restrict search (e.g., "*.ts"). Passed as -g to ripgrep.'}},required:["pattern"]}},JD={name:"list_directory",category:"read",concurrencySafe:!0,description:"List the contents of a directory. Returns file and subdirectory names with type annotations (directories end with /). Use for exploring project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Absolute path to the directory to list."}},required:["path"]}},VD={name:"send_telegram",category:"web",concurrencySafe:!1,riskClass:"caution",description:'Send a Telegram message to the operator. Use to surface terminal-state notifications, blocking questions, or important status updates when the user is away from keyboard (AFK). The message is delivered through the same Telegram bot the operator uses to drive this session. By default the message goes to your primary chat (the first private chat in `AFK_TELEGRAM_ALLOWED_CHAT_IDS`, or `AFK_TELEGRAM_PRIMARY_CHAT_ID` if set); set `telegram.notify` in afk.config.json to broadcast to all allowed chats or target a custom set.\n\nPlain text only \u2014 Telegram\'s 4096-character limit per message is enforced. Returns an error if Telegram is not configured (missing `TELEGRAM_BOT_TOKEN` or empty allowlist) so the tool is safe to attempt unconditionally.\n\nUse sparingly: this is a real push notification to a human. Reserve for terminal states (Done/Blocked/Asking) and material progress, not running commentary. When running inside the Telegram bot, prefer replying normally \u2014 your response already reaches the operator through the bot. Use this tool only from CLI or daemon sessions.\n\nOptionally set `chat` to route to a SPECIFIC chat instead of the default primary target: pass a numeric chat id (e.g. -1001234567890 for a group) or a chat alias name defined in afk.config.json `telegram.chatAliases` (e.g. "ops"). An explicitly-targeted chat must be in the inbound allowlist (AFK_TELEGRAM_ALLOWED_CHAT_IDS) \u2014 a non-allowlisted target is rejected (fail-closed). Omit `chat` for the default behavior (unchanged).',input_schema:{type:"object",properties:{message:{type:"string",description:"Plain-text message body to send to the operator. Max 4096 characters (Telegram API limit). Must be non-empty."},chat:{type:["number","string"],description:"Optional. Target a specific chat instead of the default primary target. A number (or numeric string) is a raw Telegram chat id; a non-numeric string is looked up as a name in afk.config.json `telegram.chatAliases`. The resolved chat must be allowlisted (AFK_TELEGRAM_ALLOWED_CHAT_IDS) or the send is rejected. Omit to send to the configured default (primary DM chat / notify targets)."}},required:["message"]}},YD={name:"web_scrape",category:"web",concurrencySafe:!0,description:'Scrape a web page or run a web search and return text content suitable for reasoning over. Three modes:\n\n- `markdown` (default): fetches the URL and extracts the main content as clean markdown (Readability + Turndown). Handles JS-rendered pages: if the plain fetch yields thin content, it escalates to a headless-browser render and re-extracts. Use this for articles, docs, blog posts, and most "I want to read this page" cases. No API key required (the render fallback needs the Playwright chromium binary; if it is absent the error names the exact install command for this installation).\n- `raw`: GETs the URL directly and returns the response body as decoded text, with no markdown transformation. Use for JSON APIs, robots.txt, RSS, or plain-text endpoints. Not byte-preserving \u2014 binary payloads are decoded as text, so do not rely on this for exact bytes. No API key required.\n- `search`: runs a web search and returns ranked markdown results. Use when you need to FIND a URL, not read one. Provide `query` instead of `url`. Requires `EXA_API_KEY` (free tier at https://exa.ai); the handler returns a clear error if it is unset.\n\nOutputs are capped at `max_bytes` UTF-8 bytes (default 100KB, ceiling 1MB); content over the cap is reduced to head+tail with a `\u2026 [N bytes truncated: \u2026] \u2026` marker so both ends survive. The request is aborted after `timeout_ms` (default 30000, ceiling 120000).',input_schema:{type:"object",properties:{mode:{type:"string",enum:["markdown","raw","search"],description:'Fetch mode. Defaults to "markdown".'},url:{type:"string",description:"Absolute http(s) URL. Required for markdown and raw modes. Ignored in search mode."},query:{type:"string",description:"Search query string. Required for search mode. Ignored otherwise."},timeout_ms:{type:"number",description:"Request timeout in milliseconds (default 30000, clamped to 120000)."},max_bytes:{type:"number",description:"Maximum UTF-8 bytes returned. Content beyond this is reduced to head+tail with a truncation marker (both ends preserved). Default 100000, clamped to 1000000."}},required:[]}},We={name:"agent",category:"subagent",concurrencySafe:!0,description:`Dispatch an independent subagent with its own context window and tool access. Use for tasks that protect the main session's context: codebase exploration, multi-file inspection, repo search, verification, debugging, failing-test investigation, PR review, parallel hypothesis testing, independent re-derivation of a claim, audit work, stale-path detection, feature-wiring checks, and any research-shaped investigation.
|
|
846
846
|
|
|
847
847
|
Parallelize: dispatch multiple \`agent\` calls in a single tool-use turn to run independent investigations concurrently.
|
|
848
848
|
|
|
@@ -867,7 +867,7 @@ ${n}
|
|
|
867
867
|
Remedy: these paths are outside the fork's granted read roots. Re-dispatch with the needed paths inside the child's cwd/worktree, or pass explicit readRoots granting them. If this worker is deliberately confined (e.g. an \`afk farm\` branch worker), this failure is expected \u2014 the paths are outside its assigned scope; widen the scope or narrow the task.`}var Sr,Dw,fF,Da=h(()=>{"use strict";Sr="denial-breaker",Dw=new Set(["read_file","list_directory","glob","grep"]),fF="Sub-agent path access denied:"});import{createHash as mF}from"node:crypto";function $w(){return{recent:[],firedFingerprints:new Set}}function Fa(t){let e;try{e=hF(t.input)}catch{e=String(t.input)}return mF("sha256").update(t.name).update("\0").update(e).digest("hex")}function hF(t){return JSON.stringify(ep(t))??"null"}function ep(t){if(Array.isArray(t))return t.map(ep);if(t!==null&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=ep(e[r]);return n}return t}function yF(t,e){let n=0;for(let r of t)r===e&&(n+=1);return n}function Uw(t,e){t.recent.push(e),t.recent.length>tp&&t.recent.shift();let n=yF(t.recent,e);return n>=gF&&!t.firedFingerprints.has(e)?(t.firedFingerprints.add(e),{fired:!0,count:n}):{fired:!1,count:n}}var gF,tp,np=h(()=>{"use strict";gF=5,tp=20});function wF(t){if(t===null||typeof t!="object"||Array.isArray(t))return t;let e={};for(let[n,r]of Object.entries(t))bF.has(n)||(e[n]=r);return e}function Lo(t){return Fa({...t,input:wF(t.input)})}function SF(t){let e=t.content.split(`
|
|
868
868
|
`).find(n=>n.trim()!=="")?.trim()??"";return e.length<=Bw?e:`${e.slice(0,Bw)}\u2026`}var rp,bF,Bw,La,Hw=h(()=>{"use strict";np();rp=3,bF=new Set(["timeout_ms","timeoutMs","timeout"]),Bw=240;La=class{streaks=new Map;check(e){let n=this.streaks.get(Lo(e));return n===void 0||n.count<rp?null:{count:n.count,tool:e.name,result:{content:`Repeat-failure guard: "${e.name}" has already failed ${n.count} times in a row with the same arguments, so this call was NOT executed again. The last failure was: ${n.lastError}
|
|
869
869
|
|
|
870
|
-
Retrying it verbatim will fail the same way. Fix the underlying cause, change the arguments, use a different tool, or stop and report the blocker.`,isError:!0,failureClass:"repeat-failure"}}}note(e,n){let r=Lo(e);if(n.isError!==!0){this.streaks.delete(r);return}let o=this.streaks.get(r);this.streaks.set(r,{count:(o?.count??0)+1,lastError:SF(n)})}streakFor(e){return this.streaks.get(Lo(e))?.count??0}}});var kF,op,EF,vt,Na=h(()=>{"use strict";ce();pe();Ca();Ea();xa();Yu();Pn();Oa();Q();Zu();Ow();Da();np();Hw();Zu();kF=8,op=new Set,EF=8,vt=class{handlers;schemas;hookRegistry;permissions;canUseTool;subagentExecutor;skillExecutor;composeExecutor;classifier;maxConcurrentSafeCalls;resolveBase;_readRoots;_writeRoots;_allowAll;_env;sessionId;parentSessionId;subagentId;sessionGrantManager;traceWriter;readOnlyBash;maxOutputBytes;repeatBreaker=null;repeatFailureGuard=new La;denialBreaker=null;suspectedLoopWindow=null;grantManager;constructor(e){this.handlers=e.handlers,this.schemas=e.schemas,this.hookRegistry=e.hookRegistry,this.permissions=e.permissions,this.canUseTool=e.canUseTool,this.subagentExecutor=e.subagentExecutor,this.skillExecutor=e.skillExecutor,this.composeExecutor=e.composeExecutor,this.classifier=e.concurrencyClassifier??Qu,this.maxConcurrentSafeCalls=typeof e.maxConcurrentSafeCalls=="number"&&Number.isFinite(e.maxConcurrentSafeCalls)&&e.maxConcurrentSafeCalls>=1?Math.floor(e.maxConcurrentSafeCalls):EF,this.resolveBase=e.cwd,this._env=e.env,this.sessionId=e.sessionId,this.parentSessionId=e.parentSessionId,this.subagentId=e.subagentId,this.sessionGrantManager=e.sessionGrantManager,this.traceWriter=e.traceWriter,this.readOnlyBash=e.readOnlyBash===!0,this.maxOutputBytes=typeof e.maxOutputBytes=="number"&&Number.isFinite(e.maxOutputBytes)&&e.maxOutputBytes>0?e.maxOutputBytes:void 0,this._allowAll=e.allowAll===!0;let n=e.cwd?[e.cwd]:[];this._readRoots=e.readRoots??n.slice(),this._writeRoots=e.writeRoots??n.slice(),this.grantManager=new en({getReadRoots:()=>this._readRoots,getWriteRoots:()=>this._writeRoots,getProtectedRoot:()=>this.resolveBase,getAllowAll:()=>this._allowAll,getDefaultSessionId:()=>this.sessionId})}get handlerContext(){return{cwd:this.resolveBase,resolveBase:this.resolveBase,readRoots:this._readRoots.slice(),writeRoots:this._writeRoots.slice(),...this._allowAll?{allowAll:!0}:{},...this._env!==void 0?{env:this._env}:{},...this.sessionId!==void 0?{sessionId:this.sessionId}:{}}}callHandlerContext(e){return{...this.handlerContext,toolUseId:e.id,...this.traceWriter!==void 0?{traceWriter:this.traceWriter}:{}}}addReadRoot(e,n="slash"){this.grantManager.addReadRoot(e,n)}addWriteRoot(e,n="slash"){this.grantManager.addWriteRoot(e,n)}revokeRoot(e,n="slash"){this.grantManager.revokeRoot(e,n)}getGrants(){return this.grantManager.getGrants()}setAllowAll(e){this._allowAll=e}setResolveBase(e){let n=this.resolveBase;if(n!==e){if(this.resolveBase=e,n!==void 0){let r=this._readRoots.indexOf(n);r!==-1?this._readRoots[r]=e:this._readRoots.includes(e)||this._readRoots.push(e);let o=this._writeRoots.indexOf(n);o!==-1?this._writeRoots[o]=e:this._writeRoots.includes(e)||this._writeRoots.push(e)}else this._readRoots.includes(e)||this._readRoots.push(e),this._writeRoots.includes(e)||this._writeRoots.push(e);this.subagentExecutor?.setCwd(e),this.skillExecutor?.setCwd(e),this.composeExecutor?.setCwd(e)}}get toolDefs(){let e=this.permissions?.allowedTools;if(!e)return this.schemas;let n=new Set(e);return this.schemas.filter(r=>n.has(r.name))}async checkReadOnlyBash(e){if(!this.readOnlyBash||e.name!=="bash")return null;let n=e.input,r=typeof n=="object"&&n!==null?n.command:void 0;if(typeof r!="string")return null;let o=Pa(r);if(!o.mutating)return null;let s=`Bash command blocked: read-only skill may not run mutating commands (${o.reason??"mutation detected"}). Allowed: read-only recon (git status/log/diff, ls, cat, find, grep).`;return await this.emitPreToolUseBlock(e.name,s),{content:s,isError:!0,failureClass:"permission-denied"}}async emitPreToolUseBlock(e,n){await Ye(this.traceWriter,{hookEvent:"PreToolUse",decision:"block",blockedTool:e,reason:n,...this.subagentId!==void 0?{subagentId:this.subagentId}:{}})}checkRepeatCircuitBreaker(e){if(op.has(e.name))return null;let n=Mw(e);return this.repeatBreaker!==null&&this.repeatBreaker.fingerprint===n?this.repeatBreaker.count+=1:this.repeatBreaker={fingerprint:n,count:1},this.repeatBreaker.count<kF?null:{content:`Loop circuit breaker: "${e.name}" has been called ${this.repeatBreaker.count} times in a row with byte-identical input. The result will not change. Stop repeating this call \u2014 reuse the previous result, change the input, try a different tool, or end the turn.`,isError:!0,circuitBreaker:!0}}checkRepeatFailureGuard(e){if(op.has(e.name))return null;let n=this.repeatFailureGuard.check(e);return n===null?null:(D(`[repeat-failure-guard #723] refused ${n.tool} after ${n.count} identical failures`),n.result)}observeSuspectedLoop(e){if(this.parentSessionId===void 0)return;this.suspectedLoopWindow===null&&(this.suspectedLoopWindow=$w());let n=Fa(e),r=Uw(this.suspectedLoopWindow,n);r.fired&&G(this.traceWriter,{phase:"suspected_loop",metadata:{tool:e.name,count:r.count,windowSize:tp}})}recordForkReadDenial(e,n,r){if(this.parentSessionId===void 0||!Dw.has(e.name)||!Fw(n))return r;let o=this.denialBreaker??{count:0,deniedPaths:[]};o.count+=1;let s=Lw(e);return o.deniedPaths.includes(s)||o.deniedPaths.push(s),this.denialBreaker=o,o.count<5?r:{content:Nw(o.deniedPaths,o.count),isError:!0,failureClass:Sr}}resetDenialBreaker(){this.denialBreaker=null}async runCanUseTool(e){if(!this.canUseTool)return null;let n;try{n=await this.canUseTool(e.name,e.input??{},{signal:e.signal,toolUseID:e.id})}catch(r){let o=`Tool "${e.name}" denied by canUseTool (threw): ${r instanceof Error?r.message:String(r)}`;return await this.emitPreToolUseBlock(e.name,o),{content:o,isError:!0,failureClass:"permission-denied"}}if(n.behavior==="deny"){let r=n.message||`Tool "${e.name}" denied by permission policy`;return await this.emitPreToolUseBlock(e.name,r),{content:r,isError:!0,failureClass:"permission-denied"}}return n.updatedInput!==void 0&&(e.input=n.updatedInput),null}async execute(e){if(e.signal.aborted)return{content:"Tool call aborted",isError:!0,failureClass:"abort"};if(this.hookRegistry){let l={event:"PreToolUse",toolName:e.name,input:e.input,...this.sessionId!==void 0?{sessionId:this.sessionId}:{},...this.resolveBase!==void 0?{cwd:this.resolveBase}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{}};try{await Wu(this.hookRegistry,l,{signal:e.signal,...this.traceWriter?{traceWriter:this.traceWriter}:{}})}catch(c){if(c instanceof Z)return this.recordForkReadDenial(e,c.reason,{content:`Tool "${e.name}" blocked by PreToolUse hook: ${c.message}`,isError:!0,failureClass:"hook-block"});throw c}}let n=Ju(e.name,this.permissions);if(!n.allowed){let l=n.reason??`Tool "${e.name}" is not permitted`;return await this.emitPreToolUseBlock(e.name,l),{content:l,isError:!0,failureClass:"permission-denied"}}let r=await this.runCanUseTool(e);if(r)return r;let o=await this.checkReadOnlyBash(e);if(o)return o;let s=this.checkRepeatCircuitBreaker(e);if(s)return s;let i=this.checkRepeatFailureGuard(e);if(i)return i;this.observeSuspectedLoop(e);let a=await this.executeCore(e);return this.repeatFailureGuard.note(e,a),a.isError!==!0&&this.resetDenialBreaker(),a}async executeBatch(e){if(e.length===0)return[];if(e.length===1)return[await this.execute(e[0])];let n=new Array(e.length),r=new Set;for(let i=0;i<e.length;i++){let a=e[i];if(a.signal.aborted){n[i]={content:"Tool call aborted",isError:!0,failureClass:"abort"},r.add(i);continue}if(this.hookRegistry){let f={event:"PreToolUse",toolName:a.name,input:a.input,...this.sessionId!==void 0?{sessionId:this.sessionId}:{},...this.resolveBase!==void 0?{cwd:this.resolveBase}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{}};try{await Wu(this.hookRegistry,f,{signal:a.signal,...this.traceWriter?{traceWriter:this.traceWriter}:{}})}catch(m){if(m instanceof Z){n[i]=this.recordForkReadDenial(a,m.reason,{content:`Tool "${a.name}" blocked by PreToolUse hook: ${m.message}`,isError:!0,failureClass:"hook-block"}),r.add(i);continue}throw m}}let l=Ju(a.name,this.permissions);if(!l.allowed){let f=l.reason??`Tool "${a.name}" is not permitted`;await this.emitPreToolUseBlock(a.name,f),n[i]={content:f,isError:!0,failureClass:"permission-denied"},r.add(i);continue}let c=await this.runCanUseTool(a);if(c){n[i]=c,r.add(i);continue}let d=await this.checkReadOnlyBash(a);if(d){n[i]=d,r.add(i);continue}let u=this.checkRepeatCircuitBreaker(a);if(u){n[i]=u,r.add(i);continue}let p=this.checkRepeatFailureGuard(a);if(p){n[i]=p,r.add(i);continue}this.observeSuspectedLoop(a)}let o=e.map((i,a)=>({call:i,originalIndex:a})).filter((i,a)=>!r.has(a));if(o.length===0)return n;let s=Pw(o.map(i=>i.call),this.classifier);for(let i of s){if(i.isConcurrencySafe){let l=[...i.indices];for(;l.length>0;){let c=new Map,d=[],u=[];for(let f of l){let{call:m,originalIndex:g}=o[f],y=this.checkRepeatFailureGuard(m);if(y){n[g]=y;continue}if(op.has(m.name)){d.push(f);continue}let w=Lo(m),v=rp-this.repeatFailureGuard.streakFor(m),A=c.get(w)??0;A<v?(c.set(w,A+1),d.push(f)):u.push(f)}l=u;let p=await wr(d,this.maxConcurrentSafeCalls,async f=>{let{call:m,originalIndex:g}=o[f];return m.signal.aborted?{result:{content:"Tool call aborted",isError:!0,failureClass:"abort"},originalIndex:g}:{result:await this.executeCore(m),originalIndex:g}});for(let f of p)if(f.status==="fulfilled")n[f.value.originalIndex]=f.value.result;else{let m=f.reason instanceof Error?f.reason.message:String(f.reason),g=d[p.indexOf(f)];n[o[g].originalIndex]={content:`Tool execution error: ${m}`,isError:!0}}for(let f of d){let{call:m,originalIndex:g}=o[f],y=n[g];y!==void 0&&y.failureClass!=="abort"&&this.repeatFailureGuard.note(m,y)}}}else for(let l of i.indices){let{call:c,originalIndex:d}=o[l];if(c.signal.aborted){n[d]={content:"Tool call aborted",isError:!0,failureClass:"abort"};continue}let u=this.checkRepeatFailureGuard(c);if(u){n[d]=u;continue}let p=await this.executeCore(c);n[d]=p,this.repeatFailureGuard.note(c,p)}let a=i.indices.length;i.indices.forEach((l,c)=>{let d=n[o[l].originalIndex];d&&(d.batchIndex=c+1,d.batchSize=a)})}return n.some(i=>i!==void 0&&i.isError!==!0)&&this.resetDenialBreaker(),n}async executeCore(e){let n=await this.executeCoreInner(e);return this.applyOutputCap(n)}applyOutputCap(e){let n=this.maxOutputBytes;if(n===void 0)return e;let r=Buffer.byteLength(e.content,"utf8");return r<=n||(e.content=Ft(e.content,n),e.truncated=!0,D(`[output-cap #661] fork tool result capped: original=${r}B capped=${Buffer.byteLength(e.content,"utf8")}B (cap=${n}B)`)),e}async executeCoreInner(e){if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let i,a=!1,l="";try{i=await this.subagentExecutor.execute(e)}catch(c){a=!0,l=c instanceof Error?c.message:String(c),i={content:`Agent tool error: ${l}`,isError:!0}}return a?this.firePostToolUseFailure(e.name,l,e.signal,e.input):this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let i,a=!1,l="";try{i=await this.skillExecutor.execute(e)}catch(c){a=!0,l=c instanceof Error?c.message:String(c),i={content:`Skill tool error: ${l}`,isError:!0}}return a?this.firePostToolUseFailure(e.name,l,e.signal,e.input):this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}if(e.name==="compose"){let i=await this.executeCompose(e);return this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}let n=this.handlers.get(e.name);if(!n)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let r,o=!1,s="";try{r=await n(e.input,e.signal,this.callHandlerContext(e))}catch(i){o=!0,s=i instanceof Error?i.message:String(i),r={content:`Tool execution error: ${s}`,isError:!0}}return o?this.firePostToolUseFailure(e.name,s,e.signal,e.input):this.firePostToolUse(e.name,r.content,e.signal,e.input,r),r}async executeCompose(e){if(!this.composeExecutor)return{content:"Compose tool is not available in this session configuration",isError:!0};try{return await this.composeExecutor.execute(e)}catch(n){return{content:`Compose tool error: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}firePostToolUse(e,n,r,o,s){if(!this.hookRegistry)return;let i={event:"PostToolUse",toolName:e,output:n,...o!==void 0?{input:o}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{},...s?.incomplete===!0?{incomplete:!0}:{},...s?.incompleteReason?{incompleteReason:s.incompleteReason}:{}};ww(this.hookRegistry,i,{signal:r,...this.traceWriter?{traceWriter:this.traceWriter}:{}}).catch(()=>{})}firePostToolUseFailure(e,n,r,o){if(!this.hookRegistry)return;let s={event:"PostToolUseFailure",toolName:e,error:n,...o!==void 0?{input:o}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{}};Sw(this.hookRegistry,s,{signal:r,...this.traceWriter?{traceWriter:this.traceWriter}:{}}).catch(i=>{D(`firePostToolUseFailure outer catch (tool=${e}): ${String(i)}`)})}}});function DF(t){let e=t.match(AF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10),o=e[3]!==void 0?parseInt(e[3],10):void 0;return{runner:"vitest",passed:n,failed:r,...o!==void 0?{skipped:o}:{}}}function FF(t){let e=t.match(_F);if(!e)return null;let n=parseInt(e[1]??"0",10);return{runner:"jest",passed:parseInt(e[2]??"0",10),failed:n}}function LF(t){let e=t.match(TF);if(!e)return null;if(e[2]!==void 0){let n=parseInt(e[2],10),r=parseInt(e[1]??"0",10);return{runner:"pytest",passed:n,failed:r}}return e[4]!==void 0?{runner:"pytest",passed:parseInt(e[4],10),failed:0}:null}function NF(t){let e=t.match(RF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=t.match(xF),o=r?parseInt(r[1]??"0",10):0;return{runner:"mocha",passed:n,failed:o}}function $F(t){let e=[...t.matchAll(CF)];if(e.length===0)return null;let n=0,r=0;for(let o of e)o[1]==="ok"?n++:o[1]==="FAIL"&&r++;return{runner:"go-test",passed:n,failed:r}}function UF(t){let e=t.match(IF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10),o=e[3]!==void 0?parseInt(e[3],10):void 0;return{runner:"cargo",passed:n,failed:r,...o!==void 0?{skipped:o}:{}}}function BF(t){let e=t.match(PF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10);return{runner:"rspec",passed:n-r,failed:r}}function HF(t){let e=t.match(MF);if(e)return{runner:"phpunit",passed:parseInt(e[1]??"0",10),failed:0};let n=t.match(OF);if(n){let r=parseInt(n[1]??"0",10),o=parseInt(n[2]??"0",10);return{runner:"phpunit",passed:r-o,failed:o}}return null}function sp(t){return DF(t)??FF(t)??LF(t)??NF(t)??$F(t)??UF(t)??BF(t)??HF(t)??null}var AF,_F,TF,RF,xF,CF,IF,PF,MF,OF,jw=h(()=>{"use strict";AF=/Tests\s+(\d+)\s+passed(?:\s*\|\s*(\d+)\s+failed)?(?:\s*\|\s*(\d+)\s+skipped)?/,_F=/Tests:\s+(?:(\d+)\s+failed,\s*)?(\d+)\s+passed,\s*\d+\s+total/,TF=/={3,}\s*(?:(\d+)\s+failed,\s*)?(\d+)\s+passed(?:,\s*(\d+)\s+warning)?.*in\s+[\d.]+s\s*={3,}|={3,}\s*(\d+)\s+passed.*in\s+[\d.]+s\s*={3,}/,RF=/(\d+)\s+passing/,xF=/(\d+)\s+failing/,CF=/^(ok|FAIL)\s+\S+\s+[\d.]+s/gm,IF=/test result: (?:ok|FAILED)\. (\d+) passed; (\d+) failed(?:; (\d+) ignored)?/,PF=/(\d+) examples?, (\d+) failures?/,MF=/OK \((\d+) tests?/,OF=/Tests:\s*(\d+)[^]*?Failures:\s*(\d+)/});import{statSync as jF}from"node:fs";function No(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.code==="ENOENT"&&typeof e.syscall=="string"&&e.syscall.startsWith("spawn")}function WF(t){if(t===void 0)return!1;try{return jF(t),!1}catch{return!0}}function vr(t,e){let n=t instanceof Error?t.message:typeof t?.message=="string"?String(t.message):String(t);return No(t)&&WF(e)?`working directory does not exist: ${e} (deleted worktree?) \u2014 underlying: ${n}`:n}var ip=h(()=>{"use strict"});function kt(t){if(Ww)return;Ww=!0;let e=t instanceof Error?t.message:String(t);console.warn(`[afk-home] Malformed AFK home/state env var ignored while deriving the credential floor: ${e}. The relocated tree is NOT protected \u2014 the default ~/.afk entries still apply. Fix the env var to restore coverage.`)}var Ww,$o=h(()=>{"use strict";Ww=!1});import{statSync as lp}from"node:fs";import{homedir as KF}from"node:os";import{basename as GF,dirname as Gw,join as qF}from"node:path";function qw(t){return typeof t=="object"&&t!==null&&"code"in t?String(t.code):void 0}function zF(t){let e=GF(t),n=e===e.toLowerCase()?e.toUpperCase():e.toLowerCase();if(n===e)return;let r;try{r=lp(t)}catch{return}let o=ap.get(r.dev);if(o!==void 0)return o;try{let s=lp(qF(Gw(t),n)),i=r.dev===s.dev&&r.ino===s.ino;return ap.set(r.dev,i),i}catch(s){let i=qw(s);return i==="ENOENT"||i==="ENOTDIR"?(ap.set(r.dev,!1),!1):void 0}}function zw(t=KF()){if(Kw!==void 0)return Kw;let e=t;for(;;)try{return lp(e),zF(e)??!0}catch(n){let r=qw(n);if(r!=="ENOENT"&&r!=="ENOTDIR")return!0;let o=Gw(e);if(o===e)return!0;e=o}}function kr(t,e,n=e){if(t===e||t.startsWith(e+"/"))return!0;if(!zw(n))return!1;let r=t.toLowerCase(),o=e.toLowerCase();return r===o||r.startsWith(o+"/")}function cp(t,e){return t.includes(e)?!0:zw(e)?t.toLowerCase().includes(e.toLowerCase()):!1}var Kw,ap,$a=h(()=>{"use strict";ap=new Map});import{realpathSync as Jw}from"fs";import{dirname as JF,resolve as Dn,join as dp}from"path";import{homedir as tn}from"os";function YF(){let t=[];try{let e=re();t.push(ge(Dn(dp(e,"config")))),t.push(ge(Dn(dp(e,"state"))))}catch(e){kt(e)}try{t.push(ge(Dn(ye())))}catch(e){kt(e)}return t}function up(){let t=k.AFK_WRITE_DENYLIST,e=t?t.split(":").map(r=>ge(Dn(r))).filter(Boolean):[];return[...[...new Set([...VF.map(r=>ge(Dn(r))),...YF()])],...e]}function ge(t){let e=Dn(t);try{return Jw(e)}catch{}let n=[],r=e;for(let o=0;o<64;o++){let s=JF(r);if(s===r)break;n.unshift(r.slice(s.length+1)),r=s;try{let i=Jw(r);return dp(i,...n)}catch{}}return e}function Ua(t,e="write_file"){let n=ge(Dn(t));for(let r of up())if(kr(n,r))throw new Error(`${e}: refusing to write to protected path: ${n} (matches denylist entry: ${r})`)}var VF,Er=h(()=>{"use strict";B();W();$o();$a();VF=[`${tn()}/.ssh`,`${tn()}/.aws`,`${tn()}/.gnupg`,`${tn()}/.config/gcloud`,"/etc","/System","/private/etc","/usr/local/etc",`${tn()}/.afk/config`,`${tn()}/.afk/state`,`${tn()}/.npmrc`,`${tn()}/.docker/config.json`]});import{basename as XF,dirname as QF,join as Ba,relative as ZF,resolve as Ar,sep as Uo}from"path";import{homedir as me}from"os";function Yw(t){let e=Ar(t);return Ba(ge(QF(e)),XF(e))}function fp(t){return t?t.split(":").map(e=>e.trim()).filter(Boolean).map(e=>e==="~"||e.startsWith("~/")?Ba(me(),e.slice(1)):e).map(e=>Ar(e)):[]}function tL(){try{return[ge(Ar(Ba(re(),"config")))]}catch(t){return kt(t),[]}}function nL(){try{let t=re();return _r.filter(e=>e.startsWith(Vw)).map(e=>Yw(Ba(t,e.slice(Vw.length))))}catch(t){return kt(t),[]}}function Xw(){let t=`${k.AFK_READ_DENYLIST??""}\0${k.AFK_HOME??""}`;if(Bo&&Bo.key===t)return Bo;let e=fp(k.AFK_READ_DENYLIST).map(r=>ge(r)).filter(Boolean),n=[...new Set([...pp.map(r=>ge(Ar(r))),...tL()])];return Bo={key:t,builtins:n,extras:e,allow:[...new Set([...eL.map(Yw),...nL()])]},Bo}function mp(){let{builtins:t,extras:e}=Xw();return[...t,...e]}function Qw(t){let e=ge(Ar(t));return mp().filter(n=>n!==e&&kr(n,e,n)).map(n=>(n.startsWith(e+Uo)?ZF(e,n):n.split(Uo).slice(e.split(Uo).length).join(Uo)).split(Uo).join("/"))}function Qe(t){let e=ge(Ar(t)),{builtins:n,extras:r,allow:o}=Xw();for(let s of r)if(kr(e,s))return{denied:!0,matched:s};if(o.includes(e))return{denied:!1};for(let s of n)if(kr(e,s))return{denied:!0,matched:s};return{denied:!1}}var pp,_r,eL,Bo,Vw,nn=h(()=>{"use strict";B();Er();W();$o();$a();pp=[`${me()}/.ssh`,`${me()}/.aws`,`${me()}/.gnupg`,`${me()}/.config/gcloud`,`${me()}/.afk/config`,`${me()}/.npmrc`,`${me()}/.docker/config.json`,`${me()}/.git-credentials`,`${me()}/.netrc`,`${me()}/.config/gh/hosts.yml`,`${me()}/.kube/config`,"/etc/shadow","/etc/sudoers","/private/etc/master.passwd",`${me()}/.password-store`,`${me()}/Library/Application Support/Google/Chrome`,`${me()}/Library/Application Support/Chromium`,`${me()}/Library/Application Support/BraveSoftware`,`${me()}/Library/Application Support/Microsoft Edge`,`${me()}/Library/Application Support/Arc`,`${me()}/Library/Application Support/Firefox`],_r=[".afk/config/mcp.json",".ssh/config",".ssh/known_hosts"],eL=_r.map(t=>`${me()}/${t}`);Vw=".afk/"});import Fn from"path";import{realpathSync as rL}from"fs";function Ze(t){try{return rL.native(t)}catch{let e=Fn.dirname(t),n=Fn.basename(t);return e===t?t:Fn.join(Ze(e),n)}}function oL(t){let e=Zw.get(t);if(e!==void 0)return e;let n=Ze(t);return Zw.set(t,n),n}function eS(t,e,n,r){let o=e?.resolveBase??e?.cwd??r,s=Fn.isAbsolute(t)?t:Fn.resolve(o??process.cwd(),t);if(e?.allowAll===!0)return{restricted:!1,resolved:s,roots:[]};if(o===void 0)return{restricted:!1,resolved:s,roots:[]};let i=Ze(s),a=n==="read"?e?.readRoots??[o]:e?.writeRoots??[o];for(let l of a){let c=oL(l),d=Fn.relative(c,i);if(!d.startsWith("..")&&!Fn.isAbsolute(d))return{restricted:!1,resolved:s,roots:a}}return{restricted:!0,resolved:s,roots:a}}function Me(t,e,n="read",r){let{restricted:o,resolved:s,roots:i}=eS(t,e,n,r);if(n==="read"){let a=Qe(s);if(a.denied)throw new Error(`Path \`${t}\` is a protected credential/secret path (read-denylist entry: \`${a.matched}\`) and cannot be read.`)}if(o){let a=i.map(c=>`\`${c}\``).join(", "),l=n==="read"?"read roots":"write roots";throw new Error(`Path \`${t}\` is outside the allowed ${l} [${a}].`)}return s}function Ho(t,e,n="read",r){return eS(t,e,n,r)}function tS(t){let e=new Set,n=[];for(let r of t.split(/\s+/)){if(r.length===0)continue;let o=r.replace(/^\d*[<>|&]+/,"").replace(/^['"]/,"").replace(/['";,)]+$/,"");if(o.length===0)continue;let s=o.startsWith("/"),i=o==="~"||o.startsWith("~/");!s&&!i||e.has(o)||(e.add(o),n.push(o))}return n}var Zw,et=h(()=>{"use strict";nn();Zw=new Map});import{spawn as sL}from"child_process";import iL from"os";function aL(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.command!="string")throw new Error('Input must have a "command" field of type string');let n=12e4;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number")throw new Error("timeout_ms must be a number");if(e.timeout_ms<0||e.timeout_ms>6e5)throw new Error("timeout_ms must be between 0 and 600000");n=e.timeout_ms}return{command:e.command,timeout_ms:n}}function Ha(t,e){let n=!1,r=!1;function o(){n||t==="bypassPermissions"&&(n=!0,console.warn("[security] bash handler: shell=true with bypassPermissions \u2014 all shell metacharacters are interpreted without confirmation. Migrate to execFile to eliminate this risk (tracked: C4)."))}function s(i,a){if(r)return;let l=a.resolveBase??a.cwd??e,c=iL.homedir(),d=[];for(let u of tS(i)){let p=u==="~"?c:u.startsWith("~/")?c+u.slice(1):u,f=Ho(p,a,"write",l);f.restricted&&d.push(f.resolved)}d.length!==0&&(r=!0,console.warn(`[security] bash: command references path(s) outside writeRoots: ${d.join(", ")} \u2014 bash containment is best-effort (tracked C4); use file tools for contained writes.`),se({event:"tool.bash_path_escape",tool:"bash",restricted_count:d.length,mode:"write"}))}return async(i,a,l)=>{let{command:c,timeout_ms:d}=aL(i);if(a.aborted)return{content:"Command aborted",isError:!0};if(o(),l!==void 0)try{s(c,l)}catch{}return new Promise(u=>{let p=!1;function f(_){p||(p=!0,clearTimeout(g),a.removeEventListener("abort",T),u(_))}let m=sL(c,{shell:!0,detached:!0,stdio:["ignore","pipe","pipe"],...(l?.resolveBase??l?.cwd??e)!==void 0?{cwd:l?.resolveBase??l?.cwd??e}:{},...l?.env!==void 0?{env:{...process.env,...l.env}}:{}});m.unref();let g=setTimeout(()=>{m.pid!==void 0&&process.kill(-m.pid,"SIGKILL"),f({content:`Command timed out after ${d}ms`,isError:!0})},d),y="",w="",v=0,A=!1;function S(_){if(A||p||v<8e6)return;A=!0,console.warn(`[bash] overflow kill: stream=${_} totalBytes=${v} command="${c}"`),se({event:"tool.overflow_kill",tool:"bash",total_bytes:v,stream:_}),m.kill("SIGKILL");let I=bt((y+w).trimEnd()),R=sp(I)??void 0,E=Ft(I,1e5)+Ma;f({content:E,truncated:!0,...R!==void 0?{testResult:R}:{}})}m.stdout.on("data",_=>{let I=8e6-v,R=_.length<=I?_:_.subarray(0,Math.max(0,I));v+=R.length,y+=R.toString("utf8"),S("stdout")}),m.stderr.on("data",_=>{let I=8e6-v,R=_.length<=I?_:_.subarray(0,Math.max(0,I));v+=R.length,w+=R.toString("utf8"),S("stderr")});let T=()=>{m.pid!==void 0&&process.kill(-m.pid,"SIGKILL"),f({content:"Command aborted",isError:!0})};a.addEventListener("abort",T),a.aborted&&T(),m.on("close",_=>{if(a.aborted){f({content:"Command aborted",isError:!0});return}if(_!==null&&_!==0){let C=Zt(w.trimEnd()||y.trimEnd());f({content:`Command exited with code ${_}${C.content?`
|
|
870
|
+
Retrying it verbatim will fail the same way. Fix the underlying cause, change the arguments, use a different tool, or stop and report the blocker.`,isError:!0,failureClass:"repeat-failure"}}}note(e,n){let r=Lo(e);if(n.isError!==!0){this.streaks.delete(r);return}let o=this.streaks.get(r);this.streaks.set(r,{count:(o?.count??0)+1,lastError:SF(n)})}streakFor(e){return this.streaks.get(Lo(e))?.count??0}}});var kF,op,EF,vt,Na=h(()=>{"use strict";ce();pe();Ca();Ea();xa();Yu();Pn();Oa();Q();Zu();Ow();Da();np();Hw();Zu();kF=8,op=new Set,EF=8,vt=class{handlers;schemas;hookRegistry;permissions;canUseTool;subagentExecutor;skillExecutor;composeExecutor;classifier;maxConcurrentSafeCalls;resolveBase;_readRoots;_writeRoots;_allowAll;_env;sessionId;parentSessionId;subagentId;sessionGrantManager;traceWriter;readOnlyBash;maxOutputBytes;repeatBreaker=null;repeatFailureGuard=new La;denialBreaker=null;suspectedLoopWindow=null;grantManager;constructor(e){this.handlers=e.handlers,this.schemas=e.schemas,this.hookRegistry=e.hookRegistry,this.permissions=e.permissions,this.canUseTool=e.canUseTool,this.subagentExecutor=e.subagentExecutor,this.skillExecutor=e.skillExecutor,this.composeExecutor=e.composeExecutor,this.classifier=e.concurrencyClassifier??Qu,this.maxConcurrentSafeCalls=typeof e.maxConcurrentSafeCalls=="number"&&Number.isFinite(e.maxConcurrentSafeCalls)&&e.maxConcurrentSafeCalls>=1?Math.floor(e.maxConcurrentSafeCalls):EF,this.resolveBase=e.cwd,this._env=e.env,this.sessionId=e.sessionId,this.parentSessionId=e.parentSessionId,this.subagentId=e.subagentId,this.sessionGrantManager=e.sessionGrantManager,this.traceWriter=e.traceWriter,this.readOnlyBash=e.readOnlyBash===!0,this.maxOutputBytes=typeof e.maxOutputBytes=="number"&&Number.isFinite(e.maxOutputBytes)&&e.maxOutputBytes>0?e.maxOutputBytes:void 0,this._allowAll=e.allowAll===!0;let n=e.cwd?[e.cwd]:[];this._readRoots=e.readRoots??n.slice(),this._writeRoots=e.writeRoots??n.slice(),this.grantManager=new en({getReadRoots:()=>this._readRoots,getWriteRoots:()=>this._writeRoots,getProtectedRoot:()=>this.resolveBase,getAllowAll:()=>this._allowAll,getDefaultSessionId:()=>this.sessionId})}get handlerContext(){return{cwd:this.resolveBase,resolveBase:this.resolveBase,readRoots:this._readRoots.slice(),writeRoots:this._writeRoots.slice(),...this._allowAll?{allowAll:!0}:{},...this._env!==void 0?{env:this._env}:{},...this.sessionId!==void 0?{sessionId:this.sessionId}:{}}}callHandlerContext(e){return{...this.handlerContext,toolUseId:e.id,...this.traceWriter!==void 0?{traceWriter:this.traceWriter}:{}}}addReadRoot(e,n="slash"){this.grantManager.addReadRoot(e,n)}addWriteRoot(e,n="slash"){this.grantManager.addWriteRoot(e,n)}revokeRoot(e,n="slash"){this.grantManager.revokeRoot(e,n)}getGrants(){return this.grantManager.getGrants()}setAllowAll(e){this._allowAll=e}setResolveBase(e){let n=this.resolveBase;if(n!==e){if(this.resolveBase=e,n!==void 0){let r=this._readRoots.indexOf(n);r!==-1?this._readRoots[r]=e:this._readRoots.includes(e)||this._readRoots.push(e);let o=this._writeRoots.indexOf(n);o!==-1?this._writeRoots[o]=e:this._writeRoots.includes(e)||this._writeRoots.push(e)}else this._readRoots.includes(e)||this._readRoots.push(e),this._writeRoots.includes(e)||this._writeRoots.push(e);this.subagentExecutor?.setCwd(e),this.skillExecutor?.setCwd(e),this.composeExecutor?.setCwd(e)}}get toolDefs(){let e=this.permissions?.allowedTools;if(!e)return this.schemas;let n=new Set(e);return this.schemas.filter(r=>n.has(r.name))}async checkReadOnlyBash(e){if(!this.readOnlyBash||e.name!=="bash")return null;let n=e.input,r=typeof n=="object"&&n!==null?n.command:void 0;if(typeof r!="string")return null;let o=Pa(r);if(!o.mutating)return null;let s=`Bash command blocked: read-only skill may not run mutating commands (${o.reason??"mutation detected"}). Allowed: read-only recon (git status/log/diff/show/ls-remote, ls, cat, find, grep, gh pr view/diff). For a remote ref you have not fetched, \`gh pr diff <n>\`, \`gh pr view <n>\` and \`git ls-remote\` need no local ref \u2014 \`git fetch\` is blocked. Do NOT retry variants of a blocked command: if the task genuinely requires a mutation, stop and report that requirement to your caller instead.`;return await this.emitPreToolUseBlock(e.name,s),{content:s,isError:!0,failureClass:"permission-denied"}}async emitPreToolUseBlock(e,n){await Ye(this.traceWriter,{hookEvent:"PreToolUse",decision:"block",blockedTool:e,reason:n,...this.subagentId!==void 0?{subagentId:this.subagentId}:{}})}checkRepeatCircuitBreaker(e){if(op.has(e.name))return null;let n=Mw(e);return this.repeatBreaker!==null&&this.repeatBreaker.fingerprint===n?this.repeatBreaker.count+=1:this.repeatBreaker={fingerprint:n,count:1},this.repeatBreaker.count<kF?null:{content:`Loop circuit breaker: "${e.name}" has been called ${this.repeatBreaker.count} times in a row with byte-identical input. The result will not change. Stop repeating this call \u2014 reuse the previous result, change the input, try a different tool, or end the turn.`,isError:!0,circuitBreaker:!0}}checkRepeatFailureGuard(e){if(op.has(e.name))return null;let n=this.repeatFailureGuard.check(e);return n===null?null:(D(`[repeat-failure-guard #723] refused ${n.tool} after ${n.count} identical failures`),n.result)}observeSuspectedLoop(e){if(this.parentSessionId===void 0)return;this.suspectedLoopWindow===null&&(this.suspectedLoopWindow=$w());let n=Fa(e),r=Uw(this.suspectedLoopWindow,n);r.fired&&G(this.traceWriter,{phase:"suspected_loop",metadata:{tool:e.name,count:r.count,windowSize:tp}})}recordForkReadDenial(e,n,r){if(this.parentSessionId===void 0||!Dw.has(e.name)||!Fw(n))return r;let o=this.denialBreaker??{count:0,deniedPaths:[]};o.count+=1;let s=Lw(e);return o.deniedPaths.includes(s)||o.deniedPaths.push(s),this.denialBreaker=o,o.count<5?r:{content:Nw(o.deniedPaths,o.count),isError:!0,failureClass:Sr}}resetDenialBreaker(){this.denialBreaker=null}async runCanUseTool(e){if(!this.canUseTool)return null;let n;try{n=await this.canUseTool(e.name,e.input??{},{signal:e.signal,toolUseID:e.id})}catch(r){let o=`Tool "${e.name}" denied by canUseTool (threw): ${r instanceof Error?r.message:String(r)}`;return await this.emitPreToolUseBlock(e.name,o),{content:o,isError:!0,failureClass:"permission-denied"}}if(n.behavior==="deny"){let r=n.message||`Tool "${e.name}" denied by permission policy`;return await this.emitPreToolUseBlock(e.name,r),{content:r,isError:!0,failureClass:"permission-denied"}}return n.updatedInput!==void 0&&(e.input=n.updatedInput),null}async execute(e){if(e.signal.aborted)return{content:"Tool call aborted",isError:!0,failureClass:"abort"};if(this.hookRegistry){let l={event:"PreToolUse",toolName:e.name,input:e.input,...this.sessionId!==void 0?{sessionId:this.sessionId}:{},...this.resolveBase!==void 0?{cwd:this.resolveBase}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{}};try{await Wu(this.hookRegistry,l,{signal:e.signal,...this.traceWriter?{traceWriter:this.traceWriter}:{}})}catch(c){if(c instanceof Z)return this.recordForkReadDenial(e,c.reason,{content:`Tool "${e.name}" blocked by PreToolUse hook: ${c.message}`,isError:!0,failureClass:"hook-block"});throw c}}let n=Ju(e.name,this.permissions);if(!n.allowed){let l=n.reason??`Tool "${e.name}" is not permitted`;return await this.emitPreToolUseBlock(e.name,l),{content:l,isError:!0,failureClass:"permission-denied"}}let r=await this.runCanUseTool(e);if(r)return r;let o=await this.checkReadOnlyBash(e);if(o)return o;let s=this.checkRepeatCircuitBreaker(e);if(s)return s;let i=this.checkRepeatFailureGuard(e);if(i)return i;this.observeSuspectedLoop(e);let a=await this.executeCore(e);return this.repeatFailureGuard.note(e,a),a.isError!==!0&&this.resetDenialBreaker(),a}async executeBatch(e){if(e.length===0)return[];if(e.length===1)return[await this.execute(e[0])];let n=new Array(e.length),r=new Set;for(let i=0;i<e.length;i++){let a=e[i];if(a.signal.aborted){n[i]={content:"Tool call aborted",isError:!0,failureClass:"abort"},r.add(i);continue}if(this.hookRegistry){let f={event:"PreToolUse",toolName:a.name,input:a.input,...this.sessionId!==void 0?{sessionId:this.sessionId}:{},...this.resolveBase!==void 0?{cwd:this.resolveBase}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{}};try{await Wu(this.hookRegistry,f,{signal:a.signal,...this.traceWriter?{traceWriter:this.traceWriter}:{}})}catch(m){if(m instanceof Z){n[i]=this.recordForkReadDenial(a,m.reason,{content:`Tool "${a.name}" blocked by PreToolUse hook: ${m.message}`,isError:!0,failureClass:"hook-block"}),r.add(i);continue}throw m}}let l=Ju(a.name,this.permissions);if(!l.allowed){let f=l.reason??`Tool "${a.name}" is not permitted`;await this.emitPreToolUseBlock(a.name,f),n[i]={content:f,isError:!0,failureClass:"permission-denied"},r.add(i);continue}let c=await this.runCanUseTool(a);if(c){n[i]=c,r.add(i);continue}let d=await this.checkReadOnlyBash(a);if(d){n[i]=d,r.add(i);continue}let u=this.checkRepeatCircuitBreaker(a);if(u){n[i]=u,r.add(i);continue}let p=this.checkRepeatFailureGuard(a);if(p){n[i]=p,r.add(i);continue}this.observeSuspectedLoop(a)}let o=e.map((i,a)=>({call:i,originalIndex:a})).filter((i,a)=>!r.has(a));if(o.length===0)return n;let s=Pw(o.map(i=>i.call),this.classifier);for(let i of s){if(i.isConcurrencySafe){let l=[...i.indices];for(;l.length>0;){let c=new Map,d=[],u=[];for(let f of l){let{call:m,originalIndex:g}=o[f],y=this.checkRepeatFailureGuard(m);if(y){n[g]=y;continue}if(op.has(m.name)){d.push(f);continue}let w=Lo(m),v=rp-this.repeatFailureGuard.streakFor(m),A=c.get(w)??0;A<v?(c.set(w,A+1),d.push(f)):u.push(f)}l=u;let p=await wr(d,this.maxConcurrentSafeCalls,async f=>{let{call:m,originalIndex:g}=o[f];return m.signal.aborted?{result:{content:"Tool call aborted",isError:!0,failureClass:"abort"},originalIndex:g}:{result:await this.executeCore(m),originalIndex:g}});for(let f of p)if(f.status==="fulfilled")n[f.value.originalIndex]=f.value.result;else{let m=f.reason instanceof Error?f.reason.message:String(f.reason),g=d[p.indexOf(f)];n[o[g].originalIndex]={content:`Tool execution error: ${m}`,isError:!0}}for(let f of d){let{call:m,originalIndex:g}=o[f],y=n[g];y!==void 0&&y.failureClass!=="abort"&&this.repeatFailureGuard.note(m,y)}}}else for(let l of i.indices){let{call:c,originalIndex:d}=o[l];if(c.signal.aborted){n[d]={content:"Tool call aborted",isError:!0,failureClass:"abort"};continue}let u=this.checkRepeatFailureGuard(c);if(u){n[d]=u;continue}let p=await this.executeCore(c);n[d]=p,this.repeatFailureGuard.note(c,p)}let a=i.indices.length;i.indices.forEach((l,c)=>{let d=n[o[l].originalIndex];d&&(d.batchIndex=c+1,d.batchSize=a)})}return n.some(i=>i!==void 0&&i.isError!==!0)&&this.resetDenialBreaker(),n}async executeCore(e){let n=await this.executeCoreInner(e);return this.applyOutputCap(n)}applyOutputCap(e){let n=this.maxOutputBytes;if(n===void 0)return e;let r=Buffer.byteLength(e.content,"utf8");return r<=n||(e.content=Ft(e.content,n),e.truncated=!0,D(`[output-cap #661] fork tool result capped: original=${r}B capped=${Buffer.byteLength(e.content,"utf8")}B (cap=${n}B)`)),e}async executeCoreInner(e){if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let i,a=!1,l="";try{i=await this.subagentExecutor.execute(e)}catch(c){a=!0,l=c instanceof Error?c.message:String(c),i={content:`Agent tool error: ${l}`,isError:!0}}return a?this.firePostToolUseFailure(e.name,l,e.signal,e.input):this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let i,a=!1,l="";try{i=await this.skillExecutor.execute(e)}catch(c){a=!0,l=c instanceof Error?c.message:String(c),i={content:`Skill tool error: ${l}`,isError:!0}}return a?this.firePostToolUseFailure(e.name,l,e.signal,e.input):this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}if(e.name==="compose"){let i=await this.executeCompose(e);return this.firePostToolUse(e.name,i.content,e.signal,e.input,i),i}let n=this.handlers.get(e.name);if(!n)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let r,o=!1,s="";try{r=await n(e.input,e.signal,this.callHandlerContext(e))}catch(i){o=!0,s=i instanceof Error?i.message:String(i),r={content:`Tool execution error: ${s}`,isError:!0}}return o?this.firePostToolUseFailure(e.name,s,e.signal,e.input):this.firePostToolUse(e.name,r.content,e.signal,e.input,r),r}async executeCompose(e){if(!this.composeExecutor)return{content:"Compose tool is not available in this session configuration",isError:!0};try{return await this.composeExecutor.execute(e)}catch(n){return{content:`Compose tool error: ${n instanceof Error?n.message:String(n)}`,isError:!0}}}firePostToolUse(e,n,r,o,s){if(!this.hookRegistry)return;let i={event:"PostToolUse",toolName:e,output:n,...o!==void 0?{input:o}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{},...this.sessionGrantManager!==void 0?{grantManager:this.sessionGrantManager}:{},...s?.incomplete===!0?{incomplete:!0}:{},...s?.incompleteReason?{incompleteReason:s.incompleteReason}:{}};ww(this.hookRegistry,i,{signal:r,...this.traceWriter?{traceWriter:this.traceWriter}:{}}).catch(()=>{})}firePostToolUseFailure(e,n,r,o){if(!this.hookRegistry)return;let s={event:"PostToolUseFailure",toolName:e,error:n,...o!==void 0?{input:o}:{},...this.parentSessionId!==void 0?{parentSessionId:this.parentSessionId}:{}};Sw(this.hookRegistry,s,{signal:r,...this.traceWriter?{traceWriter:this.traceWriter}:{}}).catch(i=>{D(`firePostToolUseFailure outer catch (tool=${e}): ${String(i)}`)})}}});function DF(t){let e=t.match(AF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10),o=e[3]!==void 0?parseInt(e[3],10):void 0;return{runner:"vitest",passed:n,failed:r,...o!==void 0?{skipped:o}:{}}}function FF(t){let e=t.match(_F);if(!e)return null;let n=parseInt(e[1]??"0",10);return{runner:"jest",passed:parseInt(e[2]??"0",10),failed:n}}function LF(t){let e=t.match(TF);if(!e)return null;if(e[2]!==void 0){let n=parseInt(e[2],10),r=parseInt(e[1]??"0",10);return{runner:"pytest",passed:n,failed:r}}return e[4]!==void 0?{runner:"pytest",passed:parseInt(e[4],10),failed:0}:null}function NF(t){let e=t.match(RF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=t.match(xF),o=r?parseInt(r[1]??"0",10):0;return{runner:"mocha",passed:n,failed:o}}function $F(t){let e=[...t.matchAll(CF)];if(e.length===0)return null;let n=0,r=0;for(let o of e)o[1]==="ok"?n++:o[1]==="FAIL"&&r++;return{runner:"go-test",passed:n,failed:r}}function UF(t){let e=t.match(IF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10),o=e[3]!==void 0?parseInt(e[3],10):void 0;return{runner:"cargo",passed:n,failed:r,...o!==void 0?{skipped:o}:{}}}function BF(t){let e=t.match(PF);if(!e)return null;let n=parseInt(e[1]??"0",10),r=parseInt(e[2]??"0",10);return{runner:"rspec",passed:n-r,failed:r}}function HF(t){let e=t.match(MF);if(e)return{runner:"phpunit",passed:parseInt(e[1]??"0",10),failed:0};let n=t.match(OF);if(n){let r=parseInt(n[1]??"0",10),o=parseInt(n[2]??"0",10);return{runner:"phpunit",passed:r-o,failed:o}}return null}function sp(t){return DF(t)??FF(t)??LF(t)??NF(t)??$F(t)??UF(t)??BF(t)??HF(t)??null}var AF,_F,TF,RF,xF,CF,IF,PF,MF,OF,jw=h(()=>{"use strict";AF=/Tests\s+(\d+)\s+passed(?:\s*\|\s*(\d+)\s+failed)?(?:\s*\|\s*(\d+)\s+skipped)?/,_F=/Tests:\s+(?:(\d+)\s+failed,\s*)?(\d+)\s+passed,\s*\d+\s+total/,TF=/={3,}\s*(?:(\d+)\s+failed,\s*)?(\d+)\s+passed(?:,\s*(\d+)\s+warning)?.*in\s+[\d.]+s\s*={3,}|={3,}\s*(\d+)\s+passed.*in\s+[\d.]+s\s*={3,}/,RF=/(\d+)\s+passing/,xF=/(\d+)\s+failing/,CF=/^(ok|FAIL)\s+\S+\s+[\d.]+s/gm,IF=/test result: (?:ok|FAILED)\. (\d+) passed; (\d+) failed(?:; (\d+) ignored)?/,PF=/(\d+) examples?, (\d+) failures?/,MF=/OK \((\d+) tests?/,OF=/Tests:\s*(\d+)[^]*?Failures:\s*(\d+)/});import{statSync as jF}from"node:fs";function No(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.code==="ENOENT"&&typeof e.syscall=="string"&&e.syscall.startsWith("spawn")}function WF(t){if(t===void 0)return!1;try{return jF(t),!1}catch{return!0}}function vr(t,e){let n=t instanceof Error?t.message:typeof t?.message=="string"?String(t.message):String(t);return No(t)&&WF(e)?`working directory does not exist: ${e} (deleted worktree?) \u2014 underlying: ${n}`:n}var ip=h(()=>{"use strict"});function kt(t){if(Ww)return;Ww=!0;let e=t instanceof Error?t.message:String(t);console.warn(`[afk-home] Malformed AFK home/state env var ignored while deriving the credential floor: ${e}. The relocated tree is NOT protected \u2014 the default ~/.afk entries still apply. Fix the env var to restore coverage.`)}var Ww,$o=h(()=>{"use strict";Ww=!1});import{statSync as lp}from"node:fs";import{homedir as KF}from"node:os";import{basename as GF,dirname as Gw,join as qF}from"node:path";function qw(t){return typeof t=="object"&&t!==null&&"code"in t?String(t.code):void 0}function zF(t){let e=GF(t),n=e===e.toLowerCase()?e.toUpperCase():e.toLowerCase();if(n===e)return;let r;try{r=lp(t)}catch{return}let o=ap.get(r.dev);if(o!==void 0)return o;try{let s=lp(qF(Gw(t),n)),i=r.dev===s.dev&&r.ino===s.ino;return ap.set(r.dev,i),i}catch(s){let i=qw(s);return i==="ENOENT"||i==="ENOTDIR"?(ap.set(r.dev,!1),!1):void 0}}function zw(t=KF()){if(Kw!==void 0)return Kw;let e=t;for(;;)try{return lp(e),zF(e)??!0}catch(n){let r=qw(n);if(r!=="ENOENT"&&r!=="ENOTDIR")return!0;let o=Gw(e);if(o===e)return!0;e=o}}function kr(t,e,n=e){if(t===e||t.startsWith(e+"/"))return!0;if(!zw(n))return!1;let r=t.toLowerCase(),o=e.toLowerCase();return r===o||r.startsWith(o+"/")}function cp(t,e){return t.includes(e)?!0:zw(e)?t.toLowerCase().includes(e.toLowerCase()):!1}var Kw,ap,$a=h(()=>{"use strict";ap=new Map});import{realpathSync as Jw}from"fs";import{dirname as JF,resolve as Dn,join as dp}from"path";import{homedir as tn}from"os";function YF(){let t=[];try{let e=re();t.push(ge(Dn(dp(e,"config")))),t.push(ge(Dn(dp(e,"state"))))}catch(e){kt(e)}try{t.push(ge(Dn(ye())))}catch(e){kt(e)}return t}function up(){let t=k.AFK_WRITE_DENYLIST,e=t?t.split(":").map(r=>ge(Dn(r))).filter(Boolean):[];return[...[...new Set([...VF.map(r=>ge(Dn(r))),...YF()])],...e]}function ge(t){let e=Dn(t);try{return Jw(e)}catch{}let n=[],r=e;for(let o=0;o<64;o++){let s=JF(r);if(s===r)break;n.unshift(r.slice(s.length+1)),r=s;try{let i=Jw(r);return dp(i,...n)}catch{}}return e}function Ua(t,e="write_file"){let n=ge(Dn(t));for(let r of up())if(kr(n,r))throw new Error(`${e}: refusing to write to protected path: ${n} (matches denylist entry: ${r})`)}var VF,Er=h(()=>{"use strict";B();W();$o();$a();VF=[`${tn()}/.ssh`,`${tn()}/.aws`,`${tn()}/.gnupg`,`${tn()}/.config/gcloud`,"/etc","/System","/private/etc","/usr/local/etc",`${tn()}/.afk/config`,`${tn()}/.afk/state`,`${tn()}/.npmrc`,`${tn()}/.docker/config.json`]});import{basename as XF,dirname as QF,join as Ba,relative as ZF,resolve as Ar,sep as Uo}from"path";import{homedir as me}from"os";function Yw(t){let e=Ar(t);return Ba(ge(QF(e)),XF(e))}function fp(t){return t?t.split(":").map(e=>e.trim()).filter(Boolean).map(e=>e==="~"||e.startsWith("~/")?Ba(me(),e.slice(1)):e).map(e=>Ar(e)):[]}function tL(){try{return[ge(Ar(Ba(re(),"config")))]}catch(t){return kt(t),[]}}function nL(){try{let t=re();return _r.filter(e=>e.startsWith(Vw)).map(e=>Yw(Ba(t,e.slice(Vw.length))))}catch(t){return kt(t),[]}}function Xw(){let t=`${k.AFK_READ_DENYLIST??""}\0${k.AFK_HOME??""}`;if(Bo&&Bo.key===t)return Bo;let e=fp(k.AFK_READ_DENYLIST).map(r=>ge(r)).filter(Boolean),n=[...new Set([...pp.map(r=>ge(Ar(r))),...tL()])];return Bo={key:t,builtins:n,extras:e,allow:[...new Set([...eL.map(Yw),...nL()])]},Bo}function mp(){let{builtins:t,extras:e}=Xw();return[...t,...e]}function Qw(t){let e=ge(Ar(t));return mp().filter(n=>n!==e&&kr(n,e,n)).map(n=>(n.startsWith(e+Uo)?ZF(e,n):n.split(Uo).slice(e.split(Uo).length).join(Uo)).split(Uo).join("/"))}function Qe(t){let e=ge(Ar(t)),{builtins:n,extras:r,allow:o}=Xw();for(let s of r)if(kr(e,s))return{denied:!0,matched:s};if(o.includes(e))return{denied:!1};for(let s of n)if(kr(e,s))return{denied:!0,matched:s};return{denied:!1}}var pp,_r,eL,Bo,Vw,nn=h(()=>{"use strict";B();Er();W();$o();$a();pp=[`${me()}/.ssh`,`${me()}/.aws`,`${me()}/.gnupg`,`${me()}/.config/gcloud`,`${me()}/.afk/config`,`${me()}/.npmrc`,`${me()}/.docker/config.json`,`${me()}/.git-credentials`,`${me()}/.netrc`,`${me()}/.config/gh/hosts.yml`,`${me()}/.kube/config`,"/etc/shadow","/etc/sudoers","/private/etc/master.passwd",`${me()}/.password-store`,`${me()}/Library/Application Support/Google/Chrome`,`${me()}/Library/Application Support/Chromium`,`${me()}/Library/Application Support/BraveSoftware`,`${me()}/Library/Application Support/Microsoft Edge`,`${me()}/Library/Application Support/Arc`,`${me()}/Library/Application Support/Firefox`],_r=[".afk/config/mcp.json",".ssh/config",".ssh/known_hosts"],eL=_r.map(t=>`${me()}/${t}`);Vw=".afk/"});import Fn from"path";import{realpathSync as rL}from"fs";function Ze(t){try{return rL.native(t)}catch{let e=Fn.dirname(t),n=Fn.basename(t);return e===t?t:Fn.join(Ze(e),n)}}function oL(t){let e=Zw.get(t);if(e!==void 0)return e;let n=Ze(t);return Zw.set(t,n),n}function eS(t,e,n,r){let o=e?.resolveBase??e?.cwd??r,s=Fn.isAbsolute(t)?t:Fn.resolve(o??process.cwd(),t);if(e?.allowAll===!0)return{restricted:!1,resolved:s,roots:[]};if(o===void 0)return{restricted:!1,resolved:s,roots:[]};let i=Ze(s),a=n==="read"?e?.readRoots??[o]:e?.writeRoots??[o];for(let l of a){let c=oL(l),d=Fn.relative(c,i);if(!d.startsWith("..")&&!Fn.isAbsolute(d))return{restricted:!1,resolved:s,roots:a}}return{restricted:!0,resolved:s,roots:a}}function Me(t,e,n="read",r){let{restricted:o,resolved:s,roots:i}=eS(t,e,n,r);if(n==="read"){let a=Qe(s);if(a.denied)throw new Error(`Path \`${t}\` is a protected credential/secret path (read-denylist entry: \`${a.matched}\`) and cannot be read.`)}if(o){let a=i.map(c=>`\`${c}\``).join(", "),l=n==="read"?"read roots":"write roots";throw new Error(`Path \`${t}\` is outside the allowed ${l} [${a}].`)}return s}function Ho(t,e,n="read",r){return eS(t,e,n,r)}function tS(t){let e=new Set,n=[];for(let r of t.split(/\s+/)){if(r.length===0)continue;let o=r.replace(/^\d*[<>|&]+/,"").replace(/^['"]/,"").replace(/['";,)]+$/,"");if(o.length===0)continue;let s=o.startsWith("/"),i=o==="~"||o.startsWith("~/");!s&&!i||e.has(o)||(e.add(o),n.push(o))}return n}var Zw,et=h(()=>{"use strict";nn();Zw=new Map});import{spawn as sL}from"child_process";import iL from"os";function aL(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.command!="string")throw new Error('Input must have a "command" field of type string');let n=12e4;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number")throw new Error("timeout_ms must be a number");if(e.timeout_ms<0||e.timeout_ms>6e5)throw new Error("timeout_ms must be between 0 and 600000");n=e.timeout_ms}return{command:e.command,timeout_ms:n}}function Ha(t,e){let n=!1,r=!1;function o(){n||t==="bypassPermissions"&&(n=!0,console.warn("[security] bash handler: shell=true with bypassPermissions \u2014 all shell metacharacters are interpreted without confirmation. Migrate to execFile to eliminate this risk (tracked: C4)."))}function s(i,a){if(r)return;let l=a.resolveBase??a.cwd??e,c=iL.homedir(),d=[];for(let u of tS(i)){let p=u==="~"?c:u.startsWith("~/")?c+u.slice(1):u,f=Ho(p,a,"write",l);f.restricted&&d.push(f.resolved)}d.length!==0&&(r=!0,console.warn(`[security] bash: command references path(s) outside writeRoots: ${d.join(", ")} \u2014 bash containment is best-effort (tracked C4); use file tools for contained writes.`),se({event:"tool.bash_path_escape",tool:"bash",restricted_count:d.length,mode:"write"}))}return async(i,a,l)=>{let{command:c,timeout_ms:d}=aL(i);if(a.aborted)return{content:"Command aborted",isError:!0};if(o(),l!==void 0)try{s(c,l)}catch{}return new Promise(u=>{let p=!1;function f(_){p||(p=!0,clearTimeout(g),a.removeEventListener("abort",T),u(_))}let m=sL(c,{shell:!0,detached:!0,stdio:["ignore","pipe","pipe"],...(l?.resolveBase??l?.cwd??e)!==void 0?{cwd:l?.resolveBase??l?.cwd??e}:{},...l?.env!==void 0?{env:{...process.env,...l.env}}:{}});m.unref();let g=setTimeout(()=>{m.pid!==void 0&&process.kill(-m.pid,"SIGKILL"),f({content:`Command timed out after ${d}ms`,isError:!0})},d),y="",w="",v=0,A=!1;function S(_){if(A||p||v<8e6)return;A=!0,console.warn(`[bash] overflow kill: stream=${_} totalBytes=${v} command="${c}"`),se({event:"tool.overflow_kill",tool:"bash",total_bytes:v,stream:_}),m.kill("SIGKILL");let I=bt((y+w).trimEnd()),R=sp(I)??void 0,E=Ft(I,1e5)+Ma;f({content:E,truncated:!0,...R!==void 0?{testResult:R}:{}})}m.stdout.on("data",_=>{let I=8e6-v,R=_.length<=I?_:_.subarray(0,Math.max(0,I));v+=R.length,y+=R.toString("utf8"),S("stdout")}),m.stderr.on("data",_=>{let I=8e6-v,R=_.length<=I?_:_.subarray(0,Math.max(0,I));v+=R.length,w+=R.toString("utf8"),S("stderr")});let T=()=>{m.pid!==void 0&&process.kill(-m.pid,"SIGKILL"),f({content:"Command aborted",isError:!0})};a.addEventListener("abort",T),a.aborted&&T(),m.on("close",_=>{if(a.aborted){f({content:"Command aborted",isError:!0});return}if(_!==null&&_!==0){let C=Zt(w.trimEnd()||y.trimEnd());f({content:`Command exited with code ${_}${C.content?`
|
|
871
871
|
`+C.content:""}`,isError:!0,...C.truncated?{truncated:!0}:{}});return}if(A)return;let I=bt((y+w).trimEnd()),R=sp(I)??void 0,E=Zt(I);f({content:E.content,...E.truncated?{truncated:!0}:{},...R!==void 0?{testResult:R}:{}})}),m.on("error",_=>{let I=l?.resolveBase??l?.cwd??e,R;if(I===void 0&&No(_))try{let E=process.cwd();R=vr(_,E)}catch{R=`working directory does not exist (process cwd deleted \u2014 deleted worktree?) \u2014 underlying: ${_.message}`}else R=vr(_,I);f({content:`Failed to execute: ${R}`,isError:!0})})})}}var nS,rS=h(()=>{"use strict";at();jw();_n();ip();Pn();et();nS=Ha("default")});import{promises as lL}from"fs";function gp(t){return(e,n,r)=>cL(e,n,r,t)}var cL,oS,sS=h(()=>{"use strict";et();cL=async(t,e,n,r)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let o=t,s=o.file_path,i=o.offset??1,a=o.limit??2e3;if(typeof s!="string")return{content:"Invalid input: file_path must be a string",isError:!0};if(typeof i!="number"||i<1)return{content:"Invalid input: offset must be a positive number",isError:!0};if(typeof a!="number"||a<1)return{content:"Invalid input: limit must be a positive number",isError:!0};let l;try{l=Me(s,n,"read",r)}catch(c){return{content:c instanceof Error?c.message:String(c),isError:!0}}try{let c=await lL.readFile(l),d=Math.min(8192,c.length);for(let A=0;A<d;A++)if(c[A]===0)return{content:`File appears to be binary: ${l}`,isError:!0};let u=c.toString("utf-8");if(u.length===0)return{content:""};let p=u.split(`
|
|
872
872
|
`),f=Math.max(0,i-1),m=Math.min(p.length,f+a),g=p.slice(f,m),y=p.length;if(g.length===0)return{content:`... (offset ${i} is past end of file \u2014 file has ${y} lines)`};let w=String(y).length,v=g.map((A,S)=>{let T=f+S+1;return`${String(T).padStart(w," ")} ${A}`}).join(`
|
|
873
873
|
`);if(g.length<y){let A=f+1,S=f+g.length,T=S<y?` \u2014 pass offset=${S+1} to continue`:"";return{content:`${v}
|
|
@@ -878,7 +878,7 @@ Retrying it verbatim will fail the same way. Fix the underlying cause, change th
|
|
|
878
878
|
|
|
879
879
|
`).trim()}function $L(t){return(t?.textContent??"").replace(/\s+/g," ").trim().length}async function AS(t,e){let{JSDOM:n,Readability:r,turndown:o}=await NL(),i=new n(t,{url:e}).window.document,a=(i.title??"").trim(),l=(()=>{try{let p=i.cloneNode(!0);return new r(p).parse()}catch{return null}})();if(l&&typeof l.content=="string"&&l.content.trim().length>0){let p=ES(o.turndown(l.content)),f=(l.title??"").trim()||a,m=typeof l.length=="number"&&l.length>0?l.length:(l.textContent??"").replace(/\s+/g," ").trim().length;return{title:f,markdown:p,textLength:m,usedFallback:!1}}let c=i.body,d=c?.innerHTML??"",u=ES(o.turndown(d));return{title:a,markdown:u,textLength:$L(c),usedFallback:!0}}var kp,_S=h(()=>{"use strict";kp=null});function BL(t,e){return new Promise((n,r)=>{if(e?.aborted){r(e.reason??new Error("aborted"));return}let o=()=>{clearTimeout(s),r(e?.reason??new Error("aborted"))},s=setTimeout(()=>{e?.removeEventListener("abort",o),n()},t);e?.addEventListener("abort",o,{once:!0})})}function TS(t,e,n){let r=Math.min(e*2**t,n);return Math.round(Math.random()*r)}function HL(t,e){let n=t.headers.get("retry-after");if(n===null)return null;let r=Number(n.trim());return!Number.isFinite(r)||r<0?null:Math.min(r*1e3,e)}async function RS(t,e,n={},r={}){let o=r.retries??3,s=r.baseDelayMs??500,i=r.maxDelayMs??1e4,a=r.sleep??BL,l=n.signal??void 0,c;for(let d=0;d<=o;d++){if(l?.aborted)throw l.reason??new Error("aborted");try{let u=await t(e,n);if(!UL.has(u.status)||d===o)return u;let p=HL(u,i)??TS(d,s,i);D("[web/retryFetch] retrying",{url:e,attempt:d,status:u.status,waitMs:p}),await u.body?.cancel().catch(()=>{}),await a(p,l)}catch(u){if(l?.aborted||(c=u,d===o))throw u;let p=TS(d,s,i);D("[web/retryFetch] retrying after error",{url:e,attempt:d,waitMs:p}),await a(p,l)}}throw c??new Error("retryFetch: exhausted without a result")}var UL,xS=h(()=>{"use strict";ce();UL=new Set([429,502,503,504])});import{BlockList as jL,isIP as Ap}from"node:net";import{lookup as WL}from"node:dns/promises";import{Agent as KL}from"undici";function IS(){let t=k.AFK_WEB_ALLOW_PRIVATE_HOSTS?.trim().toLowerCase();return t==="1"||t==="true"}function JL(t){return t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t}function Ep(t){let e=Ap(t);return e===0?!1:zL.check(t,e===4?"ipv4":"ipv6")}async function PS(t){return WL(t,{all:!0,verbatim:!0})}async function _p(t,e={}){if(e.allowPrivateHosts??IS())return{allowed:!0};let n;try{n=new URL(t)}catch{return{allowed:!1,reason:`"${t}" is not a valid absolute URL`}}if(n.protocol!=="http:"&&n.protocol!=="https:")return{allowed:!1,reason:`protocol "${n.protocol}" not supported (http/https only)`};let r=JL(n.hostname),o=(a,l)=>`refusing to fetch ${l} \u2014 internal/private address ${a} (loopback, link-local, cloud metadata, or RFC1918 space). Set AFK_WEB_ALLOW_PRIVATE_HOSTS=1 to allow private-host access.`;if(Ap(r)!==0)return Ep(r)?{allowed:!1,reason:o(r,r)}:{allowed:!0};let s=e.lookupFn??PS,i;try{i=await s(r)}catch{return{allowed:!0}}for(let a of i)if(Ep(a.address))return{allowed:!1,reason:o(a.address,`${r} (resolved)`)};return{allowed:!0}}async function Wo(t,e={}){let n=await _p(t,e);if(!n.allowed)throw new dt(n.reason)}async function Wa(t,e,n={},r={}){let o={...r.lookupFn!==void 0?{lookupFn:r.lookupFn}:{},...r.allowPrivateHosts!==void 0?{allowPrivateHosts:r.allowPrivateHosts}:{}},s=e;for(let i=0;i<=CS;i++){await Wo(s,o);let a={...n,redirect:"manual",...t===globalThis.fetch&&!(r.allowPrivateHosts??IS())?{dispatcher:VL}:{}},l=await RS(t,s,a,r.retry??{});if(!YL.has(l.status))return l;let c=l.headers.get("location");if(c===null||c.trim()==="")return l;let d;try{d=new URL(c,l.url||s).toString()}catch{return l}await l.body?.cancel().catch(()=>{}),s=d}throw new dt(`too many redirects (>${CS}) starting from ${e}`)}var GL,qL,zL,dt,VL,CS,YL,Tp=h(()=>{"use strict";B();xS();GL=[["0.0.0.0",8],["10.0.0.0",8],["100.64.0.0",10],["127.0.0.0",8],["169.254.0.0",16],["172.16.0.0",12],["192.168.0.0",16]],qL=[["::",96],["64:ff9b::",96],["fc00::",7],["fe80::",10]],zL=(()=>{let t=new jL;for(let[e,n]of GL)t.addSubnet(e,n,"ipv4");for(let[e,n]of qL)t.addSubnet(e,n,"ipv6");return t})(),dt=class extends Error{constructor(e){super(e),this.name="EgressBlockedError"}};VL=new KL({connect:{lookup(t,e,n){PS(t).then(r=>{let o=r.find(i=>Ep(i.address));if(o!==void 0){n(new dt(`refusing to connect to ${t} (resolved) \u2014 internal/private address ${o.address} (loopback, link-local, cloud metadata, or RFC1918 space). Set AFK_WEB_ALLOW_PRIVATE_HOSTS=1 to allow private-host access.`),"",0);return}let s=r[0];if(s===void 0){n(new Error(`DNS lookup returned no addresses for ${t}`),"",0);return}n(null,s.address,Ap(s.address))},r=>n(r,"",0))}}});CS=20,YL=new Set([301,302,303,307,308])});import{readFileSync as XL}from"node:fs";import{join as QL}from"path";function ZL(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function MS(t,e){return ZL(e).test(t)}function nN(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(eN.has(e))return!0;if(tN.has(e))return!1}return!1}function OS(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function rN(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 DS(t){let e=t===void 0||t.trim()===""?"default":t.trim();return _d(e),e}function oN(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function sN(t){try{return XL(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function iN(t,e){let n={...t};if(typeof e.headless=="boolean"&&(n.headless=e.headless),Array.isArray(e.allowedDomains)&&(n.allowedDomains=e.allowedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),Array.isArray(e.blockedDomains)&&(n.blockedDomains=e.blockedDomains.filter(r=>typeof r=="string").map(r=>r.trim().toLowerCase()).filter(r=>r.length>0)),typeof e.domSnapshots=="boolean"&&(n.domSnapshots=e.domSnapshots),e.backend==="playwright")n.backend="playwright";else if(e.backend!==void 0)throw new Error(`AFK_BROWSER_BACKEND: only "playwright" is supported in Phase 1, got: ${String(e.backend)}`);return typeof e.defaultProfile=="string"&&(n.defaultProfile=DS(e.defaultProfile)),n}function FS(t){let e=t?.env??k,n=t?.readFileSync??sN,r=t?.surface??e.AGENT_SURFACE,o=nN(e.AFK_BROWSER_HEADLESS,r),s=OS(e.AFK_BROWSER_ALLOWED_DOMAINS),i=OS(e.AFK_BROWSER_BLOCKED_DOMAINS),a=oN(e.AFK_BROWSER_DOM_SNAPSHOTS),l=rN(e.AFK_BROWSER_BACKEND),c=DS(e.AFK_BROWSER_DEFAULT_PROFILE),d={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:l,configPath:null,defaultProfile:c},u=e.AFK_BROWSER_CONFIG,p=u!==void 0&&u.trim()!==""?u.trim():QL(xt(),"browser.json"),f=n(p);if(f===void 0)return d;let m;try{m=JSON.parse(f)}catch(y){throw new Error(`Failed to parse browser config at ${p}: ${String(y)}`)}if(typeof m!="object"||m===null||Array.isArray(m))throw new Error(`Browser config at ${p} must be a JSON object`);let g=iN(d,m);return g.configPath=p,g}function Ka(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(MS(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>MS(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var eN,tN,Ga=h(()=>{"use strict";B();W();eN=new Set(["daemon","subagent","telegram","afk"]),tN=new Set(["repl","interactive","cli"])});import{existsSync as aN,readFileSync as lN}from"node:fs";import{createRequire as cN}from"node:module";import{dirname as dN,join as uN}from"node:path";function $S(t){if(typeof t=="string")return t;let e=[],n=t;for(let r=0;r<fN&&n instanceof Error;r++)e.push(n.message),n=n.cause;return e.length>0?e.join(" | "):String(t)}function Oe(t){let e=$S(t);return NS.some(n=>e.includes(n))}function mN(){try{let e=cN(import.meta.url).resolve("playwright/package.json"),n=JSON.parse(lN(e,"utf8"));if(typeof n!="object"||n===null)return;let r=n.bin,o=typeof r=="string"?r:typeof r=="object"&&r!==null?r.playwright:void 0;if(typeof o!="string"||o.length===0)return;let s=uN(dN(e),o);return aN(s)?`node ${/\s/.test(s)?`"${s}"`:s} install chromium`:void 0}catch{return}}function Ko(){return LS??=mN()??pN,LS}function Rp(t){return t.includes("install chromium")}function tt(t,e){let n=$S(t),r=e?.latched===!0?` ${gN}`:"";if(n.includes("Executable doesn't exist")){let o="";return e?.headless===!0?o=" This launch was headless, which needs the `chromium_headless_shell-*` build.":e?.headless===!1&&(o=" This launch was headed, which needs the full `chromium-*` build \u2014 the headless shell alone does not satisfy it."),`browser tools require the Playwright chromium binary. Install via: ${Ko()}.${o}${r}`}return`browser tools require the optional \`playwright\` peer dependency. Install via: pnpm add playwright (then ${Ko()}). Or pick a different tool.${r}`}function xp(t,e,n=!1){if(!Oe(t))return t;let r=t instanceof Error?t.message:String(t);return new Error(`${r}
|
|
880
880
|
|
|
881
|
-
${tt(t,{headless:e,latched:n})}`,{cause:t})}var NS,pN,fN,LS,gN,Cp=h(()=>{"use strict";NS=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],pN="pnpm exec playwright install chromium",fN=4;gN="This session already latched the failure, so browser tools keep fast-failing with this same error \u2014 after installing, call browser_close once to retry."});import Nn from"node:fs";import qa from"node:path";import{randomBytes as hN}from"node:crypto";import{chromium as yN}from"playwright";function bN(){try{return"5.89.0"}catch{}try{let t=qa.resolve(import.meta.dirname,"../../../package.json"),e=Nn.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var wN,za,US=h(()=>{"use strict";Cp();W();ce();wN=bN(),za=class{config;browser;sessions=new Map;launchPromise;launchFailure;shutdownComplete=!1;constructor(e){this.config=e}clearLaunchFailure(){this.launchFailure=void 0}latchLaunchFailure(e){this.launchFailure={error:e}}async ensureBrowser(){if(this.browser!==void 0&&this.browser.isConnected())return this.browser;if(this.launchFailure!==void 0)throw this.launchFailure.error;return this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=yN.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,this.clearLaunchFailure(),e)).catch(e=>{this.launchPromise=void 0;let n=xp(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),this.launchPromise)}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(l){s=l,await a.abort("blockedbyclient")}});let i=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",i,{once:!0});try{let a=await o.newPage(),l;try{l=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let c=await a.content();if(s!==void 0)throw s;let d=a.url(),u=l!==null?l.status():null;return{html:c,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${wN}`}}loadStorageState(e){let n=Td(e);try{if(!Nn.existsSync(n))return;let r=JSON.parse(Nn.readFileSync(n,"utf8"));return D("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){D("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=Td(e);if(!Nn.existsSync(r))return;let o=await n.storageState(),s=qa.join(qa.dirname(r),`.${qa.basename(r)}.${process.pid}.${hN(4).toString("hex")}.tmp`);Nn.writeFileSync(s,JSON.stringify(o),{mode:384}),Nn.chmodSync(s,384),Nn.renameSync(s,r),D("[browser/vault] saved session",{profile:e,file:r})}catch(r){D("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as SN}from"crypto";function BS(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&vN.test(t.label))}function HS(t){return SN("sha256").update(t,"utf8").digest("hex").slice(0,8)}function jS(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var vN,Ja=h(()=>{"use strict";vN=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as kN}from"node:crypto";function EN(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function AN(t,e,n){return`el_${kN("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function _N(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function WS(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function GS(t,e){let n=t.role??"",r=t.name??"";KS.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])GS(s,e)}async function TN(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(),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},qS).catch(()=>[])}async function RN(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")??"",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 g=s.type;g==="checkbox"?c="checkbox":g==="radio"?c="radio":g==="button"||g==="submit"||g==="reset"?c="button":g==="search"?c="searchbox":c="textbox"}if(!c)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,m={role:c,name:l,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},qS).catch(()=>[])}function xN(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Va(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=xN(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=TN(t),l=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,g]=await Promise.all([i,a,l,c,d]),y,w=!1;u!==null?(y=[],GS(u,y)):(o.push("observation skipped accessibility tree (returned null)"),w=!0,y=(await RN(t)).filter(P=>KS.has(P.role??"")));let v=new Map;for(let x of p){let P=WS(x.name),N=v.get(P);(!N||N.bbox.w===0&&x.bbox.w>0)&&v.set(P,x)}let A=y.map(x=>({ax:x,dom:v.get(WS(x.name??""))})),S=r?A:A.filter(x=>x.dom?x.dom.bbox.w>0||x.dom.bbox.h>0:!0);S.sort((x,P)=>{let N=x.dom?.bbox.y??0,F=P.dom?.bbox.y??0;if(N!==F)return N-F;let U=x.dom?.bbox.x??0,$=P.dom?.bbox.x??0;return U-$}),S.length>200&&o.push("page has 200+ interactive elements; consider scoping");let _=S.slice(0,n).map((x,P)=>{let N=x.ax.role??"generic",F=x.ax.name??"",U=AN(N,F,P),$=x.dom?.bbox??{x:0,y:0,w:0,h:0},M=x.dom?.type??null,L=null;x.ax.value!==void 0&&x.ax.value!==null&&(L=String(x.ax.value)),x.ax.checked!==void 0&&(L=String(x.ax.checked)),BS({role:N,kind:M})&&(L="[redacted]");let j={disabled:x.ax.disabled??!1};x.ax.checked!==void 0&&(j.checked=x.ax.checked===!0||x.ax.checked==="mixed"),x.ax.selected!==void 0&&(j.selected=x.ax.selected),x.ax.expanded!==void 0&&(j.expanded=x.ax.expanded);let J;x.dom?.testId?J=`[data-testid="${x.dom.testId}"]`:x.dom?.id&&(J=`#${x.dom.id}`);let ee={id:U,role:N,label:EN(F),kind:M,value:L,state:j,bbox:$};return J!==void 0&&(ee.selector=J),ee}),I="idle";try{let x=await t.evaluate(()=>document.readyState);x==="loading"?I="loading":x==="interactive"?I="navigating":I="idle"}catch{I="navigating"}I!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),w&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let R=_N(f),E=`obs_${e.observationCounter.toString(36)}`,C=new Date().toISOString();return{observationId:E,url:m,title:g,textSummary:R,interactive:_,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:C}}var KS,qS,zS=h(()=>{"use strict";Ja();KS=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);qS="a[href], button, input, select, textarea, [role], [tabindex], label"});async function JS(t,e){try{let n=await t.nth(e).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")??"",d=a.getBoundingClientRect();return{role:l,label:c,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 Ip(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>JS(t,s)))).filter(o=>o!==null)}async function CN(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 l=a,c=l.getBoundingClientRect();return`${l.tagName}@${Math.round(c.x)},${Math.round(c.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Pp(t,e,n){switch(e.kind){case"element_id":return IN(t,e,n);case"selector":return PN(t,e);case"semantic":return MN(t,e)}}async function IN(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 l=t.locator(r.selector);if(await l.count()===1)return{outcome:"resolved",locator:l}}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 Ip(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function PN(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 Ip(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function MN(t,e){return e.role!==void 0?ON(t,e.text,e.role):DN(t,e.text,e)}async function ON(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 Ip(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function DN(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{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 d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),l>0&&d.push({loc:s,count:l});let u=await CN(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 w=await JS(y.locator,y.index);if(w!==null){let v=`${w.role}:${w.label}:${g}`,A=0;for(let S=0;S<v.length;S++)A=A*31+v.charCodeAt(S)>>>0;f.push({...w,id:`el_${A.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var VS=h(()=>{"use strict"});async function Mp(t,e,n,r){let o=t.url();if(o===n)return null;let s=Ka(o,e);if(s.allowed)return null;try{await t.goBack()}catch{await r()}return{outcome:"blocked_by_policy",url:o,reason:s.reason}}var YS=h(()=>{"use strict";Ga()});import{randomBytes as FN}from"crypto";import{mkdir as LN,stat as NN,writeFile as $N}from"fs/promises";import{join as Op}from"path";import{gzip as UN}from"zlib";import{promisify as BN}from"util";function HN(t){return Op(no(t),"browser")}function jN(t){return Op(HN(t),"screenshots")}function WN(){return new Date().toISOString().replace(/[:.]/g,"-")}function KN(){return FN(3).toString("hex")}async function Dp(t,e,n){if(e.length>XS)throw new Error(`writeScreenshotSidecar: buffer exceeds ${XS} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=jN(t);await LN(r,{recursive:!0});let o=`${WN()}-${KN()}-${n}.png`,s=Op(r,o);await $N(s,e);let{size:i}=await NN(s);return{path:s,bytes:i}}var J3,XS,QS=h(()=>{"use strict";W();Ja();J3=BN(UN);XS=5*1024*1024});var ev={};yd(ev,{PlaywrightProvider:()=>Fp});function ZS(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 Fp,tv=h(()=>{"use strict";US();zS();VS();Ga();YS();QS();Fp=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new za(e)}async open(e){let n=Ka(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(u){a=u}let l=o.url();if(!(a!==null&&(l===""||l==="about:blank"))){let u=await Mp(o,this.config,e.url,()=>this.close({sessionId:r}));if(u!==null)return u}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let d=await Va(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,d.interactive,d.url,d.title,"browser_open"),a!==null)throw a;return d}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Va(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 Pp(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${ZS(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:l}=a,c=null,d=async()=>{switch(e.action){case"click":await l.click({timeout:i});break;case"fill":await l.fill(e.value??"");break;case"press":await l.press(e.value??"");break;case"select":await l.selectOption(e.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 d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(y){c=y}else c=g}let u=await Mp(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||c!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Va(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),c!==null)throw c;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal,requestGuard:e.requestGuard})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await Pp(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${ZS(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 Dp(n,s,"browser_screenshot"),l=0,c=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));l=d.w,c=d.h}catch{let d=r.viewportSize();l=d?.width??0,c=d?.height??0}else{let d=r.viewportSize();l=d?.width??0,c=d?.height??0}return{path:i,bytes:a,width:l,height:c,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await Dp(n,o,r);return s}catch{return null}}}});var Un={};yd(Un,{__resetBrowserRegistryForTests:()=>VN,browserProviderActive:()=>zN,closeBrowserProvider:()=>Lp,getBrowserProvider:()=>qN,peekBrowserProvider:()=>JN});function nv(){Promise.resolve(Lp()).then(()=>{process.exit(130)})}function rv(){Promise.resolve(Lp()).then(()=>{process.exit(143)})}function ov(){Et=null}function GN(){Ya||(process.on("SIGINT",nv),process.on("SIGTERM",rv),process.on("exit",ov),Ya=!0)}function sv(){Ya&&(process.removeListener("SIGINT",nv),process.removeListener("SIGTERM",rv),process.removeListener("exit",ov),Ya=!1)}async function qN(t){return Et!==null?Et:($n!==null||($n=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(tv(),ev)),n=FS(t),r=new e(n);return GN(),Et=r,$n=null,r})()),$n)}async function Lp(){if(Et===null)return;let t=Et;Et=null,$n=null,sv(),await t.shutdown()}function zN(){return Et!==null}function JN(){return Et}function VN(){Et=null,$n=null,sv()}var Et,$n,Ya,Bn=h(()=>{"use strict";Ga();Et=null,$n=null,Ya=!1});async function iv(t,e){try{return await AS(t,e)}catch(n){return D("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function t$(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Bn(),Un));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function av(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??t$,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i=t,a=null,l=null;try{let d=await Wa(n,t,{headers:e$,signal:e.signal},o);a=d.status,i=d.url||t;let u=d.headers.get("content-type")??"";if(d.ok){if(ZN.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 p=await d.text();if(QN.test(u)&&!XN.test(u))return{title:"",markdown:p.trim(),finalUrl:i,usedRender:!1};if(s=await iv(p,i),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(d){if(e.signal.aborted||d instanceof dt||d instanceof Error&&d.message.startsWith("web_scrape markdown mode received binary"))throw d;l=d}if(!(s===null||s.textLength<200)&&s!==null)return{title:s.title,markdown:s.markdown,finalUrl:i,usedRender:!1};try{await Wo(t,o);let d=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:p=>Wo(p,o)});d.finalUrl!==t&&/^https?:\/\//i.test(d.finalUrl)&&await Wo(d.finalUrl,o);let u=await iv(d.html,d.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||u.textLength>=s.textLength)return{title:u.title,markdown:u.markdown,finalUrl:d.finalUrl,usedRender:!0}}catch(d){if(e.signal.aborted||d instanceof dt)throw d;if(s===null){let u=d instanceof Error?d.message:String(d),p=l instanceof Error?l.message:`HTTP ${a??"error"}`,f=new Error(`web_scrape could not retrieve ${t}: fetch failed (${p}) and render failed (${u}).`);throw f.cause=d,f}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:i,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${a??"error"}).`)}var XN,QN,ZN,e$,lv=h(()=>{"use strict";_S();Tp();ce();XN=/(text\/html|application\/xhtml\+xml)/i,QN=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,ZN=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,e$={"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 o$(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(n$,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":t.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),r$),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let l="";try{let d=await s.text(),u=yr(d);u&&(l=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let c=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${c}${l}`)}let i;try{i=await s.json()}catch(l){throw new Error(`Exa Search response was not JSON: ${l instanceof Error?l.message:String(l)}`)}return(i.results??[]).slice(0,r).map(l=>({title:(l.title??"").trim()||"(untitled)",url:l.url??"",description:(l.highlights?.[0]??"").trim()})).filter(l=>l.url.length>0)}}}function cv(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?o$({apiKey:t.exaApiKey,fetchFn:t.fetchFn}):{error:'web_scrape search mode requires a search backend. Set EXA_API_KEY (free tier at https://exa.ai) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function dv(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
881
|
+
${tt(t,{headless:e,latched:n})}`,{cause:t})}var NS,pN,fN,LS,gN,Cp=h(()=>{"use strict";NS=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],pN="pnpm exec playwright install chromium",fN=4;gN="This session already latched the failure, so browser tools keep fast-failing with this same error \u2014 after installing, call browser_close once to retry."});import Nn from"node:fs";import qa from"node:path";import{randomBytes as hN}from"node:crypto";import{chromium as yN}from"playwright";function bN(){try{return"5.89.1"}catch{}try{let t=qa.resolve(import.meta.dirname,"../../../package.json"),e=Nn.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var wN,za,US=h(()=>{"use strict";Cp();W();ce();wN=bN(),za=class{config;browser;sessions=new Map;launchPromise;launchFailure;shutdownComplete=!1;constructor(e){this.config=e}clearLaunchFailure(){this.launchFailure=void 0}latchLaunchFailure(e){this.launchFailure={error:e}}async ensureBrowser(){if(this.browser!==void 0&&this.browser.isConnected())return this.browser;if(this.launchFailure!==void 0)throw this.launchFailure.error;return this.browser!==void 0&&!this.browser.isConnected()&&(this.browser=void 0,this.launchPromise=void 0),this.launchPromise!==void 0?this.launchPromise:(this.launchPromise=yN.launch({headless:this.config.headless}).then(e=>(this.browser=e,this.launchPromise=void 0,this.clearLaunchFailure(),e)).catch(e=>{this.launchPromise=void 0;let n=xp(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),this.launchPromise)}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(l){s=l,await a.abort("blockedbyclient")}});let i=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",i,{once:!0});try{let a=await o.newPage(),l;try{l=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let c=await a.content();if(s!==void 0)throw s;let d=a.url(),u=l!==null?l.status():null;return{html:c,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${wN}`}}loadStorageState(e){let n=Td(e);try{if(!Nn.existsSync(n))return;let r=JSON.parse(Nn.readFileSync(n,"utf8"));return D("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){D("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=Td(e);if(!Nn.existsSync(r))return;let o=await n.storageState(),s=qa.join(qa.dirname(r),`.${qa.basename(r)}.${process.pid}.${hN(4).toString("hex")}.tmp`);Nn.writeFileSync(s,JSON.stringify(o),{mode:384}),Nn.chmodSync(s,384),Nn.renameSync(s,r),D("[browser/vault] saved session",{profile:e,file:r})}catch(r){D("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as SN}from"crypto";function BS(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&vN.test(t.label))}function HS(t){return SN("sha256").update(t,"utf8").digest("hex").slice(0,8)}function jS(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var vN,Ja=h(()=>{"use strict";vN=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as kN}from"node:crypto";function EN(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function AN(t,e,n){return`el_${kN("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function _N(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function WS(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function GS(t,e){let n=t.role??"",r=t.name??"";KS.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])GS(s,e)}async function TN(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(),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},qS).catch(()=>[])}async function RN(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")??"",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 g=s.type;g==="checkbox"?c="checkbox":g==="radio"?c="radio":g==="button"||g==="submit"||g==="reset"?c="button":g==="search"?c="searchbox":c="textbox"}if(!c)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,m={role:c,name:l,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},qS).catch(()=>[])}function xN(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Va(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=xN(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=TN(t),l=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),c=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,g]=await Promise.all([i,a,l,c,d]),y,w=!1;u!==null?(y=[],GS(u,y)):(o.push("observation skipped accessibility tree (returned null)"),w=!0,y=(await RN(t)).filter(P=>KS.has(P.role??"")));let v=new Map;for(let x of p){let P=WS(x.name),N=v.get(P);(!N||N.bbox.w===0&&x.bbox.w>0)&&v.set(P,x)}let A=y.map(x=>({ax:x,dom:v.get(WS(x.name??""))})),S=r?A:A.filter(x=>x.dom?x.dom.bbox.w>0||x.dom.bbox.h>0:!0);S.sort((x,P)=>{let N=x.dom?.bbox.y??0,F=P.dom?.bbox.y??0;if(N!==F)return N-F;let U=x.dom?.bbox.x??0,$=P.dom?.bbox.x??0;return U-$}),S.length>200&&o.push("page has 200+ interactive elements; consider scoping");let _=S.slice(0,n).map((x,P)=>{let N=x.ax.role??"generic",F=x.ax.name??"",U=AN(N,F,P),$=x.dom?.bbox??{x:0,y:0,w:0,h:0},M=x.dom?.type??null,L=null;x.ax.value!==void 0&&x.ax.value!==null&&(L=String(x.ax.value)),x.ax.checked!==void 0&&(L=String(x.ax.checked)),BS({role:N,kind:M})&&(L="[redacted]");let j={disabled:x.ax.disabled??!1};x.ax.checked!==void 0&&(j.checked=x.ax.checked===!0||x.ax.checked==="mixed"),x.ax.selected!==void 0&&(j.selected=x.ax.selected),x.ax.expanded!==void 0&&(j.expanded=x.ax.expanded);let J;x.dom?.testId?J=`[data-testid="${x.dom.testId}"]`:x.dom?.id&&(J=`#${x.dom.id}`);let ee={id:U,role:N,label:EN(F),kind:M,value:L,state:j,bbox:$};return J!==void 0&&(ee.selector=J),ee}),I="idle";try{let x=await t.evaluate(()=>document.readyState);x==="loading"?I="loading":x==="interactive"?I="navigating":I="idle"}catch{I="navigating"}I!=="idle"&&o.push("page is still loading \u2014 observation may be incomplete"),w&&!o.includes("observation skipped accessibility tree (returned null)")&&o.push("observation skipped accessibility tree (returned null)");let R=_N(f),E=`obs_${e.observationCounter.toString(36)}`,C=new Date().toISOString();return{observationId:E,url:m,title:g,textSummary:R,interactive:_,status:{httpStatus:e.httpStatus??null,loadingState:I,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:C}}var KS,qS,zS=h(()=>{"use strict";Ja();KS=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);qS="a[href], button, input, select, textarea, [role], [tabindex], label"});async function JS(t,e){try{let n=await t.nth(e).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")??"",d=a.getBoundingClientRect();return{role:l,label:c,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 Ip(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>JS(t,s)))).filter(o=>o!==null)}async function CN(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 l=a,c=l.getBoundingClientRect();return`${l.tagName}@${Math.round(c.x)},${Math.round(c.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function Pp(t,e,n){switch(e.kind){case"element_id":return IN(t,e,n);case"selector":return PN(t,e);case"semantic":return MN(t,e)}}async function IN(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 l=t.locator(r.selector);if(await l.count()===1)return{outcome:"resolved",locator:l}}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 Ip(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function PN(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 Ip(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function MN(t,e){return e.role!==void 0?ON(t,e.text,e.role):DN(t,e.text,e)}async function ON(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 Ip(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function DN(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{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 d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),l>0&&d.push({loc:s,count:l});let u=await CN(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 w=await JS(y.locator,y.index);if(w!==null){let v=`${w.role}:${w.label}:${g}`,A=0;for(let S=0;S<v.length;S++)A=A*31+v.charCodeAt(S)>>>0;f.push({...w,id:`el_${A.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var VS=h(()=>{"use strict"});async function Mp(t,e,n,r){let o=t.url();if(o===n)return null;let s=Ka(o,e);if(s.allowed)return null;try{await t.goBack()}catch{await r()}return{outcome:"blocked_by_policy",url:o,reason:s.reason}}var YS=h(()=>{"use strict";Ga()});import{randomBytes as FN}from"crypto";import{mkdir as LN,stat as NN,writeFile as $N}from"fs/promises";import{join as Op}from"path";import{gzip as UN}from"zlib";import{promisify as BN}from"util";function HN(t){return Op(no(t),"browser")}function jN(t){return Op(HN(t),"screenshots")}function WN(){return new Date().toISOString().replace(/[:.]/g,"-")}function KN(){return FN(3).toString("hex")}async function Dp(t,e,n){if(e.length>XS)throw new Error(`writeScreenshotSidecar: buffer exceeds ${XS} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=jN(t);await LN(r,{recursive:!0});let o=`${WN()}-${KN()}-${n}.png`,s=Op(r,o);await $N(s,e);let{size:i}=await NN(s);return{path:s,bytes:i}}var J3,XS,QS=h(()=>{"use strict";W();Ja();J3=BN(UN);XS=5*1024*1024});var ev={};yd(ev,{PlaywrightProvider:()=>Fp});function ZS(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 Fp,tv=h(()=>{"use strict";US();zS();VS();Ga();YS();QS();Fp=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new za(e)}async open(e){let n=Ka(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(u){a=u}let l=o.url();if(!(a!==null&&(l===""||l==="about:blank"))){let u=await Mp(o,this.config,e.url,()=>this.close({sessionId:r}));if(u!==null)return u}(e.screenshot===!0||a!==null)&&(i=await this.captureScreenshot(o,r,"browser_open")),s.observationCounter+=1;let d=await Va(o,{observationCounter:s.observationCounter,screenshotPath:i,consoleErrors:this.launcher.getConsoleErrorCount(r),httpStatus:this.launcher.getLastHttpStatus(r),hasDialog:this.launcher.hasOpenDialog(r)});if(this.updateSessionFromObservation(s,d.interactive,d.url,d.title,"browser_open"),a!==null)throw a;return d}async observe(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_observe: no page open for session ${n}`);let o=this.ensureSessionState(n),s=null;e.screenshot===!0&&(s=await this.captureScreenshot(r,n,"browser_observe")),o.observationCounter+=1;let i=await Va(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 Pp(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${ZS(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:l}=a,c=null,d=async()=>{switch(e.action){case"click":await l.click({timeout:i});break;case"fill":await l.fill(e.value??"");break;case"press":await l.press(e.value??"");break;case"select":await l.selectOption(e.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 d()}catch(g){if(g instanceof Error&&/navigation|net::ERR/i.test(g.message))try{await d()}catch(y){c=y}else c=g}let u=await Mp(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||c!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Va(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),c!==null)throw c;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal,requestGuard:e.requestGuard})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await Pp(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${ZS(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 Dp(n,s,"browser_screenshot"),l=0,c=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));l=d.w,c=d.h}catch{let d=r.viewportSize();l=d?.width??0,c=d?.height??0}else{let d=r.viewportSize();l=d?.width??0,c=d?.height??0}return{path:i,bytes:a,width:l,height:c,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await Dp(n,o,r);return s}catch{return null}}}});var Un={};yd(Un,{__resetBrowserRegistryForTests:()=>VN,browserProviderActive:()=>zN,closeBrowserProvider:()=>Lp,getBrowserProvider:()=>qN,peekBrowserProvider:()=>JN});function nv(){Promise.resolve(Lp()).then(()=>{process.exit(130)})}function rv(){Promise.resolve(Lp()).then(()=>{process.exit(143)})}function ov(){Et=null}function GN(){Ya||(process.on("SIGINT",nv),process.on("SIGTERM",rv),process.on("exit",ov),Ya=!0)}function sv(){Ya&&(process.removeListener("SIGINT",nv),process.removeListener("SIGTERM",rv),process.removeListener("exit",ov),Ya=!1)}async function qN(t){return Et!==null?Et:($n!==null||($n=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(tv(),ev)),n=FS(t),r=new e(n);return GN(),Et=r,$n=null,r})()),$n)}async function Lp(){if(Et===null)return;let t=Et;Et=null,$n=null,sv(),await t.shutdown()}function zN(){return Et!==null}function JN(){return Et}function VN(){Et=null,$n=null,sv()}var Et,$n,Ya,Bn=h(()=>{"use strict";Ga();Et=null,$n=null,Ya=!1});async function iv(t,e){try{return await AS(t,e)}catch(n){return D("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function t$(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(Bn(),Un));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function av(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??t$,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i=t,a=null,l=null;try{let d=await Wa(n,t,{headers:e$,signal:e.signal},o);a=d.status,i=d.url||t;let u=d.headers.get("content-type")??"";if(d.ok){if(ZN.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 p=await d.text();if(QN.test(u)&&!XN.test(u))return{title:"",markdown:p.trim(),finalUrl:i,usedRender:!1};if(s=await iv(p,i),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(d){if(e.signal.aborted||d instanceof dt||d instanceof Error&&d.message.startsWith("web_scrape markdown mode received binary"))throw d;l=d}if(!(s===null||s.textLength<200)&&s!==null)return{title:s.title,markdown:s.markdown,finalUrl:i,usedRender:!1};try{await Wo(t,o);let d=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:p=>Wo(p,o)});d.finalUrl!==t&&/^https?:\/\//i.test(d.finalUrl)&&await Wo(d.finalUrl,o);let u=await iv(d.html,d.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||u.textLength>=s.textLength)return{title:u.title,markdown:u.markdown,finalUrl:d.finalUrl,usedRender:!0}}catch(d){if(e.signal.aborted||d instanceof dt)throw d;if(s===null){let u=d instanceof Error?d.message:String(d),p=l instanceof Error?l.message:`HTTP ${a??"error"}`,f=new Error(`web_scrape could not retrieve ${t}: fetch failed (${p}) and render failed (${u}).`);throw f.cause=d,f}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:i,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${a??"error"}).`)}var XN,QN,ZN,e$,lv=h(()=>{"use strict";_S();Tp();ce();XN=/(text\/html|application\/xhtml\+xml)/i,QN=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,ZN=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,e$={"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 o$(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(n$,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json","x-api-key":t.apiKey,"User-Agent":"agent-afk/web_scrape"},body:JSON.stringify({query:n,type:"auto",numResults:Math.min(Math.max(r,1),r$),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let l="";try{let d=await s.text(),u=yr(d);u&&(l=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let c=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${c}${l}`)}let i;try{i=await s.json()}catch(l){throw new Error(`Exa Search response was not JSON: ${l instanceof Error?l.message:String(l)}`)}return(i.results??[]).slice(0,r).map(l=>({title:(l.title??"").trim()||"(untitled)",url:l.url??"",description:(l.highlights?.[0]??"").trim()})).filter(l=>l.url.length>0)}}}function cv(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?o$({apiKey:t.exaApiKey,fetchFn:t.fetchFn}):{error:'web_scrape search mode requires a search backend. Set EXA_API_KEY (free tier at https://exa.ai) to enable it. Use mode: "markdown" to read a known URL, or mode: "raw" for a direct fetch.'}}function dv(t,e){if(e.length===0)return`# Search results for "${t}"
|
|
882
882
|
|
|
883
883
|
(no results)`;let n=[`# Search results for "${t}"`,""];return e.forEach((r,o)=>{n.push(`## ${o+1}. ${r.title}`),r.url&&n.push(r.url),r.description&&n.push(r.description),n.push("")}),n.join(`
|
|
884
884
|
`).trimEnd()}var n$,r$,uv=h(()=>{"use strict";_n();n$="https://api.exa.ai/search",r$=10});function Xa(t){if(t instanceof Error&&t.name==="TimeoutError")return"timeout";let e=t instanceof Error?t.message:String(t);return/Timeout\s+\d+\s*ms exceeded/i.test(e)?"timeout":void 0}var Hn=h(()=>{"use strict";Cp()});function d$(t){if(!t||typeof t!="object")return{error:"Invalid input: expected an object"};let e=t,n=e.mode??"markdown";if(n!=="markdown"&&n!=="raw"&&n!=="search")return{error:`Invalid input: mode must be one of "markdown", "raw", "search" (got ${JSON.stringify(n)})`};let r=n,o,s;if(r==="search"){if(typeof e.query!="string"||e.query.length===0)return{error:'Invalid input: search mode requires a non-empty "query" string'};s=e.query}else{if(typeof e.url!="string"||e.url.length===0)return{error:`Invalid input: ${r} mode requires a non-empty "url" string`};let l;try{l=new URL(e.url)}catch{return{error:`Invalid input: "${e.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=s$;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number"||!Number.isFinite(e.timeout_ms)||e.timeout_ms<=0)return{error:"Invalid input: timeout_ms must be a positive finite number"};i=Math.min(e.timeout_ms,i$)}let a=a$;if(e.max_bytes!==void 0){if(typeof e.max_bytes!="number"||!Number.isFinite(e.max_bytes)||e.max_bytes<=0)return{error:"Invalid input: max_bytes must be a positive finite number"};a=Math.min(e.max_bytes,l$)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Np(t,e){return Buffer.byteLength(t,"utf8")<=e?{content:t,truncated:!1}:{content:Ft(t,e),truncated:!0}}function u$(t={}){let e=t.fetchFn??globalThis.fetch,n=t.env??process.env,r=t.lookupFn!==void 0?{lookupFn:t.lookupFn}:{};return async(o,s)=>{if(typeof e!="function")return{content:"web_scrape unavailable: global fetch() is not present in this runtime (agent-afk requires Node 20+).",isError:!0};let i=d$(o);if("error"in i)return{content:i.error,isError:!0};if(s.aborted){let u=s.reason;return{content:`web_scrape aborted: ${u instanceof Error?u.message:String(u??"aborted")}`,isError:!0}}let a=new AbortController,l=()=>{a.abort(s.reason)},c,d=()=>{let u=a.signal.reason;return u instanceof Error?u.message:String(u??"aborted")};try{if(s.addEventListener("abort",l,{once:!0}),c=setTimeout(()=>{a.abort(new Error(`web_scrape timeout after ${i.timeoutMs}ms`))},i.timeoutMs),i.url!==void 0){let p=await _p(i.url,r);if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(!p.allowed)return{content:`web_scrape blocked: ${p.reason}`,isError:!0}}if(i.mode==="raw"){let p;try{let g={method:"GET",headers:{"User-Agent":"agent-afk/web_scrape",Accept:"*/*"},signal:a.signal};p=await Wa(e,i.url,g,r)}catch(g){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:g instanceof dt?{content:`web_scrape blocked: ${g.message}`,isError:!0}:{content:`web_scrape network error: ${g instanceof Error?g.message:String(g)}`,isError:!0}}if(!p.ok)return{content:`web_scrape HTTP ${p.status} ${p.statusText||""}`.trimEnd()+` for ${i.url}`,isError:!0};let f;try{f=await p.text()}catch(g){return{content:`web_scrape read error: ${g instanceof Error?g.message:String(g)}`,isError:!0}}let m=Np(f,i.maxBytes);return{content:m.content,...m.truncated?{truncated:!0}:{}}}if(i.mode==="markdown")try{let p=await av(i.url,{fetchFn:e,renderFn:t.renderFn,timeoutMs:i.timeoutMs,signal:a.signal,...t.lookupFn!==void 0?{lookupFn:t.lookupFn}:{}});if(p.markdown.trim().length===0)return{content:`web_scrape extracted no readable content from ${i.url}.`,isError:!0};let f=Np(p.markdown,i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(p instanceof dt)return{content:`web_scrape blocked: ${p.message}`,isError:!0};let f=p instanceof Error?p.message:String(p),m=Oe(p)&&!Rp(f)?` (the render fallback needs the optional Playwright browser \u2014 run \`${Ko()}\`)`:"";return{content:`web_scrape markdown error: ${f}${m}`,isError:!0}}let u=cv({exaApiKey:n.EXA_API_KEY,fetchFn:e});if("error"in u)return{content:u.error,isError:!0};try{let p=await u.search(i.query,{limit:c$,timeoutMs:i.timeoutMs,signal:a.signal}),f=Np(dv(i.query,p),i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:{content:`web_scrape search error (${u.name}): ${p instanceof Error?p.message:String(p)}`,isError:!0}}}finally{c!==void 0&&clearTimeout(c),s.removeEventListener("abort",l)}}}var s$,i$,a$,l$,c$,pv,fv=h(()=>{"use strict";lv();uv();Tp();Pn();Hn();s$=3e4,i$=12e4,a$=1e5,l$=1e6,c$=10;pv=u$()});import{existsSync as gv,mkdirSync as p$,readFileSync as f$,renameSync as m$,unlinkSync as g$,writeFileSync as h$}from"node:fs";import{dirname as mv,join as y$}from"node:path";import{randomBytes as b$}from"node:crypto";function Tr(t){let e=t??kd();if(!gv(e))return[];try{let n=f$(e,"utf-8");return JSON.parse(n)}catch(n){let r=n instanceof Error?n.message:String(n);return console.error(`[schedule-store] failed to parse ${e}: ${r}`),[]}}function Qa(t,e){let n=e??kd();p$(mv(n),{recursive:!0});let r=y$(mv(n),`.schedules.json.${process.pid}.${b$(4).toString("hex")}.tmp`),o=JSON.stringify(t,null,2);try{h$(r,o,"utf-8"),m$(r,n)}catch(s){try{gv(r)&&g$(r)}catch{}throw s}}function hv(t,e){let n=Tr(e),r=n.map(l=>l.id),o=w$(t.name),s=S$(o,r),i=new Date().toISOString(),a={...t,notifyOn:t.notifyOn??"failure",id:s,createdAt:i,updatedAt:i};return n.push(a),Qa(n,e),a}function yv(t,e){let n=Tr(e),r=n.length,o=n.filter(s=>s.id!==t);return o.length===r?!1:(Qa(o,e),!0)}function bv(t,e){return Tr(e).find(n=>n.id===t)}function w$(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}function S$(t,e){if(!e.includes(t))return t;let n=2;for(;e.includes(`${t}-${n}`);)n+=1;return`${t}-${n}`}var wv=h(()=>{"use strict";W()});import{existsSync as v$,readFileSync as k$}from"node:fs";import{join as E$}from"node:path";async function Go(t,e,n){let r;try{let o=E$(Vg("default"),"port");if(!v$(o))return{synced:!1,detail:"daemon-not-detected (no port file)"};let s=k$(o,"utf-8").trim();if(r=parseInt(s,10),Number.isNaN(r))return{synced:!1,detail:"daemon-not-detected (invalid port file)"}}catch{return{synced:!1,detail:"daemon-not-detected (unreadable port file)"}}try{let o=await fetch(`http://localhost:${r}${e}`,{method:t,headers:{"Content-Type":"application/json"},body:n!==void 0?JSON.stringify(n):void 0,signal:AbortSignal.timeout(2e3)});return o.ok?{synced:!0,detail:"synced"}:t==="POST"&&o.status===409?{synced:!0,detail:"already-registered"}:t==="DELETE"&&o.status===404?{synced:!0,detail:"not-registered"}:{synced:!1,detail:`daemon-rejected (HTTP ${o.status})`}}catch{return{synced:!1,detail:"daemon-unreachable (stale port file or network error)"}}}var $p,Sv=h(()=>{"use strict";W();$p="Change saved to schedules.json, but a running daemon (if any) did not pick it up \u2014 it will apply on the next daemon (re)start."});import{existsSync as A$}from"node:fs";import{readFile as _$}from"node:fs/promises";var vv,kv,Ev,Av,_v=h(()=>{"use strict";wv();W();Sv();vv=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected object",isError:!0};let n=t;if(typeof n.name!="string"||!n.name)return{content:"Invalid input: name required",isError:!0};if(typeof n.command!="string"||!n.command)return{content:"Invalid input: command required",isError:!0};if(typeof n.cron!="string"||!n.cron)return{content:"Invalid input: cron required",isError:!0};let r=n.cron.trim().split(/\s+/);if(r.length!==5&&r.length!==6)return{content:"Invalid input: cron must be a 5 or 6-field expression",isError:!0};let o=n.notifyChat;if(o!==void 0&&typeof o!="number"&&typeof o!="string")return{content:"Invalid input: notifyChat must be a number (chat id) or string (chat id or alias name)",isError:!0};let s=hv({name:n.name,command:n.command,cron:n.cron,trigger:n.trigger??"cron",notifyOn:n.notifyOn,...o!==void 0?{notifyChat:o}:{},enabled:typeof n.enabled=="boolean"?n.enabled:!0}),i=s.enabled?await Go("POST","/tasks",{taskId:s.id,command:s.command,cron:s.cron,trigger:s.trigger,notifyOn:s.notifyOn,...s.notifyChat!==void 0?{notifyChat:s.notifyChat}:{}}):await Go("DELETE",`/tasks/${s.id}`);return{content:JSON.stringify({id:s.id,name:s.name,cron:s.cron,enabled:s.enabled,daemonSynced:i.synced,syncDetail:i.detail,...i.synced?{}:{syncNote:$p}})}},kv=async(t,e)=>{let n=Tr();return{content:JSON.stringify(n.map(r=>({id:r.id,name:r.name,cron:r.cron,trigger:r.trigger,enabled:r.enabled,notifyOn:r.notifyOn})))}},Ev=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected object",isError:!0};let n=t;if(typeof n.taskId!="string"||!n.taskId)return{content:"Invalid input: taskId required",isError:!0};let r=n.taskId,o=typeof n.limit=="number"?Math.min(Math.max(1,n.limit),50):10,s=ni();if(!A$(s))return{content:JSON.stringify([])};let i;try{let c=await _$(s);i=(c.length>1048576?c.subarray(c.length-1048576):c).toString("utf-8")}catch{return{content:JSON.stringify([])}}let a=i.split(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-afk",
|
|
3
|
-
"version": "5.89.
|
|
3
|
+
"version": "5.89.1",
|
|
4
4
|
"description": "Open-source coding-agent harness you can actually change — own the loop (prompts, gates, routing, skills, terminal states), use any model, run long tasks while you're away.",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|