lensmcp 1.25.21 → 1.25.23

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.
@@ -187,14 +187,14 @@ CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);
187
187
  `);import{createSocket as VV}from"node:dgram";import{closeSync as JV,existsSync as KV,openSync as QV,readSync as YV,statSync as jp}from"node:fs";import{StringDecoder as a_}from"node:string_decoder";import{createServer as XV}from"node:net";import{existsSync as o_,unlinkSync as u_}from"node:fs";var eJ=1024*1024;function l_(e){let t=e.onError??(()=>{});try{o_(e.path)&&u_(e.path)}catch{}let s=new Set,n=e.maxFrameBytes??eJ,r=XV(i=>{s.add(i);let a="";i.setEncoding("utf8"),i.on("data",o=>{a+=o;let c;for(;(c=a.indexOf(`
188
188
  `))!==-1;){let p=a.slice(0,c);a=a.slice(c+1),p&&e.onMessage(p)}a.length>n&&(t(new Error(`uds: frame exceeded ${n} bytes without a newline \u2014 connection dropped`)),a="",i.destroy())}),i.on("error",o=>t(o)),i.on("close",()=>s.delete(i))});return r.on("error",i=>t(i)),r.listen(e.path,()=>e.onListening?.()),r.unref(),{close:u(()=>new Promise(i=>{for(let a of s)try{a.destroy()}catch{}s.clear();try{r.close(()=>{try{o_(e.path)&&u_(e.path)}catch{}i()})}catch{i()}}),"close")}}l(l_,"R$"),u(l_,"createUdsServer");function d_(e){let t=e.eventFile??process.env.LENSMCP_EVENT_FILE,s=e.socketPath??process.env.LENSMCP_IPC_SOCKET,n=e.udsPath??process.env.LENSMCP_UDS,r=e.onError??(()=>{}),i=0,a=u(f=>{let v=f.trim();if(!v)return;let g;try{g=JSON.parse(v)}catch{return}if(!(!g||typeof g!="object"||!("id"in g)||!("source"in g)))try{e.sessionId&&g.sessionId==="pending"&&(g.sessionId=e.sessionId,g.context&&g.context.sessionId==="pending"&&(g.context.sessionId=e.sessionId)),e.bus.publish(g),i+=1}catch(y){r(y)}},"publish"),o=[],c=!1,p=!1,d=!1,h=0;if(t){c=!0;let f=e.drainBudgetMs??40,v=0,g,y=t,w=new a_("utf8"),b="",k=0,$=!1,E=e.replayBytes??Number(process.env.LENSMCP_REPLAY_BYTES??4*1024*1024);if(KV(t))try{let W=jp(t);g=W.ino,Number.isFinite(E)&&E>0&&W.size>0?(v=Math.max(0,W.size-E),$=v>0):v=W.size}catch{v=0}let x=Buffer.alloc(64*1024),S=u(()=>{k>0&&(b=b.slice(k),k=0)},"compact"),A=u(W=>{let U;for(;(U=b.indexOf(`
189
189
  `,k))!==-1;){let fe=b.slice(k,U);if(k=U+1,$){$=!1;continue}if(a(fe),performance.now()>=W&&b.indexOf(`
190
- `,k)!==-1)return S(),!1}return S(),!0},"publishPending"),I=u((W,U)=>{let fe;try{fe=jp(W).size}catch{return!0}for(;v<fe;){if(performance.now()>=U)return!1;let F;try{F=QV(W,"r")}catch(V){return r(V),!0}try{let V=YV(F,x,0,Math.min(x.length,fe-v),v);if(V<=0)break;v+=V,b+=w.write(x.subarray(0,V))}finally{JV(F)}if(!A(U))return!1}return!0},"readOn"),C=u(W=>{y=t,v=0,g=W,w=new a_("utf8"),b="",k=0},"restart"),_=u(()=>{for(let W=1;W<=9;W++)try{if(jp(`${t}.${W}`).ino===g)return`${t}.${W}`}catch{}},"rotatedTo"),N=u(()=>{let W=performance.now()+f;if(!A(W))return!0;if(y!==t){if(!I(y,W))return!0;C(void 0)}let U;try{U=jp(t)}catch{return h=b.length-k,!1}if(g===void 0&&(g=U.ino),U.ino!==g){let F=_();if(F&&(y=F,!I(F,W)))return!0;C(U.ino)}else U.size<v&&C(U.ino);let fe=!I(t,W);return h=Math.max(0,U.size-v)+(b.length-k),fe},"drain"),q=!1,M,L=u(()=>{if(M=void 0,q)return;q=!0;let W=!1;try{W=N()}catch(U){r(U)}finally{q=!1}W&&!M&&(M=setImmediate(L))},"pump"),H=setInterval(L,e.pollMs??50);H.unref?.(),o.push(()=>{clearInterval(H),M&&clearImmediate(M)})}if(s){let[f,v]=s.split(":"),g=Number(v);if(f&&Number.isFinite(g)){p=!0;let y;try{y=VV("udp4"),y.on("message",w=>a(w.toString("utf8"))),y.on("error",w=>r(w)),y.bind(g,f),y.unref()}catch(w){r(w),p=!1}if(y){let w=y;o.push(()=>new Promise(b=>{try{w.close(()=>b())}catch{b()}}))}}}if(n)try{let f=l_({path:n,onMessage:u(v=>a(v),"onMessage"),onError:r});d=!0,o.push(()=>f.close())}catch(f){r(f)}let m=[];return c&&m.push("file"),p&&m.push("udp"),d&&m.push("uds"),{mode:m.join("+")||"none",count:u(()=>i,"count"),behind:u(()=>h,"behind"),async stop(){for(let f of o)try{await f()}catch{}}}}l(d_,"M$"),u(d_,"startEventIngest");import{existsSync as tJ,readFileSync as c_}from"node:fs";import{dirname as sJ,join as rJ}from"node:path";function p_(e=process.cwd()){let t=hb("nx.json",e);if(!t)return Ms();try{let s=JSON.parse(c_(t,"utf8"));return Ms(s.lensmcp?.thresholds)}catch{return Ms()}}l(p_,"O$"),u(p_,"loadWorkspaceThresholds");function h_(e=process.cwd()){let t=hb("nx.json",e);if(!t)return sn;try{let s=JSON.parse(c_(t,"utf8"));return R5(s.lensmcp?.flows)}catch(s){return{...sn,problems:[`${t} could not be read as JSON (${s instanceof Error?s.message:String(s)}) \u2014 flow config ignored`]}}}l(h_,"C$"),u(h_,"loadWorkspaceFlowsConfig");function hb(e,t){let s=t;for(let n=0;n<8;n++){let r=rJ(s,e);if(tJ(r))return r;let i=sJ(s);if(i===s)break;s=i}}l(hb,"eq"),u(hb,"findUp");import{PerformanceObserver as nJ,constants as Rp,performance as iJ}from"node:perf_hooks";function m_(e){if(!(e.cpuMs===void 0||e.ms<=0))return e.cpuMs>=e.ms*.5?"working":"waiting"}l(m_,"N$"),u(m_,"stallKind");function f_(e=128,t=Date.now){let s=[];return{begin(n){let r={what:n,start:t()};return s.push(r),s.length>e&&s.splice(0,s.length-e),()=>{r.end??=t()}},overlapping(n,r){return s.filter(i=>i.start<=r&&(i.end??r)>=n).map(i=>({s:i,ms:(i.end??r)-i.start})).sort((i,a)=>a.ms-i.ms).slice(0,8).map(({s:i,ms:a})=>`${i.what} ${a}ms${i.end===void 0?" (still running)":""}`)}}}l(f_,"tq"),u(f_,"createWorkLog");var aJ=f_(),oJ={[Rp.NODE_PERFORMANCE_GC_MAJOR]:"major",[Rp.NODE_PERFORMANCE_GC_MINOR]:"minor",[Rp.NODE_PERFORMANCE_GC_INCREMENTAL]:"incremental",[Rp.NODE_PERFORMANCE_GC_WEAKCB]:"weakcb"};function g_(e){let t=Number(process.env.LENSMCP_STALL_MS),s=e.thresholdMs??(Number.isFinite(t)&&t>0?t:1e3),n=e.tickMs??100,r=e.work??aJ,i=[],a;try{a=new nJ(m=>{for(let f of m.getEntries()){let v=iJ.timeOrigin+f.startTime,g=oJ[f.detail?.kind??-1]??"gc";i.push({start:v,end:v+f.duration,kind:g})}i.length>256&&i.splice(0,i.length-256)}),a.observe({entryTypes:["gc"]})}catch{a=void 0}let o=Date.now(),c=e.ingested?.()??0,p=u(()=>{try{let m=process.resourceUsage();return{cpu:m.userCPUTime+m.systemCPUTime,major:m.majorPageFault,minor:m.minorPageFault}}catch{return}},"usage"),d=p(),h=setInterval(()=>{let m=Date.now(),f=m-o-n,v=e.ingested?.()??0,g=p();if(f>s){let y=o,w=v-c,b=g&&d?{cpuMs:Math.round((g.cpu-d.cpu)/1e3),faults:{major:g.major-d.major,minor:g.minor-d.minor}}:{};setImmediate(()=>{let k=i.filter(E=>E.end>=y&&E.start<=m),$=process.memoryUsage();try{e.onStall({at:m,ms:f,gcMs:Math.round(k.reduce((E,x)=>E+(Math.min(x.end,m)-Math.max(x.start,y)),0)),gcs:k.length,gcKinds:[...new Set(k.map(E=>E.kind))],work:r.overlapping(y,m),...e.ingested?{ingested:w}:{},...b,heapUsed:$.heapUsed,rss:$.rss})}catch{}})}o=m,c=v,d=g},n);return h.unref?.(),()=>{clearInterval(h),a?.disconnect()}}l(g_,"j$"),u(g_,"startStallWatch");function P(e,t,s,n){var r=arguments.length,i=r<3?t:n===null?n=Object.getOwnPropertyDescriptor(t,s):n,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(e,t,s,n);else for(var o=e.length-1;o>=0;o--)(a=e[o])&&(i=(r<3?a(i):r>3?a(t,s,i):a(t,s))||i);return r>3&&i&&Object.defineProperty(t,s,i),i}l(P,"M"),u(P,"__decorate");import{App as uJ}from"@frontmcp/sdk";import{Resource as lJ,ResourceContext as dJ}from"@frontmcp/sdk";import{existsSync as cJ,readFileSync as pJ}from"node:fs";import{dirname as hJ,join as mJ}from"node:path";var ur="perf://rules",xi="pod/heap-budget",Ei="pod/retained-generation",v_=512,y_=.9,fJ=64,gJ=16,vJ=16,w_=256,b_=1024*1024,yJ="LENSMCP_PERF_RULES",wJ="LENSMCP_POD_HEAP_BUDGET_MB",bJ={heapBudgetEnabled:!0,retainedEnabled:!0,budgetMb:v_,services:{}},kJ=/^(0|off|false|no)$/i,mb=u(e=>{let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>=16&&t<=1e6?t:void 0},"budget");function Op(e,t){let s=t&&typeof t=="object"&&!Array.isArray(t)?t:{},n=s[xi]&&typeof s[xi]=="object"?s[xi]:{},r=s[Ei]&&typeof s[Ei]=="object"?s[Ei]:{},i=kJ.test((e[yJ]??"").trim())||s.enabled===!1,a={};if(n.services&&typeof n.services=="object"&&!Array.isArray(n.services))for(let[o,c]of Object.entries(n.services)){let p=mb(c);p!==void 0&&(a[o]=p)}return{heapBudgetEnabled:!i&&n.enabled!==!1,retainedEnabled:!i&&r.enabled!==!1,budgetMb:mb(e[wJ])??mb(n.budgetMb)??v_,services:a}}l(Op,"Gm"),u(Op,"resolvePodRuleThresholds");function k_(e=process.cwd(),t=process.env){let s=e;for(let n=0;n<8;n++){let r=mJ(s,".lensmcp","config.json");if(cJ(r))try{let a=JSON.parse(pJ(r,"utf8"));return Op(t,a?.perfRules)}catch{return Op(t,void 0)}let i=hJ(s);if(i===s)break;s=i}return Op(t,void 0)}l(k_,"D$"),u(k_,"loadPodRuleThresholds");var sl=u((e,t,s)=>`${e}\0${t}\0${s}`,"key"),lr=u(e=>Math.round(e/b_),"mb"),fb=0,$J=u(()=>(fb=(fb+1)%65535,`perf-${Date.now().toString(36)}${fb.toString(36)}${Math.random().toString(36).slice(2,7)}`),"eventId"),xJ=class{static{l(this,"_l")}static{u(this,"PerfRuleBook")}constructor(e={}){this.options=e,this.findings=new Map,this.pods=new Map,this.heard=!1,this.thresholds=e.thresholds??bJ,this.now=e.now??Date.now}ingest(e){return e.source==="perf"?this.ingestRule(e):e.source==="memory"?this.ingestPod(e):!1}ingestRule(e){let t=hT(e.raw);if(!t||t.rule.startsWith("pod/"))return!1;let s=!this.heard;if(this.heard=!0,t.kind==="perf-rule-scan"){let i=!1,a=new Set(t.open);for(let[o,c]of this.findings)c.rule===t.rule&&c.project===t.project&&!a.has(c.subject)&&(this.findings.delete(o),i=!0);return i||s}let n=sl(t.rule,t.project,t.subject);if(t.kind==="perf-rule-retracted")return this.findings.delete(n)||s;let r=this.findings.get(n);return this.findings.set(n,{rule:t.rule,project:t.project,subject:t.subject,severity:t.severity,title:t.title,summary:t.summary,evidence:t.evidence,cost:t.cost,fix:t.fix,verify:t.verify,docs:t.docs,firstSeenAt:r?.firstSeenAt??e.timestamp,lastSeenAt:Math.max(e.timestamp,r?.lastSeenAt??0)}),this.bound(),!0}projectPods(e,t,s){let n=this.pods.get(e);if(!n&&(n={service:t,lastSeenAt:s,readings:new Map,retained:new Map},this.pods.set(e,n),this.pods.size>fJ)){let r=[...this.pods.entries()].sort((i,a)=>i[1].lastSeenAt-a[1].lastSeenAt)[0];r&&r[0]!==e&&(this.pods.delete(r[0]),this.close(sl(xi,r[0],r[1].service),"evicted",s),this.close(sl(Ei,r[0],r[1].service),"evicted",s))}return n.service=t||n.service,n.lastSeenAt=Math.max(n.lastSeenAt,s),n}ingestPod(e){let t=yp(e.raw);if(!t)return!1;let s=e.timestamp,n=this.projectPods(t.project,t.service||t.project,s),r=`${t.pod}:${t.pid}`;if(t.kind==="pod-memory"){if(t.previousAlive!==!0&&n.readings.set(r,this.reading(t,s)),t.trigger==="boot"){for(let c of[...n.readings.keys()])c.startsWith(`${t.pod}:`)&&c!==r&&n.readings.delete(c);for(let c of[...n.retained.keys()])c.startsWith(`${t.pod}:`)&&!c.startsWith(`${r}:`)&&n.retained.delete(c)}if(n.readings.size>gJ){let c=[...n.readings.entries()].sort((p,d)=>p[1].at-d[1].at)[0];c&&n.readings.delete(c[0])}}else if(t.kind==="pod-memory-retained"){n.retained.set(`${r}:${t.gen}`,this.retainedOf(t,s));let c=[...n.retained.keys()].filter(p=>p.startsWith(`${r}:`));c.length>vJ&&n.retained.delete(c[0])}else if(t.kind==="pod-memory-released")n.retained.delete(`${r}:${t.gen}`);else if(t.kind==="pod-memory-exited"){n.readings.delete(r);for(let c of[...n.retained.keys()])c.startsWith(`${r}:`)&&n.retained.delete(c)}let i=!this.heard;this.heard=!0;let a=this.evaluateHeap(t.project,n,s),o=this.evaluateRetained(t.project,n,s);return a||o||i}reading(e,t){return{pod:e.pod,pid:e.pid,service:e.service||e.project,at:e.at??t,trigger:e.trigger,gen:e.gen,swaps:e.swaps,live:e.live,reserved:e.reserved,rss:e.rss,...e.baseline!==void 0?{baseline:e.baseline}:{}}}retainedOf(e,t){return{pod:e.pod,pid:e.pid,gen:e.gen,at:t,ageMs:e.ageMs,swapsSinceClose:e.swapsSinceClose,gcs:e.gcs,alive:Array.isArray(e.alive)?e.alive.slice(0,8):[],...e.counts?{counts:e.counts}:{},live:e.live}}budgetFor(e,t){return this.thresholds.services[t]??this.thresholds.services[e]??this.thresholds.budgetMb}related(e){return[...this.findings.values()].filter(t=>t.project===e&&!t.rule.startsWith("pod/")).map(t=>`${t.rule}: ${t.title}`)}evaluateHeap(e,t,s){let n=t.service,r=sl(xi,e,n),i=this.findings.get(r);if(!this.thresholds.heapBudgetEnabled)return i?this.close(r,"disabled",s):!1;let a=this.budgetFor(e,t.service),o=a*b_,c=[...t.readings.values()].sort((v,g)=>g.live-v.live),p=c.filter(v=>v.live>o),d=c.some(v=>v.live>o*y_);if(p.length===0&&!(i&&d))return i?this.close(r,c.length?"cleared":"pod-exited",s):!1;if(p.length===0)return!1;let h=p[0],m=p.reduce((v,g)=>v+(g.live-o),0),f={rule:xi,project:e,subject:n,severity:h.live>=2*o?"error":"warning",title:`${t.service}: ${lr(h.live)} MB live heap after a full GC \u2014 over its ${a} MB budget${p.length>1?` (${p.length} pods)`:""}`,summary:`Pod #${h.pod} of ${t.service} holds ${lr(h.live)} MB of live objects right after a full GC (${lr(h.reserved)} MB reserved, rss ${lr(h.rss)} MB${h.baseline!==void 0?`; ${lr(h.baseline)} MB at boot`:""}, generation ${h.gen} after ${h.swaps} swap${h.swaps===1?"":"s"}). That is not garbage: it is what the app keeps, in every pod of the service.`,evidence:{budgetMb:a,pods:p.map(v=>({pod:v.pod,pid:v.pid,liveMb:lr(v.live),reservedMb:lr(v.reserved),rssMb:lr(v.rss),...v.baseline!==void 0?{baselineMb:lr(v.baseline)}:{},gen:v.gen,swaps:v.swaps,trigger:v.trigger,at:v.at})),related:this.related(e)},cost:{bytes:m,memoryMb:lr(m),basis:`live heap after a full GC above the ${a} MB budget, summed over the pods over it`},fix:[`See what the heap is made of: \`memory_explain_pod({ service: '${t.service}' })\`, then \`lensmcp mem ${t.service} --snapshot --analyze\` \u2014 read "bytes by package/module" and the largest retainers.`,`If one shared library dominates (FoodGuard: ~300 MB of zod schemas per pod from a contracts barrel), import it by subpath \u2014 see any bundle/heavy-barrel-import finding for ${e} \u2014 and build large schema catalogs lazily (a function that builds on first use), not at module load.`,"If the bundle text dominates (eval strings, source maps), keep the default `eval` devtool and no `--enable-source-maps` (LENSMCP_DEV_DEVTOOL unset).",`If the heap grows with each swap or request, it is retention, not size: look for module-level caches, registries and listeners that outlive a request (\`memory_explain_leak\`). A service that genuinely needs more raises its budget: \`.lensmcp/config.json\` perfRules["pod/heap-budget"].services["${t.service}"].`],verify:`After the change rebuilds and the pod swaps, its next post-GC report (\`memory_pods\`) shows live heap under ${Math.round(a*y_)} MB and LensMCP retracts this finding (\`observe_current_status\` no longer lists pod/heap-budget for ${t.service}).`,docs:cT[xi],firstSeenAt:i?.firstSeenAt??s,lastSeenAt:s};return this.open(r,f,i)}evaluateRetained(e,t,s){let n=t.service,r=sl(Ei,e,n),i=this.findings.get(r),a=[...t.retained.values()].sort((d,h)=>h.ageMs-d.ageMs);if(!this.thresholds.retainedEnabled||a.length===0)return i?this.close(r,this.thresholds.retainedEnabled?"released":"disabled",s):!1;let o=a[0],c=Math.max(1,Math.round(o.ageMs/6e4)),p={rule:Ei,project:e,subject:n,severity:"warning",title:`${t.service}: ${a.length===1?`generation ${o.gen} is`:`${a.length} closed generations are`} still in memory ${c} min after the hot swap that closed ${a.length===1?"it":"them"}`,summary:`Pod #${o.pod} closed generation ${o.gen} ${c} min ago, ${o.swapsSinceClose} swap(s) and ${o.gcs} full GC(s) since, and ${o.alive.join(", ")||"its objects"} ${o.alive.length===1?"is":"are"} still alive: something still points into the old app \u2014 a whole copy of it stays resident with every swap that leaks.`,evidence:{generations:a.slice(0,8).map(d=>({pod:d.pod,pid:d.pid,gen:d.gen,ageMs:d.ageMs,swapsSinceClose:d.swapsSinceClose,gcs:d.gcs,alive:d.alive,...d.counts?{counts:d.counts}:{},liveMb:lr(d.live)}))},cost:{basis:"one copy of the app per retained generation; its size is in the heap snapshot (`lensmcp mem --snapshot --analyze`)"},fix:[`Find what holds it: \`lensmcp mem ${t.service} --snapshot --analyze\` prints the shortest path from the GC roots to generation ${o.gen} \u2014 the first frame outside your app's own objects is the culprit.`,"Usual culprits: a timer or interval never cleared on shutdown; a BullMQ worker, queue event or Redis client never closed in onModuleDestroy / onApplicationShutdown; `process.on(\u2026)` / an EventEmitter listener added per app instance; a module-level registry, cache or singleton keyed by class or holding app instances.","Release it in the app's shutdown hooks (Nest calls them on every hot swap), or move the module-level state into a provider the container owns."],verify:'Save a file to swap again; within ~5 min the pod reports "generation N freed" (`memory_pods`), LensMCP retracts this finding, and `memory://leaks/suspected` no longer lists the generation.',docs:cT[Ei],firstSeenAt:i?.firstSeenAt??s,lastSeenAt:s};return this.open(r,p,i)}open(e,t,s){return this.findings.set(e,t),this.bound(),(!s||s.title!==t.title||s.severity!==t.severity)&&this.emit(t,"finding"),!0}close(e,t,s){let n=this.findings.get(e);return n?(this.findings.delete(e),this.emit({...n,lastSeenAt:s},"retracted",t),!0):!1}emit(e,t,s){let n=this.options.publish;if(!n)return;let r=this.options.sessionId??"pending",i=this.now(),a={id:$J(),sessionId:r,timestamp:i,source:"perf",category:"performance",severity:t==="finding"?e.severity:"info",context:{sessionId:r,projectName:e.project},fingerprint:pT(e.rule,e.project,e.subject),title:t==="finding"?`${e.rule}: ${e.title}`:`${e.rule}: cleared for ${e.project} (${e.subject})`,raw:t==="finding"?{kind:"perf-rule-finding",rule:e.rule,project:e.project,subject:e.subject,severity:e.severity,title:e.title,summary:e.summary,evidence:e.evidence,cost:e.cost,fix:e.fix,verify:e.verify,docs:e.docs,detectedAt:i}:{kind:"perf-rule-retracted",rule:e.rule,project:e.project,subject:e.subject,reason:s??"cleared",at:i}};queueMicrotask(()=>{try{n(a)}catch{}})}bound(){if(this.findings.size<=w_)return;let e=[...this.findings.entries()].sort((t,s)=>t[1].lastSeenAt-s[1].lastSeenAt).slice(0,this.findings.size-w_);for(let[t]of e)this.findings.delete(t)}openFindings(){return[...this.findings.values()].sort((e,t)=>e.severity===t.severity?t.lastSeenAt-e.lastSeenAt:e.severity==="error"?-1:1)}report(e){let t=this.openFindings(),s={};for(let n of t)s[n.rule]=(s[n.rule]??0)+1;return{schemaVersion:1,revision:e,updatedAt:new Date(this.now()).toISOString(),producer:this.heard?"connected":"none",detail:this.heard?t.length?`${t.length} open performance finding${t.length===1?"":"s"}: ${Object.entries(s).map(([n,r])=>`${r} ${n}`).join(", ")}`:"no open performance findings":"no performance rule has reported yet \u2014 rules run after a dev-cluster compilation (bundle/*) and on pod memory reports (pod/*); start the gateway",findings:t,counts:s}}};function gb(e,t=700){let s=e.fix.map((n,r)=>`${r+1}) ${n}`).join(" ");return s.length>t?`${s.slice(0,t-40).trimEnd()}\u2026 (all steps: ${ur})`:s}l(gb,"Vm"),u(gb,"compactFix");var Ir=u(e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0,"asRecord"),$_=u(e=>Array.isArray(e)?e.length:void 0,"arrayLen"),Dt=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"asCount"),_e=u(e=>typeof e=="string"?e:void 0,"asString");function et(e,...t){for(let s of t){let n=$_(e[s])??Dt(e[s]);if(n!==void 0)return n}}l(et,"mt"),u(et,"countOf");var ge=u((e,t,s=`${t}s`)=>`${e} ${e===1?t:s}`,"plural");function Np(e,t,s,n,r){if(t>0)return{state:"failed",count:t,detail:`${ge(t,`${n} error`)} \u2014 read ${r}`};if(s>0)return{state:"warning",count:s,detail:ge(s,`${n} warning`)};let i=_e(e.status);return i==="clean"||i==="passed"?{state:"passed",count:0,detail:`${n} clean`}:{state:"unknown",detail:`${n} has not reported a result yet (status=${i??"absent"})`}}l(Np,"U$"),u(Np,"fromStatusField");var Pp=[{kind:"typecheck",resource:"typecheck://current",reads:u(()=>["typecheck://errors"],"reads"),blocking:!0,source:"typescript",read:u(e=>Np(e,et(e,"errorCount","errors")??0,0,"typecheck","typecheck://errors"),"read")},{kind:"lint",resource:"lint://current",reads:u(e=>e==="warning"?["lint://warnings"]:["lint://errors"],"reads"),blocking:!0,source:"eslint",read:u(e=>Np(e,et(e,"errorCount","errors")??0,et(e,"warningCount","warnings")??0,"lint","lint://errors"),"read")},{kind:"build",resource:"build://current",reads:u(e=>e==="warning"?["build://current"]:["build://failures"],"reads"),blocking:!0,source:"vite",read:u(e=>{let t=Array.isArray(e.failures)?e.failures.filter(r=>{let i=r?.domain;return i!=="typecheck"&&i!=="lint"}).length:et(e,"failures","failureCount")??0,s=($_(e.failures)??t)-t,n=t===0&&s>0&&_e(e.status)==="failing"?{...e,status:"clean"}:e;return Np(n,t,et(e,"warnings","warningCount")??0,"build","build://failures")},"read")},{kind:"runtime",resource:"runtime://browser/errors",reads:u(()=>["runtime://browser/errors","runtime://browser/failed-requests"],"reads"),blocking:!0,source:"client-runtime",read:u(e=>{let t=et(e,"count","entries")??0;return t>0?{state:"failed",count:t,detail:`${ge(t,"browser runtime error")} \u2014 read runtime://browser/errors`}:{state:"unknown",count:0,detail:"no browser runtime errors recorded (a browser may never have connected)"}},"read")},{kind:"runtime",resource:"runtime://errors",reads:u(()=>["runtime://errors"],"reads"),blocking:!0,source:"nestjs",read:u(e=>{let t=et(e,"count","entries")??0,s=Array.isArray(e.entries)?e.entries.filter(r=>r?.outcome==="declared").length:0,n=s>0?` (${t-s} unhandled, ${s} a 5xx the app answered on purpose)`:"";return t>0?{state:"failed",count:t,detail:`${ge(t,"server-side error")}${n} \u2014 read runtime://errors (route, status, request id and stack)`}:{state:"unknown",count:0,detail:"no server-side errors recorded (no pod may have handled a request yet)"}},"read")},{kind:"cluster",resource:"process://cluster",reads:u(()=>["process://cluster"],"reads"),blocking:!0,source:"gateway",read:u(e=>{let t=et(e,"services")??0,s=Array.isArray(e.workersDown)?e.workersDown:[],n=u(x=>`${String(x.project)} ${String(x.name)} ${x.state==="crash-looping"?`crash-looping (${String(x.inARow??"?")} crashes in a row)`:x.state==="exited"?"ended \u2014 not started again until a build":"crashed, being started again"}`,"workerName"),r=s.filter(x=>x.state==="crash-looping"||x.state==="exited"),i=s.filter(x=>x.state==="restarting"),a=u(x=>`${ge(x.length,"worker")} not running (${x.map(n).join("; ")}) \u2014 nothing consumes ${x.length===1?"its":"their"} queues; read process://cluster \`workersDown\` for the last lines each one printed`,"workerPart");if(t===0&&s.length===0)return{state:"unknown",detail:"no cluster lifecycle events seen (the gateway may not be running)"};let o=et(e,"crashLooping")??0,c=et(e,"wedged")??0,p=et(e,"buildFailed")??0,d=et(e,"typeErrors")??0,h=d>0?`${ge(d,"service")} with type errors no typecheck producer reports`:void 0,m=et(e,"down")??0,f=Dt(e.restarts)??0,v=Array.isArray(e.services)?e.services.filter(x=>{let S=x??{};return S.buildFailed===!0&&S.state==="up"}).length:0,g=Math.max(0,p-v),y=Array.isArray(e.incidents)?e.incidents:[],w=y.length>0?`${ge(y.length,"request")} the gateway answered itself in the last 15 min (${[...new Set(y.map(x=>`${String(x.project)} ${x.kind==="pod-evicted"?"pod evicted":"request given up"} \u2192 ${String(x.status)}`))].join("; ")}) \u2014 read process://cluster \`incidents\`, or observe_errors kind cluster`:void 0,b=v>0?`${ge(v,"service")} failing to build while still serving the last good bundle`:void 0,k=[b,h?`${h} (still serving)`:void 0].filter(Boolean);if(o>0||c>0||g>0){let x=[o>0?`${ge(o,"service")} crash-looping`:void 0,c>0?`${ge(c,"service")} wedged`:void 0,g>0?`${ge(g,"service")} failing to build`:void 0].filter(Boolean);return{state:"failed",count:o+c+p+d+s.length,detail:`${x.join(", ")} \u2014 read process://cluster (requests to them 502)${k.length?`; ${k.join("; ")}`:""}${s.length?`; ${a(s)}`:""}`}}if(r.length>0)return{state:"failed",count:s.length+p+d,detail:`${a(s)}${k.length?`; ${k.join("; ")}`:""}`};let $=i.length?`; ${a(i)}`:"";if(b)return{state:"failed",count:p+d+i.length,detail:`${b} \u2014 read process://cluster for the error lines${h?`; ${h} (still serving)`:""}${$}`};if(h)return{state:"failed",count:d+i.length,detail:`${h} \u2014 read process://cluster for the lines (the bundle built; the services still serve)${$}`};if(i.length>0)return{state:"warning",count:i.length+y.length+m,detail:`${a(i)}${w?`; ${w}`:""}${m>0?`; ${ge(m,"service")} down (idle scale-to-zero is normal)`:""}`};if(w)return{state:"warning",count:y.length+m,detail:`${w}${m>0?`; ${ge(m,"service")} down (idle scale-to-zero is normal)`:""}`};if(m>0)return{state:"warning",count:m,detail:`${ge(m,"service")} down (idle scale-to-zero is normal; the next request restarts it)`};let E=et(e,"up")??0;return{state:"passed",count:0,detail:`${ge(E,"service")} up${f>0?`, ${ge(f,"restart")} this session`:""}`}},"read")},{kind:"memory",resource:"memory://leaks/suspected",reads:u(()=>["memory://leaks/suspected","memory://owners/growing"],"reads"),blocking:!1,source:"memory",read:u(e=>{let t=et(e,"suspected","leaks")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"suspected leak")} \u2014 read memory://leaks/suspected`}:{state:"passed",count:0,detail:"no suspected leaks"}},"read")},{kind:"visual",resource:"visual://violations/current",reads:u(()=>["visual://violations/current"],"reads"),blocking:!1,source:"visual",read:u(e=>{let t=et(e,"violations")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"visual violation")} \u2014 read visual://violations/current`}:{state:"passed",count:0,detail:"no visual violations"}},"read")},{kind:"perf",resource:"perf://slow-routes",reads:u(()=>["perf://slow-routes"],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"routes")??0,s=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"route")} over${s?` ${s}ms`:" the slow-route threshold"} \u2014 read perf://slow-routes`}:{state:"passed",count:0,detail:"no slow routes"}},"read")},{kind:"duplicate-requests",resource:"perf://duplicate-requests",reads:u(()=>["perf://duplicate-requests"],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"endpoints")??0,s=Dt(e.peakThreshold);return t>0?{state:"warning",count:t,detail:`${ge(t,"endpoint")} called ${s?`\u2265${s}\xD7`:"several times"} concurrently by one page \u2014 read perf://duplicate-requests`}:{state:"passed",count:0,detail:"no duplicated requests"}},"read")},{kind:"db",resource:"db://slow-queries",reads:u(()=>["db://slow-queries","db://analysis"],"reads"),blocking:!1,source:"db",read:u(e=>{let t=et(e,"queries")??0,s=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"query shape")} over${s?` ${s}ms`:" the slow-query threshold"} \u2014 read db://slow-queries`}:{state:"passed",count:0,detail:"no slow query shapes"}},"read")},{kind:"db-lint",resource:"db://lint",reads:u(()=>["db://lint"],"reads"),blocking:!1,source:"db",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0,n=Dt(e.warnBelow)??70;return!t&&!s?{state:"passed",count:0,detail:"every statement named; no SQL review under the threshold"}:{state:"warning",count:t+s,detail:[t?`${ge(t,"SQL lint error")} \u2014 unnamed statements are not reviewed until named`:"",s?`${ge(s,"statement")} whose SQL review scores under ${n}`:""].filter(Boolean).join("; ")+" \u2014 read db://lint"}},"read")},{kind:"routes-lint",resource:"routes://lint",reads:u(()=>["routes://lint"],"reads"),blocking:!1,source:"routes",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no route lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"route lint error"):"",s?ge(s,"route lint warning"):""].filter(Boolean).join("; ")+" \u2014 read routes://lint (each SQL issue links its db://lint/<statement>)"}},"read")},{kind:"kv-lint",resource:"kv://lint",reads:u(()=>["kv://lint"],"reads"),blocking:!1,source:"redis",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no key-family lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"key-family lint error"):"",s?ge(s,"key-family lint warning"):""].filter(Boolean).join("; ")+" \u2014 read kv://lint (review_cache { pattern } for one family)"}},"read")},{kind:"queues-lint",resource:"queues://lint",reads:u(()=>["queues://lint"],"reads"),blocking:!1,source:"queue",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no queue lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"queue lint error"):"",s?ge(s,"queue lint warning"):""].filter(Boolean).join("; ")+" \u2014 read queues://lint (review_queue { queue } for one queue)"}},"read")},{kind:"suggestions",resource:"agent://suggestions",reads:u(()=>["agent://suggestions"],"reads"),blocking:!1,source:"review",read:u(e=>{let t=Array.isArray(e.suggestions)?e.suggestions.length:0;return t?{state:"warning",count:t,detail:`${ge(t,"accepted suggestion")} from LensMCP's reviews to make \u2014 read agent://suggestions, then suggestion_set { id, state: "applied" } and suggestion_check { id, \u2026 }`}:{state:"passed",count:0,detail:"no accepted suggestion to make"}},"read")},{kind:"egress",resource:"net://egress/hosts",reads:u(e=>e==="warning"?["net://egress/hosts","net://egress/failures"]:["net://egress/hosts"],"reads"),blocking:!1,source:"external",read:u(e=>{let t=et(e,"failingHosts")??0,s=et(e,"slowHosts")??0,n=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"external host")} failing \u2014 read net://egress/failures`}:s>0?{state:"warning",count:s,detail:`${ge(s,"external host")} over${n?` ${n}ms`:" the slow-egress threshold"} \u2014 read net://egress/hosts`}:{state:"passed",count:0,detail:"no failing or slow external calls"}},"read")},{kind:"perf-rules",resource:ur,reads:u(()=>[ur],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"findings")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"performance finding")} \u2014 read ${ur} (each has a fix and a verify step)`}:{state:"passed",count:0,detail:"no open performance findings"}},"read"),items:u(e=>{let t=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(n=>!!n),s=t.slice(0,vb).map(n=>{let r=_e(n.rule)??"perf",i=_e(n.project)??"?",a=_e(n.subject)??"?",o=Array.isArray(n.fix)?n.fix.filter(c=>typeof c=="string"):[];return{source:"perf",severity:"warning",title:`${r} \xB7 ${_e(n.title)??i}`,fingerprint:`agent-status:perf-rule:${r}:${i}:${a}`,resource:ur,rule:r,...o.length?{fix:gb({fix:o})}:{},..._e(n.verify)?{verify:_e(n.verify)}:{},..._e(n.docs)?{docs:_e(n.docs)}:{}}});return t.length>vb&&s.push({source:"perf",severity:"warning",title:`${ge(t.length-vb,"more performance finding")} \u2014 read ${ur}`,fingerprint:"agent-status:perf-rules:more",resource:ur}),s},"items")},{kind:"sources",resource:ds,reads:u(()=>[ds],"reads"),blocking:!1,source:"sources",read:u(e=>{let t=(Array.isArray(e.sources)?e.sources:[]).map(Ir).filter(f=>!!f),s=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(f=>!!f),n=et(e,"findings")??0,r=u(f=>s.filter(v=>(_e(v.rule)??nl)===f).length,"byRule"),i=t.filter(f=>["unreachable","refused","malformed","stale"].includes(_e(f.state)??"")),a=t.filter(f=>f.state==="current"),o=u(f=>`${_e(f.project)??"?"}/${_e(f.name)??"?"}`,"name"),c=(Array.isArray(e.problems)?e.problems:[]).map(Ir).filter(f=>!!f);if(n>0||i.length>0||c.length>0)return{state:"warning",count:n+i.length+c.length,detail:[r(nl)>0?`${ge(r(nl),"reported queue group")} waiting longer than its threshold`:"",r("queue/stalled")>0?`${ge(r("queue/stalled"),"reported queue group")} stalled \u2014 nothing taken or finished`:"",r("loop/overdue")>0?`${ge(r("loop/overdue"),"reported loop")} overdue`:"",r("loop/failing")>0?`${ge(r("loop/failing"),"reported loop")} failing run after run`:"",r("loop/idle-while-fed")>0?`${ge(r("loop/idle-while-fed"),"reported loop")} taking nothing while its queue has work`:"",r("store/near-quota")>0?`${ge(r("store/near-quota"),"reported store")} near its quota`:"",r("store/errors")>0?`${ge(r("store/errors"),"reported store")} failing operations`:"",r("store/orphans")>0?`${ge(r("store/orphans"),"reported store")} growing with nothing deleted`:"",r("traffic/rate-limited")>0?`${ge(r("traffic/rate-limited"),"reported channel")} answered \xABtoo many requests\xBB`:"",r("traffic/failures")>0?`${ge(r("traffic/failures"),"reported channel")} failing over its threshold`:"",r("traffic/latency")>0?`${ge(r("traffic/latency"),"reported channel")} slow (p95 over its threshold)`:"",i.length>0?`${ge(i.length,"source")} not read (${i.map(f=>`${o(f)} ${_e(f.state)}`).join("; ")}) \u2014 its backlog is unknown, not empty`:"",c.length>0?`${ge(c.length,"cluster.sources entry","cluster.sources entries")} not polled (${_e(c[0].project)??"?"}: ${_e(c[0].problem)??"?"})`:""].filter(Boolean).join("; ")+` \u2014 read ${ds} (observe_sources)`};if(a.length===0)return{state:"unknown",detail:t.length?`no reported source read yet (${t.map(f=>`${o(f)} ${_e(f.state)}`).join("; ")}) \u2014 a service scaled to zero is not woken to read it`:`${ds} holds no source`};let p=Ir(e.totals)??{},d=a.map(f=>Dt(Ir(f.headline)?.oldestWaitMs)).filter(f=>f!==void 0),h=d.length?Math.max(...d):void 0,m=a.filter(f=>f.sourceKind==="loop").length;return{state:"passed",count:0,detail:`${ge(a.length,"reported source")} read: ${Dt(p.pending)??0} pending${h!==void 0?`, the oldest waiting ${yb(h).replace(/ ago$/,"")}`:""}${m?`, ${ge(m,"loop")} running as it says`:""} \u2014 none over its threshold`}},"read"),items:u(e=>{let t=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(i=>!!i),s=t.slice(0,rl).map(i=>{let a=Array.isArray(i.fix)?i.fix.filter(p=>typeof p=="string"):[],o=_e(i.rule)??nl,c=`${_e(i.project)??"?"}:${_e(i.name)??"?"}:${_e(i.group)??_e(i.channel)??"?"}`;return{source:"sources",severity:"warning",title:_e(i.title)??"a reported source is over one of its thresholds",fingerprint:o===nl?`agent-status:sources:${c}`:`agent-status:sources:${o}:${c}`,resource:ds,rule:o,...a.length?{fix:gb({fix:a},1200)}:{},..._e(i.verify)?{verify:_e(i.verify)}:{}}});t.length>rl&&s.push({source:"sources",severity:"warning",title:`${ge(t.length-rl,"more reported source finding")} \u2014 observe_sources`,fingerprint:"agent-status:sources:more",resource:ds});let n=(Array.isArray(e.sources)?e.sources:[]).map(Ir).filter(i=>!!i);for(let i of n.filter(a=>["unreachable","refused","malformed","stale"].includes(_e(a.state)??"")).slice(0,rl)){let a=_e(i.state)??"?";s.push({source:"sources",severity:"warning",title:`${_e(i.project)??"?"} \xB7 ${_e(i.name)??"?"} (reported source) is ${a}${_e(i.detail)?` \u2014 ${_e(i.detail)}`:""}; its numbers are unknown, not zero`,fingerprint:`agent-status:sources:read:${_e(i.project)??"?"}:${_e(i.name)??"?"}:${a}`,resource:ds})}let r=(Array.isArray(e.problems)?e.problems:[]).map(Ir).filter(i=>!!i);for(let[i,a]of r.slice(0,rl).entries())s.push({source:"sources",severity:"warning",title:`${_e(a.project)??"?"}: cluster.sources \u2014 ${_e(a.problem)??"?"}`,fingerprint:`agent-status:sources:declaration:${_e(a.project)??"?"}:${i}`,resource:ds});return s},"items")}],vb=5,rl=5,nl="queue/oldest-wait",x_=new WeakMap,zve=Pp.map(e=>e.resource),EJ=2e3;async function E_(e,t,s=0){let n={kind:t.kind,resource:t.resource},r;try{r=Ir(await(s>0?e.readRecent(t.resource,s):e.read(t.resource)))}catch{return{...n,producer:"none",state:"unknown",detail:`no producer for ${t.resource} \u2014 this signal is unmonitored, not healthy`,reads:t.reads("unknown")}}if(!r)return{...n,producer:"none",state:"unknown",detail:`${t.resource} produced no readable payload`,reads:t.reads("unknown")};let i=_e(r.producer),a=(e.revision(t.resource)??0)>0,o=i==="none"?"none":i==="connected"||a?"connected":"none",c=_e(r.detail);if(o==="none")return{...n,producer:o,state:"unknown",detail:c??(i==="none"?`${t.resource} reports no producer attached \u2014 this signal is unmonitored, not healthy`:`${t.resource} is registered but has never reported \u2014 this signal is unmonitored, not healthy`),reads:t.reads("unknown")};let p;try{p=t.read(r)}catch{p={state:"unknown",detail:`${t.resource} payload could not be interpreted`}}let d=r.stale===!0,h=d?`${p.detail} (as of ${Dt(r.ageMs)!==void 0?yb(Dt(r.ageMs)):"a while ago"}; nothing has re-checked since)`:p.detail,m={...n,producer:o,state:p.state,...p.count===void 0?{}:{count:p.count},...d?{stale:!0}:{},detail:h,reads:t.reads(p.state)};if(t.items&&(p.state==="warning"||p.state==="failed"))try{let f=t.items(r);f.length&&x_.set(m,f)}catch{}return m}l(E_,"D8"),u(E_,"readSignal");function yb(e){return e<6e4?`${Math.max(1,Math.round(e/1e3))}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:`${Math.round(e/36e5)}h ago`}l(yb,"lq"),u(yb,"describeAge");async function wb(e,t=0){return Promise.all(Pp.map(s=>E_(e,s,t)))}l(wb,"Zm"),u(wb,"readSignals");var il=u(e=>Pp.find(t=>t.resource===e.resource)??Pp.find(t=>t.kind===e.kind),"specFor");function S_(e){return{source:il(e).source,severity:e.state==="failed"?"error":"warning",title:e.detail,fingerprint:`agent-status:${e.kind}:${e.state}`,resource:e.reads[0]??e.resource}}l(S_,"U8"),u(S_,"toItem");function A_(e){let t={failed:3,warning:2,unknown:1,passed:0},s=u(i=>{let a=e.filter(o=>o.kind===i);return a.length===0?"unknown":a.reduce((o,c)=>t[c.state]>t[o]?c.state:o,a[0].state)},"pick"),n=u(i=>i==="failed"?"failed":i==="passed"||i==="warning"?"passed":"unknown","tri"),r=u(i=>i,"quad");return{typecheck:n(s("typecheck")),lint:n(s("lint")),build:n(s("build")),runtime:r(s("runtime")),visual:r(s("visual")),memory:r(s("memory"))}}l(A_,"z8"),u(A_,"toChecks");function C_(e){let t=e.filter(d=>d.state==="failed"),s=e.filter(d=>d.state==="warning"),n=e.filter(d=>d.state==="passed"),r=u(d=>x_.get(d)??[S_(d)],"itemsOf"),i=t.filter(d=>il(d).blocking).flatMap(r),a=[...t.filter(d=>!il(d).blocking),...s].flatMap(r),o=i.length>0?"failing":a.length>0?"warning":n.length>0?"clean":"starting",c=[...t.filter(d=>il(d).blocking).flatMap(d=>d.reads),...t.filter(d=>!il(d).blocking).flatMap(d=>d.reads),...s.flatMap(d=>d.reads)],p=[...new Set(c)];return p.length===0&&p.push("events://recent"),{status:o,blocking:i,warnings:a,suggestedReads:p,checks:A_(e)}}l(C_,"uq"),u(C_,"deriveVerdict");function I_(e=process.env){let t=e.LENSMCP_TRANSPORT==="http"||e.LENSMCP_TRANSPORT==="socket",s=e.LENSMCP_PORT;return{mode:t?"shared":"embedded",pid:process.pid,startedAt:new Date(Date.now()-Math.round(process.uptime()*1e3)).toISOString(),...t&&s?{url:`http://127.0.0.1:${s}/mcp`}:{}}}l(I_,"F8"),u(I_,"readServerInfo");async function Lp(e){let t=await wb(e.resources,e.signalFreshMs??0),s=C_(t);return{schemaVersion:1,revision:e.revision,updatedAt:new Date().toISOString(),sessionId:e.sessionId,server:I_(),status:s.status,blocking:s.blocking,warnings:s.warnings,suggestedReads:s.suggestedReads,checks:s.checks,signals:t}}l(Lp,"$i"),u(Lp,"aggregateStatus");function D_(e){let t=Array.isArray(e.signals)?e.signals:[],s=u(i=>[...new Set(t.filter(i).map(a=>String(a.kind)))],"named"),n=s(i=>i.producer!=="none"&&(i.state==="passed"||i.state==="unknown")),r=s(i=>i.producer==="none");return{status:e.status,updatedAt:e.updatedAt??"",revision:e.revision??0,blocking:(e.blocking??[]).map(i=>({title:i.title,...i.resource?{resource:i.resource}:{},...i.fix?{fix:i.fix}:{},...i.verify?{verify:i.verify}:{}})),warnings:(e.warnings??[]).map(i=>({title:i.title,...i.resource?{resource:i.resource}:{},...i.rule?{rule:i.rule}:{}})),...e.checks?{checks:e.checks}:{},...n.length?{quiet:n}:{},...r.length?{unmonitored:r}:{},next:e.suggestedReads??[],...e.server?{server:e.server}:{},more:"Read only what a line points at. Each warning's fix and how to verify it, and every signal's own sentence: observe_current_status { detail: true }."}}l(D_,"F$"),u(D_,"briefStatus");var bb="agent://current-status",kb=class extends dJ{static{l(this,"H$")}static{u(this,"AgentCurrentStatusResource")}async execute(){let e=this.get(X);try{return await e.read(bb)}catch{}let t=this.get(Wu);return Lp({resources:e,sessionId:t.id,revision:e.revision(bb)??0})}};kb=P([lJ({name:"agent-current-status",uri:bb,mimeType:"application/json",description:'Workspace health in one read: status (clean/warning/failing/starting), what is BLOCKING (typecheck/lint/build errors, browser runtime errors, wedged or crash-looping services), warnings, and the exact resources to read next. Signals with no producer report `producer: "none"` \u2014 unmonitored, not healthy.'})],kb);var SJ=kb;import{Resource as AJ,ResourceContext as CJ}from"@frontmcp/sdk";var $b=class extends CJ{static{l(this,"G$")}static{u(this,"ProcessClusterResource")}async execute(){return this.get(X).read("process://cluster")}};$b=P([AJ({name:"process-cluster",uri:"process://cluster",mimeType:"application/json",description:"Dev-cluster service health: which services are up / down / wedged / crash-looping, which fail to build, restart counts, and the error lines services printed (ERROR in, EADDRINUSE, and error TS\u2026 for a project no typecheck producer reports for \u2014 otherwise type errors are in typecheck://errors), and `incidents`: the requests of the last 15 minutes the gateway answered itself because of the pod \u2014 evicted (502: silent through the liveness check, or the process gone; the service restarted, so work in flight was cut short) or given up on (504: alive past the ceiling, pod kept) \u2014 each with its method, path and the traceId of the 502/504 body. Read this when a request 502s or a dev server stopped responding. Each service also says what it is `serving` \u2014 the app generation its pod runs, when it swapped to it, the files that build carried, and whether a build is running; the `service_state` tool reads one service's and can wait for the swap."})],$b);var IJ=$b;import{Resource as DJ,ResourceContext as TJ}from"@frontmcp/sdk";var xb=class extends TJ{static{l(this,"K$")}static{u(this,"PerfRulesResource")}async execute(){return this.get(X).read("perf://rules")}};xb=P([DJ({name:"perf-rules",uri:"perf://rules",mimeType:"application/json",description:"Performance problems the lens detected by rule, each with a stable rule id, the measured evidence, the estimated cost (modules / MB / compile ms), the FIX steps and a VERIFY step: bundle/heavy-barrel-import (a service compiles most of a shared library through its root barrel while using a few symbols), pod/heap-budget (a dev pod's live heap after GC is over its budget), pod/retained-generation (a hot-swapped app copy is still in memory). A finding is retracted when the next build or memory report no longer shows it \u2014 that is how to prove a fix."})],xb);var _J=xb;import{Resource as MJ,ResourceContext as BJ}from"@frontmcp/sdk";var Eb=class extends BJ{static{l(this,"J$")}static{u(this,"AgentSessionsResource")}async execute(){return this.get(X).read("agent://sessions")}};Eb=P([MJ({name:"agent-sessions",uri:"agent://sessions",mimeType:"application/json",description:"The coding agents connected to this worktree's lens, and the ones that left recently: each session's client and version, live / idle / ended, what it says it is doing (agent_task), and every tool call and resource read it made \u2014 name, redacted arguments, how long it took, how big the answer was, whether it failed. Read it to see what another agent on this worktree is doing before you start the same work."})],Eb);var qJ=Eb;import{Resource as jJ,ResourceContext as RJ}from"@frontmcp/sdk";var Sb=class extends RJ{static{l(this,"X$")}static{u(this,"ProcessSourcesResource")}async execute(){return this.get(X).read(ds)}};Sb=P([jJ({name:"process-sources",uri:ds,mimeType:"application/json",description:"Custom sources: what each service REPORTS that no tap can see \u2014 this release, `queue` sources: work waiting in the app's own tables (an outbox) before it becomes a BullMQ job. Per source: its state (`current`, or `stale`, `unreachable`, `refused`, `malformed`, `not-running`, `never-polled` \u2014 each UNKNOWN, not zero), the age of the last good snapshot, its groups by oldest wait, and `findings`: groups whose oldest pending item has waited longer than the source's `thresholds.oldestWaitMin`. Everything is `provenance: \"reported\"` \u2014 the app's claim. The tools observe_sources and source_get read it."})],Sb);var OJ=Sb;import{Tool as NJ,ToolContext as PJ}from"@frontmcp/sdk";var T_=["typecheck","lint","build","runtime","cluster"],LJ=[...T_,"all"],FJ={typecheck:[{signal:"typecheck://current",resource:"typecheck://errors",keys:["errors"],hint:"TypeScript diagnostics from the watching tsc. Already computed \u2014 no need to run `nx typecheck`."}],lint:[{signal:"lint://current",resource:"lint://errors",keys:["errors"],hint:"ESLint errors from the watching lint pass. Already computed \u2014 no need to run `nx lint`."}],build:[{signal:"build://current",resource:"build://failures",keys:["failures"],hint:"Bundler/compile failures. The dev server is serving a stale or broken bundle until these clear."}],runtime:[{signal:"runtime://browser/errors",resource:"runtime://browser/errors",keys:["entries"],hint:"Uncaught errors from the browser. Pair with flow_list_recent to see what the user did first."},{signal:"runtime://errors",resource:"runtime://errors",keys:["entries"],hint:"Errors a dev service raised while handling a request (a 500 from a curl, an e2e runner or the page) \u2014 route, status, request id and stack. No browser is involved."}],cluster:[{signal:"process://cluster",resource:"process://cluster",keys:["errors"],hint:"Error lines printed by dev services (ERROR in / EADDRINUSE; error TS only for a project no typecheck producer reports for). A wedged or crash-looping service 502s every request routed to it."},{signal:"process://cluster",resource:"process://cluster",keys:["incidents"],hint:"Requests the gateway answered itself because of the pod, in the last 15 minutes \u2014 each with its method, path and traceId (the one in the 502/504 body). `pod-evicted` (502): the pod sent nothing and its liveness route stayed silent past the confirmation window (or its process was gone); the service is restarted, so work it was doing for that request may have been cut short \u2014 check before repeating a call that is not safe to repeat. `request-gave-up` (504): the pod stayed alive past the ceiling and was kept; the request may still complete there."},{signal:"process://cluster",resource:"process://cluster",keys:["workersDown"],hint:"A service's `serve` workers (queue consumers, background loops) that are not running: `restarting` \u2014 it crashed and starts again at `nextAt`; `crash-looping` \u2014 it keeps crashing at boot, each wait longer (up to a minute); `exited` \u2014 it ended on its own or its bundle is missing, and nothing starts it until the next build. `lastCrash.lines` is what it printed last. The service still answers requests; its queues have no consumer."}]},al=u(e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0,"asRecord");async function __(e,t){let s;try{s=al(await e.read(t.resource))}catch{return{items:[]}}if(!s)return{items:[]};let n={};for(let r of["capacity","dropped","oldestAt","newestAt"])typeof s[r]=="number"&&(n[r]=s[r]);for(let r of t.keys){let i=s[r];if(Array.isArray(i))return{items:i,...Object.keys(n).length>0?{ring:n}:{}}}return{items:[]}}l(__,"eX"),u(__,"readItems");var Si=u(e=>{let t=al(e),s=t?.timestamp??t?.at;return typeof s=="number"&&Number.isFinite(s)?s:void 0},"timeOf");function M_(e){return e.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,"#").replace(/\b[0-9a-f]{12,}\b/gi,"#").replace(/\d+/g,"#").slice(0,160)}l(M_,"tX"),u(M_,"shapeOfTitle");var Ab=50,UJ=new Set(["id","timestamp","title","project","fingerprint","handled","floodSuppressed"]);function B_(e){let t=new Map;for(let s of e){let n=[s.project,s.fingerprint,s.status,s.errorName,M_(String(s.title??""))].join("\0"),r=t.get(n);r?r.push(s):t.set(n,[s])}return[...t.values()].map(s=>{let n=s.map(p=>Si(p)),r=Math.max(...n),i=s.find(p=>Si(p)===r),a=s.every(p=>p.handled===i.handled)&&typeof i.handled=="boolean"?i.handled:void 0,o=s.reduce((p,d)=>p+(typeof d.floodSuppressed=="number"?d.floodSuppressed:0),0),c=s.slice().sort((p,d)=>Si(d)-Si(p)).map(p=>String(p.id));return{title:String(i.title??""),...typeof i.project=="string"?{project:i.project}:{},fingerprint:String(i.fingerprint),count:s.length,firstSeenAt:Math.min(...n),lastSeenAt:r,...a!==void 0?{handled:a}:{},...o>0?{floodSuppressed:o}:{},ids:c.slice(0,Ab),...c.length>Ab?{idsOmitted:c.length-Ab}:{},sample:Object.fromEntries(Object.entries(i).filter(([p])=>!UJ.has(p)))}}).sort((s,n)=>n.lastSeenAt-s.lastSeenAt)}l(B_,"pq"),u(B_,"byFailure");async function q_(e){let t=e.kind==="all"?T_:[e.kind],s=Math.max(0,e.offset??0),n=e.now??Date.now(),r=[e.sinceMs,e.withinMs!==void 0?n-e.withinMs:void 0].filter(b=>typeof b=="number"&&Number.isFinite(b)),i=r.length>0?Math.max(...r):void 0,a=i!==void 0||e.project!==void 0||e.handled!==void 0,o=await wb(e.resources),c=new Map(o.map(b=>[b.resource,b])),p=[],d=new Map;for(let b of t)for(let k of FJ[b]){let $=c.get(k.signal),E=$?.producer??"none",x=$?.state??"unknown",S=E==="none"?{items:[]}:await __(e.resources,k),A=BT(S.items),I=A.length>0&&A.every(H=>Si(H)!==void 0),C=i!==void 0&&I,_=A.filter(H=>{let W=al(H);return!(C&&Si(H)<i||e.project!==void 0&&W?.project!==e.project||e.handled!==void 0&&W?.handled!==e.handled)}),N=!e.expand&&_.length>0&&_.every(H=>Si(H)!==void 0&&typeof al(H)?.fingerprint=="string"&&typeof al(H)?.id=="string"),q=N?B_(_):_,M=q.slice(s,s+e.limit),L={kind:b,resource:k.resource,producer:E,state:x,count:A.length,...a?{matching:_.length}:{},...N?{grouped:!0,distinct:q.length}:{},returned:M.length,...S.ring?{ring:S.ring}:{},...i!==void 0&&!I&&A.length>0?{unfiltered:"the time window was not applied: this list is what is wrong now, not a history of when"}:{},items:M,detail:$?.detail??`no producer for ${k.resource} \u2014 unmonitored, not healthy`,hint:k.hint};d.set(L,q.length),p.push(L)}if(i!==void 0)for(let b of p)b.returned>0||b.producer==="none"||(delete b.hint,delete b.detail);let h=p.reduce((b,k)=>b+(k.matching??0),0),m=i!==void 0&&h===0,f={kind:e.kind,totalErrors:p.reduce((b,k)=>b+k.count,0),...a?{totalMatching:h}:{},readAt:n,...m?{nothingNew:!0}:{},next:m?`Nothing failed since ${new Date(i).toISOString()}. Poll again with \`sinceMs: ${n}\`.`:`Only what happens from here: call again with \`sinceMs: ${n}\`.`,unmonitored:[...new Set(p.filter(b=>b.producer==="none").map(b=>b.kind))],groups:p},v=e.budgetBytes??xp(),g=p.map(b=>or(b.items)),y=or(f),w=!1;if(y>v){let b=y-g.reduce(($,E)=>$+E,0),k=RT(g,v-b-zJ);p.forEach(($,E)=>{if(g[E]<=k[E])return;let x=Gw($.items,k[E],{keep:"start"});$.items=x.items,$.returned=x.returned,w=!0})}for(let b of p)s+b.returned<(d.get(b)??0)&&(b.nextOffset=s+b.returned);return w&&(f.cutToFit=`Shown as much as fits one tool result (${v} bytes): long texts are cut to their head and a text repeated between items is stated once. \`count\` is what each list holds, \`returned\` what is shown here; call again with \`offset\` = a group's \`nextOffset\` (and its \`kind\`) for the items after these.`),f}l(q_,"r_"),u(q_,"collectErrors");var zJ=600,j_={name:"observe_current_status",description:"Workspace health in one call, as a brief: anything BLOCKING now (typecheck, lint, build, browser errors, wedged or crash-looping services), the warnings \u2014 PERFORMANCE problems found by rule included (a root barrel compiled whole, a pod over its heap budget), each with its rule id, a fix and how to verify it on `detail: true` \u2014 and what to read next. Call this FIRST when something looks broken, and before running `nx typecheck` / `nx lint` for a watched project (already computed here). `unmonitored` signals are not healthy. The items: observe_errors."},Ai={name:"observe_errors",description:"The error items the lens already computed \u2014 TypeScript, ESLint, build failures, browser errors, server-side request errors (route, status, stack) and error lines dev services printed. Prefer it to running `nx typecheck` / `nx lint` or tailing a dev-server log. `producer: \"none\"` means nothing feeds that check: an empty list there is not proof it is clean. Runtime lists come newest first, one entry per distinct failure (`count`, `ids`, `sample`); `expand: true` lists every occurrence. Poll with `sinceMs` = the last answer's `readAt` for only what is new; `offset` = a group's `nextOffset` reads on.",kinds:LJ,defaultKind:"all",defaultLimit:25,maxLimit:200},ol={name:"service_state",description:"\xABDid my edit land in the service?\xBB \u2014 what ONE dev service serves now: its app generation, when it swapped to it (`serving.swappedAt`), the build that swap carried (`serving.lastCompile`: `changedFiles`, `ok`), whether a build is running, its type check, and a one-sentence `answer`. After saving a backend file pass `file` (for `edit.landed`) and `awaitSwapAfter` (epoch ms: when you saved) to WAIT until it swapped or its build failed (`waited.outcome`) \u2014 instead of tailing a log or sleeping. No `service`: every service's generation. `service` is the Nx project.",defaultAwaitMs:2e4,maxAwaitMs:55e3},Fp={name:"observe_dismiss_errors",description:"Hide runtime errors you have EXPLAINED that are not a problem to fix (a 401 your own signed-out test browser caused), so they stop counting in observe_current_status. Give the `ids` observe_errors lists for a failure, or `all: true`, and a `reason`: it is shown to the person in the dashboard. It HIDES, it does not fix: an error shows again the next time it happens. It cannot dismiss a failing typecheck, lint, build or a broken service. Never dismiss an error you have not explained; undo with observe_restore_errors.",maxIds:250,minReasonChars:8},Cb={name:"observe_restore_errors",description:"Undo a dismissal, so the errors it hid are listed and counted again. Give the dismissal `ids` from runtime://dismissed (or the id of an entry it hid), or `all: true` for every dismissal in effect \u2014 including ones a person made in the dashboard.",maxIds:250},R_={name:"service_restart",description:"Restart ONE dev service \u2014 of this workspace, or of a worktree of it (`worktree`: its name; `main`: the main checkout) \u2014 so it reads again what it reads only at boot: config files, env, its bundle (a hot swap re-reads only what the rebuilt bundle does). A new tree starts beside the old one, which serves until the new one answers; `hard` stops it first. Waits for it to settle: `restart.done` says which generation serves, or why it failed (the old one then still serves). `done: false`: call again with `check: true`, which starts no second restart. `service` is the Nx project."},O_={name:"app_call",description:"Call this workspace's running app as a person who signed in to it \u2014 an authenticated route behind the dev gateway (`GET https://api.<app>.localhost/\u2026`) \u2014 instead of asking a person to open a page or sign in for you. It acts as someone who signed in to this workspace's app in the browser: the most recent by default, or `as` (user id, email or name) and `tenant`; `worktree` calls a worktree's app. Answers `status`, `headers`, `body` (cut at `maxBodyBytes`), who it acted `as`, and `mode`: `token` \u2014 their browser's own token rode along; `identity` \u2014 it had expired and the gateway stamped the identity it verified, so a service that reads the raw bearer itself can fail where the browser would not (`caveat` says what to do). Every call is a `verify-call-*` flow the lens records: flow_get { flowId } shows what it did. Who can be acted as: app_identities."},N_={name:"app_identities",description:"Who app_call can act as: the people who signed in to this workspace's app in the browser (`worktree`: a worktree's app), most recent first \u2014 user id, email, name, tenant, roles, the host their browser called, when last seen, and `mode` (`token`: their browser's token is still valid; `identity`: it expired, the gateway stamps the identity it verified). Empty: nobody has signed in since the gateway started remembering \u2014 ask the person to sign in to the app once; the identity is kept 30 days."},P_={name:"worktree_create",description:"Make a git worktree of this workspace and run it as its own instance of the app \u2014 its own hosts (app.<name>.<project>.localhost), databases and queues (nx.json \u2192 lensmcp.instances) \u2014 and point THIS session's lens at it: for a risky change, a migration, a parallel task, or reviewing a branch (`frozen`). It starts from the main checkout's HEAD, not its uncommitted edits. Then do every edit and command in the returned `root` (`lensmcp instance exec -- <cmd>` gives a command its variables). A slow `prepare` may still be running: `state` says so, worktree_list follows it. The lensmcp-worktrees skill has the workflow."},L_={name:"worktree_list",description:"This workspace's checkouts \u2014 the main one and every worktree instance: its state (running, stopped, preparing, failed\u2026), branch, how many files hold uncommitted work, its hosts and dashboard, whether the lens made it, and `active` \u2014 the one this session's lens reports on now. Call it to find a worktree to continue in, to see whether a create has finished, or to check which app the observe.* tools are describing."},F_={name:"worktree_switch",description:"Point this session's lens at another checkout of this workspace \u2014 a worktree by name, or 'main' \u2014 so observe.*, flows, errors and every other lens tool describe ITS running app. A stopped worktree is started first. It does not move your shell: work in the returned `root`."},U_={name:"worktree_remove",description:"Take a worktree away: stop its app, drop the databases and queues the lens made for it, and \u2014 when the lens made the worktree \u2014 remove its folder. The branch is kept (deleteBranch: true deletes it once merged). It REFUSES while the worktree holds uncommitted work and lists the files: commit them on its branch first. Pass force: true only when the person has said to throw that work away. Removing the worktree the lens is on moves the lens back to main."},z_={name:"agent_task",description:'Say what you are working on, so the developer sees it on the Agents page beside every call you make: `task` \u2014 the task you were given, in a sentence (its first line is kept) \u2014 and `step` \u2014 what you are doing now ("reproducing the 401", "running the e2e"). Call it when you start a task, and again when the step changes; either alone is fine. Nothing else depends on it, and it never fails.'},Ib={name:"observe_sources",description:"Work the services REPORT that the lens cannot see by itself \u2014 a `queue` source is work waiting in an app's own tables (an outbox) before it ever becomes a BullMQ job, so near-empty BullMQ queues do not mean nothing waits; a `loop` source is the background loop that drains it (when it last ran, what it took, when it runs next); a `store` is a storage backend no tap models (objects and bytes against its quota, its writes, deletes and errors); `traffic` is messages over a channel no tap classifies (per channel: messages, failures, \xABtoo many requests\xBB, p95 \u2014 polled, or counted from what the app pushes when it declares no route). Every source each service declares (`cluster.sources` in project.json): its kind, its `state`, the age of its last snapshot, the headline numbers (pending, in flight, failed, the oldest wait; a loop's last run) and its findings \u2014 a group waiting over `oldestWaitMin`, a group STALLED (nothing taken or finished for `stalledMin`), a loop overdue, failing run after run, or taking nothing while its queue has work; a store near its quota, failing, or growing with nothing deleted; a channel rate-limited, failing or slow. Answers carry `provenance: \"reported\"` (the app's claim, not a measurement). Only `current` was read: `unreachable`, `refused`, `malformed`, `not-running`, `stale` and `never-polled` mean UNKNOWN, not zero. Filters: `service` (Nx project), `kind`. One source in full: source_get.",kinds:["queue","loop","store","traffic"]},W_={name:"source_get",description:"One custom source in full \u2014 a queue's latest snapshot (every group, with its labels, pending, in-flight, failed, completed-in-window counts, the oldest wait and how long it has not moved) and its history; a loop's last run, next run and its recent runs; a store's groups and its history; a traffic source's every channel; what the app pushed about it (`lensEmitCustom`: enqueued, admitted, run-end, write, delete, inbound, outbound \u2026, each with the flowId it ran in \u2014 open it with flow_get); its state and why, the age of the snapshot, and its findings. `service` is the Nx project, `name` the source's name in `cluster.sources` (observe_sources lists them). `provenance: \"reported\"`: the numbers are the app's claim; a state other than `current` means unknown, not zero."};import{z as Oa}from"@frontmcp/sdk";var WJ={task:Oa.string().max(2e3).optional().describe("The task, in a sentence; its first line is kept."),step:Oa.string().max(500).optional().describe("What you are doing now.")},HJ=Oa.object({task:Oa.string().optional(),step:Oa.string().optional(),shown:Oa.string()}).passthrough(),Db=class extends PJ{static{l(this,"m_")}static{u(this,"AgentTaskTool")}async execute(e){let t=e.task?.split(`
190
+ `,k)!==-1)return S(),!1}return S(),!0},"publishPending"),I=u((W,U)=>{let fe;try{fe=jp(W).size}catch{return!0}for(;v<fe;){if(performance.now()>=U)return!1;let F;try{F=QV(W,"r")}catch(V){return r(V),!0}try{let V=YV(F,x,0,Math.min(x.length,fe-v),v);if(V<=0)break;v+=V,b+=w.write(x.subarray(0,V))}finally{JV(F)}if(!A(U))return!1}return!0},"readOn"),C=u(W=>{y=t,v=0,g=W,w=new a_("utf8"),b="",k=0},"restart"),_=u(()=>{for(let W=1;W<=9;W++)try{if(jp(`${t}.${W}`).ino===g)return`${t}.${W}`}catch{}},"rotatedTo"),N=u(()=>{let W=performance.now()+f;if(!A(W))return!0;if(y!==t){if(!I(y,W))return!0;C(void 0)}let U;try{U=jp(t)}catch{return h=b.length-k,!1}if(g===void 0&&(g=U.ino),U.ino!==g){let F=_();if(F&&(y=F,!I(F,W)))return!0;C(U.ino)}else U.size<v&&C(U.ino);let fe=!I(t,W);return h=Math.max(0,U.size-v)+(b.length-k),fe},"drain"),q=!1,M,L=u(()=>{if(M=void 0,q)return;q=!0;let W=!1;try{W=N()}catch(U){r(U)}finally{q=!1}W&&!M&&(M=setImmediate(L))},"pump"),H=setInterval(L,e.pollMs??50);H.unref?.(),o.push(()=>{clearInterval(H),M&&clearImmediate(M)})}if(s){let[f,v]=s.split(":"),g=Number(v);if(f&&Number.isFinite(g)){p=!0;let y;try{y=VV("udp4"),y.on("message",w=>a(w.toString("utf8"))),y.on("error",w=>r(w)),y.bind(g,f),y.unref()}catch(w){r(w),p=!1}if(y){let w=y;o.push(()=>new Promise(b=>{try{w.close(()=>b())}catch{b()}}))}}}if(n)try{let f=l_({path:n,onMessage:u(v=>a(v),"onMessage"),onError:r});d=!0,o.push(()=>f.close())}catch(f){r(f)}let m=[];return c&&m.push("file"),p&&m.push("udp"),d&&m.push("uds"),{mode:m.join("+")||"none",count:u(()=>i,"count"),behind:u(()=>h,"behind"),async stop(){for(let f of o)try{await f()}catch{}}}}l(d_,"M$"),u(d_,"startEventIngest");import{existsSync as tJ,readFileSync as c_}from"node:fs";import{dirname as sJ,join as rJ}from"node:path";function p_(e=process.cwd()){let t=hb("nx.json",e);if(!t)return Ms();try{let s=JSON.parse(c_(t,"utf8"));return Ms(s.lensmcp?.thresholds)}catch{return Ms()}}l(p_,"O$"),u(p_,"loadWorkspaceThresholds");function h_(e=process.cwd()){let t=hb("nx.json",e);if(!t)return sn;try{let s=JSON.parse(c_(t,"utf8"));return R5(s.lensmcp?.flows)}catch(s){return{...sn,problems:[`${t} could not be read as JSON (${s instanceof Error?s.message:String(s)}) \u2014 flow config ignored`]}}}l(h_,"C$"),u(h_,"loadWorkspaceFlowsConfig");function hb(e,t){let s=t;for(let n=0;n<8;n++){let r=rJ(s,e);if(tJ(r))return r;let i=sJ(s);if(i===s)break;s=i}}l(hb,"eq"),u(hb,"findUp");import{PerformanceObserver as nJ,constants as Rp,performance as iJ}from"node:perf_hooks";function m_(e){if(!(e.cpuMs===void 0||e.ms<=0))return e.cpuMs>=e.ms*.5?"working":"waiting"}l(m_,"N$"),u(m_,"stallKind");function f_(e=128,t=Date.now){let s=[];return{begin(n){let r={what:n,start:t()};return s.push(r),s.length>e&&s.splice(0,s.length-e),()=>{r.end??=t()}},overlapping(n,r){return s.filter(i=>i.start<=r&&(i.end??r)>=n).map(i=>({s:i,ms:(i.end??r)-i.start})).sort((i,a)=>a.ms-i.ms).slice(0,8).map(({s:i,ms:a})=>`${i.what} ${a}ms${i.end===void 0?" (still running)":""}`)}}}l(f_,"tq"),u(f_,"createWorkLog");var aJ=f_(),oJ={[Rp.NODE_PERFORMANCE_GC_MAJOR]:"major",[Rp.NODE_PERFORMANCE_GC_MINOR]:"minor",[Rp.NODE_PERFORMANCE_GC_INCREMENTAL]:"incremental",[Rp.NODE_PERFORMANCE_GC_WEAKCB]:"weakcb"};function g_(e){let t=Number(process.env.LENSMCP_STALL_MS),s=e.thresholdMs??(Number.isFinite(t)&&t>0?t:1e3),n=e.tickMs??100,r=e.work??aJ,i=[],a;try{a=new nJ(m=>{for(let f of m.getEntries()){let v=iJ.timeOrigin+f.startTime,g=oJ[f.detail?.kind??-1]??"gc";i.push({start:v,end:v+f.duration,kind:g})}i.length>256&&i.splice(0,i.length-256)}),a.observe({entryTypes:["gc"]})}catch{a=void 0}let o=Date.now(),c=e.ingested?.()??0,p=u(()=>{try{let m=process.resourceUsage();return{cpu:m.userCPUTime+m.systemCPUTime,major:m.majorPageFault,minor:m.minorPageFault}}catch{return}},"usage"),d=p(),h=setInterval(()=>{let m=Date.now(),f=m-o-n,v=e.ingested?.()??0,g=p();if(f>s){let y=o,w=v-c,b=g&&d?{cpuMs:Math.round((g.cpu-d.cpu)/1e3),faults:{major:g.major-d.major,minor:g.minor-d.minor}}:{};setImmediate(()=>{let k=i.filter(E=>E.end>=y&&E.start<=m),$=process.memoryUsage();try{e.onStall({at:m,ms:f,gcMs:Math.round(k.reduce((E,x)=>E+(Math.min(x.end,m)-Math.max(x.start,y)),0)),gcs:k.length,gcKinds:[...new Set(k.map(E=>E.kind))],work:r.overlapping(y,m),...e.ingested?{ingested:w}:{},...b,heapUsed:$.heapUsed,rss:$.rss})}catch{}})}o=m,c=v,d=g},n);return h.unref?.(),()=>{clearInterval(h),a?.disconnect()}}l(g_,"j$"),u(g_,"startStallWatch");function P(e,t,s,n){var r=arguments.length,i=r<3?t:n===null?n=Object.getOwnPropertyDescriptor(t,s):n,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(e,t,s,n);else for(var o=e.length-1;o>=0;o--)(a=e[o])&&(i=(r<3?a(i):r>3?a(t,s,i):a(t,s))||i);return r>3&&i&&Object.defineProperty(t,s,i),i}l(P,"M"),u(P,"__decorate");import{App as uJ}from"@frontmcp/sdk";import{Resource as lJ,ResourceContext as dJ}from"@frontmcp/sdk";import{existsSync as cJ,readFileSync as pJ}from"node:fs";import{dirname as hJ,join as mJ}from"node:path";var ur="perf://rules",xi="pod/heap-budget",Ei="pod/retained-generation",v_=512,y_=.9,fJ=64,gJ=16,vJ=16,w_=256,b_=1024*1024,yJ="LENSMCP_PERF_RULES",wJ="LENSMCP_POD_HEAP_BUDGET_MB",bJ={heapBudgetEnabled:!0,retainedEnabled:!0,budgetMb:v_,services:{}},kJ=/^(0|off|false|no)$/i,mb=u(e=>{let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>=16&&t<=1e6?t:void 0},"budget");function Op(e,t){let s=t&&typeof t=="object"&&!Array.isArray(t)?t:{},n=s[xi]&&typeof s[xi]=="object"?s[xi]:{},r=s[Ei]&&typeof s[Ei]=="object"?s[Ei]:{},i=kJ.test((e[yJ]??"").trim())||s.enabled===!1,a={};if(n.services&&typeof n.services=="object"&&!Array.isArray(n.services))for(let[o,c]of Object.entries(n.services)){let p=mb(c);p!==void 0&&(a[o]=p)}return{heapBudgetEnabled:!i&&n.enabled!==!1,retainedEnabled:!i&&r.enabled!==!1,budgetMb:mb(e[wJ])??mb(n.budgetMb)??v_,services:a}}l(Op,"Gm"),u(Op,"resolvePodRuleThresholds");function k_(e=process.cwd(),t=process.env){let s=e;for(let n=0;n<8;n++){let r=mJ(s,".lensmcp","config.json");if(cJ(r))try{let a=JSON.parse(pJ(r,"utf8"));return Op(t,a?.perfRules)}catch{return Op(t,void 0)}let i=hJ(s);if(i===s)break;s=i}return Op(t,void 0)}l(k_,"D$"),u(k_,"loadPodRuleThresholds");var sl=u((e,t,s)=>`${e}\0${t}\0${s}`,"key"),lr=u(e=>Math.round(e/b_),"mb"),fb=0,$J=u(()=>(fb=(fb+1)%65535,`perf-${Date.now().toString(36)}${fb.toString(36)}${Math.random().toString(36).slice(2,7)}`),"eventId"),xJ=class{static{l(this,"_l")}static{u(this,"PerfRuleBook")}constructor(e={}){this.options=e,this.findings=new Map,this.pods=new Map,this.heard=!1,this.thresholds=e.thresholds??bJ,this.now=e.now??Date.now}ingest(e){return e.source==="perf"?this.ingestRule(e):e.source==="memory"?this.ingestPod(e):!1}ingestRule(e){let t=hT(e.raw);if(!t||t.rule.startsWith("pod/"))return!1;let s=!this.heard;if(this.heard=!0,t.kind==="perf-rule-scan"){let i=!1,a=new Set(t.open);for(let[o,c]of this.findings)c.rule===t.rule&&c.project===t.project&&!a.has(c.subject)&&(this.findings.delete(o),i=!0);return i||s}let n=sl(t.rule,t.project,t.subject);if(t.kind==="perf-rule-retracted")return this.findings.delete(n)||s;let r=this.findings.get(n);return this.findings.set(n,{rule:t.rule,project:t.project,subject:t.subject,severity:t.severity,title:t.title,summary:t.summary,evidence:t.evidence,cost:t.cost,fix:t.fix,verify:t.verify,docs:t.docs,firstSeenAt:r?.firstSeenAt??e.timestamp,lastSeenAt:Math.max(e.timestamp,r?.lastSeenAt??0)}),this.bound(),!0}projectPods(e,t,s){let n=this.pods.get(e);if(!n&&(n={service:t,lastSeenAt:s,readings:new Map,retained:new Map},this.pods.set(e,n),this.pods.size>fJ)){let r=[...this.pods.entries()].sort((i,a)=>i[1].lastSeenAt-a[1].lastSeenAt)[0];r&&r[0]!==e&&(this.pods.delete(r[0]),this.close(sl(xi,r[0],r[1].service),"evicted",s),this.close(sl(Ei,r[0],r[1].service),"evicted",s))}return n.service=t||n.service,n.lastSeenAt=Math.max(n.lastSeenAt,s),n}ingestPod(e){let t=yp(e.raw);if(!t)return!1;let s=e.timestamp,n=this.projectPods(t.project,t.service||t.project,s),r=`${t.pod}:${t.pid}`;if(t.kind==="pod-memory"){if(t.previousAlive!==!0&&n.readings.set(r,this.reading(t,s)),t.trigger==="boot"){for(let c of[...n.readings.keys()])c.startsWith(`${t.pod}:`)&&c!==r&&n.readings.delete(c);for(let c of[...n.retained.keys()])c.startsWith(`${t.pod}:`)&&!c.startsWith(`${r}:`)&&n.retained.delete(c)}if(n.readings.size>gJ){let c=[...n.readings.entries()].sort((p,d)=>p[1].at-d[1].at)[0];c&&n.readings.delete(c[0])}}else if(t.kind==="pod-memory-retained"){n.retained.set(`${r}:${t.gen}`,this.retainedOf(t,s));let c=[...n.retained.keys()].filter(p=>p.startsWith(`${r}:`));c.length>vJ&&n.retained.delete(c[0])}else if(t.kind==="pod-memory-released")n.retained.delete(`${r}:${t.gen}`);else if(t.kind==="pod-memory-exited"){n.readings.delete(r);for(let c of[...n.retained.keys()])c.startsWith(`${r}:`)&&n.retained.delete(c)}let i=!this.heard;this.heard=!0;let a=this.evaluateHeap(t.project,n,s),o=this.evaluateRetained(t.project,n,s);return a||o||i}reading(e,t){return{pod:e.pod,pid:e.pid,service:e.service||e.project,at:e.at??t,trigger:e.trigger,gen:e.gen,swaps:e.swaps,live:e.live,reserved:e.reserved,rss:e.rss,...e.baseline!==void 0?{baseline:e.baseline}:{}}}retainedOf(e,t){return{pod:e.pod,pid:e.pid,gen:e.gen,at:t,ageMs:e.ageMs,swapsSinceClose:e.swapsSinceClose,gcs:e.gcs,alive:Array.isArray(e.alive)?e.alive.slice(0,8):[],...e.counts?{counts:e.counts}:{},live:e.live}}budgetFor(e,t){return this.thresholds.services[t]??this.thresholds.services[e]??this.thresholds.budgetMb}related(e){return[...this.findings.values()].filter(t=>t.project===e&&!t.rule.startsWith("pod/")).map(t=>`${t.rule}: ${t.title}`)}evaluateHeap(e,t,s){let n=t.service,r=sl(xi,e,n),i=this.findings.get(r);if(!this.thresholds.heapBudgetEnabled)return i?this.close(r,"disabled",s):!1;let a=this.budgetFor(e,t.service),o=a*b_,c=[...t.readings.values()].sort((v,g)=>g.live-v.live),p=c.filter(v=>v.live>o),d=c.some(v=>v.live>o*y_);if(p.length===0&&!(i&&d))return i?this.close(r,c.length?"cleared":"pod-exited",s):!1;if(p.length===0)return!1;let h=p[0],m=p.reduce((v,g)=>v+(g.live-o),0),f={rule:xi,project:e,subject:n,severity:h.live>=2*o?"error":"warning",title:`${t.service}: ${lr(h.live)} MB live heap after a full GC \u2014 over its ${a} MB budget${p.length>1?` (${p.length} pods)`:""}`,summary:`Pod #${h.pod} of ${t.service} holds ${lr(h.live)} MB of live objects right after a full GC (${lr(h.reserved)} MB reserved, rss ${lr(h.rss)} MB${h.baseline!==void 0?`; ${lr(h.baseline)} MB at boot`:""}, generation ${h.gen} after ${h.swaps} swap${h.swaps===1?"":"s"}). That is not garbage: it is what the app keeps, in every pod of the service.`,evidence:{budgetMb:a,pods:p.map(v=>({pod:v.pod,pid:v.pid,liveMb:lr(v.live),reservedMb:lr(v.reserved),rssMb:lr(v.rss),...v.baseline!==void 0?{baselineMb:lr(v.baseline)}:{},gen:v.gen,swaps:v.swaps,trigger:v.trigger,at:v.at})),related:this.related(e)},cost:{bytes:m,memoryMb:lr(m),basis:`live heap after a full GC above the ${a} MB budget, summed over the pods over it`},fix:[`See what the heap is made of: \`memory_explain_pod({ service: '${t.service}' })\`, then \`lensmcp mem ${t.service} --snapshot --analyze\` \u2014 read "bytes by package/module" and the largest retainers.`,`If one shared library dominates (FoodGuard: ~300 MB of zod schemas per pod from a contracts barrel), import it by subpath \u2014 see any bundle/heavy-barrel-import finding for ${e} \u2014 and build large schema catalogs lazily (a function that builds on first use), not at module load.`,"If the bundle text dominates (eval strings, source maps), keep the default `eval` devtool and no `--enable-source-maps` (LENSMCP_DEV_DEVTOOL unset).",`If the heap grows with each swap or request, it is retention, not size: look for module-level caches, registries and listeners that outlive a request (\`memory_explain_leak\`). A service that genuinely needs more raises its budget: \`.lensmcp/config.json\` perfRules["pod/heap-budget"].services["${t.service}"].`],verify:`After the change rebuilds and the pod swaps, its next post-GC report (\`memory_pods\`) shows live heap under ${Math.round(a*y_)} MB and LensMCP retracts this finding (\`observe_current_status\` no longer lists pod/heap-budget for ${t.service}).`,docs:cT[xi],firstSeenAt:i?.firstSeenAt??s,lastSeenAt:s};return this.open(r,f,i)}evaluateRetained(e,t,s){let n=t.service,r=sl(Ei,e,n),i=this.findings.get(r),a=[...t.retained.values()].sort((d,h)=>h.ageMs-d.ageMs);if(!this.thresholds.retainedEnabled||a.length===0)return i?this.close(r,this.thresholds.retainedEnabled?"released":"disabled",s):!1;let o=a[0],c=Math.max(1,Math.round(o.ageMs/6e4)),p={rule:Ei,project:e,subject:n,severity:"warning",title:`${t.service}: ${a.length===1?`generation ${o.gen} is`:`${a.length} closed generations are`} still in memory ${c} min after the hot swap that closed ${a.length===1?"it":"them"}`,summary:`Pod #${o.pod} closed generation ${o.gen} ${c} min ago, ${o.swapsSinceClose} swap(s) and ${o.gcs} full GC(s) since, and ${o.alive.join(", ")||"its objects"} ${o.alive.length===1?"is":"are"} still alive: something still points into the old app \u2014 a whole copy of it stays resident with every swap that leaks.`,evidence:{generations:a.slice(0,8).map(d=>({pod:d.pod,pid:d.pid,gen:d.gen,ageMs:d.ageMs,swapsSinceClose:d.swapsSinceClose,gcs:d.gcs,alive:d.alive,...d.counts?{counts:d.counts}:{},liveMb:lr(d.live)}))},cost:{basis:"one copy of the app per retained generation; its size is in the heap snapshot (`lensmcp mem --snapshot --analyze`)"},fix:[`Find what holds it: \`lensmcp mem ${t.service} --snapshot --analyze\` prints the shortest path from the GC roots to generation ${o.gen} \u2014 the first frame outside your app's own objects is the culprit.`,"Usual culprits: a timer or interval never cleared on shutdown; a BullMQ worker, queue event or Redis client never closed in onModuleDestroy / onApplicationShutdown; `process.on(\u2026)` / an EventEmitter listener added per app instance; a module-level registry, cache or singleton keyed by class or holding app instances.","Release it in the app's shutdown hooks (Nest calls them on every hot swap), or move the module-level state into a provider the container owns."],verify:'Save a file to swap again; within ~5 min the pod reports "generation N freed" (`memory_pods`), LensMCP retracts this finding, and `memory://leaks/suspected` no longer lists the generation.',docs:cT[Ei],firstSeenAt:i?.firstSeenAt??s,lastSeenAt:s};return this.open(r,p,i)}open(e,t,s){return this.findings.set(e,t),this.bound(),(!s||s.title!==t.title||s.severity!==t.severity)&&this.emit(t,"finding"),!0}close(e,t,s){let n=this.findings.get(e);return n?(this.findings.delete(e),this.emit({...n,lastSeenAt:s},"retracted",t),!0):!1}emit(e,t,s){let n=this.options.publish;if(!n)return;let r=this.options.sessionId??"pending",i=this.now(),a={id:$J(),sessionId:r,timestamp:i,source:"perf",category:"performance",severity:t==="finding"?e.severity:"info",context:{sessionId:r,projectName:e.project},fingerprint:pT(e.rule,e.project,e.subject),title:t==="finding"?`${e.rule}: ${e.title}`:`${e.rule}: cleared for ${e.project} (${e.subject})`,raw:t==="finding"?{kind:"perf-rule-finding",rule:e.rule,project:e.project,subject:e.subject,severity:e.severity,title:e.title,summary:e.summary,evidence:e.evidence,cost:e.cost,fix:e.fix,verify:e.verify,docs:e.docs,detectedAt:i}:{kind:"perf-rule-retracted",rule:e.rule,project:e.project,subject:e.subject,reason:s??"cleared",at:i}};queueMicrotask(()=>{try{n(a)}catch{}})}bound(){if(this.findings.size<=w_)return;let e=[...this.findings.entries()].sort((t,s)=>t[1].lastSeenAt-s[1].lastSeenAt).slice(0,this.findings.size-w_);for(let[t]of e)this.findings.delete(t)}openFindings(){return[...this.findings.values()].sort((e,t)=>e.severity===t.severity?t.lastSeenAt-e.lastSeenAt:e.severity==="error"?-1:1)}report(e){let t=this.openFindings(),s={};for(let n of t)s[n.rule]=(s[n.rule]??0)+1;return{schemaVersion:1,revision:e,updatedAt:new Date(this.now()).toISOString(),producer:this.heard?"connected":"none",detail:this.heard?t.length?`${t.length} open performance finding${t.length===1?"":"s"}: ${Object.entries(s).map(([n,r])=>`${r} ${n}`).join(", ")}`:"no open performance findings":"no performance rule has reported yet \u2014 rules run after a dev-cluster compilation (bundle/*) and on pod memory reports (pod/*); start the gateway",findings:t,counts:s}}};function gb(e,t=700){let s=e.fix.map((n,r)=>`${r+1}) ${n}`).join(" ");return s.length>t?`${s.slice(0,t-40).trimEnd()}\u2026 (all steps: ${ur})`:s}l(gb,"Vm"),u(gb,"compactFix");var Ir=u(e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0,"asRecord"),$_=u(e=>Array.isArray(e)?e.length:void 0,"arrayLen"),Dt=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"asCount"),_e=u(e=>typeof e=="string"?e:void 0,"asString");function et(e,...t){for(let s of t){let n=$_(e[s])??Dt(e[s]);if(n!==void 0)return n}}l(et,"mt"),u(et,"countOf");var ge=u((e,t,s=`${t}s`)=>`${e} ${e===1?t:s}`,"plural");function Np(e,t,s,n,r){if(t>0)return{state:"failed",count:t,detail:`${ge(t,`${n} error`)} \u2014 read ${r}`};if(s>0)return{state:"warning",count:s,detail:ge(s,`${n} warning`)};let i=_e(e.status);return i==="clean"||i==="passed"?{state:"passed",count:0,detail:`${n} clean`}:{state:"unknown",detail:`${n} has not reported a result yet (status=${i??"absent"})`}}l(Np,"U$"),u(Np,"fromStatusField");var Pp=[{kind:"typecheck",resource:"typecheck://current",reads:u(()=>["typecheck://errors"],"reads"),blocking:!0,source:"typescript",read:u(e=>Np(e,et(e,"errorCount","errors")??0,0,"typecheck","typecheck://errors"),"read")},{kind:"lint",resource:"lint://current",reads:u(e=>e==="warning"?["lint://warnings"]:["lint://errors"],"reads"),blocking:!0,source:"eslint",read:u(e=>Np(e,et(e,"errorCount","errors")??0,et(e,"warningCount","warnings")??0,"lint","lint://errors"),"read")},{kind:"build",resource:"build://current",reads:u(e=>e==="warning"?["build://current"]:["build://failures"],"reads"),blocking:!0,source:"vite",read:u(e=>{let t=Array.isArray(e.failures)?e.failures.filter(r=>{let i=r?.domain;return i!=="typecheck"&&i!=="lint"}).length:et(e,"failures","failureCount")??0,s=($_(e.failures)??t)-t,n=t===0&&s>0&&_e(e.status)==="failing"?{...e,status:"clean"}:e;return Np(n,t,et(e,"warnings","warningCount")??0,"build","build://failures")},"read")},{kind:"runtime",resource:"runtime://browser/errors",reads:u(()=>["runtime://browser/errors","runtime://browser/failed-requests"],"reads"),blocking:!0,source:"client-runtime",read:u(e=>{let t=et(e,"count","entries")??0;return t>0?{state:"failed",count:t,detail:`${ge(t,"browser runtime error")} \u2014 read runtime://browser/errors`}:{state:"unknown",count:0,detail:"no browser runtime errors recorded (a browser may never have connected)"}},"read")},{kind:"runtime",resource:"runtime://errors",reads:u(()=>["runtime://errors"],"reads"),blocking:!0,source:"nestjs",read:u(e=>{let t=et(e,"count","entries")??0,s=Array.isArray(e.entries)?e.entries.filter(r=>r?.outcome==="declared").length:0,n=s>0?` (${t-s} unhandled, ${s} a 5xx the app answered on purpose)`:"";return t>0?{state:"failed",count:t,detail:`${ge(t,"server-side error")}${n} \u2014 read runtime://errors (route, status, request id and stack)`}:{state:"unknown",count:0,detail:"no server-side errors recorded (no pod may have handled a request yet)"}},"read")},{kind:"cluster",resource:"process://cluster",reads:u(()=>["process://cluster"],"reads"),blocking:!0,source:"gateway",read:u(e=>{let t=et(e,"services")??0,s=Array.isArray(e.workersDown)?e.workersDown:[],n=u(x=>`${String(x.project)} ${String(x.name)} ${x.state==="crash-looping"?`crash-looping (${String(x.inARow??"?")} crashes in a row)`:x.state==="exited"?"ended \u2014 not started again until a build":"crashed, being started again"}`,"workerName"),r=s.filter(x=>x.state==="crash-looping"||x.state==="exited"),i=s.filter(x=>x.state==="restarting"),a=u(x=>`${ge(x.length,"worker")} not running (${x.map(n).join("; ")}) \u2014 nothing consumes ${x.length===1?"its":"their"} queues; read process://cluster \`workersDown\` for the last lines each one printed`,"workerPart");if(t===0&&s.length===0)return{state:"unknown",detail:"no cluster lifecycle events seen (the gateway may not be running)"};let o=et(e,"crashLooping")??0,c=et(e,"wedged")??0,p=et(e,"buildFailed")??0,d=et(e,"typeErrors")??0,h=d>0?`${ge(d,"service")} with type errors no typecheck producer reports`:void 0,m=et(e,"down")??0,f=Dt(e.restarts)??0,v=Array.isArray(e.services)?e.services.filter(x=>{let S=x??{};return S.buildFailed===!0&&S.state==="up"}).length:0,g=Math.max(0,p-v),y=Array.isArray(e.incidents)?e.incidents:[],w=y.length>0?`${ge(y.length,"request")} the gateway answered itself in the last 15 min (${[...new Set(y.map(x=>`${String(x.project)} ${x.kind==="pod-evicted"?"pod evicted":"request given up"} \u2192 ${String(x.status)}`))].join("; ")}) \u2014 read process://cluster \`incidents\`, or observe_errors kind cluster`:void 0,b=v>0?`${ge(v,"service")} failing to build while still serving the last good bundle`:void 0,k=[b,h?`${h} (still serving)`:void 0].filter(Boolean);if(o>0||c>0||g>0){let x=[o>0?`${ge(o,"service")} crash-looping`:void 0,c>0?`${ge(c,"service")} wedged`:void 0,g>0?`${ge(g,"service")} failing to build`:void 0].filter(Boolean);return{state:"failed",count:o+c+p+d+s.length,detail:`${x.join(", ")} \u2014 read process://cluster (requests to them 502)${k.length?`; ${k.join("; ")}`:""}${s.length?`; ${a(s)}`:""}`}}if(r.length>0)return{state:"failed",count:s.length+p+d,detail:`${a(s)}${k.length?`; ${k.join("; ")}`:""}`};let $=i.length?`; ${a(i)}`:"";if(b)return{state:"failed",count:p+d+i.length,detail:`${b} \u2014 read process://cluster for the error lines${h?`; ${h} (still serving)`:""}${$}`};if(h)return{state:"failed",count:d+i.length,detail:`${h} \u2014 read process://cluster for the lines (the bundle built; the services still serve)${$}`};if(i.length>0)return{state:"warning",count:i.length+y.length+m,detail:`${a(i)}${w?`; ${w}`:""}${m>0?`; ${ge(m,"service")} down (idle scale-to-zero is normal)`:""}`};if(w)return{state:"warning",count:y.length+m,detail:`${w}${m>0?`; ${ge(m,"service")} down (idle scale-to-zero is normal)`:""}`};if(m>0)return{state:"warning",count:m,detail:`${ge(m,"service")} down (idle scale-to-zero is normal; the next request restarts it)`};let E=et(e,"up")??0;return{state:"passed",count:0,detail:`${ge(E,"service")} up${f>0?`, ${ge(f,"restart")} this session`:""}`}},"read")},{kind:"memory",resource:"memory://leaks/suspected",reads:u(()=>["memory://leaks/suspected","memory://owners/growing"],"reads"),blocking:!1,source:"memory",read:u(e=>{let t=et(e,"suspected","leaks")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"suspected leak")} \u2014 read memory://leaks/suspected`}:{state:"passed",count:0,detail:"no suspected leaks"}},"read")},{kind:"visual",resource:"visual://violations/current",reads:u(()=>["visual://violations/current"],"reads"),blocking:!1,source:"visual",read:u(e=>{let t=et(e,"violations")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"visual violation")} \u2014 read visual://violations/current`}:{state:"passed",count:0,detail:"no visual violations"}},"read")},{kind:"perf",resource:"perf://slow-routes",reads:u(()=>["perf://slow-routes"],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"routes")??0,s=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"route")} over${s?` ${s}ms`:" the slow-route threshold"} \u2014 read perf://slow-routes`}:{state:"passed",count:0,detail:"no slow routes"}},"read")},{kind:"duplicate-requests",resource:"perf://duplicate-requests",reads:u(()=>["perf://duplicate-requests"],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"endpoints")??0,s=Dt(e.peakThreshold);return t>0?{state:"warning",count:t,detail:`${ge(t,"endpoint")} called ${s?`\u2265${s}\xD7`:"several times"} concurrently by one page \u2014 read perf://duplicate-requests`}:{state:"passed",count:0,detail:"no duplicated requests"}},"read")},{kind:"db",resource:"db://slow-queries",reads:u(()=>["db://slow-queries","db://analysis"],"reads"),blocking:!1,source:"db",read:u(e=>{let t=et(e,"queries")??0,s=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"query shape")} over${s?` ${s}ms`:" the slow-query threshold"} \u2014 read db://slow-queries`}:{state:"passed",count:0,detail:"no slow query shapes"}},"read")},{kind:"db-lint",resource:"db://lint",reads:u(()=>["db://lint"],"reads"),blocking:!1,source:"db",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0,n=Dt(e.warnBelow)??70;return!t&&!s?{state:"passed",count:0,detail:"every statement named; no SQL review under the threshold"}:{state:"warning",count:t+s,detail:[t?`${ge(t,"SQL lint error")} \u2014 unnamed statements are not reviewed until named`:"",s?`${ge(s,"statement")} whose SQL review scores under ${n}`:""].filter(Boolean).join("; ")+" \u2014 read db://lint"}},"read")},{kind:"routes-lint",resource:"routes://lint",reads:u(()=>["routes://lint"],"reads"),blocking:!1,source:"routes",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no route lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"route lint error"):"",s?ge(s,"route lint warning"):""].filter(Boolean).join("; ")+" \u2014 read routes://lint (each SQL issue links its db://lint/<statement>)"}},"read")},{kind:"kv-lint",resource:"kv://lint",reads:u(()=>["kv://lint"],"reads"),blocking:!1,source:"redis",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no key-family lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"key-family lint error"):"",s?ge(s,"key-family lint warning"):""].filter(Boolean).join("; ")+" \u2014 read kv://lint (review_cache { pattern } for one family)"}},"read")},{kind:"queues-lint",resource:"queues://lint",reads:u(()=>["queues://lint"],"reads"),blocking:!1,source:"queue",read:u(e=>{let t=Dt(e.errors)??0,s=Dt(e.warnings)??0;return!t&&!s?{state:"passed",count:0,detail:"no queue lint issue"}:{state:"warning",count:t+s,detail:[t?ge(t,"queue lint error"):"",s?ge(s,"queue lint warning"):""].filter(Boolean).join("; ")+" \u2014 read queues://lint (review_queue { queue } for one queue)"}},"read")},{kind:"suggestions",resource:"agent://suggestions",reads:u(()=>["agent://suggestions"],"reads"),blocking:!1,source:"review",read:u(e=>{let t=Array.isArray(e.suggestions)?e.suggestions.length:0;return t?{state:"warning",count:t,detail:`${ge(t,"accepted suggestion")} from LensMCP's reviews to make \u2014 read agent://suggestions, then suggestion_set { id, state: "applied" } and suggestion_check { id, \u2026 }`}:{state:"passed",count:0,detail:"no accepted suggestion to make"}},"read")},{kind:"egress",resource:"net://egress/hosts",reads:u(e=>e==="warning"?["net://egress/hosts","net://egress/failures"]:["net://egress/hosts"],"reads"),blocking:!1,source:"external",read:u(e=>{let t=et(e,"failingHosts")??0,s=et(e,"slowHosts")??0,n=Dt(e.thresholdMs);return t>0?{state:"warning",count:t,detail:`${ge(t,"external host")} failing \u2014 read net://egress/failures`}:s>0?{state:"warning",count:s,detail:`${ge(s,"external host")} over${n?` ${n}ms`:" the slow-egress threshold"} \u2014 read net://egress/hosts`}:{state:"passed",count:0,detail:"no failing or slow external calls"}},"read")},{kind:"perf-rules",resource:ur,reads:u(()=>[ur],"reads"),blocking:!1,source:"perf",read:u(e=>{let t=et(e,"findings")??0;return t>0?{state:"warning",count:t,detail:`${ge(t,"performance finding")} \u2014 read ${ur} (each has a fix and a verify step)`}:{state:"passed",count:0,detail:"no open performance findings"}},"read"),items:u(e=>{let t=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(n=>!!n),s=t.slice(0,vb).map(n=>{let r=_e(n.rule)??"perf",i=_e(n.project)??"?",a=_e(n.subject)??"?",o=Array.isArray(n.fix)?n.fix.filter(c=>typeof c=="string"):[];return{source:"perf",severity:"warning",title:`${r} \xB7 ${_e(n.title)??i}`,fingerprint:`agent-status:perf-rule:${r}:${i}:${a}`,resource:ur,rule:r,...o.length?{fix:gb({fix:o})}:{},..._e(n.verify)?{verify:_e(n.verify)}:{},..._e(n.docs)?{docs:_e(n.docs)}:{}}});return t.length>vb&&s.push({source:"perf",severity:"warning",title:`${ge(t.length-vb,"more performance finding")} \u2014 read ${ur}`,fingerprint:"agent-status:perf-rules:more",resource:ur}),s},"items")},{kind:"sources",resource:ds,reads:u(()=>[ds],"reads"),blocking:!1,source:"sources",read:u(e=>{let t=(Array.isArray(e.sources)?e.sources:[]).map(Ir).filter(f=>!!f),s=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(f=>!!f),n=et(e,"findings")??0,r=u(f=>s.filter(v=>(_e(v.rule)??nl)===f).length,"byRule"),i=t.filter(f=>["unreachable","refused","malformed","stale"].includes(_e(f.state)??"")),a=t.filter(f=>f.state==="current"),o=u(f=>`${_e(f.project)??"?"}/${_e(f.name)??"?"}`,"name"),c=(Array.isArray(e.problems)?e.problems:[]).map(Ir).filter(f=>!!f);if(n>0||i.length>0||c.length>0)return{state:"warning",count:n+i.length+c.length,detail:[r(nl)>0?`${ge(r(nl),"reported queue group")} waiting longer than its threshold`:"",r("queue/stalled")>0?`${ge(r("queue/stalled"),"reported queue group")} stalled \u2014 nothing taken or finished`:"",r("loop/overdue")>0?`${ge(r("loop/overdue"),"reported loop")} overdue`:"",r("loop/failing")>0?`${ge(r("loop/failing"),"reported loop")} failing run after run`:"",r("loop/idle-while-fed")>0?`${ge(r("loop/idle-while-fed"),"reported loop")} taking nothing while its queue has work`:"",r("store/near-quota")>0?`${ge(r("store/near-quota"),"reported store")} near its quota`:"",r("store/errors")>0?`${ge(r("store/errors"),"reported store")} failing operations`:"",r("store/orphans")>0?`${ge(r("store/orphans"),"reported store")} growing with nothing deleted`:"",r("traffic/rate-limited")>0?`${ge(r("traffic/rate-limited"),"reported channel")} answered \xABtoo many requests\xBB`:"",r("traffic/failures")>0?`${ge(r("traffic/failures"),"reported channel")} failing over its threshold`:"",r("traffic/latency")>0?`${ge(r("traffic/latency"),"reported channel")} slow (p95 over its threshold)`:"",i.length>0?`${ge(i.length,"source")} not read (${i.map(f=>`${o(f)} ${_e(f.state)}`).join("; ")}) \u2014 its backlog is unknown, not empty`:"",c.length>0?`${ge(c.length,"cluster.sources entry","cluster.sources entries")} not polled (${_e(c[0].project)??"?"}: ${_e(c[0].problem)??"?"})`:""].filter(Boolean).join("; ")+` \u2014 read ${ds} (observe_sources)`};if(a.length===0)return{state:"unknown",detail:t.length?`no reported source read yet (${t.map(f=>`${o(f)} ${_e(f.state)}`).join("; ")}) \u2014 a service scaled to zero is not woken to read it`:`${ds} holds no source`};let p=Ir(e.totals)??{},d=a.map(f=>Dt(Ir(f.headline)?.oldestWaitMs)).filter(f=>f!==void 0),h=d.length?Math.max(...d):void 0,m=a.filter(f=>f.sourceKind==="loop").length;return{state:"passed",count:0,detail:`${ge(a.length,"reported source")} read: ${Dt(p.pending)??0} pending${h!==void 0?`, the oldest waiting ${yb(h).replace(/ ago$/,"")}`:""}${m?`, ${ge(m,"loop")} running as it says`:""} \u2014 none over its threshold`}},"read"),items:u(e=>{let t=(Array.isArray(e.findings)?e.findings:[]).map(Ir).filter(i=>!!i),s=t.slice(0,rl).map(i=>{let a=Array.isArray(i.fix)?i.fix.filter(p=>typeof p=="string"):[],o=_e(i.rule)??nl,c=`${_e(i.project)??"?"}:${_e(i.name)??"?"}:${_e(i.group)??_e(i.channel)??"?"}`;return{source:"sources",severity:"warning",title:_e(i.title)??"a reported source is over one of its thresholds",fingerprint:o===nl?`agent-status:sources:${c}`:`agent-status:sources:${o}:${c}`,resource:ds,rule:o,...a.length?{fix:gb({fix:a},1200)}:{},..._e(i.verify)?{verify:_e(i.verify)}:{}}});t.length>rl&&s.push({source:"sources",severity:"warning",title:`${ge(t.length-rl,"more reported source finding")} \u2014 observe_sources`,fingerprint:"agent-status:sources:more",resource:ds});let n=(Array.isArray(e.sources)?e.sources:[]).map(Ir).filter(i=>!!i);for(let i of n.filter(a=>["unreachable","refused","malformed","stale"].includes(_e(a.state)??"")).slice(0,rl)){let a=_e(i.state)??"?";s.push({source:"sources",severity:"warning",title:`${_e(i.project)??"?"} \xB7 ${_e(i.name)??"?"} (reported source) is ${a}${_e(i.detail)?` \u2014 ${_e(i.detail)}`:""}; its numbers are unknown, not zero`,fingerprint:`agent-status:sources:read:${_e(i.project)??"?"}:${_e(i.name)??"?"}:${a}`,resource:ds})}let r=(Array.isArray(e.problems)?e.problems:[]).map(Ir).filter(i=>!!i);for(let[i,a]of r.slice(0,rl).entries())s.push({source:"sources",severity:"warning",title:`${_e(a.project)??"?"}: cluster.sources \u2014 ${_e(a.problem)??"?"}`,fingerprint:`agent-status:sources:declaration:${_e(a.project)??"?"}:${i}`,resource:ds});return s},"items")}],vb=5,rl=5,nl="queue/oldest-wait",x_=new WeakMap,zve=Pp.map(e=>e.resource),EJ=2e3;async function E_(e,t,s=0){let n={kind:t.kind,resource:t.resource},r;try{r=Ir(await(s>0?e.readRecent(t.resource,s):e.read(t.resource)))}catch{return{...n,producer:"none",state:"unknown",detail:`no producer for ${t.resource} \u2014 this signal is unmonitored, not healthy`,reads:t.reads("unknown")}}if(!r)return{...n,producer:"none",state:"unknown",detail:`${t.resource} produced no readable payload`,reads:t.reads("unknown")};let i=_e(r.producer),a=(e.revision(t.resource)??0)>0,o=i==="none"?"none":i==="connected"||a?"connected":"none",c=_e(r.detail);if(o==="none")return{...n,producer:o,state:"unknown",detail:c??(i==="none"?`${t.resource} reports no producer attached \u2014 this signal is unmonitored, not healthy`:`${t.resource} is registered but has never reported \u2014 this signal is unmonitored, not healthy`),reads:t.reads("unknown")};let p;try{p=t.read(r)}catch{p={state:"unknown",detail:`${t.resource} payload could not be interpreted`}}let d=r.stale===!0,h=d?`${p.detail} (as of ${Dt(r.ageMs)!==void 0?yb(Dt(r.ageMs)):"a while ago"}; nothing has re-checked since)`:p.detail,m={...n,producer:o,state:p.state,...p.count===void 0?{}:{count:p.count},...d?{stale:!0}:{},detail:h,reads:t.reads(p.state)};if(t.items&&(p.state==="warning"||p.state==="failed"))try{let f=t.items(r);f.length&&x_.set(m,f)}catch{}return m}l(E_,"D8"),u(E_,"readSignal");function yb(e){return e<6e4?`${Math.max(1,Math.round(e/1e3))}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:`${Math.round(e/36e5)}h ago`}l(yb,"lq"),u(yb,"describeAge");async function wb(e,t=0){return Promise.all(Pp.map(s=>E_(e,s,t)))}l(wb,"Zm"),u(wb,"readSignals");var il=u(e=>Pp.find(t=>t.resource===e.resource)??Pp.find(t=>t.kind===e.kind),"specFor");function S_(e){return{source:il(e).source,severity:e.state==="failed"?"error":"warning",title:e.detail,fingerprint:`agent-status:${e.kind}:${e.state}`,resource:e.reads[0]??e.resource}}l(S_,"U8"),u(S_,"toItem");function A_(e){let t={failed:3,warning:2,unknown:1,passed:0},s=u(i=>{let a=e.filter(o=>o.kind===i);return a.length===0?"unknown":a.reduce((o,c)=>t[c.state]>t[o]?c.state:o,a[0].state)},"pick"),n=u(i=>i==="failed"?"failed":i==="passed"||i==="warning"?"passed":"unknown","tri"),r=u(i=>i,"quad");return{typecheck:n(s("typecheck")),lint:n(s("lint")),build:n(s("build")),runtime:r(s("runtime")),visual:r(s("visual")),memory:r(s("memory"))}}l(A_,"z8"),u(A_,"toChecks");function C_(e){let t=e.filter(d=>d.state==="failed"),s=e.filter(d=>d.state==="warning"),n=e.filter(d=>d.state==="passed"),r=u(d=>x_.get(d)??[S_(d)],"itemsOf"),i=t.filter(d=>il(d).blocking).flatMap(r),a=[...t.filter(d=>!il(d).blocking),...s].flatMap(r),o=i.length>0?"failing":a.length>0?"warning":n.length>0?"clean":"starting",c=[...t.filter(d=>il(d).blocking).flatMap(d=>d.reads),...t.filter(d=>!il(d).blocking).flatMap(d=>d.reads),...s.flatMap(d=>d.reads)],p=[...new Set(c)];return p.length===0&&p.push("events://recent"),{status:o,blocking:i,warnings:a,suggestedReads:p,checks:A_(e)}}l(C_,"uq"),u(C_,"deriveVerdict");function I_(e=process.env){let t=e.LENSMCP_TRANSPORT==="http"||e.LENSMCP_TRANSPORT==="socket",s=e.LENSMCP_PORT;return{mode:t?"shared":"embedded",pid:process.pid,startedAt:new Date(Date.now()-Math.round(process.uptime()*1e3)).toISOString(),...t&&s?{url:`http://127.0.0.1:${s}/mcp`}:{}}}l(I_,"F8"),u(I_,"readServerInfo");async function Lp(e){let t=await wb(e.resources,e.signalFreshMs??0),s=C_(t);return{schemaVersion:1,revision:e.revision,updatedAt:new Date().toISOString(),sessionId:e.sessionId,server:I_(),status:s.status,blocking:s.blocking,warnings:s.warnings,suggestedReads:s.suggestedReads,checks:s.checks,signals:t}}l(Lp,"$i"),u(Lp,"aggregateStatus");function D_(e){let t=Array.isArray(e.signals)?e.signals:[],s=u(i=>[...new Set(t.filter(i).map(a=>String(a.kind)))],"named"),n=s(i=>i.producer!=="none"&&(i.state==="passed"||i.state==="unknown")),r=s(i=>i.producer==="none");return{status:e.status,updatedAt:e.updatedAt??"",revision:e.revision??0,blocking:(e.blocking??[]).map(i=>({title:i.title,...i.resource?{resource:i.resource}:{},...i.fix?{fix:i.fix}:{},...i.verify?{verify:i.verify}:{}})),warnings:(e.warnings??[]).map(i=>({title:i.title,...i.resource?{resource:i.resource}:{},...i.rule?{rule:i.rule}:{}})),...e.checks?{checks:e.checks}:{},...n.length?{quiet:n}:{},...r.length?{unmonitored:r}:{},next:e.suggestedReads??[],...e.server?{server:e.server}:{},more:"Read only what a line points at. Each warning's fix and how to verify it, and every signal's own sentence: observe_current_status { detail: true }."}}l(D_,"F$"),u(D_,"briefStatus");var bb="agent://current-status",kb=class extends dJ{static{l(this,"H$")}static{u(this,"AgentCurrentStatusResource")}async execute(){let e=this.get(X);try{return await e.read(bb)}catch{}let t=this.get(Wu);return Lp({resources:e,sessionId:t.id,revision:e.revision(bb)??0})}};kb=P([lJ({name:"agent-current-status",uri:bb,mimeType:"application/json",description:'Workspace health in one read: status (clean/warning/failing/starting), what is BLOCKING (typecheck/lint/build errors, browser runtime errors, wedged or crash-looping services), warnings, and the exact resources to read next. Signals with no producer report `producer: "none"` \u2014 unmonitored, not healthy.'})],kb);var SJ=kb;import{Resource as AJ,ResourceContext as CJ}from"@frontmcp/sdk";var $b=class extends CJ{static{l(this,"G$")}static{u(this,"ProcessClusterResource")}async execute(){return this.get(X).read("process://cluster")}};$b=P([AJ({name:"process-cluster",uri:"process://cluster",mimeType:"application/json",description:"Dev-cluster service health: which services are up / down / wedged / crash-looping, which fail to build, restart counts, and the error lines services printed (ERROR in, EADDRINUSE, and error TS\u2026 for a project no typecheck producer reports for \u2014 otherwise type errors are in typecheck://errors), and `incidents`: the requests of the last 15 minutes the gateway answered itself because of the pod \u2014 evicted (502: silent through the liveness check, or the process gone; the service restarted, so work in flight was cut short) or given up on (504: alive past the ceiling, pod kept) \u2014 each with its method, path and the traceId of the 502/504 body. Read this when a request 502s or a dev server stopped responding. Each service also says what it is `serving` \u2014 the app generation its pod runs, when it swapped to it, the files that build carried, and whether a build is running; the `service_state` tool reads one service's and can wait for the swap."})],$b);var IJ=$b;import{Resource as DJ,ResourceContext as TJ}from"@frontmcp/sdk";var xb=class extends TJ{static{l(this,"K$")}static{u(this,"PerfRulesResource")}async execute(){return this.get(X).read("perf://rules")}};xb=P([DJ({name:"perf-rules",uri:"perf://rules",mimeType:"application/json",description:"Performance problems the lens detected by rule, each with a stable rule id, the measured evidence, the estimated cost (modules / MB / compile ms), the FIX steps and a VERIFY step: bundle/heavy-barrel-import (a service compiles most of a shared library through its root barrel while using a few symbols), pod/heap-budget (a dev pod's live heap after GC is over its budget), pod/retained-generation (a hot-swapped app copy is still in memory). A finding is retracted when the next build or memory report no longer shows it \u2014 that is how to prove a fix."})],xb);var _J=xb;import{Resource as MJ,ResourceContext as BJ}from"@frontmcp/sdk";var Eb=class extends BJ{static{l(this,"J$")}static{u(this,"AgentSessionsResource")}async execute(){return this.get(X).read("agent://sessions")}};Eb=P([MJ({name:"agent-sessions",uri:"agent://sessions",mimeType:"application/json",description:"The coding agents connected to this worktree's lens, and the ones that left recently: each session's client and version, live / idle / ended, what it says it is doing (agent_task), and every tool call and resource read it made \u2014 name, redacted arguments, how long it took, how big the answer was, whether it failed. Read it to see what another agent on this worktree is doing before you start the same work."})],Eb);var qJ=Eb;import{Resource as jJ,ResourceContext as RJ}from"@frontmcp/sdk";var Sb=class extends RJ{static{l(this,"X$")}static{u(this,"ProcessSourcesResource")}async execute(){return this.get(X).read(ds)}};Sb=P([jJ({name:"process-sources",uri:ds,mimeType:"application/json",description:"Custom sources: what each service REPORTS that no tap can see \u2014 this release, `queue` sources: work waiting in the app's own tables (an outbox) before it becomes a BullMQ job. Per source: its state (`current`, or `stale`, `unreachable`, `refused`, `malformed`, `not-running`, `never-polled` \u2014 each UNKNOWN, not zero), the age of the last good snapshot, its groups by oldest wait, and `findings`: groups whose oldest pending item has waited longer than the source's `thresholds.oldestWaitMin`. Everything is `provenance: \"reported\"` \u2014 the app's claim. The tools observe_sources and source_get read it."})],Sb);var OJ=Sb;import{Tool as NJ,ToolContext as PJ}from"@frontmcp/sdk";var T_=["typecheck","lint","build","runtime","cluster"],LJ=[...T_,"all"],FJ={typecheck:[{signal:"typecheck://current",resource:"typecheck://errors",keys:["errors"],hint:"TypeScript diagnostics from the watching tsc. Already computed \u2014 no need to run `nx typecheck`."}],lint:[{signal:"lint://current",resource:"lint://errors",keys:["errors"],hint:"ESLint errors from the watching lint pass. Already computed \u2014 no need to run `nx lint`."}],build:[{signal:"build://current",resource:"build://failures",keys:["failures"],hint:"Bundler/compile failures. The dev server is serving a stale or broken bundle until these clear."}],runtime:[{signal:"runtime://browser/errors",resource:"runtime://browser/errors",keys:["entries"],hint:"Uncaught errors from the browser. Pair with flow_list_recent to see what the user did first."},{signal:"runtime://errors",resource:"runtime://errors",keys:["entries"],hint:"Errors a dev service raised while handling a request (a 500 from a curl, an e2e runner or the page) \u2014 route, status, request id and stack. No browser is involved."}],cluster:[{signal:"process://cluster",resource:"process://cluster",keys:["errors"],hint:"Error lines printed by dev services (ERROR in / EADDRINUSE; error TS only for a project no typecheck producer reports for). A wedged or crash-looping service 502s every request routed to it."},{signal:"process://cluster",resource:"process://cluster",keys:["incidents"],hint:"Requests the gateway answered itself because of the pod, in the last 15 minutes \u2014 each with its method, path and traceId (the one in the 502/504 body). `pod-evicted` (502): the pod sent nothing and its liveness route stayed silent past the confirmation window (or its process was gone); the service is restarted, so work it was doing for that request may have been cut short \u2014 check before repeating a call that is not safe to repeat. `request-gave-up` (504): the pod stayed alive past the ceiling and was kept; the request may still complete there."},{signal:"process://cluster",resource:"process://cluster",keys:["workersDown"],hint:"A service's `serve` workers (queue consumers, background loops) that are not running: `restarting` \u2014 it crashed and starts again at `nextAt`; `crash-looping` \u2014 it keeps crashing at boot, each wait longer (up to a minute); `exited` \u2014 it ended on its own or its bundle is missing, and nothing starts it until the next build. `lastCrash.lines` is what it printed last. The service still answers requests; its queues have no consumer."}]},al=u(e=>typeof e=="object"&&e!==null&&!Array.isArray(e)?e:void 0,"asRecord");async function __(e,t){let s;try{s=al(await e.read(t.resource))}catch{return{items:[]}}if(!s)return{items:[]};let n={};for(let r of["capacity","dropped","oldestAt","newestAt"])typeof s[r]=="number"&&(n[r]=s[r]);for(let r of t.keys){let i=s[r];if(Array.isArray(i))return{items:i,...Object.keys(n).length>0?{ring:n}:{}}}return{items:[]}}l(__,"eX"),u(__,"readItems");var Si=u(e=>{let t=al(e),s=t?.timestamp??t?.at;return typeof s=="number"&&Number.isFinite(s)?s:void 0},"timeOf");function M_(e){return e.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,"#").replace(/\b[0-9a-f]{12,}\b/gi,"#").replace(/\d+/g,"#").slice(0,160)}l(M_,"tX"),u(M_,"shapeOfTitle");var Ab=50,UJ=new Set(["id","timestamp","title","project","fingerprint","handled","floodSuppressed"]);function B_(e){let t=new Map;for(let s of e){let n=[s.project,s.fingerprint,s.status,s.errorName,M_(String(s.title??""))].join("\0"),r=t.get(n);r?r.push(s):t.set(n,[s])}return[...t.values()].map(s=>{let n=s.map(p=>Si(p)),r=Math.max(...n),i=s.find(p=>Si(p)===r),a=s.every(p=>p.handled===i.handled)&&typeof i.handled=="boolean"?i.handled:void 0,o=s.reduce((p,d)=>p+(typeof d.floodSuppressed=="number"?d.floodSuppressed:0),0),c=s.slice().sort((p,d)=>Si(d)-Si(p)).map(p=>String(p.id));return{title:String(i.title??""),...typeof i.project=="string"?{project:i.project}:{},fingerprint:String(i.fingerprint),count:s.length,firstSeenAt:Math.min(...n),lastSeenAt:r,...a!==void 0?{handled:a}:{},...o>0?{floodSuppressed:o}:{},ids:c.slice(0,Ab),...c.length>Ab?{idsOmitted:c.length-Ab}:{},sample:Object.fromEntries(Object.entries(i).filter(([p])=>!UJ.has(p)))}}).sort((s,n)=>n.lastSeenAt-s.lastSeenAt)}l(B_,"pq"),u(B_,"byFailure");async function q_(e){let t=e.kind==="all"?T_:[e.kind],s=Math.max(0,e.offset??0),n=e.now??Date.now(),r=[e.sinceMs,e.withinMs!==void 0?n-e.withinMs:void 0].filter(b=>typeof b=="number"&&Number.isFinite(b)),i=r.length>0?Math.max(...r):void 0,a=i!==void 0||e.project!==void 0||e.handled!==void 0,o=await wb(e.resources),c=new Map(o.map(b=>[b.resource,b])),p=[],d=new Map;for(let b of t)for(let k of FJ[b]){let $=c.get(k.signal),E=$?.producer??"none",x=$?.state??"unknown",S=E==="none"?{items:[]}:await __(e.resources,k),A=BT(S.items),I=A.length>0&&A.every(H=>Si(H)!==void 0),C=i!==void 0&&I,_=A.filter(H=>{let W=al(H);return!(C&&Si(H)<i||e.project!==void 0&&W?.project!==e.project||e.handled!==void 0&&W?.handled!==e.handled)}),N=!e.expand&&_.length>0&&_.every(H=>Si(H)!==void 0&&typeof al(H)?.fingerprint=="string"&&typeof al(H)?.id=="string"),q=N?B_(_):_,M=q.slice(s,s+e.limit),L={kind:b,resource:k.resource,producer:E,state:x,count:A.length,...a?{matching:_.length}:{},...N?{grouped:!0,distinct:q.length}:{},returned:M.length,...S.ring?{ring:S.ring}:{},...i!==void 0&&!I&&A.length>0?{unfiltered:"the time window was not applied: this list is what is wrong now, not a history of when"}:{},items:M,detail:$?.detail??`no producer for ${k.resource} \u2014 unmonitored, not healthy`,hint:k.hint};d.set(L,q.length),p.push(L)}if(i!==void 0)for(let b of p)b.returned>0||b.producer==="none"||(delete b.hint,delete b.detail);let h=p.reduce((b,k)=>b+(k.matching??0),0),m=i!==void 0&&h===0,f={kind:e.kind,totalErrors:p.reduce((b,k)=>b+k.count,0),...a?{totalMatching:h}:{},readAt:n,...m?{nothingNew:!0}:{},next:m?`Nothing failed since ${new Date(i).toISOString()}. Poll again with \`sinceMs: ${n}\`.`:`Only what happens from here: call again with \`sinceMs: ${n}\`.`,unmonitored:[...new Set(p.filter(b=>b.producer==="none").map(b=>b.kind))],groups:p},v=e.budgetBytes??xp(),g=p.map(b=>or(b.items)),y=or(f),w=!1;if(y>v){let b=y-g.reduce(($,E)=>$+E,0),k=RT(g,v-b-zJ);p.forEach(($,E)=>{if(g[E]<=k[E])return;let x=Gw($.items,k[E],{keep:"start"});$.items=x.items,$.returned=x.returned,w=!0})}for(let b of p)s+b.returned<(d.get(b)??0)&&(b.nextOffset=s+b.returned);return w&&(f.cutToFit=`Shown as much as fits one tool result (${v} bytes): long texts are cut to their head and a text repeated between items is stated once. \`count\` is what each list holds, \`returned\` what is shown here; call again with \`offset\` = a group's \`nextOffset\` (and its \`kind\`) for the items after these.`),f}l(q_,"r_"),u(q_,"collectErrors");var zJ=600,j_={name:"observe_current_status",description:"Workspace health in one call, as a brief: anything BLOCKING now (typecheck, lint, build, browser errors, wedged or crash-looping services), the warnings \u2014 PERFORMANCE problems found by rule included (a root barrel compiled whole, a pod over its heap budget), each with its rule id, a fix and how to verify it on `detail: true` \u2014 and what to read next. Call this FIRST when something looks broken, and before running `nx typecheck` / `nx lint` for a watched project (already computed here). `unmonitored` signals are not healthy. The items: observe_errors."},Ai={name:"observe_errors",description:"The error items the lens already computed \u2014 TypeScript, ESLint, build failures, browser errors, server-side request errors (route, status, stack) and error lines dev services printed. Prefer it to running `nx typecheck` / `nx lint` or tailing a dev-server log. `producer: \"none\"` means nothing feeds that check: an empty list there is not proof it is clean. Runtime lists come newest first, one entry per distinct failure (`count`, `ids`, `sample`); `expand: true` lists every occurrence. Poll with `sinceMs` = the last answer's `readAt` for only what is new; `offset` = a group's `nextOffset` reads on.",kinds:LJ,defaultKind:"all",defaultLimit:25,maxLimit:200},ol={name:"service_state",description:"\xABDid my edit land in the service?\xBB \u2014 what ONE dev service serves now: its app generation, when it swapped to it (`serving.swappedAt`), the build that swap carried (`serving.lastCompile`: `changedFiles`, `ok`), whether a build is running, its type check, and a one-sentence `answer`. After saving a backend file pass `file` (for `edit.landed`) and `awaitSwapAfter` (epoch ms: when you saved) to WAIT until it swapped or its build failed (`waited.outcome`) \u2014 instead of tailing a log or sleeping. No `service`: every service's generation. `service` is the Nx project.",defaultAwaitMs:2e4,maxAwaitMs:55e3},Fp={name:"observe_dismiss_errors",description:"Hide runtime errors you have EXPLAINED that are not a problem to fix (a 401 your own signed-out test browser caused), so they stop counting in observe_current_status. Give the `ids` observe_errors lists for a failure, or `all: true`, and a `reason`: it is shown to the person in the dashboard. It HIDES, it does not fix: an error shows again the next time it happens. It cannot dismiss a failing typecheck, lint, build or a broken service. Never dismiss an error you have not explained; undo with observe_restore_errors.",maxIds:250,minReasonChars:8},Cb={name:"observe_restore_errors",description:"Undo a dismissal, so the errors it hid are listed and counted again. Give the dismissal `ids` from runtime://dismissed (or the id of an entry it hid), or `all: true` for every dismissal in effect \u2014 including ones a person made in the dashboard.",maxIds:250},R_={name:"service_restart",description:"Restart ONE dev service \u2014 of this workspace, or of a worktree of it (`worktree`: its name; `main`: the main checkout) \u2014 so it reads again what it reads only at boot: config files, env, its bundle (a hot swap re-reads only what the rebuilt bundle does). A new tree starts beside the old one, which serves until the new one answers; `hard` stops it first. Waits for it to settle: `restart.done` says which generation serves, or why it failed (the old one then still serves). `done: false`: call again with `check: true`, which starts no second restart. `service` is the Nx project."},O_={name:"app_call",description:"Call this workspace's running app as a person who signed in to it \u2014 an authenticated route behind the dev gateway (`GET https://api.<app>.localhost/\u2026`) \u2014 instead of asking a person to open a page or sign in for you. It acts as someone who signed in to this workspace's app in the browser: the most recent by default, or `as` (user id, email or name) and `tenant`; `worktree` calls a worktree's app. Answers `status`, `headers`, `body` (cut at `maxBodyBytes`), who it acted `as`, and `mode`: `token` \u2014 their browser's own token rode along; `identity` \u2014 it had expired and the gateway stamped the identity it verified, so a service that reads the raw bearer itself can fail where the browser would not (`caveat` says what to do). Every call is a `verify-call-*` flow the lens records: flow_get { flowId } shows what it did. Who can be acted as: app_identities."},N_={name:"app_identities",description:"Who app_call can act as: the people who signed in to this workspace's app in the browser (`worktree`: a worktree's app), most recent first \u2014 user id, email, name, tenant, roles, the host their browser called, when last seen, and `mode` (`token`: their browser's token is still valid; `identity`: it expired, the gateway stamps the identity it verified). Empty: nobody has signed in since the gateway started remembering \u2014 ask the person to sign in to the app once; the identity is kept 30 days."},P_={name:"worktree_create",description:"Make a git worktree of this workspace and run it as its own instance of the app \u2014 its own hosts (app.<name>.<project>.localhost), databases and queues (nx.json \u2192 lensmcp.instances) \u2014 and point THIS session's lens at it: for a risky change, a migration, a parallel task, or reviewing a branch (`frozen`). It starts from the main checkout's HEAD, not its uncommitted edits. Then do every edit and command in the returned `root` (`lensmcp instance exec -- <cmd>` gives a command its variables). A slow `prepare` may still be running: `state` says so, worktree_list follows it. The lens stays on the current checkout until preparation and registration finish; use worktree_switch once it is running. The lensmcp-worktrees skill has the workflow."},L_={name:"worktree_list",description:"This workspace's checkouts \u2014 the main one and every worktree instance: its state (running, stopped, preparing, failed\u2026), branch, how many files hold uncommitted work, its hosts and dashboard, whether the lens made it, and `active` \u2014 the one this session's lens reports on now. Call it to find a worktree to continue in, to see whether a create has finished, or to check which app the observe.* tools are describing."},F_={name:"worktree_switch",description:"Point this session's lens at another checkout of this workspace \u2014 a worktree by name, or 'main' \u2014 so observe.*, flows, errors and every other lens tool describe ITS running app. A stopped worktree is started first. It does not move your shell: work in the returned `root`."},U_={name:"worktree_remove",description:"Take a worktree away: stop its app, drop the databases and queues the lens made for it, and \u2014 when the lens made the worktree \u2014 remove its folder. The branch is kept (deleteBranch: true deletes it once merged). It REFUSES while the worktree holds uncommitted work and lists the files: commit them on its branch first. Pass force: true only when the person has said to throw that work away. Removing the worktree the lens is on moves the lens back to main."},z_={name:"agent_task",description:'Say what you are working on, so the developer sees it on the Agents page beside every call you make: `task` \u2014 the task you were given, in a sentence (its first line is kept) \u2014 and `step` \u2014 what you are doing now ("reproducing the 401", "running the e2e"). Call it when you start a task, and again when the step changes; either alone is fine. Nothing else depends on it, and it never fails.'},Ib={name:"observe_sources",description:"Work the services REPORT that the lens cannot see by itself \u2014 a `queue` source is work waiting in an app's own tables (an outbox) before it ever becomes a BullMQ job, so near-empty BullMQ queues do not mean nothing waits; a `loop` source is the background loop that drains it (when it last ran, what it took, when it runs next); a `store` is a storage backend no tap models (objects and bytes against its quota, its writes, deletes and errors); `traffic` is messages over a channel no tap classifies (per channel: messages, failures, \xABtoo many requests\xBB, p95 \u2014 polled, or counted from what the app pushes when it declares no route). Every source each service declares (`cluster.sources` in project.json): its kind, its `state`, the age of its last snapshot, the headline numbers (pending, in flight, failed, the oldest wait; a loop's last run) and its findings \u2014 a group waiting over `oldestWaitMin`, a group STALLED (nothing taken or finished for `stalledMin`), a loop overdue, failing run after run, or taking nothing while its queue has work; a store near its quota, failing, or growing with nothing deleted; a channel rate-limited, failing or slow. Answers carry `provenance: \"reported\"` (the app's claim, not a measurement). Only `current` was read: `unreachable`, `refused`, `malformed`, `not-running`, `stale` and `never-polled` mean UNKNOWN, not zero. Filters: `service` (Nx project), `kind`. One source in full: source_get.",kinds:["queue","loop","store","traffic"]},W_={name:"source_get",description:"One custom source in full \u2014 a queue's latest snapshot (every group, with its labels, pending, in-flight, failed, completed-in-window counts, the oldest wait and how long it has not moved) and its history; a loop's last run, next run and its recent runs; a store's groups and its history; a traffic source's every channel; what the app pushed about it (`lensEmitCustom`: enqueued, admitted, run-end, write, delete, inbound, outbound \u2026, each with the flowId it ran in \u2014 open it with flow_get); its state and why, the age of the snapshot, and its findings. `service` is the Nx project, `name` the source's name in `cluster.sources` (observe_sources lists them). `provenance: \"reported\"`: the numbers are the app's claim; a state other than `current` means unknown, not zero."};import{z as Oa}from"@frontmcp/sdk";var WJ={task:Oa.string().max(2e3).optional().describe("The task, in a sentence; its first line is kept."),step:Oa.string().max(500).optional().describe("What you are doing now.")},HJ=Oa.object({task:Oa.string().optional(),step:Oa.string().optional(),shown:Oa.string()}).passthrough(),Db=class extends PJ{static{l(this,"m_")}static{u(this,"AgentTaskTool")}async execute(e){let t=e.task?.split(`
191
191
  `)[0]?.trim(),s=e.step?.split(`
192
192
  `)[0]?.trim();return{...t?{task:t}:{},...s?{step:s}:{},shown:"on the Agents page, beside this session's calls"}}};Db=P([NJ({name:z_.name,description:z_.description,inputSchema:WJ,outputSchema:HJ})],Db);var GJ=Db;import{Tool as ZJ,ToolContext as VJ}from"@frontmcp/sdk";import{z as Be}from"@frontmcp/sdk";var H_=Be.object({title:Be.string(),resource:Be.string().optional(),rule:Be.string().optional(),fix:Be.string().optional(),verify:Be.string().optional()}).passthrough(),JJ={detail:Be.boolean().optional().describe("`true`: the whole document \u2014 every signal with its own sentence and reads. Default: the brief (verdict, blockers, warnings, what to read next).")},KJ=Be.object({status:Be.string(),updatedAt:Be.string().optional(),revision:Be.number().optional(),blocking:Be.array(H_).optional(),warnings:Be.array(H_).optional(),checks:Be.object({typecheck:Be.string().optional(),lint:Be.string().optional(),build:Be.string().optional(),runtime:Be.string().optional(),visual:Be.string().optional(),memory:Be.string().optional()}).passthrough().optional(),server:Be.object({mode:Be.string(),pid:Be.number(),startedAt:Be.string(),url:Be.string().optional()}).passthrough().optional(),quiet:Be.array(Be.string()).optional(),unmonitored:Be.array(Be.string()).optional(),next:Be.array(Be.string()).optional(),more:Be.string().optional(),schemaVersion:Be.unknown().optional(),sessionId:Be.string().optional(),suggestedReads:Be.array(Be.string()).optional(),signals:Be.array(Be.unknown()).optional()}).passthrough(),G_="agent://current-status",Tb=class extends VJ{static{l(this,"g_")}static{u(this,"ObserveCurrentStatusTool")}async execute(e){let t=await this.read();return e.detail?t:D_(t)}async read(){let e=this.get(X);try{return await e.read(G_)}catch{}let t=this.get(Wu);return Lp({resources:e,sessionId:t.id,revision:e.revision(G_)??0})}};Tb=P([ZJ({name:j_.name,description:j_.description,annotations:{readOnlyHint:!0},inputSchema:JJ,outputSchema:KJ})],Tb);var QJ=Tb;import{Tool as YJ,ToolContext as XJ}from"@frontmcp/sdk";import{z as Ie}from"@frontmcp/sdk";var eK=Ie.object({kind:Ie.string(),resource:Ie.string(),producer:Ie.string(),state:Ie.string(),count:Ie.number(),matching:Ie.number().optional(),grouped:Ie.boolean().optional(),distinct:Ie.number().optional(),returned:Ie.number(),nextOffset:Ie.number().optional(),ring:Ie.object({capacity:Ie.number().optional(),dropped:Ie.number().optional(),oldestAt:Ie.number().optional(),newestAt:Ie.number().optional()}).passthrough().optional(),unfiltered:Ie.string().optional(),items:Ie.array(Ie.unknown()),detail:Ie.string().optional(),hint:Ie.string().optional()}).passthrough(),tK={kind:Ie.enum(Ai.kinds).default(Ai.defaultKind).describe("'runtime': browser errors and a service's request errors (500s); 'cluster': dev-service / pod errors (502s). Default 'all'."),limit:Ie.number().int().positive().max(Ai.maxLimit).default(Ai.defaultLimit).describe(`Max items per kind (default ${Ai.defaultLimit}).`),offset:Ie.number().int().min(0).default(0).describe("A group's `nextOffset`, to continue its list."),withinMs:Ie.number().int().positive().optional().describe("Only the last this-many ms (300000 = five minutes): note the time, act, read what it caused."),sinceMs:Ie.number().int().positive().optional().describe("Only at or after this epoch ms \u2014 a previous answer's `readAt`."),project:Ie.string().min(1).optional().describe(`Only this service's (Nx project, e.g. "engine").`),handled:Ie.boolean().optional().describe("`false`: only unhandled failures; `true`: only a 5xx the app answered on purpose."),expand:Ie.boolean().optional().describe("Every occurrence, instead of one entry per distinct failure.")},sK=Ie.object({kind:Ie.string(),totalErrors:Ie.number(),totalMatching:Ie.number().optional(),unmonitored:Ie.array(Ie.string()),cutToFit:Ie.unknown().optional(),readAt:Ie.number(),nothingNew:Ie.boolean().optional(),next:Ie.string(),groups:Ie.array(eK)}).passthrough(),_b=class extends XJ{static{l(this,"w_")}static{u(this,"ObserveErrorsTool")}async execute(e){let t=this.get(X);return await q_({resources:t,kind:e.kind,limit:e.limit,offset:e.offset,...e.withinMs!==void 0?{withinMs:e.withinMs}:{},...e.sinceMs!==void 0?{sinceMs:e.sinceMs}:{},...e.project!==void 0?{project:e.project}:{},...e.handled!==void 0?{handled:e.handled}:{},...e.expand!==void 0?{expand:e.expand}:{}})}};_b=P([YJ({name:Ai.name,description:Ai.description,annotations:{readOnlyHint:!0},inputSchema:tK,outputSchema:sK})],_b);var rK=_b;import{Tool as nK,ToolContext as iK}from"@frontmcp/sdk";import{appendFileSync as aK,closeSync as oK,mkdirSync as uK,openSync as lK,renameSync as dK,statSync as cK,unlinkSync as pK}from"node:fs";import{dirname as hK,join as mK}from"node:path";function Z_(e,t){let{fs:s,maxBytes:n,maxFiles:r}=t,i=`${e}.rotate.lock`,a=t.staleLockMs??3e4,o;for(let c=0;c<2&&o===void 0;c++)try{o=s.openSync(i,"wx")}catch{try{if(Date.now()-s.statSync(i).mtimeMs<=a)return"busy";s.unlinkSync(i)}catch{}}if(o===void 0)return"busy";try{try{if(s.statSync(e).size<=n)return"not-needed"}catch{return"not-needed"}try{s.unlinkSync(`${e}.${r}`)}catch{}for(let c=r+1;c<=20;c++)try{s.unlinkSync(`${e}.${c}`)}catch{}for(let c=r-1;c>=1;c--)try{s.renameSync(`${e}.${c}`,`${e}.${c+1}`)}catch{}try{s.renameSync(e,`${e}.1`)}catch{}return"rotated"}finally{try{s.closeSync(o)}catch{}try{s.unlinkSync(i)}catch{}}}l(Z_,"kq"),u(Z_,"rotateBusFile");function Bs(e=process.env,t=process.cwd()){return e.LENSMCP_EVENT_FILE??mK(t,".lensmcp","events.jsonl")}l(Bs,"sn"),u(Bs,"lensEventFile");var V_=u((e,t,s,n,r)=>({id:Qr(),sessionId:e,timestamp:t,source:dT,category:"runtime",severity:"info",context:{sessionId:e},fingerprint:s,title:n,raw:r}),"lensEvent");function Mb(e,t){return V_(t,e.until,`${_a}:${e.groupId}`,`error dismissed: ${e.title??e.groupId}`,{kind:_a,groupId:e.groupId,until:e.until,eventIds:e.eventIds,...e.by?{by:e.by}:{},...e.reason?{reason:e.reason}:{},...e.title?{title:e.title}:{}})}l(Mb,"Jm"),u(Mb,"dismissalEvent");function Bb(e,t,s){return V_(t,s,`${vp}:${e}`,"error restored",{kind:vp,groupId:e})}l(Bb,"Qm"),u(Bb,"restoralEvent");var J_=u((e,t,s)=>{let n=Number(process.env[e]);return Number.isFinite(n)&&s(n)?n:t},"envNumber");function Up(e,t){t.length!==0&&(uK(hK(e),{recursive:!0}),Z_(e,{maxBytes:J_("LENSMCP_EVENT_MAX_BYTES",50*1024*1024,s=>s>0),maxFiles:J_("LENSMCP_EVENT_MAX_FILES",5,s=>s>=1&&s<=20),fs:{statSync:cK,renameSync:dK,unlinkSync:pK,openSync:lK,closeSync:oK}}),aK(e,t.map(s=>JSON.stringify(s)+`
193
193
  `).join("")))}l(Up,"sc"),u(Up,"appendBusEvents");var fK=["runtime://errors","runtime://browser/errors","runtime://browser/failed-requests"],gK="runtime://dismissed";async function K_(e,t){let s;try{s=await e.read(t)}catch{return[]}let n=s?.entries;return Array.isArray(n)?n.flatMap(r=>{let i=r;if(!i||typeof i.id!="string"||!i.id)return[];let a=typeof i.title=="string"&&i.title?i.title:typeof i.message=="string"?i.message:i.id;return[{id:i.id,title:a,timestamp:typeof i.timestamp=="number"?i.timestamp:0}]}):[]}l(K_,"xX"),u(K_,"entriesOf");async function Q_(e,t,s=Date.now()){let n=new Set(t.ids??[]),r=[],i=s;for(let p of fK)for(let d of await K_(e,p))!t.all&&!n.has(d.id)||r.some(h=>h.id===d.id)||(r.push({id:d.id,title:d.title,resource:p}),i=Math.max(i,d.timestamp));let a=new Set(r.map(p=>p.id)),o=t.reason.trim().slice(0,500),c=[];for(let p=0;p<r.length;p+=200){let d=r.slice(p,p+200),h=d[0]?.title??"";c.push({groupId:`events:${Qr()}`,until:i,eventIds:d.map(m=>m.id),by:t.by??"agent",reason:o,title:d.length===1?h:`${d.length} errors \u2014 ${h}`})}return{drafts:c,items:r,notFound:[...n].filter(p=>!a.has(p))}}l(Q_,"$q"),u(Q_,"planDismissal");async function Y_(e,t){let s;try{s=await e.read(gK)}catch{s=void 0}let n=s?.dismissals,r=(Array.isArray(n)?n:[]).flatMap(c=>{let p=c;return p&&typeof p.id=="string"?[{id:p.id,eventIds:Array.isArray(p.eventIds)?p.eventIds.filter(d=>typeof d=="string"):[]}]:[]});if(t.all)return{keys:r.map(c=>c.id),notFound:[]};let i=[...new Set(t.ids??[])],a=new Set,o=[];for(let c of i){let p=r.filter(d=>d.id===c||d.eventIds.includes(c));p.length===0&&o.push(c);for(let d of p)a.add(d.id)}return{keys:[...a],notFound:o}}l(Y_,"_q"),u(Y_,"planRestore");var vK="Hidden, not fixed. Each of these shows again the next time it happens, and runtime://dismissed lists what is hidden, by whom and why.";import{PublicMcpError as qb}from"@frontmcp/sdk";var Wt=u(e=>new qb(e,"UNAVAILABLE",503),"unavailable"),Bn=u(e=>new qb(e,"NOT_FOUND",404),"notFound"),Na=u(e=>new qb(e,"REFUSED",409),"refused");function zp(e){let t=typeof e.error=="string"&&e.error.trim()?e.error.trim():"the lensmcp CLI gave no reason",s=typeof e.answer=="string"&&e.answer.trim()?e.answer.trim():void 0,n=e.identities;return Array.isArray(n)?n.length?Bn(`${t} Who signed in (most recent first): ${nn(n.map(X_))}. Name one with \`as\` (and \`tenant\`).`):Wt(s??t):Array.isArray(e.workspaces)?Bn(s??`${t} \u2014 workspaces the gateway serves: ${nn(e.workspaces)||"none"}.`):Array.isArray(e.services)?Bn(s??`${t} \u2014 its services: ${nn(e.services)||"none"}.`):typeof e.flowId=="string"||yK.test(t)?Wt(s??t):Na(s??t)}l(zp,"oc"),u(zp,"cliFailure");function Wp(e){let t=typeof e.error=="string"&&e.error.trim()?e.error.trim():"the lensmcp CLI gave no reason",s=Array.isArray(e.uncommitted)?` Uncommitted: ${nn(e.uncommitted)}.`:"",n=typeof e.logTail=="string"&&e.logTail.trim()&&e.logTail.trim()!==t?`
194
194
  ${e.logTail.trim()}`:"",r=typeof e.log=="string"?`
195
195
  Its log: ${e.log}.`:"",i=typeof e.next=="string"?` ${e.next}`:"",a=`${t}${s}${n}${r}${i}`;return/^No worktree '/.test(t)?Bn(a):/^lensmcp instance list failed|^could not start `lensmcp instance create`|has not started yet/.test(t)?Wt(a):Na(a)}l(Wp,"ic"),u(Wp,"worktreeFailure");var yK=/no gateway answers|LENSMCP_GW_ACT=0|predates `lensmcp call`|cannot restart a service|the gateway is stopping|exited (?:by a signal|-?\d+)$/;function nn(e,t=20){return`${e.slice(0,t).map(s=>typeof s=="string"?s:JSON.stringify(s)).join(", ")}${e.length>t?`, \u2026 ${e.length-t} more`:""}`}l(nn,"hr"),u(nn,"listed");function X_(e){let t=e&&typeof e=="object"?e:{},s=typeof t.user=="string"?t.user:"?",n=[t.email,t.name,typeof t.tenant=="string"?`tenant ${t.tenant}`:void 0].filter(r=>typeof r=="string"&&!!r);return n.length?`${s} (${n.join(", ")})`:s}l(X_,"_X"),u(X_,"identityLine");import{z as nt}from"@frontmcp/sdk";var wK={ids:nt.array(nt.string().min(1)).max(Fp.maxIds).optional().describe("The `ids` of a failure observe_errors lists (kind `runtime`)."),all:nt.boolean().optional().describe("Every runtime error now listed."),reason:nt.string().min(Fp.minReasonChars).describe("Why they are not a problem to fix \u2014 shown to the person in the dashboard."),by:nt.enum(["agent","cli"]).default("agent").describe("Leave as 'agent'.")},bK=nt.object({dismissed:nt.number(),items:nt.array(nt.object({id:nt.string(),title:nt.string(),resource:nt.string()}).passthrough()),notFound:nt.array(nt.string()),note:nt.string()}).passthrough(),kK={ids:nt.array(nt.string().min(1)).max(Cb.maxIds).optional().describe("Dismissal ids from runtime://dismissed, or ids of entries a dismissal hid."),all:nt.boolean().optional().describe("Undo every dismissal in effect.")},$K=nt.object({restored:nt.number(),notFound:nt.array(nt.string()),note:nt.string()}).passthrough(),jb=class extends iK{static{l(this,"k_")}static{u(this,"ObserveDismissErrorsTool")}async execute(e){!e.all&&!e.ids?.length&&this.fail(Na("Nothing named: pass `ids` (from observe_errors, kind runtime) or `all: true`."));let t=this.get(X),s=this.get(Wu),n=await Q_(t,e);!e.all&&!n.items.length&&this.fail(Bn(`Nothing was dismissed: none of those ids is in a runtime error list right now (${nn(n.notFound)}) \u2014 observe_errors { kind: "runtime" } lists them.`));let r=n.drafts.map(a=>Mb(a,s.id)),i=process.env.LENSMCP_EVENT_FILE;if(i)Up(i,r);else for(let a of r)this.get(Hu).publish(a);return{dismissed:n.items.length,items:n.items.map(a=>({...a})),notFound:n.notFound,note:n.items.length?vK:"Nothing was dismissed: no runtime error is listed right now."}}};jb=P([nK({name:Fp.name,description:Fp.description,inputSchema:wK,outputSchema:bK})],jb);var xK=jb;import{Tool as EK,ToolContext as SK}from"@frontmcp/sdk";var Rb=class extends SK{static{l(this,"x_")}static{u(this,"ObserveRestoreErrorsTool")}async execute(e){!e.all&&!e.ids?.length&&this.fail(Na("Nothing named: pass dismissal `ids` (from runtime://dismissed) or `all: true`."));let t=this.get(X),s=this.get(Wu),n=await Y_(t,e);!e.all&&!n.keys.length&&this.fail(Bn(`Nothing was restored: no dismissal matches ${nn(n.notFound)} \u2014 runtime://dismissed lists the dismissals in effect.`));let r=Date.now(),i=n.keys.map(o=>Bb(o,s.id,r)),a=process.env.LENSMCP_EVENT_FILE;if(a)Up(a,i);else for(let o of i)this.get(Hu).publish(o);return{restored:n.keys.length,notFound:n.notFound,note:n.keys.length?"Restored: what those dismissals hid is listed and counted again.":"Nothing was restored: no dismissal is in effect."}}};Rb=P([EK({name:Cb.name,description:Cb.description,inputSchema:kK,outputSchema:$K})],Rb);var AK=Rb;import{statSync as CK}from"node:fs";import{resolve as eM,sep as IK}from"node:path";import{Tool as DK,ToolContext as TK}from"@frontmcp/sdk";var tM="process://cluster/built-files",_K={"service-starting":"starting","service-respawn":"starting","lens-app-up":"starting","service-up":"up","cold-start":"up","service-down":"down","idle-kill":"idle","service-recycle":"wedged","pod-recycle":"wedged","service-crash-loop":"crash-looping","lens-handoff-complete":"up","gateway-up":"up","gateway-down":"down","lens-child-starting":"starting","lens-child-up":"up","lens-child-exit":"down"},MK=50,BK=new Set(["service-respawn","service-recycle","pod-recycle","lens-handoff-complete"]),sM=new Set(["build","types","process"]),rM=u(e=>sM.has(e)?e:"unknown","faultOf"),qK=class{static{l(this,"Ol")}static{u(this,"ClusterHealth")}constructor(){this.services=new Map,this.errors=[],this.incidents=[],this.typechecked=new Set,this.typecheckOf=new Map,this.built=new Map,this.workers=new Map}builtFiles(e){let t={};for(let[s,n]of this.built)(e===void 0||s===e)&&(t[s]=Object.fromEntries(n));return t}noteBuilt(e,t,s){let n=this.built.get(e);n||this.built.set(e,n=new Map);for(let r of t){let i=s(n.get(r));n.delete(r),n.set(r,i)}for(;n.size>500;)n.delete(n.keys().next().value)}ingest(e){if(e.category==="typecheck")return this.noteTypecheck(e);if(e.source!=="gateway"||e.category!=="cluster")return!1;let t=this.pruneIncidents(e.timestamp),s=e.raw??{},n=typeof s.kind=="string"?s.kind:void 0;if(!n)return t;let r=typeof s.project=="string"?s.project:void 0;if(!r)return t;if(n.startsWith("worker-"))return this.noteWorker(n,r,e)||t;if(n==="pod-evicted"||n==="request-gave-up"){let o=e.raw,c=u(h=>typeof o[h]=="string"?o[h]:void 0,"str"),p=u(h=>typeof o[h]=="number"&&Number.isFinite(o[h])?o[h]:void 0,"num"),d={project:r,timestamp:e.timestamp,kind:n,pod:c("pod")??"?",status:p("status")??(n==="pod-evicted"?502:504),reason:c("reason")??e.title};for(let h of["traceId","method","path","failure"]){let m=c(h);m&&(d[h]=m)}for(let h of["heldMs","silentMs","probes"]){let m=p(h);m!==void 0&&(d[h]=m)}return this.incidents.push(d),this.incidents.length>30&&this.incidents.splice(0,this.incidents.length-30),!0}if(n==="service-error"){let o=rM(s.fault),c=this.touch(r,e.timestamp);if(c.faults.add(o),c.lastTitle=e.title,o==="types"&&this.typechecked.has(r))return!0;let p=typeof s.line=="string"?s.line:e.message??e.title;return this.errors.push({project:r,timestamp:e.timestamp,line:p,fingerprint:e.fingerprint,fault:o}),this.errors.length>50&&this.errors.splice(0,this.errors.length-50),!0}if(n==="service-fault-closed"){let o=this.services.get(r),c=Array.isArray(s.closed)?s.closed.filter(p=>sM.has(p)).map(rM):[];return!o||c.length===0?t:(o.lastSeenAt=e.timestamp,o.lastTitle=e.title,this.resolve(o,c),!0)}if(n==="service-recovered"){let o=this.services.get(r);return o?(o.lastSeenAt=e.timestamp,this.resolve(o),o.lastTitle=e.title,!0):t}if(n==="lens-handoff-start"){let o=this.touch(r,e.timestamp);return s.oldServing!==!0&&(o.state="starting"),o.lastTitle=e.title,!0}if(n==="lens-handoff-failed"){let o=this.touch(r,e.timestamp);return s.oldKept!==!0&&(o.state="down"),o.lastTitle=e.title,!0}if(n==="service-build"||n==="service-swap"){let o=e.raw,c=u(g=>typeof g=="number"&&Number.isFinite(g)?g:void 0,"num"),p=Array.isArray(o.changedFiles)?o.changedFiles.filter(g=>typeof g=="string").slice(0,MK):[],d=c(o.moreChanged),h=this.services.get(r)??this.touch(r,e.timestamp,"up"),m=h.serving??{compiling:!1},f=c(o.podGeneration);if(f!==void 0&&m.podGeneration!==void 0&&f<m.podGeneration)return t;if(m.heardAt=e.timestamp,n==="service-build"){let g=c(o.startedAt)??e.timestamp;if(o.phase==="failed"){m.compiling=!1,m.lastCompile={startedAt:g,endedAt:c(o.endedAt)??e.timestamp,ok:!1,changedFiles:p,...d?{moreChanged:d}:{}};let y=m.lastCompile.endedAt;this.noteBuilt(r,p,w=>({...w,failedAt:y}))}else m.compiling=!0,m.lastCompile={startedAt:g,changedFiles:p,...d?{moreChanged:d}:{}}}else{let g=o.compile??{};m.compiling=!1;for(let w of["generation","swaps","podGeneration","swapMs","draining"]){let b=c(o[w]);b!==void 0&&(m[w]=b)}m.swappedAt=c(o.swappedAt)??e.timestamp;let y=c(g.startedAt);if(y!==void 0){m.lastCompile={startedAt:y,...c(g.endedAt)!==void 0?{endedAt:c(g.endedAt)}:{},ok:!0,changedFiles:p,...d?{moreChanged:d}:{}};let w=m.swappedAt;this.noteBuilt(r,p,()=>({builtAt:y,swappedAt:w}))}else delete m.lastCompile}let v=this.typecheckOf.get(r);return v&&(m.typecheck=v),h.serving=m,!0}if(n==="pod-handoff-complete"){let o=this.services.get(r);if(!o?.serving)return t;let c=e.raw,p=typeof c.generation=="number"&&Number.isFinite(c.generation)?c.generation:void 0,{compiling:d,lastCompile:h,typecheck:m}=o.serving;return o.serving={compiling:d,...p!==void 0?{podGeneration:p}:{},treeSince:e.timestamp,...h?{lastCompile:h}:{},...m?{typecheck:m}:{},heardAt:e.timestamp},!0}let i=_K[n];if(!i)return t;let a=this.touch(r,e.timestamp);if(n==="service-starting"||n==="service-respawn"){let o=a.serving?.typecheck;a.serving={compiling:!1,treeSince:e.timestamp,...o?{typecheck:o}:{},heardAt:e.timestamp},this.built.delete(r)}if(a.state=i,a.lastTitle=e.title,BK.has(n)&&(a.restarts+=1),i==="down"||i==="idle")for(let o of this.workers.get(r)?.values()??[])o.state!=="stopped"&&(o.state="stopped",o.since=e.timestamp,o.reason=i==="idle"?"its service was scaled to zero":"its service is down",delete o.nextAt,delete o.inARow);return i==="up"&&this.resolve(a),!0}noteWorker(e,t,s){let n=s.raw??{},r=typeof n.worker=="string"?n.worker:"";if(!r)return!1;let i=u(p=>typeof p=="number"&&Number.isFinite(p)?p:void 0,"num"),a=i(n.pid);e!=="worker-exited"&&e!=="worker-stopped"&&!this.services.has(t)&&this.touch(t,s.timestamp,"up");let o=this.workers.get(t);o||(this.workers.size>=100&&this.workers.delete(this.workers.keys().next().value),this.workers.set(t,o=new Map));let c=o.get(r);if(e==="worker-started"){if(!c){if(o.size>=16)return!1;o.set(r,c={project:t,name:r,state:"running",since:s.timestamp,crashes:0})}return c.state="running",c.since=s.timestamp,a!==void 0&&(c.pid=a),delete c.nextAt,delete c.reason,n.why!=="respawn"&&delete c.inARow,!0}if(c&&c.state==="running"&&a!==void 0&&c.pid!==void 0&&a!==c.pid)return!1;if(!c){if(o.size>=16)return!1;o.set(r,c={project:t,name:r,state:"running",since:s.timestamp,crashes:0})}if(a!==void 0&&a>0&&(c.pid=a),e==="worker-up")return c.state="running",delete c.inARow,delete c.nextAt,!0;if(e==="worker-crashed"){let p=i(n.crashes)??1;c.state=n.crashLooping===!0||p>=3?"crash-looping":"restarting",c.since=s.timestamp,c.crashes+=1,c.inARow=p;let d=i(n.nextInMs);d!==void 0?c.nextAt=s.timestamp+d:delete c.nextAt,delete c.reason;let h=Array.isArray(n.lines)?n.lines.filter(m=>typeof m=="string").slice(-12):[];return c.lastCrash={at:s.timestamp,exitCode:i(n.exitCode)??null,signal:typeof n.signal=="string"?n.signal:null,...typeof n.reading=="string"?{reading:n.reading}:{},...n.external===!0?{external:!0}:{},lines:h},!0}return e==="worker-exited"||e==="worker-stopped"?(c.state=e==="worker-exited"?"exited":"stopped",c.since=s.timestamp,c.reason=typeof n.reason=="string"?n.reason:e==="worker-exited"?"it ended on its own (code 0)":"its devserver stopped",delete c.nextAt,delete c.inARow,!0):!1}pruneIncidents(e){if(this.incidents.length===0||e-this.incidents[0].timestamp<=9e5)return!1;let t=this.incidents.filter(s=>e-s.timestamp<=9e5);return this.incidents.splice(0,this.incidents.length,...t),!0}resolve(e,t){if(t)for(let n of t)e.faults.delete(n);else e.faults.clear();let s=u(n=>n.project===e.project&&(!t||t.includes(n.fault)),"gone");this.errors.splice(0,this.errors.length,...this.errors.filter(n=>!s(n)))}noteTypecheck(e){let t=e.raw??{};if(t.kind!=="typecheck-run"||t.phase!=="end"||typeof t.project!="string")return!1;let s=t.project,n=t.status==="clean"||t.status==="failing",r=!1;if(n&&typeof t.errorCount=="number"){let i={errors:t.errorCount,at:e.timestamp};this.typecheckOf.size>=100&&!this.typecheckOf.has(s)&&this.typecheckOf.delete(this.typecheckOf.keys().next().value),this.typecheckOf.set(s,i);let a=this.services.get(s);a?.serving&&(a.serving.typecheck=i,r=!0)}return n===this.typechecked.has(s)?r:n===this.typechecked.has(s)?!1:(n?(this.typechecked.size>=100&&this.typechecked.delete(this.typechecked.values().next().value),this.typechecked.add(s),this.errors.splice(0,this.errors.length,...this.errors.filter(i=>!(i.project===s&&i.fault==="types")))):this.typechecked.delete(s),(this.services.get(s)?.faults.has("types")??!1)||r)}snapshot(){let e=[...this.services.values()].sort((s,n)=>s.project.localeCompare(n.project)).map(({faults:s,...n})=>{let r=this.workersOf(n.project);return{...n,buildFailed:s.has("build")||s.has("process")||s.has("unknown"),typeErrors:s.has("types")&&!this.typechecked.has(n.project),...r.length?{workers:r}:{}}}),t=u(s=>e.filter(n=>n.state===s).map(n=>n.project),"byState");return{services:e,up:t("up"),down:t("down"),wedged:t("wedged"),crashLooping:t("crash-looping"),idle:t("idle"),buildFailed:e.filter(s=>s.buildFailed).map(s=>s.project),typeErrors:e.filter(s=>s.typeErrors).map(s=>s.project),restarts:e.reduce((s,n)=>s+n.restarts,0),errors:this.errors.slice(),incidents:this.incidents.slice(),workersDown:[...this.workers.keys()].sort().flatMap(s=>this.workersOf(s)).filter(s=>s.state!=="running"&&s.state!=="stopped")}}workersOf(e){return[...this.workers.get(e)?.values()??[]].sort((t,s)=>t.name.localeCompare(s.name)).map(t=>({...t,...t.lastCrash?{lastCrash:{...t.lastCrash,lines:[...t.lastCrash.lines]}}:{}}))}touch(e,t,s="starting"){let n=this.services.get(e);if(!n){if(this.services.size>=100){let r;for(let i of this.services.values())(!r||i.lastSeenAt<r.lastSeenAt)&&(r=i);r&&this.services.delete(r.project)}n={project:e,state:s,restarts:0,faults:new Set,lastTitle:"",lastSeenAt:t},this.services.set(e,n)}return n.lastSeenAt=t,n}},jK=2e4,RK=55e3,nM=200,an=u((e,t)=>{let s=Math.max(0,Math.round((t-e)/1e3));return s<90?`${s}s ago`:s<5400?`${Math.round(s/60)}m ago`:`${Math.round(s/3600)}h ago`},"ago"),Ob=u(e=>{let t=e.changedFiles.length+(e.moreChanged??0);if(t===0)return"no source change";let s=e.changedFiles.slice(0,3).join(", ");return`${t} file${t===1?"":"s"}: ${s}${t>3?", \u2026":""}`},"files");function iM(e,t){let s=(e.workers??[]).filter(n=>n.state!=="running"&&n.state!=="stopped");if(s.length)return s.map(n=>{if(n.state==="exited")return`its worker ${n.name} is NOT RUNNING \u2014 ${n.reason??"it ended"}; it starts again at the next build`;let r=n.nextAt!==void 0?`; next start ${n.nextAt>t?`in ${Math.max(1,Math.round((n.nextAt-t)/1e3))}s`:"due now"}`:"",i=n.state==="crash-looping"?`is CRASH-LOOPING (${n.inARow??"?"} crashes in a row)`:"CRASHED and is being started again";return`its worker ${n.name} ${i}${r} \u2014 nothing consumes its queues meanwhile`}).join("; ")}l(iM,"jX"),u(iM,"workersClause");function aM(e,t){let s=e.serving,n=iM(e,t);if(!s)return`${e.project} is ${e.state}; its devserver has reported no build and no swap to this session \u2014 it serves the build it started with (a devserver that predates the report says nothing either)${n?`; ${n}`:""}.`;let r=[];return s.swappedAt!==void 0?r.push(`serving generation ${s.generation??"?"} since ${an(s.swappedAt,t)}${s.lastCompile?.ok?`, after a build that changed ${Ob(s.lastCompile)}`:""}`):s.treeSince!==void 0?r.push(`a new pod tree${s.podGeneration!==void 0?` (g${s.podGeneration})`:""} took over ${an(s.treeSince,t)} and has swapped nothing since \u2014 it serves the build it started with`):r.push("no swap seen since it started \u2014 it serves the build it started with"),s.compiling&&s.lastCompile?r.push(`a build is RUNNING (started ${an(s.lastCompile.startedAt,t)}, for ${Ob(s.lastCompile)}) \u2014 what it serves is about to change`):s.lastCompile?.ok===!1&&r.push(`the last build FAILED ${an(s.lastCompile.endedAt??s.lastCompile.startedAt,t)} (for ${Ob(s.lastCompile)}) \u2014 nothing was swapped`),s.draining&&r.push(`${s.draining} replaced app${s.draining===1?"":"s"} still finishing work`),s.typecheck&&s.typecheck.errors>0&&r.push(`its type check has ${s.typecheck.errors} error${s.typecheck.errors===1?"":"s"}`),n&&r.push(n),`${e.project} is ${e.state}: ${r.join("; ")}.`}l(aM,"PX"),u(aM,"sentence");function oM(e,t,s,n,r,i){let a=e.serving,o=t.replace(/\\/g,"/").replace(/^\.\//,""),c=u(w=>w===o||w.endsWith(`/${o}`)||o.endsWith(`/${w}`),"matches"),p=u(w=>!!w&&w.changedFiles.some(c),"inBuild"),d=u((w,b)=>({file:t,landed:w,why:b}),"said");if(!a||a.swappedAt===void 0&&a.treeSince===void 0)return d("unknown","no swap that names its files has been reported for this service");if(a.compiling)return d(!1,p(a.lastCompile)?"a build that includes it is running \u2014 not swapped yet":"a build is running \u2014 not swapped yet");if(a.lastCompile?.ok===!1)return d(!1,p(a.lastCompile)?"the build that included it FAILED \u2014 the pod serves the build before it":"the last build failed");let h=Math.max(a.swappedAt??0,a.treeSince??0);if(s!==void 0&&h<s)return d(!1,a.swappedAt!==void 0&&a.swappedAt>=(a.treeSince??0)?"the last swap is older than your change":"its pod tree took over before your change, and nothing has swapped since");if(a.lastCompile&&p(a.lastCompile))return d(!0,a.swappedAt!==void 0&&a.swappedAt>=(a.treeSince??0)?`generation ${a.generation??"?"} was built from it`:"its pod tree started from the bundle the build that named it wrote");let m=Object.keys(n).filter(c),f=m.length===1?m[0]:m.find(w=>w===o),v=f!==void 0?n[f]:void 0;if(f!==void 0&&v){if(v.failedAt!==void 0&&v.failedAt>h)return d(!1,"a build that named it FAILED, and nothing has been swapped since \u2014 its newest contents are in no bundle");if(v.builtAt===void 0)return d("unknown","the only build this session saw name it failed; a build since then succeeded with it in it, if it is in this service's bundle");if(s!==void 0&&v.builtAt<s)return d(!1,"no build since your change has named it \u2014 the watcher has not woken for it yet, or it is not in this service's bundle");let w=r?.(f);return w!==void 0&&w>v.builtAt?d(!1,`it changed on disk ${an(w,i)}, after the last build that named it (${an(v.builtAt,i)}), and no build has named it since \u2014 the watcher has not woken for it yet`):d(!0,`built ${an(v.builtAt,i)} by a build that was swapped in${v.swappedAt!==void 0?` ${an(v.swappedAt,i)}`:""}; the builds since changed other files and carry it`)}if(m.length>1)return d("unknown",`${m.length} files this service built end in that \u2014 name more of its path`);if(a.lastCompile&&(a.lastCompile.moreChanged??0)>0)return d("unknown",`the serving build names ${a.lastCompile.changedFiles.length} of its ${a.lastCompile.changedFiles.length+(a.lastCompile.moreChanged??0)} files, and this is not among those named`);let g=r?.(o),y=a.lastCompile?.startedAt??a.treeSince;return g!==void 0&&y!==void 0&&g>y?d(!1,`it changed on disk ${an(g,i)}, after the serving build started, and no build has named it since \u2014 the watcher has not woken for it yet, or it is not in this service's bundle`):d("unknown","no build this session has seen named it \u2014 the serving build carries it as it was when that build started if it is in this service's bundle at all, which this session cannot tell")}l(oM,"LX"),u(oM,"landed");async function uM(e,t){try{return(await e.read(tM))?.[t]??{}}catch{return{}}}l(uM,"qX"),u(uM,"builtFiles");async function Nb(e){try{let t=await e.read("process://cluster");return t&&Array.isArray(t.services)?t:void 0}catch{return}}l(Nb,"Nq"),u(Nb,"cluster");async function lM(e,t,s={}){let n=s.now??Date.now,r=s.sleep??(d=>new Promise(h=>setTimeout(h,d))),i=await Nb(e);if(!i)return{found:!1,reason:"no dev cluster has reported into this session \u2014 nothing is watching the services (run them under the dev cluster)"};if(!t.service)return{found:!0,services:i.services.map(d=>({service:d.project,state:d.state,...d.serving?.generation!==void 0?{generation:d.serving.generation}:{},...d.serving?.swappedAt!==void 0?{swappedAt:d.serving.swappedAt}:{},compiling:d.serving?.compiling??!1,said:d.serving?.swappedAt!==void 0||d.serving?.lastCompile!==void 0,...(d.workers??[]).some(h=>h.state!=="running"&&h.state!=="stopped")?{workersDown:(d.workers??[]).filter(h=>h.state!=="running"&&h.state!=="stopped").map(h=>`${h.name}: ${h.state}`)}:{}})),hint:"Pass `service` for one service's builds and files; `said: false` is a service whose devserver has reported no build or swap yet."};let a=u(()=>i?.services.find(d=>d.project===t.service),"find"),o=a();if(!o)return{found:!1,service:t.service,reason:"no service of that name has reported \u2014 it is the Nx project name",services:i.services.map(d=>d.project)};let c;if(t.awaitSwapAfter!==void 0){let d=t.awaitSwapAfter,h=Math.min(RK,Math.max(0,t.timeoutMs??jK)),m=n(),f=u(g=>{let y=g?.serving;if(y){if(y.swappedAt!==void 0&&y.swappedAt>d&&!y.compiling)return"swapped";if(y.lastCompile?.ok===!1&&(y.lastCompile.endedAt??0)>d)return"build-failed"}},"settled"),v=f(o);for(let g=Math.ceil(h/nM);!v&&g>0&&n()-m<h;g--)await r(nM),i=await Nb(e)??i,o=a()??o,v=f(o);c={outcome:v??"timeout",ms:n()-m}}let p=n();return{found:!0,service:o.project,state:o.state,...o.buildFailed?{buildFailed:!0}:{},...o.serving?{serving:o.serving}:{},...o.workers?.length?{workers:o.workers}:{},...t.file?{edit:oM(o,t.file,t.awaitSwapAfter,await uM(e,o.project),s.mtimeOf,p)}:{},...c?{waited:c}:{},answer:aM(o,p)}}l(lM,"E_"),u(lM,"readServiceState");import{z as he}from"@frontmcp/sdk";var OK=he.object({startedAt:he.number(),endedAt:he.number().optional(),ok:he.boolean().optional(),changedFiles:he.array(he.string()),moreChanged:he.number().optional()}).passthrough(),NK={service:he.string().min(1).optional().describe('The service \u2014 its Nx project name, e.g. "assistant". Omit to list every service.'),file:he.string().min(1).optional().describe("A file you changed \u2014 a workspace-relative path, or the end of one. The answer says whether the build being served was built from it (`edit.landed`)."),awaitSwapAfter:he.number().int().positive().optional().describe("Wait until the service has swapped AFTER this time (epoch milliseconds \u2014 when you saved the file), or its build has failed."),timeoutMs:he.number().int().positive().max(ol.maxAwaitMs).optional().describe(`With \`awaitSwapAfter\`: how long to wait at most (default ${ol.defaultAwaitMs} ms, at most ${ol.maxAwaitMs}).`)},PK=he.object({services:he.array(he.object({service:he.string(),state:he.string(),generation:he.number().optional(),swappedAt:he.number().optional(),compiling:he.boolean(),said:he.boolean(),workersDown:he.array(he.string()).optional()}).passthrough()).optional(),hint:he.string().optional(),service:he.string().optional(),state:he.string().optional(),buildFailed:he.boolean().optional(),serving:he.object({generation:he.number().optional(),swaps:he.number().optional(),podGeneration:he.number().optional(),treeSince:he.number().optional(),swappedAt:he.number().optional(),swapMs:he.number().optional(),draining:he.number().optional(),compiling:he.boolean(),lastCompile:OK.optional(),typecheck:he.object({errors:he.number(),at:he.number()}).passthrough().optional(),heardAt:he.number().optional()}).passthrough().optional(),workers:he.array(he.object({project:he.string(),name:he.string(),state:he.string()}).passthrough()).optional(),edit:he.object({file:he.string(),landed:he.union([he.boolean(),he.literal("unknown")]),why:he.string()}).passthrough().optional(),waited:he.object({outcome:he.string(),ms:he.number()}).passthrough().optional(),answer:he.string().optional()}).passthrough(),Pb=class extends TK{static{l(this,"A_")}static{u(this,"ServiceStateTool")}async execute(e){let t=await lM(this.get(X),e,{mtimeOf:dM});t.found||("services"in t&&this.fail(Bn(`no service '${t.service}' has reported \u2014 it is the Nx project name. Services: ${nn(t.services??[])||"none"}.`)),this.fail(Wt(t.reason)));let{found:s,...n}=t;return n}};Pb=P([DK({name:ol.name,description:ol.description,annotations:{readOnlyHint:!0},inputSchema:NK,outputSchema:PK})],Pb);var LK=Pb;function dM(e){let t=eM(process.env.LENSMCP_WORKSPACE_ROOT??process.cwd()),s=eM(t,e);if(s.startsWith(t+IK))try{return CK(s).mtimeMs}catch{return}}l(dM,"HX"),u(dM,"workspaceMtime");import{Tool as FK,ToolContext as UK}from"@frontmcp/sdk";import{spawn as cM}from"node:child_process";import{closeSync as zK,existsSync as pM,mkdirSync as WK,openSync as HK,readFileSync as hM,realpathSync as GK,statSync as ZK}from"node:fs";import{homedir as VK}from"node:os";import{dirname as Lb,join as Ci,resolve as mM}from"node:path";var JK="lensmcp/switch",KK="lensmcp/replay",Fb=/^[a-z0-9](?:[a-z0-9-]{0,18}[a-z0-9])?$/,QK=45e3;function Ub(e){try{let t=JSON.parse(hM(e,"utf8"));return t&&typeof t=="object"?t:void 0}catch{return}}l(Ub,"Gq"),u(Ub,"readJson");function fM(e=process.env,t=process.cwd()){let s=mM(e.LENSMCP_WORKSPACE_ROOT??t),n=Ub(Ci(s,".lensmcp","config.json")),r=typeof n?.key=="string"?n.key:e.LENSMCP_WORKSPACE_KEY;if(!r)return;let i=n?.instance;return typeof i?.name=="string"&&typeof i.baseKey=="string"&&r===`${i.baseKey}-${i.name}`?{root:s,key:r,baseKey:i.baseKey,mainRoot:typeof i.mainRoot=="string"?i.mainRoot:s,instance:i.name}:{root:s,key:r,baseKey:r,mainRoot:s}}l(fM,"Vq"),u(fM,"servedWorkspace");function gM(e,t,s){let n=e.LENSMCP_CLI;if(n)return pM(n)?n:void 0;let r=[];if(t){let i=mM(t),a=i;try{a=GK(i)}catch{}for(let o of new Set([i,a])){let c=Lb(Lb(o));r.push(Ci(c,"bin.js"),Ci(c,"dist","bin.js"))}}return r.push(Ci(s,"node_modules","lensmcp","bin.js"),Ci(s,"node_modules","lensmcp","dist","bin.js")),r.find(i=>pM(i))}l(gM,"Kq"),u(gM,"findCli");function vM(e){let t={...e};for(let s of["LENSMCP_EVENT_FILE","LENSMCP_PORT","LENSMCP_TRANSPORT","LENSMCP_PROCESS_ROLE","LENSMCP_WORKSPACE_KEY","LENSMCP_WORKSPACE_ROOT","LENSMCP_MCP_MODE","LENSMCP_DASHBOARD_BASE","LENSMCP_GATEWAY_PORTS","LENSMCP_SHARED_OWNER","LENSMCP_PARENT_PID"])delete t[s];return t}l(vM,"XX"),u(vM,"cliEnv");function yM(e,t,s=process.env){let n=vM(s);return{ws:e,home:s.LENSMCP_HOME||VK(),run:u((r,i)=>new Promise(a=>{let o=cM(process.execPath,[t,...r],{cwd:i?.cwd??e.root,env:n,stdio:["ignore","pipe","pipe"]}),c="",p="";o.stdout.on("data",h=>c+=h.toString()),o.stderr.on("data",h=>p+=h.toString());let d=setTimeout(()=>o.kill("SIGTERM"),i?.timeoutMs??6e4);o.on("error",h=>{clearTimeout(d),a({code:null,stdout:c,stderr:p+h.message})}),o.on("close",h=>{clearTimeout(d),a({code:h,stdout:c,stderr:p})})}),"run"),spawnDetached:u((r,i)=>{WK(Lb(i.log),{recursive:!0,mode:448});let a=HK(i.log,"a",384);try{let o=cM(process.execPath,[t,...r],{cwd:i.cwd,env:{...n,LENSMCP_CREATE_LOG:i.log},stdio:["ignore",a,a],detached:!0});return o.on("error",()=>{}),o.unref(),o.pid}finally{zK(a)}},"spawnDetached"),now:u(()=>Date.now(),"now"),sleep:u(r=>new Promise(i=>setTimeout(i,r)),"sleep"),alive:u(r=>{try{return process.kill(r,0),!0}catch(i){return i.code==="EPERM"}},"alive")}}l(yM,"Zq"),u(yM,"defaultDeps");var wM=u(e=>`https://lensmcp.local/${e}/`,"dashboardOf");function zb(e,t,s){let n=e.progress?.state??(t?"running":e.folderGone?"folder-gone":"stopped");return{name:e.instance??e.name??e.key,key:e.key,root:e.root??"",state:n,active:e.key===s,...e.branch?{branch:e.branch}:{},...typeof e.changes=="number"?{changes:e.changes}:{},...e.frozen?{frozen:!0}:{},...e.apex?{apex:e.apex}:{},...e.hosts&&Object.keys(e.hosts).length?{hosts:e.hosts}:{},dashboard:wM(e.key),...typeof e.services=="number"?{services:e.services}:{},createdByLens:!!e.worktree,...e.progress?.detail?{detail:e.progress.detail}:{}}}l(zb,"Uq"),u(zb,"viewOf");async function Hp(e){let{ws:t}=e,s=await e.run(["instance","list","--json",`--base=${t.baseKey}`],{cwd:t.mainRoot,timeoutMs:3e4}),n;try{n=JSON.parse(s.stdout)}catch{return{error:`lensmcp instance list failed (exit ${s.code}): ${s.stderr.trim()||s.stdout.trim()}`}}let r={...n.checkout?.branch?{branch:n.checkout.branch}:{},...typeof n.checkout?.changes=="number"?{changes:n.checkout.changes}:{}},i=[{name:"main",key:t.baseKey,root:t.mainRoot,state:"running",active:t.key===t.baseKey,...r,dashboard:wM(t.baseKey),createdByLens:!1},...(n.instances??[]).map(a=>zb(a,!0,t.key)),...(n.stopped??[]).map(a=>zb(a,!1,t.key))];return{project:t.baseKey,active:t.instance??"main",worktrees:i,...i.length===1?{note:"No worktrees yet \u2014 worktree_create makes one."}:{}}}l(Hp,"ef"),u(Hp,"listWorktrees");var YK=u((e,t)=>Ci(e,".lensmcp","worktrees",`${t}.json`),"progressPath"),XK=u((e,t)=>Ci(e,".lensmcp","worktrees",`${t}.log`),"logPath"),eQ=u(e=>{try{return ZK(e).size}catch{return 0}},"sizeOf");function Wb(e){let t=Ub(e);return t&&typeof t.state=="string"&&typeof t.pid=="number"?t:void 0}l(Wb,"zq"),u(Wb,"readProgress");function Hb(e,t=0,s=25){try{return hM(e).subarray(t).toString("utf8").trimEnd().split(`
196
196
  `).slice(-s).join(`
197
- `)}catch{return""}}l(Hb,"Qq"),u(Hb,"tail");function Ii(e,t,s,n=!1){return{...e,_meta:{[JK]:{root:t,key:s},...n?{[KK]:!0}:{}}}}l(Ii,"ac"),u(Ii,"switching");async function bM(e,t,s=QK){let{ws:n}=e;if(!Fb.test(t.name))return{ok:!1,error:`'${t.name}' is not a worktree name: one DNS label of at most 20 characters \u2014 lowercase letters, digits and inner hyphens (it becomes part of its hosts).`};let r=`${n.baseKey}-${t.name}`,i=["instance","create",t.name,"--json",...t.detach?["--detach"]:t.branch?[`--branch=${t.branch}`]:[],...t.from?[`--from=${t.from}`]:[],...t.frozen?["--frozen"]:[],...t.prepare===!1?["--no-prepare"]:t.prepare===!0?["--prepare"]:[],`--cwd=${n.mainRoot}`],a=YK(e.home,r),o=XK(e.home,r),c=eQ(o),p=e.spawnDetached(i,{cwd:n.mainRoot,log:o});if(p===void 0)return{ok:!1,error:"could not start `lensmcp instance create`"};let d=e.now()+s,h;for(;;){let m=Wb(a);if(m?.pid===p&&(h=m),h&&(h.state==="ready"||h.state==="failed"))break;if(!e.alive(p)){let f=Wb(a);if(f?.pid===p&&(h=f),!h||h.state!=="ready"&&h.state!=="failed")return{ok:!1,error:Hb(o,c)||"lensmcp instance create ended without a word",log:o};break}if(e.now()>=d)break;await e.sleep(300)}return h?kM(h,o,n,c):{ok:!1,error:"lensmcp instance create has not started yet \u2014 call worktree_list in a moment",log:o}}l(bM,"Xq"),u(bM,"createWorktree");function kM(e,t,s,n=0){let r=e.key.slice(s.baseKey.length+1),i=e.worktree?.path??e.root,a={...e.result??{},name:r,key:e.key,root:e.root,...e.worktree?{worktree:e.worktree}:{},state:e.state},o=e.state==="preparing"||e.state==="ready"||e.state==="failed"&&!!e.result,c=e.worktree?.path?` If your client can move its session into an existing git worktree, do it now (Claude Code: EnterWorktree { path: "${e.worktree.path}" }).`:"",p=`Do this task's work in ${e.root}: edit files there (absolute paths, or cd there first) and run its commands there \u2014 \`lensmcp instance exec -- <cmd>\` gives a command the worktree's own database, queues and hosts. Your edits in ${s.mainRoot} are not in it: it starts from the commit, not the working copy.${c}`;if(e.state==="ready")return Ii({ok:!0,...a,next:`${p} The lens now reports on this worktree \u2014 observe.*, flows and errors are ITS app's. worktree_remove takes it away when the work is committed.`},e.root,e.key);if(e.state==="failed"){let h={ok:!1,...a,error:e.detail??"the create failed",log:t,logTail:Hb(t,n)};return o?Ii({...h,next:`It is served, but not ready: read the log, fix the cause, then \`lensmcp instance start --prepare\` in ${e.root} \u2014 or worktree_remove { name: '${r}', force: true } to drop it.`},e.root,e.key):{...h,next:`worktree_remove { name: '${r}' } takes away what was made.`}}let d={ok:!0,...a,detail:e.detail,log:t,next:`Still ${e.state}${e.detail?` (${e.detail})`:""}. The files are at ${i} \u2014 you can start editing. worktree_list shows when it is ready.`};return o?Ii({...d,next:`${d.next} The lens already reports on this worktree. ${p}`},e.root,e.key):d}l(kM,"nY"),u(kM,"createAnswer");async function $M(e,t){let{ws:s}=e;if(t==="main"||t===s.baseKey)return s.instance?Ii({ok:!0,active:"main",root:s.mainRoot,next:`The lens reports on the main checkout (${s.mainRoot}) again.`},s.mainRoot,s.baseKey):{ok:!0,active:"main",note:"The lens already reports on the main checkout."};let n=await Hp(e);if("error"in n)return{ok:!1,error:n.error};let r=n.worktrees.find(i=>i.name===t||i.key===t);if(!r)return{ok:!1,error:`No worktree '${t}' in ${s.baseKey}: ${n.worktrees.map(i=>i.name).join(", ")}.`};if(r.active)return{ok:!0,active:r.name,note:`The lens already reports on '${r.name}'.`};if(r.state==="folder-gone")return{ok:!1,error:`'${r.name}' has no folder any more \u2014 worktree_remove clears it.`};if(r.state==="creating"||r.state==="provisioning"||r.state==="registering")return{ok:!1,error:`'${r.name}' is still ${r.state} \u2014 try again when worktree_list shows it running.`};if(r.state==="stopped"||r.state==="failed"){let i=await e.run(["instance","start",`--name=${r.name}`,`--cwd=${r.root}`],{cwd:r.root,timeoutMs:12e4});if(i.code!==0)return{ok:!1,error:`could not start '${r.name}': ${i.stderr.trim()||i.stdout.trim()}`}}return Ii({ok:!0,active:r.name,key:r.key,root:r.root,...r.branch?{branch:r.branch}:{},...r.hosts?{hosts:r.hosts}:{},dashboard:r.dashboard,next:`The lens now reports on '${r.name}'. Do its work in ${r.root}.`},r.root,r.key)}l($M,"Yq"),u($M,"switchWorktree");async function xM(e,t){let{ws:s}=e;if(t.name==="main"||t.name===s.baseKey)return{ok:!1,error:"The main checkout is not a worktree \u2014 it cannot be removed."};if(s.instance&&(t.name===s.instance||t.name===s.key))return Ii({ok:!1,retry:!0,note:`Moving the lens back to the main checkout to remove '${s.instance}'.`},s.mainRoot,s.baseKey,!0);let n=await Hp(e);if("error"in n)return{ok:!1,error:n.error};let r=n.worktrees.find(c=>c.name===t.name||c.key===t.name);if(!r||r.name==="main")return{ok:!1,error:`No worktree '${t.name}' in ${s.baseKey}: ${n.worktrees.filter(c=>c.name!=="main").map(c=>c.name).join(", ")||"none"}.`};let i=["instance","rm",r.key,"--json",`--base=${s.baseKey}`,...r.createdByLens?["--worktree"]:[],...t.force?["--force"]:[],...t.keepData?["--keep-data"]:[],...t.deleteBranch?["--delete-branch"]:[],`--cwd=${s.mainRoot}`],a=await e.run(i,{cwd:s.mainRoot,timeoutMs:18e4}),o={};try{o=JSON.parse(a.stdout)}catch{}if(a.code!==0){let c=o.uncommitted;return{ok:!1,name:r.name,...o,error:Array.isArray(c)?`'${r.name}' has uncommitted work \u2014 commit it on its branch first. Pass force: true ONLY if the person said to throw it away.`:a.stderr.trim()||`lensmcp instance rm exited ${a.code}`}}return{ok:!0,name:r.name,...o,...r.createdByLens?{}:{note:`The lens did not make ${r.root}, so the folder stays \u2014 only its instance and data are gone.`}}}l(xM,"eD"),u(xM,"removeWorktree");var EM=45e3,Gb=55e3,SM=new RegExp(`^(?:main|${Fb.source.slice(1,-1)})$`);async function AM(e,t){let s=Math.min(Gb,Math.max(0,t.waitMs??EM)),n=["restart",t.service,"--json","--wait",String(s/1e3),...t.worktree?["--worktree",t.worktree]:[],...t.check?["--status"]:["--reason","asked by an agent (service_restart)",...t.hard?["--hard"]:[]]],r=await e.run(n,{cwd:e.ws.root,timeoutMs:s+15e3}),i;try{let a=JSON.parse(r.stdout);a&&typeof a=="object"&&!Array.isArray(a)&&(i=a)}catch{}if(!i)return{ok:!1,error:(r.stderr||r.stdout).trim().slice(-2e3)||`lensmcp restart exited ${r.code??"by a signal"}`};if(i.done===!1){let a=[`service: '${t.service}'`,...t.worktree?[`worktree: '${t.worktree}'`]:[],"check: true"].join(", ");return{...i,next:`Still restarting. Call service_restart { ${a} } to wait for it \u2014 that starts no second restart.`}}return i}l(AM,"M_"),u(AM,"restartService");function qn(e=process.env){let t=fM(e);if(!t)return{error:"This lens server does not know which workspace it serves (no LENSMCP_WORKSPACE_ROOT and no .lensmcp/config.json)."};let s=gM(e,process.argv[1],t.mainRoot);return s?yM(t,s,e):{error:`The lensmcp CLI was not found beside this server or in ${t.mainRoot}/node_modules \u2014 install lensmcp in the workspace.`}}l(qn,"Hn"),u(qn,"worktreeDeps");import{z as tt}from"@frontmcp/sdk";var tQ={service:tt.string().min(1).describe('The service \u2014 its Nx project name, e.g. "registry".'),worktree:tt.string().regex(SM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves."),hard:tt.boolean().optional().describe("Stop it first, then start it \u2014 nothing serves in between. Default: the old tree serves until the new one answers."),check:tt.boolean().optional().describe("Only follow the latest restart until it settles; start none."),waitMs:tt.number().int().min(0).max(Gb).optional().describe(`How long to wait for it to settle (default ${EM} ms, at most ${Gb}).`)},sQ=tt.object({wsKey:tt.string().optional(),service:tt.string().optional(),state:tt.string().optional(),generation:tt.number().optional(),done:tt.boolean().optional(),joined:tt.boolean().optional(),restart:tt.object({how:tt.string().optional(),reason:tt.string().optional(),startedAt:tt.number().optional(),fromGeneration:tt.number().optional(),done:tt.object({ok:tt.boolean(),at:tt.number().optional(),generation:tt.number().optional(),error:tt.string().optional()}).passthrough().optional()}).passthrough().optional(),answer:tt.string().optional(),next:tt.string().optional()}).passthrough(),Zb=class extends UK{static{l(this,"O_")}static{u(this,"ServiceRestartTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await AM(t,e);s.ok===!1&&s.done!==!0&&this.fail(zp(s));let{ok:n,...r}=s;return r}};Zb=P([FK({name:R_.name,description:R_.description,inputSchema:tQ,outputSchema:sQ})],Zb);var rQ=Zb;import{Tool as nQ,ToolContext as iQ}from"@frontmcp/sdk";var aQ=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"],CM=16*1024,Vb=64*1024,IM=30,DM=SM;function TM(e){if(typeof e=="string")try{return JSON.stringify(JSON.parse(e))}catch{}return JSON.stringify(e??null)}l(TM,"oY"),u(TM,"jsonText");async function Jb(e,t,s,n){let r=await e.run(t,{cwd:e.ws.root,timeoutMs:s});try{let i=JSON.parse(r.stdout);if(i&&typeof i=="object"&&!Array.isArray(i))return i}catch{}return{error:(r.stderr||r.stdout).trim().slice(-2e3)||`${n} exited ${r.code??"by a signal"}`}}l(Jb,"oD"),u(Jb,"said");async function _M(e,t){let s=Math.min(Vb,Math.max(1,Math.round(t.maxBodyBytes??CM))),n=["call",...t.method?[t.method]:[],t.url,"--json",`--max-body=${s}`,`--timeout=${IM}`,...t.body!==void 0?[`--data=${TM(t.body)}`]:[],...Object.entries(t.headers??{}).map(([a,o])=>`--header=${a}: ${o}`),...t.as?[`--as=${t.as}`]:[],...t.tenant?[`--tenant=${t.tenant}`]:[],...t.worktree?[`--worktree=${t.worktree}`]:[]],r=await Jb(e,n,(IM+15)*1e3,"lensmcp call");if("error"in r)return{ok:!1,...r};let i=typeof r.flowId=="string"?r.flowId:void 0;return{...r,...i?{next:`Read what the call did: flow_get { flowId: '${i}' } \u2014 the route, its SQL and its spans. Then db://lint and routes://lint: what to fix about the statements it ran and about the route.`}:{}}}l(_M,"iD"),u(_M,"callApp");async function MM(e,t){let s=await Jb(e,["call","--who","--json",...t.worktree?[`--worktree=${t.worktree}`]:[]],2e4,"lensmcp call --who");return"error"in s?{ok:!1,...s}:s}l(MM,"aD"),u(MM,"listIdentities");import{z as Se}from"@frontmcp/sdk";var BM=Se.object({user:Se.string(),tenant:Se.string().optional(),email:Se.string().optional(),name:Se.string().optional(),roles:Se.array(Se.string()).optional(),host:Se.string().optional(),firstSeenAt:Se.number().optional(),lastSeenAt:Se.number().optional(),mode:Se.string().optional()}).passthrough(),oQ={url:Se.string().regex(/^https:\/\/[^\s/]+\/\S*$/).describe('The full URL on a host the dev gateway serves, e.g. "https://api.foodguard.localhost/registry/v1/business-profile/situation-state".'),method:Se.enum(aQ).optional().describe("Default GET; POST when a `body` is given."),body:Se.unknown().optional().describe("The JSON body \u2014 any JSON value (a string holding JSON text is sent as that JSON)."),headers:Se.record(Se.string(),Se.string()).optional().describe("Request headers beyond the defaults. Not `authorization`: the call says who you are."),as:Se.string().min(1).optional().describe("Whom to act as: a user id, email or name from app_identities. Default: the person seen most recently."),tenant:Se.string().min(1).optional().describe("Act in this tenant (a user in several)."),worktree:Se.string().regex(DM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves."),maxBodyBytes:Se.number().int().min(1).max(Vb).optional().describe(`The most response-body bytes returned (default ${CM}, at most ${Vb}).`)},uQ=Se.object({status:Se.number(),ms:Se.number(),method:Se.string(),url:Se.string(),wsKey:Se.string(),as:BM,mode:Se.string().optional(),flowId:Se.string(),requestId:Se.string().optional(),headers:Se.record(Se.string(),Se.unknown()),body:Se.unknown(),truncated:Se.boolean().optional(),caveat:Se.string().optional(),next:Se.string().optional()}).passthrough(),lQ={worktree:Se.string().regex(DM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves.")},dQ=Se.object({wsKey:Se.string(),identities:Se.array(BM)}).passthrough(),Kb=class extends iQ{static{l(this,"P_")}static{u(this,"AppCallTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await _M(t,e);return s.ok===!1&&this.fail(zp(s)),s}};Kb=P([nQ({name:O_.name,description:O_.description,inputSchema:oQ,outputSchema:uQ})],Kb);var cQ=Kb;import{Tool as pQ,ToolContext as hQ}from"@frontmcp/sdk";var Qb=class extends hQ{static{l(this,"L_")}static{u(this,"AppIdentitiesTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await MM(t,e);return s.ok===!1&&this.fail(zp(s)),s}};Qb=P([pQ({name:N_.name,description:N_.description,annotations:{readOnlyHint:!0},inputSchema:lQ,outputSchema:dQ})],Qb);var mQ=Qb;import{Tool as fQ,ToolContext as gQ}from"@frontmcp/sdk";var Yb=200,Pa=5,vQ=5,Xb=5,ul=u((e,t)=>`${e} ${t}`,"id");function Je(e){let t=Math.max(0,Math.round(e/1e3));if(t<90)return`${t}s`;let s=Math.round(e/6e4);return s<120?`${s}m`:`${Math.floor(s/60)}h${s%60?` ${s%60}m`:""}`}l(Je,"lt"),u(Je,"span");var e1={current:"read",stale:"its newest report is overdue \u2014 whatever it last said is no longer known",unreachable:"could not be read \u2014 its numbers are UNKNOWN, not zero",refused:"the service refused the read \u2014 its numbers are UNKNOWN, not zero",malformed:"the service answered something that is not the snapshot schema \u2014 its numbers are UNKNOWN, not zero","not-running":"its service is not running, and the lens does not start one to read it \u2014 not read","never-polled":"not read by this lens yet \u2014 its numbers are unknown, not zero"},dr=u(e=>{let t=e?Date.parse(e):NaN;return Number.isFinite(t)?t:void 0},"parse"),t1=u(e=>e.thresholds.oldestWaitMin??eZ,"oldestWaitMinOf"),s1=u(e=>e.thresholds.stalledMin??tZ,"stalledMinOf"),Gp=u(e=>e.thresholds.quotaPct??nZ,"quotaPctOf"),r1=u(e=>e.thresholds.errorRatePct??iZ,"errorRatePctOf"),n1=u(e=>e.thresholds.orphanMin??aZ,"orphanMinOf"),Zp=u(e=>e.thresholds.failurePct??oZ,"failurePctOf"),Vp=u(e=>e.thresholds.p95Ms??uZ,"p95MsOf"),i1=u(e=>e.thresholds.rateLimited??lZ,"rateLimitedOf"),a1=u((e,t)=>Math.round(e/t*1e3)/10,"pct");function ll(e){if(e<1024)return`${e} B`;let t=["KB","MB","GB","TB"],s=e/1024,n=0;for(;s>=1024&&n<t.length-1;)s/=1024,n+=1;return`${s.toFixed(1)} ${t[n]}`}l(ll,"cf"),u(ll,"bytesText");var yQ=u(e=>e.thresholds.idleMin??sZ,"idleMinOf"),o1=u(e=>({at:e.at-(e.durationMs??0),...e.outcome?{outcome:e.outcome}:{},...e.items!==void 0?{items:e.items}:{},...e.durationMs!==void 0?{durationMs:e.durationMs}:{},...e.error?{error:e.error}:{},via:"pushed"}),"runOfPushed"),u1=u(e=>e[wp[e.sourceKind]],"snapOf");function l1(e,t){let s=Math.max(1e3,t.durationMs??0),n=e.find(r=>Math.abs(r.at-t.at)<=s);if(n){t.via==="snapshot"&&(n.at=t.at),n.outcome===void 0&&t.outcome&&(n.outcome=t.outcome),n.items===void 0&&t.items!==void 0&&(n.items=t.items),n.durationMs===void 0&&t.durationMs!==void 0&&(n.durationMs=t.durationMs),n.error===void 0&&t.error&&(n.error=t.error);return}e.push(t),e.sort((r,i)=>i.at-r.at),e.length>vT&&(e.length=vT)}l(l1,"fD"),u(l1,"addRunTo");var wQ=class{static{l(this,"jl")}static{u(this,"SourceBook")}constructor(){this.held=new Map,this.declarations=new Map,this.pushed=new Map}ingest(e){if(e.source===HG)return this.ingestPushed(e);if(e.source!=="gateway"||e.category!=="cluster")return!1;let t=e.raw?.kind;if(t==="source-poll"){let s=CT(e.raw);if(!s)return!1;let n=ul(s.project,s.name),r=this.held.get(n);if(r&&r.poll.polledAt>s.polledAt)return!1;let i=r??{poll:s,awaiting:!1,history:[],groups:new Map,runs:[],storeHistory:[]};for(this.held.delete(n),this.held.set(n,i);this.held.size>Yb;)this.held.delete(this.held.keys().next().value);if(!r&&s.sourceKind==="loop")for(let a of[...this.pushed.get(n)?.recent??[]].reverse())a.event==="run-end"&&this.addRun(i,o1(a));return this.fold(i,s,r?.poll),!0}if(t==="source-declaration"){let s=DT(e.raw);if(!s)return!1;for(this.declarations.delete(s.project),this.declarations.set(s.project,s);this.declarations.size>Yb;)this.declarations.delete(this.declarations.keys().next().value);let n=new Set(s.sources.map(r=>r.name));for(let[r,i]of[...this.held])i.poll.project===s.project&&!n.has(i.poll.name)&&this.held.delete(r);return!0}return!1}fold(e,t,s){let n=wp[t.sourceKind],r=t,i=!1;if(t.same){let{same:c,...p}=t,d=s&&s.sourceKind===t.sourceKind?u1(s):void 0;d&&d.digest===c.digest?r={...p,[n]:{...d,at:c.at,receivedAt:c.receivedAt}}:(r={...p,...d?{[n]:d}:{}},i=t.state==="current")}if(e.poll=r,e.awaiting=i,r.state!=="current"||i)return;let a=u1(r);if(!a)return;let o=a.receivedAt;e.lastReadAt!==void 0&&o<=e.lastReadAt||(e.lastReadAt!==void 0&&o-e.lastReadAt>Uw(r.reportEveryMs)&&(e.groups.clear(),e.idleSince=void 0,e.orphan=void 0),e.lastReadAt=o,r.sourceKind==="loop"?this.foldLoop(e,r,r.loop):r.sourceKind==="store"?this.foldStore(e,r.store):r.sourceKind==="queue"&&this.foldQueue(e,r.snapshot))}foldStore(e,t){let s=t.receivedAt;e.storeHistory.push({t:s,objects:t.objects,bytes:t.bytes}),e.storeHistory.length>kp&&e.storeHistory.splice(0,e.storeHistory.length-kp);let n=(t.deletesInWindow??0)>0||e.orphan!==void 0&&t.objects<e.orphan.last;!e.orphan||n?e.orphan={since:s,from:t.objects,last:t.objects}:e.orphan.last=t.objects}foldQueue(e,t){let s=t.receivedAt,n=dr(t.at),r=t.groups.map(o=>o.pending>0&&n!==void 0?n-(dr(o.oldestPendingAt)??n):0),i=r.some(o=>o>0)?Math.max(...r):void 0;e.history.push({t:s,pending:t.totals.pending,inFlight:t.totals.inFlight,failed:t.totals.failed,...i!==void 0?{oldestWaitMs:i}:{}}),e.history.length>kp&&e.history.splice(0,e.history.length-kp);let a=new Set;for(let o of t.groups){if(o.pending===0)continue;a.add(o.group);let c=dr(o.oldestPendingAt),p=e.groups.get(o.group);if(!p){e.groups.set(o.group,{movedAt:s,pending:o.pending,...c!==void 0?{oldest:c}:{},...o.completedInWindow!==void 0?{completed:o.completedInWindow}:{}});continue}(o.pending<p.pending||c!==void 0&&p.oldest!==void 0&&c>p.oldest||o.completedInWindow!==void 0&&p.completed!==void 0&&o.completedInWindow>p.completed)&&(p.movedAt=s),p.pending=o.pending,c!==void 0?p.oldest=c:delete p.oldest,o.completedInWindow!==void 0?p.completed=o.completedInWindow:delete p.completed}for(let o of[...e.groups.keys()])a.has(o)||e.groups.delete(o)}foldLoop(e,t,s){let n=dr(s.lastRunAt);n!==void 0&&this.addRun(e,{at:n,...s.lastOutcome?{outcome:s.lastOutcome}:{},...s.lastItems!==void 0?{items:s.lastItems}:{},...s.lastDurationMs!==void 0?{durationMs:s.lastDurationMs}:{},...s.lastOutcome==="failed"&&s.lastError?{error:s.lastError}:{},via:"snapshot"});let r=dr(s.at)??s.receivedAt,i=s.intervalSec*1e3,a=n!==void 0&&r-n<=(bp+1)*i,o=s.lastItems!==void 0?s.lastItems>0:s.itemsInWindow!==void 0?s.itemsInWindow>0:void 0;this.judgeIdle(e,t,a?o:void 0,s.receivedAt)}judgeIdle(e,t,s,n){e.idleSince=this.idleFrom(e.idleSince,t.project,t.feeds,s,n)}idleFrom(e,t,s,n,r){let i=s?this.held.get(ul(t,s)):void 0,a=i&&i.poll.state==="current"&&!i.awaiting?i.poll.snapshot:void 0;return n===!1&&a&&a.totals.pending>0?e??r:void 0}addRun(e,t){l1(e.runs,t)}pushRun(e,t,s){if(t.event==="run-start"){e.runningSince=s;return}e.runningSince=void 0,l1(e.loopRuns??=[],o1(e.recent[0]));let n=this.declarations.get(t.project)?.sources.find(r=>r.name===t.name)?.feeds;e.idleSince=this.idleFrom(e.idleSince,t.project,n,t.items===void 0?void 0:t.items>0,s)}ingestPushed(e){let t=IT(e.raw);if(!t)return!1;let s=ul(t.project,t.name),n=e.timestamp,r=this.pushed.get(s);if(!r)for(r={project:t.project,sourceKind:t.sourceKind,name:t.name,counts:{},since:n,lastAt:n,recent:[],suppressed:0},this.pushed.set(s,r);this.pushed.size>Yb;)this.pushed.delete(this.pushed.keys().next().value);r.counts[t.event]=(r.counts[t.event]??0)+1,r.since=Math.min(r.since,n),r.lastAt=Math.max(r.lastAt,n),r.suppressed+=t.floodSuppressed??0,r.recent.unshift({at:n,event:t.event,...t.item?{item:t.item}:{},...t.group?{group:t.group}:{},...t.items!==void 0?{items:t.items}:{},...t.durationMs!==void 0?{durationMs:t.durationMs}:{},...t.outcome?{outcome:t.outcome}:{},...t.object?{object:t.object}:{},...t.bytes!==void 0?{bytes:t.bytes}:{},...t.channel?{channel:t.channel}:{},...t.counterpart?{counterpart:t.counterpart}:{},...t.correlation?{correlation:t.correlation}:{},...t.error?{error:t.error.slice(0,500)}:{},...e.context.flowId?{flowId:e.context.flowId}:{},...e.context.requestId?{requestId:e.context.requestId}:{}}),r.recent.length>yT&&(r.recent.length=yT),t.sourceKind==="traffic"&&t.channel&&this.pushChannel(r,t,n),t.sourceKind==="loop"&&this.pushRun(r,t,n);let i=this.held.get(s);if(i&&i.poll.sourceKind===t.sourceKind)if(t.sourceKind==="queue"&&(t.event==="admitted"||t.event==="completed")){let a=t.group?[i.groups.get(t.group)].filter(o=>!!o):[...i.groups.values()];for(let o of a)o.movedAt=Math.max(o.movedAt,n)}else t.sourceKind==="loop"&&t.event==="run-end"?(this.addRun(i,o1(r.recent[0])),t.items!==void 0&&this.judgeIdle(i,i.poll,t.items>0,n)):t.sourceKind==="store"&&t.event==="delete"&&(i.orphan=void 0);return!0}pushChannel(e,t,s){let n=e.channels??=new Map,r=t.channel,i=n.get(r);if(!i&&(i={events:[],held:[],lastAt:s},n.set(r,i),n.size>cZ)){let a=[...n.entries()].sort((o,c)=>o[1].lastAt-c[1].lastAt)[0][0];n.delete(a)}i.direction=t.event==="inbound"?"inbound":"outbound",t.counterpart&&(i.counterpart=t.counterpart),t.error&&t.outcome!=="ok"&&(i.lastError=t.error.slice(0,500)),i.lastAt=Math.max(i.lastAt,s),i.events.push({t:s,...t.outcome?{outcome:t.outcome}:{},...t.durationMs!==void 0?{durationMs:t.durationMs}:{}}),i.events.length>wT&&i.events.splice(0,i.events.length-wT),t.floodSuppressed&&(i.held.push({t:s,n:t.floodSuppressed}),i.held.length>100&&i.held.shift())}report(e){let t=[];for(let[p,d]of this.held)t.push(jM(d,e,this.pushed.get(p)));for(let p of this.declarations.values())for(let d of p.sources){let h=ul(p.project,d.name);if(this.held.has(h))continue;let m=this.pushed.get(h);t.push(d.path!==void 0?qM(p.project,d,m):d.sourceKind==="loop"?LM(p.project,d,m,e):FM(p.project,d,m,e))}t.sort((p,d)=>p.project<d.project?-1:p.project>d.project?1:p.name<d.name?-1:p.name>d.name?1:0);for(let p of t){if(!p.loop||!p.feeds)continue;let d=t.find(h=>h.project===p.project&&h.name===p.feeds&&h.sourceKind==="queue");d&&(p.loop.fed={name:d.name,state:d.state,...d.headline?{pending:d.headline.pending}:{}})}let s=t.flatMap(p=>WM(p,e)).sort((p,d)=>(d.oldestWaitMs??d.forMs??0)-(p.oldestWaitMs??p.forMs??0)),n=Object.fromEntries(XG.map(p=>[p,0])),r={pending:0,inFlight:0,failed:0};for(let p of t)n[p.state]+=1,p.state==="current"&&p.headline&&(r.pending+=p.headline.pending,r.inFlight+=p.headline.inFlight,r.failed+=p.headline.failed);let i=[...this.declarations.values()].flatMap(p=>p.problems.map(d=>({project:p.project,problem:d}))),a=new Set(t.map(p=>ul(p.project,p.name))),o=[...this.pushed.entries()].filter(([p])=>!a.has(p)).map(([,p])=>({project:p.project,sourceKind:p.sourceKind,name:p.name,events:Object.values(p.counts).reduce((d,h)=>d+h,0),lastAt:p.lastAt})),c=t.length===0&&i.length===0&&o.length===0;return{provenance:"reported",producer:c?"none":"connected",...c?{detail:'no service declares a custom source \u2014 work an app keeps waiting in its own tables (an outbox) is not watched; declare it in project.json `cluster.sources` (kind "queue", "loop" for the loop that drains it, "store" for a storage backend, "traffic" for messages over a channel no tap classifies)'}:{},readAt:e,sources:t,findings:s,problems:i,...o.length?{undeclared:o}:{},counts:n,totals:r}}};function dl(e){return e?{pushed:{counts:{...e.counts},since:e.since,lastAt:e.lastAt,recent:e.recent.map(t=>({...t})),...e.suppressed?{suppressed:e.suppressed}:{}}}:{}}l(dl,"df"),u(dl,"pushedView");function qM(e,t,s){return{provenance:"reported",project:e,...t,state:"never-polled",detail:"no poll of it has reached the lens yet",groups:[],...dl(s)}}l(qM,"pY"),u(qM,"neverPolled");function jM(e,t,s){let n=e.poll,r=t-n.polledAt>Uw(n.reportEveryMs),i=r?"stale":e.awaiting?"never-polled":n.state,a=r?`its last report (${n.state}${n.detail?`: ${n.detail}`:""}) is ${Je(t-n.polledAt)} old and was due every ${Je(n.reportEveryMs)} \u2014 nothing has polled it since; is the dev gateway running?`:e.awaiting?"polled, but its full snapshot has not reached this lens (it started after the report that carried it); the gateway sends one at least once a minute":n.detail,o=u1(n),c={provenance:"reported",project:n.project,sourceKind:n.sourceKind,name:n.name,path:n.path,intervalSec:n.intervalSec,thresholds:n.thresholds,...n.feeds?{feeds:n.feeds}:{},state:i,...a!==void 0?{detail:a}:{},...n.status!==void 0?{status:n.status}:{},polledAt:n.polledAt,...n.failures?{failures:n.failures}:{},...o?{ageMs:Math.max(0,t-o.receivedAt),snapshotAt:o.at}:{},groups:[],...dl(s)};switch(n.sourceKind){case"loop":return zM(c,e,n.loop);case"store":return RM(c,e,n.store,i==="current");case"traffic":return n.traffic?{...c,traffic:OM(c,n.traffic)}:c;default:return UM(c,e,n.snapshot,i==="current")}}l(jM,"hY"),u(jM,"viewOf");function RM(e,t,s,n){let r=t.storeHistory.length?{storeHistory:t.storeHistory.map(v=>({...v}))}:{};if(!s)return{...e,...r};let{at:i,receivedAt:a,digest:o,...c}=s,p=s.quotaBytes?a1(s.bytes,s.quotaBytes):void 0,d=s.opsInWindow&&s.errorsInWindow!==void 0?a1(s.errorsInWindow,s.opsInWindow):void 0,h=n?t.orphan:void 0,m=h!==void 0&&s.objects>h.from,f={...c,...p!==void 0?{usedPct:p}:{},nearQuota:p!==void 0&&p>=Gp(e),...d!==void 0?{errorRatePct:d}:{},...m?{growingSince:h.since,growingFrom:h.from}:{}};return{...e,store:f,...r}}l(RM,"mY"),u(RM,"storeViewOf");function OM(e,t){let s=t.channels.map(n=>d1(e,n));return s.sort((n,r)=>(r.messagesInWindow??0)-(n.messagesInWindow??0)||(n.channel<r.channel?-1:1)),{pushOnly:!1,...t.windowSec!==void 0?{windowSec:t.windowSec}:{},channels:s,...t.truncated?{truncated:t.truncated}:{},totals:NM(s)}}l(OM,"fY"),u(OM,"trafficViewOf");function d1(e,t){let s=t.messagesInWindow&&t.failuresInWindow!==void 0?a1(t.failuresInWindow,t.messagesInWindow):void 0;return{...t,...s!==void 0?{failurePct:s}:{},overFailure:s!==void 0&&(t.messagesInWindow??0)>=dZ&&s>Zp(e),overLatency:t.p95Ms!==void 0&&t.p95Ms>Vp(e),rateLimited:(t.rateLimitedInWindow??0)>=i1(e)}}l(d1,"yD"),u(d1,"judgeChannel");var NM=u(e=>({channels:e.length,messages:e.reduce((t,s)=>t+(s.messagesInWindow??0),0),failures:e.reduce((t,s)=>t+(s.failuresInWindow??0),0),rateLimited:e.reduce((t,s)=>t+(s.rateLimitedInWindow??0),0)}),"totalsOf");function PM(e,t){if(!e.length)return;let s=[...e].sort((n,r)=>n-r);return s[Math.min(s.length-1,Math.max(0,Math.ceil(t*s.length)-1))]}l(PM,"gY"),u(PM,"percentile");function LM(e,t,s,n){let r={provenance:"reported",project:e,...t,groups:[],state:"never-polled",...dl(s)},i=s?.loopRuns??[];if(!s||!i.length&&s.runningSince===void 0)return{...r,detail:"push-only: no run pushed yet \u2014 it has not run since the lens started, or the app does not call lensEmitCustom"};let a=t.intervalSec*1e3,o=i[0],c=s.runningSince??o.at+(o.durationMs??0),p=n-(c+a),d=0;for(let m of i){if(m.outcome!=="failed")break;d+=1}let h={intervalSec:t.intervalSec,lastRunAt:o?new Date(o.at).toISOString():null,...o?.durationMs!==void 0?{lastDurationMs:o.durationMs}:{},...o?.outcome?{lastOutcome:o.outcome}:{},...o?.items!==void 0?{lastItems:o.items}:{},...o?.error?{lastError:o.error}:{},...p>0?{lateMs:p}:{},overdue:p>bp*a,failingRuns:d,...s.idleSince!==void 0?{idleSince:s.idleSince}:{},pushOnly:!0,...s.runningSince!==void 0?{runningSince:s.runningSince}:{}};return{...r,state:"current",detail:"push-only: read from the runs the app pushed",ageMs:Math.max(0,n-s.lastAt),snapshotAt:new Date(n).toISOString(),loop:h,...i.length?{runs:i.map(m=>({...m}))}:{}}}l(LM,"yY"),u(LM,"pushOnlyLoopView");function FM(e,t,s,n){let r={provenance:"reported",project:e,...t,groups:[],state:"never-polled",...dl(s)};if(!s?.channels?.size)return{...r,detail:"push-only: nothing pushed yet \u2014 no traffic on it, or the app does not call lensEmitCustom"};let i=n-Lw,a=0,o=[...s.channels.entries()].map(([p,d])=>{let h=d.events.filter(g=>g.t>=i),m=d.held.filter(g=>g.t>=i).reduce((g,y)=>g+y.n,0);a+=m;let f=h.map(g=>g.durationMs).filter(g=>g!==void 0),v=PM(f,.95);return d1(r,{channel:p,...d.direction?{direction:d.direction}:{},...d.counterpart?{counterpart:d.counterpart}:{},messagesInWindow:h.length+m,failuresInWindow:h.filter(g=>g.outcome==="failed").length,rateLimitedInWindow:h.filter(g=>g.outcome==="rate-limited").length,...v!==void 0?{p95Ms:v}:{},lastAt:new Date(d.lastAt).toISOString(),...d.lastError?{lastError:d.lastError}:{}})});o.sort((p,d)=>(d.messagesInWindow??0)-(p.messagesInWindow??0)||(p.channel<d.channel?-1:1));let c={pushOnly:!0,windowSec:Lw/1e3,channels:o,totals:NM(o),...a?{heldBack:a}:{}};return{...r,state:"current",detail:`push-only: counted from what the app pushed in the last ${Je(Lw)}${a?` \u2014 its flood guard held back ${a}, so every count is a floor`:""}`,ageMs:Math.max(0,n-s.lastAt),traffic:c}}l(FM,"wY"),u(FM,"pushOnlyView");function UM(e,t,s,n){let r=t1(e)*6e4,i=s1(e)*6e4,a=dr(s?.at),o=(s?.groups??[]).map(p=>{let d=p.pending>0&&p.oldestPendingAt&&a!==void 0?Math.max(0,a-Date.parse(p.oldestPendingAt)):void 0,h=d!==void 0&&Number.isFinite(d),m=n&&p.pending>0&&s?t.groups.get(p.group):void 0,f=m?s.receivedAt-m.movedAt:0;return{...p,...h?{oldestWaitMs:d}:{},overThreshold:h&&d>r,...f>0?{stillMs:f}:{},stalled:f>=i}});o.sort((p,d)=>(d.oldestWaitMs??-1)-(p.oldestWaitMs??-1)||d.pending-p.pending);let c=o.map(p=>p.oldestWaitMs).filter(p=>p!==void 0);return{...e,...s?{headline:{...s.totals,...c.length?{oldestWaitMs:Math.max(...c)}:{},overThreshold:o.filter(p=>p.overThreshold).length,stalled:o.filter(p=>p.stalled).length}}:{},groups:o,...s?.truncated?{truncated:s.truncated}:{},...t.history.length?{history:t.history.map(p=>({...p}))}:{}}}l(UM,"vY"),u(UM,"queueViewOf");function zM(e,t,s){let n=t.runs.map(g=>({...g}));if(!s)return{...e,...n.length?{runs:n}:{}};let{at:r,receivedAt:i,digest:a,...o}=s,c=dr(s.at)??s.receivedAt,p=s.intervalSec*1e3,d=dr(s.lastRunAt),h=dr(s.nextRunAt)??(d!==void 0?d+p:void 0),m=h!==void 0&&c>h?c-h:void 0,f=0;for(let g of n){if(g.outcome!=="failed")break;f+=1}!n.length&&s.lastOutcome==="failed"&&(f=1);let v={...o,...m!==void 0?{lateMs:m}:{},overdue:m!==void 0&&m>bp*p,failingRuns:f,...t.idleSince!==void 0?{idleSince:t.idleSince}:{}};return{...e,loop:v,...n.length?{runs:n}:{}}}l(zM,"bY"),u(zM,"loopViewOf");function WM(e,t){if(e.state!=="current")return[];switch(e.sourceKind){case"loop":return GM(e,t);case"store":return ZM(e,t);case"traffic":return VM(e);default:return HM(e)}}l(WM,"kY"),u(WM,"findingsOf");var on=u(e=>({provenance:"reported",project:e.project,name:e.name,sourceKind:e.sourceKind}),"base"),St=u(e=>`source_get { service: "${e.project}", name: "${e.name}" }`,"getSource");function HM(e){let t=t1(e),s=s1(e),n=[];for(let r of e.groups)r.overThreshold&&n.push({rule:qG,...on(e),group:r.group,...r.labels?{labels:r.labels}:{},pending:r.pending,oldestWaitMs:r.oldestWaitMs,thresholdMin:t,title:`${e.project} \xB7 ${e.name} (reported): ${r.group} \u2014 ${r.pending} pending, the oldest waiting ${Je(r.oldestWaitMs)} (over ${t} min)`,fix:[`Find why ${e.project} is not draining "${e.name}": is the process that takes this work running (service_state { service: "${e.project}" } \u2014 its workers), and is it failing (observe_errors { project: "${e.project}" })?`,"If a gate holds the work on purpose (a quiet window, a rate limit, a cap per tenant), the wait is the gate working: raise thresholds.oldestWaitMin on this source in cluster.sources instead of ignoring the warning.",`Read the group in full \u2014 its labels, in-flight and failed counts \u2014 with ${St(e)}.`],verify:`${St(e)}: the group's oldest wait under ${t} min, or the group gone`}),r.stalled&&r.stillMs!==void 0&&n.push({rule:jG,...on(e),group:r.group,...r.labels?{labels:r.labels}:{},pending:r.pending,forMs:r.stillMs,thresholdMin:s,title:`${e.project} \xB7 ${e.name} (reported): ${r.group} \u2014 ${r.pending} pending and nothing taken or finished for ${Je(r.stillMs)} (stalled: over ${s} min)`,fix:[`Nothing drains this group: is the loop or worker that takes "${e.name}" running and taking work (observe_sources { service: "${e.project}", kind: "loop" }; service_state { service: "${e.project}" } \u2014 its workers)?`,`Is the work failing as it is taken (observe_errors { project: "${e.project}" })? An item that fails and goes back to pending moves nothing.`,"If a gate holds this group on purpose (a rate-limit hold, a per-tenant cap), raise thresholds.stalledMin on this source in cluster.sources."],verify:`${St(e)}: the group's pending falls, or its oldest item changes, within ${s} min`});return n}l(HM,"SY"),u(HM,"queueFindings");function GM(e,t){let s=e.loop;if(!s)return[];let n=[],r=Je(s.intervalSec*1e3),i=s.lastRunAt?`its last run began ${s.lastRunAt}`:"it has not run since its service started";s.overdue&&s.lateMs!==void 0&&n.push({rule:RG,...on(e),forMs:s.lateMs,title:s.runningSince!==void 0?`${e.project} \xB7 ${e.name} (reported loop): a run began ${Je(s.lateMs+s.intervalSec*1e3)} ago and has not ended \u2014 it runs every ${r}`:`${e.project} \xB7 ${e.name} (reported loop): its next run is ${Je(s.lateMs)} late \u2014 it runs every ${r}; ${i}`,fix:[`Is the process that runs "${e.name}" alive (service_state { service: "${e.project}" } \u2014 its workers), and is a run stuck (a long await, a lock)? Its errors: observe_errors { project: "${e.project}" }.`,`What the loop says of itself in full: ${St(e)}.`],verify:`${St(e)}: lastRunAt within ${bp} intervals of now, and not overdue`});let a=e.runs??[];if(s.failingRuns>=rZ){let p=a.slice(0,s.failingRuns),d=p.length>1?p[0].at-p[p.length-1].at:void 0,h=p.find(m=>m.error)?.error??s.lastError;n.push({rule:OG,...on(e),...d!==void 0?{forMs:d}:{},title:`${e.project} \xB7 ${e.name} (reported loop): its last ${s.failingRuns} runs failed${h?` \u2014 ${h.slice(0,200)}`:""}`,fix:[`Read why it fails: observe_errors { project: "${e.project}" }, and the runs in full with ${St(e)}.`,"Fix the cause, then let it run once: the next run that ends `ok` clears this."],verify:`${St(e)}: the newest run's outcome is ok`})}let o=s.fed,c=yQ(e);if(s.idleSince!==void 0&&o&&o.state==="current"&&(o.pending??0)>0){let p=Math.max(0,t-(e.ageMs??0)-s.idleSince);p>=c*6e4&&n.push({rule:NG,...on(e),pending:o.pending,forMs:p,thresholdMin:c,title:`${e.project} \xB7 ${e.name} (reported loop): it runs and takes nothing \u2014 for ${Je(p)} \u2014 while "${o.name}" has ${o.pending} pending (over ${c} min)`,fix:[`Something it checks before it takes work says no: a gate (a quiet window, a rate-limit hold, a per-tenant cap), a filter that matches nothing, or a lock it cannot get. Read what it says of itself with ${St(e)} and what waits with source_get { service: "${e.project}", name: "${o.name}" }.`,"If the gate holds the work on purpose for this long, raise thresholds.idleMin on this loop in cluster.sources."],verify:`${St(e)}: a run that takes items (lastItems > 0), or "${o.name}" with nothing pending`})}return n}l(GM,"xY"),u(GM,"loopFindings");var Jp=u(e=>e?`the last ${Je(e*1e3)}`:"its window","windowText");function ZM(e,t){let s=e.store;if(!s)return[];let n=[],r=`${e.project} \xB7 ${e.name} (reported store)`;s.nearQuota&&s.usedPct!==void 0&&s.quotaBytes&&n.push({rule:PG,...on(e),value:s.usedPct,threshold:Gp(e),title:`${r}: ${s.usedPct}% of its quota used \u2014 ${ll(s.bytes)} of ${ll(s.quotaBytes)} (at or over ${Gp(e)}%)`,fix:[`What fills it: ${St(e)} \u2014 its groups, the largest first. Delete what nothing reads any more, or raise the quota where it is set.`,"If writes will fail at the quota, that is the failure to prevent: the app's writes into it error once it is full."],verify:`${St(e)}: usedPct under ${Gp(e)}`});let i=s.errorsInWindow??0;if(i>0&&(s.errorRatePct===void 0||s.errorRatePct>r1(e))&&n.push({rule:LG,...on(e),value:s.errorRatePct??i,threshold:r1(e),title:`${r}: ${i} failed operation${i===1?"":"s"} in ${Jp(s.windowSec)}${s.errorRatePct!==void 0?` \u2014 ${s.errorRatePct}% of ${s.opsInWindow} (over ${r1(e)}%)`:""}${s.lastError?`: ${s.lastError.slice(0,200)}`:""}`,fix:[`Read why: the last error is in ${St(e)} (lastError); the service's own errors: observe_errors { project: "${e.project}" }.`,"A permission, a full disk or a missing bucket fails every write the same way \u2014 fix the cause, then let it write again."],verify:`${St(e)}: errorsInWindow 0 once its window has passed`}),s.growingSince!==void 0&&s.growingFrom!==void 0){let a=Math.max(0,t-(e.ageMs??0)-s.growingSince);a>=n1(e)*6e4&&n.push({rule:FG,...on(e),forMs:a,thresholdMin:n1(e),value:s.objects-s.growingFrom,title:`${r}: it grew from ${s.growingFrom} to ${s.objects} objects over ${Je(a)} and deleted nothing (over ${n1(e)} min) \u2014 what removes them?`,fix:["Objects that are written and never deleted are what nothing cleans up: a file kept after its record was deleted, a temporary upload never removed, a version never pruned. Find the write that has no matching delete.","If the store only ever grows by design (an archive), raise thresholds.orphanMin on this source in cluster.sources (at most 10080)."],verify:`${St(e)}: deletesInWindow above 0, or the objects stop growing`})}return n}l(ZM,"$Y"),u(ZM,"storeFindings");function VM(e){let t=e.traffic;if(!t)return[];let s=[],n=Jp(t.windowSec);for(let r of t.channels){let i=`${e.project} \xB7 ${e.name} (reported traffic): ${r.channel}${r.counterpart?` ${r.direction==="inbound"?"\u2190":"\u2192"} ${r.counterpart}`:""}`,a={...on(e),channel:r.channel,...r.labels?{labels:r.labels}:{}};r.rateLimited&&s.push({rule:WG,...a,value:r.rateLimitedInWindow??0,threshold:i1(e),title:`${i}: answered \xABtoo many requests\xBB ${r.rateLimitedInWindow} time${r.rateLimitedInWindow===1?"":"s"} in ${n}${r.messagesInWindow?` of ${r.messagesInWindow} messages`:""}`,fix:[`The other end limits how fast it is called: spread the calls (a queue with a rate limit, a backoff that honours Retry-After), batch them, or cache what is read again. What calls it: ${St(e)} \u2014 the pushed events carry the flow each ran in.`],verify:`${St(e)}: rateLimitedInWindow under ${i1(e)} on ${r.channel}`}),r.overFailure&&r.failurePct!==void 0&&s.push({rule:UG,...a,value:r.failurePct,threshold:Zp(e),title:`${i}: ${r.failuresInWindow} of ${r.messagesInWindow} messages failed in ${n} (${r.failurePct}%, over ${Zp(e)}%)${r.lastError?`: ${r.lastError.slice(0,200)}`:""}`,fix:[`Read why they fail: the last error (lastError) and the pushed events with their flows in ${St(e)}; the service's errors: observe_errors { project: "${e.project}" }.`],verify:`${St(e)}: failures on ${r.channel} under ${Zp(e)}% of its messages`}),r.overLatency&&r.p95Ms!==void 0&&s.push({rule:zG,...a,value:r.p95Ms,threshold:Vp(e),title:`${i}: p95 ${Math.round(r.p95Ms)} ms in ${n} (over ${Vp(e)} ms)`,fix:[`Slow at the other end, or waiting before it is sent (a pool, a lock, a rate limiter)? Open a slow one's flow from ${St(e)} and see where its time went.`],verify:`${St(e)}: p95 on ${r.channel} under ${Vp(e)} ms`})}return s}l(VM,"_Y"),u(VM,"trafficFindings");async function c1(e){try{let t=await e.read(ds);return t&&Array.isArray(t.sources)?t:void 0}catch{return}}l(c1,"vD"),u(c1,"readReport");function p1(e){let t=e.loop,s=dr(e.snapshotAt),n=dr(t.lastRunAt),r=n===void 0||s===void 0?"it has not run since its service started":`its last run began ${Je(s-n)} ${t.pushOnly?"ago":"before it was measured"}${t.lastOutcome?` and ended ${t.lastOutcome}`:""}${t.lastItems!==void 0?`, ${t.lastItems} item${t.lastItems===1?"":"s"} taken`:""}`,i=t.overdue&&t.lateMs!==void 0?` \u2014 its next run is ${Je(t.lateMs)} LATE (it runs every ${Je(t.intervalSec*1e3)})`:"",a=t.failingRuns>=2?` \u2014 its last ${t.failingRuns} runs failed${t.lastError?`: ${t.lastError.slice(0,160)}`:""}`:"",o=t.idleSince!==void 0&&t.fed?` \u2014 taking nothing while "${t.fed.name}" has ${t.fed.pending??"?"} pending`:"";return`${r}${i}${a}${o}`}l(p1,"gD"),u(p1,"loopWords");function JM(e){let t=e.store,s=t.quotaBytes?` of ${ll(t.quotaBytes)} (${t.usedPct}%${t.nearQuota?" \u2014 NEAR ITS QUOTA":""})`:"",n=[t.writesInWindow!==void 0?`${t.writesInWindow} writes`:"",t.deletesInWindow!==void 0?`${t.deletesInWindow} deletes`:"",t.errorsInWindow!==void 0?`${t.errorsInWindow} errors${t.errorRatePct!==void 0?` (${t.errorRatePct}%)`:""}`:""].filter(Boolean).join(", "),r=t.growingSince!==void 0&&t.growingFrom!==void 0?` \u2014 grown from ${t.growingFrom} objects with nothing deleted`:"";return`${t.objects} objects, ${ll(t.bytes)}${s}${n?` \u2014 ${n} in ${Jp(t.windowSec)}`:""}${r}`}l(JM,"EY"),u(JM,"storeWords");function KM(e){let t=e.traffic,s=t.totals,n=t.channels.filter(i=>i.rateLimited||i.overFailure||i.overLatency).map(i=>{let a=[i.rateLimited?`${i.rateLimitedInWindow} rate-limited`:"",i.overFailure?`${i.failurePct}% failed`:"",i.overLatency?`p95 ${Math.round(i.p95Ms??0)} ms`:""].filter(Boolean).join(", ");return`${i.channel}: ${a}`}),r=t.heldBack?` (a floor \u2014 ${t.heldBack} held back by the app's flood guard)`:"";return`${s.messages} message${s.messages===1?"":"s"} on ${s.channels} channel${s.channels===1?"":"s"} in ${Jp(t.windowSec)}${r}, ${s.failures} failed, ${s.rateLimited} rate-limited${t.pushOnly?" \u2014 counted from what the app pushed":""}${n.length?` \u2014 ${n.join("; ")}`:""}`}l(KM,"AY"),u(KM,"trafficWords");function h1(e){let t=`${e.project} \xB7 ${e.name} (${e.sourceKind}, reported)`;if(e.sourceKind==="store"||e.sourceKind==="traffic"){let r=e.store?JM(e):e.traffic?KM(e):void 0;if(e.state==="current"&&r)return`${t}: ${r} (${e.traffic?.pushOnly?`last pushed ${Je(e.ageMs??0)} ago`:`read ${Je(e.ageMs??0)} ago`}).`;let i=r?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${r}`:"";return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${i}.`}if(e.sourceKind==="loop"){if(e.state==="current"&&e.loop)return`${t}: ${p1(e)} (${e.loop.pushOnly?`last pushed ${Je(e.ageMs??0)} ago`:`read ${Je(e.ageMs??0)} ago`}).`;let r=e.loop?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${p1(e)}`:"";return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${r}.`}let s=e.headline,n=s?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${s.pending} pending`:"";if(e.state==="current"&&s){let r=s.oldestWaitMs!==void 0?`, the oldest waiting ${Je(s.oldestWaitMs)}`:"",i=s.overThreshold?` \u2014 ${s.overThreshold} group${s.overThreshold===1?"":"s"} over ${t1(e)} min`:"",a=s.stalled?` \u2014 ${s.stalled} group${s.stalled===1?"":"s"} STALLED (nothing taken or finished for over ${s1(e)} min)`:"",o=e.truncated?` (the service dropped ${e.truncated.groups} more groups)`:"";return s.groups===0&&s.pending===0?`${t}: nothing pending (read ${Je(e.ageMs??0)} ago).`:`${t}: ${s.pending} pending in ${s.groups} group${s.groups===1?"":"s"}${r}${i}${a}${o} (read ${Je(e.ageMs??0)} ago).`}return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${n}.`}l(h1,"Z_"),u(h1,"sourceSentence");var bQ=u((e,t)=>e.pushed?{pushed:{counts:e.pushed.counts,lastAgoMs:Math.max(0,t-e.pushed.lastAt),...e.pushed.suppressed?{suppressed:e.pushed.suppressed}:{}}}:{},"pushedSummary");async function QM(e,t={}){let s=await c1(e);if(!s)return{found:!1,provenance:"reported",reason:"no dev cluster has reported a custom source into this session \u2014 the gateway reads `cluster.sources` and polls them"};let n=u(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind),"pick"),r=s.sources.filter(n),i=s.findings.filter(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind)),a=s.problems.filter(p=>!t.service||p.project===t.service),o=(s.undeclared??[]).filter(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind));if(s.producer==="none")return{found:!0,provenance:"reported",readAt:s.readAt,sources:[],findings:[],problems:a,answer:s.detail??"no service declares a custom source."};let c=r.length?r.map(h1).join(" "):`no declared source matches${t.service?` service "${t.service}"`:""}${t.kind?` kind "${t.kind}"`:""} \u2014 declared: ${s.sources.map(p=>`${p.project}/${p.name}`).join(", ")||"none"}.`;return{found:!0,provenance:"reported",readAt:s.readAt,sources:r.map(p=>({provenance:p.provenance,service:p.project,name:p.name,kind:p.sourceKind,state:p.state,...p.detail?{detail:p.detail}:{},...p.ageMs!==void 0?{ageMs:p.ageMs}:{},...p.polledAt!==void 0?{polledAt:p.polledAt}:{},...p.headline?{headline:p.headline}:{},...p.loop?{loop:p.loop}:{},...p.store?{store:{...p.store,...p.store.groups?{groups:p.store.groups.slice(0,Pa)}:{}}}:{},...p.store?.groups&&p.store.groups.length>Pa?{moreGroups:p.store.groups.length-Pa}:{},...p.traffic?{traffic:{...p.traffic,channels:p.traffic.channels.slice(0,Xb)}}:{},...p.traffic&&p.traffic.channels.length>Xb?{moreChannels:p.traffic.channels.length-Xb}:{},...p.feeds?{feeds:p.feeds}:{},thresholds:p.thresholds,findings:i.filter(d=>d.project===p.project&&d.name===p.name).map(d=>d.title),...p.groups.length?{oldestGroups:p.groups.slice(0,Pa).map(d=>({group:d.group,pending:d.pending,...d.oldestWaitMs!==void 0?{oldestWaitMs:d.oldestWaitMs}:{},overThreshold:d.overThreshold,...d.stillMs!==void 0?{stillMs:d.stillMs}:{},stalled:d.stalled}))}:{},...p.groups.length>Pa?{moreGroups:p.groups.length-Pa}:{},...p.runs?.length?{recentRuns:p.runs.slice(0,vQ)}:{},...bQ(p,s.readAt)})),findings:i.length,...a.length?{problems:a}:{},...o.length?{undeclared:o}:{},answer:o.length?`${c} ${o.map(p=>`${p.project} pushes ${p.sourceKind} events for "${p.name}" (${p.events}), which no cluster.sources entry of ${p.project} declares \u2014 they are read nowhere until it is declared.`).join(" ")}`:c,hint:"Numbers are REPORTED by each service, not measured by the lens. Only a `current` source was read; every other state means its numbers are unknown, not zero. One source in full \u2014 every group or channel, its history, a loop's runs, what the app pushed and the flows it pushed them from: source_get { service, name }."}}l(QM,"J_"),u(QM,"readSources");async function YM(e,t){let s=await c1(e);if(!s)return{found:!1,provenance:"reported",reason:"no dev cluster has reported a custom source into this session"};let n=s.sources.find(r=>r.project===t.service&&r.name===t.name);if(!n){let r=s.undeclared?.find(i=>i.project===t.service&&i.name===t.name);return{found:!1,provenance:"reported",service:t.service,name:t.name,reason:r?`${t.service} pushes ${r.sourceKind} events for "${t.name}" (${r.events}), but no cluster.sources entry of ${t.service} declares it \u2014 declare it (with the route that answers its snapshot) to read it`:"no declared source of that service and name \u2014 `service` is the Nx project, `name` the declaration's",declared:s.sources.map(i=>({service:i.project,name:i.name}))}}return{found:!0,...n,service:n.project,findings:s.findings.filter(r=>r.project===n.project&&r.name===n.name),answer:h1(n)}}l(YM,"Q_"),u(YM,"readSource");import{z as le}from"@frontmcp/sdk";var Ot=le.object({}).passthrough(),kQ={service:le.string().min(1).optional().describe(`Only this service's sources \u2014 its Nx project name, e.g. "engine".`),kind:le.enum(Ib.kinds).optional().describe('Only sources of this kind: "queue", "loop", "store" or "traffic".')},$Q=le.object({provenance:le.string(),readAt:le.number(),sources:le.array(le.object({provenance:le.string().optional(),service:le.string(),name:le.string(),kind:le.string(),state:le.string(),detail:le.string().optional(),ageMs:le.number().optional(),polledAt:le.number().optional(),headline:Ot.optional(),loop:Ot.optional(),store:Ot.optional(),traffic:Ot.optional(),feeds:le.string().optional(),thresholds:Ot.optional(),findings:le.array(le.string()),oldestGroups:le.array(Ot).optional(),moreGroups:le.number().optional(),moreChannels:le.number().optional(),recentRuns:le.array(Ot).optional(),pushed:Ot.optional()}).passthrough()),findings:le.union([le.number(),le.array(le.unknown())]),problems:le.array(le.object({project:le.string(),problem:le.string()}).passthrough()).optional(),undeclared:le.array(le.object({project:le.string(),sourceKind:le.string(),name:le.string(),events:le.number()}).passthrough()).optional(),answer:le.string(),hint:le.string().optional()}).passthrough(),xQ={service:le.string().min(1).describe('The service \u2014 its Nx project name, e.g. "engine".'),name:le.string().min(1).describe("The source's name, as `cluster.sources` declares it (observe_sources lists them).")},EQ=le.object({provenance:le.string().optional(),service:le.string(),project:le.string().optional(),name:le.string(),sourceKind:le.string().optional(),state:le.string(),detail:le.string().optional(),ageMs:le.number().optional(),polledAt:le.number().optional(),snapshotAt:le.string().optional(),intervalSec:le.number().optional(),thresholds:Ot.optional(),headline:Ot.optional(),groups:le.array(Ot).optional(),history:le.array(Ot).optional(),loop:Ot.optional(),runs:le.array(Ot).optional(),store:Ot.optional(),storeHistory:le.array(Ot).optional(),traffic:Ot.optional(),pushed:Ot.optional(),findings:le.array(le.object({rule:le.string(),title:le.string(),fix:le.array(le.string()),verify:le.string()}).passthrough()),answer:le.string()}).passthrough(),m1=class extends gQ{static{l(this,"X_")}static{u(this,"ObserveSourcesTool")}async execute(e){let t=await QM(this.get(X),e);t.found||this.fail(Wt(t.reason));let{found:s,...n}=t;return n}};m1=P([fQ({name:Ib.name,description:Ib.description,annotations:{readOnlyHint:!0},inputSchema:kQ,outputSchema:$Q})],m1);var SQ=m1;import{Tool as AQ,ToolContext as CQ}from"@frontmcp/sdk";var f1=class extends CQ{static{l(this,"eE")}static{u(this,"SourceGetTool")}async execute(e){let t=await YM(this.get(X),e);t.found||("declared"in t&&this.fail(Bn(`${t.reason}. Declared: ${nn((t.declared??[]).map(r=>`${r.service}/${r.name}`))||"none"}.`)),this.fail(Wt(t.reason)));let{found:s,...n}=t;return n}};f1=P([AQ({name:W_.name,description:W_.description,annotations:{readOnlyHint:!0},inputSchema:xQ,outputSchema:EQ})],f1);var IQ=f1;import{Tool as DQ,ToolContext as TQ}from"@frontmcp/sdk";import{z as oe}from"@frontmcp/sdk";var _Q=oe.object({name:oe.string(),key:oe.string(),root:oe.string(),state:oe.string(),active:oe.boolean(),branch:oe.string().optional(),changes:oe.number().optional(),frozen:oe.boolean().optional(),apex:oe.string().optional(),hosts:oe.record(oe.string(),oe.string()).optional(),dashboard:oe.string(),services:oe.number().optional(),createdByLens:oe.boolean(),detail:oe.string().optional()}).passthrough(),MQ={name:oe.string().regex(Fb).describe("Short and lowercase \u2014 one DNS label of at most 20 characters (it becomes part of its hosts: app.<name>.<project>.localhost). E.g. 'auth-fix'."),branch:oe.string().min(1).max(200).optional().describe("The branch to work on. Default lensmcp/<name>, made new from `from`. An existing branch is checked out as it is."),from:oe.string().min(1).max(200).optional().describe("The commit a new branch starts from (a branch, tag or sha). Default: the main checkout's HEAD."),detach:oe.boolean().optional().describe("Check out `from` itself with no branch \u2014 to look at or review a commit."),frozen:oe.boolean().optional().describe("Serve the commit as it is: every service compiles once, no file watcher, no type checker. For reviewing or comparing, not for editing."),prepare:oe.boolean().optional().describe("Run the project's prepare (migrations, seeds): true always, false never. Default: when its data is new.")},BQ=oe.object({name:oe.string(),key:oe.string(),root:oe.string(),worktree:oe.object({path:oe.string(),branch:oe.string().optional(),createdBranch:oe.boolean().optional(),from:oe.string().optional()}).passthrough().optional(),state:oe.string(),detail:oe.string().optional(),log:oe.string().optional(),error:oe.string().optional(),logTail:oe.string().optional(),next:oe.string().optional()}).passthrough(),qQ={},jQ=oe.object({project:oe.string(),active:oe.string(),worktrees:oe.array(_Q),note:oe.string().optional()}).passthrough(),RQ={name:oe.string().min(1).max(80).describe("A worktree's name (or key) from worktree_list, or 'main'.")},OQ=oe.object({active:oe.string(),key:oe.string().optional(),root:oe.string().optional(),branch:oe.string().optional(),hosts:oe.record(oe.string(),oe.string()).optional(),dashboard:oe.string().optional(),note:oe.string().optional(),next:oe.string().optional()}).passthrough(),NQ={name:oe.string().min(1).max(80).describe("The worktree's name (or key) from worktree_list."),force:oe.boolean().optional().describe("Throw away its uncommitted work (and delete an unmerged branch with deleteBranch). ONLY when the person said so."),keepData:oe.boolean().optional().describe("Keep its databases and queues on record, for a worktree you will start again."),deleteBranch:oe.boolean().optional().describe("Also delete the branch the lens made for it \u2014 refused while it has commits merged nowhere, unless force.")},PQ=oe.object({name:oe.string().optional(),retry:oe.boolean().optional(),note:oe.string().optional(),stopped:oe.boolean().optional(),keptData:oe.array(oe.string()).optional(),worktreeRemoved:oe.string().optional(),worktreeKept:oe.string().optional(),worktreeError:oe.string().optional(),branchDeleted:oe.string().optional(),branchKept:oe.object({branch:oe.string(),why:oe.string()}).passthrough().optional()}).passthrough(),g1=class extends TQ{static{l(this,"nE")}static{u(this,"WorktreeCreateTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await bM(t,e);s.ok===!1&&!s._meta&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};g1=P([DQ({name:P_.name,description:P_.description,inputSchema:MQ,outputSchema:BQ})],g1);var LQ=g1;import{Tool as FQ,ToolContext as UQ}from"@frontmcp/sdk";var v1=class extends UQ{static{l(this,"sE")}static{u(this,"WorktreeListTool")}async execute(){let e=qn();"error"in e&&this.fail(Wt(e.error));let t=await Hp(e);return"error"in t&&this.fail(Wt(t.error)),t}};v1=P([FQ({name:L_.name,description:L_.description,annotations:{readOnlyHint:!0},inputSchema:qQ,outputSchema:jQ})],v1);var zQ=v1;import{Tool as WQ,ToolContext as HQ}from"@frontmcp/sdk";var y1=class extends HQ{static{l(this,"iE")}static{u(this,"WorktreeSwitchTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await $M(t,e.name);s.ok===!1&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};y1=P([WQ({name:F_.name,description:F_.description,inputSchema:RQ,outputSchema:OQ})],y1);var GQ=y1;import{Tool as ZQ,ToolContext as VQ}from"@frontmcp/sdk";var w1=class extends VQ{static{l(this,"cE")}static{u(this,"WorktreeRemoveTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await xM(t,e);s.ok===!1&&s.retry!==!0&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};w1=P([ZQ({name:U_.name,description:U_.description,inputSchema:NQ,outputSchema:PQ})],w1);var JQ=w1;import{spawn as KQ}from"node:child_process";import{existsSync as b1,readFileSync as QQ}from"node:fs";import{join as XM}from"node:path";import{Job as YQ,JobContext as XQ,z as ks}from"@frontmcp/sdk";import{existsSync as eY}from"node:fs";import{dirname as tY,join as sY,relative as rY,resolve as Di,isAbsolute as nY}from"node:path";var iY=6;function eB(e=process.env,t=process.cwd()){return Di(e.LENSMCP_WORKSPACE_ROOT??t)}l(eB,"OD"),u(eB,"resolveAllowedRoot");function Kp(e,t){let s=rY(Di(e),Di(t));return s===""||!s.startsWith("..")&&!nY(s)}l(Kp,"lE"),u(Kp,"isWithinRoot");function tB(e,t){let s=Di(e);if(t===void 0)return{ok:!0,cwd:s};let n=Di(s,t);return Kp(s,n)?{ok:!0,cwd:n}:{ok:!1,reason:`cwd ${n} is outside this server's workspace (${s}). verify_fix runs a workspace-defined Nx target, so it only runs in the workspace this server was started for. Set LENSMCP_WORKSPACE_ROOT to serve a different one.`}}l(tB,"CD"),u(tB,"confineToWorkspace");function sB(e,t){let s=Di(t),n=Di(e);if(Kp(s,n))for(let r=0;r<iY;r++){if(eY(sY(n,"nx.json")))return n;if(n===s)break;let i=tY(n);if(i===n||!Kp(s,i))break;n=i}}l(sB,"ND"),u(sB,"findNxWorkspaceRootWithin");var aY=/^[@A-Za-z0-9][\w./-]*$/;function rB(e){return e.length<=214&&aY.test(e)}l(rB,"jD"),u(rB,"isValidProjectName");var k1=class extends XQ{static{l(this,"pE")}static{u(this,"VerifyFixJob")}async execute(e){let t=Date.now(),s=e.project??process.env.LENSMCP_VERIFY_PROJECT??"example-web",n=eB(),r=tB(n,e.cwd);r.ok||(this.log(`[verify_fix] refused: ${r.reason}`),this.fail(Na(r.reason)));let i=r.cwd;rB(s)||(this.log(`[verify_fix] refused: ${s} is not a valid Nx project name`),this.fail(Na(`${s.slice(0,120)} is not a valid Nx project name`)));let a=sB(i,n);a||(this.log(`No nx.json found between ${i} and ${n}`),this.fail(Wt(`No nx.json found between ${i} and ${n} \u2014 nothing to verify there`)));let o=nB("nx",[a]);o||(this.log(`Could not find node_modules/.bin/nx under ${a}`),this.fail(Wt(`Could not find node_modules/.bin/nx under ${a} \u2014 install the workspace's dependencies`))),this.log(`[verify_fix] nx run ${s}:agent-verify (cwd=${a})`);let c=KQ(o,["run",`${s}:agent-verify`],{cwd:a,env:{...process.env},stdio:["ignore","pipe","pipe"]}),p=[],d=u(y=>{let w=/\[agent-verify\] ([a-z]+): (passed|failed|skipped|errored)/.exec(y);w&&w[1]&&w[2]&&(p.push({name:w[1],result:w[2],durationMs:0}),this.log(` ${w[1]}: ${w[2]}`))},"captureLine");$1(c.stdout,d),$1(c.stderr,d);let h=!1,m=setTimeout(()=>{h=!0;try{c.kill("SIGTERM")}catch{}},e.timeoutMs),f=await new Promise(y=>{c.on("exit",w=>y(w??1))});if(clearTimeout(m),h)return{status:"timeout",project:s,durationMs:Date.now()-t,stages:p,reportPath:null};let v=XM(a,".lensmcp","verifications","latest.json"),g;if(b1(v))try{g=JSON.parse(QQ(v,"utf-8"))}catch{g=void 0}return{status:g?.status??(f===0?"passed":"failed"),project:s,durationMs:g?.durationMs??Date.now()-t,stages:g?.stages??p,reportPath:b1(v)?v:null}}};k1=P([YQ({name:"observe_verify_fix",description:"Run the deterministic verification loop (typecheck \u2192 lint \u2192 build) for a host project. Returns a per-stage report; suggested next read on failure is the relevant *://errors resource.",inputSchema:{project:ks.string().describe('Nx project name in the host workspace to verify. Defaults to LENSMCP_VERIFY_PROJECT or "example-web".').optional(),cwd:ks.string().describe("Directory to verify from. MUST be inside the workspace this server was started for (LENSMCP_WORKSPACE_ROOT, else the server's cwd); a path outside it is refused. Defaults to that workspace root.").optional(),timeoutMs:ks.number().int().positive().default(5*6e4).describe("How long to wait for the verify pipeline before declaring it stuck.")},outputSchema:{status:ks.enum(["passed","failed","errored","timeout"]),project:ks.string().nullable(),durationMs:ks.number(),stages:ks.array(ks.object({name:ks.string(),result:ks.enum(["passed","failed","skipped","errored"]),durationMs:ks.number(),exitCode:ks.number().optional(),summary:ks.string().optional()})),reportPath:ks.string().nullable()}})],k1);var oY=k1;function nB(e,t){for(let s of t){let n=XM(s,"node_modules",".bin",e);if(b1(n))return n}}l(nB,"YY"),u(nB,"locateBin");function $1(e,t){if(!e)return;let s="";e.setEncoding("utf-8"),e.on("data",n=>{s+=typeof n=="string"?n:n.toString("utf-8");let r;for(;(r=s.indexOf(`
197
+ `)}catch{return""}}l(Hb,"Qq"),u(Hb,"tail");function Ii(e,t,s,n=!1){return{...e,_meta:{[JK]:{root:t,key:s},...n?{[KK]:!0}:{}}}}l(Ii,"ac"),u(Ii,"switching");async function bM(e,t,s=QK){let{ws:n}=e;if(!Fb.test(t.name))return{ok:!1,error:`'${t.name}' is not a worktree name: one DNS label of at most 20 characters \u2014 lowercase letters, digits and inner hyphens (it becomes part of its hosts).`};let r=`${n.baseKey}-${t.name}`,i=["instance","create",t.name,"--json",...t.detach?["--detach"]:t.branch?[`--branch=${t.branch}`]:[],...t.from?[`--from=${t.from}`]:[],...t.frozen?["--frozen"]:[],...t.prepare===!1?["--no-prepare"]:t.prepare===!0?["--prepare"]:[],`--cwd=${n.mainRoot}`],a=YK(e.home,r),o=XK(e.home,r),c=eQ(o),p=e.spawnDetached(i,{cwd:n.mainRoot,log:o});if(p===void 0)return{ok:!1,error:"could not start `lensmcp instance create`"};let d=e.now()+s,h;for(;;){let m=Wb(a);if(m?.pid===p&&(h=m),h&&(h.state==="ready"||h.state==="failed"))break;if(!e.alive(p)){let f=Wb(a);if(f?.pid===p&&(h=f),!h||h.state!=="ready"&&h.state!=="failed")return{ok:!1,error:Hb(o,c)||"lensmcp instance create ended without a word",log:o};break}if(e.now()>=d)break;await e.sleep(300)}return h?kM(h,o,n,c):{ok:!1,error:"lensmcp instance create has not started yet \u2014 call worktree_list in a moment",log:o}}l(bM,"Xq"),u(bM,"createWorktree");function kM(e,t,s,n=0){let r=e.key.slice(s.baseKey.length+1),i=e.worktree?.path??e.root,a={...e.result??{},name:r,key:e.key,root:e.root,...e.worktree?{worktree:e.worktree}:{},state:e.state},o=e.state==="ready"||e.state==="failed"&&!!e.result,c=e.worktree?.path?` If your client can move its session into an existing git worktree, do it now (Claude Code: EnterWorktree { path: "${e.worktree.path}" }).`:"",p=`Do this task's work in ${e.root}: edit files there (absolute paths, or cd there first) and run its commands there \u2014 \`lensmcp instance exec -- <cmd>\` gives a command the worktree's own database, queues and hosts. Your edits in ${s.mainRoot} are not in it: it starts from the commit, not the working copy.${c}`;if(e.state==="ready")return Ii({ok:!0,...a,next:`${p} The lens now reports on this worktree \u2014 observe.*, flows and errors are ITS app's. worktree_remove takes it away when the work is committed.`},e.root,e.key);if(e.state==="failed"){let h={ok:!1,...a,error:e.detail??"the create failed",log:t,logTail:Hb(t,n)};return o?Ii({...h,next:`It is served, but not ready: read the log, fix the cause, then \`lensmcp instance start --prepare\` in ${e.root} \u2014 or worktree_remove { name: '${r}', force: true } to drop it.`},e.root,e.key):{...h,next:`Read the log and fix the cause, then run \`lensmcp instance start\` in ${e.root}; unfinished preparation retries before services start. worktree_remove { name: '${r}' } takes away what was made.`}}let d={ok:!0,...a,detail:e.detail,log:t,next:`Still ${e.state}${e.detail?` (${e.detail})`:""}. The files are at ${i} \u2014 you can start editing. worktree_list shows when it is ready.`};return o?Ii({...d,next:`${d.next} The lens already reports on this worktree. ${p}`},e.root,e.key):d}l(kM,"nY"),u(kM,"createAnswer");async function $M(e,t){let{ws:s}=e;if(t==="main"||t===s.baseKey)return s.instance?Ii({ok:!0,active:"main",root:s.mainRoot,next:`The lens reports on the main checkout (${s.mainRoot}) again.`},s.mainRoot,s.baseKey):{ok:!0,active:"main",note:"The lens already reports on the main checkout."};let n=await Hp(e);if("error"in n)return{ok:!1,error:n.error};let r=n.worktrees.find(i=>i.name===t||i.key===t);if(!r)return{ok:!1,error:`No worktree '${t}' in ${s.baseKey}: ${n.worktrees.map(i=>i.name).join(", ")}.`};if(r.active)return{ok:!0,active:r.name,note:`The lens already reports on '${r.name}'.`};if(r.state==="folder-gone")return{ok:!1,error:`'${r.name}' has no folder any more \u2014 worktree_remove clears it.`};if(r.state==="creating"||r.state==="provisioning"||r.state==="preparing"||r.state==="registering")return{ok:!1,error:`'${r.name}' is still ${r.state} \u2014 try again when worktree_list shows it running.`};if(r.state==="stopped"||r.state==="failed"){let i=await e.run(["instance","start",`--name=${r.name}`,`--cwd=${r.root}`],{cwd:r.root,timeoutMs:12e4});if(i.code!==0)return{ok:!1,error:`could not start '${r.name}': ${i.stderr.trim()||i.stdout.trim()}`}}return Ii({ok:!0,active:r.name,key:r.key,root:r.root,...r.branch?{branch:r.branch}:{},...r.hosts?{hosts:r.hosts}:{},dashboard:r.dashboard,next:`The lens now reports on '${r.name}'. Do its work in ${r.root}.`},r.root,r.key)}l($M,"Yq"),u($M,"switchWorktree");async function xM(e,t){let{ws:s}=e;if(t.name==="main"||t.name===s.baseKey)return{ok:!1,error:"The main checkout is not a worktree \u2014 it cannot be removed."};if(s.instance&&(t.name===s.instance||t.name===s.key))return Ii({ok:!1,retry:!0,note:`Moving the lens back to the main checkout to remove '${s.instance}'.`},s.mainRoot,s.baseKey,!0);let n=await Hp(e);if("error"in n)return{ok:!1,error:n.error};let r=n.worktrees.find(c=>c.name===t.name||c.key===t.name);if(!r||r.name==="main")return{ok:!1,error:`No worktree '${t.name}' in ${s.baseKey}: ${n.worktrees.filter(c=>c.name!=="main").map(c=>c.name).join(", ")||"none"}.`};let i=["instance","rm",r.key,"--json",`--base=${s.baseKey}`,...r.createdByLens?["--worktree"]:[],...t.force?["--force"]:[],...t.keepData?["--keep-data"]:[],...t.deleteBranch?["--delete-branch"]:[],`--cwd=${s.mainRoot}`],a=await e.run(i,{cwd:s.mainRoot,timeoutMs:18e4}),o={};try{o=JSON.parse(a.stdout)}catch{}if(a.code!==0){let c=o.uncommitted;return{ok:!1,name:r.name,...o,error:Array.isArray(c)?`'${r.name}' has uncommitted work \u2014 commit it on its branch first. Pass force: true ONLY if the person said to throw it away.`:a.stderr.trim()||`lensmcp instance rm exited ${a.code}`}}return{ok:!0,name:r.name,...o,...r.createdByLens?{}:{note:`The lens did not make ${r.root}, so the folder stays \u2014 only its instance and data are gone.`}}}l(xM,"eD"),u(xM,"removeWorktree");var EM=45e3,Gb=55e3,SM=new RegExp(`^(?:main|${Fb.source.slice(1,-1)})$`);async function AM(e,t){let s=Math.min(Gb,Math.max(0,t.waitMs??EM)),n=["restart",t.service,"--json","--wait",String(s/1e3),...t.worktree?["--worktree",t.worktree]:[],...t.check?["--status"]:["--reason","asked by an agent (service_restart)",...t.hard?["--hard"]:[]]],r=await e.run(n,{cwd:e.ws.root,timeoutMs:s+15e3}),i;try{let a=JSON.parse(r.stdout);a&&typeof a=="object"&&!Array.isArray(a)&&(i=a)}catch{}if(!i)return{ok:!1,error:(r.stderr||r.stdout).trim().slice(-2e3)||`lensmcp restart exited ${r.code??"by a signal"}`};if(i.done===!1){let a=[`service: '${t.service}'`,...t.worktree?[`worktree: '${t.worktree}'`]:[],"check: true"].join(", ");return{...i,next:`Still restarting. Call service_restart { ${a} } to wait for it \u2014 that starts no second restart.`}}return i}l(AM,"M_"),u(AM,"restartService");function qn(e=process.env){let t=fM(e);if(!t)return{error:"This lens server does not know which workspace it serves (no LENSMCP_WORKSPACE_ROOT and no .lensmcp/config.json)."};let s=gM(e,process.argv[1],t.mainRoot);return s?yM(t,s,e):{error:`The lensmcp CLI was not found beside this server or in ${t.mainRoot}/node_modules \u2014 install lensmcp in the workspace.`}}l(qn,"Hn"),u(qn,"worktreeDeps");import{z as tt}from"@frontmcp/sdk";var tQ={service:tt.string().min(1).describe('The service \u2014 its Nx project name, e.g. "registry".'),worktree:tt.string().regex(SM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves."),hard:tt.boolean().optional().describe("Stop it first, then start it \u2014 nothing serves in between. Default: the old tree serves until the new one answers."),check:tt.boolean().optional().describe("Only follow the latest restart until it settles; start none."),waitMs:tt.number().int().min(0).max(Gb).optional().describe(`How long to wait for it to settle (default ${EM} ms, at most ${Gb}).`)},sQ=tt.object({wsKey:tt.string().optional(),service:tt.string().optional(),state:tt.string().optional(),generation:tt.number().optional(),done:tt.boolean().optional(),joined:tt.boolean().optional(),restart:tt.object({how:tt.string().optional(),reason:tt.string().optional(),startedAt:tt.number().optional(),fromGeneration:tt.number().optional(),done:tt.object({ok:tt.boolean(),at:tt.number().optional(),generation:tt.number().optional(),error:tt.string().optional()}).passthrough().optional()}).passthrough().optional(),answer:tt.string().optional(),next:tt.string().optional()}).passthrough(),Zb=class extends UK{static{l(this,"O_")}static{u(this,"ServiceRestartTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await AM(t,e);s.ok===!1&&s.done!==!0&&this.fail(zp(s));let{ok:n,...r}=s;return r}};Zb=P([FK({name:R_.name,description:R_.description,inputSchema:tQ,outputSchema:sQ})],Zb);var rQ=Zb;import{Tool as nQ,ToolContext as iQ}from"@frontmcp/sdk";var aQ=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"],CM=16*1024,Vb=64*1024,IM=30,DM=SM;function TM(e){if(typeof e=="string")try{return JSON.stringify(JSON.parse(e))}catch{}return JSON.stringify(e??null)}l(TM,"oY"),u(TM,"jsonText");async function Jb(e,t,s,n){let r=await e.run(t,{cwd:e.ws.root,timeoutMs:s});try{let i=JSON.parse(r.stdout);if(i&&typeof i=="object"&&!Array.isArray(i))return i}catch{}return{error:(r.stderr||r.stdout).trim().slice(-2e3)||`${n} exited ${r.code??"by a signal"}`}}l(Jb,"oD"),u(Jb,"said");async function _M(e,t){let s=Math.min(Vb,Math.max(1,Math.round(t.maxBodyBytes??CM))),n=["call",...t.method?[t.method]:[],t.url,"--json",`--max-body=${s}`,`--timeout=${IM}`,...t.body!==void 0?[`--data=${TM(t.body)}`]:[],...Object.entries(t.headers??{}).map(([a,o])=>`--header=${a}: ${o}`),...t.as?[`--as=${t.as}`]:[],...t.tenant?[`--tenant=${t.tenant}`]:[],...t.worktree?[`--worktree=${t.worktree}`]:[]],r=await Jb(e,n,(IM+15)*1e3,"lensmcp call");if("error"in r)return{ok:!1,...r};let i=typeof r.flowId=="string"?r.flowId:void 0;return{...r,...i?{next:`Read what the call did: flow_get { flowId: '${i}' } \u2014 the route, its SQL and its spans. Then db://lint and routes://lint: what to fix about the statements it ran and about the route.`}:{}}}l(_M,"iD"),u(_M,"callApp");async function MM(e,t){let s=await Jb(e,["call","--who","--json",...t.worktree?[`--worktree=${t.worktree}`]:[]],2e4,"lensmcp call --who");return"error"in s?{ok:!1,...s}:s}l(MM,"aD"),u(MM,"listIdentities");import{z as Se}from"@frontmcp/sdk";var BM=Se.object({user:Se.string(),tenant:Se.string().optional(),email:Se.string().optional(),name:Se.string().optional(),roles:Se.array(Se.string()).optional(),host:Se.string().optional(),firstSeenAt:Se.number().optional(),lastSeenAt:Se.number().optional(),mode:Se.string().optional()}).passthrough(),oQ={url:Se.string().regex(/^https:\/\/[^\s/]+\/\S*$/).describe('The full URL on a host the dev gateway serves, e.g. "https://api.foodguard.localhost/registry/v1/business-profile/situation-state".'),method:Se.enum(aQ).optional().describe("Default GET; POST when a `body` is given."),body:Se.unknown().optional().describe("The JSON body \u2014 any JSON value (a string holding JSON text is sent as that JSON)."),headers:Se.record(Se.string(),Se.string()).optional().describe("Request headers beyond the defaults. Not `authorization`: the call says who you are."),as:Se.string().min(1).optional().describe("Whom to act as: a user id, email or name from app_identities. Default: the person seen most recently."),tenant:Se.string().min(1).optional().describe("Act in this tenant (a user in several)."),worktree:Se.string().regex(DM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves."),maxBodyBytes:Se.number().int().min(1).max(Vb).optional().describe(`The most response-body bytes returned (default ${CM}, at most ${Vb}).`)},uQ=Se.object({status:Se.number(),ms:Se.number(),method:Se.string(),url:Se.string(),wsKey:Se.string(),as:BM,mode:Se.string().optional(),flowId:Se.string(),requestId:Se.string().optional(),headers:Se.record(Se.string(),Se.unknown()),body:Se.unknown(),truncated:Se.boolean().optional(),caveat:Se.string().optional(),next:Se.string().optional()}).passthrough(),lQ={worktree:Se.string().regex(DM).optional().describe("A worktree of this project by name (worktree_list), or 'main' for the main checkout. Default: the workspace this lens serves.")},dQ=Se.object({wsKey:Se.string(),identities:Se.array(BM)}).passthrough(),Kb=class extends iQ{static{l(this,"P_")}static{u(this,"AppCallTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await _M(t,e);return s.ok===!1&&this.fail(zp(s)),s}};Kb=P([nQ({name:O_.name,description:O_.description,inputSchema:oQ,outputSchema:uQ})],Kb);var cQ=Kb;import{Tool as pQ,ToolContext as hQ}from"@frontmcp/sdk";var Qb=class extends hQ{static{l(this,"L_")}static{u(this,"AppIdentitiesTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await MM(t,e);return s.ok===!1&&this.fail(zp(s)),s}};Qb=P([pQ({name:N_.name,description:N_.description,annotations:{readOnlyHint:!0},inputSchema:lQ,outputSchema:dQ})],Qb);var mQ=Qb;import{Tool as fQ,ToolContext as gQ}from"@frontmcp/sdk";var Yb=200,Pa=5,vQ=5,Xb=5,ul=u((e,t)=>`${e} ${t}`,"id");function Je(e){let t=Math.max(0,Math.round(e/1e3));if(t<90)return`${t}s`;let s=Math.round(e/6e4);return s<120?`${s}m`:`${Math.floor(s/60)}h${s%60?` ${s%60}m`:""}`}l(Je,"lt"),u(Je,"span");var e1={current:"read",stale:"its newest report is overdue \u2014 whatever it last said is no longer known",unreachable:"could not be read \u2014 its numbers are UNKNOWN, not zero",refused:"the service refused the read \u2014 its numbers are UNKNOWN, not zero",malformed:"the service answered something that is not the snapshot schema \u2014 its numbers are UNKNOWN, not zero","not-running":"its service is not running, and the lens does not start one to read it \u2014 not read","never-polled":"not read by this lens yet \u2014 its numbers are unknown, not zero"},dr=u(e=>{let t=e?Date.parse(e):NaN;return Number.isFinite(t)?t:void 0},"parse"),t1=u(e=>e.thresholds.oldestWaitMin??eZ,"oldestWaitMinOf"),s1=u(e=>e.thresholds.stalledMin??tZ,"stalledMinOf"),Gp=u(e=>e.thresholds.quotaPct??nZ,"quotaPctOf"),r1=u(e=>e.thresholds.errorRatePct??iZ,"errorRatePctOf"),n1=u(e=>e.thresholds.orphanMin??aZ,"orphanMinOf"),Zp=u(e=>e.thresholds.failurePct??oZ,"failurePctOf"),Vp=u(e=>e.thresholds.p95Ms??uZ,"p95MsOf"),i1=u(e=>e.thresholds.rateLimited??lZ,"rateLimitedOf"),a1=u((e,t)=>Math.round(e/t*1e3)/10,"pct");function ll(e){if(e<1024)return`${e} B`;let t=["KB","MB","GB","TB"],s=e/1024,n=0;for(;s>=1024&&n<t.length-1;)s/=1024,n+=1;return`${s.toFixed(1)} ${t[n]}`}l(ll,"cf"),u(ll,"bytesText");var yQ=u(e=>e.thresholds.idleMin??sZ,"idleMinOf"),o1=u(e=>({at:e.at-(e.durationMs??0),...e.outcome?{outcome:e.outcome}:{},...e.items!==void 0?{items:e.items}:{},...e.durationMs!==void 0?{durationMs:e.durationMs}:{},...e.error?{error:e.error}:{},via:"pushed"}),"runOfPushed"),u1=u(e=>e[wp[e.sourceKind]],"snapOf");function l1(e,t){let s=Math.max(1e3,t.durationMs??0),n=e.find(r=>Math.abs(r.at-t.at)<=s);if(n){t.via==="snapshot"&&(n.at=t.at),n.outcome===void 0&&t.outcome&&(n.outcome=t.outcome),n.items===void 0&&t.items!==void 0&&(n.items=t.items),n.durationMs===void 0&&t.durationMs!==void 0&&(n.durationMs=t.durationMs),n.error===void 0&&t.error&&(n.error=t.error);return}e.push(t),e.sort((r,i)=>i.at-r.at),e.length>vT&&(e.length=vT)}l(l1,"fD"),u(l1,"addRunTo");var wQ=class{static{l(this,"jl")}static{u(this,"SourceBook")}constructor(){this.held=new Map,this.declarations=new Map,this.pushed=new Map}ingest(e){if(e.source===HG)return this.ingestPushed(e);if(e.source!=="gateway"||e.category!=="cluster")return!1;let t=e.raw?.kind;if(t==="source-poll"){let s=CT(e.raw);if(!s)return!1;let n=ul(s.project,s.name),r=this.held.get(n);if(r&&r.poll.polledAt>s.polledAt)return!1;let i=r??{poll:s,awaiting:!1,history:[],groups:new Map,runs:[],storeHistory:[]};for(this.held.delete(n),this.held.set(n,i);this.held.size>Yb;)this.held.delete(this.held.keys().next().value);if(!r&&s.sourceKind==="loop")for(let a of[...this.pushed.get(n)?.recent??[]].reverse())a.event==="run-end"&&this.addRun(i,o1(a));return this.fold(i,s,r?.poll),!0}if(t==="source-declaration"){let s=DT(e.raw);if(!s)return!1;for(this.declarations.delete(s.project),this.declarations.set(s.project,s);this.declarations.size>Yb;)this.declarations.delete(this.declarations.keys().next().value);let n=new Set(s.sources.map(r=>r.name));for(let[r,i]of[...this.held])i.poll.project===s.project&&!n.has(i.poll.name)&&this.held.delete(r);return!0}return!1}fold(e,t,s){let n=wp[t.sourceKind],r=t,i=!1;if(t.same){let{same:c,...p}=t,d=s&&s.sourceKind===t.sourceKind?u1(s):void 0;d&&d.digest===c.digest?r={...p,[n]:{...d,at:c.at,receivedAt:c.receivedAt}}:(r={...p,...d?{[n]:d}:{}},i=t.state==="current")}if(e.poll=r,e.awaiting=i,r.state!=="current"||i)return;let a=u1(r);if(!a)return;let o=a.receivedAt;e.lastReadAt!==void 0&&o<=e.lastReadAt||(e.lastReadAt!==void 0&&o-e.lastReadAt>Uw(r.reportEveryMs)&&(e.groups.clear(),e.idleSince=void 0,e.orphan=void 0),e.lastReadAt=o,r.sourceKind==="loop"?this.foldLoop(e,r,r.loop):r.sourceKind==="store"?this.foldStore(e,r.store):r.sourceKind==="queue"&&this.foldQueue(e,r.snapshot))}foldStore(e,t){let s=t.receivedAt;e.storeHistory.push({t:s,objects:t.objects,bytes:t.bytes}),e.storeHistory.length>kp&&e.storeHistory.splice(0,e.storeHistory.length-kp);let n=(t.deletesInWindow??0)>0||e.orphan!==void 0&&t.objects<e.orphan.last;!e.orphan||n?e.orphan={since:s,from:t.objects,last:t.objects}:e.orphan.last=t.objects}foldQueue(e,t){let s=t.receivedAt,n=dr(t.at),r=t.groups.map(o=>o.pending>0&&n!==void 0?n-(dr(o.oldestPendingAt)??n):0),i=r.some(o=>o>0)?Math.max(...r):void 0;e.history.push({t:s,pending:t.totals.pending,inFlight:t.totals.inFlight,failed:t.totals.failed,...i!==void 0?{oldestWaitMs:i}:{}}),e.history.length>kp&&e.history.splice(0,e.history.length-kp);let a=new Set;for(let o of t.groups){if(o.pending===0)continue;a.add(o.group);let c=dr(o.oldestPendingAt),p=e.groups.get(o.group);if(!p){e.groups.set(o.group,{movedAt:s,pending:o.pending,...c!==void 0?{oldest:c}:{},...o.completedInWindow!==void 0?{completed:o.completedInWindow}:{}});continue}(o.pending<p.pending||c!==void 0&&p.oldest!==void 0&&c>p.oldest||o.completedInWindow!==void 0&&p.completed!==void 0&&o.completedInWindow>p.completed)&&(p.movedAt=s),p.pending=o.pending,c!==void 0?p.oldest=c:delete p.oldest,o.completedInWindow!==void 0?p.completed=o.completedInWindow:delete p.completed}for(let o of[...e.groups.keys()])a.has(o)||e.groups.delete(o)}foldLoop(e,t,s){let n=dr(s.lastRunAt);n!==void 0&&this.addRun(e,{at:n,...s.lastOutcome?{outcome:s.lastOutcome}:{},...s.lastItems!==void 0?{items:s.lastItems}:{},...s.lastDurationMs!==void 0?{durationMs:s.lastDurationMs}:{},...s.lastOutcome==="failed"&&s.lastError?{error:s.lastError}:{},via:"snapshot"});let r=dr(s.at)??s.receivedAt,i=s.intervalSec*1e3,a=n!==void 0&&r-n<=(bp+1)*i,o=s.lastItems!==void 0?s.lastItems>0:s.itemsInWindow!==void 0?s.itemsInWindow>0:void 0;this.judgeIdle(e,t,a?o:void 0,s.receivedAt)}judgeIdle(e,t,s,n){e.idleSince=this.idleFrom(e.idleSince,t.project,t.feeds,s,n)}idleFrom(e,t,s,n,r){let i=s?this.held.get(ul(t,s)):void 0,a=i&&i.poll.state==="current"&&!i.awaiting?i.poll.snapshot:void 0;return n===!1&&a&&a.totals.pending>0?e??r:void 0}addRun(e,t){l1(e.runs,t)}pushRun(e,t,s){if(t.event==="run-start"){e.runningSince=s;return}e.runningSince=void 0,l1(e.loopRuns??=[],o1(e.recent[0]));let n=this.declarations.get(t.project)?.sources.find(r=>r.name===t.name)?.feeds;e.idleSince=this.idleFrom(e.idleSince,t.project,n,t.items===void 0?void 0:t.items>0,s)}ingestPushed(e){let t=IT(e.raw);if(!t)return!1;let s=ul(t.project,t.name),n=e.timestamp,r=this.pushed.get(s);if(!r)for(r={project:t.project,sourceKind:t.sourceKind,name:t.name,counts:{},since:n,lastAt:n,recent:[],suppressed:0},this.pushed.set(s,r);this.pushed.size>Yb;)this.pushed.delete(this.pushed.keys().next().value);r.counts[t.event]=(r.counts[t.event]??0)+1,r.since=Math.min(r.since,n),r.lastAt=Math.max(r.lastAt,n),r.suppressed+=t.floodSuppressed??0,r.recent.unshift({at:n,event:t.event,...t.item?{item:t.item}:{},...t.group?{group:t.group}:{},...t.items!==void 0?{items:t.items}:{},...t.durationMs!==void 0?{durationMs:t.durationMs}:{},...t.outcome?{outcome:t.outcome}:{},...t.object?{object:t.object}:{},...t.bytes!==void 0?{bytes:t.bytes}:{},...t.channel?{channel:t.channel}:{},...t.counterpart?{counterpart:t.counterpart}:{},...t.correlation?{correlation:t.correlation}:{},...t.error?{error:t.error.slice(0,500)}:{},...e.context.flowId?{flowId:e.context.flowId}:{},...e.context.requestId?{requestId:e.context.requestId}:{}}),r.recent.length>yT&&(r.recent.length=yT),t.sourceKind==="traffic"&&t.channel&&this.pushChannel(r,t,n),t.sourceKind==="loop"&&this.pushRun(r,t,n);let i=this.held.get(s);if(i&&i.poll.sourceKind===t.sourceKind)if(t.sourceKind==="queue"&&(t.event==="admitted"||t.event==="completed")){let a=t.group?[i.groups.get(t.group)].filter(o=>!!o):[...i.groups.values()];for(let o of a)o.movedAt=Math.max(o.movedAt,n)}else t.sourceKind==="loop"&&t.event==="run-end"?(this.addRun(i,o1(r.recent[0])),t.items!==void 0&&this.judgeIdle(i,i.poll,t.items>0,n)):t.sourceKind==="store"&&t.event==="delete"&&(i.orphan=void 0);return!0}pushChannel(e,t,s){let n=e.channels??=new Map,r=t.channel,i=n.get(r);if(!i&&(i={events:[],held:[],lastAt:s},n.set(r,i),n.size>cZ)){let a=[...n.entries()].sort((o,c)=>o[1].lastAt-c[1].lastAt)[0][0];n.delete(a)}i.direction=t.event==="inbound"?"inbound":"outbound",t.counterpart&&(i.counterpart=t.counterpart),t.error&&t.outcome!=="ok"&&(i.lastError=t.error.slice(0,500)),i.lastAt=Math.max(i.lastAt,s),i.events.push({t:s,...t.outcome?{outcome:t.outcome}:{},...t.durationMs!==void 0?{durationMs:t.durationMs}:{}}),i.events.length>wT&&i.events.splice(0,i.events.length-wT),t.floodSuppressed&&(i.held.push({t:s,n:t.floodSuppressed}),i.held.length>100&&i.held.shift())}report(e){let t=[];for(let[p,d]of this.held)t.push(jM(d,e,this.pushed.get(p)));for(let p of this.declarations.values())for(let d of p.sources){let h=ul(p.project,d.name);if(this.held.has(h))continue;let m=this.pushed.get(h);t.push(d.path!==void 0?qM(p.project,d,m):d.sourceKind==="loop"?LM(p.project,d,m,e):FM(p.project,d,m,e))}t.sort((p,d)=>p.project<d.project?-1:p.project>d.project?1:p.name<d.name?-1:p.name>d.name?1:0);for(let p of t){if(!p.loop||!p.feeds)continue;let d=t.find(h=>h.project===p.project&&h.name===p.feeds&&h.sourceKind==="queue");d&&(p.loop.fed={name:d.name,state:d.state,...d.headline?{pending:d.headline.pending}:{}})}let s=t.flatMap(p=>WM(p,e)).sort((p,d)=>(d.oldestWaitMs??d.forMs??0)-(p.oldestWaitMs??p.forMs??0)),n=Object.fromEntries(XG.map(p=>[p,0])),r={pending:0,inFlight:0,failed:0};for(let p of t)n[p.state]+=1,p.state==="current"&&p.headline&&(r.pending+=p.headline.pending,r.inFlight+=p.headline.inFlight,r.failed+=p.headline.failed);let i=[...this.declarations.values()].flatMap(p=>p.problems.map(d=>({project:p.project,problem:d}))),a=new Set(t.map(p=>ul(p.project,p.name))),o=[...this.pushed.entries()].filter(([p])=>!a.has(p)).map(([,p])=>({project:p.project,sourceKind:p.sourceKind,name:p.name,events:Object.values(p.counts).reduce((d,h)=>d+h,0),lastAt:p.lastAt})),c=t.length===0&&i.length===0&&o.length===0;return{provenance:"reported",producer:c?"none":"connected",...c?{detail:'no service declares a custom source \u2014 work an app keeps waiting in its own tables (an outbox) is not watched; declare it in project.json `cluster.sources` (kind "queue", "loop" for the loop that drains it, "store" for a storage backend, "traffic" for messages over a channel no tap classifies)'}:{},readAt:e,sources:t,findings:s,problems:i,...o.length?{undeclared:o}:{},counts:n,totals:r}}};function dl(e){return e?{pushed:{counts:{...e.counts},since:e.since,lastAt:e.lastAt,recent:e.recent.map(t=>({...t})),...e.suppressed?{suppressed:e.suppressed}:{}}}:{}}l(dl,"df"),u(dl,"pushedView");function qM(e,t,s){return{provenance:"reported",project:e,...t,state:"never-polled",detail:"no poll of it has reached the lens yet",groups:[],...dl(s)}}l(qM,"pY"),u(qM,"neverPolled");function jM(e,t,s){let n=e.poll,r=t-n.polledAt>Uw(n.reportEveryMs),i=r?"stale":e.awaiting?"never-polled":n.state,a=r?`its last report (${n.state}${n.detail?`: ${n.detail}`:""}) is ${Je(t-n.polledAt)} old and was due every ${Je(n.reportEveryMs)} \u2014 nothing has polled it since; is the dev gateway running?`:e.awaiting?"polled, but its full snapshot has not reached this lens (it started after the report that carried it); the gateway sends one at least once a minute":n.detail,o=u1(n),c={provenance:"reported",project:n.project,sourceKind:n.sourceKind,name:n.name,path:n.path,intervalSec:n.intervalSec,thresholds:n.thresholds,...n.feeds?{feeds:n.feeds}:{},state:i,...a!==void 0?{detail:a}:{},...n.status!==void 0?{status:n.status}:{},polledAt:n.polledAt,...n.failures?{failures:n.failures}:{},...o?{ageMs:Math.max(0,t-o.receivedAt),snapshotAt:o.at}:{},groups:[],...dl(s)};switch(n.sourceKind){case"loop":return zM(c,e,n.loop);case"store":return RM(c,e,n.store,i==="current");case"traffic":return n.traffic?{...c,traffic:OM(c,n.traffic)}:c;default:return UM(c,e,n.snapshot,i==="current")}}l(jM,"hY"),u(jM,"viewOf");function RM(e,t,s,n){let r=t.storeHistory.length?{storeHistory:t.storeHistory.map(v=>({...v}))}:{};if(!s)return{...e,...r};let{at:i,receivedAt:a,digest:o,...c}=s,p=s.quotaBytes?a1(s.bytes,s.quotaBytes):void 0,d=s.opsInWindow&&s.errorsInWindow!==void 0?a1(s.errorsInWindow,s.opsInWindow):void 0,h=n?t.orphan:void 0,m=h!==void 0&&s.objects>h.from,f={...c,...p!==void 0?{usedPct:p}:{},nearQuota:p!==void 0&&p>=Gp(e),...d!==void 0?{errorRatePct:d}:{},...m?{growingSince:h.since,growingFrom:h.from}:{}};return{...e,store:f,...r}}l(RM,"mY"),u(RM,"storeViewOf");function OM(e,t){let s=t.channels.map(n=>d1(e,n));return s.sort((n,r)=>(r.messagesInWindow??0)-(n.messagesInWindow??0)||(n.channel<r.channel?-1:1)),{pushOnly:!1,...t.windowSec!==void 0?{windowSec:t.windowSec}:{},channels:s,...t.truncated?{truncated:t.truncated}:{},totals:NM(s)}}l(OM,"fY"),u(OM,"trafficViewOf");function d1(e,t){let s=t.messagesInWindow&&t.failuresInWindow!==void 0?a1(t.failuresInWindow,t.messagesInWindow):void 0;return{...t,...s!==void 0?{failurePct:s}:{},overFailure:s!==void 0&&(t.messagesInWindow??0)>=dZ&&s>Zp(e),overLatency:t.p95Ms!==void 0&&t.p95Ms>Vp(e),rateLimited:(t.rateLimitedInWindow??0)>=i1(e)}}l(d1,"yD"),u(d1,"judgeChannel");var NM=u(e=>({channels:e.length,messages:e.reduce((t,s)=>t+(s.messagesInWindow??0),0),failures:e.reduce((t,s)=>t+(s.failuresInWindow??0),0),rateLimited:e.reduce((t,s)=>t+(s.rateLimitedInWindow??0),0)}),"totalsOf");function PM(e,t){if(!e.length)return;let s=[...e].sort((n,r)=>n-r);return s[Math.min(s.length-1,Math.max(0,Math.ceil(t*s.length)-1))]}l(PM,"gY"),u(PM,"percentile");function LM(e,t,s,n){let r={provenance:"reported",project:e,...t,groups:[],state:"never-polled",...dl(s)},i=s?.loopRuns??[];if(!s||!i.length&&s.runningSince===void 0)return{...r,detail:"push-only: no run pushed yet \u2014 it has not run since the lens started, or the app does not call lensEmitCustom"};let a=t.intervalSec*1e3,o=i[0],c=s.runningSince??o.at+(o.durationMs??0),p=n-(c+a),d=0;for(let m of i){if(m.outcome!=="failed")break;d+=1}let h={intervalSec:t.intervalSec,lastRunAt:o?new Date(o.at).toISOString():null,...o?.durationMs!==void 0?{lastDurationMs:o.durationMs}:{},...o?.outcome?{lastOutcome:o.outcome}:{},...o?.items!==void 0?{lastItems:o.items}:{},...o?.error?{lastError:o.error}:{},...p>0?{lateMs:p}:{},overdue:p>bp*a,failingRuns:d,...s.idleSince!==void 0?{idleSince:s.idleSince}:{},pushOnly:!0,...s.runningSince!==void 0?{runningSince:s.runningSince}:{}};return{...r,state:"current",detail:"push-only: read from the runs the app pushed",ageMs:Math.max(0,n-s.lastAt),snapshotAt:new Date(n).toISOString(),loop:h,...i.length?{runs:i.map(m=>({...m}))}:{}}}l(LM,"yY"),u(LM,"pushOnlyLoopView");function FM(e,t,s,n){let r={provenance:"reported",project:e,...t,groups:[],state:"never-polled",...dl(s)};if(!s?.channels?.size)return{...r,detail:"push-only: nothing pushed yet \u2014 no traffic on it, or the app does not call lensEmitCustom"};let i=n-Lw,a=0,o=[...s.channels.entries()].map(([p,d])=>{let h=d.events.filter(g=>g.t>=i),m=d.held.filter(g=>g.t>=i).reduce((g,y)=>g+y.n,0);a+=m;let f=h.map(g=>g.durationMs).filter(g=>g!==void 0),v=PM(f,.95);return d1(r,{channel:p,...d.direction?{direction:d.direction}:{},...d.counterpart?{counterpart:d.counterpart}:{},messagesInWindow:h.length+m,failuresInWindow:h.filter(g=>g.outcome==="failed").length,rateLimitedInWindow:h.filter(g=>g.outcome==="rate-limited").length,...v!==void 0?{p95Ms:v}:{},lastAt:new Date(d.lastAt).toISOString(),...d.lastError?{lastError:d.lastError}:{}})});o.sort((p,d)=>(d.messagesInWindow??0)-(p.messagesInWindow??0)||(p.channel<d.channel?-1:1));let c={pushOnly:!0,windowSec:Lw/1e3,channels:o,totals:NM(o),...a?{heldBack:a}:{}};return{...r,state:"current",detail:`push-only: counted from what the app pushed in the last ${Je(Lw)}${a?` \u2014 its flood guard held back ${a}, so every count is a floor`:""}`,ageMs:Math.max(0,n-s.lastAt),traffic:c}}l(FM,"wY"),u(FM,"pushOnlyView");function UM(e,t,s,n){let r=t1(e)*6e4,i=s1(e)*6e4,a=dr(s?.at),o=(s?.groups??[]).map(p=>{let d=p.pending>0&&p.oldestPendingAt&&a!==void 0?Math.max(0,a-Date.parse(p.oldestPendingAt)):void 0,h=d!==void 0&&Number.isFinite(d),m=n&&p.pending>0&&s?t.groups.get(p.group):void 0,f=m?s.receivedAt-m.movedAt:0;return{...p,...h?{oldestWaitMs:d}:{},overThreshold:h&&d>r,...f>0?{stillMs:f}:{},stalled:f>=i}});o.sort((p,d)=>(d.oldestWaitMs??-1)-(p.oldestWaitMs??-1)||d.pending-p.pending);let c=o.map(p=>p.oldestWaitMs).filter(p=>p!==void 0);return{...e,...s?{headline:{...s.totals,...c.length?{oldestWaitMs:Math.max(...c)}:{},overThreshold:o.filter(p=>p.overThreshold).length,stalled:o.filter(p=>p.stalled).length}}:{},groups:o,...s?.truncated?{truncated:s.truncated}:{},...t.history.length?{history:t.history.map(p=>({...p}))}:{}}}l(UM,"vY"),u(UM,"queueViewOf");function zM(e,t,s){let n=t.runs.map(g=>({...g}));if(!s)return{...e,...n.length?{runs:n}:{}};let{at:r,receivedAt:i,digest:a,...o}=s,c=dr(s.at)??s.receivedAt,p=s.intervalSec*1e3,d=dr(s.lastRunAt),h=dr(s.nextRunAt)??(d!==void 0?d+p:void 0),m=h!==void 0&&c>h?c-h:void 0,f=0;for(let g of n){if(g.outcome!=="failed")break;f+=1}!n.length&&s.lastOutcome==="failed"&&(f=1);let v={...o,...m!==void 0?{lateMs:m}:{},overdue:m!==void 0&&m>bp*p,failingRuns:f,...t.idleSince!==void 0?{idleSince:t.idleSince}:{}};return{...e,loop:v,...n.length?{runs:n}:{}}}l(zM,"bY"),u(zM,"loopViewOf");function WM(e,t){if(e.state!=="current")return[];switch(e.sourceKind){case"loop":return GM(e,t);case"store":return ZM(e,t);case"traffic":return VM(e);default:return HM(e)}}l(WM,"kY"),u(WM,"findingsOf");var on=u(e=>({provenance:"reported",project:e.project,name:e.name,sourceKind:e.sourceKind}),"base"),St=u(e=>`source_get { service: "${e.project}", name: "${e.name}" }`,"getSource");function HM(e){let t=t1(e),s=s1(e),n=[];for(let r of e.groups)r.overThreshold&&n.push({rule:qG,...on(e),group:r.group,...r.labels?{labels:r.labels}:{},pending:r.pending,oldestWaitMs:r.oldestWaitMs,thresholdMin:t,title:`${e.project} \xB7 ${e.name} (reported): ${r.group} \u2014 ${r.pending} pending, the oldest waiting ${Je(r.oldestWaitMs)} (over ${t} min)`,fix:[`Find why ${e.project} is not draining "${e.name}": is the process that takes this work running (service_state { service: "${e.project}" } \u2014 its workers), and is it failing (observe_errors { project: "${e.project}" })?`,"If a gate holds the work on purpose (a quiet window, a rate limit, a cap per tenant), the wait is the gate working: raise thresholds.oldestWaitMin on this source in cluster.sources instead of ignoring the warning.",`Read the group in full \u2014 its labels, in-flight and failed counts \u2014 with ${St(e)}.`],verify:`${St(e)}: the group's oldest wait under ${t} min, or the group gone`}),r.stalled&&r.stillMs!==void 0&&n.push({rule:jG,...on(e),group:r.group,...r.labels?{labels:r.labels}:{},pending:r.pending,forMs:r.stillMs,thresholdMin:s,title:`${e.project} \xB7 ${e.name} (reported): ${r.group} \u2014 ${r.pending} pending and nothing taken or finished for ${Je(r.stillMs)} (stalled: over ${s} min)`,fix:[`Nothing drains this group: is the loop or worker that takes "${e.name}" running and taking work (observe_sources { service: "${e.project}", kind: "loop" }; service_state { service: "${e.project}" } \u2014 its workers)?`,`Is the work failing as it is taken (observe_errors { project: "${e.project}" })? An item that fails and goes back to pending moves nothing.`,"If a gate holds this group on purpose (a rate-limit hold, a per-tenant cap), raise thresholds.stalledMin on this source in cluster.sources."],verify:`${St(e)}: the group's pending falls, or its oldest item changes, within ${s} min`});return n}l(HM,"SY"),u(HM,"queueFindings");function GM(e,t){let s=e.loop;if(!s)return[];let n=[],r=Je(s.intervalSec*1e3),i=s.lastRunAt?`its last run began ${s.lastRunAt}`:"it has not run since its service started";s.overdue&&s.lateMs!==void 0&&n.push({rule:RG,...on(e),forMs:s.lateMs,title:s.runningSince!==void 0?`${e.project} \xB7 ${e.name} (reported loop): a run began ${Je(s.lateMs+s.intervalSec*1e3)} ago and has not ended \u2014 it runs every ${r}`:`${e.project} \xB7 ${e.name} (reported loop): its next run is ${Je(s.lateMs)} late \u2014 it runs every ${r}; ${i}`,fix:[`Is the process that runs "${e.name}" alive (service_state { service: "${e.project}" } \u2014 its workers), and is a run stuck (a long await, a lock)? Its errors: observe_errors { project: "${e.project}" }.`,`What the loop says of itself in full: ${St(e)}.`],verify:`${St(e)}: lastRunAt within ${bp} intervals of now, and not overdue`});let a=e.runs??[];if(s.failingRuns>=rZ){let p=a.slice(0,s.failingRuns),d=p.length>1?p[0].at-p[p.length-1].at:void 0,h=p.find(m=>m.error)?.error??s.lastError;n.push({rule:OG,...on(e),...d!==void 0?{forMs:d}:{},title:`${e.project} \xB7 ${e.name} (reported loop): its last ${s.failingRuns} runs failed${h?` \u2014 ${h.slice(0,200)}`:""}`,fix:[`Read why it fails: observe_errors { project: "${e.project}" }, and the runs in full with ${St(e)}.`,"Fix the cause, then let it run once: the next run that ends `ok` clears this."],verify:`${St(e)}: the newest run's outcome is ok`})}let o=s.fed,c=yQ(e);if(s.idleSince!==void 0&&o&&o.state==="current"&&(o.pending??0)>0){let p=Math.max(0,t-(e.ageMs??0)-s.idleSince);p>=c*6e4&&n.push({rule:NG,...on(e),pending:o.pending,forMs:p,thresholdMin:c,title:`${e.project} \xB7 ${e.name} (reported loop): it runs and takes nothing \u2014 for ${Je(p)} \u2014 while "${o.name}" has ${o.pending} pending (over ${c} min)`,fix:[`Something it checks before it takes work says no: a gate (a quiet window, a rate-limit hold, a per-tenant cap), a filter that matches nothing, or a lock it cannot get. Read what it says of itself with ${St(e)} and what waits with source_get { service: "${e.project}", name: "${o.name}" }.`,"If the gate holds the work on purpose for this long, raise thresholds.idleMin on this loop in cluster.sources."],verify:`${St(e)}: a run that takes items (lastItems > 0), or "${o.name}" with nothing pending`})}return n}l(GM,"xY"),u(GM,"loopFindings");var Jp=u(e=>e?`the last ${Je(e*1e3)}`:"its window","windowText");function ZM(e,t){let s=e.store;if(!s)return[];let n=[],r=`${e.project} \xB7 ${e.name} (reported store)`;s.nearQuota&&s.usedPct!==void 0&&s.quotaBytes&&n.push({rule:PG,...on(e),value:s.usedPct,threshold:Gp(e),title:`${r}: ${s.usedPct}% of its quota used \u2014 ${ll(s.bytes)} of ${ll(s.quotaBytes)} (at or over ${Gp(e)}%)`,fix:[`What fills it: ${St(e)} \u2014 its groups, the largest first. Delete what nothing reads any more, or raise the quota where it is set.`,"If writes will fail at the quota, that is the failure to prevent: the app's writes into it error once it is full."],verify:`${St(e)}: usedPct under ${Gp(e)}`});let i=s.errorsInWindow??0;if(i>0&&(s.errorRatePct===void 0||s.errorRatePct>r1(e))&&n.push({rule:LG,...on(e),value:s.errorRatePct??i,threshold:r1(e),title:`${r}: ${i} failed operation${i===1?"":"s"} in ${Jp(s.windowSec)}${s.errorRatePct!==void 0?` \u2014 ${s.errorRatePct}% of ${s.opsInWindow} (over ${r1(e)}%)`:""}${s.lastError?`: ${s.lastError.slice(0,200)}`:""}`,fix:[`Read why: the last error is in ${St(e)} (lastError); the service's own errors: observe_errors { project: "${e.project}" }.`,"A permission, a full disk or a missing bucket fails every write the same way \u2014 fix the cause, then let it write again."],verify:`${St(e)}: errorsInWindow 0 once its window has passed`}),s.growingSince!==void 0&&s.growingFrom!==void 0){let a=Math.max(0,t-(e.ageMs??0)-s.growingSince);a>=n1(e)*6e4&&n.push({rule:FG,...on(e),forMs:a,thresholdMin:n1(e),value:s.objects-s.growingFrom,title:`${r}: it grew from ${s.growingFrom} to ${s.objects} objects over ${Je(a)} and deleted nothing (over ${n1(e)} min) \u2014 what removes them?`,fix:["Objects that are written and never deleted are what nothing cleans up: a file kept after its record was deleted, a temporary upload never removed, a version never pruned. Find the write that has no matching delete.","If the store only ever grows by design (an archive), raise thresholds.orphanMin on this source in cluster.sources (at most 10080)."],verify:`${St(e)}: deletesInWindow above 0, or the objects stop growing`})}return n}l(ZM,"$Y"),u(ZM,"storeFindings");function VM(e){let t=e.traffic;if(!t)return[];let s=[],n=Jp(t.windowSec);for(let r of t.channels){let i=`${e.project} \xB7 ${e.name} (reported traffic): ${r.channel}${r.counterpart?` ${r.direction==="inbound"?"\u2190":"\u2192"} ${r.counterpart}`:""}`,a={...on(e),channel:r.channel,...r.labels?{labels:r.labels}:{}};r.rateLimited&&s.push({rule:WG,...a,value:r.rateLimitedInWindow??0,threshold:i1(e),title:`${i}: answered \xABtoo many requests\xBB ${r.rateLimitedInWindow} time${r.rateLimitedInWindow===1?"":"s"} in ${n}${r.messagesInWindow?` of ${r.messagesInWindow} messages`:""}`,fix:[`The other end limits how fast it is called: spread the calls (a queue with a rate limit, a backoff that honours Retry-After), batch them, or cache what is read again. What calls it: ${St(e)} \u2014 the pushed events carry the flow each ran in.`],verify:`${St(e)}: rateLimitedInWindow under ${i1(e)} on ${r.channel}`}),r.overFailure&&r.failurePct!==void 0&&s.push({rule:UG,...a,value:r.failurePct,threshold:Zp(e),title:`${i}: ${r.failuresInWindow} of ${r.messagesInWindow} messages failed in ${n} (${r.failurePct}%, over ${Zp(e)}%)${r.lastError?`: ${r.lastError.slice(0,200)}`:""}`,fix:[`Read why they fail: the last error (lastError) and the pushed events with their flows in ${St(e)}; the service's errors: observe_errors { project: "${e.project}" }.`],verify:`${St(e)}: failures on ${r.channel} under ${Zp(e)}% of its messages`}),r.overLatency&&r.p95Ms!==void 0&&s.push({rule:zG,...a,value:r.p95Ms,threshold:Vp(e),title:`${i}: p95 ${Math.round(r.p95Ms)} ms in ${n} (over ${Vp(e)} ms)`,fix:[`Slow at the other end, or waiting before it is sent (a pool, a lock, a rate limiter)? Open a slow one's flow from ${St(e)} and see where its time went.`],verify:`${St(e)}: p95 on ${r.channel} under ${Vp(e)} ms`})}return s}l(VM,"_Y"),u(VM,"trafficFindings");async function c1(e){try{let t=await e.read(ds);return t&&Array.isArray(t.sources)?t:void 0}catch{return}}l(c1,"vD"),u(c1,"readReport");function p1(e){let t=e.loop,s=dr(e.snapshotAt),n=dr(t.lastRunAt),r=n===void 0||s===void 0?"it has not run since its service started":`its last run began ${Je(s-n)} ${t.pushOnly?"ago":"before it was measured"}${t.lastOutcome?` and ended ${t.lastOutcome}`:""}${t.lastItems!==void 0?`, ${t.lastItems} item${t.lastItems===1?"":"s"} taken`:""}`,i=t.overdue&&t.lateMs!==void 0?` \u2014 its next run is ${Je(t.lateMs)} LATE (it runs every ${Je(t.intervalSec*1e3)})`:"",a=t.failingRuns>=2?` \u2014 its last ${t.failingRuns} runs failed${t.lastError?`: ${t.lastError.slice(0,160)}`:""}`:"",o=t.idleSince!==void 0&&t.fed?` \u2014 taking nothing while "${t.fed.name}" has ${t.fed.pending??"?"} pending`:"";return`${r}${i}${a}${o}`}l(p1,"gD"),u(p1,"loopWords");function JM(e){let t=e.store,s=t.quotaBytes?` of ${ll(t.quotaBytes)} (${t.usedPct}%${t.nearQuota?" \u2014 NEAR ITS QUOTA":""})`:"",n=[t.writesInWindow!==void 0?`${t.writesInWindow} writes`:"",t.deletesInWindow!==void 0?`${t.deletesInWindow} deletes`:"",t.errorsInWindow!==void 0?`${t.errorsInWindow} errors${t.errorRatePct!==void 0?` (${t.errorRatePct}%)`:""}`:""].filter(Boolean).join(", "),r=t.growingSince!==void 0&&t.growingFrom!==void 0?` \u2014 grown from ${t.growingFrom} objects with nothing deleted`:"";return`${t.objects} objects, ${ll(t.bytes)}${s}${n?` \u2014 ${n} in ${Jp(t.windowSec)}`:""}${r}`}l(JM,"EY"),u(JM,"storeWords");function KM(e){let t=e.traffic,s=t.totals,n=t.channels.filter(i=>i.rateLimited||i.overFailure||i.overLatency).map(i=>{let a=[i.rateLimited?`${i.rateLimitedInWindow} rate-limited`:"",i.overFailure?`${i.failurePct}% failed`:"",i.overLatency?`p95 ${Math.round(i.p95Ms??0)} ms`:""].filter(Boolean).join(", ");return`${i.channel}: ${a}`}),r=t.heldBack?` (a floor \u2014 ${t.heldBack} held back by the app's flood guard)`:"";return`${s.messages} message${s.messages===1?"":"s"} on ${s.channels} channel${s.channels===1?"":"s"} in ${Jp(t.windowSec)}${r}, ${s.failures} failed, ${s.rateLimited} rate-limited${t.pushOnly?" \u2014 counted from what the app pushed":""}${n.length?` \u2014 ${n.join("; ")}`:""}`}l(KM,"AY"),u(KM,"trafficWords");function h1(e){let t=`${e.project} \xB7 ${e.name} (${e.sourceKind}, reported)`;if(e.sourceKind==="store"||e.sourceKind==="traffic"){let r=e.store?JM(e):e.traffic?KM(e):void 0;if(e.state==="current"&&r)return`${t}: ${r} (${e.traffic?.pushOnly?`last pushed ${Je(e.ageMs??0)} ago`:`read ${Je(e.ageMs??0)} ago`}).`;let i=r?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${r}`:"";return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${i}.`}if(e.sourceKind==="loop"){if(e.state==="current"&&e.loop)return`${t}: ${p1(e)} (${e.loop.pushOnly?`last pushed ${Je(e.ageMs??0)} ago`:`read ${Je(e.ageMs??0)} ago`}).`;let r=e.loop?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${p1(e)}`:"";return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${r}.`}let s=e.headline,n=s?` \u2014 the last good snapshot, ${Je(e.ageMs??0)} old, said ${s.pending} pending`:"";if(e.state==="current"&&s){let r=s.oldestWaitMs!==void 0?`, the oldest waiting ${Je(s.oldestWaitMs)}`:"",i=s.overThreshold?` \u2014 ${s.overThreshold} group${s.overThreshold===1?"":"s"} over ${t1(e)} min`:"",a=s.stalled?` \u2014 ${s.stalled} group${s.stalled===1?"":"s"} STALLED (nothing taken or finished for over ${s1(e)} min)`:"",o=e.truncated?` (the service dropped ${e.truncated.groups} more groups)`:"";return s.groups===0&&s.pending===0?`${t}: nothing pending (read ${Je(e.ageMs??0)} ago).`:`${t}: ${s.pending} pending in ${s.groups} group${s.groups===1?"":"s"}${r}${i}${a}${o} (read ${Je(e.ageMs??0)} ago).`}return`${t}: ${e.state.toUpperCase()} \u2014 ${e.detail?`${e.detail}; `:""}${e1[e.state]}${n}.`}l(h1,"Z_"),u(h1,"sourceSentence");var bQ=u((e,t)=>e.pushed?{pushed:{counts:e.pushed.counts,lastAgoMs:Math.max(0,t-e.pushed.lastAt),...e.pushed.suppressed?{suppressed:e.pushed.suppressed}:{}}}:{},"pushedSummary");async function QM(e,t={}){let s=await c1(e);if(!s)return{found:!1,provenance:"reported",reason:"no dev cluster has reported a custom source into this session \u2014 the gateway reads `cluster.sources` and polls them"};let n=u(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind),"pick"),r=s.sources.filter(n),i=s.findings.filter(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind)),a=s.problems.filter(p=>!t.service||p.project===t.service),o=(s.undeclared??[]).filter(p=>(!t.service||p.project===t.service)&&(!t.kind||p.sourceKind===t.kind));if(s.producer==="none")return{found:!0,provenance:"reported",readAt:s.readAt,sources:[],findings:[],problems:a,answer:s.detail??"no service declares a custom source."};let c=r.length?r.map(h1).join(" "):`no declared source matches${t.service?` service "${t.service}"`:""}${t.kind?` kind "${t.kind}"`:""} \u2014 declared: ${s.sources.map(p=>`${p.project}/${p.name}`).join(", ")||"none"}.`;return{found:!0,provenance:"reported",readAt:s.readAt,sources:r.map(p=>({provenance:p.provenance,service:p.project,name:p.name,kind:p.sourceKind,state:p.state,...p.detail?{detail:p.detail}:{},...p.ageMs!==void 0?{ageMs:p.ageMs}:{},...p.polledAt!==void 0?{polledAt:p.polledAt}:{},...p.headline?{headline:p.headline}:{},...p.loop?{loop:p.loop}:{},...p.store?{store:{...p.store,...p.store.groups?{groups:p.store.groups.slice(0,Pa)}:{}}}:{},...p.store?.groups&&p.store.groups.length>Pa?{moreGroups:p.store.groups.length-Pa}:{},...p.traffic?{traffic:{...p.traffic,channels:p.traffic.channels.slice(0,Xb)}}:{},...p.traffic&&p.traffic.channels.length>Xb?{moreChannels:p.traffic.channels.length-Xb}:{},...p.feeds?{feeds:p.feeds}:{},thresholds:p.thresholds,findings:i.filter(d=>d.project===p.project&&d.name===p.name).map(d=>d.title),...p.groups.length?{oldestGroups:p.groups.slice(0,Pa).map(d=>({group:d.group,pending:d.pending,...d.oldestWaitMs!==void 0?{oldestWaitMs:d.oldestWaitMs}:{},overThreshold:d.overThreshold,...d.stillMs!==void 0?{stillMs:d.stillMs}:{},stalled:d.stalled}))}:{},...p.groups.length>Pa?{moreGroups:p.groups.length-Pa}:{},...p.runs?.length?{recentRuns:p.runs.slice(0,vQ)}:{},...bQ(p,s.readAt)})),findings:i.length,...a.length?{problems:a}:{},...o.length?{undeclared:o}:{},answer:o.length?`${c} ${o.map(p=>`${p.project} pushes ${p.sourceKind} events for "${p.name}" (${p.events}), which no cluster.sources entry of ${p.project} declares \u2014 they are read nowhere until it is declared.`).join(" ")}`:c,hint:"Numbers are REPORTED by each service, not measured by the lens. Only a `current` source was read; every other state means its numbers are unknown, not zero. One source in full \u2014 every group or channel, its history, a loop's runs, what the app pushed and the flows it pushed them from: source_get { service, name }."}}l(QM,"J_"),u(QM,"readSources");async function YM(e,t){let s=await c1(e);if(!s)return{found:!1,provenance:"reported",reason:"no dev cluster has reported a custom source into this session"};let n=s.sources.find(r=>r.project===t.service&&r.name===t.name);if(!n){let r=s.undeclared?.find(i=>i.project===t.service&&i.name===t.name);return{found:!1,provenance:"reported",service:t.service,name:t.name,reason:r?`${t.service} pushes ${r.sourceKind} events for "${t.name}" (${r.events}), but no cluster.sources entry of ${t.service} declares it \u2014 declare it (with the route that answers its snapshot) to read it`:"no declared source of that service and name \u2014 `service` is the Nx project, `name` the declaration's",declared:s.sources.map(i=>({service:i.project,name:i.name}))}}return{found:!0,...n,service:n.project,findings:s.findings.filter(r=>r.project===n.project&&r.name===n.name),answer:h1(n)}}l(YM,"Q_"),u(YM,"readSource");import{z as le}from"@frontmcp/sdk";var Ot=le.object({}).passthrough(),kQ={service:le.string().min(1).optional().describe(`Only this service's sources \u2014 its Nx project name, e.g. "engine".`),kind:le.enum(Ib.kinds).optional().describe('Only sources of this kind: "queue", "loop", "store" or "traffic".')},$Q=le.object({provenance:le.string(),readAt:le.number(),sources:le.array(le.object({provenance:le.string().optional(),service:le.string(),name:le.string(),kind:le.string(),state:le.string(),detail:le.string().optional(),ageMs:le.number().optional(),polledAt:le.number().optional(),headline:Ot.optional(),loop:Ot.optional(),store:Ot.optional(),traffic:Ot.optional(),feeds:le.string().optional(),thresholds:Ot.optional(),findings:le.array(le.string()),oldestGroups:le.array(Ot).optional(),moreGroups:le.number().optional(),moreChannels:le.number().optional(),recentRuns:le.array(Ot).optional(),pushed:Ot.optional()}).passthrough()),findings:le.union([le.number(),le.array(le.unknown())]),problems:le.array(le.object({project:le.string(),problem:le.string()}).passthrough()).optional(),undeclared:le.array(le.object({project:le.string(),sourceKind:le.string(),name:le.string(),events:le.number()}).passthrough()).optional(),answer:le.string(),hint:le.string().optional()}).passthrough(),xQ={service:le.string().min(1).describe('The service \u2014 its Nx project name, e.g. "engine".'),name:le.string().min(1).describe("The source's name, as `cluster.sources` declares it (observe_sources lists them).")},EQ=le.object({provenance:le.string().optional(),service:le.string(),project:le.string().optional(),name:le.string(),sourceKind:le.string().optional(),state:le.string(),detail:le.string().optional(),ageMs:le.number().optional(),polledAt:le.number().optional(),snapshotAt:le.string().optional(),intervalSec:le.number().optional(),thresholds:Ot.optional(),headline:Ot.optional(),groups:le.array(Ot).optional(),history:le.array(Ot).optional(),loop:Ot.optional(),runs:le.array(Ot).optional(),store:Ot.optional(),storeHistory:le.array(Ot).optional(),traffic:Ot.optional(),pushed:Ot.optional(),findings:le.array(le.object({rule:le.string(),title:le.string(),fix:le.array(le.string()),verify:le.string()}).passthrough()),answer:le.string()}).passthrough(),m1=class extends gQ{static{l(this,"X_")}static{u(this,"ObserveSourcesTool")}async execute(e){let t=await QM(this.get(X),e);t.found||this.fail(Wt(t.reason));let{found:s,...n}=t;return n}};m1=P([fQ({name:Ib.name,description:Ib.description,annotations:{readOnlyHint:!0},inputSchema:kQ,outputSchema:$Q})],m1);var SQ=m1;import{Tool as AQ,ToolContext as CQ}from"@frontmcp/sdk";var f1=class extends CQ{static{l(this,"eE")}static{u(this,"SourceGetTool")}async execute(e){let t=await YM(this.get(X),e);t.found||("declared"in t&&this.fail(Bn(`${t.reason}. Declared: ${nn((t.declared??[]).map(r=>`${r.service}/${r.name}`))||"none"}.`)),this.fail(Wt(t.reason)));let{found:s,...n}=t;return n}};f1=P([AQ({name:W_.name,description:W_.description,annotations:{readOnlyHint:!0},inputSchema:xQ,outputSchema:EQ})],f1);var IQ=f1;import{Tool as DQ,ToolContext as TQ}from"@frontmcp/sdk";import{z as oe}from"@frontmcp/sdk";var _Q=oe.object({name:oe.string(),key:oe.string(),root:oe.string(),state:oe.string(),active:oe.boolean(),branch:oe.string().optional(),changes:oe.number().optional(),frozen:oe.boolean().optional(),apex:oe.string().optional(),hosts:oe.record(oe.string(),oe.string()).optional(),dashboard:oe.string(),services:oe.number().optional(),createdByLens:oe.boolean(),detail:oe.string().optional()}).passthrough(),MQ={name:oe.string().regex(Fb).describe("Short and lowercase \u2014 one DNS label of at most 20 characters (it becomes part of its hosts: app.<name>.<project>.localhost). E.g. 'auth-fix'."),branch:oe.string().min(1).max(200).optional().describe("The branch to work on. Default lensmcp/<name>, made new from `from`. An existing branch is checked out as it is."),from:oe.string().min(1).max(200).optional().describe("The commit a new branch starts from (a branch, tag or sha). Default: the main checkout's HEAD."),detach:oe.boolean().optional().describe("Check out `from` itself with no branch \u2014 to look at or review a commit."),frozen:oe.boolean().optional().describe("Serve the commit as it is: every service compiles once, no file watcher, no type checker. For reviewing or comparing, not for editing."),prepare:oe.boolean().optional().describe("Run the project's prepare (migrations, seeds) before services start: true always, false skips this start. Default: new data, incomplete preparation, or changed resource/prepare configuration.")},BQ=oe.object({name:oe.string(),key:oe.string(),root:oe.string(),worktree:oe.object({path:oe.string(),branch:oe.string().optional(),createdBranch:oe.boolean().optional(),from:oe.string().optional()}).passthrough().optional(),state:oe.string(),detail:oe.string().optional(),log:oe.string().optional(),error:oe.string().optional(),logTail:oe.string().optional(),next:oe.string().optional()}).passthrough(),qQ={},jQ=oe.object({project:oe.string(),active:oe.string(),worktrees:oe.array(_Q),note:oe.string().optional()}).passthrough(),RQ={name:oe.string().min(1).max(80).describe("A worktree's name (or key) from worktree_list, or 'main'.")},OQ=oe.object({active:oe.string(),key:oe.string().optional(),root:oe.string().optional(),branch:oe.string().optional(),hosts:oe.record(oe.string(),oe.string()).optional(),dashboard:oe.string().optional(),note:oe.string().optional(),next:oe.string().optional()}).passthrough(),NQ={name:oe.string().min(1).max(80).describe("The worktree's name (or key) from worktree_list."),force:oe.boolean().optional().describe("Throw away its uncommitted work (and delete an unmerged branch with deleteBranch). ONLY when the person said so."),keepData:oe.boolean().optional().describe("Keep its databases and queues on record, for a worktree you will start again."),deleteBranch:oe.boolean().optional().describe("Also delete the branch the lens made for it \u2014 refused while it has commits merged nowhere, unless force.")},PQ=oe.object({name:oe.string().optional(),retry:oe.boolean().optional(),note:oe.string().optional(),stopped:oe.boolean().optional(),keptData:oe.array(oe.string()).optional(),worktreeRemoved:oe.string().optional(),worktreeKept:oe.string().optional(),worktreeError:oe.string().optional(),branchDeleted:oe.string().optional(),branchKept:oe.object({branch:oe.string(),why:oe.string()}).passthrough().optional()}).passthrough(),g1=class extends TQ{static{l(this,"nE")}static{u(this,"WorktreeCreateTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await bM(t,e);s.ok===!1&&!s._meta&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};g1=P([DQ({name:P_.name,description:P_.description,inputSchema:MQ,outputSchema:BQ})],g1);var LQ=g1;import{Tool as FQ,ToolContext as UQ}from"@frontmcp/sdk";var v1=class extends UQ{static{l(this,"sE")}static{u(this,"WorktreeListTool")}async execute(){let e=qn();"error"in e&&this.fail(Wt(e.error));let t=await Hp(e);return"error"in t&&this.fail(Wt(t.error)),t}};v1=P([FQ({name:L_.name,description:L_.description,annotations:{readOnlyHint:!0},inputSchema:qQ,outputSchema:jQ})],v1);var zQ=v1;import{Tool as WQ,ToolContext as HQ}from"@frontmcp/sdk";var y1=class extends HQ{static{l(this,"iE")}static{u(this,"WorktreeSwitchTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await $M(t,e.name);s.ok===!1&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};y1=P([WQ({name:F_.name,description:F_.description,inputSchema:RQ,outputSchema:OQ})],y1);var GQ=y1;import{Tool as ZQ,ToolContext as VQ}from"@frontmcp/sdk";var w1=class extends VQ{static{l(this,"cE")}static{u(this,"WorktreeRemoveTool")}async execute(e){let t=qn();"error"in t&&this.fail(Wt(t.error));let s=await xM(t,e);s.ok===!1&&s.retry!==!0&&this.fail(Wp(s));let{ok:n,...r}=s;return r}};w1=P([ZQ({name:U_.name,description:U_.description,inputSchema:NQ,outputSchema:PQ})],w1);var JQ=w1;import{spawn as KQ}from"node:child_process";import{existsSync as b1,readFileSync as QQ}from"node:fs";import{join as XM}from"node:path";import{Job as YQ,JobContext as XQ,z as ks}from"@frontmcp/sdk";import{existsSync as eY}from"node:fs";import{dirname as tY,join as sY,relative as rY,resolve as Di,isAbsolute as nY}from"node:path";var iY=6;function eB(e=process.env,t=process.cwd()){return Di(e.LENSMCP_WORKSPACE_ROOT??t)}l(eB,"OD"),u(eB,"resolveAllowedRoot");function Kp(e,t){let s=rY(Di(e),Di(t));return s===""||!s.startsWith("..")&&!nY(s)}l(Kp,"lE"),u(Kp,"isWithinRoot");function tB(e,t){let s=Di(e);if(t===void 0)return{ok:!0,cwd:s};let n=Di(s,t);return Kp(s,n)?{ok:!0,cwd:n}:{ok:!1,reason:`cwd ${n} is outside this server's workspace (${s}). verify_fix runs a workspace-defined Nx target, so it only runs in the workspace this server was started for. Set LENSMCP_WORKSPACE_ROOT to serve a different one.`}}l(tB,"CD"),u(tB,"confineToWorkspace");function sB(e,t){let s=Di(t),n=Di(e);if(Kp(s,n))for(let r=0;r<iY;r++){if(eY(sY(n,"nx.json")))return n;if(n===s)break;let i=tY(n);if(i===n||!Kp(s,i))break;n=i}}l(sB,"ND"),u(sB,"findNxWorkspaceRootWithin");var aY=/^[@A-Za-z0-9][\w./-]*$/;function rB(e){return e.length<=214&&aY.test(e)}l(rB,"jD"),u(rB,"isValidProjectName");var k1=class extends XQ{static{l(this,"pE")}static{u(this,"VerifyFixJob")}async execute(e){let t=Date.now(),s=e.project??process.env.LENSMCP_VERIFY_PROJECT??"example-web",n=eB(),r=tB(n,e.cwd);r.ok||(this.log(`[verify_fix] refused: ${r.reason}`),this.fail(Na(r.reason)));let i=r.cwd;rB(s)||(this.log(`[verify_fix] refused: ${s} is not a valid Nx project name`),this.fail(Na(`${s.slice(0,120)} is not a valid Nx project name`)));let a=sB(i,n);a||(this.log(`No nx.json found between ${i} and ${n}`),this.fail(Wt(`No nx.json found between ${i} and ${n} \u2014 nothing to verify there`)));let o=nB("nx",[a]);o||(this.log(`Could not find node_modules/.bin/nx under ${a}`),this.fail(Wt(`Could not find node_modules/.bin/nx under ${a} \u2014 install the workspace's dependencies`))),this.log(`[verify_fix] nx run ${s}:agent-verify (cwd=${a})`);let c=KQ(o,["run",`${s}:agent-verify`],{cwd:a,env:{...process.env},stdio:["ignore","pipe","pipe"]}),p=[],d=u(y=>{let w=/\[agent-verify\] ([a-z]+): (passed|failed|skipped|errored)/.exec(y);w&&w[1]&&w[2]&&(p.push({name:w[1],result:w[2],durationMs:0}),this.log(` ${w[1]}: ${w[2]}`))},"captureLine");$1(c.stdout,d),$1(c.stderr,d);let h=!1,m=setTimeout(()=>{h=!0;try{c.kill("SIGTERM")}catch{}},e.timeoutMs),f=await new Promise(y=>{c.on("exit",w=>y(w??1))});if(clearTimeout(m),h)return{status:"timeout",project:s,durationMs:Date.now()-t,stages:p,reportPath:null};let v=XM(a,".lensmcp","verifications","latest.json"),g;if(b1(v))try{g=JSON.parse(QQ(v,"utf-8"))}catch{g=void 0}return{status:g?.status??(f===0?"passed":"failed"),project:s,durationMs:g?.durationMs??Date.now()-t,stages:g?.stages??p,reportPath:b1(v)?v:null}}};k1=P([YQ({name:"observe_verify_fix",description:"Run the deterministic verification loop (typecheck \u2192 lint \u2192 build) for a host project. Returns a per-stage report; suggested next read on failure is the relevant *://errors resource.",inputSchema:{project:ks.string().describe('Nx project name in the host workspace to verify. Defaults to LENSMCP_VERIFY_PROJECT or "example-web".').optional(),cwd:ks.string().describe("Directory to verify from. MUST be inside the workspace this server was started for (LENSMCP_WORKSPACE_ROOT, else the server's cwd); a path outside it is refused. Defaults to that workspace root.").optional(),timeoutMs:ks.number().int().positive().default(5*6e4).describe("How long to wait for the verify pipeline before declaring it stuck.")},outputSchema:{status:ks.enum(["passed","failed","errored","timeout"]),project:ks.string().nullable(),durationMs:ks.number(),stages:ks.array(ks.object({name:ks.string(),result:ks.enum(["passed","failed","skipped","errored"]),durationMs:ks.number(),exitCode:ks.number().optional(),summary:ks.string().optional()})),reportPath:ks.string().nullable()}})],k1);var oY=k1;function nB(e,t){for(let s of t){let n=XM(s,"node_modules",".bin",e);if(b1(n))return n}}l(nB,"YY"),u(nB,"locateBin");function $1(e,t){if(!e)return;let s="";e.setEncoding("utf-8"),e.on("data",n=>{s+=typeof n=="string"?n:n.toString("utf-8");let r;for(;(r=s.indexOf(`
198
198
  `))!==-1;){let i=s.slice(0,r);s=s.slice(r+1),t(i)}}),e.on("end",()=>{s.length&&t(s)})}l($1,"PD"),u($1,"bufferLines");var iB=class{static{l(this,"mE")}static{u(this,"AgentApp")}};iB=P([uJ({id:"agent",name:"Agent",description:"Agent-facing summary, suggested reads, verification.",resources:[SJ,IJ,_J,qJ,OJ],tools:[QJ,rK,xK,AK,LK,rQ,cQ,mQ,SQ,IQ,LQ,zQ,GQ,JQ,GJ],jobs:[oY]})],iB);var Ht=u(e=>typeof e=="string"&&e?e:void 0,"str"),uY=u(e=>!!e&&/^lensmcp-/i.test(e),"isLensClient"),lY=50,Ti=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),dY=class{static{l(this,"Pl")}static{u(this,"AgentSessions")}constructor(){this.sessions=new Map,this.owner=new Map,this.lens=new Set,this.pendingAsks=new Map}observe(e){if(e.category!=="agent")return!1;let t=e.raw??{};if(t.kind==="agent-asked")return this.asked(t,e.timestamp);let s=Ht(t.agent);return!s||this.lens.has(s)?!1:t.kind==="agent-session"?this.opened(s,t,e.timestamp):t.kind==="agent-call"?this.called(s,t,e.timestamp):!1}asked(e,t){let s=Ht(e.text),n=(Array.isArray(e.shims)?e.shims:[e.shim]).map(Ti).filter(i=>i!==void 0);if(!s||!n.length)return!1;let r=[...this.sessions.values()].filter(i=>i.conn.shim!==void 0&&n.includes(i.conn.shim)&&i.endedAt===void 0).sort((i,a)=>a.lastSeenAt-i.lastSeenAt)[0];if(!r){for(let i of n)this.pendingAsks.set(i,{text:s,at:t}),this.pendingAsks.size>lY&&this.pendingAsks.delete(this.pendingAsks.keys().next().value);return!1}return this.ask(r,s,t),!0}ask(e,t,s){e.asked=t,e.askedAt=s,e.events.push({at:s,kind:"ask",name:"prompt",result:t}),e.events.length>500&&e.events.splice(0,e.events.length-500),e.lastSeenAt=Math.max(e.lastSeenAt,s)}opened(e,t,s){if(this.owner.has(e))return!1;let n=Ht((t.client??{}).name);if(uY(n))return this.lens.add(e),!1;let r=Ht(t.server)??"?",i=Ti(t.shim),a=i!==void 0?[...this.sessions.values()].find(d=>d.conn.shim===i&&d.server===r&&d.endedAt===void 0):void 0;if(a)return a.aliases.add(e),a.conn.reconnects++,a.conn.pid=Ti(t.pid)??a.conn.pid,this.owner.set(e,a.id),!0;let o=t.client??{},c={id:e,client:{name:Ht(o.name)??"an MCP client",...Ht(o.version)?{version:Ht(o.version)}:{}},server:r,startedAt:s,lastSeenAt:s,events:[],ms:[],aliases:new Set([e]),conn:{transport:Ht(t.transport)??"streamable-http",pid:Ti(t.pid)??0,...i!==void 0?{shim:i}:{},...Ht(t.protocol)?{protocol:Ht(t.protocol)}:{},calls:0,reads:0,errors:0,reconnects:0}};this.sessions.set(e,c),this.owner.set(e,e);let p=i!==void 0?this.pendingAsks.get(i):void 0;return p&&i!==void 0&&(this.pendingAsks.delete(i),this.ask(c,p.text,p.at)),this.trim(r),!0}called(e,t,s){let n=this.sessions.get(this.owner.get(e)??"");if(!n&&(this.opened(e,{server:t.server,pid:t.pid,shim:t.shim},s),n=this.sessions.get(this.owner.get(e)??""),!n))return!1;let r=Ht(t.name)??"?",i=t.said??void 0,a=i?"say":t.call==="read"?"read":"tool",o=Ti(t.ms),c={at:s,kind:a,name:r,...Ht(t.args)?{args:Ht(t.args)}:{},...o!==void 0?{ms:o}:{},...Ti(t.bytes)!==void 0?{bytes:Ti(t.bytes)}:{},...t.isError===!0?{isError:!0}:{},...Ht(t.result)?{result:Ht(t.result)}:{}};if(n.events.push(c),n.events.length>500&&n.events.splice(0,n.events.length-500),n.lastSeenAt=Math.max(n.lastSeenAt,s),a==="read"?n.conn.reads++:n.conn.calls++,c.isError&&n.conn.errors++,o!==void 0&&(n.conn.lastMs=o,n.ms.push(o),n.ms.length>200&&n.ms.shift()),i){let p=Ht(i.task),d=Ht(i.step);p&&(n.task=p),(d!==void 0||p)&&(d?n.step=d:delete n.step),n.saidAt=s}return!0}trim(e){let t=[...this.sessions.values()].filter(s=>s.server===e).sort((s,n)=>n.lastSeenAt-s.lastSeenAt);for(let s of t.slice(20)){this.sessions.delete(s.id);for(let n of s.aliases)this.owner.delete(n)}}report(e,t){let s=[...this.sessions.values()].map(r=>{if(r.endedAt===void 0){let m=r.conn.shim!==void 0&&t(r.conn.shim);m&&(r.aliveAt=e),(r.conn.shim!==void 0?!m:e-r.lastSeenAt>18e5)&&(r.endedAt=Math.max(r.lastSeenAt,r.aliveAt??0))}let i=[...r.ms].sort((m,f)=>m-f),a=i.length?i[Math.min(i.length-1,Math.floor(i.length*.95))]:void 0,{ms:o,aliases:c,aliveAt:p,conn:d,...h}=r;return{...h,state:r.endedAt!==void 0?"ended":e-r.lastSeenAt<=12e4?"live":"idle",conn:{...d,...a!==void 0?{p95Ms:a}:{}},events:[...r.events]}}),n={live:0,idle:1,ended:2};return s.sort((r,i)=>n[r.state]-n[i.state]||i.lastSeenAt-r.lastSeenAt),{at:e,sessions:s}}},Qp="agent://current-status",x1="agent://sessions",cY=u(e=>{try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}},"pidAlive"),Yp="process://cluster",aB=250,pY=new Set(["build","lint","typecheck","runtime","cluster","memory","visual","performance"]);function oB(e){let t=new qK,s=new wQ,n=e.now??Date.now,r=e.sessionId??"pending",i=new xJ({thresholds:e.podRules??k_(),sessionId:r,publish:u(f=>e.bus.publish(f),"publish")}),a=new dY,o,c=u(()=>{o||(o=setTimeout(()=>{o=void 0,e.resources.markDirty(x1)},aB),o.unref?.())},"scheduleAgentsRefresh"),p,d=u(()=>{p||(p=setTimeout(()=>{p=void 0,e.resources.markDirty(Qp)},aB),p.unref?.())},"scheduleStatusRefresh"),h=u(f=>{if(f.category==="agent"){a.observe(f)&&c();return}let v=t.ingest(f);v&&e.resources.markDirty(Yp);let g=i.ingest(f);g&&e.resources.markDirty(ur);let y=s.ingest(f);y&&e.resources.markDirty(ds),(v||g||y||pY.has(f.category))&&d()},"handler"),m=e.bus.subscribe(h);return e.resources.register(Yp,()=>({schemaVersion:1,revision:e.resources.revision(Yp)??0,updatedAt:new Date().toISOString(),...t.snapshot()})),e.resources.register(tM,()=>t.builtFiles()),e.resources.register(ur,()=>i.report(e.resources.revision(ur)??0)),e.resources.register(x1,()=>a.report(Date.now(),cY)),e.resources.register(ds,()=>({schemaVersion:1,revision:e.resources.revision(ds)??0,updatedAt:new Date(n()).toISOString(),...s.report(n())})),e.resources.register(Qp,()=>Lp({resources:e.resources,sessionId:r,revision:e.resources.revision(Qp)??0,signalFreshMs:e.signalFreshMs??EJ})),{unsubscribe:u(()=>{m(),o&&clearTimeout(o),p&&(clearTimeout(p),p=void 0)},"unsubscribe"),uris:[Qp,Yp,ur,x1,ds]}}l(oB,"fE"),u(oB,"installAgentReducer");import{App as hY}from"@frontmcp/sdk";import{Resource as mY,ResourceContext as fY}from"@frontmcp/sdk";var E1=class extends fY{static{l(this,"gE")}static{u(this,"FlowRecentResource")}async execute(){return this.get(X).read("flow://recent")}};E1=P([mY({name:"flow-recent",uri:"flow://recent",mimeType:"application/json",description:"Last 50 flows seen this session, most recent first."})],E1);var gY=E1;import{Resource as vY,ResourceContext as yY}from"@frontmcp/sdk";var S1=class extends yY{static{l(this,"wE")}static{u(this,"FlowCurrentResource")}async execute(){return this.get(X).read("flow://current")}};S1=P([vY({name:"flow-current",uri:"flow://current",mimeType:"application/json",description:"The most recently active flow (origin + event count + headline)."})],S1);var wY=S1;import{Resource as bY,ResourceContext as kY}from"@frontmcp/sdk";var A1=class extends kY{static{l(this,"bE")}static{u(this,"FlowOriginsRecentResource")}async execute(){return this.get(X).read("flow://origins/recent")}};A1=P([bY({name:"flow-origins-recent",uri:"flow://origins/recent",mimeType:"application/json",description:"Last 50 flow-origin events (one per detected flow start)."})],A1);var $Y=A1;import{Tool as xY,ToolContext as EY}from"@frontmcp/sdk";var uB;function C1(e){uB=e}l(C1,"mf"),u(C1,"setActiveFlowLookups");function Tt(){return uB}l(Tt,"We"),u(Tt,"activeFlowLookups");var lB;function I1(e){lB=e}l(I1,"ff"),u(I1,"setFlowRecoverySource");function Xp(){return lB}l(Xp,"Ri"),u(Xp,"flowRecoverySource");var dB=/ \(\d+(?:\.\d+)?ms\)$/,SY=/\d\s?ms\b/,cB=new Set(["warning","error","fatal"]),AY=6,pB=u(e=>e.count!==void 0&&e.count>1&&e.wallMs!==void 0?e.wallMs:e.durationMs,"msOf");function hB(e,t={}){let s=t.fold!==!1,n=new Map(e.map(d=>[d.id,d])),r=new Set;for(let d of e)d.parent&&n.has(d.parent)&&r.add(d.parent);let i=u(d=>d.kind==="span"&&(pB(d)??0)===0&&!r.has(d.id)&&!cB.has(d.severity??"")&&d.parent!==void 0&&n.has(d.parent),"isFrame"),a=new Map,o=[];for(let d of e)if(s&&i(d)){let h=a.get(d.parent)??new Map,m=d.sig??d.title.replace(dB,"");h.set(m,(h.get(m)??0)+(d.count??1)),a.set(d.parent,h)}else o.push(d);let c=u(d=>{let h=0,m=d;for(;m?.parent&&n.has(m.parent)&&h<64;)m=n.get(m.parent),h+=1;return h},"depthOf"),p=e.reduce((d,h)=>Math.min(d,h.start),1/0);return o.map(d=>{let h=pB(d),m=d.title.replace(dB,""),f=h!==void 0&&(m!==d.title||!SY.test(d.title)),v=m.length>160?`${m.slice(0,160)}\u2026`:m,g=a.get(d.id);return{id:d.id,at:Math.max(0,Math.round(d.start-(Number.isFinite(p)?p:d.start))),depth:c(d),area:d.area??"",kind:d.kind??"",title:v,...f?{ms:Math.round(h*10)/10}:{},...d.count!==void 0&&d.count>1?{count:d.count}:{},...cB.has(d.severity??"")?{severity:d.severity}:{},...g?{folded:[...g].map(([y,w])=>({name:y,count:w}))}:{},...d.outlivedParentMs!==void 0?{outlivedParentMs:d.outlivedParentMs}:{},...d.leftRunning?{leftRunning:d.leftRunning}:{}}})}l(hB,"WD"),u(hB,"outlineRows");var mB="+<ms from the unit's start> <one dot per level of depth><area> <kind>: <title> \u2014 <duration> \xD7<how many events it stands for> !<warning|error> !left-running <n> (+<ms>: this span ended before <n> calls it started had finished) !outlived-parent +<ms> (+<n> zero-time: frames that took 0 ms and did no I/O, named here instead of listed) [<node id>]";function D1(e){let t=[e.area,e.kind].filter(Boolean).join(" "),s=`+${e.at} ${".".repeat(e.depth)}${t}${t?": ":""}${e.title}`;if(e.ms!==void 0&&(s+=` \u2014 ${e.ms}ms`),e.count!==void 0&&(s+=` \xD7${e.count}`),e.severity&&(s+=` !${e.severity}`),e.leftRunning&&(s+=` !left-running ${e.leftRunning.count} (+${e.leftRunning.longestMs}ms)`),e.outlivedParentMs!==void 0&&(s+=` !outlived-parent +${e.outlivedParentMs}ms`),e.folded?.length){let n=e.folded.reduce((a,o)=>a+o.count,0),r=e.folded.slice(0,AY).map(a=>a.count>1?`${a.name} \xD7${a.count}`:a.name),i=e.folded.length-r.length;s+=` (+${n} zero-time: ${r.join(", ")}${i>0?`, +${i} more names`:""})`}return`${s} [${e.id}]`}l(D1,"xE"),u(D1,"renderOutlineRow");function fB(e,t=8){let s=u(n=>n.severity==="error"||n.severity==="fatal"?2:n.severity==="warning"||n.leftRunning?1:0,"rank");return e.map((n,r)=>({r:n,row:r})).filter(({r:n})=>s(n)>0||(n.ms??0)>0).sort((n,r)=>s(r.r)-s(n.r)||(r.r.ms??0)-(n.r.ms??0)||n.row-r.row).slice(0,t).sort((n,r)=>n.row-r.row).map(({r:n,row:r})=>({row:r,line:D1(n)}))}l(fB,"GD"),u(fB,"heaviestRows");import{existsSync as CY}from"node:fs";import{open as IY}from"node:fs/promises";import{basename as DY}from"node:path";var eh="flow://recent",th="flow://current",sh="flow://origins/recent",La=50,Fa=50,gB=50,T1=2e3,TY=4*1024*1024,_1=32*1024*1024,vB=u(e=>`${e.summary.eventCount}:${e.events.length}:${e.summary.lastSeenAt}`,"versionOf"),_Y=La+Fa+10;function M1(e){let t={flows:new Map,origins:[],recentOrder:[],retainedEvents:0,retainedBytes:0,evictedEvents:0,evictedForBytes:0,evictedFlows:0},s=e.register??!0,n=u((m,f,v,g=!0)=>{let y=Math.min(f,m.events.length);if(y<=0)return;if(g&&y>0&&(m.events[0]?.raw??{}).kind==="flow-origin"&&m.events.length>1){let b=m.eventBytes[1]??0;if(m.events.splice(1,1),m.eventBytes.splice(1,1),m.retainedBytes=Math.max(0,m.retainedBytes-b),t.retainedEvents=Math.max(0,t.retainedEvents-1),t.retainedBytes=Math.max(0,t.retainedBytes-b),t.evictedEvents+=1,v&&(t.evictedForBytes+=1),y-=1,y<=0)return}let w=0;for(let b=0;b<y;b+=1)w+=m.eventBytes[b]??0;m.events.splice(0,y),m.eventBytes.splice(0,y),m.retainedBytes=Math.max(0,m.retainedBytes-w),t.retainedEvents=Math.max(0,t.retainedEvents-y),t.retainedBytes=Math.max(0,t.retainedBytes-w),t.evictedEvents+=y,v&&(t.evictedForBytes+=y)},"evictPrefix"),r=u(m=>{let f=0,v=m.retainedBytes;for(;v>TY&&f<m.eventBytes.length;)v-=m.eventBytes[f]??0,f+=1;n(m,f,!0)},"enforceEntryByteCap"),i=u(()=>{for(let m=t.recentOrder.length-1;t.retainedBytes>_1&&m>=0;m-=1){let f=t.flows.get(t.recentOrder[m]);if(!f)continue;let v=0,g=t.retainedBytes;for(;g>_1&&v<f.eventBytes.length;)g-=f.eventBytes[v]??0,v+=1;n(f,v,!0)}},"enforceGlobalByteCap"),a=u(m=>{let f=m.context.flowId;if(!f)return;let v=(m.raw??{}).kind;if(v==="subscription-added"||v==="subscription-removed"||v==="hook-run"||v==="store-created"||v==="singleton-instance"||v==="visual-frame")return;let g=v==="flow-origin";(t.seenSince===void 0||m.timestamp<t.seenSince)&&(t.seenSince=m.timestamp);let y=t.flows.get(f);if(!y){y={summary:{flowId:f,originType:m.context.originType,originNodeId:m.context.originNodeId,startedAt:m.timestamp,lastSeenAt:m.timestamp,eventCount:0,headline:m.title},events:[],eventBytes:[],retainedBytes:0,hasOrigin:!1},t.flows.set(f,y);let k={flowId:f,originType:m.context.originType,originNodeId:m.context.originNodeId,at:m.timestamp,label:m.title,eventId:m.id};t.origins.push(k),t.origins.length>gB&&t.origins.splice(0,t.origins.length-gB),e.resources.markDirty(sh)}g&&!y.hasOrigin&&(y.hasOrigin=!0,y.summary.headline=m.title,m.context.originType&&(y.summary.originType=m.context.originType),m.context.originNodeId&&(y.summary.originNodeId=m.context.originNodeId)),m.timestamp<y.summary.startedAt&&(y.summary.startedAt=m.timestamp);let w=Bp(m);y.events.push(m),y.eventBytes.push(w),y.retainedBytes+=w,t.retainedEvents+=1,t.retainedBytes+=w,y.events.length>T1&&n(y,y.events.length-T1,!1),r(y),y.summary.eventCount+=1,y.summary.lastSeenAt=m.timestamp;let b=t.recentOrder.indexOf(f);if(b>=0&&t.recentOrder.splice(b,1),t.recentOrder.unshift(f),t.recentOrder.length>La||t.recentOrder.length>Fa){let k=0,$=0,E=new Set;for(let x of t.recentOrder)M5(x)?($+=1,$>Fa&&E.add(x)):(k+=1,k>La&&E.add(x));E.size>0&&(t.recentOrder=t.recentOrder.filter(x=>!E.has(x)));for(let x of E){let S=t.flows.get(x);S&&(t.evictedFlows+=1,t.evictedThrough=Math.max(t.evictedThrough??0,S.summary.lastSeenAt),n(S,S.events.length,!1,!1)),t.flows.delete(x)}}i(),t.currentFlowId!==f&&(t.currentFlowId=f,e.resources.markDirty(th)),e.resources.markDirty(eh)},"handler"),o=e.bus.subscribe(a);e.resources.register(eh,()=>({schemaVersion:1,revision:e.resources.revision(eh)??0,updatedAt:new Date().toISOString(),flows:t.recentOrder.map(m=>t.flows.get(m)?.summary).filter(m=>!!m)})),e.resources.register(th,()=>{let m=t.currentFlowId,f=m?t.flows.get(m):void 0;return{schemaVersion:1,revision:e.resources.revision(th)??0,updatedAt:new Date().toISOString(),flow:f?.summary??null}}),e.resources.register(sh,()=>({schemaVersion:1,revision:e.resources.revision(sh)??0,updatedAt:new Date().toISOString(),origins:t.origins.slice().reverse()}));let c=e.flows??sn,p=new Map,d=u(m=>{let f=vB(m);return m.sorted?.key!==f&&(m.sorted={key:f,events:m.events.slice().sort((v,g)=>v.timestamp-g.timestamp)}),m.sorted.events},"sortedEvents"),h={getFlowEvents(m){let f=t.flows.get(m);return f?d(f).slice():void 0},getFlowSummary(m){return t.flows.get(m)?.summary},recentFlowIds(){return t.recentOrder.slice()},findFlowsByOrigin(m){return[...t.flows.values()].filter(f=>f.summary.originNodeId===m).map(f=>f.summary)},flowsConfig:c,analyzeFlow(m){let f=t.flows.get(m);if(!f)return;let v=vB(f),g=p.get(m);if(g&&g.key===v)return p.delete(m),p.set(m,g),g.analysis;let y=Yu(d(f),c);for(p.delete(m),p.set(m,{key:v,analysis:y});p.size>_Y;)p.delete(p.keys().next().value);return y},classifiedRecent(m=La+Fa){let f=[];for(let v of t.recentOrder){if(f.length>=m)break;let g=t.flows.get(v)?.summary,y=h.analyzeFlow(v);!g||!y||f.push({summary:g,category:y.classification.category,decidedBy:y.classification.decidedBy,...y.classification.subject?{subject:y.classification.subject}:{},tags:y.classification.tags,segmentCount:y.segmentation.stats.segments,phaseCount:y.segmentation.stats.phases,signalCount:y.segmentation.stats.signal})}return f},window(){return{since:(t.evictedThrough!==void 0?Math.max(t.evictedThrough,t.seenSince??0):t.seenSince)??null,flows:t.flows.size,maxFlows:La,maxHeadlessFlows:Fa,evicted:t.evictedFlows}}};return s&&C1(h),{unsubscribe:u(()=>{s&&C1(void 0),o()},"unsubscribe"),uris:[eh,th,sh],lookups:h,retentionStats:u(()=>({residentEvents:t.retainedEvents,residentBytes:t.retainedBytes,evictedEvents:t.evictedEvents,evictedForBytes:t.evictedForBytes,eventCap:(La+Fa)*T1,byteCap:_1}),"retentionStats")}}l(M1,"Ll"),u(M1,"installFlowReducer");var B1={maxBytes:320*1024*1024,maxMs:2e3};function yB(e=process.env){let t=Number(e.LENSMCP_FLOW_RECOVER_BYTES??""),s=Number(e.LENSMCP_FLOW_RECOVER_MS??""),n=u(r=>(e[r]??"").trim()!=="","set");return{maxBytes:n("LENSMCP_FLOW_RECOVER_BYTES")&&Number.isFinite(t)&&t>=0?t:B1.maxBytes,maxMs:n("LENSMCP_FLOW_RECOVER_MS")&&Number.isFinite(s)&&s>0?s:B1.maxMs}}l(yB,"RE"),u(yB,"recoveryBudgetFromEnv");var wB=5e3,bB=1024*1024,q1=10;function kB(e,t){let s=[e];for(let n=1;n<=t;n++)s.push(`${e}.${n}`);return s.filter(n=>CY(n))}l(kB,"y7"),u(kB,"busFiles");function $B(e,t){try{let s=JSON.parse(e);return!s||typeof s!="object"||!("id"in s)||!("source"in s)?void 0:s.context?.flowId===t?s:void 0}catch{return}}l($B,"w7"),u($B,"eventOf");function xB(e,t,s,n){let r=e.indexOf(t);for(;r!==-1;){let i=e.lastIndexOf(q1,r)+1,a=e.indexOf(q1,r),o=$B(e.toString("utf8",i,a),s);o&&n.push(o),r=e.indexOf(t,a+1)}}l(xB,"v7"),u(xB,"collect");async function EB(e,t,s,n,r){let i=[],a={file:DY(e),size:0,read:0,matched:0},o;try{o=await IY(e,"r")}catch{return{searched:a,events:i}}let c=u(p=>(a.matched=i.length,{searched:a,events:i,...p?{stoppedBy:p}:{}}),"done");try{a.size=(await o.stat()).size;let p=Buffer.allocUnsafe(bB),d=Buffer.alloc(0);for(;a.read<a.size;){if(a.read>=n)return c("bytes");if(Date.now()>=r)return c("time");let h=Math.min(bB,a.size-a.read,n-a.read),{bytesRead:m}=await o.read(p,0,h,a.read);if(m<=0)break;a.read+=m;let f=d.length>0?Buffer.concat([d,p.subarray(0,m)]):p.subarray(0,m),v=f.lastIndexOf(q1);v>=0&&xB(f.subarray(0,v+1),t,s,i),d=Buffer.from(f.subarray(v+1))}}finally{await o.close().catch(()=>{})}return c()}l(EB,"b7"),u(EB,"searchFile");async function SB(e,t,s){let n=Date.now(),r=n+s.maxMs,i=Buffer.from(JSON.stringify(t)),a=[],o=[],c=0,p;for(let d of kB(e.eventFile,e.maxGenerations??20)){let h=await EB(d,i,t,s.maxBytes-c,r);if(a.push(h.searched),c+=h.searched.read,o.push(h.events),h.stoppedBy){p=h.stoppedBy;break}let m=o.some(v=>v.length>0),f=h.events.some(v=>v.raw?.kind==="flow-origin");if(m&&(f||h.events.length===0))break}return{events:o.reverse().flat(),files:a,bytesRead:c,elapsedMs:Date.now()-n,...p?{stoppedBy:p}:{}}}l(SB,"k7"),u(SB,"findFlowOnBus");var AB=4,un=new Map,j1=new Map;function R1(e,t){let s=new fA,n=M1({bus:s,resources:new CA,...t.flows?{flows:t.flows}:{},register:!1});for(let r of e)s.publish(t.prepare(r));return n.unsubscribe(),n.lookups}l(R1,"QD"),u(R1,"replay");var CB="There is no bus file to search (LENSMCP_EVENT_FILE is not set for this server).",IB="Searching the bus files is turned off (LENSMCP_FLOW_RECOVER_BYTES=0).";function rh(e,t,s,n=CB){let r=t.maxHeadlessFlows?`, plus the ${t.maxHeadlessFlows} most recent the lens started for a request or a job that carried no flow (api:\u2026, job:\u2026)`:"",i=`This server holds the ${t.maxFlows} most recently active flows${r}${t.since!==null?` (every flow active since ${new Date(t.since).toISOString()})`:""}, and on start replays only the recent tail of the bus \u2014 this id is not among them.`,a=s?`Its search of the bus files ran out of budget (${s.stoppedBy==="time"?`${s.budgetMs} ms`:`${s.budgetBytes} bytes`}) before finding the flow.`:n;return{found:!1,flowId:e,reason:"outside-window",window:t,...s?{searched:s}:{},hint:`${i} ${a} The flow may still exist further back: re-run it to capture it fresh, raise LENSMCP_FLOW_RECOVER_BYTES / LENSMCP_FLOW_RECOVER_MS, or search .lensmcp/events.jsonl* for the id.`}}l(rh,"IE"),u(rh,"outsideWindow");function DB(e,t){let s;try{s=t.history?.(e)}catch{return}if(!s?.length)return;let n=[...s].sort((i,a)=>i.timestamp-a.timestamp),r=R1(n,t);if(r.getFlowSummary(e))return{lookups:r,recovered:{from:"history",files:[],events:n.length,complete:n.length<wB}}}l(DB,"S7"),u(DB,"fromHistory");async function TB(e,t,s,n,r){let i=DB(t,s);if(i){for(un.set(r,i);un.size>AB;)un.delete(un.keys().next().value);return i}if(n.maxBytes<=0){let o=e.window();return o.evicted>0?rh(t,o,void 0,IB):{found:!1,flowId:t}}let a=await SB(s,t,n);if(a.events.length>0){let o=R1(a.events,s);if(!o.getFlowSummary(t))return{found:!1,flowId:t};let c={lookups:o,recovered:{from:"bus",files:a.files.filter(p=>p.matched>0).map(p=>p.file),events:a.events.length,complete:a.stoppedBy===void 0}};for(un.set(r,c);un.size>AB;)un.delete(un.keys().next().value);return c}if(a.stoppedBy){let o={files:a.files,bytes:a.bytesRead,budgetBytes:n.maxBytes,budgetMs:n.maxMs,stoppedBy:a.stoppedBy};return rh(t,e.window(),o)}return{found:!1,flowId:t}}l(TB,"x7"),u(TB,"search");async function nh(e,t,s){if(e.getFlowSummary(t))return{lookups:e};let n=s?.budget??B1;if(!s||n.maxBytes<=0&&!s.history){let o=e.window();return o.evicted>0?rh(t,o,void 0,s?IB:CB):{found:!1,flowId:t}}let r=`${s.eventFile}\0${t}`,i=un.get(r);if(i)return i;let a=j1.get(r);return a||(a=TB(e,t,s,n,r).finally(()=>j1.delete(r)),j1.set(r,a)),a}l(nh,"uc"),u(nh,"locateFlow");var MY=120;function O1(e,t,s){return{id:e.id,kind:e.kind,label:e.label,category:t,phase:e.phase,startOffsetMs:Math.max(0,e.start-s),durationMs:e.durationMs,events:e.counts.total,signal:e.counts.signal,errors:e.counts.errors,worstSeverity:e.worstSeverity,projects:e.projects,...e.route?{route:e.route}:{},...e.method?{method:e.method}:{},...e.part?{part:e.part}:{},...e.hot?{hot:e.hot}:{},...e.after?{after:e.after}:{},...e.sql?{sql:e.sql}:{}}}l(O1,"ME"),u(O1,"segmentView");function ih(e,t={}){let{segmentation:s,classification:n,segmentCategories:r}=e,i=Math.max(1,t.maxSegments??MY),a=s.segments.reduce((p,d)=>Math.min(p,d.start),1/0),o=Number.isFinite(a)?a:0,c=s.segments;if(c.length>i){let p=u(h=>h.counts.errors*1e6+h.counts.signal,"rank"),d=new Set([...c].sort((h,m)=>p(m)-p(h)||(h.id<m.id?-1:1)).slice(0,i).map(h=>h.id));c=c.filter(h=>d.has(h.id))}return{flowId:s.flowId,category:n.category,decidedBy:n.decidedBy,...n.subject?{subject:n.subject}:{},tags:n.tags,origin:n.origin,stats:{events:s.stats.events,signal:s.stats.signal,bookkeeping:s.stats.bookkeeping,segments:s.stats.segments,phases:s.stats.phases},phases:s.phases.map(p=>({index:p.index,startOffsetMs:Math.max(0,p.start-o),endOffsetMs:Math.max(0,p.end-o),segmentIds:p.segmentIds})),segments:c.map(p=>O1(p,r[p.id]??"other",o)),segmentsTruncated:c.length<s.segments.length,...s.sql?{sql:s.sql}:{}}}l(ih,"bf"),u(ih,"overviewOf");function _B(e,t,s){let n=t.segmentation.segments.find(i=>i.id===s);if(!n)return;let r=new Set(n.eventIds);return e.filter(i=>r.has(i.id))}l(_B,"eU"),u(_B,"eventsOfSegment");function MB(e,t){return e.filter(s=>(t.category===void 0||s.category===t.category)&&(t.tag===void 0||s.tags.includes(t.tag))&&(t.subject===void 0||s.subject===t.subject))}l(MB,"tU"),u(MB,"filterClassified");function BB(e){let t=e.map(s=>({category:s.category,...s.subject?{subject:s.subject}:{},id:s.summary.flowId}));return T5(t).map(s=>({category:s.category,count:s.count,subjects:s.subjects.map(n=>({...n.subject!==void 0?{subject:n.subject}:{},count:n.count,flowIds:n.items.map(r=>r.id)}))}))}l(BB,"nU"),u(BB,"groupClassified");function qB(e){let t={};for(let s of e)t[s.category]=(t[s.category]??0)+1;return t}l(qB,"rU"),u(qB,"categoryCounts");var BY=200,jB=2048;async function RB(e,t,s,n={}){if(!e)return L1(e,t,n);let r=await nh(e,t.flowId,s);if(!("lookups"in r))return r;let i=L1(r.lookups,t,n);return r.recovered?{...i,recovered:r.recovered}:i}l(RB,"dU"),u(RB,"readFlowDetail");function OB(e,t){let s=new Map(t.map(n=>[n.id,n.raw]));return e.map(n=>"ai"in n||!s.has(n.id)?n:{...n,raw:s.get(n.id)})}l(OB,"E7"),u(OB,"withRaw");function NB(e){let t=new Map;for(let r of e)r.requestId&&t.set(r.requestId,(t.get(r.requestId)??0)+1);let s,n=0;for(let[r,i]of t)i>n&&(s=r,n=i);return s!==void 0&&n*2>e.length?s:void 0}l(NB,"A7"),u(NB,"unitRequestId");function N1(e,t){let{memberIds:s,items:n,...r}=e;return t!==void 0&&r.requestId===t&&delete r.requestId,r.detail===r.title&&delete r.detail,r}l(N1,"oU"),u(N1,"slimNode");function P1(e,t){let s=2,n=0;for(let r of e){if(n>0&&s+r+1>t)break;s+=r+1,n+=1}return n}l(P1,"iU"),u(P1,"fitCount");function L1(e,t,s={}){if(!e)return{found:!1,reason:"no active flow reducer"};let n=e.getFlowSummary(t.flowId),r=e.getFlowEvents(t.flowId);if(!n||!r)return{found:!1,flowId:t.flowId};let i=e.analyzeFlow(t.flowId),a=s.budgetBytes!==void 0&&Number.isFinite(s.budgetBytes)&&s.budgetBytes>0?s.budgetBytes:void 0,o=r,c;if(t.segmentId){let S=i?_B(r,i,t.segmentId):void 0,A=i?.segmentation.segments.find(C=>C.id===t.segmentId);if(!i||!S||!A)return{found:!1,flowId:t.flowId,segmentId:t.segmentId,reason:"unknown segment id for this flow (the flow may have changed \u2014 re-read overview.segments)",segmentIds:i?.segmentation.segments.map(C=>C.id)??[]};let I=i.segmentation.segments.reduce((C,_)=>Math.min(C,_.start),1/0);o=S,c=O1(A,i.segmentCategories[A.id]??"other",Number.isFinite(I)?I:A.start)}let p=Qu(o,{includeRaw:t.includeRaw}).events,d=c?NB(p):void 0;if(t.expand){let S=p.find(C=>C.id===t.expand)??(c?Qu(r,{includeRaw:t.includeRaw}).events.find(C=>C.id===t.expand):void 0);if(!S)return{found:!1,flowId:t.flowId,expand:t.expand};let A=new Set(S.memberIds??[S.id]),I=r.filter(C=>A.has(C.id));return{found:!0,flowId:t.flowId,expanded:{id:S.id,title:S.title,count:I.length},node:N1(S,void 0),events:I.map(C=>({id:C.id,timestamp:C.timestamp,source:C.source,category:C.category,severity:C.severity,title:C.title,message:C.message,...t.includeRaw?{raw:C.raw}:{}}))}}let h=!c&&i?ih(i):void 0;if(h&&a!==void 0)for(let S=h.segments.length;or(h)>a/2&&S>5;)S=Math.max(5,Math.floor(S/2)),h=ih(i,{maxSegments:S});let m={found:!0,summary:n,...c?{segment:{...c,...d!==void 0?{requestId:d}:{}}}:{},...h?{overview:h}:{}},f=a===void 0?1/0:Math.max(jB,a-or(m)-600),v=Math.max(0,Math.floor(t.offset??0)),g=u(()=>{let S=p.map(_=>N1(_,d)),A=t.includeRaw?OB(S,o):S,I=A.slice(v,v+Math.max(1,t.limit??BY)),C=f===1/0?I.length:P1(I.map(_=>or(_)),f);return{nodes:I.slice(0,C),total:A.length,fits:v===0&&C===A.length}},"tree"),y=t.includeRaw?"tree":t.view??(a===void 0?"auto":"outline"),w=y==="outline"?void 0:g();if(w&&(y==="tree"||w.fits)){let S=v+w.nodes.length;return{...m,view:"tree",total:w.total,truncated:S<w.total,...S<w.total?{nextOffset:S,hint:'More nodes follow: pass `offset: nextOffset`. `view: "outline"` gives the whole unit as one short line a node.'}:{},events:w.nodes}}let b=hB(p,{fold:t.fold!==!1}),k=b.slice(v).map(D1),$=f===1/0?k.length:P1(k.map(S=>Ep(JSON.stringify(S))),Math.max(jB,f-Ep(mB)-1200)),E=v+$,x=E<b.length;return{...m,view:"outline",...y==="auto"?{why:'this unit is larger than one answer as a tree \u2014 pass `view: "tree"` (with `offset`) for every field of every node'}:{},total:b.length,nodes:p.length,truncated:x,...x?{nextOffset:E}:{},legend:mB,...x||v>0?{heaviest:fB(b)}:{},rows:k.slice(0,$),hint:'Open a row with `expand: "<node id>"` (add `includeRaw: true` for payloads). `fold: false` lists the zero-time frames a row names.'}}l(L1,"aU"),u(L1,"getFlowDetail");async function PB(e,t,s){if(e){let r=e.classifiedRecent(),i=MB(r,{...t.category?{category:t.category}:{},...t.tag?{tag:t.tag}:{}}),a=i.slice(0,t.limit);return{flows:a.map(o=>({...o.summary,category:o.category,decidedBy:o.decidedBy,...o.subject?{subject:o.subject}:{},tags:o.tags,segmentCount:o.segmentCount,phaseCount:o.phaseCount,signalCount:o.signalCount})),totalKnown:r.length,matching:i.length,categories:qB(r),...t.groupBy==="category"?{groups:BB(a)}:{}}}let n=await s();return{flows:n.flows.slice(0,t.limit),totalKnown:n.flows.length}}l(PB,"lU"),u(PB,"listRecentFlows");async function LB(e,t,s){if(!e)return F1(e,t);let n=await nh(e,t.flowId,s);if(!("lookups"in n))return n;let r=F1(n.lookups,t);return n.recovered?{...r,recovered:n.recovered}:r}l(LB,"uU"),u(LB,"readFlowSegments");function F1(e,t){if(!e)return{found:!1,reason:"no active flow reducer"};let s=e.analyzeFlow(t.flowId);return s?{found:!0,...ih(s,{maxSegments:t.maxSegments})}:{found:!1,flowId:t.flowId}}l(F1,"cU"),u(F1,"getFlowSegments");import{z as He}from"@frontmcp/sdk";var U1=100,qY={limit:He.number().int().positive().default(10).describe(`How many flows to return (default 10, at most ${U1} \u2014 more reads as ${U1}).`),category:He.string().optional().describe('Only flows in this category, e.g. "page-load" or "checkout".'),tag:He.string().optional().describe('Only flows carrying this tag, e.g. "has-error" or "fan-out".'),groupBy:He.enum(["none","category"]).default("none").describe('"category" adds `groups`: the returned flows grouped category \u2192 subject.')},jY=He.object({flowId:He.string(),originType:He.string().optional(),originNodeId:He.string().optional(),startedAt:He.number(),lastSeenAt:He.number(),eventCount:He.number(),headline:He.string(),category:He.string().optional(),decidedBy:He.string().optional(),subject:He.string().optional(),tags:He.array(He.string()).optional(),segmentCount:He.number().optional(),phaseCount:He.number().optional(),signalCount:He.number().optional()}).passthrough(),RY=He.object({flows:He.array(jY),totalKnown:He.number(),matching:He.number().optional(),categories:He.record(He.string(),He.number()).optional(),groups:He.array(He.unknown()).optional().describe('`groupBy: "category"`: { category, count, subjects: [{ subject, count, flowIds }] }.')}).passthrough(),z1=class extends EY{static{l(this,"OE")}static{u(this,"FlowListRecentTool")}async execute(e){let t=await PB(Tt(),{...e,limit:Math.min(e.limit,U1)},async()=>await this.get(X).read("flow://recent"));return{...t,flows:t.flows.map(s=>({...s}))}}};z1=P([xY({name:"flow_list_recent",description:'The last N flows: origin, event count, headline, `category` (page-load, user-action, api, ai, test, or one you defined), `subject` (the page, component or route) and `tags` (has-error, slow, fan-out\u2026). Filter by `category` / `tag`; `groupBy: "category"` groups them category \u2192 subject. A request made without a browser is `api:<x-request-id>`, a queue job nobody stamped `job:<queue>#<job id>`.',annotations:{readOnlyHint:!0},inputSchema:qY,outputSchema:RY})],z1);var OY=z1;import{Tool as NY,ToolContext as PY}from"@frontmcp/sdk";import{z as Ae}from"@frontmcp/sdk";var W1=500,LY={flowId:Ae.string().describe("From flow_list_recent, or derived: `api:<x-request-id>` (a request without a browser), `job:<queue>#<job id>`."),includeRaw:Ae.boolean().default(!1).describe("Each event's full `raw` payload (always the tree)."),view:Ae.enum(["auto","tree","outline"]).optional().describe("`outline` (default): one short line a node. `tree`: every field of every node. `auto`: the tree when the whole unit fits, else the outline."),limit:Ae.number().int().positive().optional().describe(`Tree only: the most nodes in one answer (default 200, at most ${W1} \u2014 a bigger one reads as ${W1}). The outline is cut by the answer's size; page either with \`offset\`.`),offset:Ae.number().int().nonnegative().optional().describe("The previous answer's `nextOffset`."),fold:Ae.boolean().optional().describe("Outline: 0 ms frames named on their parent's row (default); `false` gives each a row."),expand:Ae.string().optional().describe("A node id: that node in full and the events it collapsed."),segmentId:Ae.string().optional().describe("A segment id from `overview.segments`: only that unit.")},FY=Ae.object({summary:Ae.unknown().optional().describe("The flow: flowId, originType, originNodeId, startedAt, lastSeenAt, eventCount, headline."),segment:Ae.object({id:Ae.string(),kind:Ae.string(),label:Ae.string(),category:Ae.string()}).passthrough().optional().describe("The unit read (`segmentId`): its kind, label, category, phase, times, counts, route, sql."),overview:Ae.unknown().optional().describe("The whole flow cut into segments and phases (as flow_segments gives it); `overview.sql.status` says whether every statement is here."),view:Ae.enum(["tree","outline"]).optional(),why:Ae.string().optional(),total:Ae.number().optional(),nodes:Ae.number().optional().describe("Outline: the nodes the rows stand for."),truncated:Ae.boolean().optional(),nextOffset:Ae.number().optional(),legend:Ae.string().optional(),heaviest:Ae.array(Ae.object({row:Ae.number(),line:Ae.string()}).passthrough()).optional(),rows:Ae.array(Ae.string()).optional(),hint:Ae.string().optional(),events:Ae.array(Ae.unknown()).optional().describe("Tree: the nodes, each with its `parent`. `expand`: the events the node stands for."),flowId:Ae.string().optional(),expanded:Ae.object({id:Ae.string(),title:Ae.string(),count:Ae.number()}).passthrough().optional(),node:Ae.record(Ae.string(),Ae.unknown()).optional(),recovered:Ae.unknown().optional().describe('Where it was read back from: { from: "history" | "bus", files, events, complete }.')}).passthrough();import{PublicMcpError as FB}from"@frontmcp/sdk";var H1=u(e=>new FB(e,"UNAVAILABLE",503),"unavailable"),ln=u(e=>new FB(e,"NOT_FOUND",404),"notFound"),UB="no active flow reducer: this lens server holds no flows";function G1(e,t){if(e.segmentId!==void 0){let s=e.segmentIds??[],n=s.length?` Its segments: ${s.slice(0,40).join(", ")}${s.length>40?` \u2026 (${s.length})`:""}.`:"";return ln(`flow ${t} has no segment ${e.segmentId} \u2014 the flow may have changed: re-read overview.segments (or flow_segments).${n}`)}return e.expand!==void 0?ln(`flow ${t} has no node ${e.expand} \u2014 open a node by the [id] at the end of an outline row, or by a tree node's id.`):e.reason==="outside-window"?H1(`flow ${t} may be older than this server can see \u2014 re-run it rather than conclude it never happened. ${e.hint??""}`.trim()):e.flowId===void 0?H1(UB):ln(`no event of flow ${t} is held \u2014 not in this server's memory, the workspace's event history or the bus files. flow_list_recent names the flows it holds.`)}l(G1,"PE"),u(G1,"flowUnreadable");var Z1=class extends PY{static{l(this,"NE")}static{u(this,"FlowGetTool")}async execute(e){let t=e.limit===void 0?{}:{limit:Math.min(e.limit,W1)},s=await RB(Tt(),{...e,...t},Xp(),{budgetBytes:xp()});s.found===!1&&this.fail(G1(s,e.flowId));let{found:n,...r}=s;return r}};Z1=P([NY({name:"flow_get",description:'One flow \u2014 or one unit of it (`segmentId`) \u2014 as the ordered, parented mechanism the dashboard renders, always within one answer. Default `view: "outline"`: one short line a node, indented by depth \u2014 `+<ms from start> <dots = depth><area> <kind>: <title> \u2014 <duration> \xD7<count> !<severity> [<node id>]`; `view: "tree"` gives every field of every node. `expand: "<node id>"` opens one node and the events it stands for (`includeRaw: true` adds payloads). A cut answer says `truncated` and `nextOffset`; a cut outline lists `heaviest` (what failed or took longest in the whole unit). `overview` cuts the flow into segments by phase \u2014 read it first for a big flow. Before summing SQL, check `overview.sql.status`: only "complete" means every statement is here. A flow no longer in memory is read back from the workspace\'s event history (30 days) or the bus (`recovered`). It fails NOT_FOUND when no event of the id (or no such segment or node) is held, and UNAVAILABLE when the flow may be older than the server can see \u2014 the message says what it holds; re-run it rather than conclude it never happened.',annotations:{readOnlyHint:!0},inputSchema:LY,outputSchema:FY})],Z1);var UY=Z1;import{Tool as zY,ToolContext as WY}from"@frontmcp/sdk";import{z as Vs}from"@frontmcp/sdk";var HY={originNodeId:Vs.string().describe("Origin node id \u2014 usually the value of data-agent-component on the originating element.")},GY=Vs.object({flowId:Vs.string(),originType:Vs.string().optional(),originNodeId:Vs.string().optional(),startedAt:Vs.number(),lastSeenAt:Vs.number(),eventCount:Vs.number(),headline:Vs.string()}).passthrough(),ZY=Vs.object({count:Vs.number(),flows:Vs.array(GY)}).passthrough(),V1=class extends WY{static{l(this,"qE")}static{u(this,"FlowFindByOriginTool")}async execute(e){let t=Tt();t||this.fail(H1(UB));let s=t.findFlowsByOrigin(e.originNodeId);return{count:s.length,flows:s.map(n=>({...n}))}}};V1=P([zY({name:"flow_find_by_origin",description:"Returns all flows whose origin node id matches `originNodeId` (e.g. a data-agent-component target).",annotations:{readOnlyHint:!0},inputSchema:HY,outputSchema:ZY})],V1);var VY=V1;import{Tool as JY,ToolContext as KY}from"@frontmcp/sdk";import*as QY from"node:fs";import{dirname as YY,join as zB}from"node:path";var XY="ai",eX=/^ai_[0-9a-z]{8,40}$/,ah=u(e=>typeof e=="string"&&eX.test(e),"isAiCallId");function WB(e){return zB(YY(e),XY)}l(WB,"D7"),u(WB,"aiContentDir");function HB(e,t){if(!ah(t))throw new Error("invalid ai call id");return zB(WB(e),`${t}.json`)}l(HB,"U7"),u(HB,"aiContentFile");function J1(e,t){if(ah(t))try{let s=JSON.parse(QY.readFileSync(HB(e,t),"utf8"));return s&&s.schemaVersion===1&&s.id===t?s:void 0}catch{return}}l(J1,"xf"),u(J1,"readAiContent");import{z as it}from"@frontmcp/sdk";import{z as jn}from"@frontmcp/sdk";var tX=jn.object({entry:jn.string(),bytes:jn.number(),shape:jn.array(jn.string()),query:jn.string(),resultHandle:jn.string().optional()}).passthrough(),K1=u(e=>jn.union([e,tX]).meta({type:"object"}),"foldable"),sX={callId:it.string().describe('The contentRef of an ai-call flow node, e.g. "ai_0abc12345xyz78".')},rX=it.object({id:it.string(),capturedAt:it.number(),flowId:it.string().optional(),requestId:it.string().optional(),project:it.string().optional(),provider:it.string(),api:it.string(),model:it.string().optional(),host:it.string(),endpoint:it.string(),stream:it.boolean(),status:it.number().optional(),request:it.object({system:it.string().optional(),messages:it.array(it.unknown())}).passthrough(),response:it.object({completion:it.string().optional(),finishReason:it.string().optional()}).passthrough().optional(),truncated:it.boolean().optional()}).passthrough(),nX=K1(it.object({call:rX}).passthrough()),Q1=class extends KY{static{l(this,"UE")}static{u(this,"AiGetCallTool")}async execute(e){let t=JSON.stringify(e.callId.slice(0,80));ah(e.callId)||this.fail(ln(`${t} is not an AI call id \u2014 pass the \`ai.contentRef\` of an ai-call flow node (ai_\u2026, see flow_get)`));let s=J1(process.env.LENSMCP_EVENT_FILE??`${process.cwd()}/.lensmcp/events.jsonl`,e.callId);return s||this.fail(ln(`no captured content for AI call ${t} \u2014 it was not captured (LENSMCP_AI_CAPTURE=content), or it has been rotated away`)),{call:{...s}}}};Q1=P([JY({name:"ai_get_call",description:"Returns the prompt and completion of ONE AI call (OpenAI, Anthropic, \u2026) captured by the node tap: system prompt, messages, tools offered, completion, tool calls, usage. `callId` is the `ai.contentRef` of a flow node whose kind is `ai-call` (see flow_get). Only exists when the service ran with LENSMCP_AI_CAPTURE=content (else it fails NOT_FOUND); the text was redacted and size-capped when it was captured, and `truncated: true` says if anything was cut.",annotations:{readOnlyHint:!0},inputSchema:sX,outputSchema:nX})],Q1);var iX=Q1;import{dirname as aX}from"node:path";import{Tool as oX,ToolContext as uX}from"@frontmcp/sdk";import{createReadStream as GB}from"node:fs";import{join as lX}from"node:path";import{createInterface as ZB}from"node:readline";var dX="sql",cX="cache",Y1=/^(sqv|cav)_(\d{12})_(\d{1,10})_([0-9a-z]{1,12})$/,pX={sqv:dX,cav:cX};function X1(e,t){let s=Y1.exec(t);return s?lX(e,pX[s[1]],`${s[3]}-${s[2]}.jsonl`):void 0}l(X1,"EU"),u(X1,"keptValuesFile");function oh(e){return typeof e=="string"&&Y1.test(e)&&e.startsWith("sqv_")}l(oh,"Dl"),u(oh,"isSqlValuesId");function e4(e){return typeof e=="string"&&Y1.test(e)&&e.startsWith("cav_")}l(e4,"FE"),u(e4,"isCacheValuesId");async function t4(e,t){return oh(t)?await s4(e,t):void 0}l(t4,"$f"),u(t4,"readSqlValues");async function VB(e,t){return e4(t)?await s4(e,t):void 0}l(VB,"AU"),u(VB,"readCacheValues");async function s4(e,t){let s=X1(e,t);if(!s)return;let n=`{"id":${JSON.stringify(t)},`,r=GB(s,{encoding:"utf8"}),i=ZB({input:r,crlfDelay:1/0});try{for await(let a of i){if(!a.startsWith(n))continue;let o=JSON.parse(a);return o.id===t?o:void 0}}catch{}finally{i.close(),r.destroy()}}l(s4,"TU"),u(s4,"readKeptValues");async function JB(e,t){let s=new Map;for(let r of t){let i=X1(e,r);if(!i)continue;let a=s.get(i)??new Set;a.add(r),s.set(i,a)}let n=new Map;for(let[r,i]of s){let a=GB(r,{encoding:"utf8"}),o=ZB({input:a,crlfDelay:1/0}),c=i.size;try{for await(let p of o){let d=/^\{"id":"((?:sqv|cav)_[0-9a-z_]+)",/.exec(p);if(!(!d||!i.has(d[1])||n.has(d[1]))){try{n.set(d[1],JSON.parse(p))}catch{continue}if(--c===0)break}}}catch{}finally{o.close(),a.destroy()}}return n}l(JB,"IU"),u(JB,"readKeptValuesMany");function KB(e,t){if(!t?.length)return e;let s=u(i=>i==="null"||i==="undefined"?"NULL":`'${i.replace(/'/g,"''")}'`,"literal"),n="",r=0;for(;r<e.length;){let i=e[r];if(i==="'"){let o=e.indexOf("'",r+1),c=o<0?e.length:o+1;n+=e.slice(r,c),r=c;continue}let a=i==="$"?/^\$(\d+)/.exec(e.slice(r,r+12)):null;if(a){let o=t[Number(a[1])-1];n+=o===void 0?a[0]:s(o),r+=a[0].length;continue}n+=i,r++}return n}l(KB,"RU"),u(KB,"sqlWithValues");import{z as Js}from"@frontmcp/sdk";var hX={valuesId:Js.string().describe('The valuesId of a db-query flow node or a replay_story SQL item, e.g. "sqv_202610211530_4242_1k".')},mX=Js.object({id:Js.string(),at:Js.number(),params:Js.array(Js.string()).optional(),paramCount:Js.number().optional(),rows:Js.array(Js.unknown()).optional(),rowCount:Js.number().optional(),cut:Js.boolean().optional()}).passthrough(),fX=K1(Js.object({values:mX}).passthrough()),r4=class extends uX{static{l(this,"BE")}static{u(this,"SqlGetValuesTool")}async execute(e){let t=JSON.stringify(e.valuesId.slice(0,80));oh(e.valuesId)||this.fail(ln(`${t} is not a SQL values id \u2014 pass the \`valuesId\` of a db-query flow node or a replay_story SQL item (sqv_\u2026)`));let s=aX(Bs(process.env,process.env.LENSMCP_WORKSPACE_ROOT||process.cwd())),n=await t4(s,e.valuesId);return n||this.fail(ln(`no values kept for ${t} \u2014 written within the last second, turned off (Settings \u203A Features \u203A SQL, or LENSMCP_SQL_VALUES=0), pruned (a day), or written by another checkout's services`)),{values:{...n}}}};r4=P([oX({name:"sql_get_values",description:'Every parameter of ONE SQL run, at full length, and the rows it returned \u2014 where a flow step keeps the first 10 values at 80 characters. `valuesId` is on a db-query flow node (flow_get) or a replay_story SQL item. `params[i]` is `$i+1`; a value bound to a credential column or shaped like a secret is "REDACTED"; `cut: true` says the run passed its 64 KB (`paramCount` / `rowCount` say how many there were). Fails NOT_FOUND when it is not kept: written within the last second, turned off (Settings \u203A Features \u203A SQL), pruned (a day), or written by another checkout\'s services.',annotations:{readOnlyHint:!0},inputSchema:hX,outputSchema:fX})],r4);var gX=r4;import{dirname as vX}from"node:path";import{Tool as yX,ToolContext as wX}from"@frontmcp/sdk";import{z as Ks}from"@frontmcp/sdk";var bX={valuesId:Ks.string().describe('The valuesId of a redis-op flow node or a replay_story cache item, e.g. "cav_202610211530_4242_1k".')},kX=Ks.object({id:Ks.string(),at:Ks.number(),op:Ks.string(),key:Ks.string(),args:Ks.array(Ks.string()).optional(),argCount:Ks.number().optional(),reply:Ks.unknown().optional(),cut:Ks.boolean().optional()}).passthrough(),$X=K1(Ks.object({values:kX}).passthrough()),n4=class extends wX{static{l(this,"HE")}static{u(this,"CacheGetValueTool")}async execute(e){let t=JSON.stringify(e.valuesId.slice(0,80));e4(e.valuesId)||this.fail(ln(`${t} is not a cache values id \u2014 pass the \`valuesId\` of a redis-op flow node or a replay_story cache item (cav_\u2026); a SQL run's (sqv_\u2026) is sql_get_values'`));let s=vX(Bs(process.env,process.env.LENSMCP_WORKSPACE_ROOT||process.cwd())),n=await VB(s,e.valuesId);return n||this.fail(ln(`no values kept for ${t} \u2014 written within the last second, turned off (Settings \u203A Features, or LENSMCP_SQL_VALUES=0), pruned (a day), or written by another checkout's services`)),{values:{...n}}}};n4=P([yX({name:"cache_get_value",description:'Every argument of ONE cache (Redis) command at full length and the reply it got \u2014 a JSON reply parsed \u2014 where a flow step keeps 48 characters of an argument and 120 of a reply. `valuesId` is on a redis-op flow node (flow_get) or a replay_story cache item. A credential-named field of a reply, or a secret-shaped value, is "REDACTED"; a key that keeps a credential (a session, a one-time code) is never kept. `cut: true` says it passed its 64 KB. Fails NOT_FOUND when it is not kept: written within the last second, turned off (Settings \u203A Features \u203A SQL and cache), pruned (a day), or written by another checkout\'s services.',annotations:{readOnlyHint:!0},inputSchema:bX,outputSchema:$X})],n4);var xX=n4;import{Tool as EX,ToolContext as SX}from"@frontmcp/sdk";import{z as at}from"@frontmcp/sdk";var i4=500,AX={flowId:at.string().describe("Flow id from flow://recent or flow_list_recent (or derived: `api:<x-request-id>`, `job:<queue>#<job id>`)."),maxSegments:at.number().int().positive().default(120).describe(`Cap on segments listed (default 120, at most ${i4} \u2014 more reads as ${i4}); failing and heaviest are kept first when it truncates.`)},CX=at.object({flowId:at.string(),category:at.string(),decidedBy:at.string(),subject:at.string().optional(),tags:at.array(at.string()),origin:at.unknown().describe("How the flow started: { type, nodeId }."),stats:at.object({events:at.number(),signal:at.number(),bookkeeping:at.number(),segments:at.number(),phases:at.number()}).passthrough(),phases:at.array(at.unknown()).describe("Each: index, startOffsetMs, endOffsetMs, segmentIds."),segments:at.array(at.unknown()).describe("Each: id, kind, label, category, phase, startOffsetMs, durationMs, events, signal, errors, worstSeverity, projects, route, method, sql\u2026"),segmentsTruncated:at.boolean(),sql:at.unknown().optional().describe('The flow\'s SQL completeness: sum SQL only when `status` is "complete".'),recovered:at.unknown().optional().describe('A flow no longer in memory: where it was read back from \u2014 { from: "history" | "bus", files, events, complete }.')}).passthrough(),a4=class extends SX{static{l(this,"WE")}static{u(this,"FlowSegmentsTool")}async execute(e){let t=await LB(Tt(),{...e,maxSegments:Math.min(e.maxSegments,i4)},Xp());t.found===!1&&this.fail(G1(t,e.flowId));let{found:s,...n}=t;return n}};a4=P([EX({name:"flow_segments",description:"One flow cut into segments \u2014 a backend request with its hops and db / cache / AI work, a UI burst, the origin \u2014 and phases, with times, event and error counts and categories: the first read for a big flow. Open one with flow_get { flowId, segmentId }. A flow no longer in memory is read back from the event history or the bus (`recovered`); like flow_get it fails NOT_FOUND for a flow no event of which is held, UNAVAILABLE for one older than the server can see.",annotations:{readOnlyHint:!0},inputSchema:AX,outputSchema:CX})],a4);var IX=a4,QB=class{static{l(this,"GE")}static{u(this,"FlowApp")}};QB=P([hY({id:"flow",name:"Flow",description:"Causal-chain index: every event carries a flowId; the app surfaces recent flows + origin events. story_compile turns one of these into a phase summary.",resources:[gY,wY,$Y],tools:[OY,UY,IX,VY,iX,gX,xX]})],QB);import{App as DX}from"@frontmcp/sdk";import{Resource as TX,ResourceContext as _X}from"@frontmcp/sdk";var o4=class extends _X{static{l(this,"VE")}static{u(this,"StoryRecentResource")}async execute(){return this.get(X).read("story://recent")}};o4=P([TX({name:"story-recent",uri:"story://recent",mimeType:"application/json",description:"Last 50 compiled stories (one per flow), most recent first."})],o4);var MX=o4;import{Resource as BX,ResourceContext as qX}from"@frontmcp/sdk";var u4=class extends qX{static{l(this,"ZE")}static{u(this,"StoryLastResource")}async execute(){return this.get(X).read("story://last")}};u4=P([BX({name:"story-last",uri:"story://last",mimeType:"application/json",description:"The most recently compiled story (full phase list)."})],u4);var jX=u4;import{Tool as RX,ToolContext as OX}from"@frontmcp/sdk";var uh="story://recent",lh="story://last",Qs={byFlowId:new Map,order:[]},YB=!1;function XB(e){return YB||(e.resources.register(uh,()=>({schemaVersion:1,revision:e.resources.revision(uh)??0,updatedAt:new Date().toISOString(),stories:Qs.order.map(t=>Qs.byFlowId.get(t)).filter(t=>!!t).map(t=>({flowId:t.flowId,origin:t.origin,phaseCount:t.phases.length,startedAt:t.startedAt,endedAt:t.endedAt,eventCount:t.eventCount,finalState:t.finalState}))})),e.resources.register(lh,()=>{let t=Qs.order[0],s=t?Qs.byFlowId.get(t):void 0;return{schemaVersion:1,revision:e.resources.revision(lh)??0,updatedAt:new Date().toISOString(),story:s??null}}),YB=!0),eq(e.resources),{uris:[uh,lh]}}l(XB,"XE"),u(XB,"installStoryReducer");var l4;function eq(e){l4=u(t=>{e.markDirty(t)},"markDirty")}l(eq,"lee"),u(eq,"setMarkDirty");function d4(e){Qs.byFlowId.set(e.flowId,e);let t=Qs.order.indexOf(e.flowId);if(t>=0&&Qs.order.splice(t,1),Qs.order.unshift(e.flowId),Qs.order.length>50){let s=Qs.order.splice(50);for(let n of s)Qs.byFlowId.delete(n)}l4?.(uh),l4?.(lh)}l(d4,"Ul"),u(d4,"recordCompiledStory");function tq(e){return Qs.byFlowId.get(e)}l(tq,"YE"),u(tq,"getCompiledStory");import{z as $s}from"@frontmcp/sdk";var NX={flowId:$s.string().describe("Flow id (from flow://recent).")},sq=$s.object({flowId:$s.string(),origin:$s.object({type:$s.string().optional(),nodeId:$s.string().optional(),at:$s.number()}).passthrough(),phases:$s.array($s.unknown()).describe("Each: kind (user-action, loading-ui, idle-ui, route-transition, state-update, backend-request, render, final-render, visual-violation), at, label, eventIds, details."),finalState:$s.unknown().optional().describe("The state it settled in: page, route, componentName, renderId, visualFrameId."),startedAt:$s.number(),endedAt:$s.number(),eventCount:$s.number()}).passthrough(),PX=$s.object({story:sq}).passthrough();import{PublicMcpError as c4}from"@frontmcp/sdk";var LX=u(e=>new c4(e,"UNAVAILABLE",503),"unavailable"),rq=u(e=>new c4(e,"NOT_FOUND",404),"notFound"),FX=u(e=>new c4(e,"REFUSED",409),"refused"),p4=class extends OX{static{l(this,"nA")}static{u(this,"StoryCompileTool")}async execute(e){let t=Tt();t||this.fail(LX("no active flow reducer: this lens server holds no flows to compile"));let s=t.getFlowEvents(e.flowId);s||this.fail(rq(`no flow ${e.flowId} is held \u2014 flow_list_recent names the flows held`));let n=Vw(s,{flowId:e.flowId});return n||this.fail(FX(`flow ${e.flowId} is held, but none of its events carries its id \u2014 there is nothing to compile a story from`)),d4(n),{story:{...n}}}};p4=P([RX({name:"story_compile",description:"Compile a flow into a `FlowStory` (origin, phases, finalState). Caches the result; subsequent story_get { flowId } calls return it directly. A flow the lens does not hold fails NOT_FOUND.",inputSchema:NX,outputSchema:PX})],p4);var UX=p4;import{Tool as zX,ToolContext as WX}from"@frontmcp/sdk";import{z as nq}from"@frontmcp/sdk";import{z as Rn}from"@frontmcp/sdk";var HX=Rn.object({entry:Rn.string(),bytes:Rn.number(),shape:Rn.array(Rn.string()),query:Rn.string(),resultHandle:Rn.string().optional()}).passthrough(),GX=u(e=>Rn.union([e,HX]).meta({type:"object"}),"foldable"),ZX={flowId:nq.string().describe("Flow id.")},VX=GX(nq.object({story:sq}).passthrough()),h4=class extends WX{static{l(this,"sA")}static{u(this,"StoryGetTool")}async execute(e){let t=tq(e.flowId);return t||this.fail(rq(`no story compiled for flow ${e.flowId} \u2014 story_compile { flowId } compiles it`)),{story:{...t}}}};h4=P([zX({name:"story_get",description:"Returns a previously compiled story. A story not compiled yet fails NOT_FOUND; call story_compile first.",annotations:{readOnlyHint:!0},inputSchema:ZX,outputSchema:VX})],h4);var JX=h4,iq=class{static{l(this,"iA")}static{u(this,"StoryApp")}};iq=P([DX({id:"story",name:"Story",description:"Compiles flows into phase summaries (user-action / loading-ui / backend-request / state-update / final-render).",resources:[MX,jX],tools:[UX,JX]})],iq);import{App as KX}from"@frontmcp/sdk";import{Resource as QX,ResourceContext as YX}from"@frontmcp/sdk";var m4=class extends YX{static{l(this,"aA")}static{u(this,"BuildCurrentResource")}async execute(){return this.get(X).read("build://current")}};m4=P([QX({name:"build-current",uri:"build://current",mimeType:"application/json",description:"Current build status (clean / warning / failing), open failures and warnings."})],m4);var XX=m4;import{Resource as eee,ResourceContext as tee}from"@frontmcp/sdk";var f4=class extends tee{static{l(this,"dA")}static{u(this,"BuildFailuresResource")}async execute(){return this.get(X).read("build://failures")}};f4=P([eee({name:"build-failures",uri:"build://failures",mimeType:"application/json",description:"Currently-open build failures (deduped by fingerprint)."})],f4);var see=f4;import{Resource as ree,ResourceContext as nee}from"@frontmcp/sdk";var g4=class extends nee{static{l(this,"uA")}static{u(this,"BuildRecentResource")}async execute(){return this.get(X).read("build://events/recent")}};g4=P([ree({name:"build-events-recent",uri:"build://events/recent",mimeType:"application/json",description:"Last 50 build/lint/typecheck/HMR events in chronological order."})],g4);var iee=g4,aq=class{static{l(this,"hA")}static{u(this,"BuildApp")}};aq=P([KX({id:"build",name:"Build",description:"Vite / TS / lint / HMR state.",resources:[XX,see,iee]})],aq);var dh="build://current",ch="build://failures",cl="build://events/recent",aee=new Set(["vite","rollup","typescript","eslint"]),oq=new Set(["build","typecheck","lint"]),uq=50,oee="Install the LensMCP Vite plugin (@lensmcp/vite-plugin) in the dev server, or run under the dev cluster, so build events reach this session.";function lq(e){let t=e.raw;return t&&typeof t=="object"?t:{}}l(lq,"Eee"),u(lq,"readRaw");function dq(e,t){return e==="typecheck"?"tsc":e==="lint"?"eslint":t}l(dq,"Aee"),u(dq,"defaultTool");function cq(e){let t={status:"unknown",recent:[],failures:new Map,warnings:new Map,hmrUpdates:0,producers:new Map,sawVerdict:!1,newInRun:new Map,repeatedInRun:new Map},s=u((m,f)=>{let v=t.producers.get(m);t.producers.set(m,{id:m,tool:f.tool,...f.project?{project:f.project}:{},firstReportedAt:v?.firstReportedAt??f.at,lastReportedAt:Math.max(v?.lastReportedAt??0,f.at),lastRunStatus:f.runStatus,errorCount:f.errorCount??v?.errorCount??0,...f.warningCount!==void 0?{warningCount:f.warningCount}:v?.warningCount!==void 0?{warningCount:v.warningCount}:{},...f.durationMs!==void 0?{lastRunDurationMs:f.durationMs}:v?.lastRunDurationMs!==void 0?{lastRunDurationMs:v.lastRunDurationMs}:{},...f.error?{error:f.error}:{}}),wi(t.producers,Gu)},"touchProducer"),n=u(m=>{for(let[f,v]of t.failures)m(v)&&t.failures.delete(f);for(let[f,v]of t.warnings)m(v)&&t.warnings.delete(f)},"drop"),r=u((m,f)=>{n(v=>v.domain===m&&(f===void 0||v.project===f))},"clearScope"),i=u((m,f)=>{if(f.length===0)return;let v=new Set(f);n(g=>g.domain===m&&g.file!==void 0&&v.has(g.file))},"clearFiles"),a=u(()=>{if(t.failures.size>0){t.status="failing";return}if(t.warnings.size>0){t.status="warning";return}let m=[...t.producers.values()].some(f=>f.lastRunStatus==="error");t.status=m||!t.sawVerdict?"unknown":"clean"},"recomputeStatus"),o=u(()=>{e.resources.markDirty(dh),e.resources.markDirty(ch),e.resources.markDirty(cl)},"markDirty"),c=u(m=>{if([...t.failures.values()].some(f=>f.project===m)||[...t.warnings.values()].some(f=>f.project===m)||[...t.producers.values()].some(f=>f.project===m)){for(let f of oq)r(f,m);for(let[f,v]of t.producers)v.project===m&&t.producers.delete(f);t.sawVerdict=[...t.producers.values()].some(f=>f.lastRunStatus!=="error"),a(),o()}},"supersedeProject"),p=u(m=>{if(m.source==="gateway"&&m.category==="cluster"){let x=m.raw??null,S=x?.kind;(S==="service-starting"||S==="service-respawn")&&x?.project&&c(x.project),(S==="service-swap"||S==="service-build")&&(Ua(t,mq(m)),e.resources.markDirty(cl));return}if(!aee.has(m.source)||!oq.has(m.category))return;let f=m.category,v=lq(m),g=v.project,y=v.tool??dq(f,m.source),w=`${y}:${g??"*"}`,b=typeof v.kind=="string"&&v.kind.endsWith("-run"),k=hq(m.title,m.message),$={id:m.id,timestamp:m.timestamp,severity:m.severity,title:k.title,...k.message!==void 0?{message:k.message}:{},...m.location?.file?{file:m.location.file}:v.file?{file:v.file}:{},domain:f,...g?{project:g}:{},fingerprint:m.fingerprint};if(m.severity==="info"&&(b&&v.phase==="start"||m.title.startsWith("tsc clear")||m.title.startsWith("ESLint clear"))){r(f,g),t.lastRunAt=m.timestamp,t.newInRun.set(w,0),Ua(t,$),s(w,{tool:y,...g?{project:g}:{},at:m.timestamp,runStatus:"running"}),b||(t.sawVerdict=!0),a(),o();return}if(b&&v.phase==="end"){let x=v.status==="error"?"error":v.status==="failing"?"failing":"clean";x==="clean"&&r(f,g),x!=="error"&&(t.sawVerdict=!0),t.lastRunAt=m.timestamp,x==="failing"&&t.newInRun.get(w)===0&&t.repeatedInRun.get(w)&&($.unchanged=!0,$.title=`${$.title}, unchanged`),t.newInRun.delete(w),t.repeatedInRun.delete(w),Ua(t,$),s(w,{tool:y,...g?{project:g}:{},at:m.timestamp,runStatus:x,...v.durationMs!==void 0?{durationMs:v.durationMs}:{},...v.errorCount!==void 0?{errorCount:v.errorCount}:{},...v.warningCount!==void 0?{warningCount:v.warningCount}:{},...v.error?{error:v.error}:{}}),a(),o();return}if(v.kind==="hmr"||m.title.startsWith("HMR ")){t.hmrUpdates+=1;let x=[...$.file?[$.file]:[],...m.relatedFiles??[]];i("build",x),t.lastRunAt=m.timestamp,t.sawVerdict=!0,Ua(t,$),s(w,{tool:y,...g?{project:g}:{},at:m.timestamp,runStatus:"clean"}),a(),o();return}let E=m.severity!=="info"?t.recent.find(x=>x.fingerprint===$.fingerprint&&x.domain===f&&x.project===$.project&&x.title===$.title):void 0;E?(E.lastSeenAt=m.timestamp,E.runs=(E.runs??1)+1,t.repeatedInRun.set(w,!0)):(Ua(t,$),t.newInRun.has(w)&&m.severity!=="info"&&t.newInRun.set(w,(t.newInRun.get(w)??0)+1)),m.severity==="error"||m.severity==="fatal"?(t.failures.set($.fingerprint,$),t.warnings.delete($.fingerprint)):m.severity==="warning"?t.failures.has($.fingerprint)||t.warnings.set($.fingerprint,$):(t.failures.delete($.fingerprint),t.warnings.delete($.fingerprint)),t.lastRunAt=m.timestamp,t.sawVerdict=!0,s(w,{tool:y,...g?{project:g}:{},at:m.timestamp,runStatus:t.failures.size>0?"failing":"clean"}),a(),o()},"handler"),d=e.bus.subscribe(p),h=u(()=>fp({producers:[...t.producers.values()],domain:"build",noProducerHint:oee}),"health");return e.resources.register(dh,()=>({schemaVersion:1,revision:e.resources.revision(dh)??0,updatedAt:new Date().toISOString(),status:t.status,failures:[...t.failures.values()],warnings:[...t.warnings.values()],hmrUpdates:t.hmrUpdates,lastRunAt:t.lastRunAt,...h()})),e.resources.register(ch,()=>({schemaVersion:1,revision:e.resources.revision(ch)??0,updatedAt:new Date().toISOString(),failures:[...t.failures.values()],...h()})),e.resources.register(cl,()=>({schemaVersion:1,revision:e.resources.revision(cl)??0,updatedAt:new Date().toISOString(),events:t.recent.slice()})),{unsubscribe:d,uris:[dh,ch,cl]}}l(cq,"mA"),u(cq,"installBuildReducer");var pq=160;function hq(e,t){if(t===void 0||t==="")return{title:e};if(t===e)return{title:e};let s=e.indexOf("\u2026[lensmcp truncated"),n=s>=0?e.slice(0,s):e,r=t.slice(0,Math.min(t.length,48)),i=r.length>=12?n.indexOf(r):-1;if(i<0||i>40)return{title:e,message:t};let a=n.slice(0,i),o=t.split(`
199
199
  `,1)[0]??t;return o===t&&t.length<=pq?{title:`${a}${t}`}:{title:`${a}${o.slice(0,pq)}\u2026`,message:t}}l(hq,"Tee"),u(hq,"onceEach");function mq(e){let t=e.raw??{},s=t.compile??{},n=Array.isArray(t.changedFiles)?t.changedFiles.filter(i=>typeof i=="string"):void 0,r=typeof s.ms=="number"?s.ms:typeof t.compileMs=="number"?t.compileMs:void 0;return{id:e.id,timestamp:e.timestamp,severity:e.severity,title:e.title,domain:"build",...typeof t.project=="string"?{project:t.project}:{},fingerprint:e.fingerprint,kind:String(t.kind),...typeof t.phase=="string"?{phase:t.phase}:{},...typeof t.generation=="number"?{generation:t.generation}:{},...typeof t.swaps=="number"?{swaps:t.swaps}:{},...n?{changedFiles:n}:{},...typeof t.moreChanged=="number"?{moreChanged:t.moreChanged}:{},...r!==void 0?{compileMs:r}:{}}}l(mq,"Iee"),u(mq,"clusterEntry");function Ua(e,t){e.recent.push(t),e.recent.length>uq&&e.recent.splice(0,e.recent.length-uq)}l(Ua,"Fl"),u(Ua,"pushRecent");import{App as uee}from"@frontmcp/sdk";import{Resource as lee,ResourceContext as dee}from"@frontmcp/sdk";var v4=class extends dee{static{l(this,"fA")}static{u(this,"LintCurrentResource")}async execute(){return this.get(X).read("lint://current")}};v4=P([lee({name:"lint-current",uri:"lint://current",mimeType:"application/json",description:"Current lint status (clean / warning / failing) + counts."})],v4);var cee=v4;import{Resource as pee,ResourceContext as hee}from"@frontmcp/sdk";var y4=class extends hee{static{l(this,"yA")}static{u(this,"LintErrorsResource")}async execute(){return this.get(X).read("lint://errors")}};y4=P([pee({name:"lint-errors",uri:"lint://errors",mimeType:"application/json",description:"Currently-open ESLint errors (deduped by fingerprint)."})],y4);var mee=y4;import{Resource as fee,ResourceContext as gee}from"@frontmcp/sdk";var w4=class extends gee{static{l(this,"vA")}static{u(this,"LintWarningsResource")}async execute(){return this.get(X).read("lint://warnings")}};w4=P([fee({name:"lint-warnings",uri:"lint://warnings",mimeType:"application/json",description:"Currently-open ESLint warnings."})],w4);var vee=w4,fq=class{static{l(this,"kA")}static{u(this,"LintApp")}};fq=P([uee({id:"lint",name:"Lint",description:"ESLint state.",resources:[cee,mee,vee]})],fq);var ph="lint://current",hh="lint://errors",mh="lint://warnings",yee="Nothing runs ESLint in the dev loop, so this is expected. Run `lensmcp lint [paths\u2026]` to publish a run; until then treat lint as UNCHECKED, not passing.";function gq(e){let t=e.raw;return t&&typeof t=="object"?t:{}}l(gq,"qee"),u(gq,"readRaw");function vq(e){let t={status:"unknown",errors:new Map,warnings:new Map,producers:new Map,sawVerdict:!1},s=u((d,h)=>{let m=t.producers.get(d);t.producers.set(d,{id:d,tool:h.tool,...h.project?{project:h.project}:{},firstReportedAt:m?.firstReportedAt??h.at,lastReportedAt:Math.max(m?.lastReportedAt??0,h.at),lastRunStatus:h.runStatus,errorCount:h.errorCount??m?.errorCount??0,...h.warningCount!==void 0?{warningCount:h.warningCount}:m?.warningCount!==void 0?{warningCount:m.warningCount}:{},...h.durationMs!==void 0?{lastRunDurationMs:h.durationMs}:m?.lastRunDurationMs!==void 0?{lastRunDurationMs:m.lastRunDurationMs}:{},...h.error?{error:h.error}:{}}),wi(t.producers,Gu)},"touchProducer"),n=u((d,h)=>{let m=u((f,v)=>{for(let[g,y]of f)v(y)&&f.delete(g)},"drop");if(d){m(t.errors,f=>f.project===d),m(t.warnings,f=>f.project===d);return}if(h){m(t.errors,f=>f.file===h),m(t.warnings,f=>f.file===h);return}t.errors.clear(),t.warnings.clear()},"clearScope"),r=u(()=>{if(t.errors.size>0){t.status="failing";return}if(t.warnings.size>0){t.status="warning";return}let d=[...t.producers.values()].some(h=>h.lastRunStatus==="error");t.status=d||!t.sawVerdict?"unknown":"clean"},"recomputeStatus"),i=u(()=>{e.resources.markDirty(ph),e.resources.markDirty(hh),e.resources.markDirty(mh)},"markDirty"),a=u(d=>{if([...t.errors.values()].some(h=>h.project===d)||[...t.warnings.values()].some(h=>h.project===d)||[...t.producers.values()].some(h=>h.project===d)){n(d,void 0);for(let[h,m]of t.producers)m.project===d&&t.producers.delete(h);t.sawVerdict=[...t.producers.values()].some(h=>h.lastRunStatus!=="error"),r(),i()}},"supersedeProject"),o=u(d=>{if(d.source==="gateway"&&d.category==="cluster"){let b=d.raw??null,k=b?.kind;(k==="service-starting"||k==="service-respawn")&&b?.project&&a(b.project);return}if(d.source!=="eslint"||d.category!=="lint")return;let h=gq(d),m=h.project,f=h.tool??"eslint",v=`${f}:${m??"*"}`,g=h.kind==="lint-run";if(d.severity==="info"&&(g&&h.phase==="start"||d.title.startsWith("ESLint clear"))){n(m,d.location?.file),t.lastRunAt=d.timestamp,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:"running"}),g||(t.sawVerdict=!0),r(),i();return}if(g&&h.phase==="end"){let b=h.status==="error"?"error":h.status==="failing"?"failing":"clean";b!=="error"&&(t.sawVerdict=!0),t.lastRunAt=d.timestamp,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:b,...h.durationMs!==void 0?{durationMs:h.durationMs}:{},...h.errorCount!==void 0?{errorCount:h.errorCount}:{},...h.warningCount!==void 0?{warningCount:h.warningCount}:{},...h.error?{error:h.error}:{}}),r(),i();return}let y=d.title.match(/^\[([^\]]+)\]/),w={id:d.id,timestamp:d.timestamp,severity:d.severity,...h.rule?{rule:h.rule}:y?.[1]?{rule:y[1]}:{},message:d.message??d.title,...d.location?.file?{file:d.location.file}:{},...d.location?.line!==void 0?{line:d.location.line}:{},...d.location?.column!==void 0?{column:d.location.column}:{},...m?{project:m}:{},fingerprint:d.fingerprint};if(d.severity==="error"||d.severity==="fatal")t.errors.set(w.fingerprint,w),t.warnings.delete(w.fingerprint);else if(d.severity==="warning")t.errors.has(w.fingerprint)||t.warnings.set(w.fingerprint,w);else return;t.lastRunAt=d.timestamp,t.sawVerdict=!0,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:t.errors.size>0?"failing":"clean"}),r(),i()},"handler"),c=e.bus.subscribe(o),p=u(()=>fp({producers:[...t.producers.values()],domain:"lint",noProducerHint:yee}),"health");return e.resources.register(ph,()=>({schemaVersion:1,revision:e.resources.revision(ph)??0,updatedAt:new Date().toISOString(),status:t.status,errorCount:t.errors.size,warningCount:t.warnings.size,lastRunAt:t.lastRunAt,...p()})),e.resources.register(hh,()=>({schemaVersion:1,revision:e.resources.revision(hh)??0,updatedAt:new Date().toISOString(),errors:[...t.errors.values()],...p()})),e.resources.register(mh,()=>({schemaVersion:1,revision:e.resources.revision(mh)??0,updatedAt:new Date().toISOString(),warnings:[...t.warnings.values()],...p()})),{unsubscribe:c,uris:[ph,hh,mh]}}l(vq,"SA"),u(vq,"installLintReducer");import{App as wee}from"@frontmcp/sdk";import{Resource as bee,ResourceContext as kee}from"@frontmcp/sdk";var b4=class extends kee{static{l(this,"xA")}static{u(this,"TypecheckCurrentResource")}async execute(){return this.get(X).read("typecheck://current")}};b4=P([bee({name:"typecheck-current",uri:"typecheck://current",mimeType:"application/json",description:"Current TypeScript typecheck status + error count."})],b4);var $ee=b4;import{Resource as xee,ResourceContext as Eee}from"@frontmcp/sdk";var k4=class extends Eee{static{l(this,"_A")}static{u(this,"TypecheckErrorsResource")}async execute(){return this.get(X).read("typecheck://errors")}};k4=P([xee({name:"typecheck-errors",uri:"typecheck://errors",mimeType:"application/json",description:"Current TypeScript errors (deduped by fingerprint)."})],k4);var See=k4,yq=class{static{l(this,"AA")}static{u(this,"TypecheckApp")}};yq=P([wee({id:"typecheck",name:"Typecheck",description:"TypeScript diagnostics from `tsc --watch`.",resources:[$ee,See]})],yq);var fh="typecheck://current",gh="typecheck://errors",Aee="Wire one: the dev cluster publishes from `TsgoCheckPlugin` when `LENSMCP_TYPECHECK=tsgo` (@lensmcp/cluster), or call `startTscCollector()` from @lensmcp/session for a `tsc --watch` workspace.";function wq(e){let t=e.raw;return t&&typeof t=="object"?t:{}}l(wq,"Wee"),u(wq,"readRaw");function bq(e){let t={status:"unknown",errors:new Map,producers:new Map,sawVerdict:!1},s=u((d,h)=>{let m=t.producers.get(d),f={id:d,tool:h.tool,...h.project?{project:h.project}:{},firstReportedAt:m?.firstReportedAt??h.at,lastReportedAt:Math.max(m?.lastReportedAt??0,h.at),lastRunStatus:h.runStatus,errorCount:h.errorCount??m?.errorCount??0,...h.durationMs!==void 0?{lastRunDurationMs:h.durationMs}:m?.lastRunDurationMs!==void 0?{lastRunDurationMs:m.lastRunDurationMs}:{},...h.warningCount!==void 0?{warningCount:h.warningCount}:{},...h.error?{error:h.error}:{}};t.producers.set(d,f),wi(t.producers,Gu)},"touchProducer"),n=u(d=>{if(!d){t.errors.clear();return}for(let[h,m]of t.errors)m.project===d&&t.errors.delete(h)},"clearScope"),r=u(()=>{if(t.errors.size>0){t.status="failing";return}let d=[...t.producers.values()].some(h=>h.lastRunStatus==="error");t.status=d||!t.sawVerdict?"unknown":"clean"},"recomputeStatus"),i=u(()=>{e.resources.markDirty(fh),e.resources.markDirty(gh)},"markDirty"),a=u(d=>{let h=[...t.errors.values()].some(f=>f.project===d),m=[...t.producers.values()].some(f=>f.project===d);if(!(!h&&!m)){n(d);for(let[f,v]of t.producers)v.project===d&&t.producers.delete(f);t.sawVerdict=[...t.producers.values()].some(f=>f.lastRunStatus!=="error"),r(),i()}},"supersedeProject"),o=u(d=>{if(d.source==="gateway"&&d.category==="cluster"){let b=d.raw??null,k=b?.kind;(k==="service-starting"||k==="service-respawn")&&b?.project&&a(b.project);return}if(d.source!=="typescript"||d.category!=="typecheck")return;let h=wq(d),m=h.project,f=h.tool??"tsc",v=`${f}:${m??"*"}`,g=h.kind==="typecheck-run";if(d.severity==="info"&&(g&&h.phase==="start"||d.title.startsWith("tsc clear"))){n(m),t.lastRunAt=d.timestamp,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:"running"}),g||(t.sawVerdict=!0),r(),i();return}if(g&&h.phase==="end"){let b=h.status==="error"?"error":h.status==="failing"?"failing":"clean";b!=="error"&&(t.sawVerdict=!0),t.lastRunAt=d.timestamp,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:b,...h.durationMs!==void 0?{durationMs:h.durationMs}:{},...h.errorCount!==void 0?{errorCount:h.errorCount}:{},...h.warningCount!==void 0?{warningCount:h.warningCount}:{},...h.error?{error:h.error}:{}}),r(),i();return}if(d.severity!=="error"&&d.severity!=="fatal")return;let y=d.title.match(/\bTS(\d+):/),w={id:d.id,timestamp:d.timestamp,...h.code?{code:h.code}:y?{code:`TS${y[1]}`}:{},message:d.message??d.title,...d.location?.file?{file:d.location.file}:{},...d.location?.line!==void 0?{line:d.location.line}:{},...d.location?.column!==void 0?{column:d.location.column}:{},...m?{project:m}:{},fingerprint:d.fingerprint};t.errors.set(w.fingerprint,w),t.lastRunAt=d.timestamp,t.sawVerdict=!0,s(v,{tool:f,...m?{project:m}:{},at:d.timestamp,runStatus:"failing"}),r(),i()},"handler"),c=e.bus.subscribe(o),p=u(()=>fp({producers:[...t.producers.values()],domain:"typecheck",noProducerHint:Aee}),"health");return e.resources.register(fh,()=>({schemaVersion:1,revision:e.resources.revision(fh)??0,updatedAt:new Date().toISOString(),status:t.status,errorCount:t.errors.size,lastRunAt:t.lastRunAt,...p()})),e.resources.register(gh,()=>({schemaVersion:1,revision:e.resources.revision(gh)??0,updatedAt:new Date().toISOString(),errors:[...t.errors.values()],...p()})),{unsubscribe:c,uris:[fh,gh]}}l(bq,"TA"),u(bq,"installTypecheckReducer");import{App as Cee}from"@frontmcp/sdk";import{Resource as Iee,ResourceContext as Dee}from"@frontmcp/sdk";var $4=class extends Dee{static{l(this,"IA")}static{u(this,"BundleCurrentResource")}async execute(){return this.get(X).read("bundle://current")}};$4=P([Iee({name:"bundle-current",uri:"bundle://current",mimeType:"application/json",description:"Most recent Vite/Rollup bundle report (chunks + sizes)."})],$4);var Tee=$4;import{Resource as _ee,ResourceContext as Mee}from"@frontmcp/sdk";var x4=class extends Mee{static{l(this,"MA")}static{u(this,"BundleChunksResource")}async execute(){return this.get(X).read("bundle://chunks")}};x4=P([_ee({name:"bundle-chunks",uri:"bundle://chunks",mimeType:"application/json",description:"Per-chunk bundle sizes (most recent build)."})],x4);var Bee=x4;import{Resource as qee,ResourceContext as jee}from"@frontmcp/sdk";var E4=class extends jee{static{l(this,"CA")}static{u(this,"BundleModulesResource")}async execute(){return this.get(X).read("bundle://modules")}};E4=P([qee({name:"bundle-modules",uri:"bundle://modules",mimeType:"application/json",description:"Flattened per-module bundle sizes (most recent build)."})],E4);var Ree=E4;import{Resource as Oee,ResourceContext as Nee}from"@frontmcp/sdk";var S4=class extends Nee{static{l(this,"jA")}static{u(this,"BundleRegressionsResource")}async execute(){return this.get(X).read("bundle://regressions")}};S4=P([Oee({name:"bundle-regressions",uri:"bundle://regressions",mimeType:"application/json",description:"Chunks/modules that grew, were added, or were removed vs the baseline."})],S4);var Pee=S4;import{Resource as Lee,ResourceContext as Fee}from"@frontmcp/sdk";var A4=class extends Fee{static{l(this,"LA")}static{u(this,"BundleCompareResource")}async execute(){return this.get(X).read("bundle://compare/latest")}};A4=P([Lee({name:"bundle-compare-latest",uri:"bundle://compare/latest",mimeType:"application/json",description:"Most recent build vs baseline: totals + delta."})],A4);var Uee=A4,kq=class{static{l(this,"DA")}static{u(this,"BundleApp")}};kq=P([Cee({id:"bundle",name:"Bundle",description:"Vite/Rollup bundle reports + regressions against baseline.",resources:[Tee,Bee,Ree,Pee,Uee]})],kq);function C4(e,t){let s=[],n=new Map(e.chunks.map(i=>[i.name,i])),r=new Map(t.chunks.map(i=>[i.name,i]));for(let[i,a]of r){let o=n.get(i);if(!o){s.push({kind:"chunk-added",name:i,afterBytes:a.sizeBytes,deltaBytes:a.sizeBytes});continue}let c=a.sizeBytes-o.sizeBytes;c>256&&s.push({kind:"chunk-grew",name:i,beforeBytes:o.sizeBytes,afterBytes:a.sizeBytes,deltaBytes:c}),s.push(...$q(o,a))}for(let[i,a]of n)r.has(i)||s.push({kind:"chunk-removed",name:i,beforeBytes:a.sizeBytes,deltaBytes:-a.sizeBytes});return s.sort((i,a)=>Math.abs(a.deltaBytes)-Math.abs(i.deltaBytes))}l(C4,"Pf"),u(C4,"compareReports");function $q(e,t){let s=[],n=new Map(e.modules.map(r=>[r.id,r.sizeBytes]));for(let r of t.modules){let i=n.get(r.id);if(i===void 0)r.sizeBytes>256&&s.push({kind:"module-added",name:`${t.name}::${r.id}`,afterBytes:r.sizeBytes,deltaBytes:r.sizeBytes});else{let a=r.sizeBytes-i;a>256&&s.push({kind:"module-grew",name:`${t.name}::${r.id}`,beforeBytes:i,afterBytes:r.sizeBytes,deltaBytes:a})}}return s}l($q,"rte"),u($q,"compareModules");var vh="bundle://current",yh="bundle://chunks",wh="bundle://modules",pl="bundle://regressions",hl="bundle://compare/latest";function xq(e){let t={baseline:e.initialBaseline,regressions:[]},s=u(r=>{if(r.source!=="rollup"&&r.source!=="vite"||r.category!=="build")return;let i=r.raw;if(!i||typeof i!="object"||!("kind"in i)||i.kind!=="bundle-report")return;let a=i.report;!a||!Array.isArray(a.chunks)||(t.current=a,t.regressions=t.baseline?C4(t.baseline,a):[],e.resources.markDirty(vh),e.resources.markDirty(yh),e.resources.markDirty(wh),e.resources.markDirty(pl),e.resources.markDirty(hl))},"handler"),n=e.bus.subscribe(s);return e.resources.register(vh,()=>({schemaVersion:1,revision:e.resources.revision(vh)??0,updatedAt:new Date().toISOString(),report:t.current??null})),e.resources.register(yh,()=>({schemaVersion:1,revision:e.resources.revision(yh)??0,updatedAt:new Date().toISOString(),chunks:t.current?.chunks??[]})),e.resources.register(wh,()=>{let r=t.current?.chunks.flatMap(i=>i.modules.map(a=>({...a,chunk:i.name})))??[];return{schemaVersion:1,revision:e.resources.revision(wh)??0,updatedAt:new Date().toISOString(),modules:r}}),e.resources.register(pl,()=>({schemaVersion:1,revision:e.resources.revision(pl)??0,updatedAt:new Date().toISOString(),regressions:t.regressions.slice()})),e.resources.register(hl,()=>({schemaVersion:1,revision:e.resources.revision(hl)??0,updatedAt:new Date().toISOString(),baseline:t.baseline??null,current:t.current??null,deltaBytes:t.baseline&&t.current?t.current.totalBytes-t.baseline.totalBytes:0})),{unsubscribe:n,uris:[vh,yh,wh,pl,hl],setBaseline:u(r=>{t.baseline=r,t.current&&(t.regressions=C4(t.baseline,t.current)),e.resources.markDirty(pl),e.resources.markDirty(hl)},"setBaseline")}}l(xq,"UA"),u(xq,"installBundleReducer");import{App as zee}from"@frontmcp/sdk";import{Resource as Wee,ResourceContext as Hee}from"@frontmcp/sdk";var I4=class extends Hee{static{l(this,"zA")}static{u(this,"RuntimeBrowserConsoleResource")}async execute(){return this.get(X).read("runtime://browser/console")}};I4=P([Wee({name:"runtime-browser-console",uri:"runtime://browser/console",mimeType:"application/json",description:"Most recent 200 console.* messages from any tab."})],I4);var Gee=I4;import{Resource as Zee,ResourceContext as Vee}from"@frontmcp/sdk";var D4=class extends Vee{static{l(this,"BA")}static{u(this,"RuntimeBrowserErrorsResource")}async execute(){return this.get(X).read("runtime://browser/errors")}};D4=P([Zee({name:"runtime-browser-errors",uri:"runtime://browser/errors",mimeType:"application/json",description:"Uncaught browser errors + promise rejections, per tab, since that tab's current page load (a reload retracts the previous document's errors)."})],D4);var Jee=D4;import{Resource as Kee,ResourceContext as Qee}from"@frontmcp/sdk";var T4=class extends Qee{static{l(this,"WA")}static{u(this,"RuntimeServerErrorsResource")}async execute(){return this.get(X).read("runtime://errors")}};T4=P([Kee({name:"runtime-errors",uri:"runtime://errors",mimeType:"application/json",description:"Errors raised INSIDE a backend pod, with no browser involved \u2014 the 500s a curl, an e2e runner or a queue job produces. Each entry carries the route, the status, the request id the gateway stamped, and the stack. Use this when a server-side call failed and no browser flow exists to explain it; `runtime://browser/errors` is the browser-side counterpart."})],T4);var Yee=T4;import{Resource as Xee,ResourceContext as ete}from"@frontmcp/sdk";var _4=class extends ete{static{l(this,"VA")}static{u(this,"RuntimeBrowserNetworkResource")}async execute(){return this.get(X).read("runtime://browser/network")}};_4=P([Xee({name:"runtime-browser-network",uri:"runtime://browser/network",mimeType:"application/json",description:"Recent fetch / XHR / browser network activity."})],_4);var tte=_4;import{Resource as ste,ResourceContext as rte}from"@frontmcp/sdk";var M4=class extends rte{static{l(this,"ZA")}static{u(this,"RuntimeBrowserFailedRequestsResource")}async execute(){return this.get(X).read("runtime://browser/failed-requests")}};M4=P([ste({name:"runtime-browser-failed-requests",uri:"runtime://browser/failed-requests",mimeType:"application/json",description:"Recent failed network requests (status >= 400 or transport errors)."})],M4);var nte=M4;import{Resource as ite,ResourceContext as ate}from"@frontmcp/sdk";var B4=class extends ate{static{l(this,"QA")}static{u(this,"RuntimeDismissedResource")}async execute(){return this.get(X).read("runtime://dismissed")}};B4=P([ite({name:"runtime-dismissed",uri:"runtime://dismissed",mimeType:"application/json",description:"Errors someone DISMISSED by hand \u2014 in the dashboard, at the CLI, or an agent through observe_dismiss_errors \u2014 with who did it and the reason they gave. A dismissed error is hidden from runtime://errors and the browser error lists, not fixed: it shows again the next time it happens. Read this when an error list is shorter than you expected."})],B4);var ote=B4;import{Resource as ute,ResourceContext as lte}from"@frontmcp/sdk";var q4=class extends lte{static{l(this,"YA")}static{u(this,"RuntimeLogsResource")}async execute(){return this.get(X).read("runtime://logs")}};q4=P([ute({name:"runtime-logs",uri:"runtime://logs",mimeType:"application/json",description:"Which services this session holds log lines for, and how many: per service `linesHeld`, `oldestAt`, `newestAt`, error lines, and lines the pod's flood guard held back. The lines themselves are read with the `logs_read` tool (by service, level, text, or the request / flow they were written in)."})],q4);var dte=q4;import{Tool as cte,ToolContext as pte}from"@frontmcp/sdk";var Eq;function j4(e){Eq=e}l(j4,"Uf"),u(j4,"setActiveServiceLogs");function Sq(){return Eq}l(Sq,"tT"),u(Sq,"activeServiceLogs");var ml={debug:0,info:1,warning:2,error:3,fatal:4},Aq=Object.keys(ml),hte=2e3,mte=64,R4=4096,O4=u(e=>typeof e=="object"&&e!==null&&!Array.isArray(e),"isObj"),Ys=u(e=>typeof e=="string"&&e!==""?e:void 0,"str");function Cq(e){return Aq.includes(e.severity)?e.severity:"info"}l(Cq,"bte"),u(Cq,"levelOf");function Iq(e){let t=O4(e.raw)?e.raw:void 0;if(!t||t.kind!=="log")return;let s=e.context??{},n=Ys(t.project)??Ys(s.projectName);if(!n)return;let r=O4(t.request)&&O4(t.request.error)?t.request.error:void 0,i=Ys(r?.stack)??Ys(t.text)??Ys(e.message)??e.title??"",a=i.length>R4?`${i.slice(0,R4)}\u2026[lensmcp truncated: ${i.length-R4} more chars]`:i,o=Ys(t.stream),c=typeof t.floodSuppressed=="number"&&t.floodSuppressed>0?t.floodSuppressed:0;return{service:n,line:{at:e.timestamp,level:Cq(e),...o==="stdout"||o==="stderr"||o==="logger"?{stream:o}:{},...Ys(t.logger)?{logger:Ys(t.logger)}:{},text:a,...Ys(s.requestId)?{requestId:Ys(s.requestId)}:{},...Ys(s.flowId)?{flowId:Ys(s.flowId)}:{},...c?{suppressedBefore:c}:{}}}}l(Iq,"YU"),u(Iq,"logLineOf");var fl="What each service's pods wrote to stdout / stderr (after the app's own log-level filter), and \u2014 while serving a request or running a job \u2014 what a handler handed the Nest Logger, captured at the call, before that filter (`stream: \"logger\"`). Not here: the devserver's own lines (compiles, hot swaps reported by `[parent]`) \u2014 `lensmcp logs <service> --no-follow` has those. `suppressed` counts lines a pod's flood guard held back under a burst.",Dq=class{static{l(this,"Mi")}static{u(this,"ServiceLogs")}constructor(e={linesPerService:hte,services:mte}){this.caps=e,this.rings=new Map,this.seq=0}ingest(e){let t=Iq(e);if(!t)return!1;let s=this.rings.get(t.service);if(s&&this.rings.delete(t.service),s??={lines:[],seen:0,suppressed:0},this.rings.set(t.service,s),this.seq+=1,s.lines.push({seq:this.seq,...t.line}),s.seen+=1,s.suppressed+=t.line.suppressedBefore??0,s.lines.length>this.caps.linesPerService){let n=s.lines.splice(0,s.lines.length-this.caps.linesPerService);for(let r of n)s.suppressed-=r.suppressedBefore??0}return this.rings.size>this.caps.services&&this.rings.delete(this.rings.keys().next().value),!0}summary(){return[...this.rings].map(([e,t])=>({service:e,linesHeld:t.lines.length,linesSeen:t.seen,oldestAt:t.lines[0]?.at??0,newestAt:t.lines[t.lines.length-1]?.at??0,errors:t.lines.filter(s=>ml[s.level]>=ml.error).length,suppressed:t.suppressed})).sort((e,t)=>e.service<t.service?-1:1)}read(e,t={}){let s=t.now??Date.now(),n=this.summary(),r=!e.service&&(e.requestId!==void 0||e.flowId!==void 0),i=e.service?this.rings.has(e.service)?[[e.service,this.rings.get(e.service)]]:[]:r?[...this.rings]:[],a=e.level?ml[e.level]:0,o=e.sinceMs!==void 0&&e.sinceMs>=0?s-e.sinceMs:void 0,c=e.pattern?e.pattern.toLowerCase():void 0,p=e.requestId?`${e.requestId}.`:void 0,d=e.after!==void 0&&e.after>=0?e.after:void 0,h=u(A=>(d===void 0||(A.seq??0)>d)&&ml[A.level]>=a&&(o===void 0||A.at>=o)&&(c===void 0||A.text.toLowerCase().includes(c)||(A.logger?.toLowerCase().includes(c)??!1))&&(e.requestId===void 0||A.requestId===e.requestId||p!==void 0&&(A.requestId?.startsWith(p)??!1))&&(e.flowId===void 0||A.flowId===e.flowId),"matches"),m=[];for(let[A,I]of i)for(let C of I.lines)h(C)&&m.push(r?{...C,service:A}:C);r&&m.sort((A,I)=>A.at-I.at);let f=Math.max(1,Math.floor(e.tail??100)),v=m.slice(Math.max(0,m.length-f)),g=t.budgetBytes!==void 0&&Number.isFinite(t.budgetBytes)?Gw(v,t.budgetBytes,{newest:"end",name:"lines",maxStringChars:1500}).items:v,y=i.reduce((A,[,I])=>A+I.lines.length,0),w=i.reduce((A,[,I])=>I.lines[0]?Math.min(A??1/0,I.lines[0].at):A,void 0),b=i.reduce((A,[,I])=>I.lines.length?Math.max(A??0,I.lines[I.lines.length-1].at):A,void 0),k=e.service?this.rings.has(e.service):this.rings.size>0,$=i.reduce((A,[,I])=>Math.max(A,I.lines[I.lines.length-1]?.seq??0),i.length?0:this.seq)||d||0,E=!e.service&&!r,x=d!==void 0&&m.length===0&&k,S=this.rings.size===0?"No pod has reported a line into this session \u2014 this is NOT evidence that nothing was logged: nothing is feeding the ring (run the service under the dev cluster). "+fl:E?"Name a `service` (see `services`), or give a `requestId` / `flowId` to read every service's lines for it. "+fl:k?x?`Nothing new since cursor ${d}. Call again with \`after: ${$}\` to wait for the next lines.`:m.length===0?'No held line matches. That is not "nothing was logged": a line the app did not print and no handler logged inside a request is not here, and the ring keeps the last lines only (`linesHeld`, `oldestAt`). '+fl:d===void 0?`Poll with \`after: ${$}\` to read only the lines that come next. `+fl:void 0:`No line is held for "${e.service}" \u2014 a service that has printed nothing since this server started, or a name that is not one of \`services\`. `+fl;return{producer:this.rings.size>0?"connected":"none",...e.service?{service:e.service}:{},...E||!k?{services:n}:{},cursor:$,...x?{nothingNew:!0}:{},linesHeld:y,...w!==void 0?{oldestAt:w}:{},...b!==void 0?{newestAt:b}:{},suppressed:i.reduce((A,[,I])=>A+I.suppressed,0),matched:m.length,returned:g.length,lines:g,...S?{note:S}:{}}}},fte=3e3;function Tq(e,t,s={}){let n=e??new Dq,r=s.budgetBytes!==void 0&&Number.isFinite(s.budgetBytes)?Math.max(1e3,s.budgetBytes-fte):void 0;return n.read({...t.service?{service:t.service}:{},tail:t.tail,...t.sinceMs!==void 0?{sinceMs:t.sinceMs}:{},...t.level?{level:t.level}:{},...t.pattern?{pattern:t.pattern}:{},...t.requestId?{requestId:t.requestId}:{},...t.flowId?{flowId:t.flowId}:{},...t.after!==void 0?{after:t.after}:{}},{...s.now!==void 0?{now:s.now}:{},...r!==void 0?{budgetBytes:r}:{}})}l(Tq,"oT"),u(Tq,"readLogs");var za={name:"logs_read",description:'What a dev service printed or logged \u2014 its newest lines, oldest first. Give a `service`, or a `requestId` / `flowId` for every service\'s lines of that request or flow. Narrow with `level`, `pattern`, `sinceMs`, `tail`; poll with `after` = the last answer\'s `cursor` for only new lines. Includes what a handler passed the Nest Logger inside a request, captured BEFORE that filter (`stream: "logger"`). The answer says what the ring holds, so an empty list is never mistaken for "nothing was logged". No arguments: the services it has lines for. Compiles and hot swaps: `lensmcp logs <service>`.',levels:Aq,defaultTail:100,maxTail:1e3};import{z as st}from"@frontmcp/sdk";var gte={service:st.string().optional().describe('The service (Nx project), e.g. "assistant". Omit to list them.'),tail:st.number().int().positive().max(za.maxTail).default(za.defaultTail).describe(`How many matching lines, newest kept (default ${za.defaultTail}).`),sinceMs:st.number().int().positive().optional().describe("Only lines from the last this-many milliseconds."),level:st.enum(za.levels).optional().describe("Only lines at or above this level."),pattern:st.string().max(200).optional().describe("Text to match (case-insensitive), the logger's context too."),requestId:st.string().optional().describe("Lines written serving this request (x-request-id) or the calls it made."),flowId:st.string().optional().describe("Only lines written inside this flow."),after:st.number().int().min(0).optional().describe("The last answer's `cursor`: only newer lines.")},vte=st.object({producer:st.enum(["connected","none"]),service:st.string().optional(),services:st.array(st.object({}).passthrough()).optional(),cursor:st.number(),nothingNew:st.literal(!0).optional(),linesHeld:st.number(),oldestAt:st.number().optional(),newestAt:st.number().optional(),suppressed:st.number(),matched:st.number(),returned:st.number(),lines:st.array(st.object({}).passthrough()),note:st.string().optional()}).passthrough(),N4=class extends pte{static{l(this,"iT")}static{u(this,"LogsReadTool")}async execute(e){return Tq(Sq(),e,{budgetBytes:xp()})}};N4=P([cte({name:za.name,description:za.description,annotations:{readOnlyHint:!0},inputSchema:gte,outputSchema:vte})],N4);var yte=N4,_q=class{static{l(this,"cT")}static{u(this,"RuntimeApp")}};_q=P([zee({id:"runtime",name:"Runtime",description:"Live browser/node runtime state (console, errors, network) and what each service logged.",tools:[yte],resources:[Gee,Jee,Yee,tte,nte,ote,dte]})],_q);var Wa="runtime://browser/console",Dr="runtime://browser/errors",Ha="runtime://browser/network",Tr="runtime://browser/failed-requests",_r="runtime://errors",gl="runtime://dismissed",vl="runtime://logs",wte=500,P4=new Set([_r,Dr,Tr]),bte=200,bh=100,kte=200,Mq=50,$te=500,xte="default",Ete=1e3,L4=u(e=>e??xte,"tabOf");function Bq(e){if(e.category!=="runtime")return!1;let t=e.raw;return t&&typeof t=="object"&&t.kind==="ready"?!0:e.title==="Client runtime ready"}l(Bq,"Mte"),u(Bq,"isDocumentBoundary");function qq(e){if(e.category!=="runtime")return!1;let t=e.raw;return!!(t&&typeof t=="object"&&t.kind==="gone")}l(qq,"Ote"),u(qq,"isTabGone");function jq(e){let t=(e.now??(()=>Date.now()))(),s={console:[],errors:[],network:[],failed:[],serverErrors:[],readyByTab:new Map,dismissed:new Map,dropped:new Map,changedAt:new Map},n=u((v,g,y,w)=>{let b=$h(g,y,w);b>0&&s.dropped.set(v,(s.dropped.get(v)??0)+b)},"pushCounted"),r=u((v,g)=>{s.changedAt.set(v,g),e.resources.markDirty(v)},"touch"),i=u((v,g,y)=>{let w=v.filter(b=>!(L4(b.tabId)===g&&b.timestamp<y));w.length!==v.length&&(v.length=0,v.push(...w))},"retract"),a=new Dq;j4(a);let o,c=t,p=u(v=>{c=Math.max(c,v),!o&&(o=setTimeout(()=>{o=void 0,r(vl,c)},wte),o.unref?.())},"logsTouched"),d=u(v=>{a.ingest(v)&&p(v.timestamp);let g=Nw(v);if(g){let w=s.dismissed.get(g.groupId);s.dismissed.delete(g.groupId),g.kind===_a&&(s.dismissed.set(g.groupId,{eventIds:new Set(g.eventIds),at:v.timestamp,...g.by?{by:g.by}:{},...g.reason?{reason:g.reason}:{},...g.title?{title:g.title}:{}}),s.dismissed.size>$te&&s.dismissed.delete(s.dismissed.keys().next().value));let b=new Set([...w?.eventIds??[],...s.dismissed.get(g.groupId)?.eventIds??[]]);for(let[k,$]of[[_r,s.serverErrors],[Dr,s.errors],[Tr,s.failed]])$.some(E=>b.has(E.id))&&r(k,v.timestamp);r(gl,v.timestamp);return}if(Rq(v)){let w=v.raw?.project;if(w){let b=s.serverErrors.length;s.serverErrors=s.serverErrors.filter(k=>k.project!==w),s.serverErrors.length!==b&&r(_r,v.timestamp)}return}if(Oq(v)){s.lastServerEventAt=Math.max(s.lastServerEventAt??0,v.timestamp),n(_r,s.serverErrors,Nq(v),bh),r(_r,v.timestamp);return}if(!(v.source==="client-runtime"||v.source==="chrome")&&!(v.source==="react"&&v.category==="network"))return;if(s.lastEventAt=Math.max(s.lastEventAt??0,v.timestamp),qq(v)){let w=L4(v.context.tabId);i(s.errors,w,Number.POSITIVE_INFINITY),i(s.failed,w,Number.POSITIVE_INFINITY),s.readyByTab.delete(w);for(let b of[Dr,Tr,Wa,Ha])r(b,v.timestamp);return}if(Bq(v)){let w=L4(v.context.tabId);s.readyByTab.set(w,Math.max(s.readyByTab.get(w)??0,v.timestamp)),s.lastReadyAt=Math.max(s.lastReadyAt??0,v.timestamp);let b=v.timestamp-Ete;i(s.errors,w,b),i(s.failed,w,b);for(let k of[Dr,Tr,Wa,Ha])r(k,v.timestamp);return}let y={id:v.id,timestamp:v.timestamp,severity:v.severity,title:v.title,message:v.message,source:v.source,fingerprint:v.fingerprint,tabId:v.context.tabId,url:v.context.url,raw:v.raw};if(v.category==="network"){$h(s.network,y,kte),r(Ha,v.timestamp),v.severity==="error"&&(n(Tr,s.failed,y,Mq),r(Tr,v.timestamp));return}(v.severity==="error"||v.severity==="fatal")&&(n(Dr,s.errors,y,bh),r(Dr,v.timestamp)),v.title?.startsWith("console.")&&($h(s.console,y,bte),r(Wa,v.timestamp))},"handler"),h=e.bus.subscribe(d),m=u(()=>{h(),o&&clearTimeout(o),j4(void 0)},"unsubscribe");e.resources.register(vl,()=>{let v=a.summary();return{schemaVersion:1,revision:e.resources.revision(vl)??0,updatedAt:new Date(s.changedAt.get(vl)??t).toISOString(),producer:v.length>0?"connected":"none",count:v.length,services:v,detail:v.length>0?`log lines held for ${v.length} service${v.length===1?"":"s"} \u2014 read them with the logs_read tool (by service, level, text, or the request / flow they were written in)`:"No pod has reported a log line into this session \u2014 this is NOT evidence that nothing was logged: nothing is feeding the ring. Run the backend under the dev cluster."}});let f=u((v,g)=>{if(!P4.has(v)||s.dismissed.size===0)return U4(e.resources,v,g,s,t,0);let y=new Set([...s.dismissed.values()].flatMap(b=>[...b.eventIds])),w=g.filter(b=>!y.has(b.id));return U4(e.resources,v,w,s,t,g.length-w.length)},"snap");return e.resources.register(_r,()=>f(_r,s.serverErrors)),e.resources.register(Wa,()=>f(Wa,s.console)),e.resources.register(Dr,()=>f(Dr,s.errors)),e.resources.register(Ha,()=>f(Ha,s.network)),e.resources.register(Tr,()=>f(Tr,s.failed)),e.resources.register(gl,()=>{let v=new Set([...s.serverErrors,...s.errors,...s.failed].map(y=>y.id)),g=[...s.dismissed].map(([y,w])=>({id:y,at:w.at,...w.by?{by:w.by}:{},...w.reason?{reason:w.reason}:{},...w.title?{title:w.title}:{},eventIds:[...w.eventIds],hiding:[...w.eventIds].filter(b=>v.has(b)).length}));return{schemaVersion:1,revision:e.resources.revision(gl)??0,updatedAt:new Date(s.changedAt.get(gl)??t).toISOString(),count:g.length,dismissals:g,detail:g.length?`${g.length} dismissal${g.length===1?"":"s"} in effect \u2014 hidden, not fixed. Each error shows again the next time it happens; undo one with observe_restore_errors.`:"Nothing has been dismissed."}}),{unsubscribe:m,uris:[Wa,Dr,Ha,Tr,_r,gl,vl]}}l(jq,"hT"),u(jq,"installRuntimeReducer");function F4(e){let t=e.raw??null,s=e.context;return t?.project??s.projectName}l(F4,"nz"),u(F4,"projectOf");function Rq(e){if(e.source!=="gateway"||e.category!=="cluster")return!1;let t=e.raw?.kind;return t==="service-starting"||t==="service-respawn"}l(Rq,"Cte"),u(Rq,"isGenerationBoundary");function Oq(e){if(e.source!=="nestjs"||e.severity!=="error"&&e.severity!=="fatal")return!1;let t=e.raw??{};return t.kind==="server-request"||t.kind==="uncaught"?!0:t.kind!=="log"?!1:t.request?.error||t.stream==="logger"?!0:/\b[A-Za-z0-9_$]*(?:Error|Exception)\b|\b(?:ERROR|FATAL)\b/.test(e.title??"")}l(Oq,"Nte"),u(Oq,"isServerError");function Nq(e){let t=e.raw??{},s=t.request??{},n=s.error,r=e.message??(typeof n?.message=="string"?n.message:void 0),i=typeof n?.stack=="string"&&n.stack?n.stack:typeof t.text=="string"&&t.text!==e.title?t.text:void 0,a=e.context.flowId??(typeof s.flowId=="string"?s.flowId:void 0);return{id:e.id,timestamp:e.timestamp,severity:e.severity,title:e.title,...r&&r!==e.title?{message:r}:{},source:e.source,fingerprint:e.fingerprint,...e.context.requestId?{requestId:e.context.requestId}:{},...a?{flowId:a}:{},...F4(e)?{project:F4(e)}:{},...typeof t.kind=="string"?{kind:t.kind}:{},...typeof t.logger=="string"&&t.logger?{logger:t.logger}:{},...typeof s.method=="string"?{method:s.method}:{},...typeof s.route=="string"?{route:s.route}:{},...typeof s.status=="number"?{status:s.status}:{},...typeof s.outcome=="string"?{outcome:s.outcome}:{},...s.outcome==="declared"?{handled:!0}:s.outcome==="fault"||t.kind==="uncaught"?{handled:!1}:{},...typeof s.durationMs=="number"?{durationMs:s.durationMs}:{},...typeof n?.name=="string"&&n.name?{errorName:n.name}:{},...typeof t.floodSuppressed=="number"&&t.floodSuppressed>0?{floodSuppressed:t.floodSuppressed}:{},...i?{stack:i}:{}}}l(Nq,"jte"),u(Nq,"serverEntry");function U4(e,t,s,n,r,i){let a=t===_r,o=a?n.lastServerEventAt:n.lastEventAt,c=o!==void 0;return{schemaVersion:1,revision:e.revision(t)??0,updatedAt:new Date(n.changedAt.get(t)??r).toISOString(),count:s.length,entries:P4.has(t)?s.slice().reverse():s.slice(),...P4.has(t)?{capacity:Ste[t],dropped:n.dropped.get(t)??0,...s.length>0?{oldestAt:s.reduce((p,d)=>Math.min(p,d.timestamp),1/0),newestAt:s.reduce((p,d)=>Math.max(p,d.timestamp),0)}:{}}:{},...i>0?{dismissedCount:i}:{},producer:c?"connected":"none",lastEventAt:o,lastReadyAt:n.lastReadyAt,detail:a?c?s.length===0?"No server-side errors held. Pods HAVE reported, but a new pod generation retracts the errors of the one it replaced \u2014 so this is NOT evidence the routes are healthy: nobody may have re-made the failing request since."+kh(i):`${s.length} server-side error${s.length===1?"":"s"} from ${new Set(s.map(p=>p.project??"unknown")).size} project${new Set(s.map(p=>p.project??"unknown")).size===1?"":"s"}`+kh(i):"No pod has ever reported into this session \u2014 this is NOT evidence the backend is healthy, nothing is watching. Run the backend under the dev cluster so pod errors reach this session.":c?`browser attached; ${s.length} entr${s.length===1?"y":"ies"} from ${n.readyByTab.size} open tab${n.readyByTab.size===1?"":"s"}`+(n.lastReadyAt===void 0?" (no page load observed yet)":"")+kh(i):"No browser has ever reported into this session \u2014 this is NOT evidence the app is healthy, nothing is watching. Open the app under the dev cluster (or the Vite dev server with @lensmcp/vite-plugin installed) so browser events reach this session."}}l(U4,"rz"),u(U4,"snapshot");function kh(e){return e>0?` \u2014 ${e} more dismissed by hand in the dashboard (hidden, not fixed)`:""}l(kh,"lT"),u(kh,"dismissedNote");function $h(e,t,s){return e.push(t),e.length<=s?0:e.splice(0,e.length-s).length}l($h,"uT"),u($h,"pushBounded");var Ste={[_r]:bh,[Dr]:bh,[Tr]:Mq};import{App as Ate}from"@frontmcp/sdk";import{Resource as Cte,ResourceContext as Ite}from"@frontmcp/sdk";var z4=class extends Ite{static{l(this,"mT")}static{u(this,"BrowserTabsResource")}async execute(){return this.get(X).read("browser://tabs")}};z4=P([Cte({name:"browser-tabs",uri:"browser://tabs",mimeType:"application/json",description:"Open browser tabs with per-tab status, url, and event counts. `status` reflects the tab's CURRENT page load \u2014 a reload resets it."})],z4);var Dte=z4;import{Resource as Tte,ResourceContext as _te}from"@frontmcp/sdk";var W4=class extends _te{static{l(this,"gT")}static{u(this,"BrowserActiveTabResource")}async execute(){return this.get(X).read("browser://active-tab")}};W4=P([Tte({name:"browser-active-tab",uri:"browser://active-tab",mimeType:"application/json",description:"The currently-focused browser tab."})],W4);var Mte=W4,Pq=class{static{l(this,"wT")}static{u(this,"BrowserApp")}};Pq=P([Ate({id:"browser",name:"Browser",description:"Per-tab browser state (multi-tab refinement comes in Phase 6).",resources:[Dte,Mte]})],Pq);var On="browser://tabs",Nn="browser://active-tab";function Lq(e){if(e.category!=="runtime")return!1;let t=e.raw;return t&&typeof t=="object"&&t.kind==="ready"?!0:e.title==="Client runtime ready"}l(Lq,"Fte"),u(Lq,"isDocumentBoundary");function Fq(e){if(e.category!=="runtime")return!1;let t=e.raw;return!!(t&&typeof t=="object"&&t.kind==="gone")}l(Fq,"Bte"),u(Fq,"isTabGone");function Uq(e){let t=(e.now??(()=>Date.now()))(),s={tabs:new Map,changedAt:new Map},n=u(a=>{if(a.source!=="chrome"&&a.source!=="client-runtime")return;let o=a.context.tabId??"default";if(Fq(a)){if(s.tabs.delete(o),s.activePageId===o){let p=[...s.tabs.keys()];s.activePageId=p[p.length-1]}s.lastEventAt=Math.max(s.lastEventAt??0,a.timestamp),s.changedAt.set(On,a.timestamp),s.changedAt.set(Nn,a.timestamp),e.resources.markDirty(On),e.resources.markDirty(Nn);return}let c=s.tabs.get(o);if(c||(c={pageId:o,url:a.context.url??"",status:"unknown",unreadEvents:0,totalEvents:0,loads:0}),s.tabs.delete(o),s.tabs.set(o,c),s.tabs.size>100){let p=s.tabs.keys().next().value;p!==void 0&&p!==o&&s.tabs.delete(p)}a.context.url&&(c.url=a.context.url),c.totalEvents+=1,c.lastEventAt=a.timestamp,s.activePageId=o,s.lastEventAt=Math.max(s.lastEventAt??0,a.timestamp),Lq(a)?(c.status="clean",c.unreadEvents=0,c.loads+=1,c.lastReadyAt=a.timestamp):(c.unreadEvents+=1,a.severity==="error"||a.severity==="fatal"?c.status="failing":c.status!=="failing"&&a.severity==="warning"?c.status="warning":c.status==="unknown"&&(c.status="clean")),s.changedAt.set(On,a.timestamp),s.changedAt.set(Nn,a.timestamp),e.resources.markDirty(On),e.resources.markDirty(Nn)},"handler"),r=e.bus.subscribe(n),i=u(a=>new Date(s.changedAt.get(a)??t).toISOString(),"stamp");return e.resources.register(On,()=>({schemaVersion:1,revision:e.resources.revision(On)??0,updatedAt:i(On),activePageId:s.activePageId,tabs:[...s.tabs.values()],lastEventAt:s.lastEventAt,producer:s.lastEventAt===void 0?"none":"connected"})),e.resources.register(Nn,()=>{let a=s.activePageId;return{schemaVersion:1,revision:e.resources.revision(Nn)??0,updatedAt:i(Nn),tab:a?s.tabs.get(a)??null:null,lastEventAt:s.lastEventAt,producer:s.lastEventAt===void 0?"none":"connected"}}),{unsubscribe:r,uris:[On,Nn]}}l(Uq,"vT"),u(Uq,"installBrowserReducer");import{App as Bte}from"@frontmcp/sdk";import{Resource as qte,ResourceContext as jte}from"@frontmcp/sdk";var H4=class extends jte{static{l(this,"bT")}static{u(this,"NestProvidersResource")}async execute(){return this.get(X).read("nest://providers")}};H4=P([qte({name:"nest-providers",uri:"nest://providers",mimeType:"application/json",description:"All known NestJS singleton-instance generations (with lifecycle)."})],H4);var Rte=H4;import{Resource as Ote,ResourceContext as Nte}from"@frontmcp/sdk";var G4=class extends Nte{static{l(this,"ST")}static{u(this,"NestRequestsResource")}async execute(){return this.get(X).read("nest://requests/recent")}};G4=P([Ote({name:"nest-requests-recent",uri:"nest://requests/recent",mimeType:"application/json",description:"Last 50 NestJS server requests with status + duration."})],G4);var Pte=G4,zq=class{static{l(this,"$T")}static{u(this,"NestApp")}};zq=P([Bte({id:"nest",name:"Nest",description:"NestJS providers, request lifecycle, singleton generations.",resources:[Rte,Pte]})],zq);var xh="nest://providers",Eh="nest://requests/recent";function Wq(e){let t={providers:new Map,recentRequests:[]},s=u(r=>{if(r.source!=="nestjs")return;let i=r.raw??null;if(i?.kind==="singleton-instance"&&i.provider){let a=i.provider;if(t.providers.delete(a.instanceId),t.providers.set(a.instanceId,{...a}),t.providers.size>500){for(let o of t.providers.keys())if(t.providers.delete(o),t.providers.size<=500)break}e.resources.markDirty(xh);return}if(i?.kind==="server-request"&&i.request){let a={...i.request,fingerprint:r.fingerprint,id:r.id};t.recentRequests.push(a),t.recentRequests.length>50&&t.recentRequests.splice(0,t.recentRequests.length-50),e.resources.markDirty(Eh);return}},"handler"),n=e.bus.subscribe(s);return e.resources.register(xh,()=>({schemaVersion:1,revision:e.resources.revision(xh)??0,updatedAt:new Date().toISOString(),providers:[...t.providers.values()]})),e.resources.register(Eh,()=>({schemaVersion:1,revision:e.resources.revision(Eh)??0,updatedAt:new Date().toISOString(),requests:t.recentRequests.slice()})),{unsubscribe:n,uris:[xh,Eh]}}l(Wq,"_T"),u(Wq,"installNestReducer");import{App as Lte}from"@frontmcp/sdk";import{Resource as Fte,ResourceContext as Ute}from"@frontmcp/sdk";var Z4=class extends Ute{static{l(this,"ET")}static{u(this,"TraceRecentResource")}async execute(){return this.get(X).read("trace://recent")}};Z4=P([Fte({name:"trace-recent",uri:"trace://recent",mimeType:"application/json",description:"Last 100 trace spans (flattened)."})],Z4);var zte=Z4;import{Resource as Wte,ResourceContext as Hte}from"@frontmcp/sdk";var V4=class extends Hte{static{l(this,"TT")}static{u(this,"TraceFailedResource")}async execute(){return this.get(X).read("trace://failed")}};V4=P([Wte({name:"trace-failed",uri:"trace://failed",mimeType:"application/json",description:"Trace spans that ended with status=error."})],V4);var Gte=V4,Hq=class{static{l(this,"RT")}static{u(this,"TraceApp")}};Hq=P([Lte({id:"trace",name:"Trace",description:"Cross-process span timeline (Phase 3 \u2014 flat; Phase 7 promotes to multi-axis graph).",resources:[zte,Gte]})],Hq);var Sh="trace://recent",Ah="trace://failed";function Gq(e){let t={recent:[],failed:[]},s=u(r=>{let i=r.raw??null;if(!i||i.kind!=="span"||!i.span?.name)return;let a={id:r.id,traceId:i.span.traceId,parentSpanId:i.span.parentSpanId,flowId:i.span.flowId??r.context.flowId,requestId:i.span.requestId??r.context.requestId,name:i.span.name,source:r.source,startTime:i.span.startTime??r.timestamp,endTime:i.span.endTime,durationMs:i.span.durationMs,status:i.span.status??(r.severity==="error"?"error":"ok")};J4(t.recent,a,100),a.status==="error"&&J4(t.failed,a,50),e.resources.markDirty(Sh),a.status==="error"&&e.resources.markDirty(Ah)},"handler"),n=e.bus.subscribe(s);return e.resources.register(Sh,()=>({schemaVersion:1,revision:e.resources.revision(Sh)??0,updatedAt:new Date().toISOString(),spans:t.recent.slice()})),e.resources.register(Ah,()=>({schemaVersion:1,revision:e.resources.revision(Ah)??0,updatedAt:new Date().toISOString(),spans:t.failed.slice()})),{unsubscribe:n,uris:[Sh,Ah]}}l(Gq,"MT"),u(Gq,"installTraceReducer");function J4(e,t,s){e.push(t),e.length>s&&e.splice(0,e.length-s)}l(J4,"oz"),u(J4,"pushBounded");import{App as Zte}from"@frontmcp/sdk";import{Resource as Vte,ResourceContext as Jte}from"@frontmcp/sdk";var K4=class extends Jte{static{l(this,"OT")}static{u(this,"PerfSlowRoutesResource")}async execute(){return this.get(X).read("perf://slow-routes")}};K4=P([Vte({name:"perf-slow-routes",uri:"perf://slow-routes",mimeType:"application/json",description:"Routes that are slow NOW (\u2265 threshold on their latest call, or repeatedly lately). A one-off spike is retracted once later calls prove the route recovered; worstEver keeps the history."})],K4);var Kte=K4;import{Resource as Qte,ResourceContext as Yte}from"@frontmcp/sdk";var Q4=class extends Yte{static{l(this,"NT")}static{u(this,"PerfDuplicateRequestsResource")}async execute(){return this.get(X).read("perf://duplicate-requests")}};Q4=P([Qte({name:"perf-duplicate-requests",uri:"perf://duplicate-requests",mimeType:"application/json",description:"Endpoints one page called SEVERAL TIMES CONCURRENTLY \u2014 the missing-dedupe signal (a hook fetching outside the shared resource cache, multiplied by however many components mount it). Concurrency, not count: sequential repeats are a caching question and are not reported. The threshold sits above 2 so React StrictMode\u2019s double-invoke never fires it. Two consecutive clean loads retract a finding, so a fix clears it without a restart."})],Q4);var Xte=Q4,Zq=class{static{l(this,"PT")}static{u(this,"PerfApp")}};Zq=P([Zte({id:"perf",name:"Perf",description:"Performance signals: slow server routes, and endpoints one page calls concurrently (the missing-dedupe signal).",resources:[Kte,Xte]})],Zq);var Ch="perf://slow-routes",Ih=20,Vq=2,ese=200;function Jq(e){let t=Ms(e.thresholds).slowRouteMs,s=(e.now??(()=>Date.now()))(),n={routes:new Map},r=u(c=>{let p=c.raw??null;if(p?.kind!=="server-request"||!p.request)return;let{method:d,route:h}=p.request,m=p.request.durationMs??0,f=`${d} ${h}`,v=n.routes.get(f);if(v||(v={method:d,route:h,recent:[],samples:0,slowSamples:0,lastDurationMs:m,lastSeenAt:c.timestamp,worstEverMs:0,worstEverAt:c.timestamp}),n.routes.delete(f),n.routes.set(f,v),v.recent.push(m),v.recent.length>Ih&&v.recent.splice(0,v.recent.length-Ih),v.samples+=1,m>=t&&(v.slowSamples+=1),v.lastDurationMs=m,v.lastSeenAt=c.timestamp,m>v.worstEverMs&&(v.worstEverMs=m,v.worstEverAt=c.timestamp),n.routes.size>ese){let g=n.routes.keys().next().value;g!==void 0&&n.routes.delete(g)}n.lastSampleAt=Math.max(n.lastSampleAt??0,c.timestamp),n.changedAt=c.timestamp,e.resources.markDirty(Ch)},"handler"),i=e.bus.subscribe(r),a=u(c=>c.recent.reduce((p,d)=>d>=t?p+1:p,0),"recentSlowCount"),o=u(c=>c.lastDurationMs>=t||a(c)>=Vq,"currentlySlow");return e.resources.register(Ch,()=>{let c=[...n.routes.values()].filter(o);return{schemaVersion:1,revision:e.resources.revision(Ch)??0,updatedAt:new Date(n.changedAt??s).toISOString(),thresholdMs:t,routes:c.map(p=>({method:p.method,route:p.route,worstRecentMs:Math.max(...p.recent),lastDurationMs:p.lastDurationMs,recentMs:[...p.recent],lastSeenAt:p.lastSeenAt,samples:p.samples,slowSamples:p.slowSamples,recentSlowSamples:a(p),worstEverMs:p.worstEverMs,worstEverAt:p.worstEverAt})).sort((p,d)=>d.worstRecentMs-p.worstRecentMs),routesTracked:n.routes.size,recentSampleWindow:Ih,minRecentSlowToKeep:Vq,lastSampleAt:n.lastSampleAt,producer:n.lastSampleAt===void 0?"none":"connected",detail:n.lastSampleAt===void 0?"No server request has ever been observed \u2014 this is NOT evidence the backend is fast, nothing is watching. Run the backend under the dev cluster (or with @lensmcp/nest-instrumentation) so request timings reach this session.":`${n.routes.size} route${n.routes.size===1?"":"s"} observed; ${c.length} slow in the last ${Ih} calls each (\u2265${t}ms).`}}),{unsubscribe:i,uris:[Ch]}}l(Jq,"LT"),u(Jq,"installPerfReducer");var Dh="perf://duplicate-requests",Y4=10,Kq=2,tse=200,Qq=300,sse=new Set(["t","_","cacheBust","ts"]),rse=8,Yq=2,nse="react";function Xq(e,t){return t.start<=e.end+Yq&&t.end>=e.start-Yq}l(Xq,"lne"),u(Xq,"sameRequest");function ej(e){try{let t=new URL(e,"http://lensmcp.invalid");for(let r of[...t.searchParams.keys()])sse.has(r)&&t.searchParams.delete(r);let s=t.searchParams.toString(),n=`${t.pathname}${s?`?${s}`:""}`;return t.host==="lensmcp.invalid"?n:`${t.origin}${n}`}catch{return e}}l(ej,"lz"),u(ej,"normalizeRequestUrl");function tj(e){if(e.length===0)return 0;let t=[];for(let{start:r,end:i}of e)t.push({at:r,delta:1}),t.push({at:i+1,delta:-1});t.sort((r,i)=>r.at-i.at||r.delta-i.delta);let s=0,n=0;for(let{delta:r}of t)s+=r,s>n&&(n=s);return n}l(tj,"uz"),u(tj,"peakConcurrency");function sj(e){let t=Ms(e.thresholds).duplicateRequestPeak,s=(e.now??(()=>Date.now()))(),n={endpoints:new Map},r=u((d,h,m)=>{d.open.delete(h),m.windows.length!==0&&(d.recentPeaks.push(m.peak),d.recentPeaks.length>Y4&&d.recentPeaks.splice(0,d.recentPeaks.length-Y4))},"closeFlow"),i=u(d=>{if(d.source!==nse||d.category!=="network")return;let h=d.raw??null;if(h?.kind!=="fetch-done"&&h?.kind!=="fetch-error"||!h.url||!h.method)return;let m=ej(h.url),f=h.method.toUpperCase();if(typeof h.startedAt!="number")return;let v=h.startedAt,g=v+(typeof h.durationMs=="number"?h.durationMs:0),y=d.context?.originNodeId??null,w=d.context?.flowId??null,b=d.context?.tabId??"-",k=h.requestId??d.context?.requestId,$=k?`${b}|${k}`:void 0,E=`${f} ${m} @ ${y??"-"}`,x=n.endpoints.get(E);x||(x={method:f,url:m,originNodeId:y,open:new Map,recentPeaks:[],totalRequests:0,repeatedReceipts:0,lastSeenAt:d.timestamp,worstEverPeak:0,worstEverAt:d.timestamp}),n.endpoints.delete(E),n.endpoints.set(E,x);let S=x.open.get(b);if(S&&S.flowId!==w&&(r(x,b,S),S=void 0),S||(S={flowId:w,windows:[],byIdentity:new Map,peak:0}),x.open.delete(b),x.open.set(b,S),x.open.size>rse){let[C,_]=x.open.entries().next().value;r(x,C,_)}let A={start:v,end:g},I=$?S.byIdentity.get($):void 0;if(I&&Xq(I,A))I.start=Math.min(I.start,v),I.end=Math.max(I.end,g),x.repeatedReceipts+=1;else{let C=$?{...A,identity:$}:A;if(S.windows.push(C),$&&S.byIdentity.set($,C),S.windows.length>Qq)for(let _ of S.windows.splice(0,S.windows.length-Qq))_.identity&&S.byIdentity.get(_.identity)===_&&S.byIdentity.delete(_.identity);x.totalRequests+=1}if(S.peak=tj(S.windows),x.lastSeenAt=d.timestamp,S.peak>x.worstEverPeak&&(x.worstEverPeak=S.peak,x.worstEverAt=d.timestamp),n.endpoints.size>tse){let C=n.endpoints.keys().next().value;C!==void 0&&n.endpoints.delete(C)}n.lastSampleAt=Math.max(n.lastSampleAt??0,d.timestamp),n.changedAt=d.timestamp,e.resources.markDirty(Dh)},"handler"),a=e.bus.subscribe(i),o=u(d=>[...d.open.values()].filter(h=>h.windows.length>0).map(h=>h.peak),"openPeaks"),c=u(d=>{let h=[...d.recentPeaks,...o(d)],m=0;for(let f=h.length-1;f>=0&&!((h[f]??0)>=t);f-=1)m+=1;return m},"consecutiveCleanFlows"),p=u(d=>d.worstEverPeak>=t&&c(d)<Kq,"currentlyDuplicated");return e.resources.register(Dh,()=>{let d=[...n.endpoints.values()].filter(p);return{schemaVersion:1,revision:e.resources.revision(Dh)??0,updatedAt:new Date(n.changedAt??s).toISOString(),peakThreshold:t,endpoints:d.map(h=>({method:h.method,url:h.url,originNodeId:h.originNodeId,peakConcurrent:o(h).at(-1)??0,cleanFlowsSince:c(h),flowsObserved:h.recentPeaks.length+o(h).length,totalRequests:h.totalRequests,repeatedReceipts:h.repeatedReceipts,worstEverPeak:h.worstEverPeak,worstEverAt:h.worstEverAt,lastSeenAt:h.lastSeenAt})).sort((h,m)=>m.peakConcurrent-h.peakConcurrent),endpointsTracked:n.endpoints.size,recentFlowWindow:Y4,minCleanFlowsToRetract:Kq,lastSampleAt:n.lastSampleAt,producer:n.lastSampleAt===void 0?"none":"connected",detail:n.lastSampleAt===void 0?"No browser fetch has ever been observed \u2014 this is NOT evidence the app fetches cleanly, nothing is watching. Load a page under the dev cluster so flow-fetch events reach this session.":d.length===0?`${n.endpoints.size} endpoint${n.endpoints.size===1?"":"s"} observed; none exceeded ${t} concurrent identical calls.`:`${d.length} endpoint${d.length===1?"":"s"} called \u2265${t}\xD7 concurrently \u2014 usually a hook fetching outside the shared resource cache, multiplied by however many components mount it.`}}),{unsubscribe:a,uris:[Dh]}}l(sj,"DT"),u(sj,"installDuplicateRequestsReducer");import{App as ise}from"@frontmcp/sdk";import{Resource as ase,ResourceContext as ose}from"@frontmcp/sdk";var X4=class extends ose{static{l(this,"UT")}static{u(this,"DbSlowQueriesResource")}async execute(){return this.get(X).read("db://slow-queries")}};X4=P([ase({name:"db-slow-queries",uri:"db://slow-queries",mimeType:"application/json",description:"Query shapes (project\xB7op\xB7table) whose worst observed duration crosses the slowQueryMs threshold, aggregated live from the pg instrumentation. counts are an undercount for hot shapes (the emitter flood-guards per shape); suppressedEvents carries the drop count."})],X4);var use=X4;import{Resource as lse,ResourceContext as dse}from"@frontmcp/sdk";var ek=class extends dse{static{l(this,"FT")}static{u(this,"DbAnalysisResource")}async execute(){return this.get(X).read("db://analysis")}};ek=P([lse({name:"db-analysis",uri:"db://analysis",mimeType:"application/json",description:"The latest DB analyzer run per project (missing indexes, seq-scan hot spots, unused indexes, migration-parity drift, slow statements) \u2014 ingested from the workspace analyzer's `db-analyze-run` events on the lens bus file."})],ek);var cse=ek;import{Resource as pse,ResourceContext as hse}from"@frontmcp/sdk";var tk=class extends hse{static{l(this,"HT")}static{u(this,"DbPoolResource")}async execute(){return this.get(X).read("db://pool")}};tk=P([pse({name:"db-pool",uri:"db://pool",mimeType:"application/json",description:"When a service could not get a database connection, and why \u2014 each incident with its cause: a hot swap that froze the process (swap-freeze), a blocked event loop (loop-blocked), a pool with every connection out (pool-full), Postgres at max_connections (server-full), a slow connect. \xABtimeout exceeded when trying to connect\xBB is the service\u2019s OWN pool wait, not Postgres refusing. Also: connections held too long (where they were taken), and an older hot-swap generation\u2019s pool that still holds connections."})],tk);var mse=tk,rj=class{static{l(this,"GT")}static{u(this,"DbApp")}};rj=P([ise({id:"db",name:"Db",description:"Database signals: slow query shapes observed live from the pg instrumentation, and the latest externally-ingested analyzer run (missing indexes, migration parity, unused indexes), and when a service could not get a connection and why (db://pool).",resources:[use,cse,mse]})],rj);var yl="db://slow-queries",Th="db://analysis",nj=50,fse=20,gse=200,vse=1e3,yse=["statements","failed","workMs","recorded","suppressed","unwritten"];function ij(e){let t=e[Mw];if(!t)return;let s=Array.isArray(t.paths)?t.paths:[];for(let n of s){let r=typeof n=="string"?/^findings\[\] \(\+(\d+) items dropped\)$/.exec(n):null;if(r)return Number(r[1])}return s.some(n=>typeof n=="string"&&n.startsWith("findings"))?0:void 0}l(ij,"Sne"),u(ij,"findingsDroppedByClamp");function aj(e,t){if(!e||!e.stores.length&&!e.read.length)return"";if(!e.read.length)return` LensMCP's own checks are separate and need no run: db_schema { store: "${e.stores[0]}" } reads ${e.stores.join(", ")} \u2014 invalid, unused and redundant indexes, foreign keys no index serves, big tables read whole, dead rows.`;let s=u(n=>{let r=Object.entries(n.byKind).map(([a,o])=>`${o} ${a}`).join(", "),i=Math.max(0,Math.round((t-n.at)/6e4));return`${n.store}/${n.database}: ${n.findings} finding${n.findings===1?"":"s"}${r?` (${r})`:""}, read ${i?`${i} min ago`:"just now"}`+(n.judged?` \u2014 ${n.judged}`:"")},"one");return` LensMCP's own checks are separate (db_schema reads them): ${e.read.slice(0,3).map(s).join(" \xB7 ")}`}l(aj,"xne"),u(aj,"lensChecksWords");function oj(e){let t=Ms(e.thresholds).slowQueryMs,s=e.now??(()=>Date.now()),n=s(),r={shapes:new Map,analyzeRuns:new Map,accounts:new Map,accountsSeen:0,census:{statements:0,failed:0,workMs:0,recorded:0,suppressed:0,unwritten:0}},i=u(c=>{let p=c.raw??null;if(p){if(p.kind==="db-query"){let d=p.project??"unknown",h=p.op??"query",m=p.table??"query",f=p.durationMs??0,v=`${d}|${h}|${m}`,g=r.shapes.get(v);if(g||(g={project:d,op:h,table:m,count:0,errorCount:0,totalMs:0,maxMs:0,maxAt:c.timestamp,recent:[],rowsTotal:0,lastSql:"",lastDurationMs:0,lastSeenAt:c.timestamp,suppressed:0}),r.shapes.delete(v),r.shapes.set(v,g),g.count+=1,p.error!==void 0&&(g.errorCount+=1),g.totalMs+=f,f>g.maxMs&&(g.maxMs=f,g.maxAt=c.timestamp),g.recent.push(f),g.recent.length>nj&&g.recent.splice(0,g.recent.length-nj),g.rowsTotal+=p.rows??0,p.query&&(g.lastSql=p.query),g.lastDurationMs=f,g.lastSeenAt=c.timestamp,g.suppressed+=p.floodSuppressed??0,r.shapes.size>gse){let y=r.shapes.keys().next().value;y!==void 0&&r.shapes.delete(y)}r.lastQueryAt=Math.max(r.lastQueryAt??0,c.timestamp),r.changedAt=c.timestamp,e.resources.markDirty(yl);return}if(p.kind==="db-request-account"){let d=p,h=typeof d.accountId=="string"?d.accountId:c.id,m=typeof d.seq=="number"?d.seq:0,f=r.accounts.get(h);if(f&&f.seq>=m)return;let v={seq:m,statements:0,failed:0,workMs:0,recorded:0,suppressed:0,unwritten:0};for(let g of yse){let y=d[g];v[g]=typeof y=="number"&&Number.isFinite(y)?y:0,r.census[g]+=v[g]-(f?.[g]??0)}if(f||(r.accountsSeen+=1),r.accounts.delete(h),r.accounts.set(h,v),r.accounts.size>vse){let g=r.accounts.keys().next().value;g!==void 0&&r.accounts.delete(g)}r.changedAt=c.timestamp,e.resources.markDirty(yl);return}if(p.kind==="db-analyze-run"){let d=p.project??"unknown",h=ij(p);r.analyzeRuns.set(d,{project:d,runAt:p.runAt??c.timestamp,tool:p.tool??"unknown",findings:Array.isArray(p.findings)?p.findings:[],...h!==void 0?{droppedFindings:h}:{}}),wi(r.analyzeRuns,Gu),r.lastAnalyzeAt=Math.max(r.lastAnalyzeAt??0,c.timestamp),r.changedAt=c.timestamp,e.resources.markDirty(Th)}}},"handler"),a=e.bus.subscribe(i),o=u(c=>{if(c.length===0)return 0;let p=[...c].sort((d,h)=>d-h);return p[Math.min(p.length-1,Math.floor(p.length*.95))]??0},"p95");return e.resources.register(yl,()=>{let c=[...r.shapes.values()].filter(p=>p.maxMs>=t);return{schemaVersion:1,revision:e.resources.revision(yl)??0,updatedAt:new Date(r.changedAt??n).toISOString(),thresholdMs:t,queries:c.map(p=>({project:p.project,op:p.op,table:p.table,count:p.count,errorCount:p.errorCount,maxMs:p.maxMs,maxAt:p.maxAt,avgMs:Math.round(p.totalMs/Math.max(p.count,1)*10)/10,p95Ms:o(p.recent),rowsTotal:p.rowsTotal,lastDurationMs:p.lastDurationMs,lastSeenAt:p.lastSeenAt,lastSql:p.lastSql,suppressedEvents:p.suppressed})).sort((p,d)=>d.maxMs-p.maxMs).slice(0,fse),shapesTracked:r.shapes.size,...r.accountsSeen>0?{requestAccounting:{requests:r.accountsSeen,...r.census}}:{},note:"count/avg are an UNDERCOUNT for hot shapes: the emitter flood-guards each query-shape fingerprint at 30 burst / 5 events/s; suppressedEvents is the emitter's own count of dropped events, reported by the next admitted event of the shape \u2014 drops with none after them are missing from it. requestAccounting, when present, is the requests' own census (statements run vs recorded on the bus), exact including those; per flow, read flow_get's overview.sql.",lastSampleAt:r.lastQueryAt,producer:r.lastQueryAt===void 0?"none":"connected",detail:r.lastQueryAt===void 0?"No db-query event has ever been observed \u2014 this is NOT evidence queries are fast, nothing is watching. Run the backend under the dev cluster (the @lensmcp/cluster serve preload taps pg) so query timings reach this session.":`${r.shapes.size} query shape${r.shapes.size===1?"":"s"} observed; ${c.length} with a worst duration \u2265${t}ms.`}}),e.resources.register(Th,()=>{let c=[...r.analyzeRuns.values()].sort((k,$)=>$.runAt-k.runAt),p=c.flatMap(k=>k.findings),d=p.length,h=p.filter(k=>k.severity==="error").length,m=p.filter(k=>k.severity==="warning").length,f=d-h-m,v=c.filter(k=>k.droppedFindings!==void 0),g=v.reduce((k,$)=>k+($.droppedFindings??0),0),y=v.length>0,w;try{w=e.lensChecks?.()}catch{w=void 0}let b=aj(w,s());return{schemaVersion:1,revision:e.resources.revision(Th)??0,updatedAt:new Date(r.changedAt??n).toISOString(),runs:c,findingCount:d,errorCount:h,warningCount:m,infoCount:f,...y?{incomplete:!0,droppedFindings:g}:{},lastSampleAt:r.lastAnalyzeAt,producer:r.lastAnalyzeAt===void 0?"none":"connected",...w&&(w.stores.length||w.read.length)?{lensChecks:{tool:"db_schema",stores:w.stores,read:w.read.map(k=>({...k,at:new Date(k.at).toISOString()}))}}:{},detail:(r.lastAnalyzeAt===void 0?"No db-analyze run has ever been ingested \u2014 this is NOT evidence the schema is healthy: the workspace's analyzer has not run. Run the workspace's DB analyzer (it appends a `db-analyze-run` event to the lens bus file) to populate this.":`${c.length} analyze run${c.length===1?"":"s"} held (latest per project); ${d} finding${d===1?"":"s"} (${h} error, ${m} warning, ${f} info).`+(y?` INCOMPLETE: ${g>0?`${g} more findings were`:"part of a run was"} cut by the bus payload bound before reaching the lens (an event over 32 KiB keeps only the first 64 items of a list), and the cut takes whatever came last. The analyzer must keep one run under that bound, most severe first.`:""))+b}}),{unsubscribe:a,uris:[yl,Th]}}l(oj,"VT"),u(oj,"installDbReducer");var uj=[["pool-wait-timeout",/timeout exceeded when trying to connect/i],["connect-timeout",/Connection terminated due to connection timeout/i],["server-full",/sorry, too many clients already|remaining connection slots are reserved|too many connections for role/i],["pool-ended",/Cannot use a pool after calling end on the pool/i],["auth-failed",/password authentication failed|no pg_hba\.conf entry/i],["server-unreachable",/connect (ECONNREFUSED|EHOSTUNREACH|ETIMEDOUT)|getaddrinfo ENOTFOUND/i]],lj={53300:"server-full","28P01":"auth-failed",28e3:"auth-failed",ECONNREFUSED:"server-unreachable",EHOSTUNREACH:"server-unreachable",ENOTFOUND:"server-unreachable"},wse=new RegExp(uj.map(([,e])=>e.source).join("|"),"i");function sk(e){let t=e,s=typeof t=="object"&&t&&typeof t.code=="string"?t.code:void 0;if(s&&lj[s])return lj[s];let n=typeof t=="string"?t:typeof t=="object"&&t&&typeof t.message=="string"?t.message:"";for(let[r,i]of uj)if(i.test(n))return r}l(sk,"KT"),u(sk,"pgConnectReason");var _h="db://pool",bse=6e4,Mh=1e3,kse=5e3,dj=500,$se=60,xse=120,Ese=30,Sse=50,De=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),Bh=u(e=>typeof e=="string"&&e?e:void 0,"str"),wl=u((e,t,s)=>{e.push(t),e.length>s&&e.splice(0,e.length-s)},"push"),Ase=u(e=>Bh(e.raw?.project)??Bh(e.context?.projectName)??"unknown","projectOf");function cj(e,t,s){let n=new Map;for(let i of e){let a=n.get(i.project)??[];a.push(i),n.set(i.project,a)}let r=[];for(let[i,a]of n){let o=a.slice().sort((p,d)=>p.at-d.at),c=[];for(let p of o){let d=c[c.length-1];d&&p.at-d[d.length-1].at<=bse?d.push(p):c.push([p])}for(let p of c){let d=p.some(I=>I.tapped)?p.filter(I=>I.tapped):p,h=d[0].at,m=d[d.length-1].at,f=Math.max(...d.map(I=>I.timeoutMs??0))||kse,v={};for(let I of d)I.reason&&(v[I.reason]=(v[I.reason]??0)+1);let g=Math.max(0,...d.map(I=>I.blockedMs??0))||void 0,y=(t.get(i)??[]).find(I=>{let C=I.at-I.swapMs-f,_=I.at+15e3;return d.some(N=>N.at>=C&&N.at<=_)}),w=Math.max(0,...(s.get(i)??[]).filter(I=>I.at>=h-f&&I.at-I.windowMs<=m+1e3).map(I=>I.maxMs))||void 0,b=d.find(I=>I.tapped&&I.reason==="pool-wait-timeout"&&!I.blockedMs&&I.total!==void 0&&I.max!==void 0&&I.total>=I.max),k=u(I=>(v[I]??0)>0,"has"),$=(g??0)>=Mh||(w??0)>=Mh,E=k("server-full")?"server-full":k("auth-failed")?"auth-failed":k("server-unreachable")?"server-unreachable":y&&($||!y.handoff&&y.swapMs>=Mh)&&!b?"swap-freeze":$?"loop-blocked":b?"pool-full":k("connect-timeout")?"connect-slow":k("pool-ended")?"pool-ended":"unknown",x=E==="swap-freeze"?y:void 0,S=Math.max(g??0,w??0,x&&!x.handoff?x.swapMs:0)||void 0,A=d.slice().reverse().find(I=>I.total!==void 0&&I.max!==void 0);r.push({project:i,cause:E,firstAt:h,lastAt:m,failures:d.length,reasons:v,tapped:d.some(I=>I.tapped),...S?{frozenMs:S}:{},...g?{blockedMs:g}:{},...w?{lagMs:w}:{},...x?{swap:x}:{},waitLimitMs:f,...A?{pool:{total:A.total,max:A.max,...A.waiting!==void 0?{waiting:A.waiting}:{}}}:{},eventIds:d.slice(-50).map(I=>I.eventId),example:d[d.length-1].title})}}return r.sort((i,a)=>a.lastAt-i.lastAt).slice(0,Sse)}l(cj,"yz"),u(cj,"incidentsOf");function pj(e){let t=(e.now??(()=>Date.now()))(),s=[],n=new Map,r=new Map,i=[],a=new Map,o,c=!1,p=u(h=>{let m=h.raw??{},f=Bh(m.kind),v=h.timestamp,g=Ase(h),y=!1;if(f==="db-pool-error"){c=!0;let w=Bh(m.reason)??sk(m.error);wl(s,{at:v,project:g,tapped:!0,eventId:h.id,title:h.title??"",...w?{reason:w}:{},...De(m.waitedMs)!==void 0?{waitedMs:De(m.waitedMs)}:{},...De(m.timeoutMs)!==void 0?{timeoutMs:De(m.timeoutMs)}:{},...De(m.blockedMs)!==void 0?{blockedMs:De(m.blockedMs)}:{},...De(m.total)!==void 0?{total:De(m.total)}:{},...De(m.max)!==void 0?{max:De(m.max)}:{},...De(m.waiting)!==void 0?{waiting:De(m.waiting)}:{},...De(m.generation)!==void 0?{generation:De(m.generation)}:{}},dj),y=!0}else if(f==="db-pool-hold")c=!0,wl(i,{at:v,project:g,heldMs:De(m.heldMs)??0,site:Array.isArray(m.site)?m.site.filter(w=>typeof w=="string"):[],eventId:h.id,...De(m.generation)!==void 0?{generation:De(m.generation)}:{}},Ese),y=!0;else if(f==="db-pool"){c=!0;let w=Array.isArray(m.pools)?m.pools.map(b=>({...De(b.generation)!==void 0?{generation:De(b.generation)}:{},total:De(b.total)??0})):[];a.set(g,{at:v,total:De(m.total)??0,idle:De(m.idle)??0,waiting:De(m.waiting)??0,max:De(m.max)??0,pools:w,...De(m.generation)!==void 0?{generation:De(m.generation)}:{},...De(m.serving)!==void 0?{serving:De(m.serving)}:{},...De(m.peakWaiting)!==void 0?{peakWaiting:De(m.peakWaiting)}:{},...De(m.failures)!==void 0?{failures:De(m.failures)}:{}}),y=!0}else if(f==="service-swap"){let w=n.get(g)??[];wl(w,{at:De(m.swappedAt)??v,swapMs:De(m.swapMs)??0,...De(m.generation)!==void 0?{generation:De(m.generation)}:{},...De(m.swaps)!==void 0?{swaps:De(m.swaps)}:{},...m.handoff?{handoff:!0}:{}},$se),n.set(g,w),y=!0}else if(f==="event-loop-lag"){let w=De(m.maxMs)??0;if(w>=Mh){let b=r.get(g)??[];wl(b,{at:v,maxMs:w,windowMs:De(m.windowMs)??3e4},xse),r.set(g,b),y=!0}}else if(h.source!=="lens"&&h.title&&wse.test(h.title)){let w=sk(h.title);wl(s,{at:v,project:g,tapped:!1,eventId:h.id,title:h.title,...w?{reason:w}:{}},dj),y=!0}y&&(o=v,e.resources.markDirty(_h))},"handler"),d=e.bus.subscribe(p);return e.resources.register(_h,()=>{let h=cj(s,n,r),m=[...a.entries()].flatMap(([f,v])=>{let g=Math.max(0,...v.pools.map(y=>y.generation??0));return v.pools.filter(y=>(y.generation??0)<g&&y.total>0).map(y=>({project:f,at:v.at,generation:y.generation??0,connections:y.total,serving:v.serving??g}))});return{schemaVersion:1,revision:e.resources.revision(_h)??0,updatedAt:new Date(o??t).toISOString(),incidents:h,holds:i.slice().reverse(),pools:Object.fromEntries(a),leftovers:m,producer:c?"connected":s.length?"logs-only":"none",detail:c?`${h.length} incident${h.length===1?"":"s"} where a service could not get a database connection; ${i.length} connection${i.length===1?"":"s"} held too long.`:s.length?`${h.length} incident${h.length===1?"":"s"}, read from what the services logged \u2014 their pg tap does not see the pool (lensmcp after 1.25.1 does), so the pool's counts and how late its timers fired are missing.`:"No service has failed to get a database connection \u2014 or none runs a tap that sees its pool."}}),{unsubscribe:d,uris:[_h]}}l(pj,"ZT"),u(pj,"installDbPoolReducer");import{App as Cse}from"@frontmcp/sdk";import{Resource as Ise,ResourceContext as Dse}from"@frontmcp/sdk";var rk=class extends Dse{static{l(this,"JT")}static{u(this,"NetEgressHostsResource")}async execute(){return this.get(X).read("net://egress/hosts")}};rk=P([Ise({name:"net-egress-hosts",uri:"net://egress/hosts",mimeType:"application/json",description:"External hosts this backend called (pod \u2192 third party), rolled up per project\xB7host with count, error/4xx/5xx counters, p95 and worst duration, plus the top endpoints under each. `slow` and `failing` are retracted by later healthy responses, so a one-off blip does not warn all day."})],rk);var Tse=rk;import{Resource as _se,ResourceContext as Mse}from"@frontmcp/sdk";var nk=class extends Mse{static{l(this,"XT")}static{u(this,"NetEgressRecentResource")}async execute(){return this.get(X).read("net://egress/recent")}};nk=P([_se({name:"net-egress-recent",uri:"net://egress/recent",mimeType:"application/json",description:"The last 200 outbound calls with their RAW path and the flowId that caused them \u2014 the evidence behind net://egress/hosts. Query strings are never captured; treat this as the sensitive view, since a path segment can itself be a secret."})],nk);var Bse=nk;import{Resource as qse,ResourceContext as jse}from"@frontmcp/sdk";var ik=class extends jse{static{l(this,"eI")}static{u(this,"NetEgressFailuresResource")}async execute(){return this.get(X).read("net://egress/failures")}};ik=P([qse({name:"net-egress-failures",uri:"net://egress/failures",mimeType:"application/json",description:"Outbound calls that failed \u2014 transport errors and any status \u2265 400 \u2014 kept in their own ring so a high-volume host cannot evict the one failure you need. Empty is NOT proof nothing failed: check `producer`."})],ik);var Rse=ik,hj=class{static{l(this,"nI")}static{u(this,"NetApp")}};hj=P([Cse({id:"net",name:"Net",description:"Outbound (egress) HTTP the backend makes to THIRD PARTIES \u2014 which external services, how often, how slow, and whether they failed. The server-side twin of runtime://browser/network. Internal service-to-service traffic is deliberately absent: the gateway already attributes it.",resources:[Tse,Bse,Rse]})],hj);var qh="net://egress/hosts",jh="net://egress/recent",Rh="net://egress/failures",Ga=20,Ose=25,Nse=200,Pse=20,Lse=5,mj=200,fj=50,gj=2;function vj(e){let t=Ms(e.thresholds).slowEgressMs,s=(e.now??(()=>Date.now()))(),n={hosts:new Map,recent:[],failures:[]},r=u(d=>{let h=d.raw??null;if(!h||h.kind!=="egress")return;let m=h.project??"unknown",f=h.host??"unknown",v=(h.method??"GET").toUpperCase(),g=h.durationMs??0,y=typeof h.status=="number"?h.status:void 0,w=h.error===void 0?void 0:String(h.error),b=w!==void 0||y!==void 0&&y>=400,k=h.path??"(path not captured \u2014 upgrade @lensmcp/node-instrumentation)",$=`${m}|${f}`,E=n.hosts.get($);E||(E={project:m,host:f,count:0,errorCount:0,status4xx:0,status5xx:0,totalMs:0,maxMs:0,maxAt:d.timestamp,recent:[],outcomes:[],firstSeenAt:d.timestamp,lastSeenAt:d.timestamp,lastDurationMs:0,lastBad:!1,suppressed:0,endpoints:new Map}),n.hosts.delete($),n.hosts.set($,E),E.count+=1,w!==void 0&&(E.errorCount+=1),y!==void 0&&y>=400&&y<500&&(E.status4xx+=1),y!==void 0&&y>=500&&(E.status5xx+=1),E.totalMs+=g,g>E.maxMs&&(E.maxMs=g,E.maxAt=d.timestamp),E.recent.push(g),E.recent.length>Ga&&E.recent.splice(0,E.recent.length-Ga),E.outcomes.push(b),E.outcomes.length>Ga&&E.outcomes.splice(0,E.outcomes.length-Ga),E.lastDurationMs=g,E.lastBad=b,E.lastSeenAt=d.timestamp,E.suppressed+=h.floodSuppressed??0;let x=_s(k),S=`${v} ${x}`,A=E.endpoints.get(S);if(A||(A={method:v,path:x,count:0,errorCount:0,status4xx:0,status5xx:0,totalMs:0,maxMs:0,recent:[],lastDurationMs:0,lastSeenAt:d.timestamp}),E.endpoints.delete(S),E.endpoints.set(S,A),A.count+=1,w!==void 0&&(A.errorCount+=1,A.lastError=w),y!==void 0&&y>=400&&y<500&&(A.status4xx+=1),y!==void 0&&y>=500&&(A.status5xx+=1),A.totalMs+=g,g>A.maxMs&&(A.maxMs=g),A.recent.push(g),A.recent.length>Ga&&A.recent.splice(0,A.recent.length-Ga),A.lastStatus=y,A.lastDurationMs=g,A.lastSeenAt=d.timestamp,E.endpoints.size>Pse){let _=E.endpoints.keys().next().value;_!==void 0&&E.endpoints.delete(_)}if(n.hosts.size>Nse){let _=n.hosts.keys().next().value;_!==void 0&&n.hosts.delete(_)}let I=d.context??{},C={id:d.id,timestamp:d.timestamp,project:m,method:v,host:f,path:k,...y!==void 0?{status:y}:{},...w!==void 0?{error:w}:{},durationMs:g,...I.flowId?{flowId:I.flowId}:{},...I.requestId?{requestId:I.requestId}:{}};n.recent.push(C),n.recent.length>mj&&n.recent.splice(0,n.recent.length-mj),b&&(n.failures.push(C),n.failures.length>fj&&n.failures.splice(0,n.failures.length-fj),e.resources.markDirty(Rh)),n.lastSampleAt=Math.max(n.lastSampleAt??0,d.timestamp),n.changedAt=d.timestamp,e.resources.markDirty(qh),e.resources.markDirty(jh)},"handler"),i=e.bus.subscribe(r),a=u(d=>{if(d.length===0)return 0;let h=[...d].sort((m,f)=>m-f);return h[Math.min(h.length-1,Math.floor(h.length*.95))]??0},"p95"),o=u(d=>d.lastDurationMs>=t||d.recent.filter(h=>h>=t).length>=gj,"isSlow"),c=u(d=>d.lastBad||d.outcomes.filter(Boolean).length>=gj,"isFailing"),p=u(d=>{let h=d.outcomes.filter(Boolean).length;return c(d)?`${h} of the last ${d.outcomes.length} call${d.outcomes.length===1?"":"s"} failed`:o(d)?`${d.recent.filter(m=>m>=t).length} of the last ${d.recent.length} call${d.recent.length===1?"":"s"} took \u2265${t}ms`:"healthy"},"describe");return e.resources.register(qh,()=>{let d=[...n.hosts.values()],h=d.filter(c),m=d.filter(f=>!c(f)&&o(f));return{schemaVersion:1,revision:e.resources.revision(qh)??0,updatedAt:new Date(n.changedAt??s).toISOString(),thresholdMs:t,hosts:d.map(f=>({project:f.project,host:f.host,count:f.count,errorCount:f.errorCount,status4xx:f.status4xx,status5xx:f.status5xx,avgMs:Math.round(f.totalMs/Math.max(f.count,1)*10)/10,p95Ms:a(f.recent),maxMs:f.maxMs,maxAt:f.maxAt,lastDurationMs:f.lastDurationMs,firstSeenAt:f.firstSeenAt,lastSeenAt:f.lastSeenAt,slow:o(f),failing:c(f),detail:p(f),suppressedEvents:f.suppressed,endpoints:[...f.endpoints.values()].map(v=>({method:v.method,path:v.path,count:v.count,errorCount:v.errorCount,status4xx:v.status4xx,status5xx:v.status5xx,avgMs:Math.round(v.totalMs/Math.max(v.count,1)*10)/10,p95Ms:a(v.recent),maxMs:v.maxMs,...v.lastStatus!==void 0?{lastStatus:v.lastStatus}:{},...v.lastError!==void 0?{lastError:v.lastError}:{},lastSeenAt:v.lastSeenAt})).sort((v,g)=>g.maxMs-v.maxMs).slice(0,Lse)})).sort((f,v)=>f.failing!==v.failing?f.failing?-1:1:v.maxMs-f.maxMs).slice(0,Ose),hostsTracked:n.hosts.size,failingHosts:h.length,slowHosts:m.length,note:"count/avg are an UNDERCOUNT for hot hosts: the emitter flood-guards each host fingerprint at 30 burst / 5 events/s; suppressedEvents is the emitter's own count of dropped events. Query strings are not captured; endpoint paths are templatised (\u2026/:id).",lastSampleAt:n.lastSampleAt,producer:n.lastSampleAt===void 0?"none":"connected",detail:n.lastSampleAt===void 0?"No egress event has ever been observed \u2014 this is NOT evidence the app makes no external calls, nothing is watching. Run the backend under the dev cluster (the @lensmcp/cluster serve preload taps fetch and http/https) so outbound calls reach this session. Internal destinations (*.local, loopback, RFC1918) are skipped by design \u2014 the gateway already attributes service-to-service traffic.":`${n.hosts.size} external host${n.hosts.size===1?"":"s"} observed; ${h.length} failing, ${m.length} slower than ${t}ms.`}}),e.resources.register(jh,()=>({schemaVersion:1,revision:e.resources.revision(jh)??0,updatedAt:new Date(n.changedAt??s).toISOString(),entries:[...n.recent],count:n.recent.length,note:"Raw paths, as requested. flowId joins an outbound call back to the click that caused it. Treat this as the sensitive view: a path segment can itself be a secret (a presigned key, a reset token), which the templatised rollup collapses but this does not.",lastSampleAt:n.lastSampleAt,producer:n.lastSampleAt===void 0?"none":"connected",detail:n.lastSampleAt===void 0?"No egress event has ever been observed \u2014 this is NOT evidence the app makes no external calls, nothing is watching.":`${n.recent.length} recent outbound call${n.recent.length===1?"":"s"}.`})),e.resources.register(Rh,()=>({schemaVersion:1,revision:e.resources.revision(Rh)??0,updatedAt:new Date(n.changedAt??s).toISOString(),entries:[...n.failures],count:n.failures.length,note:"A separate ring from net://egress/recent on purpose: a host called 200\xD7/min would otherwise evict the one 503 you need.",lastSampleAt:n.lastSampleAt,producer:n.lastSampleAt===void 0?"none":"connected",detail:n.lastSampleAt===void 0?"No egress event has ever been observed \u2014 an empty list here is NOT evidence that nothing failed, nothing is watching.":`${n.failures.length} failed outbound call${n.failures.length===1?"":"s"} held.`})),{unsubscribe:i,uris:[qh,jh,Rh]}}l(vj,"rI"),u(vj,"installNetReducer");import{App as Fse}from"@frontmcp/sdk";import{Resource as Use,ResourceContext as zse}from"@frontmcp/sdk";var ak=class extends zse{static{l(this,"sI")}static{u(this,"CatalogRoutesResource")}async execute(){return this.get(X).read("catalog://routes")}};ak=P([Use({name:"catalog-routes",uri:"catalog://routes",mimeType:"application/json",description:"Every backend route the services handled (`service METHOD /route`, ids folded to :id), most recent first: runs, errors, p50 / p95, the latest run (status, time, flow id), who called it, what the latest run touched (svc: services it called \xB7 sql: statement shapes \xB7 cache: \xB7 queue: \xB7 ext: hosts outside the cluster \xB7 err: what threw) and what its latest run did differently from its earlier runs. Kept for 30 days, beyond the flow window. One route in full: catalog_route."})],ak);var Wse=ak;import{Tool as Hse,ToolContext as Gse}from"@frontmcp/sdk";var Zse=u(e=>e&&typeof e=="object"?e:{},"obj"),_i=u(e=>typeof e=="string"&&e?e:void 0,"str"),Vse=2e3,Za=u(e=>e.split("?")[0]||"/","pathOnly"),yj=class{static{l(this,"Ci")}static{u(this,"GatewayRouting")}constructor(e){this.hosts=new Set,this.prefixes=new Map,this.hops=new Map;for(let t of e?.hosts??[])this.hosts.add(t);for(let[t,s]of Object.entries(e?.prefixes??{}))for(let n of s)this.addPrefix(t,n.prefix,n.project)}learn(e,t){let s=_i(e.host),n=_i(e.project),r=_i(e.url);s&&this.hosts.add(s);let i=Array.isArray(e.steps)?e.steps:[];for(let a of i){let o=Zse(a),c=_i(o.prefix),p=_i(o.project),d=_i(o.routeHost)??s;o.step!=="route-match"||!c||!p||!d||(this.hosts.add(d),this.addPrefix(d,c,p))}if(s&&n&&r){let a=`${s} ${(_i(e.method)??"GET").toUpperCase()} ${Za(r)}`;this.hops.delete(a),this.hops.set(a,{project:n,...t?{requestId:t}:{}}),this.hops.size>Vse&&this.hops.delete(this.hops.keys().next().value)}}addPrefix(e,t,s){let n=this.prefixes.get(e)??[];n.some(r=>r.prefix===t)||(n.push({prefix:t,project:s}),n.sort((r,i)=>i.prefix.length-r.prefix.length),this.prefixes.set(e,n))}fronts(e){return this.hosts.has(e)}serviceAt(e,t,s){let n=this.hops.get(`${e} ${t.toUpperCase()} ${Za(s)}`);if(n)return n;let r=Za(s),i=this.prefixes.get(e)?.find(a=>r===a.prefix||r.startsWith(a.prefix.endsWith("/")?a.prefix:`${a.prefix}/`))?.project;return i?{project:i}:void 0}known(){return[...this.hosts].sort().map(e=>({host:e,services:[...new Set((this.prefixes.get(e)??[]).map(t=>t.project))].sort()}))}toFile(){return{hosts:[...this.hosts],prefixes:Object.fromEntries(this.prefixes)}}};function ok(e,t){if(!(!e||/^(LATERAL|ONLY|SELECT|VALUES|ROWS|MAX|MIN|COUNT|SUM|AVG|UNNEST)$/i.test(e))&&!t.includes(`${e}(`))return e}l(ok,"iI"),u(ok,"tapTable");function wj(e){let t=typeof e.statement=="string"?e.statement:typeof e.query=="string"?e.query:"",s=t?ts(t):void 0,n=typeof e.op=="string"?e.op.toUpperCase():"QUERY",r=s&&s.verb!=="QUERY"?s.verb:n,i=Array.isArray(e.tables)&&typeof e.tables[0]=="string"?e.tables[0]:void 0,a=(s?.target??s?.tables[0]??i??ok(typeof e.table=="string"?e.table:void 0,t))?.split(".").pop();return{verb:r,...a?{table:a}:{}}}l(wj,"kz"),u(wj,"statementOf");var Jse=20,Kse=40,bl=u((e,t)=>{t&&(!(t in e)&&Object.keys(e).length>=Kse||(e[t]=(e[t]??0)+1))},"bump"),bj=u((e,t)=>{let s=ki(t)?t:void 0;return e&&s?Ma(e,s):e??s},"merge"),Qse=["location","lastModified","retryAfter","hsts","nosniff","poweredBy","deprecation","sunset","rateLimit","requestId"];function kj(e){return{samples:0,firstAt:e,lastAt:e,request:{contentTypes:{},schemes:{},query:{},params:[],ifMatch:0,ifNoneMatch:0,idempotencyKey:0,origin:0,cookies:0},responses:{}}}l(kj,"xz"),u(kj,"emptyContract");function $j(e){let t=e,s=t?.request;return!s||typeof s.schemes!="object"||!t.responses||typeof t.responses!="object"?!1:(s.body===void 0||ki(s.body))&&Object.values(t.responses).every(n=>n.body===void 0||ki(n.body))}l($j,"$z"),u($j,"isContract");function xj(e,t,s,n,r){e.samples++,e.lastAt=Math.max(e.lastAt,t),e.firstAt=Math.min(e.firstAt,t);let i=e.request;bl(i.contentTypes,n.contentType??(n.body?"(none)":void 0)),bl(i.schemes,n.scheme??"none");for(let d of n.query??[])bl(i.query,d);for(let d of n.params??[])i.params.includes(d)||i.params.push(d);n.ifMatch&&i.ifMatch++,n.ifNoneMatch&&i.ifNoneMatch++,n.idempotencyKey&&i.idempotencyKey++,n.origin&&i.origin++,n.cookies&&i.cookies++,n.bytes!==void 0&&(i.bytesMax=Math.max(i.bytesMax??0,n.bytes));let a=bj(i.body,n.body);a&&(i.body=a);let o=String(s);if(!e.responses[o]&&Object.keys(e.responses).length>=Jse)return e;let c=e.responses[o]??={n:0,contentTypes:{},cacheControl:{},has:{}};c.n++,bl(c.contentTypes,r.contentType??"(none)"),bl(c.cacheControl,r.cacheControl??"(none)"),r.bytes!==void 0&&(c.bytesMax=Math.max(c.bytesMax??0,r.bytes)),r.etag&&(c.etag=c.etag==="strong"||r.etag==="strong"?c.etag&&c.etag!==r.etag?"weak":r.etag:"weak"),r.vary&&(c.vary=r.vary),r.wwwAuthenticate&&(c.wwwAuthenticate=r.wwwAuthenticate),r.allow&&(c.allow=r.allow),r.cookies?.length&&(c.cookies=[...(c.cookies??[]).filter(d=>!r.cookies.some(h=>h.name===d.name)),...r.cookies].slice(0,10)),r.cors&&(c.cors=r.cors);for(let d of Qse)r[d]&&(c.has[d]=(c.has[d]??0)+1);let p=bj(c.body,r.body);return p&&(c.body=p),e}l(xj,"_z"),u(xj,"foldExchange");var Ej=20,Sj=100,Yse=500,Va=5e3,Xse=/^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS|TRACE|CONNECT)$/i,Aj=200,Xs=720*60*6e4,ere=200,tre=2e3,Oh=5;function Cj(e){let t=Re(e.accountId),s=er(e.statements),n=er(e.firstStartedAt);if(!t||s===void 0||n===void 0)return;let r=Re(e.runId);return{accountId:t,...r?{runId:r}:{},seq:er(e.seq)??1,statements:s,ms:er(e.workMs)??0,seen:er(e.recorded)??0,failed:er(e.failed)??0,firstStartedAt:n}}l(Cj,"Yne"),u(Cj,"readAccount");var Ja=u(e=>{let t=e.indexOf(".");return t===-1?e:e.slice(0,t)},"requestRoot");function Ij(e,t){for(let[s,n]of Object.entries(t.touches))e.touches[s]=(e.touches[s]??0)+n;e.sqlMs+=t.sqlMs;for(let s of t.calls)e.calls.length<Aj&&e.calls.push(s);for(let[s,n]of Object.entries(t.called))e.called[s]=(e.called[s]??0)+n;return e}l(Ij,"ere"),u(Ij,"mergeWork");var Pn=u(e=>e&&typeof e=="object"?e:{},"obj"),Re=u(e=>typeof e=="string"&&e?e:void 0,"str"),er=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),sre=new Set(["BEGIN","START","COMMIT","END","ROLLBACK","SAVEPOINT","RELEASE","SET","RESET","SHOW","DISCARD","DEALLOCATE","PREPARE","LISTEN","UNLISTEN"]),rre=/^[A-Za-z_][\w$]*(\.[A-Za-z_][\w$]*)?$/;function Dj(e){let t=Pn(e.raw),s=Re(t.kind);if(s==="db-query"){let{verb:n,table:r}=wj(t);return sre.has(n)?void 0:`sql:${n}${r&&rre.test(r)?` ${r}`:""}`}if(s==="redis-op")return`cache:${(Re(t.op)??"command").toUpperCase()}`;if(s==="egress")return`ext:${Re(t.host)??"unknown"}`;if(s==="ai-call")return`ext:${Re(t.host)??Re(t.provider)??"ai"}`;if(s==="queue-enqueued")return`queue:${Re(t.queue)??"queue"}`;if(s==="span"){let n=Pn(t.span);if(n.outcome==="threw"||n.status==="error"){let r=Pn(n.error);return`err:${Re(r.name)??Re(n.name)??"error"}`}}}l(Dj,"Cz"),u(Dj,"touchOf");function uk(e,t){if(e.length)return e[Math.min(e.length-1,Math.floor(t/100*e.length))]}l(uk,"Tz"),u(uk,"percentile");var Tj=new WeakMap;function _j(e){let t=Tj.get(e);if(t&&t.count===e.count&&t.n===e.samples.length)return t.sorted;let s=[...e.samples].sort((n,r)=>n-r);return Tj.set(e,{count:e.count,n:e.samples.length,sorted:s}),s}l(_j,"rre"),u(_j,"samplesInOrder");function Ka(e){let t=e.slice(0,e.indexOf(":"));return t==="svc"||t==="ext"||t==="sql"||t==="cache"||t==="queue"||t==="err"?t:"other"}l(Ka,"Xl"),u(Ka,"useKind");function Nh(e){let t=e.slice(e.indexOf(":")+1);return Ka(e)==="sql"||Ka(e)==="cache"?t.toLowerCase():t}l(Nh,"aI"),u(Nh,"useName");var Mj={"new-external":0,"new-error":1,status:2,"new-service":3,"new-queue":4,"new-query":5,"new-cache":6,count:7,duration:8,"gone-error":9,gone:10},Bj=u(e=>{if(!e.length)return;let t=[...e].sort((s,n)=>s-n);return t[Math.floor(t.length/2)]},"median");function lk(e,t){if(!t.length)return[];let s=[],n=t.length>1?"usually ":"",r=new Set(t.flatMap(p=>Object.keys(p.touches))),i=[...r].filter(p=>t.every(d=>(d.touches[p]??0)>0));for(let[p,d]of Object.entries(e.touches)){let h=Ka(p),m=Nh(p);if(!r.has(p)){let v=h==="ext"?"new-external":h==="svc"?"new-service":h==="queue"?"new-queue":h==="cache"?"new-cache":h==="err"?"new-error":"new-query",g=h==="ext"?`now calls ${m}`:h==="svc"?`now calls the ${m} service`:h==="err"?`now throws ${m}`:h==="queue"?`now adds jobs to ${m}`:h==="cache"?`now sends ${m.toUpperCase()} to the cache`:`now runs ${m}`;s.push({kind:v,key:p,text:g});continue}let f=h==="sql"?Bj(t.map(v=>v.touches[p]??0).filter(v=>v>0)):void 0;f!==void 0&&d!==f&&Math.max(d,f)>=2*Math.min(d,f)&&Math.abs(d-f)>=2&&s.push({kind:"count",key:p,text:`${m} ${n}\xD7${f} \u2192 \xD7${d}`})}for(let p of i){if((e.touches[p]??0)>0)continue;let d=Ka(p),h=Nh(p),m=d==="err"?`no longer throws ${h}`:d==="ext"?`no longer calls ${h}`:d==="svc"?`no longer calls the ${h} service`:d==="queue"?`no longer adds jobs to ${h}`:d==="cache"?`no longer sends ${h.toUpperCase()} to the cache`:`no longer runs ${h}`;s.push({kind:d==="err"?"gone-error":"gone",key:p,text:m})}let a=t[t.length-1];e.status!==void 0&&a?.status!==void 0&&e.status!==a.status&&s.push({kind:"status",text:`${a.status} \u2192 ${e.status}`});let o=e.durationMs,c=Bj(t.map(p=>p.durationMs).filter(p=>p!==void 0));return o!==void 0&&c!==void 0&&Math.abs(o-c)>50&&Math.abs(o-c)/Math.max(1,c)>.3&&s.push({kind:"duration",text:`${n}${Math.round(c)} ms \u2192 ${Math.round(o)} ms`}),s.sort((p,d)=>Mj[p.kind]-Mj[d.kind])}l(lk,"dI"),u(lk,"diffHistory");function dk(e,t){return lk(e,[t])}l(dk,"cI"),u(dk,"diffRuns");function qj(e){let t=e.slice(-10),s=t[t.length-1],n=new Map;for(let i of t)for(let[a,o]of Object.entries(i.touches)){let c=n.get(a)??{inRuns:0,total:0};c.inRuns+=1,c.total+=o,n.set(a,c)}let r={svc:0,sql:1,cache:2,queue:3,ext:4,err:5,other:6};return[...n.entries()].map(([i,a])=>{let o=Ka(i),c=o==="sql"?i.slice(4).split(" ")[0]:void 0;return{key:i,kind:o,name:Nh(i),...c?{verb:c}:{},inRuns:a.inRuns,perRun:Math.round(a.total/a.inRuns*10)/10,latestOnly:a.inRuns===1&&!!s&&(s.touches[i]??0)>0&&t.length>1}}).sort((i,a)=>r[i.kind]-r[a.kind]||a.inRuns-i.inRuns||i.name.localeCompare(a.name))}l(qj,"Nz"),u(qj,"usesOf");var nre=class{static{l(this,"Yl")}static{u(this,"RouteCatalog")}constructor(e,t=Date.now(),s=new yj,n,r){if(this.routing=s,this.onRun=n,this.onAccount=r,this.routes=new Map,this.pending=new Map,this.runOfRequest=new Map,this.runsByRoot=new Map,this.runsIndexed=0,this.runOfRunId=new Map,this.held=new Map,this.heldCount=0,this.accounted=new Map,this.contracts=new Map,this.newest=0,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1)for(let i of e.routes)t-i.lastSeenAt>Xs||(i.contract&&!$j(i.contract)&&delete i.contract,this.routes.set(i.id,i))}get size(){return this.routes.size}observe(e){if(e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp);let t=Pn(e.raw),s=Pn(e.context),n=Re(t.kind),r=Re(s.requestId);if(n==="server-request")return this.finish(e,t,s);if(n==="http-exchange")return this.exchange(e,t,s);if(n==="db-request-account")return this.account(t,s);if(n==="gateway-request")return this.hop(t,r);let i=Dj(e);if(i&&r){let a=this.work(Re(s.runId)??r),o=er(t.count)??1;a.touches[i]=(a.touches[i]??0)+o,n==="db-query"&&(a.sqlMs+=er(t.durationMs)??0);let c=Re(t.host),p=Re(t.path);n==="egress"&&c&&p&&a.calls.length<Aj&&a.calls.push({host:c,method:(Re(t.method)??"GET").toUpperCase(),path:Za(p),count:o})}return!1}exchange(e,t,s){let n=(Re(t.method)??"GET").toUpperCase(),r=Re(t.route),i=er(t.status);if(!r||i===void 0)return!1;let a=r.split("?")[0]??r,o=a.includes(":")?a:_s(a),c=`${Re(s.projectName)??Re(t.project)??"unknown"} ${n} ${o}`,p=this.routes.get(c),d=p?.contract??this.contracts.get(c)??kj(e.timestamp);if(xj(d,e.timestamp,i,Pn(t.request),Pn(t.response)),p)p.contract=d;else for(this.contracts.set(c,d);this.contracts.size>Va;)this.contracts.delete(this.contracts.keys().next().value);return!!p}work(e){let t=this.pending.get(e);if(!t)for(t={touches:{},sqlMs:0,calls:[],called:{}},this.pending.set(e,t);this.pending.size>Va;)this.pending.delete(this.pending.keys().next().value);return t}hop(e,t){this.routing.learn(e,t);let s=Re(e.caller);return!!(t&&s&&this.nameCaller(t,s))}nameCaller(e,t){let s=this.runOfRequest.get(e);return!s||s.caller&&s.caller!=="client"&&s.caller!=="service"?!1:(s.caller=t,!0)}serviceCalled(e,t){let s=this.routing.serviceAt(e.host,e.method,e.path);return s?.requestId&&this.nameCaller(s.requestId,t),s?.project}settle(e,t){let s={...e.touches},n={};for(let r of e.calls){let i=this.serviceCalled(r,t);if(!i)continue;let a=`ext:${r.host}`,o=(s[a]??0)-r.count;o>0?s[a]=o:delete s[a],n[i]=(n[i]??0)+r.count}for(let[r,i]of Object.entries(e.called))n[r]=Math.max(n[r]??0,i);for(let[r,i]of Object.entries(n))s[`svc:${r}`]=i;return s}finish(e,t,s){let n=Pn(t.request),r=(Re(n.method)??"GET").toUpperCase(),i=Re(n.route);if(!i)return!1;let a=i.split("?")[0]??i,o=a.includes(":")?a:_s(a),c=Re(s.projectName)??Re(t.project)??"unknown",p=Re(s.requestId)??Re(n.requestId),d=Re(s.parentRequestId),h=er(n.status),m=er(n.durationMs),f=er(n.endedAt)??e.timestamp,v=Re(n.exchangeId);if(d){let A=this.work(d).called;A[c]=(A[c]??0)+1}let g=Re(n.runId)??Re(s.runId),y=g?this.pending.get(g):void 0,w=p?this.pending.get(p):void 0,b=y&&w?Ij(y,w):y??w;g&&this.pending.delete(g),p&&this.pending.delete(p);let k=b?this.settle(b,c):{};h!==void 0&&h>=500&&!Object.keys(k).some(A=>A.startsWith("err:"))&&(k[`err:${h}`]=1);let $={at:f,...Re(s.flowId)?{flowId:Re(s.flowId)}:{},...p?{requestId:p}:{},...h!==void 0?{status:h}:{},...m!==void 0?{durationMs:m}:{},...b&&b.sqlMs>0?{sqlMs:Math.round(b.sqlMs*10)/10}:{},caller:d?"service":"client",touches:k,...v?{exchangeId:v}:{}};p&&(this.runOfRequest.set(p,$),this.runOfRequest.size>Va&&this.runOfRequest.delete(this.runOfRequest.keys().next().value)),g&&(this.runOfRunId.set(g,$),this.runOfRunId.size>Va&&this.runOfRunId.delete(this.runOfRunId.keys().next().value));let E=p?this.takeHeld(c,p,$,g):void 0;E&&this.fold($,E,!g);let x=`${c} ${r} ${o}`;p&&(this.indexRun(p,{routeId:x,service:c,method:r,route:o,run:$}),this.onRun?.(p,x,$,g));let S=this.routes.get(x);if(S)this.routes.delete(x);else{S={id:x,service:c,method:r,route:o,firstSeenAt:f,lastSeenAt:f,count:0,errors:0,samples:[],runs:[]};let A=this.contracts.get(x);A&&(S.contract=A,this.contracts.delete(x))}return S.lastSeenAt=Math.max(S.lastSeenAt,f),S.count+=1,h!==void 0&&h>=400&&(S.errors+=1),m!==void 0&&(S.samples.push(m),S.samples.length>Sj&&S.samples.splice(0,S.samples.length-Sj)),S.runs.push($),S.runs.length>Ej&&S.runs.splice(0,S.runs.length-Ej),this.routes.set(x,S),this.routes.size>Yse&&this.routes.delete(this.routes.keys().next().value),!0}account(e,t){let s=Cj(e);if(!s)return!1;let n=this.accounted.get(s.accountId);if(n)return s.seq<=n.seq?!1:this.fold(n.run,s,n.run.sqlAccount?.byTime===!0);let r=Re(t.requestId);if(!r)return!1;let i=Re(t.projectName)??Re(e.project)??"unknown";if(s.runId){let a=this.runOfRunId.get(s.runId);if(a)return this.fold(a,s,!1)}else{let a=this.runByTime(i,r,s.firstStartedAt);if(a)return this.fold(a,s,!0)}return this.hold(`${i} ${r}`,s),!1}runByTime(e,t,s){let n,r=-1/0,i=u(a=>{if(a.sqlAccount||a.requestId!==t)return;let o=a.at-(a.durationMs??0);s<o-Oh||s>a.at+Oh||o<=r||(n=a,r=o)},"consider");for(let a of this.runsOf(Ja(t)))a.service===e&&i(a.run);return n}hold(e,t){let s=this.held.get(e);for(s?s.push(t):this.held.set(e,[t]),this.heldCount+=1;this.heldCount>tre;){let[n,r]=this.held.entries().next().value;this.held.delete(n),this.heldCount-=r.length}}takeHeld(e,t,s,n){let r=`${e} ${t}`,i=this.held.get(r);if(!i)return;let a=s.at-(s.durationMs??0),o=i.findIndex(p=>n?p.runId===n:!p.runId&&p.firstStartedAt>=a-Oh&&p.firstStartedAt<=s.at+Oh);if(o===-1)return;let[c]=i.splice(o,1);return this.heldCount-=1,i.length||this.held.delete(r),c}fold(e,t,s){let n={statements:t.statements,ms:Math.round(t.ms*10)/10,seen:t.seen,...t.failed?{failed:t.failed}:{},...s?{byTime:!0}:{}};return e.sqlAccount=n,this.accounted.delete(t.accountId),this.accounted.set(t.accountId,{run:e,seq:t.seq}),this.accounted.size>Va&&this.accounted.delete(this.accounted.keys().next().value),this.onAccount?.(e),!0}indexRun(e,t){let s=Ja(e),n=this.runsByRoot.get(s);if(n||(n=[],this.runsByRoot.set(s,n)),!(n.length>=ere))for(n.push(t),this.runsIndexed+=1;this.runsIndexed>Va;){let[r,i]=this.runsByRoot.entries().next().value;this.runsByRoot.delete(r),this.runsIndexed-=i.length}}runsOf(e){return this.runsByRoot.get(e)??[]}prune(e){let t=!1;for(let[s,n]of this.routes){if(e-n.lastSeenAt>Xs){this.routes.delete(s),t=!0;continue}let r=n.runs.filter(i=>e-i.at<=Xs);r.length!==n.runs.length&&(n.runs=r,t=!0)}return t}summary(e){let t=_j(e),s=e.runs[e.runs.length-1],n=uk(t,50),r=uk(t,95),i=s?Object.entries(s.touches).sort((a,o)=>o[1]-a[1]).map(([a])=>a):[];return{id:e.id,service:e.service,method:e.method,route:e.route,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,runs:e.count,errors:e.errors,...n!==void 0?{p50:n}:{},...r!==void 0?{p95:r}:{},last:{at:s?.at??e.lastSeenAt,...s?.status!==void 0?{status:s.status}:{},...s?.durationMs!==void 0?{durationMs:s.durationMs}:{},...s?.flowId?{flowId:s.flowId}:{},...s?{touches:s.touches}:{}},callers:[...new Set(e.runs.map(a=>a.caller??"client"))],uses:i,changes:s?lk(s,e.runs.slice(0,-1)):[]}}lintRoutes(e){return(e===void 0?[...this.routes.values()].reverse():[this.find(e)].filter(t=>!!t)).map(t=>({id:t.id,service:t.service,method:t.method,route:t.route,runs:t.count,lastSeenAt:t.lastSeenAt,...t.contract?{contract:t.contract}:{},recent:t.runs}))}summaries(){return[...this.routes.values()].reverse().map(e=>this.summary(e))}detail(e){let t=this.find(e);return t?this.detailOf(t):void 0}details(){let e=[];for(let t of[...this.routes.values()].reverse()){let s=t.id===t.id.trim()?t:this.find(t.id);s&&e.push(this.detailOf(s))}return e}find(e){let t=e.trim(),s=this.routes.get(t);if(!s){let n=t.split(/\s+/),r=n.length>2&&!Xse.test(n[0]??"")?n.shift():void 0,[i,...a]=n,o=a.join(" ");s=[...this.routes.values()].reverse().find(c=>(!r||c.service===r)&&c.method===i?.toUpperCase()&&(c.route===o||c.route===_s(o)))}return s}detailOf(e){let t=e.runs[0],s=e.runs[e.runs.length-2],n=e.runs[e.runs.length-1];return{...this.summary(e),recent:[...e.runs].reverse(),usesDetail:qj(e.runs),changesSincePrev:n&&s&&e.runs.length>1?dk(n,s):[],changesSinceOldest:n&&t&&e.runs.length>1?dk(n,t):[],...e.contract?{contract:e.contract}:{}}}runByExchange(e){for(let t of[...this.routes.values()].reverse()){let s=t.runs.find(n=>n.exchangeId===e);if(s)return{route:this.summary(t),run:s}}}oldestKeptAt(){let e;for(let t of this.routes.values())for(let s of t.runs)(e===void 0||s.at<e)&&(e=s.at);return e}toFile(e){return{version:1,savedAt:e,watermark:this.newest,routes:[...this.routes.values()]}}},ire=200,are=20,Mi=100,ore=50,ck=20,ure=50,lre=10,dre=5e3,jj=2*6e4,Qa=720*60*6e4,cre=60,pre=20,hre=10,mre=10,fre=1e3,gre=2e3,vre=500,Rj=5,Mr=u(e=>e&&typeof e=="object"?e:{},"obj"),ss=u((e,t=300)=>typeof e=="string"&&e?e.slice(0,t):void 0,"str"),Bi=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),Ya=u(e=>Math.round(e*10)/10,"round1"),dn=u((e,t,s)=>{e.push(t),e.length>s&&e.splice(0,e.length-s)},"pushCapped");function Ph(e,t){if(e.length)return e[Math.min(e.length-1,Math.floor(t/100*e.length))]}l(Ph,"mI"),u(Ph,"percentile");var pk=u(e=>e.length?{p50:Ph(e,50),p95:Ph(e,95),n:e.length}:void 0,"statOf");function Lh(e){if(e.startsWith("/"))return{path:e};let t=e.indexOf("/");return t===-1?{host:e,path:"/"}:{host:e.slice(0,t),path:e.slice(t)}}l(Lh,"fI"),u(Lh,"splitTarget");var Oj=u((e,t)=>`${e} ${_s(Lh(t).path)}`,"templateOf"),kl=new Map;function Nj(e){let t=kl.get(e);if(!t){let s=e.split("/").map(n=>n.startsWith(":")?"[^/]+":n==="*"||n==="(.*)"?".*":n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("/");t={exact:new RegExp(`^${s}/?$`),tail:new RegExp(`^(?:/[^/]+)+${s.startsWith("/")?s:`/${s}`}/?$`)},kl.set(e,t),kl.size>2e3&&kl.delete(kl.keys().next().value)}return t}l(Nj,"yre"),u(Nj,"routeMatcher");var $l=new Map;function Pj(e,t){let s=$l.get(e);if(!s){let n="";for(let r of e.split("/").filter(Boolean)){let i=r.endsWith("?"),a=i?r.slice(0,-1):r,o=a==="*"?"(?:/.*)?":a.startsWith(":")?"/[^/]+":`/${a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`;n+=i&&a!=="*"?`(?:${o})?`:o}s=new RegExp(`^${n}/?$`),$l.set(e,s),$l.size>2e3&&$l.delete($l.keys().next().value)}return s.test(t)}l(Pj,"Hz"),u(Pj,"patternMatches");function Lj(e){let t=e.trim().split(/[?#]/)[0]??"",s=/^[a-z][a-z0-9+.-]*:\/\/[^/]*(\/.*)?$/i.exec(t),n=s?s[1]??"/":t;return n.startsWith("/")?n:`/${n}`}l(Lj,"wre"),u(Lj,"pathOfUrl");var hk=u(e=>e.at-(e.durationMs??0),"startOf");function Fj(e,t){for(let s in e){let n=e[s]??0;s.startsWith("cache:")?t.cache+=n:s.startsWith("ext:")&&(t.ext+=n)}}l(Fj,"vre"),u(Fj,"tally");function mk(e){if(e.sqlAccount)return{n:e.sqlAccount.statements,ms:e.sqlAccount.ms,seen:e.sqlAccount.seen};let t=0;for(let s in e.touches)s.startsWith("sql:")&&(t+=e.touches[s]??0);return{n:t,ms:e.sqlMs??0,seen:t}}l(mk,"Lz"),u(mk,"sqlOfRun");function xl(e,t,s,n){let r=(e.sqlSeen??e.sql??0)+n;e.sql=(e.sql??0)+t,e.sqlMs=Ya((e.sqlMs??0)+s),r<e.sql?e.sqlSeen=r:delete e.sqlSeen}l(xl,"rg"),u(xl,"addSql");function fk(e,t,s){let n=e.lastIndexOf(t);n!==-1&&(e[n]=s)}l(fk,"qz"),u(fk,"replaceSample");var Uj=u(e=>e.nav==="hard"?e.appReadyMs:e.readyMs,"readyOf"),Fh=u(e=>Uj(e)??e.readyMs,"readyAny"),yre=u(e=>e!==void 0&&(e===0||e>=400),"requestFailed"),zj=u(e=>e===0?"failed":`${Math.floor(e/100)}xx`,"statusClass"),wre=new Set(["navigate","reload","back_forward","push","replace","pop"]),bre=new Set(["settled","no-requests","no-commit","timeout","left"]),Wj=u((e,t,s)=>(Array.isArray(e)?e:[]).map(n=>ss(n,t)).filter(n=>!!n).slice(0,s),"strs");function Hj(e){let t=e.phase,s=e.nav,n=ss(e.visitId,120),r=ss(e.app,120),i=ss(e.path,200),a=Bi(e.startAt);if(t!=="ready"&&t!=="end"||s!=="hard"&&s!=="spa"||!n||!r||!i||a===void 0)return;let o=u((w,b)=>Bi(w[b])??0,"n"),c=[];for(let w of Array.isArray(e.requests)?e.requests.slice(0,cre):[]){let b=Mr(w),k=ss(b.m,12),$=ss(b.p,300),E=Bi(b.s);if(!k||!$||E===void 0)continue;let x={rid:ss(b.rid,120)??"",m:k.toUpperCase(),p:$,s:E},S=ss(b.qh,40),A=Bi(b.d),I=Bi(b.st),C=ss(b.flowId,120);S&&(x.qh=S),A!==void 0&&(x.d=A),I!==void 0&&(x.st=I),C&&(x.flowId=C),b.late===!0&&(x.late=!0),c.push(x)}let p=Mr(e.renders),d=Mr(e.store),h=Mr(e.errors),m={kind:TT,phase:t,visitId:n,app:r,path:i,nav:s,startAt:a,flowIds:Wj(e.flowIds,120,20),requests:c,renders:{commits:o(p,"commits"),renders:o(p,"renders"),renderMs:o(p,"renderMs"),maxCommitMs:o(p,"maxCommitMs"),stormCommits:o(p,"stormCommits"),mounts:o(p,"mounts"),suspenseWaits:o(p,"suspenseWaits"),top:(Array.isArray(p.top)?p.top:[]).slice(0,8).map(Mr).flatMap(w=>{let b=ss(w.name,120);return b?[{name:b,n:o(w,"n"),ms:o(w,"ms")}]:[]})},store:{updates:o(d,"updates"),top:(Array.isArray(d.top)?d.top:[]).slice(0,8).map(Mr).flatMap(w=>{let b=ss(w.store,120),k=ss(w.path,200);return b&&k?[{store:b,path:k,n:o(w,"n")}]:[]})},errors:{n:o(h,"n")}},f=ss(h.first,300);f&&(m.errors.first=f);let v=ss(e.tabId,80);v&&(m.tabId=v);let g=ss(e.pattern,300);g&&(m.pattern=g),typeof e.navType=="string"&&wre.has(e.navType)&&(m.navType=e.navType),e.cause==="hmr"&&(m.cause="hmr");let y=ss(e.redirectedFrom,200);y&&(m.redirectedFrom=y),typeof e.readyBy=="string"&&bre.has(e.readyBy)&&(m.readyBy=e.readyBy);for(let w of["readyAt","readyMs","appReadyMs","endAt","requestsDropped","heapMb"]){let b=Bi(e[w]);b!==void 0&&(m[w]=b)}if(e.afterReady){let w=Mr(e.afterReady);m.afterReady={requests:o(w,"requests"),templates:Wj(w.templates,200,20),renders:o(w,"renders"),updates:o(w,"updates")}}if(e.vitals&&(m.vitals=Gj(Mr(e.vitals))),e.longTasks){let w=Mr(e.longTasks);m.longTasks={n:o(w,"n"),totalMs:o(w,"totalMs"),maxMs:o(w,"maxMs")}}if(e.chunks){let w=Mr(e.chunks);m.chunks={n:o(w,"n"),kb:o(w,"kb")}}return m}l(Hj,"xre"),u(Hj,"readVisit");function Gj(e){let t={};for(let s of["ttfb","fcp","lcp","cls","inp","dcl","load"]){let n=Bi(e[s]);n!==void 0&&(t[s]=n)}return t}l(Gj,"$re"),u(Gj,"readVitals");function Uh(e){if(!e)return;let t=new Map;for(let s of e){if(s.late)continue;let n=Oj(s.m,s.p),r=t.get(n)??{n:0};r.n+=1,s.st!==void 0&&(r.worst===void 0||s.st===0||s.st>r.worst)&&(r.worst=s.st),t.set(n,r)}return t}l(Uh,"gI"),u(Uh,"templatesOf");var Zj={"new-request":0,status:1,failed:2,"gone-request":3,count:4,sql:5,duration:6};function Vj(e,t){let s=[],n=Uh(e.requestList),r=Uh(t.requestList);if(n&&r){for(let[o,c]of n){let p=r.get(o);if(!p){s.push({kind:"new-request",key:o,text:`now requests ${o}`});continue}c.n!==p.n&&Math.max(c.n,p.n)>=2*Math.min(c.n,p.n)&&Math.abs(c.n-p.n)>=2&&s.push({kind:"count",key:o,text:`${o} \xD7${p.n} \u2192 \xD7${c.n}`}),c.worst!==void 0&&p.worst!==void 0&&zj(c.worst)!==zj(p.worst)&&s.push({kind:"status",key:o,text:`${o} ${p.worst} \u2192 ${c.worst}`})}for(let o of r.keys())n.has(o)||s.push({kind:"gone-request",key:o,text:`no longer requests ${o}`})}if(e.failed&&!t.failed){let o=e.readyBy==="timeout"?"not ready in 30 s":e.errors>0?`the page threw${e.firstError?`: ${e.firstError}`:""}`:"a request answered 5xx";s.push({kind:"failed",text:`failed \u2014 ${o}`})}!e.waiting&&!t.waiting&&e.sql!==t.sql&&Math.max(e.sql,t.sql)>=2*Math.min(e.sql,t.sql)&&Math.abs(e.sql-t.sql)>=5&&s.push({kind:"sql",text:`SQL ${t.sql} \u2192 ${e.sql} statements`});let i=Fh(e),a=Fh(t);return e.nav===t.nav&&i!==void 0&&a!==void 0&&Math.abs(i-a)>100&&Math.abs(i-a)/Math.max(1,a)>.3&&s.push({kind:"duration",text:`ready ${Math.round(a)} ms \u2192 ${Math.round(i)} ms`}),s.sort((o,c)=>Zj[o.kind]-Zj[c.kind])}l(Vj,"Gz"),u(Vj,"diffVisits");var Jj=new WeakMap;function zh(e,t){let s=Jj.get(e);return(!s||s.rev!==e.rev)&&(s={rev:e.rev,sorted:{}},Jj.set(e,s)),s.sorted[t]??=[...e.samples[t]].sort((n,r)=>n-r)}l(zh,"hI"),u(zh,"samplesInOrder");var kre=u(()=>({hard:[],spa:[],requests:[],sql:[],sqlMs:[],renders:[],renderMs:[],updates:[]}),"emptySamples");function Kj(e){if(!e.requestList)return e;let t={...e};return delete t.requestList,t}l(Kj,"Ere"),u(Kj,"bare");var $re=class{static{l(this,"nu")}static{u(this,"PageCatalog")}constructor(e,t=Date.now(),s=()=>[]){if(this.runsOf=s,this.pages=new Map,this.unmatched=new Map,this.waiting=new Map,this.open=new Map,this.joins=new WeakMap,this.seen=new Map,this.tabs=new Map,this.newest=0,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1){for(let n of e.pages??[])if(!(t-n.lastSeenAt>Qa)){for(let r of n.recent)delete r.waiting;n.slowest&&delete n.slowest.waiting,this.pages.set(n.id,n);for(let r of n.recent)this.remember(r.visitId,n.id)}for(let n of e.unmatched??[])t-n.lastSeenAt<=Qa&&this.unmatched.set(`${n.app} ${n.path}`,n)}}get size(){return this.pages.size}observe(e){let t=e.raw;if(t?.kind!==TT||e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp),this.expire(e.timestamp);let s=Hj(t);return s?s.phase==="end"?this.end(s,e.timestamp):this.ready(s,e.timestamp):!1}runArrived(e){let t=Ja(e),s=this.waiting.get(t);if(!s)return!1;let n=this.open.get(s.visitId);if(!n)return this.waiting.delete(t),!1;let r=!1,i=!1;return n.reqs.forEach((a,o)=>{a.routeId||!a.rid||Ja(a.rid)!==t||(this.join(n,a,o)?(this.applyJoin(n,a,o),n.pending-=1,r=!0):i=!0)}),i||this.waiting.delete(t),n.pending<=0?this.finalize(n):n.visit.waiting=n.pending,r}remember(e,t){this.seen.delete(e),this.seen.set(e,t),this.seen.size>gre&&this.seen.delete(this.seen.keys().next().value)}ready(e,t){if(this.seen.has(e.visitId))return!1;let s=e.pattern?`${e.app} ${e.pattern}`:"";this.remember(e.visitId,s);let n=this.cameFrom(e,s);return s?(this.fold(e,s,n,t),!0):this.unmatchedVisit(e)}cameFrom(e,t){if(!e.tabId)return;let s=e.nav==="spa"?this.tabs.get(e.tabId):void 0;return this.tabs.delete(e.tabId),this.tabs.set(e.tabId,t?e.pattern:_s(e.path)),this.tabs.size>vre&&this.tabs.delete(this.tabs.keys().next().value),s}unmatchedVisit(e){let t=_s(e.path),s=`${e.app} ${t}`,n=this.unmatched.get(s)??{app:e.app,path:t,visits:0,lastSeenAt:0};return this.unmatched.delete(s),n.visits+=1,n.lastSeenAt=Math.max(n.lastSeenAt,e.startAt),this.unmatched.set(s,n),this.unmatched.size>ure&&this.unmatched.delete(this.unmatched.keys().next().value),!0}end(e,t){let s=this.seen.get(e.visitId);return s===void 0?this.ready({...e,requests:e.requests.filter(n=>!n.late)},t):s?this.mergeEnd(s,e):!1}mergeEnd(e,t){let s=this.pages.get(e);if(!s)return!1;let n=[...s.recent.filter(a=>a.visitId===t.visitId),...s.slowest?.visitId===t.visitId?[s.slowest]:[]];if(!n.length)return!1;let r=this.open.get(t.visitId),i=new Map(t.requests.filter(a=>!a.late&&a.d!==void 0).map(a=>[`${a.rid} ${a.s}`,a]));for(let a of new Set(n)){t.endAt!==void 0&&(a.endAt=t.endAt),t.afterReady&&(a.afterReady=t.afterReady),t.vitals&&(a.vitals={...a.vitals,...t.vitals}),t.longTasks&&(a.longTasks=t.longTasks),t.heapMb!==void 0&&(a.heapMb=t.heapMb),t.chunks&&(a.chunks=t.chunks),t.errors.n>a.errors&&(a===n[0]&&(s.errors+=t.errors.n-a.errors),a.errors=t.errors.n,t.errors.first&&!a.firstError&&(a.firstError=t.errors.first),a.failed||(a.failed=!0,a===n[0]&&(s.failedVisits+=1)));for(let o of[a.requestList,a===r?.visit?r.reqs:void 0])for(let c of o??[]){if(c.d!==void 0)continue;let p=i.get(`${c.rid} ${c.s}`);p&&(c.d=p.d,p.st!==void 0&&(c.st=p.st))}}return!0}fold(e,t,s,n){let r=this.pages.get(t);r?this.pages.delete(t):r={id:t,app:e.app,pattern:e.pattern,firstSeenAt:e.startAt,lastSeenAt:e.startAt,visits:0,hard:0,spa:0,hmr:0,errors:0,failedVisits:0,samples:kre(),rev:0,recent:[],uses:{},components:{},store:{},paths:[],from:{}},this.pages.set(t,r),this.pages.size>ire&&this.pages.delete(this.pages.keys().next().value);let i=e.cause==="hmr",a=e.requests.filter(v=>!v.late),o=a.map(v=>({...v})),c=o.map(v=>Oj(v.m,v.p)),p=new Set,d=0;for(let v of o){let g=`${v.m} ${v.p} ${v.qh??""}`;p.has(g)?(v.dup=!0,d+=1):p.add(g)}let h=o.some(v=>v.st!==void 0&&v.st>=500)||e.errors.n>0||e.readyBy==="timeout",m={visitId:e.visitId,...e.tabId?{tabId:e.tabId}:{},path:e.path,nav:e.nav,...e.navType?{navType:e.navType}:{},...i?{cause:"hmr"}:{},...e.redirectedFrom?{redirectedFrom:e.redirectedFrom}:{},...s?{from:s}:{},startAt:e.startAt,...e.readyAt!==void 0?{readyAt:e.readyAt}:{},...e.readyBy?{readyBy:e.readyBy}:{},...e.readyMs!==void 0?{readyMs:e.readyMs}:{},...e.appReadyMs!==void 0?{appReadyMs:e.appReadyMs}:{},...e.endAt!==void 0?{endAt:e.endAt}:{},flowIds:e.flowIds,requests:a.length+(e.requestsDropped??0),joined:0,duplicates:d,sql:0,sqlMs:0,commits:e.renders.commits,renders:e.renders.renders,renderMs:Ya(e.renders.renderMs),maxCommitMs:Ya(e.renders.maxCommitMs),stormCommits:e.renders.stormCommits,suspenseWaits:e.renders.suspenseWaits,updates:e.store.updates,errors:e.errors.n,...e.errors.first?{firstError:e.errors.first}:{},...h?{failed:!0}:{},...e.afterReady?{afterReady:e.afterReady}:{},...e.vitals?{vitals:e.vitals}:{},...e.longTasks?{longTasks:e.longTasks}:{},...e.heapMb!==void 0?{heapMb:e.heapMb}:{},...e.chunks?{chunks:e.chunks}:{},requestList:o};if(r.lastSeenAt=Math.max(r.lastSeenAt,e.startAt),r.firstSeenAt=Math.min(r.firstSeenAt,e.startAt),r.visits+=1,e.nav==="hard"?r.hard+=1:r.spa+=1,i&&(r.hmr+=1),r.errors+=e.errors.n,h&&(r.failedVisits+=1),r.paths=[e.path,...r.paths.filter(v=>v!==e.path)].slice(0,lre),s&&(r.from[s]!==void 0||Object.keys(r.from).length<hre)&&(r.from[s]=(r.from[s]??0)+1),!i){let v=Uj(e);v!==void 0&&dn(r.samples[e.nav],v,Mi),dn(r.samples.requests,m.requests,Mi),dn(r.samples.renders,m.renders,Mi),dn(r.samples.renderMs,m.renderMs,Mi),dn(r.samples.updates,m.updates,Mi),r.rev+=1,this.foldUses(r,o,c,e.startAt),this.foldTop(r,e);let g=Fh(m);g!==void 0&&(!r.slowest||g>(Fh(r.slowest)??-1))&&(r.slowest=m)}dn(r.recent,m,are);for(let v=0;v<r.recent.length-2;v++){let g=r.recent[v];g!==r.slowest&&g.requestList&&delete g.requestList}let f={visit:m,pageId:t,reqs:o,templates:c,startAt:e.startAt,hmr:i,pending:0,at:n};o.forEach((v,g)=>{v.rid&&(this.join(f,v,g)?this.applyJoin(f,v,g):(f.pending+=1,this.wait(Ja(v.rid),e.visitId,n)))}),f.pending>0?(m.waiting=f.pending,this.open.set(e.visitId,f),this.open.size>fre&&this.finalize(this.open.values().next().value)):this.finalize(f)}wait(e,t,s){this.waiting.delete(e),this.waiting.set(e,{visitId:t,at:s}),this.waiting.size>dre&&this.waiting.delete(this.waiting.keys().next().value)}join(e,t,s){let n=this.runsOf(Ja(t.rid));if(!n.length)return!1;let{path:r}=Lh(t.p),i=e.startAt+t.s,a=u(g=>{let y=new Map,w,b=1/0;for(let k of n){if(k.method!==t.m)continue;let $=y.get(k.route);if($===void 0&&($=Nj(k.route)[g].test(r),y.set(k.route,$)),!$)continue;let E=Math.abs(hk(k.run)-i);E<b&&(b=E,w=k)}return w},"pick"),o=a("exact")??a("tail");if(!o)return!1;let c=o.run.at,p=hk(o.run),d={cache:0,ext:0};t.sql=0,t.sqlMs=0;let h=u(g=>{Fj(g.touches,d);let y=mk(g);xl(t,y.n,y.ms,y.seen),this.joins.set(g,{o:e,req:t,i:s,...y})},"take");h(o.run);let m=new Map;for(let g of n)g===o||hk(g.run)<p-Rj||g.run.at>c+Rj||(h(g.run),m.set(g.routeId,(m.get(g.routeId)??0)+1));let{cache:f,ext:v}=d;if(t.routeId=o.routeId,t.service=o.service,o.run.status!==void 0&&(t.status=o.run.status),o.run.durationMs!==void 0&&(t.serverMs=o.run.durationMs),f&&(t.cache=f),v&&(t.ext=v),m.size){let g=0;for(let y of m.values())g+=y;t.callCount=g,t.calls=[...m.entries()].sort((y,w)=>w[1]-y[1]).slice(0,mre).map(([y,w])=>({routeId:y,n:w}))}return!0}applyJoin(e,t,s){let n=e.visit;if(n.joined+=1,xl(n,t.sql??0,t.sqlMs??0,t.sqlSeen??t.sql??0),t.service&&((n.services??={})[t.service]=(n.services[t.service]??0)+1),e.hmr)return;let r=this.pages.get(e.pageId)?.uses[e.templates[s]];r&&(t.routeId&&(r.routeId=t.routeId),r.sql+=t.sql??0,r.sqlCalls+=1)}accountArrived(e){let t=this.joins.get(e);if(!t)return!1;let s=mk(e),n=s.n-t.n,r=s.ms-t.ms,i=s.seen-t.seen;if(!n&&!r&&!i)return!1;Object.assign(t,s);let{o:a,req:o}=t,c={sql:a.visit.sql,sqlMs:a.visit.sqlMs};if(xl(o,n,r,i),xl(a.visit,n,r,i),a.hmr)return!0;let p=this.pages.get(a.pageId);if(!p)return!0;let d=p.uses[a.templates[t.i]];return d&&(d.sql+=n),a.done&&(fk(p.samples.sql,c.sql,a.visit.sql),fk(p.samples.sqlMs,c.sqlMs,a.visit.sqlMs),p.rev+=1),!0}finalize(e){if(this.open.delete(e.visit.visitId),delete e.visit.waiting,e.done=!0,e.hmr)return;let t=this.pages.get(e.pageId);t&&(dn(t.samples.sql,e.visit.sql,Mi),dn(t.samples.sqlMs,e.visit.sqlMs,Mi),t.rev+=1)}expire(e){for(let[t,s]of this.waiting){if(e-s.at<=jj)break;this.waiting.delete(t)}for(let t of this.open.values()){if(e-t.at<=jj)break;this.finalize(t)}}foldUses(e,t,s,n){let r=new Map;t.forEach((i,a)=>{let o=s[a],c=r.get(o);if(!c){let p=Lh(i.p).host;c={n:0,failed:0,dups:0,ds:[],m:i.m,...p?{host:p}:{}},r.set(o,c)}c.n+=1,yre(i.st)&&(c.failed+=1),i.dup&&(c.dups+=1),i.d!==void 0&&c.ds.push(i.d)});for(let[i,a]of r){let o=e.uses[i];if(!o){let c=Object.keys(e.uses);if(c.length>=ore){let p=c[0];for(let d of c)(e.uses[d]?.lastAt??0)<(e.uses[p]?.lastAt??0)&&(p=d);delete e.uses[p]}o={method:a.m,path:i.slice(i.indexOf(" ")+1),inVisits:0,total:0,durations:[],failed:0,duplicates:0,sql:0,sqlCalls:0,lastAt:n},e.uses[i]=o}o.inVisits+=1,o.total+=a.n,o.failed+=a.failed,o.duplicates+=a.dups,o.lastAt=Math.max(o.lastAt,n),a.host&&(o.host=a.host);for(let c of a.ds)dn(o.durations,c,pre)}}foldTop(e,t){let s=u((n,r,i,a,o)=>{let c=n[r];if(!c){let p=Object.keys(n);if(p.length>=ck){let d=p[0];for(let h of p)(n[h]?.n??0)<(n[d]?.n??0)&&(d=h);if((n[d]?.n??0)>=i)return;delete n[d]}c=a(),n[r]=c}c.inVisits+=1,o(c)},"into");for(let n of t.renders.top)s(e.components,n.name,n.n,()=>({n:0,ms:0,inVisits:0}),r=>{r.n+=n.n,r.ms=Ya(r.ms+n.ms)});for(let n of t.store.top)s(e.store,`${n.store} ${n.path}`,n.n,()=>({store:n.store,path:n.path,n:0,inVisits:0}),r=>{r.n+=n.n})}prune(e){this.expire(e);let t=!1;for(let[s,n]of this.pages){if(e-n.lastSeenAt>Qa){this.pages.delete(s),t=!0;continue}let r=n.recent.filter(i=>e-i.startAt<=Qa);r.length!==n.recent.length&&(n.recent=r,t=!0),n.slowest&&e-n.slowest.startAt>Qa&&(delete n.slowest,t=!0)}for(let[s,n]of this.unmatched)e-n.lastSeenAt>Qa&&(this.unmatched.delete(s),t=!0);return t}summary(e){let t=e.recent.filter(c=>c.cause!=="hmr"),s=t.at(-1)??e.recent.at(-1),n=t.at(-2),r={},i=pk(zh(e,"spa")),a=pk(zh(e,"hard"));i&&(r.spa=i),a&&(r.hard=a);let o={};for(let c of["requests","sql","sqlMs","renders","renderMs","updates"]){let p=pk(zh(e,c));p&&(o[c]=p)}return{id:e.id,app:e.app,pattern:e.pattern,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,visits:e.visits,hard:e.hard,spa:e.spa,hmr:e.hmr,errors:e.errors,failedVisits:e.failedVisits,ready:r,perVisit:o,...s?{last:Kj(s)}:{},from:Object.entries(e.from).sort((c,p)=>p[1]-c[1]).slice(0,3).map(([c,p])=>({page:c,n:p})),changes:s&&n?Vj(s,n):[]}}summaries(){return[...this.pages.values()].reverse().map(e=>this.summary(e))}payload(e){let t=[...this.unmatched.values()].reverse(),s=this.oldestKeptAt();return{at:e,pages:this.summaries(),unmatched:{visits:t.reduce((n,r)=>n+r.visits,0),paths:t},...s!==void 0?{since:s}:{}}}detail(e){let t=this.find(e);return t?this.detailOf(t):void 0}find(e){let t=e.trim(),s=this.pages.get(t);if(s)return s;let n=[...this.pages.values()].reverse().find(i=>i.pattern===t);if(n)return n;let r=t.indexOf(" ");return r>0&&!t.startsWith("/")?this.resolve(t.slice(r+1),t.slice(0,r)):this.resolve(t)}resolvePath(e,t){let s=this.resolve(e,t);return s?this.detailOf(s):void 0}resolve(e,t){let s=Lj(e),n=[...this.pages.values()].reverse().filter(o=>!t||o.app===t),r=n.find(o=>o.paths.includes(s));if(r)return r;let i,a=-1;for(let o of n){if(!Pj(o.pattern,s))continue;let c=o.pattern.split("/").filter(p=>p&&!p.startsWith(":")&&p!=="*").length;c>a&&(a=c,i=o)}return i}detailOf(e){let t=e.recent.filter(r=>r.cause!=="hmr").at(-1)??e.recent.at(-1),s=Uh(t?.requestList),n=Object.entries(e.uses).map(([r,i])=>{let a=Ph([...i.durations].sort((o,c)=>o-c),50);return{template:r,method:i.method,path:i.path,...i.host?{host:i.host}:{},...i.routeId?{routeId:i.routeId}:{},inVisits:i.inVisits,perVisit:Ya(i.total/Math.max(1,i.inVisits)),...a!==void 0?{p50:a}:{},failed:i.failed,duplicates:i.duplicates,...i.sqlCalls?{sqlPerCall:Ya(i.sql/i.sqlCalls)}:{},latest:!!s?.has(r)}}).sort((r,i)=>i.inVisits-r.inVisits||i.perVisit-r.perVisit||r.template.localeCompare(i.template));return{...this.summary(e),recent:[...e.recent].reverse(),...e.slowest?{slowest:e.slowest}:{},uses:n,components:Object.entries(e.components).map(([r,i])=>({name:r,...i})).sort((r,i)=>i.n-r.n).slice(0,ck),store:Object.values(e.store).sort((r,i)=>i.n-r.n).slice(0,ck),paths:e.paths}}oldestKeptAt(){let e;for(let t of this.pages.values())for(let s of t.recent)(e===void 0||s.startAt<e)&&(e=s.startAt);return e}toFile(e){return{version:1,savedAt:e,watermark:this.newest,pages:[...this.pages.values()],unmatched:[...this.unmatched.values()]}}},xre=100,Ere=20,Qj=2,Sre=200,Are=200,Cre=50,Ire=20,Yj=10,Dre=5e3,Wh=u(e=>e&&typeof e=="object"?e:{},"obj"),Gt=u(e=>typeof e=="string"&&e?e:void 0,"str"),Ln=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),Hh=u((e,t,s)=>{e.push(t),e.length>s&&e.splice(0,e.length-s)},"pushCapped"),Tre=u((e,t)=>{e.includes(t)||e.push(t)},"addOnce");function El(e,t){if(!e.length)return;let s=[...e].sort((n,r)=>n-r);return s[Math.min(s.length-1,Math.floor(t/100*s.length))]}l(El,"ag"),u(El,"percentile");var _re=u(e=>e>=1e3&&e%1e3===0?`${e/1e3} s`:`${e} ms`,"fmtThreshold"),Mre=class{static{l(this,"ru")}static{u(this,"ExternalCatalog")}constructor(e,t,s,n){if(this.routing=s,this.slowMs=n,this.hosts=new Map,this.index=new Map,this.internal=new Map,this.awaiting=new Map,this.newest=0,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1){for(let r of e.hosts)t-r.lastSeenAt>Xs||(this.hosts.set(r.host,r),this.index.set(r.host,new Map(r.endpoints.map(i=>[`${i.method} ${i.path}`,i]))));for(let[r,i]of Object.entries(e.internal??{}))this.internal.set(r,i)}}get size(){return this.hosts.size}observe(e){if(e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp);let t=Wh(e.raw),s=Gt(t.kind);return s==="egress"?this.call(e,t):s==="ai-call"?this.aiCall(e,t):!1}attribute(e,t){let s=this.awaiting.get(e);if(!s)return!1;this.awaiting.delete(e);for(let{call:n,endpoint:r}of s){n.route=t;let i=r.routes.indexOf(t);i>=0&&r.routes.splice(i,1),r.routes.unshift(t),r.routes.length>Yj&&(r.routes.length=Yj)}return!0}hostOf(e,t){let s=this.hosts.get(e);if(s?this.hosts.delete(e):(s={host:e,services:[],calls:0,failed:0,samples:[],outcomes:[],maxMs:0,firstSeenAt:t,lastSeenAt:t,viaEgress:!1,endpoints:[],recent:[],failures:[]},this.index.set(e,new Map)),this.hosts.set(e,s),this.hosts.size>Sre){let n=this.hosts.keys().next().value;this.hosts.delete(n),this.index.delete(n)}return s}endpointOf(e,t,s,n){let r=this.index.get(e.host)??new Map;this.index.set(e.host,r);let i=`${t} ${s}`,a=r.get(i);if(!a&&(a={id:`${e.host} ${i}`,host:e.host,method:t,path:s,services:[],routes:[],calls:0,failed:0,status4xx:0,status5xx:0,samples:[],maxMs:0,firstSeenAt:n,lastSeenAt:n,ai:{}},r.set(i,a),e.endpoints.push(a),e.endpoints.length>Are)){e.endpoints.sort((c,p)=>c.lastSeenAt-p.lastSeenAt);let o=e.endpoints.shift();o&&r.delete(`${o.method} ${o.path}`)}return a}count(e,t,s){let n=s.error!==void 0||s.status!==void 0&&s.status>=400,r=s.durationMs??0;for(let i of[e,t])i.calls+=1,n&&(i.failed+=1),i.lastSeenAt=Math.max(i.lastSeenAt,s.at),s.durationMs!==void 0&&(Hh(i.samples,s.durationMs,xre),s.durationMs>i.maxMs&&(i.maxMs=s.durationMs)),Tre(i.services,s.service);return Hh(e.outcomes,{bad:n,ms:r},Ere),s.status!==void 0&&s.status>=400&&s.status<500&&(t.status4xx+=1),s.status!==void 0&&s.status>=500&&(t.status5xx+=1),s.status!==void 0&&(t.lastStatus=s.status),s.error!==void 0&&(t.lastError=s.error),n}call(e,t){let s=Gt(t.host);if(!s)return!1;if(this.routing.fronts(s))return this.internal.set(s,(this.internal.get(s)??0)+1),!0;let n=Wh(e.context),r=Ln(t.startedAt)??e.timestamp,i=(Gt(t.method)??"GET").toUpperCase(),a=_s(Za(Gt(t.path)??"/")),o=Gt(n.projectName)??Gt(t.project)??"unknown",c=Ln(t.status),p=t.error===void 0||t.error===null?void 0:String(t.error),d=Ln(t.durationMs),h=this.hostOf(s,r);h.viaEgress=!0;let m=this.endpointOf(h,i,a,r),f=this.count(h,m,{at:r,service:o,...c!==void 0?{status:c}:{},...p!==void 0?{error:p}:{},...d!==void 0?{durationMs:d}:{}}),v=Gt(n.flowId),g=Gt(n.requestId),y=Gt(t.exchangeId),w={at:r,service:o,method:i,path:a,...c!==void 0?{status:c}:{},...p!==void 0?{error:p}:{},...d!==void 0?{durationMs:d}:{},...v?{flowId:v}:{},...y?{exchangeId:y}:{},...g?{requestId:g}:{}};Hh(h.recent,w,Cre),f&&Hh(h.failures,w,Ire);let b=Gt(n.runId)??g;if(b){let k=this.awaiting.get(b)??[];for(k.push({call:w,endpoint:m}),this.awaiting.set(b,k);this.awaiting.size>Dre;)this.awaiting.delete(this.awaiting.keys().next().value)}return!0}aiCall(e,t){let s=Gt(t.host);if(!s||this.routing.fronts(s))return!1;let n=Wh(e.context),r=Ln(t.startedAt)??e.timestamp,i=(Gt(t.method)??"POST").toUpperCase(),a=_s(Za(Gt(t.endpoint)??Gt(t.path)??"/")),o=this.hostOf(s,r),c=this.endpointOf(o,i,a,r);if(!o.viaEgress){let v=Ln(t.status),g=Ln(t.durationMs),y=Gt(n.projectName)??Gt(t.project)??"unknown";this.count(o,c,{at:r,service:y,...v!==void 0?{status:v}:{},...g!==void 0?{durationMs:g}:{}})}let p=Gt(t.model)??"unknown",d=Wh(t.usage),h=Ln(d.promptTokens),m=Ln(d.completionTokens),f=c.ai[p]??{model:p,calls:0,promptTokens:0,completionTokens:0,unmetered:0};return f.calls+=1,f.promptTokens+=h??0,f.completionTokens+=m??0,h===void 0&&m===void 0&&(f.unmetered+=1),c.ai[p]=f,!0}isSlow(e){return(e.outcomes[e.outcomes.length-1]?.ms??0)>=this.slowMs||e.outcomes.filter(t=>t.ms>=this.slowMs).length>=Qj}isFailing(e){return!!e.outcomes[e.outcomes.length-1]?.bad||e.outcomes.filter(t=>t.bad).length>=Qj}aiOf(e){let t=new Map;for(let s of e)for(let n of Object.values(s.ai)){let r=t.get(n.model)??{model:n.model,calls:0,promptTokens:0,completionTokens:0,unmetered:0};r.calls+=n.calls,r.promptTokens+=n.promptTokens,r.completionTokens+=n.completionTokens,r.unmetered+=n.unmetered,t.set(n.model,r)}return t.size?[...t.values()].sort((s,n)=>n.calls-s.calls):void 0}summary(e){let t=this.isFailing(e),s=!t&&this.isSlow(e),n=e.outcomes.length,r=t?`${e.outcomes.filter(c=>c.bad).length} of the last ${n} call${n===1?"":"s"} failed`:s?`${e.outcomes.filter(c=>c.ms>=this.slowMs).length} of the last ${n} call${n===1?"":"s"} took \u2265 ${_re(this.slowMs)}`:"healthy",i=El(e.samples,50),a=El(e.samples,95),o=this.aiOf(e.endpoints);return{host:e.host,services:[...e.services],health:t?"failing":s?"slow":"ok",verdict:r,calls:e.calls,failed:e.failed,...i!==void 0?{p50:i}:{},...a!==void 0?{p95:a}:{},maxMs:e.maxMs,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,endpoints:e.endpoints.length,...o?{ai:o}:{}}}endpointSummary(e){let t=El(e.samples,50),s=El(e.samples,95),n=this.aiOf([e]),r=e.samples.length?Math.round(e.samples.reduce((i,a)=>i+a,0)/e.samples.length*10)/10:void 0;return{id:e.id,host:e.host,method:e.method,path:e.path,services:[...e.services],routes:[...e.routes],calls:e.calls,failed:e.failed,status4xx:e.status4xx,status5xx:e.status5xx,...r!==void 0?{avgMs:r}:{},...t!==void 0?{p50:t}:{},...s!==void 0?{p95:s}:{},maxMs:e.maxMs,firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,...e.lastStatus!==void 0?{lastStatus:e.lastStatus}:{},...e.lastError!==void 0?{lastError:e.lastError}:{},...n?{ai:n}:{}}}payload(e){let t={failing:0,slow:1,ok:2},s=[...this.hosts.values()].filter(a=>!this.routing.fronts(a.host)),n=new Map(this.internal);for(let a of this.hosts.values())this.routing.fronts(a.host)&&n.set(a.host,(n.get(a.host)??0)+a.calls);let r=new Map(this.routing.known().map(a=>[a.host,a.services])),i;for(let a of s)(i===void 0||a.firstSeenAt<i)&&(i=a.firstSeenAt);return{at:e,hosts:s.map(a=>this.summary(a)).sort((a,o)=>t[a.health]-t[o.health]||(o.p95??0)-(a.p95??0)||o.calls-a.calls),endpoints:s.flatMap(a=>a.endpoints.map(o=>this.endpointSummary(o))).sort((a,o)=>o.lastSeenAt-a.lastSeenAt),gatewayHosts:[...n.entries()].map(([a,o])=>({host:a,services:r.get(a)??[],calls:o})).sort((a,o)=>o.calls-a.calls),slowMs:this.slowMs,...i!==void 0?{since:i}:{}}}detail(e){let t=this.hosts.get(e.trim().toLowerCase())??this.hosts.get(e.trim());if(!(!t||this.routing.fronts(t.host)))return{...this.summary(t),slowMs:this.slowMs,endpointList:t.endpoints.map(s=>this.endpointSummary(s)).sort((s,n)=>(n.p95??0)-(s.p95??0)||n.calls-s.calls),recent:[...t.recent].reverse(),failures:[...t.failures].reverse()}}callByExchange(e){for(let t of this.hosts.values()){let s=t.recent.find(n=>n.exchangeId===e)??t.failures.find(n=>n.exchangeId===e);if(s&&!this.routing.fronts(t.host))return{host:t.host,call:s}}}sameRequest(e){let t=new Map;for(let s of this.hosts.values())if(!this.routing.fronts(s.host))for(let n of[...s.recent,...s.failures])n.requestId===e&&t.set(`${s.host} ${n.at} ${n.method} ${n.path}`,{host:s.host,call:n});return[...t.values()].sort((s,n)=>s.call.at-n.call.at)}prune(e){let t=!1;for(let[s,n]of this.hosts){if(this.routing.fronts(s)){this.internal.set(s,(this.internal.get(s)??0)+n.calls),this.hosts.delete(s),this.index.delete(s),t=!0;continue}if(e-n.lastSeenAt>Xs){this.hosts.delete(s),this.index.delete(s),t=!0;continue}let r=n.endpoints.filter(i=>e-i.lastSeenAt<=Xs);r.length!==n.endpoints.length&&(n.endpoints=r,this.index.set(s,new Map(r.map(i=>[`${i.method} ${i.path}`,i]))),t=!0)}return t}toFile(e){return{version:1,savedAt:e,watermark:this.newest,hosts:[...this.hosts.values()],internal:Object.fromEntries(this.internal),routing:this.routing.toFile()}}},Bre=new Set(["SELECT","INSERT","UPDATE","DELETE","MERGE"]),Xj=6e4,eR=60,tR=/\b(?!pg_catalog\.|information_schema\.|pg_)([a-z_][a-z0-9_]*)\.([a-z_][a-z0-9_]*)\s*\(/i,Sl=u(e=>!e.test&&Bre.has(e.verb)&&(e.tables.length?e.tables.some(t=>!/^(pg_catalog\.|information_schema\.|pg_)/i.test(t)):/\bFROM\b/i.test(e.template)||tR.test(e.template)),"isAppStatement");function Gh(e){let t=(e.target??e.tables[0]??(e.template?tR.exec(e.template)?.[2]:void 0)??"statement").split(".").pop().replace(/_/g,"-").toLowerCase();return`${(e.services[0]??"app").replace(/[^\w.-]/g,"-")}.${e.verb.toLowerCase()}-${t}`}l(Gh,"su"),u(Gh,"suggestName");function Zh(e){let t=new Set(e.flatMap(n=>n.name?[n.name]:[])),s=new Map;for(let n of e.filter(r=>!r.name).sort((r,i)=>i.runs-r.runs||r.id.localeCompare(i.id))){let r=Gh(n),i=/\bWHERE\s+(?:"?\w+"?\.)?"?(\w+)"?/i.exec(n.template)?.[1]?.toLowerCase().replace(/_/g,"-"),a=i?`${r}-by-${i}`.slice(0,76):r,o=t.has(r)?a:r;for(let c=2;t.has(o);c++)o=`${a}-${c}`;t.add(o),s.set(n.id,o)}return s}l(Zh,"bc"),u(Zh,"suggestNames");var Vh='Name it where the code builds it, with a comment that comes first in the statement: /* <service>.<what-it-does> */ SELECT \u2026 (letters, digits and . - _ / :, 3 to 80 characters; TypeORM: .comment("<name>"); Kysely: sql`/* <name> */ \u2026`; raw SQL: the comment first). Keep the comment when you change the statement: the lens follows the statement by its name, so its next review knows what the last one asked for.';function sR(e,t,s,n=70){let{app:r,issues:i,names:a}=yk(e,t,n),o=i.filter(c=>c.severity==="error").length;return{at:s,warnBelow:n,errors:o,warnings:i.length-o,statements:r.length,named:r.filter(c=>c.name).length,issues:i.slice(0,eR),more:Math.max(0,i.length-eR),names:a}}l(sR,"yI"),u(sR,"sqlLint");var qre=u(e=>`db://lint/${e}`,"statementLintUri");function rR(e,t,s,n,r=70){let{issues:i,names:a}=yk(e,t,r),o=e.some(m=>m.id===s)?s:a.find(m=>m.name===s)?.current,c=o?e.find(m=>m.id===o):void 0;if(!c)return{at:n,asked:s,found:!1,ok:!1,issues:[],routes:[],next:`No statement "${s.slice(0,120)}" in catalog://sql \u2014 it appears once a service has run it; db://lint lists every statement's issues.`};let p=i.filter(m=>m.statement===c.id),d=t.get(c.id),h=!p.length&&!!c.name;return{at:n,asked:s,found:!0,statement:c.id,...c.name?{name:c.name}:{},verb:c.verb,tables:c.tables,services:c.services,ok:h,issues:p,...d?{review:{runId:d.runId,at:d.at,...d.overall!==void 0?{overall:d.overall}:{},...d.title?{title:d.title}:{},...d.top?{top:d.top}:{}}}:{},routes:c.routes,next:p[0]?.fix??(d?`Nothing to fix: its review scores ${d.overall??"\u2014"}. After a change, keep the name, run the code path, then review_sql { statement: "${c.name??c.id}", run: true }.`:`Named and not reviewed yet: review_sql { statement: "${c.name??c.id}", run: true } reviews it.`)}}l(rR,"vI"),u(rR,"statementLint");function gk(e){let t=e.sites?.[0];if(!t)return;let s=t.changed?" \u2014 the file changed since, find the function":t.exact?"":" \u2014 the line is approximate, find the function",n=(e.sites?.length??0)>1?` (and ${e.sites.length-1} more code path${e.sites.length===2?"":"s"})`:"";return`${t.at}${s}${n}`}l(gk,"Jz"),u(gk,"whereItRuns");var jre=u((e,t)=>e.length===t.length&&e.every(s=>t.includes(s)),"sameSet"),Rre=u((e,t)=>e.file===t.file&&(e.symbol!==void 0&&e.symbol===t.symbol||Math.abs(e.line-t.line)<=3),"samePlace");function vk(e){let t=e.filter(Sl),s=t.filter(r=>r.name),n=new Map;for(let r of t){if(r.name)continue;let i=s.filter(p=>p.firstSeenAt>r.firstSeenAt&&p.lastSeenAt>r.lastSeenAt&&r.lastSeenAt<=p.firstSeenAt+Xj),a=i.filter(p=>r.sites?.some(d=>p.sites?.some(h=>Rre(d,h)))),o=i.filter(p=>p.verb===r.verb&&jre(p.tables,r.tables)&&p.services.some(d=>r.services.includes(d))),c=(a.length?a:!r.sites?.length&&o.length===1?o:[]).sort((p,d)=>p.firstSeenAt-d.firstSeenAt)[0];c&&n.set(r.id,c.id)}return n}l(vk,"bI"),u(vk,"replacedUnnamed");function yk(e,t,s){let n=e.filter(Sl),r=[],i=Zh(n),a=u(f=>{let v=gk(f);return{statement:f.id,...f.name?{name:f.name}:{},verb:f.verb,tables:f.tables,services:f.services,routes:f.routes.slice(0,3),runs:f.runs,lastSeenAt:f.lastSeenAt,...v?{where:v,sites:f.sites.slice(0,3)}:{}}},"base"),o=u(f=>{let v=gk(f);return v?` It runs at ${v}.`:""},"at"),c=new Map,p=vk(n),d=new Map;for(let[f,v]of p)d.set(v,[...d.get(v)??[],f]);for(let f of n)if(!(!f.name&&p.has(f.id))){if(!f.name){let v=i.get(f.id)??Gh(f);r.push({severity:"error",rule:"unnamed-statement",...a(f),message:`This ${f.verb} on ${f.tables.join(", ")||"what it calls"} has no name, so it is not reviewed \u2014 and a change to it would look like a new statement.`,fix:`${Vh} For example /* ${v} */.${o(f)}`,suggestedName:v});continue}c.set(f.name,[...c.get(f.name)??[],f])}let h=[],m=[];for(let[f,v]of c){v.sort((k,$)=>k.firstSeenAt-$.firstSeenAt);let g=v[v.length-1],y=v.filter(k=>k===g||k.lastSeenAt>g.firstSeenAt+Xj);if(y.length>1)for(let k of y)r.push({severity:"error",rule:"name-reused",...a(k),message:`The name ${f} is on ${y.length} statements that run side by side (${y.map($=>$.id).join(", ")}).`,fix:`Give each statement its own name \u2014 a name follows one statement through its changes. ${Vh}${o(k)}`});m.push(...y);let w=t.get(g.id),b=[...v.filter(k=>!y.includes(k)).map(k=>k.id),...v.flatMap(k=>d.get(k.id)??[])];h.push({name:f,current:g.id,replaced:b,...w?.overall!==void 0?{overall:w.overall}:{}})}for(let f of m){let v=t.get(f.id);v?.overall===void 0||v.overall>=s||r.push({severity:"warning",rule:"review-below",...a(f),message:`Its SQL review scores ${v.overall} (under ${s})${v.top?` \u2014 first: ${v.top}`:""}.`,fix:`Read the review: review_sql { statement: "${f.id}" }.${o(f)} Fix what it asks for, keep the name comment, run the code path so the services run the new statement, then review_sql { statement: "${f.name}", run: true } \u2014 the new version is reviewed against what this one was asked.`,review:{runId:v.runId,at:v.at,overall:v.overall,...v.title?{title:v.title}:{},...v.top?{top:v.top}:{}}})}return r.sort((f,v)=>f.severity===v.severity?v.runs-f.runs:f.severity==="error"?-1:1),{app:n.filter(f=>!p.has(f.id)),issues:r,names:h.sort((f,v)=>f.name.localeCompare(v.name))}}l(yk,"Yz"),u(yk,"lintAll");import{readFileSync as Ore}from"node:fs";import{join as Nre}from"node:path";var Pre=["**/*.spec.*","**/*.int-spec.*","**/*.e2e-spec.*","**/*.e2e.*","**/*.api-e2e.*","**/*.story.*","**/*.test.*","**/__tests__/**","**/test/**","**/tests/**","**/e2e/**","**/*.fixture.*","**/fixtures/**","**/*.harness.*"];function nR(e){let t="";for(let s=0;s<e.length;s++){let n=e[s];n==="*"&&e[s+1]==="*"?e[s+2]==="/"?(t+="(?:.*/)?",s+=2):(t+=".*",s+=1):n==="*"?t+="[^/]*":n==="?"?t+="[^/]":t+=n.replace(/[.+^${}()|[\]\\]/g,"\\$&")}return new RegExp(`^${t}$`)}l(nR,"tF"),u(nR,"globToRegExp");function wk(e={}){let t=Array.isArray(e.paths)&&e.paths.every(n=>typeof n=="string")?e.paths:Pre,s=Array.isArray(e.listed)?e.listed.filter(n=>typeof n=="string"&&n.length>0):[];return{paths:t.map(nR),listed:new Set(s)}}l(wk,"cg"),u(wk,"testSqlRules");function iR(e,t=3e4,s=Date.now){let n;return()=>{let r=s();if(n&&r-n.at<t)return n.rules;let i;try{i=JSON.parse(Ore(Nre(e,"nx.json"),"utf8")).lensmcp}catch{i=void 0}return n={at:r,rules:wk({paths:i?.tests?.paths,listed:i?.sql?.test})},n.rules}}l(iR,"kI"),u(iR,"workspaceTestSqlRules");var Lre=/^test\./i;function aR(e,t){if(t.listed.has(e.id)||e.name&&t.listed.has(e.name))return{by:"listed",why:"nx.json \u2192 lensmcp.sql.test lists it"};if(e.name&&Lre.test(e.name))return{by:"name",why:`its name, ${e.name}, starts with test.`};let s=e.sites??[];if(s.length&&s.every(n=>t.paths.some(r=>r.test(n.file.replace(/^\.\//,"")))))return{by:"sites",why:`it runs only from test code \u2014 ${s[0].file}${s.length>1?` and ${s.length-1} more`:""}`}}l(aR,"SI"),u(aR,"testMarkOf");var bk,oR=0;function uR(e){bk=e,oR+=1}l(uR,"$I"),u(uR,"setSiteResolver");var Fre=3e4;function kk(e=Date.now()){return`${oR}:${bk?.generation?.()??0}:${Math.floor(e/Fre)}`}l(kk,"_I"),u(kk,"sitesEpoch");var Ure=3,zre=6,Wre=6;function lR(e){let t=e;if(!t||!Array.isArray(t.frames))return;let s=[];for(let n of t.frames)if(!(!n||typeof n.file!="string"||!n.file||typeof n.line!="number"||!Number.isFinite(n.line))&&(s.push({file:n.file.slice(0,1024),line:n.line,...typeof n.column=="number"&&Number.isFinite(n.column)?{column:n.column}:{},...typeof n.fn=="string"&&n.fn?{fn:n.fn.slice(0,200)}:{}}),s.length>=Ure))break;return s.length?{frames:s,mapped:t.mapped===!0}:void 0}l(lR,"EI"),u(lR,"readSite");var dR=u(e=>`${e.frames[0].file}:${e.frames[0].line}`,"keyOf");function cR(e,t,s,n){let r=dR(t),i=e.find(a=>dR(a)===r);if(!i){if(e.length>=zre){let a=0;for(let o=1;o<e.length;o++){let c=e[o],p=e[a];(c.seen<p.seen||c.seen===p.seen&&c.lastSeenAt<p.lastSeenAt)&&(a=o)}e.splice(a,1)}i={frames:t.frames,mapped:t.mapped,seen:0,lastSeenAt:s,services:[]},e.push(i)}i.seen+=1,t.frames.length>=i.frames.length&&(i.frames=t.frames),i.mapped=t.mapped,s>i.lastSeenAt&&(i.lastSeenAt=s),i.services.includes(n)||(i.services.push(n),i.services.length>Wre&&i.services.shift())}l(cR,"AI"),u(cR,"foldSite");var pR=u((e,t,s)=>{try{let n=bk?.({file:e.file,line:e.line,...e.column!==void 0?{column:e.column}:{},mapped:t,...s!==void 0?{seenAt:s}:{}});if(n)return n}catch{}return{file:e.file,line:e.line,exact:t}},"resolve");function hR(e){if(e?.length)return[...e].sort((t,s)=>s.seen-t.seen||s.lastSeenAt-t.lastSeenAt).map(t=>{let[s,...n]=t.frames,r=pR(s,t.mapped,t.lastSeenAt),i=s.fn??n.find(a=>a.fn)?.fn;return{at:`${r.file}:${r.line}${i?` (${i})`:""}`,file:r.file,line:r.line,...s.column!==void 0&&r.exact&&t.mapped?{column:s.column}:{},...i?{symbol:i}:{},exact:r.exact,...r.changed?{changed:!0}:{},...n.length?{via:n.map(a=>{let o=pR(a,t.mapped);return{file:o.file,line:o.line,...a.fn?{symbol:a.fn}:{}}})}:{},seen:t.seen,services:[...t.services],lastSeenAt:t.lastSeenAt}})}l(hR,"TI"),u(hR,"siteViews");var Hre=100,Gre=500,Zre=20,Vre=5,mR=10,Jre=4,Kre=500,Qre=8192,fR=5e3,Yre=50,Xre=400,ene=new Set(["BEGIN","START","COMMIT","END","ROLLBACK","SAVEPOINT","RELEASE","SET","RESET","SHOW","DEALLOCATE","DISCARD","LISTEN","UNLISTEN"]),gR=new Set(["INSERT","UPDATE","DELETE","MERGE","TRUNCATE","COPY","CREATE","ALTER","DROP"]),$k=u(e=>e&&typeof e=="object"?e:{},"obj"),Ke=u(e=>typeof e=="string"&&e?e:void 0,"str"),Al=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),vR=u(e=>e.split(".").pop()??e,"bare"),tne=u(e=>{let t=hR(e.sites);return t?{sites:t}:{}},"sitesOf");function Jh(e,t){if(e.length)return e[Math.min(e.length-1,Math.floor(t/100*e.length))]}l(Jh,"RI"),u(Jh,"percentile");var yR=new WeakMap;function xk(e){let t=yR.get(e);if(t&&t.runs===e.runs&&t.n===e.samples.length)return t.sorted;let s=[...e.samples].sort((n,r)=>n-r);return yR.set(e,{runs:e.runs,n:e.samples.length,sorted:s}),s}l(xk,"lF"),u(xk,"samplesInOrder");var Kh=u((e,t,s)=>{e.push(t),e.length>s&&e.splice(0,e.length-s)},"pushCapped"),sne=wk(),rne=class{static{l(this,"iu")}static{u(this,"SqlCatalog")}constructor(e,t,s,n,r=()=>sne){if(this.slowMs=s,this.loopAt=n,this.testRules=r,this.templates=new Map,this.perRequest=new Map,this.recentRequests=new Map,this.awaiting=new Map,this.findings=new Map,this.newest=0,this.version=0,this.revs=new WeakMap,this.summaries=new WeakMap,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1){for(let i of e.templates)t-i.lastSeenAt<=Xs&&this.templates.set(i.id,i);for(let i of e.findings??[]){let a=this.findings.get(i.tool)??[];a.push(i),this.findings.set(i.tool,a)}}}get size(){return this.templates.size}observe(e){if(e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp);let t=$k(e.raw),s=Ke(t.kind);return s==="db-query"?this.execution(e,t):s==="db-analyze-run"?this.analysis(e,t):!1}attribute(e,t){let s=this.awaiting.get(e);if(!s)return!1;this.awaiting.delete(e);for(let{exec:n,template:r}of s){this.touch(r),n.route=t;let i=r.routes.indexOf(t);i>=0&&r.routes.splice(i,1),r.routes.unshift(t),r.routes.length>mR&&(r.routes.length=mR)}return!0}execution(e,t){let s=Ke(t.statement),n=Ke(t.query),r=u((C,_)=>!!C&&!(C.length>=_&&C.endsWith("\u2026")),"uncut"),i=r(s,Qre)?s:r(n,Kre)?n:void 0,a=s??n;if(!a)return!1;let o=ts(a),c=o.verb==="QUERY"?(Ke(t.op)??"query").toUpperCase():o.verb;if(ene.has(c))return!1;let p=Ke(t.sqlId)??o.id,d=$k(e.context),h=Al(t.startedAt)??e.timestamp,m=this.templates.get(p);if(m)this.templates.delete(p);else{let C=Array.isArray(t.tables)?t.tables.filter(q=>typeof q=="string"):[],_=ok(Ke(t.table),a),N=o.tables.length?o.tables:C.length?C:_?[_]:[];m={id:p,template:o.template,statement:a,complete:!!i,verb:c,tables:N,...o.target?{target:o.target}:gR.has(c)&&N[0]?{target:N[0]}:{},...o.name??Ke(t.sqlName)?{name:o.name??Ke(t.sqlName)}:{},services:[],routes:[],runs:0,errors:0,totalMs:0,samples:[],maxMs:0,rowsTotal:0,rowsMax:0,perRequestMax:0,firstSeenAt:h,lastSeenAt:h,suppressed:0,executions:[],failures:[]}}if(this.templates.set(p,m),this.touch(m),this.templates.size>Gre){let C=this.templates.keys().next().value;this.templates.delete(C),this.recentRequests.delete(C)}let f=o.name??Ke(t.sqlName);f&&m.name!==f&&(m.name=f),i&&!m.complete&&(m.statement=i,m.complete=!0,m.template=o.template,o.tables.length&&(m.tables=o.tables),o.target&&(m.target=o.target));let v=Ke(d.projectName)??Ke(t.project)??"unknown",g=Al(t.durationMs),y=Al(t.rows),w=t.error===void 0||t.error===null?void 0:String(t.error);m.runs+=1,w!==void 0&&(m.errors+=1),g!==void 0&&(m.totalMs+=g,Kh(m.samples,g,Hre),g>m.maxMs&&(m.maxMs=g)),y!==void 0&&(m.rowsTotal+=y,y>m.rowsMax&&(m.rowsMax=y)),m.lastSeenAt=Math.max(m.lastSeenAt,h),m.suppressed+=Al(t.floodSuppressed)??0,m.services.includes(v)||m.services.push(v);let b=lR(t.site);b&&cR(m.sites??=[],b,h,v);let k=Ke(t.database);if(k){let C=(m.databases??[]).filter(_=>_!==k);m.databases=[k,...C].slice(0,Jre)}let $=Ke(t.server);$&&(m.server=$);let E=Array.isArray(t.params)?t.params.map(C=>String(C)):void 0,x=Ke(d.flowId),S=Ke(t.result),A={at:h,service:v,...g!==void 0?{durationMs:g}:{},...y!==void 0?{rows:y}:{},...E?{params:E}:{},...Ke(t.valuesId)?{valuesId:Ke(t.valuesId)}:{},...S?{result:S}:{},...w!==void 0?{error:w}:{},...x?{flowId:x}:{}};Kh(m.executions,A,Zre),w!==void 0&&Kh(m.failures,A,Vre);let I=Ke(d.runId)??Ke(d.requestId);if(I){let C=this.perRequest.get(I);if(!C)for(C=new Map,this.perRequest.set(I,C);this.perRequest.size>fR;)this.perRequest.delete(this.perRequest.keys().next().value);let _=(C.get(p)??0)+1;C.set(p,_);let N=this.recentRequests.get(p)??[],q=_>1?N.slice(-16).find(L=>L.key===I):void 0;q?q.n=_:(Kh(N,{key:I,n:_,at:h},Yre),this.recentRequests.set(p,N)),_>m.perRequestMax&&(m.perRequestMax=_,x?m.perRequestMaxFlow=x:delete m.perRequestMaxFlow);let M=this.awaiting.get(I)??[];for(M.push({exec:A,template:m}),this.awaiting.set(I,M);this.awaiting.size>fR;)this.awaiting.delete(this.awaiting.keys().next().value)}return!0}analysis(e,t){let s=Ke(t.tool)??Ke(t.project)??"analyzer",n=Al(t.runAt)??e.timestamp,r=[];for(let i of Array.isArray(t.findings)?t.findings:[]){let a=$k(i),o=Ke(a.table);if(!(!o||o.startsWith("("))&&(r.push({kind:Ke(a.kind)??"finding",table:o,detail:Ke(a.detail)??"",severity:Ke(a.severity)??"info",tool:s,at:n}),r.length>=Xre))break}return this.findings.set(s,r),this.version+=1,!0}findingsFor(e){let t=new Set(e.map(vR));return[...this.findings.values()].flat().filter(s=>t.has(vR(s.table)))}touch(e){this.revs.set(e,(this.revs.get(e)??0)+1),this.version+=1}summary(e){let t=this.testRules(),s=kk(),n=this.revs.get(e)??0,r=this.summaries.get(e);if(r&&r.rev===n&&r.epoch===s&&r.rules===t)return r.value;let i=this.summarize(e);return this.summaries.set(e,{rev:n,epoch:s,rules:t,value:i}),i}summarize(e){let t=xk(e),s=Jh(t,50),n=Jh(t,95),r=tne(e),i=aR({id:e.id,...e.name?{name:e.name}:{},...r},this.testRules());return{id:e.id,template:e.template,...e.name?{name:e.name}:{},verb:e.verb,tables:[...e.tables],...e.target?{target:e.target}:{},services:[...e.services],routes:[...e.routes],...e.databases?.length?{databases:[...e.databases]}:{},...e.server?{server:e.server}:{},runs:e.runs,errors:e.errors,totalMs:e.totalMs,...s!==void 0?{p50:s}:{},...n!==void 0?{p95:n}:{},maxMs:e.maxMs,rowsTotal:e.rowsTotal,rowsMax:e.rowsMax,perRequestMax:e.perRequestMax,...e.perRequestMaxFlow?{perRequestMaxFlow:e.perRequestMaxFlow}:{},firstSeenAt:e.firstSeenAt,lastSeenAt:e.lastSeenAt,suppressed:e.suppressed,complete:e.complete,...r,...i?{test:i}:{}}}payload(e,t=0){let s=this.testRules(),n=kk(),r=this.kept;if(r&&r.epoch===n&&r.rules===s&&(r.version===this.version||Date.now()-r.builtAt<t))return r.value.at===e?r.value:{...r.value,at:e};let i=this.build(e);return this.kept={version:this.version,epoch:n,rules:s,value:i,builtAt:Date.now()},i}build(e){let t=[...this.templates.values()],s=new Map;for(let i of t){let a=Jh(xk(i),95);for(let o of i.tables){let c=s.get(o)??{name:o,reads:0,writes:0,statements:0,services:[],findings:this.findingsFor([o]),lastSeenAt:0};gR.has(i.verb)&&(!i.target||i.target===o)?c.writes+=i.runs:c.reads+=i.runs,c.statements+=1;for(let p of i.services)c.services.includes(p)||c.services.push(p);for(let p of i.databases??[])(c.databases??=[]).includes(p)||c.databases.push(p);a!==void 0&&(c.slowestP95===void 0||a>c.slowestP95)&&(c.slowestP95=a),c.lastSeenAt=Math.max(c.lastSeenAt,i.lastSeenAt),s.set(o,c)}}let n;for(let[i,a]of this.findings){let o=a[0]?.at??0;(!n||o>n.at)&&(n={at:o,tool:i,findings:a.length})}let r;for(let i of t)(r===void 0||i.firstSeenAt<r)&&(r=i.firstSeenAt);return{at:e,templates:this.suggested(t.map(i=>this.summary(i))).sort((i,a)=>a.totalMs-i.totalMs||a.runs-i.runs),tables:[...s.values()].sort((i,a)=>a.reads+a.writes-(i.reads+i.writes)),slowMs:this.slowMs,loopAt:this.loopAt,...n?{analysis:n}:{},...r!==void 0?{since:r}:{}}}statements(){return[...this.templates.values()].map(e=>({id:e.id,statement:e.statement,complete:e.complete,verb:e.verb,tables:[...e.tables],...e.databases?.length?{databases:[...e.databases]}:{},params:Math.max(0,...e.executions.map(t=>t.params?.length??0))}))}suggested(e){let t=vk(e),s=Zh(e.filter(n=>Sl(n)&&!t.has(n.id)));return e.map(n=>t.has(n.id)?{...n,replacedBy:t.get(n.id)}:s.has(n.id)?{...n,suggestedName:s.get(n.id)}:n)}detail(e){let t=this.templates.get(e.trim());if(!t)return;let s=t.name?void 0:this.payload(Date.now()).templates.find(n=>n.id===t.id);return{...this.summary(t),...s?.suggestedName?{suggestedName:s.suggestedName}:{},...s?.replacedBy?{replacedBy:s.replacedBy}:{},statement:t.statement,executions:[...t.executions].reverse(),failures:[...t.failures].reverse(),findings:this.findingsFor(t.tables)}}requestsSince(e,t){if(!this.templates.has(e))return;let s=this.recentRequests.get(e)??[],n=s.filter(r=>r.at>=t);return{requests:n.length,max:n.reduce((r,i)=>Math.max(r,i.n),0),reaches:s.some(r=>r.at<t)}}recentRuns(e=200){let t=[];for(let s of this.templates.values())for(let n of s.executions)t.push({...n,id:s.id,verb:s.verb,template:s.template,tables:[...s.tables]});return t.sort((s,n)=>n.at-s.at).slice(0,e)}prune(e){let t=!1;for(let[s,n]of this.templates)e-n.lastSeenAt>Xs&&(this.templates.delete(s),this.recentRequests.delete(s),t=!0);return t&&(this.version+=1),t}toFile(e){return{version:1,savedAt:e,watermark:this.newest,templates:[...this.templates.values()],findings:[...this.findings.values()].flat()}}},nne=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;function Qh(e){return e.replace(nne,"*").replace(/(?<=^|[:=/])(?=[A-Za-z0-9_-]*\d)(?=[A-Za-z0-9_-]*[A-Za-z])[A-Za-z0-9_-]{16,}(?=$|[:=/])/g,"*").replace(/(?<![A-Za-z])(?=[0-9a-f]*\d)[0-9a-f]{8,}(?![A-Za-z])/gi,"*").replace(/(?<![A-Za-z0-9])\d{2,}(?![A-Za-z0-9])/g,"*").replace(/\*(?:[_-]?\*)+/g,"*")}l(Qh,"au"),u(Qh,"foldKeyPattern");function wR(e){let t={};for(let s of e.split(/\r?\n/)){let n=s.indexOf(":");n>0&&!s.startsWith("#")&&(t[s.slice(0,n)]=s.slice(n+1).trim())}return t}l(wR,"uF"),u(wR,"parseInfo");function bR(e){return Object.entries(e).filter(([t])=>/^db\d+$/.test(t)).map(([t,s])=>{let n=Object.fromEntries(s.split(",").map(r=>r.split("=")));return{db:Number(t.slice(2)),keys:Number(n.keys??0),expires:Number(n.expires??0)}}).sort((t,s)=>t.db-s.db)}l(bR,"pF"),u(bR,"keyspace");var Yh=Qh,ine=u(e=>Yh(e),"queueFamily"),Xh=4096,Cl=u((e,t)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,"clip"),ane=/(?<![A-Za-z0-9_\-+/])(?=[A-Za-z0-9_\-+/]*[a-z])(?=[A-Za-z0-9_\-+/]*[A-Z])(?=[A-Za-z0-9_\-+/]*\d)[A-Za-z0-9_\-+/]{32,}={0,2}(?![A-Za-z0-9_\-+/])/g,qi=u(e=>e.replace(ane,t=>`${t.slice(0,4)}\u2026${t.slice(-3)} \xB7 ${t.length} chars`),"maskTokens");function xs(e,t=Xh){let s=e.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{return Cl(qi(JSON.stringify(xn(JSON.parse(s)))),t)}catch{}return Cl(qi(one(kR(jt(e)))),t)}l(xs,"Rn"),u(xs,"maskValue");function kR(e){return e.replace(/\{[^{}]*\}|\[[^[\]]*\]/g,t=>{try{return JSON.stringify(xn(JSON.parse(t)))}catch{return t}})}l(kR,"ise"),u(kR,"maskJsonInText");var one=u(e=>e.replace(/(?<![\w.-])([\w.-]+)=([^\s&,;]+)/g,(t,s)=>Gs(s)?`${s}=${qt}`:t),"maskPairs"),Il=u((e,t,s=Xh)=>Gs(e)?qt:xs(t,s),"maskField"),une=new Set(["meta","id","events","wait","active","paused","delayed","prioritized","completed","failed","waiting-children","stalled","stalled-check","limiter","marker","pc","de","metrics","repeat","qe","lock"]);function Ek(e,t=new Set(["bull"])){let s=e.split(":");if(s.length!==3||!t.has(s[0]))return;let[n,r,i]=s;if(!(!r||!i||une.has(i)))return{prefix:n,queue:r,id:i}}l(Ek,"MI"),u(Ek,"jobOfKey");var Br=u(e=>e===void 0||e===""||Number.isNaN(Number(e))?void 0:Number(e),"num");function Sk(e,t,s,n){let r;try{r=s.opts?JSON.parse(s.opts):void 0}catch{r=void 0}let i=r?.__lensmcpFlow,a=typeof i=="string"?i:typeof i?.flowId=="string"?i.flowId:void 0,o;try{let p=s.stacktrace?JSON.parse(s.stacktrace):void 0;o=Array.isArray(p)?p.filter(d=>typeof d=="string").map(d=>Cl(jt(d),Xh)):void 0}catch{o=void 0}let c=typeof r?.attempts=="number"?r.attempts:void 0;return{queue:e,id:t,name:s.name??"",state:n,data:xs(s.data??""),...s.opts?{opts:xs(s.opts,1024)}:{},...Br(s.timestamp)!==void 0?{addedAt:Br(s.timestamp)}:{},...Br(s.processedOn)!==void 0?{processedAt:Br(s.processedOn)}:{},...Br(s.finishedOn)!==void 0?{finishedAt:Br(s.finishedOn)}:{},...Br(s.delay)?{delayMs:Br(s.delay)}:{},attemptsMade:Br(s.atm)??Br(s.attemptsMade)??0,...c!==void 0?{attemptsLimit:c}:{},...s.failedReason?{failedReason:Cl(jt(s.failedReason),Xh)}:{},...o?.length?{stacktrace:o}:{},...s.returnvalue!==void 0?{returnValue:xs(s.returnvalue,1024)}:{},...s.progress!==void 0&&s.progress!=="0"?{progress:Cl(s.progress,200)}:{},flowId:a??`job:${e}#${t}`}}l(Sk,"OI"),u(Sk,"bullJob");function cr(e){let t={};if(!Array.isArray(e))return t;for(let s=0;s+1<e.length;s+=2)t[String(e[s])]=String(e[s+1]);return t}l(cr,"Nr"),u(cr,"pairs");function Ak(e,t,s,n){let r=new Array(n).fill(0);if(!Array.isArray(e))return r;for(let i=1;i<e.length;i+=2){let a=Number(e[i]),o=Math.floor((a-t)/s);o>=0&&o<n&&(r[o]+=1)}return r}l(Ak,"CI"),u(Ak,"binScores");function $R(e,t,s){let n=`${t}:${Buffer.from(s).toString("base64")}`,r=0;for(let i of e.split(`
200
200
  `)){let a=/ name=(\S*)/.exec(` ${i}`)?.[1]??"";(a===n||a.startsWith(`${n}:w:`))&&r++}return r}l($R,"hF"),u($R,"workersOf");var lne=2e3,dne=20,cne=200,xR=10,pne=5e3,hne=new Set(["eval","evalsha","eval_ro","evalsha_ro","fcall","fcall_ro"]),ER=u(e=>e&&typeof e=="object"?e:{},"obj"),qr=u(e=>typeof e=="string"&&e?e:void 0,"str"),SR=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num");function Ck(e,t){if(!e.length)return;let s=[...e].sort((n,r)=>n-r);return s[Math.min(s.length-1,Math.floor(t/100*s.length))]}l(Ck,"yF"),u(Ck,"percentile");var AR=u((e,t,s)=>{e.push(t),e.length>s&&e.splice(0,e.length-s)},"pushCapped");function CR(e,t){let s=qr(e.key);if(s&&s!==qt)return s;let n=(qr(e.command)??"").split(" ");return(n[0]??"").toLowerCase()!==t.toLowerCase()?"":n[1]??""}l(CR,"mse"),u(CR,"keyOf");function IR(e,t){let s=e.toUpperCase();if(hne.has(e.toLowerCase())){let i=t.length>16?t.slice(0,12):t;return{id:`${s} ${i}`,pattern:i,script:!0}}let n=t.endsWith("\u2026")?`${t.slice(0,t.lastIndexOf(":")+1)}*`:t,r=qi(Yh(n));return{id:`${s} ${r}`,pattern:r,script:!1}}l(IR,"fse"),u(IR,"commandShape");var mne=class{static{l(this,"du")}static{u(this,"KvCommandCatalog")}constructor(e,t){if(this.shapes=new Map,this.awaiting=new Map,this.newest=0,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1)for(let s of e.shapes)t-s.lastSeenAt<=Xs&&this.shapes.set(s.id,s)}get size(){return this.shapes.size}observe(e){if(e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp);let t=ER(e.raw);if(qr(t.kind)!=="redis-op")return!1;let s=qr(t.op);if(!s)return!1;let n=CR(t,s),r=ER(e.context),i=SR(t.startedAt)??e.timestamp,{id:a,pattern:o,script:c}=IR(s,n),p=this.shapes.get(a);p?this.shapes.delete(a):p={id:a,op:s.toUpperCase(),pattern:o,...c?{script:!0}:{},runs:0,hits:0,misses:0,totalMs:0,maxMs:0,services:[],routes:[],firstSeenAt:i,lastSeenAt:i,sampleKey:qi(n),samples:[],runsKept:[]},this.shapes.set(a,p),this.shapes.size>lne&&this.shapes.delete(this.shapes.keys().next().value);let d=qr(r.projectName)??qr(t.project)??"unknown",h=SR(t.durationMs),m=t.hit===!0?"hit":t.hit===!1?"miss":void 0;p.runs+=1,m==="hit"&&(p.hits+=1),m==="miss"&&(p.misses+=1),h!==void 0&&(p.totalMs+=h,AR(p.samples,h,cne),h>p.maxMs&&(p.maxMs=h)),p.lastSeenAt=Math.max(p.lastSeenAt,i),p.sampleKey=qi(n)||p.sampleKey,p.services.includes(d)||p.services.push(d);let f=qr(r.flowId),v={shape:a,at:i,op:s.toUpperCase(),key:qi(n),command:xs(qr(t.command)??`${s.toUpperCase()} ${n}`,300),...m?{result:m}:{},...h!==void 0?{durationMs:h}:{},service:d,...f?{flowId:f}:{}};AR(p.runsKept,v,dne);let g=qr(r.runId)??qr(r.requestId);if(g){let y=this.awaiting.get(g)??[];y.push({run:v,shape:p}),this.awaiting.set(g,y),this.awaiting.size>pne&&this.awaiting.delete(this.awaiting.keys().next().value)}return!0}attribute(e,t){let s=this.awaiting.get(e);if(!s)return!1;this.awaiting.delete(e);for(let{run:n,shape:r}of s){n.route=t;let i=r.routes.indexOf(t);i>=0&&r.routes.splice(i,1),r.routes.unshift(t),r.routes.length>xR&&(r.routes.length=xR)}return!0}summary(e){let t=Ck(e.samples,50),s=Ck(e.samples,95),{samples:n,runsKept:r,...i}=e;return{...i,services:[...e.services],routes:[...e.routes],...t!==void 0?{p50:t}:{},...s!==void 0?{p95:s}:{}}}payload(e){let t=[...this.shapes.values()].map(n=>this.summary(n)).sort((n,r)=>r.runs-n.runs||r.lastSeenAt-n.lastSeenAt),s=t.reduce((n,r)=>n===void 0||r.firstSeenAt<n?r.firstSeenAt:n,void 0);return{at:e,shapes:t,...s!==void 0?{since:s}:{}}}recentRuns(e,t){return[...t?this.shapes.get(t)?.runsKept??[]:[...this.shapes.values()].flatMap(s=>s.runsKept)].sort((s,n)=>n.at-s.at).slice(0,e)}prune(e){let t=!1;for(let[s,n]of this.shapes)e-n.lastSeenAt>Xs&&(this.shapes.delete(s),t=!0);return t}toFile(e){return{version:1,savedAt:e,watermark:this.newest,shapes:[...this.shapes.values()]}}},fne=2e3,DR=10,TR=20,gne=5e3,vne=new Set(["read","write","append"]),Ik=u(e=>e&&typeof e=="object"?e:{},"obj"),Fn=u(e=>typeof e=="string"&&e?e:void 0,"str"),Dk=u(e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,"num"),yne=class{static{l(this,"lu")}static{u(this,"FileCatalog")}constructor(e,t){if(this.paths=new Map,this.awaiting=new Map,this.newest=0,this.replayedUpTo=e&&e.version===1?e.watermark:0,this.newest=this.replayedUpTo,e&&e.version===1)for(let s of e.paths)t-s.lastSeenAt<=Xs&&this.paths.set(s.id,s)}get size(){return this.paths.size}observe(e){if(e.timestamp<=this.replayedUpTo)return!1;e.timestamp>this.newest&&(this.newest=e.timestamp);let t=Ik(e.raw);if(Fn(t.kind)!=="fs-ops"||!Array.isArray(t.paths))return!1;let s=Fn(Ik(e.context).projectName)??Fn(t.project)??"unknown",n=!1;for(let r of t.paths){let i=Ik(r),a=Fn(i.path),o=Fn(i.op);if(!a||!o||!vne.has(o))continue;let c=Math.max(1,Dk(i.n)??1),p=Math.max(0,Dk(i.bytes)??0),d=Dk(i.at)??e.timestamp,h=`${s} ${o} ${a}`,m=this.paths.get(h);if(m?this.paths.delete(h):m={id:h,path:a,op:o,service:s,n:0,bytes:0,lastBytes:0,firstSeenAt:d,lastSeenAt:d,routes:[]},this.paths.set(h,m),this.paths.size>fne&&this.paths.delete(this.paths.keys().next().value),m.n+=c,m.bytes+=p,d>=m.lastSeenAt){m.lastSeenAt=d,m.lastBytes=Math.round(p/c);let y=Fn(i.flowId);y&&(m.flowId=y)}i.stream===!0&&(m.stream=!0);let f=Fn(i.requestId),v=Fn(i.flowId),g=m.uses??=[];if(g.unshift({at:d,n:c,bytes:p,...v?{flowId:v}:{},...f?{requestId:f}:{}}),g.length>1&&g[0].at<g[1].at&&g.sort((y,w)=>w.at-y.at),g.length>TR&&(g.length=TR),f){let y=this.awaiting.get(f)??[];y.includes(m)||y.push(m),this.awaiting.set(f,y),this.awaiting.size>gne&&this.awaiting.delete(this.awaiting.keys().next().value)}n=!0}return n}attribute(e,t){let s=this.awaiting.get(e);if(!s)return!1;this.awaiting.delete(e);for(let n of s){let r=n.routes.indexOf(t);r>=0&&n.routes.splice(r,1),n.routes.unshift(t),n.routes.length>DR&&(n.routes.length=DR)}return!0}payload(e){let t=[...this.paths.values()].map(n=>({...n,routes:[...n.routes],...n.uses?{uses:n.uses.map(r=>({...r}))}:{}})).sort((n,r)=>r.lastSeenAt-n.lastSeenAt),s=t.reduce((n,r)=>n===void 0||r.firstSeenAt<n?r.firstSeenAt:n,void 0);return{at:e,paths:t,...s!==void 0?{since:s}:{}}}prune(e){let t=!1;for(let[s,n]of this.paths)e-n.lastSeenAt>Xs&&(this.paths.delete(s),t=!0);return t}toFile(e){return{version:1,savedAt:e,watermark:this.newest,paths:[...this.paths.values()]}}};import{mkdirSync as wne,readFileSync as bne,renameSync as kne,writeFileSync as $ne}from"node:fs";import{dirname as _R,join as em}from"node:path";var xne=9e4;function MR(e=process.env,t=process.cwd()){let s=e.LENSMCP_EVENT_FILE??em(t,".lensmcp","events.jsonl");return em(_R(s),"catalog")}l(MR,"PI"),u(MR,"catalogDir");var Ene=u(e=>{try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}},"alive");function Tk(e){try{return JSON.parse(bne(e,"utf8"))}catch{return}}l(Tk,"SF"),u(Tk,"readJson");function _k(e,t){wne(_R(e),{recursive:!0});let s=`${e}.${process.pid}.tmp`;$ne(s,JSON.stringify(t),{mode:384}),kne(s,e)}l(_k,"LI"),u(_k,"writeJsonAtomic");function BR(e,t){return Tk(em(e,t))}l(BR,"xF"),u(BR,"readCatalogFile");function qR(e,t,s,n=process.pid,r=Ene){let i=em(e,"owner.json"),a=Tk(i),o=a?.pid===n;if(!(!a||o||!r(a.pid)||s-a.at>xne||t==="dashboard"&&a.role!=="dashboard"))return!1;try{return _k(i,{pid:n,role:t,at:s}),!0}catch{return!1}}l(qR,"qI"),u(qR,"claimWriter");var jR;function Mk(e){jR=e}l(Mk,"hg"),u(Mk,"setReviewDesk");function pt(){return jR}l(pt,"et"),u(pt,"reviewDesk");var Sne=["authorization","exposure","write_safety"],RR=new Set(["INSERT","UPDATE","DELETE","MERGE"]),Ane=/^(stack|stacktrace|stack_trace|trace)$/i,OR=80,Cne=u(e=>e?.split(".").pop()?.toLowerCase(),"bare");function tm(e,t=0){return!e||t>1?[]:e.t==="obj"?e.fields.flatMap(s=>[s.name,...tm(s,t+1)]):e.t==="any"?e.of.flatMap(s=>tm(s,t)):[]}l(tm,"DI"),u(tm,"fieldNames");function NR(e,t,s,n,r={}){let i=r.warnBelow??70,a=r.holeBelow??50,o=r.loopAt??5,c=t.filter(Sl),p=Zh(c),d=[],h=new Map;for(let g of c)for(let y of g.routes)(h.get(y)??h.set(y,[]).get(y)).push(g);let m=u((g,y={})=>({id:g.id,...g.name?{name:g.name}:{},verb:g.verb,tables:g.tables,db:qre(g.id),...y}),"statementOf");for(let g of e){let y={route:g.id,service:g.service,method:g.method,path:g.route,runs:g.runs,lastSeenAt:g.lastSeenAt},w=u(N=>d.push({...y,...N,check:N.check??N.statements?.map(q=>q.db)??[]}),"push"),b=[...h.get(g.id)??[]].sort((N,q)=>q.totalMs-N.totalMs),k=b.filter(N=>!N.name);k.length&&w({severity:"error",rule:"unnamed-sql",message:`It runs ${k.length===1?"a SQL statement":`${k.length} SQL statements`} without a name, so the SQL review cannot review ${k.length===1?"it":"them"} \u2014 and this route's review sees ${k.length===1?"it":"them"} unreviewed.`,fix:`Name each where the code builds it \u2014 each db:// link checks one and has a suggested name. ${Vh}`,statements:k.map(N=>m(N,{suggestedName:p.get(N.id)}))});let $=s.routes.get(g.id),E=u(N=>$?{review:{runId:$.runId,at:$.at,...$.overall!==void 0?{overall:$.overall}:{},...$.title?{title:$.title}:{},...$.top?{top:$.top}:{},...N?.length?{low:N}:{}}}:{},"reviewOf"),x=($?.indicators??[]).filter(N=>Sne.includes(N.id)&&N.score!==null&&N.score<a);$&&x.length?w({severity:"error",rule:"review-hole",message:`Its route review (${new Date($.at).toISOString().slice(0,10)}) found a hole: ${x.map(N=>`${N.id.replace("_"," ")} ${N.score}`).join(", ")} (under ${a})${$.top?` \u2014 first: ${$.top}`:""}.`,fix:`Read it: review_route { route: "${g.id}" }. Fix what it asks for under ${x.map(N=>N.id).join(" and ")}, run the endpoint so its service answers it again, then review_route { route: "${g.id}", run: true }.`,...E(x)}):$?.overall!==void 0&&$.overall<i&&w({severity:"warning",rule:"review-below",message:`Its route review scores ${$.overall} (under ${i})${$.top?` \u2014 first: ${$.top}`:""}.`,fix:`Read it: review_route { route: "${g.id}" }. Fix what it asks for, run the endpoint, then review_route { route: "${g.id}", run: true }.`,...E()});let S=Object.keys(g.contract?.request.query??{}).filter(Gs);S.length&&w({severity:"error",rule:"credential-in-url",message:`Its requests carry ${S.map(N=>`\`${N}\``).join(", ")} in the query string \u2014 a credential in a URL is kept by every access log, proxy and browser history.`,fix:"Take it from a header (Authorization) or the body, and refuse it in the query."});let A=Object.entries(g.contract?.responses??{}).filter(([N,q])=>Number(N)>=400&&tm(q.body).some(M=>Ane.test(M))).map(([N])=>N);A.length&&w({severity:"error",rule:"stack-in-error",message:`Its ${A.join(", ")} answers carry a stack trace in the body \u2014 internals reach the client.`,fix:"Answer failures as one problem format (RFC 9457 problem details) from a single exception filter: log the stack with the request id, never send it."});let I=b.filter(N=>N.name&&(s.sql.get(N.id)?.overall??100)<i);I.length&&w({severity:"warning",rule:"sql-review-below",message:`${I.length===1?"A statement it runs has":`${I.length} statements it runs have`} a SQL review under ${i}: ${I.map(N=>`${N.name} ${s.sql.get(N.id).overall}`).join(", ")}.`,fix:'Each db:// link has its issue and its review; fix what that review asks for, keep the name, run this route, then review_sql { statement: "<name>", run: true }.',statements:I.map(N=>m(N,{overall:s.sql.get(N.id).overall}))});let C=new Map;for(let N of g.recent)for(let[q,M]of Object.entries(N.touches))q.startsWith("sql:")&&M>(C.get(q)??0)&&C.set(q,M);let _=[...C].filter(([,N])=>N>=o).sort((N,q)=>q[1]-N[1]);if(_.length){let N=_.flatMap(([q,M])=>{let[L,H]=q.slice(4).split(" ");return b.filter(W=>W.verb===L&&Cne(W.target??W.tables[0])===H?.toLowerCase()).map(W=>m(W,{perRequest:M}))});w({severity:"warning",rule:"sql-loop",message:`One request runs ${_.map(([q,M])=>`${q.slice(4)} \xD7${M}`).join(", ")} \u2014 a statement per item.`,fix:`Load them with one statement (IN, a JOIN, a batch loader) per request.${N.length?" Each db:// link has the statement and its review.":""}`,...N.length?{statements:N}:{}})}if(g.method==="GET"||g.method==="HEAD"){let N=[...C.keys()].filter(q=>RR.has(q.slice(4).split(" ")[0]));if(N.length){let q=b.filter(M=>RR.has(M.verb)).map(M=>m(M));w({severity:"warning",rule:"get-writes",message:`A ${g.method} that writes: its runs ran ${N.map(M=>M.slice(4)).join(", ")}. Clients, caches and prefetchers repeat a ${g.method} freely.`,fix:`Move the write to a POST, PUT or PATCH \u2014 or, when it is a side record the read does not depend on (an audit row, a last-seen time), keep it and tell the route review so: review_remember { analyzer: "route.endpoint", subject: "${g.id}", text: "\u2026" }.`,...q.length?{statements:q}:{}})}}}d.sort((g,y)=>g.severity===y.severity?y.runs-g.runs:g.severity==="error"?-1:1);let f=d.filter(g=>g.severity==="error").length,v={};for(let g of d){let y=v[g.route]??={errors:0,warnings:0};g.severity==="error"?y.errors++:y.warnings++}return{at:n,warnBelow:i,holeBelow:a,loopAt:o,errors:f,warnings:d.length-f,routes:e.length,reviewed:e.filter(g=>s.routes.has(g.id)).length,issues:d.slice(0,OR),more:Math.max(0,d.length-OR),byRoute:v}}l(NR,"UI"),u(NR,"routeLint");var Ine=new Set(["get","mget","hget","hmget","hgetall","hkeys","hvals","hexists","hlen","exists","ttl","pttl","type","strlen","smembers","sismember","smismember","scard","srandmember","sscan","hscan","zscan","zrange","zrangebyscore","zrevrange","zrevrangebyscore","zscore","zcard","zcount","zrank","lrange","lindex","llen","xrange","xrevrange","xlen","xread","scan"]),PR=new Set(["incr","incrby","incrbyfloat","decr","decrby","hincrby","hincrbyfloat","zincrby"]),Dne=new Set(["expire","pexpire","expireat","pexpireat","hexpire","hpexpire"]),Tne=new Set(["del","unlink","getdel","hdel","srem","zrem","lrem","ltrim","xtrim","xdel","zremrangebyscore","zremrangebyrank","lpop","rpop","spop","zpopmin","zpopmax"]),_ne=new Set(["set","setex","psetex","setnx","getset","getex","mset","msetnx"]);function jr(e){let t=e.toLowerCase();return t==="persist"?"persist":/^(eval|evalsha|fcall)/.test(t)?"script":Ine.has(t)?"read":PR.has(t)?"incr":Dne.has(t)?"expire":Tne.has(t)?"delete":"write"}l(jr,"er"),u(jr,"kvAccessOf");function Xa(e){let t=e.trim().split(/\s+/),s=(t[0]??"").toLowerCase();if(s==="setex"||s==="psetex")return"set";let n=t.slice(1).map(r=>r.toUpperCase());return n.includes("KEEPTTL")?"kept":n.some(r=>r==="EX"||r==="PX"||r==="EXAT"||r==="PXAT")?"set":"none"}l(Xa,"zs"),u(Xa,"kvExpiryOf");var Mne=u(e=>_ne.has(e.toLowerCase()),"isStringWrite"),Bne=["exposure","correctness"],qne=/…\S* · \d+ chars/,jne=/[^\s:@/]+@[^\s:@/]+\.[a-z]{2,}/i,Rne=/…\((\d+(?:\.\d+)?)kb\)/g,One=512*1024,LR=80,FR=u((e,t,s=`${t}s`)=>`${e.toLocaleString("en-US")} ${e===1?t:s}`,"plural");function sm(e,t,s,n,r,i={}){let a=i.warnBelow??70,o=i.holeBelow??50,c=new Map;for(let f of e)f.script||!f.pattern||f.pattern.startsWith("bull:")||f.pattern.startsWith("{bull")||c.set(f.pattern,[...c.get(f.pattern)??[],f]);let p=[];for(let[f,v]of c){let g=[...new Set(v.map(U=>U.op.toUpperCase()))],y={pattern:f,ops:g,runs:v.reduce((U,fe)=>U+fe.runs,0),services:[...new Set(v.flatMap(U=>U.services))],lastSeenAt:Math.max(...v.map(U=>U.lastSeenAt))},w=`review_cache { pattern: "${f}" }`,b=u(U=>p.push({...y,...U,check:U.check??[w]}),"push"),k=u(U=>v.some(fe=>jr(fe.op)===U),"has"),$=v.flatMap(U=>t(U.id)),E=$.filter(U=>Mne(U.op)),x=E.filter(U=>Xa(U.command)!=="none"),S=s?.get(f),A=S?.described?S.noExpiry===S.described:void 0,I=S?.gone||(S?.described?(S.noExpiry??0)<S.described:!1);qne.test(f)&&b({severity:"error",rule:"secret-in-key",message:"Its key names carry a token \u2014 a credential in a key name is kept by every log, MONITOR and SCAN, and cannot be masked.",fix:"Key it by a stable id (a user or session id, or a hash of the token), and keep the token in the value with a short expiry."}),v.some(U=>jne.test(U.sampleKey))&&b({severity:"warning",rule:"personal-data-in-key",message:"Its key names hold an email address \u2014 personal data in a key name shows in every SCAN, log and dashboard.",fix:"Key it by the user's id (or a hash of the address); keep the address in the value if it is needed."});let C=n.get(f),_=u(U=>C?{review:{runId:C.runId,at:C.at,...C.overall!==void 0?{overall:C.overall}:{},...C.title?{title:C.title}:{},...C.top?{top:C.top}:{},...U?.length?{low:U}:{}}}:{},"reviewOf"),N=(C?.indicators??[]).filter(U=>Bne.includes(U.id)&&U.score!==null&&U.score<o);if(C&&N.length?b({severity:"error",rule:"review-hole",message:`Its cache review (${new Date(C.at).toISOString().slice(0,10)}) found a hole: ${N.map(U=>`${U.id} ${U.score}`).join(", ")} (under ${o})${C.top?` \u2014 first: ${C.top}`:""}.`,fix:`Read it: ${w}. Fix what it asks for, let the services run the new code, then review_cache { pattern: "${f}", run: true }.`,..._(N)}):C?.overall!==void 0&&C.overall<a&&b({severity:"warning",rule:"review-below",message:`Its cache review scores ${C.overall} (under ${a})${C.top?` \u2014 first: ${C.top}`:""}.`,fix:`Read it: ${w}. Fix what it asks for, then review_cache { pattern: "${f}", run: true }.`,..._()}),k("incr")&&!k("expire")&&!k("delete")&&!x.length&&!I){let U=(S?.keys??0)>=1e3;b({severity:U&&A?"error":"warning",rule:"counter-unbounded",message:`Its counters are incremented (${g.filter(fe=>PR.has(fe.toLowerCase())).join(", ")}) and nothing expires or deletes them${S?.partial?" \u2014 none of its keys was found in a scan that stopped early, so whether they expire is unknown":S?` \u2014 ${FR(S.keys,"key")} of it in the sample${A?", none of those read expiring":""}`:""}. A counter per time window or per id that is never removed grows the store for ever.`,fix:"Give each counter an expiry when it is created (INCR then EXPIRE \u2026 NX in one MULTI or pipeline, or a script), sized to how long its window is read; or delete it once read.",check:[w,`the keys: Data \u203A Key-value \u203A Keys, ${f}`]})}v.some(U=>U.op.toLowerCase()==="get"||U.op.toLowerCase()==="mget")&&E.length&&!x.length&&!k("expire")&&A!==!1&&b({severity:"warning",rule:"no-expiry",message:`Written whole and read with GET, and none of its writes${A?" or keys read":""} expires \u2014 temporary data that is never let go.`,fix:`Write it with an expiry (SET \u2026 EX <seconds>) sized to how stale it may be \u2014 or, when it is durable state, say so to the cache review (review_remember { analyzer: "cache.redis", subject: "${f}", text: "\u2026" }).`}),x.length&&x.length<E.length&&b({severity:"warning",rule:"ttl-dropped",message:`${FR(E.length-x.length,"write")} of its latest ${E.length} set no expiry, beside ${x.length} that do \u2014 a plain SET removes a key's TTL.`,fix:"Pass the expiry on every write (SET \u2026 EX, or KEEPTTL to keep the one it has)."}),k("persist")&&b({severity:"warning",rule:"persist",message:"PERSIST removes its keys' expiry.",fix:"Make sure the key is meant to live for ever; otherwise drop the PERSIST."});let q=Math.max(0,...$.flatMap(U=>[...U.command.matchAll(Rne)].map(fe=>Number(fe[1])*1024))),M=Math.max(q,S?.maxBytes??0);M>=One&&b({severity:"warning",rule:"oversized-value",message:`Its values reach ${(M/1048576).toFixed(1)} MB \u2014 every read moves all of it, and a large key blocks the server while it is written or freed.`,fix:"Store less (only what readers need), split it (a hash read by field), or compress it."});let L=v.filter(U=>U.op.toLowerCase()==="get"),H=L.reduce((U,fe)=>U+fe.hits,0),W=L.reduce((U,fe)=>U+fe.misses,0);H+W>=50&&H/(H+W)<.2&&b({severity:"warning",rule:"miss-heavy",message:`Its GETs rarely hit: ${H.toLocaleString("en-US")} of ${(H+W).toLocaleString("en-US")} (${Math.round(100*H/(H+W))}%). As a cache it costs a round trip and saves nothing; as a flag that exists only once set (a tombstone, a lock), a miss is the usual answer.`,fix:`If it is a cache: fill it after a miss (read-through), keep it longer, or stop looking it up where it is never there. If it is a flag, tell the cache review so (review_remember { analyzer: "cache.redis", subject: "${f}", text: "a flag: a miss is the normal answer" }).`})}p.sort((f,v)=>f.severity===v.severity?v.runs-f.runs:f.severity==="error"?-1:1);let d=p.filter(f=>f.severity==="error").length,h={};for(let f of p){let v=h[f.pattern]??={errors:0,warnings:0};f.severity==="error"?v.errors++:v.warnings++}let m={};for(let f of c.keys()){let v=n.get(f);v&&(m[f]={runId:v.runId,at:v.at,...v.overall!==void 0?{overall:v.overall,warning:v.overall<a}:{}})}return{at:r,warnBelow:a,holeBelow:o,errors:d,warnings:p.length-d,families:c.size,reviewed:Object.keys(m).length,keysRead:!!s,issues:p.slice(0,LR),more:Math.max(0,p.length-LR),byPattern:h,reviews:m,...i.unread?{unread:i.unread}:{}}}l(sm,"uu"),u(sm,"kvLint");var Nne=["reliability"];function UR(e){let t=e??"",s=/"attempts":\s*(\d+)/.exec(t)?.[1],n=u(r=>new RegExp(`"${r}":\\s*(?!false|null|0[,}])`).test(t),"set");return{...s?{attempts:Number(s)}:{},backoff:n("backoff"),removeOnComplete:n("removeOnComplete"),removeOnFail:n("removeOnFail")}}l(UR,"qse"),u(UR,"options");var Pne=u((e,t)=>e.reduce((s,n)=>s+n.counts[t],0),"sum");function zR(e,t,s,n={}){let r=n.warnBelow??70,i=n.holeBelow??50,a=[],o={};for(let d of e){if(!d.queues.length)continue;let h=[...d.queues].sort((q,M)=>Object.values(M.counts).reduce((L,H)=>L+H,0)-Object.values(q.counts).reduce((L,H)=>L+H,0))[0],m=`${d.store}/${d.db}/${h.name}`,f=Object.fromEntries(Object.keys(h.counts).map(q=>[q,Pne(d.queues,q)])),v=d.queues.reduce((q,M)=>q+M.workers,0),g={queue:m,name:h.name,family:h.family,queues:d.queues.length,counts:f,workers:v},y=`review_queue { queue: "${m}" }`,w=u(q=>a.push({...g,...q,check:q.check??[y]}),"push"),b=d.queues.length>1?`the ${h.family} queues (${d.queues.length})`:h.name;d.policy&&d.policy!=="noeviction"&&w({severity:"error",rule:"eviction",message:`Its store ${d.store} evicts (maxmemory-policy ${d.policy}): under memory pressure Redis may drop a queue's keys, and BullMQ cannot run on half a queue.`,fix:"Set maxmemory-policy noeviction on the store that holds the queues (or move them to one that has it), and give it a maxmemory with headroom.",check:[y,`/api/kv/stores \u2014 ${d.store}'s policy`]});let k=f.waiting+f.prioritized;k>0&&v===0&&!d.queues.some(q=>q.paused)&&w({severity:"error",rule:"no-worker",message:`${k.toLocaleString("en-US")} jobs are waiting in ${b} and no worker is connected to it.`,fix:"Start its worker (or check that the worker uses the same connection, database and prefix as the producer)."});let $=(d.jobs??[]).map(q=>UR(q.opts)),E=f.failed/Math.max(1,f.failed+f.completed),x=$.length>0&&$.every(q=>(q.attempts??1)<=1);f.failed>=5&&E>=.1&&x?w({severity:"error",rule:"failing-no-retry",message:`${Math.round(E*100)}% of the jobs ${b} keeps have failed (${f.failed.toLocaleString("en-US")} of ${(f.failed+f.completed).toLocaleString("en-US")}), and none of the ${$.length} jobs read retries (attempts 1).${d.detail?.events.failures[0]?` The commonest failure: ${d.detail.events.failures[0].reason}.`:""}`,fix:"Give its jobs attempts with an exponential backoff (and jitter) for the failures that pass \u2014 a dependency busy, a timeout \u2014 and fail at once on those that never will (UnrecoverableError)."}):$.length&&$.filter(q=>(q.attempts??1)>1&&!q.backoff).length>=Math.ceil($.length/2)&&w({severity:"warning",rule:"no-backoff",message:`Its jobs retry with no backoff (attempts ${Math.max(...$.map(q=>q.attempts??1))}, backoff not set) \u2014 a failing dependency is hit again at once, every attempt.`,fix:"Add backoff: { type: 'exponential', delay: <ms> } (and jitter) so retries spread out."});for(let q of d.queues){let M=t.get(`${d.store}/${d.db}/${q.name}`);M&&(o[`${d.store}/${d.db}/${q.name}`]={runId:M.runId,at:M.at,...M.overall!==void 0?{overall:M.overall,warning:M.overall<r}:{}})}let S=t.get(m),A=u(q=>S?{review:{runId:S.runId,at:S.at,...S.overall!==void 0?{overall:S.overall}:{},...S.title?{title:S.title}:{},...S.top?{top:S.top}:{},...q?.length?{low:q}:{}}}:{},"reviewOf"),I=(S?.indicators??[]).filter(q=>Nne.includes(q.id)&&q.score!==null&&q.score<i);if(S&&I.length?w({severity:"error",rule:"review-hole",message:`Its queue review (${new Date(S.at).toISOString().slice(0,10)}) scores failures and retries ${I[0].score} (under ${i})${S.top?` \u2014 first: ${S.top}`:""}.`,fix:`Read it: ${y}. Change what it asks for, let new jobs run, then review_queue { queue: "${m}", run: true }.`,...A(I)}):S?.overall!==void 0&&S.overall<r&&w({severity:"warning",rule:"review-below",message:`Its queue review scores ${S.overall} (under ${r})${S.top?` \u2014 first: ${S.top}`:""}.`,fix:`Read it: ${y}. Change what it asks for, then review_queue { queue: "${m}", run: true }.`,...A()}),$.length){let q=!$.some(H=>H.removeOnComplete),M=!$.some(H=>H.removeOnFail),L=[q&&f.completed>=1e3?`${f.completed.toLocaleString("en-US")} completed`:"",M&&f.failed>=1e3?`${f.failed.toLocaleString("en-US")} failed`:""].filter(Boolean);L.length&&w({severity:"warning",rule:"retention-unbounded",message:`It keeps every finished job \u2014 ${L.join(" and ")} now, none of the jobs read sets ${[q?"removeOnComplete":"",M?"removeOnFail":""].filter(Boolean).join(" or ")}. Each one is a hash in Redis, for ever.`,fix:"Set removeOnComplete and removeOnFail ({ age: <seconds>, count: <n> }) to what you need for debugging and history."})}let C=(d.detail?.schedulers??[]).filter(q=>q.next!==void 0&&s-q.next>6e4);C.length&&w({severity:"warning",rule:"schedule-late",message:`${C.length===1?"A job scheduler is":`${C.length} job schedulers are`} past due: ${C.slice(0,3).map(q=>`${q.name??q.id} (${q.pattern??(q.every?`every ${q.every} ms`:"?")}) was due ${Math.round((s-q.next)/6e4)} min ago`).join("; ")} \u2014 no worker is running its runs.`,fix:"Check that a worker for the queue is running; a scheduler only creates the next job when one is processed."});let _=d.detail?.events.counts.stalled??0;_&&w({severity:"warning",rule:"stalls",message:`${_.toLocaleString("en-US")} stalled job${_===1?"":"s"} in its newest ${d.detail.events.read.toLocaleString("en-US")} events \u2014 a worker lost a job's lock (it blocked the event loop, crashed, or lost its connection).`,fix:"Keep the processor from blocking the event loop (move CPU work to a sandboxed processor or a child process), and give long jobs a lockDuration that fits."});let N=d.detail?.events.counts["retries-exhausted"]??0;N&&!a.some(q=>q.queue===m&&q.rule==="failing-no-retry")&&w({severity:"warning",rule:"retries-exhausted",message:`${N.toLocaleString("en-US")} job${N===1?"":"s"} used every attempt and failed for good, in its newest ${d.detail.events.read.toLocaleString("en-US")} events${d.detail.events.failures[0]?` \u2014 the commonest: ${d.detail.events.failures[0].reason}`:""}.`,fix:"Read the failures (Data \u203A Queues \u203A Jobs, Failed): retry what passes with a backoff, fail at once what never will."}),d.queues.some(q=>q.paused)&&k>0&&w({severity:"warning",rule:"paused-backlog",message:`It is paused with ${k.toLocaleString("en-US")} jobs waiting.`,fix:"Resume it when the pause is over (queue.resume()), or say why it is paused."})}a.sort((d,h)=>d.severity===h.severity?h.counts.failed+h.counts.waiting-(d.counts.failed+d.counts.waiting):d.severity==="error"?-1:1);let c=a.filter(d=>d.severity==="error").length,p={};for(let d of a)for(let h of new Set([d.queue,`${d.queue.slice(0,d.queue.lastIndexOf("/")+1)}${d.family}`])){let m=p[h]??={errors:0,warnings:0};d.severity==="error"?m.errors++:m.warnings++}return{at:s,warnBelow:r,holeBelow:i,errors:c,warnings:a.length-c,families:e.filter(d=>d.queues.length).length,reviewed:Object.keys(o).length,issues:a.slice(0,80),more:Math.max(0,a.length-80),byQueue:p,reviews:o,...n.unread?.length?{unread:n.unread}:{}}}l(zR,"zI"),u(zR,"queuesLint");import{readFileSync as WR}from"node:fs";import{join as Dl}from"node:path";var Lne=/^[A-Za-z0-9_-]+$/,Fne=new Set(["kind","url","databases","lens","run"]);function Bk(e){let t;try{t=JSON.parse(WR(Dl(e,"nx.json"),"utf8"))}catch{return{stores:{},errors:[],notes:[]}}let s=t?.lensmcp?.stores;return s===void 0?{stores:{},errors:[],notes:[]}:HR(s)}l(Bk,"mg"),u(Bk,"readStoresDecl");function HR(e){let t=[],s=[],n={};if(!e||typeof e!="object"||Array.isArray(e))return{stores:n,errors:["`lensmcp.stores` must be an object"],notes:s};for(let[r,i]of Object.entries(e)){let a=`stores.${r}`;if(!Lne.test(r)){t.push(`${a}: a store name is letters, digits, '-' and '_'`);continue}if(!i||typeof i!="object"||Array.isArray(i)){t.push(`${a}: must be an object`);continue}let o=i,c=o.kind;if(c!=="postgres"&&c!=="redis"){t.push(`${a}.kind: one of "postgres", "redis"`);continue}let p=typeof o.url=="string"?o.url.trim():"";if(!p){t.push(`${a}.url: the connection URL is required (e.g. "\${${c==="postgres"?"PG_URL":"REDIS_URL"}}")`);continue}let d=o.databases??[];if(!Array.isArray(d)||!d.every(f=>typeof f=="string"&&f.trim())){t.push(`${a}.databases: a list of URLs or database names`);continue}if(d.length&&c!=="postgres"){t.push(`${a}.databases: only a postgres store has databases`);continue}let h=o.lens??{};if(!h||typeof h!="object"||Array.isArray(h)){t.push(`${a}.lens: must be an object`);continue}let m=h;if(m.url!==void 0&&(typeof m.url!="string"||!m.url.trim())){t.push(`${a}.lens.url: a connection URL`);continue}if(m.read!==void 0&&typeof m.read!="boolean"){t.push(`${a}.lens.read: true or false`);continue}if(m.prepare!==void 0&&typeof m.prepare!="boolean"){t.push(`${a}.lens.prepare: true or false`);continue}o.run!==void 0&&s.push(`${a}.run: planned \u2014 lensmcp does not start stores yet; the store is used as declared`);for(let f of Object.keys(o))Fne.has(f)||s.push(`${a}.${f}: not a store setting \u2014 ignored`);n[r]={kind:c,url:p,databases:d.map(f=>f.trim()),lens:{...typeof m.url=="string"?{url:m.url.trim()}:{},read:m.read!==!1,prepare:m.prepare!==!1}}}return{stores:n,errors:t,notes:s}}l(HR,"Fse"),u(HR,"validateStoresDecl");function GR(e,t={}){let s={},n=u(r=>r.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g,(i,a)=>s[a]??t[a]??""),"expand");for(let r of e.split(/\r?\n/)){let i=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/.exec(r);if(!i)continue;let a=i[1],o=i[2];o.startsWith("'")&&o.indexOf("'",1)>0?s[a]=o.slice(1,o.indexOf("'",1)):o.startsWith('"')&&o.indexOf('"',1)>0?s[a]=n(o.slice(1,o.indexOf('"',1)).replace(/\\n/g,`