browser-devtools-mcp 0.6.0 → 0.6.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{isToolEnabled,platformInfo}from"../core-MEE5B4UB.js";import{AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,AWS_PROFILE,AWS_REGION,DAEMON_PORT,DAEMON_SESSION_IDLE_CHECK_SECONDS,DAEMON_SESSION_IDLE_SECONDS,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,OTEL_ENABLE,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_TYPE,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION}from"../core-X3FD2EZG.js";import{Command,Option}from"commander";import{ZodFirstPartyTypeKind}from"zod";function _unwrapZodType(zodType){let current=zodType,isOptional=!1,defaultValue;for(;;){let typeName=current._def.typeName;if(typeName===ZodFirstPartyTypeKind.ZodOptional)isOptional=!0,current=current._def.innerType;else if(typeName===ZodFirstPartyTypeKind.ZodDefault)isOptional=!0,defaultValue=current._def.defaultValue(),current=current._def.innerType;else if(typeName===ZodFirstPartyTypeKind.ZodNullable)isOptional=!0,current=current._def.innerType;else break}return{innerType:current,isOptional,defaultValue}}function _getDescription(zodType){return zodType._def.description}function _toCamelCase(str){return str.replace(/[-_]([a-z])/g,(_,letter)=>letter.toUpperCase())}function _toKebabCase(str){return str.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function schemaFieldToCliFlag(fieldName){return _toKebabCase(fieldName)}function _createOptionsForField(name,zodType){let{innerType,isOptional,defaultValue}=_unwrapZodType(zodType),description=_getDescription(zodType)||`The ${name} value`,flagName=_toKebabCase(name),typeName=innerType._def.typeName;if(typeName===ZodFirstPartyTypeKind.ZodBoolean){if(defaultValue===!0){let positive=new Option(`--${flagName}`,description);positive.default(!0);let negative=new Option(`--no-${flagName}`,`Disable: ${description}`);return[positive,negative]}let boolOpt=new Option(`--${flagName}`,description);return defaultValue===!1&&boolOpt.default(!1),!isOptional&&defaultValue===void 0&&boolOpt.makeOptionMandatory(!0),[boolOpt]}let option;switch(typeName){case ZodFirstPartyTypeKind.ZodString:option=new Option(`--${flagName} <string>`,description);break;case ZodFirstPartyTypeKind.ZodNumber:option=new Option(`--${flagName} <number>`,description),option.argParser(value=>{let n=Number(value);if(!Number.isFinite(n))throw new Error(`Invalid number: ${value}`);return n});break;case ZodFirstPartyTypeKind.ZodEnum:let enumValues=innerType._def.values;option=new Option(`--${flagName} <choice>`,description).choices(enumValues);break;case ZodFirstPartyTypeKind.ZodArray:option=new Option(`--${flagName} <value...>`,description);break;case ZodFirstPartyTypeKind.ZodObject:case ZodFirstPartyTypeKind.ZodRecord:option=new Option(`--${flagName} <json>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{throw new Error(`Invalid JSON: ${value}`)}});break;case ZodFirstPartyTypeKind.ZodAny:case ZodFirstPartyTypeKind.ZodUnknown:option=new Option(`--${flagName} <value>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{return value}});break;case ZodFirstPartyTypeKind.ZodLiteral:let literalValue=innerType._def.value;if(typeof literalValue=="boolean"){if(literalValue===!0){let positive=new Option(`--${flagName}`,description);positive.default(!0);let negative=new Option(`--no-${flagName}`,`Disable: ${description}`);return[positive,negative]}let litFalse=new Option(`--${flagName}`,description);return litFalse.default(!1),[litFalse]}option=new Option(`--${flagName} <value>`,description),option.default(literalValue);break;case ZodFirstPartyTypeKind.ZodUnion:let unionOptions=innerType._def.options;if(unionOptions.every(opt=>opt._def.typeName===ZodFirstPartyTypeKind.ZodLiteral)){let choices=unionOptions.map(opt=>String(opt._def.value));option=new Option(`--${flagName} <choice>`,description).choices(choices)}else option=new Option(`--${flagName} <value>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{return value}});break;default:option=new Option(`--${flagName} <value>`,description);break}return defaultValue!==void 0&&option.default(defaultValue),!isOptional&&defaultValue===void 0&&option.makeOptionMandatory(!0),[option]}function _generateOptionsFromSchema(schema,_toolName){let options=[];for(let[name,zodType]of Object.entries(schema))name!=="_metadata"&&options.push(..._createOptionsForField(name,zodType));return options}function _parseOptionsToToolInput(options){let result={};for(let[key,value]of Object.entries(options)){let camelKey=_toCamelCase(key);value!==void 0&&(result[camelKey]=value)}return result}function _parseToolName(toolName){let underscoreIndex=toolName.indexOf("_");return underscoreIndex===-1?{domain:"default",commandName:toolName}:{domain:toolName.substring(0,underscoreIndex),commandName:toolName.substring(underscoreIndex+1)}}function registerToolCommands(program,tools2,handler){let domainCommands=new Map;for(let tool of tools2){let{domain,commandName}=_parseToolName(tool.name()),domainCommand=domainCommands.get(domain);domainCommand||(domainCommand=new Command(domain).description(`${domain.charAt(0).toUpperCase()+domain.slice(1)} commands`),domainCommands.set(domain,domainCommand),program.addCommand(domainCommand));let toolCommand=new Command(commandName).description(tool.description().trim()),options=_generateOptionsFromSchema(tool.inputSchema(),tool.name());for(let option of options)toolCommand.addOption(option);toolCommand.action(async opts=>{let toolInput=_parseOptionsToToolInput(opts),globalOptions=program.opts();await handler(tool.name(),toolInput,globalOptions)}),domainCommand.addCommand(toolCommand)}}import{spawn,execSync}from"node:child_process";import{existsSync,readFileSync}from"node:fs";import{createRequire}from"node:module";import*as path from"node:path";import*as readline from"node:readline";import{fileURLToPath}from"node:url";import{Command as Command2,Option as Option2}from"commander";var require2=createRequire(import.meta.url),__filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);function _resolveDaemonServerScriptPath(){let dir=__dirname;for(let i=0;i<10;i++){let candidate=path.join(dir,"daemon-server.js");if(existsSync(candidate))return candidate;let parent=path.dirname(dir);if(parent===dir)break;dir=parent}throw new Error("Could not find daemon-server.js (rebuild with npm run build or reinstall the package).")}var cliProvider=platformInfo.cliInfo.cliProvider,tools=cliProvider.tools.filter(isToolEnabled),DEFAULT_TIMEOUT=3e4,verboseEnabled=!1,quietEnabled=!1;function _debug(message,data){if(verboseEnabled){let timestamp=new Date().toISOString();data!==void 0?console.error(`[${timestamp}] [DEBUG] ${message}`,data):console.error(`[${timestamp}] [DEBUG] ${message}`)}}function _output(message){quietEnabled||console.log(message)}function _error(message){console.error(message)}async function _isDaemonRunning(port){_debug(`Checking if daemon is running on port ${port}`);try{let response=await fetch(`http://localhost:${port}/health`,{method:"GET",signal:AbortSignal.timeout(3e3)});if(response.ok){let isRunning=(await response.json()).status==="ok";return _debug(`Daemon health check result: ${isRunning?"running":"not running"}`),isRunning}return _debug(`Daemon health check failed: HTTP ${response.status}`),!1}catch(err){return _debug(`Daemon health check error: ${err.message}`),!1}}function _buildDaemonEnv(opts){return cliProvider.buildEnv(opts)}function _startDaemonDetached(opts){let daemonServerPath=_resolveDaemonServerScriptPath(),env=_buildDaemonEnv(opts);_debug(`Starting daemon server from: ${daemonServerPath}`),_debug(`Daemon port: ${opts.port}`);let child=spawn(process.execPath,[daemonServerPath,"--port",String(opts.port)],{detached:!0,stdio:"ignore",env});child.unref(),_debug(`Daemon process spawned with PID: ${child.pid}`),_output(`Started daemon server as detached process (PID: ${child.pid})`)}async function _ensureDaemonRunning(opts){if(await _isDaemonRunning(opts.port))_debug("Daemon is already running");else{_output(`Daemon server is not running on port ${opts.port}, starting...`),_startDaemonDetached(opts);let maxRetries=10,retryDelay=500;_debug(`Waiting for daemon to be ready (max ${maxRetries} retries, ${retryDelay}ms delay)`);for(let i=0;i<maxRetries;i++)if(await new Promise(resolve2=>setTimeout(resolve2,retryDelay)),_debug(`Retry ${i+1}/${maxRetries}: checking daemon status...`),await _isDaemonRunning(opts.port)){_debug("Daemon is now ready"),_output("Daemon server is ready");return}throw new Error(`Daemon server failed to start within ${maxRetries*retryDelay/1e3} seconds`)}}async function _stopDaemon(port,timeout){try{return(await fetch(`http://localhost:${port}/shutdown`,{method:"POST",signal:AbortSignal.timeout(timeout)})).ok}catch{return!1}}async function _callTool(port,toolName,toolInput,sessionId,timeout){let headers={"Content-Type":"application/json"};sessionId&&(headers["session-id"]=sessionId);let request={toolName,toolInput};_debug(`Calling tool: ${toolName}`),_debug("Tool input:",toolInput),_debug(`Session ID: ${sessionId||"(default)"}`),_debug(`Timeout: ${timeout||"none"}`);let startTime=Date.now(),response=await fetch(`http://localhost:${port}/call`,{method:"POST",headers,body:JSON.stringify(request),signal:timeout?AbortSignal.timeout(timeout):void 0}),duration=Date.now()-startTime;if(_debug(`Tool call completed in ${duration}ms, status: ${response.status}`),!response.ok){let errorBody=await response.json().catch(()=>({}));_debug("Tool call error:",errorBody);let message=errorBody?.toolError?.message||errorBody?.error?.message||`HTTP ${response.status}: ${response.statusText}`;throw new Error(message)}let result=await response.json();return _debug("Tool call result:",result.toolError?{error:result.toolError}:{success:!0}),result}async function _deleteSession(port,sessionId,timeout){try{return(await fetch(`http://localhost:${port}/session`,{method:"DELETE",headers:{"session-id":sessionId},signal:AbortSignal.timeout(timeout)})).ok}catch{return!1}}async function _getDaemonInfo(port,timeout){try{let response=await fetch(`http://localhost:${port}/info`,{method:"GET",signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}async function _listSessions(port,timeout){try{let response=await fetch(`http://localhost:${port}/sessions`,{method:"GET",signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}async function _getSessionInfo(port,sessionId,timeout){try{let response=await fetch(`http://localhost:${port}/session`,{method:"GET",headers:{"session-id":sessionId},signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}function _formatUptime(seconds){let days=Math.floor(seconds/86400),hours=Math.floor(seconds%86400/3600),minutes=Math.floor(seconds%3600/60),secs=seconds%60,parts=[];return days>0&&parts.push(`${days}d`),hours>0&&parts.push(`${hours}h`),minutes>0&&parts.push(`${minutes}m`),parts.push(`${secs}s`),parts.join(" ")}function _formatTimestamp(timestamp){return new Date(timestamp).toISOString()}function _getZodTypeName(schema){let typeName=schema._def.typeName;return typeName==="ZodOptional"||typeName==="ZodNullable"||typeName==="ZodDefault"?_getZodTypeName(schema._def.innerType):typeName==="ZodArray"?`${_getZodTypeName(schema._def.type)}[]`:typeName==="ZodEnum"?schema._def.values.join(" | "):typeName==="ZodLiteral"?JSON.stringify(schema._def.value):typeName==="ZodUnion"?schema._def.options.map(opt=>_getZodTypeName(opt)).join(" | "):{ZodString:"string",ZodNumber:"number",ZodBoolean:"boolean",ZodObject:"object",ZodRecord:"Record<string, any>",ZodAny:"any"}[typeName]||typeName.replace("Zod","").toLowerCase()}function _getZodDescription(schema){if(schema._def.description)return schema._def.description;if(schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable"||schema._def.typeName==="ZodDefault")return _getZodDescription(schema._def.innerType)}function _isZodOptional(schema){let typeName=schema._def.typeName;return typeName==="ZodOptional"||typeName==="ZodNullable"}function _hasZodDefault(schema){return schema._def.typeName==="ZodDefault"?!0:schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable"?_hasZodDefault(schema._def.innerType):!1}function _getZodDefault(schema){if(schema._def.typeName==="ZodDefault")return schema._def.defaultValue();if(schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable")return _getZodDefault(schema._def.innerType)}function _formatOutput(output,indent=0){let prefix=" ".repeat(indent);if(output==null)return`${prefix}(empty)`;if(typeof output=="string")return output.split(`
2
+ import{isToolEnabled,platformInfo}from"../core-YPBKINC4.js";import{AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,AWS_PROFILE,AWS_REGION,DAEMON_PORT,DAEMON_SESSION_IDLE_CHECK_SECONDS,DAEMON_SESSION_IDLE_SECONDS,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,OTEL_ENABLE,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_TYPE,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION}from"../core-S5JHUB3Z.js";import{Command,Option}from"commander";import{ZodFirstPartyTypeKind}from"zod";function _unwrapZodType(zodType){let current=zodType,isOptional=!1,defaultValue;for(;;){let typeName=current._def.typeName;if(typeName===ZodFirstPartyTypeKind.ZodOptional)isOptional=!0,current=current._def.innerType;else if(typeName===ZodFirstPartyTypeKind.ZodDefault)isOptional=!0,defaultValue=current._def.defaultValue(),current=current._def.innerType;else if(typeName===ZodFirstPartyTypeKind.ZodNullable)isOptional=!0,current=current._def.innerType;else break}return{innerType:current,isOptional,defaultValue}}function _getDescription(zodType){return zodType._def.description}function _toCamelCase(str){return str.replace(/[-_]([a-z])/g,(_,letter)=>letter.toUpperCase())}function _toKebabCase(str){return str.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function schemaFieldToCliFlag(fieldName){return _toKebabCase(fieldName)}function _createOptionsForField(name,zodType){let{innerType,isOptional,defaultValue}=_unwrapZodType(zodType),description=_getDescription(zodType)||`The ${name} value`,flagName=_toKebabCase(name),typeName=innerType._def.typeName;if(typeName===ZodFirstPartyTypeKind.ZodBoolean){if(defaultValue===!0){let positive=new Option(`--${flagName}`,description);positive.default(!0);let negative=new Option(`--no-${flagName}`,`Disable: ${description}`);return[positive,negative]}let boolOpt=new Option(`--${flagName}`,description);return defaultValue===!1&&boolOpt.default(!1),!isOptional&&defaultValue===void 0&&boolOpt.makeOptionMandatory(!0),[boolOpt]}let option;switch(typeName){case ZodFirstPartyTypeKind.ZodString:option=new Option(`--${flagName} <string>`,description);break;case ZodFirstPartyTypeKind.ZodNumber:option=new Option(`--${flagName} <number>`,description),option.argParser(value=>{let n=Number(value);if(!Number.isFinite(n))throw new Error(`Invalid number: ${value}`);return n});break;case ZodFirstPartyTypeKind.ZodEnum:let enumValues=innerType._def.values;option=new Option(`--${flagName} <choice>`,description).choices(enumValues);break;case ZodFirstPartyTypeKind.ZodArray:option=new Option(`--${flagName} <value...>`,description);break;case ZodFirstPartyTypeKind.ZodObject:case ZodFirstPartyTypeKind.ZodRecord:option=new Option(`--${flagName} <json>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{throw new Error(`Invalid JSON: ${value}`)}});break;case ZodFirstPartyTypeKind.ZodAny:case ZodFirstPartyTypeKind.ZodUnknown:option=new Option(`--${flagName} <value>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{return value}});break;case ZodFirstPartyTypeKind.ZodLiteral:let literalValue=innerType._def.value;if(typeof literalValue=="boolean"){if(literalValue===!0){let positive=new Option(`--${flagName}`,description);positive.default(!0);let negative=new Option(`--no-${flagName}`,`Disable: ${description}`);return[positive,negative]}let litFalse=new Option(`--${flagName}`,description);return litFalse.default(!1),[litFalse]}option=new Option(`--${flagName} <value>`,description),option.default(literalValue);break;case ZodFirstPartyTypeKind.ZodUnion:let unionOptions=innerType._def.options;if(unionOptions.every(opt=>opt._def.typeName===ZodFirstPartyTypeKind.ZodLiteral)){let choices=unionOptions.map(opt=>String(opt._def.value));option=new Option(`--${flagName} <choice>`,description).choices(choices)}else option=new Option(`--${flagName} <value>`,description),option.argParser(value=>{try{return JSON.parse(value)}catch{return value}});break;default:option=new Option(`--${flagName} <value>`,description);break}return defaultValue!==void 0&&option.default(defaultValue),!isOptional&&defaultValue===void 0&&option.makeOptionMandatory(!0),[option]}function _generateOptionsFromSchema(schema,_toolName){let options=[];for(let[name,zodType]of Object.entries(schema))name!=="_metadata"&&options.push(..._createOptionsForField(name,zodType));return options}function _parseOptionsToToolInput(options){let result={};for(let[key,value]of Object.entries(options)){let camelKey=_toCamelCase(key);value!==void 0&&(result[camelKey]=value)}return result}function _parseToolName(toolName){let underscoreIndex=toolName.indexOf("_");return underscoreIndex===-1?{domain:"default",commandName:toolName}:{domain:toolName.substring(0,underscoreIndex),commandName:toolName.substring(underscoreIndex+1)}}function registerToolCommands(program,tools2,handler){let domainCommands=new Map;for(let tool of tools2){let{domain,commandName}=_parseToolName(tool.name()),domainCommand=domainCommands.get(domain);domainCommand||(domainCommand=new Command(domain).description(`${domain.charAt(0).toUpperCase()+domain.slice(1)} commands`),domainCommands.set(domain,domainCommand),program.addCommand(domainCommand));let toolCommand=new Command(commandName).description(tool.description().trim()),options=_generateOptionsFromSchema(tool.inputSchema(),tool.name());for(let option of options)toolCommand.addOption(option);toolCommand.action(async opts=>{let toolInput=_parseOptionsToToolInput(opts),globalOptions=program.opts();await handler(tool.name(),toolInput,globalOptions)}),domainCommand.addCommand(toolCommand)}}import{spawn,execSync}from"node:child_process";import{existsSync,readFileSync}from"node:fs";import{createRequire}from"node:module";import*as path from"node:path";import*as readline from"node:readline";import{fileURLToPath}from"node:url";import{Command as Command2,Option as Option2}from"commander";var require2=createRequire(import.meta.url),__filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);function _resolveDaemonServerScriptPath(){let dir=__dirname;for(let i=0;i<10;i++){let candidate=path.join(dir,"daemon-server.js");if(existsSync(candidate))return candidate;let parent=path.dirname(dir);if(parent===dir)break;dir=parent}throw new Error("Could not find daemon-server.js (rebuild with npm run build or reinstall the package).")}var cliProvider=platformInfo.cliInfo.cliProvider,tools=cliProvider.tools.filter(isToolEnabled),DEFAULT_TIMEOUT=3e4,verboseEnabled=!1,quietEnabled=!1;function _debug(message,data){if(verboseEnabled){let timestamp=new Date().toISOString();data!==void 0?console.error(`[${timestamp}] [DEBUG] ${message}`,data):console.error(`[${timestamp}] [DEBUG] ${message}`)}}function _output(message){quietEnabled||console.log(message)}function _error(message){console.error(message)}async function _isDaemonRunning(port){_debug(`Checking if daemon is running on port ${port}`);try{let response=await fetch(`http://localhost:${port}/health`,{method:"GET",signal:AbortSignal.timeout(3e3)});if(response.ok){let isRunning=(await response.json()).status==="ok";return _debug(`Daemon health check result: ${isRunning?"running":"not running"}`),isRunning}return _debug(`Daemon health check failed: HTTP ${response.status}`),!1}catch(err){return _debug(`Daemon health check error: ${err.message}`),!1}}function _buildDaemonEnv(opts){return cliProvider.buildEnv(opts)}function _startDaemonDetached(opts){let daemonServerPath=_resolveDaemonServerScriptPath(),env=_buildDaemonEnv(opts);_debug(`Starting daemon server from: ${daemonServerPath}`),_debug(`Daemon port: ${opts.port}`);let child=spawn(process.execPath,[daemonServerPath,"--port",String(opts.port)],{detached:!0,stdio:"ignore",env});child.unref(),_debug(`Daemon process spawned with PID: ${child.pid}`),_output(`Started daemon server as detached process (PID: ${child.pid})`)}async function _ensureDaemonRunning(opts){if(await _isDaemonRunning(opts.port))_debug("Daemon is already running");else{_output(`Daemon server is not running on port ${opts.port}, starting...`),_startDaemonDetached(opts);let maxRetries=10,retryDelay=500;_debug(`Waiting for daemon to be ready (max ${maxRetries} retries, ${retryDelay}ms delay)`);for(let i=0;i<maxRetries;i++)if(await new Promise(resolve2=>setTimeout(resolve2,retryDelay)),_debug(`Retry ${i+1}/${maxRetries}: checking daemon status...`),await _isDaemonRunning(opts.port)){_debug("Daemon is now ready"),_output("Daemon server is ready");return}throw new Error(`Daemon server failed to start within ${maxRetries*retryDelay/1e3} seconds`)}}async function _stopDaemon(port,timeout){try{return(await fetch(`http://localhost:${port}/shutdown`,{method:"POST",signal:AbortSignal.timeout(timeout)})).ok}catch{return!1}}async function _callTool(port,toolName,toolInput,sessionId,timeout){let headers={"Content-Type":"application/json"};sessionId&&(headers["session-id"]=sessionId);let request={toolName,toolInput};_debug(`Calling tool: ${toolName}`),_debug("Tool input:",toolInput),_debug(`Session ID: ${sessionId||"(default)"}`),_debug(`Timeout: ${timeout||"none"}`);let startTime=Date.now(),response=await fetch(`http://localhost:${port}/call`,{method:"POST",headers,body:JSON.stringify(request),signal:timeout?AbortSignal.timeout(timeout):void 0}),duration=Date.now()-startTime;if(_debug(`Tool call completed in ${duration}ms, status: ${response.status}`),!response.ok){let errorBody=await response.json().catch(()=>({}));_debug("Tool call error:",errorBody);let message=errorBody?.toolError?.message||errorBody?.error?.message||`HTTP ${response.status}: ${response.statusText}`;throw new Error(message)}let result=await response.json();return _debug("Tool call result:",result.toolError?{error:result.toolError}:{success:!0}),result}async function _deleteSession(port,sessionId,timeout){try{return(await fetch(`http://localhost:${port}/session`,{method:"DELETE",headers:{"session-id":sessionId},signal:AbortSignal.timeout(timeout)})).ok}catch{return!1}}async function _getDaemonInfo(port,timeout){try{let response=await fetch(`http://localhost:${port}/info`,{method:"GET",signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}async function _listSessions(port,timeout){try{let response=await fetch(`http://localhost:${port}/sessions`,{method:"GET",signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}async function _getSessionInfo(port,sessionId,timeout){try{let response=await fetch(`http://localhost:${port}/session`,{method:"GET",headers:{"session-id":sessionId},signal:AbortSignal.timeout(timeout)});return response.ok?await response.json():null}catch{return null}}function _formatUptime(seconds){let days=Math.floor(seconds/86400),hours=Math.floor(seconds%86400/3600),minutes=Math.floor(seconds%3600/60),secs=seconds%60,parts=[];return days>0&&parts.push(`${days}d`),hours>0&&parts.push(`${hours}h`),minutes>0&&parts.push(`${minutes}m`),parts.push(`${secs}s`),parts.join(" ")}function _formatTimestamp(timestamp){return new Date(timestamp).toISOString()}function _getZodTypeName(schema){let typeName=schema._def.typeName;return typeName==="ZodOptional"||typeName==="ZodNullable"||typeName==="ZodDefault"?_getZodTypeName(schema._def.innerType):typeName==="ZodArray"?`${_getZodTypeName(schema._def.type)}[]`:typeName==="ZodEnum"?schema._def.values.join(" | "):typeName==="ZodLiteral"?JSON.stringify(schema._def.value):typeName==="ZodUnion"?schema._def.options.map(opt=>_getZodTypeName(opt)).join(" | "):{ZodString:"string",ZodNumber:"number",ZodBoolean:"boolean",ZodObject:"object",ZodRecord:"Record<string, any>",ZodAny:"any"}[typeName]||typeName.replace("Zod","").toLowerCase()}function _getZodDescription(schema){if(schema._def.description)return schema._def.description;if(schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable"||schema._def.typeName==="ZodDefault")return _getZodDescription(schema._def.innerType)}function _isZodOptional(schema){let typeName=schema._def.typeName;return typeName==="ZodOptional"||typeName==="ZodNullable"}function _hasZodDefault(schema){return schema._def.typeName==="ZodDefault"?!0:schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable"?_hasZodDefault(schema._def.innerType):!1}function _getZodDefault(schema){if(schema._def.typeName==="ZodDefault")return schema._def.defaultValue();if(schema._def.typeName==="ZodOptional"||schema._def.typeName==="ZodNullable")return _getZodDefault(schema._def.innerType)}function _formatOutput(output,indent=0){let prefix=" ".repeat(indent);if(output==null)return`${prefix}(empty)`;if(typeof output=="string")return output.split(`
3
3
  `).map(line=>`${prefix}${line}`).join(`
4
4
  `);if(typeof output=="number"||typeof output=="boolean")return`${prefix}${output}`;if(Array.isArray(output))return output.length===0?`${prefix}[]`:output.map(item=>_formatOutput(item,indent)).join(`
5
5
  `);if(typeof output=="object"){let lines=[];for(let[key,value]of Object.entries(output))value!==void 0&&(typeof value=="object"&&value!==null&&!Array.isArray(value)?(lines.push(`${prefix}${key}:`),lines.push(_formatOutput(value,indent+1))):Array.isArray(value)?(lines.push(`${prefix}${key}:`),lines.push(_formatOutput(value,indent+1))):lines.push(`${prefix}${key}: ${value}`));return lines.join(`
@@ -1 +1 @@
1
- import{DEFAULT_NODE_DEBUG_CONFIG,ProbeKind,addWatchExpression,clearProbes,clearSnapshots,clearSnapshotsByProbe,clearWatchExpressions,createProbe,detachDebugging,disableDebugging,enableDebugging,evaluateInNode,getConsoleMessages,getExceptionBreakpoint,getOriginalSources,getScripts,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStore,getStoreKey,hasSourceMaps,isDebuggingEnabled,listProbes,listStoreKeys,listWatchExpressions,loadSourceMaps,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint}from"./core-X3FD2EZG.js";export{DEFAULT_NODE_DEBUG_CONFIG,ProbeKind,addWatchExpression,clearProbes,clearSnapshots,clearSnapshotsByProbe,clearWatchExpressions,createProbe,detachDebugging,disableDebugging,enableDebugging,evaluateInNode,getConsoleMessages,getExceptionBreakpoint,getOriginalSources,getScripts,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStore,getStoreKey,hasSourceMaps,isDebuggingEnabled,listProbes,listStoreKeys,listWatchExpressions,loadSourceMaps,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint};
1
+ import{DEFAULT_NODE_DEBUG_CONFIG,ProbeKind,addWatchExpression,clearProbes,clearSnapshots,clearSnapshotsByProbe,clearWatchExpressions,createProbe,detachDebugging,disableDebugging,enableDebugging,evaluateInNode,getConsoleMessages,getExceptionBreakpoint,getOriginalSources,getScripts,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStore,getStoreKey,hasSourceMaps,isDebuggingEnabled,listProbes,listStoreKeys,listWatchExpressions,loadSourceMaps,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint}from"./core-S5JHUB3Z.js";export{DEFAULT_NODE_DEBUG_CONFIG,ProbeKind,addWatchExpression,clearProbes,clearSnapshots,clearSnapshotsByProbe,clearWatchExpressions,createProbe,detachDebugging,disableDebugging,enableDebugging,evaluateInNode,getConsoleMessages,getExceptionBreakpoint,getOriginalSources,getScripts,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStore,getStoreKey,hasSourceMaps,isDebuggingEnabled,listProbes,listStoreKeys,listWatchExpressions,loadSourceMaps,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint};
@@ -1,4 +1,4 @@
1
- import{augmentToolInputSchema}from"./core-MEE5B4UB.js";import{TOOL_INPUT_METADATA_ENABLE,denormalizeToolName}from"./core-X3FD2EZG.js";import*as fs2 from"node:fs";import{fileURLToPath}from"node:url";import{PostHog}from"posthog-node";import*as crypto from"node:crypto";import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";var CONFIG_DIR=path.join(os.homedir(),".browser-devtools-mcp"),CONFIG_FILE=path.join(CONFIG_DIR,"config.json");function readConfig(){let existing={};if(fs.existsSync(CONFIG_FILE))try{let raw=fs.readFileSync(CONFIG_FILE,"utf-8");existing=JSON.parse(raw)}catch{}let dirty=!1;return existing.anonymousId||(existing.anonymousId=crypto.randomUUID(),dirty=!0),existing.telemetryEnabled===void 0&&(existing.telemetryEnabled=!0,dirty=!0),existing.telemetryNoticeShown===void 0&&(existing.telemetryNoticeShown=!1,dirty=!0),dirty&&_writeConfig(existing),existing}function updateConfig(updates){let current=readConfig();_writeConfig({...current,...updates})}function _writeConfig(config){try{fs.existsSync(CONFIG_DIR)||fs.mkdirSync(CONFIG_DIR,{recursive:!0}),fs.writeFileSync(CONFIG_FILE,JSON.stringify(config,null,2),"utf-8")}catch{}}var POSTHOG_API_KEY=process.env.POSTHOG_API_KEY??"phc_ekFEnQ9ipk0F1BbO0KCkaD8OaYPa4bIqqUoxsCfeFsy",POSTHOG_HOST="https://us.posthog.com",_initialized=!1,_client=null,_anonymousId="",_enabled=!1,_source="mcp-unknown",_mcpTransport,_browserDevtoolsVersion=(()=>{let candidates=[new URL("../package.json",import.meta.url),new URL("../../package.json",import.meta.url)];for(let candidate of candidates)try{let raw=fs2.readFileSync(fileURLToPath(candidate),"utf-8"),ver=JSON.parse(raw).version;if(ver)return ver}catch{}return"unknown"})();function _detectMCPClientSource(clientInfo){if(process.env.CURSOR_TRACE_ID)return"mcp-cursor";if(process.env.CLAUDE_DESKTOP)return"mcp-claude";if(clientInfo?.name){let name=clientInfo.name.toLowerCase();if(name.includes("cursor"))return"mcp-cursor";if(name.includes("claude")||name.includes("local-agent-mode"))return"mcp-claude";if(name.includes("codex")||name.includes("openai"))return"mcp-codex"}return"mcp-unknown"}function _detectCLISource(){return"cli"}function _buildBaseProperties(){return{source:_source,browser_devtools_version:_browserDevtoolsVersion,node_version:process.version,os_platform:process.platform,os_arch:process.arch,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:new Date().toUTCString()}}function init(opts={}){if(!_initialized){_initialized=!0;try{let config=readConfig();_anonymousId=config.anonymousId;let telemetryEnabled=process.env.TELEMETRY_ENABLE!=="false";if(_enabled=config.telemetryEnabled&&!opts.disabled&&telemetryEnabled,opts.source==="cli")_source=_detectCLISource();else if(opts.source==="mcp"){let detectedSource=_detectMCPClientSource(opts.clientInfo);_source=detectedSource==="cli"?"mcp-unknown":detectedSource}else _source=_detectMCPClientSource(opts.clientInfo);if(!config.telemetryNoticeShown&&telemetryEnabled&&(process.stderr.write(`
1
+ import{augmentToolInputSchema}from"./core-YPBKINC4.js";import{TOOL_INPUT_METADATA_ENABLE,denormalizeToolName}from"./core-S5JHUB3Z.js";import*as fs2 from"node:fs";import{fileURLToPath}from"node:url";import{PostHog}from"posthog-node";import*as crypto from"node:crypto";import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";var CONFIG_DIR=path.join(os.homedir(),".browser-devtools-mcp"),CONFIG_FILE=path.join(CONFIG_DIR,"config.json");function readConfig(){let existing={};if(fs.existsSync(CONFIG_FILE))try{let raw=fs.readFileSync(CONFIG_FILE,"utf-8");existing=JSON.parse(raw)}catch{}let dirty=!1;return existing.anonymousId||(existing.anonymousId=crypto.randomUUID(),dirty=!0),existing.telemetryEnabled===void 0&&(existing.telemetryEnabled=!0,dirty=!0),existing.telemetryNoticeShown===void 0&&(existing.telemetryNoticeShown=!1,dirty=!0),dirty&&_writeConfig(existing),existing}function updateConfig(updates){let current=readConfig();_writeConfig({...current,...updates})}function _writeConfig(config){try{fs.existsSync(CONFIG_DIR)||fs.mkdirSync(CONFIG_DIR,{recursive:!0}),fs.writeFileSync(CONFIG_FILE,JSON.stringify(config,null,2),"utf-8")}catch{}}var POSTHOG_API_KEY=process.env.POSTHOG_API_KEY??"phc_ekFEnQ9ipk0F1BbO0KCkaD8OaYPa4bIqqUoxsCfeFsy",POSTHOG_HOST="https://us.posthog.com",_initialized=!1,_client=null,_anonymousId="",_enabled=!1,_source="mcp-unknown",_mcpTransport,_browserDevtoolsVersion=(()=>{let candidates=[new URL("../package.json",import.meta.url),new URL("../../package.json",import.meta.url)];for(let candidate of candidates)try{let raw=fs2.readFileSync(fileURLToPath(candidate),"utf-8"),ver=JSON.parse(raw).version;if(ver)return ver}catch{}return"unknown"})();function _detectMCPClientSource(clientInfo){if(process.env.CURSOR_TRACE_ID)return"mcp-cursor";if(process.env.CLAUDE_DESKTOP)return"mcp-claude";if(clientInfo?.name){let name=clientInfo.name.toLowerCase();if(name.includes("cursor"))return"mcp-cursor";if(name.includes("claude")||name.includes("local-agent-mode"))return"mcp-claude";if(name.includes("codex")||name.includes("openai"))return"mcp-codex"}return"mcp-unknown"}function _detectCLISource(){return"cli"}function _buildBaseProperties(){return{source:_source,browser_devtools_version:_browserDevtoolsVersion,node_version:process.version,os_platform:process.platform,os_arch:process.arch,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timestamp:new Date().toUTCString()}}function init(opts={}){if(!_initialized){_initialized=!0;try{let config=readConfig();_anonymousId=config.anonymousId;let telemetryEnabled=process.env.TELEMETRY_ENABLE!=="false";if(_enabled=config.telemetryEnabled&&!opts.disabled&&telemetryEnabled,opts.source==="cli")_source=_detectCLISource();else if(opts.source==="mcp"){let detectedSource=_detectMCPClientSource(opts.clientInfo);_source=detectedSource==="cli"?"mcp-unknown":detectedSource}else _source=_detectMCPClientSource(opts.clientInfo);if(!config.telemetryNoticeShown&&telemetryEnabled&&(process.stderr.write(`
2
2
  Telemetry is enabled by default to help improve this tool.
3
3
  Run with --no-telemetry for CLI and set TELEMETRY_ENABLE=false for MCP Servers to disable.
4
4
 
@@ -0,0 +1,18 @@
1
+ var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res)=>function(){return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);import fs from"node:fs";import path2 from"node:path";function initFileLogging(filePath){let dir=path2.dirname(filePath);fs.existsSync(dir)||fs.mkdirSync(dir,{recursive:!0}),_logStream=fs.createWriteStream(filePath,{flags:"a"})}function _timeAsString(){return`${new Date().toLocaleTimeString(void 0,{hour:"numeric",minute:"numeric",second:"numeric",hour12:!1,timeZoneName:"short"})}`}function _normalizeArgs(...args){return isDebugEnabled()?args:(args||[]).map(arg=>arg?arg instanceof Error||arg.name&&arg.message&&arg.stack?`${arg.name}: ${arg.message}`:arg:"")}function _writeToFile(level,args){if(!_logStream)return;let message=_normalizeArgs(...args).map(a=>typeof a=="string"?a:String(a)).join(" ");_logStream.write(`${BANNER_TEXT} ${_timeAsString()} | ${level} - ${message}
2
+ `)}function enable(){enabled=!0}function disable(){enabled=!1}function isDebugEnabled(){return debugEnabled}function debug(...args){_writeToFile("DEBUG",args),enabled&&isDebugEnabled()&&console.debug(BANNER_TEXT,_timeAsString(),"|","DEBUG","-",..._normalizeArgs(...args))}function info(...args){_writeToFile("INFO ",args),enabled&&console.info(BANNER_TEXT,_timeAsString(),"|","INFO ","-",..._normalizeArgs(...args))}function warn(...args){_writeToFile("WARN ",args),enabled&&console.warn(BANNER_TEXT,_timeAsString(),"|","WARN ","-",..._normalizeArgs(...args))}function error(...args){_writeToFile("ERROR",args),enabled&&console.error(BANNER_TEXT,_timeAsString(),"|","ERROR","-",..._normalizeArgs(...args))}function _getCircularReplacer(){let seen=new WeakSet;return(key,value)=>{if(typeof value=="object"&&value!==null){if(seen.has(value))return;seen.add(value)}return value}}function toJson(obj){return JSON.stringify(obj,_getCircularReplacer())}var BANNER_TEXT,enabled,debugEnabled,_logStream,init_logger=__esm({"src/logger.ts"(){"use strict";BANNER_TEXT="[BROWSER-DEVTOOLS]",enabled=!0,debugEnabled=process.env.DEBUG_ENABLE==="true",_logStream=null}});import path from"node:path";function _envStr(name){let v=process.env[name];if(!v)return;let t=v.trim();return t||void 0}function _envInt(name){let v=_envStr(name);if(!v)return;let n=Number(v);if(Number.isFinite(n))return Math.floor(n)}function _envBool(name){let v=_envStr(name);if(v)return v==="true"}function _parseKeyValueFromEnv(envValue){let headers={};if(!envValue)return headers;let pairs=envValue.split(",");for(let pair of pairs){let trimmed=pair.trim();if(!trimmed)continue;let eqIndex=trimmed.indexOf("=");if(eqIndex===-1)continue;let key=trimmed.slice(0,eqIndex).trim(),value=trimmed.slice(eqIndex+1).trim();!key||!value||(headers[key]=value)}return headers}var PORT=_envInt("PORT")??3e3,TOOL_OUTPUT_SCHEMA_DISABLE=_envBool("TOOL_OUTPUT_SCHEMA_DISABLE")??!1,TOOL_NAME_PREFIX=_envStr("TOOL_NAME_PREFIX"),TOOL_INPUT_METADATA_ENABLE=_envBool("TOOL_INPUT_METADATA_ENABLE")??!1,AVAILABLE_TOOL_DOMAINS=(()=>{let v=_envStr("AVAILABLE_TOOL_DOMAINS");if(!v)return;let set=new Set(v.split(",").map(s=>s.trim().toLowerCase()).filter(Boolean));return set.size>0?set:void 0})(),_PLATFORM_RAW=_envStr("PLATFORM"),PLATFORM=_PLATFORM_RAW==="browser"||_PLATFORM_RAW==="node"?_PLATFORM_RAW:"browser",SESSION_IDLE_SECONDS=_envInt("SESSION_IDLE_SECONDS")??300,SESSION_IDLE_CHECK_SECONDS=_envInt("SESSION_IDLE_CHECK_SECONDS")??30,SESSION_CLOSE_ON_SOCKET_CLOSE=_envBool("SESSION_CLOSE_ON_SOCKET_CLOSE")??!1,BROWSER_HEADLESS_ENABLE=_envBool("BROWSER_HEADLESS_ENABLE")??!0,BROWSER_PERSISTENT_ENABLE=_envBool("BROWSER_PERSISTENT_ENABLE")??!1,BROWSER_PERSISTENT_USER_DATA_DIR=_envStr("BROWSER_PERSISTENT_USER_DATA_DIR")??path.join(process.cwd(),"browser-devtools-mcp"),BROWSER_USE_INSTALLED_ON_SYSTEM=_envBool("BROWSER_USE_INSTALLED_ON_SYSTEM")??!1,BROWSER_EXECUTABLE_PATH=_envStr("BROWSER_EXECUTABLE_PATH"),BROWSER_LOCALE=_envStr("BROWSER_LOCALE"),BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE=_envInt("BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE")??1e3,BROWSER_HTTP_REQUESTS_BUFFER_SIZE=_envInt("BROWSER_HTTP_REQUESTS_BUFFER_SIZE")??1e3,BROWSER_SERVER_INSTRUCTIONS_ENABLE=_envBool("BROWSER_SERVER_INSTRUCTIONS_ENABLE")??!0,BROWSER_POLICY_UI_DEBUGGING_ENABLE=_envBool("BROWSER_POLICY_UI_DEBUGGING_ENABLE")??!1,_BROWSER_CDP_ENDPOINT=_envStr("BROWSER_CDP_ENDPOINT_URL"),_BROWSER_CDP_ENABLE=_envBool("BROWSER_CDP_ENABLE")??!1,BROWSER_CDP_CONNECT_URL=_BROWSER_CDP_ENDPOINT??(_BROWSER_CDP_ENABLE?"http://127.0.0.1:9222":void 0),BROWSER_CDP_ENDPOINT_EXPLICIT=!!_BROWSER_CDP_ENDPOINT,BROWSER_CDP_OPEN_INSPECT=_envStr("BROWSER_CDP_OPEN_INSPECT")!=="false",NODE_SERVER_INSTRUCTIONS_ENABLE=_envBool("NODE_SERVER_INSTRUCTIONS_ENABLE")??!0,NODE_POLICY_DEBUGGING_ENABLE=_envBool("NODE_POLICY_DEBUGGING_ENABLE")??!1,NODE_CONSOLE_MESSAGES_BUFFER_SIZE=_envInt("NODE_CONSOLE_MESSAGES_BUFFER_SIZE")??1e3,NODE_INSPECTOR_HOST=_envStr("NODE_INSPECTOR_HOST"),COLLECTOR_URL=_envStr("COLLECTOR_URL"),COLLECTOR_API_KEY=_envStr("COLLECTOR_API_KEY"),OTEL_ENABLE=_envBool("OTEL_ENABLE")??!1,OTEL_SERVICE_NAME=_envStr("OTEL_SERVICE_NAME")??"frontend",OTEL_SERVICE_VERSION=_envStr("OTEL_SERVICE_VERSION"),OTEL_ASSETS_DIR=_envStr("OTEL_ASSETS_DIR"),OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS=_envStr("OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS")?.split(",")??["click"],OTEL_EXPORTER_TYPE=_envStr("OTEL_EXPORTER_TYPE")??"none",OTEL_EXPORTER_HTTP_URL=_envStr("OTEL_EXPORTER_HTTP_URL"),OTEL_EXPORTER_HTTP_HEADERS=_parseKeyValueFromEnv(_envStr("OTEL_EXPORTER_HTTP_HEADERS")),AWS_REGION=_envStr("AWS_REGION"),AWS_PROFILE=_envStr("AWS_PROFILE"),AMAZON_BEDROCK_ENABLE=_envBool("AMAZON_BEDROCK_ENABLE")??!1,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID=_envStr("AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID"),AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID=_envStr("AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID"),AMAZON_BEDROCK_VISION_MODEL_ID=_envStr("AMAZON_BEDROCK_VISION_MODEL_ID"),FIGMA_ACCESS_TOKEN=_envStr("FIGMA_ACCESS_TOKEN")??"",FIGMA_API_BASE_URL=_envStr("FIGMA_API_BASE_URL")??"https://api.figma.com/v1",WORKING_DIR=_envStr("WORKING_DIR")??process.cwd(),LOG_FILE=_envStr("LOG_FILE"),SEARCH_STRATEGY=_envStr("SEARCH_STRATEGY")??"SIMPLE",SCENARIO_SEARCH_STRATEGY=_envStr("SCENARIO_SEARCH_STRATEGY"),DAEMON_PORT=_envInt("DAEMON_PORT")??2020,DAEMON_SESSION_IDLE_SECONDS=_envInt("DAEMON_SESSION_IDLE_SECONDS")??300,DAEMON_SESSION_IDLE_CHECK_SECONDS=_envInt("DAEMON_SESSION_IDLE_CHECK_SECONDS")??30;function normalizeToolName(toolName){return TOOL_NAME_PREFIX?`${TOOL_NAME_PREFIX}${toolName}`:toolName}function stripMCPToolNamePrefixIfPresent(mcpToolName){return TOOL_NAME_PREFIX&&mcpToolName.startsWith(TOOL_NAME_PREFIX)?mcpToolName.slice(TOOL_NAME_PREFIX.length):mcpToolName}function denormalizeToolName(toolName){let n=toolName,colonIdx=n.indexOf(":");return colonIdx>=0&&(n=n.substring(colonIdx+1)),n.length>2&&n.startsWith("<")&&n.endsWith(">")&&(n=n.slice(1,-1)),stripMCPToolNamePrefixIfPresent(n)}function applyNormalizedToolNamesInText(text,canonicalToolNames){if(canonicalToolNames.length===0)return text;let known=new Set(canonicalToolNames);return text.replace(/<([a-zA-Z0-9_-]+)>/g,(full,inner)=>known.has(inner)?normalizeToolName(inner):full)}var ConsoleMessageLevelName=(ConsoleMessageLevelName2=>(ConsoleMessageLevelName2.ALL="all",ConsoleMessageLevelName2.DEBUG="debug",ConsoleMessageLevelName2.INFO="info",ConsoleMessageLevelName2.WARNING="warning",ConsoleMessageLevelName2.ERROR="error",ConsoleMessageLevelName2))(ConsoleMessageLevelName||{});var ConsoleMessageLevel={all:{code:-1},debug:{code:0},info:{code:1},warning:{code:2},error:{code:3}};init_logger();var BASE64_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",BASE64_MAP=new Map;for(let i=0;i<BASE64_CHARS.length;i++)BASE64_MAP.set(BASE64_CHARS[i],i);function _decodeVLQ(encoded){let values=[],shift=0,value=0;for(let char of encoded){let digit=BASE64_MAP.get(char);if(digit===void 0)throw new Error(`Invalid base64 character: ${char}`);let hasContinuation=(digit&32)!==0;if(value+=(digit&31)<<shift,hasContinuation)shift+=5;else{let isNegative=(value&1)!==0;value=value>>1,isNegative&&(value=-value),values.push(value),value=0,shift=0}}return values}function _parseMappings(mappings,sources){let entries=[],lines=mappings.split(";"),generatedLine=0,sourceIndex=0,originalLine=0,originalColumn=0,nameIndex=0;for(let line of lines){let generatedColumn=0,segments=line.split(",");for(let segment of segments){if(!segment)continue;let values=_decodeVLQ(segment);if(values.length===0)continue;generatedColumn+=values[0];let entry={generatedLine,generatedColumn};values.length>=4&&(sourceIndex+=values[1],originalLine+=values[2],originalColumn+=values[3],entry.source=sources[sourceIndex],entry.originalLine=originalLine,entry.originalColumn=originalColumn,values.length>=5&&(nameIndex+=values[4])),entries.push(entry)}generatedLine++}return entries}var SourceMapResolver=class{scripts=new Map;scriptsByUrl=new Map;sourceToScripts=new Map;fetchCache=new Map;page;customFetcher;constructor(source){typeof source=="function"?this.customFetcher=source:this.page=source}registerScript(script){let resolved={scriptId:script.scriptId,url:script.url,sourceMapURL:script.sourceMapURL,originalSources:[]};if(this.scripts.set(script.scriptId,resolved),script.url){let existing=this.scriptsByUrl.get(script.url)||[];existing.push(resolved),this.scriptsByUrl.set(script.url,existing)}}getScriptUrl(scriptId){return this.scripts.get(scriptId)?.url}async loadSourceMap(scriptId){let script=this.scripts.get(scriptId);if(!script||!script.sourceMapURL)return!1;if(script.sourceMap)return!0;try{let sourceMap=await this._fetchSourceMap(script.sourceMapURL,script.url);if(!sourceMap)return!1;script.sourceMap=sourceMap,script.mappings=_parseMappings(sourceMap.mappings,sourceMap.sources),script.originalSources=sourceMap.sources.map(s=>this._resolveSourcePath(s,sourceMap.sourceRoot,script.url));for(let source of script.originalSources){let existing=this.sourceToScripts.get(source)||[];existing.push(script),this.sourceToScripts.set(source,existing)}return!0}catch(error2){return debug(`Failed to load source map for ${script.url}:`,error2),!1}}async loadAllSourceMaps(){let loaded=0;for(let scriptId of this.scripts.keys())await this.loadSourceMap(scriptId)&&loaded++;return loaded}originalToGenerated(originalSource,line,column=0){let normalizedSource=this._normalizeSourcePath(originalSource),scripts=this._findScriptsForSource(normalizedSource);if(scripts.length!==0)for(let script of scripts){if(!script.mappings)continue;let sourceIndex=script.originalSources.findIndex(s=>this._normalizeSourcePath(s)===normalizedSource||s.endsWith(normalizedSource)||normalizedSource.endsWith(s));if(sourceIndex===-1)continue;let bestMatch,bestDistance=1/0;for(let mapping of script.mappings)if(mapping.source===script.sourceMap?.sources[sourceIndex]&&mapping.originalLine!==void 0&&mapping.originalLine===line){let colDist=mapping.originalColumn!==void 0?Math.abs(mapping.originalColumn-column):0;colDist<bestDistance&&(bestDistance=colDist,bestMatch=mapping)}if(bestMatch)return{scriptId:script.scriptId,location:{line:bestMatch.generatedLine,column:bestMatch.generatedColumn}}}}async resolveLocationByUrl(url,line,column=1){let line0=Math.max(0,line-1),column0=Math.max(0,column-1),candidates=this.scriptsByUrl.get(url)||[];if(candidates.length===0)for(let script of this.scripts.values())(script.url===url||script.url.endsWith(url)||url.endsWith(script.url))&&candidates.push(script);for(let script of candidates){if(!await this.loadSourceMap(script.scriptId)||!script.mappings)continue;let resolved=this.generatedToOriginal(script.scriptId,line0,column0);if(resolved)return resolved}return null}generatedToOriginal(scriptId,line,column=0){let script=this.scripts.get(scriptId);if(!script?.mappings)return;let bestMatch,bestDistance=1/0;for(let mapping of script.mappings){if(mapping.generatedLine!==line||mapping.source===void 0)continue;let colDist=Math.abs(mapping.generatedColumn-column);colDist<bestDistance&&(bestDistance=colDist,bestMatch=mapping)}if(bestMatch&&bestMatch.source!==void 0&&bestMatch.originalLine!==void 0){let sourceIndex=script.sourceMap?.sources.indexOf(bestMatch.source);return{source:sourceIndex!==void 0&&sourceIndex>=0?script.originalSources[sourceIndex]:bestMatch.source,line:bestMatch.originalLine,column:bestMatch.originalColumn??0,name:bestMatch.name}}}getOriginalSources(){return Array.from(this.sourceToScripts.keys())}findScriptsForSource(sourcePattern){let normalized=this._normalizeSourcePath(sourcePattern);return this._findScriptsForSource(normalized)}hasSourceMaps(){for(let script of this.scripts.values())if(script.sourceMap)return!0;return!1}clear(){this.scripts.clear(),this.scriptsByUrl.clear(),this.sourceToScripts.clear(),this.fetchCache.clear()}_findScriptsForSource(normalizedSource){let exact=this.sourceToScripts.get(normalizedSource);if(exact&&exact.length>0)return exact;let results=[];for(let[source,scripts]of this.sourceToScripts.entries()){let normalizedKey=this._normalizeSourcePath(source);(normalizedKey.endsWith(normalizedSource)||normalizedSource.endsWith(normalizedKey))&&results.push(...scripts)}return results}_normalizeSourcePath(path4){let normalized=path4.replace(/^webpack:\/\/[^/]*\//,"").replace(/^file:\/\//,"").replace(/^\.*\//,"");for(normalized=normalized.replace(/\\/g,"/");normalized.startsWith("./");)normalized=normalized.slice(2);return normalized}_resolveSourcePath(source,sourceRoot,scriptUrl){return source.startsWith("webpack://")||source.startsWith("http://")||source.startsWith("https://")||sourceRoot&&(source=sourceRoot.replace(/\/$/,"")+"/"+source),source}async _fetchSourceMap(sourceMapURL,scriptUrl){if(sourceMapURL.startsWith("data:"))return this._parseDataUrl(sourceMapURL);let absoluteUrl=this._resolveUrl(sourceMapURL,scriptUrl);if(this.fetchCache.has(absoluteUrl))return this.fetchCache.get(absoluteUrl)||null;try{let sourceMap=null;if(this.customFetcher){let content=await this.customFetcher(absoluteUrl,scriptUrl);content&&(sourceMap=JSON.parse(content))}else this.page&&(sourceMap=await this._fetchViaBrowser(absoluteUrl));return this.fetchCache.set(absoluteUrl,sourceMap),sourceMap}catch(error2){return debug(`Failed to fetch source map from ${absoluteUrl}:`,error2),this.fetchCache.set(absoluteUrl,null),null}}_parseDataUrl(dataUrl){try{let match=dataUrl.match(/^data:[^,]*(?:;base64)?,(.*)$/);if(!match)return null;let isBase64=dataUrl.includes(";base64,"),data=match[1],json=isBase64?Buffer.from(data,"base64").toString("utf-8"):decodeURIComponent(data);return JSON.parse(json)}catch{return null}}_resolveUrl(url,baseUrl){if(url.startsWith("http://")||url.startsWith("https://"))return url;try{return new URL(url,baseUrl).href}catch{return baseUrl.replace(/[^/]*$/,"")+url}}async _fetchViaBrowser(url){if(!this.page)return null;try{let typedResult=await this.page.evaluate(async fetchUrl=>{try{let response=await fetch(fetchUrl);return response.ok?{data:await response.text()}:{error:`HTTP ${response.status}`}}catch(err){return{error:err.message||"Fetch failed"}}},url);return"error"in typedResult?(debug(`Browser fetch error for ${url}: ${typedResult.error}`),null):JSON.parse(typedResult.data)}catch(error2){return debug(`Failed to fetch ${url} via browser:`,error2),null}}};var V8API_DEFAULT_OPTIONS={maxDepth:3,maxProperties:50,maxArrayLength:100,maxStringLength:1e3},V8Api=class{cdp=null;enabled=!1;scripts=new Map;scriptsByUrl=new Map;eventHandlers={};options;cdpProvider;constructor(source,options){if(this.options={...V8API_DEFAULT_OPTIONS,...options},typeof source=="function")this.cdpProvider=source;else if(source&&typeof source.context=="function"){let page=source;this.cdpProvider=async()=>await page.context().newCDPSession(page)}else if(source&&typeof source.send=="function"){let session=source;this.cdp=session,this.cdpProvider=async()=>session}else throw new Error("V8Api: Invalid source. Expected Page, CDPSessionProvider, or ICDPSession.")}getOptions(){return{...this.options}}isEnabled(){return this.enabled}async getCdp(){return this.cdp||(this.cdp=await this.cdpProvider()),this.cdp}on(event,handler){this.eventHandlers[event]=handler}off(event){delete this.eventHandlers[event]}async enable(){if(this.enabled)return;let cdp=await this.getCdp();cdp.on("Debugger.scriptParsed",event=>{let parsed=event;if(this.scripts.set(parsed.scriptId,parsed),parsed.url){let existing=this.scriptsByUrl.get(parsed.url)||[];existing.push(parsed),this.scriptsByUrl.set(parsed.url,existing)}this.eventHandlers.scriptParsed&&this.eventHandlers.scriptParsed(parsed)}),cdp.on("Debugger.paused",event=>{let pausedEvent=event;this.eventHandlers.paused&&this.eventHandlers.paused(pausedEvent)}),cdp.on("Debugger.resumed",()=>{this.eventHandlers.resumed&&this.eventHandlers.resumed()}),await cdp.send("Debugger.enable",{maxScriptsCacheSize:1e8}),await cdp.send("Runtime.enable"),this.enabled=!0}async disable(){if(!(!this.enabled||!this.cdp)){try{await this.cdp.send("Debugger.disable"),await this.cdp.send("Runtime.disable")}catch{}this.scripts.clear(),this.scriptsByUrl.clear(),this.enabled=!1}}async detach(){if(await this.disable(),this.cdp){try{await this.cdp.detach()}catch{}this.cdp=null}}getScripts(){return Array.from(this.scripts.values())}getScript(scriptId){return this.scripts.get(scriptId)}findScriptsByUrl(urlPattern){let regex=new RegExp(urlPattern),results=[];for(let script of this.scripts.values())script.url&&regex.test(script.url)&&results.push(script);return results}async setBreakpointByUrl(options){let cdp=await this.getCdp(),params={lineNumber:options.lineNumber};options.urlRegex?params.urlRegex=options.urlRegex:options.url&&(params.url=options.url),options.columnNumber!==void 0&&(params.columnNumber=options.columnNumber),options.condition&&(params.condition=options.condition);let result=await cdp.send("Debugger.setBreakpointByUrl",params);return{breakpointId:result.breakpointId,locations:result.locations||[]}}async setBreakpoint(location,condition){let cdp=await this.getCdp(),params={location:{scriptId:location.scriptId,lineNumber:location.lineNumber,columnNumber:location.columnNumber}};condition&&(params.condition=condition);let result=await cdp.send("Debugger.setBreakpoint",params);return{breakpointId:result.breakpointId,actualLocation:result.actualLocation}}async removeBreakpoint(breakpointId){await(await this.getCdp()).send("Debugger.removeBreakpoint",{breakpointId})}async resume(){await(await this.getCdp()).send("Debugger.resume")}async stepOver(){await(await this.getCdp()).send("Debugger.stepOver")}async stepInto(){await(await this.getCdp()).send("Debugger.stepInto")}async stepOut(){await(await this.getCdp()).send("Debugger.stepOut")}async pause(){await(await this.getCdp()).send("Debugger.pause")}async setPauseOnExceptions(state){await(await this.getCdp()).send("Debugger.setPauseOnExceptions",{state})}async evaluateOnCallFrame(callFrameId,expression,options){let result=await(await this.getCdp()).send("Debugger.evaluateOnCallFrame",{callFrameId,expression,returnByValue:options?.returnByValue??!0,generatePreview:options?.generatePreview??!0,throwOnSideEffect:options?.throwOnSideEffect??!1});return{result:result.result,exceptionDetails:result.exceptionDetails}}async getProperties(objectId,options){let result=await(await this.getCdp()).send("Runtime.getProperties",{objectId,ownProperties:options?.ownProperties??!0,accessorPropertiesOnly:options?.accessorPropertiesOnly??!1,generatePreview:options?.generatePreview??!0});return{result:result.result||[],internalProperties:result.internalProperties,privateProperties:result.privateProperties}}async getScopeVariables(scope,options){if(!scope.object.objectId)return{};let opts={maxDepth:options?.maxDepth??this.options.maxDepth,maxProperties:options?.maxProperties??this.options.maxProperties,maxArrayLength:options?.maxArrayLength??this.options.maxArrayLength},{result}=await this.getProperties(scope.object.objectId,{ownProperties:!0,generatePreview:!0}),variables={},visited=new Set,propCount=0;for(let prop of result){if(propCount>=opts.maxProperties){variables.__truncated__=`${result.length-propCount} more properties`;break}prop.value&&(variables[prop.name]=await this.extractValueDeep(prop.value,opts.maxDepth,opts.maxProperties,opts.maxArrayLength,visited),propCount++)}return variables}extractValue(obj){return this._extractValueShallow(obj)}async extractValueDeep(obj,maxDepth,maxProperties,maxArrayLength,visited=new Set){let depth=maxDepth??this.options.maxDepth,props=maxProperties??this.options.maxProperties,arrLen=maxArrayLength??this.options.maxArrayLength;if(obj.value!==void 0)return typeof obj.value=="string"&&obj.value.length>this.options.maxStringLength?obj.value.slice(0,this.options.maxStringLength)+`... (${obj.value.length} chars)`:obj.value;if(obj.unserializableValue)return obj.unserializableValue==="NaN"?NaN:obj.unserializableValue==="Infinity"?1/0:obj.unserializableValue==="-Infinity"?-1/0:obj.unserializableValue==="-0"?-0:obj.unserializableValue.endsWith("n")?`BigInt(${obj.unserializableValue.slice(0,-1)})`:obj.unserializableValue;if(obj.subtype==="null")return null;if(obj.type!=="undefined"){if(obj.type==="function")return`[function${obj.description?`: ${obj.description.split(`
3
+ `)[0]}`:""}]`;if(!obj.objectId)return this._extractValueShallow(obj);if(depth<=0)return this._getShallowDescription(obj);if(visited.has(obj.objectId))return"[Circular]";visited.add(obj.objectId);try{return obj.subtype==="array"?await this._extractArray(obj.objectId,depth-1,props,arrLen,visited):obj.subtype==="map"?await this._extractMap(obj.objectId,depth-1,props,arrLen,visited):obj.subtype==="set"?await this._extractSet(obj.objectId,depth-1,arrLen,visited):obj.subtype==="date"?obj.description||"[Date]":obj.subtype==="regexp"?obj.description||"[RegExp]":obj.subtype==="error"?obj.description||"[Error]":obj.subtype==="promise"?`[Promise: ${obj.description||"pending"}]`:obj.subtype==="node"||obj.className?.includes("Element")||obj.className?.includes("Node")?`[DOM: ${obj.description||obj.className||"Node"}]`:obj.type==="object"?await this._extractObject(obj.objectId,depth-1,props,arrLen,visited,obj.className):this._extractValueShallow(obj)}catch{return this._getShallowDescription(obj)}}}async _extractArray(objectId,maxDepth,maxProperties,maxArrayLength,visited){let{result}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),arr=[],length=0;for(let prop of result)if(prop.name==="length"&&prop.value?.value!==void 0){length=prop.value.value;break}for(let prop of result){let index=parseInt(prop.name,10);if(!(isNaN(index)||index<0)){if(arr.length>=maxArrayLength)break;prop.value&&(arr[index]=await this.extractValueDeep(prop.value,maxDepth,maxProperties,maxArrayLength,visited))}}return length>maxArrayLength&&(arr.__truncated__=`${length-maxArrayLength} more items`),arr}async _extractMap(objectId,maxDepth,maxProperties,maxArrayLength,visited){let{internalProperties}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),mapObj={__type__:"Map"},entries=[],entriesProp=internalProperties?.find(p=>p.name==="[[Entries]]");if(entriesProp?.value?.objectId){let{result:entryResults}=await this.getProperties(entriesProp.value.objectId,{ownProperties:!0,generatePreview:!0}),count=0;for(let entry of entryResults){if(count>=maxArrayLength)break;let index=parseInt(entry.name,10);if(isNaN(index)||!entry.value?.objectId)continue;let{result:kvResult}=await this.getProperties(entry.value.objectId,{ownProperties:!0,generatePreview:!0}),keyProp=kvResult.find(p=>p.name==="key"),valueProp=kvResult.find(p=>p.name==="value");if(keyProp?.value&&valueProp?.value){let key=await this.extractValueDeep(keyProp.value,maxDepth,maxProperties,maxArrayLength,visited),value=await this.extractValueDeep(valueProp.value,maxDepth,maxProperties,maxArrayLength,visited);entries.push([key,value])}count++}}return mapObj.entries=entries,mapObj}async _extractSet(objectId,maxDepth,maxArrayLength,visited){let{internalProperties}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),setObj={__type__:"Set"},values=[],entriesProp=internalProperties?.find(p=>p.name==="[[Entries]]");if(entriesProp?.value?.objectId){let{result:entryResults}=await this.getProperties(entriesProp.value.objectId,{ownProperties:!0,generatePreview:!0}),count=0;for(let entry of entryResults){if(count>=maxArrayLength)break;let index=parseInt(entry.name,10);isNaN(index)||(entry.value&&values.push(await this.extractValueDeep(entry.value,maxDepth,50,maxArrayLength,visited)),count++)}}return setObj.values=values,setObj}async _extractObject(objectId,maxDepth,maxProperties,maxArrayLength,visited,className){let{result}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),obj={};className&&className!=="Object"&&(obj.__class__=className);let count=0;for(let prop of result){if(count>=maxProperties){obj.__truncated__=`${result.length-count} more properties`;break}prop.isOwn&&(prop.name.startsWith("__")&&prop.name.endsWith("__")||prop.value&&(obj[prop.name]=await this.extractValueDeep(prop.value,maxDepth,maxProperties,maxArrayLength,visited),count++))}return obj}_extractValueShallow(obj){if(obj.value!==void 0)return obj.value;if(obj.unserializableValue)return obj.unserializableValue==="NaN"?NaN:obj.unserializableValue==="Infinity"?1/0:obj.unserializableValue==="-Infinity"?-1/0:obj.unserializableValue==="-0"?-0:obj.unserializableValue.endsWith("n")?`BigInt(${obj.unserializableValue.slice(0,-1)})`:obj.unserializableValue;if(obj.subtype==="null")return null;if(obj.type!=="undefined")return this._getShallowDescription(obj)}_getShallowDescription(obj){if(obj.description){let desc=obj.description.split(`
4
+ `)[0];return desc.length>100?`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}] ${desc.slice(0,100)}...`:`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}] ${desc}`}return`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}]`}async getScriptSource(scriptId){return await(await this.getCdp()).send("Debugger.getScriptSource",{scriptId})}async setScriptSource(scriptId,scriptSource,dryRun){let result=await(await this.getCdp()).send("Debugger.setScriptSource",{scriptId,scriptSource,dryRun:dryRun??!1});return{callFrames:result.callFrames,stackChanged:result.stackChanged,asyncStackTrace:result.asyncStackTrace,exceptionDetails:result.exceptionDetails}}};import*as fs2 from"node:fs";import*as http from"node:http";import*as https from"node:https";import*as path3 from"node:path";var ProbeKind=(ProbeKind2=>(ProbeKind2.TRACEPOINT="tracepoint",ProbeKind2.LOGPOINT="logpoint",ProbeKind2))(ProbeKind||{}),DEFAULT_NODE_DEBUG_CONFIG={maxSnapshots:1e3,maxCallStackDepth:1,maxFramesWithScopes:1,maxAsyncStackSegments:10,maxFramesPerAsyncSegment:10},STORES=new Map;function _generateId(){let t=Date.now(),r=Math.floor(Math.random()*1e6);return`${t.toString(36)}-${r.toString(36)}`}function _columnForLocationKey(column){return column==null||column===0?1:column}function _locationKey(urlPattern,lineNumber,columnNumber){return`${urlPattern}:${lineNumber}:${columnNumber}`}function _cdpConsoleTypeToLevelName(type){switch(type){case"error":return"error";case"warning":case"warn":return"warning";case"info":return"info";case"debug":return"debug";default:return"info"}}function _cdpArgsToText(args){return!args||args.length===0?"":args.map(a=>a.type==="string"&&a.value!==void 0||a.value!==void 0?String(a.value):a.description?a.description:"[object]").join(" ")}function _evaluateHitCondition(hitCondition,hitCount){try{let condition=hitCondition.trim();return/^[=<>!%]/.test(condition)&&(condition=`hitCount ${condition}`),!!new Function("hitCount",`return (${condition});`)(hitCount)}catch{return!1}}async function _getOtelTraceContext(session){let expression=`(function(){
5
+ try {
6
+ var api = require('@opentelemetry/api');
7
+ var span = api.trace.getActiveSpan();
8
+ if (!span) return null;
9
+ var ctx = span.spanContext();
10
+ return ctx.traceId && ctx.spanId ? { traceId: ctx.traceId, spanId: ctx.spanId } : null;
11
+ } catch (e) {
12
+ return null;
13
+ }
14
+ })()`;try{let result=await session.send("Runtime.evaluate",{expression,returnByValue:!0,timeout:500});if(result.exceptionDetails)return null;let value=result.result?.value;if(value&&typeof value.traceId=="string"&&typeof value.spanId=="string")return{traceId:value.traceId,spanId:value.spanId}}catch{}return null}function _createNodeSourceMapFetcher(){return async(url,baseUrl)=>{let filePath=null;if(url.startsWith("file://"))filePath=url.replace("file://","");else if(url.startsWith("/")||url.match(/^[a-zA-Z]:\\/))filePath=url;else if(baseUrl.startsWith("file://")){let baseDir=path3.dirname(baseUrl.replace("file://",""));filePath=path3.resolve(baseDir,url)}else if(!url.startsWith("http://")&&!url.startsWith("https://")){let baseDir=path3.dirname(baseUrl.replace(/^file:\/\//,""));filePath=path3.resolve(baseDir,url)}if(filePath)try{return fs2.readFileSync(filePath,"utf-8")}catch{}return url.startsWith("http://")||url.startsWith("https://")?new Promise(resolve2=>{let req=(url.startsWith("https://")?https:http).get(url,res=>{if(res.statusCode!==200){resolve2(null);return}let data="";res.on("data",chunk=>{data+=chunk}),res.on("end",()=>resolve2(data))});req.on("error",()=>resolve2(null)),req.setTimeout(5e3,()=>{req.destroy(),resolve2(null)})}):null}}async function _captureScopes(v8Api,callFrame,maxDepth=3){let scopeSnapshots=[];for(let scope of callFrame.scopeChain)if(!(scope.type==="global"||scope.type==="script"||scope.type==="with"||scope.type==="eval"||scope.type==="wasm-expression-stack")){if(scopeSnapshots.length>=maxDepth)break;try{let variables=await v8Api.getScopeVariables(scope),scopeVariables=[];for(let[name,value]of Object.entries(variables))scopeVariables.push({name,value,type:typeof value});scopeSnapshots.push({type:scope.type,name:scope.name,variables:scopeVariables})}catch{}}return scopeSnapshots}async function _callFrameToSnapshot(v8Api,frame,captureScopes,sourceMapResolver){let scopes=[];captureScopes&&(scopes=await _captureScopes(v8Api,frame));let originalLocation;if(sourceMapResolver){let resolved=sourceMapResolver.generatedToOriginal(frame.location.scriptId,frame.location.lineNumber,frame.location.columnNumber??0);resolved&&(originalLocation={source:resolved.source,line:resolved.line+1,column:resolved.column!==void 0?resolved.column+1:void 0,name:resolved.name})}return{functionName:frame.functionName||"(anonymous)",url:frame.url||"",lineNumber:frame.location.lineNumber+1,columnNumber:frame.location.columnNumber!==void 0?frame.location.columnNumber+1:void 0,scriptId:frame.location.scriptId,scopes,originalLocation}}function _convertAsyncStackTrace(asyncTrace,sourceMapResolver,maxSegments,maxFramesPerSegment){if(!asyncTrace)return;let maxSegs=maxSegments??DEFAULT_NODE_DEBUG_CONFIG.maxAsyncStackSegments,maxFrames=maxFramesPerSegment??DEFAULT_NODE_DEBUG_CONFIG.maxFramesPerAsyncSegment,segments=[],currentTrace=asyncTrace,segmentCount=0;for(;currentTrace&&segmentCount<maxSegs;){let asyncFrames=[];for(let frame of currentTrace.callFrames.slice(0,maxFrames)){let originalLocation;if(sourceMapResolver){let resolved=sourceMapResolver.generatedToOriginal(frame.location.scriptId,frame.location.lineNumber,frame.location.columnNumber??0);resolved&&(originalLocation={source:resolved.source,line:resolved.line+1,column:resolved.column!==void 0?resolved.column+1:void 0,name:resolved.name})}asyncFrames.push({functionName:frame.functionName||"(anonymous)",url:frame.url||"",lineNumber:frame.location.lineNumber+1,columnNumber:frame.location.columnNumber!==void 0?frame.location.columnNumber+1:void 0,originalLocation})}asyncFrames.length>0&&segments.push({description:currentTrace.description,callFrames:asyncFrames}),currentTrace=currentTrace.parent,segmentCount++}return segments.length===0?void 0:{segments}}async function _evaluateWatchExpressionsOnFrame(v8Api,callFrameId,watchExpressions){let results={};for(let watch of watchExpressions.values())try{let result=await v8Api.evaluateOnCallFrame(callFrameId,watch.expression);result.exceptionDetails?results[watch.expression]=`[Error: ${result.exceptionDetails.text||"Evaluation failed"}]`:results[watch.expression]=await v8Api.extractValueDeep(result.result,2)}catch(e){results[watch.expression]=`[Error: ${e.message||"Unknown error"}]`}return results}function getStoreKey(pid,wsUrl){return wsUrl||`pid:${pid}`}async function enableDebugging(storeKey,session,processInfo,v8Options,config){if(STORES.get(storeKey)?.enabled)return;let v8Api=new V8Api(session,v8Options),sourceMapResolver=new SourceMapResolver(_createNodeSourceMapFetcher()),mergedConfig={...DEFAULT_NODE_DEBUG_CONFIG,...config},store={v8Api,sourceMapResolver,probes:new Map,locationIndex:new Map,watchExpressions:new Map,snapshots:[],snapshotSequence:0,consoleMessages:[],consoleMessageSequence:0,config:mergedConfig,enabled:!1,sourceMapsLoaded:!1,exceptionBreakpoint:"none",session,processInfo};STORES.set(storeKey,store),await store.v8Api.enable(),session.on("Runtime.consoleAPICalled",params=>{let type=params.type||"log",args=params.args||[],text=_cdpArgsToText(args),levelName=_cdpConsoleTypeToLevelName(type),levelCode=ConsoleMessageLevel[levelName]?.code??1,location,stackTrace=params.stackTrace;if(stackTrace?.callFrames?.length){let frame=stackTrace.callFrames[0];location={url:frame.url||"",lineNumber:frame.lineNumber??0,columnNumber:frame.columnNumber??0}}store.consoleMessageSequence++,store.consoleMessages.push({type,text,level:{name:levelName,code:levelCode},location,timestamp:Date.now(),sequenceNumber:store.consoleMessageSequence}),store.consoleMessages.length>NODE_CONSOLE_MESSAGES_BUFFER_SIZE&&store.consoleMessages.splice(0,store.consoleMessages.length-NODE_CONSOLE_MESSAGES_BUFFER_SIZE)}),store.v8Api.on("scriptParsed",script=>{store.sourceMapResolver.registerScript(script)});for(let script of store.v8Api.getScripts())store.sourceMapResolver.registerScript(script);store.v8Api.on("paused",async event=>{let startTime=Date.now();try{let isException=event.reason==="exception"||event.reason==="promiseRejection",hitBreakpointIds=event.hitBreakpoints||[],hitProbes=[];for(let probe of store.probes.values()){if(!probe.enabled)continue;if(probe.v8BreakpointIds.some(id=>hitBreakpointIds.includes(id))){let conditionMet=!0;probe.hitCondition&&(conditionMet=_evaluateHitCondition(probe.hitCondition,probe.hitCount+1)),hitProbes.push({probe,conditionMet})}}let shouldCaptureBreakpoint=hitProbes.some(p=>p.conditionMet),shouldCaptureException=isException&&store.exceptionBreakpoint!=="none";for(let{probe}of hitProbes)probe.hitCount++,probe.lastHitAt=Date.now();if((shouldCaptureBreakpoint||shouldCaptureException)&&event.callFrames.length>0){let topFrame=event.callFrames[0],exceptionInfo;if(isException&&event.data){let excData=event.data;exceptionInfo={type:event.reason==="promiseRejection"?"promiseRejection":"exception",message:excData.description||excData.value||String(excData),name:excData.className,stack:excData.description}}let originalLocation,resolvedLoc=store.sourceMapResolver.generatedToOriginal(topFrame.location.scriptId,topFrame.location.lineNumber,topFrame.location.columnNumber??0);resolvedLoc&&(originalLocation={source:resolvedLoc.source,line:resolvedLoc.line+1,column:resolvedLoc.column!==void 0?resolvedLoc.column+1:void 0,name:resolvedLoc.name});let callStackFull=[],framesToProcess=event.callFrames.slice(0,store.config.maxCallStackDepth);for(let i=0;i<framesToProcess.length;i++)callStackFull.push(await _callFrameToSnapshot(store.v8Api,framesToProcess[i],i<store.config.maxFramesWithScopes,store.sourceMapResolver));let asyncStackTraceFull=_convertAsyncStackTrace(event.asyncStackTrace,store.sourceMapResolver,store.config.maxAsyncStackSegments,store.config.maxFramesPerAsyncSegment),traceContext=await _getOtelTraceContext(store.session),probesToCapture=hitProbes.filter(p=>p.conditionMet),snapshotCount=probesToCapture.length+(shouldCaptureException?1:0);for(let s=0;s<snapshotCount;s++){let probeId,isLogpoint,logResult,callStack,asyncStackTrace,watchResults;if(s<probesToCapture.length){let{probe}=probesToCapture[s];if(probeId=probe.id,isLogpoint=probe.kind==="logpoint",isLogpoint&&probe.logExpression)try{let wrappedExpression=`(
15
+ ${probe.logExpression}
16
+ )`,evalResult=await store.v8Api.evaluateOnCallFrame(topFrame.callFrameId,wrappedExpression,{returnByValue:!0,generatePreview:!0});logResult=store.v8Api.extractValue(evalResult.result)}catch{logResult="[evaluation error]"}else logResult=void 0;isLogpoint?(callStack=[],asyncStackTrace=void 0,watchResults=void 0):(callStack=callStackFull,asyncStackTrace=asyncStackTraceFull,watchResults=store.watchExpressions.size>0?await _evaluateWatchExpressionsOnFrame(store.v8Api,topFrame.callFrameId,store.watchExpressions):void 0)}else probeId="__exception__",isLogpoint=!1,logResult=void 0,callStack=callStackFull,asyncStackTrace=asyncStackTraceFull,watchResults=store.watchExpressions.size>0?await _evaluateWatchExpressionsOnFrame(store.v8Api,topFrame.callFrameId,store.watchExpressions):void 0;let snapshot={id:_generateId(),probeId,timestamp:Date.now(),sequenceNumber:++store.snapshotSequence,url:topFrame.url||"",lineNumber:topFrame.location.lineNumber+1,columnNumber:topFrame.location.columnNumber!==void 0?topFrame.location.columnNumber+1:void 0,originalLocation,exception:exceptionInfo,callStack,asyncStackTrace,logResult,watchResults,captureTimeMs:Date.now()-startTime,traceContext:traceContext??void 0};store.snapshots.push(snapshot)}store.snapshots.length>store.config.maxSnapshots&&store.snapshots.splice(0,store.snapshots.length-store.config.maxSnapshots)}}finally{await store.v8Api.resume()}}),store.enabled=!0,store.sourceMapResolver.loadAllSourceMaps().then(()=>{store.sourceMapsLoaded=!0}).catch(()=>{})}async function disableDebugging(storeKey){let store=STORES.get(storeKey);if(store?.enabled){for(let entry of store.locationIndex.values())try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}store.locationIndex.clear(),store.probes.clear(),store.snapshots.length=0,store.snapshotSequence=0,store.consoleMessages.length=0,store.consoleMessageSequence=0,await store.v8Api.disable(),store.enabled=!1}}async function detachDebugging(storeKey){let store=STORES.get(storeKey);store&&(await disableDebugging(storeKey),await store.v8Api.detach(),STORES.delete(storeKey))}function isDebuggingEnabled(storeKey){return STORES.get(storeKey)?.enabled??!1}function getStore(storeKey){return STORES.get(storeKey)}async function resolveSourceLocation(storeKey,url,line,column=1){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Not connected to Node.js process or debugging not enabled. You MUST connect first.");let resolved=await store.sourceMapResolver.resolveLocationByUrl(url,line,column);return resolved?{source:resolved.source,line:resolved.line+1,column:resolved.column+1,name:resolved.name}:null}function listStoreKeys(){return Array.from(STORES.keys())}async function setExceptionBreakpoint(storeKey,state){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");await store.v8Api.setPauseOnExceptions(state),store.exceptionBreakpoint=state}function getExceptionBreakpoint(storeKey){return STORES.get(storeKey)?.exceptionBreakpoint??"none"}async function createProbe(storeKey,options){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");let probeId=_generateId(),columnForKey=_columnForLocationKey(options.columnNumber),locationKey=_locationKey(options.urlPattern,options.lineNumber,columnForKey),existingEntry=store.locationIndex.get(locationKey);if(existingEntry){existingEntry.refCount++;let probe2={id:probeId,kind:options.kind,enabled:!0,urlPattern:options.urlPattern,lineNumber:options.lineNumber,columnNumber:options.columnNumber,condition:options.condition,logExpression:options.logExpression,hitCondition:options.hitCondition,v8BreakpointIds:[existingEntry.breakpointId],resolvedLocations:existingEntry.resolvedLocations,hitCount:0,createdAt:Date.now()};return store.probes.set(probeId,probe2),probe2}let fullCondition=options.condition?`(${options.condition})`:"true",line0based=options.lineNumber-1,column0based=columnForKey-1,resolved=store.sourceMapResolver.originalToGenerated(options.urlPattern,line0based,column0based),breakpointId,resolvedLocationsCount=0;if(resolved)try{breakpointId=(await store.v8Api.setBreakpoint({scriptId:resolved.scriptId,lineNumber:resolved.location.line,columnNumber:resolved.location.column},fullCondition)).breakpointId,resolvedLocationsCount=1}catch{let scriptUrl=store.sourceMapResolver.getScriptUrl(resolved.scriptId);if(scriptUrl){let result=await store.v8Api.setBreakpointByUrl({url:scriptUrl,lineNumber:resolved.location.line,columnNumber:resolved.location.column,condition:fullCondition});breakpointId=result.breakpointId,resolvedLocationsCount=result.locations.length}else throw new Error("Failed to set breakpoint at resolved location and could not fall back (script URL unknown). A probe may already exist at this line; remove it first or use a different line.")}else{let urlRegex=options.urlPattern.replace(/\\([.*+?^${}()|[\]\\/-])/g,"$1").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*").replace(/\\\?/g,"."),result=await store.v8Api.setBreakpointByUrl({urlRegex,lineNumber:options.lineNumber-1,columnNumber:options.columnNumber!=null?Math.max(0,options.columnNumber-1):void 0,condition:fullCondition});breakpointId=result.breakpointId,resolvedLocationsCount=result.locations.length}store.locationIndex.set(locationKey,{breakpointId,resolvedLocations:resolvedLocationsCount,refCount:1});let probe={id:probeId,kind:options.kind,enabled:!0,urlPattern:options.urlPattern,lineNumber:options.lineNumber,columnNumber:options.columnNumber,condition:options.condition,logExpression:options.logExpression,hitCondition:options.hitCondition,v8BreakpointIds:[breakpointId],resolvedLocations:resolvedLocationsCount,hitCount:0,createdAt:Date.now()};return store.probes.set(probeId,probe),probe}async function removeProbe(storeKey,probeId){let store=STORES.get(storeKey);if(!store)return!1;let probe=store.probes.get(probeId);if(!probe)return!1;let locationKey=_locationKey(probe.urlPattern,probe.lineNumber,_columnForLocationKey(probe.columnNumber)),entry=store.locationIndex.get(locationKey);if(entry&&(entry.refCount--,entry.refCount===0)){try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}store.locationIndex.delete(locationKey)}return store.probes.delete(probeId),!0}function listProbes(storeKey){return Array.from(STORES.get(storeKey)?.probes.values()??[])}async function clearProbes(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.probes.size;for(let entry of store.locationIndex.values())try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}return store.locationIndex.clear(),store.probes.clear(),count}function getSnapshots(storeKey){return[...STORES.get(storeKey)?.snapshots??[]]}function getSnapshotsByProbe(storeKey,probeId){return(STORES.get(storeKey)?.snapshots??[]).filter(s=>s.probeId===probeId)}function clearSnapshots(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.snapshots.length;return store.snapshots.length=0,count}function clearSnapshotsByProbe(storeKey,probeId){let store=STORES.get(storeKey);if(!store)return 0;let before=store.snapshots.length;return store.snapshots=store.snapshots.filter(s=>s.probeId!==probeId),before-store.snapshots.length}function getSnapshotStats(storeKey){let store=STORES.get(storeKey);if(!store||store.snapshots.length===0)return{totalSnapshots:0,snapshotsByProbe:{},averageCaptureTimeMs:0};let snapshotsByProbe={},totalCaptureTime=0;for(let s of store.snapshots)snapshotsByProbe[s.probeId]=(snapshotsByProbe[s.probeId]||0)+1,totalCaptureTime+=s.captureTimeMs;return{totalSnapshots:store.snapshots.length,snapshotsByProbe,oldestTimestamp:store.snapshots[0].timestamp,newestTimestamp:store.snapshots[store.snapshots.length-1].timestamp,averageCaptureTimeMs:totalCaptureTime/store.snapshots.length}}function getConsoleMessages(storeKey){return[...STORES.get(storeKey)?.consoleMessages??[]]}function addWatchExpression(storeKey,expression){let store=STORES.get(storeKey);if(!store)throw new Error("Debug store not initialized");let id=_generateId(),watchExpr={id,expression,createdAt:Date.now()};return store.watchExpressions.set(id,watchExpr),watchExpr}function removeWatchExpression(storeKey,watchExpressionId){return STORES.get(storeKey)?.watchExpressions.delete(watchExpressionId)??!1}function listWatchExpressions(storeKey){return Array.from(STORES.get(storeKey)?.watchExpressions.values()??[])}function clearWatchExpressions(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.watchExpressions.size;return store.watchExpressions.clear(),count}async function loadSourceMaps(storeKey){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");let loaded=await store.sourceMapResolver.loadAllSourceMaps(),sources=store.sourceMapResolver.getOriginalSources();return store.sourceMapsLoaded=!0,{loaded,sources}}function hasSourceMaps(storeKey){return STORES.get(storeKey)?.sourceMapResolver.hasSourceMaps()??!1}function getOriginalSources(storeKey){return STORES.get(storeKey)?.sourceMapResolver.getOriginalSources()??[]}function getScripts(storeKey){return STORES.get(storeKey)?.v8Api.getScripts()??[]}function wrapScriptInAsyncIIFE(script){return`(async function() { ${script} })()`}function formatEvaluationException(exc){let parts=[],text=exc.text??exc.description;text&&parts.push(text);let desc=exc.exception?.description;desc&&desc!==text&&parts.push(desc);let className=exc.exception?.className;className&&!parts.some(p=>p.includes(className))&&parts.push(className),parts.length===0&&parts.push(JSON.stringify(exc));let stack=exc.stackTrace?.callFrames?.slice(0,5).map(f=>` at ${f.functionName??"?"} (${f.url??"?"}:${f.lineNumber??0})`).join(`
17
+ `);return stack&&parts.push(`Stack:
18
+ ${stack}`),parts.join(" \u2014 ")}async function evaluateInNode(storeKey,expression,timeoutMs=5e3){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Not connected to Node.js process or debugging not enabled. You MUST connect first.");let codeToRun=wrapScriptInAsyncIIFE(expression),result=await store.session.send("Runtime.evaluate",{expression:codeToRun,returnByValue:!0,awaitPromise:!0,timeout:Math.min(timeoutMs,3e4)});if(result.exceptionDetails){let exc=result.exceptionDetails,message=formatEvaluationException(exc);throw new Error(`Node evaluation failed: ${message}`)}return store.v8Api.extractValue(result.result)}export{__esm,__export,__toCommonJS,PORT,TOOL_OUTPUT_SCHEMA_DISABLE,TOOL_INPUT_METADATA_ENABLE,AVAILABLE_TOOL_DOMAINS,PLATFORM,SESSION_IDLE_SECONDS,SESSION_IDLE_CHECK_SECONDS,SESSION_CLOSE_ON_SOCKET_CLOSE,BROWSER_HEADLESS_ENABLE,BROWSER_PERSISTENT_ENABLE,BROWSER_PERSISTENT_USER_DATA_DIR,BROWSER_USE_INSTALLED_ON_SYSTEM,BROWSER_EXECUTABLE_PATH,BROWSER_LOCALE,BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE,BROWSER_HTTP_REQUESTS_BUFFER_SIZE,BROWSER_SERVER_INSTRUCTIONS_ENABLE,BROWSER_POLICY_UI_DEBUGGING_ENABLE,BROWSER_CDP_CONNECT_URL,BROWSER_CDP_ENDPOINT_EXPLICIT,BROWSER_CDP_OPEN_INSPECT,NODE_SERVER_INSTRUCTIONS_ENABLE,NODE_POLICY_DEBUGGING_ENABLE,NODE_CONSOLE_MESSAGES_BUFFER_SIZE,NODE_INSPECTOR_HOST,COLLECTOR_URL,COLLECTOR_API_KEY,OTEL_ENABLE,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION,OTEL_ASSETS_DIR,OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS,OTEL_EXPORTER_TYPE,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_HTTP_HEADERS,AWS_REGION,AWS_PROFILE,AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,WORKING_DIR,LOG_FILE,SEARCH_STRATEGY,SCENARIO_SEARCH_STRATEGY,DAEMON_PORT,DAEMON_SESSION_IDLE_SECONDS,DAEMON_SESSION_IDLE_CHECK_SECONDS,normalizeToolName,denormalizeToolName,applyNormalizedToolNamesInText,initFileLogging,enable,disable,isDebugEnabled,debug,info,warn,error,toJson,init_logger,ConsoleMessageLevelName,ConsoleMessageLevel,V8Api,SourceMapResolver,ProbeKind,DEFAULT_NODE_DEBUG_CONFIG,getStoreKey,enableDebugging,disableDebugging,detachDebugging,isDebuggingEnabled,getStore,resolveSourceLocation,listStoreKeys,setExceptionBreakpoint,getExceptionBreakpoint,createProbe,removeProbe,listProbes,clearProbes,getSnapshots,getSnapshotsByProbe,clearSnapshots,clearSnapshotsByProbe,getSnapshotStats,getConsoleMessages,addWatchExpression,removeWatchExpression,listWatchExpressions,clearWatchExpressions,loadSourceMaps,hasSourceMaps,getOriginalSources,getScripts,evaluateInNode};
@@ -1,4 +1,4 @@
1
- import{AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,AWS_PROFILE,AWS_REGION,BROWSER_CDP_CONNECT_URL,BROWSER_CDP_ENDPOINT_EXPLICIT,BROWSER_CDP_OPEN_INSPECT,BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE,BROWSER_EXECUTABLE_PATH,BROWSER_HEADLESS_ENABLE,BROWSER_HTTP_REQUESTS_BUFFER_SIZE,BROWSER_LOCALE,BROWSER_PERSISTENT_ENABLE,BROWSER_PERSISTENT_USER_DATA_DIR,BROWSER_POLICY_UI_DEBUGGING_ENABLE,BROWSER_SERVER_INSTRUCTIONS_ENABLE,BROWSER_USE_INSTALLED_ON_SYSTEM,COLLECTOR_API_KEY,COLLECTOR_URL,ConsoleMessageLevel,ConsoleMessageLevelName,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,NODE_CONSOLE_MESSAGES_BUFFER_SIZE,NODE_INSPECTOR_HOST,NODE_POLICY_DEBUGGING_ENABLE,NODE_SERVER_INSTRUCTIONS_ENABLE,OTEL_ASSETS_DIR,OTEL_ENABLE,OTEL_EXPORTER_HTTP_HEADERS,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_TYPE,OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION,PLATFORM,SCENARIO_SEARCH_STRATEGY,SEARCH_STRATEGY,SourceMapResolver,TOOL_INPUT_METADATA_ENABLE,V8Api,WORKING_DIR,__esm,__export,__toCommonJS,addWatchExpression,clearWatchExpressions,createProbe,debug,denormalizeToolName,detachDebugging,enableDebugging,error,getConsoleMessages,getExceptionBreakpoint,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStoreKey,hasSourceMaps,init_logger,isDebuggingEnabled,listProbes,listWatchExpressions,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint,toJson,warn}from"./core-X3FD2EZG.js";var fts5_strategy_exports={};__export(fts5_strategy_exports,{Fts5Strategy:()=>Fts5Strategy});import{createRequire as createRequire2}from"node:module";function _loadBetterSqlite3(){try{return require3("better-sqlite3")}catch{throw new Error("better-sqlite3 is not installed. Install it with: npm install better-sqlite3")}}var require3,Fts5Strategy,init_fts5_strategy=__esm({"src/search/strategies/fts5-strategy.ts"(){"use strict";require3=createRequire2(import.meta.url);Fts5Strategy=class{_db;_fieldNames=[];_initialized=!1;constructor(){let BetterSqlite3=_loadBetterSqlite3();this._db=new BetterSqlite3(":memory:")}_bm25Weights="";_ensureTable(fields){if(this._initialized)return;this._fieldNames=Object.keys(fields);let columns=this._fieldNames.join(", ");this._db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS documents USING fts5(id, ${columns}, tokenize='porter unicode61')`);let weights=[0,...this._fieldNames.map((_,i)=>i===0?5:1)];this._bm25Weights=weights.join(", "),this._initialized=!0}index(documents){if(documents.length===0)return;this._ensureTable(documents[0].fields);let columns=["id",...this._fieldNames].join(", "),placeholders=["id",...this._fieldNames].map(()=>"?").join(", "),stmt=this._db.prepare(`INSERT INTO documents (${columns}) VALUES (${placeholders})`);this._db.exec("BEGIN");try{for(let doc of documents){let values=[doc.id,...this._fieldNames.map(f=>doc.fields[f]??"")];stmt.run(...values)}this._db.exec("COMMIT")}catch(err){throw this._db.exec("ROLLBACK"),err}}add(document2){this._ensureTable(document2.fields);let columns=["id",...this._fieldNames].join(", "),placeholders=["id",...this._fieldNames].map(()=>"?").join(", "),values=[document2.id,...this._fieldNames.map(f=>document2.fields[f]??"")];this._db.prepare(`INSERT INTO documents (${columns}) VALUES (${placeholders})`).run(...values)}update(id,document2){this.remove(id),this.add(document2)}remove(id){this._initialized&&this._db.prepare("DELETE FROM documents WHERE id = ?").run(id)}search(query,limit){if(!this._initialized||!query.trim())return[];let FTS5_RESERVED=new Set(["AND","OR","NOT","NEAR"]),tokens=query.replace(/['"\[\]{}\*:^~()\-]/g," ").split(/\s+/).filter(t=>t.length>0&&!FTS5_RESERVED.has(t.toUpperCase()));if(tokens.length===0)return[];let ftsQuery=tokens.map(t=>`"${t}"`).join(" OR "),safeLimit=limit?Math.max(1,Math.floor(limit)):100;return this._db.prepare(`SELECT id, bm25(documents, ${this._bm25Weights}) AS rank FROM documents WHERE documents MATCH ? ORDER BY rank LIMIT ?`).all(ftsQuery,safeLimit).map(row=>({id:row.id,score:-row.rank}))}close(){this._db.close()}}}});var minisearch_strategy_exports={};__export(minisearch_strategy_exports,{MiniSearchStrategy:()=>MiniSearchStrategy});import MiniSearch from"minisearch";import{stemmer}from"stemmer";var MiniSearchStrategy,init_minisearch_strategy=__esm({"src/search/strategies/minisearch-strategy.ts"(){"use strict";init_logger();MiniSearchStrategy=class{_index;_fieldNames=[];constructor(){this._index=this._createIndex([])}_createIndex(fieldNames){return new MiniSearch({fields:fieldNames,storeFields:[],processTerm:term=>stemmer(term.toLowerCase()),searchOptions:{fuzzy:.2,prefix:!0}})}_ensureFields(fields){let names=Object.keys(fields);names.some(n=>!this._fieldNames.includes(n))&&(this._fieldNames.length===0?(this._fieldNames=names,this._index=this._createIndex(this._fieldNames)):debug(`minisearch: document has new fields [${names.join(", ")}] not in index [${this._fieldNames.join(", ")}] \u2014 extra fields ignored`))}index(documents){if(documents.length===0)return;this._ensureFields(documents[0].fields);let docs=documents.map(doc=>({id:doc.id,...doc.fields}));this._index.addAll(docs)}add(document2){this._ensureFields(document2.fields),this._index.add({id:document2.id,...document2.fields})}update(id,document2){try{this._index.discard(id)}catch{}this._index.add({id:document2.id,...document2.fields})}remove(id){try{this._index.discard(id)}catch{}}search(query,limit){let results=this._index.search(query);return(limit?results.slice(0,limit):results).map(r=>({id:r.id,score:r.score}))}close(){}}}});import{z}from"zod";function augmentToolInputSchema(shape){if(!TOOL_INPUT_METADATA_ENABLE)return shape;let extra={};return Object.prototype.hasOwnProperty.call(shape,"_metadata")||(extra._metadata=z.object({projectName:z.string().optional(),sessionId:z.string().optional(),verificationId:z.string().optional(),traceId:z.string().optional(),traceState:z.string().optional(),collectorUrl:z.string().optional(),collectorApiKey:z.string().optional()}).catchall(z.unknown()).optional()),Object.keys(extra).length===0?shape:{...shape,...extra}}import{z as z2,ZodError}from"zod";function formatZodError(err){return"Validation failed: "+err.issues.map(issue=>(issue.path.length?issue.path.join(".")+": ":"")+issue.message).join("; ")}var ToolRegistry=class{tools=new Map;addTool(tool){if(this.tools.has(tool.name()))throw new Error(`Tool already registered: ${tool.name()}`);this.tools.set(tool.name(),{tool,inputSchema:z2.object(augmentToolInputSchema(tool.inputSchema())).strict(),outputSchema:z2.object(tool.outputSchema()).strict()})}async runTool(context,toolName,toolArgs){let canonicalKey=denormalizeToolName(toolName),toolDef=this.tools.get(canonicalKey);if(!toolDef)throw new Error(`Tool not found: ${toolName}`);let parsedToolArgs;try{parsedToolArgs=await toolDef.inputSchema.parseAsync(toolArgs)}catch(e){throw e instanceof ZodError?new Error(formatZodError(e)):e}let rawToolResult=await toolDef.tool.handle(context,parsedToolArgs);return await toolDef.outputSchema.parseAsync(rawToolResult)}};function isToolEnabled(tool){return tool.isEnabled?.()??!0}init_logger();import fs from"node:fs";import os from"node:os";import path from"node:path";var DIR_NAME=".browser-devtools-mcp",FILE_NAME="scenarios.json";function _scenariosPath(scope){let baseDir=scope==="project"?WORKING_DIR:os.homedir();return path.join(baseDir,DIR_NAME,FILE_NAME)}function _isValidScenario(value){return typeof value=="object"&&value!==null&&typeof value.name=="string"&&typeof value.description=="string"&&typeof value.script=="string"}function _readFile(filePath){try{if(!fs.existsSync(filePath))return{};let content=fs.readFileSync(filePath,"utf-8"),parsed=JSON.parse(content);if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return debug(`scenario-store: invalid format in ${filePath}, expected object`),{};let result={};for(let[key,value]of Object.entries(parsed))_isValidScenario(value)?result[key]=value:debug(`scenario-store: skipping invalid scenario "${key}" in ${filePath}`);return result}catch(err){return debug(`scenario-store: failed to read ${filePath}: ${err}`),{}}}function _writeFile(filePath,scenarios){let dir=path.dirname(filePath);fs.existsSync(dir)||fs.mkdirSync(dir,{recursive:!0}),fs.writeFileSync(filePath,JSON.stringify(scenarios,null,2),"utf-8")}function _validateName(name){if(!name||name.length>200)throw new Error("Scenario name must be between 1 and 200 characters");if(/[/\\:*?"<>|.]/.test(name)||name.includes(".."))throw new Error('Scenario name contains invalid characters (no /, \\, :, *, ?, ", <, >, |, .)')}var _fileLocks=new Map;function _withFileLock(filePath,fn){let prev=_fileLocks.get(filePath)??Promise.resolve(),resolve,next=new Promise(r=>{resolve=r});_fileLocks.set(filePath,next);let result;try{result=fn()}finally{resolve()}return result}var ScenarioStore=class{_scope;_filePath;constructor(scope){this._scope=scope,this._filePath=_scenariosPath(scope)}get(name){return _readFile(this._filePath)[name]}add(scenario){_validateName(scenario.name),_withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath);if(scenarios[scenario.name])throw new Error(`Scenario "${scenario.name}" already exists in ${this._scope} scope`);scenarios[scenario.name]=scenario,_writeFile(this._filePath,scenarios)})}update(name,updates){return _validateName(name),_withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath),existing=scenarios[name];if(!existing)throw new Error(`Scenario "${name}" not found in ${this._scope} scope`);let updated={...existing,...updates,name};return scenarios[name]=updated,_writeFile(this._filePath,scenarios),updated})}delete(name){return _withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath);return scenarios[name]?(delete scenarios[name],_writeFile(this._filePath,scenarios),!0):!1})}list(){let scenarios=_readFile(this._filePath);return Object.values(scenarios)}getAll(){return _readFile(this._filePath)}};function resolveScenario(name){let projectScenario=new ScenarioStore("project").get(name);return projectScenario||new ScenarioStore("global").get(name)}function listAllScenarios(){let globalStore=new ScenarioStore("global"),projectStore=new ScenarioStore("project"),merged={...globalStore.getAll(),...projectStore.getAll()};return Object.values(merged)}import{z as z3}from"zod";var MAX_RECURSION_DEPTH=5,ScenarioRun=class{_toolRegistry;constructor(toolRegistry){this._toolRegistry=toolRegistry}name(){return"scenario-run"}description(){return`
1
+ import{AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,AWS_PROFILE,AWS_REGION,BROWSER_CDP_CONNECT_URL,BROWSER_CDP_ENDPOINT_EXPLICIT,BROWSER_CDP_OPEN_INSPECT,BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE,BROWSER_EXECUTABLE_PATH,BROWSER_HEADLESS_ENABLE,BROWSER_HTTP_REQUESTS_BUFFER_SIZE,BROWSER_LOCALE,BROWSER_PERSISTENT_ENABLE,BROWSER_PERSISTENT_USER_DATA_DIR,BROWSER_POLICY_UI_DEBUGGING_ENABLE,BROWSER_SERVER_INSTRUCTIONS_ENABLE,BROWSER_USE_INSTALLED_ON_SYSTEM,COLLECTOR_API_KEY,COLLECTOR_URL,ConsoleMessageLevel,ConsoleMessageLevelName,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,NODE_CONSOLE_MESSAGES_BUFFER_SIZE,NODE_INSPECTOR_HOST,NODE_POLICY_DEBUGGING_ENABLE,NODE_SERVER_INSTRUCTIONS_ENABLE,OTEL_ASSETS_DIR,OTEL_ENABLE,OTEL_EXPORTER_HTTP_HEADERS,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_TYPE,OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION,PLATFORM,SCENARIO_SEARCH_STRATEGY,SEARCH_STRATEGY,SourceMapResolver,TOOL_INPUT_METADATA_ENABLE,V8Api,WORKING_DIR,__esm,__export,__toCommonJS,addWatchExpression,clearWatchExpressions,createProbe,debug,denormalizeToolName,detachDebugging,enableDebugging,error,getConsoleMessages,getExceptionBreakpoint,getSnapshotStats,getSnapshots,getSnapshotsByProbe,getStoreKey,hasSourceMaps,init_logger,isDebuggingEnabled,listProbes,listWatchExpressions,removeProbe,removeWatchExpression,resolveSourceLocation,setExceptionBreakpoint,toJson,warn}from"./core-S5JHUB3Z.js";var fts5_strategy_exports={};__export(fts5_strategy_exports,{Fts5Strategy:()=>Fts5Strategy});import{createRequire as createRequire2}from"node:module";function _loadBetterSqlite3(){try{return require3("better-sqlite3")}catch{throw new Error("better-sqlite3 is not installed. Install it with: npm install better-sqlite3")}}var require3,Fts5Strategy,init_fts5_strategy=__esm({"src/search/strategies/fts5-strategy.ts"(){"use strict";require3=createRequire2(import.meta.url);Fts5Strategy=class{_db;_fieldNames=[];_initialized=!1;constructor(){let BetterSqlite3=_loadBetterSqlite3();this._db=new BetterSqlite3(":memory:")}_bm25Weights="";_ensureTable(fields){if(this._initialized)return;this._fieldNames=Object.keys(fields);let columns=this._fieldNames.join(", ");this._db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS documents USING fts5(id, ${columns}, tokenize='porter unicode61')`);let weights=[0,...this._fieldNames.map((_,i)=>i===0?5:1)];this._bm25Weights=weights.join(", "),this._initialized=!0}index(documents){if(documents.length===0)return;this._ensureTable(documents[0].fields);let columns=["id",...this._fieldNames].join(", "),placeholders=["id",...this._fieldNames].map(()=>"?").join(", "),stmt=this._db.prepare(`INSERT INTO documents (${columns}) VALUES (${placeholders})`);this._db.exec("BEGIN");try{for(let doc of documents){let values=[doc.id,...this._fieldNames.map(f=>doc.fields[f]??"")];stmt.run(...values)}this._db.exec("COMMIT")}catch(err){throw this._db.exec("ROLLBACK"),err}}add(document2){this._ensureTable(document2.fields);let columns=["id",...this._fieldNames].join(", "),placeholders=["id",...this._fieldNames].map(()=>"?").join(", "),values=[document2.id,...this._fieldNames.map(f=>document2.fields[f]??"")];this._db.prepare(`INSERT INTO documents (${columns}) VALUES (${placeholders})`).run(...values)}update(id,document2){this.remove(id),this.add(document2)}remove(id){this._initialized&&this._db.prepare("DELETE FROM documents WHERE id = ?").run(id)}search(query,limit){if(!this._initialized||!query.trim())return[];let FTS5_RESERVED=new Set(["AND","OR","NOT","NEAR"]),tokens=query.replace(/['"\[\]{}\*:^~()\-]/g," ").split(/\s+/).filter(t=>t.length>0&&!FTS5_RESERVED.has(t.toUpperCase()));if(tokens.length===0)return[];let ftsQuery=tokens.map(t=>`"${t}"`).join(" OR "),safeLimit=limit?Math.max(1,Math.floor(limit)):100;return this._db.prepare(`SELECT id, bm25(documents, ${this._bm25Weights}) AS rank FROM documents WHERE documents MATCH ? ORDER BY rank LIMIT ?`).all(ftsQuery,safeLimit).map(row=>({id:row.id,score:-row.rank}))}close(){this._db.close()}}}});var minisearch_strategy_exports={};__export(minisearch_strategy_exports,{MiniSearchStrategy:()=>MiniSearchStrategy});import MiniSearch from"minisearch";import{stemmer}from"stemmer";var MiniSearchStrategy,init_minisearch_strategy=__esm({"src/search/strategies/minisearch-strategy.ts"(){"use strict";init_logger();MiniSearchStrategy=class{_index;_fieldNames=[];constructor(){this._index=this._createIndex([])}_createIndex(fieldNames){return new MiniSearch({fields:fieldNames,storeFields:[],processTerm:term=>stemmer(term.toLowerCase()),searchOptions:{fuzzy:.2,prefix:!0}})}_ensureFields(fields){let names=Object.keys(fields);names.some(n=>!this._fieldNames.includes(n))&&(this._fieldNames.length===0?(this._fieldNames=names,this._index=this._createIndex(this._fieldNames)):debug(`minisearch: document has new fields [${names.join(", ")}] not in index [${this._fieldNames.join(", ")}] \u2014 extra fields ignored`))}index(documents){if(documents.length===0)return;this._ensureFields(documents[0].fields);let docs=documents.map(doc=>({id:doc.id,...doc.fields}));this._index.addAll(docs)}add(document2){this._ensureFields(document2.fields),this._index.add({id:document2.id,...document2.fields})}update(id,document2){try{this._index.discard(id)}catch{}this._index.add({id:document2.id,...document2.fields})}remove(id){try{this._index.discard(id)}catch{}}search(query,limit){let results=this._index.search(query);return(limit?results.slice(0,limit):results).map(r=>({id:r.id,score:r.score}))}close(){}}}});import{z}from"zod";function augmentToolInputSchema(shape){if(!TOOL_INPUT_METADATA_ENABLE)return shape;let extra={};return Object.prototype.hasOwnProperty.call(shape,"_metadata")||(extra._metadata=z.object({projectName:z.string().optional(),sessionId:z.string().optional(),verificationId:z.string().optional(),traceId:z.string().optional(),traceState:z.string().optional(),collectorUrl:z.string().optional(),collectorApiKey:z.string().optional()}).catchall(z.unknown()).optional()),Object.keys(extra).length===0?shape:{...shape,...extra}}import{z as z2,ZodError}from"zod";function formatZodError(err){return"Validation failed: "+err.issues.map(issue=>(issue.path.length?issue.path.join(".")+": ":"")+issue.message).join("; ")}var ToolRegistry=class{tools=new Map;addTool(tool){if(this.tools.has(tool.name()))throw new Error(`Tool already registered: ${tool.name()}`);this.tools.set(tool.name(),{tool,inputSchema:z2.object(augmentToolInputSchema(tool.inputSchema())).strict(),outputSchema:z2.object(tool.outputSchema()).strict()})}async runTool(context,toolName,toolArgs){let canonicalKey=denormalizeToolName(toolName),toolDef=this.tools.get(canonicalKey);if(!toolDef)throw new Error(`Tool not found: ${toolName}`);let parsedToolArgs;try{parsedToolArgs=await toolDef.inputSchema.parseAsync(toolArgs)}catch(e){throw e instanceof ZodError?new Error(formatZodError(e)):e}let rawToolResult=await toolDef.tool.handle(context,parsedToolArgs);return await toolDef.outputSchema.parseAsync(rawToolResult)}};function isToolEnabled(tool){return tool.isEnabled?.()??!0}init_logger();import fs from"node:fs";import os from"node:os";import path from"node:path";var DIR_NAME=".browser-devtools-mcp",FILE_NAME="scenarios.json";function _scenariosPath(scope){let baseDir=scope==="project"?WORKING_DIR:os.homedir();return path.join(baseDir,DIR_NAME,FILE_NAME)}function _isValidScenario(value){return typeof value=="object"&&value!==null&&typeof value.name=="string"&&typeof value.description=="string"&&typeof value.script=="string"}function _readFile(filePath){try{if(!fs.existsSync(filePath))return{};let content=fs.readFileSync(filePath,"utf-8"),parsed=JSON.parse(content);if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return debug(`scenario-store: invalid format in ${filePath}, expected object`),{};let result={};for(let[key,value]of Object.entries(parsed))_isValidScenario(value)?result[key]=value:debug(`scenario-store: skipping invalid scenario "${key}" in ${filePath}`);return result}catch(err){return debug(`scenario-store: failed to read ${filePath}: ${err}`),{}}}function _writeFile(filePath,scenarios){let dir=path.dirname(filePath);fs.existsSync(dir)||fs.mkdirSync(dir,{recursive:!0}),fs.writeFileSync(filePath,JSON.stringify(scenarios,null,2),"utf-8")}function _validateName(name){if(!name||name.length>200)throw new Error("Scenario name must be between 1 and 200 characters");if(/[/\\:*?"<>|.]/.test(name)||name.includes(".."))throw new Error('Scenario name contains invalid characters (no /, \\, :, *, ?, ", <, >, |, .)')}var _fileLocks=new Map;function _withFileLock(filePath,fn){let prev=_fileLocks.get(filePath)??Promise.resolve(),resolve,next=new Promise(r=>{resolve=r});_fileLocks.set(filePath,next);let result;try{result=fn()}finally{resolve()}return result}var ScenarioStore=class{_scope;_filePath;constructor(scope){this._scope=scope,this._filePath=_scenariosPath(scope)}get(name){return _readFile(this._filePath)[name]}add(scenario){_validateName(scenario.name),_withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath);if(scenarios[scenario.name])throw new Error(`Scenario "${scenario.name}" already exists in ${this._scope} scope`);scenarios[scenario.name]=scenario,_writeFile(this._filePath,scenarios)})}update(name,updates){return _validateName(name),_withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath),existing=scenarios[name];if(!existing)throw new Error(`Scenario "${name}" not found in ${this._scope} scope`);let updated={...existing,...updates,name};return scenarios[name]=updated,_writeFile(this._filePath,scenarios),updated})}delete(name){return _withFileLock(this._filePath,()=>{let scenarios=_readFile(this._filePath);return scenarios[name]?(delete scenarios[name],_writeFile(this._filePath,scenarios),!0):!1})}list(){let scenarios=_readFile(this._filePath);return Object.values(scenarios)}getAll(){return _readFile(this._filePath)}};function resolveScenario(name){let projectScenario=new ScenarioStore("project").get(name);return projectScenario||new ScenarioStore("global").get(name)}function listAllScenarios(){let globalStore=new ScenarioStore("global"),projectStore=new ScenarioStore("project"),merged={...globalStore.getAll(),...projectStore.getAll()};return Object.values(merged)}import{z as z3}from"zod";var MAX_RECURSION_DEPTH=5,ScenarioRun=class{_toolRegistry;constructor(toolRegistry){this._toolRegistry=toolRegistry}name(){return"scenario-run"}description(){return`
2
2
  Runs a saved scenario by name. Looks up the scenario in project scope first, then global.
3
3
  The scenario's JS script runs in the same sandbox as <execute>: callTool(), console, sleep are available.
4
4
  Scenarios can compose other scenarios via callTool('scenario-run', { name: '...' }).
@@ -268,10 +268,10 @@ Starts video recording of the browser page.
268
268
  Recording captures all page interactions until <content_stop-recording> is called.
269
269
  Uses CDP screencast \u2014 works in all modes (headless, headed, persistent, CDP attach).
270
270
  Only supported on Chromium-based browsers.
271
- `.trim()}inputSchema(){return{outputDir:z9.string().optional().default(os3.tmpdir()).describe("Directory where the video file will be saved."),name:z9.string().optional().describe('Name for the video file (without extension). Defaults to "recording".')}}outputSchema(){return{message:z9.string().describe("Status message.")}}async handle(context,args){return context.isRecording()?{message:"Recording is already in progress."}:(await context.startRecording({outputDir:args.outputDir??os3.tmpdir(),name:args.name}),{message:"Recording started."})}};import{z as z10}from"zod";var StopRecording=class{name(){return"content_stop-recording"}description(){return`
271
+ `.trim()}inputSchema(){return{outputDir:z9.string().optional().default(os3.tmpdir()).describe("Directory where the video file will be saved."),name:z9.string().optional().describe('Name for the video file (without extension). Defaults to "recording".')}}outputSchema(){return{message:z9.string().describe("Status message.")}}async handle(context,args){return context.isRecording()?{message:"Recording is already in progress."}:(await context.startRecording({outputDir:args.outputDir??os3.tmpdir(),name:args.name}),{message:"Recording started."})}};init_logger();import{z as z10}from"zod";var StopRecording=class{name(){return"content_stop-recording"}description(){return`
272
272
  Stops video recording of the browser page and saves the video file.
273
273
  Must be called after <content_start-recording>. The video is saved as a WebM file.
274
- `.trim()}inputSchema(){return{}}outputSchema(){return{filePath:z10.string().optional().describe("Full path of the saved video file.")}}async handle(context,_args){if(!context.isRecording())return{};let result=await context.stopRecording();if(!result)return{};let artifacts=[{type:"VIDEO",filePath:result.filePath,mimeType:"video/webm"}];return{filePath:result.filePath,_artifacts:artifacts}}};var REF_ROLES_INTERACTIVE=new Set(["button","link","textbox","searchbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","slider","spinbutton","switch","tab","tabpanel","treeitem","listitem","row","cell","gridcell","columnheader","rowheader","separator","dialog","alertdialog","clickable","focusable"]);function parseQuotedString(s,i){let q=s[i];if(q!=="'"&&q!=='"')return null;let j=i+1,parts=[];for(;j<s.length;){let c=s[j];if(c==="\\"){j++,j<s.length&&parts.push(s[j]),j++;continue}if(c===q)return{value:parts.join(""),end:j+1};parts.push(c),j++}return null}function parseRegexLiteral(s,i){if(s[i]!=="/")return null;let j=i+1;for(;j<s.length;){if(s[j]==="\\"){j+=2;continue}if(s[j]==="/")break;j++}if(j>=s.length)return null;let pattern=s.slice(i+1,j);j++;let flags="";for(;j<s.length&&/[gimsuy]/.test(s[j])&&!flags.includes(s[j]);)flags+=s[j],j++;try{return{value:new RegExp(pattern,flags),end:j}}catch{return null}}function parseOptionsObject(s,i){for(;i<s.length&&/\s/.test(s[i]);)i++;if(s[i]!=="{")return null;i++;let obj={};for(;i<s.length;){for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;if(s[i]==="}")return{value:obj,end:i+1};let keyMatch=s.slice(i).match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:/);if(!keyMatch)return null;let key=keyMatch[1];for(i+=keyMatch[0].length;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;if(s[i]==="'"||s[i]==='"'){let parsed=parseQuotedString(s,i);if(!parsed)return null;obj[key]=parsed.value,i=parsed.end}else if(s[i]==="/"){let parsed=parseRegexLiteral(s,i);if(!parsed)return null;obj[key]=parsed.value,i=parsed.end}else if(s.slice(i).startsWith("true"))obj[key]=!0,i+=4;else if(s.slice(i).startsWith("false"))obj[key]=!1,i+=5;else{let numMatch=s.slice(i).match(/^-?\d+/);if(numMatch)obj[key]=parseInt(numMatch[0],10),i+=numMatch[0].length;else return null}for(;i<s.length&&/\s/.test(s[i]);)i++;if(i<s.length&&s[i]===","){i++;continue}break}for(;i<s.length&&/\s/.test(s[i]);)i++;return s[i]!=="}"?null:{value:obj,end:i+1}}function parseGetByArgs(inner){let s=inner.trim(),i=0;for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;let first;if(s[i]==="'"||s[i]==='"'){let firstParsed=parseQuotedString(s,i);if(!firstParsed)return null;first=firstParsed.value,i=firstParsed.end}else if(s[i]==="/"){let regexParsed=parseRegexLiteral(s,i);if(!regexParsed)return null;first=regexParsed.value,i=regexParsed.end}else return null;for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return{first};if(s[i]!==",")return{first};i++;let optParsed=parseOptionsObject(s,i);return optParsed?{first,options:optParsed.value}:{first}}function tryParsePlaywrightLocatorExpression(page,selectorOrExpression){let match=selectorOrExpression.trim().match(/^\s*(getByRole|getByLabel|getByText|getByPlaceholder|getByAltText|getByTitle|getByTestId)\s*\(\s*([\s\S]*)\s*\)\s*$/);if(!match)return null;let method=match[1],argsInner=match[2],parsed=parseGetByArgs(argsInner);if(!parsed)return null;let{first,options}=parsed;if(method==="getByTestId")return page.getByTestId(first).first();if(method==="getByRole"){if(typeof first!="string")return null;let opts=options??{},roleOpts={};return opts.name!==void 0&&(roleOpts.name=typeof opts.name=="string"||opts.name instanceof RegExp?opts.name:String(opts.name)),opts.exact!==void 0&&(roleOpts.exact=!!opts.exact),opts.checked!==void 0&&(roleOpts.checked=!!opts.checked),opts.disabled!==void 0&&(roleOpts.disabled=!!opts.disabled),opts.expanded!==void 0&&(roleOpts.expanded=!!opts.expanded),opts.includeHidden!==void 0&&(roleOpts.includeHidden=!!opts.includeHidden),opts.level!==void 0&&(roleOpts.level=Number(opts.level)),opts.pressed!==void 0&&(roleOpts.pressed=!!opts.pressed),opts.selected!==void 0&&(roleOpts.selected=!!opts.selected),page.getByRole(first,Object.keys(roleOpts).length>0?roleOpts:void 0).first()}let exactOpts=options&&options.exact!==void 0?{exact:!!options.exact}:void 0;switch(method){case"getByLabel":return page.getByLabel(first,exactOpts).first();case"getByText":return page.getByText(first,exactOpts).first();case"getByPlaceholder":return page.getByPlaceholder(first,exactOpts).first();case"getByAltText":return page.getByAltText(first,exactOpts).first();case"getByTitle":return page.getByTitle(first,exactOpts).first();default:return null}}function parseRef(arg){let s=arg.trim();return s.startsWith("@")?s.slice(1):s.toLowerCase().startsWith("ref=")?s.slice(4):/^e\d+$/.test(s)?s:null}function getLocatorFromRef(page,refMap,ref){let data=refMap[ref];if(!data)return null;if(data.role==="clickable"||data.role==="focusable"){let locator2=page.locator(data.selector);return data.nth!==void 0?locator2.nth(data.nth):locator2.first()}let locator;return data.name!==void 0&&data.name!==""?locator=page.getByRole(data.role,{name:data.name,exact:!0}):locator=page.getByRole(data.role),data.nth!==void 0?locator.nth(data.nth):locator.first()}function assertRefRole(context,selectorOrRef,allowedRoles,actionLabel,hint){let ref=parseRef(selectorOrRef),refMap=context.getRefMap();if(!ref||!refMap[ref])return;let entry=refMap[ref];if(allowedRoles.has(entry.role))return;let namePart=entry.name?` "${entry.name}"`:"";throw new Error(`Ref ${ref} points to a ${entry.role}${namePart}, which is not valid for ${actionLabel}. ${hint}`)}function resolveSelectorOrRef(context,selectorOrRef){let ref=parseRef(selectorOrRef),refMap=context.getRefMap();if(ref&&Object.keys(refMap).length>0){let locator=getLocatorFromRef(context.page,refMap,ref);if(locator)return locator}let playwrightLocator=tryParsePlaywrightLocatorExpression(context.page,selectorOrRef);return playwrightLocator||context.page.locator(selectorOrRef).first()}import jpegjs from"jpeg-js";import{PNG}from"pngjs";var ANNOTATION_OVERLAY_ID="__browser_devtools_mcp_annotations__",ANNOTATE_BOX_TIMEOUT_MS=2e3,ScreenshotType=(ScreenshotType2=>(ScreenshotType2.PNG="png",ScreenshotType2.JPEG="jpeg",ScreenshotType2))(ScreenshotType||{}),MAX_BUFFER_SIZE=800*1024,MAX_PIXELS=1.15*1024*1024,MAX_LINEAR_SIZE=1568;function scaleImageToSize(image,size){let{data:src,width:w1,height:h1}=image,w2=Math.max(1,Math.floor(size.width)),h2=Math.max(1,Math.floor(size.height));if(w1===w2&&h1===h2)return image;if(w1<=0||h1<=0)throw new Error("Invalid input image");if(size.width<=0||size.height<=0||!isFinite(size.width)||!isFinite(size.height))throw new Error("Invalid output dimensions");let clamp=(v,lo,hi)=>v<lo?lo:v>hi?hi:v,weights=(t,o)=>{let t2=t*t,t3=t2*t;o[0]=-.5*t+1*t2-.5*t3,o[1]=1-2.5*t2+1.5*t3,o[2]=.5*t+2*t2-1.5*t3,o[3]=-.5*t2+.5*t3},srcRowStride=w1*4,dstRowStride=w2*4,xOff=new Int32Array(w2*4),xW=new Float32Array(w2*4),wx=new Float32Array(4),xScale=w1/w2;for(let x=0;x<w2;x++){let sx=(x+.5)*xScale-.5,sxi=Math.floor(sx),t=sx-sxi;weights(t,wx);let b=x*4,i0=clamp(sxi-1,0,w1-1),i1=clamp(sxi+0,0,w1-1),i2=clamp(sxi+1,0,w1-1),i3=clamp(sxi+2,0,w1-1);xOff[b+0]=i0<<2,xOff[b+1]=i1<<2,xOff[b+2]=i2<<2,xOff[b+3]=i3<<2,xW[b+0]=wx[0],xW[b+1]=wx[1],xW[b+2]=wx[2],xW[b+3]=wx[3]}let yRow=new Int32Array(h2*4),yW=new Float32Array(h2*4),wy=new Float32Array(4),yScale=h1/h2;for(let y=0;y<h2;y++){let sy=(y+.5)*yScale-.5,syi=Math.floor(sy),t=sy-syi;weights(t,wy);let b=y*4,j0=clamp(syi-1,0,h1-1),j1=clamp(syi+0,0,h1-1),j2=clamp(syi+1,0,h1-1),j3=clamp(syi+2,0,h1-1);yRow[b+0]=j0*srcRowStride,yRow[b+1]=j1*srcRowStride,yRow[b+2]=j2*srcRowStride,yRow[b+3]=j3*srcRowStride,yW[b+0]=wy[0],yW[b+1]=wy[1],yW[b+2]=wy[2],yW[b+3]=wy[3]}let dst=new Uint8Array(w2*h2*4);for(let y=0;y<h2;y++){let yb=y*4,rb0=yRow[yb+0],rb1=yRow[yb+1],rb2=yRow[yb+2],rb3=yRow[yb+3],wy0=yW[yb+0],wy1=yW[yb+1],wy2=yW[yb+2],wy3=yW[yb+3],dstBase=y*dstRowStride;for(let x=0;x<w2;x++){let xb=x*4,xo0=xOff[xb+0],xo1=xOff[xb+1],xo2=xOff[xb+2],xo3=xOff[xb+3],wx0=xW[xb+0],wx1=xW[xb+1],wx2=xW[xb+2],wx3=xW[xb+3],di=dstBase+(x<<2);for(let c=0;c<4;c++){let r0=src[rb0+xo0+c]*wx0+src[rb0+xo1+c]*wx1+src[rb0+xo2+c]*wx2+src[rb0+xo3+c]*wx3,r1=src[rb1+xo0+c]*wx0+src[rb1+xo1+c]*wx1+src[rb1+xo2+c]*wx2+src[rb1+xo3+c]*wx3,r2=src[rb2+xo0+c]*wx0+src[rb2+xo1+c]*wx1+src[rb2+xo2+c]*wx2+src[rb2+xo3+c]*wx3,r3=src[rb3+xo0+c]*wx0+src[rb3+xo1+c]*wx1+src[rb3+xo2+c]*wx2+src[rb3+xo3+c]*wx3,v=r0*wy0+r1*wy1+r2*wy2+r3*wy3;dst[di+c]=v<0?0:v>255?255:v|0}}}return{data:Buffer.from(dst.buffer),width:w2,height:h2}}function scaleImageToFitMessage(buffer,screenshotType){let image=screenshotType==="png"?PNG.sync.read(buffer):jpegjs.decode(buffer,{maxMemoryUsageInMB:512}),pixels=image.width*image.height,shrink=Math.min(MAX_LINEAR_SIZE/image.width,MAX_LINEAR_SIZE/image.height,Math.sqrt(MAX_PIXELS/pixels));shrink>1&&(shrink=1);let width=image.width*shrink|0,height=image.height*shrink|0,scaledImage=scaleImageToSize(image,{width,height}),quality=screenshotType==="png"?75:70,result=screenshotType==="png"?jpegjs.encode(scaledImage,quality).data:jpegjs.encode(scaledImage,quality).data,iterations=0,MAX_ITERATIONS=5;for(;result.length>MAX_BUFFER_SIZE&&iterations<MAX_ITERATIONS;)quality=Math.max(50,quality-10),quality<=50&&result.length>MAX_BUFFER_SIZE&&(shrink*=.85,width=Math.max(200,image.width*shrink|0),height=Math.max(200,image.height*shrink|0),scaledImage=scaleImageToSize(image,{width,height})),result=jpegjs.encode(scaledImage,quality).data,iterations++;return result}async function captureScreenshot(context,options){let fullPage=options.fullPage??!1,screenshotType=options.type??"png",annotate=options.annotate??!1,annotateContent=options.annotateContent??!1,annotateCursorInteractive=options.annotateCursorInteractive??!1,quality=options.quality??(screenshotType==="png"?void 0:100),overlayInjected=!1,annotations,scopedElement=null;if(options.selector&&(scopedElement=await resolveSelectorOrRef(context,options.selector).elementHandle({timeout:1e4}),!scopedElement))throw new Error(`Element not found: ${options.selector}`);if(annotate){let refMap=context.getRefMap(),wantContent=annotateContent,wantCursorInteractive=annotateCursorInteractive;if(Object.keys(refMap).length===0||wantCursorInteractive||wantContent){let raw=await context.page.locator("body").ariaSnapshot(),{refs}=processAriaTreeWithRefs(raw,{interactiveOnly:!wantContent}),mergedRefs={...refs};if(wantCursorInteractive){let cursorEntries=await findCursorInteractiveElements(context.page,null);if(cursorEntries.length>0){let maxNum=Object.keys(mergedRefs).reduce((m,k)=>Math.max(m,parseInt(k.replace(/^e/,""),10)||0),0);cursorEntries.forEach((entry,i)=>{mergedRefs[`e${maxNum+1+i}`]={role:entry.role,name:entry.name,selector:entry.selector,nth:entry.nth}})}}context.setRefMap(mergedRefs),refMap=mergedRefs}let entries=Object.entries(refMap),allBoxes=[];for(let[ref,data]of entries){let locator=getLocatorFromRef(context.page,refMap,ref);if(!locator)continue;let box=await locator.boundingBox({timeout:ANNOTATE_BOX_TIMEOUT_MS}).catch(()=>null);if(!box||box.width===0||box.height===0)continue;let num=parseInt(ref.replace(/^e/,""),10)||0;allBoxes.push({ref,number:num,role:data.role,name:data.name,box:{x:Math.round(box.x),y:Math.round(box.y),width:Math.round(box.width),height:Math.round(box.height)}})}allBoxes.sort((a,b)=>a.number-b.number);let boxes=allBoxes,overlayBoxesViewport=allBoxes;if(scopedElement){let elementBox=await scopedElement.boundingBox();if(elementBox&&elementBox.width>0&&elementBox.height>0){let overlapping=allBoxes.filter(a=>{let b=a.box;return b.x<elementBox.x+elementBox.width&&b.x+b.width>elementBox.x&&b.y<elementBox.y+elementBox.height&&b.y+b.height>elementBox.y});overlayBoxesViewport=overlapping,boxes=overlapping.map(a=>{let b=a.box,relX=Math.max(0,b.x-elementBox.x),relY=Math.max(0,b.y-elementBox.y),relRight=Math.min(b.x+b.width-elementBox.x,elementBox.width),relBottom=Math.min(b.y+b.height-elementBox.y,elementBox.height);return{...a,box:{x:Math.round(relX),y:Math.round(relY),width:Math.round(Math.max(0,relRight-relX)),height:Math.round(Math.max(0,relBottom-relY))}}})}}if(boxes.length>0){let overlayPayload={data:overlayBoxesViewport.map(a=>({number:a.number,x:a.box.x,y:a.box.y,width:a.box.width,height:a.box.height})),id:ANNOTATION_OVERLAY_ID};if(await context.page.evaluate(({data,id})=>{let sx=window.scrollX||0,sy=window.scrollY||0,c=document.createElement("div");c.id=id,c.style.cssText="position:absolute;top:0;left:0;width:0;height:0;pointer-events:none;z-index:2147483647;";for(let it of data){let dx=it.x+sx,dy=it.y+sy,b=document.createElement("div");b.style.cssText=`position:absolute;left:${dx}px;top:${dy}px;width:${it.width}px;height:${it.height}px;border:2px solid rgba(255,0,0,0.8);box-sizing:border-box;pointer-events:none;`;let l=document.createElement("div");l.textContent=String(it.number);let labelTop=dy<14?"2px":"-14px";l.style.cssText=`position:absolute;top:${labelTop};left:-2px;background:rgba(255,0,0,0.9);color:#fff;font:bold 11px/14px monospace;padding:0 4px;border-radius:2px;white-space:nowrap;`,b.appendChild(l),c.appendChild(b)}document.documentElement.appendChild(c)},overlayPayload),overlayInjected=!0,fullPage&&!scopedElement&&boxes.length>0){let scroll=await context.page.evaluate(()=>({x:window.scrollX||0,y:window.scrollY||0}));annotations=boxes.map(a=>({...a,box:{x:a.box.x+scroll.x,y:a.box.y+scroll.y,width:a.box.width,height:a.box.height}}))}else annotations=boxes}}try{let screenshotOptions={type:screenshotType,fullPage,quality};scopedElement&&(screenshotOptions.element=scopedElement);let rawBuffer=await context.page.screenshot(screenshotOptions),scaledBuffer=scaleImageToFitMessage(rawBuffer,screenshotType);return{rawBuffer,image:{data:scaledBuffer,mimeType:`image/${screenshotType}`},annotations,screenshotType}}finally{overlayInjected&&await context.page.evaluate(id=>{let el=document.getElementById(id);el&&el.remove()},ANNOTATION_OVERLAY_ID).catch(()=>{})}}import fs5 from"node:fs/promises";import os4 from"node:os";import path5 from"node:path";import{z as z11}from"zod";var DEFAULT_SCREENSHOT_NAME="screenshot",DEFAULT_SCREENSHOT_TYPE="png",DEFAULT_SCREENSHOT_QUALITY=100,TakeScreenshot=class{name(){return"content_take-screenshot"}description(){return`
274
+ `.trim()}inputSchema(){return{}}outputSchema(){return{filePath:z10.string().optional().describe("Full path of the saved video file.")}}async handle(context,_args){if(!context.isRecording())return debug("stop-recording: isRecording() returned false"),{};let result=await context.stopRecording();if(!result)return debug("stop-recording: stopRecording() returned undefined"),{};let artifacts=[{type:"VIDEO",filePath:result.filePath,mimeType:"video/webm"}];return{filePath:result.filePath,_artifacts:artifacts}}};var REF_ROLES_INTERACTIVE=new Set(["button","link","textbox","searchbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","slider","spinbutton","switch","tab","tabpanel","treeitem","listitem","row","cell","gridcell","columnheader","rowheader","separator","dialog","alertdialog","clickable","focusable"]);function parseQuotedString(s,i){let q=s[i];if(q!=="'"&&q!=='"')return null;let j=i+1,parts=[];for(;j<s.length;){let c=s[j];if(c==="\\"){j++,j<s.length&&parts.push(s[j]),j++;continue}if(c===q)return{value:parts.join(""),end:j+1};parts.push(c),j++}return null}function parseRegexLiteral(s,i){if(s[i]!=="/")return null;let j=i+1;for(;j<s.length;){if(s[j]==="\\"){j+=2;continue}if(s[j]==="/")break;j++}if(j>=s.length)return null;let pattern=s.slice(i+1,j);j++;let flags="";for(;j<s.length&&/[gimsuy]/.test(s[j])&&!flags.includes(s[j]);)flags+=s[j],j++;try{return{value:new RegExp(pattern,flags),end:j}}catch{return null}}function parseOptionsObject(s,i){for(;i<s.length&&/\s/.test(s[i]);)i++;if(s[i]!=="{")return null;i++;let obj={};for(;i<s.length;){for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;if(s[i]==="}")return{value:obj,end:i+1};let keyMatch=s.slice(i).match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:/);if(!keyMatch)return null;let key=keyMatch[1];for(i+=keyMatch[0].length;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;if(s[i]==="'"||s[i]==='"'){let parsed=parseQuotedString(s,i);if(!parsed)return null;obj[key]=parsed.value,i=parsed.end}else if(s[i]==="/"){let parsed=parseRegexLiteral(s,i);if(!parsed)return null;obj[key]=parsed.value,i=parsed.end}else if(s.slice(i).startsWith("true"))obj[key]=!0,i+=4;else if(s.slice(i).startsWith("false"))obj[key]=!1,i+=5;else{let numMatch=s.slice(i).match(/^-?\d+/);if(numMatch)obj[key]=parseInt(numMatch[0],10),i+=numMatch[0].length;else return null}for(;i<s.length&&/\s/.test(s[i]);)i++;if(i<s.length&&s[i]===","){i++;continue}break}for(;i<s.length&&/\s/.test(s[i]);)i++;return s[i]!=="}"?null:{value:obj,end:i+1}}function parseGetByArgs(inner){let s=inner.trim(),i=0;for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return null;let first;if(s[i]==="'"||s[i]==='"'){let firstParsed=parseQuotedString(s,i);if(!firstParsed)return null;first=firstParsed.value,i=firstParsed.end}else if(s[i]==="/"){let regexParsed=parseRegexLiteral(s,i);if(!regexParsed)return null;first=regexParsed.value,i=regexParsed.end}else return null;for(;i<s.length&&/\s/.test(s[i]);)i++;if(i>=s.length)return{first};if(s[i]!==",")return{first};i++;let optParsed=parseOptionsObject(s,i);return optParsed?{first,options:optParsed.value}:{first}}function tryParsePlaywrightLocatorExpression(page,selectorOrExpression){let match=selectorOrExpression.trim().match(/^\s*(getByRole|getByLabel|getByText|getByPlaceholder|getByAltText|getByTitle|getByTestId)\s*\(\s*([\s\S]*)\s*\)\s*$/);if(!match)return null;let method=match[1],argsInner=match[2],parsed=parseGetByArgs(argsInner);if(!parsed)return null;let{first,options}=parsed;if(method==="getByTestId")return page.getByTestId(first).first();if(method==="getByRole"){if(typeof first!="string")return null;let opts=options??{},roleOpts={};return opts.name!==void 0&&(roleOpts.name=typeof opts.name=="string"||opts.name instanceof RegExp?opts.name:String(opts.name)),opts.exact!==void 0&&(roleOpts.exact=!!opts.exact),opts.checked!==void 0&&(roleOpts.checked=!!opts.checked),opts.disabled!==void 0&&(roleOpts.disabled=!!opts.disabled),opts.expanded!==void 0&&(roleOpts.expanded=!!opts.expanded),opts.includeHidden!==void 0&&(roleOpts.includeHidden=!!opts.includeHidden),opts.level!==void 0&&(roleOpts.level=Number(opts.level)),opts.pressed!==void 0&&(roleOpts.pressed=!!opts.pressed),opts.selected!==void 0&&(roleOpts.selected=!!opts.selected),page.getByRole(first,Object.keys(roleOpts).length>0?roleOpts:void 0).first()}let exactOpts=options&&options.exact!==void 0?{exact:!!options.exact}:void 0;switch(method){case"getByLabel":return page.getByLabel(first,exactOpts).first();case"getByText":return page.getByText(first,exactOpts).first();case"getByPlaceholder":return page.getByPlaceholder(first,exactOpts).first();case"getByAltText":return page.getByAltText(first,exactOpts).first();case"getByTitle":return page.getByTitle(first,exactOpts).first();default:return null}}function parseRef(arg){let s=arg.trim();return s.startsWith("@")?s.slice(1):s.toLowerCase().startsWith("ref=")?s.slice(4):/^e\d+$/.test(s)?s:null}function getLocatorFromRef(page,refMap,ref){let data=refMap[ref];if(!data)return null;if(data.role==="clickable"||data.role==="focusable"){let locator2=page.locator(data.selector);return data.nth!==void 0?locator2.nth(data.nth):locator2.first()}let locator;return data.name!==void 0&&data.name!==""?locator=page.getByRole(data.role,{name:data.name,exact:!0}):locator=page.getByRole(data.role),data.nth!==void 0?locator.nth(data.nth):locator.first()}function assertRefRole(context,selectorOrRef,allowedRoles,actionLabel,hint){let ref=parseRef(selectorOrRef),refMap=context.getRefMap();if(!ref||!refMap[ref])return;let entry=refMap[ref];if(allowedRoles.has(entry.role))return;let namePart=entry.name?` "${entry.name}"`:"";throw new Error(`Ref ${ref} points to a ${entry.role}${namePart}, which is not valid for ${actionLabel}. ${hint}`)}function resolveSelectorOrRef(context,selectorOrRef){let ref=parseRef(selectorOrRef),refMap=context.getRefMap();if(ref&&Object.keys(refMap).length>0){let locator=getLocatorFromRef(context.page,refMap,ref);if(locator)return locator}let playwrightLocator=tryParsePlaywrightLocatorExpression(context.page,selectorOrRef);return playwrightLocator||context.page.locator(selectorOrRef).first()}import jpegjs from"jpeg-js";import{PNG}from"pngjs";var ANNOTATION_OVERLAY_ID="__browser_devtools_mcp_annotations__",ANNOTATE_BOX_TIMEOUT_MS=2e3,ScreenshotType=(ScreenshotType2=>(ScreenshotType2.PNG="png",ScreenshotType2.JPEG="jpeg",ScreenshotType2))(ScreenshotType||{}),MAX_BUFFER_SIZE=800*1024,MAX_PIXELS=1.15*1024*1024,MAX_LINEAR_SIZE=1568;function scaleImageToSize(image,size){let{data:src,width:w1,height:h1}=image,w2=Math.max(1,Math.floor(size.width)),h2=Math.max(1,Math.floor(size.height));if(w1===w2&&h1===h2)return image;if(w1<=0||h1<=0)throw new Error("Invalid input image");if(size.width<=0||size.height<=0||!isFinite(size.width)||!isFinite(size.height))throw new Error("Invalid output dimensions");let clamp=(v,lo,hi)=>v<lo?lo:v>hi?hi:v,weights=(t,o)=>{let t2=t*t,t3=t2*t;o[0]=-.5*t+1*t2-.5*t3,o[1]=1-2.5*t2+1.5*t3,o[2]=.5*t+2*t2-1.5*t3,o[3]=-.5*t2+.5*t3},srcRowStride=w1*4,dstRowStride=w2*4,xOff=new Int32Array(w2*4),xW=new Float32Array(w2*4),wx=new Float32Array(4),xScale=w1/w2;for(let x=0;x<w2;x++){let sx=(x+.5)*xScale-.5,sxi=Math.floor(sx),t=sx-sxi;weights(t,wx);let b=x*4,i0=clamp(sxi-1,0,w1-1),i1=clamp(sxi+0,0,w1-1),i2=clamp(sxi+1,0,w1-1),i3=clamp(sxi+2,0,w1-1);xOff[b+0]=i0<<2,xOff[b+1]=i1<<2,xOff[b+2]=i2<<2,xOff[b+3]=i3<<2,xW[b+0]=wx[0],xW[b+1]=wx[1],xW[b+2]=wx[2],xW[b+3]=wx[3]}let yRow=new Int32Array(h2*4),yW=new Float32Array(h2*4),wy=new Float32Array(4),yScale=h1/h2;for(let y=0;y<h2;y++){let sy=(y+.5)*yScale-.5,syi=Math.floor(sy),t=sy-syi;weights(t,wy);let b=y*4,j0=clamp(syi-1,0,h1-1),j1=clamp(syi+0,0,h1-1),j2=clamp(syi+1,0,h1-1),j3=clamp(syi+2,0,h1-1);yRow[b+0]=j0*srcRowStride,yRow[b+1]=j1*srcRowStride,yRow[b+2]=j2*srcRowStride,yRow[b+3]=j3*srcRowStride,yW[b+0]=wy[0],yW[b+1]=wy[1],yW[b+2]=wy[2],yW[b+3]=wy[3]}let dst=new Uint8Array(w2*h2*4);for(let y=0;y<h2;y++){let yb=y*4,rb0=yRow[yb+0],rb1=yRow[yb+1],rb2=yRow[yb+2],rb3=yRow[yb+3],wy0=yW[yb+0],wy1=yW[yb+1],wy2=yW[yb+2],wy3=yW[yb+3],dstBase=y*dstRowStride;for(let x=0;x<w2;x++){let xb=x*4,xo0=xOff[xb+0],xo1=xOff[xb+1],xo2=xOff[xb+2],xo3=xOff[xb+3],wx0=xW[xb+0],wx1=xW[xb+1],wx2=xW[xb+2],wx3=xW[xb+3],di=dstBase+(x<<2);for(let c=0;c<4;c++){let r0=src[rb0+xo0+c]*wx0+src[rb0+xo1+c]*wx1+src[rb0+xo2+c]*wx2+src[rb0+xo3+c]*wx3,r1=src[rb1+xo0+c]*wx0+src[rb1+xo1+c]*wx1+src[rb1+xo2+c]*wx2+src[rb1+xo3+c]*wx3,r2=src[rb2+xo0+c]*wx0+src[rb2+xo1+c]*wx1+src[rb2+xo2+c]*wx2+src[rb2+xo3+c]*wx3,r3=src[rb3+xo0+c]*wx0+src[rb3+xo1+c]*wx1+src[rb3+xo2+c]*wx2+src[rb3+xo3+c]*wx3,v=r0*wy0+r1*wy1+r2*wy2+r3*wy3;dst[di+c]=v<0?0:v>255?255:v|0}}}return{data:Buffer.from(dst.buffer),width:w2,height:h2}}function scaleImageToFitMessage(buffer,screenshotType){let image=screenshotType==="png"?PNG.sync.read(buffer):jpegjs.decode(buffer,{maxMemoryUsageInMB:512}),pixels=image.width*image.height,shrink=Math.min(MAX_LINEAR_SIZE/image.width,MAX_LINEAR_SIZE/image.height,Math.sqrt(MAX_PIXELS/pixels));shrink>1&&(shrink=1);let width=image.width*shrink|0,height=image.height*shrink|0,scaledImage=scaleImageToSize(image,{width,height}),quality=screenshotType==="png"?75:70,result=screenshotType==="png"?jpegjs.encode(scaledImage,quality).data:jpegjs.encode(scaledImage,quality).data,iterations=0,MAX_ITERATIONS=5;for(;result.length>MAX_BUFFER_SIZE&&iterations<MAX_ITERATIONS;)quality=Math.max(50,quality-10),quality<=50&&result.length>MAX_BUFFER_SIZE&&(shrink*=.85,width=Math.max(200,image.width*shrink|0),height=Math.max(200,image.height*shrink|0),scaledImage=scaleImageToSize(image,{width,height})),result=jpegjs.encode(scaledImage,quality).data,iterations++;return result}async function captureScreenshot(context,options){let fullPage=options.fullPage??!1,screenshotType=options.type??"png",annotate=options.annotate??!1,annotateContent=options.annotateContent??!1,annotateCursorInteractive=options.annotateCursorInteractive??!1,quality=options.quality??(screenshotType==="png"?void 0:100),overlayInjected=!1,annotations,scopedElement=null;if(options.selector&&(scopedElement=await resolveSelectorOrRef(context,options.selector).elementHandle({timeout:1e4}),!scopedElement))throw new Error(`Element not found: ${options.selector}`);if(annotate){let refMap=context.getRefMap(),wantContent=annotateContent,wantCursorInteractive=annotateCursorInteractive;if(Object.keys(refMap).length===0||wantCursorInteractive||wantContent){let raw=await context.page.locator("body").ariaSnapshot(),{refs}=processAriaTreeWithRefs(raw,{interactiveOnly:!wantContent}),mergedRefs={...refs};if(wantCursorInteractive){let cursorEntries=await findCursorInteractiveElements(context.page,null);if(cursorEntries.length>0){let maxNum=Object.keys(mergedRefs).reduce((m,k)=>Math.max(m,parseInt(k.replace(/^e/,""),10)||0),0);cursorEntries.forEach((entry,i)=>{mergedRefs[`e${maxNum+1+i}`]={role:entry.role,name:entry.name,selector:entry.selector,nth:entry.nth}})}}context.setRefMap(mergedRefs),refMap=mergedRefs}let entries=Object.entries(refMap),allBoxes=[];for(let[ref,data]of entries){let locator=getLocatorFromRef(context.page,refMap,ref);if(!locator)continue;let box=await locator.boundingBox({timeout:ANNOTATE_BOX_TIMEOUT_MS}).catch(()=>null);if(!box||box.width===0||box.height===0)continue;let num=parseInt(ref.replace(/^e/,""),10)||0;allBoxes.push({ref,number:num,role:data.role,name:data.name,box:{x:Math.round(box.x),y:Math.round(box.y),width:Math.round(box.width),height:Math.round(box.height)}})}allBoxes.sort((a,b)=>a.number-b.number);let boxes=allBoxes,overlayBoxesViewport=allBoxes;if(scopedElement){let elementBox=await scopedElement.boundingBox();if(elementBox&&elementBox.width>0&&elementBox.height>0){let overlapping=allBoxes.filter(a=>{let b=a.box;return b.x<elementBox.x+elementBox.width&&b.x+b.width>elementBox.x&&b.y<elementBox.y+elementBox.height&&b.y+b.height>elementBox.y});overlayBoxesViewport=overlapping,boxes=overlapping.map(a=>{let b=a.box,relX=Math.max(0,b.x-elementBox.x),relY=Math.max(0,b.y-elementBox.y),relRight=Math.min(b.x+b.width-elementBox.x,elementBox.width),relBottom=Math.min(b.y+b.height-elementBox.y,elementBox.height);return{...a,box:{x:Math.round(relX),y:Math.round(relY),width:Math.round(Math.max(0,relRight-relX)),height:Math.round(Math.max(0,relBottom-relY))}}})}}if(boxes.length>0){let overlayPayload={data:overlayBoxesViewport.map(a=>({number:a.number,x:a.box.x,y:a.box.y,width:a.box.width,height:a.box.height})),id:ANNOTATION_OVERLAY_ID};if(await context.page.evaluate(({data,id})=>{let sx=window.scrollX||0,sy=window.scrollY||0,c=document.createElement("div");c.id=id,c.style.cssText="position:absolute;top:0;left:0;width:0;height:0;pointer-events:none;z-index:2147483647;";for(let it of data){let dx=it.x+sx,dy=it.y+sy,b=document.createElement("div");b.style.cssText=`position:absolute;left:${dx}px;top:${dy}px;width:${it.width}px;height:${it.height}px;border:2px solid rgba(255,0,0,0.8);box-sizing:border-box;pointer-events:none;`;let l=document.createElement("div");l.textContent=String(it.number);let labelTop=dy<14?"2px":"-14px";l.style.cssText=`position:absolute;top:${labelTop};left:-2px;background:rgba(255,0,0,0.9);color:#fff;font:bold 11px/14px monospace;padding:0 4px;border-radius:2px;white-space:nowrap;`,b.appendChild(l),c.appendChild(b)}document.documentElement.appendChild(c)},overlayPayload),overlayInjected=!0,fullPage&&!scopedElement&&boxes.length>0){let scroll=await context.page.evaluate(()=>({x:window.scrollX||0,y:window.scrollY||0}));annotations=boxes.map(a=>({...a,box:{x:a.box.x+scroll.x,y:a.box.y+scroll.y,width:a.box.width,height:a.box.height}}))}else annotations=boxes}}try{let screenshotOptions={type:screenshotType,fullPage,quality};scopedElement&&(screenshotOptions.element=scopedElement);let rawBuffer=await context.page.screenshot(screenshotOptions),scaledBuffer=scaleImageToFitMessage(rawBuffer,screenshotType);return{rawBuffer,image:{data:scaledBuffer,mimeType:`image/${screenshotType}`},annotations,screenshotType}}finally{overlayInjected&&await context.page.evaluate(id=>{let el=document.getElementById(id);el&&el.remove()},ANNOTATION_OVERLAY_ID).catch(()=>{})}}import fs5 from"node:fs/promises";import os4 from"node:os";import path5 from"node:path";import{z as z11}from"zod";var DEFAULT_SCREENSHOT_NAME="screenshot",DEFAULT_SCREENSHOT_TYPE="png",DEFAULT_SCREENSHOT_QUALITY=100,TakeScreenshot=class{name(){return"content_take-screenshot"}description(){return`
275
275
  Takes a screenshot of the current page or a specific element.
276
276
  Do NOT use for page structure\u2014use ARIA/AX snapshots instead.
277
277
  Use only for visual verification (design check, visual bug, contrast, layout).
@@ -790,7 +790,7 @@ Retrieves snapshots captured by tracepoints, logpoints, and/or exceptionpoints.
790
790
  Optional \`types\`: array of \`tracepoint\`, \`logpoint\`, \`exceptionpoint\`. If omitted or empty, returns all.
791
791
  Response: tracepointSnapshots, logpointSnapshots, exceptionpointSnapshots. Optional probeId, fromSequence, limit apply per type.
792
792
  Output trimming: by default only the top ${DEFAULT_TRIM_OPTIONS.maxCallStackDepth} call stack frames are returned, only \`${NODE_DEFAULT_INCLUDE_SCOPES.join(", ")}\` scope(s) are included, and variables per scope are capped at ${DEFAULT_TRIM_OPTIONS.maxVariablesPerScope}. Override with maxCallStackDepth, includeScopes, maxVariablesPerScope.
793
- `.trim()}inputSchema(){return{types:z57.array(z57.enum(GET_SNAPSHOT_TYPES)).optional().describe("Which snapshot types to return. If omitted or empty, all are returned."),probeId:z57.string().optional().describe("Filter tracepoint or logpoint snapshots by this probe ID"),fromSequence:z57.number().int().nonnegative().optional().describe("Return snapshots with sequence number > fromSequence (per type)."),limit:z57.number().int().positive().optional().describe("Maximum number of snapshots per type."),maxCallStackDepth:z57.number().int().positive().optional().default(DEFAULT_TRIM_OPTIONS.maxCallStackDepth).describe(`Max call stack frames per snapshot. Default ${DEFAULT_TRIM_OPTIONS.maxCallStackDepth}.`),includeScopes:z57.array(z57.enum(SCOPE_TYPE_VALUES2)).optional().default([...NODE_DEFAULT_INCLUDE_SCOPES]).describe(`Scope types to include. Default [${NODE_DEFAULT_INCLUDE_SCOPES.join(", ")}] (local only to keep payload small).`),maxVariablesPerScope:z57.number().int().positive().optional().default(DEFAULT_TRIM_OPTIONS.maxVariablesPerScope).describe(`Max variables per scope. Default ${DEFAULT_TRIM_OPTIONS.maxVariablesPerScope}.`)}}outputSchema(){return{tracepointSnapshots:z57.array(z57.any()).describe("Tracepoint snapshots"),logpointSnapshots:z57.array(z57.any()).describe("Logpoint snapshots"),exceptionpointSnapshots:z57.array(z57.any()).describe("Exceptionpoint snapshots")}}async handle(context,args){let getTracepoint=!args.types?.length||args.types.includes("tracepoint"),getLogpoint=!args.types?.length||args.types.includes("logpoint"),getExceptionpoint=!args.types?.length||args.types.includes("exceptionpoint"),trimOpts={maxCallStackDepth:args.maxCallStackDepth,includeScopes:args.includeScopes,maxVariablesPerScope:args.maxVariablesPerScope},tracepointSnapshots=[],logpointSnapshots=[],exceptionpointSnapshots=[],allSnapshots=getSnapshots(context.storeKey),probes=listProbes(context.storeKey);if(args.probeId&&(getTracepoint||getLogpoint)){let raw=getSnapshotsByProbe(context.storeKey,args.probeId),filtered=applySnapshotFilters(raw,args.fromSequence,args.limit),probe=probes.find(p=>p.id===args.probeId);probe?.kind==="tracepoint"&&getTracepoint?tracepointSnapshots=filtered:probe?.kind==="logpoint"&&getLogpoint&&(logpointSnapshots=filtered)}else{if(getTracepoint){let tracepointIds=new Set(probes.filter(p=>p.kind==="tracepoint").map(p=>p.id)),raw=allSnapshots.filter(s=>tracepointIds.has(s.probeId));tracepointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}if(getLogpoint){let logpointIds=new Set(probes.filter(p=>p.kind==="logpoint").map(p=>p.id)),raw=allSnapshots.filter(s=>logpointIds.has(s.probeId));logpointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}}if(getExceptionpoint){let raw=allSnapshots.filter(s=>s.probeId==="__exception__");exceptionpointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}return{tracepointSnapshots:trimSnapshots(tracepointSnapshots,trimOpts),logpointSnapshots:trimSnapshots(logpointSnapshots,trimOpts),exceptionpointSnapshots:trimSnapshots(exceptionpointSnapshots,trimOpts)}}},SNAPSHOT_TYPES3=["tracepoint","logpoint","exceptionpoint"],ClearProbeSnapshots2=class{name(){return"debug_clear-probe-snapshots"}description(){return"\nClears snapshots captured by tracepoints, logpoints, and/or exceptionpoints.\nOptional `types`: array of `tracepoint`, `logpoint`, `exceptionpoint`. If omitted or empty, clears all.\nOptional `probeId`: clear only snapshots for this probe (tracepoint/logpoint).\n ".trim()}inputSchema(){return{types:z57.array(z57.enum(SNAPSHOT_TYPES3)).optional().describe("Which snapshot types to clear. If omitted or empty, all are cleared."),probeId:z57.string().optional().describe("Clear only snapshots for this probe ID (tracepoint or logpoint). Ignored for exceptionpoint.")}}outputSchema(){return{tracepointCleared:z57.number().describe("Tracepoint snapshots cleared"),logpointCleared:z57.number().describe("Logpoint snapshots cleared"),exceptionpointCleared:z57.number().describe("Exceptionpoint snapshots cleared"),message:z57.string().describe("Status message")}}async handle(context,args){let{clearSnapshotsByProbe:clearSnapshotsByProbe2,listProbes:listProbes3}=await import("./core-5GP5ISLC.js"),clearTracepoint=!args.types?.length||args.types.includes("tracepoint"),clearLogpoint=!args.types?.length||args.types.includes("logpoint"),clearExceptionpoint=!args.types?.length||args.types.includes("exceptionpoint"),tracepointCleared=0,logpointCleared=0,exceptionpointCleared=0;if(args.probeId&&(clearTracepoint||clearLogpoint)){let n=clearSnapshotsByProbe2(context.storeKey,args.probeId),p=listProbes3(context.storeKey).find(x=>x.id===args.probeId);clearTracepoint&&clearLogpoint?p?.kind==="tracepoint"?tracepointCleared=n:p?.kind==="logpoint"&&(logpointCleared=n):clearTracepoint?tracepointCleared=n:logpointCleared=n}else{if(clearTracepoint)for(let p of listProbes3(context.storeKey).filter(x=>x.kind==="tracepoint"))tracepointCleared+=clearSnapshotsByProbe2(context.storeKey,p.id);if(clearLogpoint)for(let p of listProbes3(context.storeKey).filter(x=>x.kind==="logpoint"))logpointCleared+=clearSnapshotsByProbe2(context.storeKey,p.id);clearExceptionpoint&&(exceptionpointCleared=clearSnapshotsByProbe2(context.storeKey,"__exception__"))}let parts=[tracepointCleared&&`${tracepointCleared} tracepoint snapshot(s)`,logpointCleared&&`${logpointCleared} logpoint snapshot(s)`,exceptionpointCleared&&`${exceptionpointCleared} exceptionpoint snapshot(s)`].filter(Boolean),message=parts.length>0?`Cleared: ${parts.join(", ")}`:"Nothing to clear";return{tracepointCleared,logpointCleared,exceptionpointCleared,message}}};import{z as z58}from"zod";var GetLogs=class{name(){return"debug_get-logs"}description(){return"Retrieves console messages/logs from the Node.js process with filtering options."}inputSchema(){return{type:z58.enum(getEnumKeyTuples(ConsoleMessageLevelName)).transform(createEnumTransformer(ConsoleMessageLevelName)).optional().describe("Filter by level (this level or higher)."),search:z58.string().optional().describe("Filter by message text."),timestamp:z58.number().int().nonnegative().optional().describe("Only messages at or after this Unix ms."),sequenceNumber:z58.number().int().nonnegative().optional().describe("Incremental: only messages with sequence > this."),limit:z58.object({count:z58.number().int().nonnegative().default(0).describe("0 = no limit."),from:z58.enum(["start","end"]).default("end").describe("Keep from start or end when truncating.")}).optional()}}outputSchema(){return{messages:z58.array(z58.object({type:z58.string().describe("Type of the console message."),text:z58.string().describe("Text of the console message."),location:z58.object({url:z58.string().describe("URL of the resource."),lineNumber:z58.number().nonnegative().describe("0-based line number."),columnNumber:z58.number().nonnegative().describe("0-based column number.")}).describe("Location of the console message.").optional(),timestamp:z58.number().int().nonnegative().describe("Unix epoch timestamp (ms)."),sequenceNumber:z58.number().int().nonnegative().describe("Monotonic sequence number.")})).describe("Retrieved console messages.")}}async handle(context,args){let levelCodeThreshold=args.type?ConsoleMessageLevel[args.type]?.code:void 0,filtered=getConsoleMessages(context.storeKey).filter(msg=>!(levelCodeThreshold!==void 0&&msg.level.code<levelCodeThreshold||args.timestamp&&msg.timestamp<args.timestamp||args.sequenceNumber&&msg.sequenceNumber<=args.sequenceNumber||args.search&&!msg.text.includes(args.search)));return{messages:(args.limit?.count?args.limit.from==="start"?filtered.slice(0,args.limit.count):filtered.slice(-args.limit.count):filtered).map(msg=>({type:msg.type,text:msg.text,location:msg.location?{url:msg.location.url,lineNumber:msg.location.lineNumber,columnNumber:msg.location.columnNumber}:void 0,timestamp:msg.timestamp,sequenceNumber:msg.sequenceNumber}))}}};import{z as z59}from"zod";var REMOVE_TYPES2=["tracepoint","logpoint","watch"],RemoveProbe2=class{name(){return"debug_remove-probe"}description(){return"Removes a tracepoint, logpoint, or watch expression by ID. `type`: tracepoint, logpoint, or watch. `id`: the probe or watch ID."}inputSchema(){return{type:z59.enum(REMOVE_TYPES2).describe("Kind of probe to remove: tracepoint, logpoint, or watch"),id:z59.string().describe("Probe or watch expression ID to remove")}}outputSchema(){return{removed:z59.boolean().describe("Whether the probe or watch was removed"),message:z59.string().describe("Status message")}}async handle(context,args){if(args.type==="watch"){let removed2=removeWatchExpression(context.storeKey,args.id);return{removed:removed2,message:removed2?`Watch expression ${args.id} removed`:`Watch expression ${args.id} not found`}}let removed=await removeProbe(context.storeKey,args.id),label=args.type==="tracepoint"?"Tracepoint":"Logpoint";return{removed,message:removed?`${label} ${args.id} removed`:`Failed to remove ${args.type}`}}},LIST_TYPES2=["tracepoint","logpoint","watch"],ListProbes2=class{name(){return"debug_list-probes"}description(){return"Lists tracepoints, logpoints, and/or watch expressions. Optional `types`: array of `tracepoint`, `logpoint`, `watch`. If omitted or empty, returns all."}inputSchema(){return{types:z59.array(z59.enum(LIST_TYPES2)).optional().describe("Which probe types to list. If omitted or empty, all are returned.")}}outputSchema(){return{tracepoints:z59.array(z59.any()).describe("Tracepoints"),logpoints:z59.array(z59.any()).describe("Logpoints"),watches:z59.array(z59.any()).describe("Watch expressions")}}async handle(context,args){let listTracepoints=!args.types?.length||args.types.includes("tracepoint"),listLogpoints=!args.types?.length||args.types.includes("logpoint"),listWatches=!args.types?.length||args.types.includes("watch"),probes=listProbes(context.storeKey),tracepoints=listTracepoints?probes.filter(p=>p.kind==="tracepoint").map(p=>({id:p.id,urlPattern:p.urlPattern,lineNumber:p.lineNumber,columnNumber:p.columnNumber,condition:p.condition,hitCondition:p.hitCondition,hitCount:p.hitCount,resolvedLocations:p.resolvedLocations,enabled:p.enabled})):[],logpoints=listLogpoints?probes.filter(p=>p.kind==="logpoint").map(p=>({id:p.id,urlPattern:p.urlPattern,lineNumber:p.lineNumber,logExpression:p.logExpression,condition:p.condition,hitCondition:p.hitCondition,hitCount:p.hitCount,resolvedLocations:p.resolvedLocations,enabled:p.enabled})):[],watches=listWatches?listWatchExpressions(context.storeKey):[];return{tracepoints,logpoints,watches}}},PROBE_TYPES2=["tracepoint","logpoint","watches"],ClearProbes2=class{name(){return"debug_clear-probes"}description(){return"Removes tracepoints, logpoints, and/or watch expressions. Optional `types`: array of `tracepoint`, `logpoint`, `watches`. If omitted or empty, clears all."}inputSchema(){return{types:z59.array(z59.enum(PROBE_TYPES2)).optional().describe("Which probe types to clear. If omitted or empty, all are cleared.")}}outputSchema(){return{tracepointsCleared:z59.number().describe("Number of tracepoints cleared"),logpointsCleared:z59.number().describe("Number of logpoints cleared"),watchesCleared:z59.number().describe("Number of watch expressions cleared"),message:z59.string().describe("Status message")}}async handle(context,args){let clearTracepoints=!args.types?.length||args.types.includes("tracepoint"),clearLogpoints=!args.types?.length||args.types.includes("logpoint"),clearWatches=!args.types?.length||args.types.includes("watches"),tracepointsCleared=0,logpointsCleared=0,watchesCleared=0;if(clearTracepoints||clearLogpoints){let probes=listProbes(context.storeKey);for(let p of probes)p.kind==="tracepoint"&&clearTracepoints?await removeProbe(context.storeKey,p.id)&&tracepointsCleared++:p.kind==="logpoint"&&clearLogpoints&&await removeProbe(context.storeKey,p.id)&&logpointsCleared++}clearWatches&&(watchesCleared=clearWatchExpressions(context.storeKey));let parts=[];tracepointsCleared&&parts.push(`${tracepointsCleared} tracepoint(s)`),logpointsCleared&&parts.push(`${logpointsCleared} logpoint(s)`),watchesCleared&&parts.push(`${watchesCleared} watch(es)`);let message=parts.length>0?`Cleared: ${parts.join(", ")}`:"Nothing to clear";return{tracepointsCleared,logpointsCleared,watchesCleared,message}}};import{z as z60}from"zod";var PutExceptionpoint2=class{name(){return"debug_put-exceptionpoint"}description(){return`
793
+ `.trim()}inputSchema(){return{types:z57.array(z57.enum(GET_SNAPSHOT_TYPES)).optional().describe("Which snapshot types to return. If omitted or empty, all are returned."),probeId:z57.string().optional().describe("Filter tracepoint or logpoint snapshots by this probe ID"),fromSequence:z57.number().int().nonnegative().optional().describe("Return snapshots with sequence number > fromSequence (per type)."),limit:z57.number().int().positive().optional().describe("Maximum number of snapshots per type."),maxCallStackDepth:z57.number().int().positive().optional().default(DEFAULT_TRIM_OPTIONS.maxCallStackDepth).describe(`Max call stack frames per snapshot. Default ${DEFAULT_TRIM_OPTIONS.maxCallStackDepth}.`),includeScopes:z57.array(z57.enum(SCOPE_TYPE_VALUES2)).optional().default([...NODE_DEFAULT_INCLUDE_SCOPES]).describe(`Scope types to include. Default [${NODE_DEFAULT_INCLUDE_SCOPES.join(", ")}] (local only to keep payload small).`),maxVariablesPerScope:z57.number().int().positive().optional().default(DEFAULT_TRIM_OPTIONS.maxVariablesPerScope).describe(`Max variables per scope. Default ${DEFAULT_TRIM_OPTIONS.maxVariablesPerScope}.`)}}outputSchema(){return{tracepointSnapshots:z57.array(z57.any()).describe("Tracepoint snapshots"),logpointSnapshots:z57.array(z57.any()).describe("Logpoint snapshots"),exceptionpointSnapshots:z57.array(z57.any()).describe("Exceptionpoint snapshots")}}async handle(context,args){let getTracepoint=!args.types?.length||args.types.includes("tracepoint"),getLogpoint=!args.types?.length||args.types.includes("logpoint"),getExceptionpoint=!args.types?.length||args.types.includes("exceptionpoint"),trimOpts={maxCallStackDepth:args.maxCallStackDepth,includeScopes:args.includeScopes,maxVariablesPerScope:args.maxVariablesPerScope},tracepointSnapshots=[],logpointSnapshots=[],exceptionpointSnapshots=[],allSnapshots=getSnapshots(context.storeKey),probes=listProbes(context.storeKey);if(args.probeId&&(getTracepoint||getLogpoint)){let raw=getSnapshotsByProbe(context.storeKey,args.probeId),filtered=applySnapshotFilters(raw,args.fromSequence,args.limit),probe=probes.find(p=>p.id===args.probeId);probe?.kind==="tracepoint"&&getTracepoint?tracepointSnapshots=filtered:probe?.kind==="logpoint"&&getLogpoint&&(logpointSnapshots=filtered)}else{if(getTracepoint){let tracepointIds=new Set(probes.filter(p=>p.kind==="tracepoint").map(p=>p.id)),raw=allSnapshots.filter(s=>tracepointIds.has(s.probeId));tracepointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}if(getLogpoint){let logpointIds=new Set(probes.filter(p=>p.kind==="logpoint").map(p=>p.id)),raw=allSnapshots.filter(s=>logpointIds.has(s.probeId));logpointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}}if(getExceptionpoint){let raw=allSnapshots.filter(s=>s.probeId==="__exception__");exceptionpointSnapshots=applySnapshotFilters(raw,args.fromSequence,args.limit)}return{tracepointSnapshots:trimSnapshots(tracepointSnapshots,trimOpts),logpointSnapshots:trimSnapshots(logpointSnapshots,trimOpts),exceptionpointSnapshots:trimSnapshots(exceptionpointSnapshots,trimOpts)}}},SNAPSHOT_TYPES3=["tracepoint","logpoint","exceptionpoint"],ClearProbeSnapshots2=class{name(){return"debug_clear-probe-snapshots"}description(){return"\nClears snapshots captured by tracepoints, logpoints, and/or exceptionpoints.\nOptional `types`: array of `tracepoint`, `logpoint`, `exceptionpoint`. If omitted or empty, clears all.\nOptional `probeId`: clear only snapshots for this probe (tracepoint/logpoint).\n ".trim()}inputSchema(){return{types:z57.array(z57.enum(SNAPSHOT_TYPES3)).optional().describe("Which snapshot types to clear. If omitted or empty, all are cleared."),probeId:z57.string().optional().describe("Clear only snapshots for this probe ID (tracepoint or logpoint). Ignored for exceptionpoint.")}}outputSchema(){return{tracepointCleared:z57.number().describe("Tracepoint snapshots cleared"),logpointCleared:z57.number().describe("Logpoint snapshots cleared"),exceptionpointCleared:z57.number().describe("Exceptionpoint snapshots cleared"),message:z57.string().describe("Status message")}}async handle(context,args){let{clearSnapshotsByProbe:clearSnapshotsByProbe2,listProbes:listProbes3}=await import("./core-42ZXN723.js"),clearTracepoint=!args.types?.length||args.types.includes("tracepoint"),clearLogpoint=!args.types?.length||args.types.includes("logpoint"),clearExceptionpoint=!args.types?.length||args.types.includes("exceptionpoint"),tracepointCleared=0,logpointCleared=0,exceptionpointCleared=0;if(args.probeId&&(clearTracepoint||clearLogpoint)){let n=clearSnapshotsByProbe2(context.storeKey,args.probeId),p=listProbes3(context.storeKey).find(x=>x.id===args.probeId);clearTracepoint&&clearLogpoint?p?.kind==="tracepoint"?tracepointCleared=n:p?.kind==="logpoint"&&(logpointCleared=n):clearTracepoint?tracepointCleared=n:logpointCleared=n}else{if(clearTracepoint)for(let p of listProbes3(context.storeKey).filter(x=>x.kind==="tracepoint"))tracepointCleared+=clearSnapshotsByProbe2(context.storeKey,p.id);if(clearLogpoint)for(let p of listProbes3(context.storeKey).filter(x=>x.kind==="logpoint"))logpointCleared+=clearSnapshotsByProbe2(context.storeKey,p.id);clearExceptionpoint&&(exceptionpointCleared=clearSnapshotsByProbe2(context.storeKey,"__exception__"))}let parts=[tracepointCleared&&`${tracepointCleared} tracepoint snapshot(s)`,logpointCleared&&`${logpointCleared} logpoint snapshot(s)`,exceptionpointCleared&&`${exceptionpointCleared} exceptionpoint snapshot(s)`].filter(Boolean),message=parts.length>0?`Cleared: ${parts.join(", ")}`:"Nothing to clear";return{tracepointCleared,logpointCleared,exceptionpointCleared,message}}};import{z as z58}from"zod";var GetLogs=class{name(){return"debug_get-logs"}description(){return"Retrieves console messages/logs from the Node.js process with filtering options."}inputSchema(){return{type:z58.enum(getEnumKeyTuples(ConsoleMessageLevelName)).transform(createEnumTransformer(ConsoleMessageLevelName)).optional().describe("Filter by level (this level or higher)."),search:z58.string().optional().describe("Filter by message text."),timestamp:z58.number().int().nonnegative().optional().describe("Only messages at or after this Unix ms."),sequenceNumber:z58.number().int().nonnegative().optional().describe("Incremental: only messages with sequence > this."),limit:z58.object({count:z58.number().int().nonnegative().default(0).describe("0 = no limit."),from:z58.enum(["start","end"]).default("end").describe("Keep from start or end when truncating.")}).optional()}}outputSchema(){return{messages:z58.array(z58.object({type:z58.string().describe("Type of the console message."),text:z58.string().describe("Text of the console message."),location:z58.object({url:z58.string().describe("URL of the resource."),lineNumber:z58.number().nonnegative().describe("0-based line number."),columnNumber:z58.number().nonnegative().describe("0-based column number.")}).describe("Location of the console message.").optional(),timestamp:z58.number().int().nonnegative().describe("Unix epoch timestamp (ms)."),sequenceNumber:z58.number().int().nonnegative().describe("Monotonic sequence number.")})).describe("Retrieved console messages.")}}async handle(context,args){let levelCodeThreshold=args.type?ConsoleMessageLevel[args.type]?.code:void 0,filtered=getConsoleMessages(context.storeKey).filter(msg=>!(levelCodeThreshold!==void 0&&msg.level.code<levelCodeThreshold||args.timestamp&&msg.timestamp<args.timestamp||args.sequenceNumber&&msg.sequenceNumber<=args.sequenceNumber||args.search&&!msg.text.includes(args.search)));return{messages:(args.limit?.count?args.limit.from==="start"?filtered.slice(0,args.limit.count):filtered.slice(-args.limit.count):filtered).map(msg=>({type:msg.type,text:msg.text,location:msg.location?{url:msg.location.url,lineNumber:msg.location.lineNumber,columnNumber:msg.location.columnNumber}:void 0,timestamp:msg.timestamp,sequenceNumber:msg.sequenceNumber}))}}};import{z as z59}from"zod";var REMOVE_TYPES2=["tracepoint","logpoint","watch"],RemoveProbe2=class{name(){return"debug_remove-probe"}description(){return"Removes a tracepoint, logpoint, or watch expression by ID. `type`: tracepoint, logpoint, or watch. `id`: the probe or watch ID."}inputSchema(){return{type:z59.enum(REMOVE_TYPES2).describe("Kind of probe to remove: tracepoint, logpoint, or watch"),id:z59.string().describe("Probe or watch expression ID to remove")}}outputSchema(){return{removed:z59.boolean().describe("Whether the probe or watch was removed"),message:z59.string().describe("Status message")}}async handle(context,args){if(args.type==="watch"){let removed2=removeWatchExpression(context.storeKey,args.id);return{removed:removed2,message:removed2?`Watch expression ${args.id} removed`:`Watch expression ${args.id} not found`}}let removed=await removeProbe(context.storeKey,args.id),label=args.type==="tracepoint"?"Tracepoint":"Logpoint";return{removed,message:removed?`${label} ${args.id} removed`:`Failed to remove ${args.type}`}}},LIST_TYPES2=["tracepoint","logpoint","watch"],ListProbes2=class{name(){return"debug_list-probes"}description(){return"Lists tracepoints, logpoints, and/or watch expressions. Optional `types`: array of `tracepoint`, `logpoint`, `watch`. If omitted or empty, returns all."}inputSchema(){return{types:z59.array(z59.enum(LIST_TYPES2)).optional().describe("Which probe types to list. If omitted or empty, all are returned.")}}outputSchema(){return{tracepoints:z59.array(z59.any()).describe("Tracepoints"),logpoints:z59.array(z59.any()).describe("Logpoints"),watches:z59.array(z59.any()).describe("Watch expressions")}}async handle(context,args){let listTracepoints=!args.types?.length||args.types.includes("tracepoint"),listLogpoints=!args.types?.length||args.types.includes("logpoint"),listWatches=!args.types?.length||args.types.includes("watch"),probes=listProbes(context.storeKey),tracepoints=listTracepoints?probes.filter(p=>p.kind==="tracepoint").map(p=>({id:p.id,urlPattern:p.urlPattern,lineNumber:p.lineNumber,columnNumber:p.columnNumber,condition:p.condition,hitCondition:p.hitCondition,hitCount:p.hitCount,resolvedLocations:p.resolvedLocations,enabled:p.enabled})):[],logpoints=listLogpoints?probes.filter(p=>p.kind==="logpoint").map(p=>({id:p.id,urlPattern:p.urlPattern,lineNumber:p.lineNumber,logExpression:p.logExpression,condition:p.condition,hitCondition:p.hitCondition,hitCount:p.hitCount,resolvedLocations:p.resolvedLocations,enabled:p.enabled})):[],watches=listWatches?listWatchExpressions(context.storeKey):[];return{tracepoints,logpoints,watches}}},PROBE_TYPES2=["tracepoint","logpoint","watches"],ClearProbes2=class{name(){return"debug_clear-probes"}description(){return"Removes tracepoints, logpoints, and/or watch expressions. Optional `types`: array of `tracepoint`, `logpoint`, `watches`. If omitted or empty, clears all."}inputSchema(){return{types:z59.array(z59.enum(PROBE_TYPES2)).optional().describe("Which probe types to clear. If omitted or empty, all are cleared.")}}outputSchema(){return{tracepointsCleared:z59.number().describe("Number of tracepoints cleared"),logpointsCleared:z59.number().describe("Number of logpoints cleared"),watchesCleared:z59.number().describe("Number of watch expressions cleared"),message:z59.string().describe("Status message")}}async handle(context,args){let clearTracepoints=!args.types?.length||args.types.includes("tracepoint"),clearLogpoints=!args.types?.length||args.types.includes("logpoint"),clearWatches=!args.types?.length||args.types.includes("watches"),tracepointsCleared=0,logpointsCleared=0,watchesCleared=0;if(clearTracepoints||clearLogpoints){let probes=listProbes(context.storeKey);for(let p of probes)p.kind==="tracepoint"&&clearTracepoints?await removeProbe(context.storeKey,p.id)&&tracepointsCleared++:p.kind==="logpoint"&&clearLogpoints&&await removeProbe(context.storeKey,p.id)&&logpointsCleared++}clearWatches&&(watchesCleared=clearWatchExpressions(context.storeKey));let parts=[];tracepointsCleared&&parts.push(`${tracepointsCleared} tracepoint(s)`),logpointsCleared&&parts.push(`${logpointsCleared} logpoint(s)`),watchesCleared&&parts.push(`${watchesCleared} watch(es)`);let message=parts.length>0?`Cleared: ${parts.join(", ")}`:"Nothing to clear";return{tracepointsCleared,logpointsCleared,watchesCleared,message}}};import{z as z60}from"zod";var PutExceptionpoint2=class{name(){return"debug_put-exceptionpoint"}description(){return`
794
794
  Sets the exception tracepoint state for a Node.js process:
795
795
  - "none": Don't capture on exceptions
796
796
  - "uncaught": Capture only on uncaught exceptions
@@ -1 +1 @@
1
- import{Execute,init,shutdown,trackToolCalled}from"./core-Y6NR2NG6.js";import{ScenarioRun,ToolRegistry,augmentToolInputSchema,isToolEnabled,platformInfo}from"./core-MEE5B4UB.js";import{AVAILABLE_TOOL_DOMAINS,DAEMON_PORT,DAEMON_SESSION_IDLE_CHECK_SECONDS,DAEMON_SESSION_IDLE_SECONDS,debug,enable,error,info,init_logger,isDebugEnabled}from"./core-X3FD2EZG.js";import{createRequire}from"node:module";init_logger();import{Command,Option,InvalidOptionArgumentError}from"commander";import{serve}from"@hono/node-server";import{Hono}from"hono";import{cors}from"hono/cors";import{z}from"zod";var require2=createRequire(import.meta.url),daemonStartTime=0,daemonPort=0,app=new Hono,sessions=new Map,DEFAULT_SESSION_ID="#default",ERRORS={get sessionNotFound(){return _buildErrorResponse(404,"Session Not Found")},get toolNotFound(){return _buildErrorResponse(404,"Tool Not Found")},get internalServerError(){return _buildErrorResponse(500,"Internal Server Error")}};function _buildErrorResponse(code,message){return{error:{code,message}}}async function _closeSession(session){session.closed=!0;try{await session.context.close(),debug("Closed MCP session context")}catch(err){error("Error occurred while closing MCP session context",err)}sessions.delete(session.id)}async function _createSession(ctx,sessionId){let now=Date.now(),session={id:sessionId,context:await platformInfo.toolsInfo.createToolSessionContext(()=>sessionId),toolExecutor:platformInfo.toolsInfo.createToolExecutor(),closed:!1,createdAt:now,lastActiveAt:now};return debug(`Created session with id ${sessionId}`),session}function _getSessionInfo(session){let now=Date.now();return{id:session.id,createdAt:session.createdAt,lastActiveAt:session.lastActiveAt,idleSeconds:Math.floor((now-session.lastActiveAt)/1e3)}}async function _getSession(ctx){let sessionId=ctx.req.header("session-id")||DEFAULT_SESSION_ID;return sessions.get(sessionId)}async function _getOrCreateSession(ctx){let sessionId=ctx.req.header("session-id")||DEFAULT_SESSION_ID,session=sessions.get(sessionId);return session?debug(`Reusing session with id ${sessionId}`):(debug(`No session could be found with id ${sessionId}`),session=await _createSession(ctx,sessionId),sessions.set(sessionId,session)),session}function _scheduleIdleSessionCheck(){let noActiveSession=!1;setInterval(()=>{let currentTime=Date.now();noActiveSession&&sessions.size===0&&(info("No active session found, so terminating daemon server"),process.exit(0));for(let[sessionId,session]of sessions)session.closed||(debug(`Checking whether session with id ${sessionId} is idle or not ...`),currentTime-session.lastActiveAt>DAEMON_SESSION_IDLE_SECONDS*1e3&&(debug(`Session with id ${sessionId} is idle, so it will be closing ...`),_closeSession(session).then(()=>{debug(`Session with id ${sessionId} was idle, so it has been closed`)}).catch(err=>{error(`Unable to delete idle session with id ${sessionId}`,err)})));noActiveSession=sessions.size===0},DAEMON_SESSION_IDLE_CHECK_SECONDS*1e3)}async function _logRequest(ctx){let reqClone=ctx.req.raw.clone();debug(`Got request: ${await reqClone.json()}`)}async function startDaemonHTTPServer(port){init({source:"cli"});let allowedDomains=AVAILABLE_TOOL_DOMAINS,allTools=platformInfo.toolsInfo.tools.filter(tool=>isToolEnabled(tool)),toolsToExpose=allowedDomains===void 0?allTools:allTools.filter(tool=>{let domain=tool.name().split("_")[0]?.toLowerCase()??"";return allowedDomains.has(domain)}),toolRegistry=new ToolRegistry;for(let tool of toolsToExpose)toolRegistry.addTool(tool);let executeTool=new Execute(toolRegistry,platformInfo.toolsInfo.executeImportantDescription,platformInfo.toolsInfo.executeDescription);toolRegistry.addTool(executeTool);let scenarioRunTool=new ScenarioRun(toolRegistry),toolMap=Object.fromEntries(toolsToExpose.map(tool=>[tool.name(),tool]));toolMap[executeTool.name()]=executeTool,toolMap[scenarioRunTool.name()]=scenarioRunTool,app.use("*",cors({origin:"*",allowMethods:["GET","POST","DELETE","OPTIONS"],allowHeaders:["Content-Type","Authorization","session-id"]})),daemonPort=port,daemonStartTime=Date.now();let gracefulShutdown=async signal=>{info(`Received ${signal}, initiating graceful shutdown...`);let closePromises=[];for(let session of sessions.values())closePromises.push(_closeSession(session));await Promise.allSettled(closePromises),await shutdown(),info("All sessions closed, exiting..."),process.exit(0)};process.on("SIGTERM",()=>gracefulShutdown("SIGTERM")),process.on("SIGINT",()=>gracefulShutdown("SIGINT")),process.on("uncaughtException",err=>{error("Uncaught exception",err)}),process.on("unhandledRejection",reason=>{error("Unhandled rejection",reason)}),app.get("/health",ctx=>ctx.json({status:"ok"})),app.get("/info",ctx=>{let info2={version:require2("../package.json").version,uptime:Math.floor((Date.now()-daemonStartTime)/1e3),sessionCount:sessions.size,port:daemonPort};return ctx.json(info2)}),app.get("/sessions",ctx=>{let sessionList=[];for(let session of sessions.values())sessionList.push(_getSessionInfo(session));return ctx.json({sessions:sessionList})}),app.get("/session",async ctx=>{let session=await _getSession(ctx);return session?ctx.json(_getSessionInfo(session)):ctx.json(ERRORS.sessionNotFound,404)}),app.post("/shutdown",async ctx=>{info("Shutdown request received, closing all sessions...");let closePromises=[];for(let session of sessions.values())closePromises.push(_closeSession(session));return await Promise.allSettled(closePromises),await shutdown(),info("All sessions closed, shutting down daemon server..."),setTimeout(()=>{process.exit(0)},500),ctx.json({status:"shutting_down"},200)}),app.post("/call",async ctx=>{try{isDebugEnabled()&&await _logRequest(ctx);let session=await _getOrCreateSession(ctx);session.lastActiveAt=Date.now();let toolCallRequest=await ctx.req.json(),tool=toolMap[toolCallRequest.toolName];if(!tool)return ctx.json(ERRORS.toolNotFound,404);let toolInput;try{toolInput=z.object(augmentToolInputSchema(tool.inputSchema())).strict().parse(toolCallRequest.toolInput)}catch(err){let errorMessage=err.errors&&Array.isArray(err.errors)?err.errors.map(e=>`${e.path?.join(".")||"input"}: ${e.message}`).join("; "):"Invalid tool input";return ctx.json(_buildErrorResponse(400,`Invalid Tool Request: ${errorMessage}`),400)}let toolStartTime=Date.now();try{let toolOutput=await session.toolExecutor.executeTool(session.context,tool,toolInput);trackToolCalled({toolName:tool.name(),durationMs:Date.now()-toolStartTime,success:!0,sessionId:session.id});let toolCallResponse={toolOutput};return ctx.json(toolCallResponse,200)}catch(err){trackToolCalled({toolName:toolCallRequest.toolName,durationMs:Date.now()-toolStartTime,success:!1,sessionId:session.id,error:err});let toolCallResponse={toolError:{code:err.code,message:err.message}};return ctx.json(toolCallResponse,500)}}catch(err){error("Error occurred while handling tool call request",err);let message=err instanceof Error?err.message:typeof err=="string"?err:"Internal Server Error";return ctx.json(_buildErrorResponse(500,message),500)}}),app.delete("/session",async ctx=>{try{let session=await _getSession(ctx);return session?(await _closeSession(session),ctx.json({ok:!0},200)):ctx.json(ERRORS.sessionNotFound,404)}catch(err){return error("Error occurred while deleting session",err),ctx.json(ERRORS.internalServerError,500)}}),app.onError((err,ctx)=>(error("Unhandled error in request handler",err),ctx.json({error:{code:500,message:"Internal Server Error"}},500))),app.notFound(ctx=>ctx.json({error:"Not Found",status:404},404)),serve({fetch:app.fetch,port},()=>info(`Listening on port ${port}`)),_scheduleIdleSessionCheck()}var isMainModule=import.meta.url===`file://${process.argv[1]}`||import.meta.url===`file://${process.argv[1]}.mjs`||process.argv[1]?.endsWith("daemon-server.js")||process.argv[1]?.endsWith("daemon-server.mjs");if(isMainModule){let parsePort=function(value){let n=Number(value);if(!Number.isInteger(n)||n<1||n>65535)throw new InvalidOptionArgumentError("port must be an integer between 1 and 65535");return n};parsePort2=parsePort;let options=new Command().addOption(new Option("--port <number>","port for daemon HTTP server").argParser(parsePort).default(DAEMON_PORT)).allowUnknownOption().parse(process.argv).opts();enable(),info("Starting daemon HTTP server..."),startDaemonHTTPServer(options.port).then(()=>{info("Daemon HTTP server started")}).catch(err=>{error("Failed to start daemon HTTP server",err),process.exit(1)})}var parsePort2;export{startDaemonHTTPServer};
1
+ import{Execute,init,shutdown,trackToolCalled}from"./core-MHH6YZLG.js";import{ScenarioRun,ToolRegistry,augmentToolInputSchema,isToolEnabled,platformInfo}from"./core-YPBKINC4.js";import{AVAILABLE_TOOL_DOMAINS,DAEMON_PORT,DAEMON_SESSION_IDLE_CHECK_SECONDS,DAEMON_SESSION_IDLE_SECONDS,debug,enable,error,info,init_logger,isDebugEnabled}from"./core-S5JHUB3Z.js";import{createRequire}from"node:module";init_logger();import{Command,Option,InvalidOptionArgumentError}from"commander";import{serve}from"@hono/node-server";import{Hono}from"hono";import{cors}from"hono/cors";import{z}from"zod";var require2=createRequire(import.meta.url),daemonStartTime=0,daemonPort=0,app=new Hono,sessions=new Map,DEFAULT_SESSION_ID="#default",ERRORS={get sessionNotFound(){return _buildErrorResponse(404,"Session Not Found")},get toolNotFound(){return _buildErrorResponse(404,"Tool Not Found")},get internalServerError(){return _buildErrorResponse(500,"Internal Server Error")}};function _buildErrorResponse(code,message){return{error:{code,message}}}async function _closeSession(session){session.closed=!0;try{await session.context.close(),debug("Closed MCP session context")}catch(err){error("Error occurred while closing MCP session context",err)}sessions.delete(session.id)}async function _createSession(ctx,sessionId){let now=Date.now(),session={id:sessionId,context:await platformInfo.toolsInfo.createToolSessionContext(()=>sessionId),toolExecutor:platformInfo.toolsInfo.createToolExecutor(),closed:!1,createdAt:now,lastActiveAt:now};return debug(`Created session with id ${sessionId}`),session}function _getSessionInfo(session){let now=Date.now();return{id:session.id,createdAt:session.createdAt,lastActiveAt:session.lastActiveAt,idleSeconds:Math.floor((now-session.lastActiveAt)/1e3)}}async function _getSession(ctx){let sessionId=ctx.req.header("session-id")||DEFAULT_SESSION_ID;return sessions.get(sessionId)}async function _getOrCreateSession(ctx){let sessionId=ctx.req.header("session-id")||DEFAULT_SESSION_ID,session=sessions.get(sessionId);return session?debug(`Reusing session with id ${sessionId}`):(debug(`No session could be found with id ${sessionId}`),session=await _createSession(ctx,sessionId),sessions.set(sessionId,session)),session}function _scheduleIdleSessionCheck(){let noActiveSession=!1;setInterval(()=>{let currentTime=Date.now();noActiveSession&&sessions.size===0&&(info("No active session found, so terminating daemon server"),process.exit(0));for(let[sessionId,session]of sessions)session.closed||(debug(`Checking whether session with id ${sessionId} is idle or not ...`),currentTime-session.lastActiveAt>DAEMON_SESSION_IDLE_SECONDS*1e3&&(debug(`Session with id ${sessionId} is idle, so it will be closing ...`),_closeSession(session).then(()=>{debug(`Session with id ${sessionId} was idle, so it has been closed`)}).catch(err=>{error(`Unable to delete idle session with id ${sessionId}`,err)})));noActiveSession=sessions.size===0},DAEMON_SESSION_IDLE_CHECK_SECONDS*1e3)}async function _logRequest(ctx){let reqClone=ctx.req.raw.clone();debug(`Got request: ${await reqClone.json()}`)}async function startDaemonHTTPServer(port){init({source:"cli"});let allowedDomains=AVAILABLE_TOOL_DOMAINS,allTools=platformInfo.toolsInfo.tools.filter(tool=>isToolEnabled(tool)),toolsToExpose=allowedDomains===void 0?allTools:allTools.filter(tool=>{let domain=tool.name().split("_")[0]?.toLowerCase()??"";return allowedDomains.has(domain)}),toolRegistry=new ToolRegistry;for(let tool of toolsToExpose)toolRegistry.addTool(tool);let executeTool=new Execute(toolRegistry,platformInfo.toolsInfo.executeImportantDescription,platformInfo.toolsInfo.executeDescription);toolRegistry.addTool(executeTool);let scenarioRunTool=new ScenarioRun(toolRegistry),toolMap=Object.fromEntries(toolsToExpose.map(tool=>[tool.name(),tool]));toolMap[executeTool.name()]=executeTool,toolMap[scenarioRunTool.name()]=scenarioRunTool,app.use("*",cors({origin:"*",allowMethods:["GET","POST","DELETE","OPTIONS"],allowHeaders:["Content-Type","Authorization","session-id"]})),daemonPort=port,daemonStartTime=Date.now();let gracefulShutdown=async signal=>{info(`Received ${signal}, initiating graceful shutdown...`);let closePromises=[];for(let session of sessions.values())closePromises.push(_closeSession(session));await Promise.allSettled(closePromises),await shutdown(),info("All sessions closed, exiting..."),process.exit(0)};process.on("SIGTERM",()=>gracefulShutdown("SIGTERM")),process.on("SIGINT",()=>gracefulShutdown("SIGINT")),process.on("uncaughtException",err=>{error("Uncaught exception",err)}),process.on("unhandledRejection",reason=>{error("Unhandled rejection",reason)}),app.get("/health",ctx=>ctx.json({status:"ok"})),app.get("/info",ctx=>{let info2={version:require2("../package.json").version,uptime:Math.floor((Date.now()-daemonStartTime)/1e3),sessionCount:sessions.size,port:daemonPort};return ctx.json(info2)}),app.get("/sessions",ctx=>{let sessionList=[];for(let session of sessions.values())sessionList.push(_getSessionInfo(session));return ctx.json({sessions:sessionList})}),app.get("/session",async ctx=>{let session=await _getSession(ctx);return session?ctx.json(_getSessionInfo(session)):ctx.json(ERRORS.sessionNotFound,404)}),app.post("/shutdown",async ctx=>{info("Shutdown request received, closing all sessions...");let closePromises=[];for(let session of sessions.values())closePromises.push(_closeSession(session));return await Promise.allSettled(closePromises),await shutdown(),info("All sessions closed, shutting down daemon server..."),setTimeout(()=>{process.exit(0)},500),ctx.json({status:"shutting_down"},200)}),app.post("/call",async ctx=>{try{isDebugEnabled()&&await _logRequest(ctx);let session=await _getOrCreateSession(ctx);session.lastActiveAt=Date.now();let toolCallRequest=await ctx.req.json(),tool=toolMap[toolCallRequest.toolName];if(!tool)return ctx.json(ERRORS.toolNotFound,404);let toolInput;try{toolInput=z.object(augmentToolInputSchema(tool.inputSchema())).strict().parse(toolCallRequest.toolInput)}catch(err){let errorMessage=err.errors&&Array.isArray(err.errors)?err.errors.map(e=>`${e.path?.join(".")||"input"}: ${e.message}`).join("; "):"Invalid tool input";return ctx.json(_buildErrorResponse(400,`Invalid Tool Request: ${errorMessage}`),400)}let toolStartTime=Date.now();try{let toolOutput=await session.toolExecutor.executeTool(session.context,tool,toolInput);trackToolCalled({toolName:tool.name(),durationMs:Date.now()-toolStartTime,success:!0,sessionId:session.id});let toolCallResponse={toolOutput};return ctx.json(toolCallResponse,200)}catch(err){trackToolCalled({toolName:toolCallRequest.toolName,durationMs:Date.now()-toolStartTime,success:!1,sessionId:session.id,error:err});let toolCallResponse={toolError:{code:err.code,message:err.message}};return ctx.json(toolCallResponse,500)}}catch(err){error("Error occurred while handling tool call request",err);let message=err instanceof Error?err.message:typeof err=="string"?err:"Internal Server Error";return ctx.json(_buildErrorResponse(500,message),500)}}),app.delete("/session",async ctx=>{try{let session=await _getSession(ctx);return session?(await _closeSession(session),ctx.json({ok:!0},200)):ctx.json(ERRORS.sessionNotFound,404)}catch(err){return error("Error occurred while deleting session",err),ctx.json(ERRORS.internalServerError,500)}}),app.onError((err,ctx)=>(error("Unhandled error in request handler",err),ctx.json({error:{code:500,message:"Internal Server Error"}},500))),app.notFound(ctx=>ctx.json({error:"Not Found",status:404},404)),serve({fetch:app.fetch,port},()=>info(`Listening on port ${port}`)),_scheduleIdleSessionCheck()}var isMainModule=import.meta.url===`file://${process.argv[1]}`||import.meta.url===`file://${process.argv[1]}.mjs`||process.argv[1]?.endsWith("daemon-server.js")||process.argv[1]?.endsWith("daemon-server.mjs");if(isMainModule){let parsePort=function(value){let n=Number(value);if(!Number.isInteger(n)||n<1||n>65535)throw new InvalidOptionArgumentError("port must be an integer between 1 and 65535");return n};parsePort2=parsePort;let options=new Command().addOption(new Option("--port <number>","port for daemon HTTP server").argParser(parsePort).default(DAEMON_PORT)).allowUnknownOption().parse(process.argv).opts();enable(),info("Starting daemon HTTP server..."),startDaemonHTTPServer(options.port).then(()=>{info("Daemon HTTP server started")}).catch(err=>{error("Failed to start daemon HTTP server",err),process.exit(1)})}var parsePort2;export{startDaemonHTTPServer};
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{Execute,init,shutdown,trackMCPServerStarted,trackToolCalled}from"./core-Y6NR2NG6.js";import{ScenarioRun,ToolRegistry,augmentToolInputSchema,isToolEnabled,platformInfo}from"./core-MEE5B4UB.js";import{AVAILABLE_TOOL_DOMAINS,PORT,SESSION_CLOSE_ON_SOCKET_CLOSE,SESSION_IDLE_CHECK_SECONDS,SESSION_IDLE_SECONDS,TOOL_OUTPUT_SCHEMA_DISABLE,applyNormalizedToolNamesInText,debug,disable,enable,error,info,init_logger,isDebugEnabled,normalizeToolName}from"./core-X3FD2EZG.js";init_logger();init_logger();import{createRequire}from"node:module";var require2=createRequire(import.meta.url),SERVER_NAME="browser-devtools-mcp",SERVER_VERSION=require2("../package.json").version;function getServerInstructions(){if(!platformInfo.serverInfo.instructions)return;let parts=[];return parts.push(platformInfo.serverInfo.instructions),parts.join(`
2
+ import{Execute,init,shutdown,trackMCPServerStarted,trackToolCalled}from"./core-MHH6YZLG.js";import{ScenarioRun,ToolRegistry,augmentToolInputSchema,isToolEnabled,platformInfo}from"./core-YPBKINC4.js";import{AVAILABLE_TOOL_DOMAINS,LOG_FILE,PORT,SESSION_CLOSE_ON_SOCKET_CLOSE,SESSION_IDLE_CHECK_SECONDS,SESSION_IDLE_SECONDS,TOOL_OUTPUT_SCHEMA_DISABLE,applyNormalizedToolNamesInText,debug,disable,enable,error,info,initFileLogging,init_logger,isDebugEnabled,normalizeToolName}from"./core-S5JHUB3Z.js";init_logger();init_logger();import{createRequire}from"node:module";var require2=createRequire(import.meta.url),SERVER_NAME="browser-devtools-mcp",SERVER_VERSION=require2("../package.json").version;function getServerInstructions(){if(!platformInfo.serverInfo.instructions)return;let parts=[];return parts.push(platformInfo.serverInfo.instructions),parts.join(`
3
3
 
4
- `).trim()}function getServerPolicies(){return platformInfo.serverInfo.policies}import crypto from"node:crypto";import{StreamableHTTPTransport}from"@hono/mcp";import{serve}from"@hono/node-server";import{McpServer as MCPServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{Hono}from"hono";import{cors}from"hono/cors";var MCP_TEMPLATE={jsonrpc:"2.0",error:{code:0,message:"N/A"},id:null};function _canonicalToolNamesForMCPDocs(){let ids=platformInfo.toolsInfo.tools.map(t=>t.name());return ids.push("execute"),ids}var MCP_ERRORS={get sessionNotFound(){return _buildMCPErrorResponse(-32001,"Session Not Found")},get unauthorized(){return _buildMCPErrorResponse(-32001,"Unauthorized")},get internalServerError(){return _buildMCPErrorResponse(-32603,"Internal Server Error")}},sessions=new Map;function _buildMCPErrorResponse(code,message){let result={...MCP_TEMPLATE};return result.error.code=code,result.error.message=message,result}function _getImage(response){if("image"in response&&response.image!==null&&typeof response.image=="object"&&"data"in response.image&&"mimeType"in response.image&&Buffer.isBuffer(response.image.data)&&typeof response.image.mimeType=="string"){let image=response.image;return delete response.image,image}}function _toResponse(response){let image=_getImage(response);for(let key of Object.keys(response))key.startsWith("_")&&delete response[key];let contents=[];return contents.push({type:"text",text:JSON.stringify(response,null,2)}),image&&(image.mimeType==="image/svg+xml"?contents.push({type:"text",text:image.data.toString(),mimeType:image.mimeType}):contents.push({type:"image",data:image.data.toString("base64"),mimeType:image.mimeType})),{content:contents,structuredContent:response,isError:!1}}function _createServer(opts){let canonicalNamesForMCP=_canonicalToolNamesForMCPDocs(),mcpText=s=>{if(s)return applyNormalizedToolNamesInText(s,canonicalNamesForMCP)},server=new MCPServer({name:SERVER_NAME,version:SERVER_VERSION},{capabilities:{resources:{},tools:{}},instructions:mcpText(getServerInstructions())}),messages=[];for(let policy of getServerPolicies()??[]){let text=mcpText(policy);text&&messages.push({role:"user",content:{type:"text",text}})}server.registerPrompt("default_system",{title:"Default System Prompt",description:"General behavior for the AI assistant"},async()=>({description:"Defines the assistant's general reasoning and tool usage rules.",messages}));let toolExecutor=platformInfo.toolsInfo.createToolExecutor(),fallbackSessionId=crypto.randomUUID(),toolSessionContext,toolSessionContextPromise,createToolCallback=tool=>async args=>{let startTime=Date.now(),session=opts.sessionProvider?opts.sessionProvider():void 0,sessionId=session?.id||fallbackSessionId,clientName=server.server.getClientVersion()?.name;try{toolSessionContext||(session&&(toolSessionContext=session.context),toolSessionContext||(toolSessionContextPromise||(toolSessionContextPromise=platformInfo.toolsInfo.createToolSessionContext(()=>sessionId)),toolSessionContext=await toolSessionContextPromise,toolSessionContextPromise=void 0,session&&(session.context=toolSessionContext)));let response=await toolExecutor.executeTool(toolSessionContext,tool,args);return trackToolCalled({toolName:tool.name(),durationMs:Date.now()-startTime,success:!0,sessionId,clientName}),_toResponse(response)}catch(error2){return trackToolCalled({toolName:tool.name(),durationMs:Date.now()-startTime,success:!1,error:error2,sessionId,clientName}),{content:[{type:"text",text:`Error: ${error2.message}`}],isError:!0}}},includeOutputSchema=!TOOL_OUTPUT_SCHEMA_DISABLE,allowedDomains=AVAILABLE_TOOL_DOMAINS,toolRegistry=new ToolRegistry;platformInfo.toolsInfo.tools.forEach(t=>{if(!isToolEnabled(t)){debug(`Skipping tool ${t.name()} (isEnabled returned false)`);return}let domain=t.name().split("_")[0]?.toLowerCase()??"";if(allowedDomains&&!allowedDomains.has(domain)){debug(`Skipping tool ${t.name()} (domain ${domain} not in AVAILABLE_TOOL_DOMAINS)`);return}debug(`Registering tool ${t.name()} ...`);let toolOptions=includeOutputSchema?{description:mcpText(t.description()),inputSchema:augmentToolInputSchema(t.inputSchema()),outputSchema:t.outputSchema()}:{description:mcpText(t.description()),inputSchema:augmentToolInputSchema(t.inputSchema())};server.registerTool(normalizeToolName(t.name()),toolOptions,createToolCallback(t)),toolRegistry.addTool(t)});let executeTool=new Execute(toolRegistry,mcpText(platformInfo.toolsInfo.executeImportantDescription),mcpText(platformInfo.toolsInfo.executeDescription)),executeToolOptions=includeOutputSchema?{description:mcpText(executeTool.description()),inputSchema:augmentToolInputSchema(executeTool.inputSchema()),outputSchema:executeTool.outputSchema()}:{description:mcpText(executeTool.description()),inputSchema:augmentToolInputSchema(executeTool.inputSchema())};server.registerTool(normalizeToolName(executeTool.name()),executeToolOptions,createToolCallback(executeTool)),toolRegistry.addTool(executeTool);let scenarioRunTool=new ScenarioRun(toolRegistry),scenarioRunToolOptions=includeOutputSchema?{description:mcpText(scenarioRunTool.description()),inputSchema:augmentToolInputSchema(scenarioRunTool.inputSchema()),outputSchema:scenarioRunTool.outputSchema()}:{description:mcpText(scenarioRunTool.description()),inputSchema:augmentToolInputSchema(scenarioRunTool.inputSchema())};return server.registerTool(normalizeToolName(scenarioRunTool.name()),scenarioRunToolOptions,createToolCallback(scenarioRunTool)),server}async function _createAndConnectServer(transport,opts){let server=_createServer({config:opts.config,sessionProvider:()=>sessions.get(transport.sessionId),transportType:opts.transportType});return await server.connect(transport),server}function _getConfig(){return{}}function _createSession(id,ctx,transport,server,closeOnTransportClose=!0){let session={id,transport,server,closed:!1,lastActiveAt:Date.now()},socket=ctx.env.incoming.socket;return socket._mcpRegistered||(socket._mcpRegistered=!0,socket.on("close",async()=>{debug(`Socket, which is for MCP session with id ${transport.sessionId}, has been closed`),SESSION_CLOSE_ON_SOCKET_CLOSE&&await transport.close()})),_registerMCPSessionClose(transport,session.server,closeOnTransportClose),debug(`Created MCP server session with id ${transport.sessionId}`),session}function _createOrUpdateSession(id,ctx,transport,server,closeOnTransportClose=!0){let session=sessions.get(id);return session?(session.transport=transport,session.server=server,session.closed=!1,session.lastActiveAt=Date.now(),session):_createSession(id,ctx,transport,server,closeOnTransportClose)}async function _createTransport(ctx){let serverConfig=_getConfig(),holder={},useSessionId=ctx.req.header("mcp-use-session-id"),transport=new StreamableHTTPTransport({enableJsonResponse:!0,sessionIdGenerator:()=>useSessionId||crypto.randomUUID(),onsessioninitialized:async sessionId=>{let session=_createOrUpdateSession(sessionId,ctx,transport,holder.server);sessions.set(sessionId,session),debug(`MCP session initialized with id ${sessionId}`)},onsessionclosed:async sessionId=>{debug(`Closing MCP session closed with id ${sessionId} ...`),await transport.close(),debug(`MCP session closed with id ${sessionId}`)}});return holder.server=await _createAndConnectServer(transport,{config:serverConfig,transportType:"streamable-http"}),transport}function _getSessionId(ctx){return ctx.req.header("mcp-session-id")}async function _getTransport(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);if(session)return debug(`Reusing MCP session with id ${sessionId}`),session.transport}}async function _getOrCreateTransport(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);if(session)return debug(`Reusing MCP session with id ${sessionId}`),session.transport;debug(`No MCP session could be found with id ${sessionId}`);return}return await _createTransport(ctx)}function _registerMCPSessionClose(transport,mcpServer,closeSession=!0){let closed=!1;transport.onclose=async()=>{if(debug(`Closing MCP session with id ${transport.sessionId} ...`),closed){debug(`MCP session with id ${transport.sessionId} has already been closed`);return}closed=!0;try{await mcpServer.close(),debug("Closed MCP server")}catch(err){error("Error occurred while closing MCP server",err)}if(closeSession&&transport.sessionId){let session=sessions.get(transport.sessionId);if(session&&(session.closed=!0,session.context))try{await session.context.close(),debug("Closed MCP session context")}catch(err){error("Error occurred while closing MCP session context",err)}sessions.delete(transport.sessionId),debug(`Closing MCP session with id ${transport.sessionId} ...`)}}}function _scheduleIdleSessionCheck(){setInterval(()=>{let currentTime=Date.now();for(let[sessionId,session]of sessions)debug(`Checking whether session with id ${sessionId} is idle or not ...`),currentTime-session.lastActiveAt>SESSION_IDLE_SECONDS*1e3&&(debug(`Session with id ${sessionId} is idle, so it will be closing ...`),session.transport.close().then(()=>{debug(`Session with id ${sessionId} was idle, so it has been closed`)}).catch(err=>{error(`Unable to delete idle session with id ${sessionId}`,err)}))},SESSION_IDLE_CHECK_SECONDS*1e3)}async function _logRequest(ctx){let reqClone=ctx.req.raw.clone();debug(`Got request: ${await reqClone.text()}`)}function _markSessionAsActive(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);session&&(session.lastActiveAt=Date.now())}}async function startStdioServer(){init({source:"mcp"});let transport=new StdioServerTransport;await _createAndConnectServer(transport,{config:_getConfig(),transportType:"stdio"}),trackMCPServerStarted("stdio")}var app=new Hono;async function startStreamableHTTPServer(port){init({source:"mcp"}),app.use("*",cors({origin:"*",allowMethods:["GET","POST","OPTIONS"],allowHeaders:["Content-Type","Authorization","MCP-Protocol-Version"]})),app.get("/health",ctx=>ctx.json({status:"ok"})),app.get("/ping",ctx=>ctx.json({status:"ok",message:"pong"})),app.get("/mcp",ctx=>ctx.json({status:"ok",protocol:"model-context-protocol",version:"1.0"})),app.post("/mcp",async ctx=>{try{isDebugEnabled()&&await _logRequest(ctx);let transport=await _getOrCreateTransport(ctx);return transport?(_markSessionAsActive(ctx),await transport.handleRequest(ctx)):ctx.json(MCP_ERRORS.sessionNotFound,400)}catch(err){return error("Error occurred while handling MCP request",err),ctx.json(MCP_ERRORS.internalServerError,500)}}),app.delete("/mcp",async ctx=>{try{let transport=await _getTransport(ctx);return transport?(await transport.close(),ctx.json({ok:!0},200)):ctx.json(MCP_ERRORS.sessionNotFound,400)}catch(err){return error("Error occurred while deleting MCP session",err),ctx.json(MCP_ERRORS.internalServerError,500)}}),app.notFound(ctx=>ctx.json({error:"Not Found",status:404},404)),serve({fetch:app.fetch,port},()=>{trackMCPServerStarted("streamable-http"),info(`Listening on port ${port}`)}),_scheduleIdleSessionCheck()}import{Command,Option,InvalidOptionArgumentError}from"commander";function _parsePort(value){let n=Number(value);if(!Number.isInteger(n)||n<1||n>65535)throw new InvalidOptionArgumentError("port must be an integer between 1 and 65535");return n}function _getOptions(){return new Command().addOption(new Option("--transport <type>","transport type").choices(["stdio","streamable-http"]).default("stdio")).addOption(new Option("--port <number>","port for Streamable HTTP transport").argParser(_parsePort).default(PORT)).allowUnknownOption().allowExcessArguments().parse(process.argv).opts()}async function _shutdown(){await shutdown()}async function main(){let options=_getOptions();for(let signal of["SIGTERM","SIGINT"])process.on(signal,async()=>{await _shutdown(),process.exit(0)});options.transport==="stdio"?(disable(),await startStdioServer()):options.transport==="streamable-http"?(info("Starting MCP server..."),await startStreamableHTTPServer(options.port),info("Started MCP Server")):(error(`Invalid transport: ${options.transport}`),process.exit(1))}main().catch(async err=>{enable(),error("MCP server error",err),await _shutdown(),process.exit(1)});
4
+ `).trim()}function getServerPolicies(){return platformInfo.serverInfo.policies}import crypto from"node:crypto";import{StreamableHTTPTransport}from"@hono/mcp";import{serve}from"@hono/node-server";import{McpServer as MCPServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{Hono}from"hono";import{cors}from"hono/cors";var MCP_TEMPLATE={jsonrpc:"2.0",error:{code:0,message:"N/A"},id:null};function _canonicalToolNamesForMCPDocs(){let ids=platformInfo.toolsInfo.tools.map(t=>t.name());return ids.push("execute"),ids}var MCP_ERRORS={get sessionNotFound(){return _buildMCPErrorResponse(-32001,"Session Not Found")},get unauthorized(){return _buildMCPErrorResponse(-32001,"Unauthorized")},get internalServerError(){return _buildMCPErrorResponse(-32603,"Internal Server Error")}},sessions=new Map;function _buildMCPErrorResponse(code,message){let result={...MCP_TEMPLATE};return result.error.code=code,result.error.message=message,result}function _getImage(response){if("image"in response&&response.image!==null&&typeof response.image=="object"&&"data"in response.image&&"mimeType"in response.image&&Buffer.isBuffer(response.image.data)&&typeof response.image.mimeType=="string"){let image=response.image;return delete response.image,image}}function _toResponse(response){let image=_getImage(response);for(let key of Object.keys(response))key.startsWith("_")&&delete response[key];let contents=[];return contents.push({type:"text",text:JSON.stringify(response,null,2)}),image&&(image.mimeType==="image/svg+xml"?contents.push({type:"text",text:image.data.toString(),mimeType:image.mimeType}):contents.push({type:"image",data:image.data.toString("base64"),mimeType:image.mimeType})),{content:contents,structuredContent:response,isError:!1}}function _createServer(opts){let canonicalNamesForMCP=_canonicalToolNamesForMCPDocs(),mcpText=s=>{if(s)return applyNormalizedToolNamesInText(s,canonicalNamesForMCP)},server=new MCPServer({name:SERVER_NAME,version:SERVER_VERSION},{capabilities:{resources:{},tools:{}},instructions:mcpText(getServerInstructions())}),messages=[];for(let policy of getServerPolicies()??[]){let text=mcpText(policy);text&&messages.push({role:"user",content:{type:"text",text}})}server.registerPrompt("default_system",{title:"Default System Prompt",description:"General behavior for the AI assistant"},async()=>({description:"Defines the assistant's general reasoning and tool usage rules.",messages}));let toolExecutor=platformInfo.toolsInfo.createToolExecutor(),fallbackSessionId=crypto.randomUUID(),toolSessionContext,toolSessionContextPromise,createToolCallback=tool=>async args=>{let startTime=Date.now(),session=opts.sessionProvider?opts.sessionProvider():void 0,sessionId=session?.id||fallbackSessionId,clientName=server.server.getClientVersion()?.name;try{toolSessionContext||(session&&(toolSessionContext=session.context),toolSessionContext||(toolSessionContextPromise||(toolSessionContextPromise=platformInfo.toolsInfo.createToolSessionContext(()=>sessionId)),toolSessionContext=await toolSessionContextPromise,toolSessionContextPromise=void 0,session&&(session.context=toolSessionContext)));let response=await toolExecutor.executeTool(toolSessionContext,tool,args);return trackToolCalled({toolName:tool.name(),durationMs:Date.now()-startTime,success:!0,sessionId,clientName}),_toResponse(response)}catch(error2){return trackToolCalled({toolName:tool.name(),durationMs:Date.now()-startTime,success:!1,error:error2,sessionId,clientName}),{content:[{type:"text",text:`Error: ${error2.message}`}],isError:!0}}},includeOutputSchema=!TOOL_OUTPUT_SCHEMA_DISABLE,allowedDomains=AVAILABLE_TOOL_DOMAINS,toolRegistry=new ToolRegistry;platformInfo.toolsInfo.tools.forEach(t=>{if(!isToolEnabled(t)){debug(`Skipping tool ${t.name()} (isEnabled returned false)`);return}let domain=t.name().split("_")[0]?.toLowerCase()??"";if(allowedDomains&&!allowedDomains.has(domain)){debug(`Skipping tool ${t.name()} (domain ${domain} not in AVAILABLE_TOOL_DOMAINS)`);return}debug(`Registering tool ${t.name()} ...`);let toolOptions=includeOutputSchema?{description:mcpText(t.description()),inputSchema:augmentToolInputSchema(t.inputSchema()),outputSchema:t.outputSchema()}:{description:mcpText(t.description()),inputSchema:augmentToolInputSchema(t.inputSchema())};server.registerTool(normalizeToolName(t.name()),toolOptions,createToolCallback(t)),toolRegistry.addTool(t)});let executeTool=new Execute(toolRegistry,mcpText(platformInfo.toolsInfo.executeImportantDescription),mcpText(platformInfo.toolsInfo.executeDescription)),executeToolOptions=includeOutputSchema?{description:mcpText(executeTool.description()),inputSchema:augmentToolInputSchema(executeTool.inputSchema()),outputSchema:executeTool.outputSchema()}:{description:mcpText(executeTool.description()),inputSchema:augmentToolInputSchema(executeTool.inputSchema())};server.registerTool(normalizeToolName(executeTool.name()),executeToolOptions,createToolCallback(executeTool)),toolRegistry.addTool(executeTool);let scenarioRunTool=new ScenarioRun(toolRegistry),scenarioRunToolOptions=includeOutputSchema?{description:mcpText(scenarioRunTool.description()),inputSchema:augmentToolInputSchema(scenarioRunTool.inputSchema()),outputSchema:scenarioRunTool.outputSchema()}:{description:mcpText(scenarioRunTool.description()),inputSchema:augmentToolInputSchema(scenarioRunTool.inputSchema())};return server.registerTool(normalizeToolName(scenarioRunTool.name()),scenarioRunToolOptions,createToolCallback(scenarioRunTool)),server}async function _createAndConnectServer(transport,opts){let server=_createServer({config:opts.config,sessionProvider:()=>sessions.get(transport.sessionId),transportType:opts.transportType});return await server.connect(transport),server}function _getConfig(){return{}}function _createSession(id,ctx,transport,server,closeOnTransportClose=!0){let session={id,transport,server,closed:!1,lastActiveAt:Date.now()},socket=ctx.env.incoming.socket;return socket._mcpRegistered||(socket._mcpRegistered=!0,socket.on("close",async()=>{debug(`Socket, which is for MCP session with id ${transport.sessionId}, has been closed`),SESSION_CLOSE_ON_SOCKET_CLOSE&&await transport.close()})),_registerMCPSessionClose(transport,session.server,closeOnTransportClose),debug(`Created MCP server session with id ${transport.sessionId}`),session}function _createOrUpdateSession(id,ctx,transport,server,closeOnTransportClose=!0){let session=sessions.get(id);return session?(session.transport=transport,session.server=server,session.closed=!1,session.lastActiveAt=Date.now(),session):_createSession(id,ctx,transport,server,closeOnTransportClose)}async function _createTransport(ctx){let serverConfig=_getConfig(),holder={},useSessionId=ctx.req.header("mcp-use-session-id"),transport=new StreamableHTTPTransport({enableJsonResponse:!0,sessionIdGenerator:()=>useSessionId||crypto.randomUUID(),onsessioninitialized:async sessionId=>{let session=_createOrUpdateSession(sessionId,ctx,transport,holder.server);sessions.set(sessionId,session),debug(`MCP session initialized with id ${sessionId}`)},onsessionclosed:async sessionId=>{debug(`Closing MCP session closed with id ${sessionId} ...`),await transport.close(),debug(`MCP session closed with id ${sessionId}`)}});return holder.server=await _createAndConnectServer(transport,{config:serverConfig,transportType:"streamable-http"}),transport}function _getSessionId(ctx){return ctx.req.header("mcp-session-id")}async function _getTransport(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);if(session)return debug(`Reusing MCP session with id ${sessionId}`),session.transport}}async function _getOrCreateTransport(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);if(session)return debug(`Reusing MCP session with id ${sessionId}`),session.transport;debug(`No MCP session could be found with id ${sessionId}`);return}return await _createTransport(ctx)}function _registerMCPSessionClose(transport,mcpServer,closeSession=!0){let closed=!1;transport.onclose=async()=>{if(debug(`Closing MCP session with id ${transport.sessionId} ...`),closed){debug(`MCP session with id ${transport.sessionId} has already been closed`);return}closed=!0;try{await mcpServer.close(),debug("Closed MCP server")}catch(err){error("Error occurred while closing MCP server",err)}if(closeSession&&transport.sessionId){let session=sessions.get(transport.sessionId);if(session&&(session.closed=!0,session.context))try{await session.context.close(),debug("Closed MCP session context")}catch(err){error("Error occurred while closing MCP session context",err)}sessions.delete(transport.sessionId),debug(`Closing MCP session with id ${transport.sessionId} ...`)}}}function _scheduleIdleSessionCheck(){setInterval(()=>{let currentTime=Date.now();for(let[sessionId,session]of sessions)debug(`Checking whether session with id ${sessionId} is idle or not ...`),currentTime-session.lastActiveAt>SESSION_IDLE_SECONDS*1e3&&(debug(`Session with id ${sessionId} is idle, so it will be closing ...`),session.transport.close().then(()=>{debug(`Session with id ${sessionId} was idle, so it has been closed`)}).catch(err=>{error(`Unable to delete idle session with id ${sessionId}`,err)}))},SESSION_IDLE_CHECK_SECONDS*1e3)}async function _logRequest(ctx){let reqClone=ctx.req.raw.clone();debug(`Got request: ${await reqClone.text()}`)}function _markSessionAsActive(ctx){let sessionId=_getSessionId(ctx);if(sessionId){let session=sessions.get(sessionId);session&&(session.lastActiveAt=Date.now())}}async function startStdioServer(){init({source:"mcp"});let transport=new StdioServerTransport;await _createAndConnectServer(transport,{config:_getConfig(),transportType:"stdio"}),trackMCPServerStarted("stdio")}var app=new Hono;async function startStreamableHTTPServer(port){init({source:"mcp"}),app.use("*",cors({origin:"*",allowMethods:["GET","POST","OPTIONS"],allowHeaders:["Content-Type","Authorization","MCP-Protocol-Version"]})),app.get("/health",ctx=>ctx.json({status:"ok"})),app.get("/ping",ctx=>ctx.json({status:"ok",message:"pong"})),app.get("/mcp",ctx=>ctx.json({status:"ok",protocol:"model-context-protocol",version:"1.0"})),app.post("/mcp",async ctx=>{try{isDebugEnabled()&&await _logRequest(ctx);let transport=await _getOrCreateTransport(ctx);return transport?(_markSessionAsActive(ctx),await transport.handleRequest(ctx)):ctx.json(MCP_ERRORS.sessionNotFound,400)}catch(err){return error("Error occurred while handling MCP request",err),ctx.json(MCP_ERRORS.internalServerError,500)}}),app.delete("/mcp",async ctx=>{try{let transport=await _getTransport(ctx);return transport?(await transport.close(),ctx.json({ok:!0},200)):ctx.json(MCP_ERRORS.sessionNotFound,400)}catch(err){return error("Error occurred while deleting MCP session",err),ctx.json(MCP_ERRORS.internalServerError,500)}}),app.notFound(ctx=>ctx.json({error:"Not Found",status:404},404)),serve({fetch:app.fetch,port},()=>{trackMCPServerStarted("streamable-http"),info(`Listening on port ${port}`)}),_scheduleIdleSessionCheck()}import{Command,Option,InvalidOptionArgumentError}from"commander";function _parsePort(value){let n=Number(value);if(!Number.isInteger(n)||n<1||n>65535)throw new InvalidOptionArgumentError("port must be an integer between 1 and 65535");return n}function _getOptions(){return new Command().addOption(new Option("--transport <type>","transport type").choices(["stdio","streamable-http"]).default("stdio")).addOption(new Option("--port <number>","port for Streamable HTTP transport").argParser(_parsePort).default(PORT)).allowUnknownOption().allowExcessArguments().parse(process.argv).opts()}async function _shutdown(){await shutdown()}async function main(){let options=_getOptions();for(let signal of["SIGTERM","SIGINT"])process.on(signal,async()=>{await _shutdown(),process.exit(0)});LOG_FILE&&initFileLogging(LOG_FILE),options.transport==="stdio"?(disable(),await startStdioServer()):options.transport==="streamable-http"?(info("Starting MCP server..."),await startStreamableHTTPServer(options.port),info("Started MCP Server")):(error(`Invalid transport: ${options.transport}`),process.exit(1))}main().catch(async err=>{enable(),error("MCP server error",err),await _shutdown(),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-devtools-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "MCP Server for Browser Dev Tools",
5
5
  "private": false,
6
6
  "type": "module",
@@ -1,17 +0,0 @@
1
- var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res)=>function(){return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);function _timeAsString(){return`${new Date().toLocaleTimeString(void 0,{hour:"numeric",minute:"numeric",second:"numeric",hour12:!1,timeZoneName:"short"})}`}function _normalizeArgs(...args){return isDebugEnabled()?args:(args||[]).map(arg=>arg?arg instanceof Error||arg.name&&arg.message&&arg.stack?`${arg.name}: ${arg.message}`:arg:"")}function enable(){enabled=!0}function disable(){enabled=!1}function isDebugEnabled(){return debugEnabled}function debug(...args){enabled&&isDebugEnabled()&&console.debug(BANNER_TEXT,_timeAsString(),"|","DEBUG","-",..._normalizeArgs(...args))}function info(...args){enabled&&console.info(BANNER_TEXT,_timeAsString(),"|","INFO ","-",..._normalizeArgs(...args))}function warn(...args){enabled&&console.warn(BANNER_TEXT,_timeAsString(),"|","WARN ","-",..._normalizeArgs(...args))}function error(...args){enabled&&console.error(BANNER_TEXT,_timeAsString(),"|","ERROR","-",..._normalizeArgs(...args))}function _getCircularReplacer(){let seen=new WeakSet;return(key,value)=>{if(typeof value=="object"&&value!==null){if(seen.has(value))return;seen.add(value)}return value}}function toJson(obj){return JSON.stringify(obj,_getCircularReplacer())}var BANNER_TEXT,enabled,debugEnabled,init_logger=__esm({"src/logger.ts"(){"use strict";BANNER_TEXT="[BROWSER-DEVTOOLS]",enabled=!0,debugEnabled=process.env.DEBUG_ENABLE==="true"}});import path from"node:path";function _envStr(name){let v=process.env[name];if(!v)return;let t=v.trim();return t||void 0}function _envInt(name){let v=_envStr(name);if(!v)return;let n=Number(v);if(Number.isFinite(n))return Math.floor(n)}function _envBool(name){let v=_envStr(name);if(v)return v==="true"}function _parseKeyValueFromEnv(envValue){let headers={};if(!envValue)return headers;let pairs=envValue.split(",");for(let pair of pairs){let trimmed=pair.trim();if(!trimmed)continue;let eqIndex=trimmed.indexOf("=");if(eqIndex===-1)continue;let key=trimmed.slice(0,eqIndex).trim(),value=trimmed.slice(eqIndex+1).trim();!key||!value||(headers[key]=value)}return headers}var PORT=_envInt("PORT")??3e3,TOOL_OUTPUT_SCHEMA_DISABLE=_envBool("TOOL_OUTPUT_SCHEMA_DISABLE")??!1,TOOL_NAME_PREFIX=_envStr("TOOL_NAME_PREFIX"),TOOL_INPUT_METADATA_ENABLE=_envBool("TOOL_INPUT_METADATA_ENABLE")??!1,AVAILABLE_TOOL_DOMAINS=(()=>{let v=_envStr("AVAILABLE_TOOL_DOMAINS");if(!v)return;let set=new Set(v.split(",").map(s=>s.trim().toLowerCase()).filter(Boolean));return set.size>0?set:void 0})(),_PLATFORM_RAW=_envStr("PLATFORM"),PLATFORM=_PLATFORM_RAW==="browser"||_PLATFORM_RAW==="node"?_PLATFORM_RAW:"browser",SESSION_IDLE_SECONDS=_envInt("SESSION_IDLE_SECONDS")??300,SESSION_IDLE_CHECK_SECONDS=_envInt("SESSION_IDLE_CHECK_SECONDS")??30,SESSION_CLOSE_ON_SOCKET_CLOSE=_envBool("SESSION_CLOSE_ON_SOCKET_CLOSE")??!1,BROWSER_HEADLESS_ENABLE=_envBool("BROWSER_HEADLESS_ENABLE")??!0,BROWSER_PERSISTENT_ENABLE=_envBool("BROWSER_PERSISTENT_ENABLE")??!1,BROWSER_PERSISTENT_USER_DATA_DIR=_envStr("BROWSER_PERSISTENT_USER_DATA_DIR")??path.join(process.cwd(),"browser-devtools-mcp"),BROWSER_USE_INSTALLED_ON_SYSTEM=_envBool("BROWSER_USE_INSTALLED_ON_SYSTEM")??!1,BROWSER_EXECUTABLE_PATH=_envStr("BROWSER_EXECUTABLE_PATH"),BROWSER_LOCALE=_envStr("BROWSER_LOCALE"),BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE=_envInt("BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE")??1e3,BROWSER_HTTP_REQUESTS_BUFFER_SIZE=_envInt("BROWSER_HTTP_REQUESTS_BUFFER_SIZE")??1e3,BROWSER_SERVER_INSTRUCTIONS_ENABLE=_envBool("BROWSER_SERVER_INSTRUCTIONS_ENABLE")??!0,BROWSER_POLICY_UI_DEBUGGING_ENABLE=_envBool("BROWSER_POLICY_UI_DEBUGGING_ENABLE")??!1,_BROWSER_CDP_ENDPOINT=_envStr("BROWSER_CDP_ENDPOINT_URL"),_BROWSER_CDP_ENABLE=_envBool("BROWSER_CDP_ENABLE")??!1,BROWSER_CDP_CONNECT_URL=_BROWSER_CDP_ENDPOINT??(_BROWSER_CDP_ENABLE?"http://127.0.0.1:9222":void 0),BROWSER_CDP_ENDPOINT_EXPLICIT=!!_BROWSER_CDP_ENDPOINT,BROWSER_CDP_OPEN_INSPECT=_envStr("BROWSER_CDP_OPEN_INSPECT")!=="false",NODE_SERVER_INSTRUCTIONS_ENABLE=_envBool("NODE_SERVER_INSTRUCTIONS_ENABLE")??!0,NODE_POLICY_DEBUGGING_ENABLE=_envBool("NODE_POLICY_DEBUGGING_ENABLE")??!1,NODE_CONSOLE_MESSAGES_BUFFER_SIZE=_envInt("NODE_CONSOLE_MESSAGES_BUFFER_SIZE")??1e3,NODE_INSPECTOR_HOST=_envStr("NODE_INSPECTOR_HOST"),COLLECTOR_URL=_envStr("COLLECTOR_URL"),COLLECTOR_API_KEY=_envStr("COLLECTOR_API_KEY"),OTEL_ENABLE=_envBool("OTEL_ENABLE")??!1,OTEL_SERVICE_NAME=_envStr("OTEL_SERVICE_NAME")??"frontend",OTEL_SERVICE_VERSION=_envStr("OTEL_SERVICE_VERSION"),OTEL_ASSETS_DIR=_envStr("OTEL_ASSETS_DIR"),OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS=_envStr("OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS")?.split(",")??["click"],OTEL_EXPORTER_TYPE=_envStr("OTEL_EXPORTER_TYPE")??"none",OTEL_EXPORTER_HTTP_URL=_envStr("OTEL_EXPORTER_HTTP_URL"),OTEL_EXPORTER_HTTP_HEADERS=_parseKeyValueFromEnv(_envStr("OTEL_EXPORTER_HTTP_HEADERS")),AWS_REGION=_envStr("AWS_REGION"),AWS_PROFILE=_envStr("AWS_PROFILE"),AMAZON_BEDROCK_ENABLE=_envBool("AMAZON_BEDROCK_ENABLE")??!1,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID=_envStr("AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID"),AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID=_envStr("AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID"),AMAZON_BEDROCK_VISION_MODEL_ID=_envStr("AMAZON_BEDROCK_VISION_MODEL_ID"),FIGMA_ACCESS_TOKEN=_envStr("FIGMA_ACCESS_TOKEN")??"",FIGMA_API_BASE_URL=_envStr("FIGMA_API_BASE_URL")??"https://api.figma.com/v1",WORKING_DIR=_envStr("WORKING_DIR")??process.cwd(),SEARCH_STRATEGY=_envStr("SEARCH_STRATEGY")??"SIMPLE",SCENARIO_SEARCH_STRATEGY=_envStr("SCENARIO_SEARCH_STRATEGY"),DAEMON_PORT=_envInt("DAEMON_PORT")??2020,DAEMON_SESSION_IDLE_SECONDS=_envInt("DAEMON_SESSION_IDLE_SECONDS")??300,DAEMON_SESSION_IDLE_CHECK_SECONDS=_envInt("DAEMON_SESSION_IDLE_CHECK_SECONDS")??30;function normalizeToolName(toolName){return TOOL_NAME_PREFIX?`${TOOL_NAME_PREFIX}${toolName}`:toolName}function stripMCPToolNamePrefixIfPresent(mcpToolName){return TOOL_NAME_PREFIX&&mcpToolName.startsWith(TOOL_NAME_PREFIX)?mcpToolName.slice(TOOL_NAME_PREFIX.length):mcpToolName}function denormalizeToolName(toolName){let n=toolName,colonIdx=n.indexOf(":");return colonIdx>=0&&(n=n.substring(colonIdx+1)),n.length>2&&n.startsWith("<")&&n.endsWith(">")&&(n=n.slice(1,-1)),stripMCPToolNamePrefixIfPresent(n)}function applyNormalizedToolNamesInText(text,canonicalToolNames){if(canonicalToolNames.length===0)return text;let known=new Set(canonicalToolNames);return text.replace(/<([a-zA-Z0-9_-]+)>/g,(full,inner)=>known.has(inner)?normalizeToolName(inner):full)}var ConsoleMessageLevelName=(ConsoleMessageLevelName2=>(ConsoleMessageLevelName2.ALL="all",ConsoleMessageLevelName2.DEBUG="debug",ConsoleMessageLevelName2.INFO="info",ConsoleMessageLevelName2.WARNING="warning",ConsoleMessageLevelName2.ERROR="error",ConsoleMessageLevelName2))(ConsoleMessageLevelName||{});var ConsoleMessageLevel={all:{code:-1},debug:{code:0},info:{code:1},warning:{code:2},error:{code:3}};init_logger();var BASE64_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",BASE64_MAP=new Map;for(let i=0;i<BASE64_CHARS.length;i++)BASE64_MAP.set(BASE64_CHARS[i],i);function _decodeVLQ(encoded){let values=[],shift=0,value=0;for(let char of encoded){let digit=BASE64_MAP.get(char);if(digit===void 0)throw new Error(`Invalid base64 character: ${char}`);let hasContinuation=(digit&32)!==0;if(value+=(digit&31)<<shift,hasContinuation)shift+=5;else{let isNegative=(value&1)!==0;value=value>>1,isNegative&&(value=-value),values.push(value),value=0,shift=0}}return values}function _parseMappings(mappings,sources){let entries=[],lines=mappings.split(";"),generatedLine=0,sourceIndex=0,originalLine=0,originalColumn=0,nameIndex=0;for(let line of lines){let generatedColumn=0,segments=line.split(",");for(let segment of segments){if(!segment)continue;let values=_decodeVLQ(segment);if(values.length===0)continue;generatedColumn+=values[0];let entry={generatedLine,generatedColumn};values.length>=4&&(sourceIndex+=values[1],originalLine+=values[2],originalColumn+=values[3],entry.source=sources[sourceIndex],entry.originalLine=originalLine,entry.originalColumn=originalColumn,values.length>=5&&(nameIndex+=values[4])),entries.push(entry)}generatedLine++}return entries}var SourceMapResolver=class{scripts=new Map;scriptsByUrl=new Map;sourceToScripts=new Map;fetchCache=new Map;page;customFetcher;constructor(source){typeof source=="function"?this.customFetcher=source:this.page=source}registerScript(script){let resolved={scriptId:script.scriptId,url:script.url,sourceMapURL:script.sourceMapURL,originalSources:[]};if(this.scripts.set(script.scriptId,resolved),script.url){let existing=this.scriptsByUrl.get(script.url)||[];existing.push(resolved),this.scriptsByUrl.set(script.url,existing)}}getScriptUrl(scriptId){return this.scripts.get(scriptId)?.url}async loadSourceMap(scriptId){let script=this.scripts.get(scriptId);if(!script||!script.sourceMapURL)return!1;if(script.sourceMap)return!0;try{let sourceMap=await this._fetchSourceMap(script.sourceMapURL,script.url);if(!sourceMap)return!1;script.sourceMap=sourceMap,script.mappings=_parseMappings(sourceMap.mappings,sourceMap.sources),script.originalSources=sourceMap.sources.map(s=>this._resolveSourcePath(s,sourceMap.sourceRoot,script.url));for(let source of script.originalSources){let existing=this.sourceToScripts.get(source)||[];existing.push(script),this.sourceToScripts.set(source,existing)}return!0}catch(error2){return debug(`Failed to load source map for ${script.url}:`,error2),!1}}async loadAllSourceMaps(){let loaded=0;for(let scriptId of this.scripts.keys())await this.loadSourceMap(scriptId)&&loaded++;return loaded}originalToGenerated(originalSource,line,column=0){let normalizedSource=this._normalizeSourcePath(originalSource),scripts=this._findScriptsForSource(normalizedSource);if(scripts.length!==0)for(let script of scripts){if(!script.mappings)continue;let sourceIndex=script.originalSources.findIndex(s=>this._normalizeSourcePath(s)===normalizedSource||s.endsWith(normalizedSource)||normalizedSource.endsWith(s));if(sourceIndex===-1)continue;let bestMatch,bestDistance=1/0;for(let mapping of script.mappings)if(mapping.source===script.sourceMap?.sources[sourceIndex]&&mapping.originalLine!==void 0&&mapping.originalLine===line){let colDist=mapping.originalColumn!==void 0?Math.abs(mapping.originalColumn-column):0;colDist<bestDistance&&(bestDistance=colDist,bestMatch=mapping)}if(bestMatch)return{scriptId:script.scriptId,location:{line:bestMatch.generatedLine,column:bestMatch.generatedColumn}}}}async resolveLocationByUrl(url,line,column=1){let line0=Math.max(0,line-1),column0=Math.max(0,column-1),candidates=this.scriptsByUrl.get(url)||[];if(candidates.length===0)for(let script of this.scripts.values())(script.url===url||script.url.endsWith(url)||url.endsWith(script.url))&&candidates.push(script);for(let script of candidates){if(!await this.loadSourceMap(script.scriptId)||!script.mappings)continue;let resolved=this.generatedToOriginal(script.scriptId,line0,column0);if(resolved)return resolved}return null}generatedToOriginal(scriptId,line,column=0){let script=this.scripts.get(scriptId);if(!script?.mappings)return;let bestMatch,bestDistance=1/0;for(let mapping of script.mappings){if(mapping.generatedLine!==line||mapping.source===void 0)continue;let colDist=Math.abs(mapping.generatedColumn-column);colDist<bestDistance&&(bestDistance=colDist,bestMatch=mapping)}if(bestMatch&&bestMatch.source!==void 0&&bestMatch.originalLine!==void 0){let sourceIndex=script.sourceMap?.sources.indexOf(bestMatch.source);return{source:sourceIndex!==void 0&&sourceIndex>=0?script.originalSources[sourceIndex]:bestMatch.source,line:bestMatch.originalLine,column:bestMatch.originalColumn??0,name:bestMatch.name}}}getOriginalSources(){return Array.from(this.sourceToScripts.keys())}findScriptsForSource(sourcePattern){let normalized=this._normalizeSourcePath(sourcePattern);return this._findScriptsForSource(normalized)}hasSourceMaps(){for(let script of this.scripts.values())if(script.sourceMap)return!0;return!1}clear(){this.scripts.clear(),this.scriptsByUrl.clear(),this.sourceToScripts.clear(),this.fetchCache.clear()}_findScriptsForSource(normalizedSource){let exact=this.sourceToScripts.get(normalizedSource);if(exact&&exact.length>0)return exact;let results=[];for(let[source,scripts]of this.sourceToScripts.entries()){let normalizedKey=this._normalizeSourcePath(source);(normalizedKey.endsWith(normalizedSource)||normalizedSource.endsWith(normalizedKey))&&results.push(...scripts)}return results}_normalizeSourcePath(path3){let normalized=path3.replace(/^webpack:\/\/[^/]*\//,"").replace(/^file:\/\//,"").replace(/^\.*\//,"");for(normalized=normalized.replace(/\\/g,"/");normalized.startsWith("./");)normalized=normalized.slice(2);return normalized}_resolveSourcePath(source,sourceRoot,scriptUrl){return source.startsWith("webpack://")||source.startsWith("http://")||source.startsWith("https://")||sourceRoot&&(source=sourceRoot.replace(/\/$/,"")+"/"+source),source}async _fetchSourceMap(sourceMapURL,scriptUrl){if(sourceMapURL.startsWith("data:"))return this._parseDataUrl(sourceMapURL);let absoluteUrl=this._resolveUrl(sourceMapURL,scriptUrl);if(this.fetchCache.has(absoluteUrl))return this.fetchCache.get(absoluteUrl)||null;try{let sourceMap=null;if(this.customFetcher){let content=await this.customFetcher(absoluteUrl,scriptUrl);content&&(sourceMap=JSON.parse(content))}else this.page&&(sourceMap=await this._fetchViaBrowser(absoluteUrl));return this.fetchCache.set(absoluteUrl,sourceMap),sourceMap}catch(error2){return debug(`Failed to fetch source map from ${absoluteUrl}:`,error2),this.fetchCache.set(absoluteUrl,null),null}}_parseDataUrl(dataUrl){try{let match=dataUrl.match(/^data:[^,]*(?:;base64)?,(.*)$/);if(!match)return null;let isBase64=dataUrl.includes(";base64,"),data=match[1],json=isBase64?Buffer.from(data,"base64").toString("utf-8"):decodeURIComponent(data);return JSON.parse(json)}catch{return null}}_resolveUrl(url,baseUrl){if(url.startsWith("http://")||url.startsWith("https://"))return url;try{return new URL(url,baseUrl).href}catch{return baseUrl.replace(/[^/]*$/,"")+url}}async _fetchViaBrowser(url){if(!this.page)return null;try{let typedResult=await this.page.evaluate(async fetchUrl=>{try{let response=await fetch(fetchUrl);return response.ok?{data:await response.text()}:{error:`HTTP ${response.status}`}}catch(err){return{error:err.message||"Fetch failed"}}},url);return"error"in typedResult?(debug(`Browser fetch error for ${url}: ${typedResult.error}`),null):JSON.parse(typedResult.data)}catch(error2){return debug(`Failed to fetch ${url} via browser:`,error2),null}}};var V8API_DEFAULT_OPTIONS={maxDepth:3,maxProperties:50,maxArrayLength:100,maxStringLength:1e3},V8Api=class{cdp=null;enabled=!1;scripts=new Map;scriptsByUrl=new Map;eventHandlers={};options;cdpProvider;constructor(source,options){if(this.options={...V8API_DEFAULT_OPTIONS,...options},typeof source=="function")this.cdpProvider=source;else if(source&&typeof source.context=="function"){let page=source;this.cdpProvider=async()=>await page.context().newCDPSession(page)}else if(source&&typeof source.send=="function"){let session=source;this.cdp=session,this.cdpProvider=async()=>session}else throw new Error("V8Api: Invalid source. Expected Page, CDPSessionProvider, or ICDPSession.")}getOptions(){return{...this.options}}isEnabled(){return this.enabled}async getCdp(){return this.cdp||(this.cdp=await this.cdpProvider()),this.cdp}on(event,handler){this.eventHandlers[event]=handler}off(event){delete this.eventHandlers[event]}async enable(){if(this.enabled)return;let cdp=await this.getCdp();cdp.on("Debugger.scriptParsed",event=>{let parsed=event;if(this.scripts.set(parsed.scriptId,parsed),parsed.url){let existing=this.scriptsByUrl.get(parsed.url)||[];existing.push(parsed),this.scriptsByUrl.set(parsed.url,existing)}this.eventHandlers.scriptParsed&&this.eventHandlers.scriptParsed(parsed)}),cdp.on("Debugger.paused",event=>{let pausedEvent=event;this.eventHandlers.paused&&this.eventHandlers.paused(pausedEvent)}),cdp.on("Debugger.resumed",()=>{this.eventHandlers.resumed&&this.eventHandlers.resumed()}),await cdp.send("Debugger.enable",{maxScriptsCacheSize:1e8}),await cdp.send("Runtime.enable"),this.enabled=!0}async disable(){if(!(!this.enabled||!this.cdp)){try{await this.cdp.send("Debugger.disable"),await this.cdp.send("Runtime.disable")}catch{}this.scripts.clear(),this.scriptsByUrl.clear(),this.enabled=!1}}async detach(){if(await this.disable(),this.cdp){try{await this.cdp.detach()}catch{}this.cdp=null}}getScripts(){return Array.from(this.scripts.values())}getScript(scriptId){return this.scripts.get(scriptId)}findScriptsByUrl(urlPattern){let regex=new RegExp(urlPattern),results=[];for(let script of this.scripts.values())script.url&&regex.test(script.url)&&results.push(script);return results}async setBreakpointByUrl(options){let cdp=await this.getCdp(),params={lineNumber:options.lineNumber};options.urlRegex?params.urlRegex=options.urlRegex:options.url&&(params.url=options.url),options.columnNumber!==void 0&&(params.columnNumber=options.columnNumber),options.condition&&(params.condition=options.condition);let result=await cdp.send("Debugger.setBreakpointByUrl",params);return{breakpointId:result.breakpointId,locations:result.locations||[]}}async setBreakpoint(location,condition){let cdp=await this.getCdp(),params={location:{scriptId:location.scriptId,lineNumber:location.lineNumber,columnNumber:location.columnNumber}};condition&&(params.condition=condition);let result=await cdp.send("Debugger.setBreakpoint",params);return{breakpointId:result.breakpointId,actualLocation:result.actualLocation}}async removeBreakpoint(breakpointId){await(await this.getCdp()).send("Debugger.removeBreakpoint",{breakpointId})}async resume(){await(await this.getCdp()).send("Debugger.resume")}async stepOver(){await(await this.getCdp()).send("Debugger.stepOver")}async stepInto(){await(await this.getCdp()).send("Debugger.stepInto")}async stepOut(){await(await this.getCdp()).send("Debugger.stepOut")}async pause(){await(await this.getCdp()).send("Debugger.pause")}async setPauseOnExceptions(state){await(await this.getCdp()).send("Debugger.setPauseOnExceptions",{state})}async evaluateOnCallFrame(callFrameId,expression,options){let result=await(await this.getCdp()).send("Debugger.evaluateOnCallFrame",{callFrameId,expression,returnByValue:options?.returnByValue??!0,generatePreview:options?.generatePreview??!0,throwOnSideEffect:options?.throwOnSideEffect??!1});return{result:result.result,exceptionDetails:result.exceptionDetails}}async getProperties(objectId,options){let result=await(await this.getCdp()).send("Runtime.getProperties",{objectId,ownProperties:options?.ownProperties??!0,accessorPropertiesOnly:options?.accessorPropertiesOnly??!1,generatePreview:options?.generatePreview??!0});return{result:result.result||[],internalProperties:result.internalProperties,privateProperties:result.privateProperties}}async getScopeVariables(scope,options){if(!scope.object.objectId)return{};let opts={maxDepth:options?.maxDepth??this.options.maxDepth,maxProperties:options?.maxProperties??this.options.maxProperties,maxArrayLength:options?.maxArrayLength??this.options.maxArrayLength},{result}=await this.getProperties(scope.object.objectId,{ownProperties:!0,generatePreview:!0}),variables={},visited=new Set,propCount=0;for(let prop of result){if(propCount>=opts.maxProperties){variables.__truncated__=`${result.length-propCount} more properties`;break}prop.value&&(variables[prop.name]=await this.extractValueDeep(prop.value,opts.maxDepth,opts.maxProperties,opts.maxArrayLength,visited),propCount++)}return variables}extractValue(obj){return this._extractValueShallow(obj)}async extractValueDeep(obj,maxDepth,maxProperties,maxArrayLength,visited=new Set){let depth=maxDepth??this.options.maxDepth,props=maxProperties??this.options.maxProperties,arrLen=maxArrayLength??this.options.maxArrayLength;if(obj.value!==void 0)return typeof obj.value=="string"&&obj.value.length>this.options.maxStringLength?obj.value.slice(0,this.options.maxStringLength)+`... (${obj.value.length} chars)`:obj.value;if(obj.unserializableValue)return obj.unserializableValue==="NaN"?NaN:obj.unserializableValue==="Infinity"?1/0:obj.unserializableValue==="-Infinity"?-1/0:obj.unserializableValue==="-0"?-0:obj.unserializableValue.endsWith("n")?`BigInt(${obj.unserializableValue.slice(0,-1)})`:obj.unserializableValue;if(obj.subtype==="null")return null;if(obj.type!=="undefined"){if(obj.type==="function")return`[function${obj.description?`: ${obj.description.split(`
2
- `)[0]}`:""}]`;if(!obj.objectId)return this._extractValueShallow(obj);if(depth<=0)return this._getShallowDescription(obj);if(visited.has(obj.objectId))return"[Circular]";visited.add(obj.objectId);try{return obj.subtype==="array"?await this._extractArray(obj.objectId,depth-1,props,arrLen,visited):obj.subtype==="map"?await this._extractMap(obj.objectId,depth-1,props,arrLen,visited):obj.subtype==="set"?await this._extractSet(obj.objectId,depth-1,arrLen,visited):obj.subtype==="date"?obj.description||"[Date]":obj.subtype==="regexp"?obj.description||"[RegExp]":obj.subtype==="error"?obj.description||"[Error]":obj.subtype==="promise"?`[Promise: ${obj.description||"pending"}]`:obj.subtype==="node"||obj.className?.includes("Element")||obj.className?.includes("Node")?`[DOM: ${obj.description||obj.className||"Node"}]`:obj.type==="object"?await this._extractObject(obj.objectId,depth-1,props,arrLen,visited,obj.className):this._extractValueShallow(obj)}catch{return this._getShallowDescription(obj)}}}async _extractArray(objectId,maxDepth,maxProperties,maxArrayLength,visited){let{result}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),arr=[],length=0;for(let prop of result)if(prop.name==="length"&&prop.value?.value!==void 0){length=prop.value.value;break}for(let prop of result){let index=parseInt(prop.name,10);if(!(isNaN(index)||index<0)){if(arr.length>=maxArrayLength)break;prop.value&&(arr[index]=await this.extractValueDeep(prop.value,maxDepth,maxProperties,maxArrayLength,visited))}}return length>maxArrayLength&&(arr.__truncated__=`${length-maxArrayLength} more items`),arr}async _extractMap(objectId,maxDepth,maxProperties,maxArrayLength,visited){let{internalProperties}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),mapObj={__type__:"Map"},entries=[],entriesProp=internalProperties?.find(p=>p.name==="[[Entries]]");if(entriesProp?.value?.objectId){let{result:entryResults}=await this.getProperties(entriesProp.value.objectId,{ownProperties:!0,generatePreview:!0}),count=0;for(let entry of entryResults){if(count>=maxArrayLength)break;let index=parseInt(entry.name,10);if(isNaN(index)||!entry.value?.objectId)continue;let{result:kvResult}=await this.getProperties(entry.value.objectId,{ownProperties:!0,generatePreview:!0}),keyProp=kvResult.find(p=>p.name==="key"),valueProp=kvResult.find(p=>p.name==="value");if(keyProp?.value&&valueProp?.value){let key=await this.extractValueDeep(keyProp.value,maxDepth,maxProperties,maxArrayLength,visited),value=await this.extractValueDeep(valueProp.value,maxDepth,maxProperties,maxArrayLength,visited);entries.push([key,value])}count++}}return mapObj.entries=entries,mapObj}async _extractSet(objectId,maxDepth,maxArrayLength,visited){let{internalProperties}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),setObj={__type__:"Set"},values=[],entriesProp=internalProperties?.find(p=>p.name==="[[Entries]]");if(entriesProp?.value?.objectId){let{result:entryResults}=await this.getProperties(entriesProp.value.objectId,{ownProperties:!0,generatePreview:!0}),count=0;for(let entry of entryResults){if(count>=maxArrayLength)break;let index=parseInt(entry.name,10);isNaN(index)||(entry.value&&values.push(await this.extractValueDeep(entry.value,maxDepth,50,maxArrayLength,visited)),count++)}}return setObj.values=values,setObj}async _extractObject(objectId,maxDepth,maxProperties,maxArrayLength,visited,className){let{result}=await this.getProperties(objectId,{ownProperties:!0,generatePreview:!0}),obj={};className&&className!=="Object"&&(obj.__class__=className);let count=0;for(let prop of result){if(count>=maxProperties){obj.__truncated__=`${result.length-count} more properties`;break}prop.isOwn&&(prop.name.startsWith("__")&&prop.name.endsWith("__")||prop.value&&(obj[prop.name]=await this.extractValueDeep(prop.value,maxDepth,maxProperties,maxArrayLength,visited),count++))}return obj}_extractValueShallow(obj){if(obj.value!==void 0)return obj.value;if(obj.unserializableValue)return obj.unserializableValue==="NaN"?NaN:obj.unserializableValue==="Infinity"?1/0:obj.unserializableValue==="-Infinity"?-1/0:obj.unserializableValue==="-0"?-0:obj.unserializableValue.endsWith("n")?`BigInt(${obj.unserializableValue.slice(0,-1)})`:obj.unserializableValue;if(obj.subtype==="null")return null;if(obj.type!=="undefined")return this._getShallowDescription(obj)}_getShallowDescription(obj){if(obj.description){let desc=obj.description.split(`
3
- `)[0];return desc.length>100?`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}] ${desc.slice(0,100)}...`:`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}] ${desc}`}return`[${obj.type}${obj.subtype?`:${obj.subtype}`:""}]`}async getScriptSource(scriptId){return await(await this.getCdp()).send("Debugger.getScriptSource",{scriptId})}async setScriptSource(scriptId,scriptSource,dryRun){let result=await(await this.getCdp()).send("Debugger.setScriptSource",{scriptId,scriptSource,dryRun:dryRun??!1});return{callFrames:result.callFrames,stackChanged:result.stackChanged,asyncStackTrace:result.asyncStackTrace,exceptionDetails:result.exceptionDetails}}};import*as fs from"node:fs";import*as http from"node:http";import*as https from"node:https";import*as path2 from"node:path";var ProbeKind=(ProbeKind2=>(ProbeKind2.TRACEPOINT="tracepoint",ProbeKind2.LOGPOINT="logpoint",ProbeKind2))(ProbeKind||{}),DEFAULT_NODE_DEBUG_CONFIG={maxSnapshots:1e3,maxCallStackDepth:1,maxFramesWithScopes:1,maxAsyncStackSegments:10,maxFramesPerAsyncSegment:10},STORES=new Map;function _generateId(){let t=Date.now(),r=Math.floor(Math.random()*1e6);return`${t.toString(36)}-${r.toString(36)}`}function _columnForLocationKey(column){return column==null||column===0?1:column}function _locationKey(urlPattern,lineNumber,columnNumber){return`${urlPattern}:${lineNumber}:${columnNumber}`}function _cdpConsoleTypeToLevelName(type){switch(type){case"error":return"error";case"warning":case"warn":return"warning";case"info":return"info";case"debug":return"debug";default:return"info"}}function _cdpArgsToText(args){return!args||args.length===0?"":args.map(a=>a.type==="string"&&a.value!==void 0||a.value!==void 0?String(a.value):a.description?a.description:"[object]").join(" ")}function _evaluateHitCondition(hitCondition,hitCount){try{let condition=hitCondition.trim();return/^[=<>!%]/.test(condition)&&(condition=`hitCount ${condition}`),!!new Function("hitCount",`return (${condition});`)(hitCount)}catch{return!1}}async function _getOtelTraceContext(session){let expression=`(function(){
4
- try {
5
- var api = require('@opentelemetry/api');
6
- var span = api.trace.getActiveSpan();
7
- if (!span) return null;
8
- var ctx = span.spanContext();
9
- return ctx.traceId && ctx.spanId ? { traceId: ctx.traceId, spanId: ctx.spanId } : null;
10
- } catch (e) {
11
- return null;
12
- }
13
- })()`;try{let result=await session.send("Runtime.evaluate",{expression,returnByValue:!0,timeout:500});if(result.exceptionDetails)return null;let value=result.result?.value;if(value&&typeof value.traceId=="string"&&typeof value.spanId=="string")return{traceId:value.traceId,spanId:value.spanId}}catch{}return null}function _createNodeSourceMapFetcher(){return async(url,baseUrl)=>{let filePath=null;if(url.startsWith("file://"))filePath=url.replace("file://","");else if(url.startsWith("/")||url.match(/^[a-zA-Z]:\\/))filePath=url;else if(baseUrl.startsWith("file://")){let baseDir=path2.dirname(baseUrl.replace("file://",""));filePath=path2.resolve(baseDir,url)}else if(!url.startsWith("http://")&&!url.startsWith("https://")){let baseDir=path2.dirname(baseUrl.replace(/^file:\/\//,""));filePath=path2.resolve(baseDir,url)}if(filePath)try{return fs.readFileSync(filePath,"utf-8")}catch{}return url.startsWith("http://")||url.startsWith("https://")?new Promise(resolve2=>{let req=(url.startsWith("https://")?https:http).get(url,res=>{if(res.statusCode!==200){resolve2(null);return}let data="";res.on("data",chunk=>{data+=chunk}),res.on("end",()=>resolve2(data))});req.on("error",()=>resolve2(null)),req.setTimeout(5e3,()=>{req.destroy(),resolve2(null)})}):null}}async function _captureScopes(v8Api,callFrame,maxDepth=3){let scopeSnapshots=[];for(let scope of callFrame.scopeChain)if(!(scope.type==="global"||scope.type==="script"||scope.type==="with"||scope.type==="eval"||scope.type==="wasm-expression-stack")){if(scopeSnapshots.length>=maxDepth)break;try{let variables=await v8Api.getScopeVariables(scope),scopeVariables=[];for(let[name,value]of Object.entries(variables))scopeVariables.push({name,value,type:typeof value});scopeSnapshots.push({type:scope.type,name:scope.name,variables:scopeVariables})}catch{}}return scopeSnapshots}async function _callFrameToSnapshot(v8Api,frame,captureScopes,sourceMapResolver){let scopes=[];captureScopes&&(scopes=await _captureScopes(v8Api,frame));let originalLocation;if(sourceMapResolver){let resolved=sourceMapResolver.generatedToOriginal(frame.location.scriptId,frame.location.lineNumber,frame.location.columnNumber??0);resolved&&(originalLocation={source:resolved.source,line:resolved.line+1,column:resolved.column!==void 0?resolved.column+1:void 0,name:resolved.name})}return{functionName:frame.functionName||"(anonymous)",url:frame.url||"",lineNumber:frame.location.lineNumber+1,columnNumber:frame.location.columnNumber!==void 0?frame.location.columnNumber+1:void 0,scriptId:frame.location.scriptId,scopes,originalLocation}}function _convertAsyncStackTrace(asyncTrace,sourceMapResolver,maxSegments,maxFramesPerSegment){if(!asyncTrace)return;let maxSegs=maxSegments??DEFAULT_NODE_DEBUG_CONFIG.maxAsyncStackSegments,maxFrames=maxFramesPerSegment??DEFAULT_NODE_DEBUG_CONFIG.maxFramesPerAsyncSegment,segments=[],currentTrace=asyncTrace,segmentCount=0;for(;currentTrace&&segmentCount<maxSegs;){let asyncFrames=[];for(let frame of currentTrace.callFrames.slice(0,maxFrames)){let originalLocation;if(sourceMapResolver){let resolved=sourceMapResolver.generatedToOriginal(frame.location.scriptId,frame.location.lineNumber,frame.location.columnNumber??0);resolved&&(originalLocation={source:resolved.source,line:resolved.line+1,column:resolved.column!==void 0?resolved.column+1:void 0,name:resolved.name})}asyncFrames.push({functionName:frame.functionName||"(anonymous)",url:frame.url||"",lineNumber:frame.location.lineNumber+1,columnNumber:frame.location.columnNumber!==void 0?frame.location.columnNumber+1:void 0,originalLocation})}asyncFrames.length>0&&segments.push({description:currentTrace.description,callFrames:asyncFrames}),currentTrace=currentTrace.parent,segmentCount++}return segments.length===0?void 0:{segments}}async function _evaluateWatchExpressionsOnFrame(v8Api,callFrameId,watchExpressions){let results={};for(let watch of watchExpressions.values())try{let result=await v8Api.evaluateOnCallFrame(callFrameId,watch.expression);result.exceptionDetails?results[watch.expression]=`[Error: ${result.exceptionDetails.text||"Evaluation failed"}]`:results[watch.expression]=await v8Api.extractValueDeep(result.result,2)}catch(e){results[watch.expression]=`[Error: ${e.message||"Unknown error"}]`}return results}function getStoreKey(pid,wsUrl){return wsUrl||`pid:${pid}`}async function enableDebugging(storeKey,session,processInfo,v8Options,config){if(STORES.get(storeKey)?.enabled)return;let v8Api=new V8Api(session,v8Options),sourceMapResolver=new SourceMapResolver(_createNodeSourceMapFetcher()),mergedConfig={...DEFAULT_NODE_DEBUG_CONFIG,...config},store={v8Api,sourceMapResolver,probes:new Map,locationIndex:new Map,watchExpressions:new Map,snapshots:[],snapshotSequence:0,consoleMessages:[],consoleMessageSequence:0,config:mergedConfig,enabled:!1,sourceMapsLoaded:!1,exceptionBreakpoint:"none",session,processInfo};STORES.set(storeKey,store),await store.v8Api.enable(),session.on("Runtime.consoleAPICalled",params=>{let type=params.type||"log",args=params.args||[],text=_cdpArgsToText(args),levelName=_cdpConsoleTypeToLevelName(type),levelCode=ConsoleMessageLevel[levelName]?.code??1,location,stackTrace=params.stackTrace;if(stackTrace?.callFrames?.length){let frame=stackTrace.callFrames[0];location={url:frame.url||"",lineNumber:frame.lineNumber??0,columnNumber:frame.columnNumber??0}}store.consoleMessageSequence++,store.consoleMessages.push({type,text,level:{name:levelName,code:levelCode},location,timestamp:Date.now(),sequenceNumber:store.consoleMessageSequence}),store.consoleMessages.length>NODE_CONSOLE_MESSAGES_BUFFER_SIZE&&store.consoleMessages.splice(0,store.consoleMessages.length-NODE_CONSOLE_MESSAGES_BUFFER_SIZE)}),store.v8Api.on("scriptParsed",script=>{store.sourceMapResolver.registerScript(script)});for(let script of store.v8Api.getScripts())store.sourceMapResolver.registerScript(script);store.v8Api.on("paused",async event=>{let startTime=Date.now();try{let isException=event.reason==="exception"||event.reason==="promiseRejection",hitBreakpointIds=event.hitBreakpoints||[],hitProbes=[];for(let probe of store.probes.values()){if(!probe.enabled)continue;if(probe.v8BreakpointIds.some(id=>hitBreakpointIds.includes(id))){let conditionMet=!0;probe.hitCondition&&(conditionMet=_evaluateHitCondition(probe.hitCondition,probe.hitCount+1)),hitProbes.push({probe,conditionMet})}}let shouldCaptureBreakpoint=hitProbes.some(p=>p.conditionMet),shouldCaptureException=isException&&store.exceptionBreakpoint!=="none";for(let{probe}of hitProbes)probe.hitCount++,probe.lastHitAt=Date.now();if((shouldCaptureBreakpoint||shouldCaptureException)&&event.callFrames.length>0){let topFrame=event.callFrames[0],exceptionInfo;if(isException&&event.data){let excData=event.data;exceptionInfo={type:event.reason==="promiseRejection"?"promiseRejection":"exception",message:excData.description||excData.value||String(excData),name:excData.className,stack:excData.description}}let originalLocation,resolvedLoc=store.sourceMapResolver.generatedToOriginal(topFrame.location.scriptId,topFrame.location.lineNumber,topFrame.location.columnNumber??0);resolvedLoc&&(originalLocation={source:resolvedLoc.source,line:resolvedLoc.line+1,column:resolvedLoc.column!==void 0?resolvedLoc.column+1:void 0,name:resolvedLoc.name});let callStackFull=[],framesToProcess=event.callFrames.slice(0,store.config.maxCallStackDepth);for(let i=0;i<framesToProcess.length;i++)callStackFull.push(await _callFrameToSnapshot(store.v8Api,framesToProcess[i],i<store.config.maxFramesWithScopes,store.sourceMapResolver));let asyncStackTraceFull=_convertAsyncStackTrace(event.asyncStackTrace,store.sourceMapResolver,store.config.maxAsyncStackSegments,store.config.maxFramesPerAsyncSegment),traceContext=await _getOtelTraceContext(store.session),probesToCapture=hitProbes.filter(p=>p.conditionMet),snapshotCount=probesToCapture.length+(shouldCaptureException?1:0);for(let s=0;s<snapshotCount;s++){let probeId,isLogpoint,logResult,callStack,asyncStackTrace,watchResults;if(s<probesToCapture.length){let{probe}=probesToCapture[s];if(probeId=probe.id,isLogpoint=probe.kind==="logpoint",isLogpoint&&probe.logExpression)try{let wrappedExpression=`(
14
- ${probe.logExpression}
15
- )`,evalResult=await store.v8Api.evaluateOnCallFrame(topFrame.callFrameId,wrappedExpression,{returnByValue:!0,generatePreview:!0});logResult=store.v8Api.extractValue(evalResult.result)}catch{logResult="[evaluation error]"}else logResult=void 0;isLogpoint?(callStack=[],asyncStackTrace=void 0,watchResults=void 0):(callStack=callStackFull,asyncStackTrace=asyncStackTraceFull,watchResults=store.watchExpressions.size>0?await _evaluateWatchExpressionsOnFrame(store.v8Api,topFrame.callFrameId,store.watchExpressions):void 0)}else probeId="__exception__",isLogpoint=!1,logResult=void 0,callStack=callStackFull,asyncStackTrace=asyncStackTraceFull,watchResults=store.watchExpressions.size>0?await _evaluateWatchExpressionsOnFrame(store.v8Api,topFrame.callFrameId,store.watchExpressions):void 0;let snapshot={id:_generateId(),probeId,timestamp:Date.now(),sequenceNumber:++store.snapshotSequence,url:topFrame.url||"",lineNumber:topFrame.location.lineNumber+1,columnNumber:topFrame.location.columnNumber!==void 0?topFrame.location.columnNumber+1:void 0,originalLocation,exception:exceptionInfo,callStack,asyncStackTrace,logResult,watchResults,captureTimeMs:Date.now()-startTime,traceContext:traceContext??void 0};store.snapshots.push(snapshot)}store.snapshots.length>store.config.maxSnapshots&&store.snapshots.splice(0,store.snapshots.length-store.config.maxSnapshots)}}finally{await store.v8Api.resume()}}),store.enabled=!0,store.sourceMapResolver.loadAllSourceMaps().then(()=>{store.sourceMapsLoaded=!0}).catch(()=>{})}async function disableDebugging(storeKey){let store=STORES.get(storeKey);if(store?.enabled){for(let entry of store.locationIndex.values())try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}store.locationIndex.clear(),store.probes.clear(),store.snapshots.length=0,store.snapshotSequence=0,store.consoleMessages.length=0,store.consoleMessageSequence=0,await store.v8Api.disable(),store.enabled=!1}}async function detachDebugging(storeKey){let store=STORES.get(storeKey);store&&(await disableDebugging(storeKey),await store.v8Api.detach(),STORES.delete(storeKey))}function isDebuggingEnabled(storeKey){return STORES.get(storeKey)?.enabled??!1}function getStore(storeKey){return STORES.get(storeKey)}async function resolveSourceLocation(storeKey,url,line,column=1){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Not connected to Node.js process or debugging not enabled. You MUST connect first.");let resolved=await store.sourceMapResolver.resolveLocationByUrl(url,line,column);return resolved?{source:resolved.source,line:resolved.line+1,column:resolved.column+1,name:resolved.name}:null}function listStoreKeys(){return Array.from(STORES.keys())}async function setExceptionBreakpoint(storeKey,state){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");await store.v8Api.setPauseOnExceptions(state),store.exceptionBreakpoint=state}function getExceptionBreakpoint(storeKey){return STORES.get(storeKey)?.exceptionBreakpoint??"none"}async function createProbe(storeKey,options){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");let probeId=_generateId(),columnForKey=_columnForLocationKey(options.columnNumber),locationKey=_locationKey(options.urlPattern,options.lineNumber,columnForKey),existingEntry=store.locationIndex.get(locationKey);if(existingEntry){existingEntry.refCount++;let probe2={id:probeId,kind:options.kind,enabled:!0,urlPattern:options.urlPattern,lineNumber:options.lineNumber,columnNumber:options.columnNumber,condition:options.condition,logExpression:options.logExpression,hitCondition:options.hitCondition,v8BreakpointIds:[existingEntry.breakpointId],resolvedLocations:existingEntry.resolvedLocations,hitCount:0,createdAt:Date.now()};return store.probes.set(probeId,probe2),probe2}let fullCondition=options.condition?`(${options.condition})`:"true",line0based=options.lineNumber-1,column0based=columnForKey-1,resolved=store.sourceMapResolver.originalToGenerated(options.urlPattern,line0based,column0based),breakpointId,resolvedLocationsCount=0;if(resolved)try{breakpointId=(await store.v8Api.setBreakpoint({scriptId:resolved.scriptId,lineNumber:resolved.location.line,columnNumber:resolved.location.column},fullCondition)).breakpointId,resolvedLocationsCount=1}catch{let scriptUrl=store.sourceMapResolver.getScriptUrl(resolved.scriptId);if(scriptUrl){let result=await store.v8Api.setBreakpointByUrl({url:scriptUrl,lineNumber:resolved.location.line,columnNumber:resolved.location.column,condition:fullCondition});breakpointId=result.breakpointId,resolvedLocationsCount=result.locations.length}else throw new Error("Failed to set breakpoint at resolved location and could not fall back (script URL unknown). A probe may already exist at this line; remove it first or use a different line.")}else{let urlRegex=options.urlPattern.replace(/\\([.*+?^${}()|[\]\\/-])/g,"$1").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*").replace(/\\\?/g,"."),result=await store.v8Api.setBreakpointByUrl({urlRegex,lineNumber:options.lineNumber-1,columnNumber:options.columnNumber!=null?Math.max(0,options.columnNumber-1):void 0,condition:fullCondition});breakpointId=result.breakpointId,resolvedLocationsCount=result.locations.length}store.locationIndex.set(locationKey,{breakpointId,resolvedLocations:resolvedLocationsCount,refCount:1});let probe={id:probeId,kind:options.kind,enabled:!0,urlPattern:options.urlPattern,lineNumber:options.lineNumber,columnNumber:options.columnNumber,condition:options.condition,logExpression:options.logExpression,hitCondition:options.hitCondition,v8BreakpointIds:[breakpointId],resolvedLocations:resolvedLocationsCount,hitCount:0,createdAt:Date.now()};return store.probes.set(probeId,probe),probe}async function removeProbe(storeKey,probeId){let store=STORES.get(storeKey);if(!store)return!1;let probe=store.probes.get(probeId);if(!probe)return!1;let locationKey=_locationKey(probe.urlPattern,probe.lineNumber,_columnForLocationKey(probe.columnNumber)),entry=store.locationIndex.get(locationKey);if(entry&&(entry.refCount--,entry.refCount===0)){try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}store.locationIndex.delete(locationKey)}return store.probes.delete(probeId),!0}function listProbes(storeKey){return Array.from(STORES.get(storeKey)?.probes.values()??[])}async function clearProbes(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.probes.size;for(let entry of store.locationIndex.values())try{await store.v8Api.removeBreakpoint(entry.breakpointId)}catch{}return store.locationIndex.clear(),store.probes.clear(),count}function getSnapshots(storeKey){return[...STORES.get(storeKey)?.snapshots??[]]}function getSnapshotsByProbe(storeKey,probeId){return(STORES.get(storeKey)?.snapshots??[]).filter(s=>s.probeId===probeId)}function clearSnapshots(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.snapshots.length;return store.snapshots.length=0,count}function clearSnapshotsByProbe(storeKey,probeId){let store=STORES.get(storeKey);if(!store)return 0;let before=store.snapshots.length;return store.snapshots=store.snapshots.filter(s=>s.probeId!==probeId),before-store.snapshots.length}function getSnapshotStats(storeKey){let store=STORES.get(storeKey);if(!store||store.snapshots.length===0)return{totalSnapshots:0,snapshotsByProbe:{},averageCaptureTimeMs:0};let snapshotsByProbe={},totalCaptureTime=0;for(let s of store.snapshots)snapshotsByProbe[s.probeId]=(snapshotsByProbe[s.probeId]||0)+1,totalCaptureTime+=s.captureTimeMs;return{totalSnapshots:store.snapshots.length,snapshotsByProbe,oldestTimestamp:store.snapshots[0].timestamp,newestTimestamp:store.snapshots[store.snapshots.length-1].timestamp,averageCaptureTimeMs:totalCaptureTime/store.snapshots.length}}function getConsoleMessages(storeKey){return[...STORES.get(storeKey)?.consoleMessages??[]]}function addWatchExpression(storeKey,expression){let store=STORES.get(storeKey);if(!store)throw new Error("Debug store not initialized");let id=_generateId(),watchExpr={id,expression,createdAt:Date.now()};return store.watchExpressions.set(id,watchExpr),watchExpr}function removeWatchExpression(storeKey,watchExpressionId){return STORES.get(storeKey)?.watchExpressions.delete(watchExpressionId)??!1}function listWatchExpressions(storeKey){return Array.from(STORES.get(storeKey)?.watchExpressions.values()??[])}function clearWatchExpressions(storeKey){let store=STORES.get(storeKey);if(!store)return 0;let count=store.watchExpressions.size;return store.watchExpressions.clear(),count}async function loadSourceMaps(storeKey){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Debugging is not enabled");let loaded=await store.sourceMapResolver.loadAllSourceMaps(),sources=store.sourceMapResolver.getOriginalSources();return store.sourceMapsLoaded=!0,{loaded,sources}}function hasSourceMaps(storeKey){return STORES.get(storeKey)?.sourceMapResolver.hasSourceMaps()??!1}function getOriginalSources(storeKey){return STORES.get(storeKey)?.sourceMapResolver.getOriginalSources()??[]}function getScripts(storeKey){return STORES.get(storeKey)?.v8Api.getScripts()??[]}function wrapScriptInAsyncIIFE(script){return`(async function() { ${script} })()`}function formatEvaluationException(exc){let parts=[],text=exc.text??exc.description;text&&parts.push(text);let desc=exc.exception?.description;desc&&desc!==text&&parts.push(desc);let className=exc.exception?.className;className&&!parts.some(p=>p.includes(className))&&parts.push(className),parts.length===0&&parts.push(JSON.stringify(exc));let stack=exc.stackTrace?.callFrames?.slice(0,5).map(f=>` at ${f.functionName??"?"} (${f.url??"?"}:${f.lineNumber??0})`).join(`
16
- `);return stack&&parts.push(`Stack:
17
- ${stack}`),parts.join(" \u2014 ")}async function evaluateInNode(storeKey,expression,timeoutMs=5e3){let store=STORES.get(storeKey);if(!store?.enabled)throw new Error("Not connected to Node.js process or debugging not enabled. You MUST connect first.");let codeToRun=wrapScriptInAsyncIIFE(expression),result=await store.session.send("Runtime.evaluate",{expression:codeToRun,returnByValue:!0,awaitPromise:!0,timeout:Math.min(timeoutMs,3e4)});if(result.exceptionDetails){let exc=result.exceptionDetails,message=formatEvaluationException(exc);throw new Error(`Node evaluation failed: ${message}`)}return store.v8Api.extractValue(result.result)}export{__esm,__export,__toCommonJS,PORT,TOOL_OUTPUT_SCHEMA_DISABLE,TOOL_INPUT_METADATA_ENABLE,AVAILABLE_TOOL_DOMAINS,PLATFORM,SESSION_IDLE_SECONDS,SESSION_IDLE_CHECK_SECONDS,SESSION_CLOSE_ON_SOCKET_CLOSE,BROWSER_HEADLESS_ENABLE,BROWSER_PERSISTENT_ENABLE,BROWSER_PERSISTENT_USER_DATA_DIR,BROWSER_USE_INSTALLED_ON_SYSTEM,BROWSER_EXECUTABLE_PATH,BROWSER_LOCALE,BROWSER_CONSOLE_MESSAGES_BUFFER_SIZE,BROWSER_HTTP_REQUESTS_BUFFER_SIZE,BROWSER_SERVER_INSTRUCTIONS_ENABLE,BROWSER_POLICY_UI_DEBUGGING_ENABLE,BROWSER_CDP_CONNECT_URL,BROWSER_CDP_ENDPOINT_EXPLICIT,BROWSER_CDP_OPEN_INSPECT,NODE_SERVER_INSTRUCTIONS_ENABLE,NODE_POLICY_DEBUGGING_ENABLE,NODE_CONSOLE_MESSAGES_BUFFER_SIZE,NODE_INSPECTOR_HOST,COLLECTOR_URL,COLLECTOR_API_KEY,OTEL_ENABLE,OTEL_SERVICE_NAME,OTEL_SERVICE_VERSION,OTEL_ASSETS_DIR,OTEL_INSTRUMENTATION_USER_INTERACTION_EVENTS,OTEL_EXPORTER_TYPE,OTEL_EXPORTER_HTTP_URL,OTEL_EXPORTER_HTTP_HEADERS,AWS_REGION,AWS_PROFILE,AMAZON_BEDROCK_ENABLE,AMAZON_BEDROCK_IMAGE_EMBED_MODEL_ID,AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID,AMAZON_BEDROCK_VISION_MODEL_ID,FIGMA_ACCESS_TOKEN,FIGMA_API_BASE_URL,WORKING_DIR,SEARCH_STRATEGY,SCENARIO_SEARCH_STRATEGY,DAEMON_PORT,DAEMON_SESSION_IDLE_SECONDS,DAEMON_SESSION_IDLE_CHECK_SECONDS,normalizeToolName,denormalizeToolName,applyNormalizedToolNamesInText,enable,disable,isDebugEnabled,debug,info,warn,error,toJson,init_logger,ConsoleMessageLevelName,ConsoleMessageLevel,V8Api,SourceMapResolver,ProbeKind,DEFAULT_NODE_DEBUG_CONFIG,getStoreKey,enableDebugging,disableDebugging,detachDebugging,isDebuggingEnabled,getStore,resolveSourceLocation,listStoreKeys,setExceptionBreakpoint,getExceptionBreakpoint,createProbe,removeProbe,listProbes,clearProbes,getSnapshots,getSnapshotsByProbe,clearSnapshots,clearSnapshotsByProbe,getSnapshotStats,getConsoleMessages,addWatchExpression,removeWatchExpression,listWatchExpressions,clearWatchExpressions,loadSourceMaps,hasSourceMaps,getOriginalSources,getScripts,evaluateInNode};