@lensmcp/core 1.22.3 → 1.22.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +1 -0
- package/index.js +1 -1
- package/lib/flow-shape.d.ts +100 -0
- package/lib/flow-shape.js +1 -0
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './lib/graph-store.js';
|
|
|
7
7
|
export * from './lib/fingerprint.js';
|
|
8
8
|
export * from './lib/reducer-registry.js';
|
|
9
9
|
export * from './lib/story.js';
|
|
10
|
+
export * from './lib/flow-shape.js';
|
|
10
11
|
export * from './lib/patterns.js';
|
|
11
12
|
export * from './lib/thresholds.js';
|
|
12
13
|
export * from './lib/graph-from-events.js';
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export*from"./lib/common.js";export*from"./lib/ulid.js";export*from"./lib/event-bus.js";export*from"./lib/event-redactor.js";export*from"./lib/resource-store.js";export*from"./lib/graph-store.js";export*from"./lib/fingerprint.js";export*from"./lib/reducer-registry.js";export*from"./lib/story.js";export*from"./lib/patterns.js";export*from"./lib/thresholds.js";export*from"./lib/graph-from-events.js";
|
|
1
|
+
"use strict";export*from"./lib/common.js";export*from"./lib/ulid.js";export*from"./lib/event-bus.js";export*from"./lib/event-redactor.js";export*from"./lib/resource-store.js";export*from"./lib/graph-store.js";export*from"./lib/fingerprint.js";export*from"./lib/reducer-registry.js";export*from"./lib/story.js";export*from"./lib/flow-shape.js";export*from"./lib/patterns.js";export*from"./lib/thresholds.js";export*from"./lib/graph-from-events.js";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type BaseEvent } from '@lensmcp/protocol-types';
|
|
2
|
+
/**
|
|
3
|
+
* Architectural area of one flow event — the swimlane it renders in, and a
|
|
4
|
+
* classification agents can reuse. Order mirrors the request's journey:
|
|
5
|
+
* browser → state → network → gateway → services → data.
|
|
6
|
+
*/
|
|
7
|
+
export type FlowArea = 'browser' | 'state' | 'network' | 'gateway' | 'services' | 'data' | 'ai';
|
|
8
|
+
export declare function areaOf(event: {
|
|
9
|
+
source: string;
|
|
10
|
+
category: string;
|
|
11
|
+
title: string;
|
|
12
|
+
kind?: string | undefined;
|
|
13
|
+
}): FlowArea;
|
|
14
|
+
/** One chart-ready node per flow event: area-typed, titled, with start/duration/payload. */
|
|
15
|
+
export interface FlowShapeOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Inline an AI turn's full `raw` payload — prompt messages, completion text, tool-call inputs and
|
|
18
|
+
* outputs. Off by default; `/api/flow` requires `?raw=1` AND a loopback-bound dashboard.
|
|
19
|
+
*/
|
|
20
|
+
includeRaw?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function trimFlowEvent(event: BaseEvent, opts?: FlowShapeOptions): {
|
|
23
|
+
steps?: string[] | undefined;
|
|
24
|
+
detail?: string | undefined;
|
|
25
|
+
ai?: Record<string, unknown> | undefined;
|
|
26
|
+
fetchStartedAt?: number | undefined;
|
|
27
|
+
durationMs?: number | undefined;
|
|
28
|
+
project?: string | undefined;
|
|
29
|
+
why?: string[] | undefined;
|
|
30
|
+
phase?: string | undefined;
|
|
31
|
+
component?: string | undefined;
|
|
32
|
+
commitId?: string | undefined;
|
|
33
|
+
parentRequestId?: string | undefined;
|
|
34
|
+
requestId?: string | undefined;
|
|
35
|
+
role?: string | undefined;
|
|
36
|
+
source: "nx" | "vite" | "typescript" | "eslint" | "rollup" | "client-runtime" | "chrome" | "react" | "valtio" | "nestjs" | "nextjs" | "db" | "redis" | "queue" | "memory" | "visual" | "perf" | "security" | "gateway" | "external" | "ai";
|
|
37
|
+
category: "db" | "memory" | "visual" | "security" | "ai" | "build" | "lint" | "typecheck" | "test" | "runtime" | "render" | "trace" | "state" | "network" | "backend" | "performance" | "deps" | "cluster";
|
|
38
|
+
severity: "error" | "debug" | "info" | "warning" | "fatal";
|
|
39
|
+
title: string;
|
|
40
|
+
kind: string | undefined;
|
|
41
|
+
area: FlowArea;
|
|
42
|
+
jobId?: string | undefined;
|
|
43
|
+
queue?: string | undefined;
|
|
44
|
+
urlKey?: string | undefined;
|
|
45
|
+
sig?: string | undefined;
|
|
46
|
+
id: string;
|
|
47
|
+
t: number;
|
|
48
|
+
start: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* The pure flow transform: raw correlated events → ordered, parented,
|
|
52
|
+
* aggregated display nodes. No I/O, no server — see module header.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildFlowDetail(rawEvents: BaseEvent[], opts?: FlowShapeOptions): {
|
|
55
|
+
events: ({
|
|
56
|
+
steps?: string[] | undefined;
|
|
57
|
+
detail?: string | undefined;
|
|
58
|
+
ai?: Record<string, unknown> | undefined;
|
|
59
|
+
fetchStartedAt?: number | undefined;
|
|
60
|
+
durationMs?: number | undefined;
|
|
61
|
+
project?: string | undefined;
|
|
62
|
+
why?: string[] | undefined;
|
|
63
|
+
phase?: string | undefined;
|
|
64
|
+
component?: string | undefined;
|
|
65
|
+
commitId?: string | undefined;
|
|
66
|
+
parentRequestId?: string | undefined;
|
|
67
|
+
requestId?: string | undefined;
|
|
68
|
+
role?: string | undefined;
|
|
69
|
+
source: "nx" | "vite" | "typescript" | "eslint" | "rollup" | "client-runtime" | "chrome" | "react" | "valtio" | "nestjs" | "nextjs" | "db" | "redis" | "queue" | "memory" | "visual" | "perf" | "security" | "gateway" | "external" | "ai";
|
|
70
|
+
category: "db" | "memory" | "visual" | "security" | "ai" | "build" | "lint" | "typecheck" | "test" | "runtime" | "render" | "trace" | "state" | "network" | "backend" | "performance" | "deps" | "cluster";
|
|
71
|
+
severity: "error" | "debug" | "info" | "warning" | "fatal";
|
|
72
|
+
title: string;
|
|
73
|
+
kind: string | undefined;
|
|
74
|
+
area: FlowArea;
|
|
75
|
+
jobId?: string | undefined;
|
|
76
|
+
queue?: string | undefined;
|
|
77
|
+
urlKey?: string | undefined;
|
|
78
|
+
sig?: string | undefined;
|
|
79
|
+
id: string;
|
|
80
|
+
t: number;
|
|
81
|
+
start: number;
|
|
82
|
+
} & {
|
|
83
|
+
parent?: string;
|
|
84
|
+
group?: string;
|
|
85
|
+
} & {
|
|
86
|
+
sig?: string;
|
|
87
|
+
count?: number;
|
|
88
|
+
parallel?: boolean;
|
|
89
|
+
avgMs?: number;
|
|
90
|
+
wallMs?: number;
|
|
91
|
+
items?: Array<{
|
|
92
|
+
start: number;
|
|
93
|
+
durationMs?: number;
|
|
94
|
+
}>;
|
|
95
|
+
selfMs?: number;
|
|
96
|
+
detail?: string;
|
|
97
|
+
/** Every event id this node stands for, so a collapsed node can be opened again. */
|
|
98
|
+
memberIds?: string[];
|
|
99
|
+
})[];
|
|
100
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var V=Object.defineProperty;var S=(i,y)=>V(i,"name",{value:y,configurable:!0});var X=Object.defineProperty,M=S((i,y)=>X(i,"name",{value:y,configurable:!0}),"I");import{redactDeep as Y,redactText as G}from"./redact.js";import{boundedClone as Z}from"@lensmcp/protocol-types";export function areaOf(i){const{source:y,category:e,title:$,kind:c}=i;return y==="ai"?"ai":c?.startsWith("memory")||c==="db-query"?"data":y==="gateway"||c==="gateway-request"?"gateway":c==="queue-process"||c==="queue-active"||c==="queue-completed"||c==="queue-failed"?"services":y==="db"||y==="redis"||y==="queue"||c==="redis-op"||c?.startsWith("queue-")?"data":y==="external"||c==="egress"?"network":y==="nestjs"||y==="nest"?/(?:Repository|Repo|Dao|Store)\./.test($)?"data":"services":y==="valtio"?"state":e==="network"?"network":"browser"}S(areaOf,"areaOf"),M(areaOf,"areaOf");const J=240,tt=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),et=new Set(["tenantId","caller","userId","accountId","email","subject"]),rt=8;function U(i){const y=W(i,0);return Z(Y({redacted:!0,...y}),{rawByteLimit:16*1024}).value}S(U,"X"),M(U,"aiProjection");function W(i,y){if(typeof i=="string")return _(i);if(i===null||typeof i!="object")return i;if(y>=rt)return;if(Array.isArray(i))return i.slice(0,32).map($=>W($,y+1));const e={};for(const[$,c]of Object.entries(i))if(!et.has($)){if(tt.has($)){typeof c=="string"?e[`${$}Chars`]=c.length:Array.isArray(c)?e[`${$}Count`]=c.length:c!=null&&(e[`${$}Present`]=!0);continue}e[$]=W(c,y+1)}return e}S(W,"G"),M(W,"projectAi");function _(i){return i.length<=J?G(i):`${G(i.slice(0,J))}\u2026`}S(_,"Z"),M(_,"clipText");export function trimFlowEvent(i,y={}){const e=i.raw??{},$=e.render??{},c=e.span??{},N=e.request??{},l=M(a=>typeof a=="number"?a:void 0,"num"),I=e.loop??{},B=l(e.durationMs)??l(c.durationMs)??l(N.durationMs)??l(I.durationMs)??l($.actualDurationMs),p=typeof e.kind=="string"?e.kind:void 0,E=p==="fetch-done"||p==="fetch-error",A=E?i.timestamp:l(e.startedAt)??l(c.startTime)??l(N.startedAt)??l(I.startedAt)??(B!==void 0?i.timestamp-B:i.timestamp);let k;if(typeof e.query=="string"){const a=Array.isArray(e.params)?` [${e.params.join(", ")}]`:"",g=typeof e.result=="string"?` \u2192 ${e.result}`:"";k=e.query+a+g}else if(typeof e.command=="string"){const a=typeof e.value=="string"?` \u2192 ${e.value}`:e.hit===!1?" \u2192 (miss)":"";k=e.command+a}else if(p==="state-update"){const a=e.update??{};let g="";try{g=JSON.stringify(a.preview)}catch{}k=`${a.storeId??""}.${a.path??""} = ${g}`}else p==="queue-completed"&&typeof e.returned=="string"?k=`returned ${e.returned}`:p==="queue-enqueued"&&(k=`${e.job??"job"}#${e.jobId??"?"} \u2192 ${e.queue??""}${typeof e.data=="string"?" "+e.data:""}`);let D;if(p==="gateway-request")D=`${e.host??""}${String(e.url??"").split("?")[0]}`;else if(p==="fetch-start"||p==="fetch-done"||p==="fetch-error")try{const a=new URL(String(e.href??e.url??""));D=`${a.hostname}${a.pathname}`}catch{}let R;if(p==="gateway-request"&&Array.isArray(e.steps))R=e.steps.map(a=>{const g=[String(a.step)];return a.project&&g.push(String(a.project)),a.prefix&&g.push(String(a.prefix)),a.mode&&g.push(String(a.mode)+(a.ok===!1?" \u2717":a.ok===!0?" \u2713":"")),a.caller&&g.push("by "+String(a.caller)),a.pod&&g.push(String(a.pod)),typeof a.atMs=="number"&&g.push(`@${a.atMs}ms`),g.join(" ")}),k=R.map(a=>a.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(p==="egress")k=`${e.method??"GET"} ${e.host??""} \u2192 ${e.status??"?"}`;else if(i.source==="ai"){if(p==="ai-round"){const a=e.model??{},g=e.usage??{},v=Array.isArray(e.toolCalls)?e.toolCalls:[],P=`${l(g.promptTokens)??"?"}\u2192${l(g.completionTokens)??"?"} tok`,t=v.length?` \xB7 ${v.length} tool call${v.length===1?"":"s"}`:"",s=l(e.durationMs)!==void 0?` \xB7 ${(l(e.durationMs)/1e3).toFixed(1)}s`:"";k=`${a.provider??""}/${a.model??""} \xB7 ${P}${t}${s}`}else if(p==="ai-turn-start"){const a=Array.isArray(e.tools)?e.tools:[];k=`skill ${e.skill??""} \xB7 ${e.output??""}${a.length?" \xB7 tools: "+a.join(", "):""}`}else if(p==="ai-tool-call"){const a=e.call??{},g=e.result??{},v=l(e.durationMs)!==void 0?` \xB7 ${(l(e.durationMs)/1e3).toFixed(1)}s`:"";k=`${a.name??"tool"} ${g.error!=null?"\u2717 "+String(g.error):"\u2713"}${v}`}else if(p==="ai-turn-end"){const a=e.usage??{},g=l(e.rounds)!==void 0?` \xB7 ${l(e.rounds)} round${l(e.rounds)===1?"":"s"}`:"",v=l(e.durationMs)!==void 0?` \xB7 ${(l(e.durationMs)/1e3).toFixed(1)}s`:"";k=`${e.ok===!1?"FAILED":"ok"} \xB7 ${l(a.promptTokens)??"?"}+${l(a.completionTokens)??"?"} tok${g}${v}`}}let b;p==="db-query"&&typeof e.query=="string"?b=e.query:p==="redis-op"?b=`${e.op??""} ${String(e.key??"").replace(/\d+/g,"#")}`:p==="egress"?b=`${e.method??"GET"} ${e.host??""}`:p==="queue-enqueued"?b=`enqueue ${e.queue??""}`:p==="span"&&typeof c.name=="string"&&(b=c.name);const x=i.context??{},O=e.effect??{},C=$.commitId??O.commitId??e.commitId,m=Array.isArray($.why)?$.why.map(a=>typeof a?.type=="string"?a.type:void 0).filter(a=>!!a):[];return{id:i.id,t:i.timestamp,start:A,...b?{sig:b}:{},...D?{urlKey:D}:{},...typeof e.queue=="string"?{queue:e.queue}:{},...e.jobId!=null?{jobId:String(e.jobId)}:{},source:i.source,category:i.category,severity:i.severity,title:i.title,kind:p,area:areaOf({source:i.source,category:i.category,title:i.title,kind:p}),...typeof c.role=="string"?{role:c.role}:{},...typeof x.requestId=="string"?{requestId:x.requestId}:{},...typeof x.parentRequestId=="string"?{parentRequestId:x.parentRequestId}:{},...typeof C=="string"?{commitId:C}:{},...typeof $.componentName=="string"?{component:$.componentName}:{},...typeof $.phase=="string"?{phase:$.phase}:{},...m.length?{why:m}:{},...typeof x.projectName=="string"?{project:x.projectName}:typeof e.project=="string"?{project:e.project}:{},...B!==void 0?{durationMs:B}:{},...E&&l(e.startedAt)!==void 0?{fetchStartedAt:l(e.startedAt)}:{},...i.source==="ai"?{ai:y.includeRaw?e:U(e)}:{},...k?{detail:k}:{},...R?{steps:R}:{}}}S(trimFlowEvent,"trimFlowEvent"),M(trimFlowEvent,"trimFlowEvent");function H(i){return i==="flow-origin"?0:i?.endsWith("-start")?1:i==="gateway-request"?2:i==="server-request"?3:i==="span"?4:5}S(H,"tt"),M(H,"kindRank");function F(i){return i.kind==="span"&&i.role==="controller"?3.5:i.kind==="queue-process"?3:H(i.kind)}S(F,"T"),M(F,"causalRank");export function buildFlowDetail(i,y={}){const e=i.slice().filter(t=>{const s=t.raw??{},n=typeof s.kind=="string"?s.kind:"";if(n==="subscription-added"||n==="subscription-removed"||n==="hook-run"||n==="store-created"||n==="singleton-instance")return!1;const r=s.span;return!(typeof r?.name=="string"&&r.name.startsWith("nest.request "))}).map(t=>trimFlowEvent(t,y)),$=new Set;for(let t=e.length-1;t>=0;t--)$.has(e[t].id)?e.splice(t,1):$.add(e[t].id);const c=new Map;for(const t of e)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&!c.has(t.requestId)&&c.set(t.requestId,t.start);const N=M(t=>t.source!=="react"&&t.source!=="valtio"&&t.requestId&&c.has(t.requestId)?c.get(t.requestId):t.start,"anchorOf");e.sort((t,s)=>N(t)-N(s)||t.start-s.start||F(t)-F(s)||(s.durationMs??0)-(t.durationMs??0)||t.t-s.t);const l=M(t=>(t.kind==="span"||t.kind==="server-request"||t.kind==="gateway-request"||t.kind==="queue-process")&&(t.durationMs??0)>0,"spanLike"),I=e;for(const t of I)t.group=t.source==="react"||t.source==="valtio"||t.source==="client-runtime"||t.source==="visual"?"browser":"server";const B=new Map;for(const t of I)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&t.project&&B.set(t.requestId,t.project);for(const t of I)if(!t.project&&t.source==="nestjs"&&t.requestId){const s=B.get(t.requestId);s&&(t.project=s)}for(const t of I){let s;const n=t.requestId;for(const r of I){if(r===t||!l(r)||r.group!==t.group||r.requestId!==n)continue;const o=r.project,d=t.project;if(r.kind!=="gateway-request"&&t.kind!=="gateway-request"&&o!==void 0&&d!==void 0&&o!==d)continue;const q=r.durationMs??0,h=t.durationMs??0;r.start<=t.start&&r.start+q>t.start&&(r.start<t.start||q>h||q===h&&F(r)<F(t))&&(!s||r.start>s.start||r.start===s.start&&(r.durationMs??0)<(s.durationMs??0)||r.start===s.start&&(r.durationMs??0)===(s.durationMs??0)&&F(r)>F(s))&&(s=r)}s&&(t.parent=s.id)}const p=new Map;for(const t of I){if(!t.requestId)continue;const s=p.get(t.requestId);s?s.push(t):p.set(t.requestId,[t])}const E=M((t,s)=>{const n=(p.get(t)??[]).filter(r=>l(r)&&r.start<=s&&r.start+(r.durationMs??0)>=s);if(n.length!==0)return n.sort((r,o)=>o.start-r.start||(r.durationMs??0)-(o.durationMs??0)),n[0]},"callerNodeFor");for(const t of I){if(!t.parentRequestId||t.kind!=="server-request")continue;const s=E(t.parentRequestId,t.start);s&&s!==t&&s.start<=t.start&&(t.parent=s.id)}const A=I,k=new Map;for(const t of A)t.kind==="gateway-request"&&t.requestId&&!k.has(t.requestId)&&k.set(t.requestId,t);for(const t of A)if(t.group==="server"&&!t.parent&&t.requestId&&t.kind!=="gateway-request"){const s=k.get(t.requestId);s&&s!==t&&s.start<=t.start&&(t.parent=s.id)}const D=new Set,R=new Set,b=[];for(const t of A){if(t.kind!=="gateway-request")continue;if(!t.requestId){b.push(t);continue}const s=p.get(t.requestId)??[];if(s.filter(o=>o.kind==="gateway-request").sort((o,d)=>o.start-d.start)[0]!==t)continue;const n=s.find(o=>o.kind==="fetch-start"),r=s.find(o=>o.kind==="fetch-done"||o.kind==="fetch-error");if(!n&&!r){b.push(t);continue}n&&(t.fetchStartId=n.id,D.add(n.id)),r&&(t.fetchDoneId=r.id,R.add(r.id))}const x=new Map;for(const t of A){if(!t.urlKey)continue;const s=x.get(t.urlKey)??{gws:[],starts:[],dones:[]};t.kind==="gateway-request"?b.includes(t)&&s.gws.push(t):t.kind==="fetch-start"?D.has(t.id)||s.starts.push(t):(t.kind==="fetch-done"||t.kind==="fetch-error")&&(R.has(t.id)||s.dones.push(t)),x.set(t.urlKey,s)}for(const{gws:t,starts:s,dones:n}of x.values()){t.sort((o,d)=>o.start-d.start),s.sort((o,d)=>o.start-d.start);const r=new Set;t.forEach((o,d)=>{const q=s[d];q&&(o.fetchStartId=q.id);const h=q?q.t:o.start;let w,u=1/0;for(const j of n){if(r.has(j.id))continue;const z=j.fetchStartedAt??j.start-(j.durationMs??0),K=Math.abs(z-h);K<u&&(u=K,w=j)}w&&(o.fetchDoneId=w.id,r.add(w.id))})}const O=new Map,C=new Map;for(const t of A)!t.queue||!t.jobId||(t.kind==="queue-enqueued"&&O.set(`${t.queue}#${t.jobId}`,t),t.kind==="queue-process"&&C.set(`${t.queue}#${t.jobId}`,t));for(const t of A){if(!t.queue||!t.jobId)continue;const s=`${t.queue}#${t.jobId}`;if(t.kind==="queue-process"&&!t.parent){const n=O.get(s);n&&n!==t&&n.start<=t.start&&(t.parent=n.id)}else if(t.kind==="queue-active"||t.kind==="queue-completed"||t.kind==="queue-failed"){const n=C.get(s);n&&n!==t&&(t.parent=n.id)}}let m=I;{const t=new Map;for(const n of m)n.kind==="fetch-start"&&t.set(n.id,n);const s=new Map;for(const n of m){if(n.kind!=="fetch-done"&&n.kind!=="fetch-error")continue;const r=[...t.values()].find(q=>q.requestId&&q.requestId===n.requestId)?.id,o=r?t.get(r):void 0;if(!o)continue;const d=n.fetchStartedAt??o.start;o.title=n.title,o.severity=n.severity,o.durationMs=n.durationMs??Math.max(0,n.t-d),o.kind="fetch",n.detail&&!o.detail&&(o.detail=n.detail),s.set(n.id,o.id)}if(s.size>0){m=m.filter(n=>!s.has(n.id));for(const n of m)for(n.fetchDoneId&&s.has(n.fetchDoneId)&&(n.fetchDoneId=s.get(n.fetchDoneId));n.parent&&s.has(n.parent);)n.parent=s.get(n.parent)}}const a=M(t=>!!t.commitId&&(t.kind==="render"||t.kind==="effect-run"),"commitMember"),g=[],v=new Map;for(let t=0;t<m.length;){const s=m[t];if(!a(s)){g.push(s),t+=1;continue}let n=t+1;for(;n<m.length;){const f=m[n];if(!a(f)||f.commitId!==s.commitId)break;n+=1}const r=m.slice(t,n);if(t=n,r.length<2){g.push(...r);continue}const o=r.filter(f=>f.kind==="render"),d=r.filter(f=>f.kind==="effect-run"),q=o.filter(f=>!(f.why??[]).includes("parent-render")),h=[...new Set(q.flatMap(f=>f.why??[]))],w=[...new Set(q.map(f=>f.component).filter(Boolean))],u=[...new Set(o.map(f=>f.component).filter(Boolean))],j=Math.min(...r.map(f=>f.start)),z=Math.max(...r.map(f=>f.start+(f.durationMs??0))),K=w.length===1?w[0]:w.length>1?`${w.length} roots`:u[0]??"view",L=h.length===1?h[0]:h.length>1?h.join(" + "):void 0,Q=o.some(f=>f.phase==="mount"),T={...s,kind:"view-update",title:`view update \xB7 ${K}${L?` \u2190 ${L}`:""}`,start:j,durationMs:z-j,commitId:s.commitId,cause:L,components:u,effects:d.length,memberIds:r.map(f=>f.id),sig:`commit:${L??"-"}:${w.join(",")}:${u.slice().sort().join(",")}`,detail:[`${u.length} component${u.length===1?"":"s"}${Q?" (mount)":""}`,d.length?`${d.length} effect${d.length===1?"":"s"}`:"",u.join(", ")].filter(Boolean).join(" \xB7 "),severity:r.some(f=>f.severity==="error")?"error":s.severity};delete T.component,delete T.why,delete T.phase;for(const f of r)f.id!==T.id&&v.set(f.id,T.id);g.push(T)}if(v.size>0){m=g;for(const t of m)for(;t.parent&&v.has(t.parent);)t.parent=v.get(t.parent)}for(let t=1;t<m.length;t++){const s=m[t-1],n=m[t];n.kind!=="view-update"||s.kind!=="view-update"||n.sig&&n.sig===s.sig&&(s.redundant=!0,n.redundant=!0)}const P=M(t=>{const s=new Map;for(const r of m){if(!r.sig||l(r)!==t||r.kind==="server-request"||r.kind==="gateway-request")continue;const o=`${r.parent??"root"}|${r.kind}|${r.sig}`,d=s.get(o);d?d.push(r):s.set(o,[r])}const n=new Map;for(const r of s.values()){if(r.length<3)continue;r.sort((u,j)=>u.start-j.start);const o=r[0];let d=!1;for(let u=0;u+1<r.length;u++)if(r[u+1].start<r[u].start+(r[u].durationMs??0)){d=!0;break}const q=o.start,h=Math.max(...r.map(u=>u.start+(u.durationMs??0))),w=r.reduce((u,j)=>u+(j.durationMs??0),0);if(o.count=r.length,o.parallel=d,o.avgMs=Math.round(w/r.length*10)/10,o.wallMs=h-q,o.durationMs=h-q,o.title=`\xD7${r.length} ${o.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,o.kind==="view-update"){const u=o.redundant===!0;o.detail=[`${r.length} commits \xB7 avg ${o.avgMs}ms \xB7 wall ${o.wallMs}ms`,u?`no state change between them \u2014 ${r.length-1} of these had nothing new to render`:"one per update \u2014 expected for this many changes",o.components?.join(", ")??""].filter(Boolean).join(" \xB7 ")}else o.detail=`${o.sig} \xD7${r.length} ${d?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${o.avgMs}ms \xB7 wall ${o.wallMs}ms`;o.items=r.slice(0,12).map(u=>({start:u.start-q,...u.durationMs!=null?{durationMs:u.durationMs}:{}})),o.memberIds=r.flatMap(u=>u.memberIds??[u.id]),r.some(u=>u.severity==="error")&&(o.severity="error");for(const u of r.slice(1))n.set(u.id,o.id)}if(n.size!==0){m=m.filter(r=>!n.has(r.id));for(const r of m)for(;r.parent&&n.has(r.parent);)r.parent=n.get(r.parent)}},"aggregatePass");P(!0),P(!1);for(const t of m){if(!l(t))continue;const s=t.durationMs??0;if(s<40)continue;const n=m.filter(h=>h.parent===t.id&&(h.durationMs??0)>0).map(h=>[h.start,h.start+(h.durationMs??0)]).sort((h,w)=>h[0]-w[0]);let r=0,o=-1,d=-1;for(const[h,w]of n)h>d?(d>o&&(r+=d-o),o=h,d=w):w>d&&(d=w);d>o&&(r+=d-o);const q=Math.max(0,s-r);(q>=50||q/s>=.7&&s>=40)&&(t.selfMs=q,t.detail=`\u26A0 cpu-heavy: ${q}ms self-time of ${s}ms${t.detail?" \xB7 "+t.detail:""}`)}return{events:m}}S(buildFlowDetail,"buildFlowDetail"),M(buildFlowDetail,"buildFlowDetail");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/core",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@lensmcp/protocol-types": "1.22.
|
|
22
|
+
"@lensmcp/protocol-types": "1.22.5",
|
|
23
23
|
"tslib": "^2.3.0"
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|