@arvoretech/runtime-lens-mcp 1.1.0 → 1.2.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.
@@ -1,22 +1,25 @@
1
1
  "use strict";
2
2
 
3
3
  // agent/index.ts
4
- var import_node_http = require("node:http");
5
4
  var import_node_crypto = require("node:crypto");
5
+ var import_node_http = require("node:http");
6
6
  var PORT = parseInt(process.env.RUNTIME_LENS_PORT || "9500", 10);
7
- var client = null;
7
+ var clients = /* @__PURE__ */ new Set();
8
8
  var buffer = [];
9
- var MAX_BUFFER = 500;
9
+ var MAX_BUFFER = 1e3;
10
10
  function serialize(value, depth = 0) {
11
11
  if (depth > 3) return "[...]";
12
12
  if (value === null) return "null";
13
13
  if (value === void 0) return "undefined";
14
- if (typeof value === "string") return value.length > 100 ? `"${value.slice(0, 100)}..."` : `"${value}"`;
15
- if (typeof value === "number" || typeof value === "boolean") return String(value);
14
+ if (typeof value === "string")
15
+ return value.length > 100 ? `"${value.slice(0, 100)}..."` : `"${value}"`;
16
+ if (typeof value === "number" || typeof value === "boolean")
17
+ return String(value);
16
18
  if (typeof value === "function") return `fn ${value.name || "anonymous"}()`;
17
19
  if (typeof value === "symbol") return value.toString();
18
20
  if (typeof value === "bigint") return `${value}n`;
19
- if (value instanceof Error) return `${value.name}: ${value.message}`;
21
+ if (value instanceof Error)
22
+ return `${value.name}: ${value.message}${value.stack ? "\n" + value.stack : ""}`;
20
23
  if (value instanceof Date) return value.toISOString();
21
24
  if (value instanceof RegExp) return value.toString();
22
25
  if (value instanceof Map) return `Map(${value.size})`;
@@ -31,30 +34,32 @@ function serialize(value, depth = 0) {
31
34
  if (typeof value === "object") {
32
35
  const keys = Object.keys(value);
33
36
  if (keys.length === 0) return "{}";
34
- const entries = keys.slice(0, 5).map((k) => `${k}: ${serialize(value[k], depth + 1)}`);
37
+ const entries = keys.slice(0, 5).map(
38
+ (k) => `${k}: ${serialize(value[k], depth + 1)}`
39
+ );
35
40
  const suffix = keys.length > 5 ? `, ...+${keys.length - 5}` : "";
36
41
  return `{${entries.join(", ")}${suffix}}`;
37
42
  }
38
43
  return typeof value === "object" ? Object.prototype.toString.call(value) : String(value);
39
44
  }
40
- function wsSend(msg) {
45
+ function broadcast(msg) {
41
46
  const payload = JSON.stringify(msg);
42
- if (client && !client.destroyed) {
43
- const buf = Buffer.from(payload, "utf-8");
44
- const frame = buildWsFrame(buf);
45
- client.write(frame);
46
- } else {
47
- buffer.push(msg);
48
- if (buffer.length > MAX_BUFFER) buffer.shift();
47
+ const buf = Buffer.from(payload, "utf-8");
48
+ const frame = buildWsFrame(buf);
49
+ for (const client of clients) {
50
+ if (!client.destroyed) {
51
+ client.write(frame);
52
+ } else {
53
+ clients.delete(client);
54
+ }
49
55
  }
56
+ buffer.push(msg);
57
+ if (buffer.length > MAX_BUFFER) buffer.shift();
50
58
  }
51
- function flushBuffer() {
52
- while (buffer.length > 0 && client && !client.destroyed) {
53
- const msg = buffer.shift();
54
- if (msg) {
55
- const buf = Buffer.from(JSON.stringify(msg), "utf-8");
56
- client.write(buildWsFrame(buf));
57
- }
59
+ function flushBuffer(socket) {
60
+ for (const msg of buffer) {
61
+ const buf = Buffer.from(JSON.stringify(msg), "utf-8");
62
+ socket.write(buildWsFrame(buf));
58
63
  }
59
64
  }
60
65
  function buildWsFrame(data) {
@@ -107,10 +112,15 @@ function extractCallSite() {
107
112
  const lines = stack.split("\n");
108
113
  for (let i = 2; i < lines.length; i++) {
109
114
  const line = lines[i];
110
- if (line.includes("node:") || line.includes("dist/agent/index.js")) continue;
115
+ if (line.includes("node:") || line.includes("dist/agent/index.js"))
116
+ continue;
111
117
  const match = /\((.+):(\d+):(\d+)\)/.exec(line) || /at (.+):(\d+):(\d+)/.exec(line);
112
118
  if (match) {
113
- return { file: match[1], line: parseInt(match[2], 10), column: parseInt(match[3], 10) };
119
+ return {
120
+ file: match[1],
121
+ line: parseInt(match[2], 10),
122
+ column: parseInt(match[3], 10)
123
+ };
114
124
  }
115
125
  }
116
126
  return { file: "unknown", line: 0, column: 0 };
@@ -127,7 +137,7 @@ function patchConsole() {
127
137
  for (const method of methods) {
128
138
  console[method] = (...args) => {
129
139
  const site = extractCallSite();
130
- wsSend({
140
+ broadcast({
131
141
  type: method,
132
142
  file: site.file,
133
143
  line: site.line,
@@ -141,7 +151,15 @@ function patchConsole() {
141
151
  }
142
152
  var server = (0, import_node_http.createServer)((_req, res) => {
143
153
  res.writeHead(200, { "Content-Type": "application/json" });
144
- res.end(JSON.stringify({ status: "ok", pid: process.pid, uptime: process.uptime() }));
154
+ res.end(
155
+ JSON.stringify({
156
+ status: "ok",
157
+ pid: process.pid,
158
+ uptime: process.uptime(),
159
+ clients: clients.size,
160
+ buffered: buffer.length
161
+ })
162
+ );
145
163
  });
146
164
  server.on("upgrade", (req, socket) => {
147
165
  const key = req.headers["sec-websocket-key"];
@@ -158,8 +176,11 @@ Sec-WebSocket-Accept: ${acceptKey}\r
158
176
  \r
159
177
  `
160
178
  );
161
- client = socket;
162
- flushBuffer();
179
+ clients.add(socket);
180
+ originalConsole.log(
181
+ `[runtime-lens] client connected (${clients.size} total)`
182
+ );
183
+ flushBuffer(socket);
163
184
  socket.on("data", (data) => {
164
185
  const text = parseWsFrame(data);
165
186
  if (!text) return;
@@ -169,7 +190,7 @@ Sec-WebSocket-Accept: ${acceptKey}\r
169
190
  try {
170
191
  const fn = new Function(`return (${msg.expression})`);
171
192
  const result = fn();
172
- wsSend({
193
+ broadcast({
173
194
  type: "result",
174
195
  file: msg.file || "eval",
175
196
  line: msg.line || 0,
@@ -179,7 +200,7 @@ Sec-WebSocket-Accept: ${acceptKey}\r
179
200
  expression: msg.expression
180
201
  });
181
202
  } catch (err) {
182
- wsSend({
203
+ broadcast({
183
204
  type: "error",
184
205
  file: msg.file || "eval",
185
206
  line: msg.line || 0,
@@ -189,31 +210,66 @@ Sec-WebSocket-Accept: ${acceptKey}\r
189
210
  expression: msg.expression
190
211
  });
191
212
  }
213
+ } else if (msg.type === "get_buffer") {
214
+ const payload = JSON.stringify({ type: "buffer", logs: buffer });
215
+ const buf = Buffer.from(payload, "utf-8");
216
+ socket.write(buildWsFrame(buf));
192
217
  }
193
218
  } catch {
194
219
  }
195
220
  });
196
221
  socket.on("close", () => {
197
- client = null;
222
+ clients.delete(socket);
223
+ originalConsole.log(
224
+ `[runtime-lens] client disconnected (${clients.size} total)`
225
+ );
198
226
  });
199
227
  socket.on("error", () => {
200
- client = null;
228
+ clients.delete(socket);
201
229
  });
202
230
  });
203
231
  server.on("error", (err) => {
204
232
  if (err.code === "EADDRINUSE") {
205
- originalConsole.log(`[runtime-lens] port ${PORT} in use, skipping agent server`);
233
+ originalConsole.log(
234
+ `[runtime-lens] port ${PORT} in use, skipping agent server`
235
+ );
206
236
  }
207
237
  });
208
238
  server.listen(PORT, () => {
209
- originalConsole.log(`[runtime-lens] agent listening on ws://localhost:${PORT}`);
239
+ originalConsole.log(
240
+ `[runtime-lens] agent listening on ws://localhost:${PORT}`
241
+ );
242
+ });
243
+ var keepAliveTimer = null;
244
+ var KEEP_ALIVE_MS = parseInt(
245
+ process.env.RUNTIME_LENS_KEEP_ALIVE || "30000",
246
+ 10
247
+ );
248
+ function scheduleShutdown() {
249
+ if (keepAliveTimer) return;
250
+ keepAliveTimer = setTimeout(() => {
251
+ if (clients.size === 0) {
252
+ originalConsole.log(
253
+ `[runtime-lens] no clients connected, shutting down agent`
254
+ );
255
+ server.close();
256
+ process.exit(0);
257
+ } else {
258
+ keepAliveTimer = null;
259
+ scheduleShutdown();
260
+ }
261
+ }, KEEP_ALIVE_MS);
262
+ keepAliveTimer.unref();
263
+ }
264
+ process.on("beforeExit", () => {
265
+ server.ref();
266
+ scheduleShutdown();
210
267
  });
211
- server.unref();
212
268
  patchConsole();
213
269
  globalThis.__runtimeLens = {
214
270
  log: (...args) => {
215
271
  const site = extractCallSite();
216
- wsSend({
272
+ broadcast({
217
273
  type: "result",
218
274
  file: site.file,
219
275
  line: site.line,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../agent/index.ts"],
4
- "sourcesContent": ["import { createServer } from \"node:http\";\nimport { createHash } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { Socket } from \"node:net\";\n\nconst PORT = parseInt(process.env.RUNTIME_LENS_PORT || \"9500\", 10);\n\ninterface LogMessage {\n type: \"log\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"result\";\n file: string;\n line: number;\n column: number;\n values: string[];\n timestamp: number;\n expression?: string;\n}\n\nlet client: Socket | null = null;\nconst buffer: LogMessage[] = [];\nconst MAX_BUFFER = 500;\n\nfunction serialize(value: unknown, depth = 0): string {\n if (depth > 3) return \"[...]\";\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"string\") return value.length > 100 ? `\"${value.slice(0, 100)}...\"` : `\"${value}\"`;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n if (typeof value === \"function\") return `fn ${value.name || \"anonymous\"}()`;\n if (typeof value === \"symbol\") return value.toString();\n if (typeof value === \"bigint\") return `${value}n`;\n if (value instanceof Error) return `${value.name}: ${value.message}`;\n if (value instanceof Date) return value.toISOString();\n if (value instanceof RegExp) return value.toString();\n if (value instanceof Map) return `Map(${value.size})`;\n if (value instanceof Set) return `Set(${value.size})`;\n if (value instanceof Promise) return \"Promise\";\n if (Array.isArray(value)) {\n if (value.length === 0) return \"[]\";\n const items = value.slice(0, 5).map(v => serialize(v, depth + 1));\n const suffix = value.length > 5 ? `, ...+${value.length - 5}` : \"\";\n return `[${items.join(\", \")}${suffix}]`;\n }\n if (typeof value === \"object\") {\n const keys = Object.keys(value);\n if (keys.length === 0) return \"{}\";\n const entries = keys.slice(0, 5).map(k => `${k}: ${serialize((value as Record<string, unknown>)[k], depth + 1)}`);\n const suffix = keys.length > 5 ? `, ...+${keys.length - 5}` : \"\";\n return `{${entries.join(\", \")}${suffix}}`;\n }\n return typeof value === \"object\" ? Object.prototype.toString.call(value) : String(value);\n}\n\nfunction wsSend(msg: LogMessage): void {\n const payload = JSON.stringify(msg);\n if (client && !client.destroyed) {\n const buf = Buffer.from(payload, \"utf-8\");\n const frame = buildWsFrame(buf);\n client.write(frame);\n } else {\n buffer.push(msg);\n if (buffer.length > MAX_BUFFER) buffer.shift();\n }\n}\n\nfunction flushBuffer(): void {\n while (buffer.length > 0 && client && !client.destroyed) {\n const msg = buffer.shift();\n if (msg) {\n const buf = Buffer.from(JSON.stringify(msg), \"utf-8\");\n client.write(buildWsFrame(buf));\n }\n }\n}\n\nfunction buildWsFrame(data: Buffer): Buffer {\n const len = data.length;\n let header: Buffer;\n if (len < 126) {\n header = Buffer.alloc(2);\n header[0] = 0x81;\n header[1] = len;\n } else if (len < 65536) {\n header = Buffer.alloc(4);\n header[0] = 0x81;\n header[1] = 126;\n header.writeUInt16BE(len, 2);\n } else {\n header = Buffer.alloc(10);\n header[0] = 0x81;\n header[1] = 127;\n header.writeBigUInt64BE(BigInt(len), 2);\n }\n return Buffer.concat([header, data]);\n}\n\nfunction parseWsFrame(data: Buffer): string | null {\n if (data.length < 2) return null;\n const masked = (data[1] & 0x80) !== 0;\n let payloadLen = data[1] & 0x7f;\n let offset = 2;\n\n if (payloadLen === 126) {\n payloadLen = data.readUInt16BE(2);\n offset = 4;\n } else if (payloadLen === 127) {\n payloadLen = Number(data.readBigUInt64BE(2));\n offset = 10;\n }\n\n let maskKey: Buffer | null = null;\n if (masked) {\n maskKey = data.subarray(offset, offset + 4);\n offset += 4;\n }\n\n const payload = data.subarray(offset, offset + payloadLen);\n if (maskKey) {\n for (let i = 0; i < payload.length; i++) {\n payload[i] ^= maskKey[i % 4];\n }\n }\n return payload.toString(\"utf-8\");\n}\n\nfunction extractCallSite(): { file: string; line: number; column: number } {\n const stack = new Error().stack || \"\";\n const lines = stack.split(\"\\n\");\n for (let i = 2; i < lines.length; i++) {\n const line = lines[i];\n if (line.includes(\"node:\") || line.includes(\"dist/agent/index.js\")) continue;\n const match = /\\((.+):(\\d+):(\\d+)\\)/.exec(line) || /at (.+):(\\d+):(\\d+)/.exec(line);\n if (match) {\n return { file: match[1], line: parseInt(match[2], 10), column: parseInt(match[3], 10) };\n }\n }\n return { file: \"unknown\", line: 0, column: 0 };\n}\n\ntype ConsoleMethod = \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\";\nconst originalConsole: Record<ConsoleMethod, (...args: unknown[]) => void> = {\n log: console.log.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n};\n\nfunction patchConsole(): void {\n const methods: ConsoleMethod[] = [\"log\", \"info\", \"warn\", \"error\", \"debug\"];\n for (const method of methods) {\n console[method] = (...args: unknown[]) => {\n const site = extractCallSite();\n wsSend({\n type: method,\n file: site.file,\n line: site.line,\n column: site.column,\n values: args.map(a => serialize(a)),\n timestamp: Date.now(),\n });\n originalConsole[method](...args);\n };\n }\n}\n\nconst server = createServer((_req, res) => {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", pid: process.pid, uptime: process.uptime() }));\n});\n\nserver.on(\"upgrade\", (req: IncomingMessage, socket: Socket) => {\n const key = req.headers[\"sec-websocket-key\"];\n if (!key) {\n socket.destroy();\n return;\n }\n\n const acceptKey = createHash(\"sha1\")\n .update(key + \"258EAFA5-E914-47DA-95CA-5AB5DC11650B\")\n .digest(\"base64\");\n\n socket.write(\n \"HTTP/1.1 101 Switching Protocols\\r\\n\" +\n \"Upgrade: websocket\\r\\n\" +\n \"Connection: Upgrade\\r\\n\" +\n `Sec-WebSocket-Accept: ${acceptKey}\\r\\n` +\n \"\\r\\n\"\n );\n\n client = socket;\n flushBuffer();\n\n socket.on(\"data\", (data: Buffer) => {\n const text = parseWsFrame(data);\n if (!text) return;\n try {\n const msg = JSON.parse(text);\n if (msg.type === \"eval\") {\n try {\n const fn = new Function(`return (${msg.expression})`);\n const result = fn();\n wsSend({\n type: \"result\",\n file: msg.file || \"eval\",\n line: msg.line || 0,\n column: msg.column || 0,\n values: [serialize(result)],\n timestamp: Date.now(),\n expression: msg.expression,\n });\n } catch (err: unknown) {\n wsSend({\n type: \"error\",\n file: msg.file || \"eval\",\n line: msg.line || 0,\n column: msg.column || 0,\n values: [err instanceof Error ? err.message : String(err)],\n timestamp: Date.now(),\n expression: msg.expression,\n });\n }\n }\n } catch {\n // invalid JSON\n }\n });\n\n socket.on(\"close\", () => {\n client = null;\n });\n\n socket.on(\"error\", () => {\n client = null;\n });\n});\n\nserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n originalConsole.log(`[runtime-lens] port ${PORT} in use, skipping agent server`);\n }\n});\n\nserver.listen(PORT, () => {\n originalConsole.log(`[runtime-lens] agent listening on ws://localhost:${PORT}`);\n});\n\nserver.unref();\n\npatchConsole();\n\n(globalThis as Record<string, unknown>).__runtimeLens = {\n log: (...args: unknown[]) => {\n const site = extractCallSite();\n wsSend({\n type: \"result\",\n file: site.file,\n line: site.line,\n column: site.column,\n values: args.map(a => serialize(a)),\n timestamp: Date.now(),\n });\n },\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createHash } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport { createServer } from \"node:http\";\nimport type { Socket } from \"node:net\";\n\nconst PORT = parseInt(process.env.RUNTIME_LENS_PORT || \"9500\", 10);\n\ninterface LogMessage {\n\ttype: \"log\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"result\";\n\tfile: string;\n\tline: number;\n\tcolumn: number;\n\tvalues: string[];\n\ttimestamp: number;\n\texpression?: string;\n\tcount?: number;\n}\n\nconst clients: Set<Socket> = new Set();\nconst buffer: LogMessage[] = [];\nconst MAX_BUFFER = 1000;\n\nfunction serialize(value: unknown, depth = 0): string {\n\tif (depth > 3) return \"[...]\";\n\tif (value === null) return \"null\";\n\tif (value === undefined) return \"undefined\";\n\tif (typeof value === \"string\")\n\t\treturn value.length > 100 ? `\"${value.slice(0, 100)}...\"` : `\"${value}\"`;\n\tif (typeof value === \"number\" || typeof value === \"boolean\")\n\t\treturn String(value);\n\tif (typeof value === \"function\") return `fn ${value.name || \"anonymous\"}()`;\n\tif (typeof value === \"symbol\") return value.toString();\n\tif (typeof value === \"bigint\") return `${value}n`;\n\tif (value instanceof Error)\n\t\treturn `${value.name}: ${value.message}${value.stack ? \"\\n\" + value.stack : \"\"}`;\n\tif (value instanceof Date) return value.toISOString();\n\tif (value instanceof RegExp) return value.toString();\n\tif (value instanceof Map) return `Map(${value.size})`;\n\tif (value instanceof Set) return `Set(${value.size})`;\n\tif (value instanceof Promise) return \"Promise\";\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return \"[]\";\n\t\tconst items = value.slice(0, 5).map((v) => serialize(v, depth + 1));\n\t\tconst suffix = value.length > 5 ? `, ...+${value.length - 5}` : \"\";\n\t\treturn `[${items.join(\", \")}${suffix}]`;\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst keys = Object.keys(value);\n\t\tif (keys.length === 0) return \"{}\";\n\t\tconst entries = keys\n\t\t\t.slice(0, 5)\n\t\t\t.map(\n\t\t\t\t(k) =>\n\t\t\t\t\t`${k}: ${serialize((value as Record<string, unknown>)[k], depth + 1)}`,\n\t\t\t);\n\t\tconst suffix = keys.length > 5 ? `, ...+${keys.length - 5}` : \"\";\n\t\treturn `{${entries.join(\", \")}${suffix}}`;\n\t}\n\treturn typeof value === \"object\"\n\t\t? Object.prototype.toString.call(value)\n\t\t: String(value);\n}\n\nfunction broadcast(msg: LogMessage): void {\n\tconst payload = JSON.stringify(msg);\n\tconst buf = Buffer.from(payload, \"utf-8\");\n\tconst frame = buildWsFrame(buf);\n\n\tfor (const client of clients) {\n\t\tif (!client.destroyed) {\n\t\t\tclient.write(frame);\n\t\t} else {\n\t\t\tclients.delete(client);\n\t\t}\n\t}\n\n\t// Always buffer for late-connecting clients (MCP server, extension)\n\tbuffer.push(msg);\n\tif (buffer.length > MAX_BUFFER) buffer.shift();\n}\n\nfunction flushBuffer(socket: Socket): void {\n\tfor (const msg of buffer) {\n\t\tconst buf = Buffer.from(JSON.stringify(msg), \"utf-8\");\n\t\tsocket.write(buildWsFrame(buf));\n\t}\n}\n\nfunction buildWsFrame(data: Buffer): Buffer {\n\tconst len = data.length;\n\tlet header: Buffer;\n\tif (len < 126) {\n\t\theader = Buffer.alloc(2);\n\t\theader[0] = 0x81;\n\t\theader[1] = len;\n\t} else if (len < 65536) {\n\t\theader = Buffer.alloc(4);\n\t\theader[0] = 0x81;\n\t\theader[1] = 126;\n\t\theader.writeUInt16BE(len, 2);\n\t} else {\n\t\theader = Buffer.alloc(10);\n\t\theader[0] = 0x81;\n\t\theader[1] = 127;\n\t\theader.writeBigUInt64BE(BigInt(len), 2);\n\t}\n\treturn Buffer.concat([header, data]);\n}\n\nfunction parseWsFrame(data: Buffer): string | null {\n\tif (data.length < 2) return null;\n\tconst masked = (data[1] & 0x80) !== 0;\n\tlet payloadLen = data[1] & 0x7f;\n\tlet offset = 2;\n\n\tif (payloadLen === 126) {\n\t\tpayloadLen = data.readUInt16BE(2);\n\t\toffset = 4;\n\t} else if (payloadLen === 127) {\n\t\tpayloadLen = Number(data.readBigUInt64BE(2));\n\t\toffset = 10;\n\t}\n\n\tlet maskKey: Buffer | null = null;\n\tif (masked) {\n\t\tmaskKey = data.subarray(offset, offset + 4);\n\t\toffset += 4;\n\t}\n\n\tconst payload = data.subarray(offset, offset + payloadLen);\n\tif (maskKey) {\n\t\tfor (let i = 0; i < payload.length; i++) {\n\t\t\tpayload[i] ^= maskKey[i % 4];\n\t\t}\n\t}\n\treturn payload.toString(\"utf-8\");\n}\n\nfunction extractCallSite(): { file: string; line: number; column: number } {\n\tconst stack = new Error().stack || \"\";\n\tconst lines = stack.split(\"\\n\");\n\tfor (let i = 2; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line.includes(\"node:\") || line.includes(\"dist/agent/index.js\"))\n\t\t\tcontinue;\n\t\tconst match =\n\t\t\t/\\((.+):(\\d+):(\\d+)\\)/.exec(line) || /at (.+):(\\d+):(\\d+)/.exec(line);\n\t\tif (match) {\n\t\t\treturn {\n\t\t\t\tfile: match[1],\n\t\t\t\tline: parseInt(match[2], 10),\n\t\t\t\tcolumn: parseInt(match[3], 10),\n\t\t\t};\n\t\t}\n\t}\n\treturn { file: \"unknown\", line: 0, column: 0 };\n}\n\ntype ConsoleMethod = \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\";\nconst originalConsole: Record<ConsoleMethod, (...args: unknown[]) => void> = {\n\tlog: console.log.bind(console),\n\tinfo: console.info.bind(console),\n\twarn: console.warn.bind(console),\n\terror: console.error.bind(console),\n\tdebug: console.debug.bind(console),\n};\n\nfunction patchConsole(): void {\n\tconst methods: ConsoleMethod[] = [\"log\", \"info\", \"warn\", \"error\", \"debug\"];\n\tfor (const method of methods) {\n\t\tconsole[method] = (...args: unknown[]) => {\n\t\t\tconst site = extractCallSite();\n\t\t\tbroadcast({\n\t\t\t\ttype: method,\n\t\t\t\tfile: site.file,\n\t\t\t\tline: site.line,\n\t\t\t\tcolumn: site.column,\n\t\t\t\tvalues: args.map((a) => serialize(a)),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t\toriginalConsole[method](...args);\n\t\t};\n\t}\n}\n\nconst server = createServer((_req, res) => {\n\tres.writeHead(200, { \"Content-Type\": \"application/json\" });\n\tres.end(\n\t\tJSON.stringify({\n\t\t\tstatus: \"ok\",\n\t\t\tpid: process.pid,\n\t\t\tuptime: process.uptime(),\n\t\t\tclients: clients.size,\n\t\t\tbuffered: buffer.length,\n\t\t}),\n\t);\n});\n\nserver.on(\"upgrade\", (req: IncomingMessage, socket: Socket) => {\n\tconst key = req.headers[\"sec-websocket-key\"];\n\tif (!key) {\n\t\tsocket.destroy();\n\t\treturn;\n\t}\n\n\tconst acceptKey = createHash(\"sha1\")\n\t\t.update(key + \"258EAFA5-E914-47DA-95CA-5AB5DC11650B\")\n\t\t.digest(\"base64\");\n\n\tsocket.write(\n\t\t\"HTTP/1.1 101 Switching Protocols\\r\\n\" +\n\t\t\t\"Upgrade: websocket\\r\\n\" +\n\t\t\t\"Connection: Upgrade\\r\\n\" +\n\t\t\t`Sec-WebSocket-Accept: ${acceptKey}\\r\\n` +\n\t\t\t\"\\r\\n\",\n\t);\n\n\tclients.add(socket);\n\toriginalConsole.log(\n\t\t`[runtime-lens] client connected (${clients.size} total)`,\n\t);\n\n\tflushBuffer(socket);\n\n\tsocket.on(\"data\", (data: Buffer) => {\n\t\tconst text = parseWsFrame(data);\n\t\tif (!text) return;\n\t\ttry {\n\t\t\tconst msg = JSON.parse(text);\n\t\t\tif (msg.type === \"eval\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst fn = new Function(`return (${msg.expression})`);\n\t\t\t\t\tconst result = fn();\n\t\t\t\t\tbroadcast({\n\t\t\t\t\t\ttype: \"result\",\n\t\t\t\t\t\tfile: msg.file || \"eval\",\n\t\t\t\t\t\tline: msg.line || 0,\n\t\t\t\t\t\tcolumn: msg.column || 0,\n\t\t\t\t\t\tvalues: [serialize(result)],\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\texpression: msg.expression,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tbroadcast({\n\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\tfile: msg.file || \"eval\",\n\t\t\t\t\t\tline: msg.line || 0,\n\t\t\t\t\t\tcolumn: msg.column || 0,\n\t\t\t\t\t\tvalues: [err instanceof Error ? err.message : String(err)],\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\texpression: msg.expression,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (msg.type === \"get_buffer\") {\n\t\t\t\tconst payload = JSON.stringify({ type: \"buffer\", logs: buffer });\n\t\t\t\tconst buf = Buffer.from(payload, \"utf-8\");\n\t\t\t\tsocket.write(buildWsFrame(buf));\n\t\t\t}\n\t\t} catch {\n\t\t\t// invalid JSON\n\t\t}\n\t});\n\n\tsocket.on(\"close\", () => {\n\t\tclients.delete(socket);\n\t\toriginalConsole.log(\n\t\t\t`[runtime-lens] client disconnected (${clients.size} total)`,\n\t\t);\n\t});\n\n\tsocket.on(\"error\", () => {\n\t\tclients.delete(socket);\n\t});\n});\n\nserver.on(\"error\", (err: NodeJS.ErrnoException) => {\n\tif (err.code === \"EADDRINUSE\") {\n\t\toriginalConsole.log(\n\t\t\t`[runtime-lens] port ${PORT} in use, skipping agent server`,\n\t\t);\n\t}\n});\n\nserver.listen(PORT, () => {\n\toriginalConsole.log(\n\t\t`[runtime-lens] agent listening on ws://localhost:${PORT}`,\n\t);\n});\n\nlet keepAliveTimer: ReturnType<typeof setTimeout> | null = null;\nconst KEEP_ALIVE_MS = parseInt(\n\tprocess.env.RUNTIME_LENS_KEEP_ALIVE || \"30000\",\n\t10,\n);\n\nfunction scheduleShutdown(): void {\n\tif (keepAliveTimer) return;\n\tkeepAliveTimer = setTimeout(() => {\n\t\tif (clients.size === 0) {\n\t\t\toriginalConsole.log(\n\t\t\t\t`[runtime-lens] no clients connected, shutting down agent`,\n\t\t\t);\n\t\t\tserver.close();\n\t\t\tprocess.exit(0);\n\t\t} else {\n\t\t\tkeepAliveTimer = null;\n\t\t\tscheduleShutdown();\n\t\t}\n\t}, KEEP_ALIVE_MS);\n\tkeepAliveTimer.unref();\n}\n\nprocess.on(\"beforeExit\", () => {\n\tserver.ref();\n\tscheduleShutdown();\n});\n\npatchConsole();\n\n(globalThis as Record<string, unknown>).__runtimeLens = {\n\tlog: (...args: unknown[]) => {\n\t\tconst site = extractCallSite();\n\t\tbroadcast({\n\t\t\ttype: \"result\",\n\t\t\tfile: site.file,\n\t\t\tline: site.line,\n\t\t\tcolumn: site.column,\n\t\t\tvalues: args.map((a) => serialize(a)),\n\t\t\ttimestamp: Date.now(),\n\t\t});\n\t},\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,20 @@
1
+ import type { LogCollector } from "./log-collector.js";
2
+ export declare class AgentBridge {
3
+ private socket;
4
+ private reconnectTimer;
5
+ private connected;
6
+ private readonly port;
7
+ private readonly collector;
8
+ private dataBuffer;
9
+ private stopped;
10
+ constructor(collector: LogCollector, port?: number);
11
+ connect(): void;
12
+ disconnect(): void;
13
+ isConnected(): boolean;
14
+ private processFrames;
15
+ private handleMessage;
16
+ private ingestLog;
17
+ private sendFrame;
18
+ private scheduleReconnect;
19
+ }
20
+ //# sourceMappingURL=agent-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-bridge.d.ts","sourceRoot":"","sources":["../src/agent-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAuBvD,qBAAa,WAAW;IACvB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,OAAO,CAAS;gBAEZ,SAAS,EAAE,YAAY,EAAE,IAAI,SAAO;IAKhD,OAAO,IAAI,IAAI;IAyDf,UAAU,IAAI,IAAI;IAalB,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,aAAa;IA2CrB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,iBAAiB;CAOzB"}
@@ -0,0 +1,185 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { request } from "node:http";
3
+ const LEVEL_MAP = {
4
+ log: "info",
5
+ info: "info",
6
+ warn: "warn",
7
+ error: "error",
8
+ debug: "debug",
9
+ result: "info",
10
+ };
11
+ export class AgentBridge {
12
+ socket = null;
13
+ reconnectTimer = null;
14
+ connected = false;
15
+ port;
16
+ collector;
17
+ dataBuffer = Buffer.alloc(0);
18
+ stopped = false;
19
+ constructor(collector, port = 9500) {
20
+ this.collector = collector;
21
+ this.port = parseInt(process.env.RUNTIME_LENS_PORT || String(port), 10);
22
+ }
23
+ connect() {
24
+ if (this.socket || this.stopped)
25
+ return;
26
+ const key = randomBytes(16).toString("base64");
27
+ const req = request({
28
+ hostname: "localhost",
29
+ port: this.port,
30
+ path: "/",
31
+ method: "GET",
32
+ timeout: 3000,
33
+ headers: {
34
+ Upgrade: "websocket",
35
+ Connection: "Upgrade",
36
+ "Sec-WebSocket-Key": key,
37
+ "Sec-WebSocket-Version": "13",
38
+ },
39
+ });
40
+ req.on("upgrade", (_res, socket) => {
41
+ this.socket = socket;
42
+ this.connected = true;
43
+ this.dataBuffer = Buffer.alloc(0);
44
+ console.error("[runtime-lens-mcp] Connected to agent on port", this.port);
45
+ // Request buffered logs
46
+ this.sendFrame(JSON.stringify({ type: "get_buffer" }));
47
+ socket.on("data", (data) => {
48
+ this.dataBuffer = Buffer.concat([this.dataBuffer, data]);
49
+ this.processFrames();
50
+ });
51
+ socket.on("close", () => {
52
+ this.connected = false;
53
+ this.socket = null;
54
+ this.scheduleReconnect();
55
+ });
56
+ socket.on("error", () => {
57
+ this.connected = false;
58
+ this.socket = null;
59
+ });
60
+ });
61
+ req.on("error", () => {
62
+ this.scheduleReconnect();
63
+ });
64
+ req.on("timeout", () => {
65
+ req.destroy();
66
+ this.scheduleReconnect();
67
+ });
68
+ req.end();
69
+ }
70
+ disconnect() {
71
+ this.stopped = true;
72
+ if (this.reconnectTimer) {
73
+ clearTimeout(this.reconnectTimer);
74
+ this.reconnectTimer = null;
75
+ }
76
+ if (this.socket) {
77
+ this.socket.end();
78
+ this.socket = null;
79
+ }
80
+ this.connected = false;
81
+ }
82
+ isConnected() {
83
+ return this.connected;
84
+ }
85
+ processFrames() {
86
+ while (this.dataBuffer.length >= 2) {
87
+ const firstByte = this.dataBuffer[0];
88
+ const secondByte = this.dataBuffer[1];
89
+ const isFin = (firstByte & 0x80) !== 0;
90
+ const opcode = firstByte & 0x0f;
91
+ if (opcode === 0x08) {
92
+ this.socket?.end();
93
+ return;
94
+ }
95
+ let payloadLen = secondByte & 0x7f;
96
+ let headerLen = 2;
97
+ if (payloadLen === 126) {
98
+ if (this.dataBuffer.length < 4)
99
+ return;
100
+ payloadLen = this.dataBuffer.readUInt16BE(2);
101
+ headerLen = 4;
102
+ }
103
+ else if (payloadLen === 127) {
104
+ if (this.dataBuffer.length < 10)
105
+ return;
106
+ payloadLen = Number(this.dataBuffer.readBigUInt64BE(2));
107
+ headerLen = 10;
108
+ }
109
+ const totalLen = headerLen + payloadLen;
110
+ if (this.dataBuffer.length < totalLen)
111
+ return;
112
+ const payload = this.dataBuffer.subarray(headerLen, totalLen);
113
+ this.dataBuffer = this.dataBuffer.subarray(totalLen);
114
+ if (isFin && (opcode === 0x01 || opcode === 0x02)) {
115
+ const text = payload.toString("utf-8");
116
+ try {
117
+ const msg = JSON.parse(text);
118
+ this.handleMessage(msg);
119
+ }
120
+ catch {
121
+ // invalid JSON
122
+ }
123
+ }
124
+ }
125
+ }
126
+ handleMessage(msg) {
127
+ if (msg.type === "buffer" && msg.logs) {
128
+ for (const log of msg.logs) {
129
+ this.ingestLog(log);
130
+ }
131
+ return;
132
+ }
133
+ this.ingestLog(msg);
134
+ }
135
+ ingestLog(msg) {
136
+ const level = LEVEL_MAP[msg.type] || "info";
137
+ this.collector.addLog({
138
+ level,
139
+ message: msg.values.join(", "),
140
+ source: msg.file || "agent",
141
+ framework: "unknown",
142
+ metadata: {
143
+ line: msg.line,
144
+ column: msg.column,
145
+ agentType: msg.type,
146
+ expression: msg.expression,
147
+ originalTimestamp: msg.timestamp,
148
+ },
149
+ });
150
+ }
151
+ sendFrame(text) {
152
+ if (!this.socket)
153
+ return;
154
+ const data = Buffer.from(text, "utf-8");
155
+ const len = data.length;
156
+ let header;
157
+ if (len < 126) {
158
+ header = Buffer.alloc(2);
159
+ header[0] = 0x81;
160
+ header[1] = len;
161
+ }
162
+ else if (len < 65536) {
163
+ header = Buffer.alloc(4);
164
+ header[0] = 0x81;
165
+ header[1] = 126;
166
+ header.writeUInt16BE(len, 2);
167
+ }
168
+ else {
169
+ header = Buffer.alloc(10);
170
+ header[0] = 0x81;
171
+ header[1] = 127;
172
+ header.writeBigUInt64BE(BigInt(len), 2);
173
+ }
174
+ this.socket.write(Buffer.concat([header, data]));
175
+ }
176
+ scheduleReconnect() {
177
+ if (this.reconnectTimer || this.stopped)
178
+ return;
179
+ this.reconnectTimer = setTimeout(() => {
180
+ this.reconnectTimer = null;
181
+ this.connect();
182
+ }, 5000);
183
+ }
184
+ }
185
+ //# sourceMappingURL=agent-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-bridge.js","sourceRoot":"","sources":["../src/agent-bridge.ts"],"names":[],"mappings":"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"}