@lensmcp/core 1.24.4 → 1.24.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.
@@ -26,6 +26,7 @@ export declare function trimFlowEvent(event: BaseEvent, opts?: FlowShapeOptions)
26
26
  fetchStartedAt?: number | undefined;
27
27
  durationMs?: number | undefined;
28
28
  project?: string | undefined;
29
+ renderWalkStoppedAt?: number | undefined;
29
30
  renderTotal?: number | undefined;
30
31
  renderPublished?: number | undefined;
31
32
  cleanup?: boolean | undefined;
@@ -81,6 +82,7 @@ export declare function buildFlowDetail(rawEvents: BaseEvent[], opts?: FlowShape
81
82
  fetchStartedAt?: number | undefined;
82
83
  durationMs?: number | undefined;
83
84
  project?: string | undefined;
85
+ renderWalkStoppedAt?: number | undefined;
84
86
  renderTotal?: number | undefined;
85
87
  renderPublished?: number | undefined;
86
88
  cleanup?: boolean | undefined;
package/lib/flow-shape.js CHANGED
@@ -1 +1 @@
1
- "use strict";var yt=Object.defineProperty;var R=(d,v)=>yt(d,"name",{value:v,configurable:!0});var kt=Object.defineProperty,y=R((d,v)=>kt(d,"name",{value:v,configurable:!0}),"$");import{redactDeep as Mt,redactText as rt}from"./redact.js";import{SQL_ACCOUNT_KIND as wt,sqlAccountingOf as vt}from"./flow-segments.js";import{boundedClone as qt}from"@lensmcp/protocol-types";export function areaOf(d){const{source:v,category:n,title:M,kind:m}=d;return v==="ai"?"ai":m?.startsWith("memory")||m==="db-query"?"data":v==="gateway"||m==="gateway-request"?"gateway":m==="queue-process"||m==="queue-active"||m==="queue-completed"||m==="queue-failed"?"services":v==="db"||v==="redis"||v==="queue"||m==="redis-op"||m?.startsWith("queue-")?"data":v==="external"||m==="egress"?"network":v==="nestjs"||v==="nest"?/(?:Repository|Repo|Dao|Store)\./.test(M)?"data":"services":v==="valtio"?"state":n==="network"?"network":"browser"}R(areaOf,"areaOf"),y(areaOf,"areaOf");const ct=240,It=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),xt=new Set(["tenantId","caller","userId","accountId","email","subject"]),bt=8;function lt(d){const v=tt(d,0);return qt(Mt({redacted:!0,...v}),{rawByteLimit:16*1024}).value}R(lt,"It"),y(lt,"aiProjection");function tt(d,v){if(typeof d=="string")return ft(d);if(d===null||typeof d!="object")return d;if(v>=bt)return;if(Array.isArray(d))return d.slice(0,32).map(M=>tt(M,v+1));const n={};for(const[M,m]of Object.entries(d))if(!xt.has(M)){if(It.has(M)){typeof m=="string"?n[`${M}Chars`]=m.length:Array.isArray(m)?n[`${M}Count`]=m.length:m!=null&&(n[`${M}Present`]=!0);continue}n[M]=tt(m,v+1)}return n}R(tt,"ot"),y(tt,"projectAi");function ft(d){return d.length<=ct?rt(d):`${rt(d.slice(0,ct))}\u2026`}R(ft,"qt"),y(ft,"clipText");export function trimFlowEvent(d,v={}){const n=d.raw??{},M=n.render??{},m=n.span??{},C=n.request??{},p=y(a=>typeof a=="number"?a:void 0,"num"),O=n.loop??{},b=n.effect??{},T=p(n.durationMs)??p(m.durationMs)??p(C.durationMs)??p(O.durationMs)??p(M.actualDurationMs)??p(b.durationMs),g=typeof n.kind=="string"?n.kind:void 0,F=g==="fetch-done"||g==="fetch-error",X=p(M.commitTime),et=g==="render"&&X!==void 0&&Math.abs(X-d.timestamp)<6e4,P=F?d.timestamp:et?X:p(n.startedAt)??p(m.startTime)??p(C.startedAt)??p(O.startedAt)??(T!==void 0?d.timestamp-T:d.timestamp);let I;if(typeof n.query=="string"){const a=Array.isArray(n.params)?` [${n.params.join(", ")}]`:"",h=typeof n.result=="string"?` \u2192 ${n.result}`:"";I=n.query+a+h}else if(typeof n.command=="string"){const a=typeof n.value=="string"?` \u2192 ${n.value}`:n.hit===!1?" \u2192 (miss)":"";I=n.command+a}else if(g==="state-update"){const a=n.update??{};let h="";try{h=JSON.stringify(a.preview)}catch{}I=`${a.storeId??""}.${a.path??""} = ${h}`}else if(g==="queue-completed"&&typeof n.returned=="string")I=`returned ${n.returned}`;else if(g==="queue-enqueued")I=`${n.job??"job"}#${n.jobId??"?"} \u2192 ${n.queue??""}${typeof n.data=="string"?" "+n.data:""}`;else if(g==="log"){const a=C.error??{},h=typeof a.stack=="string"?a.stack:typeof n.text=="string"?n.text:void 0;h&&h!==d.title&&(I=h)}let N,U,L,E;if(g==="span"){const a=m.outcome;if(N=a==="threw"||a==="returned"?a:m.status==="error"?"threw":m.status==="ok"?"returned":void 0,N==="threw"){const A=m.error??{},S=typeof A.name=="string"?A.name:void 0,V=typeof A.message=="string"?A.message:typeof d.message=="string"?d.message:void 0;L=S,U=rt([S,V].filter(Boolean).join(": "))||void 0}const h=typeof m.args=="string"?m.args:void 0,B=typeof m.result=="string"?m.result:void 0;if(h!==void 0||B!==void 0){E=[...h!==void 0?["args"]:[],...B!==void 0?["result"]:[]];const A=y(S=>S.length>pt?`${S.slice(0,pt)}\u2026`:S,"short");I=[h!==void 0?`args ${A(h)}`:"",B!==void 0?`returned ${A(B)}`:""].filter(Boolean).join(" \u2192 ")}}let K;if(g==="gateway-request")K=`${n.host??""}${String(n.url??"").split("?")[0]}`;else if(g==="fetch-start"||g==="fetch-done"||g==="fetch-error")try{const a=new URL(String(n.href??n.url??""));K=`${a.hostname}${a.pathname}`}catch{}let _;if(g==="gateway-request"&&Array.isArray(n.steps))_=n.steps.map(a=>{const h=[String(a.step)];return a.project&&h.push(String(a.project)),a.prefix&&h.push(String(a.prefix)),a.mode&&h.push(String(a.mode)+(a.ok===!1?" \u2717":a.ok===!0?" \u2713":"")),a.caller&&h.push("by "+String(a.caller)),a.pod&&h.push(String(a.pod)),typeof a.atMs=="number"&&h.push(`@${a.atMs}ms`),h.join(" ")}),I=_.map(a=>a.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(g==="egress")I=`${n.method??"GET"} ${n.host??""} \u2192 ${n.status??"?"}`;else if(d.source==="ai"){if(g==="ai-call"){const a=n.usage??{},h=a.promptTokens!==void 0||a.completionTokens!==void 0?` \xB7 ${p(a.promptTokens)??"?"}\u2192${p(a.completionTokens)??"?"} tok`:"",B=n.status!==void 0?` \xB7 ${String(n.status)}`:n.error?" \xB7 failed":"",A=p(n.toolCallCount)?` \xB7 ${p(n.toolCallCount)} tool call${p(n.toolCallCount)===1?"":"s"}`:"",S=p(n.durationMs)!==void 0?` \xB7 ${(p(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${n.provider??""}/${n.model??"?"}${h}${B}${A}${S}${n.stream===!0?" \xB7 stream":""}`}else if(g==="ai-round"){const a=n.model??{},h=n.usage??{},B=Array.isArray(n.toolCalls)?n.toolCalls:[],A=`${p(h.promptTokens)??"?"}\u2192${p(h.completionTokens)??"?"} tok`,S=B.length?` \xB7 ${B.length} tool call${B.length===1?"":"s"}`:"",V=p(n.durationMs)!==void 0?` \xB7 ${(p(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${a.provider??""}/${a.model??""} \xB7 ${A}${S}${V}`}else if(g==="ai-turn-start"){const a=Array.isArray(n.tools)?n.tools:[];I=`skill ${n.skill??""} \xB7 ${n.output??""}${a.length?" \xB7 tools: "+a.join(", "):""}`}else if(g==="ai-tool-call"){const a=n.call??{},h=n.result??{},B=p(n.durationMs)!==void 0?` \xB7 ${(p(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${a.name??"tool"} ${h.error!=null?"\u2717 "+String(h.error):"\u2713"}${B}`}else if(g==="ai-turn-end"){const a=n.usage??{},h=p(n.rounds)!==void 0?` \xB7 ${p(n.rounds)} round${p(n.rounds)===1?"":"s"}`:"",B=p(n.durationMs)!==void 0?` \xB7 ${(p(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${n.ok===!1?"FAILED":"ok"} \xB7 ${p(a.promptTokens)??"?"}+${p(a.completionTokens)??"?"} tok${h}${B}`}}let f;g==="db-query"&&typeof n.query=="string"?f=n.query:g==="redis-op"?f=`${n.op??""} ${String(n.key??"").replace(/\d+/g,"#")}`:g==="egress"?f=`${n.method??"GET"} ${n.host??""}`:g==="ai-call"?f=`ai ${n.provider??""} ${n.model??""} ${n.api??""}`:g==="queue-enqueued"?f=`enqueue ${n.queue??""}`:g==="span"&&typeof m.name=="string"?f=m.name:g==="memory-mutation"&&(f=d.title);const D=d.context??{},W=M.commitId??b.commitId??n.commitId,G=Array.isArray(M.why)?M.why.map(a=>typeof a?.type=="string"?a.type:void 0).filter(a=>!!a):[];return{id:d.id,t:d.timestamp,start:P,...f?{sig:f}:{},...K?{urlKey:K}:{},...typeof n.queue=="string"?{queue:n.queue}:{},...n.jobId!=null?{jobId:String(n.jobId)}:{},source:d.source,category:d.category,severity:d.severity,title:N==="threw"&&typeof m.name=="string"?`${m.name} \u2014 threw${L?` ${L}`:""}${T!==void 0?` after ${T}ms`:""}`:d.title,kind:g,area:areaOf({source:d.source,category:d.category,title:d.title,kind:g}),...N?{outcome:N}:{},...U?{error:U}:{},...E?{captured:E}:{},...typeof m.role=="string"?{role:m.role}:{},...g==="log"&&typeof n.level=="string"?{level:n.level}:{},...g==="log"&&typeof n.logger=="string"?{logger:n.logger}:{},...g==="log"&&typeof n.stream=="string"?{stream:n.stream}:{},...typeof D.requestId=="string"?{requestId:D.requestId}:{},...typeof D.parentRequestId=="string"?{parentRequestId:D.parentRequestId}:{},...typeof W=="string"?{commitId:W}:{},...typeof M.componentName=="string"?{component:M.componentName}:{},...typeof M.phase=="string"?{phase:M.phase}:{},...G.length?{why:G}:{},...g==="effect-run"&&typeof b.hookLogicalId=="string"?{hook:b.hookLogicalId}:{},...g==="effect-run"&&b.cleanupRan===!0?{cleanup:!0}:{},...g==="render-commit-truncated"?{renderTotal:p(n.total),renderPublished:p(n.published)}:{},...typeof D.projectName=="string"?{project:D.projectName}:typeof n.project=="string"?{project:n.project}:{},...T!==void 0?{durationMs:T}:{},...F&&p(n.startedAt)!==void 0?{fetchStartedAt:p(n.startedAt)}:{},...d.source==="ai"?{ai:v.includeRaw?n:lt(n)}:{},...I?{detail:I}:{},..._?{steps:_}:{}}}R(trimFlowEvent,"trimFlowEvent"),y(trimFlowEvent,"trimFlowEvent");const pt=300;export const OUTLIVED_PARENT_MIN_MS=250;const jt=new Set(["egress","db-query","redis-op","ai-call","span","gateway-request","server-request"]),mt=1;function gt(d){return d==="flow-origin"?0:d?.endsWith("-start")?1:d==="gateway-request"?2:d==="server-request"?3:d==="span"?4:d==="render"||d==="render-commit-truncated"?6:d==="effect-run"?7:5}R(gt,"jt"),y(gt,"kindRank");function J(d){return d.kind==="span"&&d.role==="controller"?3.5:d.kind==="queue-process"?3:gt(d.kind)}R(J,"Z"),y(J,"causalRank");export function buildFlowDetail(d,v={}){const n=vt(d),M=d.slice().filter(t=>{const e=t.raw??{},r=typeof e.kind=="string"?e.kind:"";if(r==="subscription-added"||r==="subscription-removed"||r==="hook-run"||r==="store-created"||r==="singleton-instance"||r===wt)return!1;const o=e.span;return!(typeof o?.name=="string"&&o.name.startsWith("nest.request "))}).map(t=>trimFlowEvent(t,v)),m=new Set;for(let t=M.length-1;t>=0;t--)m.has(M[t].id)?M.splice(t,1):m.add(M[t].id);const C=new Map;for(const t of M)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&!C.has(t.requestId)&&C.set(t.requestId,t.start);const p=y(t=>t.source!=="react"&&t.source!=="valtio"&&t.requestId&&C.has(t.requestId)?C.get(t.requestId):t.start,"anchorOf");M.sort((t,e)=>p(t)-p(e)||t.start-e.start||J(t)-J(e)||(e.durationMs??0)-(t.durationMs??0)||t.t-e.t);const O=y(t=>(t.kind==="span"||t.kind==="server-request"||t.kind==="gateway-request"||t.kind==="queue-process")&&(t.durationMs??0)>0,"spanLike"),b=M;for(const t of b)t.group=t.source==="react"||t.source==="valtio"||t.source==="client-runtime"||t.source==="visual"?"browser":"server";const T=new Map;for(const t of b)if((t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&t.project){const e=T.get(t.requestId)??[];e.push({project:t.project,start:t.start,end:t.start+(t.durationMs??0)}),T.set(t.requestId,e)}const g=y((t,e)=>{const r=T.get(t);if(r?.length)return r.every(o=>o.project===r[0].project)?r[0].project:r.filter(o=>o.start<=e+1&&o.end>=e-1).sort((o,s)=>s.start-o.start)[0]?.project},"projectOf");for(const t of b)if(!t.project&&t.source==="nestjs"&&t.requestId){const e=g(t.requestId,t.start);e&&(t.project=e)}for(const t of b){let e;const r=t.requestId;for(const o of b){if(o===t||!O(o)||o.group!==t.group||o.requestId!==r)continue;const s=o.project,c=t.project;if(o.kind!=="gateway-request"&&t.kind!=="gateway-request"&&s!==void 0&&c!==void 0&&s!==c)continue;const $=o.durationMs??0,k=t.durationMs??0,i=Math.abs(o.start-t.start)<=mt,u=J(o),l=J(t),w=o.start<=t.start;if(!(o.start+$>t.start&&(w||i&&u<l)&&(!i||(u!==l?u<l:w&&$>k))))continue;const j=e?J(e):-1,q=e?Math.abs(o.start-e.start)<=mt:!1;(!e||!q&&o.start>e.start||q&&u>j||q&&u===j&&(o.durationMs??0)<(e.durationMs??0))&&(e=o)}e&&(t.parent=e.id)}const F=new Map;for(const t of b){if(!t.requestId)continue;const e=F.get(t.requestId);e?e.push(t):F.set(t.requestId,[t])}const X=new Map(b.map(t=>[t.id,t])),et=y((t,e)=>{const r=(F.get(t)??[]).filter(o=>O(o)&&o.start<=e&&o.start+(o.durationMs??0)>=e);if(r.length!==0)return r.sort((o,s)=>s.start-o.start||(o.durationMs??0)-(s.durationMs??0)),r[0]},"callerNodeFor");for(const t of b){if(!t.parentRequestId||t.kind!=="server-request"&&t.kind!=="gateway-request")continue;const e=t.parent?X.get(t.parent):void 0;if(e&&e.requestId===t.requestId)continue;const r=et(t.parentRequestId,t.start);r&&r!==t&&r.start<=t.start&&(t.parent=r.id)}const P=b,I=new Map;for(const t of P)t.kind==="gateway-request"&&t.requestId&&!I.has(t.requestId)&&I.set(t.requestId,t);for(const t of P)if(t.group==="server"&&!t.parent&&t.requestId&&t.kind!=="gateway-request"){const e=I.get(t.requestId);e&&e!==t&&e.start<=t.start&&(t.parent=e.id)}const N=new Set,U=new Set,L=[];for(const t of P){if(t.kind!=="gateway-request")continue;if(!t.requestId){L.push(t);continue}const e=F.get(t.requestId)??[];if(e.filter(s=>s.kind==="gateway-request").sort((s,c)=>s.start-c.start)[0]!==t)continue;const r=e.find(s=>s.kind==="fetch-start"),o=e.find(s=>s.kind==="fetch-done"||s.kind==="fetch-error");if(!r&&!o){L.push(t);continue}r&&(t.fetchStartId=r.id,N.add(r.id)),o&&(t.fetchDoneId=o.id,U.add(o.id))}const E=new Map;for(const t of P){if(!t.urlKey)continue;const e=E.get(t.urlKey)??{gws:[],starts:[],dones:[]};t.kind==="gateway-request"?L.includes(t)&&e.gws.push(t):t.kind==="fetch-start"?N.has(t.id)||e.starts.push(t):(t.kind==="fetch-done"||t.kind==="fetch-error")&&(U.has(t.id)||e.dones.push(t)),E.set(t.urlKey,e)}for(const{gws:t,starts:e,dones:r}of E.values()){t.sort((s,c)=>s.start-c.start),e.sort((s,c)=>s.start-c.start);const o=new Set;t.forEach((s,c)=>{const $=e[c];$&&(s.fetchStartId=$.id);const k=$?$.t:s.start;let i,u=1/0;for(const l of r){if(o.has(l.id))continue;const w=l.fetchStartedAt??l.start-(l.durationMs??0),j=Math.abs(w-k);j<u&&(u=j,i=l)}i&&(s.fetchDoneId=i.id,o.add(i.id))})}const K=new Map,_=new Map;for(const t of P)!t.queue||!t.jobId||(t.kind==="queue-enqueued"&&K.set(`${t.queue}#${t.jobId}`,t),t.kind==="queue-process"&&_.set(`${t.queue}#${t.jobId}`,t));for(const t of P){if(!t.queue||!t.jobId)continue;const e=`${t.queue}#${t.jobId}`;if(t.kind==="queue-process"&&!t.parent){const r=K.get(e);r&&r!==t&&r.start<=t.start&&(t.parent=r.id)}else if(t.kind==="queue-active"||t.kind==="queue-completed"||t.kind==="queue-failed"){const r=_.get(e);r&&r!==t&&r.start<=t.start&&(t.parent=r.id)}}{const t=new Map(b.map(e=>[e.id,e]));for(const e of b){if(!e.parent||!jt.has(e.kind??"")||e.durationMs===void 0)continue;const r=t.get(e.parent);if(!r||r.kind!=="span"||!((r.durationMs??0)>0))continue;const o=Math.round(e.start+e.durationMs-(r.start+r.durationMs));if(o<OUTLIVED_PARENT_MIN_MS)continue;e.outlivedParentMs=o;const s=r.leftRunning??{count:0,longestMs:0};r.leftRunning={count:s.count+1,longestMs:Math.max(s.longestMs,o)}}for(const e of b){const r=[];e.leftRunning&&r.push(`ended before ${e.leftRunning.count===1?"a call":`${e.leftRunning.count} calls`} it started had finished \u2014 ${e.leftRunning.count===1?"it":"the longest"} ran on ${e.leftRunning.longestMs}ms (a timeout that gave up, or work not awaited)`),e.outlivedParentMs!==void 0&&r.push(`ran on ${e.outlivedParentMs}ms after the span that started it had ended`),r.length>0&&(e.detail=[e.detail,...r].filter(Boolean).join(" \xB7 "))}}let f=b;{const t=new Map;for(const r of f)r.kind==="fetch-start"&&t.set(r.id,r);const e=new Map;for(const r of f){if(r.kind!=="fetch-done"&&r.kind!=="fetch-error")continue;const o=[...t.values()].find($=>$.requestId&&$.requestId===r.requestId)?.id,s=o?t.get(o):void 0;if(!s)continue;const c=r.fetchStartedAt??s.start;s.title=r.title,s.severity=r.severity,s.durationMs=r.durationMs??Math.max(0,r.t-c),s.kind="fetch",r.detail&&!s.detail&&(s.detail=r.detail),e.set(r.id,s.id)}if(e.size>0){f=f.filter(r=>!e.has(r.id));for(const r of f)for(r.fetchDoneId&&e.has(r.fetchDoneId)&&(r.fetchDoneId=e.get(r.fetchDoneId));r.parent&&e.has(r.parent);)r.parent=e.get(r.parent)}}const D=y(t=>!!t.commitId&&(t.kind==="render"||t.kind==="effect-run"||t.kind==="render-commit-truncated"),"commitMember"),W=y(t=>[...new Set(t)],"uniq"),G=y(t=>W(t.map(e=>e.component).filter(e=>!!e)),"named"),a=y(t=>t.length<=2?t.join(" + "):`${t[0]} + ${t.length-1} more`,"nameList"),h=y(t=>{const e=new Map;for(const r of t)r.component&&e.set(r.component,(e.get(r.component)??0)+1);return[...e].map(([r,o])=>o>1?`${r} \xD7${o}`:r).join(", ")},"tally"),B=y(t=>{if(!t)return"effect";const e=/([^/\\]+?):(\d+)(?::\d+)?$/.exec(t);return e?`${e[1]}:${e[2]}`:t},"shortHook"),A=y(t=>`${B(t.hook)}${t.cleanup?" (cleanup)":""}`,"hookLabel"),S=y(t=>{const e=Math.min(...t.map(o=>o.start)),r=Math.max(...t.map(o=>o.start+(o.durationMs??0)));return{start:e,durationMs:r-e}},"extent"),V=y(t=>(delete t.component,delete t.why,delete t.phase,delete t.hook,delete t.cleanup,delete t.renderTotal,delete t.renderPublished,t),"asGroup");function ot(t){const e=t[0],r=t.filter(x=>x.kind==="render"),o=t.filter(x=>x.kind==="effect-run"),s=t.find(x=>x.kind==="render-commit-truncated"),c=[...r].sort((x,Y)=>(Y.durationMs??0)-(x.durationMs??0)),$=c.filter(x=>(x.why??[]).some(Y=>Y!=="parent-render")),k=W($.flatMap(x=>(x.why??[]).filter(Y=>Y!=="parent-render"))),i=G($),u=r.filter(x=>x.phase==="mount"),l=r.filter(x=>x.phase!=="mount"&&!$.includes(x)),w=c[0]?.component??"view",j=r.length>0&&u.length===r.length,q=k.length?k.join(" + "):void 0,z=j?"mount":"update",H=i.length?`view update \xB7 ${a(i)} \u2190 ${q}`:j?`view mount \xB7 ${w}`:`view update \xB7 ${w}`,dt=s?.renderTotal??r.length,$t=[u.length?`mounted ${h(u)}`:"",l.length?`re-rendered ${h(l)}`:"",!i.length&&!j&&r.length?"trigger not recorded \u2014 every captured render came from its parent":"",s?`${dt} renders, ${s.renderPublished??r.length} recorded (per-commit cap)`:`${r.length} render${r.length===1?"":"s"}`,o.length?`${o.length} effect${o.length===1?"":"s"}: ${o.map(A).join(", ")}`:""].filter(Boolean).join(" \xB7 "),ut=G(r);return V({...e,...S(t),kind:"view-update",title:H,detail:$t,commitId:e.commitId,viewPhase:z,...q?{cause:q}:{},causeComponents:i,components:ut,mounted:G(u),renderCount:dt,recordedRenders:r.length,effects:o.length,effectHooks:o.map(A),memberIds:t.map(x=>x.id),sig:`commit:${z}:${q??"-"}:${i.join(",")}:${ut.slice().sort().join(",")}`,severity:t.some(x=>x.severity==="error")?"error":e.severity})}R(ot,"ut"),y(ot,"viewUpdateNode");function nt(t){const e=t[0],r=t.map(A);return V({...e,...S(t),kind:"commit-effects",title:t.length===1?`effect \xB7 ${r[0]}`:`effects \xB7 ${r[0]} + ${t.length-1} more`,detail:r.join(", "),commitId:e.commitId,effects:t.length,effectHooks:r,memberIds:t.map(o=>o.id),sig:`effects:${r.slice().sort().join(",")}`})}R(nt,"ft"),y(nt,"effectsNode");const ht=y(t=>W(t.map(e=>e==="state-update"?"state update":e==="fetch-start"?"request":e==="flow-origin"?"interaction":"response")).join(" + "),"describeInputs");function st(t,e){const r=t[0],o=t[t.length-1],s=t.length,c=r.detail,$=Math.min(...t.map(l=>l.start)),k=Math.max(...t.map(l=>l.start+(l.durationMs??0))),i=Math.round(t.reduce((l,w)=>l+(w.durationMs??0),0)/s*10)/10,u=Math.round((k-$)*10)/10;r.count=s,r.avgMs=i,r.wallMs=u,r.durationMs=k-$,r.items=t.slice(0,12).map(l=>({start:l.start-$,...l.durationMs!=null?{durationMs:l.durationMs}:{}})),r.memberIds=t.flatMap(l=>l.memberIds??[l.id]),r.title=`\xD7${s} ${r.title}`,t.some(l=>l.severity==="error")&&(r.severity="error"),r.kind==="view-update"?r.detail=[`${s} commits, ${e.length?`one per ${ht(e)}`:"back to back"}`,`avg ${i}ms \xB7 wall ${u}ms`,c??""].filter(Boolean).join(" \xB7 "):r.kind==="state-update"&&c&&o.detail?r.detail=`${s} updates in a row \xB7 wall ${u}ms \xB7 first ${c} \xB7 last ${o.detail}`:r.detail=[`${s} in a row \xB7 wall ${u}ms`,c??""].filter(Boolean).join(" \xB7 ")}R(st,"pt"),y(st,"collapseRepeat");const Q=[],Z=new Map,at=new Set;for(let t=0;t<f.length;t++){if(at.has(t))continue;const e=f[t];if(!D(e)){Q.push(e);continue}const r=[t];for(let c=t+1;c<f.length;c++){const $=f[c];if($.group==="browser"){if(!D($)||$.commitId!==e.commitId)break;r.push(c)}}for(const c of r)at.add(c);const o=r.map(c=>f[c]),s=o.some(c=>c.kind!=="effect-run")?ot(o):nt(o);for(const c of o)c.id!==s.id&&Z.set(c.id,s.id);Q.push(s)}if(Z.size>0||Q.some(t=>t.kind==="view-update"||t.kind==="commit-effects")){f=Q;for(const t of f)for(;t.parent&&Z.has(t.parent);)t.parent=Z.get(t.parent)}{const t=new Map;for(const e of f)e.kind==="view-update"&&e.commitId&&!t.has(e.commitId)&&t.set(e.commitId,e);for(const e of f){if(e.kind!=="commit-effects"||e.parent||!e.commitId)continue;const r=t.get(e.commitId);r&&r.start<=e.start&&(e.parent=r.id)}}{const t=new Set(["state-update","fetch","fetch-start","fetch-done","fetch-error","flow-origin"]),e=f.map((i,u)=>i.group==="browser"?u:-1).filter(i=>i>=0),r=y(i=>`${i.kind}|${i.sig??i.title}`,"keyOf"),o=e.map(i=>r(f[i])),s=y((i,u,l)=>{for(let w=0;w<l;w++)if(o[i+w]!==o[u+w])return!1;return!0},"sameBlock"),c=y(i=>o[i].split("|")[0],"kindAt"),$=y(i=>{let u=0,l=1;for(let w=1;w<=4&&i+w<=o.length;w++){let j=1;for(;i+(j+1)*w<=o.length&&s(i,i+j*w,w);)j+=1;j>=3&&w*j>u*l&&(u=w,l=j)}return{k:u,r:l}},"bestBlockAt"),k=new Map;for(let i=0;i<o.length;){const{k:u,r:l}=$(i);if(u===0){i+=1;continue}const w=[...Array(u).keys()].find(q=>t.has(c(i+q)));if(w!==void 0&&w>0){const q=$(i+w);if(q.k===u&&q.r>=3&&q.r>=l-1){i+=w;continue}}const j=o.slice(i,i+u).map(q=>q.split("|")[0]).filter(q=>t.has(q));for(let q=0;q<u;q++){const z=[];for(let H=0;H<l;H++)z.push(f[e[i+q+H*u]]);st(z,j);for(const H of z.slice(1))k.set(H.id,z[0].id)}i+=u*l}if(k.size>0){f=f.filter(i=>!k.has(i.id));for(const i of f)for(;i.parent&&k.has(i.parent);)i.parent=k.get(i.parent)}}{const t=new Map(f.map(e=>[e.id,e]));for(const e of f){const r=new Set([e.id]);let o=e;for(;o?.parent;){if(r.has(o.parent)){o.parent=void 0;break}r.add(o.parent),o=t.get(o.parent)}}}const it=y(t=>{const e=new Map;for(const o of f){if(!o.sig||O(o)!==t||o.kind==="server-request"||o.kind==="gateway-request"||o.group==="browser")continue;const s=`${o.parent??"root"}|${o.kind}|${o.sig}`,c=e.get(s);c?c.push(o):e.set(s,[o])}const r=new Map;for(const o of e.values()){if(o.length<3)continue;o.sort((u,l)=>u.start-l.start);const s=o[0];let c=!1;for(let u=0;u+1<o.length;u++)if(o[u+1].start<o[u].start+(o[u].durationMs??0)){c=!0;break}const $=s.start,k=Math.max(...o.map(u=>u.start+(u.durationMs??0))),i=o.reduce((u,l)=>u+(l.durationMs??0),0);s.count=o.length,s.parallel=c,s.avgMs=Math.round(i/o.length*10)/10,s.wallMs=k-$,s.durationMs=k-$,s.title=`\xD7${o.length} ${s.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,s.detail=`${s.sig} \xD7${o.length} ${c?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${s.avgMs}ms \xB7 wall ${s.wallMs}ms`,s.items=o.slice(0,12).map(u=>({start:u.start-$,...u.durationMs!=null?{durationMs:u.durationMs}:{}})),s.memberIds=o.flatMap(u=>u.memberIds??[u.id]),o.some(u=>u.severity==="error")&&(s.severity="error");for(const u of o.slice(1))r.set(u.id,s.id)}if(r.size!==0){f=f.filter(o=>!r.has(o.id));for(const o of f)for(;o.parent&&r.has(o.parent);)o.parent=r.get(o.parent)}},"aggregatePass");it(!0),it(!1);for(const t of f){if(!O(t))continue;const e=t.durationMs??0;if(e<40)continue;const r=f.filter(k=>k.parent===t.id&&(k.durationMs??0)>0).map(k=>[k.start,k.start+(k.durationMs??0)]).sort((k,i)=>k[0]-i[0]);let o=0,s=-1,c=-1;for(const[k,i]of r)k>c?(c>s&&(o+=c-s),s=k,c=i):i>c&&(c=i);c>s&&(o+=c-s);const $=Math.max(0,e-o);($>=50||$/e>=.7&&e>=40)&&(t.selfMs=$,t.detail=`\u26A0 cpu-heavy: ${$}ms self-time of ${e}ms${t.detail?" \xB7 "+t.detail:""}`)}return{events:f,...n?{sql:n}:{}}}R(buildFlowDetail,"buildFlowDetail"),y(buildFlowDetail,"buildFlowDetail");
1
+ "use strict";var ke=Object.defineProperty;var R=(d,v)=>ke(d,"name",{value:v,configurable:!0});var ye=Object.defineProperty,k=R((d,v)=>ye(d,"name",{value:v,configurable:!0}),"$");import{redactDeep as Me,redactText as oe}from"./redact.js";import{SQL_ACCOUNT_KIND as we,sqlAccountingOf as ve}from"./flow-segments.js";import{boundedClone as qe}from"@lensmcp/protocol-types";export function areaOf(d){const{source:v,category:n,title:M,kind:m}=d;return v==="ai"?"ai":m?.startsWith("memory")||m==="db-query"?"data":v==="gateway"||m==="gateway-request"?"gateway":m==="queue-process"||m==="queue-active"||m==="queue-completed"||m==="queue-failed"?"services":v==="db"||v==="redis"||v==="queue"||m==="redis-op"||m?.startsWith("queue-")?"data":v==="external"||m==="egress"?"network":v==="nestjs"||v==="nest"?/(?:Repository|Repo|Dao|Store)\./.test(M)?"data":"services":v==="valtio"?"state":n==="network"?"network":"browser"}R(areaOf,"areaOf"),k(areaOf,"areaOf");const le=240,Ie=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),xe=new Set(["tenantId","caller","userId","accountId","email","subject"]),be=8;function ce(d){const v=ee(d,0);return qe(Me({redacted:!0,...v}),{rawByteLimit:16*1024}).value}R(ce,"It"),k(ce,"aiProjection");function ee(d,v){if(typeof d=="string")return fe(d);if(d===null||typeof d!="object")return d;if(v>=be)return;if(Array.isArray(d))return d.slice(0,32).map(M=>ee(M,v+1));const n={};for(const[M,m]of Object.entries(d))if(!xe.has(M)){if(Ie.has(M)){typeof m=="string"?n[`${M}Chars`]=m.length:Array.isArray(m)?n[`${M}Count`]=m.length:m!=null&&(n[`${M}Present`]=!0);continue}n[M]=ee(m,v+1)}return n}R(ee,"rt"),k(ee,"projectAi");function fe(d){return d.length<=le?oe(d):`${oe(d.slice(0,le))}\u2026`}R(fe,"qt"),k(fe,"clipText");export function trimFlowEvent(d,v={}){const n=d.raw??{},M=n.render??{},m=n.span??{},C=n.request??{},f=k(a=>typeof a=="number"?a:void 0,"num"),L=n.loop??{},b=n.effect??{},T=f(n.durationMs)??f(m.durationMs)??f(C.durationMs)??f(L.durationMs)??f(M.actualDurationMs)??f(b.durationMs),g=typeof n.kind=="string"?n.kind:void 0,O=g==="fetch-done"||g==="fetch-error",X=f(M.commitTime),te=g==="render"&&X!==void 0&&Math.abs(X-d.timestamp)<6e4,P=O?d.timestamp:te?X:f(n.startedAt)??f(m.startTime)??f(C.startedAt)??f(L.startedAt)??(T!==void 0?d.timestamp-T:d.timestamp);let I;if(typeof n.query=="string"){const a=Array.isArray(n.params)?` [${n.params.join(", ")}]`:"",h=typeof n.result=="string"?` \u2192 ${n.result}`:"";I=n.query+a+h}else if(typeof n.command=="string"){const a=typeof n.value=="string"?` \u2192 ${n.value}`:n.hit===!1?" \u2192 (miss)":"";I=n.command+a}else if(g==="state-update"){const a=n.update??{};let h="";try{h=JSON.stringify(a.preview)}catch{}I=`${a.storeId??""}.${a.path??""} = ${h}`}else if(g==="queue-completed"&&typeof n.returned=="string")I=`returned ${n.returned}`;else if(g==="queue-enqueued")I=`${n.job??"job"}#${n.jobId??"?"} \u2192 ${n.queue??""}${typeof n.data=="string"?" "+n.data:""}`;else if(g==="log"){const a=C.error??{},h=typeof a.stack=="string"?a.stack:typeof n.text=="string"?n.text:void 0;h&&h!==d.title&&(I=h)}let N,G,F,E;if(g==="span"){const a=m.outcome;if(N=a==="threw"||a==="returned"?a:m.status==="error"?"threw":m.status==="ok"?"returned":void 0,N==="threw"){const S=m.error??{},A=typeof S.name=="string"?S.name:void 0,V=typeof S.message=="string"?S.message:typeof d.message=="string"?d.message:void 0;F=A,G=oe([A,V].filter(Boolean).join(": "))||void 0}const h=typeof m.args=="string"?m.args:void 0,B=typeof m.result=="string"?m.result:void 0;if(h!==void 0||B!==void 0){E=[...h!==void 0?["args"]:[],...B!==void 0?["result"]:[]];const S=k(A=>A.length>pe?`${A.slice(0,pe)}\u2026`:A,"short");I=[h!==void 0?`args ${S(h)}`:"",B!==void 0?`returned ${S(B)}`:""].filter(Boolean).join(" \u2192 ")}}let W;if(g==="gateway-request")W=`${n.host??""}${String(n.url??"").split("?")[0]}`;else if(g==="fetch-start"||g==="fetch-done"||g==="fetch-error")try{const a=new URL(String(n.href??n.url??""));W=`${a.hostname}${a.pathname}`}catch{}let K;if(g==="gateway-request"&&Array.isArray(n.steps))K=n.steps.map(a=>{const h=[String(a.step)];return a.project&&h.push(String(a.project)),a.prefix&&h.push(String(a.prefix)),a.mode&&h.push(String(a.mode)+(a.ok===!1?" \u2717":a.ok===!0?" \u2713":"")),a.caller&&h.push("by "+String(a.caller)),a.pod&&h.push(String(a.pod)),typeof a.atMs=="number"&&h.push(`@${a.atMs}ms`),h.join(" ")}),I=K.map(a=>a.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(g==="egress")I=`${n.method??"GET"} ${n.host??""} \u2192 ${n.status??"?"}`;else if(d.source==="ai"){if(g==="ai-call"){const a=n.usage??{},h=a.promptTokens!==void 0||a.completionTokens!==void 0?` \xB7 ${f(a.promptTokens)??"?"}\u2192${f(a.completionTokens)??"?"} tok`:"",B=n.status!==void 0?` \xB7 ${String(n.status)}`:n.error?" \xB7 failed":"",S=f(n.toolCallCount)?` \xB7 ${f(n.toolCallCount)} tool call${f(n.toolCallCount)===1?"":"s"}`:"",A=f(n.durationMs)!==void 0?` \xB7 ${(f(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${n.provider??""}/${n.model??"?"}${h}${B}${S}${A}${n.stream===!0?" \xB7 stream":""}`}else if(g==="ai-round"){const a=n.model??{},h=n.usage??{},B=Array.isArray(n.toolCalls)?n.toolCalls:[],S=`${f(h.promptTokens)??"?"}\u2192${f(h.completionTokens)??"?"} tok`,A=B.length?` \xB7 ${B.length} tool call${B.length===1?"":"s"}`:"",V=f(n.durationMs)!==void 0?` \xB7 ${(f(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${a.provider??""}/${a.model??""} \xB7 ${S}${A}${V}`}else if(g==="ai-turn-start"){const a=Array.isArray(n.tools)?n.tools:[];I=`skill ${n.skill??""} \xB7 ${n.output??""}${a.length?" \xB7 tools: "+a.join(", "):""}`}else if(g==="ai-tool-call"){const a=n.call??{},h=n.result??{},B=f(n.durationMs)!==void 0?` \xB7 ${(f(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${a.name??"tool"} ${h.error!=null?"\u2717 "+String(h.error):"\u2713"}${B}`}else if(g==="ai-turn-end"){const a=n.usage??{},h=f(n.rounds)!==void 0?` \xB7 ${f(n.rounds)} round${f(n.rounds)===1?"":"s"}`:"",B=f(n.durationMs)!==void 0?` \xB7 ${(f(n.durationMs)/1e3).toFixed(1)}s`:"";I=`${n.ok===!1?"FAILED":"ok"} \xB7 ${f(a.promptTokens)??"?"}+${f(a.completionTokens)??"?"} tok${h}${B}`}}let p;g==="db-query"&&typeof n.query=="string"?p=n.query:g==="redis-op"?p=`${n.op??""} ${String(n.key??"").replace(/\d+/g,"#")}`:g==="egress"?p=`${n.method??"GET"} ${n.host??""}`:g==="ai-call"?p=`ai ${n.provider??""} ${n.model??""} ${n.api??""}`:g==="queue-enqueued"?p=`enqueue ${n.queue??""}`:g==="span"&&typeof m.name=="string"?p=m.name:g==="memory-mutation"&&(p=d.title);const D=d.context??{},U=M.commitId??b.commitId??n.commitId,H=Array.isArray(M.why)?M.why.map(a=>typeof a?.type=="string"?a.type:void 0).filter(a=>!!a):[];return{id:d.id,t:d.timestamp,start:P,...p?{sig:p}:{},...W?{urlKey:W}:{},...typeof n.queue=="string"?{queue:n.queue}:{},...n.jobId!=null?{jobId:String(n.jobId)}:{},source:d.source,category:d.category,severity:d.severity,title:N==="threw"&&typeof m.name=="string"?`${m.name} \u2014 threw${F?` ${F}`:""}${T!==void 0?` after ${T}ms`:""}`:d.title,kind:g,area:areaOf({source:d.source,category:d.category,title:d.title,kind:g}),...N?{outcome:N}:{},...G?{error:G}:{},...E?{captured:E}:{},...typeof m.role=="string"?{role:m.role}:{},...g==="log"&&typeof n.level=="string"?{level:n.level}:{},...g==="log"&&typeof n.logger=="string"?{logger:n.logger}:{},...g==="log"&&typeof n.stream=="string"?{stream:n.stream}:{},...typeof D.requestId=="string"?{requestId:D.requestId}:{},...typeof D.parentRequestId=="string"?{parentRequestId:D.parentRequestId}:{},...typeof U=="string"?{commitId:U}:{},...typeof M.componentName=="string"?{component:M.componentName}:{},...typeof M.phase=="string"?{phase:M.phase}:{},...H.length?{why:H}:{},...g==="effect-run"&&typeof b.hookLogicalId=="string"?{hook:b.hookLogicalId}:{},...g==="effect-run"&&b.cleanupRan===!0?{cleanup:!0}:{},...g==="render-commit-truncated"?{renderTotal:f(n.total),renderPublished:f(n.published),...f(n.walkStoppedAt)!==void 0?{renderWalkStoppedAt:f(n.walkStoppedAt)}:{}}:{},...typeof D.projectName=="string"?{project:D.projectName}:typeof n.project=="string"?{project:n.project}:{},...T!==void 0?{durationMs:T}:{},...O&&f(n.startedAt)!==void 0?{fetchStartedAt:f(n.startedAt)}:{},...d.source==="ai"?{ai:v.includeRaw?n:ce(n)}:{},...I?{detail:I}:{},...K?{steps:K}:{}}}R(trimFlowEvent,"trimFlowEvent"),k(trimFlowEvent,"trimFlowEvent");const pe=300;export const OUTLIVED_PARENT_MIN_MS=250;const je=new Set(["egress","db-query","redis-op","ai-call","span","gateway-request","server-request"]),me=1;function ge(d){return d==="flow-origin"?0:d?.endsWith("-start")?1:d==="gateway-request"?2:d==="server-request"?3:d==="span"?4:d==="render"||d==="render-commit-truncated"?6:d==="effect-run"?7:5}R(ge,"jt"),k(ge,"kindRank");function J(d){return d.kind==="span"&&d.role==="controller"?3.5:d.kind==="queue-process"?3:ge(d.kind)}R(J,"Z"),k(J,"causalRank");export function buildFlowDetail(d,v={}){const n=ve(d),M=d.slice().filter(e=>{const t=e.raw??{},r=typeof t.kind=="string"?t.kind:"";if(r==="subscription-added"||r==="subscription-removed"||r==="hook-run"||r==="store-created"||r==="singleton-instance"||r===we)return!1;const o=t.span;return!(typeof o?.name=="string"&&o.name.startsWith("nest.request "))}).map(e=>trimFlowEvent(e,v)),m=new Set;for(let e=M.length-1;e>=0;e--)m.has(M[e].id)?M.splice(e,1):m.add(M[e].id);const C=new Map;for(const e of M)(e.kind==="gateway-request"||e.kind==="queue-process")&&e.requestId&&!C.has(e.requestId)&&C.set(e.requestId,e.start);const f=k(e=>e.source!=="react"&&e.source!=="valtio"&&e.requestId&&C.has(e.requestId)?C.get(e.requestId):e.start,"anchorOf");M.sort((e,t)=>f(e)-f(t)||e.start-t.start||J(e)-J(t)||(t.durationMs??0)-(e.durationMs??0)||e.t-t.t);const L=k(e=>(e.kind==="span"||e.kind==="server-request"||e.kind==="gateway-request"||e.kind==="queue-process")&&(e.durationMs??0)>0,"spanLike"),b=M;for(const e of b)e.group=e.source==="react"||e.source==="valtio"||e.source==="client-runtime"||e.source==="visual"?"browser":"server";const T=new Map;for(const e of b)if((e.kind==="gateway-request"||e.kind==="queue-process")&&e.requestId&&e.project){const t=T.get(e.requestId)??[];t.push({project:e.project,start:e.start,end:e.start+(e.durationMs??0)}),T.set(e.requestId,t)}const g=k((e,t)=>{const r=T.get(e);if(r?.length)return r.every(o=>o.project===r[0].project)?r[0].project:r.filter(o=>o.start<=t+1&&o.end>=t-1).sort((o,s)=>s.start-o.start)[0]?.project},"projectOf");for(const e of b)if(!e.project&&e.source==="nestjs"&&e.requestId){const t=g(e.requestId,e.start);t&&(e.project=t)}for(const e of b){let t;const r=e.requestId;for(const o of b){if(o===e||!L(o)||o.group!==e.group||o.requestId!==r)continue;const s=o.project,l=e.project;if(o.kind!=="gateway-request"&&e.kind!=="gateway-request"&&s!==void 0&&l!==void 0&&s!==l)continue;const $=o.durationMs??0,y=e.durationMs??0,i=Math.abs(o.start-e.start)<=me,u=J(o),c=J(e),w=o.start<=e.start;if(!(o.start+$>e.start&&(w||i&&u<c)&&(!i||(u!==c?u<c:w&&$>y))))continue;const j=t?J(t):-1,q=t?Math.abs(o.start-t.start)<=me:!1;(!t||!q&&o.start>t.start||q&&u>j||q&&u===j&&(o.durationMs??0)<(t.durationMs??0))&&(t=o)}t&&(e.parent=t.id)}const O=new Map;for(const e of b){if(!e.requestId)continue;const t=O.get(e.requestId);t?t.push(e):O.set(e.requestId,[e])}const X=new Map(b.map(e=>[e.id,e])),te=k((e,t)=>{const r=(O.get(e)??[]).filter(o=>L(o)&&o.start<=t&&o.start+(o.durationMs??0)>=t);if(r.length!==0)return r.sort((o,s)=>s.start-o.start||(o.durationMs??0)-(s.durationMs??0)),r[0]},"callerNodeFor");for(const e of b){if(!e.parentRequestId||e.kind!=="server-request"&&e.kind!=="gateway-request")continue;const t=e.parent?X.get(e.parent):void 0;if(t&&t.requestId===e.requestId)continue;const r=te(e.parentRequestId,e.start);r&&r!==e&&r.start<=e.start&&(e.parent=r.id)}const P=b,I=new Map;for(const e of P)e.kind==="gateway-request"&&e.requestId&&!I.has(e.requestId)&&I.set(e.requestId,e);for(const e of P)if(e.group==="server"&&!e.parent&&e.requestId&&e.kind!=="gateway-request"){const t=I.get(e.requestId);t&&t!==e&&t.start<=e.start&&(e.parent=t.id)}const N=new Set,G=new Set,F=[];for(const e of P){if(e.kind!=="gateway-request")continue;if(!e.requestId){F.push(e);continue}const t=O.get(e.requestId)??[];if(t.filter(s=>s.kind==="gateway-request").sort((s,l)=>s.start-l.start)[0]!==e)continue;const r=t.find(s=>s.kind==="fetch-start"),o=t.find(s=>s.kind==="fetch-done"||s.kind==="fetch-error");if(!r&&!o){F.push(e);continue}r&&(e.fetchStartId=r.id,N.add(r.id)),o&&(e.fetchDoneId=o.id,G.add(o.id))}const E=new Map;for(const e of P){if(!e.urlKey)continue;const t=E.get(e.urlKey)??{gws:[],starts:[],dones:[]};e.kind==="gateway-request"?F.includes(e)&&t.gws.push(e):e.kind==="fetch-start"?N.has(e.id)||t.starts.push(e):(e.kind==="fetch-done"||e.kind==="fetch-error")&&(G.has(e.id)||t.dones.push(e)),E.set(e.urlKey,t)}for(const{gws:e,starts:t,dones:r}of E.values()){e.sort((s,l)=>s.start-l.start),t.sort((s,l)=>s.start-l.start);const o=new Set;e.forEach((s,l)=>{const $=t[l];$&&(s.fetchStartId=$.id);const y=$?$.t:s.start;let i,u=1/0;for(const c of r){if(o.has(c.id))continue;const w=c.fetchStartedAt??c.start-(c.durationMs??0),j=Math.abs(w-y);j<u&&(u=j,i=c)}i&&(s.fetchDoneId=i.id,o.add(i.id))})}const W=new Map,K=new Map;for(const e of P)!e.queue||!e.jobId||(e.kind==="queue-enqueued"&&W.set(`${e.queue}#${e.jobId}`,e),e.kind==="queue-process"&&K.set(`${e.queue}#${e.jobId}`,e));for(const e of P){if(!e.queue||!e.jobId)continue;const t=`${e.queue}#${e.jobId}`;if(e.kind==="queue-process"&&!e.parent){const r=W.get(t);r&&r!==e&&r.start<=e.start&&(e.parent=r.id)}else if(e.kind==="queue-active"||e.kind==="queue-completed"||e.kind==="queue-failed"){const r=K.get(t);r&&r!==e&&r.start<=e.start&&(e.parent=r.id)}}{const e=new Map(b.map(t=>[t.id,t]));for(const t of b){if(!t.parent||!je.has(t.kind??"")||t.durationMs===void 0)continue;const r=e.get(t.parent);if(!r||r.kind!=="span"||!((r.durationMs??0)>0))continue;const o=Math.round(t.start+t.durationMs-(r.start+r.durationMs));if(o<OUTLIVED_PARENT_MIN_MS)continue;t.outlivedParentMs=o;const s=r.leftRunning??{count:0,longestMs:0};r.leftRunning={count:s.count+1,longestMs:Math.max(s.longestMs,o)}}for(const t of b){const r=[];t.leftRunning&&r.push(`ended before ${t.leftRunning.count===1?"a call":`${t.leftRunning.count} calls`} it started had finished \u2014 ${t.leftRunning.count===1?"it":"the longest"} ran on ${t.leftRunning.longestMs}ms (a timeout that gave up, or work not awaited)`),t.outlivedParentMs!==void 0&&r.push(`ran on ${t.outlivedParentMs}ms after the span that started it had ended`),r.length>0&&(t.detail=[t.detail,...r].filter(Boolean).join(" \xB7 "))}}let p=b;{const e=new Map;for(const r of p)r.kind==="fetch-start"&&e.set(r.id,r);const t=new Map;for(const r of p){if(r.kind!=="fetch-done"&&r.kind!=="fetch-error")continue;const o=[...e.values()].find($=>$.requestId&&$.requestId===r.requestId)?.id,s=o?e.get(o):void 0;if(!s)continue;const l=r.fetchStartedAt??s.start;s.title=r.title,s.severity=r.severity,s.durationMs=r.durationMs??Math.max(0,r.t-l),s.kind="fetch",r.detail&&!s.detail&&(s.detail=r.detail),t.set(r.id,s.id)}if(t.size>0){p=p.filter(r=>!t.has(r.id));for(const r of p)for(r.fetchDoneId&&t.has(r.fetchDoneId)&&(r.fetchDoneId=t.get(r.fetchDoneId));r.parent&&t.has(r.parent);)r.parent=t.get(r.parent)}}const D=k(e=>!!e.commitId&&(e.kind==="render"||e.kind==="effect-run"||e.kind==="render-commit-truncated"),"commitMember"),U=k(e=>[...new Set(e)],"uniq"),H=k(e=>U(e.map(t=>t.component).filter(t=>!!t)),"named"),a=k(e=>e.length<=2?e.join(" + "):`${e[0]} + ${e.length-1} more`,"nameList"),h=k(e=>{const t=new Map;for(const r of e)r.component&&t.set(r.component,(t.get(r.component)??0)+1);return[...t].map(([r,o])=>o>1?`${r} \xD7${o}`:r).join(", ")},"tally"),B=k(e=>{if(!e)return"effect";const t=/([^/\\]+?):(\d+)(?::\d+)?$/.exec(e);return t?`${t[1]}:${t[2]}`:e},"shortHook"),S=k(e=>`${B(e.hook)}${e.cleanup?" (cleanup)":""}`,"hookLabel"),A=k(e=>{const t=Math.min(...e.map(o=>o.start)),r=Math.max(...e.map(o=>o.start+(o.durationMs??0)));return{start:t,durationMs:r-t}},"extent"),V=k(e=>(delete e.component,delete e.why,delete e.phase,delete e.hook,delete e.cleanup,delete e.renderTotal,delete e.renderPublished,e),"asGroup");function ne(e){const t=e[0],r=e.filter(x=>x.kind==="render"),o=e.filter(x=>x.kind==="effect-run"),s=e.find(x=>x.kind==="render-commit-truncated"),l=[...r].sort((x,Y)=>(Y.durationMs??0)-(x.durationMs??0)),$=l.filter(x=>(x.why??[]).some(Y=>Y!=="parent-render")),y=U($.flatMap(x=>(x.why??[]).filter(Y=>Y!=="parent-render"))),i=H($),u=r.filter(x=>x.phase==="mount"),c=r.filter(x=>x.phase!=="mount"&&!$.includes(x)),w=l[0]?.component??"view",j=r.length>0&&u.length===r.length,q=y.length?y.join(" + "):void 0,_=j?"mount":"update",z=i.length?`view update \xB7 ${a(i)} \u2190 ${q}`:j?`view mount \xB7 ${w}`:`view update \xB7 ${w}`,re=s?.renderTotal??r.length,$e=[u.length?`mounted ${h(u)}`:"",c.length?`re-rendered ${h(c)}`:"",!i.length&&!j&&r.length?"trigger not recorded \u2014 every captured render came from its parent":"",s?.renderWalkStoppedAt!==void 0?`at least ${re} renders (the walk stopped at ${s.renderWalkStoppedAt} fibers), ${s.renderPublished??r.length} recorded`:s?`${re} renders, ${s.renderPublished??r.length} recorded (per-commit cap)`:`${r.length} render${r.length===1?"":"s"}`,o.length?`${o.length} effect${o.length===1?"":"s"}: ${o.map(S).join(", ")}`:""].filter(Boolean).join(" \xB7 "),ue=H(r);return V({...t,...A(e),kind:"view-update",title:z,detail:$e,commitId:t.commitId,viewPhase:_,...q?{cause:q}:{},causeComponents:i,components:ue,mounted:H(u),renderCount:re,...s?.renderWalkStoppedAt!==void 0?{renderCountAtLeast:!0}:{},recordedRenders:r.length,effects:o.length,effectHooks:o.map(S),memberIds:e.map(x=>x.id),sig:`commit:${_}:${q??"-"}:${i.join(",")}:${ue.slice().sort().join(",")}`,severity:e.some(x=>x.severity==="error")?"error":t.severity})}R(ne,"ut"),k(ne,"viewUpdateNode");function se(e){const t=e[0],r=e.map(S);return V({...t,...A(e),kind:"commit-effects",title:e.length===1?`effect \xB7 ${r[0]}`:`effects \xB7 ${r[0]} + ${e.length-1} more`,detail:r.join(", "),commitId:t.commitId,effects:e.length,effectHooks:r,memberIds:e.map(o=>o.id),sig:`effects:${r.slice().sort().join(",")}`})}R(se,"ft"),k(se,"effectsNode");const he=k(e=>U(e.map(t=>t==="state-update"?"state update":t==="fetch-start"?"request":t==="flow-origin"?"interaction":"response")).join(" + "),"describeInputs");function ae(e,t){const r=e[0],o=e[e.length-1],s=e.length,l=r.detail,$=Math.min(...e.map(c=>c.start)),y=Math.max(...e.map(c=>c.start+(c.durationMs??0))),i=Math.round(e.reduce((c,w)=>c+(w.durationMs??0),0)/s*10)/10,u=Math.round((y-$)*10)/10;r.count=s,r.avgMs=i,r.wallMs=u,r.durationMs=y-$,r.items=e.slice(0,12).map(c=>({start:c.start-$,...c.durationMs!=null?{durationMs:c.durationMs}:{}})),r.memberIds=e.flatMap(c=>c.memberIds??[c.id]),r.title=`\xD7${s} ${r.title}`,e.some(c=>c.severity==="error")&&(r.severity="error"),r.kind==="view-update"?r.detail=[`${s} commits, ${t.length?`one per ${he(t)}`:"back to back"}`,`avg ${i}ms \xB7 wall ${u}ms`,l??""].filter(Boolean).join(" \xB7 "):r.kind==="state-update"&&l&&o.detail?r.detail=`${s} updates in a row \xB7 wall ${u}ms \xB7 first ${l} \xB7 last ${o.detail}`:r.detail=[`${s} in a row \xB7 wall ${u}ms`,l??""].filter(Boolean).join(" \xB7 ")}R(ae,"pt"),k(ae,"collapseRepeat");const Q=[],Z=new Map,ie=new Set;for(let e=0;e<p.length;e++){if(ie.has(e))continue;const t=p[e];if(!D(t)){Q.push(t);continue}const r=[e];for(let l=e+1;l<p.length;l++){const $=p[l];if($.group==="browser"){if(!D($)||$.commitId!==t.commitId)break;r.push(l)}}for(const l of r)ie.add(l);const o=r.map(l=>p[l]),s=o.some(l=>l.kind!=="effect-run")?ne(o):se(o);for(const l of o)l.id!==s.id&&Z.set(l.id,s.id);Q.push(s)}if(Z.size>0||Q.some(e=>e.kind==="view-update"||e.kind==="commit-effects")){p=Q;for(const e of p)for(;e.parent&&Z.has(e.parent);)e.parent=Z.get(e.parent)}{const e=new Map;for(const t of p)t.kind==="view-update"&&t.commitId&&!e.has(t.commitId)&&e.set(t.commitId,t);for(const t of p){if(t.kind!=="commit-effects"||t.parent||!t.commitId)continue;const r=e.get(t.commitId);r&&r.start<=t.start&&(t.parent=r.id)}}{const e=new Set(["state-update","fetch","fetch-start","fetch-done","fetch-error","flow-origin"]),t=p.map((i,u)=>i.group==="browser"?u:-1).filter(i=>i>=0),r=k(i=>`${i.kind}|${i.sig??i.title}`,"keyOf"),o=t.map(i=>r(p[i])),s=k((i,u,c)=>{for(let w=0;w<c;w++)if(o[i+w]!==o[u+w])return!1;return!0},"sameBlock"),l=k(i=>o[i].split("|")[0],"kindAt"),$=k(i=>{let u=0,c=1;for(let w=1;w<=4&&i+w<=o.length;w++){let j=1;for(;i+(j+1)*w<=o.length&&s(i,i+j*w,w);)j+=1;j>=3&&w*j>u*c&&(u=w,c=j)}return{k:u,r:c}},"bestBlockAt"),y=new Map;for(let i=0;i<o.length;){const{k:u,r:c}=$(i);if(u===0){i+=1;continue}const w=[...Array(u).keys()].find(q=>e.has(l(i+q)));if(w!==void 0&&w>0){const q=$(i+w);if(q.k===u&&q.r>=3&&q.r>=c-1){i+=w;continue}}const j=o.slice(i,i+u).map(q=>q.split("|")[0]).filter(q=>e.has(q));for(let q=0;q<u;q++){const _=[];for(let z=0;z<c;z++)_.push(p[t[i+q+z*u]]);ae(_,j);for(const z of _.slice(1))y.set(z.id,_[0].id)}i+=u*c}if(y.size>0){p=p.filter(i=>!y.has(i.id));for(const i of p)for(;i.parent&&y.has(i.parent);)i.parent=y.get(i.parent)}}{const e=new Map(p.map(t=>[t.id,t]));for(const t of p){const r=new Set([t.id]);let o=t;for(;o?.parent;){if(r.has(o.parent)){o.parent=void 0;break}r.add(o.parent),o=e.get(o.parent)}}}const de=k(e=>{const t=new Map;for(const o of p){if(!o.sig||L(o)!==e||o.kind==="server-request"||o.kind==="gateway-request"||o.group==="browser")continue;const s=`${o.parent??"root"}|${o.kind}|${o.sig}`,l=t.get(s);l?l.push(o):t.set(s,[o])}const r=new Map;for(const o of t.values()){if(o.length<3)continue;o.sort((u,c)=>u.start-c.start);const s=o[0];let l=!1;for(let u=0;u+1<o.length;u++)if(o[u+1].start<o[u].start+(o[u].durationMs??0)){l=!0;break}const $=s.start,y=Math.max(...o.map(u=>u.start+(u.durationMs??0))),i=o.reduce((u,c)=>u+(c.durationMs??0),0);s.count=o.length,s.parallel=l,s.avgMs=Math.round(i/o.length*10)/10,s.wallMs=y-$,s.durationMs=y-$,s.title=`\xD7${o.length} ${s.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,s.detail=`${s.sig} \xD7${o.length} ${l?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${s.avgMs}ms \xB7 wall ${s.wallMs}ms`,s.items=o.slice(0,12).map(u=>({start:u.start-$,...u.durationMs!=null?{durationMs:u.durationMs}:{}})),s.memberIds=o.flatMap(u=>u.memberIds??[u.id]),o.some(u=>u.severity==="error")&&(s.severity="error");for(const u of o.slice(1))r.set(u.id,s.id)}if(r.size!==0){p=p.filter(o=>!r.has(o.id));for(const o of p)for(;o.parent&&r.has(o.parent);)o.parent=r.get(o.parent)}},"aggregatePass");de(!0),de(!1);for(const e of p){if(!L(e))continue;const t=e.durationMs??0;if(t<40)continue;const r=p.filter(y=>y.parent===e.id&&(y.durationMs??0)>0).map(y=>[y.start,y.start+(y.durationMs??0)]).sort((y,i)=>y[0]-i[0]);let o=0,s=-1,l=-1;for(const[y,i]of r)y>l?(l>s&&(o+=l-s),s=y,l=i):i>l&&(l=i);l>s&&(o+=l-s);const $=Math.max(0,t-o);($>=50||$/t>=.7&&t>=40)&&(e.selfMs=$,e.detail=`\u26A0 cpu-heavy: ${$}ms self-time of ${t}ms${e.detail?" \xB7 "+e.detail:""}`)}return{events:p,...n?{sql:n}:{}}}R(buildFlowDetail,"buildFlowDetail"),k(buildFlowDetail,"buildFlowDetail");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/core",
3
- "version": "1.24.4",
3
+ "version": "1.24.5",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -39,7 +39,7 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@lensmcp/protocol-types": "1.24.4",
42
+ "@lensmcp/protocol-types": "1.24.5",
43
43
  "tslib": "^2.3.0"
44
44
  },
45
45
  "license": "Apache-2.0",