lensmcp 1.16.6 → 1.16.9

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.
@@ -33558,7 +33558,7 @@ var require_chrome_remote_interface = __commonJS({
33558
33558
  });
33559
33559
 
33560
33560
  // libs/browser-capture/src/capture-runner.ts
33561
- import { appendFileSync, readFileSync } from "node:fs";
33561
+ import { appendFileSync, readFileSync, renameSync, statSync } from "node:fs";
33562
33562
 
33563
33563
  // libs/visual-engine/dist/lib/diff.js
33564
33564
  var LAYOUT_TOLERANCE_PX = 0.5;
@@ -34709,6 +34709,21 @@ function safe(fn) {
34709
34709
  }
34710
34710
 
34711
34711
  // libs/browser-capture/src/capture-runner.ts
34712
+ var MAX_EVENT_BYTES = (() => {
34713
+ const n = Number(process.env["LENSMCP_EVENT_MAX_BYTES"]);
34714
+ return Number.isFinite(n) && n > 0 ? n : 256 * 1024 * 1024;
34715
+ })();
34716
+ var ROTATE_CHECK_BYTES = 1024 * 1024;
34717
+ var bytesSinceCheck = 0;
34718
+ function rotateIfLarge(file, lineBytes) {
34719
+ bytesSinceCheck += lineBytes;
34720
+ if (bytesSinceCheck < ROTATE_CHECK_BYTES) return;
34721
+ bytesSinceCheck = 0;
34722
+ try {
34723
+ if (statSync(file).size > MAX_EVENT_BYTES) renameSync(file, `${file}.1`);
34724
+ } catch {
34725
+ }
34726
+ }
34712
34727
  async function main() {
34713
34728
  const url = process.env["LENSMCP_DEV_URL"];
34714
34729
  const eventFile = process.env["LENSMCP_EVENT_FILE"];
@@ -34718,7 +34733,9 @@ async function main() {
34718
34733
  }
34719
34734
  const sink = eventFile ? (e) => {
34720
34735
  try {
34721
- appendFileSync(eventFile, JSON.stringify(e) + "\n");
34736
+ const line = JSON.stringify(e) + "\n";
34737
+ rotateIfLarge(eventFile, line.length);
34738
+ appendFileSync(eventFile, line);
34722
34739
  } catch {
34723
34740
  }
34724
34741
  } : (e) => {
@@ -19859,17 +19859,21 @@ function trimFlowEvent(event) {
19859
19859
  const toolCalls = Array.isArray(raw["toolCalls"]) ? raw["toolCalls"] : [];
19860
19860
  const tok = `${num(usage["promptTokens"]) ?? "?"}\u2192${num(usage["completionTokens"]) ?? "?"} tok`;
19861
19861
  const tools = toolCalls.length ? ` \xB7 ${toolCalls.length} tool call${toolCalls.length === 1 ? "" : "s"}` : "";
19862
- detail = `${model["provider"] ?? ""}/${model["model"] ?? ""} \xB7 ${tok}${tools}`;
19862
+ const latency = num(raw["durationMs"]) !== void 0 ? ` \xB7 ${(num(raw["durationMs"]) / 1e3).toFixed(1)}s` : "";
19863
+ detail = `${model["provider"] ?? ""}/${model["model"] ?? ""} \xB7 ${tok}${tools}${latency}`;
19863
19864
  } else if (kind === "ai-turn-start") {
19864
19865
  const tools = Array.isArray(raw["tools"]) ? raw["tools"] : [];
19865
19866
  detail = `skill ${raw["skill"] ?? ""} \xB7 ${raw["output"] ?? ""}${tools.length ? " \xB7 tools: " + tools.join(", ") : ""}`;
19866
19867
  } else if (kind === "ai-tool-call") {
19867
19868
  const call = raw["call"] ?? {};
19868
19869
  const result = raw["result"] ?? {};
19869
- detail = `${call["name"] ?? "tool"} ${result["error"] != null ? "\u2717 " + String(result["error"]) : "\u2713"}`;
19870
+ const took = num(raw["durationMs"]) !== void 0 ? ` \xB7 ${(num(raw["durationMs"]) / 1e3).toFixed(1)}s` : "";
19871
+ detail = `${call["name"] ?? "tool"} ${result["error"] != null ? "\u2717 " + String(result["error"]) : "\u2713"}${took}`;
19870
19872
  } else if (kind === "ai-turn-end") {
19871
19873
  const usage = raw["usage"] ?? {};
19872
- detail = `${raw["ok"] === false ? "FAILED" : "ok"} \xB7 ${num(usage["promptTokens"]) ?? "?"}+${num(usage["completionTokens"]) ?? "?"} tok`;
19874
+ const rounds = num(raw["rounds"]) !== void 0 ? ` \xB7 ${num(raw["rounds"])} round${num(raw["rounds"]) === 1 ? "" : "s"}` : "";
19875
+ const total = num(raw["durationMs"]) !== void 0 ? ` \xB7 ${(num(raw["durationMs"]) / 1e3).toFixed(1)}s` : "";
19876
+ detail = `${raw["ok"] === false ? "FAILED" : "ok"} \xB7 ${num(usage["promptTokens"]) ?? "?"}+${num(usage["completionTokens"]) ?? "?"} tok${rounds}${total}`;
19873
19877
  }
19874
19878
  }
19875
19879
  let sig;
@@ -21074,7 +21078,7 @@ var PAGE = `<!doctype html>
21074
21078
  var model = ai.model || {};
21075
21079
  meta('round ' + (ai.round != null ? ai.round : '?') + ' \xB7 ' + (model.provider || '') + '/' + (model.model || '') + (model.promptVersion ? ' \xB7 ' + model.promptVersion : ''));
21076
21080
  var u = ai.usage || {};
21077
- meta('tokens: ' + (u.promptTokens != null ? u.promptTokens : '?') + ' prompt \u2192 ' + (u.completionTokens != null ? u.completionTokens : '?') + ' completion' + (u.costCents != null ? ' \xB7 ' + u.costCents + '\xA2' : ''));
21081
+ meta('tokens: ' + (u.promptTokens != null ? u.promptTokens : '?') + ' prompt \u2192 ' + (u.completionTokens != null ? u.completionTokens : '?') + ' completion' + (u.costCents != null ? ' \xB7 ' + u.costCents + '\xA2' : '') + (ai.durationMs != null ? ' \xB7 ' + (ai.durationMs / 1000).toFixed(1) + 's LLM latency' : ''));
21078
21082
  var prompt = Array.isArray(ai.prompt) ? ai.prompt : [];
21079
21083
  label('Prompt \xB7 ' + prompt.length + ' message' + (prompt.length === 1 ? '' : 's'));
21080
21084
  prompt.forEach(function (m) {
@@ -21092,18 +21096,20 @@ var PAGE = `<!doctype html>
21092
21096
  if (Array.isArray(ai.capabilities) && ai.capabilities.length) meta('capabilities: ' + ai.capabilities.join(', '));
21093
21097
  meta('tenant: ' + (ai.tenantId || '\u2014') + ' \xB7 caller: ' + ((ai.caller && ai.caller.callerKind) || '\u2014') + (ai.caller && ai.caller.userId ? ' (' + ai.caller.userId + ')' : ''));
21094
21098
  if (Array.isArray(ai.tools) && ai.tools.length) { label('Tools \xB7 ' + ai.tools.length); block(ai.tools.join('\\n')); }
21099
+ if (ai.skillPlan != null) { label('Skill plan (converse)'); block(aiText(ai.skillPlan)); }
21100
+ if (ai.signals != null && String(ai.signals).length) { label('Live signals (the knowledge this turn caught)'); block(aiText(ai.signals)); }
21095
21101
  if (ai.systemPrompt != null) { label('System prompt' + (ai.promptVersion ? ' \xB7 ' + ai.promptVersion : '')); block(aiText(ai.systemPrompt)); }
21096
21102
  if (ai.input != null) { label('Input'); block(aiText(ai.input)); }
21097
21103
  } else if (kind === 'ai-tool-call') {
21098
21104
  var call = ai.call || {}; var result = ai.result || {};
21099
- meta('tool: ' + (call.name || '') + ' \xB7 round ' + (ai.round != null ? ai.round : '?'));
21105
+ meta('tool: ' + (call.name || '') + ' \xB7 round ' + (ai.round != null ? ai.round : '?') + (ai.durationMs != null ? ' \xB7 took ' + (ai.durationMs / 1000).toFixed(1) + 's' : ''));
21100
21106
  label('Input'); block(aiText(call.input));
21101
21107
  if (result.error != null) { label('Error'); block(aiText(result.error)); }
21102
21108
  else { label('Output'); block(aiText(result.output)); }
21103
21109
  } else if (kind === 'ai-turn-end') {
21104
21110
  meta((ai.ok === false ? 'FAILED' : 'ok') + ' \xB7 skill: ' + (ai.skill || ''));
21105
21111
  var ue = ai.usage || {};
21106
- meta('totals: ' + (ue.promptTokens != null ? ue.promptTokens : '?') + ' prompt + ' + (ue.completionTokens != null ? ue.completionTokens : '?') + ' completion' + (ue.costCents != null ? ' \xB7 ' + ue.costCents + '\xA2' : ''));
21112
+ meta('totals: ' + (ue.promptTokens != null ? ue.promptTokens : '?') + ' prompt + ' + (ue.completionTokens != null ? ue.completionTokens : '?') + ' completion' + (ue.costCents != null ? ' \xB7 ' + ue.costCents + '\xA2' : '') + (ai.rounds != null ? ' \xB7 ' + ai.rounds + ' round' + (ai.rounds === 1 ? '' : 's') : '') + (ai.durationMs != null ? ' \xB7 ' + (ai.durationMs / 1000).toFixed(1) + 's total' : ''));
21107
21113
  if (Array.isArray(ai.modelPins) && ai.modelPins.length) { label('Model pins \xB7 per round'); block(aiText(ai.modelPins)); }
21108
21114
  if (ai.output != null) { label('Output'); block(aiText(ai.output)); }
21109
21115
  if (ai.error != null) { label('Error'); block(aiText(ai.error)); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lensmcp",
3
- "version": "1.16.6",
3
+ "version": "1.16.9",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -2,7 +2,7 @@
2
2
  "name": "lensmcp",
3
3
  "displayName": "LensMCP",
4
4
  "description": "The observability lens for coding agents. One command brings up the dev cluster gateway (every project.json `cluster` decl → its host on :443), the per-project lens dashboard at https://lensmcp.local/<project>/, and the MCP server your agent connects to — scoped automatically to whatever project you opened Claude Code in.",
5
- "version": "1.16.6",
5
+ "version": "1.16.9",
6
6
  "author": {
7
7
  "name": "David Antoon",
8
8
  "email": "davidmantoon@gmail.com"
@@ -54,6 +54,12 @@ bootstrap stay available even while the gate is closed.
54
54
 
55
55
  4. Watch it as a human anytime with `/lensmcp:dashboard`.
56
56
 
57
+ **Reading `input-change` flows:** one flow = one EDITING BURST, not one keystroke — trusted typing on the
58
+ same element coalesces under a sliding ~2s window, and a PROGRAMMATIC value stream (an AI assistant
59
+ streaming text into an input — untrusted events) mints no flow at all: its effects attribute to the
60
+ interaction that triggered it (the "send" click's flow). If you expect per-keystroke granularity, look at
61
+ the events INSIDE the burst flow instead of counting flows.
62
+
57
63
  ## Tips
58
64
 
59
65
  - If a tool returns nothing, no events have been produced yet — start the gateway (or an