@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.
- package/agent/index.ts +281 -212
- package/dist/agent/index.js +92 -36
- package/dist/agent/index.js.map +2 -2
- package/dist/agent-bridge.d.ts +20 -0
- package/dist/agent-bridge.d.ts.map +1 -0
- package/dist/agent-bridge.js +185 -0
- package/dist/agent-bridge.js.map +1 -0
- package/dist/extension/extension.js +58 -32
- package/dist/extension/extension.js.map +2 -2
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +115 -100
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/agent-bridge.ts +218 -0
- package/src/server.ts +405 -358
package/dist/agent/index.js
CHANGED
|
@@ -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
|
|
7
|
+
var clients = /* @__PURE__ */ new Set();
|
|
8
8
|
var buffer = [];
|
|
9
|
-
var MAX_BUFFER =
|
|
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")
|
|
15
|
-
|
|
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)
|
|
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(
|
|
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
|
|
45
|
+
function broadcast(msg) {
|
|
41
46
|
const payload = JSON.stringify(msg);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
client.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
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"))
|
|
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 {
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
222
|
+
clients.delete(socket);
|
|
223
|
+
originalConsole.log(
|
|
224
|
+
`[runtime-lens] client disconnected (${clients.size} total)`
|
|
225
|
+
);
|
|
198
226
|
});
|
|
199
227
|
socket.on("error", () => {
|
|
200
|
-
|
|
228
|
+
clients.delete(socket);
|
|
201
229
|
});
|
|
202
230
|
});
|
|
203
231
|
server.on("error", (err) => {
|
|
204
232
|
if (err.code === "EADDRINUSE") {
|
|
205
|
-
originalConsole.log(
|
|
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(
|
|
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
|
-
|
|
272
|
+
broadcast({
|
|
217
273
|
type: "result",
|
|
218
274
|
file: site.file,
|
|
219
275
|
line: site.line,
|
package/dist/agent/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../agent/index.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;AAAA,
|
|
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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"}
|