@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.
@@ -34,8 +34,8 @@ __export(extension_exports, {
34
34
  deactivate: () => deactivate
35
35
  });
36
36
  module.exports = __toCommonJS(extension_exports);
37
- var vscode3 = __toESM(require("vscode"));
38
37
  var import_node_path = require("node:path");
38
+ var vscode3 = __toESM(require("vscode"));
39
39
 
40
40
  // extension/decorator.ts
41
41
  var vscode = __toESM(require("vscode"));
@@ -47,6 +47,7 @@ var TYPE_COLORS = {
47
47
  debug: "#9CDCFE",
48
48
  result: "#DCDCAA"
49
49
  };
50
+ var MAX_HISTORY_PER_LINE = 10;
50
51
  var InlineDecorator = class {
51
52
  decorationTypes = /* @__PURE__ */ new Map();
52
53
  values = /* @__PURE__ */ new Map();
@@ -65,17 +66,16 @@ var InlineDecorator = class {
65
66
  addValue(value) {
66
67
  const key = value.file;
67
68
  if (!this.values.has(key)) {
68
- this.values.set(key, []);
69
+ this.values.set(key, /* @__PURE__ */ new Map());
69
70
  }
70
- const existing = this.values.get(key);
71
- const idx = existing.findIndex((v) => v.line === value.line);
72
- if (idx >= 0) {
73
- existing[idx] = value;
74
- } else {
75
- existing.push(value);
71
+ const lineMap = this.values.get(key);
72
+ if (!lineMap.has(value.line)) {
73
+ lineMap.set(value.line, []);
76
74
  }
77
- if (existing.length > 1e3) {
78
- existing.splice(0, existing.length - 1e3);
75
+ const history = lineMap.get(value.line);
76
+ history.push(value);
77
+ if (history.length > MAX_HISTORY_PER_LINE) {
78
+ history.splice(0, history.length - MAX_HISTORY_PER_LINE);
79
79
  }
80
80
  this.refresh();
81
81
  }
@@ -92,39 +92,51 @@ var InlineDecorator = class {
92
92
  if (!editor) return;
93
93
  this.clearDecorations();
94
94
  const filePath = editor.document.uri.fsPath;
95
- const fileValues = this.values.get(filePath);
96
- if (!fileValues || fileValues.length === 0) return;
95
+ const lineMap = this.values.get(filePath);
96
+ if (!lineMap || lineMap.size === 0) return;
97
97
  const decorationsByType = /* @__PURE__ */ new Map();
98
- for (const value of fileValues) {
99
- const lineIndex = value.line - 1;
98
+ for (const [lineNum, history] of lineMap) {
99
+ if (history.length === 0) continue;
100
+ const lineIndex = lineNum - 1;
100
101
  if (lineIndex < 0 || lineIndex >= editor.document.lineCount) continue;
101
102
  const lineText = editor.document.lineAt(lineIndex).text;
102
103
  const range = new vscode.Range(
103
104
  new vscode.Position(lineIndex, lineText.length),
104
105
  new vscode.Position(lineIndex, lineText.length)
105
106
  );
106
- const truncated = value.text.length > 80 ? value.text.slice(0, 80) + "\u2026" : value.text;
107
+ const latest = history[history.length - 1];
108
+ const maxLen = vscode.workspace.getConfiguration("runtimeLens").get("maxInlineLength", 80);
109
+ let inlineText = latest.text;
110
+ if (inlineText.length > maxLen) {
111
+ inlineText = inlineText.slice(0, maxLen) + "\u2026";
112
+ }
113
+ if (history.length > 1) {
114
+ inlineText = `${inlineText} (\xD7${history.length})`;
115
+ }
116
+ const hoverLines = history.slice().reverse().map((v, i) => {
117
+ const time = new Date(v.timestamp).toLocaleTimeString();
118
+ const prefix = i === 0 ? "\u25B6" : " ";
119
+ return `${prefix} \`[${time}]\` ${v.type}: \`${v.text}\``;
120
+ }).join("\n\n");
121
+ const hover = new vscode.MarkdownString(
122
+ `**Runtime Lens** \u2014 ${history.length} log(s)
123
+
124
+ ${hoverLines}`
125
+ );
126
+ hover.isTrusted = true;
107
127
  const decoration = {
108
128
  range,
109
- hoverMessage: new vscode.MarkdownString(
110
- `**Runtime Lens** (${value.type})
111
-
112
- \`\`\`
113
- ${value.text}
114
- \`\`\`
115
-
116
- *${new Date(value.timestamp).toLocaleTimeString()}*`
117
- ),
129
+ hoverMessage: hover,
118
130
  renderOptions: {
119
131
  after: {
120
- contentText: ` // \u2192 ${truncated}`,
121
- color: TYPE_COLORS[value.type] || "#6A9955",
132
+ contentText: ` // \u2192 ${inlineText}`,
133
+ color: TYPE_COLORS[latest.type] || "#6A9955",
122
134
  fontStyle: "italic",
123
135
  margin: "0 0 0 1em"
124
136
  }
125
137
  }
126
138
  };
127
- const typeKey = value.type;
139
+ const typeKey = latest.type;
128
140
  if (!decorationsByType.has(typeKey)) {
129
141
  decorationsByType.set(typeKey, []);
130
142
  }
@@ -331,7 +343,10 @@ function activate(context) {
331
343
  decorator = new InlineDecorator();
332
344
  decorator.activate(context);
333
345
  bridge = new RuntimeBridge(decorator, outputChannel);
334
- statusBarItem = vscode3.window.createStatusBarItem(vscode3.StatusBarAlignment.Right, 100);
346
+ statusBarItem = vscode3.window.createStatusBarItem(
347
+ vscode3.StatusBarAlignment.Right,
348
+ 100
349
+ );
335
350
  statusBarItem.text = "$(eye) Lens";
336
351
  statusBarItem.tooltip = "Runtime Lens - Click to toggle";
337
352
  statusBarItem.command = "runtimeLens.toggle";
@@ -342,7 +357,9 @@ function activate(context) {
342
357
  vscode3.commands.registerCommand("runtimeLens.start", () => {
343
358
  bridge.connect();
344
359
  updateStatusBar(true);
345
- vscode3.window.showInformationMessage("Runtime Lens: Listening for logs...");
360
+ vscode3.window.showInformationMessage(
361
+ "Runtime Lens: Listening for logs..."
362
+ );
346
363
  }),
347
364
  vscode3.commands.registerCommand("runtimeLens.stop", () => {
348
365
  bridge.disconnect();
@@ -376,20 +393,29 @@ function activate(context) {
376
393
  }
377
394
  terminal.sendText(`export NODE_OPTIONS="--require ${agentPath}"`, true);
378
395
  terminal.sendText(`export RUNTIME_LENS_PORT="${port}"`, true);
379
- vscode3.window.showInformationMessage("Runtime Lens: Environment injected. Run your app now.");
396
+ vscode3.window.showInformationMessage(
397
+ "Runtime Lens: Environment injected. Run your app now."
398
+ );
399
+ })
400
+ );
401
+ context.subscriptions.push(
402
+ vscode3.workspace.onDidSaveTextDocument((doc) => {
403
+ decorator.clearFile(doc.uri.fsPath);
380
404
  })
381
405
  );
382
406
  const autoStart = vscode3.workspace.getConfiguration("runtimeLens").get("autoStart", false);
383
407
  if (autoStart) {
384
408
  vscode3.commands.executeCommand("runtimeLens.start");
385
409
  }
386
- outputChannel.appendLine(`[runtime-lens] Extension activated`);
410
+ outputChannel.appendLine("[runtime-lens] Extension activated");
387
411
  outputChannel.appendLine(`[runtime-lens] Agent path: ${agentPath}`);
388
412
  }
389
413
  function updateStatusBar(active) {
390
414
  if (active) {
391
415
  statusBarItem.text = "$(eye) Lens \u25CF";
392
- statusBarItem.backgroundColor = new vscode3.ThemeColor("statusBarItem.warningBackground");
416
+ statusBarItem.backgroundColor = new vscode3.ThemeColor(
417
+ "statusBarItem.warningBackground"
418
+ );
393
419
  } else {
394
420
  statusBarItem.text = "$(eye) Lens";
395
421
  statusBarItem.backgroundColor = void 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../extension/extension.ts", "../../extension/decorator.ts", "../../extension/runtime-bridge.ts"],
4
- "sourcesContent": ["import * as vscode from \"vscode\";\nimport { join } from \"node:path\";\nimport { InlineDecorator } from \"./decorator.js\";\nimport { RuntimeBridge } from \"./runtime-bridge.js\";\n\nlet decorator: InlineDecorator;\nlet bridge: RuntimeBridge;\nlet statusBarItem: vscode.StatusBarItem;\n\nexport function activate(context: vscode.ExtensionContext): void {\n const outputChannel = vscode.window.createOutputChannel(\"Runtime Lens\");\n const agentPath = join(context.extensionPath, \"dist\", \"agent\", \"index.js\");\n\n decorator = new InlineDecorator();\n decorator.activate(context);\n\n bridge = new RuntimeBridge(decorator, outputChannel);\n\n statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);\n statusBarItem.text = \"$(eye) Lens\";\n statusBarItem.tooltip = \"Runtime Lens - Click to toggle\";\n statusBarItem.command = \"runtimeLens.toggle\";\n statusBarItem.show();\n context.subscriptions.push(statusBarItem);\n\n const port = vscode.workspace.getConfiguration(\"runtimeLens\").get(\"port\", 9500);\n\n context.subscriptions.push(\n vscode.commands.registerCommand(\"runtimeLens.start\", () => {\n bridge.connect();\n updateStatusBar(true);\n vscode.window.showInformationMessage(\"Runtime Lens: Listening for logs...\");\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.stop\", () => {\n bridge.disconnect();\n decorator.clearAll();\n updateStatusBar(false);\n vscode.window.showInformationMessage(\"Runtime Lens: Stopped\");\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.toggle\", () => {\n if (bridge.isConnected()) {\n vscode.commands.executeCommand(\"runtimeLens.stop\");\n } else {\n vscode.commands.executeCommand(\"runtimeLens.start\");\n }\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.clear\", () => {\n decorator.clearAll();\n vscode.window.showInformationMessage(\"Runtime Lens: Cleared\");\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.connect\", () => {\n bridge.connect();\n updateStatusBar(true);\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.showOutput\", () => {\n outputChannel.show();\n }),\n\n vscode.commands.registerCommand(\"runtimeLens.injectEnv\", () => {\n const terminal = vscode.window.activeTerminal;\n if (!terminal) {\n vscode.window.showWarningMessage(\"Runtime Lens: No active terminal\");\n return;\n }\n terminal.sendText(`export NODE_OPTIONS=\"--require ${agentPath}\"`, true);\n terminal.sendText(`export RUNTIME_LENS_PORT=\"${port}\"`, true);\n vscode.window.showInformationMessage(\"Runtime Lens: Environment injected. Run your app now.\");\n })\n );\n\n const autoStart = vscode.workspace.getConfiguration(\"runtimeLens\").get(\"autoStart\", false);\n if (autoStart) {\n vscode.commands.executeCommand(\"runtimeLens.start\");\n }\n\n outputChannel.appendLine(`[runtime-lens] Extension activated`);\n outputChannel.appendLine(`[runtime-lens] Agent path: ${agentPath}`);\n}\n\nfunction updateStatusBar(active: boolean): void {\n if (active) {\n statusBarItem.text = \"$(eye) Lens \u25CF\";\n statusBarItem.backgroundColor = new vscode.ThemeColor(\"statusBarItem.warningBackground\");\n } else {\n statusBarItem.text = \"$(eye) Lens\";\n statusBarItem.backgroundColor = undefined;\n }\n}\n\nexport function deactivate(): void {\n bridge?.disconnect();\n decorator?.dispose();\n}\n", "import * as vscode from \"vscode\";\n\ninterface InlineValue {\n file: string;\n line: number;\n column: number;\n text: string;\n type: \"log\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"result\";\n timestamp: number;\n}\n\nconst TYPE_COLORS: Record<string, string> = {\n log: \"#6A9955\",\n info: \"#569CD6\",\n warn: \"#CE9178\",\n error: \"#F44747\",\n debug: \"#9CDCFE\",\n result: \"#DCDCAA\",\n};\n\nexport class InlineDecorator {\n private decorationTypes: Map<string, vscode.TextEditorDecorationType> = new Map();\n private values: Map<string, InlineValue[]> = new Map();\n private disposables: vscode.Disposable[] = [];\n\n activate(context: vscode.ExtensionContext): void {\n this.disposables.push(\n vscode.window.onDidChangeActiveTextEditor(() => this.refresh()),\n vscode.workspace.onDidChangeTextDocument((e) => {\n if (e.document === vscode.window.activeTextEditor?.document) {\n this.refresh();\n }\n })\n );\n context.subscriptions.push(...this.disposables);\n }\n\n addValue(value: InlineValue): void {\n const key = value.file;\n if (!this.values.has(key)) {\n this.values.set(key, []);\n }\n\n const existing = this.values.get(key)!;\n const idx = existing.findIndex((v) => v.line === value.line);\n if (idx >= 0) {\n existing[idx] = value;\n } else {\n existing.push(value);\n }\n\n if (existing.length > 1000) {\n existing.splice(0, existing.length - 1000);\n }\n\n this.refresh();\n }\n\n clearFile(file: string): void {\n this.values.delete(file);\n this.refresh();\n }\n\n clearAll(): void {\n this.values.clear();\n this.clearDecorations();\n }\n\n refresh(): void {\n const editor = vscode.window.activeTextEditor;\n if (!editor) return;\n\n this.clearDecorations();\n\n const filePath = editor.document.uri.fsPath;\n const fileValues = this.values.get(filePath);\n if (!fileValues || fileValues.length === 0) return;\n\n const decorationsByType = new Map<string, vscode.DecorationOptions[]>();\n\n for (const value of fileValues) {\n const lineIndex = value.line - 1;\n if (lineIndex < 0 || lineIndex >= editor.document.lineCount) continue;\n\n const lineText = editor.document.lineAt(lineIndex).text;\n const range = new vscode.Range(\n new vscode.Position(lineIndex, lineText.length),\n new vscode.Position(lineIndex, lineText.length)\n );\n\n const truncated = value.text.length > 80\n ? value.text.slice(0, 80) + \"\u2026\"\n : value.text;\n\n const decoration: vscode.DecorationOptions = {\n range,\n hoverMessage: new vscode.MarkdownString(\n `**Runtime Lens** (${value.type})\\n\\n\\`\\`\\`\\n${value.text}\\n\\`\\`\\`\\n\\n*${new Date(value.timestamp).toLocaleTimeString()}*`\n ),\n renderOptions: {\n after: {\n contentText: ` // \u2192 ${truncated}`,\n color: TYPE_COLORS[value.type] || \"#6A9955\",\n fontStyle: \"italic\",\n margin: \"0 0 0 1em\",\n },\n },\n };\n\n const typeKey = value.type;\n if (!decorationsByType.has(typeKey)) {\n decorationsByType.set(typeKey, []);\n }\n decorationsByType.get(typeKey)!.push(decoration);\n }\n\n for (const [typeKey, decorations] of decorationsByType) {\n const decorationType = vscode.window.createTextEditorDecorationType({\n after: {\n color: TYPE_COLORS[typeKey] || \"#6A9955\",\n fontStyle: \"italic\",\n },\n isWholeLine: false,\n });\n\n this.decorationTypes.set(typeKey, decorationType);\n editor.setDecorations(decorationType, decorations);\n }\n }\n\n private clearDecorations(): void {\n for (const decorationType of this.decorationTypes.values()) {\n decorationType.dispose();\n }\n this.decorationTypes.clear();\n }\n\n dispose(): void {\n this.clearDecorations();\n for (const d of this.disposables) {\n d.dispose();\n }\n }\n}\n", "import * as vscode from \"vscode\";\nimport { request } from \"node:http\";\nimport { randomBytes } from \"node:crypto\";\nimport type { Socket } from \"node:net\";\nimport { InlineDecorator } from \"./decorator.js\";\n\ninterface AgentMessage {\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\nexport class RuntimeBridge {\n private socket: Socket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly decorator: InlineDecorator;\n private readonly port: number;\n private connected = false;\n private readonly outputChannel: vscode.OutputChannel;\n private dataBuffer: Buffer = Buffer.alloc(0);\n\n constructor(decorator: InlineDecorator, outputChannel: vscode.OutputChannel) {\n this.decorator = decorator;\n this.port = vscode.workspace.getConfiguration(\"runtimeLens\").get(\"port\", 9500);\n this.outputChannel = outputChannel;\n }\n\n connect(): void {\n if (this.socket) return;\n\n const key = randomBytes(16).toString(\"base64\");\n\n const req = request({\n hostname: \"localhost\",\n port: this.port,\n path: \"/\",\n method: \"GET\",\n headers: {\n Upgrade: \"websocket\",\n Connection: \"Upgrade\",\n \"Sec-WebSocket-Key\": key,\n \"Sec-WebSocket-Version\": \"13\",\n },\n });\n\n req.on(\"upgrade\", (_res, socket) => {\n this.socket = socket;\n this.connected = true;\n this.dataBuffer = Buffer.alloc(0);\n this.outputChannel.appendLine(`[runtime-lens] Connected to agent on port ${this.port}`);\n vscode.window.setStatusBarMessage(\"$(eye) Runtime Lens: Connected\", 3000);\n\n socket.on(\"data\", (data: Buffer) => {\n this.dataBuffer = Buffer.concat([this.dataBuffer, data]);\n this.processFrames();\n });\n\n socket.on(\"close\", () => {\n this.connected = false;\n this.socket = null;\n this.scheduleReconnect();\n });\n\n socket.on(\"error\", () => {\n this.connected = false;\n this.socket = null;\n });\n });\n\n req.on(\"error\", () => {\n this.scheduleReconnect();\n });\n\n req.end();\n }\n\n disconnect(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.socket) {\n this.socket.end();\n this.socket = null;\n }\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n evaluate(expression: string, file: string, line: number): void {\n if (!this.socket || !this.connected) return;\n const payload = JSON.stringify({ type: \"eval\", expression, file, line });\n this.sendFrame(payload);\n }\n\n private processFrames(): void {\n while (this.dataBuffer.length >= 2) {\n const firstByte = this.dataBuffer[0];\n const secondByte = this.dataBuffer[1];\n const isFin = (firstByte & 0x80) !== 0;\n const opcode = firstByte & 0x0f;\n\n if (opcode === 0x08) {\n this.socket?.end();\n return;\n }\n\n let payloadLen = secondByte & 0x7f;\n let headerLen = 2;\n\n if (payloadLen === 126) {\n if (this.dataBuffer.length < 4) return;\n payloadLen = this.dataBuffer.readUInt16BE(2);\n headerLen = 4;\n } else if (payloadLen === 127) {\n if (this.dataBuffer.length < 10) return;\n payloadLen = Number(this.dataBuffer.readBigUInt64BE(2));\n headerLen = 10;\n }\n\n const totalLen = headerLen + payloadLen;\n if (this.dataBuffer.length < totalLen) return;\n\n const payload = this.dataBuffer.subarray(headerLen, totalLen);\n this.dataBuffer = this.dataBuffer.subarray(totalLen);\n\n if (isFin && (opcode === 0x01 || opcode === 0x02)) {\n const text = payload.toString(\"utf-8\");\n try {\n const msg: AgentMessage = JSON.parse(text);\n this.handleMessage(msg);\n } catch {\n // invalid JSON\n }\n }\n }\n }\n\n private sendFrame(text: string): void {\n if (!this.socket) return;\n const data = Buffer.from(text, \"utf-8\");\n const len = data.length;\n let header: Buffer;\n\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\n this.socket.write(Buffer.concat([header, data]));\n }\n\n private handleMessage(msg: AgentMessage): void {\n const workspaceFolders = vscode.workspace.workspaceFolders;\n if (!workspaceFolders) return;\n\n let resolvedFile = msg.file;\n for (const folder of workspaceFolders) {\n if (msg.file.startsWith(folder.uri.fsPath)) {\n resolvedFile = msg.file;\n break;\n }\n }\n\n const text = msg.values.join(\", \");\n\n this.decorator.addValue({\n file: resolvedFile,\n line: msg.line,\n column: msg.column,\n text,\n type: msg.type,\n timestamp: msg.timestamp,\n });\n\n this.outputChannel.appendLine(\n `[${msg.type}] ${resolvedFile}:${msg.line} \u2192 ${text}`\n );\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return;\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, 3000);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { join } from \"node:path\";\nimport * as vscode from \"vscode\";\nimport { InlineDecorator } from \"./decorator.js\";\nimport { RuntimeBridge } from \"./runtime-bridge.js\";\n\nlet decorator: InlineDecorator;\nlet bridge: RuntimeBridge;\nlet statusBarItem: vscode.StatusBarItem;\n\nexport function activate(context: vscode.ExtensionContext): void {\n\tconst outputChannel = vscode.window.createOutputChannel(\"Runtime Lens\");\n\tconst agentPath = join(context.extensionPath, \"dist\", \"agent\", \"index.js\");\n\n\tdecorator = new InlineDecorator();\n\tdecorator.activate(context);\n\n\tbridge = new RuntimeBridge(decorator, outputChannel);\n\n\tstatusBarItem = vscode.window.createStatusBarItem(\n\t\tvscode.StatusBarAlignment.Right,\n\t\t100,\n\t);\n\tstatusBarItem.text = \"$(eye) Lens\";\n\tstatusBarItem.tooltip = \"Runtime Lens - Click to toggle\";\n\tstatusBarItem.command = \"runtimeLens.toggle\";\n\tstatusBarItem.show();\n\tcontext.subscriptions.push(statusBarItem);\n\n\tconst port = vscode.workspace\n\t\t.getConfiguration(\"runtimeLens\")\n\t\t.get(\"port\", 9500);\n\n\tcontext.subscriptions.push(\n\t\tvscode.commands.registerCommand(\"runtimeLens.start\", () => {\n\t\t\tbridge.connect();\n\t\t\tupdateStatusBar(true);\n\t\t\tvscode.window.showInformationMessage(\n\t\t\t\t\"Runtime Lens: Listening for logs...\",\n\t\t\t);\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.stop\", () => {\n\t\t\tbridge.disconnect();\n\t\t\tdecorator.clearAll();\n\t\t\tupdateStatusBar(false);\n\t\t\tvscode.window.showInformationMessage(\"Runtime Lens: Stopped\");\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.toggle\", () => {\n\t\t\tif (bridge.isConnected()) {\n\t\t\t\tvscode.commands.executeCommand(\"runtimeLens.stop\");\n\t\t\t} else {\n\t\t\t\tvscode.commands.executeCommand(\"runtimeLens.start\");\n\t\t\t}\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.clear\", () => {\n\t\t\tdecorator.clearAll();\n\t\t\tvscode.window.showInformationMessage(\"Runtime Lens: Cleared\");\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.connect\", () => {\n\t\t\tbridge.connect();\n\t\t\tupdateStatusBar(true);\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.showOutput\", () => {\n\t\t\toutputChannel.show();\n\t\t}),\n\n\t\tvscode.commands.registerCommand(\"runtimeLens.injectEnv\", () => {\n\t\t\tconst terminal = vscode.window.activeTerminal;\n\t\t\tif (!terminal) {\n\t\t\t\tvscode.window.showWarningMessage(\"Runtime Lens: No active terminal\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tterminal.sendText(`export NODE_OPTIONS=\"--require ${agentPath}\"`, true);\n\t\t\tterminal.sendText(`export RUNTIME_LENS_PORT=\"${port}\"`, true);\n\t\t\tvscode.window.showInformationMessage(\n\t\t\t\t\"Runtime Lens: Environment injected. Run your app now.\",\n\t\t\t);\n\t\t}),\n\t);\n\n\tcontext.subscriptions.push(\n\t\tvscode.workspace.onDidSaveTextDocument((doc) => {\n\t\t\tdecorator.clearFile(doc.uri.fsPath);\n\t\t}),\n\t);\n\n\tconst autoStart = vscode.workspace\n\t\t.getConfiguration(\"runtimeLens\")\n\t\t.get(\"autoStart\", false);\n\tif (autoStart) {\n\t\tvscode.commands.executeCommand(\"runtimeLens.start\");\n\t}\n\n\toutputChannel.appendLine(\"[runtime-lens] Extension activated\");\n\toutputChannel.appendLine(`[runtime-lens] Agent path: ${agentPath}`);\n}\n\nfunction updateStatusBar(active: boolean): void {\n\tif (active) {\n\t\tstatusBarItem.text = \"$(eye) Lens \u25CF\";\n\t\tstatusBarItem.backgroundColor = new vscode.ThemeColor(\n\t\t\t\"statusBarItem.warningBackground\",\n\t\t);\n\t} else {\n\t\tstatusBarItem.text = \"$(eye) Lens\";\n\t\tstatusBarItem.backgroundColor = undefined;\n\t}\n}\n\nexport function deactivate(): void {\n\tbridge?.disconnect();\n\tdecorator?.dispose();\n}\n", "import * as vscode from \"vscode\";\n\ninterface InlineValue {\n\tfile: string;\n\tline: number;\n\tcolumn: number;\n\ttext: string;\n\ttype: \"log\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"result\";\n\ttimestamp: number;\n}\n\nconst TYPE_COLORS: Record<string, string> = {\n\tlog: \"#6A9955\",\n\tinfo: \"#569CD6\",\n\twarn: \"#CE9178\",\n\terror: \"#F44747\",\n\tdebug: \"#9CDCFE\",\n\tresult: \"#DCDCAA\",\n};\n\nconst MAX_HISTORY_PER_LINE = 10;\n\nexport class InlineDecorator {\n\tprivate decorationTypes: Map<string, vscode.TextEditorDecorationType> =\n\t\tnew Map();\n\tprivate values: Map<string, Map<number, InlineValue[]>> = new Map();\n\tprivate disposables: vscode.Disposable[] = [];\n\n\tactivate(context: vscode.ExtensionContext): void {\n\t\tthis.disposables.push(\n\t\t\tvscode.window.onDidChangeActiveTextEditor(() => this.refresh()),\n\t\t\tvscode.workspace.onDidChangeTextDocument((e) => {\n\t\t\t\tif (e.document === vscode.window.activeTextEditor?.document) {\n\t\t\t\t\tthis.refresh();\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tcontext.subscriptions.push(...this.disposables);\n\t}\n\n\taddValue(value: InlineValue): void {\n\t\tconst key = value.file;\n\t\tif (!this.values.has(key)) {\n\t\t\tthis.values.set(key, new Map());\n\t\t}\n\t\tconst lineMap = this.values.get(key)!;\n\t\tif (!lineMap.has(value.line)) {\n\t\t\tlineMap.set(value.line, []);\n\t\t}\n\n\t\tconst history = lineMap.get(value.line)!;\n\t\thistory.push(value);\n\n\t\tif (history.length > MAX_HISTORY_PER_LINE) {\n\t\t\thistory.splice(0, history.length - MAX_HISTORY_PER_LINE);\n\t\t}\n\n\t\tthis.refresh();\n\t}\n\n\tclearFile(file: string): void {\n\t\tthis.values.delete(file);\n\t\tthis.refresh();\n\t}\n\n\tclearAll(): void {\n\t\tthis.values.clear();\n\t\tthis.clearDecorations();\n\t}\n\n\trefresh(): void {\n\t\tconst editor = vscode.window.activeTextEditor;\n\t\tif (!editor) return;\n\n\t\tthis.clearDecorations();\n\n\t\tconst filePath = editor.document.uri.fsPath;\n\t\tconst lineMap = this.values.get(filePath);\n\t\tif (!lineMap || lineMap.size === 0) return;\n\n\t\tconst decorationsByType = new Map<string, vscode.DecorationOptions[]>();\n\n\t\tfor (const [lineNum, history] of lineMap) {\n\t\t\tif (history.length === 0) continue;\n\n\t\t\tconst lineIndex = lineNum - 1;\n\t\t\tif (lineIndex < 0 || lineIndex >= editor.document.lineCount) continue;\n\n\t\t\tconst lineText = editor.document.lineAt(lineIndex).text;\n\t\t\tconst range = new vscode.Range(\n\t\t\t\tnew vscode.Position(lineIndex, lineText.length),\n\t\t\t\tnew vscode.Position(lineIndex, lineText.length),\n\t\t\t);\n\n\t\t\tconst latest = history[history.length - 1];\n\t\t\tconst maxLen = vscode.workspace\n\t\t\t\t.getConfiguration(\"runtimeLens\")\n\t\t\t\t.get(\"maxInlineLength\", 80);\n\n\t\t\tlet inlineText = latest.text;\n\t\t\tif (inlineText.length > maxLen) {\n\t\t\t\tinlineText = inlineText.slice(0, maxLen) + \"\u2026\";\n\t\t\t}\n\t\t\tif (history.length > 1) {\n\t\t\t\tinlineText = `${inlineText} (\u00D7${history.length})`;\n\t\t\t}\n\n\t\t\tconst hoverLines = history\n\t\t\t\t.slice()\n\t\t\t\t.reverse()\n\t\t\t\t.map((v, i) => {\n\t\t\t\t\tconst time = new Date(v.timestamp).toLocaleTimeString();\n\t\t\t\t\tconst prefix = i === 0 ? \"\u25B6\" : \" \";\n\t\t\t\t\treturn `${prefix} \\`[${time}]\\` ${v.type}: \\`${v.text}\\``;\n\t\t\t\t})\n\t\t\t\t.join(\"\\n\\n\");\n\n\t\t\tconst hover = new vscode.MarkdownString(\n\t\t\t\t`**Runtime Lens** \u2014 ${history.length} log(s)\\n\\n${hoverLines}`,\n\t\t\t);\n\t\t\thover.isTrusted = true;\n\n\t\t\tconst decoration: vscode.DecorationOptions = {\n\t\t\t\trange,\n\t\t\t\thoverMessage: hover,\n\t\t\t\trenderOptions: {\n\t\t\t\t\tafter: {\n\t\t\t\t\t\tcontentText: ` // \u2192 ${inlineText}`,\n\t\t\t\t\t\tcolor: TYPE_COLORS[latest.type] || \"#6A9955\",\n\t\t\t\t\t\tfontStyle: \"italic\",\n\t\t\t\t\t\tmargin: \"0 0 0 1em\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst typeKey = latest.type;\n\t\t\tif (!decorationsByType.has(typeKey)) {\n\t\t\t\tdecorationsByType.set(typeKey, []);\n\t\t\t}\n\t\t\tdecorationsByType.get(typeKey)!.push(decoration);\n\t\t}\n\n\t\tfor (const [typeKey, decorations] of decorationsByType) {\n\t\t\tconst decorationType = vscode.window.createTextEditorDecorationType({\n\t\t\t\tafter: {\n\t\t\t\t\tcolor: TYPE_COLORS[typeKey] || \"#6A9955\",\n\t\t\t\t\tfontStyle: \"italic\",\n\t\t\t\t},\n\t\t\t\tisWholeLine: false,\n\t\t\t});\n\t\t\tthis.decorationTypes.set(typeKey, decorationType);\n\t\t\teditor.setDecorations(decorationType, decorations);\n\t\t}\n\t}\n\n\tprivate clearDecorations(): void {\n\t\tfor (const decorationType of this.decorationTypes.values()) {\n\t\t\tdecorationType.dispose();\n\t\t}\n\t\tthis.decorationTypes.clear();\n\t}\n\n\tdispose(): void {\n\t\tthis.clearDecorations();\n\t\tfor (const d of this.disposables) {\n\t\t\td.dispose();\n\t\t}\n\t}\n}\n", "import * as vscode from \"vscode\";\nimport { request } from \"node:http\";\nimport { randomBytes } from \"node:crypto\";\nimport type { Socket } from \"node:net\";\nimport { InlineDecorator } from \"./decorator.js\";\n\ninterface AgentMessage {\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\nexport class RuntimeBridge {\n private socket: Socket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly decorator: InlineDecorator;\n private readonly port: number;\n private connected = false;\n private readonly outputChannel: vscode.OutputChannel;\n private dataBuffer: Buffer = Buffer.alloc(0);\n\n constructor(decorator: InlineDecorator, outputChannel: vscode.OutputChannel) {\n this.decorator = decorator;\n this.port = vscode.workspace.getConfiguration(\"runtimeLens\").get(\"port\", 9500);\n this.outputChannel = outputChannel;\n }\n\n connect(): void {\n if (this.socket) return;\n\n const key = randomBytes(16).toString(\"base64\");\n\n const req = request({\n hostname: \"localhost\",\n port: this.port,\n path: \"/\",\n method: \"GET\",\n headers: {\n Upgrade: \"websocket\",\n Connection: \"Upgrade\",\n \"Sec-WebSocket-Key\": key,\n \"Sec-WebSocket-Version\": \"13\",\n },\n });\n\n req.on(\"upgrade\", (_res, socket) => {\n this.socket = socket;\n this.connected = true;\n this.dataBuffer = Buffer.alloc(0);\n this.outputChannel.appendLine(`[runtime-lens] Connected to agent on port ${this.port}`);\n vscode.window.setStatusBarMessage(\"$(eye) Runtime Lens: Connected\", 3000);\n\n socket.on(\"data\", (data: Buffer) => {\n this.dataBuffer = Buffer.concat([this.dataBuffer, data]);\n this.processFrames();\n });\n\n socket.on(\"close\", () => {\n this.connected = false;\n this.socket = null;\n this.scheduleReconnect();\n });\n\n socket.on(\"error\", () => {\n this.connected = false;\n this.socket = null;\n });\n });\n\n req.on(\"error\", () => {\n this.scheduleReconnect();\n });\n\n req.end();\n }\n\n disconnect(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.socket) {\n this.socket.end();\n this.socket = null;\n }\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n evaluate(expression: string, file: string, line: number): void {\n if (!this.socket || !this.connected) return;\n const payload = JSON.stringify({ type: \"eval\", expression, file, line });\n this.sendFrame(payload);\n }\n\n private processFrames(): void {\n while (this.dataBuffer.length >= 2) {\n const firstByte = this.dataBuffer[0];\n const secondByte = this.dataBuffer[1];\n const isFin = (firstByte & 0x80) !== 0;\n const opcode = firstByte & 0x0f;\n\n if (opcode === 0x08) {\n this.socket?.end();\n return;\n }\n\n let payloadLen = secondByte & 0x7f;\n let headerLen = 2;\n\n if (payloadLen === 126) {\n if (this.dataBuffer.length < 4) return;\n payloadLen = this.dataBuffer.readUInt16BE(2);\n headerLen = 4;\n } else if (payloadLen === 127) {\n if (this.dataBuffer.length < 10) return;\n payloadLen = Number(this.dataBuffer.readBigUInt64BE(2));\n headerLen = 10;\n }\n\n const totalLen = headerLen + payloadLen;\n if (this.dataBuffer.length < totalLen) return;\n\n const payload = this.dataBuffer.subarray(headerLen, totalLen);\n this.dataBuffer = this.dataBuffer.subarray(totalLen);\n\n if (isFin && (opcode === 0x01 || opcode === 0x02)) {\n const text = payload.toString(\"utf-8\");\n try {\n const msg: AgentMessage = JSON.parse(text);\n this.handleMessage(msg);\n } catch {\n // invalid JSON\n }\n }\n }\n }\n\n private sendFrame(text: string): void {\n if (!this.socket) return;\n const data = Buffer.from(text, \"utf-8\");\n const len = data.length;\n let header: Buffer;\n\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\n this.socket.write(Buffer.concat([header, data]));\n }\n\n private handleMessage(msg: AgentMessage): void {\n const workspaceFolders = vscode.workspace.workspaceFolders;\n if (!workspaceFolders) return;\n\n let resolvedFile = msg.file;\n for (const folder of workspaceFolders) {\n if (msg.file.startsWith(folder.uri.fsPath)) {\n resolvedFile = msg.file;\n break;\n }\n }\n\n const text = msg.values.join(\", \");\n\n this.decorator.addValue({\n file: resolvedFile,\n line: msg.line,\n column: msg.column,\n text,\n type: msg.type,\n timestamp: msg.timestamp,\n });\n\n this.outputChannel.appendLine(\n `[${msg.type}] ${resolvedFile}:${msg.line} \u2192 ${text}`\n );\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return;\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, 3000);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["vscode", "vscode", "decorator"]
7
7
  }
package/dist/server.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare class RuntimeLensMCPServer {
3
3
  private readonly collector;
4
4
  private readonly inspector;
5
5
  private readonly interceptor;
6
+ private readonly agentBridge;
6
7
  constructor(projectRoot?: string, logPaths?: string[]);
7
8
  static fromEnvironment(): RuntimeLensMCPServer;
8
9
  private setupTools;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAaA,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;gBAErC,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE;IAarD,MAAM,CAAC,eAAe,IAAI,oBAAoB;IAM9C,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,sBAAsB;IAyB9B,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,uBAAuB;IAoB/B,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,gBAAgB;IAoBlB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B,qBAAqB,IAAI,IAAI;CAU9B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAcA,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;gBAE9B,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE;IAYrD,MAAM,CAAC,eAAe,IAAI,oBAAoB;IAO9C,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,sBAAsB;IA2B9B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,wBAAwB;IA0BhC,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,mBAAmB;IA0B3B,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,gBAAgB;IAwBlB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B,qBAAqB,IAAI,IAAI;CAU7B"}
package/dist/server.js CHANGED
@@ -1,22 +1,25 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { AgentBridge } from "./agent-bridge.js";
3
4
  import { LogCollector } from "./log-collector.js";
4
5
  import { ProcessInspector } from "./process-inspector.js";
5
6
  import { RuntimeInterceptor } from "./runtime-interceptor.js";
6
- import { TailLogsParamsSchema, SearchLogsParamsSchema, GetErrorsParamsSchema, InspectRequestParamsSchema, GetPerformanceParamsSchema, } from "./types.js";
7
+ import { GetErrorsParamsSchema, GetPerformanceParamsSchema, InspectRequestParamsSchema, SearchLogsParamsSchema, TailLogsParamsSchema, } from "./types.js";
7
8
  export class RuntimeLensMCPServer {
8
9
  server;
9
10
  collector;
10
11
  inspector;
11
12
  interceptor;
13
+ agentBridge;
12
14
  constructor(projectRoot, logPaths) {
13
15
  this.server = new McpServer({
14
16
  name: "runtime-lens-mcp",
15
- version: "1.0.0",
17
+ version: "1.1.0",
16
18
  });
17
19
  this.collector = new LogCollector(projectRoot, logPaths);
18
20
  this.inspector = new ProcessInspector(projectRoot);
19
21
  this.interceptor = new RuntimeInterceptor(this.collector);
22
+ this.agentBridge = new AgentBridge(this.collector);
20
23
  this.setupTools();
21
24
  }
22
25
  static fromEnvironment() {
@@ -50,15 +53,14 @@ export class RuntimeLensMCPServer {
50
53
  framework: TailLogsParamsSchema.shape.framework,
51
54
  source: TailLogsParamsSchema.shape.source,
52
55
  },
53
- }, async (params) => {
54
- const logs = this.collector.getLogs(params);
55
- return {
56
- content: [{
57
- type: "text",
58
- text: JSON.stringify(logs, null, 2),
59
- }],
60
- };
61
- });
56
+ }, async (params) => ({
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: JSON.stringify(this.collector.getLogs(params), null, 2),
61
+ },
62
+ ],
63
+ }));
62
64
  }
63
65
  registerSearchLogs() {
64
66
  this.server.registerTool("search_logs", {
@@ -71,15 +73,14 @@ export class RuntimeLensMCPServer {
71
73
  limit: SearchLogsParamsSchema.shape.limit,
72
74
  since: SearchLogsParamsSchema.shape.since,
73
75
  },
74
- }, async (params) => {
75
- const logs = this.collector.searchLogs(params);
76
- return {
77
- content: [{
78
- type: "text",
79
- text: JSON.stringify(logs, null, 2),
80
- }],
81
- };
82
- });
76
+ }, async (params) => ({
77
+ content: [
78
+ {
79
+ type: "text",
80
+ text: JSON.stringify(this.collector.searchLogs(params), null, 2),
81
+ },
82
+ ],
83
+ }));
83
84
  }
84
85
  registerGetErrors() {
85
86
  this.server.registerTool("get_errors", {
@@ -90,15 +91,14 @@ export class RuntimeLensMCPServer {
90
91
  framework: GetErrorsParamsSchema.shape.framework,
91
92
  grouped: GetErrorsParamsSchema.shape.grouped,
92
93
  },
93
- }, async (params) => {
94
- const errors = this.collector.getErrors(params);
95
- return {
96
- content: [{
97
- type: "text",
98
- text: JSON.stringify(errors, null, 2),
99
- }],
100
- };
101
- });
94
+ }, async (params) => ({
95
+ content: [
96
+ {
97
+ type: "text",
98
+ text: JSON.stringify(this.collector.getErrors(params), null, 2),
99
+ },
100
+ ],
101
+ }));
102
102
  }
103
103
  registerInspectRequests() {
104
104
  this.server.registerTool("inspect_requests", {
@@ -111,15 +111,14 @@ export class RuntimeLensMCPServer {
111
111
  statusCode: InspectRequestParamsSchema.shape.statusCode,
112
112
  limit: InspectRequestParamsSchema.shape.limit,
113
113
  },
114
- }, async (params) => {
115
- const requests = this.collector.getRequests(params);
116
- return {
117
- content: [{
118
- type: "text",
119
- text: JSON.stringify(requests, null, 2),
120
- }],
121
- };
122
- });
114
+ }, async (params) => ({
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: JSON.stringify(this.collector.getRequests(params), null, 2),
119
+ },
120
+ ],
121
+ }));
123
122
  }
124
123
  registerGetPerformance() {
125
124
  this.server.registerTool("get_performance", {
@@ -132,12 +131,13 @@ export class RuntimeLensMCPServer {
132
131
  },
133
132
  }, async (params) => {
134
133
  await this.collector.collectFromProcess();
135
- const metrics = this.collector.getMetrics(params);
136
134
  return {
137
- content: [{
135
+ content: [
136
+ {
138
137
  type: "text",
139
- text: JSON.stringify(metrics, null, 2),
140
- }],
138
+ text: JSON.stringify(this.collector.getMetrics(params), null, 2),
139
+ },
140
+ ],
141
141
  };
142
142
  });
143
143
  }
@@ -146,15 +146,14 @@ export class RuntimeLensMCPServer {
146
146
  title: "Get Environment Info",
147
147
  description: "Get comprehensive environment information including running Node.js processes, listening ports, project framework detection, and system resources.",
148
148
  inputSchema: {},
149
- }, async () => {
150
- const info = await this.inspector.getEnvironmentInfo();
151
- return {
152
- content: [{
153
- type: "text",
154
- text: JSON.stringify(info, null, 2),
155
- }],
156
- };
157
- });
149
+ }, async () => ({
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: JSON.stringify(await this.inspector.getEnvironmentInfo(), null, 2),
154
+ },
155
+ ],
156
+ }));
158
157
  }
159
158
  registerClearLogs() {
160
159
  this.server.registerTool("clear_logs", {
@@ -164,10 +163,14 @@ export class RuntimeLensMCPServer {
164
163
  }, async () => {
165
164
  const result = this.collector.clearLogs();
166
165
  return {
167
- content: [{
166
+ content: [
167
+ {
168
168
  type: "text",
169
- text: JSON.stringify({ message: `Cleared ${result.cleared} entries` }),
170
- }],
169
+ text: JSON.stringify({
170
+ message: `Cleared ${result.cleared} entries`,
171
+ }),
172
+ },
173
+ ],
171
174
  };
172
175
  });
173
176
  }
@@ -176,15 +179,14 @@ export class RuntimeLensMCPServer {
176
179
  title: "Get Log Statistics",
177
180
  description: "Get statistics about collected logs including counts by level and framework.",
178
181
  inputSchema: {},
179
- }, async () => {
180
- const stats = this.collector.getStats();
181
- return {
182
- content: [{
183
- type: "text",
184
- text: JSON.stringify(stats, null, 2),
185
- }],
186
- };
187
- });
182
+ }, async () => ({
183
+ content: [
184
+ {
185
+ type: "text",
186
+ text: JSON.stringify(this.collector.getStats(), null, 2),
187
+ },
188
+ ],
189
+ }));
188
190
  }
189
191
  registerStartInterceptor() {
190
192
  this.server.registerTool("start_interceptor", {
@@ -194,10 +196,15 @@ export class RuntimeLensMCPServer {
194
196
  }, async () => {
195
197
  this.interceptor.startIntercepting();
196
198
  return {
197
- content: [{
199
+ content: [
200
+ {
198
201
  type: "text",
199
- text: JSON.stringify({ message: "Console interceptor started", active: true }),
200
- }],
202
+ text: JSON.stringify({
203
+ message: "Console interceptor started",
204
+ active: true,
205
+ }),
206
+ },
207
+ ],
201
208
  };
202
209
  });
203
210
  }
@@ -209,10 +216,15 @@ export class RuntimeLensMCPServer {
209
216
  }, async () => {
210
217
  this.interceptor.stopIntercepting();
211
218
  return {
212
- content: [{
219
+ content: [
220
+ {
213
221
  type: "text",
214
- text: JSON.stringify({ message: "Console interceptor stopped", active: false }),
215
- }],
222
+ text: JSON.stringify({
223
+ message: "Console interceptor stopped",
224
+ active: false,
225
+ }),
226
+ },
227
+ ],
216
228
  };
217
229
  });
218
230
  }
@@ -223,12 +235,16 @@ export class RuntimeLensMCPServer {
223
235
  inputSchema: {},
224
236
  }, async () => {
225
237
  await this.collector.collectFromFiles();
226
- const stats = this.collector.getStats();
227
238
  return {
228
- content: [{
239
+ content: [
240
+ {
229
241
  type: "text",
230
- text: JSON.stringify({ message: "Log collection complete", stats }),
231
- }],
242
+ text: JSON.stringify({
243
+ message: "Log collection complete",
244
+ stats: this.collector.getStats(),
245
+ }),
246
+ },
247
+ ],
232
248
  };
233
249
  });
234
250
  }
@@ -237,48 +253,46 @@ export class RuntimeLensMCPServer {
237
253
  title: "Scan Project Structure",
238
254
  description: "Analyze the project to detect framework (React/Next.js/NestJS), find log files, and list configuration files.",
239
255
  inputSchema: {},
240
- }, async () => {
241
- const structure = await this.collector.scanProjectStructure();
242
- return {
243
- content: [{
244
- type: "text",
245
- text: JSON.stringify(structure, null, 2),
246
- }],
247
- };
248
- });
256
+ }, async () => ({
257
+ content: [
258
+ {
259
+ type: "text",
260
+ text: JSON.stringify(await this.collector.scanProjectStructure(), null, 2),
261
+ },
262
+ ],
263
+ }));
249
264
  }
250
265
  registerFindProcesses() {
251
266
  this.server.registerTool("find_processes", {
252
267
  title: "Find Running Node Processes",
253
268
  description: "Find running Node.js processes related to React, Next.js, or NestJS applications.",
254
269
  inputSchema: {},
255
- }, async () => {
256
- const processes = await this.inspector.findRunningProcesses();
257
- return {
258
- content: [{
259
- type: "text",
260
- text: JSON.stringify(processes, null, 2),
261
- }],
262
- };
263
- });
270
+ }, async () => ({
271
+ content: [
272
+ {
273
+ type: "text",
274
+ text: JSON.stringify(await this.inspector.findRunningProcesses(), null, 2),
275
+ },
276
+ ],
277
+ }));
264
278
  }
265
279
  registerGetPorts() {
266
280
  this.server.registerTool("get_listening_ports", {
267
281
  title: "Get Listening Ports",
268
282
  description: "List all TCP ports currently being listened on by Node.js processes.",
269
283
  inputSchema: {},
270
- }, async () => {
271
- const ports = await this.inspector.getPortListeners();
272
- return {
273
- content: [{
274
- type: "text",
275
- text: JSON.stringify(ports, null, 2),
276
- }],
277
- };
278
- });
284
+ }, async () => ({
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: JSON.stringify(await this.inspector.getPortListeners(), null, 2),
289
+ },
290
+ ],
291
+ }));
279
292
  }
280
293
  async start() {
281
294
  try {
295
+ this.agentBridge.connect();
282
296
  const transport = new StdioServerTransport();
283
297
  await this.server.connect(transport);
284
298
  console.error("Runtime Lens MCP Server started successfully");
@@ -291,6 +305,7 @@ export class RuntimeLensMCPServer {
291
305
  setupGracefulShutdown() {
292
306
  const shutdown = async (signal) => {
293
307
  console.error(`Received ${signal}, shutting down gracefully...`);
308
+ this.agentBridge.disconnect();
294
309
  this.interceptor.stopIntercepting();
295
310
  process.exit(0);
296
311
  };