@0x1f320.sh/why-did-you-render-mcp 1.0.0-dev.3 → 1.0.0-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.cjs +74 -10
- package/dist/client/index.js +74 -10
- package/dist/server/index.js +13 -1
- package/package.json +1 -1
package/dist/client/index.cjs
CHANGED
|
@@ -1,14 +1,69 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/client/utils/describe-value.ts
|
|
3
|
+
const MAX_DEPTH = 8;
|
|
4
|
+
function serialize(value, seen, depth) {
|
|
5
|
+
if (value === null) return null;
|
|
6
|
+
if (value === void 0) return null;
|
|
7
|
+
if (typeof value === "function") return {
|
|
8
|
+
type: "function",
|
|
9
|
+
name: value.name || "anonymous"
|
|
10
|
+
};
|
|
11
|
+
if (typeof value === "boolean") return value;
|
|
12
|
+
if (typeof value === "number") {
|
|
13
|
+
if (Number.isNaN(value)) return "NaN";
|
|
14
|
+
if (!Number.isFinite(value)) return value > 0 ? "Infinity" : "-Infinity";
|
|
15
|
+
if (Object.is(value, -0)) return "-0";
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "string") return value;
|
|
19
|
+
if (typeof value === "bigint") return value.toString();
|
|
20
|
+
if (typeof value === "symbol") return value.toString();
|
|
21
|
+
if (seen.has(value)) return "[Circular]";
|
|
22
|
+
if (depth >= MAX_DEPTH) return "[MaxDepth]";
|
|
23
|
+
seen.add(value);
|
|
24
|
+
if (Array.isArray(value)) return value.map((item) => serialize(item, seen, depth + 1));
|
|
25
|
+
const ctorName = Object.getPrototypeOf(value)?.constructor?.name;
|
|
26
|
+
if (ctorName && ctorName !== "Object") {
|
|
27
|
+
if (value instanceof Date) return value.toISOString();
|
|
28
|
+
if (value instanceof RegExp) return String(value);
|
|
29
|
+
if (value instanceof Map) {
|
|
30
|
+
const entries = {};
|
|
31
|
+
for (const [k, v] of value.entries()) entries[String(k)] = serialize(v, seen, depth + 1);
|
|
32
|
+
return {
|
|
33
|
+
type: "Map",
|
|
34
|
+
entries
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (value instanceof Set) return {
|
|
38
|
+
type: "Set",
|
|
39
|
+
values: [...value].map((v) => serialize(v, seen, depth + 1))
|
|
40
|
+
};
|
|
41
|
+
if (value instanceof Promise) return "Promise";
|
|
42
|
+
if (value instanceof Error) return {
|
|
43
|
+
type: "Error",
|
|
44
|
+
name: value.name,
|
|
45
|
+
message: value.message
|
|
46
|
+
};
|
|
47
|
+
if (typeof Node !== "undefined" && value instanceof Node && value instanceof Element) {
|
|
48
|
+
const attrs = {};
|
|
49
|
+
for (const attr of value.attributes) attrs[attr.name] = attr.value;
|
|
50
|
+
return {
|
|
51
|
+
type: "dom",
|
|
52
|
+
tagName: value.tagName.toLowerCase(),
|
|
53
|
+
attrs
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
type: "class",
|
|
58
|
+
name: ctorName
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const result = {};
|
|
62
|
+
for (const key of Object.keys(value)) result[key] = serialize(value[key], seen, depth + 1);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
3
65
|
function describeValue(value) {
|
|
4
|
-
|
|
5
|
-
if (value === void 0) return "undefined";
|
|
6
|
-
if (typeof value === "function") return `function ${value.name || "anonymous"}`;
|
|
7
|
-
if (typeof value !== "object") return String(value);
|
|
8
|
-
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
9
|
-
const name = Object.getPrototypeOf(value)?.constructor?.name;
|
|
10
|
-
if (name && name !== "Object") return name;
|
|
11
|
-
return "Object";
|
|
66
|
+
return serialize(value, /* @__PURE__ */ new WeakSet(), 0);
|
|
12
67
|
}
|
|
13
68
|
//#endregion
|
|
14
69
|
//#region src/client/utils/sanitize-differences.ts
|
|
@@ -50,21 +105,27 @@ function patchDevToolsHook(onCommit) {
|
|
|
50
105
|
function buildOptions(opts) {
|
|
51
106
|
const wsUrl = opts?.wsUrl ?? DEFAULT_WS_URL;
|
|
52
107
|
const projectId = opts?.projectId ?? globalThis.location?.origin ?? "default";
|
|
108
|
+
const MAX_QUEUE_SIZE = 1e3;
|
|
109
|
+
const BASE_DELAY = 1e3;
|
|
110
|
+
const MAX_DELAY = 3e4;
|
|
53
111
|
let ws = null;
|
|
54
112
|
let queue = [];
|
|
55
113
|
let commitId = 0;
|
|
114
|
+
let retryDelay = BASE_DELAY;
|
|
56
115
|
patchDevToolsHook(() => {
|
|
57
116
|
commitId++;
|
|
58
117
|
});
|
|
59
118
|
function connect() {
|
|
60
119
|
ws = new WebSocket(wsUrl);
|
|
61
120
|
ws.addEventListener("open", () => {
|
|
121
|
+
retryDelay = BASE_DELAY;
|
|
62
122
|
for (const msg of queue) ws?.send(JSON.stringify(msg));
|
|
63
123
|
queue = [];
|
|
64
124
|
});
|
|
65
125
|
ws.addEventListener("close", () => {
|
|
66
126
|
ws = null;
|
|
67
|
-
setTimeout(connect,
|
|
127
|
+
setTimeout(connect, retryDelay);
|
|
128
|
+
retryDelay = Math.min(retryDelay * 2, MAX_DELAY);
|
|
68
129
|
});
|
|
69
130
|
ws.addEventListener("error", () => {
|
|
70
131
|
ws?.close();
|
|
@@ -73,7 +134,10 @@ function buildOptions(opts) {
|
|
|
73
134
|
connect();
|
|
74
135
|
function send(msg) {
|
|
75
136
|
if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(msg));
|
|
76
|
-
else
|
|
137
|
+
else {
|
|
138
|
+
if (queue.length >= MAX_QUEUE_SIZE) queue.shift();
|
|
139
|
+
queue.push(msg);
|
|
140
|
+
}
|
|
77
141
|
}
|
|
78
142
|
let pendingBatch = null;
|
|
79
143
|
let flushScheduled = false;
|
package/dist/client/index.js
CHANGED
|
@@ -1,13 +1,68 @@
|
|
|
1
1
|
//#region src/client/utils/describe-value.ts
|
|
2
|
+
const MAX_DEPTH = 8;
|
|
3
|
+
function serialize(value, seen, depth) {
|
|
4
|
+
if (value === null) return null;
|
|
5
|
+
if (value === void 0) return null;
|
|
6
|
+
if (typeof value === "function") return {
|
|
7
|
+
type: "function",
|
|
8
|
+
name: value.name || "anonymous"
|
|
9
|
+
};
|
|
10
|
+
if (typeof value === "boolean") return value;
|
|
11
|
+
if (typeof value === "number") {
|
|
12
|
+
if (Number.isNaN(value)) return "NaN";
|
|
13
|
+
if (!Number.isFinite(value)) return value > 0 ? "Infinity" : "-Infinity";
|
|
14
|
+
if (Object.is(value, -0)) return "-0";
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === "string") return value;
|
|
18
|
+
if (typeof value === "bigint") return value.toString();
|
|
19
|
+
if (typeof value === "symbol") return value.toString();
|
|
20
|
+
if (seen.has(value)) return "[Circular]";
|
|
21
|
+
if (depth >= MAX_DEPTH) return "[MaxDepth]";
|
|
22
|
+
seen.add(value);
|
|
23
|
+
if (Array.isArray(value)) return value.map((item) => serialize(item, seen, depth + 1));
|
|
24
|
+
const ctorName = Object.getPrototypeOf(value)?.constructor?.name;
|
|
25
|
+
if (ctorName && ctorName !== "Object") {
|
|
26
|
+
if (value instanceof Date) return value.toISOString();
|
|
27
|
+
if (value instanceof RegExp) return String(value);
|
|
28
|
+
if (value instanceof Map) {
|
|
29
|
+
const entries = {};
|
|
30
|
+
for (const [k, v] of value.entries()) entries[String(k)] = serialize(v, seen, depth + 1);
|
|
31
|
+
return {
|
|
32
|
+
type: "Map",
|
|
33
|
+
entries
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (value instanceof Set) return {
|
|
37
|
+
type: "Set",
|
|
38
|
+
values: [...value].map((v) => serialize(v, seen, depth + 1))
|
|
39
|
+
};
|
|
40
|
+
if (value instanceof Promise) return "Promise";
|
|
41
|
+
if (value instanceof Error) return {
|
|
42
|
+
type: "Error",
|
|
43
|
+
name: value.name,
|
|
44
|
+
message: value.message
|
|
45
|
+
};
|
|
46
|
+
if (typeof Node !== "undefined" && value instanceof Node && value instanceof Element) {
|
|
47
|
+
const attrs = {};
|
|
48
|
+
for (const attr of value.attributes) attrs[attr.name] = attr.value;
|
|
49
|
+
return {
|
|
50
|
+
type: "dom",
|
|
51
|
+
tagName: value.tagName.toLowerCase(),
|
|
52
|
+
attrs
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
type: "class",
|
|
57
|
+
name: ctorName
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const result = {};
|
|
61
|
+
for (const key of Object.keys(value)) result[key] = serialize(value[key], seen, depth + 1);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
2
64
|
function describeValue(value) {
|
|
3
|
-
|
|
4
|
-
if (value === void 0) return "undefined";
|
|
5
|
-
if (typeof value === "function") return `function ${value.name || "anonymous"}`;
|
|
6
|
-
if (typeof value !== "object") return String(value);
|
|
7
|
-
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
8
|
-
const name = Object.getPrototypeOf(value)?.constructor?.name;
|
|
9
|
-
if (name && name !== "Object") return name;
|
|
10
|
-
return "Object";
|
|
65
|
+
return serialize(value, /* @__PURE__ */ new WeakSet(), 0);
|
|
11
66
|
}
|
|
12
67
|
//#endregion
|
|
13
68
|
//#region src/client/utils/sanitize-differences.ts
|
|
@@ -49,21 +104,27 @@ function patchDevToolsHook(onCommit) {
|
|
|
49
104
|
function buildOptions(opts) {
|
|
50
105
|
const wsUrl = opts?.wsUrl ?? DEFAULT_WS_URL;
|
|
51
106
|
const projectId = opts?.projectId ?? globalThis.location?.origin ?? "default";
|
|
107
|
+
const MAX_QUEUE_SIZE = 1e3;
|
|
108
|
+
const BASE_DELAY = 1e3;
|
|
109
|
+
const MAX_DELAY = 3e4;
|
|
52
110
|
let ws = null;
|
|
53
111
|
let queue = [];
|
|
54
112
|
let commitId = 0;
|
|
113
|
+
let retryDelay = BASE_DELAY;
|
|
55
114
|
patchDevToolsHook(() => {
|
|
56
115
|
commitId++;
|
|
57
116
|
});
|
|
58
117
|
function connect() {
|
|
59
118
|
ws = new WebSocket(wsUrl);
|
|
60
119
|
ws.addEventListener("open", () => {
|
|
120
|
+
retryDelay = BASE_DELAY;
|
|
61
121
|
for (const msg of queue) ws?.send(JSON.stringify(msg));
|
|
62
122
|
queue = [];
|
|
63
123
|
});
|
|
64
124
|
ws.addEventListener("close", () => {
|
|
65
125
|
ws = null;
|
|
66
|
-
setTimeout(connect,
|
|
126
|
+
setTimeout(connect, retryDelay);
|
|
127
|
+
retryDelay = Math.min(retryDelay * 2, MAX_DELAY);
|
|
67
128
|
});
|
|
68
129
|
ws.addEventListener("error", () => {
|
|
69
130
|
ws?.close();
|
|
@@ -72,7 +133,10 @@ function buildOptions(opts) {
|
|
|
72
133
|
connect();
|
|
73
134
|
function send(msg) {
|
|
74
135
|
if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(msg));
|
|
75
|
-
else
|
|
136
|
+
else {
|
|
137
|
+
if (queue.length >= MAX_QUEUE_SIZE) queue.shift();
|
|
138
|
+
queue.push(msg);
|
|
139
|
+
}
|
|
76
140
|
}
|
|
77
141
|
let pendingBatch = null;
|
|
78
142
|
let flushScheduled = false;
|
package/dist/server/index.js
CHANGED
|
@@ -370,10 +370,22 @@ const server = new McpServer({
|
|
|
370
370
|
});
|
|
371
371
|
registerTools(server);
|
|
372
372
|
async function main() {
|
|
373
|
-
createWsServer(Number(process.env.WDYR_WS_PORT) || DEFAULT_WS_PORT);
|
|
373
|
+
const wss = createWsServer(Number(process.env.WDYR_WS_PORT) || DEFAULT_WS_PORT);
|
|
374
374
|
const transport = new StdioServerTransport();
|
|
375
375
|
await server.connect(transport);
|
|
376
376
|
console.error("[wdyr-mcp] MCP server running on stdio");
|
|
377
|
+
let shuttingDown = false;
|
|
378
|
+
async function shutdown() {
|
|
379
|
+
if (shuttingDown) return;
|
|
380
|
+
shuttingDown = true;
|
|
381
|
+
console.error("[wdyr-mcp] Shutting down…");
|
|
382
|
+
wss?.close();
|
|
383
|
+
await server.close();
|
|
384
|
+
process.exit(0);
|
|
385
|
+
}
|
|
386
|
+
process.stdin.on("end", shutdown);
|
|
387
|
+
process.on("SIGTERM", shutdown);
|
|
388
|
+
process.on("SIGINT", shutdown);
|
|
377
389
|
}
|
|
378
390
|
main().catch((error) => {
|
|
379
391
|
console.error("[wdyr-mcp] Fatal error:", error);
|
package/package.json
CHANGED