agent-afk 5.119.0 → 5.119.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/telegram.mjs CHANGED
@@ -158,7 +158,7 @@ Send a message to start one, or /new for a fresh session.`}function Ow(t){return
158
158
  \u2026 [${n.length-i.length-a.length} bytes truncated: showing first ${i.length} + last ${a.length} of ${n.length}] \u2026
159
159
 
160
160
  `;return i.toString("utf8")+l+a.toString("utf8")}function Yt(t){return Buffer.byteLength(t,"utf8")<=1e5?{content:t,truncated:!1}:{content:Jt(t,1e5),truncated:!0}}var fU,Sc,hn=g(()=>{"use strict";fU=160;Sc=`
161
- [output truncated \u2014 command exceeded the 8000000-byte output cap and was terminated]`});var TS,ES,RS=g(()=>{"use strict";TS={name:"read_witness",category:"read",concurrencySafe:!0,description:"Read and filter events from a session's witness trace (the durable record of everything the agent did). Returns structured trace events in chronological order. Use to inspect tool calls, errors, subagent lifecycles, costs, and session phases from a specific session. Defaults to the most recent session.",input_schema:{type:"object",properties:{session:{type:"string",description:'Session ID to read, or "latest" (default). Use search_witness to find session IDs.'},kinds:{type:"array",items:{type:"string"},description:"Filter by event kind(s). Values: tool_call, subagent_lifecycle, session_phase, closure, abort, budget, hook_decision, browser_event, claim, compaction, background_agent, queued_user_message, session_sealed."},tool_name:{type:"string",description:'Filter tool_call events to only this tool name (e.g. "bash", "edit_file").'},errors_only:{type:"boolean",description:"When true, show only error events: failed tool calls and failed subagents. Default: false."},limit:{type:"number",description:"Max events to return (default: 50, max: 200). Returns the N most recent matching events."}},required:[]}},ES={name:"search_witness",category:"read",concurrencySafe:!0,description:"Search across multiple sessions' witness traces for a text pattern. Returns matching trace events grouped by session. Use to find patterns across sessions \u2014 recurring errors, specific tool usage, cost spikes, or any text that appears in trace event payloads. Scans the N most recent sessions (default 20). Results are capped at 200 total matches.",input_schema:{type:"object",properties:{query:{type:"string",description:"Text pattern to search for (case-insensitive substring match)."},sessions:{type:"number",description:'Number of recent sessions to scan (default: 20, max: 100). The result includes sessionsAvailable (sessions in this window before any since filter) and sessionsSearched (sessions actually read after the since filter) so you can distinguish "few sessions exist" from "the date filter excluded most of them".'},kinds:{type:"array",items:{type:"string"},description:"Filter results to specific event kinds (same values as read_witness)."},since:{type:"string",description:"ISO date string \u2014 only search sessions modified after this date."}},required:["query"]}}});var mU,gU,hU,yU,bU,wU,SU,vU,kU,Ye,er,tr,AU,_U,TU,EU,RU,xU,IU,CU,PU,MU,OU,DU,FU,LU,Dt,bt,x9,it=g(()=>{"use strict";RS();mU={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"]}},gU={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"]}},hU={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"]}},yU={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"]}},bU={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"]}},wU={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"]}},SU={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"]}},vU={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).\n\nFor supergroups with topics enabled, set `thread_id` alongside `chat` to send to a specific topic thread.',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)."},thread_id:{type:"number",description:"Optional. Telegram message_thread_id for sending to a specific topic in a supergroup with topics enabled. Pass the numeric thread/topic ID. Ignored when the target chat is not a supergroup with topics. Requires `chat` to be set explicitly (thread targeting without a chat target is ambiguous)."}},required:["message"]}},kU={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:[]}},Ye={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.
161
+ [output truncated \u2014 command exceeded the 8000000-byte output cap and was terminated]`});var TS,ES,RS=g(()=>{"use strict";TS={name:"read_witness",category:"read",concurrencySafe:!0,description:"Read and filter events from a session's witness trace (the durable record of everything the agent did). Returns structured trace events in chronological order. Use to inspect tool calls, errors, subagent lifecycles, costs, and session phases from a specific session. Defaults to the most recent session.",input_schema:{type:"object",properties:{session:{type:"string",description:'Session ID to read, or "latest" (default). Use search_witness to find session IDs.'},kinds:{type:"array",items:{type:"string"},description:"Filter by event kind(s). Values: tool_call, subagent_lifecycle, session_phase, closure, abort, budget, hook_decision, browser_event, claim, compaction, background_agent, queued_user_message, session_sealed."},tool_name:{type:"string",description:'Filter tool_call events to only this tool name (e.g. "bash", "edit_file").'},errors_only:{type:"boolean",description:"When true, show only error events: failed tool calls and failed subagents. Default: false."},limit:{type:"number",description:"Max events to return (default: 50, max: 200). Returns the N most recent matching events."}},required:[]}},ES={name:"search_witness",category:"read",concurrencySafe:!0,description:"Search across multiple sessions' witness traces for a text pattern. Returns matching trace events grouped by session. Use to find patterns across sessions \u2014 recurring errors, specific tool usage, cost spikes, or any text that appears in trace event payloads. Scans the N most recent sessions (default 20). Results are capped at 200 total matches across all scanned sessions.",input_schema:{type:"object",properties:{query:{type:"string",description:"Text pattern to search for (case-insensitive substring match)."},sessions:{type:"number",description:'Number of recent sessions to scan (default: 20, max: 100). The result includes sessionsAvailable (sessions in this window before any since filter) and sessionsSearched (sessions actually read after the since filter) so you can distinguish "few sessions exist" from "the date filter excluded most of them".'},kinds:{type:"array",items:{type:"string"},description:"Filter results to specific event kinds (same values as read_witness)."},since:{type:"string",description:"ISO date string \u2014 only search sessions modified after this date."}},required:["query"]}}});var mU,gU,hU,yU,bU,wU,SU,vU,kU,Ye,er,tr,AU,_U,TU,EU,RU,xU,IU,CU,PU,MU,OU,DU,FU,LU,Dt,bt,x9,it=g(()=>{"use strict";RS();mU={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"]}},gU={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"]}},hU={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"]}},yU={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"]}},bU={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"]}},wU={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"]}},SU={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"]}},vU={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).\n\nFor supergroups with topics enabled, set `thread_id` alongside `chat` to send to a specific topic thread.',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)."},thread_id:{type:"number",description:"Optional. Telegram message_thread_id for sending to a specific topic in a supergroup with topics enabled. Pass the numeric thread/topic ID. Ignored when the target chat is not a supergroup with topics. Requires `chat` to be set explicitly (thread targeting without a chat target is ambiguous)."}},required:["message"]}},kU={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:[]}},Ye={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.
162
162
 
163
163
  Parallelize: dispatch multiple \`agent\` calls in a single tool-use turn to run independent investigations concurrently.
164
164
 
@@ -211,7 +211,7 @@ ${o}`,paths:[e,n]}:o!==null?s={content:o,paths:[n]}:r!==null?s={content:r,paths:
211
211
 
212
212
  ${e}`}var jH,sm=g(()=>{"use strict";jH=new Set(["script","style","noscript","template","svg"])});function GH(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 Ok(t,e,n){let r=Math.min(e*2**t,n);return Math.round(Math.random()*r)}function qH(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 Dk(t,e,n={},r={}){let o=r.retries??3,s=r.baseDelayMs??500,i=r.maxDelayMs??1e4,a=r.sleep??GH,c=n.signal??void 0,l;for(let d=0;d<=o;d++){if(c?.aborted)throw c.reason??new Error("aborted");try{let u=await t(e,n);if(!KH.has(u.status)||d===o)return u;let p=qH(u,i)??Ok(d,s,i);$("[web/retryFetch] retrying",{url:e,attempt:d,status:u.status,waitMs:p}),await u.body?.cancel().catch(()=>{}),await a(p,c)}catch(u){if(c?.aborted||(l=u,d===o))throw u;let p=Ok(d,s,i);$("[web/retryFetch] retrying after error",{url:e,attempt:d,waitMs:p}),await a(p,c)}}throw l??new Error("retryFetch: exhausted without a result")}var KH,Fk=g(()=>{"use strict";fe();KH=new Set([429,502,503,504])});import{BlockList as XH,isIP as am}from"node:net";import{lookup as zH}from"node:dns/promises";import{Agent as VH}from"undici";function Nk(){let t=v.AFK_WEB_ALLOW_PRIVATE_HOSTS?.trim().toLowerCase();return t==="1"||t==="true"}function ZH(t){return t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t}function im(t){let e=am(t);return e===0?!1:QH.check(t,e===4?"ipv4":"ipv6")}async function Uk(t){return zH(t,{all:!0,verbatim:!0})}async function cm(t,e={}){if(e.allowPrivateHosts??Nk())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=ZH(n.hostname),o=(a,c)=>`refusing to fetch ${c} \u2014 internal/private address ${a} (loopback, link-local, cloud metadata, or RFC1918 space). Set AFK_WEB_ALLOW_PRIVATE_HOSTS=1 to allow private-host access.`;if(am(r)!==0)return im(r)?{allowed:!1,reason:o(r,r)}:{allowed:!0};let s=e.lookupFn??Uk,i;try{i=await s(r)}catch{return{allowed:!0}}for(let a of i)if(im(a.address))return{allowed:!1,reason:o(a.address,`${r} (resolved)`)};return{allowed:!0}}async function Xs(t,e={}){let n=await cm(t,e);if(!n.allowed)throw new At(n.reason)}async function qc(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<=Lk;i++){await Xs(s,o);let a={...n,redirect:"manual",...t===globalThis.fetch&&!(r.allowPrivateHosts??Nk())?{dispatcher:ej}:{}},c=await Dk(t,s,a,r.retry??{});if(!tj.has(c.status))return c;let l=c.headers.get("location");if(l===null||l.trim()==="")return c;let d;try{d=new URL(l,c.url||s).toString()}catch{return c}await c.body?.cancel().catch(()=>{}),s=d}throw new At(`too many redirects (>${Lk}) starting from ${e}`)}var JH,YH,QH,At,ej,Lk,tj,lm=g(()=>{"use strict";F();Fk();JH=[["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]],YH=[["::",96],["64:ff9b::",96],["fc00::",7],["fe80::",10]],QH=(()=>{let t=new XH;for(let[e,n]of JH)t.addSubnet(e,n,"ipv4");for(let[e,n]of YH)t.addSubnet(e,n,"ipv6");return t})(),At=class extends Error{constructor(e){super(e),this.name="EgressBlockedError"}};ej=new VH({connect:{lookup(t,e,n){Uk(t).then(r=>{let o=r.find(i=>im(i.address));if(o!==void 0){n(new At(`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,am(s.address))},r=>n(r,"",0))}}});Lk=20,tj=new Set([301,302,303,307,308])});import{readFileSync as nj}from"node:fs";import{join as rj}from"path";function oj(t){let n=t.replace(/[.+?()[\]{}/\\^$|]/g,"\\$&").replace(/\*/g,"[^.]*");return new RegExp(`^${n}$`,"i")}function $k(t,e){return oj(e).test(t)}function aj(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(sj.has(e))return!0;if(ij.has(e))return!1}return!1}function Bk(t){return t===void 0||t.trim()===""?[]:t.split(",").map(e=>e.trim().toLowerCase()).filter(e=>e.length>0)}function cj(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 Hk(t){let e=t===void 0||t.trim()===""?"default":t.trim();return Ap(e),e}function lj(t){if(t===void 0)return!1;let e=t.trim().toLowerCase();return e==="1"||e==="true"||e==="yes"}function dj(t){try{return nj(t,"utf8")}catch(e){if(e.code==="ENOENT")return;throw e}}function uj(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=Hk(e.defaultProfile)),n}function jk(t){let e=t?.env??v,n=t?.readFileSync??dj,r=t?.surface??e.AGENT_SURFACE,o=aj(e.AFK_BROWSER_HEADLESS,r),s=Bk(e.AFK_BROWSER_ALLOWED_DOMAINS),i=Bk(e.AFK_BROWSER_BLOCKED_DOMAINS),a=lj(e.AFK_BROWSER_DOM_SNAPSHOTS),c=cj(e.AFK_BROWSER_BACKEND),l=Hk(e.AFK_BROWSER_DEFAULT_PROFILE),d={headless:o,allowedDomains:s,blockedDomains:i,domSnapshots:a,backend:c,configPath:null,defaultProfile:l},u=e.AFK_BROWSER_CONFIG,p=u!==void 0&&u.trim()!==""?u.trim():rj(qt(),"browser.json"),f=n(p);if(f===void 0)return d;let m;try{m=JSON.parse(f)}catch(y){throw new Error(`Failed to parse browser config at ${p}: ${String(y)}`)}if(typeof m!="object"||m===null||Array.isArray(m))throw new Error(`Browser config at ${p} must be a JSON object`);let h=uj(d,m);return h.configPath=p,h}function Xc(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($k(n,r))return{allowed:!1,reason:`blocked by AFK_BROWSER_BLOCKED_DOMAINS: ${r}`};return e.allowedDomains.length>0&&!e.allowedDomains.some(o=>$k(n,o))?{allowed:!1,reason:"not in AFK_BROWSER_ALLOWED_DOMAINS"}:{allowed:!0}}var sj,ij,zc=g(()=>{"use strict";F();H();sj=new Set(["daemon","subagent","telegram","afk"]),ij=new Set(["repl","interactive","cli"])});import{existsSync as pj,readFileSync as fj}from"node:fs";import{createRequire as mj}from"node:module";import{dirname as gj,join as hj}from"node:path";function Gk(t){if(typeof t=="string")return t;let e=[],n=t;for(let r=0;r<bj&&n instanceof Error;r++)e.push(n.message),n=n.cause;return e.length>0?e.join(" | "):String(t)}function je(t){let e=Gk(t);return Kk.some(n=>e.includes(n))}function wj(){try{let e=mj(import.meta.url).resolve("playwright/package.json"),n=JSON.parse(fj(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=hj(gj(e),o);return pj(s)?`node ${/\s/.test(s)?`"${s}"`:s} install chromium`:void 0}catch{return}}function zs(){return Wk??=wj()??yj,Wk}function dm(t){return t.includes("install chromium")}function lt(t,e){let n=Gk(t),r=e?.latched===!0?` ${Sj}`:"";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: ${zs()}.${o}${r}`}return`browser tools require the optional \`playwright\` peer dependency. Install via: pnpm add playwright (then ${zs()}). Or pick a different tool.${r}`}function um(t,e,n=!1){if(!je(t))return t;let r=t instanceof Error?t.message:String(t);return new Error(`${r}
213
213
 
214
- ${lt(t,{headless:e,latched:n})}`,{cause:t})}var Kk,yj,bj,Wk,Sj,pm=g(()=>{"use strict";Kk=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],yj="pnpm exec playwright install chromium",bj=4;Sj="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 cr from"node:fs";import Vc from"node:path";import{randomBytes as vj}from"node:crypto";import{chromium as kj}from"playwright";function Aj(){try{return"5.119.0"}catch{}try{let t=Vc.resolve(import.meta.dirname,"../../../package.json"),e=cr.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var _j,Jc,qk=g(()=>{"use strict";pm();H();fe();_j=Aj(),Jc=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=kj.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=um(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),this.launchPromise)}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(c){s=c,await a.abort("blockedbyclient")}});let i=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",i,{once:!0});try{let a=await o.newPage(),c;try{c=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let l=await a.content();if(s!==void 0)throw s;let d=a.url(),u=c!==null?c.status():null;return{html:l,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${_j}`}}loadStorageState(e){let n=_p(e);try{if(!cr.existsSync(n))return;let r=JSON.parse(cr.readFileSync(n,"utf8"));return $("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){$("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=_p(e);if(!cr.existsSync(r))return;let o=await n.storageState(),s=Vc.join(Vc.dirname(r),`.${Vc.basename(r)}.${process.pid}.${vj(4).toString("hex")}.tmp`);cr.writeFileSync(s,JSON.stringify(o),{mode:384}),cr.chmodSync(s,384),cr.renameSync(s,r),$("[browser/vault] saved session",{profile:e,file:r})}catch(r){$("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as Tj}from"crypto";function Xk(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&Ej.test(t.label))}function zk(t){return Tj("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Vk(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Ej,Yc=g(()=>{"use strict";Ej=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Rj}from"node:crypto";function xj(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Ij(t,e,n){return`el_${Rj("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Cj(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Jk(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Qk(t,e){let n=t.role??"",r=t.name??"";Yk.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Qk(s,e)}async function Pj(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},Zk).catch(()=>[])}async function Mj(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let h=s.type;h==="checkbox"?l="checkbox":h==="radio"?l="radio":h==="button"||h==="submit"||h==="reset"?l="button":h==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,m={role:l,name:c,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},Zk).catch(()=>[])}function Oj(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Qc(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Oj(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=Pj(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,h]=await Promise.all([i,a,c,l,d]),y,w=!1;u!==null?(y=[],Qk(u,y)):(o.push("observation skipped accessibility tree (returned null)"),w=!0,y=(await Mj(t)).filter(L=>Yk.has(L.role??"")));let A=new Map;for(let I of p){let L=Jk(I.name),z=A.get(L);(!z||z.bbox.w===0&&I.bbox.w>0)&&A.set(L,I)}let _=y.map(I=>({ax:I,dom:A.get(Jk(I.name??""))})),k=r?_:_.filter(I=>I.dom?I.dom.bbox.w>0||I.dom.bbox.h>0:!0);k.sort((I,L)=>{let z=I.dom?.bbox.y??0,P=L.dom?.bbox.y??0;if(z!==P)return z-P;let B=I.dom?.bbox.x??0,N=L.dom?.bbox.x??0;return B-N}),k.length>200&&o.push("page has 200+ interactive elements; consider scoping");let T=k.slice(0,n).map((I,L)=>{let z=I.ax.role??"generic",P=I.ax.name??"",B=Ij(z,P,L),N=I.dom?.bbox??{x:0,y:0,w:0,h:0},M=I.dom?.type??null,U=null;I.ax.value!==void 0&&I.ax.value!==null&&(U=String(I.ax.value)),I.ax.checked!==void 0&&(U=String(I.ax.checked)),Xk({role:z,kind:M})&&(U="[redacted]");let j={disabled:I.ax.disabled??!1};I.ax.checked!==void 0&&(j.checked=I.ax.checked===!0||I.ax.checked==="mixed"),I.ax.selected!==void 0&&(j.selected=I.ax.selected),I.ax.expanded!==void 0&&(j.expanded=I.ax.expanded);let J;I.dom?.testId?J=`[data-testid="${I.dom.testId}"]`:I.dom?.id&&(J=`#${I.dom.id}`);let te={id:B,role:z,label:xj(P),kind:M,value:U,state:j,bbox:N};return J!==void 0&&(te.selector=J),te}),C="idle";try{let I=await t.evaluate(()=>document.readyState);I==="loading"?C="loading":I==="interactive"?C="navigating":C="idle"}catch{C="navigating"}C!=="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 x=Cj(f),S=`obs_${e.observationCounter.toString(36)}`,E=new Date().toISOString();return{observationId:S,url:m,title:h,textSummary:x,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:C,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:E}}var Yk,Zk,eA=g(()=>{"use strict";Yc();Yk=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Zk="a[href], button, input, select, textarea, [role], [tabindex], label"});async function tA(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function fm(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>tA(t,s)))).filter(o=>o!==null)}async function Dj(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function mm(t,e,n){switch(e.kind){case"element_id":return Fj(t,e,n);case"selector":return Lj(t,e);case"semantic":return Nj(t,e)}}async function Fj(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await fm(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Lj(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 fm(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Nj(t,e){return e.role!==void 0?Uj(t,e.text,e.role):$j(t,e.text,e)}async function Uj(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 fm(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function $j(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Dj(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let h=u[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let p=u.slice(0,5),f=[];for(let h=0;h<p.length;h++){let y=p[h];if(y===void 0)continue;let w=await tA(y.locator,y.index);if(w!==null){let A=`${w.role}:${w.label}:${h}`,_=0;for(let k=0;k<A.length;k++)_=_*31+A.charCodeAt(k)>>>0;f.push({...w,id:`el_${_.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var nA=g(()=>{"use strict"});async function gm(t,e,n,r){let o=t.url();if(o===n)return null;let s=Xc(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 rA=g(()=>{"use strict";zc()});import{randomBytes as Bj}from"crypto";import{mkdir as Hj,stat as jj,writeFile as Wj}from"fs/promises";import{join as hm}from"path";import{gzip as Kj}from"zlib";import{promisify as Gj}from"util";function qj(t){return hm(xt(t),"browser")}function Xj(t){return hm(qj(t),"screenshots")}function zj(){return new Date().toISOString().replace(/[:.]/g,"-")}function Vj(){return Bj(3).toString("hex")}async function ym(t,e,n){if(e.length>oA)throw new Error(`writeScreenshotSidecar: buffer exceeds ${oA} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=Xj(t);await Hj(r,{recursive:!0});let o=`${zj()}-${Vj()}-${n}.png`,s=hm(r,o);await Wj(s,e);let{size:i}=await jj(s);return{path:s,bytes:i}}var pre,oA,sA=g(()=>{"use strict";H();Yc();pre=Gj(Kj);oA=5*1024*1024});var aA={};hp(aA,{PlaywrightProvider:()=>bm});function iA(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var bm,cA=g(()=>{"use strict";qk();eA();nA();zc();rA();sA();bm=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Jc(e)}async open(e){let n=Xc(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(u){a=u}let c=o.url();if(!(a!==null&&(c===""||c==="about:blank"))){let u=await gm(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 Qc(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 Qc(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 mm(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${iA(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":await c.fill(e.value??"");break;case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await d()}catch(y){l=y}else l=h}let u=await gm(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Qc(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal,requestGuard:e.requestGuard})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await mm(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${iA(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await ym(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await ym(n,o,r);return s}catch{return null}}}});var dr={};hp(dr,{__resetBrowserRegistryForTests:()=>eW,browserProviderActive:()=>Qj,closeBrowserProvider:()=>wm,getBrowserProvider:()=>Yj,peekBrowserProvider:()=>Zj});function lA(){Promise.resolve(wm()).then(()=>{process.exit(130)})}function dA(){Promise.resolve(wm()).then(()=>{process.exit(143)})}function uA(){Ut=null}function Jj(){Zc||(process.on("SIGINT",lA),process.on("SIGTERM",dA),process.on("exit",uA),Zc=!0)}function pA(){Zc&&(process.removeListener("SIGINT",lA),process.removeListener("SIGTERM",dA),process.removeListener("exit",uA),Zc=!1)}async function Yj(t){return Ut!==null?Ut:(lr!==null||(lr=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(cA(),aA)),n=jk(t),r=new e(n);return Jj(),Ut=r,lr=null,r})()),lr)}async function wm(){if(Ut===null)return;let t=Ut;Ut=null,lr=null,pA(),await t.shutdown()}function Qj(){return Ut!==null}function Zj(){return Ut}function eW(){Ut=null,lr=null,pA()}var Ut,lr,Zc,ur=g(()=>{"use strict";zc();Ut=null,lr=null,Zc=!1});async function fA(t,e){try{return await Ck(t,e)}catch(n){return $("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function iW(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(ur(),dr));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function mA(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??iW,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await qc(n,t,{headers:sW,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(oW.test(p))throw new Error(`web_scrape markdown mode received binary content (${p.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let f=await u.text();if(rW.test(p)&&!nW.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await fA(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof At||u instanceof Error&&u.message.startsWith("web_scrape markdown mode received binary"))throw u;l=u}if(!(s===null||s.textLength<200)&&s!==null){let u=om({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await Xs(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>Xs(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await Xs(u.finalUrl,o);let p=await fA(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=om({html:u.html,extractedTextLength:p.textLength});return{title:p.title,markdown:p.markdown,finalUrl:u.finalUrl,usedRender:!0,...f!==void 0?{advisory:f}:{}}}}catch(u){if(e.signal.aborted||u instanceof At)throw u;if(s===null){let p=u instanceof Error?u.message:String(u),f=l instanceof Error?l.message:`HTTP ${c??"error"}`,m=new Error(`web_scrape could not retrieve ${t}: fetch failed (${f}) and render failed (${p}).`);throw m.cause=u,m}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${c??"error"}).`)}var nW,rW,oW,sW,gA=g(()=>{"use strict";Pk();sm();lm();fe();nW=/(text\/html|application\/xhtml\+xml)/i,rW=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,oW=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,sW={"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 lW(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(aW,{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),cW),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=ne(d);u&&(c=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let l=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${l}${c}`)}let i;try{i=await s.json()}catch(c){throw new Error(`Exa Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(i.results??[]).slice(0,r).map(c=>({title:(c.title??"").trim()||"(untitled)",url:c.url??"",description:(c.highlights?.[0]??"").trim()})).filter(c=>c.url.length>0)}}}function hA(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?lW({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 yA(t,e){if(e.length===0)return`# Search results for "${t}"
214
+ ${lt(t,{headless:e,latched:n})}`,{cause:t})}var Kk,yj,bj,Wk,Sj,pm=g(()=>{"use strict";Kk=["Cannot find package","ERR_MODULE_NOT_FOUND","Executable doesn't exist"],yj="pnpm exec playwright install chromium",bj=4;Sj="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 cr from"node:fs";import Vc from"node:path";import{randomBytes as vj}from"node:crypto";import{chromium as kj}from"playwright";function Aj(){try{return"5.119.1"}catch{}try{let t=Vc.resolve(import.meta.dirname,"../../../package.json"),e=cr.readFileSync(t,"utf8"),n=JSON.parse(e);return typeof n.version=="string"?n.version:"unknown"}catch{return"unknown"}}var _j,Jc,qk=g(()=>{"use strict";pm();H();fe();_j=Aj(),Jc=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=kj.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=um(e,this.config.headless,!0);throw this.latchLaunchFailure(n),n}),this.launchPromise)}isBrowserActive(){return this.browser!==void 0&&this.browser.isConnected()}async ensureContext(e){let n=this.sessions.get(e);if(n!==void 0)return n.context;let r=await this.ensureBrowser(),o=this.loadStorageState(this.config.defaultProfile),s=await r.newContext({...this.contextOptions(),...o!==void 0?{storageState:o}:{}}),i={context:s,page:void 0,consoleErrors:0,lastHttpStatus:null,openDialog:void 0};return this.sessions.set(e,i),s}async ensurePage(e){let n=this.sessions.get(e);if(n!==void 0&&n.page!==void 0)return n.page;await this.ensureContext(e);let r=this.sessions.get(e);if(r===void 0)throw new Error(`[BrowserLauncher] session entry disappeared for sessionId=${e}`);if(r.page!==void 0)return r.page;let o=await r.context.newPage();return r.page=o,o.on("console",s=>{s.type()==="error"&&(r.consoleErrors+=1)}),o.on("request",s=>{s.isNavigationRequest()&&s.frame()===o.mainFrame()&&(r.lastHttpStatus=null)}),o.on("response",s=>{s.frame()===o.mainFrame()&&s.request().isNavigationRequest()&&(r.lastHttpStatus=s.status())}),o.on("dialog",s=>{r.openDialog=s}),o}getPage(e){return this.sessions.get(e)?.page}async renderHtml(e,n){let o=await(await this.ensureBrowser()).newContext(this.contextOptions()),s;n.requestGuard!==void 0&&await o.route("**/*",async a=>{try{await n.requestGuard(a.request().url()),await a.continue()}catch(c){s=c,await a.abort("blockedbyclient")}});let i=()=>{o.close().catch(()=>{})};if(n.signal?.aborted===!0)throw await o.close().catch(()=>{}),new Error("render aborted");n.signal!==void 0&&n.signal.addEventListener("abort",i,{once:!0});try{let a=await o.newPage(),c;try{c=await a.goto(e,{timeout:n.timeoutMs,waitUntil:n.waitUntil})}catch(p){throw s??p}if(s!==void 0)throw s;let l=await a.content();if(s!==void 0)throw s;let d=a.url(),u=c!==null?c.status():null;return{html:l,finalUrl:d,httpStatus:u}}finally{n.signal!==void 0&&n.signal.removeEventListener("abort",i),await o.close().catch(()=>{})}}getConsoleErrorCount(e){return this.sessions.get(e)?.consoleErrors??0}getLastHttpStatus(e){return this.sessions.get(e)?.lastHttpStatus??null}hasOpenDialog(e){return this.sessions.get(e)?.openDialog!==void 0}async dismissDialog(e,n=!0){let r=this.sessions.get(e);if(r===void 0||r.openDialog===void 0)return;let o=r.openDialog;r.openDialog=void 0,n?await o.accept():await o.dismiss()}async closeSession(e){this.clearLaunchFailure();let n=this.sessions.get(e);n!==void 0&&(this.sessions.delete(e),await this.saveStorageState(this.config.defaultProfile,n.context),n.page!==void 0&&await n.page.close().catch(()=>{}),await n.context.close().catch(()=>{}))}async shutdown(){if(this.clearLaunchFailure(),this.shutdownComplete)return;this.shutdownComplete=!0;let e=[...this.sessions.keys()];if(await Promise.all(e.map(n=>this.closeSession(n))),this.browser!==void 0){let n=this.browser;this.browser=void 0,await n.close().catch(()=>{})}}activeSessions(){return this.sessions.size}contextOptions(){return{viewport:{width:1280,height:800},userAgent:`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 agent-afk/${_j}`}}loadStorageState(e){let n=_p(e);try{if(!cr.existsSync(n))return;let r=JSON.parse(cr.readFileSync(n,"utf8"));return $("[browser/vault] restored session",{profile:e,file:n}),r}catch(r){$("[browser/vault] ignoring unreadable vault",{profile:e,file:n,err:r});return}}async saveStorageState(e,n){try{let r=_p(e);if(!cr.existsSync(r))return;let o=await n.storageState(),s=Vc.join(Vc.dirname(r),`.${Vc.basename(r)}.${process.pid}.${vj(4).toString("hex")}.tmp`);cr.writeFileSync(s,JSON.stringify(o),{mode:384}),cr.chmodSync(s,384),cr.renameSync(s,r),$("[browser/vault] saved session",{profile:e,file:r})}catch(r){$("[browser/vault] save failed",{profile:e,err:r})}}}});import{createHash as Tj}from"crypto";function Xk(t){return!!(t.role==="textbox"&&t.kind==="password"||t.label&&Ej.test(t.label))}function zk(t){return Tj("sha256").update(t,"utf8").digest("hex").slice(0,8)}function Vk(t){let e=t.replace(/\s+/g," ").trim();return e.length<=80?e:e.slice(0,77)+"..."}var Ej,Yc=g(()=>{"use strict";Ej=/password|secret|token|api[_-]?key|otp|2fa/i});import{createHash as Rj}from"node:crypto";function xj(t){return t?t.replace(/\s+/g," ").trim().slice(0,200):""}function Ij(t,e,n){return`el_${Rj("sha256").update(`${t}:${e}:${n}`).digest("hex").slice(0,6)}`}function Cj(t){let e=t.replace(/\s+/g," ").trim(),n=4e3;return e.length<=n?e:e.slice(0,n)+"\u2026[truncated]"}function Jk(t){return t.replace(/\s+/g," ").trim().toLowerCase().slice(0,100)}function Qk(t,e){let n=t.role??"",r=t.name??"";Yk.has(n)&&(n!=="searchbox"&&n!=="spinbutton"||r!=="")&&e.push(t);for(let s of t.children??[])Qk(s,e)}async function Pj(t){return t.evaluate(e=>{let n=Array.from(document.querySelectorAll(e)),r=[];for(let o of n){let s=o.getBoundingClientRect(),i=o;if(s.width===0&&s.height===0){let d=window.getComputedStyle(i);if(d.display==="none"||d.visibility==="hidden")continue}let a=o.tagName.toLowerCase(),c=o.getAttribute("aria-label")??o.getAttribute("placeholder")??(o.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a==="input"?o.type||null:o.getAttribute("type");r.push({name:c,tagName:a,type:l,id:o.id||null,testId:o.getAttribute("data-testid"),bbox:{x:Math.round(s.left),y:Math.round(s.top),w:Math.round(s.width),h:Math.round(s.height)}})}return r},Zk).catch(()=>[])}async function Mj(t){return t.evaluate(e=>{let n={button:"button",a:"link",input:"textbox",textarea:"textbox",select:"combobox"},r=Array.from(document.querySelectorAll(e)),o=[];for(let s of r){let i=s.tagName.toLowerCase(),a=s.getAttribute("role")??"",c=s.getAttribute("aria-label")??s.getAttribute("placeholder")??(s.textContent??"").replace(/\s+/g," ").trim().slice(0,100),l=a||(n[i]??"");if(i==="input"){let h=s.type;h==="checkbox"?l="checkbox":h==="radio"?l="radio":h==="button"||h==="submit"||h==="reset"?l="button":h==="search"?l="searchbox":l="textbox"}if(!l)continue;let d="value"in s?s.value:void 0,u=d!==void 0?String(d):void 0,p=s.disabled??!1,f=i==="input"?s.checked:void 0,m={role:l,name:c,disabled:p};u!==void 0&&(m.value=u),f!==void 0&&(m.checked=f),o.push(m)}return o},Zk).catch(()=>[])}function Oj(t){let n=t.accessibility;return n!==null&&typeof n=="object"?n:null}async function Qc(t,e){let n=e.maxElements??80,r=e.includeHidden??!1,o=[],s=Oj(t),i=s?s.snapshot({interestingOnly:!1}).catch(()=>null):Promise.resolve(null),a=Pj(t),c=t.evaluate(()=>document.body?.innerText??"").catch(()=>""),l=Promise.resolve(t.url()),d=t.title().catch(()=>""),[u,p,f,m,h]=await Promise.all([i,a,c,l,d]),y,w=!1;u!==null?(y=[],Qk(u,y)):(o.push("observation skipped accessibility tree (returned null)"),w=!0,y=(await Mj(t)).filter(L=>Yk.has(L.role??"")));let A=new Map;for(let I of p){let L=Jk(I.name),z=A.get(L);(!z||z.bbox.w===0&&I.bbox.w>0)&&A.set(L,I)}let _=y.map(I=>({ax:I,dom:A.get(Jk(I.name??""))})),k=r?_:_.filter(I=>I.dom?I.dom.bbox.w>0||I.dom.bbox.h>0:!0);k.sort((I,L)=>{let z=I.dom?.bbox.y??0,P=L.dom?.bbox.y??0;if(z!==P)return z-P;let B=I.dom?.bbox.x??0,N=L.dom?.bbox.x??0;return B-N}),k.length>200&&o.push("page has 200+ interactive elements; consider scoping");let T=k.slice(0,n).map((I,L)=>{let z=I.ax.role??"generic",P=I.ax.name??"",B=Ij(z,P,L),N=I.dom?.bbox??{x:0,y:0,w:0,h:0},M=I.dom?.type??null,U=null;I.ax.value!==void 0&&I.ax.value!==null&&(U=String(I.ax.value)),I.ax.checked!==void 0&&(U=String(I.ax.checked)),Xk({role:z,kind:M})&&(U="[redacted]");let j={disabled:I.ax.disabled??!1};I.ax.checked!==void 0&&(j.checked=I.ax.checked===!0||I.ax.checked==="mixed"),I.ax.selected!==void 0&&(j.selected=I.ax.selected),I.ax.expanded!==void 0&&(j.expanded=I.ax.expanded);let J;I.dom?.testId?J=`[data-testid="${I.dom.testId}"]`:I.dom?.id&&(J=`#${I.dom.id}`);let te={id:B,role:z,label:xj(P),kind:M,value:U,state:j,bbox:N};return J!==void 0&&(te.selector=J),te}),C="idle";try{let I=await t.evaluate(()=>document.readyState);I==="loading"?C="loading":I==="interactive"?C="navigating":C="idle"}catch{C="navigating"}C!=="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 x=Cj(f),S=`obs_${e.observationCounter.toString(36)}`,E=new Date().toISOString();return{observationId:S,url:m,title:h,textSummary:x,interactive:T,status:{httpStatus:e.httpStatus??null,loadingState:C,hasDialog:e.hasDialog??!1,consoleErrors:e.consoleErrors??0},warnings:o,screenshotPath:e.screenshotPath??null,capturedAt:E}}var Yk,Zk,eA=g(()=>{"use strict";Yc();Yk=new Set(["button","link","textbox","combobox","checkbox","radio","tab","menuitem","menuitemcheckbox","menuitemradio","switch","option","searchbox","spinbutton"]);Zk="a[href], button, input, select, textarea, [role], [tabindex], label"});async function tA(t,e){try{let n=await t.nth(e).evaluate(i=>{let a=i,c=a.getAttribute("role")??a.tagName.toLowerCase(),l=a.getAttribute("aria-label")??a.getAttribute("placeholder")??(a.innerText!=null?a.innerText.trim().slice(0,200):"")??a.getAttribute("title")??"",d=a.getBoundingClientRect();return{role:c,label:l,x:Math.round(d.x),y:Math.round(d.y),w:Math.round(d.width),h:Math.round(d.height)}}),r=`${n.role}:${n.label}:${e}`,o=0;for(let i=0;i<r.length;i++)o=o*31+r.charCodeAt(i)>>>0;return{id:`el_${o.toString(16).padStart(6,"0").slice(0,6)}`,role:n.role,label:n.label,kind:null,value:null,state:{disabled:!1},bbox:{x:n.x,y:n.y,w:n.w,h:n.h}}}catch{return null}}async function fm(t,e){let n=Math.min(e,5);return(await Promise.all(Array.from({length:n},(o,s)=>tA(t,s)))).filter(o=>o!==null)}async function Dj(t){let e=new Set,n=[];for(let{loc:r,count:o}of t)for(let s=0;s<o;s++){let i;try{i=await r.nth(s).evaluate(a=>{let c=a,l=c.getBoundingClientRect();return`${c.tagName}@${Math.round(l.x)},${Math.round(l.y)}`})}catch{continue}e.has(i)||(e.add(i),n.push({key:i,locator:r,index:s}))}return n}async function mm(t,e,n){switch(e.kind){case"element_id":return Fj(t,e,n);case"selector":return Lj(t,e);case"semantic":return Nj(t,e)}}async function Fj(t,e,n){let r=n.get(e.elementId);if(r===void 0)return{outcome:"not_found",query:e};if(r.selector!==void 0){let c=t.locator(r.selector);if(await c.count()===1)return{outcome:"resolved",locator:c}}let o=t.getByRole(r.role,{name:r.label,exact:!0}),s=await o.count();if(s===0)return{outcome:"not_found",query:e};if(s===1)return{outcome:"resolved",locator:o};let i=await fm(o,s);return{outcome:"ambiguous_target",query:{text:r.label,role:r.role},candidates:i}}async function Lj(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 fm(n,r);return{outcome:"ambiguous_target",query:{text:`[selector: ${e.selector}]`},candidates:o}}async function Nj(t,e){return e.role!==void 0?Uj(t,e.text,e.role):$j(t,e.text,e)}async function Uj(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 fm(r,o);return{outcome:"ambiguous_target",query:{text:e,role:n},candidates:s}}async function $j(t,e,n){let r=t.getByRole("button",{name:e}),o=t.getByRole("link",{name:e}),s=t.getByLabel(e,{exact:!1}),[i,a,c]=await Promise.all([r.count(),o.count(),s.count()]);if(i+a+c===0)return{outcome:"not_found",query:n};let d=[];i>0&&d.push({loc:r,count:i}),a>0&&d.push({loc:o,count:a}),c>0&&d.push({loc:s,count:c});let u=await Dj(d);if(u.length===0)return{outcome:"not_found",query:n};if(u.length===1){let h=u[0];return h===void 0?{outcome:"not_found",query:n}:{outcome:"resolved",locator:h.locator.nth(h.index)}}let p=u.slice(0,5),f=[];for(let h=0;h<p.length;h++){let y=p[h];if(y===void 0)continue;let w=await tA(y.locator,y.index);if(w!==null){let A=`${w.role}:${w.label}:${h}`,_=0;for(let k=0;k<A.length;k++)_=_*31+A.charCodeAt(k)>>>0;f.push({...w,id:`el_${_.toString(16).padStart(6,"0").slice(0,6)}`})}}return{outcome:"ambiguous_target",query:{text:e},candidates:f}}var nA=g(()=>{"use strict"});async function gm(t,e,n,r){let o=t.url();if(o===n)return null;let s=Xc(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 rA=g(()=>{"use strict";zc()});import{randomBytes as Bj}from"crypto";import{mkdir as Hj,stat as jj,writeFile as Wj}from"fs/promises";import{join as hm}from"path";import{gzip as Kj}from"zlib";import{promisify as Gj}from"util";function qj(t){return hm(xt(t),"browser")}function Xj(t){return hm(qj(t),"screenshots")}function zj(){return new Date().toISOString().replace(/[:.]/g,"-")}function Vj(){return Bj(3).toString("hex")}async function ym(t,e,n){if(e.length>oA)throw new Error(`writeScreenshotSidecar: buffer exceeds ${oA} byte cap (received ${e.length} bytes). Refusing to write oversized screenshot.`);let r=Xj(t);await Hj(r,{recursive:!0});let o=`${zj()}-${Vj()}-${n}.png`,s=hm(r,o);await Wj(s,e);let{size:i}=await jj(s);return{path:s,bytes:i}}var pre,oA,sA=g(()=>{"use strict";H();Yc();pre=Gj(Kj);oA=5*1024*1024});var aA={};hp(aA,{PlaywrightProvider:()=>bm});function iA(t){switch(t.kind){case"semantic":return t.role!==void 0?`semantic('${t.text}', role='${t.role}')`:`semantic('${t.text}')`;case"element_id":return`element_id(${t.elementId})`;case"selector":return`selector(${t.selector})`}}var bm,cA=g(()=>{"use strict";qk();eA();nA();zc();rA();sA();bm=class{name="playwright";config;launcher;sessions=new Map;constructor(e){this.config=e,this.launcher=new Jc(e)}async open(e){let n=Xc(e.url,this.config);if(!n.allowed)return{outcome:"blocked_by_policy",url:e.url,reason:n.reason};let{sessionId:r}=e,o=await this.launcher.ensurePage(r),s=this.ensureSessionState(r),i=null,a=null;try{await o.goto(e.url,{timeout:e.timeoutMs??3e4,waitUntil:e.waitFor??"load"})}catch(u){a=u}let c=o.url();if(!(a!==null&&(c===""||c==="about:blank"))){let u=await gm(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 Qc(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 Qc(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 mm(r,e.target,o.knownElements);if(a.outcome==="not_found")throw new Error(`browser_act: target not found: ${iA(e.target)}`);if(a.outcome==="ambiguous_target")return a;let{locator:c}=a,l=null,d=async()=>{switch(e.action){case"click":await c.click({timeout:i});break;case"fill":await c.fill(e.value??"");break;case"press":await c.press(e.value??"");break;case"select":await c.selectOption(e.value??"");break;case"hover":await c.hover({timeout:i});break;case"scroll_to":await c.scrollIntoViewIfNeeded({timeout:i});break;case"wait_for":await c.waitFor({timeout:i,state:"visible"});break}};try{await d()}catch(h){if(h instanceof Error&&/navigation|net::ERR/i.test(h.message))try{await d()}catch(y){l=y}else l=h}let u=await gm(r,this.config,s,()=>this.close({sessionId:n}));if(u!==null)return u;let p=null;(e.screenshot===!0||l!==null)&&(p=await this.captureScreenshot(r,n,"browser_act")),o.observationCounter+=1;let f=await Qc(r,{observationCounter:o.observationCounter,screenshotPath:p,consoleErrors:this.launcher.getConsoleErrorCount(n),httpStatus:this.launcher.getLastHttpStatus(n),hasDialog:this.launcher.hasOpenDialog(n)}),m=`browser_act:${e.action}`;if(this.updateSessionFromObservation(o,f.interactive,f.url,f.title,m),l!==null)throw l;return f}async render(e){return this.launcher.renderHtml(e.url,{timeoutMs:e.timeoutMs??3e4,waitUntil:e.waitFor??"load",signal:e.signal,requestGuard:e.requestGuard})}async screenshot(e){let{sessionId:n}=e,r=this.launcher.getPage(n);if(r===void 0)throw new Error(`browser_screenshot: no page open for session ${n}`);let o=this.ensureSessionState(n),s;if(e.target!==void 0){let d=await mm(r,e.target,o.knownElements);if(d.outcome==="not_found")throw new Error(`browser_screenshot: target not found: ${iA(e.target)}`);if(d.outcome==="ambiguous_target")throw new Error("screenshot target ambiguous; specify element_id or selector");s=await d.locator.screenshot()}else s=await r.screenshot({fullPage:e.fullPage??!1});let{path:i,bytes:a}=await ym(n,s,"browser_screenshot"),c=0,l=0;if(e.fullPage===!0)try{let d=await r.evaluate(()=>({w:document.documentElement.scrollWidth,h:document.documentElement.scrollHeight}));c=d.w,l=d.h}catch{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}else{let d=r.viewportSize();c=d?.width??0,l=d?.height??0}return{path:i,bytes:a,width:c,height:l,dataBase64:s.toString("base64"),mediaType:"image/png"}}async extract(e){throw new Error("browser_extract not implemented in Phase 1")}async close(e){await this.launcher.closeSession(e.sessionId),this.sessions.delete(e.sessionId)}describe(e){let n=this.sessions.get(e);if(n===void 0)return null;let r=this.launcher.getPage(e);return{active:r!==void 0,url:n.currentUrl,title:n.currentTitle,lastAction:n.lastAction,lastActionAt:n.lastActionAt,openTabs:r!==void 0?1:0}}async shutdown(){this.sessions.clear(),await this.launcher.shutdown()}ensureSessionState(e){let n=this.sessions.get(e);if(n!==void 0)return n;let r={observationCounter:0,knownElements:new Map,lastAction:null,lastActionAt:null,currentUrl:null,currentTitle:null};return this.sessions.set(e,r),r}updateSessionFromObservation(e,n,r,o,s){e.knownElements=new Map(n.map(i=>[i.id,i])),e.currentUrl=r,e.currentTitle=o,e.lastAction=s,e.lastActionAt=new Date().toISOString()}async captureScreenshot(e,n,r){try{let o=await e.screenshot({fullPage:!1}),{path:s}=await ym(n,o,r);return s}catch{return null}}}});var dr={};hp(dr,{__resetBrowserRegistryForTests:()=>eW,browserProviderActive:()=>Qj,closeBrowserProvider:()=>wm,getBrowserProvider:()=>Yj,peekBrowserProvider:()=>Zj});function lA(){Promise.resolve(wm()).then(()=>{process.exit(130)})}function dA(){Promise.resolve(wm()).then(()=>{process.exit(143)})}function uA(){Ut=null}function Jj(){Zc||(process.on("SIGINT",lA),process.on("SIGTERM",dA),process.on("exit",uA),Zc=!0)}function pA(){Zc&&(process.removeListener("SIGINT",lA),process.removeListener("SIGTERM",dA),process.removeListener("exit",uA),Zc=!1)}async function Yj(t){return Ut!==null?Ut:(lr!==null||(lr=(async()=>{let{PlaywrightProvider:e}=await Promise.resolve().then(()=>(cA(),aA)),n=jk(t),r=new e(n);return Jj(),Ut=r,lr=null,r})()),lr)}async function wm(){if(Ut===null)return;let t=Ut;Ut=null,lr=null,pA(),await t.shutdown()}function Qj(){return Ut!==null}function Zj(){return Ut}function eW(){Ut=null,lr=null,pA()}var Ut,lr,Zc,ur=g(()=>{"use strict";zc();Ut=null,lr=null,Zc=!1});async function fA(t,e){try{return await Ck(t,e)}catch(n){return $("[web/scrape] extraction failed",{url:e,err:n}),{title:"",markdown:"",textLength:0,usedFallback:!0}}}async function iW(t,e){let{getBrowserProvider:n}=await Promise.resolve().then(()=>(ur(),dr));return(await n()).render({url:t,timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:e.requestGuard})}async function mA(t,e){let n=e.fetchFn??globalThis.fetch,r=e.renderFn??iW,o=e.lookupFn!==void 0?{lookupFn:e.lookupFn}:{},s=null,i="",a=t,c=null,l=null;try{let u=await qc(n,t,{headers:sW,signal:e.signal},o);c=u.status,a=u.url||t;let p=u.headers.get("content-type")??"";if(u.ok){if(oW.test(p))throw new Error(`web_scrape markdown mode received binary content (${p.split(";")[0]}). Use mode: "raw" to fetch the bytes, or a different tool.`);let f=await u.text();if(rW.test(p)&&!nW.test(p))return{title:"",markdown:f.trim(),finalUrl:a,usedRender:!1};if(i=f,s=await fA(f,a),e.signal.aborted)throw e.signal.reason??new Error("aborted")}}catch(u){if(e.signal.aborted||u instanceof At||u instanceof Error&&u.message.startsWith("web_scrape markdown mode received binary"))throw u;l=u}if(!(s===null||s.textLength<200)&&s!==null){let u=om({html:i,extractedTextLength:s.textLength});return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1,...u!==void 0?{advisory:u}:{}}}try{await Xs(t,o);let u=await r(t,{timeoutMs:e.timeoutMs,signal:e.signal,requestGuard:f=>Xs(f,o)});u.finalUrl!==t&&/^https?:\/\//i.test(u.finalUrl)&&await Xs(u.finalUrl,o);let p=await fA(u.html,u.finalUrl);if(e.signal.aborted)throw e.signal.reason??new Error("aborted");if(s===null||p.textLength>=s.textLength){let f=om({html:u.html,extractedTextLength:p.textLength});return{title:p.title,markdown:p.markdown,finalUrl:u.finalUrl,usedRender:!0,...f!==void 0?{advisory:f}:{}}}}catch(u){if(e.signal.aborted||u instanceof At)throw u;if(s===null){let p=u instanceof Error?u.message:String(u),f=l instanceof Error?l.message:`HTTP ${c??"error"}`,m=new Error(`web_scrape could not retrieve ${t}: fetch failed (${f}) and render failed (${p}).`);throw m.cause=u,m}}if(s!==null)return{title:s.title,markdown:s.markdown,finalUrl:a,usedRender:!1};throw new Error(`web_scrape could not retrieve any content from ${t} (HTTP ${c??"error"}).`)}var nW,rW,oW,sW,gA=g(()=>{"use strict";Pk();sm();lm();fe();nW=/(text\/html|application\/xhtml\+xml)/i,rW=/(application\/json|\/xml|\+xml|text\/|application\/(java|ecma)script|csv)/i,oW=/(image\/|audio\/|video\/|application\/pdf|application\/zip|application\/octet-stream|font\/)/i,sW={"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 lW(t){let e=t.fetchFn??globalThis.fetch;return{name:"exa",async search(n,{limit:r,signal:o}){let s=await e(aW,{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),cW),contents:{highlights:{numSentences:3,highlightsPerUrl:1}}}),signal:o});if(!s.ok){let c="";try{let d=await s.text(),u=ne(d);u&&(c=`: ${u.length>200?u.slice(0,200)+"\u2026":u}`)}catch{}let l=s.statusText?` ${s.statusText}`:"";throw new Error(`Exa Search HTTP ${s.status}${l}${c}`)}let i;try{i=await s.json()}catch(c){throw new Error(`Exa Search response was not JSON: ${c instanceof Error?c.message:String(c)}`)}return(i.results??[]).slice(0,r).map(c=>({title:(c.title??"").trim()||"(untitled)",url:c.url??"",description:(c.highlights?.[0]??"").trim()})).filter(c=>c.url.length>0)}}}function hA(t){return t.exaApiKey!==void 0&&t.exaApiKey.trim()!==""?lW({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 yA(t,e){if(e.length===0)return`# Search results for "${t}"
215
215
 
216
216
  (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(`
217
217
  `).trimEnd()}var aW,cW,bA=g(()=>{"use strict";kt();aW="https://api.exa.ai/search",cW=10});function el(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 pr=g(()=>{"use strict";pm()});function gW(t){if(!t||typeof t!="object")return{error:"Invalid input: expected an object"};let e=t,n=e.mode??"markdown";if(n!=="markdown"&&n!=="raw"&&n!=="search")return{error:`Invalid input: mode must be one of "markdown", "raw", "search" (got ${JSON.stringify(n)})`};let r=n,o,s;if(r==="search"){if(typeof e.query!="string"||e.query.length===0)return{error:'Invalid input: search mode requires a non-empty "query" string'};s=e.query}else{if(typeof e.url!="string"||e.url.length===0)return{error:`Invalid input: ${r} mode requires a non-empty "url" string`};let c;try{c=new URL(e.url)}catch{return{error:`Invalid input: "${e.url}" is not a valid absolute URL`}}if(c.protocol!=="http:"&&c.protocol!=="https:")return{error:`Invalid input: protocol "${c.protocol}" not supported (http/https only)`};o=c.toString()}let i=dW;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,uW)}let a=pW;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,fW)}return{mode:r,url:o,query:s,timeoutMs:i,maxBytes:a}}function Sm(t,e){return Buffer.byteLength(t,"utf8")<=e?{content:t,truncated:!1}:{content:Jt(t,e),truncated:!0}}function hW(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=gW(o);if("error"in i)return{content:i.error,isError:!0};if(s.aborted){let u=s.reason;return{content:`web_scrape aborted: ${u instanceof Error?u.message:String(u??"aborted")}`,isError:!0}}let a=new AbortController,c=()=>{a.abort(s.reason)},l,d=()=>{let u=a.signal.reason;return u instanceof Error?u.message:String(u??"aborted")};try{if(s.addEventListener("abort",c,{once:!0}),l=setTimeout(()=>{a.abort(new Error(`web_scrape timeout after ${i.timeoutMs}ms`))},i.timeoutMs),i.url!==void 0){let p=await cm(i.url,r);if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(!p.allowed)return{content:`web_scrape blocked: ${p.reason}`,isError:!0}}if(i.mode==="raw"){let p;try{let h={method:"GET",headers:{"User-Agent":"agent-afk/web_scrape",Accept:"*/*"},signal:a.signal};p=await qc(e,i.url,h,r)}catch(h){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:h instanceof At?{content:`web_scrape blocked: ${h.message}`,isError:!0}:{content:`web_scrape network error: ${h instanceof Error?h.message:String(h)}`,isError:!0}}if(!p.ok)return{content:`web_scrape HTTP ${p.status} ${p.statusText||""}`.trimEnd()+` for ${i.url}`,isError:!0};let f;try{f=await p.text()}catch(h){return{content:`web_scrape read error: ${h instanceof Error?h.message:String(h)}`,isError:!0}}let m=Sm(f,i.maxBytes);return{content:m.content,...m.truncated?{truncated:!0}:{}}}if(i.mode==="markdown")try{let p=await mA(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=Sm(Mk(p.markdown,p.advisory),i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){if(a.signal.aborted)return{content:`web_scrape aborted: ${d()}`,isError:!0};if(p instanceof At)return{content:`web_scrape blocked: ${p.message}`,isError:!0};let f=p instanceof Error?p.message:String(p),m=je(p)&&!dm(f)?` (the render fallback needs the optional Playwright browser \u2014 run \`${zs()}\`)`:"";return{content:`web_scrape markdown error: ${f}${m}`,isError:!0}}let u=hA({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:mW,timeoutMs:i.timeoutMs,signal:a.signal}),f=Sm(yA(i.query,p),i.maxBytes);return{content:f.content,...f.truncated?{truncated:!0}:{}}}catch(p){return a.signal.aborted?{content:`web_scrape aborted: ${d()}`,isError:!0}:{content:`web_scrape search error (${u.name}): ${p instanceof Error?p.message:String(p)}`,isError:!0}}}finally{l!==void 0&&clearTimeout(l),s.removeEventListener("abort",c)}}}var dW,uW,pW,fW,mW,wA,SA=g(()=>{"use strict";gA();bA();lm();hn();sm();pr();dW=3e4,uW=12e4,pW=1e5,fW=1e6,mW=10;wA=hW()});import{existsSync as kA,mkdirSync as yW,readFileSync as bW,renameSync as wW,unlinkSync as SW,writeFileSync as vW}from"node:fs";import{dirname as vA,join as kW}from"node:path";import{randomBytes as AW}from"node:crypto";function Zr(t){let e=t??Sp();if(!kA(e))return[];try{let n=bW(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 tl(t,e){let n=e??Sp();yW(vA(n),{recursive:!0});let r=kW(vA(n),`.schedules.json.${process.pid}.${AW(4).toString("hex")}.tmp`),o=JSON.stringify(t,null,2);try{vW(r,o,"utf-8"),wW(r,n)}catch(s){try{kA(r)&&SW(r)}catch{}throw s}}function AA(t,e){let n=Zr(e),r=n.map(c=>c.id),o=_W(t.name),s=TW(o,r),i=new Date().toISOString(),a={...t,notifyOn:t.notifyOn??"failure",id:s,createdAt:i,updatedAt:i};return n.push(a),tl(n,e),a}function _A(t,e){let n=Zr(e),r=n.length,o=n.filter(s=>s.id!==t);return o.length===r?!1:(tl(o,e),!0)}function TA(t,e){return Zr(e).find(n=>n.id===t)}function _W(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}function TW(t,e){if(!e.includes(t))return t;let n=2;for(;e.includes(`${t}-${n}`);)n+=1;return`${t}-${n}`}var EA=g(()=>{"use strict";H()});import{existsSync as EW,readFileSync as RW}from"node:fs";import{join as xW}from"node:path";async function Vs(t,e,n){let r;try{let o=xW(Db("default"),"port");if(!EW(o))return{synced:!1,detail:"daemon-not-detected (no port file)"};let s=RW(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 vm,RA=g(()=>{"use strict";H();vm="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 IW}from"node:fs";import{readFile as CW}from"node:fs/promises";var xA,IA,CA,PA,MA=g(()=>{"use strict";EA();H();RA();xA=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=AA({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 Vs("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 Vs("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:vm}})}},IA=async(t,e)=>{let n=Zr();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})))}},CA=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=Sa();if(!IW(s))return{content:JSON.stringify([])};let i;try{let l=await CW(s);i=(l.length>1048576?l.subarray(l.length-1048576):l).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.119.0",
3
+ "version": "5.119.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",