@lensmcp/core 1.25.37 → 1.25.38
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/ai-content.js +1 -1
- package/lib/answer-budget.d.ts +13 -1
- package/lib/answer-budget.js +2 -2
- package/lib/bus-rotation.js +1 -1
- package/lib/event-bus.js +1 -1
- package/lib/event-loop-history.js +1 -1
- package/lib/event-loop.js +1 -1
- package/lib/event-redactor.js +1 -1
- package/lib/fingerprint.js +1 -1
- package/lib/flow-categories.js +1 -1
- package/lib/flow-segments.js +1 -1
- package/lib/flow-shape.js +1 -1
- package/lib/flows-config.js +1 -1
- package/lib/graph-from-events.js +1 -1
- package/lib/graph-store.js +1 -1
- package/lib/headless-flow.js +1 -1
- package/lib/http-exchange.js +1 -1
- package/lib/http-shape.js +1 -1
- package/lib/key-pattern.js +1 -1
- package/lib/lens-dir.js +1 -1
- package/lib/lens-events.js +2 -2
- package/lib/patterns.js +1 -1
- package/lib/pg-errors.js +1 -1
- package/lib/redact.js +1 -1
- package/lib/redis-expiry.js +1 -1
- package/lib/reducer-registry.js +1 -1
- package/lib/replay-store.js +1 -1
- package/lib/resource-store.js +1 -1
- package/lib/route-template.js +1 -1
- package/lib/service-hop.js +1 -1
- package/lib/sql-shape.js +3 -3
- package/lib/sql-values.js +1 -1
- package/lib/stores.js +2 -2
- package/lib/story.js +1 -1
- package/lib/thresholds.js +1 -1
- package/lib/ulid.js +1 -1
- package/package.json +2 -2
package/lib/ai-content.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var a=Object.defineProperty;var r=(t,i)=>a(t,"name",{value:i,configurable:!0});var s=Object.defineProperty,n=r((t,i)=>s(t,"name",{value:i,configurable:!0}),"r");import*as c from"node:fs";import{dirname as l,join as o}from"node:path";export const AI_CONTENT_DIR="ai";const d=/^ai_[0-9a-z]{8,40}$/;export const isAiCallId=n(t=>typeof t=="string"&&d.test(t),"isAiCallId");export function aiContentDir(t){return o(l(t),AI_CONTENT_DIR)}r(aiContentDir,"aiContentDir"),n(aiContentDir,"aiContentDir");export function aiContentFile(t,i){if(!isAiCallId(i))throw new Error("invalid ai call id");return o(aiContentDir(t),`${i}.json`)}r(aiContentFile,"aiContentFile"),n(aiContentFile,"aiContentFile");export function readAiContent(t,i){if(isAiCallId(i))try{const e=JSON.parse(c.readFileSync(aiContentFile(t,i),"utf8"));return e&&e.schemaVersion===1&&e.id===i?e:void 0}catch{return}}r(readAiContent,"readAiContent"),n(readAiContent,"readAiContent");
|
package/lib/answer-budget.d.ts
CHANGED
|
@@ -100,6 +100,8 @@ export interface AnswerCut {
|
|
|
100
100
|
repeatedStrings: number;
|
|
101
101
|
/** Cutting lists was not enough: large values elsewhere in the document were shrunk too. */
|
|
102
102
|
clamped?: true;
|
|
103
|
+
/** The values it holds that were sent whole, whatever the budget ({@link AnswerFitOptions.whole}). */
|
|
104
|
+
whole?: string[];
|
|
103
105
|
note: string;
|
|
104
106
|
}
|
|
105
107
|
export interface AnswerFitOptions {
|
|
@@ -107,6 +109,15 @@ export interface AnswerFitOptions {
|
|
|
107
109
|
more?: string;
|
|
108
110
|
/** Per top-level list: the end that holds its newest items, for a ring whose items carry no time. */
|
|
109
111
|
newest?: Readonly<Record<string, ListEnd>>;
|
|
112
|
+
/**
|
|
113
|
+
* Values never cut, by their path of keys from the document's root (`result.role.rules`): text an agent acts on only
|
|
114
|
+
* as a whole — its own guide, whose head it would otherwise take for all of it (issues/closed/foodguard-116). Their
|
|
115
|
+
* bytes are spent first, the rest of the document is fitted into what they leave (at least
|
|
116
|
+
* {@link MIN_ANSWER_BUDGET_BYTES}), and they go back as they were — so values that alone outgrow the budget take the
|
|
117
|
+
* answer over it: bound them where they are made. A path that is not there, or that passes through a list, holds
|
|
118
|
+
* nothing.
|
|
119
|
+
*/
|
|
120
|
+
whole?: readonly string[];
|
|
110
121
|
}
|
|
111
122
|
/**
|
|
112
123
|
* Fit a whole answer into the budget.
|
|
@@ -114,7 +125,8 @@ export interface AnswerFitOptions {
|
|
|
114
125
|
* An answer that fits is returned as it is, the SAME value. Over the budget, its top-level lists
|
|
115
126
|
* are cut ({@link fitList}; small lists whole, large ones sharing what the rest of the document
|
|
116
127
|
* leaves), and the result carries {@link ANSWER_CUT_KEY} as its first key. A document that is
|
|
117
|
-
* large somewhere other than a list is shrunk by the event clamp, which keeps its shape.
|
|
128
|
+
* large somewhere other than a list is shrunk by the event clamp, which keeps its shape. What
|
|
129
|
+
* `whole` names is set aside before any of it, and goes back as it was.
|
|
118
130
|
*/
|
|
119
131
|
export declare function fitAnswer<T>(value: T, budgetBytes: number, opts?: AnswerFitOptions): {
|
|
120
132
|
value: T;
|
package/lib/answer-budget.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`,
|
|
1
|
+
"use strict";var U=Object.defineProperty;var y=(e,r)=>U(e,"name",{value:r,configurable:!0});var Y=Object.defineProperty,p=y((e,r)=>Y(e,"name",{value:r,configurable:!0}),"u");import{boundedClone as z}from"@lensmcp/protocol-types";export const DEFAULT_ANSWER_BUDGET_BYTES=24*1024,ANSWER_BUDGET_ENV="LENSMCP_ANSWER_BUDGET_BYTES",MIN_ANSWER_BUDGET_BYTES=2*1024,ANSWER_CUT_KEY="cutToFit",FITTED_STRING_CHARS=1500,REPEATED_STRING_MIN_CHARS=200;const R=900,V=32,H=new Set(["timestamp","startedAt","startTime","at","emittedAt","lastSeenAt","endedAt","endTime","t","ts","time"]),J=p(e=>typeof e=="number"&&e>=1e11&&e<=1e14,"isEpochMs"),K=.95;export function answerBudgetBytes(e=process.env){const r=e[ANSWER_BUDGET_ENV];if(r===void 0||r.trim()==="")return DEFAULT_ANSWER_BUDGET_BYTES;const t=Number(r);return!Number.isFinite(t)||t<0?DEFAULT_ANSWER_BUDGET_BYTES:t===0?Number.POSITIVE_INFINITY:Math.max(MIN_ANSWER_BUDGET_BYTES,Math.floor(t))}y(answerBudgetBytes,"answerBudgetBytes"),p(answerBudgetBytes,"answerBudgetBytes");export function utf8Bytes(e){let r=0;for(let t=0;t<e.length;t++){const s=e.charCodeAt(t);s<128?r+=1:s<2048?r+=2:s>=55296&&s<=56319&&t+1<e.length&&(e.charCodeAt(t+1)&64512)===56320?(r+=4,t+=1):r+=3}return r}y(utf8Bytes,"utf8Bytes"),p(utf8Bytes,"utf8Bytes");export function jsonBytes(e){let r;try{r=JSON.stringify(e)}catch{return Number.POSITIVE_INFINITY}return r===void 0?0:utf8Bytes(r)}y(jsonBytes,"jsonBytes"),p(jsonBytes,"jsonBytes");const C=p(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isRecord");function _(e){if(!C(e))return!1;const r=Object.getPrototypeOf(e);return r===Object.prototype||r===null}y(_,"O"),p(_,"isPlain");export function newestEndOf(e){const r=e[0];if(e.length<2||!C(r))return;let t;for(const s of Object.keys(r)){if(typeof r[s]!="number"||!(H.has(s)||J(r[s])))continue;let i=0,a=0,u=!0,c=r[s];for(let w=1;w<e.length;w++){const S=e[w],m=C(S)?S[s]:void 0;if(typeof m!="number"){u=!1;break}m>c?i+=1:m<c&&(a+=1),c=m}const o=i+a;if(!u||o===0)continue;const f=Math.max(i,a)/o;f>=K&&(!t||f>t.agreement)&&(t={end:i>=a?"end":"start",agreement:f})}return t?.end}y(newestEndOf,"newestEndOf"),p(newestEndOf,"newestEndOf");export function newestFirst(e){return newestEndOf(e)==="end"?[...e].reverse():e.slice()}y(newestFirst,"newestFirst"),p(newestFirst,"newestFirst");export function shortenText(e,r){if(e.length<=r)return e;let t=Math.max(0,r);const s=e.lastIndexOf(`
|
|
2
|
+
`,t);return s>=t/2&&(t=s),t>0&&(e.charCodeAt(t-1)&64512)===55296&&(t-=1),`${e.slice(0,t)}\u2026[lensmcp truncated: ${e.length-t} more chars]`}y(shortenText,"shortenText"),p(shortenText,"shortenText");export function fitList(e,r,t={}){const s=e.length,i=e.reduce((l,k)=>l+jsonBytes(k)+1,2);if(i<=r)return{items:e.slice(),total:s,returned:s,kept:"all",shortenedStrings:0,repeatedStrings:0,bytes:i};const a=t.newest??newestEndOf(e),u=a??t.keep??"start",c=t.name??"items",o=t.maxStringChars??FITTED_STRING_CHARS,f=u==="start"?e:[...e].reverse(),w=String(Math.max(0,s-1)).length,S=new Map,m=[],b=[];let $=2,B=0,T=0;for(let l=0;l<f.length;l++){const k=new Map,E=[];let M=0;const n=p((h,I,j,G,L)=>{if(typeof h=="string"){if(h.length>=REPEATED_STRING_MIN_CHARS){const x=S.get(h)??k.get(h);if(x)return E.push({holder:G,key:L,owner:x.owner,path:x.path}),`\u2026[lensmcp: same text as ${c}[${"9".repeat(w)}]${x.path}]`;k.set(h,{owner:l,path:I})}return h.length>o?(M+=1,shortenText(h,o)):h}if(j>=V)return h;if(Array.isArray(h)){const x=[];return h.forEach((N,W)=>x.push(n(N,`${I}[${W}]`,j+1,x,W))),x}if(_(h)){const x={};for(const N of Object.keys(h))x[N]=n(h[N],`${I}.${N}`,j+1,x,N);return x}return h},"slim"),d=[];let g=n(f[l],"",0,d,0),O=jsonBytes(g)+1;if(b.length===0&&$+O>r)g=F(f[l],Math.max(0,r-$-1)),O=jsonBytes(g)+1,E.length=0,k.clear(),M=1;else if($+O>r)break;b.push(g),$+=O,B+=M,T+=E.length;for(const[h,I]of k)S.set(h,I);for(const h of E)m.push(h.holder===d?{...h,holder:b,key:b.length-1}:h)}const A=b.length,v=p(l=>u==="start"?l:A-1-l,"indexOf");if(u==="end"){for(const l of m)l.holder===b&&(l.key=v(l.key));b.reverse()}for(const l of m)l.holder[l.key]=`\u2026[lensmcp: same text as ${c}[${v(l.owner)}]${l.path}]`;return{items:b,total:s,returned:A,kept:A===s?"all":a?"newest":u==="start"?"first":"last",shortenedStrings:B,repeatedStrings:T,bytes:jsonBytes(b)}}y(fitList,"fitList"),p(fitList,"fitList");function F(e,r){let t=Math.max(256,r),s=e;for(let i=0;i<6;i++){if(s=z(e,{rawByteLimit:t,maxStringBytes:Math.min(2e3,Math.max(128,Math.floor(t/4))),maxArrayItems:64}).value,jsonBytes(s)<=r)return s;t=Math.floor(t*.6)}return s}y(F,"W"),p(F,"clampTo");export function shareBudget(e,r){const t=e.map((a,u)=>({size:a,index:u})).sort((a,u)=>a.size-u.size),s=new Array(e.length).fill(0);let i=Math.max(0,r);return t.forEach(({size:a,index:u},c)=>{const o=Math.floor(i/(t.length-c));s[u]=Math.min(a,o),i-=s[u]}),s}y(shareBudget,"shareBudget"),p(shareBudget,"shareBudget");function P(e,r){const t={...e},s=new WeakSet([t]),i=[];let a=0;for(const u of r){const c=u.split("."),o=c[c.length-1];let f=t;for(const w of c.slice(0,-1)){const S=f[w];if(!_(S)){f=void 0;break}const m=s.has(S)?S:{...S};s.add(m),f[w]=m,f=m}!f||f[o]===void 0||f[o]===null||(i.push({keys:c,value:f[o]}),a+=jsonBytes(f[o]),f[o]=null)}return i.length?{body:t,parts:i,bytes:a}:void 0}y(P,"K"),p(P,"holdWhole");function D(e,r){for(const{keys:t,value:s}of r){let i=e;for(const a of t.slice(0,-1)){const u=i[a],c=_(u)?u:{};i[a]=c,i=c}i[t[t.length-1]]=s}return e}y(D,"z"),p(D,"putBack");export function fitAnswer(e,r,t={}){if(!Number.isFinite(r)||e===null||typeof e!="object")return{value:e};const s=jsonBytes(e);if(s<=r)return{value:e};const i=t.whole?.length&&_(e)?P(e,t.whole):void 0,a=i?i.body:e,u=i?jsonBytes(a):s,c=i?Math.max(MIN_ANSWER_BUDGET_BYTES,r-i.bytes):r;if(u<=c)return{value:e};const o={limitBytes:r,originalBytes:s,lists:[],shortenedStrings:0,repeatedStrings:0,...i?{whole:i.parts.map(n=>n.keys.join("."))}:{},note:""},f=p(()=>{const n=o.lists.map(d=>`\`${d.list}\` shows the ${d.kept} ${d.returned} of ${d.total}`);o.note=`Cut to fit one tool result (${r} bytes; the whole answer is ${Number.isFinite(s)?s:"larger"}) \u2014 it is still one valid JSON document.`+(n.length?` ${n.join("; ")}; any other count in this document describes the whole list.`:"")+(o.shortenedStrings?` ${o.shortenedStrings} long text${o.shortenedStrings===1?" was":"s were"} cut to the head.`:"")+(o.repeatedStrings?` ${o.repeatedStrings} repeated text${o.repeatedStrings===1?" is":"s are"} stated once and referenced.`:"")+(o.clamped?" Large values outside the lists were shrunk too (see `__lensmcpTruncation`).":"")+(o.whole?` Never cut: ${o.whole.map(d=>`\`${d}\``).join(", ")} \u2014 sent whole.`:"")+(t.more?` ${t.more}`:"")+` Whole answer: start the lens with ${ANSWER_BUDGET_ENV}=0.`},"describe"),w=p(n=>({value:i?D(n,i.parts):n,cut:o}),"done");if(Array.isArray(a)){const n=fitList(a,c);return n.kept!=="all"&&o.lists.push({list:"items",total:n.total,returned:n.returned,kept:n.kept}),o.shortenedStrings=n.shortenedStrings,o.repeatedStrings=n.repeatedStrings,f(),w(n.items)}if(!_(a))return{value:e};const S=Object.keys(a),m=S.filter(n=>Array.isArray(a[n])&&a[n].length>0),b=m.map(n=>jsonBytes(a[n])),$=u-b.reduce((n,d)=>n+d,0),B=shareBudget(b,c-$-R),T={};m.forEach((n,d)=>{if(b[d]<=B[d])return;const g=fitList(a[n],B[d],{name:n,...t.newest?.[n]?{newest:t.newest[n]}:{}});T[n]=g.items,g.kept!=="all"&&o.lists.push({list:n,total:g.total,returned:g.returned,kept:g.kept}),o.shortenedStrings+=g.shortenedStrings,o.repeatedStrings+=g.repeatedStrings});const A=p(n=>(f(),{[ANSWER_CUT_KEY]:o,...n}),"assemble"),v={};for(const n of S)v[n]=n in T?T[n]:a[n];let l=A(v);if(jsonBytes(l)<=c)return w(l);o.clamped=!0;let k=Math.max(512,c-R);for(let n=0;n<6;n++){if(l=A(F(v,k)),jsonBytes(l)<=c)return w(l);k=Math.floor(k*.6)}const E={};let M=R;for(const n of S){const d=a[n];if(d!==null&&typeof d=="object")continue;const g=jsonBytes(d)+utf8Bytes(n)+4;if(M+g>c)break;E[n]=d,M+=g}return w(A(E))}y(fitAnswer,"fitAnswer"),p(fitAnswer,"fitAnswer");
|
package/lib/bus-rotation.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var l=Object.defineProperty;var i=(t,r)=>l(t,"name",{value:r,configurable:!0});var S=Object.defineProperty,u=i((t,r)=>S(t,"name",{value:r,configurable:!0}),"u");export const MAX_BUS_GENERATIONS=20,BUS_ROTATE_CHECK_BYTES=1048576;export function busCapsFromEnv(t=process.env){const r=Number(t.LENSMCP_EVENT_MAX_BYTES),e=Number(t.LENSMCP_EVENT_MAX_FILES);return{maxBytes:Number.isFinite(r)&&r>0?r:50*1024*1024,maxFiles:Number.isFinite(e)&&e>=1&&e<=20?Math.floor(e):5}}i(busCapsFromEnv,"busCapsFromEnv"),u(busCapsFromEnv,"busCapsFromEnv");export function rotateBusFile(t,r){const{fs:e,maxBytes:y,maxFiles:a}=r,n=`${t}.rotate.lock`,o=r.staleLockMs??3e4;let s;for(let c=0;c<2&&s===void 0;c++)try{s=e.openSync(n,"wx")}catch{try{if(Date.now()-e.statSync(n).mtimeMs<=o)return"busy";e.unlinkSync(n)}catch{}}if(s===void 0)return"busy";try{try{if(e.statSync(t).size<=y)return"not-needed"}catch{return"not-needed"}try{e.unlinkSync(`${t}.${a}`)}catch{}for(let c=a+1;c<=20;c++)try{e.unlinkSync(`${t}.${c}`)}catch{}for(let c=a-1;c>=1;c--)try{e.renameSync(`${t}.${c}`,`${t}.${c+1}`)}catch{}try{e.renameSync(t,`${t}.1`)}catch{}return"rotated"}finally{try{e.closeSync(s)}catch{}try{e.unlinkSync(n)}catch{}}}i(rotateBusFile,"rotateBusFile"),u(rotateBusFile,"rotateBusFile");export function createBusRotator(t,r){const{fs:e,maxBytes:y}=r,a=Math.max(0,Math.min(r.checkEveryBytes??1048576,y));let n=a,o=0;return s=>{if(n>=a||o+n>y)try{o=e.statSync(t).size,n=0,o>y&&rotateBusFile(t,r)==="rotated"&&(o=0)}catch{}n+=s}}i(createBusRotator,"createBusRotator"),u(createBusRotator,"createBusRotator");
|
package/lib/event-bus.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var o=Object.defineProperty;var n=(e,t)=>o(e,"name",{value:t,configurable:!0});var c=Object.defineProperty,h=n((e,t)=>c(e,"name",{value:t,configurable:!0}),"e");export class EventBus{static{n(this,"EventBus")}static{h(this,"EventBus")}constructor(t={}){this.subs=new Set,this.dropped=0,this.capacity=t.capacity??1e4,this.onDrop=t.onDrop,this.transform=t.transform}publish(t){if(this.subs.size>this.capacity){this.dropped++,this.onDrop?.(1);return}let s=t;if(this.transform)try{s=this.transform(t)??t}catch{s=t}for(const r of this.subs)if(!(r.filter&&!r.filter(s)))try{const i=r.handler(s);i&&typeof i.then=="function"&&i.catch(()=>{})}catch{}}subscribe(t,s){const r={handler:t,filter:s};return this.subs.add(r),()=>{this.subs.delete(r)}}droppedCount(){return this.dropped}subscriberCount(){return this.subs.size}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=Object.defineProperty;var m=(n,e)=>d(n,"name",{value:e,configurable:!0});var g=Object.defineProperty,p=m((n,e)=>g(n,"name",{value:e,configurable:!0}),"u");import{LOOP_STARTUP_MS as x,loopStartedAt as v}from"@lensmcp/protocol-types";export const LOOP_SAMPLE_MS=5e3,LOOP_ROLLUP_MS=3e5,LOOP_SAMPLE_HOURS=6;const O=720,h=p(n=>typeof n=="number"&&Number.isFinite(n)&&n>=0,"finite");export function parseLoopSamples(n){if(!Array.isArray(n))return[];const e=new Map;for(const a of n.slice(-O)){if(!Array.isArray(a)||a.length<5)continue;const[o,s,t,r,i]=a;!h(o)||o<=0||!h(s)||!h(t)||!h(r)||!h(i)||e.set(o,[o,s,t,r,Math.min(1,i)])}return[...e.values()].sort((a,o)=>a[0]-o[0])}m(parseLoopSamples,"parseLoopSamples"),p(parseLoopSamples,"parseLoopSamples");export const rollupOf=p(n=>({at:n[0],n:1,meanSum:n[1],p99:n[2],max:n[3],utilSum:n[4]}),"rollupOf");export function bucketRollups(n,e){const a=Math.max(1,Math.floor(e)),o=new Map;for(const t of n){if(!(t.n>0))continue;const r=Math.floor(t.at/a)*a,i=o.get(r);i?(i.n+=t.n,i.meanSum+=t.meanSum,i.utilSum+=t.utilSum,i.p99=Math.max(i.p99,t.p99),i.max=Math.max(i.max,t.max)):o.set(r,{...t,at:r})}const s=p((t,r)=>Number(t.toFixed(r)),"round");return[...o.values()].sort((t,r)=>t.at-r.at).map(t=>[t.at,s(t.meanSum/t.n,2),s(t.p99,2),s(t.max,2),s(t.utilSum/t.n,4)])}m(bucketRollups,"bucketRollups"),p(bucketRollups,"bucketRollups");const S=[5,10,15,30,60,120,300,600,900,1800,3600,7200,21600,43200,86400].map(n=>n*1e3);export function historyStep(n,e){const a=Math.max(e.minMs,e.requestedMs??0,n/(e.maxPoints??400));return S.find(o=>o>=a&&o%e.minMs===0)??S[S.length-1]}m(historyStep,"historyStep"),p(historyStep,"historyStep");export function historySource(n,e,a=LOOP_SAMPLE_HOURS){return n>=e-a*36e5-6e4?"samples":"rollups"}m(historySource,"historySource"),p(historySource,"historySource");export function bucketStalls(n,e){const a=Math.max(1,Math.floor(e)),o=new Map;for(const s of n){const t=Math.floor(s.startAt/a)*a,r=v(s.loopId),i=r!==void 0&&s.startAt<r+x,l=`${s.loopId}\0${t}\0${i}`,u=o.get(l);u?(u.count++,u.longestMs=Math.max(u.longestMs,s.durationMs),u.unresponsive||=s.unresponsive):o.set(l,{loopId:s.loopId,project:s.project,runtime:s.runtime,at:t,count:1,longestMs:s.durationMs,unresponsive:s.unresponsive,...i?{startup:!0}:{}})}return[...o.values()].sort((s,t)=>s.at-t.at||s.loopId.localeCompare(t.loopId)||+!!s.startup-+!!t.startup)}m(bucketStalls,"bucketStalls"),p(bucketStalls,"bucketStalls");export class LoopSampleRing{static{m(this,"LoopSampleRing")}static{p(this,"LoopSampleRing")}constructor(e=36e5,a=4e4){this.keepMs=e,this.maxSamples=a,this.rings=new Map,this.total=0,this.touches=0}add(e,a,o=Date.now()){const s=o-this.keepMs;let t=this.rings.get(e.id),r=0;for(const i of a){if(i[0]<s)continue;t||this.rings.set(e.id,t={loop:e,samples:[],touched:0});const l=t.samples,u=l[l.length-1];if(!u||i[0]>u[0])l.push(i);else{let c=0,f=l.length;for(;c<f;){const M=c+f>>1;l[M][0]<i[0]?c=M+1:f=M}if(l[c]?.[0]===i[0])continue;l.splice(c,0,i)}r++}return t&&r&&(t.loop=e,t.touched=++this.touches,this.total+=r),this.trim(s),r}read(e,a,o=Date.now()){this.trim(o-this.keepMs);const s=[];for(const t of this.rings.values()){const r=t.samples.filter(i=>i[0]>=e&&i[0]<a);r.length&&s.push({loop:t.loop,samples:r})}return s}get size(){return this.total}trim(e){for(const[a,o]of this.rings){let s=0;for(;s<o.samples.length&&o.samples[s][0]<e;)s++;s&&(o.samples.splice(0,s),this.total-=s),o.samples.length||this.rings.delete(a)}if(!(this.total<=this.maxSamples))for(const a of[...this.rings.values()].sort((o,s)=>o.touched-s.touched)){if(this.total<=this.maxSamples)break;this.total-=a.samples.length,this.rings.delete(a.loop.id)}}}
|
package/lib/event-loop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var M=Object.defineProperty;var u=(n,e)=>M(n,"name",{value:e,configurable:!0});var k=Object.defineProperty,l=u((n,e)=>k(n,"name",{value:e,configurable:!0}),"u");import{LoopSampleRing as S,parseLoopSamples as L}from"./event-loop-history.js";const v=l(n=>n&&typeof n=="object"&&!Array.isArray(n)?n:{},"object"),o=l(n=>typeof n=="number"&&Number.isFinite(n)&&n>=0?n:void 0,"number"),s=l((n,e=250)=>typeof n=="string"&&n?n.slice(0,e):void 0,"text"),T=40;export function eventLoopIdentity(n){const e=v(n),t=s(e.id),i=s(e.project);if(!(!t||!i||e.runtime!=="node"&&e.runtime!=="browser"))return{id:t,project:i,runtime:e.runtime,...o(e.pid)!==void 0?{pid:o(e.pid)}:{},...o(e.threadId)!==void 0?{threadId:o(e.threadId)}:{},...s(e.tabId)?{tabId:s(e.tabId)}:{},...s(e.loadId)?{loadId:s(e.loadId)}:{}}}u(eventLoopIdentity,"eventLoopIdentity"),l(eventLoopIdentity,"eventLoopIdentity");export function eventLoopIncident(n){const e=v(n.raw);if(e.kind!=="event-loop-stall")return;const t=eventLoopIdentity(e.loop),i=o(e.startedAt),d=o(e.durationMs),r=e.mechanism;if(!t||i===void 0||d===void 0||!["callback","heartbeat","long-animation-frame","longtask"].includes(String(r)))return;const h=e.state==="unresponsive"?"unresponsive":e.state==="unknown"?"unknown":"recovered",p=[];for(const g of Array.isArray(e.scripts)?e.scripts.slice(0,8):[]){const c=v(g),f=s(c.url,512);f&&p.push({url:f,durationMs:o(c.durationMs)??0,startAt:o(c.startAt)??i,...s(c.functionName)?{functionName:s(c.functionName)}:{},...s(c.invoker)?{invoker:s(c.invoker)}:{}})}const m=r==="callback"?s(n.context?.flowId):void 0;return{id:s(e.incidentId)??n.id,loop:t,startAt:i,durationMs:d,observedAt:n.timestamp,...h==="recovered"?{endAt:i+d}:{},state:h,mechanism:r,severity:d>=1e3?"error":"warning",...m?{flowId:m}:{},...s(n.context?.requestId)?{requestId:s(n.context?.requestId)}:{},...s(e.callbackType)?{callbackType:s(e.callbackType)}:{},scripts:p,evidence:[],evidenceTruncated:e.scriptsTruncated===!0||(o(e.droppedIncidents)??0)>0||(o(e.floodSuppressed)??0)>0,explanation:r==="callback"?"Synchronous callback wall time, including any GC or process descheduling. Execution context identifies the flow; overlapping operations are not proven causes.":r==="heartbeat"?"The loop missed its heartbeat. The observer cannot identify executing code; overlapping work may have been delayed.":"Browser-measured main-thread work. Script timings identify contributing scripts where supported; overlapping flows are associated by time only."}}u(eventLoopIncident,"eventLoopIncident"),l(eventLoopIncident,"eventLoopIncident");export class EventLoopIndex{static{u(this,"EventLoopIndex")}static{l(this,"EventLoopIndex")}constructor(e=()=>{},t=()=>{}){this.onChange=e,this.onSamples=t,this.incidents=new Map,this.loops=new Map,this.recent=[],this.history=new S}ingest(e){const t=v(e.raw),i=s(t.kind)??e.source,d=eventLoopIdentity(t.loop);if(d){const a=this.loops.get(d.id);if(!a||e.timestamp>=a.lastSeen)for(this.loops.set(d.id,{loop:d,lastSeen:e.timestamp,state:t.state==="unresponsive"?"unresponsive":t.state==="unknown"?"unknown":"observed",coverage:s(t.coverage,500)??a?.coverage??(d.runtime==="node"?"Instrumented Node thread":"Browser main thread; supported PerformanceObserver entries"),...a?{meanMs:a.meanMs,maxMs:a.maxMs,p99Ms:a.p99Ms,utilization:a.utilization}:{},...o(t.lagMs)!==void 0?{meanMs:o(t.lagMs),maxMs:o(t.maxMs),p99Ms:o(t.p99Ms),utilization:o(t.utilization)}:{}});this.loops.size>200;)this.loops.delete(this.loops.keys().next().value);if(i==="event-loop-lag"){const I=L(t.samples);I.length&&(this.history.add(d,I),this.onSamples(d,I))}}const r=eventLoopIncident(e);if(r){const a=this.incidents.get(r.id);if(a&&a.observedAt>r.observedAt)return;a&&(r.evidence=a.evidence.slice(),r.evidenceTruncated||=a.evidenceTruncated);for(const I of this.recent)this.attach(r,I);for(this.incidents.set(r.id,r);this.incidents.size>200;)this.incidents.delete(this.incidents.keys().next().value);this.onChange(r);return}if(i.startsWith("event-loop-"))return;const h=s(t.loopId);if(!h)return;const p=v(t.span),m=v(t.request),g=v(t.render),c=o(t.durationMs)??o(p.durationMs)??o(m.durationMs)??o(g.actualDurationMs)??0,f=o(t.startedAt)??o(p.startTime)??o(m.startedAt)??e.timestamp-c,w=o(p.syncDurationMs),b=o(p.syncStartedAt),y=w!==void 0&&w>=50&&b!==void 0,x={loopId:h,eventId:e.id,title:(e.title??i).slice(0,250),kind:i,startAt:y?b:f,endAt:y?b+w:f+c,...e.context?.flowId?{flowId:e.context.flowId}:{},...e.context?.requestId?{requestId:e.context.requestId}:{},relation:y?"executing":"overlap"};this.recent.push(x),this.recent.length>2e3&&this.recent.splice(0,this.recent.length-2e3);for(const a of this.incidents.values())this.attach(a,x)&&this.onChange(a)}attach(e,t){if(t.loopId!==e.loop.id||t.endAt<e.startAt||t.startAt>(e.endAt??e.observedAt)||e.evidence.some(r=>r.eventId===t.eventId))return!1;if(e.evidence.length>=T){const r=!e.evidenceTruncated;return e.evidenceTruncated=!0,r}const{loopId:i,...d}=t;return e.evidence.push(d),!0}statuses(e=Date.now()){return[...this.loops.values()].map(t=>({...t,state:e-t.lastSeen>9e4?"unknown":t.state})).sort((t,i)=>i.lastSeen-t.lastSeen)}list(e){return[...this.incidents.values()].filter(t=>!e||t.flowId===e||t.evidence.some(i=>i.flowId===e)).sort((t,i)=>i.startAt-t.startAt)}}let A=l(()=>[],"readIncidents");export function setFlowLoopIncidents(n){A=n}u(setFlowLoopIncidents,"setFlowLoopIncidents"),l(setFlowLoopIncidents,"setFlowLoopIncidents");export function flowLoopIncidents(n){return A(n)}u(flowLoopIncidents,"flowLoopIncidents"),l(flowLoopIncidents,"flowLoopIncidents");
|
package/lib/event-redactor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var o=(r,t)=>u(r,"name",{value:t,configurable:!0});var l=Object.defineProperty,i=o((r,t)=>l(r,"name",{value:t,configurable:!0}),"a");import{MAX_MESSAGE_CHARS as S,MAX_TITLE_CHARS as T,redactDeep as y,redactSqlParams as _,redactText as p,safeText as E,safeTitle as g}from"./redact.js";export const BUS_REDACT_MAX_DEPTH=12;export function createEventRedactor(r={}){const t=r.maxDepth??BUS_REDACT_MAX_DEPTH;let s=0,a=0;return{redact(e){s+=1;const c=e.title===void 0?void 0:g(p(e.title)),n=e.message===void 0?void 0:E(p(e.message),S),d=e.raw===void 0?void 0:v(y(e.raw,0,t)),A=c!==e.title,f=n!==e.message,m=d!==e.raw;return!A&&!f&&!m?e:(a+=1,{...e,...c!==void 0?{title:c}:{},...n!==void 0?{message:n}:{},...d!==void 0?{raw:d}:{}})},stats:i(()=>({inspected:s,redacted:a}),"stats"),reset:i(()=>{s=0,a=0},"reset")}}o(createEventRedactor,"createEventRedactor"),i(createEventRedactor,"createEventRedactor");function v(r){if(!r||typeof r!="object"||Array.isArray(r))return r;const t=r,s=t.query,a=t.params;if(typeof s!="string"||!Array.isArray(a))return r;const e=_(s,a);return e===a?r:{...t,params:e}}o(v,"T"),i(v,"redactSqlShape");export{T as MAX_TITLE_CHARS};
|
package/lib/fingerprint.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var a=Object.defineProperty;var r=(n,e)=>a(n,"name",{value:e,configurable:!0});var f=Object.defineProperty,i=r((n,e)=>f(n,"name",{value:e,configurable:!0}),"e");const l=2166136261,u=16777619;function o(n){let e=2166136261;for(let t=0;t<n.length;t++)e^=n.charCodeAt(t),e=Math.imul(e,16777619);return(e>>>0).toString(16).padStart(8,"0")}r(o,"i"),i(o,"fnv1a32");export function fingerprint(n){const e=[n.kind,n.identity,n.file??"",n.detail??""];return`${n.kind}:${o(e.join("|"))}`}r(fingerprint,"fingerprint"),i(fingerprint,"fingerprint");
|
package/lib/flow-categories.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var M=Object.defineProperty;var c=(e,t)=>M(e,"name",{value:t,configurable:!0});var T=Object.defineProperty,s=c((e,t)=>T(e,"name",{value:t,configurable:!0}),"s");export const CATEGORY_ORDER=["user-action","page-load","navigation","api","ai","background","test","system","other"];const p=new Map;export function globMatch(e,t){let o=p.get(e);return o||(o=new RegExp(`^${e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*").replace(/\?/g,".")}$`),p.size>500&&p.clear(),p.set(e,o)),o.test(t)}c(globMatch,"globMatch"),s(globMatch,"globMatch");const F=s(e=>/^[A-Z]+ /.test(e),"hasMethod");function w(e,t){return t.some(o=>o.route?F(e)?globMatch(e,`${o.method??"GET"} ${o.route}`):globMatch(e,o.route):!1)}c(w,"$"),s(w,"routeMatches");function m(e,t){return!([e.flowId,e.originType,e.origin,e.route,e.project].filter(o=>o!==void 0).length===0||e.flowId!==void 0&&!globMatch(e.flowId,t.flowId)||e.originType!==void 0&&e.originType!==t.origin.type||e.origin!==void 0&&!(t.origin.nodeId!==void 0&&globMatch(e.origin,t.origin.nodeId))||e.route!==void 0&&!w(e.route,t.segments)||e.project!==void 0&&!t.segments.some(o=>o.projects.some(n=>globMatch(e.project,n))))}c(m,"b"),s(m,"ruleMatches");const y=s(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObj"),g=s(e=>typeof e=="string"&&e!==""?e:void 0,"str"),f=s(e=>y(e.raw)?g(e.raw.kind)??"":"","kindOf"),k=s((e,t)=>{const o=Number(e.timestamp)||0,n=Number(t.timestamp)||0;return o<n||o===n&&e.id<t.id},"earlier");function $(e){let t,o;for(const a of e)f(a)==="flow-origin"&&(!t||k(a,t))&&(t=a),g(a.context?.originType)&&(!o||k(a,o))&&(o=a);const n=t??o;if(!n)return{};const r=y(n.raw)?n.raw:{},i=g(n.context?.originType)??(t?g(n.title):void 0),u=g(r.originNodeId)??g(n.context?.originNodeId);return{...i?{type:i}:{},...u?{nodeId:u}:{}}}c($,"O"),s($,"originOf");const S=/^(verify|e2e|test|smoke|load)[-_:]/i,z=s((e,t)=>S.test(e)||t!==void 0&&/^(ui:)?(tools|scripts?|e2e)\//.test(t),"isTestFlow"),x={"page-load":"page-load","user-click":"user-action","form-submit":"user-action","input-change":"user-action","double-click":"user-action","context-menu":"user-action","key-press":"user-action","route-load":"navigation","route-change":"navigation",navigation:"navigation","ai-turn":"ai",request:"api",timer:"background",cron:"background",interval:"background",queue:"background",job:"background","websocket-message":"background","hmr-update":"system"},A=new Set(["page-load","user-action","navigation"]),E=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;export function templatePath(e){return e.replace(/[?#].*$/,"").split("/").map(t=>E.test(t)||/^[0-9a-f]{16,}$/i.test(t)||/^\d{2,}$/.test(t)?":id":t).join("/")}c(templatePath,"templatePath"),s(templatePath,"templatePath");function I(e){const t=/^ui:(?:.*\/)?([^/:]+?)(?:\.[a-z]+)?:\d+:([A-Za-z]+)$/.exec(e);return t?`${t[1]} \xB7 ${t[2]}`:e}c(I,"q"),s(I,"componentOf");export function scriptFamily(e){let t=e.replace(/[-_:][0-9a-f]{6,}(?:-[0-9a-f]+)*$/i,"");return t=t.replace(/[-_:](?=[a-z0-9]*\d)[a-z0-9]{6,}$/i,""),t=t.replace(/[-_:]\d+$/,""),t||e}c(scriptFamily,"scriptFamily"),s(scriptFamily,"scriptFamily");function j(e,t,o,n){const r=t.nodeId,i=r?/^(page|route|ambient):(.*)$/.exec(r):null;if(i)return`${i[1]}:${templatePath(i[2])}`;if(t.type&&x[t.type]==="user-action"&&r)return I(r);if(e==="test")return scriptFamily(o.flowId);const u=o.segments.find(l=>l.kind==="request"&&l.route);if(u?.route)return`${u.method??"GET"} ${templatePath(u.route)}`;const a=n.find(l=>f(l)==="ai-call");return a&&y(a.raw)?`ai \xB7 ${g(a.raw.model)??g(a.raw.provider)??"call"}`:r?templatePath(r):void 0}c(j,"R"),s(j,"subjectOf");const _=10,B=1e3,N=3,R=500,C=1e3;function q(e,t){const o=new Set,n=t.segments.filter(i=>i.kind==="request");t.segments.some(i=>i.counts.errors>0)&&o.add("has-error"),n.some(i=>i.durationMs>=B)&&o.add("slow"),n.length>=_&&o.add("fan-out"),new Set(t.segments.flatMap(i=>i.projects)).size>=3&&o.add("multi-service"),e.some(i=>f(i)==="queue-enqueued")&&o.add("queue"),e.some(i=>f(i)==="ai-call"||i.source==="ai")&&o.add("ai"),t.stats.bookkeeping>=R&&t.stats.bookkeeping*2>=t.stats.events&&o.add("storm"),t.stats.events>=C&&o.add("large");const r=new Map;for(const i of n)(!i.part||i.part.index===1)&&r.set(i.label,(r.get(i.label)??0)+1);return[...r.values()].some(i=>i>=N)&&o.add("repeated-requests"),[...o].sort()}c(q,"G"),s(q,"tagsOf");export function classifyFlow(e,t,o=[]){const n=$(e),r={flowId:t.flowId,origin:n,segments:t.segments},i=q(e,t),u=s((d,O,b)=>{const h=j(d,n,t,e);return{category:d,decidedBy:O,...b!==void 0?{ruleIndex:b}:{},tags:i,origin:n,...h?{subject:h}:{}}},"done"),a=o.findIndex(d=>d.category&&m(d,r));if(a!==-1)return u(o[a].category,"rule",a);if(z(t.flowId,n.nodeId))return u("test","test");const l=n.type?x[n.type]:void 0;if(l)return u(l,"origin");if(i.includes("ai"))return u("ai","shape");const v=t.segments.filter(d=>d.kind==="request");return v.length>0?u(v.every(d=>d.requestId?.startsWith("job:"))?"background":"api","shape"):t.segments.length>0&&t.segments.every(d=>d.kind==="ambient")?u("system","shape"):u("other","shape")}c(classifyFlow,"classifyFlow"),s(classifyFlow,"classifyFlow");export function categoryOfSegment(e,t,o=[]){const n=o.find(r=>r.category&&(r.route!==void 0||r.project!==void 0)&&r.flowId===void 0&&r.origin===void 0&&r.originType===void 0&&m(r,{flowId:e.flowId,origin:t.origin,segments:[e]}));return n?n.category:e.kind==="request"?e.requestId?.startsWith("job:")?"background":"api":e.kind==="ambient"?"system":e.kind==="origin"&&A.has(t.category)?t.category:"ui"}c(categoryOfSegment,"categoryOfSegment"),s(categoryOfSegment,"categoryOfSegment");export function groupFlows(e){return groupByCategory(e).map(t=>{const o=new Map;for(const r of t.items){const i=o.get(r.subject);i?i.push(r):o.set(r.subject,[r])}const n=[...o.entries()].sort((r,i)=>(r[0]===void 0?1:0)-(i[0]===void 0?1:0)||i[1].length-r[1].length||String(r[0]).localeCompare(String(i[0]))).map(([r,i])=>({subject:r,count:i.length,items:i}));return{...t,subjects:n}})}c(groupFlows,"groupFlows"),s(groupFlows,"groupFlows");export function groupByCategory(e){const t=new Map;for(const n of e){const r=t.get(n.category);r?r.push(n):t.set(n.category,[n])}const o=s(n=>{const r=CATEGORY_ORDER.indexOf(n);return r===-1?CATEGORY_ORDER.length:r},"rank");return[...t.entries()].sort((n,r)=>o(n[0])-o(r[0])||(n[0]<r[0]?-1:n[0]>r[0]?1:0)).map(([n,r])=>({category:n,count:r.length,items:r}))}c(groupByCategory,"groupByCategory"),s(groupByCategory,"groupByCategory");
|
package/lib/flow-segments.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var Z=Object.defineProperty;var b=(e,t)=>Z(e,"name",{value:t,configurable:!0});var ee=Object.defineProperty,I=b((e,t)=>ee(e,"name",{value:t,configurable:!0}),"b"),te=Object.defineProperty,m=I((e,t)=>te(e,"name",{value:t,configurable:!0}),"h");export const DEFAULT_SEGMENT_OPTIONS={phaseGapMs:1500,burstGapMs:250,attachWindowMs:400,maxSegmentEvents:400,occurrenceSlackMs:10},FLOW_BOOKKEEPING_KINDS=new Set(["subscription-added","subscription-removed","hook-run","store-created","singleton-instance","visual-frame"]),SQL_ACCOUNT_KIND="db-request-account";const ne=new Set(["react","valtio","client-runtime","chrome","visual"]),S=m(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObj"),v=m(e=>typeof e=="string"&&e!==""?e:void 0,"str"),$=m(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),H=new WeakMap;function E(e){let t=H.get(e);return t||(t=W(e),H.set(e,t)),t}b(E,"F"),I(E,"U"),m(E,"itemOf");function W(e){const t=S(e.raw)?e.raw:{},s=S(t.request)?t.request:{},o=S(t.span)?t.span:{},i=e.context??{},n=v(t.kind)??"",l=n===SQL_ACCOUNT_KIND,g=(l?$(t.lastEndedAt):void 0)??$(e.timestamp)??0,q=$(s.startedAt)??$(o.startTime)??$(t.startedAt)??(l?$(t.firstStartedAt):void 0),M=$(s.endedAt)??$(o.endTime)??(q!==void 0&&$(t.durationMs)!==void 0?q+t.durationMs:void 0),w=Math.min(g,q??g),j=Math.max(g,M??g),a=S(t.render)?t.render:{},u=S(t.update)?t.update:{},y=n==="render"?v(a.componentName):n==="state-update"?v(u.path)?.split(".").slice(0,2).join("."):void 0,d=v(t.queue),c=v(t.jobId),f=String(e.source),r=v(t.project)??v(i.projectName),p=n==="fetch-start"||n==="fetch-done"||n==="gateway-request";return{event:e,id:e.id,ts:g,from:w,to:j,kind:n,source:f,requestId:v(i.requestId),parentRequestId:v(i.parentRequestId),queueKey:d&&c?`${d}#${c}`:void 0,browser:ne.has(f)||f==="memory"&&r===void 0,bookkeeping:FLOW_BOOKKEEPING_KINDS.has(n),project:r,subject:y,route:p?F(v(t.url)):n==="server-request"?v(s.route):void 0,method:p?v(t.method):n==="server-request"?v(s.method):void 0}}b(W,"G"),I(W,"L"),m(W,"readItem");function F(e){if(!e)return;const t=e.search(/[?#]/),s=t===-1?e:e.slice(0,t),o=/^[a-z][a-z0-9+.-]*:\/\/[^/]*(\/.*)?$/i.exec(s);return o?o[1]??"/":s}b(F,"T"),I(F,"B"),m(F,"pathOnly");const se=m(e=>e.split(".")[0],"rootOf"),J=m((e,t)=>e.reduce((s,o)=>Math.min(s,t(o)),1/0),"minOf"),V=m((e,t)=>e.reduce((s,o)=>Math.max(s,t(o)),-1/0),"maxOf"),T=m((e,t)=>e.ts-t.ts||(e.id<t.id?-1:e.id>t.id?1:0),"compare"),G=m(e=>e.requestId&&!e.requestId.startsWith("job:")?se(e.requestId):void 0,"directFamilyOf");function B(e){if(e.requestId?.startsWith("job:"))return e.requestId.slice(4);if(e.queueKey&&e.kind!=="queue-enqueued"&&!e.requestId)return e.queueKey}b(B,"U"),I(B,"D"),m(B,"jobKeyOf");function U(e,t){const s=e.filter(n=>!n.parentRequestId&&(n.kind==="server-request"||n.kind==="gateway-request"||n.kind==="fetch-start"||n.kind==="fetch-done")).sort((n,l)=>n.from-l.from||T(n,l));if(s.length<2)return[e];const o=[];for(const n of s){const l=o[o.length-1];l&&n.from<=l.to+t?l.to=Math.max(l.to,n.to):o.push({from:n.from,to:n.to})}if(o.length<2)return[e];const i=o.map(()=>[]);for(const n of e)i[t>=0?D(o,n.ts,t):_(o,n.ts,t)].push(n);return i.filter(n=>n.length>0)}b(U,"D"),I(U,"z"),m(U,"occurrencesOf");function _(e,t,s){const o=e.findIndex(n=>t>=n.from-s&&t<=n.to+s);if(o!==-1)return o;let i=0;for(let n=0;n<e.length;n+=1)e[n].from<=t&&(i=n);return i}b(_,"R"),I(_,"P"),m(_,"spanScan");function D(e,t,s){let o=0,i=e.length;for(;o<i;){const n=o+i>>1;e[n].to+s<t?o=n+1:i=n}if(o<e.length&&t>=e[o].from-s)return o;for(o=0,i=e.length;o<i;){const n=o+i>>1;e[n].from<=t?o=n+1:i=n}return Math.max(0,o-1)}b(D,"z"),I(D,"Q"),m(D,"spanAt");const X={debug:0,info:1,warning:2,error:3,fatal:4};function A(e,t){const s=[];let o=[];for(const i of e){const n=o[o.length-1];n&&i.ts-n.ts>=t&&(s.push(o),o=[]),o.push(i)}return o.length&&s.push(o),s}b(A,"A"),I(A,"R"),m(A,"runs");export function segmentFlow(e,t={}){const s={...DEFAULT_SEGMENT_OPTIONS};for(const[r,p]of Object.entries(t))typeof p=="number"&&Number.isFinite(p)&&(s[r]=p);const o=new Set,i=[];for(const r of e)o.has(r.id)||(o.add(r.id),i.push(E(r)));i.sort(T);const n=v(i[0]?.event.context?.flowId)??v(i[0]?.event.raw?.flowId)??"",l=new Map;for(const r of i)r.kind==="queue-enqueued"&&r.queueKey&&r.requestId&&!r.requestId.startsWith("job:")&&!l.has(r.queueKey)&&l.set(r.queueKey,r);const g=new Map,q=new Map,M=[];for(const r of i){const p=B(r),h=G(r);if(p!==void 0){const k=q.get(p);k?k.push(r):q.set(p,[r])}else if(h!==void 0){const k=g.get(h);k?k.push(r):g.set(h,[r])}else M.push(r)}const w=[],j=new Map;for(const[r,p]of g)U(p,s.occurrenceSlackMs).forEach((h,k)=>{const O={id:`${n}~r:${r}${k===0?"":`@${k+1}`}`,kind:"request",items:h,requestId:r};if(w.push(O),l.size)for(const x of h)x.kind==="queue-enqueued"&&j.set(x,O)});for(const[r,p]of q){const h=l.get(r),k=h?j.get(h):void 0;k?k.items.push(...p):w.push({id:`${n}~r:job:${r}`,kind:"request",items:p,requestId:`job:${r}`})}const a=i.filter(r=>r.kind==="fetch-done"&&G(r)!==void 0),u=new Map;for(const r of w)r.requestId&&u.set(r.requestId,[...u.get(r.requestId)??[],r]);const y=m((r,p)=>{const h=u.get(r);if(h)return h.find(k=>k.items.some(O=>O.kind==="fetch-done"&&O.ts===p))??h[h.length-1]},"owningUnit"),d=M.filter(r=>r.browser);for(const r of A(d,s.burstGapMs)){const p=r[0].ts,h=a.filter(x=>x.ts<=p&&p-x.ts<=s.attachWindowMs),k=[...new Set(h.map(x=>G(x)))];if(k.length===1){const x=y(k[0],h[h.length-1].ts);if(x){x.items.push(...r);continue}}const O=r.some(x=>x.kind==="flow-origin");w.push({id:`${n}~${O?"o":"u"}:${r[0].id}`,kind:O?"origin":"ui",items:r,...k.length>1?{after:k.sort()}:{}})}for(const r of A(M.filter(p=>!p.browser),s.phaseGapMs))w.push({id:`${n}~a:${r[0].id}`,kind:"ambient",items:r});const c=P(n,i.length,w,s),f=K(i);return f?{...c,sql:f}:c}b(segmentFlow,"segmentFlow"),I(segmentFlow,"segmentFlow"),m(segmentFlow,"segmentFlow");function P(e,t,s,o){for(const a of s)a.items.sort(T);const i=s.map(a=>({unit:a,from:J(a.items,u=>u.from),to:V(a.items,u=>u.to)}));i.sort((a,u)=>a.from-u.from||(a.unit.id<u.unit.id?-1:1));const n=new Map;let l=0,g=-1/0;for(const a of i)(l===0||a.from-g>=o.phaseGapMs)&&(l+=1),g=Math.max(g,a.to),n.set(a.unit,l);const q=[];for(const a of i){const u=R(a.unit.items,o.maxSegmentEvents),y=a.unit.kind==="request"?K(a.unit.items):void 0;u.forEach((d,c)=>{const f=z(e,a.unit,d,n.get(a.unit),u.length>1?{index:c+1,total:u.length}:void 0);q.push(y&&c===0?{...f,sql:y}:f)})}const M={};for(const a of q)for(const u of a.eventIds)M[u]=a.id;const w=[];for(const a of q){let u=w[a.phase-1];u||(u={index:a.phase,start:a.start,end:a.end,segmentIds:[]},w[a.phase-1]=u),u.start=Math.min(u.start,a.start),u.end=Math.max(u.end,a.end),u.segmentIds.push(a.id)}const j=q.reduce((a,u)=>a+u.counts.signal,0);return{flowId:e,segments:q,phases:w.filter(Boolean),assignment:M,stats:{events:t,signal:j,bookkeeping:t-j,segments:q.length,phases:w.filter(Boolean).length,largestSegment:q.reduce((a,u)=>Math.max(a,u.counts.total),0)}}}b(P,"L"),I(P,"V"),m(P,"assemble");function R(e,t){if(e.filter(n=>!n.bookkeeping).length<=t)return[e];const s=[];let o=[],i=0;for(const n of e)!n.bookkeeping&&i===t&&(s.push(o),o=[],i=0),o.push(n),n.bookkeeping||(i+=1);return o.length&&s.push(o),s}b(R,"P"),I(R,"X"),m(R,"chunk");function z(e,t,s,o,i){const n={total:s.length,signal:0,bookkeeping:0,errors:0,warnings:0},l=new Set;let g="debug";for(const u of s){u.bookkeeping?n.bookkeeping+=1:n.signal+=1;const y=String(u.event.severity);y==="error"||y==="fatal"?n.errors+=1:y==="warning"&&(n.warnings+=1),(X[y]??1)>(X[g]??0)&&(g=y),u.project&&l.add(u.project)}const q=t.kind==="ui"||t.kind==="origin"?C(s):[],M=J(s,u=>u.from),w=V(s,u=>u.to),j=L(t.items),a=t.id;return{id:i&&i.index>1?`${a}#${i.index}`:a,flowId:e,kind:t.kind,label:Q(t,s,j,i,q),phase:o,start:M,end:w,durationMs:w-M,eventIds:s.map(u=>u.id),counts:n,projects:[...l].sort(),...j.route?{route:j.route}:{},...j.method?{method:j.method}:{},...t.requestId?{requestId:t.requestId}:{},...t.after?{after:t.after}:{},...q.length?{hot:q}:{},...i?{part:i}:{},worstSeverity:g}}b(z,"Q"),I(z,"Y"),m(z,"toSegment");function L(e){const t=e.find(s=>s.kind==="fetch-start"&&s.route)??e.find(s=>s.kind==="server-request"&&!s.parentRequestId&&s.route)??e.find(s=>s.kind==="gateway-request"&&s.route)??e.find(s=>s.kind==="fetch-done"&&s.route);return{...t?.route?{route:t.route}:{},...t?.method?{method:t.method.toUpperCase()}:{}}}b(L,"H"),I(L,"H"),m(L,"routeOf");function C(e){const t=new Map;for(const s of e)s.subject&&!s.bookkeeping&&t.set(s.subject,(t.get(s.subject)??0)+1);return[...t.entries()].sort((s,o)=>o[1]-s[1]||(s[0]<o[0]?-1:1)).slice(0,3).map(([s,o])=>o>1?`${s} \xD7${o}`:s)}b(C,"J"),I(C,"J"),m(C,"hotOf");function Q(e,t,s,o,i){const n=o?` (part ${o.index}/${o.total})`:"";if(e.kind==="request"){if(s.route)return`${s.method?`${s.method} `:""}${s.route}${n}`;const l=t.find(g=>g.queueKey);return l?`job ${l.queueKey}${n}`:`request ${e.requestId??""}${n}`}return e.kind==="origin"?`${t.find(l=>l.kind==="flow-origin")?.event.title||"start"}${i.length?` \xB7 ${i.join(", ")}`:""}${n}`:e.kind==="ui"?`UI update${i.length?` \xB7 ${i.join(", ")}`:""}${n}`:`background${n}`}b(Q,"V"),I(Q,"Z"),m(Q,"labelOf");const Y=50;export function sqlAccountingOf(e){return N(e,!1)}b(sqlAccountingOf,"sqlAccountingOf"),I(sqlAccountingOf,"sqlAccountingOf"),m(sqlAccountingOf,"sqlAccountingOf");function K(e){return N(e.map(t=>t.event),!0)}b(K,"N"),I(K,"T"),m(K,"accountSqlOfItems");function N(e,t){const s=new Map,o=new Map,i=t?void 0:new Set;for(const d of e){if(i){if(i.has(d.id))continue;i.add(d.id)}const c=S(d.raw)?d.raw:{},f=v(c.kind),r=v(d.context?.requestId);if(!r)continue;const p=v(c.project)??v(d.context?.projectName);if(f==="db-query"&&d.source==="db"){const h=o.get(r)??{count:0,workMs:0,...p?{project:p}:{}};h.count+=1,h.workMs+=$(c.durationMs)??0,o.set(r,h)}else if(f===SQL_ACCOUNT_KIND){const h=v(c.accountId)??d.id,k=$(c.seq)??0,O=s.get(h);if(O&&O.seq>=k)continue;s.set(h,{requestId:r,...p?{project:p}:{},seq:k,basis:c.basis==="end"?"end":"settled",statements:$(c.statements)??0,failed:$(c.failed)??0,workMs:$(c.workMs)??0,recorded:$(c.recorded)??0,suppressed:$(c.suppressed)??0,unwritten:$(c.unwritten)??0})}}const n=new Map;for(const d of s.values()){const c=n.get(d.requestId);if(!c){n.set(d.requestId,{...d});continue}d.basis==="settled"&&(c.basis="settled"),c.statements+=d.statements,c.failed+=d.failed,c.workMs+=d.workMs,c.recorded+=d.recorded,c.suppressed+=d.suppressed,c.unwritten+=d.unwritten}const l=[...new Set([...o.keys(),...n.keys()])].sort();if(l.length===0)return;const g={statements:0,failed:0,workMs:0,recorded:0,suppressed:0,unwritten:0},q={statements:0,workMs:0},M=[];for(const d of l){const c=o.get(d),f=n.get(d),r=c?.count??0;q.statements+=r,q.workMs+=c?.workMs??0;const p=!f||r>f.statements?"unverified":r===f.statements?"complete":"incomplete";f&&p!=="unverified"&&(g.statements+=f.statements,g.failed+=f.failed,g.workMs+=f.workMs,g.recorded+=f.recorded,g.suppressed+=f.suppressed,g.unwritten+=f.unwritten);const h=c?.project??f?.project;M.push({requestId:d,...h?{project:h}:{},status:p,observed:r,observedWorkMs:c?.workMs??0,...f?{basis:f.basis,statements:f.statements,failed:f.failed,workMs:f.workMs,recorded:f.recorded,suppressed:f.suppressed,unwritten:f.unwritten}:{}})}const w=m(d=>M.filter(c=>c.status===d).length,"tally"),j=w("unverified"),a=w("incomplete"),u=m(d=>(d.statements??0)-d.observed,"missing"),y=M.filter(d=>d.status!=="complete").sort((d,c)=>(d.status==="incomplete"?0:1)-(c.status==="incomplete"?0:1)||u(c)-u(d)||(d.requestId<c.requestId?-1:d.requestId>c.requestId?1:0));return{status:j>0?"unverified":a>0?"incomplete":"complete",requests:M.length,complete:w("complete"),incomplete:a,unverified:j,settled:M.filter(d=>d.status!=="unverified"&&d.basis==="settled").length,observed:q,accounted:g,gaps:y.slice(0,Y),gapsTruncated:y.length>Y}}b(N,"E"),I(N,"W"),m(N,"accountSql");
|
|
1
|
+
"use strict";var Y=Object.defineProperty;var b=(e,t)=>Y(e,"name",{value:t,configurable:!0});var Z=Object.defineProperty,m=b((e,t)=>Z(e,"name",{value:t,configurable:!0}),"h");export const DEFAULT_SEGMENT_OPTIONS={phaseGapMs:1500,burstGapMs:250,attachWindowMs:400,maxSegmentEvents:400,occurrenceSlackMs:10},FLOW_BOOKKEEPING_KINDS=new Set(["subscription-added","subscription-removed","hook-run","store-created","singleton-instance","visual-frame"]),SQL_ACCOUNT_KIND="db-request-account";const ee=new Set(["react","valtio","client-runtime","chrome","visual"]),S=m(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObj"),v=m(e=>typeof e=="string"&&e!==""?e:void 0,"str"),M=m(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),W=new WeakMap;function F(e){let t=W.get(e);return t||(t=G(e),W.set(e,t)),t}b(F,"U"),m(F,"itemOf");function G(e){const t=S(e.raw)?e.raw:{},s=S(t.request)?t.request:{},o=S(t.span)?t.span:{},i=e.context??{},n=v(t.kind)??"",p=n===SQL_ACCOUNT_KIND,g=(p?M(t.lastEndedAt):void 0)??M(e.timestamp)??0,q=M(s.startedAt)??M(o.startTime)??M(t.startedAt)??(p?M(t.firstStartedAt):void 0),I=M(s.endedAt)??M(o.endTime)??(q!==void 0&&M(t.durationMs)!==void 0?q+t.durationMs:void 0),w=Math.min(g,q??g),$=Math.max(g,I??g),a=S(t.render)?t.render:{},u=S(t.update)?t.update:{},j=n==="render"?v(a.componentName):n==="state-update"?v(u.path)?.split(".").slice(0,2).join("."):void 0,d=v(t.queue),c=v(t.jobId),f=String(e.source),r=v(t.project)??v(i.projectName),l=n==="fetch-start"||n==="fetch-done"||n==="gateway-request";return{event:e,id:e.id,ts:g,from:w,to:$,kind:n,source:f,requestId:v(i.requestId),parentRequestId:v(i.parentRequestId),queueKey:d&&c?`${d}#${c}`:void 0,browser:ee.has(f)||f==="memory"&&r===void 0,bookkeeping:FLOW_BOOKKEEPING_KINDS.has(n),project:r,subject:j,route:l?T(v(t.url)):n==="server-request"?v(s.route):void 0,method:l?v(t.method):n==="server-request"?v(s.method):void 0}}b(G,"L"),m(G,"readItem");function T(e){if(!e)return;const t=e.search(/[?#]/),s=t===-1?e:e.slice(0,t),o=/^[a-z][a-z0-9+.-]*:\/\/[^/]*(\/.*)?$/i.exec(s);return o?o[1]??"/":s}b(T,"B"),m(T,"pathOnly");const te=m(e=>e.split(".")[0],"rootOf"),_=m((e,t)=>e.reduce((s,o)=>Math.min(s,t(o)),1/0),"minOf"),B=m((e,t)=>e.reduce((s,o)=>Math.max(s,t(o)),-1/0),"maxOf"),O=m((e,t)=>e.ts-t.ts||(e.id<t.id?-1:e.id>t.id?1:0),"compare"),K=m(e=>e.requestId&&!e.requestId.startsWith("job:")?te(e.requestId):void 0,"directFamilyOf");function U(e){if(e.requestId?.startsWith("job:"))return e.requestId.slice(4);if(e.queueKey&&e.kind!=="queue-enqueued"&&!e.requestId)return e.queueKey}b(U,"D"),m(U,"jobKeyOf");function D(e,t){const s=e.filter(n=>!n.parentRequestId&&(n.kind==="server-request"||n.kind==="gateway-request"||n.kind==="fetch-start"||n.kind==="fetch-done")).sort((n,p)=>n.from-p.from||O(n,p));if(s.length<2)return[e];const o=[];for(const n of s){const p=o[o.length-1];p&&n.from<=p.to+t?p.to=Math.max(p.to,n.to):o.push({from:n.from,to:n.to})}if(o.length<2)return[e];const i=o.map(()=>[]);for(const n of e)i[t>=0?z(o,n.ts,t):R(o,n.ts,t)].push(n);return i.filter(n=>n.length>0)}b(D,"z"),m(D,"occurrencesOf");function R(e,t,s){const o=e.findIndex(n=>t>=n.from-s&&t<=n.to+s);if(o!==-1)return o;let i=0;for(let n=0;n<e.length;n+=1)e[n].from<=t&&(i=n);return i}b(R,"P"),m(R,"spanScan");function z(e,t,s){let o=0,i=e.length;for(;o<i;){const n=o+i>>1;e[n].to+s<t?o=n+1:i=n}if(o<e.length&&t>=e[o].from-s)return o;for(o=0,i=e.length;o<i;){const n=o+i>>1;e[n].from<=t?o=n+1:i=n}return Math.max(0,o-1)}b(z,"Q"),m(z,"spanAt");const C={debug:0,info:1,warning:2,error:3,fatal:4};function A(e,t){const s=[];let o=[];for(const i of e){const n=o[o.length-1];n&&i.ts-n.ts>=t&&(s.push(o),o=[]),o.push(i)}return o.length&&s.push(o),s}b(A,"R"),m(A,"runs");export function segmentFlow(e,t={}){const s={...DEFAULT_SEGMENT_OPTIONS};for(const[r,l]of Object.entries(t))typeof l=="number"&&Number.isFinite(l)&&(s[r]=l);const o=new Set,i=[];for(const r of e)o.has(r.id)||(o.add(r.id),i.push(F(r)));i.sort(O);const n=v(i[0]?.event.context?.flowId)??v(i[0]?.event.raw?.flowId)??"",p=new Map;for(const r of i)r.kind==="queue-enqueued"&&r.queueKey&&r.requestId&&!r.requestId.startsWith("job:")&&!p.has(r.queueKey)&&p.set(r.queueKey,r);const g=new Map,q=new Map,I=[];for(const r of i){const l=U(r),h=K(r);if(l!==void 0){const k=q.get(l);k?k.push(r):q.set(l,[r])}else if(h!==void 0){const k=g.get(h);k?k.push(r):g.set(h,[r])}else I.push(r)}const w=[],$=new Map;for(const[r,l]of g)D(l,s.occurrenceSlackMs).forEach((h,k)=>{const x={id:`${n}~r:${r}${k===0?"":`@${k+1}`}`,kind:"request",items:h,requestId:r};if(w.push(x),p.size)for(const y of h)y.kind==="queue-enqueued"&&$.set(y,x)});for(const[r,l]of q){const h=p.get(r),k=h?$.get(h):void 0;k?k.items.push(...l):w.push({id:`${n}~r:job:${r}`,kind:"request",items:l,requestId:`job:${r}`})}const a=i.filter(r=>r.kind==="fetch-done"&&K(r)!==void 0),u=new Map;for(const r of w)r.requestId&&u.set(r.requestId,[...u.get(r.requestId)??[],r]);const j=m((r,l)=>{const h=u.get(r);if(h)return h.find(k=>k.items.some(x=>x.kind==="fetch-done"&&x.ts===l))??h[h.length-1]},"owningUnit"),d=I.filter(r=>r.browser);for(const r of A(d,s.burstGapMs)){const l=r[0].ts,h=a.filter(y=>y.ts<=l&&l-y.ts<=s.attachWindowMs),k=[...new Set(h.map(y=>K(y)))];if(k.length===1){const y=j(k[0],h[h.length-1].ts);if(y){y.items.push(...r);continue}}const x=r.some(y=>y.kind==="flow-origin");w.push({id:`${n}~${x?"o":"u"}:${r[0].id}`,kind:x?"origin":"ui",items:r,...k.length>1?{after:k.sort()}:{}})}for(const r of A(I.filter(l=>!l.browser),s.phaseGapMs))w.push({id:`${n}~a:${r[0].id}`,kind:"ambient",items:r});const c=L(n,i.length,w,s),f=N(i);return f?{...c,sql:f}:c}b(segmentFlow,"segmentFlow"),m(segmentFlow,"segmentFlow");function L(e,t,s,o){for(const a of s)a.items.sort(O);const i=s.map(a=>({unit:a,from:_(a.items,u=>u.from),to:B(a.items,u=>u.to)}));i.sort((a,u)=>a.from-u.from||(a.unit.id<u.unit.id?-1:1));const n=new Map;let p=0,g=-1/0;for(const a of i)(p===0||a.from-g>=o.phaseGapMs)&&(p+=1),g=Math.max(g,a.to),n.set(a.unit,p);const q=[];for(const a of i){const u=P(a.unit.items,o.maxSegmentEvents),j=a.unit.kind==="request"?N(a.unit.items):void 0;u.forEach((d,c)=>{const f=Q(e,a.unit,d,n.get(a.unit),u.length>1?{index:c+1,total:u.length}:void 0);q.push(j&&c===0?{...f,sql:j}:f)})}const I={};for(const a of q)for(const u of a.eventIds)I[u]=a.id;const w=[];for(const a of q){let u=w[a.phase-1];u||(u={index:a.phase,start:a.start,end:a.end,segmentIds:[]},w[a.phase-1]=u),u.start=Math.min(u.start,a.start),u.end=Math.max(u.end,a.end),u.segmentIds.push(a.id)}const $=q.reduce((a,u)=>a+u.counts.signal,0);return{flowId:e,segments:q,phases:w.filter(Boolean),assignment:I,stats:{events:t,signal:$,bookkeeping:t-$,segments:q.length,phases:w.filter(Boolean).length,largestSegment:q.reduce((a,u)=>Math.max(a,u.counts.total),0)}}}b(L,"V"),m(L,"assemble");function P(e,t){if(e.filter(n=>!n.bookkeeping).length<=t)return[e];const s=[];let o=[],i=0;for(const n of e)!n.bookkeeping&&i===t&&(s.push(o),o=[],i=0),o.push(n),n.bookkeeping||(i+=1);return o.length&&s.push(o),s}b(P,"X"),m(P,"chunk");function Q(e,t,s,o,i){const n={total:s.length,signal:0,bookkeeping:0,errors:0,warnings:0},p=new Set;let g="debug";for(const u of s){u.bookkeeping?n.bookkeeping+=1:n.signal+=1;const j=String(u.event.severity);j==="error"||j==="fatal"?n.errors+=1:j==="warning"&&(n.warnings+=1),(C[j]??1)>(C[g]??0)&&(g=j),u.project&&p.add(u.project)}const q=t.kind==="ui"||t.kind==="origin"?J(s):[],I=_(s,u=>u.from),w=B(s,u=>u.to),$=H(t.items),a=t.id;return{id:i&&i.index>1?`${a}#${i.index}`:a,flowId:e,kind:t.kind,label:V(t,s,$,i,q),phase:o,start:I,end:w,durationMs:w-I,eventIds:s.map(u=>u.id),counts:n,projects:[...p].sort(),...$.route?{route:$.route}:{},...$.method?{method:$.method}:{},...t.requestId?{requestId:t.requestId}:{},...t.after?{after:t.after}:{},...q.length?{hot:q}:{},...i?{part:i}:{},worstSeverity:g}}b(Q,"Y"),m(Q,"toSegment");function H(e){const t=e.find(s=>s.kind==="fetch-start"&&s.route)??e.find(s=>s.kind==="server-request"&&!s.parentRequestId&&s.route)??e.find(s=>s.kind==="gateway-request"&&s.route)??e.find(s=>s.kind==="fetch-done"&&s.route);return{...t?.route?{route:t.route}:{},...t?.method?{method:t.method.toUpperCase()}:{}}}b(H,"H"),m(H,"routeOf");function J(e){const t=new Map;for(const s of e)s.subject&&!s.bookkeeping&&t.set(s.subject,(t.get(s.subject)??0)+1);return[...t.entries()].sort((s,o)=>o[1]-s[1]||(s[0]<o[0]?-1:1)).slice(0,3).map(([s,o])=>o>1?`${s} \xD7${o}`:s)}b(J,"J"),m(J,"hotOf");function V(e,t,s,o,i){const n=o?` (part ${o.index}/${o.total})`:"";if(e.kind==="request"){if(s.route)return`${s.method?`${s.method} `:""}${s.route}${n}`;const p=t.find(g=>g.queueKey);return p?`job ${p.queueKey}${n}`:`request ${e.requestId??""}${n}`}return e.kind==="origin"?`${t.find(p=>p.kind==="flow-origin")?.event.title||"start"}${i.length?` \xB7 ${i.join(", ")}`:""}${n}`:e.kind==="ui"?`UI update${i.length?` \xB7 ${i.join(", ")}`:""}${n}`:`background${n}`}b(V,"Z"),m(V,"labelOf");const X=50;export function sqlAccountingOf(e){return E(e,!1)}b(sqlAccountingOf,"sqlAccountingOf"),m(sqlAccountingOf,"sqlAccountingOf");function N(e){return E(e.map(t=>t.event),!0)}b(N,"T"),m(N,"accountSqlOfItems");function E(e,t){const s=new Map,o=new Map,i=t?void 0:new Set;for(const d of e){if(i){if(i.has(d.id))continue;i.add(d.id)}const c=S(d.raw)?d.raw:{},f=v(c.kind),r=v(d.context?.requestId);if(!r)continue;const l=v(c.project)??v(d.context?.projectName);if(f==="db-query"&&d.source==="db"){const h=o.get(r)??{count:0,workMs:0,...l?{project:l}:{}};h.count+=1,h.workMs+=M(c.durationMs)??0,o.set(r,h)}else if(f===SQL_ACCOUNT_KIND){const h=v(c.accountId)??d.id,k=M(c.seq)??0,x=s.get(h);if(x&&x.seq>=k)continue;s.set(h,{requestId:r,...l?{project:l}:{},seq:k,basis:c.basis==="end"?"end":"settled",statements:M(c.statements)??0,failed:M(c.failed)??0,workMs:M(c.workMs)??0,recorded:M(c.recorded)??0,suppressed:M(c.suppressed)??0,unwritten:M(c.unwritten)??0})}}const n=new Map;for(const d of s.values()){const c=n.get(d.requestId);if(!c){n.set(d.requestId,{...d});continue}d.basis==="settled"&&(c.basis="settled"),c.statements+=d.statements,c.failed+=d.failed,c.workMs+=d.workMs,c.recorded+=d.recorded,c.suppressed+=d.suppressed,c.unwritten+=d.unwritten}const p=[...new Set([...o.keys(),...n.keys()])].sort();if(p.length===0)return;const g={statements:0,failed:0,workMs:0,recorded:0,suppressed:0,unwritten:0},q={statements:0,workMs:0},I=[];for(const d of p){const c=o.get(d),f=n.get(d),r=c?.count??0;q.statements+=r,q.workMs+=c?.workMs??0;const l=!f||r>f.statements?"unverified":r===f.statements?"complete":"incomplete";f&&l!=="unverified"&&(g.statements+=f.statements,g.failed+=f.failed,g.workMs+=f.workMs,g.recorded+=f.recorded,g.suppressed+=f.suppressed,g.unwritten+=f.unwritten);const h=c?.project??f?.project;I.push({requestId:d,...h?{project:h}:{},status:l,observed:r,observedWorkMs:c?.workMs??0,...f?{basis:f.basis,statements:f.statements,failed:f.failed,workMs:f.workMs,recorded:f.recorded,suppressed:f.suppressed,unwritten:f.unwritten}:{}})}const w=m(d=>I.filter(c=>c.status===d).length,"tally"),$=w("unverified"),a=w("incomplete"),u=m(d=>(d.statements??0)-d.observed,"missing"),j=I.filter(d=>d.status!=="complete").sort((d,c)=>(d.status==="incomplete"?0:1)-(c.status==="incomplete"?0:1)||u(c)-u(d)||(d.requestId<c.requestId?-1:d.requestId>c.requestId?1:0));return{status:$>0?"unverified":a>0?"incomplete":"complete",requests:I.length,complete:w("complete"),incomplete:a,unverified:$,settled:I.filter(d=>d.status!=="unverified"&&d.basis==="settled").length,observed:q,accounted:g,gaps:j.slice(0,X),gapsTruncated:j.length>X}}b(E,"W"),m(E,"accountSql");
|
package/lib/flow-shape.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var Bt=Object.defineProperty;var R=(i,f)=>Bt(i,"name",{value:f,configurable:!0});var St=Object.defineProperty,P=R((i,f)=>St(i,"name",{value:f,configurable:!0}),"R"),At=Object.defineProperty,w=P((i,f)=>At(i,"name",{value:f,configurable:!0}),"I");import{redactDeep as Rt,redactText as ut,redactUrlParams as Tt}from"./redact.js";import{templatisePath as wt}from"./route-template.js";import{SQL_ACCOUNT_KIND as Dt,sqlAccountingOf as Ct}from"./flow-segments.js";import{isServiceHopHost as kt}from"./service-hop.js";import{boundedClone as Pt}from"@lensmcp/protocol-types";export function areaOf(i){const{source:f,category:s,title:q,kind:l}=i;return f==="ai"?"ai":f==="perf"&&l==="event-loop-stall"?"services":l?.startsWith("memory")||l==="db-query"?"data":f==="gateway"||l==="gateway-request"?"gateway":l==="queue-process"||l==="queue-active"||l==="queue-completed"||l==="queue-failed"?"services":f==="db"||f==="redis"||f==="queue"||l==="redis-op"||l?.startsWith("queue-")||f==="fs"||l==="fs-ops"?"data":f==="exec"||l==="exec"||l==="egress"&&kt(i.host)?"services":f==="external"||l==="egress"?"network":f==="nestjs"||f==="nest"?/(?:Repository|Repo|Dao|Store|EntityManager|DataSource|QueryRunner|OrmClient)\./.test(q)?"data":"services":f==="valtio"?"state":s==="network"?"network":"browser"}R(areaOf,"areaOf"),P(areaOf,"areaOf"),w(areaOf,"areaOf");const qt=240,Ft=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),Nt=new Set(["tenantId","caller","userId","accountId","email","subject"]),Ot=8;function ct(i){const f=et(i,0);return Pt(Rt({redacted:!0,...f}),{rawByteLimit:16*1024}).value}R(ct,"vt"),P(ct,"Ct"),w(ct,"aiProjection");function et(i,f){if(typeof i=="string")return lt(i);if(i===null||typeof i!="object")return i;if(f>=Ot)return;if(Array.isArray(i))return i.slice(0,32).map(q=>et(q,f+1));const s={};for(const[q,l]of Object.entries(i))if(!Nt.has(q)){if(Ft.has(q)){typeof l=="string"?s[`${q}Chars`]=l.length:Array.isArray(l)?s[`${q}Count`]=l.length:l!=null&&(s[`${q}Present`]=!0);continue}s[q]=et(l,f+1)}return s}R(et,"rt"),P(et,"it"),w(et,"projectAi");function lt(i){return i.length<=qt?ut(i):`${ut(i.slice(0,qt))}\u2026`}R(lt,"kt"),P(lt,"Et"),w(lt,"clipText");export function httpFacts(i,f){const s=w(I=>typeof I=="string"&&I.length>0?I:void 0,"str"),q=typeof f.status=="number"?f.status:void 0,l=w(I=>Tt(I.split("?")[0]??I)||"/","pathOf"),F=w((I,y,j={})=>({...I?{method:I.toUpperCase()}:{},...y?{rawPath:y,route:wt(y)}:{},...q!==void 0?{status:q}:{},...j}),"facts");if(i==="gateway-request"){const I=s(f.url);return F(s(f.method),I?l(I):void 0,{...s(f.host)?{host:s(f.host)}:{},...s(f.caller)?{caller:s(f.caller)}:{}})}if(i==="egress"){const I=s(f.path),y=s(f.exchangeId);return F(s(f.method)??"GET",I?l(I):void 0,{...s(f.host)?{host:s(f.host)}:{},...y?{exchangeId:y}:{}})}if(i==="fetch-start"||i==="fetch-done"||i==="fetch-error"){const I=s(f.href)??s(f.url);let y,j;if(I)try{const p=new URL(I,"http://relative.invalid");y=l(p.pathname),p.hostname!=="relative.invalid"&&(j=p.hostname)}catch{}return F(s(f.method)??"GET",y,j?{host:j}:{})}if(i==="ai-call")return{...q!==void 0?{status:q}:{},...f.stream===!0?{streamed:!0}:{}};const g=f.request;if(g&&typeof g=="object"){const I=g,y=s(I.route),j=s(I.method);if(!y&&!j)return{};const p=typeof I.status=="number"?I.status:void 0,T=y?l(y):void 0;return{...j?{method:j.toUpperCase()}:{},...T?{rawPath:T,route:T.includes(":")?T:wt(T)}:{},...p!==void 0?{status:p}:{}}}return{}}R(httpFacts,"httpFacts"),P(httpFacts,"httpFacts"),w(httpFacts,"httpFacts");export function trimFlowEvent(i,f={}){const s=i.raw??{},q=s.render??{},l=s.span??{},F=s.request??{},g=w(d=>typeof d=="number"?d:void 0,"num"),I=s.loop??{},y=s.effect??{},j=g(s.durationMs)??g(l.durationMs)??g(F.durationMs)??g(I.durationMs)??g(q.actualDurationMs)??g(y.durationMs),p=typeof s.kind=="string"?s.kind:void 0,T=p==="fetch-done"||p==="fetch-error",_=g(q.commitTime),z=p==="render"&&_!==void 0&&Math.abs(_-i.timestamp)<6e4,J=T?i.timestamp:z?_:g(s.startedAt)??g(l.startTime)??g(F.startedAt)??g(I.startedAt)??(j!==void 0?i.timestamp-j:i.timestamp);let b;if(typeof s.query=="string"){const d=Array.isArray(s.params)?` [${s.params.join(", ")}]`:"",m=typeof s.result=="string"?` \u2192 ${s.result}`:"";b=s.query+d+m}else if(typeof s.command=="string"){const d=typeof s.value=="string"?` \u2192 ${s.value}`:s.hit===!1?" \u2192 (miss)":"";b=s.command+d}else if(p==="state-update"){const d=s.update??{};let m="";try{m=JSON.stringify(d.preview)}catch{}b=`${d.storeId??""}.${d.path??""} = ${m}`}else if(p==="fs-ops"&&Array.isArray(s.paths))b=s.paths.slice(0,8).map(d=>{const m=d??{},S=typeof m.n=="number"&&m.n>1?` \xD7${m.n}`:"",h=typeof m.bytes=="number"&&m.bytes>0?` (${m.bytes>=1024?`${(m.bytes/1024).toFixed(1)} KB`:`${m.bytes} B`})`:"";return`${String(m.op??"?")} ${String(m.path??"?")}${S}${h}`}).join(" \xB7 ");else if(p==="exec"&&typeof s.cmd=="string")b=`${s.cmd} \u2192 ${s.code??s.signal??s.error??"?"}`;else if(p==="queue-completed"&&typeof s.returned=="string")b=`returned ${s.returned}`;else if(p==="queue-enqueued")b=`${s.job??"job"}#${s.jobId??"?"} \u2192 ${s.queue??""}${typeof s.data=="string"?" "+s.data:""}`;else if(p==="log"){const d=F.error??{},m=typeof d.stack=="string"?d.stack:typeof s.text=="string"?s.text:void 0;m&&m!==i.title&&(b=m)}let U,W,Y,K;if(p==="span"){const d=l.outcome;if(U=d==="threw"||d==="returned"?d:l.status==="error"?"threw":l.status==="ok"?"returned":void 0,U==="threw"){const h=l.error??{},C=typeof h.name=="string"?h.name:void 0,G=typeof h.message=="string"?h.message:typeof i.message=="string"?i.message:void 0;Y=C,W=ut([C,G].filter(Boolean).join(": "))||void 0}const m=typeof l.args=="string"?l.args:void 0,S=typeof l.result=="string"?l.result:void 0;if(m!==void 0||S!==void 0){K=[...m!==void 0?["args"]:[],...S!==void 0?["result"]:[]];const h=w(C=>C.length>Mt?`${C.slice(0,Mt)}\u2026`:C,"short");b=[m!==void 0?`args ${h(m)}`:"",S!==void 0?`returned ${h(S)}`:""].filter(Boolean).join(" \u2192 ")}}let Q;if(p==="gateway-request")Q=`${s.host??""}${String(s.url??"").split("?")[0]}`;else if(p==="fetch-start"||p==="fetch-done"||p==="fetch-error")try{const d=new URL(String(s.href??s.url??""));Q=`${d.hostname}${d.pathname}`}catch{}let O;if(p==="gateway-request"&&Array.isArray(s.steps))O=s.steps.map(d=>{const m=[String(d.step)];return d.project&&m.push(String(d.project)),d.prefix&&m.push(String(d.prefix)),d.mode&&m.push(String(d.mode)+(d.ok===!1?" \u2717":d.ok===!0?" \u2713":"")),d.caller&&m.push("by "+String(d.caller)),d.pod&&m.push(String(d.pod)),typeof d.atMs=="number"&&m.push(`@${d.atMs}ms`),m.join(" ")}),b=O.map(d=>d.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(p==="egress")b=`${s.method??"GET"} ${s.host??""} \u2192 ${s.status??"?"}`;else if(i.source==="ai"){if(p==="ai-call"){const d=s.usage??{},m=d.promptTokens!==void 0||d.completionTokens!==void 0?` \xB7 ${g(d.promptTokens)??"?"}\u2192${g(d.completionTokens)??"?"} tok`:"",S=s.status!==void 0?` \xB7 ${String(s.status)}`:s.error?" \xB7 failed":"",h=g(s.toolCallCount)?` \xB7 ${g(s.toolCallCount)} tool call${g(s.toolCallCount)===1?"":"s"}`:"",C=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${s.provider??""}/${s.model??"?"}${m}${S}${h}${C}${s.stream===!0?" \xB7 stream":""}`}else if(p==="ai-round"){const d=s.model??{},m=s.usage??{},S=Array.isArray(s.toolCalls)?s.toolCalls:[],h=`${g(m.promptTokens)??"?"}\u2192${g(m.completionTokens)??"?"} tok`,C=S.length?` \xB7 ${S.length} tool call${S.length===1?"":"s"}`:"",G=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${d.provider??""}/${d.model??""} \xB7 ${h}${C}${G}`}else if(p==="ai-turn-start"){const d=Array.isArray(s.tools)?s.tools:[];b=`skill ${s.skill??""} \xB7 ${s.output??""}${d.length?" \xB7 tools: "+d.join(", "):""}`}else if(p==="ai-tool-call"){const d=s.call??{},m=s.result??{},S=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${d.name??"tool"} ${m.error!=null?"\u2717 "+String(m.error):"\u2713"}${S}`}else if(p==="ai-turn-end"){const d=s.usage??{},m=g(s.rounds)!==void 0?` \xB7 ${g(s.rounds)} round${g(s.rounds)===1?"":"s"}`:"",S=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${s.ok===!1?"FAILED":"ok"} \xB7 ${g(d.promptTokens)??"?"}+${g(d.completionTokens)??"?"} tok${m}${S}`}}let D;p==="db-query"&&typeof s.query=="string"?D=s.query:p==="redis-op"?D=`${s.op??""} ${String(s.key??"").replace(/\d+/g,"#")}`:p==="egress"?D=`${s.method??"GET"} ${s.host??""}`:p==="ai-call"?D=`ai ${s.provider??""} ${s.model??""} ${s.api??""}`:p==="queue-enqueued"?D=`enqueue ${s.queue??""}`:p==="span"&&typeof l.name=="string"?D=l.name:p==="memory-mutation"&&(D=i.title);const L=i.context??{},X=q.commitId??y.commitId??s.commitId,V=Array.isArray(q.why)?q.why.map(d=>typeof d?.type=="string"?d.type:void 0).filter(d=>!!d):[];return{id:i.id,t:i.timestamp,start:J,...D?{sig:D}:{},...Q?{urlKey:Q}:{},...httpFacts(p,s),...(p==="db-query"||p==="redis-op")&&typeof s.valuesId=="string"?{valuesId:s.valuesId}:{},...typeof s.queue=="string"?{queue:s.queue}:{},...s.jobId!=null?{jobId:String(s.jobId)}:{},source:i.source,category:i.category,severity:i.severity,title:U==="threw"&&typeof l.name=="string"?`${l.name} \u2014 threw${Y?` ${Y}`:""}${j!==void 0?` after ${j}ms`:""}`:i.title,kind:p,area:areaOf({source:i.source,category:i.category,title:i.title,kind:p,...typeof s.host=="string"?{host:s.host}:{}}),...p==="egress"&&kt(typeof s.host=="string"?s.host:void 0)?{hop:!0}:{},...p==="egress"&&typeof s.calleeRequestId=="string"?{calleeRequestId:s.calleeRequestId}:{},...U?{outcome:U}:{},...W?{error:W}:{},...K?{captured:K}:{},...typeof l.role=="string"?{role:l.role}:{},...typeof l.spanId=="string"?{spanId:l.spanId}:{},...typeof l.parentSpanId=="string"?{parentSpanId:l.parentSpanId}:{},...p==="log"&&typeof s.level=="string"?{level:s.level}:{},...p==="log"&&typeof s.logger=="string"?{logger:s.logger}:{},...p==="log"&&typeof s.stream=="string"?{stream:s.stream}:{},...typeof L.requestId=="string"?{requestId:L.requestId}:{},...typeof L.parentRequestId=="string"?{parentRequestId:L.parentRequestId}:{},...typeof X=="string"?{commitId:X}:{},...typeof q.componentName=="string"?{component:q.componentName}:{},...typeof q.phase=="string"?{phase:q.phase}:{},...V.length?{why:V}:{},...p==="effect-run"&&typeof y.hookLogicalId=="string"?{hook:y.hookLogicalId}:{},...p==="effect-run"&&y.cleanupRan===!0?{cleanup:!0}:{},...p==="render-commit-truncated"?{renderTotal:g(s.total),renderPublished:g(s.published),...g(s.walkStoppedAt)!==void 0?{renderWalkStoppedAt:g(s.walkStoppedAt)}:{}}:{},...typeof L.projectName=="string"?{project:L.projectName}:typeof s.project=="string"?{project:s.project}:{},...j!==void 0?{durationMs:j}:{},...T&&g(s.startedAt)!==void 0?{fetchStartedAt:g(s.startedAt)}:{},...i.source==="ai"?{ai:f.includeRaw?s:ct(s)}:{},...b?{detail:b}:{},...O?{steps:O}:{}}}R(trimFlowEvent,"trimFlowEvent"),P(trimFlowEvent,"trimFlowEvent"),w(trimFlowEvent,"trimFlowEvent");const Mt=300;export const OUTLIVED_PARENT_MIN_MS=250;const Et=new Set(["egress","db-query","redis-op","ai-call","span","gateway-request","server-request"]),pt=1;function ft(i){return i==="flow-origin"?0:i?.endsWith("-start")?1:i==="gateway-request"?2:i==="server-request"?3:i==="span"?4:i==="render"||i==="render-commit-truncated"?6:i==="effect-run"?7:5}R(ft,"Mt"),P(ft,"Nt"),w(ft,"kindRank");function H(i){return i.kind==="span"&&i.role==="controller"?3.5:i.kind==="queue-process"?3:ft(i.kind)}R(H,"J"),P(H,"Z"),w(H,"causalRank");export function buildFlowDetail(i,f={}){const s=Ct(i),q=i.slice().filter(t=>{const r=t.raw??{},e=typeof r.kind=="string"?r.kind:"";if(e==="subscription-added"||e==="subscription-removed"||e==="hook-run"||e==="store-created"||e==="singleton-instance"||e===Dt)return!1;const o=r.span;return!(typeof o?.name=="string"&&o.name.startsWith("nest.request "))}).map(t=>trimFlowEvent(t,f)),l=new Set;for(let t=q.length-1;t>=0;t--)l.has(q[t].id)?q.splice(t,1):l.add(q[t].id);const F=new Map;for(const t of q)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&!F.has(t.requestId)&&F.set(t.requestId,t.start);const g=w(t=>t.source!=="react"&&t.source!=="valtio"&&t.requestId&&F.has(t.requestId)?F.get(t.requestId):t.start,"anchorOf");q.sort((t,r)=>g(t)-g(r)||t.start-r.start||H(t)-H(r)||(r.durationMs??0)-(t.durationMs??0)||t.t-r.t);const I=w(t=>(t.kind==="span"||t.kind==="server-request"||t.kind==="gateway-request"||t.kind==="queue-process")&&(t.durationMs??0)>0,"spanLike"),y=q;for(const t of y)t.group=t.source==="react"||t.source==="valtio"||t.source==="client-runtime"||t.source==="visual"?"browser":"server";const j=new Map;for(const t of y)if((t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&t.project){const r=j.get(t.requestId)??[];r.push({project:t.project,start:t.start,end:t.start+(t.durationMs??0)}),j.set(t.requestId,r)}const p=w((t,r)=>{const e=j.get(t);if(e?.length)return e.every(o=>o.project===e[0].project)?e[0].project:e.filter(o=>o.start<=r+1&&o.end>=r-1).sort((o,n)=>n.start-o.start)[0]?.project},"projectOf");for(const t of y)if(!t.project&&t.source==="nestjs"&&t.requestId){const r=p(t.requestId,t.start);r&&(t.project=r)}const T=new Map;for(const t of y)t.spanId&&T.set(t.spanId,t);const _=w((t,r)=>{let e=t.parentSpanId?T.get(t.parentSpanId):void 0;for(let o=0;e&&o<64;o++){if(e===r)return!0;e=e.parentSpanId?T.get(e.parentSpanId):void 0}return!1},"inside"),z=new Map(y.map((t,r)=>[t,r])),J=new Map,b=w(t=>{let r=J.get(t.group);r||J.set(t.group,r=new Map);const e=t.requestId;let o=r.get(e);return o||r.set(e,o={spans:[],next:0,alive:[]}),o},"legOf");for(const t of y)I(t)&&Number.isFinite(t.start)&&b(t).spans.push(t);for(const t of J.values())for(const r of t.values())r.spans.sort((e,o)=>e.start-o.start||z.get(e)-z.get(o));const U=w(t=>Number.isFinite(t.start)?t.start:1/0,"startOf");for(const t of y.slice().sort((r,e)=>U(r)-U(e))){const r=t.parentSpanId?T.get(t.parentSpanId):void 0;if(r&&r!==t&&r.group===t.group&&r.requestId===t.requestId){t.parent=r.id;continue}if(!Number.isFinite(t.start))continue;const e=b(t);for(;e.next<e.spans.length&&e.spans[e.next].start<=t.start+pt;)e.alive.push(e.spans[e.next++]);e.alive=e.alive.filter(a=>a.start+(a.durationMs??0)>t.start);const o=e.alive.length>1?e.alive.slice().sort((a,$)=>z.get(a)-z.get($)):e.alive;let n;for(const a of o){if(a===t)continue;const $=a.project,k=t.project;if(a.kind!=="gateway-request"&&t.kind!=="gateway-request"&&$!==void 0&&k!==void 0&&$!==k)continue;const u=a.durationMs??0,c=t.durationMs??0,v=Math.abs(a.start-t.start)<=pt,M=H(a),A=H(t),x=a.start<=t.start;if(!(a.start+u>t.start&&(x||v&&M<A)&&(!v||(M!==A?M<A:x&&u>c))))continue;const E=n?H(n):-1,N=n?Math.abs(a.start-n.start)<=pt:!1,Z=n&&N&&M===E?_(a,n)?1:_(n,a)?-1:0:0;(!n||!N&&a.start>n.start||N&&M>E||Z>0||Z===0&&N&&M===E&&(a.durationMs??0)<(n.durationMs??0))&&(n=a)}n&&(t.parent=n.id)}for(const t of y)delete t.spanId,delete t.parentSpanId;{const t=new Set(y.map(a=>a.id)),r=new Set,e=new Map,o=[],n=w(a=>{const $=[a];for(;$.length;){const k=$.pop();o.push(k),r.add(k.id);const u=e.get(k.id);if(u){e.delete(k.id);for(let c=u.length-1;c>=0;c--)$.push(u[c])}}},"place");for(const a of y)if(a.parent&&a.parent!==a.id&&t.has(a.parent)&&!r.has(a.parent)){const $=e.get(a.parent)??[];$.push(a),e.set(a.parent,$)}else n(a);for(const a of y)r.has(a.id)||(o.push(a),r.add(a.id));for(let a=0;a<o.length;a++)y[a]=o[a]}const W=new Map;for(const t of y){if(!t.requestId)continue;const r=W.get(t.requestId);r?r.push(t):W.set(t.requestId,[t])}const Y=new Map(y.map(t=>[t.id,t])),K=new Map;for(const t of y)t.calleeRequestId&&!K.has(t.calleeRequestId)&&K.set(t.calleeRequestId,t);const Q=w((t,r)=>{const e=(W.get(t)??[]).filter(o=>I(o)&&o.start<=r&&o.start+(o.durationMs??0)>=r);if(e.length!==0)return e.sort((o,n)=>n.start-o.start||(o.durationMs??0)-(n.durationMs??0)),e[0]},"callerNodeFor");for(const t of y){if(!t.parentRequestId||t.kind!=="server-request"&&t.kind!=="gateway-request")continue;const r=t.parent?Y.get(t.parent):void 0;if(r&&r.requestId===t.requestId)continue;const e=t.requestId?K.get(t.requestId):void 0,o=e&&e.start<=t.start?e:Q(t.parentRequestId,t.start);o&&o!==t&&o.start<=t.start&&(t.parent=o.id)}const O=y,D=new Map;for(const t of O)t.kind==="gateway-request"&&t.requestId&&!D.has(t.requestId)&&D.set(t.requestId,t);for(const t of O)if(t.group==="server"&&!t.parent&&t.requestId&&t.kind!=="gateway-request"){const r=D.get(t.requestId);r&&r!==t&&r.start<=t.start&&(t.parent=r.id)}const L=new Set,X=new Set,V=[];for(const t of O){if(t.kind!=="gateway-request")continue;if(!t.requestId){V.push(t);continue}const r=W.get(t.requestId)??[];if(r.filter(n=>n.kind==="gateway-request").sort((n,a)=>n.start-a.start)[0]!==t)continue;const e=r.find(n=>n.kind==="fetch-start"),o=r.find(n=>n.kind==="fetch-done"||n.kind==="fetch-error");if(!e&&!o){V.push(t);continue}e&&(t.fetchStartId=e.id,L.add(e.id)),o&&(t.fetchDoneId=o.id,X.add(o.id))}const d=new Map;for(const t of O){if(!t.urlKey)continue;const r=d.get(t.urlKey)??{gws:[],starts:[],dones:[]};t.kind==="gateway-request"?V.includes(t)&&r.gws.push(t):t.kind==="fetch-start"?L.has(t.id)||r.starts.push(t):(t.kind==="fetch-done"||t.kind==="fetch-error")&&(X.has(t.id)||r.dones.push(t)),d.set(t.urlKey,r)}for(const{gws:t,starts:r,dones:e}of d.values()){t.sort((n,a)=>n.start-a.start),r.sort((n,a)=>n.start-a.start);const o=new Set;t.forEach((n,a)=>{const $=r[a];$&&(n.fetchStartId=$.id);const k=$?$.t:n.start;let u,c=1/0;for(const v of e){if(o.has(v.id))continue;const M=v.fetchStartedAt??v.start-(v.durationMs??0),A=Math.abs(M-k);A<c&&(c=A,u=v)}u&&(n.fetchDoneId=u.id,o.add(u.id))})}const m=new Map,S=new Map;for(const t of O)!t.queue||!t.jobId||(t.kind==="queue-enqueued"&&m.set(`${t.queue}#${t.jobId}`,t),t.kind==="queue-process"&&S.set(`${t.queue}#${t.jobId}`,t));for(const t of O){if(!t.queue||!t.jobId)continue;const r=`${t.queue}#${t.jobId}`;if(t.kind==="queue-process"&&!t.parent){const e=m.get(r);e&&e!==t&&e.start<=t.start&&(t.parent=e.id)}else if(t.kind==="queue-active"||t.kind==="queue-completed"||t.kind==="queue-failed"){const e=S.get(r);e&&e!==t&&e.start<=t.start&&(t.parent=e.id)}}{const t=new Map(y.map(r=>[r.id,r]));for(const r of y){if(!r.parent||!Et.has(r.kind??"")||r.durationMs===void 0)continue;const e=t.get(r.parent);if(!e||e.kind!=="span"||!((e.durationMs??0)>0))continue;const o=Math.round(r.start+r.durationMs-(e.start+e.durationMs));if(o<OUTLIVED_PARENT_MIN_MS)continue;r.outlivedParentMs=o;const n=e.leftRunning??{count:0,longestMs:0};e.leftRunning={count:n.count+1,longestMs:Math.max(n.longestMs,o)}}for(const r of y){const e=[];r.leftRunning&&e.push(`ended before ${r.leftRunning.count===1?"a call":`${r.leftRunning.count} calls`} it started had finished \u2014 ${r.leftRunning.count===1?"it":"the longest"} ran on ${r.leftRunning.longestMs}ms (a timeout that gave up, or work not awaited)`),r.outlivedParentMs!==void 0&&e.push(`ran on ${r.outlivedParentMs}ms after the span that started it had ended`),e.length>0&&(r.detail=[r.detail,...e].filter(Boolean).join(" \xB7 "))}}let h=y;{const t=new Map;for(const e of h)e.kind==="fetch-start"&&t.set(e.id,e);const r=new Map;for(const e of h){if(e.kind!=="fetch-done"&&e.kind!=="fetch-error")continue;const o=[...t.values()].find($=>$.requestId&&$.requestId===e.requestId)?.id,n=o?t.get(o):void 0;if(!n)continue;const a=e.fetchStartedAt??n.start;n.title=e.title,n.severity=e.severity,n.durationMs=e.durationMs??Math.max(0,e.t-a),n.kind="fetch",e.detail&&!n.detail&&(n.detail=e.detail),r.set(e.id,n.id)}if(r.size>0){h=h.filter(e=>!r.has(e.id));for(const e of h)for(e.fetchDoneId&&r.has(e.fetchDoneId)&&(e.fetchDoneId=r.get(e.fetchDoneId));e.parent&&r.has(e.parent);)e.parent=r.get(e.parent)}}const C=w(t=>!!t.commitId&&(t.kind==="render"||t.kind==="effect-run"||t.kind==="render-commit-truncated"),"commitMember"),G=w(t=>[...new Set(t)],"uniq"),ot=w(t=>G(t.map(r=>r.component).filter(r=>!!r)),"named"),It=w(t=>t.length<=2?t.join(" + "):`${t[0]} + ${t.length-1} more`,"nameList"),mt=w(t=>{const r=new Map;for(const e of t)e.component&&r.set(e.component,(r.get(e.component)??0)+1);return[...r].map(([e,o])=>o>1?`${e} \xD7${o}`:e).join(", ")},"tally"),bt=w(t=>{if(!t)return"effect";const r=/([^/\\]+?):(\d+)(?::\d+)?$/.exec(t);return r?`${r[1]}:${r[2]}`:t},"shortHook"),nt=w(t=>`${bt(t.hook)}${t.cleanup?" (cleanup)":""}`,"hookLabel"),gt=w(t=>{const r=Math.min(...t.map(o=>o.start)),e=Math.max(...t.map(o=>o.start+(o.durationMs??0)));return{start:r,durationMs:e-r}},"extent"),ht=w(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 at(t){const r=t[0],e=t.filter(B=>B.kind==="render"),o=t.filter(B=>B.kind==="effect-run"),n=t.find(B=>B.kind==="render-commit-truncated"),a=[...e].sort((B,tt)=>(tt.durationMs??0)-(B.durationMs??0)),$=a.filter(B=>(B.why??[]).some(tt=>tt!=="parent-render")),k=G($.flatMap(B=>(B.why??[]).filter(tt=>tt!=="parent-render"))),u=ot($),c=e.filter(B=>B.phase==="mount"),v=e.filter(B=>B.phase!=="mount"&&!$.includes(B)),M=a[0]?.component??"view",A=e.length>0&&c.length===e.length,x=k.length?k.join(" + "):void 0,E=A?"mount":"update",N=u.length?`view update \xB7 ${It(u)} \u2190 ${x}`:A?`view mount \xB7 ${M}`:`view update \xB7 ${M}`,Z=n?.renderTotal??e.length,jt=[c.length?`mounted ${mt(c)}`:"",v.length?`re-rendered ${mt(v)}`:"",!u.length&&!A&&e.length?"trigger not recorded \u2014 every captured render came from its parent":"",n?.renderWalkStoppedAt!==void 0?`at least ${Z} renders (the walk stopped at ${n.renderWalkStoppedAt} fibers), ${n.renderPublished??e.length} recorded`:n?`${Z} renders, ${n.renderPublished??e.length} recorded (per-commit cap)`:`${e.length} render${e.length===1?"":"s"}`,o.length?`${o.length} effect${o.length===1?"":"s"}: ${o.map(nt).join(", ")}`:""].filter(Boolean).join(" \xB7 "),vt=ot(e);return ht({...r,...gt(t),kind:"view-update",title:N,detail:jt,commitId:r.commitId,viewPhase:E,...x?{cause:x}:{},causeComponents:u,components:vt,mounted:ot(c),renderCount:Z,...n?.renderWalkStoppedAt!==void 0?{renderCountAtLeast:!0}:{},recordedRenders:e.length,effects:o.length,effectHooks:o.map(nt),memberIds:t.map(B=>B.id),sig:`commit:${E}:${x??"-"}:${u.join(",")}:${vt.slice().sort().join(",")}`,severity:t.some(B=>B.severity==="error")?"error":r.severity})}R(at,"ct"),P(at,"It"),w(at,"viewUpdateNode");function it(t){const r=t[0],e=t.map(nt);return ht({...r,...gt(t),kind:"commit-effects",title:t.length===1?`effect \xB7 ${e[0]}`:`effects \xB7 ${e[0]} + ${t.length-1} more`,detail:e.join(", "),commitId:r.commitId,effects:t.length,effectHooks:e,memberIds:t.map(o=>o.id),sig:`effects:${e.slice().sort().join(",")}`})}R(it,"lt"),P(it,"kt"),w(it,"effectsNode");const xt=w(t=>G(t.map(r=>r==="state-update"?"state update":r==="fetch-start"?"request":r==="flow-origin"?"interaction":"response")).join(" + "),"describeInputs");function dt(t,r){const e=t[0],o=t[t.length-1],n=t.length,a=e.detail,$=Math.min(...t.map(v=>v.start)),k=Math.max(...t.map(v=>v.start+(v.durationMs??0))),u=Math.round(t.reduce((v,M)=>v+(M.durationMs??0),0)/n*10)/10,c=Math.round((k-$)*10)/10;e.count=n,e.avgMs=u,e.wallMs=c,e.durationMs=k-$,e.items=t.slice(0,12).map(v=>({start:v.start-$,...v.durationMs!=null?{durationMs:v.durationMs}:{}})),e.memberIds=t.flatMap(v=>v.memberIds??[v.id]),e.title=`\xD7${n} ${e.title}`,t.some(v=>v.severity==="error")&&(e.severity="error"),e.kind==="view-update"?e.detail=[`${n} commits, ${r.length?`one per ${xt(r)}`:"back to back"}`,`avg ${u}ms \xB7 wall ${c}ms`,a??""].filter(Boolean).join(" \xB7 "):e.kind==="state-update"&&a&&o.detail?e.detail=`${n} updates in a row \xB7 wall ${c}ms \xB7 first ${a} \xB7 last ${o.detail}`:e.detail=[`${n} in a row \xB7 wall ${c}ms`,a??""].filter(Boolean).join(" \xB7 ")}R(dt,"pt"),P(dt,"qt"),w(dt,"collapseRepeat");const rt=[],st=new Map,$t=new Set;for(let t=0;t<h.length;t++){if($t.has(t))continue;const r=h[t];if(!C(r)){rt.push(r);continue}const e=[t];for(let a=t+1;a<h.length;a++){const $=h[a];if($.group==="browser"){if(!C($)||$.commitId!==r.commitId)break;e.push(a)}}for(const a of e)$t.add(a);const o=e.map(a=>h[a]),n=o.some(a=>a.kind!=="effect-run")?at(o):it(o);for(const a of o)a.id!==n.id&&st.set(a.id,n.id);rt.push(n)}if(st.size>0||rt.some(t=>t.kind==="view-update"||t.kind==="commit-effects")){h=rt;for(const t of h)for(;t.parent&&st.has(t.parent);)t.parent=st.get(t.parent)}{const t=new Map;for(const r of h)r.kind==="view-update"&&r.commitId&&!t.has(r.commitId)&&t.set(r.commitId,r);for(const r of h){if(r.kind!=="commit-effects"||r.parent||!r.commitId)continue;const e=t.get(r.commitId);e&&e.start<=r.start&&(r.parent=e.id)}}{const t=new Set(["state-update","fetch","fetch-start","fetch-done","fetch-error","flow-origin"]),r=h.map((u,c)=>u.group==="browser"?c:-1).filter(u=>u>=0),e=w(u=>`${u.kind}|${u.sig??u.title}`,"keyOf"),o=r.map(u=>e(h[u])),n=w((u,c,v)=>{for(let M=0;M<v;M++)if(o[u+M]!==o[c+M])return!1;return!0},"sameBlock"),a=w(u=>o[u].split("|")[0],"kindAt"),$=w(u=>{let c=0,v=1;for(let M=1;M<=4&&u+M<=o.length;M++){let A=1;for(;u+(A+1)*M<=o.length&&n(u,u+A*M,M);)A+=1;A>=3&&M*A>c*v&&(c=M,v=A)}return{k:c,r:v}},"bestBlockAt"),k=new Map;for(let u=0;u<o.length;){const{k:c,r:v}=$(u);if(c===0){u+=1;continue}const M=[...Array(c).keys()].find(x=>t.has(a(u+x)));if(M!==void 0&&M>0){const x=$(u+M);if(x.k===c&&x.r>=3&&x.r>=v-1){u+=M;continue}}const A=o.slice(u,u+c).map(x=>x.split("|")[0]).filter(x=>t.has(x));for(let x=0;x<c;x++){const E=[];for(let N=0;N<v;N++)E.push(h[r[u+x+N*c]]);dt(E,A);for(const N of E.slice(1))k.set(N.id,E[0].id)}u+=c*v}if(k.size>0){h=h.filter(u=>!k.has(u.id));for(const u of h)for(;u.parent&&k.has(u.parent);)u.parent=k.get(u.parent)}}{const t=new Map(h.map(r=>[r.id,r]));for(const r of h){const e=new Set([r.id]);let o=r;for(;o?.parent;){if(e.has(o.parent)){o.parent=void 0;break}e.add(o.parent),o=t.get(o.parent)}}}const yt=w(t=>{const r=new Map;for(const o of h){if(!o.sig||I(o)!==t||o.kind==="server-request"||o.kind==="gateway-request"||o.group==="browser")continue;const n=`${o.parent??"root"}|${o.kind}|${o.sig}`,a=r.get(n);a?a.push(o):r.set(n,[o])}const e=new Map;for(const o of r.values()){if(o.length<3)continue;o.sort((c,v)=>c.start-v.start);const n=o[0];let a=!1;for(let c=0;c+1<o.length;c++)if(o[c+1].start<o[c].start+(o[c].durationMs??0)){a=!0;break}const $=n.start,k=Math.max(...o.map(c=>c.start+(c.durationMs??0))),u=o.reduce((c,v)=>c+(v.durationMs??0),0);n.count=o.length,n.parallel=a,n.avgMs=Math.round(u/o.length*10)/10,n.wallMs=k-$,n.durationMs=k-$,n.title=`\xD7${o.length} ${n.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,n.detail=`${n.sig} \xD7${o.length} ${a?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${n.avgMs}ms \xB7 wall ${n.wallMs}ms`,n.items=o.slice(0,12).map(c=>({start:c.start-$,...c.durationMs!=null?{durationMs:c.durationMs}:{}})),n.memberIds=o.flatMap(c=>c.memberIds??[c.id]),o.some(c=>c.severity==="error")&&(n.severity="error");for(const c of o.slice(1))e.set(c.id,n.id)}if(e.size!==0){h=h.filter(o=>!e.has(o.id));for(const o of h)for(;o.parent&&e.has(o.parent);)o.parent=e.get(o.parent)}},"aggregatePass");yt(!0),yt(!1);for(const t of h){if(!I(t))continue;const r=t.durationMs??0;if(r<40)continue;const e=h.filter(k=>k.parent===t.id&&(k.durationMs??0)>0).map(k=>[k.start,k.start+(k.durationMs??0)]).sort((k,u)=>k[0]-u[0]);let o=0,n=-1,a=-1;for(const[k,u]of e)k>a?(a>n&&(o+=a-n),n=k,a=u):u>a&&(a=u);a>n&&(o+=a-n);const $=Math.max(0,r-o);($>=50||$/r>=.7&&r>=40)&&(t.selfMs=$,t.detail=`\u26A0 cpu-heavy: ${$}ms self-time of ${r}ms${t.detail?" \xB7 "+t.detail:""}`)}return{events:h,...s?{sql:s}:{}}}R(buildFlowDetail,"buildFlowDetail"),P(buildFlowDetail,"buildFlowDetail"),w(buildFlowDetail,"buildFlowDetail");
|
|
1
|
+
"use strict";var jt=Object.defineProperty;var R=(i,f)=>jt(i,"name",{value:f,configurable:!0});var St=Object.defineProperty,k=R((i,f)=>St(i,"name",{value:f,configurable:!0}),"I");import{redactDeep as Bt,redactText as nt,redactUrlParams as At}from"./redact.js";import{templatisePath as ht}from"./route-template.js";import{SQL_ACCOUNT_KIND as Rt,sqlAccountingOf as Tt}from"./flow-segments.js";import{isServiceHopHost as $t}from"./service-hop.js";import{boundedClone as Ct}from"@lensmcp/protocol-types";export function areaOf(i){const{source:f,category:s,title:M,kind:l}=i;return f==="ai"?"ai":f==="perf"&&l==="event-loop-stall"?"services":l?.startsWith("memory")||l==="db-query"?"data":f==="gateway"||l==="gateway-request"?"gateway":l==="queue-process"||l==="queue-active"||l==="queue-completed"||l==="queue-failed"?"services":f==="db"||f==="redis"||f==="queue"||l==="redis-op"||l?.startsWith("queue-")||f==="fs"||l==="fs-ops"?"data":f==="exec"||l==="exec"||l==="egress"&&$t(i.host)?"services":f==="external"||l==="egress"?"network":f==="nestjs"||f==="nest"?/(?:Repository|Repo|Dao|Store|EntityManager|DataSource|QueryRunner|OrmClient)\./.test(M)?"data":"services":f==="valtio"?"state":s==="network"?"network":"browser"}R(areaOf,"areaOf"),k(areaOf,"areaOf");const yt=240,Dt=new Set(["systemPrompt","prompt","prompts","messages","completion","completions","input","output","draft","text","content","result","arguments","params"]),Pt=new Set(["tenantId","caller","userId","accountId","email","subject"]),Nt=8;function vt(i){const f=rt(i,0);return Ct(Bt({redacted:!0,...f}),{rawByteLimit:16*1024}).value}R(vt,"Ct"),k(vt,"aiProjection");function rt(i,f){if(typeof i=="string")return kt(i);if(i===null||typeof i!="object")return i;if(f>=Nt)return;if(Array.isArray(i))return i.slice(0,32).map(M=>rt(M,f+1));const s={};for(const[M,l]of Object.entries(i))if(!Pt.has(M)){if(Dt.has(M)){typeof l=="string"?s[`${M}Chars`]=l.length:Array.isArray(l)?s[`${M}Count`]=l.length:l!=null&&(s[`${M}Present`]=!0);continue}s[M]=rt(l,f+1)}return s}R(rt,"it"),k(rt,"projectAi");function kt(i){return i.length<=yt?nt(i):`${nt(i.slice(0,yt))}\u2026`}R(kt,"Et"),k(kt,"clipText");export function httpFacts(i,f){const s=k(I=>typeof I=="string"&&I.length>0?I:void 0,"str"),M=typeof f.status=="number"?f.status:void 0,l=k(I=>At(I.split("?")[0]??I)||"/","pathOf"),P=k((I,y,j={})=>({...I?{method:I.toUpperCase()}:{},...y?{rawPath:y,route:ht(y)}:{},...M!==void 0?{status:M}:{},...j}),"facts");if(i==="gateway-request"){const I=s(f.url);return P(s(f.method),I?l(I):void 0,{...s(f.host)?{host:s(f.host)}:{},...s(f.caller)?{caller:s(f.caller)}:{}})}if(i==="egress"){const I=s(f.path),y=s(f.exchangeId);return P(s(f.method)??"GET",I?l(I):void 0,{...s(f.host)?{host:s(f.host)}:{},...y?{exchangeId:y}:{}})}if(i==="fetch-start"||i==="fetch-done"||i==="fetch-error"){const I=s(f.href)??s(f.url);let y,j;if(I)try{const p=new URL(I,"http://relative.invalid");y=l(p.pathname),p.hostname!=="relative.invalid"&&(j=p.hostname)}catch{}return P(s(f.method)??"GET",y,j?{host:j}:{})}if(i==="ai-call")return{...M!==void 0?{status:M}:{},...f.stream===!0?{streamed:!0}:{}};const g=f.request;if(g&&typeof g=="object"){const I=g,y=s(I.route),j=s(I.method);if(!y&&!j)return{};const p=typeof I.status=="number"?I.status:void 0,T=y?l(y):void 0;return{...j?{method:j.toUpperCase()}:{},...T?{rawPath:T,route:T.includes(":")?T:ht(T)}:{},...p!==void 0?{status:p}:{}}}return{}}R(httpFacts,"httpFacts"),k(httpFacts,"httpFacts");export function trimFlowEvent(i,f={}){const s=i.raw??{},M=s.render??{},l=s.span??{},P=s.request??{},g=k(d=>typeof d=="number"?d:void 0,"num"),I=s.loop??{},y=s.effect??{},j=g(s.durationMs)??g(l.durationMs)??g(P.durationMs)??g(I.durationMs)??g(M.actualDurationMs)??g(y.durationMs),p=typeof s.kind=="string"?s.kind:void 0,T=p==="fetch-done"||p==="fetch-error",G=g(M.commitTime),H=p==="render"&&G!==void 0&&Math.abs(G-i.timestamp)<6e4,V=T?i.timestamp:H?G:g(s.startedAt)??g(l.startTime)??g(P.startedAt)??g(I.startedAt)??(j!==void 0?i.timestamp-j:i.timestamp);let b;if(typeof s.query=="string"){const d=Array.isArray(s.params)?` [${s.params.join(", ")}]`:"",m=typeof s.result=="string"?` \u2192 ${s.result}`:"";b=s.query+d+m}else if(typeof s.command=="string"){const d=typeof s.value=="string"?` \u2192 ${s.value}`:s.hit===!1?" \u2192 (miss)":"";b=s.command+d}else if(p==="state-update"){const d=s.update??{};let m="";try{m=JSON.stringify(d.preview)}catch{}b=`${d.storeId??""}.${d.path??""} = ${m}`}else if(p==="fs-ops"&&Array.isArray(s.paths))b=s.paths.slice(0,8).map(d=>{const m=d??{},B=typeof m.n=="number"&&m.n>1?` \xD7${m.n}`:"",h=typeof m.bytes=="number"&&m.bytes>0?` (${m.bytes>=1024?`${(m.bytes/1024).toFixed(1)} KB`:`${m.bytes} B`})`:"";return`${String(m.op??"?")} ${String(m.path??"?")}${B}${h}`}).join(" \xB7 ");else if(p==="exec"&&typeof s.cmd=="string")b=`${s.cmd} \u2192 ${s.code??s.signal??s.error??"?"}`;else if(p==="queue-completed"&&typeof s.returned=="string")b=`returned ${s.returned}`;else if(p==="queue-enqueued")b=`${s.job??"job"}#${s.jobId??"?"} \u2192 ${s.queue??""}${typeof s.data=="string"?" "+s.data:""}`;else if(p==="log"){const d=P.error??{},m=typeof d.stack=="string"?d.stack:typeof s.text=="string"?s.text:void 0;m&&m!==i.title&&(b=m)}let L,W,Y,U;if(p==="span"){const d=l.outcome;if(L=d==="threw"||d==="returned"?d:l.status==="error"?"threw":l.status==="ok"?"returned":void 0,L==="threw"){const h=l.error??{},D=typeof h.name=="string"?h.name:void 0,K=typeof h.message=="string"?h.message:typeof i.message=="string"?i.message:void 0;Y=D,W=nt([D,K].filter(Boolean).join(": "))||void 0}const m=typeof l.args=="string"?l.args:void 0,B=typeof l.result=="string"?l.result:void 0;if(m!==void 0||B!==void 0){U=[...m!==void 0?["args"]:[],...B!==void 0?["result"]:[]];const h=k(D=>D.length>wt?`${D.slice(0,wt)}\u2026`:D,"short");b=[m!==void 0?`args ${h(m)}`:"",B!==void 0?`returned ${h(B)}`:""].filter(Boolean).join(" \u2192 ")}}let _;if(p==="gateway-request")_=`${s.host??""}${String(s.url??"").split("?")[0]}`;else if(p==="fetch-start"||p==="fetch-done"||p==="fetch-error")try{const d=new URL(String(s.href??s.url??""));_=`${d.hostname}${d.pathname}`}catch{}let O;if(p==="gateway-request"&&Array.isArray(s.steps))O=s.steps.map(d=>{const m=[String(d.step)];return d.project&&m.push(String(d.project)),d.prefix&&m.push(String(d.prefix)),d.mode&&m.push(String(d.mode)+(d.ok===!1?" \u2717":d.ok===!0?" \u2713":"")),d.caller&&m.push("by "+String(d.caller)),d.pod&&m.push(String(d.pod)),typeof d.atMs=="number"&&m.push(`@${d.atMs}ms`),m.join(" ")}),b=O.map(d=>d.replace(/ @\d+ms$/,"")).join(" \u2192 ");else if(p==="egress")b=`${s.method??"GET"} ${s.host??""} \u2192 ${s.status??"?"}`;else if(i.source==="ai"){if(p==="ai-call"){const d=s.usage??{},m=d.promptTokens!==void 0||d.completionTokens!==void 0?` \xB7 ${g(d.promptTokens)??"?"}\u2192${g(d.completionTokens)??"?"} tok`:"",B=s.status!==void 0?` \xB7 ${String(s.status)}`:s.error?" \xB7 failed":"",h=g(s.toolCallCount)?` \xB7 ${g(s.toolCallCount)} tool call${g(s.toolCallCount)===1?"":"s"}`:"",D=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${s.provider??""}/${s.model??"?"}${m}${B}${h}${D}${s.stream===!0?" \xB7 stream":""}`}else if(p==="ai-round"){const d=s.model??{},m=s.usage??{},B=Array.isArray(s.toolCalls)?s.toolCalls:[],h=`${g(m.promptTokens)??"?"}\u2192${g(m.completionTokens)??"?"} tok`,D=B.length?` \xB7 ${B.length} tool call${B.length===1?"":"s"}`:"",K=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${d.provider??""}/${d.model??""} \xB7 ${h}${D}${K}`}else if(p==="ai-turn-start"){const d=Array.isArray(s.tools)?s.tools:[];b=`skill ${s.skill??""} \xB7 ${s.output??""}${d.length?" \xB7 tools: "+d.join(", "):""}`}else if(p==="ai-tool-call"){const d=s.call??{},m=s.result??{},B=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${d.name??"tool"} ${m.error!=null?"\u2717 "+String(m.error):"\u2713"}${B}`}else if(p==="ai-turn-end"){const d=s.usage??{},m=g(s.rounds)!==void 0?` \xB7 ${g(s.rounds)} round${g(s.rounds)===1?"":"s"}`:"",B=g(s.durationMs)!==void 0?` \xB7 ${(g(s.durationMs)/1e3).toFixed(1)}s`:"";b=`${s.ok===!1?"FAILED":"ok"} \xB7 ${g(d.promptTokens)??"?"}+${g(d.completionTokens)??"?"} tok${m}${B}`}}let C;p==="db-query"&&typeof s.query=="string"?C=s.query:p==="redis-op"?C=`${s.op??""} ${String(s.key??"").replace(/\d+/g,"#")}`:p==="egress"?C=`${s.method??"GET"} ${s.host??""}`:p==="ai-call"?C=`ai ${s.provider??""} ${s.model??""} ${s.api??""}`:p==="queue-enqueued"?C=`enqueue ${s.queue??""}`:p==="span"&&typeof l.name=="string"?C=l.name:p==="memory-mutation"&&(C=i.title);const E=i.context??{},Z=M.commitId??y.commitId??s.commitId,z=Array.isArray(M.why)?M.why.map(d=>typeof d?.type=="string"?d.type:void 0).filter(d=>!!d):[];return{id:i.id,t:i.timestamp,start:V,...C?{sig:C}:{},..._?{urlKey:_}:{},...httpFacts(p,s),...(p==="db-query"||p==="redis-op")&&typeof s.valuesId=="string"?{valuesId:s.valuesId}:{},...typeof s.queue=="string"?{queue:s.queue}:{},...s.jobId!=null?{jobId:String(s.jobId)}:{},source:i.source,category:i.category,severity:i.severity,title:L==="threw"&&typeof l.name=="string"?`${l.name} \u2014 threw${Y?` ${Y}`:""}${j!==void 0?` after ${j}ms`:""}`:i.title,kind:p,area:areaOf({source:i.source,category:i.category,title:i.title,kind:p,...typeof s.host=="string"?{host:s.host}:{}}),...p==="egress"&&$t(typeof s.host=="string"?s.host:void 0)?{hop:!0}:{},...p==="egress"&&typeof s.calleeRequestId=="string"?{calleeRequestId:s.calleeRequestId}:{},...L?{outcome:L}:{},...W?{error:W}:{},...U?{captured:U}:{},...typeof l.role=="string"?{role:l.role}:{},...typeof l.spanId=="string"?{spanId:l.spanId}:{},...typeof l.parentSpanId=="string"?{parentSpanId:l.parentSpanId}:{},...p==="log"&&typeof s.level=="string"?{level:s.level}:{},...p==="log"&&typeof s.logger=="string"?{logger:s.logger}:{},...p==="log"&&typeof s.stream=="string"?{stream:s.stream}:{},...typeof E.requestId=="string"?{requestId:E.requestId}:{},...typeof E.parentRequestId=="string"?{parentRequestId:E.parentRequestId}:{},...typeof Z=="string"?{commitId:Z}:{},...typeof M.componentName=="string"?{component:M.componentName}:{},...typeof M.phase=="string"?{phase:M.phase}:{},...z.length?{why:z}:{},...p==="effect-run"&&typeof y.hookLogicalId=="string"?{hook:y.hookLogicalId}:{},...p==="effect-run"&&y.cleanupRan===!0?{cleanup:!0}:{},...p==="render-commit-truncated"?{renderTotal:g(s.total),renderPublished:g(s.published),...g(s.walkStoppedAt)!==void 0?{renderWalkStoppedAt:g(s.walkStoppedAt)}:{}}:{},...typeof E.projectName=="string"?{project:E.projectName}:typeof s.project=="string"?{project:s.project}:{},...j!==void 0?{durationMs:j}:{},...T&&g(s.startedAt)!==void 0?{fetchStartedAt:g(s.startedAt)}:{},...i.source==="ai"?{ai:f.includeRaw?s:vt(s)}:{},...b?{detail:b}:{},...O?{steps:O}:{}}}R(trimFlowEvent,"trimFlowEvent"),k(trimFlowEvent,"trimFlowEvent");const wt=300;export const OUTLIVED_PARENT_MIN_MS=250;const Ot=new Set(["egress","db-query","redis-op","ai-call","span","gateway-request","server-request"]),at=1;function Mt(i){return i==="flow-origin"?0:i?.endsWith("-start")?1:i==="gateway-request"?2:i==="server-request"?3:i==="span"?4:i==="render"||i==="render-commit-truncated"?6:i==="effect-run"?7:5}R(Mt,"Nt"),k(Mt,"kindRank");function J(i){return i.kind==="span"&&i.role==="controller"?3.5:i.kind==="queue-process"?3:Mt(i.kind)}R(J,"Z"),k(J,"causalRank");export function buildFlowDetail(i,f={}){const s=Tt(i),M=i.slice().filter(t=>{const r=t.raw??{},e=typeof r.kind=="string"?r.kind:"";if(e==="subscription-added"||e==="subscription-removed"||e==="hook-run"||e==="store-created"||e==="singleton-instance"||e===Rt)return!1;const o=r.span;return!(typeof o?.name=="string"&&o.name.startsWith("nest.request "))}).map(t=>trimFlowEvent(t,f)),l=new Set;for(let t=M.length-1;t>=0;t--)l.has(M[t].id)?M.splice(t,1):l.add(M[t].id);const P=new Map;for(const t of M)(t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&!P.has(t.requestId)&&P.set(t.requestId,t.start);const g=k(t=>t.source!=="react"&&t.source!=="valtio"&&t.requestId&&P.has(t.requestId)?P.get(t.requestId):t.start,"anchorOf");M.sort((t,r)=>g(t)-g(r)||t.start-r.start||J(t)-J(r)||(r.durationMs??0)-(t.durationMs??0)||t.t-r.t);const I=k(t=>(t.kind==="span"||t.kind==="server-request"||t.kind==="gateway-request"||t.kind==="queue-process")&&(t.durationMs??0)>0,"spanLike"),y=M;for(const t of y)t.group=t.source==="react"||t.source==="valtio"||t.source==="client-runtime"||t.source==="visual"?"browser":"server";const j=new Map;for(const t of y)if((t.kind==="gateway-request"||t.kind==="queue-process")&&t.requestId&&t.project){const r=j.get(t.requestId)??[];r.push({project:t.project,start:t.start,end:t.start+(t.durationMs??0)}),j.set(t.requestId,r)}const p=k((t,r)=>{const e=j.get(t);if(e?.length)return e.every(o=>o.project===e[0].project)?e[0].project:e.filter(o=>o.start<=r+1&&o.end>=r-1).sort((o,n)=>n.start-o.start)[0]?.project},"projectOf");for(const t of y)if(!t.project&&t.source==="nestjs"&&t.requestId){const r=p(t.requestId,t.start);r&&(t.project=r)}const T=new Map;for(const t of y)t.spanId&&T.set(t.spanId,t);const G=k((t,r)=>{let e=t.parentSpanId?T.get(t.parentSpanId):void 0;for(let o=0;e&&o<64;o++){if(e===r)return!0;e=e.parentSpanId?T.get(e.parentSpanId):void 0}return!1},"inside"),H=new Map(y.map((t,r)=>[t,r])),V=new Map,b=k(t=>{let r=V.get(t.group);r||V.set(t.group,r=new Map);const e=t.requestId;let o=r.get(e);return o||r.set(e,o={spans:[],next:0,alive:[]}),o},"legOf");for(const t of y)I(t)&&Number.isFinite(t.start)&&b(t).spans.push(t);for(const t of V.values())for(const r of t.values())r.spans.sort((e,o)=>e.start-o.start||H.get(e)-H.get(o));const L=k(t=>Number.isFinite(t.start)?t.start:1/0,"startOf");for(const t of y.slice().sort((r,e)=>L(r)-L(e))){const r=t.parentSpanId?T.get(t.parentSpanId):void 0;if(r&&r!==t&&r.group===t.group&&r.requestId===t.requestId){t.parent=r.id;continue}if(!Number.isFinite(t.start))continue;const e=b(t);for(;e.next<e.spans.length&&e.spans[e.next].start<=t.start+at;)e.alive.push(e.spans[e.next++]);e.alive=e.alive.filter(a=>a.start+(a.durationMs??0)>t.start);const o=e.alive.length>1?e.alive.slice().sort((a,$)=>H.get(a)-H.get($)):e.alive;let n;for(const a of o){if(a===t)continue;const $=a.project,w=t.project;if(a.kind!=="gateway-request"&&t.kind!=="gateway-request"&&$!==void 0&&w!==void 0&&$!==w)continue;const u=a.durationMs??0,c=t.durationMs??0,v=Math.abs(a.start-t.start)<=at,q=J(a),A=J(t),x=a.start<=t.start;if(!(a.start+u>t.start&&(x||v&&q<A)&&(!v||(q!==A?q<A:x&&u>c))))continue;const F=n?J(n):-1,N=n?Math.abs(a.start-n.start)<=at:!1,Q=n&&N&&q===F?G(a,n)?1:G(n,a)?-1:0:0;(!n||!N&&a.start>n.start||N&&q>F||Q>0||Q===0&&N&&q===F&&(a.durationMs??0)<(n.durationMs??0))&&(n=a)}n&&(t.parent=n.id)}for(const t of y)delete t.spanId,delete t.parentSpanId;{const t=new Set(y.map(a=>a.id)),r=new Set,e=new Map,o=[],n=k(a=>{const $=[a];for(;$.length;){const w=$.pop();o.push(w),r.add(w.id);const u=e.get(w.id);if(u){e.delete(w.id);for(let c=u.length-1;c>=0;c--)$.push(u[c])}}},"place");for(const a of y)if(a.parent&&a.parent!==a.id&&t.has(a.parent)&&!r.has(a.parent)){const $=e.get(a.parent)??[];$.push(a),e.set(a.parent,$)}else n(a);for(const a of y)r.has(a.id)||(o.push(a),r.add(a.id));for(let a=0;a<o.length;a++)y[a]=o[a]}const W=new Map;for(const t of y){if(!t.requestId)continue;const r=W.get(t.requestId);r?r.push(t):W.set(t.requestId,[t])}const Y=new Map(y.map(t=>[t.id,t])),U=new Map;for(const t of y)t.calleeRequestId&&!U.has(t.calleeRequestId)&&U.set(t.calleeRequestId,t);const _=k((t,r)=>{const e=(W.get(t)??[]).filter(o=>I(o)&&o.start<=r&&o.start+(o.durationMs??0)>=r);if(e.length!==0)return e.sort((o,n)=>n.start-o.start||(o.durationMs??0)-(n.durationMs??0)),e[0]},"callerNodeFor");for(const t of y){if(!t.parentRequestId||t.kind!=="server-request"&&t.kind!=="gateway-request")continue;const r=t.parent?Y.get(t.parent):void 0;if(r&&r.requestId===t.requestId)continue;const e=t.requestId?U.get(t.requestId):void 0,o=e&&e.start<=t.start?e:_(t.parentRequestId,t.start);o&&o!==t&&o.start<=t.start&&(t.parent=o.id)}const O=y,C=new Map;for(const t of O)t.kind==="gateway-request"&&t.requestId&&!C.has(t.requestId)&&C.set(t.requestId,t);for(const t of O)if(t.group==="server"&&!t.parent&&t.requestId&&t.kind!=="gateway-request"){const r=C.get(t.requestId);r&&r!==t&&r.start<=t.start&&(t.parent=r.id)}const E=new Set,Z=new Set,z=[];for(const t of O){if(t.kind!=="gateway-request")continue;if(!t.requestId){z.push(t);continue}const r=W.get(t.requestId)??[];if(r.filter(n=>n.kind==="gateway-request").sort((n,a)=>n.start-a.start)[0]!==t)continue;const e=r.find(n=>n.kind==="fetch-start"),o=r.find(n=>n.kind==="fetch-done"||n.kind==="fetch-error");if(!e&&!o){z.push(t);continue}e&&(t.fetchStartId=e.id,E.add(e.id)),o&&(t.fetchDoneId=o.id,Z.add(o.id))}const d=new Map;for(const t of O){if(!t.urlKey)continue;const r=d.get(t.urlKey)??{gws:[],starts:[],dones:[]};t.kind==="gateway-request"?z.includes(t)&&r.gws.push(t):t.kind==="fetch-start"?E.has(t.id)||r.starts.push(t):(t.kind==="fetch-done"||t.kind==="fetch-error")&&(Z.has(t.id)||r.dones.push(t)),d.set(t.urlKey,r)}for(const{gws:t,starts:r,dones:e}of d.values()){t.sort((n,a)=>n.start-a.start),r.sort((n,a)=>n.start-a.start);const o=new Set;t.forEach((n,a)=>{const $=r[a];$&&(n.fetchStartId=$.id);const w=$?$.t:n.start;let u,c=1/0;for(const v of e){if(o.has(v.id))continue;const q=v.fetchStartedAt??v.start-(v.durationMs??0),A=Math.abs(q-w);A<c&&(c=A,u=v)}u&&(n.fetchDoneId=u.id,o.add(u.id))})}const m=new Map,B=new Map;for(const t of O)!t.queue||!t.jobId||(t.kind==="queue-enqueued"&&m.set(`${t.queue}#${t.jobId}`,t),t.kind==="queue-process"&&B.set(`${t.queue}#${t.jobId}`,t));for(const t of O){if(!t.queue||!t.jobId)continue;const r=`${t.queue}#${t.jobId}`;if(t.kind==="queue-process"&&!t.parent){const e=m.get(r);e&&e!==t&&e.start<=t.start&&(t.parent=e.id)}else if(t.kind==="queue-active"||t.kind==="queue-completed"||t.kind==="queue-failed"){const e=B.get(r);e&&e!==t&&e.start<=t.start&&(t.parent=e.id)}}{const t=new Map(y.map(r=>[r.id,r]));for(const r of y){if(!r.parent||!Ot.has(r.kind??"")||r.durationMs===void 0)continue;const e=t.get(r.parent);if(!e||e.kind!=="span"||!((e.durationMs??0)>0))continue;const o=Math.round(r.start+r.durationMs-(e.start+e.durationMs));if(o<OUTLIVED_PARENT_MIN_MS)continue;r.outlivedParentMs=o;const n=e.leftRunning??{count:0,longestMs:0};e.leftRunning={count:n.count+1,longestMs:Math.max(n.longestMs,o)}}for(const r of y){const e=[];r.leftRunning&&e.push(`ended before ${r.leftRunning.count===1?"a call":`${r.leftRunning.count} calls`} it started had finished \u2014 ${r.leftRunning.count===1?"it":"the longest"} ran on ${r.leftRunning.longestMs}ms (a timeout that gave up, or work not awaited)`),r.outlivedParentMs!==void 0&&e.push(`ran on ${r.outlivedParentMs}ms after the span that started it had ended`),e.length>0&&(r.detail=[r.detail,...e].filter(Boolean).join(" \xB7 "))}}let h=y;{const t=new Map;for(const e of h)e.kind==="fetch-start"&&t.set(e.id,e);const r=new Map;for(const e of h){if(e.kind!=="fetch-done"&&e.kind!=="fetch-error")continue;const o=[...t.values()].find($=>$.requestId&&$.requestId===e.requestId)?.id,n=o?t.get(o):void 0;if(!n)continue;const a=e.fetchStartedAt??n.start;n.title=e.title,n.severity=e.severity,n.durationMs=e.durationMs??Math.max(0,e.t-a),n.kind="fetch",e.detail&&!n.detail&&(n.detail=e.detail),r.set(e.id,n.id)}if(r.size>0){h=h.filter(e=>!r.has(e.id));for(const e of h)for(e.fetchDoneId&&r.has(e.fetchDoneId)&&(e.fetchDoneId=r.get(e.fetchDoneId));e.parent&&r.has(e.parent);)e.parent=r.get(e.parent)}}const D=k(t=>!!t.commitId&&(t.kind==="render"||t.kind==="effect-run"||t.kind==="render-commit-truncated"),"commitMember"),K=k(t=>[...new Set(t)],"uniq"),st=k(t=>K(t.map(r=>r.component).filter(r=>!!r)),"named"),qt=k(t=>t.length<=2?t.join(" + "):`${t[0]} + ${t.length-1} more`,"nameList"),it=k(t=>{const r=new Map;for(const e of t)e.component&&r.set(e.component,(r.get(e.component)??0)+1);return[...r].map(([e,o])=>o>1?`${e} \xD7${o}`:e).join(", ")},"tally"),It=k(t=>{if(!t)return"effect";const r=/([^/\\]+?):(\d+)(?::\d+)?$/.exec(t);return r?`${r[1]}:${r[2]}`:t},"shortHook"),ot=k(t=>`${It(t.hook)}${t.cleanup?" (cleanup)":""}`,"hookLabel"),dt=k(t=>{const r=Math.min(...t.map(o=>o.start)),e=Math.max(...t.map(o=>o.start+(o.durationMs??0)));return{start:r,durationMs:e-r}},"extent"),ut=k(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 ct(t){const r=t[0],e=t.filter(S=>S.kind==="render"),o=t.filter(S=>S.kind==="effect-run"),n=t.find(S=>S.kind==="render-commit-truncated"),a=[...e].sort((S,X)=>(X.durationMs??0)-(S.durationMs??0)),$=a.filter(S=>(S.why??[]).some(X=>X!=="parent-render")),w=K($.flatMap(S=>(S.why??[]).filter(X=>X!=="parent-render"))),u=st($),c=e.filter(S=>S.phase==="mount"),v=e.filter(S=>S.phase!=="mount"&&!$.includes(S)),q=a[0]?.component??"view",A=e.length>0&&c.length===e.length,x=w.length?w.join(" + "):void 0,F=A?"mount":"update",N=u.length?`view update \xB7 ${qt(u)} \u2190 ${x}`:A?`view mount \xB7 ${q}`:`view update \xB7 ${q}`,Q=n?.renderTotal??e.length,xt=[c.length?`mounted ${it(c)}`:"",v.length?`re-rendered ${it(v)}`:"",!u.length&&!A&&e.length?"trigger not recorded \u2014 every captured render came from its parent":"",n?.renderWalkStoppedAt!==void 0?`at least ${Q} renders (the walk stopped at ${n.renderWalkStoppedAt} fibers), ${n.renderPublished??e.length} recorded`:n?`${Q} renders, ${n.renderPublished??e.length} recorded (per-commit cap)`:`${e.length} render${e.length===1?"":"s"}`,o.length?`${o.length} effect${o.length===1?"":"s"}: ${o.map(ot).join(", ")}`:""].filter(Boolean).join(" \xB7 "),gt=st(e);return ut({...r,...dt(t),kind:"view-update",title:N,detail:xt,commitId:r.commitId,viewPhase:F,...x?{cause:x}:{},causeComponents:u,components:gt,mounted:st(c),renderCount:Q,...n?.renderWalkStoppedAt!==void 0?{renderCountAtLeast:!0}:{},recordedRenders:e.length,effects:o.length,effectHooks:o.map(ot),memberIds:t.map(S=>S.id),sig:`commit:${F}:${x??"-"}:${u.join(",")}:${gt.slice().sort().join(",")}`,severity:t.some(S=>S.severity==="error")?"error":r.severity})}R(ct,"It"),k(ct,"viewUpdateNode");function lt(t){const r=t[0],e=t.map(ot);return ut({...r,...dt(t),kind:"commit-effects",title:t.length===1?`effect \xB7 ${e[0]}`:`effects \xB7 ${e[0]} + ${t.length-1} more`,detail:e.join(", "),commitId:r.commitId,effects:t.length,effectHooks:e,memberIds:t.map(o=>o.id),sig:`effects:${e.slice().sort().join(",")}`})}R(lt,"kt"),k(lt,"effectsNode");const bt=k(t=>K(t.map(r=>r==="state-update"?"state update":r==="fetch-start"?"request":r==="flow-origin"?"interaction":"response")).join(" + "),"describeInputs");function pt(t,r){const e=t[0],o=t[t.length-1],n=t.length,a=e.detail,$=Math.min(...t.map(v=>v.start)),w=Math.max(...t.map(v=>v.start+(v.durationMs??0))),u=Math.round(t.reduce((v,q)=>v+(q.durationMs??0),0)/n*10)/10,c=Math.round((w-$)*10)/10;e.count=n,e.avgMs=u,e.wallMs=c,e.durationMs=w-$,e.items=t.slice(0,12).map(v=>({start:v.start-$,...v.durationMs!=null?{durationMs:v.durationMs}:{}})),e.memberIds=t.flatMap(v=>v.memberIds??[v.id]),e.title=`\xD7${n} ${e.title}`,t.some(v=>v.severity==="error")&&(e.severity="error"),e.kind==="view-update"?e.detail=[`${n} commits, ${r.length?`one per ${bt(r)}`:"back to back"}`,`avg ${u}ms \xB7 wall ${c}ms`,a??""].filter(Boolean).join(" \xB7 "):e.kind==="state-update"&&a&&o.detail?e.detail=`${n} updates in a row \xB7 wall ${c}ms \xB7 first ${a} \xB7 last ${o.detail}`:e.detail=[`${n} in a row \xB7 wall ${c}ms`,a??""].filter(Boolean).join(" \xB7 ")}R(pt,"qt"),k(pt,"collapseRepeat");const tt=[],et=new Map,ft=new Set;for(let t=0;t<h.length;t++){if(ft.has(t))continue;const r=h[t];if(!D(r)){tt.push(r);continue}const e=[t];for(let a=t+1;a<h.length;a++){const $=h[a];if($.group==="browser"){if(!D($)||$.commitId!==r.commitId)break;e.push(a)}}for(const a of e)ft.add(a);const o=e.map(a=>h[a]),n=o.some(a=>a.kind!=="effect-run")?ct(o):lt(o);for(const a of o)a.id!==n.id&&et.set(a.id,n.id);tt.push(n)}if(et.size>0||tt.some(t=>t.kind==="view-update"||t.kind==="commit-effects")){h=tt;for(const t of h)for(;t.parent&&et.has(t.parent);)t.parent=et.get(t.parent)}{const t=new Map;for(const r of h)r.kind==="view-update"&&r.commitId&&!t.has(r.commitId)&&t.set(r.commitId,r);for(const r of h){if(r.kind!=="commit-effects"||r.parent||!r.commitId)continue;const e=t.get(r.commitId);e&&e.start<=r.start&&(r.parent=e.id)}}{const t=new Set(["state-update","fetch","fetch-start","fetch-done","fetch-error","flow-origin"]),r=h.map((u,c)=>u.group==="browser"?c:-1).filter(u=>u>=0),e=k(u=>`${u.kind}|${u.sig??u.title}`,"keyOf"),o=r.map(u=>e(h[u])),n=k((u,c,v)=>{for(let q=0;q<v;q++)if(o[u+q]!==o[c+q])return!1;return!0},"sameBlock"),a=k(u=>o[u].split("|")[0],"kindAt"),$=k(u=>{let c=0,v=1;for(let q=1;q<=4&&u+q<=o.length;q++){let A=1;for(;u+(A+1)*q<=o.length&&n(u,u+A*q,q);)A+=1;A>=3&&q*A>c*v&&(c=q,v=A)}return{k:c,r:v}},"bestBlockAt"),w=new Map;for(let u=0;u<o.length;){const{k:c,r:v}=$(u);if(c===0){u+=1;continue}const q=[...Array(c).keys()].find(x=>t.has(a(u+x)));if(q!==void 0&&q>0){const x=$(u+q);if(x.k===c&&x.r>=3&&x.r>=v-1){u+=q;continue}}const A=o.slice(u,u+c).map(x=>x.split("|")[0]).filter(x=>t.has(x));for(let x=0;x<c;x++){const F=[];for(let N=0;N<v;N++)F.push(h[r[u+x+N*c]]);pt(F,A);for(const N of F.slice(1))w.set(N.id,F[0].id)}u+=c*v}if(w.size>0){h=h.filter(u=>!w.has(u.id));for(const u of h)for(;u.parent&&w.has(u.parent);)u.parent=w.get(u.parent)}}{const t=new Map(h.map(r=>[r.id,r]));for(const r of h){const e=new Set([r.id]);let o=r;for(;o?.parent;){if(e.has(o.parent)){o.parent=void 0;break}e.add(o.parent),o=t.get(o.parent)}}}const mt=k(t=>{const r=new Map;for(const o of h){if(!o.sig||I(o)!==t||o.kind==="server-request"||o.kind==="gateway-request"||o.group==="browser")continue;const n=`${o.parent??"root"}|${o.kind}|${o.sig}`,a=r.get(n);a?a.push(o):r.set(n,[o])}const e=new Map;for(const o of r.values()){if(o.length<3)continue;o.sort((c,v)=>c.start-v.start);const n=o[0];let a=!1;for(let c=0;c+1<o.length;c++)if(o[c+1].start<o[c].start+(o[c].durationMs??0)){a=!0;break}const $=n.start,w=Math.max(...o.map(c=>c.start+(c.durationMs??0))),u=o.reduce((c,v)=>c+(v.durationMs??0),0);n.count=o.length,n.parallel=a,n.avgMs=Math.round(u/o.length*10)/10,n.wallMs=w-$,n.durationMs=w-$,n.title=`\xD7${o.length} ${n.title.replace(/\s*\((?:\d+ rows?, )?\d+ms\)$/,"")}`,n.detail=`${n.sig} \xD7${o.length} ${a?"\u2016 parallel":"\u21BB sequential loop"} \xB7 avg ${n.avgMs}ms \xB7 wall ${n.wallMs}ms`,n.items=o.slice(0,12).map(c=>({start:c.start-$,...c.durationMs!=null?{durationMs:c.durationMs}:{}})),n.memberIds=o.flatMap(c=>c.memberIds??[c.id]),o.some(c=>c.severity==="error")&&(n.severity="error");for(const c of o.slice(1))e.set(c.id,n.id)}if(e.size!==0){h=h.filter(o=>!e.has(o.id));for(const o of h)for(;o.parent&&e.has(o.parent);)o.parent=e.get(o.parent)}},"aggregatePass");mt(!0),mt(!1);for(const t of h){if(!I(t))continue;const r=t.durationMs??0;if(r<40)continue;const e=h.filter(w=>w.parent===t.id&&(w.durationMs??0)>0).map(w=>[w.start,w.start+(w.durationMs??0)]).sort((w,u)=>w[0]-u[0]);let o=0,n=-1,a=-1;for(const[w,u]of e)w>a?(a>n&&(o+=a-n),n=w,a=u):u>a&&(a=u);a>n&&(o+=a-n);const $=Math.max(0,r-o);($>=50||$/r>=.7&&r>=40)&&(t.selfMs=$,t.detail=`\u26A0 cpu-heavy: ${$}ms self-time of ${r}ms${t.detail?" \xB7 "+t.detail:""}`)}return{events:h,...s?{sql:s}:{}}}R(buildFlowDetail,"buildFlowDetail"),k(buildFlowDetail,"buildFlowDetail");
|
package/lib/flows-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var b=Object.defineProperty;var c=(s,e)=>b(s,"name",{value:e,configurable:!0});var y=Object.defineProperty,l=c((s,e)=>y(s,"name",{value:e,configurable:!0}),"u");import{classifyFlow as $,categoryOfSegment as h}from"./flow-categories.js";import{DEFAULT_SEGMENT_OPTIONS as w,segmentFlow as j}from"./flow-segments.js";export const DEFAULT_FLOWS_CONFIG={categories:[],segments:{},problems:[]};const p=200,f=200,m=64,F=/^[A-Za-z0-9][A-Za-z0-9 ._:/-]*$/,O=["category","flowId","originType","origin","route","project"],A={phaseGapMs:[50,6e5],burstGapMs:[10,6e4],attachWindowMs:[0,6e4],maxSegmentEvents:[20,1e4],occurrenceSlackMs:[0,1e3]},g=l(s=>typeof s=="object"&&s!==null&&!Array.isArray(s),"isObj");function d(s,e){if(!g(s))return{problems:[`${e}: not an object`]};const o=[];for(const t of Object.keys(s))O.includes(t)||o.push(`${e}: unknown field "${t}" ignored`);const n=s.category;if(typeof n!="string"||n.trim()==="")return{problems:[...o,`${e}: "category" must be a non-empty string \u2014 rule dropped`]};const i=n.trim();if(i.length>m||!F.test(i))return{problems:[...o,`${e}: category "${i.slice(0,40)}" is not a usable name (letters, digits, space . _ : / -; up to ${m}) \u2014 rule dropped`]};const u={category:i};let a=0;for(const t of["flowId","originType","origin","route","project"]){const r=s[t];if(r!==void 0){if(typeof r!="string"||r===""||r.length>f)return{problems:[...o,`${e}: "${t}" must be a non-empty string of up to ${f} characters \u2014 rule dropped`]};u[t]=r,a+=1}}return a===0?{problems:[...o,`${e}: "${i}" has no match field (flowId, originType, origin, route or project) \u2014 rule dropped`]}:{rule:u,problems:o}}c(d,"w"),l(d,"parseRule");export function parseFlowsConfig(s){if(s==null)return DEFAULT_FLOWS_CONFIG;if(!g(s))return{...DEFAULT_FLOWS_CONFIG,problems:["lensmcp.flows must be an object \u2014 ignored"]};const e=[],o=[],n=s.categories;n!==void 0&&(Array.isArray(n)?(n.length>p&&e.push(`flows.categories has ${n.length} rules; only the first ${p} are used`),n.slice(0,p).forEach((a,t)=>{const r=d(a,`flows.categories[${t}]`);e.push(...r.problems),r.rule&&o.push(r.rule)})):e.push("flows.categories must be an array \u2014 ignored"));const i={},u=s.segments;if(u!==void 0)if(!g(u))e.push("flows.segments must be an object \u2014 ignored");else for(const[a,t]of Object.entries(u)){const r=A[a];if(!r){e.push(`flows.segments.${a}: unknown option ignored`);continue}if(typeof t!="number"||!Number.isFinite(t)||t<r[0]||t>r[1]){e.push(`flows.segments.${a}: ${JSON.stringify(t)} is outside ${r[0]}\u2013${r[1]}; using the default (${w[a]})`);continue}i[a]=t}return{categories:o,segments:i,problems:e}}c(parseFlowsConfig,"parseFlowsConfig"),l(parseFlowsConfig,"parseFlowsConfig");export function analyzeFlow(s,e=DEFAULT_FLOWS_CONFIG){const o=j(s,e.segments),n=$(s,o,e.categories),i={};for(const u of o.segments)i[u.id]=h(u,n,e.categories);return{segmentation:o,classification:n,segmentCategories:i}}c(analyzeFlow,"analyzeFlow"),l(analyzeFlow,"analyzeFlow");
|
package/lib/graph-from-events.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var g=Object.defineProperty;var l=(t,r)=>g(t,"name",{value:r,configurable:!0});var I=Object.defineProperty,p=l((t,r)=>I(t,"name",{value:r,configurable:!0}),"l");function m(t){const r=t.raw??null,s=r?.kind,d=t.context,a={id:t.id,parentTraceNodeId:d.causedByNodeId??d.originNodeId,lifecycle:"completed",context:d,startTime:t.timestamp,attributes:{...r??{}}};if(t.source==="react"&&s==="render"){const e=r;return{parentAxis:"render",node:{...a,type:"render",logicalId:e.render?.componentLogicalId,instanceId:e.render?.componentInstanceId,name:`render ${e.render?.componentName??"?"}`,durationMs:e.render?.actualDurationMs}}}if(t.source==="valtio"&&s==="state-update"){const e=r;return{parentAxis:"state",node:{...a,type:"state-update",logicalId:e.update?.storeId,name:`${e.update?.storeId??"?"}.${e.update?.path??"?"}`}}}if(t.source==="nestjs"&&s==="server-request"){const e=r;return{parentAxis:"backend",node:{...a,type:"server-request",name:`${e.request?.method??"?"} ${e.request?.route??"?"}`,durationMs:e.request?.durationMs}}}if(s==="db-query"){const e=r,c=[e.op,e.table].filter(Boolean).join(" ")||(e.name??"query");return{parentAxis:"backend",node:{...a,type:"db-query",logicalId:e.table?`db:${e.op??"query"}:${e.table}`:void 0,name:e.error?`${c} (failed)`:c,durationMs:e.durationMs}}}if(s==="loop")return{parentAxis:"performance",node:{...a,type:"loop",name:"loop",durationMs:r.loop?.durationMs}};if(s==="flow-origin"&&(t.source==="react"||t.source==="client-runtime")){const e=d.originNodeId??(typeof r?.originNodeId=="string"?r.originNodeId:void 0);return{parentAxis:"caused",node:{...a,parentTraceNodeId:d.causedByNodeId,type:"ui-event",logicalId:e,name:e?`${t.title} ${e}`:t.title}}}if(t.source==="client-runtime"&&s==="user-action"){const e=r;return{parentAxis:"caused",node:{...a,type:"ui-event",logicalId:e.origin?.nodeId,name:e.origin?.label??t.title}}}}l(m,"m"),p(m,"eventToNode");export function buildGraphFromEvents(t,r){const s=[...r].sort((o,n)=>o.timestamp-n.timestamp),d=[];for(const o of s){const n=m(o);n&&(t.addNode(n.node),d.push(n))}let a=0;const e=p((o,n,i,u)=>{const f={id:`${i}:${o}->${n}`,from:o,to:n,axis:i,type:u,timestamp:t.getNode(n)?.startTime??0};t.addEdge(f),a++},"addEdge");for(const o of d){const n=o.node.context.causedByNodeId;n&&t.getNode(n)&&e(n,o.node.id,o.parentAxis??"caused","caused-by")}const c=new Map;for(const o of d){const n=o.node.context.flowId;if(!n)continue;let i=c.get(n);i||(i=[],c.set(n,i)),i.push(o)}for(const o of c.values())for(let n=1;n<o.length;n++){const i=o[n-1].node,u=o[n].node;u.context.causedByNodeId!==i.id&&e(i.id,u.id,"caused","flow-sequence")}return{nodeCount:d.length,edgeCount:a}}l(buildGraphFromEvents,"buildGraphFromEvents"),p(buildGraphFromEvents,"buildGraphFromEvents");
|