@lensmcp/core 1.22.5 → 1.22.6

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/lib/flow-shape.js CHANGED
@@ -1 +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");
1
+ "use strict";var Z=Object.defineProperty;var x=(a,m)=>Z(a,"name",{value:m,configurable:!0});var _=Object.defineProperty,M=x((a,m)=>_(a,"name",{value:m,configurable:!0}),"k");import{redactDeep as tt,redactText as J}from"./redact.js";import{boundedClone as et}from"@lensmcp/protocol-types";export function areaOf(a){const{source:m,category:r,title:y,kind:c}=a;return m==="ai"?"ai":c?.startsWith("memory")||c==="db-query"?"data":m==="gateway"||c==="gateway-request"?"gateway":c==="queue-process"||c==="queue-active"||c==="queue-completed"||c==="queue-failed"?"services":m==="db"||m==="redis"||m==="queue"||c==="redis-op"||c?.startsWith("queue-")?"data":m==="external"||c==="egress"?"network":m==="nestjs"||m==="nest"?/(?:Repository|Repo|Dao|Store)\./.test(y)?"data":"services":m==="valtio"?"state":r==="network"?"network":"browser"}x(areaOf,"areaOf"),M(areaOf,"areaOf");const U=240,rt=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),st=new Set(["tenantId","caller","userId","accountId","email","subject"]),nt=8;function H(a){const m=z(a,0);return et(tt({redacted:!0,...m}),{rawByteLimit:16*1024}).value}x(H,"tt"),M(H,"aiProjection");function z(a,m){if(typeof a=="string")return Q(a);if(a===null||typeof a!="object")return a;if(m>=nt)return;if(Array.isArray(a))return a.slice(0,32).map(y=>z(y,m+1));const r={};for(const[y,c]of Object.entries(a))if(!st.has(y)){if(rt.has(y)){typeof c=="string"?r[`${y}Chars`]=c.length:Array.isArray(c)?r[`${y}Count`]=c.length:c!=null&&(r[`${y}Present`]=!0);continue}r[y]=z(c,m+1)}return r}x(z,"W"),M(z,"projectAi");function Q(a){return a.length<=U?J(a):`${J(a.slice(0,U))}\u2026`}x(Q,"et"),M(Q,"clipText");export function trimFlowEvent(a,m={}){const r=a.raw??{},y=r.render??{},c=r.span??{},C=r.request??{},l=M(o=>typeof o=="number"?o:void 0,"num"),I=r.loop??{},B=l(r.durationMs)??l(c.durationMs)??l(C.durationMs)??l(I.durationMs)??l(y.actualDurationMs),p=typeof r.kind=="string"?r.kind:void 0,L=p==="fetch-done"||p==="fetch-error",G=L?a.timestamp:l(r.startedAt)??l(c.startTime)??l(C.startedAt)??l(I.startedAt)??(B!==void 0?a.timestamp-B:a.timestamp);let w;if(typeof r.query=="string"){const o=Array.isArray(r.params)?` [${r.params.join(", ")}]`:"",g=typeof r.result=="string"?` \u2192 ${r.result}`:"";w=r.query+o+g}else if(typeof r.command=="string"){const o=typeof r.value=="string"?` \u2192 ${r.value}`:r.hit===!1?" \u2192 (miss)":"";w=r.command+o}else if(p==="state-update"){const o=r.update??{};let g="";try{g=JSON.stringify(o.preview)}catch{}w=`${o.storeId??""}.${o.path??""} = ${g}`}else p==="queue-completed"&&typeof r.returned=="string"?w=`returned ${r.returned}`:p==="queue-enqueued"&&(w=`${r.job??"job"}#${r.jobId??"?"} \u2192 ${r.queue??""}${typeof r.data=="string"?" "+r.data:""}`);let S;if(p==="gateway-request")S=`${r.host??""}${String(r.url??"").split("?")[0]}`;else if(p==="fetch-start"||p==="fetch-done"||p==="fetch-error")try{const o=new URL(String(r.href??r.url??""));S=`${o.hostname}${o.pathname}`}catch{}let D;if(p==="gateway-request"&&Array.isArray(r.steps))D=r.steps.map(o=>{const g=[String(o.step)];return o.project&&g.push(String(o.project)),o.prefix&&g.push(String(o.prefix)),o.mode&&g.push(String(o.mode)+(o.ok===!1?" \u2717":o.ok===!0?" \u2713":"")),o.caller&&g.push("by "+String(o.caller)),o.pod&&g.push(String(o.pod)),typeof o.atMs=="number"&&g.push(`@${o.atMs}ms`),g.join(" ")}),w=D.map(o=>o.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(p==="egress")w=`${r.method??"GET"} ${r.host??""} \u2192 ${r.status??"?"}`;else if(a.source==="ai"){if(p==="ai-round"){const o=r.model??{},g=r.usage??{},v=Array.isArray(r.toolCalls)?r.toolCalls:[],F=`${l(g.promptTokens)??"?"}\u2192${l(g.completionTokens)??"?"} tok`,W=v.length?` \xB7 ${v.length} tool call${v.length===1?"":"s"}`:"",t=l(r.durationMs)!==void 0?` \xB7 ${(l(r.durationMs)/1e3).toFixed(1)}s`:"";w=`${o.provider??""}/${o.model??""} \xB7 ${F}${W}${t}`}else if(p==="ai-turn-start"){const o=Array.isArray(r.tools)?r.tools:[];w=`skill ${r.skill??""} \xB7 ${r.output??""}${o.length?" \xB7 tools: "+o.join(", "):""}`}else if(p==="ai-tool-call"){const o=r.call??{},g=r.result??{},v=l(r.durationMs)!==void 0?` \xB7 ${(l(r.durationMs)/1e3).toFixed(1)}s`:"";w=`${o.name??"tool"} ${g.error!=null?"\u2717 "+String(g.error):"\u2713"}${v}`}else if(p==="ai-turn-end"){const o=r.usage??{},g=l(r.rounds)!==void 0?` \xB7 ${l(r.rounds)} round${l(r.rounds)===1?"":"s"}`:"",v=l(r.durationMs)!==void 0?` \xB7 ${(l(r.durationMs)/1e3).toFixed(1)}s`:"";w=`${r.ok===!1?"FAILED":"ok"} \xB7 ${l(o.promptTokens)??"?"}+${l(o.completionTokens)??"?"} tok${g}${v}`}}let j;p==="db-query"&&typeof r.query=="string"?j=r.query:p==="redis-op"?j=`${r.op??""} ${String(r.key??"").replace(/\d+/g,"#")}`:p==="egress"?j=`${r.method??"GET"} ${r.host??""}`:p==="queue-enqueued"?j=`enqueue ${r.queue??""}`:p==="span"&&typeof c.name=="string"&&(j=c.name);const b=a.context??{},O=r.effect??{},P=y.commitId??O.commitId??r.commitId,K=Array.isArray(y.why)?y.why.map(o=>typeof o?.type=="string"?o.type:void 0).filter(o=>!!o):[];return{id:a.id,t:a.timestamp,start:G,...j?{sig:j}:{},...S?{urlKey:S}:{},...typeof r.queue=="string"?{queue:r.queue}:{},...r.jobId!=null?{jobId:String(r.jobId)}:{},source:a.source,category:a.category,severity:a.severity,title:a.title,kind:p,area:areaOf({source:a.source,category:a.category,title:a.title,kind:p}),...typeof c.role=="string"?{role:c.role}:{},...typeof b.requestId=="string"?{requestId:b.requestId}:{},...typeof b.parentRequestId=="string"?{parentRequestId:b.parentRequestId}:{},...typeof P=="string"?{commitId:P}:{},...typeof y.componentName=="string"?{component:y.componentName}:{},...typeof y.phase=="string"?{phase:y.phase}:{},...K.length?{why:K}:{},...typeof b.projectName=="string"?{project:b.projectName}:typeof r.project=="string"?{project:r.project}:{},...B!==void 0?{durationMs:B}:{},...L&&l(r.startedAt)!==void 0?{fetchStartedAt:l(r.startedAt)}:{},...a.source==="ai"?{ai:m.includeRaw?r:H(r)}:{},...w?{detail:w}:{},...D?{steps:D}:{}}}x(trimFlowEvent,"trimFlowEvent"),M(trimFlowEvent,"trimFlowEvent");const V=1;function X(a){return a==="flow-origin"?0:a?.endsWith("-start")?1:a==="gateway-request"?2:a==="server-request"?3:a==="span"?4:5}x(X,"nt"),M(X,"kindRank");function N(a){return a.kind==="span"&&a.role==="controller"?3.5:a.kind==="queue-process"?3:X(a.kind)}x(N,"O"),M(N,"causalRank");export function buildFlowDetail(a,m={}){const r=a.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 e=s.span;return!(typeof e?.name=="string"&&e.name.startsWith("nest.request "))}).map(t=>trimFlowEvent(t,m)),y=new Set;for(let t=r.length-1;t>=0;t--)y.has(r[t].id)?r.splice(t,1):y.add(r[t].id);const c=new Map;for(const t of r)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&!c.has(t.requestId)&&c.set(t.requestId,t.start);const C=M(t=>t.source!=="react"&&t.source!=="valtio"&&t.requestId&&c.has(t.requestId)?c.get(t.requestId):t.start,"anchorOf");r.sort((t,s)=>C(t)-C(s)||t.start-s.start||N(t)-N(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=r;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 e of I){if(e===t||!l(e)||e.group!==t.group||e.requestId!==n)continue;const i=e.project,d=t.project;if(e.kind!=="gateway-request"&&t.kind!=="gateway-request"&&i!==void 0&&d!==void 0&&i!==d)continue;const q=e.durationMs??0,h=t.durationMs??0,$=Math.abs(e.start-t.start)<=V,u=N(e),k=N(t),T=e.start<=t.start;if(!(e.start+q>t.start&&(T||$&&u<k)&&(!$||(u!==k?u<k:T&&q>h))))continue;const R=s?N(s):-1,A=s?Math.abs(e.start-s.start)<=V:!1;(!s||!A&&e.start>s.start||A&&u>R||A&&u===R&&(e.durationMs??0)<(s.durationMs??0))&&(s=e)}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 L=new Map(I.map(t=>[t.id,t])),G=M((t,s)=>{const n=(p.get(t)??[]).filter(e=>l(e)&&e.start<=s&&e.start+(e.durationMs??0)>=s);if(n.length!==0)return n.sort((e,i)=>i.start-e.start||(e.durationMs??0)-(i.durationMs??0)),n[0]},"callerNodeFor");for(const t of I){if(!t.parentRequestId||t.kind!=="server-request"&&t.kind!=="gateway-request")continue;const s=t.parent?L.get(t.parent):void 0;if(s&&s.requestId===t.requestId)continue;const n=G(t.parentRequestId,t.start);n&&n!==t&&n.start<=t.start&&(t.parent=n.id)}const w=I,S=new Map;for(const t of w)t.kind==="gateway-request"&&t.requestId&&!S.has(t.requestId)&&S.set(t.requestId,t);for(const t of w)if(t.group==="server"&&!t.parent&&t.requestId&&t.kind!=="gateway-request"){const s=S.get(t.requestId);s&&s!==t&&s.start<=t.start&&(t.parent=s.id)}const D=new Set,j=new Set,b=[];for(const t of w){if(t.kind!=="gateway-request")continue;if(!t.requestId){b.push(t);continue}const s=p.get(t.requestId)??[];if(s.filter(i=>i.kind==="gateway-request").sort((i,d)=>i.start-d.start)[0]!==t)continue;const n=s.find(i=>i.kind==="fetch-start"),e=s.find(i=>i.kind==="fetch-done"||i.kind==="fetch-error");if(!n&&!e){b.push(t);continue}n&&(t.fetchStartId=n.id,D.add(n.id)),e&&(t.fetchDoneId=e.id,j.add(e.id))}const O=new Map;for(const t of w){if(!t.urlKey)continue;const s=O.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")&&(j.has(t.id)||s.dones.push(t)),O.set(t.urlKey,s)}for(const{gws:t,starts:s,dones:n}of O.values()){t.sort((i,d)=>i.start-d.start),s.sort((i,d)=>i.start-d.start);const e=new Set;t.forEach((i,d)=>{const q=s[d];q&&(i.fetchStartId=q.id);const h=q?q.t:i.start;let $,u=1/0;for(const k of n){if(e.has(k.id))continue;const T=k.fetchStartedAt??k.start-(k.durationMs??0),R=Math.abs(T-h);R<u&&(u=R,$=k)}$&&(i.fetchDoneId=$.id,e.add($.id))})}const P=new Map,K=new Map;for(const t of w)!t.queue||!t.jobId||(t.kind==="queue-enqueued"&&P.set(`${t.queue}#${t.jobId}`,t),t.kind==="queue-process"&&K.set(`${t.queue}#${t.jobId}`,t));for(const t of w){if(!t.queue||!t.jobId)continue;const s=`${t.queue}#${t.jobId}`;if(t.kind==="queue-process"&&!t.parent){const n=P.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=K.get(s);n&&n!==t&&n.start<=t.start&&(t.parent=n.id)}}let o=I;{const t=new Map;for(const n of o)n.kind==="fetch-start"&&t.set(n.id,n);const s=new Map;for(const n of o){if(n.kind!=="fetch-done"&&n.kind!=="fetch-error")continue;const e=[...t.values()].find(q=>q.requestId&&q.requestId===n.requestId)?.id,i=e?t.get(e):void 0;if(!i)continue;const d=n.fetchStartedAt??i.start;i.title=n.title,i.severity=n.severity,i.durationMs=n.durationMs??Math.max(0,n.t-d),i.kind="fetch",n.detail&&!i.detail&&(i.detail=n.detail),s.set(n.id,i.id)}if(s.size>0){o=o.filter(n=>!s.has(n.id));for(const n of o)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 g=M(t=>!!t.commitId&&(t.kind==="render"||t.kind==="effect-run"),"commitMember"),v=[],F=new Map;for(let t=0;t<o.length;){const s=o[t];if(!g(s)){v.push(s),t+=1;continue}let n=t+1;for(;n<o.length;){const f=o[n];if(!g(f)||f.commitId!==s.commitId)break;n+=1}const e=o.slice(t,n);if(t=n,e.length<2){v.push(...e);continue}const i=e.filter(f=>f.kind==="render"),d=e.filter(f=>f.kind==="effect-run"),q=i.filter(f=>!(f.why??[]).includes("parent-render")),h=[...new Set(q.flatMap(f=>f.why??[]))],$=[...new Set(q.map(f=>f.component).filter(Boolean))],u=[...new Set(i.map(f=>f.component).filter(Boolean))],k=Math.min(...e.map(f=>f.start)),T=Math.max(...e.map(f=>f.start+(f.durationMs??0))),R=$.length===1?$[0]:$.length>1?`${$.length} roots`:u[0]??"view",A=h.length===1?h[0]:h.length>1?h.join(" + "):void 0,Y=i.some(f=>f.phase==="mount"),E={...s,kind:"view-update",title:`view update \xB7 ${R}${A?` \u2190 ${A}`:""}`,start:k,durationMs:T-k,commitId:s.commitId,cause:A,components:u,effects:d.length,memberIds:e.map(f=>f.id),sig:`commit:${A??"-"}:${$.join(",")}:${u.slice().sort().join(",")}`,detail:[`${u.length} component${u.length===1?"":"s"}${Y?" (mount)":""}`,d.length?`${d.length} effect${d.length===1?"":"s"}`:"",u.join(", ")].filter(Boolean).join(" \xB7 "),severity:e.some(f=>f.severity==="error")?"error":s.severity};delete E.component,delete E.why,delete E.phase;for(const f of e)f.id!==E.id&&F.set(f.id,E.id);v.push(E)}if(F.size>0){o=v;for(const t of o)for(;t.parent&&F.has(t.parent);)t.parent=F.get(t.parent)}for(let t=1;t<o.length;t++){const s=o[t-1],n=o[t];n.kind!=="view-update"||s.kind!=="view-update"||n.sig&&n.sig===s.sig&&(s.redundant=!0,n.redundant=!0)}{const t=new Map(o.map(s=>[s.id,s]));for(const s of o){const n=new Set([s.id]);let e=s;for(;e?.parent;){if(n.has(e.parent)){e.parent=void 0;break}n.add(e.parent),e=t.get(e.parent)}}}const W=M(t=>{const s=new Map;for(const e of o){if(!e.sig||l(e)!==t||e.kind==="server-request"||e.kind==="gateway-request")continue;const i=`${e.parent??"root"}|${e.kind}|${e.sig}`,d=s.get(i);d?d.push(e):s.set(i,[e])}const n=new Map;for(const e of s.values()){if(e.length<3)continue;e.sort((u,k)=>u.start-k.start);const i=e[0];let d=!1;for(let u=0;u+1<e.length;u++)if(e[u+1].start<e[u].start+(e[u].durationMs??0)){d=!0;break}const q=i.start,h=Math.max(...e.map(u=>u.start+(u.durationMs??0))),$=e.reduce((u,k)=>u+(k.durationMs??0),0);if(i.count=e.length,i.parallel=d,i.avgMs=Math.round($/e.length*10)/10,i.wallMs=h-q,i.durationMs=h-q,i.title=`\xD7${e.length} ${i.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,i.kind==="view-update"){const u=i.redundant===!0;i.detail=[`${e.length} commits \xB7 avg ${i.avgMs}ms \xB7 wall ${i.wallMs}ms`,u?`no state change between them \u2014 ${e.length-1} of these had nothing new to render`:"one per update \u2014 expected for this many changes",i.components?.join(", ")??""].filter(Boolean).join(" \xB7 ")}else i.detail=`${i.sig} \xD7${e.length} ${d?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${i.avgMs}ms \xB7 wall ${i.wallMs}ms`;i.items=e.slice(0,12).map(u=>({start:u.start-q,...u.durationMs!=null?{durationMs:u.durationMs}:{}})),i.memberIds=e.flatMap(u=>u.memberIds??[u.id]),e.some(u=>u.severity==="error")&&(i.severity="error");for(const u of e.slice(1))n.set(u.id,i.id)}if(n.size!==0){o=o.filter(e=>!n.has(e.id));for(const e of o)for(;e.parent&&n.has(e.parent);)e.parent=n.get(e.parent)}},"aggregatePass");W(!0),W(!1);for(const t of o){if(!l(t))continue;const s=t.durationMs??0;if(s<40)continue;const n=o.filter(h=>h.parent===t.id&&(h.durationMs??0)>0).map(h=>[h.start,h.start+(h.durationMs??0)]).sort((h,$)=>h[0]-$[0]);let e=0,i=-1,d=-1;for(const[h,$]of n)h>d?(d>i&&(e+=d-i),i=h,d=$):$>d&&(d=$);d>i&&(e+=d-i);const q=Math.max(0,s-e);(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:o}}x(buildFlowDetail,"buildFlowDetail"),M(buildFlowDetail,"buildFlowDetail");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/core",
3
- "version": "1.22.5",
3
+ "version": "1.22.6",
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.5",
22
+ "@lensmcp/protocol-types": "1.22.6",
23
23
  "tslib": "^2.3.0"
24
24
  },
25
25
  "license": "Apache-2.0",