what-devtools-mcp 0.12.4 → 0.13.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-devtools-mcp",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
4
4
  "description": "MCP server bridging AI agents to live What Framework app state via WebSocket",
5
5
  "type": "module",
6
6
  "bin": {
package/src/bridge.js CHANGED
@@ -13,6 +13,12 @@ import { join } from 'path';
13
13
  const MAX_EVENT_LOG = 1000;
14
14
  const MAX_ERROR_LOG = 100;
15
15
 
16
+ /**
17
+ * @param {object} [options]
18
+ * @param {number} [options.port]
19
+ * @param {string} [options.host]
20
+ * @param {(err: any) => void} [options.onError]
21
+ */
16
22
  export function createBridge({ port = 9229, host = '127.0.0.1', onError } = {}) {
17
23
  let latestSnapshot = null;
18
24
  const eventLog = [];
@@ -601,7 +601,7 @@ export async function handleExtendedCommand(command, args, devtools) {
601
601
  tag: el.tagName.toLowerCase(),
602
602
  type: el.getAttribute('type') || undefined,
603
603
  label: label || '(unlabeled)',
604
- disabled: el.disabled || undefined,
604
+ disabled: /** @type {any} */ (el).disabled || undefined,
605
605
  rect: rectOf(el),
606
606
  });
607
607
  }
@@ -768,7 +768,7 @@ export async function handleExtendedCommand(command, args, devtools) {
768
768
  const canvas = document.createElement('canvas');
769
769
  canvas.width = canvasWidth;
770
770
  canvas.height = canvasHeight;
771
- const ctx = canvas.getContext('2d');
771
+ const ctx = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
772
772
  ctx.scale(scale * dpr, scale * dpr);
773
773
 
774
774
  // Load SVG blob as image
@@ -801,7 +801,7 @@ export async function handleExtendedCommand(command, args, devtools) {
801
801
  const smallCanvas = document.createElement('canvas');
802
802
  smallCanvas.width = Math.ceil(canvasWidth / 2);
803
803
  smallCanvas.height = Math.ceil(canvasHeight / 2);
804
- const smallCtx = smallCanvas.getContext('2d');
804
+ const smallCtx = /** @type {CanvasRenderingContext2D} */ (smallCanvas.getContext('2d'));
805
805
  smallCtx.drawImage(canvas, 0, 0, smallCanvas.width, smallCanvas.height);
806
806
  dataUrl = smallCanvas.toDataURL('image/jpeg', 0.3);
807
807
  base64 = dataUrl.split(',')[1];
package/src/client.js CHANGED
@@ -7,7 +7,6 @@
7
7
  // Branded console logger
8
8
  const BADGE = 'background:#6366f1;color:#fff;padding:2px 6px;border-radius:3px;font-weight:bold';
9
9
  const BADGE_CMD = 'background:#22c55e;color:#fff;padding:2px 6px;border-radius:3px;font-weight:bold';
10
- const BADGE_EVENT = 'background:#f97316;color:#fff;padding:2px 6px;border-radius:3px;font-weight:bold';
11
10
  const BADGE_WARN = 'background:#eab308;color:#000;padding:2px 6px;border-radius:3px;font-weight:bold';
12
11
  const DIM = 'color:#888';
13
12
 
@@ -617,7 +617,7 @@ export default ${name};
617
617
  `;
618
618
  },
619
619
 
620
- page: ({ name, props = [], signals = [] }) => {
620
+ page: ({ name, signals = [] }) => {
621
621
  const signalDecls = signals.map(s => ` const ${s} = signal(null, '${s}');`).join('\n');
622
622
 
623
623
  return `import { signal, effect, onMount } from 'what-framework';
@@ -646,7 +646,7 @@ export default ${name};
646
646
  `;
647
647
  },
648
648
 
649
- form: ({ name, props = [], signals = [] }) => {
649
+ form: ({ name, signals = [] }) => {
650
650
  const fields = signals.length > 0 ? signals : ['email', 'password'];
651
651
  const fieldDecls = fields.map(f => ` ${f}: { initial: '', rules: [rules.required('${f} is required')] },`).join('\n');
652
652
 
@@ -818,7 +818,7 @@ export function registerAgentTools(server, bridge) {
818
818
  try {
819
819
  const ruleIssues = rule.test(code);
820
820
  issues.push(...ruleIssues);
821
- } catch (e) {
821
+ } catch {
822
822
  // Rule crashed — skip silently
823
823
  }
824
824
  }
@@ -930,7 +930,7 @@ export function registerAgentTools(server, bridge) {
930
930
  componentCount: (result.output || '').match(/function\s+[A-Z]\w*\s*\(/g)?.length || 0,
931
931
  },
932
932
  });
933
- } catch (e) {
933
+ } catch {
934
934
  // Fallback: do basic validation without browser
935
935
  const issues = [];
936
936
 
@@ -1230,9 +1230,6 @@ export function registerAgentTools(server, bridge) {
1230
1230
  depCount: (e.depSignalIds || e.deps || []).length,
1231
1231
  });
1232
1232
  }
1233
- const baselineEventCount = bridge.getEvents
1234
- ? bridge.getEvents(Date.now() - 1).length
1235
- : 0;
1236
1233
  const startTs = Date.now();
1237
1234
 
1238
1235
  // ---- Wait for the window ----
@@ -33,7 +33,7 @@ export function registerExtendedTools(server, bridge) {
33
33
  };
34
34
  }
35
35
 
36
- function noSnapshot(tool) {
36
+ function noSnapshot(_tool) {
37
37
  return {
38
38
  content: [{
39
39
  type: 'text',
@@ -1000,6 +1000,7 @@ export function registerExtendedTools(server, bridge) {
1000
1000
  }
1001
1001
 
1002
1002
  // Get writer info from browser
1003
+ /** @type {Record<string, any>} */
1003
1004
  let writers = { recentWrites: [], totalWrites: 0 };
1004
1005
  try {
1005
1006
  writers = await bridge.sendCommand('get-signal-writers', { signalId }, 5000);
@@ -1048,6 +1049,7 @@ export function registerExtendedTools(server, bridge) {
1048
1049
 
1049
1050
  // Trace from recent writes
1050
1051
  for (const write of (writers.recentWrites || []).slice(-5)) {
1052
+ /** @type {Record<string, any>} */
1051
1053
  const entry = {
1052
1054
  timestamp: write.timestamp,
1053
1055
  previousValue: write.previousValue,
@@ -1114,7 +1116,6 @@ export function registerExtendedTools(server, bridge) {
1114
1116
 
1115
1117
  const { componentName, boundingRect, styles, textContent, childElements, totalChildren, layout, viewport, accessibility } = result;
1116
1118
 
1117
- const styleDesc = Object.entries(styles || {}).map(([k, v]) => `${k}: ${v}`).join(', ');
1118
1119
  const childDesc = Object.entries(childElements || {}).map(([k, v]) => `${v} ${k}${v > 1 ? 's' : ''}`).join(', ');
1119
1120
 
1120
1121
  const summary = `${componentName}: ${boundingRect.width}×${boundingRect.height}px at (${boundingRect.x},${boundingRect.y}). ` +
package/src/tools.js CHANGED
@@ -477,6 +477,7 @@ export function registerTools(server, bridge) {
477
477
  const classified = errors.map((err, idx) => {
478
478
  const msg = err.message || err.error || '';
479
479
  const parsed = parseStack(err.stack, knownComponents);
480
+ /** @type {Record<string, any>} */
480
481
  let classification = {
481
482
  id: `err_${idx}`,
482
483
  severity: 'error',
@@ -773,6 +774,7 @@ function error(message) {
773
774
  * what-core, what-devtools, node_modules, vite/, /@id/, internal anonymous).
774
775
  */
775
776
  function parseStack(stack, knownComponents = []) {
777
+ /** @type {{ file: string|null, line: number|null, column: number|null, component: string|null }} */
776
778
  const out = { file: null, line: null, column: null, component: null };
777
779
  if (!stack || typeof stack !== 'string') return out;
778
780