browser-devtools-mcp 0.2.20 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -17
- package/SECURITY.md +7 -1
- package/dist/cli/runner.js +1 -1
- package/dist/{core-5RK2ZKSC.js → core-5CXZ44ZY.js} +1 -1
- package/dist/{core-74IS3ZCO.js → core-C2BFD6GI.js} +38 -23
- package/dist/core-ZL4SKOEO.js +13 -0
- package/dist/daemon-server.js +1 -1
- package/dist/index.js +1 -1
- package/dist/platform/browser/types.d.ts +1 -32
- package/package.json +1 -1
- package/dist/core-22BVGANX.js +0 -13
package/README.md
CHANGED
|
@@ -61,18 +61,18 @@ Choose the platform by running the appropriate MCP server or CLI:
|
|
|
61
61
|
## Browser Platform Features
|
|
62
62
|
|
|
63
63
|
### Content Tools
|
|
64
|
-
- **Screenshots**: Capture full page or specific elements (PNG/JPEG) with image data
|
|
64
|
+
- **Screenshots**: Capture full page or specific elements (PNG/JPEG) with image data; optional `annotate: true` overlays numbered labels (1, 2, ...) on elements from the last ARIA snapshot refs and returns an `annotations` array (ref, number, role, name, box). If the ref map is empty, a snapshot is taken automatically. Set `annotateContent: true` to also include content elements (headings, list items, etc.) in the overlay. Set `annotateCursorInteractive: true` to also include cursor-interactive elements (clickable/focusable by CSS without ARIA role) in the overlay. With `selector`, only annotations overlapping that element are returned and box coordinates are element-relative; with `fullPage: true` (no selector), box coordinates are document-relative.
|
|
65
65
|
- **HTML/Text Extraction**: Get page content with filtering, cleaning, and minification options
|
|
66
66
|
- **PDF Export**: Save pages as PDF documents with customizable format and margins
|
|
67
67
|
|
|
68
68
|
### Interaction Tools
|
|
69
|
-
- **Click**: Click elements by CSS selector
|
|
70
|
-
- **Fill**: Fill form inputs
|
|
71
|
-
- **Hover**: Hover over elements
|
|
72
|
-
- **Press Key**: Simulate keyboard input
|
|
73
|
-
- **Select**: Select dropdown options
|
|
74
|
-
- **Drag**: Drag and drop operations
|
|
75
|
-
- **Scroll**: Scroll the page viewport or specific scrollable elements with multiple modes (by, to, top, bottom, left, right)
|
|
69
|
+
- **Click**: Click elements by CSS selector or snapshot ref (e.g. `e1`, `@e1`, `ref=e1`). Refs come from `a11y_take-aria-snapshot` and are valid until the next snapshot or navigation.
|
|
70
|
+
- **Fill**: Fill form inputs (selector or ref)
|
|
71
|
+
- **Hover**: Hover over elements (selector or ref)
|
|
72
|
+
- **Press Key**: Simulate keyboard input; optional selector or ref (e.g. `e1`, `@e1`) to focus an element before sending the key
|
|
73
|
+
- **Select**: Select dropdown options (selector or ref)
|
|
74
|
+
- **Drag**: Drag and drop operations (source and target as selector or ref)
|
|
75
|
+
- **Scroll**: Scroll the page viewport or specific scrollable elements with multiple modes (by, to, top, bottom, left, right); optional selector/ref for scrollable container
|
|
76
76
|
- **Resize Viewport**: Resize the page viewport using Playwright viewport emulation
|
|
77
77
|
- **Resize Window**: Resize the real browser window (OS-level) using Chrome DevTools Protocol
|
|
78
78
|
|
|
@@ -96,7 +96,7 @@ Choose the platform by running the appropriate MCP server or CLI:
|
|
|
96
96
|
- **Wait for Network Idle**: Wait until the page reaches a network-idle condition based on in-flight request count, useful for SPA pages and before taking screenshots
|
|
97
97
|
|
|
98
98
|
### Accessibility (A11Y) Tools
|
|
99
|
-
- **ARIA Snapshots**: Capture semantic structure and accessibility roles in YAML format
|
|
99
|
+
- **ARIA Snapshots**: Capture semantic structure and accessibility roles in YAML format. Returns a tree with element refs (e1, e2, ...) and a `refs` map; refs are stored in session context for use in interaction tools (click, fill, hover, select, drag, scroll, press-key) as the selector (e.g. `e1`, `@e1`, `ref=e1`). Refs are valid until the next ARIA snapshot or navigation—re-snapshot after page/DOM changes. Options: **interactiveOnly** (only interactive elements get refs); **cursorInteractive: true** (also assign refs to elements that are clickable/focusable by CSS but have no ARIA role, e.g. custom div/span buttons); **selector** (scope the snapshot to an element).
|
|
100
100
|
- **AX Tree Snapshots**: Combine Chromium's Accessibility tree with runtime visual diagnostics (bounding boxes, visibility, occlusion detection, computed styles)
|
|
101
101
|
|
|
102
102
|
### Stub Tools
|
|
@@ -1168,10 +1168,14 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1168
1168
|
- `type` (enum, optional): Image format - "png" or "jpeg" (default: "png")
|
|
1169
1169
|
- `quality` (number, optional): The quality of the image, between 0-100. Not applicable to PNG images, only used for JPEG format (default: 100)
|
|
1170
1170
|
- `includeBase64` (boolean, optional): Include base64-encoded image data in the response (default: false)
|
|
1171
|
+
- `annotate` (boolean, optional): Overlay numbered labels (1, 2, …) on elements from the session ref map; refs are built from the last ARIA snapshot or auto-taken if ref map is empty (default: false)
|
|
1172
|
+
- `annotateContent` (boolean, optional): When true with `annotate`, include content elements (headings, list items, etc.) in the overlay; uses interactiveOnly: false when building refs for this screenshot (default: false)
|
|
1173
|
+
- `annotateCursorInteractive` (boolean, optional): When true with `annotate`, also include cursor-interactive elements (clickable/focusable by CSS without ARIA role) in the overlay (default: false)
|
|
1171
1174
|
|
|
1172
1175
|
**Returns:**
|
|
1173
1176
|
- `filePath` (string): Full path of the saved screenshot file
|
|
1174
1177
|
- `image` (object, optional): Screenshot image data with mimeType (only included when `includeBase64` is true)
|
|
1178
|
+
- `annotations` (array, optional): When `annotate` is true, list of { ref, number, role, name, box } for each overlaid element; box coordinates are document-relative for fullPage, element-relative when `selector` is used
|
|
1175
1179
|
|
|
1176
1180
|
**Notes:**
|
|
1177
1181
|
- The screenshot is always saved to the file system and the file path is returned
|
|
@@ -1179,6 +1183,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1179
1183
|
- Set `includeBase64` to true when the AI assistant cannot access the MCP server's file system (e.g., remote server, containerized environment, or different machine)
|
|
1180
1184
|
- The `quality` parameter only applies to JPEG images. PNG images are always saved at full quality
|
|
1181
1185
|
- Lower quality values (e.g., 50-70) result in smaller file sizes but reduced image quality
|
|
1186
|
+
- Annotation uses the session ref map; use `annotateContent` to include headings/content, or `annotateCursorInteractive` to include CSS-clickable elements, without a prior ARIA snapshot with those options
|
|
1182
1187
|
</details>
|
|
1183
1188
|
|
|
1184
1189
|
<details>
|
|
@@ -1229,7 +1234,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1229
1234
|
<summary><code>interaction_click</code> - Clicks an element on the page.</summary>
|
|
1230
1235
|
|
|
1231
1236
|
**Parameters:**
|
|
1232
|
-
- `selector` (string, required): CSS selector for the element to click
|
|
1237
|
+
- `selector` (string, required): CSS selector or ref (e.g. `e1`, `@e1`) for the element to click
|
|
1233
1238
|
- `timeoutMs` (number, optional): Time to wait for the element in ms (default: 10000)
|
|
1234
1239
|
</details>
|
|
1235
1240
|
|
|
@@ -1237,7 +1242,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1237
1242
|
<summary><code>interaction_fill</code> - Fills a form input field.</summary>
|
|
1238
1243
|
|
|
1239
1244
|
**Parameters:**
|
|
1240
|
-
- `selector` (string, required): CSS selector for the input field
|
|
1245
|
+
- `selector` (string, required): CSS selector or ref (e.g. `e1`, `@e1`) for the input field
|
|
1241
1246
|
- `value` (string, required): Value to fill
|
|
1242
1247
|
- `timeoutMs` (number, optional): Time to wait for the element in ms (default: 10000)
|
|
1243
1248
|
</details>
|
|
@@ -1246,7 +1251,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1246
1251
|
<summary><code>interaction_hover</code> - Hovers over an element.</summary>
|
|
1247
1252
|
|
|
1248
1253
|
**Parameters:**
|
|
1249
|
-
- `selector` (string, required): CSS selector for the element to hover
|
|
1254
|
+
- `selector` (string, required): CSS selector or ref (e.g. `e1`, `@e1`) for the element to hover
|
|
1250
1255
|
- `timeoutMs` (number, optional): Time to wait for the element in ms (default: 10000)
|
|
1251
1256
|
</details>
|
|
1252
1257
|
|
|
@@ -1255,7 +1260,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1255
1260
|
|
|
1256
1261
|
**Parameters:**
|
|
1257
1262
|
- `key` (string, required): Key to press (e.g., "Enter", "Escape", "Tab")
|
|
1258
|
-
- `selector` (string, optional): CSS selector to focus before sending the key
|
|
1263
|
+
- `selector` (string, optional): CSS selector or ref (e.g. `e1`, `@e1`) to focus before sending the key
|
|
1259
1264
|
- `holdMs` (number, optional): Duration in milliseconds to hold the key (repeat duration if `repeat` is true)
|
|
1260
1265
|
- `repeat` (boolean, optional, default: false): If true, simulates key auto-repeat by pressing repeatedly during `holdMs`
|
|
1261
1266
|
- `repeatIntervalMs` (number, optional, default: 50, min: 10): Interval between repeated key presses in ms (only when `repeat` is true)
|
|
@@ -1266,7 +1271,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1266
1271
|
<summary><code>interaction_select</code> - Selects an option from a dropdown.</summary>
|
|
1267
1272
|
|
|
1268
1273
|
**Parameters:**
|
|
1269
|
-
- `selector` (string, required): CSS selector for the select element
|
|
1274
|
+
- `selector` (string, required): CSS selector or ref (e.g. `e1`, `@e1`) for the select element
|
|
1270
1275
|
- `value` (string, required): Value to select
|
|
1271
1276
|
- `timeoutMs` (number, optional): Time to wait for the element in ms (default: 10000)
|
|
1272
1277
|
</details>
|
|
@@ -1275,8 +1280,8 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1275
1280
|
<summary><code>interaction_drag</code> - Performs drag and drop operation.</summary>
|
|
1276
1281
|
|
|
1277
1282
|
**Parameters:**
|
|
1278
|
-
- `sourceSelector` (string, required): CSS selector for the source element
|
|
1279
|
-
- `targetSelector` (string, required): CSS selector for the target element
|
|
1283
|
+
- `sourceSelector` (string, required): CSS selector or ref (e.g. `e1`, `@e1`) for the source element
|
|
1284
|
+
- `targetSelector` (string, required): CSS selector or ref for the target element
|
|
1280
1285
|
- `timeoutMs` (number, optional): Time to wait for source and target elements in ms (default: 10000)
|
|
1281
1286
|
</details>
|
|
1282
1287
|
|
|
@@ -1285,7 +1290,7 @@ The server can be configured using environment variables. Configuration is divid
|
|
|
1285
1290
|
|
|
1286
1291
|
**Parameters:**
|
|
1287
1292
|
- `mode` (enum, optional): Scroll mode - "by" (relative delta), "to" (absolute position), "top", "bottom", "left", "right" (default: "by")
|
|
1288
|
-
- `selector` (string, optional): CSS selector for a scrollable container. If omitted, scrolls the document viewport
|
|
1293
|
+
- `selector` (string, optional): CSS selector or ref (e.g. `e1`, `@e1`) for a scrollable container. If omitted, scrolls the document viewport
|
|
1289
1294
|
- `dx` (number, optional): Horizontal scroll delta in pixels (used when mode="by", default: 0)
|
|
1290
1295
|
- `dy` (number, optional): Vertical scroll delta in pixels (used when mode="by", default: 0)
|
|
1291
1296
|
- `x` (number, optional): Absolute horizontal scroll position in pixels (used when mode="to")
|
package/SECURITY.md
CHANGED
|
@@ -53,10 +53,16 @@ Browser DevTools MCP provides powerful browser automation capabilities. Users sh
|
|
|
53
53
|
|
|
54
54
|
4. **Screenshot/PDF Capture**: Content tools can capture sensitive information
|
|
55
55
|
- Screenshots may contain PII or credentials visible on screen
|
|
56
|
+
- Optional annotated screenshots overlay ref labels and return an annotations array (ref, role, name, box); when refs are empty, an ARIA snapshot is taken automatically to populate refs
|
|
56
57
|
- PDFs preserve full page content
|
|
57
58
|
- Be mindful of what pages are captured
|
|
58
59
|
|
|
59
|
-
5. **
|
|
60
|
+
5. **ARIA Snapshots and Ref Map**: Session context stores a ref map (e1, e2, ...) from the last ARIA snapshot
|
|
61
|
+
- Refs map to element roles, names, and selectors; used by interaction tools (click, fill, hover, select, drag, scroll, press-key) and annotated screenshots
|
|
62
|
+
- Ref map is session-scoped and not persisted; it is cleared on navigation or when a new snapshot is taken
|
|
63
|
+
- Cursor-interactive refs (when cursorInteractive is enabled) may include generated CSS selectors for elements without ARIA roles
|
|
64
|
+
|
|
65
|
+
6. **Debug Tools**: Non-blocking debugging capabilities capture runtime state
|
|
60
66
|
- Tracepoints capture call stack and local variables (may include sensitive data)
|
|
61
67
|
- Logpoints evaluate expressions in page context
|
|
62
68
|
- Exception snapshots capture error state and stack traces
|
package/dist/cli/runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{platformInfo}from"../core-74IS3ZCO.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-22BVGANX.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 _createOption(name,zodType){let{innerType,isOptional,defaultValue}=_unwrapZodType(zodType),description=_getDescription(zodType)||`The ${name} value`,flagName=_toKebabCase(name),typeName=innerType._def.typeName,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.ZodBoolean:option=new Option(`--${flagName}`,description);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;typeof literalValue=="boolean"?option=new Option(`--${flagName}`,description):(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){let options=[];for(let[name,zodType]of Object.entries(schema)){let option=_createOption(name,zodType);option&&options.push(option)}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());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{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),cliProvider=platformInfo.cliInfo.cliProvider,tools=cliProvider.tools,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=path.join(__dirname,"..","daemon-server.js"),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(resolve=>setTimeout(resolve,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(()=>({}));throw _debug("Tool call error:",errorBody),new Error(errorBody?.error?.message||`HTTP ${response.status}: ${response.statusText}`)}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{platformInfo}from"../core-C2BFD6GI.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-ZL4SKOEO.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 _createOption(name,zodType){let{innerType,isOptional,defaultValue}=_unwrapZodType(zodType),description=_getDescription(zodType)||`The ${name} value`,flagName=_toKebabCase(name),typeName=innerType._def.typeName,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.ZodBoolean:option=new Option(`--${flagName}`,description);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;typeof literalValue=="boolean"?option=new Option(`--${flagName}`,description):(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){let options=[];for(let[name,zodType]of Object.entries(schema)){let option=_createOption(name,zodType);option&&options.push(option)}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());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{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),cliProvider=platformInfo.cliInfo.cliProvider,tools=cliProvider.tools,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=path.join(__dirname,"..","daemon-server.js"),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(resolve=>setTimeout(resolve,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(()=>({}));throw _debug("Tool call error:",errorBody),new Error(errorBody?.error?.message||`HTTP ${response.status}: ${response.statusText}`)}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-
|
|
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-ZL4SKOEO.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};
|