@lensmcp/cluster 1.25.3 → 1.25.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,10 @@
1
1
  export interface WorkerEntryPoint {
2
2
  name: string;
3
3
  entryPath: string;
4
+ /** This worker's own environment, merged over the devserver's. Pods never see it. */
5
+ env?: Record<string, string | number | boolean>;
6
+ /** The PORT it is given — 0 (a free one, the default), never the devserver's own. */
7
+ port?: number;
4
8
  }
5
9
 
6
10
  export interface NodeExternalsConfig {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "workers": {
42
42
  "type": "array",
43
- "description": "Worker entry points. Each produces a separate [name].js bundle compiled alongside the main entry in watch mode.",
43
+ "description": "Worker entry points. Each produces a separate [name].js bundle compiled alongside the main entry in watch mode, and runs as its own process beside the pods: started again when it crashes (the wait doubles with each crash in a row, up to 60 s), replaced on every build, stopped with its devserver, and shown on the lens (Cluster page, observe_current_status).",
44
44
  "items": {
45
45
  "type": "object",
46
46
  "properties": {
@@ -51,6 +51,19 @@
51
51
  "entryPath": {
52
52
  "type": "string",
53
53
  "description": "Path to the worker entry file. './' paths are relative to project root, otherwise relative to workspace root."
54
+ },
55
+ "env": {
56
+ "type": "object",
57
+ "description": "Environment variables for this worker only, merged over the devserver's (e.g. { \"ROLE\": \"worker\" }). Pods never see them.",
58
+ "additionalProperties": {
59
+ "type": ["string", "number", "boolean"]
60
+ }
61
+ },
62
+ "port": {
63
+ "type": "integer",
64
+ "minimum": 0,
65
+ "maximum": 65535,
66
+ "description": "The PORT this worker is given. Default 0: the kernel picks a free one, so a worker that listens (a health endpoint) never collides with the devserver's port or with its predecessor finishing its work after a build. A fixed port makes the next build's worker wait until its predecessor has exited."
54
67
  }
55
68
  },
56
69
  "required": [
@@ -1 +1 @@
1
- "use strict";var ie=Object.defineProperty;var c=(e,r)=>ie(e,"name",{value:r,configurable:!0});var se=Object.defineProperty,o=c((e,r)=>se(e,"name",{value:r,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),node_child_process_1=require("node:child_process"),yaml=tslib_1.__importStar(require("js-yaml")),dev_devtool_1=require("../../dev-devtool"),devserver_notifier_1=require("../../devserver-notifier"),process_name_1=require("../../process-name"),attach_1=require("../../shared-build/attach");function definedEnv(e){const r={};for(const[_,i]of Object.entries(e))typeof i=="string"&&(r[_]=i);return r}c(definedEnv,"definedEnv"),o(definedEnv,"definedEnv");const frozen=o(()=>process.env.LENSMCP_FREEZE==="1","frozen");async function*serveExecutor(e,r){process.env.NODE_ENV="development";const _=r.projectsConfigurations.projects[r.projectName],i=r.root,g=path.join(i,_.root),U=e.outputPath?path.join(i,e.outputPath):path.join(i,"dist",_.root),B=e.configEnv||"development",R=path.join(i,"config",`config.${B}.yaml`),$=3050;let u=$,l=r.projectName,S={};fs.existsSync(R)?(S=yaml.load(fs.readFileSync(R,"utf8")),u=Number(S.port)||u,l=S.serviceName||l):console.warn(`[serve] ${r.projectName}: no config file at ${R} \u2014 public devserver port defaults to ${$}. If another service also lacks its config, both bind ${$} \u2192 EADDRINUSE. Add config/config.${B}.yaml with a distinct \`port:\` (matching this project's cluster.port).`),e.serviceName&&(l=e.serviceName);const O=e.servePrefix??"",v=e.debugPort??(Number(process.env.LENSMCP_DEBUG_PORT)||void 0),z=/^(1|true|yes|on)$/i.test((process.env.LENSMCP_DEBUG_FIXED_PORTS??"").trim()),p=e.logFile?path.resolve(i,e.logFile):process.env.LENSMCP_LOG_FILE||void 0;if(p){fs.mkdirSync(path.dirname(p),{recursive:!0}),fs.writeFileSync(p,"",{mode:384});try{fs.chmodSync(p,384)}catch{}}let T,D;e.gateway?.middleware&&(T=path.resolve(g,e.gateway.middleware),D=JSON.stringify(S));const K=e.entryFile||"./src/deployments/service/main.ts",Q=e.tsConfigFile||"./tsconfig.app.json",Z=path.resolve(g,K),q=path.resolve(g,Q),ee=(e.workers||[]).map(t=>({entryName:t.name,entryPath:path.resolve(g,t.entryPath)})),W={appName:r.projectName,appRoot:g,outputDir:U,main:Z,tsConfig:q,assets:e.assets||[],additionalEntryPoints:ee,port:u,serviceName:l,memoryLimit:e.memoryLimit||8192,buildLibsFromSource:e.buildLibsFromSource!==!1,workspaceRoot:i,orgScopes:e.orgScopes||[],bundlePackages:e.bundlePackages||[],nodeExternalsConfig:e.nodeExternalsConfig,webpackConfigPath:e.webpackConfigPath,httpsReload:e.gateway?.https===!0,...e.devtool!==void 0&&{devtool:e.devtool}};let d=null,k=!1,I=!1,m=!1;const V=path.join(__dirname,"../../main.devserver.js"),H=path.join(__dirname,"../../main.devserver.ts"),J=!fs.existsSync(V)&&fs.existsSync(H),x=J?H:V,oe=path.join(U,"main.js");function A(){d&&!d.killed&&(d.kill("SIGTERM"),d=null)}c(A,"H"),o(A,"cleanup");function N(){m=!0,A()}c(N,"k"),o(N,"stop");const te=["SIGINT","SIGTERM","SIGHUP","SIGQUIT"].map(t=>{const n=o(()=>N(),"handler");return process.on(t,n),{sig:t,handler:n}});process.on("exit",N);function E(){if(m)return;if(!fs.existsSync(x)){console.error(`[serve] devserver script not found at ${x}`);return}const t=["--enable-source-maps"];J&&t.unshift("--require","@swc-node/register");const n=(0,node_child_process_1.fork)(x,{cwd:i,env:{...process.env,PORT:String(u),SERVICE_NAME:l,SERVE_PREFIX:O,LENSMCP_PROJECT:process.env.LENSMCP_PROJECT||r.projectName||l,LENSMCP_EVENT_FILE:process.env.LENSMCP_EVENT_FILE||path.join(i,".lensmcp","events.jsonl"),CHILD_COUNT:String(e.childCount||process.env.CHILD_COUNT||1),BUNDLE_PATH:oe,...T&&{GATEWAY_MIDDLEWARE:T},...D&&{GATEWAY_CONFIG:D},...e.gateway?.routes?.length&&{GATEWAY_ROUTES:JSON.stringify(e.gateway.routes)},...e.gateway?.https&&{GATEWAY_HTTPS:"1"},...e.gateway?.extraPorts?.length&&{GATEWAY_EXTRA_PORTS:JSON.stringify(e.gateway.extraPorts)},...e.internalPort&&{INTERNAL_PORT:String(e.internalPort)},...v&&{LENSMCP_DEBUG_PORT:String(v)},...p&&{LENSMCP_LOG_FILE:p},...e.workers?.length&&{WORKERS:JSON.stringify(e.workers.map(a=>a.name))},[dev_devtool_1.DEV_SOURCE_MAPS_ENV]:I?"1":"0"},stdio:["inherit","inherit","inherit","ipc"],execArgv:t,execPath:(0,process_name_1.namedExecPath)((0,process_name_1.processName)(process.env.LENSMCP_WS_KEY||path.basename(i),l,"dev"))});d=n,n.on("exit",(a,f)=>{d===n&&(d=null),!(f||a===0||m)&&(console.error(`[serve] devserver exited unexpectedly (code=${a}, signal=${f}) \u2014 respawning in 1.5s`),setTimeout(()=>{!m&&!d&&k&&E()},1500).unref?.())}),console.log(`[serve] Devserver started on port ${u} (service: ${l}${O?`, prefix: /${O}`:""})`),v?(console.warn(`[serve] DEBUGGER ENABLED for ${l}. Node's inspector has NO authentication \u2014 the ws:// UUID is the whole credential, and any account on this host that obtains it runs code as you. Do not enable this on a shared machine.`),z?console.warn(`[serve] LENSMCP_DEBUG_FIXED_PORTS=1 \u2014 pod inspectors bind PREDICTABLE ports 127.0.0.1:${v}+slot (workers ${v}+20+i), reachable by any account on this host. Attach WebStorm (Attach to Node.js/Chrome) to ${v}. Unset it to bind ephemeral ports instead.`):console.log(`[serve] Debug: pod inspectors bind an EPHEMERAL 127.0.0.1 port. Get the ws:// URLs with \`lensmcp debug ${l}\` (the owner-only control socket); a devserver run in your own terminal also prints them there. Set LENSMCP_DEBUG_FIXED_PORTS=1 if your IDE needs a fixed attach port.`)):console.log(`[serve] Debug on demand: \`lensmcp debug ${l}\` opens pod inspectors without a restart`),p&&console.log(`[serve] Logs teed to ${p} \u2014 tail it in WebStorm via Run/Debug configuration \u2192 Logs tab`)}c(E,"S"),o(E,"startDevServer");function re(){if(!d||d.killed){console.log("[serve] Devserver not running, restarting..."),E();return}fetch(`http://localhost:${u}/webpack/reload`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}).then(()=>console.log("[serve] Notified devserver to reload")).catch(t=>{console.warn("[serve] Failed to notify devserver, restarting...",t.message),A(),E()})}c(re,"ne"),o(re,"_notifyDevServerReload");let y=null;const M=[];function h(t){if(y){const n=y;y=null,n(t)}else M.push(t)}c(h,"h"),o(h,"pushResult");function Y(){return M.length>0?Promise.resolve(M.shift()):new Promise(t=>{y=t})}c(Y,"ee"),o(Y,"waitForNext");let w=o(()=>{},"closeBuild");function F(){return!k||!d?(k=!0,E(),!0):!1}c(F,"J"),o(F,"builtOk");function b(){if(m)return;const{createDevWebpackConfig:t}=require("../../create-webpack-dev"),n=require("webpack"),a=t(W),{watch:f,...P}=a,s=n(P);I=(0,dev_devtool_1.bundleCarriesSourceMaps)(s.options.devtool);const j=o((L,C)=>{if(L){console.error("[serve] Webpack error:",L),h({success:!1});return}const ne=C.hasErrors();if(console.info(C.toString({colors:!0,chunks:!1,assets:!0})),ne){h({success:!1});return}F(),h({success:!0,baseUrl:`http://localhost:${u}`})},"onBuild");if(frozen()){console.log(`[serve] ${r.projectName}: frozen \u2014 compiling once, no file watcher`),s.run((L,C)=>{j(L,C),s.close(()=>{})});return}const G=s.watch(a.watchOptions||{},j);w=o(()=>G.close(()=>{}),"closeBuild")}c(b,"A"),o(b,"compileOnItsOwn");function X(t){const n=t.accepted.projects.filter(s=>s!==r.projectName);console.log(`[serve] ${r.projectName}: compiled by the workspace's shared compilation ${t.accepted.group.slice(0,8)}${n.length?` with ${n.join(", ")}`:""} \u2014 no webpack in this process`);const a=new devserver_notifier_1.DevserverNotifier(u,e.gateway?.https===!0,(0,devserver_notifier_1.devserverControlSock)(l)),f=(0,attach_1.createAttachedTypecheck)({appName:r.projectName,tsConfig:q,workspaceRoot:i,memoryLimit:e.memoryLimit||8192});let P;w=o(()=>{t.close(),f.dispose()},"closeBuild"),t.listen(s=>{if(!m)switch(s.type){case"watch-run":a.watchRun(s.paths);return;case"watch-closed":a.degrade("watch closed");return;case"failed":console.error(`[serve] the shared compiler failed: ${s.message}`),a.degrade(`compiler failed: ${s.message}`),h({success:!1});return;case"refused":console.log(`[serve] ${r.projectName}: compiling on its own from now on \u2014 ${s.reason}`),w(),b();return;case"built":{if(console.info(s.text),I=s.sourceMaps,f.built(s),!s.ok){a.failed(),h({success:!1});return}const j=s.hash!==P;P=s.hash;const G=F();a.built(j&&!G),h({success:!0,baseUrl:`http://localhost:${u}`});return}default:return}})}if(c(X,"re"),o(X,"attachToSharedBuild"),(0,attach_1.sharedBuildOffered)()&&!frozen()){const t=await(0,attach_1.joinSharedBuild)({project:r.projectName,target:r.targetName??"serve-hmr",...r.configurationName?{configuration:r.configurationName}:{},options:W,targetOptions:{...e},env:definedEnv(process.env)});t.kind==="attached"?X(t.session):(console.log(`[serve] ${r.projectName}: compiling on its own \u2014 ${t.reason}`),b())}else b();try{for(;;)yield await Y()}finally{N(),w(),te.forEach(({sig:t,handler:n})=>process.removeListener(t,n))}}c(serveExecutor,"serveExecutor"),o(serveExecutor,"serveExecutor"),exports.default=serveExecutor,module.exports=serveExecutor,module.exports.default=serveExecutor;
1
+ "use strict";var ie=Object.defineProperty;var c=(e,t)=>ie(e,"name",{value:t,configurable:!0});var se=Object.defineProperty,o=c((e,t)=>se(e,"name",{value:t,configurable:!0}),"o");Object.defineProperty(exports,"__esModule",{value:!0});const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),node_child_process_1=require("node:child_process"),yaml=tslib_1.__importStar(require("js-yaml")),dev_devtool_1=require("../../dev-devtool"),devserver_notifier_1=require("../../devserver-notifier"),process_name_1=require("../../process-name"),worker_supervisor_1=require("../../worker-supervisor"),attach_1=require("../../shared-build/attach");function definedEnv(e){const t={};for(const[_,i]of Object.entries(e))typeof i=="string"&&(t[_]=i);return t}c(definedEnv,"definedEnv"),o(definedEnv,"definedEnv");const frozen=o(()=>process.env.LENSMCP_FREEZE==="1","frozen");async function*serveExecutor(e,t){process.env.NODE_ENV="development";const _=t.projectsConfigurations.projects[t.projectName],i=t.root,g=path.join(i,_.root),U=e.outputPath?path.join(i,e.outputPath):path.join(i,"dist",_.root),B=e.configEnv||"development",R=path.join(i,"config",`config.${B}.yaml`),$=3050;let d=$,a=t.projectName,S={};fs.existsSync(R)?(S=yaml.load(fs.readFileSync(R,"utf8")),d=Number(S.port)||d,a=S.serviceName||a):console.warn(`[serve] ${t.projectName}: no config file at ${R} \u2014 public devserver port defaults to ${$}. If another service also lacks its config, both bind ${$} \u2192 EADDRINUSE. Add config/config.${B}.yaml with a distinct \`port:\` (matching this project's cluster.port).`),e.serviceName&&(a=e.serviceName);const T=e.servePrefix??"",h=e.debugPort??(Number(process.env.LENSMCP_DEBUG_PORT)||void 0),z=/^(1|true|yes|on)$/i.test((process.env.LENSMCP_DEBUG_FIXED_PORTS??"").trim()),p=e.logFile?path.resolve(i,e.logFile):process.env.LENSMCP_LOG_FILE||void 0;if(p){fs.mkdirSync(path.dirname(p),{recursive:!0}),fs.writeFileSync(p,"",{mode:384});try{fs.chmodSync(p,384)}catch{}}let k,D;e.gateway?.middleware&&(k=path.resolve(g,e.gateway.middleware),D=JSON.stringify(S));const K=e.entryFile||"./src/deployments/service/main.ts",Q=e.tsConfigFile||"./tsconfig.app.json",Z=path.resolve(g,K),q=path.resolve(g,Q),ee=(e.workers||[]).map(r=>({entryName:r.name,entryPath:path.resolve(g,r.entryPath)})),W={appName:t.projectName,appRoot:g,outputDir:U,main:Z,tsConfig:q,assets:e.assets||[],additionalEntryPoints:ee,port:d,serviceName:a,memoryLimit:e.memoryLimit||8192,buildLibsFromSource:e.buildLibsFromSource!==!1,workspaceRoot:i,orgScopes:e.orgScopes||[],bundlePackages:e.bundlePackages||[],nodeExternalsConfig:e.nodeExternalsConfig,webpackConfigPath:e.webpackConfigPath,httpsReload:e.gateway?.https===!0,...e.devtool!==void 0&&{devtool:e.devtool}};let l=null,O=!1,I=!1,m=!1;const V=path.join(__dirname,"../../main.devserver.js"),H=path.join(__dirname,"../../main.devserver.ts"),Y=!fs.existsSync(V)&&fs.existsSync(H),x=Y?H:V,oe=path.join(U,"main.js");function A(){l&&!l.killed&&(l.kill("SIGTERM"),l=null)}c(A,"H"),o(A,"cleanup");function N(){m=!0,A()}c(N,"O"),o(N,"stop");const re=["SIGINT","SIGTERM","SIGHUP","SIGQUIT"].map(r=>{const n=o(()=>N(),"handler");return process.on(r,n),{sig:r,handler:n}});process.on("exit",N);function E(){if(m)return;if(!fs.existsSync(x)){console.error(`[serve] devserver script not found at ${x}`);return}const r=["--enable-source-maps"];Y&&r.unshift("--require","@swc-node/register");const n=(0,node_child_process_1.fork)(x,{cwd:i,env:{...process.env,PORT:String(d),SERVICE_NAME:a,SERVE_PREFIX:T,LENSMCP_PROJECT:process.env.LENSMCP_PROJECT||t.projectName||a,LENSMCP_EVENT_FILE:process.env.LENSMCP_EVENT_FILE||path.join(i,".lensmcp","events.jsonl"),CHILD_COUNT:String(e.childCount||process.env.CHILD_COUNT||1),BUNDLE_PATH:oe,...k&&{GATEWAY_MIDDLEWARE:k},...D&&{GATEWAY_CONFIG:D},...e.gateway?.routes?.length&&{GATEWAY_ROUTES:JSON.stringify(e.gateway.routes)},...e.gateway?.https&&{GATEWAY_HTTPS:"1"},...e.gateway?.extraPorts?.length&&{GATEWAY_EXTRA_PORTS:JSON.stringify(e.gateway.extraPorts)},...e.internalPort&&{INTERNAL_PORT:String(e.internalPort)},...h&&{LENSMCP_DEBUG_PORT:String(h)},...p&&{LENSMCP_LOG_FILE:p},...e.workers?.length&&{WORKERS:(0,worker_supervisor_1.serializeWorkerSpecs)(e.workers)},[dev_devtool_1.DEV_SOURCE_MAPS_ENV]:I?"1":"0"},stdio:["inherit","inherit","inherit","ipc"],execArgv:r,execPath:(0,process_name_1.namedExecPath)((0,process_name_1.processName)(process.env.LENSMCP_WS_KEY||path.basename(i),a,"dev"))});l=n,n.on("exit",(u,f)=>{l===n&&(l=null),!(f||u===0||m)&&(console.error(`[serve] devserver exited unexpectedly (code=${u}, signal=${f}) \u2014 respawning in 1.5s`),setTimeout(()=>{!m&&!l&&O&&E()},1500).unref?.())}),console.log(`[serve] Devserver started on port ${d} (service: ${a}${T?`, prefix: /${T}`:""})`),h?(console.warn(`[serve] DEBUGGER ENABLED for ${a}. Node's inspector has NO authentication \u2014 the ws:// UUID is the whole credential, and any account on this host that obtains it runs code as you. Do not enable this on a shared machine.`),z?console.warn(`[serve] LENSMCP_DEBUG_FIXED_PORTS=1 \u2014 pod inspectors bind PREDICTABLE ports 127.0.0.1:${h}+slot (workers ${h}+20+i), reachable by any account on this host. Attach WebStorm (Attach to Node.js/Chrome) to ${h}. Unset it to bind ephemeral ports instead.`):console.log(`[serve] Debug: pod inspectors bind an EPHEMERAL 127.0.0.1 port. Get the ws:// URLs with \`lensmcp debug ${a}\` (the owner-only control socket); a devserver run in your own terminal also prints them there. Set LENSMCP_DEBUG_FIXED_PORTS=1 if your IDE needs a fixed attach port.`)):console.log(`[serve] Debug on demand: \`lensmcp debug ${a}\` opens pod inspectors without a restart`),p&&console.log(`[serve] Logs teed to ${p} \u2014 tail it in WebStorm via Run/Debug configuration \u2192 Logs tab`)}c(E,"_"),o(E,"startDevServer");function te(){if(!l||l.killed){console.log("[serve] Devserver not running, restarting..."),E();return}fetch(`http://localhost:${d}/webpack/reload`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}).then(()=>console.log("[serve] Notified devserver to reload")).catch(r=>{console.warn("[serve] Failed to notify devserver, restarting...",r.message),A(),E()})}c(te,"ne"),o(te,"_notifyDevServerReload");let w=null;const M=[];function v(r){if(w){const n=w;w=null,n(r)}else M.push(r)}c(v,"h"),o(v,"pushResult");function J(){return M.length>0?Promise.resolve(M.shift()):new Promise(r=>{w=r})}c(J,"ee"),o(J,"waitForNext");let y=o(()=>{},"closeBuild");function F(){return!O||!l?(O=!0,E(),!0):!1}c(F,"J"),o(F,"builtOk");function b(){if(m)return;const{createDevWebpackConfig:r}=require("../../create-webpack-dev"),n=require("webpack"),u=r(W),{watch:f,...P}=u,s=n(P);I=(0,dev_devtool_1.bundleCarriesSourceMaps)(s.options.devtool);const j=o((L,C)=>{if(L){console.error("[serve] Webpack error:",L),v({success:!1});return}const ne=C.hasErrors();if(console.info(C.toString({colors:!0,chunks:!1,assets:!0})),ne){v({success:!1});return}F(),v({success:!0,baseUrl:`http://localhost:${d}`})},"onBuild");if(frozen()){console.log(`[serve] ${t.projectName}: frozen \u2014 compiling once, no file watcher`),s.run((L,C)=>{j(L,C),s.close(()=>{})});return}const G=s.watch(u.watchOptions||{},j);y=o(()=>G.close(()=>{}),"closeBuild")}c(b,"A"),o(b,"compileOnItsOwn");function X(r){const n=r.accepted.projects.filter(s=>s!==t.projectName);console.log(`[serve] ${t.projectName}: compiled by the workspace's shared compilation ${r.accepted.group.slice(0,8)}${n.length?` with ${n.join(", ")}`:""} \u2014 no webpack in this process`);const u=new devserver_notifier_1.DevserverNotifier(d,e.gateway?.https===!0,(0,devserver_notifier_1.devserverControlSock)(a)),f=(0,attach_1.createAttachedTypecheck)({appName:t.projectName,tsConfig:q,workspaceRoot:i,memoryLimit:e.memoryLimit||8192});let P;y=o(()=>{r.close(),f.dispose()},"closeBuild"),r.listen(s=>{if(!m)switch(s.type){case"watch-run":u.watchRun(s.paths);return;case"watch-closed":u.degrade("watch closed");return;case"failed":console.error(`[serve] the shared compiler failed: ${s.message}`),u.degrade(`compiler failed: ${s.message}`),v({success:!1});return;case"refused":console.log(`[serve] ${t.projectName}: compiling on its own from now on \u2014 ${s.reason}`),y(),b();return;case"built":{if(console.info(s.text),I=s.sourceMaps,f.built(s),!s.ok){u.failed(),v({success:!1});return}const j=s.hash!==P;P=s.hash;const G=F();u.built(j&&!G),v({success:!0,baseUrl:`http://localhost:${d}`});return}default:return}})}if(c(X,"re"),o(X,"attachToSharedBuild"),(0,attach_1.sharedBuildOffered)()&&!frozen()){const r=await(0,attach_1.joinSharedBuild)({project:t.projectName,target:t.targetName??"serve-hmr",...t.configurationName?{configuration:t.configurationName}:{},options:W,targetOptions:{...e},env:definedEnv(process.env)});r.kind==="attached"?X(r.session):(console.log(`[serve] ${t.projectName}: compiling on its own \u2014 ${r.reason}`),b())}else b();try{for(;;)yield await J()}finally{N(),y(),re.forEach(({sig:r,handler:n})=>process.removeListener(r,n))}}c(serveExecutor,"serveExecutor"),o(serveExecutor,"serveExecutor"),exports.default=serveExecutor,module.exports=serveExecutor,module.exports.default=serveExecutor;
package/main.devserver.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var dt=Object.defineProperty;var h=(l,f)=>dt(l,"name",{value:f,configurable:!0});var ct=Object.defineProperty,i=h((l,f)=>ct(l,"name",{value:f,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.redactInspectorUrls=exports.inspectorPortOf=exports.DEBUG_FIXED_PORTS_ENV=exports.mayDriveThePool=exports.isOwnerOnlyTransport=exports.gatewayManaged=void 0,exports.tell=tell,exports.usesFixedInspectorPorts=usesFixedInspectorPorts,exports.inspectorPortFor=inspectorPortFor;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),node_child_process_1=require("node:child_process"),http=tslib_1.__importStar(require("node:http")),readline=tslib_1.__importStar(require("node:readline")),inspector=tslib_1.__importStar(require("node:inspector")),util=tslib_1.__importStar(require("node:util")),v8=tslib_1.__importStar(require("node:v8")),exit_reason_1=require("./exit-reason"),hot_swap_registries_1=require("./hot-swap-registries"),process_name_1=require("./process-name"),inspector_secret_1=require("./inspector-secret");Object.defineProperty(exports,"inspectorPortOf",{enumerable:!0,get:i(function(){return inspector_secret_1.inspectorPortOf},"get")}),Object.defineProperty(exports,"redactInspectorUrls",{enumerable:!0,get:i(function(){return inspector_secret_1.redactInspectorUrls},"get")});const devserver_transport_1=require("./devserver-transport");Object.defineProperty(exports,"gatewayManaged",{enumerable:!0,get:i(function(){return devserver_transport_1.gatewayManaged},"get")}),Object.defineProperty(exports,"isOwnerOnlyTransport",{enumerable:!0,get:i(function(){return devserver_transport_1.isOwnerOnlyTransport},"get")}),Object.defineProperty(exports,"mayDriveThePool",{enumerable:!0,get:i(function(){return devserver_transport_1.mayDriveThePool},"get")});const schema_first_instance_1=require("./schema-first-instance"),redis_disconnect_fix_1=require("./redis-disconnect-fix"),error_stack_release_1=require("./error-stack-release"),swap_recycle_1=require("./swap-recycle"),swap_mode_1=require("./swap-mode"),handoff_retire_1=require("./handoff-retire"),gc_notice_1=require("./gc-notice"),pod_sock_1=require("./pod-sock"),notice_generation_1=require("./notice-generation"),service_build_events_1=require("./service-build-events"),stdio_guard_1=require("./stdio-guard"),bundle_parent_1=require("./bundle-parent"),checkout_cache_1=require("./checkout-cache"),dev_devtool_1=require("./dev-devtool"),pod_memory_1=require("./pod-memory"),pod_memory_events_1=require("./pod-memory-events"),heap_snapshot_1=require("./heap-snapshot"),httpProxy=require("http-proxy"),{prettyFactory}=require("pino-pretty"),BUNDLE_PATH=process.env.BUNDLE_PATH?.trim()||"./main.js",SERVICE_NAME=process.env.SERVICE_NAME||"",SERVICE_PREFIX=process.env.SERVE_PREFIX?`/${process.env.SERVE_PREFIX}`:"",GATEWAY_MIDDLEWARE_PATH=process.env.GATEWAY_MIDDLEWARE||"",GATEWAY_CONFIG=(()=>{const l=process.env.GATEWAY_CONFIG;if(!l)return{};try{return JSON.parse(l)}catch{return{}}})();let gatewayMiddleware=null;if(GATEWAY_MIDDLEWARE_PATH)try{const l=require(GATEWAY_MIDDLEWARE_PATH);gatewayMiddleware=typeof l=="function"?l:typeof l.default=="function"?l.default:null,gatewayMiddleware||console.warn(`[gateway] ${GATEWAY_MIDDLEWARE_PATH} does not export a function, gateway disabled`)}catch(l){console.error(`[gateway] Failed to load middleware from ${GATEWAY_MIDDLEWARE_PATH}:`,l)}function applyGatewayMiddleware(l){if(gatewayMiddleware)try{gatewayMiddleware(l,GATEWAY_CONFIG)}catch(f){console.error("[gateway] Middleware error:",f)}}h(applyGatewayMiddleware,"applyGatewayMiddleware"),i(applyGatewayMiddleware,"applyGatewayMiddleware");const GATEWAY_ROUTES=(()=>{try{return JSON.parse(process.env.GATEWAY_ROUTES||"[]")}catch{return[]}})(),GATEWAY_HTTPS=process.env.GATEWAY_HTTPS==="1";function hostMatches(l,f){if(l.startsWith("*.")){const g=l.slice(1);return f.endsWith(g)||f===l.slice(2)}return f===l}h(hostMatches,"hostMatches"),i(hostMatches,"hostMatches");function matchGatewayRoute(l){if(GATEWAY_ROUTES.length===0)return;const f=(l.headers.host||"").split(":")[0],g=l.url||"/";for(const E of GATEWAY_ROUTES)if(!(E.host&&!hostMatches(E.host,f))&&!(E.prefix&&!g.startsWith(E.prefix)))return E}h(matchGatewayRoute,"matchGatewayRoute"),i(matchGatewayRoute,"matchGatewayRoute");const WORKER_NAMES=(()=>{try{return JSON.parse(process.env.WORKERS||"[]")}catch{return[]}})(),LENSMCP_WS_KEY=process.env.LENSMCP_WS_KEY||"",SOCK_NS=process.env.LENSMCP_SOCK_NS||LENSMCP_WS_KEY,SOCK_DIR=SOCK_NS?path.join(os.tmpdir(),SOCK_NS,`${SERVICE_NAME||"lensmcp-cluster"}-devserver`):path.join(os.tmpdir(),`${SERVICE_NAME||"lensmcp-cluster"}-devserver`),SOCKET_ONLY=process.env.LENSMCP_SOCKET_ONLY==="1",POD_GENERATION=(()=>{const l=Number(process.env.LENSMCP_POD_GENERATION);return Number.isFinite(l)&&l>1?Math.floor(l):1})();function childSockPath(l){return path.join(SOCK_DIR,(0,pod_sock_1.podSockName)(l,POD_GENERATION))}h(childSockPath,"childSockPath"),i(childSockPath,"childSockPath");function sockOwnerPath(l){return`${l}.owner`}h(sockOwnerPath,"sockOwnerPath"),i(sockOwnerPath,"sockOwnerPath");function sockRetiringPath(l){return`${l}.retiring`}h(sockRetiringPath,"sockRetiringPath"),i(sockRetiringPath,"sockRetiringPath");function tell(l,f){if(!l.connected||typeof l.send!="function")return!1;try{return l.send(f,()=>{})}catch{return!1}}h(tell,"tell"),i(tell,"tell");function refusePoolCommand(l,f){console.warn(`[devserver] refused ${l.method} ${l.url} on the public port \u2014 under a gateway the pool is driven on the control socket only.`),f.writeHead(404,{"content-type":"application/json"}),f.end(JSON.stringify({error:"not found"}))}h(refusePoolCommand,"refusePoolCommand"),i(refusePoolCommand,"refusePoolCommand"),exports.DEBUG_FIXED_PORTS_ENV="LENSMCP_DEBUG_FIXED_PORTS";function usesFixedInspectorPorts(l=process.env){const f=(l[exports.DEBUG_FIXED_PORTS_ENV]??"").trim().toLowerCase();return f==="1"||f==="true"||f==="yes"||f==="on"}h(usesFixedInspectorPorts,"usesFixedInspectorPorts"),i(usesFixedInspectorPorts,"usesFixedInspectorPorts");function inspectorPortFor(l,f,g=process.env){if(!usesFixedInspectorPorts(g))return 0;const E=Math.trunc(l)+Math.trunc(f);return Number.isInteger(E)&&E>1024&&E<=65535?E:0}h(inspectorPortFor,"inspectorPortFor"),i(inspectorPortFor,"inspectorPortFor");function ensureOwnerOnlyDir(l){try{fs.mkdirSync(l,{recursive:!0,mode:448})}catch{}try{const f=fs.lstatSync(l);f.isDirectory()&&(f.mode&63)!==0&&fs.chmodSync(l,448)}catch{}}h(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),i(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function claimSock(l,f=process.pid){ensureOwnerOnlyDir(path.dirname(l));try{const g=sockOwnerPath(l);try{fs.unlinkSync(g)}catch{}fs.writeFileSync(g,String(f),{flag:"wx",mode:384})}catch{}try{fs.unlinkSync(l)}catch{}try{fs.unlinkSync(sockRetiringPath(l))}catch{}}h(claimSock,"claimSock"),i(claimSock,"claimSock");function sockOwnedByAnother(l,f=process.pid){try{const g=fs.readFileSync(sockOwnerPath(l),"utf8").trim();return!!g&&g!==String(f)}catch{return!1}}h(sockOwnedByAnother,"sockOwnedByAnother"),i(sockOwnedByAnother,"sockOwnedByAnother");function cleanupSock(l,f=process.pid){if(l){try{const g=fs.readFileSync(sockOwnerPath(l),"utf8").trim();if(g&&g!==String(f))return}catch{}try{fs.unlinkSync(l)}catch{}try{fs.unlinkSync(sockOwnerPath(l))}catch{}try{fs.unlinkSync(sockRetiringPath(l))}catch{}(0,gc_notice_1.clearGcNotice)(l)}}h(cleanupSock,"cleanupSock"),i(cleanupSock,"cleanupSock");function postRetiringNotice(l,f){if(!(!l||!f)){try{const g=fs.readFileSync(sockOwnerPath(l),"utf8").trim();if(g&&g!==String(f))return}catch{}try{fs.writeFileSync(sockRetiringPath(l),String(f),{flag:"w",mode:384})}catch{}}}h(postRetiringNotice,"postRetiringNotice"),i(postRetiringNotice,"postRetiringNotice");function serviceKeyFingerprint(){const l=process.env.LENSMCP_SERVICE_KEY;if(!l)return;const{createHash:f}=require("node:crypto");return f("sha256").update(l).digest("hex").slice(0,8)}h(serviceKeyFingerprint,"serviceKeyFingerprint"),i(serviceKeyFingerprint,"serviceKeyFingerprint");function rootModuleOf(l){let f;for(const g of l.getModules?.()?.values()??[])typeof g?.metatype!="function"||typeof g.distance!="number"||!Number.isFinite(g.distance)||(!f||g.distance<f.distance)&&(f=g);return f?.metatype}h(rootModuleOf,"rootModuleOf"),i(rootModuleOf,"rootModuleOf");let lastImportedModule;function takeImportedModule(){const l=lastImportedModule;return lastImportedModule=void 0,l}h(takeImportedModule,"takeImportedModule"),i(takeImportedModule,"takeImportedModule");async function importFresh(spec){process.env.DEVSERVER_MODE="1";const requested=path.isAbsolute(spec)?spec:path.join(__dirname,spec);let resolved=requested;try{resolved=fs.realpathSync(requested)}catch{}eval(`(() => {
1
+ "use strict";var yt=Object.defineProperty;var u=(l,_)=>yt(l,"name",{value:_,configurable:!0});var gt=Object.defineProperty,a=u((l,_)=>gt(l,"name",{value:_,configurable:!0}),"a");Object.defineProperty(exports,"__esModule",{value:!0}),exports.redactInspectorUrls=exports.inspectorPortOf=exports.DEBUG_FIXED_PORTS_ENV=exports.mayDriveThePool=exports.isOwnerOnlyTransport=exports.gatewayManaged=void 0,exports.tell=tell,exports.usesFixedInspectorPorts=usesFixedInspectorPorts,exports.inspectorPortFor=inspectorPortFor;const tslib_1=require("tslib"),path=tslib_1.__importStar(require("node:path")),fs=tslib_1.__importStar(require("node:fs")),os=tslib_1.__importStar(require("node:os")),node_child_process_1=require("node:child_process"),http=tslib_1.__importStar(require("node:http")),readline=tslib_1.__importStar(require("node:readline")),inspector=tslib_1.__importStar(require("node:inspector")),util=tslib_1.__importStar(require("node:util")),v8=tslib_1.__importStar(require("node:v8")),exit_reason_1=require("./exit-reason"),worker_supervisor_1=require("./worker-supervisor"),hot_swap_registries_1=require("./hot-swap-registries"),process_name_1=require("./process-name"),inspector_secret_1=require("./inspector-secret");Object.defineProperty(exports,"inspectorPortOf",{enumerable:!0,get:a(function(){return inspector_secret_1.inspectorPortOf},"get")}),Object.defineProperty(exports,"redactInspectorUrls",{enumerable:!0,get:a(function(){return inspector_secret_1.redactInspectorUrls},"get")});const devserver_transport_1=require("./devserver-transport");Object.defineProperty(exports,"gatewayManaged",{enumerable:!0,get:a(function(){return devserver_transport_1.gatewayManaged},"get")}),Object.defineProperty(exports,"isOwnerOnlyTransport",{enumerable:!0,get:a(function(){return devserver_transport_1.isOwnerOnlyTransport},"get")}),Object.defineProperty(exports,"mayDriveThePool",{enumerable:!0,get:a(function(){return devserver_transport_1.mayDriveThePool},"get")});const schema_first_instance_1=require("./schema-first-instance"),redis_disconnect_fix_1=require("./redis-disconnect-fix"),error_stack_release_1=require("./error-stack-release"),swap_recycle_1=require("./swap-recycle"),swap_mode_1=require("./swap-mode"),handoff_retire_1=require("./handoff-retire"),gc_notice_1=require("./gc-notice"),pod_sock_1=require("./pod-sock"),notice_generation_1=require("./notice-generation"),service_build_events_1=require("./service-build-events"),stdio_guard_1=require("./stdio-guard"),bundle_parent_1=require("./bundle-parent"),checkout_cache_1=require("./checkout-cache"),dev_devtool_1=require("./dev-devtool"),pod_memory_1=require("./pod-memory"),pod_memory_events_1=require("./pod-memory-events"),heap_snapshot_1=require("./heap-snapshot"),httpProxy=require("http-proxy"),{prettyFactory}=require("pino-pretty"),BUNDLE_PATH=process.env.BUNDLE_PATH?.trim()||"./main.js",SERVICE_NAME=process.env.SERVICE_NAME||"",SERVICE_PREFIX=process.env.SERVE_PREFIX?`/${process.env.SERVE_PREFIX}`:"",GATEWAY_MIDDLEWARE_PATH=process.env.GATEWAY_MIDDLEWARE||"",GATEWAY_CONFIG=(()=>{const l=process.env.GATEWAY_CONFIG;if(!l)return{};try{return JSON.parse(l)}catch{return{}}})();let gatewayMiddleware=null;if(GATEWAY_MIDDLEWARE_PATH)try{const l=require(GATEWAY_MIDDLEWARE_PATH);gatewayMiddleware=typeof l=="function"?l:typeof l.default=="function"?l.default:null,gatewayMiddleware||console.warn(`[gateway] ${GATEWAY_MIDDLEWARE_PATH} does not export a function, gateway disabled`)}catch(l){console.error(`[gateway] Failed to load middleware from ${GATEWAY_MIDDLEWARE_PATH}:`,l)}function applyGatewayMiddleware(l){if(gatewayMiddleware)try{gatewayMiddleware(l,GATEWAY_CONFIG)}catch(_){console.error("[gateway] Middleware error:",_)}}u(applyGatewayMiddleware,"applyGatewayMiddleware"),a(applyGatewayMiddleware,"applyGatewayMiddleware");const GATEWAY_ROUTES=(()=>{try{return JSON.parse(process.env.GATEWAY_ROUTES||"[]")}catch{return[]}})(),GATEWAY_HTTPS=process.env.GATEWAY_HTTPS==="1";function hostMatches(l,_){if(l.startsWith("*.")){const f=l.slice(1);return _.endsWith(f)||_===l.slice(2)}return _===l}u(hostMatches,"hostMatches"),a(hostMatches,"hostMatches");function matchGatewayRoute(l){if(GATEWAY_ROUTES.length===0)return;const _=(l.headers.host||"").split(":")[0],f=l.url||"/";for(const m of GATEWAY_ROUTES)if(!(m.host&&!hostMatches(m.host,_))&&!(m.prefix&&!f.startsWith(m.prefix)))return m}u(matchGatewayRoute,"matchGatewayRoute"),a(matchGatewayRoute,"matchGatewayRoute");const{specs:WORKER_SPECS,problems:WORKER_PROBLEMS}=(0,worker_supervisor_1.parseWorkerSpecs)(process.env.WORKERS),WORKER_NAMES=WORKER_SPECS.map(l=>l.name),LENSMCP_WS_KEY=process.env.LENSMCP_WS_KEY||"",SOCK_NS=process.env.LENSMCP_SOCK_NS||LENSMCP_WS_KEY,SOCK_DIR=SOCK_NS?path.join(os.tmpdir(),SOCK_NS,`${SERVICE_NAME||"lensmcp-cluster"}-devserver`):path.join(os.tmpdir(),`${SERVICE_NAME||"lensmcp-cluster"}-devserver`),SOCKET_ONLY=process.env.LENSMCP_SOCKET_ONLY==="1",POD_GENERATION=(()=>{const l=Number(process.env.LENSMCP_POD_GENERATION);return Number.isFinite(l)&&l>1?Math.floor(l):1})();function childSockPath(l){return path.join(SOCK_DIR,(0,pod_sock_1.podSockName)(l,POD_GENERATION))}u(childSockPath,"childSockPath"),a(childSockPath,"childSockPath");function sockOwnerPath(l){return`${l}.owner`}u(sockOwnerPath,"sockOwnerPath"),a(sockOwnerPath,"sockOwnerPath");function sockRetiringPath(l){return`${l}.retiring`}u(sockRetiringPath,"sockRetiringPath"),a(sockRetiringPath,"sockRetiringPath");function tell(l,_){if(!l.connected||typeof l.send!="function")return!1;try{return l.send(_,()=>{})}catch{return!1}}u(tell,"tell"),a(tell,"tell");function refusePoolCommand(l,_){console.warn(`[devserver] refused ${l.method} ${l.url} on the public port \u2014 under a gateway the pool is driven on the control socket only.`),_.writeHead(404,{"content-type":"application/json"}),_.end(JSON.stringify({error:"not found"}))}u(refusePoolCommand,"refusePoolCommand"),a(refusePoolCommand,"refusePoolCommand"),exports.DEBUG_FIXED_PORTS_ENV="LENSMCP_DEBUG_FIXED_PORTS";function usesFixedInspectorPorts(l=process.env){const _=(l[exports.DEBUG_FIXED_PORTS_ENV]??"").trim().toLowerCase();return _==="1"||_==="true"||_==="yes"||_==="on"}u(usesFixedInspectorPorts,"usesFixedInspectorPorts"),a(usesFixedInspectorPorts,"usesFixedInspectorPorts");function inspectorPortFor(l,_,f=process.env){if(!usesFixedInspectorPorts(f))return 0;const m=Math.trunc(l)+Math.trunc(_);return Number.isInteger(m)&&m>1024&&m<=65535?m:0}u(inspectorPortFor,"inspectorPortFor"),a(inspectorPortFor,"inspectorPortFor");function ensureOwnerOnlyDir(l){try{fs.mkdirSync(l,{recursive:!0,mode:448})}catch{}try{const _=fs.lstatSync(l);_.isDirectory()&&(_.mode&63)!==0&&fs.chmodSync(l,448)}catch{}}u(ensureOwnerOnlyDir,"ensureOwnerOnlyDir"),a(ensureOwnerOnlyDir,"ensureOwnerOnlyDir");function claimSock(l,_=process.pid){ensureOwnerOnlyDir(path.dirname(l));try{const f=sockOwnerPath(l);try{fs.unlinkSync(f)}catch{}fs.writeFileSync(f,String(_),{flag:"wx",mode:384})}catch{}try{fs.unlinkSync(l)}catch{}try{fs.unlinkSync(sockRetiringPath(l))}catch{}}u(claimSock,"claimSock"),a(claimSock,"claimSock");function sockOwnedByAnother(l,_=process.pid){try{const f=fs.readFileSync(sockOwnerPath(l),"utf8").trim();return!!f&&f!==String(_)}catch{return!1}}u(sockOwnedByAnother,"sockOwnedByAnother"),a(sockOwnedByAnother,"sockOwnedByAnother");function cleanupSock(l,_=process.pid){if(l){try{const f=fs.readFileSync(sockOwnerPath(l),"utf8").trim();if(f&&f!==String(_))return}catch{}try{fs.unlinkSync(l)}catch{}try{fs.unlinkSync(sockOwnerPath(l))}catch{}try{fs.unlinkSync(sockRetiringPath(l))}catch{}(0,gc_notice_1.clearGcNotice)(l)}}u(cleanupSock,"cleanupSock"),a(cleanupSock,"cleanupSock");function postRetiringNotice(l,_){if(!(!l||!_)){try{const f=fs.readFileSync(sockOwnerPath(l),"utf8").trim();if(f&&f!==String(_))return}catch{}try{fs.writeFileSync(sockRetiringPath(l),String(_),{flag:"w",mode:384})}catch{}}}u(postRetiringNotice,"postRetiringNotice"),a(postRetiringNotice,"postRetiringNotice");function serviceKeyFingerprint(){const l=process.env.LENSMCP_SERVICE_KEY;if(!l)return;const{createHash:_}=require("node:crypto");return _("sha256").update(l).digest("hex").slice(0,8)}u(serviceKeyFingerprint,"serviceKeyFingerprint"),a(serviceKeyFingerprint,"serviceKeyFingerprint");function rootModuleOf(l){let _;for(const f of l.getModules?.()?.values()??[])typeof f?.metatype!="function"||typeof f.distance!="number"||!Number.isFinite(f.distance)||(!_||f.distance<_.distance)&&(_=f);return _?.metatype}u(rootModuleOf,"rootModuleOf"),a(rootModuleOf,"rootModuleOf");let lastImportedModule;function takeImportedModule(){const l=lastImportedModule;return lastImportedModule=void 0,l}u(takeImportedModule,"takeImportedModule"),a(takeImportedModule,"takeImportedModule");async function importFresh(spec){process.env.DEVSERVER_MODE="1";const requested=path.isAbsolute(spec)?spec:path.join(__dirname,spec);let resolved=requested;try{resolved=fs.realpathSync(requested)}catch{}eval(`(() => {
2
2
  const key = ${JSON.stringify(resolved)};
3
3
  const previous = require.cache[key];
4
4
  delete require.cache[key]; // delete from CJS cache
@@ -9,15 +9,16 @@
9
9
  const at = owner && Array.isArray(owner.children) ? owner.children.indexOf(previous) : -1;
10
10
  if (at >= 0) owner.children.splice(at, 1);
11
11
  }
12
- })()`),(0,bundle_parent_1.routeBundleRequires)(requested,resolved);const exports=eval(`require(${JSON.stringify(resolved)})`);try{const mod=eval("require.cache")[resolved];lastImportedModule=mod&&typeof mod=="object"?mod:void 0}catch{}return exports}h(importFresh,"importFresh"),i(importFresh,"importFresh");function debounce(l,f){let g=null;return(...E)=>{g&&clearTimeout(g),g=setTimeout(()=>l(...E),f)}}if(h(debounce,"debounce"),i(debounce,"debounce"),process.env.APP_RUNNER==="1"){(0,stdio_guard_1.guardBrokenStdio)();const l=i(g=>{if(!inspector.url())try{inspector.open(g,"127.0.0.1",!1)}catch(G){console.warn(`[child] inspector.open(${g}) failed (port taken by another devserver?) \u2014 falling back to a random port:`,G.message);try{inspector.open(0,"127.0.0.1",!1)}catch{}}const E=inspector.url();E&&tell(process,{type:"inspector-url",url:E})},"openInspector"),f=process.env.CHILD_DEBUG_PORT;if(f!==void 0&&f!==""){const g=Number(f);Number.isInteger(g)&&(g===0||g>1024)&&l(g)}try{require("@lensmcp/node-instrumentation/register")}catch{}(async()=>{let g=null,E=!1,G,ee=!1;const He=(0,hot_swap_registries_1.registryPruningEnabled)(),pe=i((t,n)=>{const d=(0,hot_swap_registries_1.describePrune)(t,n);d&&console.log(d)},"logPrune");let q={app:null,handler:i((t,n)=>{n.statusCode=503,n.end("starting")},"handler"),inflight:0};const ue=(()=>{const t=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(t)&&t>=0?t:15*6e4})(),T=i(t=>{const n=globalThis.__lensmcpActiveWork;if(typeof n!="function")return{count:0};try{const d=n(t);return{count:Number(d?.count??0),...d?.oldestStartedAt?{oldestStartedAt:d.oldestStartedAt}:{}}}catch{return{count:0}}},"activeWork"),Pe=i(t=>{const n=globalThis.__lensmcpStopWorkIntake;if(typeof n=="function")try{return n(t)}catch{return}},"stopWorkIntake"),he=i(t=>{const n=globalThis.__lensmcpWorkIntakeReport;if(!(t===void 0||typeof n!="function"))try{return n(t)??void 0}catch{return}},"workIntakeReport"),Se=(()=>{const t=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(t)&&t>=1?Math.floor(t):1})(),L=new Set,Q=(()=>{const t=Number(process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS);return process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==void 0&&process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==""&&Number.isFinite(t)&&t>=0?t:3e4})(),Y=i(t=>{if(!t.abandoned?.size)return 0;const n=Date.now();for(const[d,u]of t.abandoned)(d.writableEnded||n-u>=Q)&&t.abandoned.delete(d);return t.abandoned.size},"abandonedRunning"),te=i(t=>{let n=0;for(const d of t.open??[])d.headersSent||(n+=1);return{unanswered:n+Y(t),streams:Math.max(0,t.inflight-n),work:T(t.workGen).count}},"owedBy"),re=i((t,n,d=`${n}s`)=>`${t} ${t===1?n:d}`,"plural");async function xe(){if(Q<=0)return;const t=Date.now();let n=!1;for(;!(L.size<Se);){const d=L.values().next().value;if(!d||d.closed)break;const u=te(d);if(u.unanswered===0&&u.work===0)break;const y=(d.drainingSince??t)+Q-Date.now();if(y<=0)break;n||(n=!0,console.log(`[child] swap held \u2014 the app replaced ${Math.round((Date.now()-(d.drainingSince??t))/100)/10}s ago is still `+[u.unanswered?`answering ${re(u.unanswered,"request")}`:"",u.work?`running ${re(u.work,"background job")}`:""].filter(Boolean).join(" and ")+`, and this pod keeps at most ${Se} replaced app(s) alive (LENSMCP_SWAP_MAX_DRAINING). The new build is applied when it is done \u2014 in ${Math.ceil(y/1e3)}s at the latest (LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS).`)),await new Promise(m=>{setTimeout(m,Math.min(100,y)).unref?.()})}n&&console.log(`[child] swap resumed after ${Date.now()-t}ms`)}h(xe,"Le"),i(xe,"holdForOwedWork");const R=(0,swap_recycle_1.swapRecyclePolicy)();let fe,oe=0;const qe=(()=>{const t=Number(process.env.LENSMCP_POD_RETIRE_NOTICE_MS);return Number.isFinite(t)&&t>=0?t:3500})();let _=!1,b=!1;const S=(0,pod_memory_1.podMemoryPolicy)();let B=0;const O=new Set;let _e=!1;const H=i(()=>{if(!_e)return;let t=0;for(const n of O)n.deref()===void 0?O.delete(n):t+=1;return t},"liveContainers"),k=(0,pod_memory_1.createPodMemoryMonitor)({policy:S,state:i(()=>({gen:q.gen??0,swaps:oe,...fe===void 0?{}:{baseline:fe},busy:E||ee||K.size>0,lastBusyAt:I}),"state"),send:i(t=>{tell(process,t)},"send"),containers:H,counter:(0,pod_memory_1.createLiveObjectCounter)(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH)),onRetained:i(()=>Ne(),"onRetained"),gc:i(()=>(0,gc_notice_1.withGcNotice)($,pod_memory_1.fullGc),"gc")}),W=i(()=>((0,gc_notice_1.withGcNotice)($,pod_memory_1.fullGc)&&k.tracker.noteGc(),process.memoryUsage().heapUsed),"liveHeap"),F=(()=>{if(!(0,error_stack_release_1.errorFrameReleaseEnabled)())return null;try{const t=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH))+path.sep,n=`${path.sep}node_modules${path.sep}`,d=new Set(Object.keys(require.cache));return(0,error_stack_release_1.createErrorFrameReleaser)(require.cache,{skip:i(u=>d.has(u)||u.startsWith(t)&&!u.slice(t.length).includes(n)&&!u.slice(t.length).startsWith(`node_modules${path.sep}`),"skip")})}catch{return null}})();let ne=!1;function Ae(){if(!(!F||ne))try{const t=F();t.errors>0&&console.log(`[child] read the stack of ${t.errors} Error object(s) that libraries created while loading and keep for good \u2014 unread, each held the functions that were on its stack, this bundle's included`)}catch(t){console.error("[child] could not release library error frames:",t),ne=!0}}h(Ae,"Me"),i(Ae,"releaseLibraryErrorFrames");const K=new Map;let I=Date.now();const Ge=i(()=>R.settleMs<=0||!E&&!ee&&K.size===0&&Date.now()-I>=R.settleMs,"settled");let j;function se(t){if(!(!R.enabled||_||b)){if(R.settleMs<=0){V(t);return}j&&clearTimeout(j),j=setTimeout(()=>{j=void 0,Ge()?V(t):se(t)},R.settleMs),j.unref?.()}}h(se,"de"),i(se,"recycleCheckWhenSettled");const ve=i(()=>{if(R.stuckCloseMs<=0)return 0;const t=Date.now();let n=0;for(const d of K.values())t-d>=R.stuckCloseMs&&(n+=1);return n},"stuckCloses");function V(t){if(!R.enabled||_||b||!process.send)return;const n=v8.getHeapStatistics().heap_size_limit,d=i(y=>{const m=k.oldestRetained();return{swaps:oe,usedBytes:y,limitBytes:n,stuckCloses:ve(),settled:Ge(),...fe===void 0?{}:{baselineBytes:fe},...m?{retained:{generation:m.gen,ageMs:Date.now()-m.closedAt,gcs:m.gcs}}:{}}},"state");if(!(0,swap_recycle_1.recycleReason)(R,d(process.memoryUsage().heapUsed)))return;const u=(0,swap_recycle_1.recycleReason)(R,d(W()));u&&(_=!0,console.log(`[child] asking for a fresh pod ${t} \u2014 ${u}. This pod keeps serving until its successor is ready. Size the bound with LENSMCP_SWAP_RECYCLE_HEAP_FACTOR / _HEAP_RATIO / _MIN_MB / _RETAINED_MS, or turn it off with LENSMCP_SWAP_RECYCLE=0.`),tell(process,{type:"recycle-request",reason:u}))}h(V,"z"),i(V,"considerRecycle");let ge;function Ne(){if(!R.enabled||R.retainedMs<=0||_||b)return;const t=k.oldestRetained();if(!t)return;const n=t.closedAt+R.retainedMs-Date.now();if(n<=0){V("with a closed generation still in memory");return}ge||(ge=setTimeout(()=>{ge=void 0,k.measure("retention-check").catch(()=>{})},n),ge.unref?.())}h(Ne,"Ue"),i(Ne,"retainedRecycleCheck");function ye(t,n){const d={};n&&(d.module=n),t&&(d.app=t);try{const u=t?.app;if(u&&typeof u=="object"&&(d.nestApp=u,u.container&&typeof u.container=="object")){d.container=u.container;const y=rootModuleOf(u.container);y&&(d.rootModule=y)}}catch{}return d}h(ye,"ve"),i(ye,"generationTargets");async function ie(t,n){if(t.closed||(t.closed=!0,L.delete(t),n&&console.error(`[child] ${n}`),!t.app))return;K.set(t,Date.now());const d=R.enabled&&R.stuckCloseMs>0?setTimeout(()=>{K.has(t)&&(console.error(`[child] a previous app has been closing for ${Math.round(R.stuckCloseMs/1e3)}s and its close() has not returned \u2014 one of its shutdown hooks is waiting on something that does not end (a queue worker, a connection, a stream). It stays in memory until this pod is replaced.`),V("with a previous app stuck in close()"))},R.stuckCloseMs):void 0;d?.unref?.();const u=t.app;try{await t.app.close()}catch(y){console.error("[child] error closing a previous app:",y)}finally{K.delete(t),I=Date.now(),d&&clearTimeout(d),t.app=null,t.abandoned=void 0,t.handler=(y,m)=>{m.statusCode=503,m.end("closed")},t.gen!==void 0&&k.closed(t.gen,oe,ye(u,t.module)),t.module=void 0}if(t.superseded){try{pe((0,hot_swap_registries_1.pruneRegistries)(t.superseded,"serve"),"after closing the previous app")}catch(y){console.error("[child] could not release the previous app's class registrations:",y)}t.superseded=void 0}se("after closing the previous app")}h(ie,"ye"),i(ie,"closeGeneration");async function ae(t){const n=Date.now();t.drainingSince=n;const d=i(()=>({inflight:t.inflight+Y(t),work:T(t.workGen).count}),"busy"),u=d();if(u.inflight>0||u.work>0){for(;L.size>=Se;){const M=L.values().next().value;if(!M)break;const N=te(M),J=Math.round((Date.now()-(M.drainingSince??n))/1e3);if(N.unanswered===0&&N.streams===0&&N.work===0){await ie(M);continue}await ie(M,`closing a still-draining generation early \u2014 ${L.size} were pending and the cap is ${Se} (each holds a whole app: DI container, DB pool, queue workers). `+(N.unanswered>0||N.work>0?`It was replaced ${J}s ago and had still not answered ${re(N.unanswered,"request")}`+(N.work?` or finished ${re(N.work,"background job")}`:"")+` \u2014 those fail now (a queue job keeps its lock until the TTL lapses). Raise LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS (currently ${Q}ms) to wait longer for them. `:`It held only ${re(N.streams,"open stream")}; their clients reconnect to the new app. `)+"Raise LENSMCP_SWAP_MAX_DRAINING if this pod legitimately needs more.")}L.add(t)}for(;ue>0&&Date.now()-n<ue;){if(t.closed)return;const M=d();if(M.inflight===0&&M.work===0)break;await new Promise(N=>{setTimeout(N,250).unref?.()})}if(t.closed)return;const y=d(),m=he(t.workGen);y.inflight>0||y.work>0?console.error(`[child] swap drain expired after ${Date.now()-n}ms \u2014 closing the previous app with ${y.inflight} in-flight request(s) and ${y.work} background job(s) still running. `+(m?`Previous app still processing ${m.running} queue job(s); ${m.takenAfterStop} were taken after the swap. `:"")+`A queue job killed here keeps its lock until the TTL lapses. Raise LENSMCP_SWAP_DRAIN_MS (currently ${ue}ms) if this is legitimate work.`):(Date.now()-n>250||m?.runningAtStop||m?.takenAfterStop)&&console.log(`[child] previous app drained in ${Date.now()-n}ms \u2014 closing it`+(m?` (it finished ${m.finishedAfterStop} queue job(s) after the swap; ${m.takenAfterStop} were taken after the swap)`:"")),await ie(t)}h(ae,"ge"),i(ae,"drainThenClose");async function ce(){if(E)return ee=!0,console.log("[child] Reload deferred \u2014 will re-swap after current swap completes"),g;E=!0,I=Date.now(),await xe(),process.removeAllListeners("uncaughtException"),process.removeAllListeners("unhandledRejection"),process.on("uncaughtException",(P,Z)=>{console.error(`[child] uncaughtException (${Z}):`,P)}),process.on("unhandledRejection",P=>{const Z=P instanceof Error?P.stack||P.message:String(P);Z.includes("FronteggContextScope")||Z.includes("populateLoggerMetadata")||console.error("[child] unhandledRejection:",P)});let t;if(He)try{t=(0,hot_swap_registries_1.captureRegistries)()}catch{t=void 0}const n=global.__lensmcpBeginWorkGeneration,d=typeof n=="function"?n():void 0;try{try{await importFresh(BUNDLE_PATH)}catch(P){if(!(P instanceof SyntaxError))throw P;console.warn(`[child] bundle was unreadable mid-write (${P.message}) \u2014 retrying the swap once`),await new Promise(Z=>setTimeout(Z,400)),await importFresh(BUNDLE_PATH)}}catch(P){throw E=!1,I=Date.now(),P}if(typeof global.createChildApp!="function")throw E=!1,I=Date.now(),new Error(`Bundle '${BUNDLE_PATH}' does not export createChildApp() and the zero-touch bridge is not active. Either install @lensmcp/node-instrumentation (a plain NestFactory.create + app.listen main.ts then just works) or set global.createChildApp in main.ts when DEVSERVER_MODE === '1'.`);let u;if(t)try{u=(0,hot_swap_registries_1.supersededSince)(t),pe((0,hot_swap_registries_1.pruneRegistries)(u,"build"),"at the swap")}catch(P){console.error("[child] could not release superseded class registrations:",P)}let y;try{y=await global.createChildApp()}catch(P){throw E=!1,I=Date.now(),takeImportedModule(),P}const m=q;u?.size&&(m.app?m.superseded=u:pe((0,hot_swap_registries_1.pruneRegistries)(u,"serve"),"at the swap")),g=y;const M=takeImportedModule();q={app:y,handler:y.handler,inflight:0,gen:++B,...M?{module:M}:{},...d===void 0?{}:{workGen:d}};const N=ye(y,void 0).container;N&&(O.add(new WeakRef(N)),_e=!0);const J=m.app&&d!==void 0?Pe(d):void 0;return console.log("[child] Swapped to fresh app (previous draining in background)"+(J?.workers?`; its ${J.workers} queue worker(s) stopped taking new jobs, previous app still processing ${J.runningAtStop} job(s)`:"")),Ae(),m.app&&(oe+=1,ae(m).catch(P=>console.error("[child] background close error:",P)),setTimeout(()=>V("30s after a hot swap"),3e4).unref?.(),k.swapped(m.gen,()=>m.closed===!0&&!K.has(m))),E=!1,I=Date.now(),ee?(ee=!1,ce()):y}h(ce,"we"),i(ce,"swapNow");const be=debounce(async()=>{try{console.log("[child] /webpack/reload"),await ce()}catch(t){console.error("[child] reload failed:",t)}},250),me=http.createServer((t,n)=>{if(t.method==="POST"&&t.url==="/webpack/reload"){n.writeHead(200,{"content-type":"application/json"}),n.end(JSON.stringify({ok:!0})),be();return}if(t.method==="GET"&&t.url==="/__lensmcp/alive"){const u=t.headers["x-internal-token"],y=process.env.LENSMCP_SERVICE_KEY;if(y&&u!==y){n.writeHead(404,{"content-type":"text/plain"}),n.end("not found");return}const m=T();n.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),n.end(JSON.stringify({ok:!0,pid:process.pid,swapping:E,inflight:q.inflight,oldestInflightAt:q.oldestAt,activeWork:m.count,oldestWorkAt:m.oldestStartedAt,keyFingerprint:serviceKeyFingerprint(),...G?{watcher:G}:{},...Number.isFinite(Number(process.env.LENSMCP_POD_GENERATION))&&process.env.LENSMCP_POD_GENERATION?{podGeneration:Number(process.env.LENSMCP_POD_GENERATION)}:{}}));return}const d=q;d.inflight+=1,(d.open??=new Set).add(n),d.oldestAt===void 0&&(d.oldestAt=Date.now()),n.on("close",()=>{d.inflight-=1,d.open?.delete(n),Q>0&&!d.closed&&!n.headersSent&&!n.writableEnded&&((d.abandoned??=new Map).set(n,Date.now()),d.abandoned.size>256&&Y(d)),d.inflight===0&&(d.oldestAt=void 0),k.activity()}),d.handler(t,n)});me.keepAliveTimeout=0;const $=process.env.CHILD_SOCK_PATH;process.on("disconnect",()=>{cleanupSock($),process.exit(0)});try{const t=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH);if((0,schema_first_instance_1.schemaPrewarmEnabled)())try{const n=(0,schema_first_instance_1.prewarmZodFor)(t);n?.created&&console.log(`[child] zod${n.version?` ${n.version}`:""}: built ${n.created} throwaway schemas first, so none of the bundle's own is the first of its class`)}catch{}if((0,redis_disconnect_fix_1.redisDisconnectFixEnabled)())try{const n=(0,redis_disconnect_fix_1.finishStrandedDisconnectsFor)(t);n?.patched&&console.log(`[child] ioredis${n.versions.length?` ${n.versions.join(", ")}`:""}: a disconnect() between reconnect attempts now ends the client \u2014 it used to leave a queue worker's close() waiting for good`)}catch{}await ce(),fe=(await k.booted()).live,console.log(`[child] Using bundle: ${t}`),claimSock($),me.listen($,()=>{console.log(`[child] Listening on ${$}`),tell(process,{type:"ready",socketPath:$})})}catch(t){console.error("[child] Startup error:",t),tell(process,{type:"boot-error",error:String(t?.stack||t)}),process.exitCode=1;return}process.on("message",async t=>{if(!(!t||typeof t!="object")){if(t.type==="debug-open"){const n=Number(t.port);l(Number.isInteger(n)&&n>1024?n:0);return}if(t.type==="watcher"){const n=t.testimony;n&&typeof n=="object"&&(G=n);return}if(t.type==="heap-snapshot"){Re(t);return}if(t.type==="recycle-declined"){_=!1;return}if(t.type==="retire"){U();return}if(t.type==="reload"){if(b)return;try{const n=Date.now();await ce(),tell(process,{type:"reloaded",socketPath:$,swap:{generation:B,swaps:oe,swapMs:Date.now()-n,draining:L.size}})}catch(n){console.error("[child] reload error:",n),tell(process,{type:"reload-error",error:String(n?.stack||n)})}}}});let we=!1;async function Re(t){const n=i(d=>{tell(process,{type:"heap-snapshot-result",id:t.id,...d})},"reply");if(we)return n({ok:!1,refused:"a snapshot of this pod is already being written"});we=!0;try{const d=W(),u=k.tracker.views().map(N=>N.gen),y=(0,heap_snapshot_1.heapSnapshotPolicy)();t.maxHeapBytes&&(y.maxHeapBytes=t.maxHeapBytes);const m=(0,heap_snapshot_1.heapSnapshotRefusal)(y,{live:d,...t.available?{available:t.available}:{}});if(m)return n({ok:!1,refused:m,live:d});console.log(`[child] writing a heap snapshot (${Math.round(d/1048576)} MB live) \u2014 the pod pauses while V8 serialises it`);const M=await(0,heap_snapshot_1.writeHeapSnapshot)(t.file);n({ok:!0,file:t.file,bytes:M.bytes,ms:M.ms,live:d,gen:q.gen??0,closedAlive:u})}catch(d){n({ok:!1,error:d?.message??String(d)})}finally{we=!1}}h(Re,"Fe"),i(Re,"takeHeapSnapshot");async function U(t="a fresh pod has taken over"){if(b)return;b=!0,k.stop(),console.log(`[child] retiring \u2014 ${t}; ${path.basename($,".sock")} (pid ${process.pid}) is finishing in-flight work, then exiting`);const n=Pe(Number.POSITIVE_INFINITY);n?.workers&&console.log(`[child] its ${n.workers} queue worker(s) stopped taking new jobs, still processing ${n.runningAtStop} job(s)`);try{fs.writeFileSync(sockRetiringPath($),String(process.pid),{flag:"w",mode:384})}catch{}await new Promise(u=>{setTimeout(u,qe).unref?.()}),cleanupSock($),me.close();const d=Date.now();for(;Date.now()-d<ue;){me.closeIdleConnections?.();let u=0;for(const y of L)u+=te(y).unanswered;if(q.inflight+Y(q)===0&&u===0&&T().count===0)break;await new Promise(y=>{setTimeout(y,250).unref?.()})}setTimeout(()=>process.exit(0),3e4).unref?.();try{await g?.close()}catch(u){console.error("[child] close error while retiring:",u)}process.exit(0)}h(U,"U"),i(U,"retire"),process.on("beforeExit",()=>{try{inspector?.close?.()}catch{}});const le=i(async t=>{console.log(`[child ${t}] shutting down\u2026`);const n=g?.close().catch(u=>console.error("[child] close error:",u)),d=new Promise(u=>me.close(()=>u()));cleanupSock($),setTimeout(()=>process.exit(0),700).unref(),await Promise.all([n,d]),process.exit(0)},"shutdown");["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(t=>{process.on(t,()=>{if(t==="SIGTERM"&&!b&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){U("this generation was handed over to a newer one");return}inspector?.close?.(),le(t)})})})()}else{let l=h(function(_){Y.push(_),Y.length>Q&&Y.splice(0,Y.length-Q),Se?.write((0,inspector_secret_1.redactInspectorUrls)(_.replace(L,"")));for(const b of te)try{const S=b.plain?_.replace(L,""):_;b.res.write(b.redact?(0,inspector_secret_1.redactInspectorUrls)(S):S)}catch{te.delete(b)}},"fe");i(l,"emitLogLine");const f=12,g=process.env.LENSMCP_PROJECT||SERVICE_NAME||"service",E=(0,pod_memory_events_1.createPodMemoryPublisher)(process.env.LENSMCP_EVENT_FILE),G=i(_=>({project:g,service:SERVICE_NAME||g,pod:_.id,pid:_.proc.pid??0,podGeneration:POD_GENERATION}),"podIdentity"),ee=["\x1B[36m","\x1B[33m","\x1B[35m","\x1B[32m","\x1B[34m","\x1B[31m"],He="\x1B[0m",pe=Math.max(1,Number(process.env.CHILD_COUNT||1)),q=LENSMCP_WS_KEY||path.basename(process.cwd()),ue=i(_=>(0,process_name_1.namedExecPath)((0,process_name_1.processName)(q,SERVICE_NAME||"service",_)),"execPathFor");let T=(()=>{const _=Number(process.env.LENSMCP_DEBUG_PORT||"");return Number.isInteger(_)&&_>1024?_:0})();const Pe=20;T&&(console.warn("[parent] DEBUGGER ENABLED \u2014 pods and workers open a Node inspector. Node's inspector has NO authentication: the ws:// URL's UUID is the whole credential, and any account on this host that obtains it can run code as you. Do not enable this on a shared machine. (issues/closed/codex-security-06)"),console.warn(usesFixedInspectorPorts()?`[parent] ${exports.DEBUG_FIXED_PORTS_ENV} is set \u2014 inspectors bind PREDICTABLE ports (${T}+slot, workers ${T}+${Pe}+i). Any account on this host can connect to 127.0.0.1:${T} and read the session UUID from /json/list. Unset it to use ephemeral ports.`:`[parent] Inspectors bind an EPHEMERAL loopback port; attach via the printed "Debugger listening" URL, or \`lensmcp debug <service>\` (control socket). Set ${exports.DEBUG_FIXED_PORTS_ENV}=1 for fixed ports if your IDE needs a pre-configured attach port \u2014 any account on this host can then reach them.`));const he=process.env.LENSMCP_LOG_FILE||"",Se=he?(()=>{try{fs.mkdirSync(path.dirname(he),{recursive:!0});const _=fs.createWriteStream(he,{flags:"a",mode:384});try{fs.chmodSync(he,384)}catch{}return _}catch(_){return console.warn(`[parent] cannot open log file ${he}:`,_.message),null}})():null,L=/\x1b\[[0-9;]*m/g,Q=2e3,Y=[],te=new Set,re=(0,devserver_transport_1.gatewayManaged)();for(const _ of["log","info","warn","error"]){const b=console[_].bind(console),S=_==="log"||_==="info"?process.stdout:process.stderr;console[_]=(...B)=>{b(...B.map(O=>typeof O=="string"?(0,inspector_secret_1.forStream)(S,re,O):O)),l(B.map(O=>typeof O=="string"?O:util.inspect(O)).join(" ")+`
13
- `)}}const xe=i(_=>ee[(_-1)%ee.length],"colorFor"),R=i(_=>{if(pe===1)return"";const b=`[child#${_}] `;return`${xe(_)}${b}${He}`},"tagFor"),fe=i(_=>_.startsWith("{")&&_.endsWith("}"),"isJsonLog"),oe=i((_,b,S)=>{const B=prettyFactory({sync:!0,colorize:!0,crlf:!0,messageKey:"message",errorLikeObjectKeys:["err","error"],errorProps:"type,message,stack",ignore:["logContext","context","hostname","req","res","err.driverError","module","cloudEnvironment","frontegg-application-id","frontegg-tenant-id","frontegg-trace-id","frontegg-vendor-id","host","service","version","err","error"].join(","),messageFormat:"{if module}[{module}] {end}{if context}[{context}] {end}{if logContext}[{logContext}] {end}{message}",customPrettifiers:{stack:i(H=>`
14
- `+String(H),"stack")}}),O=i((H,k)=>{const W=H==="stdout"?process.stdout:process.stderr;try{S?.(k)}catch{}const F=fe(k)?B(k):`${k}
15
- `;W.write((0,inspector_secret_1.forStream)(W,re,`${b}${F}`)),l(`${b}${F}`)},"write"),_e=i((H,k)=>{if(!H)return;const W=readline.createInterface({input:H});W.on("line",F=>O(k,F)),W.on("close",()=>{})},"attach");_e(_.stdout,"stdout"),_e(_.stderr,"stderr")},"wireProcLogging"),qe=i(_=>oe(_.proc,R(_.id),b=>_.tail.push(b)),"wireChildLogging");(async()=>{ensureOwnerOnlyDir(SOCK_DIR);const _=httpProxy.createProxyServer({});let b=Number(process.env.PORT)||0;b||(b=9090);const S=[],B=new Set;function O(){let e=0;for(;B.has(e);)e++;return B.add(e),e}h(O,"$"),i(O,"allocDebugSlot");let _e=1,H=0,k=!1,W=pe,F=[],ne=0;const Ae=(0,swap_mode_1.swapMode)(),K=(()=>{const e=Number(process.env.LENSMCP_POD_BOOT_GRACE_MS);return Number.isFinite(e)&&e>=0?e:12e4})(),I=i(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"childExited"),Ge=i(e=>e.booting&&!I(e)&&Date.now()-e.spawnedAt<K,"stillBooting");function j(){return S.filter(e=>e.healthy&&typeof e.socketPath=="string")}h(j,"K"),i(j,"healthyChildren");let se,ve=0,V;const ge={project:g,service:SERVICE_NAME||g,podGeneration:POD_GENERATION};function Ne(e){const r=(0,service_build_events_1.buildAccountOf)(e.building);r&&r.startedAt!==ve&&(ve=r.startedAt,E.publish((0,service_build_events_1.buildServiceBuildEvent)(ge,"started",r,{root:process.cwd()})));const s=(0,service_build_events_1.buildAccountOf)(e.failed);s&&(ve=0,E.publish((0,service_build_events_1.buildServiceBuildEvent)(ge,"failed",s,{root:process.cwd()})))}h(Ne,"Ue"),i(Ne,"recordBuildProgress");function ye(e){if(!e||typeof e!="object")return;const r=e;if(r.schemaVersion===1){Ne(r),"failed"in r&&delete r.failed,se=r;for(const s of S)tell(s.proc,{type:"watcher",testimony:r})}}h(ye,"ve"),i(ye,"recordWatcherTestimony");function ie(e,r=256*1024){return new Promise(s=>{let c="",a=!1;e.on("data",o=>{a||(c+=o,c.length>r&&(a=!0))}),e.on("end",()=>{if(a||!c)return s(void 0);try{s(JSON.parse(c))}catch{s(void 0)}}),e.on("error",()=>s(void 0))})}h(ie,"ye"),i(ie,"readJsonBody");function ae(){const e=j();if(e.length===0)return null;const r=H%e.length;return H=(H+1)%e.length,e[r]}h(ae,"ge"),i(ae,"pickChild");function ce(e,r){const s=`Child#${e.id}`,c=SERVICE_NAME||g,a=Date.now();if(r.type==="pod-memory"){const o=r.report;if(!o||typeof o.live!="number")return;e.memory.latest=o,e.memory.history.push(o),e.memory.history.length>12&&e.memory.history.splice(0,e.memory.history.length-12),console.log(`[parent] ${(0,pod_memory_1.describePodMemory)(s,o)}`),E.publish((0,pod_memory_events_1.buildPodMemoryEvent)(G(e),o))}else if(r.type==="pod-memory-retained"){const o=r.retained;if(!o||typeof o.gen!="number")return;e.memory.retained.set(o.gen,{...o,at:a}),console.warn(`[parent] ${(0,pod_memory_1.describeRetained)(s,c,o)}`),E.publish((0,pod_memory_events_1.buildPodRetainedEvent)(G(e),o,a))}else{const o=r.released;if(!o||typeof o.gen!="number")return;e.memory.retained.delete(o.gen),console.log(`[parent] ${(0,pod_memory_1.describeReleased)(s,c,o)}`),E.publish((0,pod_memory_events_1.buildPodReleasedEvent)(G(e),o,a))}}h(ce,"we"),i(ce,"recordPodMemory");const be=new Map;let me=0;async function $(){const e=_e++,r=childSockPath(e);cleanupSock(r);const s=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&s.unshift("--require","@swc-node/register"),s.push(...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const c=T?O():-1,a=(0,node_child_process_1.fork)(__filename,{env:{...process.env,APP_RUNNER:"1",CHILD_SOCK_PATH:r,...c>=0&&{CHILD_DEBUG_PORT:String(inspectorPortFor(T,c))}},stdio:["inherit","pipe","pipe","ipc"],execArgv:s,execPath:ue("pod")}),o={id:e,proc:a,healthy:!1,lastError:null,debugSlot:c,tail:new exit_reason_1.TailBuffer,booting:!0,spawnedAt:Date.now(),bootReloadSeq:ne,memory:{history:[],retained:new Map}};return a.on("error",v=>console.error(`[parent] Child#${e}: ${v.message}`)),a.on("message",v=>{if(!v||typeof v!="object")return;const p=v;if(p.type==="ready")o.socketPath=String(p.socketPath),o.healthy=!0,o.booting=!1,console.log(`[parent] Child#${o.id} ready on socket ${o.socketPath}`),se&&tell(a,{type:"watcher",testimony:se}),ne!==o.bootReloadSeq&&(Ae==="process"?P():tell(a,{type:"reload"}));else if(p.type==="recycle-request")m(o,String(p.reason||"it has outgrown its bound"));else if(p.type==="inspector-url")o.inspectorUrl=String(p.url),console.log(`[parent] Child#${o.id} Debugger listening on ${p.url}`);else if(p.type==="reloaded"){if(U.has(o)){console.log(`[parent] Child#${o.id} finished a swap it began before it was retired \u2014 not serving it: a fresh pod has taken over`);return}o.socketPath=String(p.socketPath),o.healthy=!0,console.log(`[parent] Child#${o.id} hot-swapped on socket ${o.socketPath}`);const w=p.swap;w&&typeof w.generation=="number"&&typeof w.swaps=="number"&&E.publish((0,service_build_events_1.buildServiceSwapEvent)(G(o),{generation:w.generation,swaps:w.swaps,swapMs:typeof w.swapMs=="number"?w.swapMs:0,draining:typeof w.draining=="number"?w.draining:0},V,{root:process.cwd()}))}else p.type==="reload-error"?(o.lastError=String(p.error||"unknown reload error"),console.error(`[parent] Child#${o.id} reload error: ${o.lastError}`),o.healthy=!1):p.type==="boot-error"?(o.lastError=String(p.error||"unknown boot error"),console.error(`[parent] Child#${o.id} boot error: ${o.lastError}`),o.healthy=!1,o.booting=!1):p.type==="pod-memory"||p.type==="pod-memory-retained"||p.type==="pod-memory-released"?ce(o,p):p.type==="heap-snapshot-result"&&be.get(Number(p.id))?.(p)}),a.on("exit",(v,p)=>{o.booting=!1;for(const C of o.memory.retained.values()){const D={gen:C.gen,closedAt:C.closedAt,ageMs:Date.now()-C.closedAt,reason:"pod-exited"};console.log(`[parent] ${(0,pod_memory_1.describeReleased)(`Child#${o.id}`,SERVICE_NAME||g,D)}`),E.publish((0,pod_memory_events_1.buildPodReleasedEvent)(G(o),D,Date.now()))}o.memory.retained.clear(),o.memory.latest&&E.publish((0,pod_memory_events_1.buildPodExitedEvent)(G(o),{code:v,signal:p},Date.now())),o.debugSlot>=0&&(B.delete(o.debugSlot),o.debugSlot=-1);const w=p==="SIGINT"||p==="SIGTERM"||v===0;if(w?console.log(`[parent] Child#${o.id} exited cleanly (code=${v}, signal=${p??"none"})`):(console.error((0,exit_reason_1.crashReport)(`[parent] Child#${o.id} crashed (code=${v}, signal=${p??"none"}, pid=${o.proc.pid}, ${o.healthy?"was serving":"was not ready"})`,v,p,o.tail.snapshot())),o.lastError||(o.lastError=`Child exited abnormally (code=${v}, signal=${p??"none"})`)),o.healthy=!1,cleanupSock(o.socketPath,o.proc.pid),o.socketPath=void 0,!w&&!k){const C=S.indexOf(o);C>=0&&S.splice(C,1);const D=Date.now();if(F=F.filter(z=>D-z<3e4),F.length>=5){console.error(`[parent] crash-loop detected (${F.length} respawns/30s) \u2014 pausing auto-respawn; POST /webpack/reload to retry`);return}F.push(D),setTimeout(()=>{const z=S.filter(Ie=>Ie.proc.killed===!1).length;!k&&z<W&&(console.log(`[parent] respawning a crashed pod (${z}/${W} live)`),$().catch(()=>{}))},1500).unref?.()}}),S.push(o),qe(o),o}h($,"I"),i($,"spawnChild");async function we(e){W=Math.max(W,e);const r=S.filter(c=>c.proc.killed===!1),s=e-r.length;for(let c=0;c<s;c++)await $()}h(we,"Ee"),i(we,"ensurePoolSize");async function Re(){const e=S.filter(r=>(!r.healthy||typeof r.socketPath!="string")&&!Ge(r));await Promise.all(e.map(async r=>{try{r.proc.kill("SIGTERM")}catch{}cleanupSock(r.socketPath,r.proc.pid),r.socketPath=void 0;const s=S.indexOf(r);s>=0&&S.splice(s,1),await $()}))}h(Re,"Fe"),i(Re,"respawnUnhealthy");const U=new Set;let le=!1,t=0;const n=3e4,d=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return(Number.isFinite(e)&&e>=0?e:15*6e4)+6e4})();async function u(e,r={}){const s=Date.now(),c=await $(),a=Date.now()+K;for(;!c.healthy&&!c.lastError&&!I(c)&&Date.now()<a;){if(r.superseded?.()){const o=S.indexOf(c);o>=0&&S.splice(o,1);try{c.proc.kill("SIGTERM")}catch{}return{why:`a newer build landed while Child#${c.id} booted`,superseded:!0}}await new Promise(o=>{setTimeout(o,100).unref?.()})}if(k)return{why:"shutting down"};if(!c.healthy){const o=S.indexOf(c);o>=0&&S.splice(o,1);try{c.proc.kill("SIGTERM")}catch{}return{why:`its successor Child#${c.id} did not come up (${c.lastError??"no answer in time"})`}}return y(e),{fresh:c,readyMs:Date.now()-s}}h(u,"_"),i(u,"replacePod");function y(e){const r=S.indexOf(e);if(r>=0&&S.splice(r,1),e.healthy=!1,I(e))return;U.add(e),postRetiringNotice(e.socketPath,e.proc.pid);const s=setTimeout(()=>{if(!I(e)){console.error(`[parent] Child#${e.id} was still running ${d}ms after it was retired \u2014 killing it`);try{e.proc.kill("SIGKILL")}catch{}}},d);if(s.unref?.(),e.proc.once("exit",()=>{clearTimeout(s),U.delete(e)}),!tell(e.proc,{type:"retire"}))try{e.proc.kill("SIGTERM")}catch{}}h(y,"y"),i(y,"retirePod");async function m(e,r){const s=i(a=>{console.log(`[parent] Child#${e.id} asked for a fresh pod (${r}) \u2014 not now: ${a}`),tell(e.proc,{type:"recycle-declined"})},"decline");if(k||!S.includes(e))return;if(le)return s("another pod is already being replaced");const c=Date.now()-t;if(c<n)return s(`a pod was replaced ${Math.round(c/1e3)}s ago`);le=!0,console.log(`[parent] Child#${e.id} asked for a fresh pod \u2014 ${r}. Starting one; Child#${e.id} keeps serving until it is ready.`);try{const a=await u(e);if("why"in a){a.why!=="shutting down"&&s(a.why);return}t=Date.now(),console.log(`[parent] Child#${a.fresh.id} took over from Child#${e.id} (pid ${e.proc.pid} \u2192 ${a.fresh.proc.pid})`)}catch(a){s(`could not start a successor: ${a?.message??String(a)}`)}finally{le=!1}}h(m,"g"),i(m,"recyclePod");let M,N=!1,J=0;function P(){if(M){N=!0;return}M=(async()=>{do{N=!1;const e=ne;for(;le&&!k;)await new Promise(s=>{setTimeout(s,100).unref?.()});let r=!1;for(const s of j().filter(c=>c.bootReloadSeq<e)){if(k)break;if(!(!S.includes(s)||!s.healthy)){le=!0;try{Z(),console.log(`[parent] A new build \u2014 starting a fresh pod for it; Child#${s.id} keeps serving the previous build until it is ready.`);const c=await u(s,{superseded:i(()=>ne!==e&&(0,swap_mode_1.abandonSuperseded)(J),"superseded")});if("why"in c){if(c.superseded){J+=1,console.log(`[parent] ${c.why} \u2014 abandoned; one fresh pod for the newest build instead (${J} in a row). Child#${s.id} keeps serving.`),r=!0;break}c.why!=="shutting down"&&console.error(`[parent] Child#${s.id} keeps serving the previous build \u2014 ${c.why}`);continue}J=0,console.log(`[parent] Child#${c.fresh.id} took over from Child#${s.id} with the new build (pid ${s.proc.pid} \u2192 ${c.fresh.proc.pid}, ready in ${(c.readyMs/1e3).toFixed(1)}s while Child#${s.id} served)`),E.publish((0,service_build_events_1.buildServiceSwapEvent)(G(c.fresh),{generation:1,swaps:0,swapMs:c.readyMs,draining:U.size,handoff:{fromPid:s.proc.pid??0}},V,{root:process.cwd()}))}catch(c){console.error(`[parent] Child#${s.id} keeps serving the previous build \u2014 could not start a successor: ${c?.message??String(c)}`)}finally{le=!1}}}r&&(N=!0)}while(N&&!k)})().finally(()=>{M=void 0})}h(P,"R"),i(P,"handoffForReload");function Z(){const e=(0,swap_mode_1.maxRetiring)(),r=[...U].filter(s=>!I(s));for(;r.length>=e;){const s=r.shift();console.error(`[parent] Child#${s.id} (pid ${s.proc.pid}) was still finishing its work when a newer build replaced its successor too \u2014 stopping it (LENSMCP_SWAP_MAX_RETIRING=${e})`);try{s.proc.kill("SIGTERM")}catch{}}}h(Z,"V"),i(Z,"capRetiring");const X=[];function Be(e){const r=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH)),s=path.join(r,`${e}.js`);if(!fs.existsSync(s))return console.error(`[parent] Worker "${e}" bundle not found: ${s}`),null;const c=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&c.unshift("--require","@swc-node/register");try{c.push("--require",require.resolve("@lensmcp/node-instrumentation/register"))}catch{}const a=inspectorPortFor(T||9229,Pe+Math.max(0,WORKER_NAMES.indexOf(e)));c.push(T?`--inspect=127.0.0.1:${a}`:`--inspect-port=127.0.0.1:${a}`,...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const o=(0,node_child_process_1.fork)(s,{env:process.env,stdio:["inherit","pipe","pipe","ipc"],execArgv:c,execPath:ue(`w-${e}`)}),v={name:e,proc:o,debugPort:a};return X.push(v),o.on("error",p=>console.error(`[parent] Worker "${e}": ${p.message}`)),oe(o,`\x1B[35m[worker:${e}] \x1B[0m`,p=>{const w=/Debugger listening on (wss?:\/\/\S+)/.exec(p);w&&(v.inspectorUrl=w[1])}),o.on("exit",(p,w)=>{w==="SIGINT"||w==="SIGTERM"||p===0||console.error(`[parent] Worker "${e}" crashed (code=${p}, signal=${w??"none"})`);const C=X.indexOf(v);C>=0&&X.splice(C,1)}),console.log(`[parent] Worker "${e}" started (pid=${o.pid})`),v}h(Be,"Ke"),i(Be,"spawnWorkerProcess");const Je=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(e)&&e>=0?e:15*6e4})(),Xe=(()=>{const e=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(e)&&e>=1?Math.floor(e):1})(),Ee=new Set,je=i(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"workerExited");function Le(e,r){if(Ee.delete(e),!je(e)){console.error(`[parent] Worker "${e.name}" (pid=${e.proc.pid}) ${r} \u2014 killing it. A worker that returns from its SIGTERM handler but leaves a handle open (a Redis client handed to BullMQ is not closed by worker.close()) never exits on its own: close what it opened, or call process.exit().`);try{e.proc.kill("SIGKILL")}catch{}}}h(Le,"Be"),i(Le,"killDrainingWorker");function Ye(e){try{e.proc.kill("SIGTERM")}catch{}if(je(e))return;const r=[...Ee].filter(c=>c.name===e.name);for(;r.length>=Xe;)Le(r.shift(),`was still running when a later reload replaced its successor (cap ${Xe})`);Ee.add(e);const s=setTimeout(()=>Le(e,`was still running ${Je}ms after SIGTERM`),Je);s.unref?.(),e.proc.once("exit",()=>{clearTimeout(s),Ee.delete(e)})}h(Ye,"Xe"),i(Ye,"retireWorker");function ze(){for(const e of[...X])Ye(e);X.length=0;for(const e of WORKER_NAMES)Be(e)}h(ze,"tt"),i(ze,"restartWorkers");const nt=debounce(async()=>{ne+=1;const e=j();if(e.length>0)if(Ae==="process")P();else{console.log(`[parent] Forwarding reload to ${e.length} child(ren)`);for(const r of e)tell(r.proc,{type:"reload"})}await Re(),WORKER_NAMES.length>0&&ze()},200),Qe=i((e,r)=>{const s=(0,notice_generation_1.noticeGeneration)(e.headers);return s===void 0||s===POD_GENERATION?!1:(e.resume(),r.writeHead(409,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!1,generation:POD_GENERATION,sentFor:s})),e.url==="/webpack/reload"&&console.log(`[parent] a build of generation g${s} reached generation g${POD_GENERATION} \u2014 not reloaded: it is not this generation's build`),!0)},"refusedForAnotherGeneration"),Te=i(async(e,r)=>{if(e.method==="POST"&&e.url==="/webpack/reload"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(Qe(e,r))return;r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0})),ie(e).then(a=>{const o=a;V=(0,service_build_events_1.buildAccountOf)(o?.build),ve=0,ye(o?.watcher)}),nt();return}if(e.method==="POST"&&e.url==="/webpack/watching"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);if(Qe(e,r))return;const a=await ie(e);ye(a),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,relayed:se!==void 0}));return}if(e.method==="POST"&&e.url==="/webpack/scale"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,r);let a="";e.on("data",o=>{a+=o}),e.on("end",async()=>{let o=0;try{o=Number(JSON.parse(a||"{}").pods)||0}catch{}o=Math.max(1,Math.min(o,16)),await we(o),r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,pods:o}))});return}if(e.method==="GET"&&e.url?.startsWith("/webpack/logs")){const a=new URL(e.url,"http://localhost").searchParams,o=Math.min(Math.max(Number(a.get("tail")??"100")||0,0),Q),v=a.get("follow")!=="0",p=a.get("plain")==="1",w=!(0,devserver_transport_1.isOwnerOnlyTransport)(e);r.writeHead(200,{"content-type":"text/plain; charset=utf-8","cache-control":"no-cache"});const C=o===0?"":Y.slice(-o).join(""),D=p?C.replace(L,""):C;if(r.write(w?(0,inspector_secret_1.redactInspectorUrls)(D):D),!v){r.end();return}const z={res:r,plain:p,redact:w};te.add(z),e.on("close",()=>te.delete(z));return}if(e.method==="POST"&&e.url?.startsWith("/webpack/debug")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const a=Number(new URL(e.url,"http://localhost").searchParams.get("port")||"");Number.isInteger(a)&&a>1024&&(T=a),T||(T=9229);const o=S.filter(p=>p.proc.exitCode===null&&p.proc.signalCode===null);for(const p of o)p.debugSlot<0&&(p.debugSlot=O()),tell(p.proc,{type:"debug-open",port:inspectorPortFor(T,p.debugSlot)});for(const p of X)try{p.proc.kill("SIGUSR1")}catch{}const v=Date.now()+2e3;for(;Date.now()<v&&o.some(p=>!p.inspectorUrl);)await new Promise(p=>setTimeout(p,50));r.writeHead(200,{"content-type":"application/json"}),r.end(JSON.stringify({ok:!0,basePort:T,fixedPorts:usesFixedInspectorPorts(),pods:o.map(p=>({id:p.id,inspectorUrl:p.inspectorUrl??null})),workers:X.map(p=>({name:p.name,port:p.debugPort||(0,inspector_secret_1.inspectorPortOf)(p.inspectorUrl),inspectorUrl:p.inspectorUrl??null}))},null,2)+`
16
- `);return}if(e.method==="GET"&&e.url==="/webpack/memory"){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const a=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),o=[...S,...U].map(v=>({id:v.id,pid:v.proc.pid??0,podGeneration:POD_GENERATION,healthy:v.healthy,retiring:U.has(v),latest:v.memory.latest??null,history:v.memory.history,retained:[...v.memory.retained.values()]}));r.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),r.end(JSON.stringify({ok:!0,service:SERVICE_NAME,project:g,bundle:{path:a},pods:o},null,2)+`
17
- `);return}if(e.method==="POST"&&e.url?.startsWith("/webpack/heap")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){r.writeHead(404,{"content-type":"application/json"}),r.end(JSON.stringify({error:"not found"}));return}const a=i((x,De)=>{r.writeHead(x,{"content-type":"application/json"}),r.end(JSON.stringify(De,null,2)+`
18
- `)},"reply"),o=new URL(e.url,"http://localhost").searchParams,v=Number(o.get("pod")||""),p=o.has("maxMb")?Number(o.get("maxMb")):void 0;if(p!==void 0&&!(Number.isFinite(p)&&p>0)){a(400,{ok:!1,error:"maxMb takes a positive number of MB"});return}const w=Number.isInteger(v)&&v>0?S.find(x=>x.id===v):j()[0];if(!w||I(w)){a(404,{ok:!1,error:v?`no pod #${v} \u2014 running: ${S.map(x=>`#${x.id}`).join(", ")||"none"}`:"no pod is serving"});return}if(be.size>0){a(409,{ok:!1,refused:"a heap snapshot is already being written for this service"});return}const C=(0,heap_snapshot_1.heapSnapshotPolicy)(),D=(0,heap_snapshot_1.heapSnapshotDir)();let z;try{(0,heap_snapshot_1.ensureHeapDir)(D);const x=(0,heap_snapshot_1.pruneHeapSnapshots)(D,C);x.length&&console.log(`[parent] removed ${x.length} older heap snapshot(s) from ${D}`),z=path.join(D,(0,heap_snapshot_1.heapSnapshotFileName)(SERVICE_NAME||g,w.id,w.proc.pid??0,w.memory.latest?.gen??0,Date.now()))}catch(x){a(500,{ok:!1,error:`cannot prepare ${D}: ${x.message}`});return}const Ie=++me,Ue=(0,heap_snapshot_1.availableSystemMemory)();let Ce;const A=await new Promise(x=>{const De=setTimeout(()=>x(void 0),6e5);De.unref?.(),be.set(Ie,lt=>{clearTimeout(De),x(lt)}),Ce=i(()=>{clearTimeout(De),x(void 0)},"onExit"),w.proc.once("exit",Ce);const at={type:"heap-snapshot",id:Ie,file:z,...Ue?{available:Ue}:{},...p!==void 0?{maxHeapBytes:Math.floor(p*1048576)}:{}};tell(w.proc,at)||Ce()}).finally(()=>{be.delete(Ie),Ce&&w.proc.off("exit",Ce)});if(!A){a(504,{ok:!1,pod:w.id,error:"the pod did not finish the snapshot (it exited, or took longer than 10 minutes)"});return}A.ok?console.log(`[parent] Child#${w.id} wrote a ${Math.round((A.bytes??0)/1048576)} MB heap snapshot in ${A.ms} ms \u2192 ${A.file}`):console.warn(`[parent] Child#${w.id} heap snapshot not taken: ${A.refused??A.error}`),a(A.ok?200:A.refused?409:500,{ok:A.ok,pod:w.id,pid:w.proc.pid??0,service:SERVICE_NAME,bundle:path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),...Ue?{available:Ue}:{},...A.file?{file:A.file,bytes:A.bytes,ms:A.ms}:{},...A.live!==void 0?{live:A.live}:{},...A.gen!==void 0?{gen:A.gen,closedAlive:A.closedAlive??[]}:{},...A.refused?{refused:A.refused}:{},...A.error?{error:A.error}:{}});return}const s=matchGatewayRoute(e);if(s?.prependPrefix&&!e.url?.startsWith(s.prependPrefix)&&(e.url=s.prependPrefix+(e.url??"/")),s?.target){applyGatewayMiddleware(e),_.web(e,r,{target:s.target,autoRewrite:typeof s.target=="string",changeOrigin:!0},a=>{console.error(`[parent] proxy error to ${s.target}:`,a),r.statusCode=502,r.setHeader("content-type","text/plain; charset=utf-8"),r.end(`Upstream error from ${s.target}.`)});return}if(SERVICE_PREFIX){if(!e.url?.startsWith(SERVICE_PREFIX)){r.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),r.end(`Not found. This service is mounted at ${SERVICE_PREFIX}/`);return}e.url=e.url.slice(SERVICE_PREFIX.length)||"/"}applyGatewayMiddleware(e);const c=ae();if(!c){r.statusCode=503,r.setHeader("content-type","text/plain; charset=utf-8");const a=S.map(o=>`#${o.id}: ${o.lastError??"no error recorded"}`).join(`
19
- `);r.end(`No healthy children available. POST /webpack/reload to recover.
12
+ })()`),(0,bundle_parent_1.routeBundleRequires)(requested,resolved);const exports=eval(`require(${JSON.stringify(resolved)})`);try{const mod=eval("require.cache")[resolved];lastImportedModule=mod&&typeof mod=="object"?mod:void 0}catch{}return exports}u(importFresh,"importFresh"),a(importFresh,"importFresh");function debounce(l,_){let f=null;return(...m)=>{f&&clearTimeout(f),f=setTimeout(()=>l(...m),_)}}if(u(debounce,"debounce"),a(debounce,"debounce"),process.env.APP_RUNNER==="1"){(0,stdio_guard_1.guardBrokenStdio)();const l=a(f=>{if(!inspector.url())try{inspector.open(f,"127.0.0.1",!1)}catch(W){console.warn(`[child] inspector.open(${f}) failed (port taken by another devserver?) \u2014 falling back to a random port:`,W.message);try{inspector.open(0,"127.0.0.1",!1)}catch{}}const m=inspector.url();m&&tell(process,{type:"inspector-url",url:m})},"openInspector"),_=process.env.CHILD_DEBUG_PORT;if(_!==void 0&&_!==""){const f=Number(_);Number.isInteger(f)&&(f===0||f>1024)&&l(f)}try{require("@lensmcp/node-instrumentation/register")}catch{}(async()=>{let f=null,m=!1,W,re=!1;const Ve=(0,hot_swap_registries_1.registryPruningEnabled)(),he=a((r,c)=>{const p=(0,hot_swap_registries_1.describePrune)(r,c);p&&console.log(p)},"logPrune");let j={app:null,handler:a((r,c)=>{c.statusCode=503,c.end("starting")},"handler"),inflight:0};const fe=(()=>{const r=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(r)&&r>=0?r:15*6e4})(),M=a(r=>{const c=globalThis.__lensmcpActiveWork;if(typeof c!="function")return{count:0};try{const p=c(r);return{count:Number(p?.count??0),...p?.oldestStartedAt?{oldestStartedAt:p.oldestStartedAt}:{}}}catch{return{count:0}}},"activeWork"),$e=a(r=>{const c=globalThis.__lensmcpStopWorkIntake;if(typeof c=="function")try{return c(r)}catch{return}},"stopWorkIntake"),_e=a(r=>{const c=globalThis.__lensmcpWorkIntakeReport;if(!(r===void 0||typeof c!="function"))try{return c(r)??void 0}catch{return}},"workIntakeReport"),ke=(()=>{const r=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(r)&&r>=1?Math.floor(r):1})(),F=new Set,Z=(()=>{const r=Number(process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS);return process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==void 0&&process.env.LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS!==""&&Number.isFinite(r)&&r>=0?r:3e4})(),V=a(r=>{if(!r.abandoned?.size)return 0;const c=Date.now();for(const[p,h]of r.abandoned)(p.writableEnded||c-h>=Z)&&r.abandoned.delete(p);return r.abandoned.size},"abandonedRunning"),oe=a(r=>{let c=0;for(const p of r.open??[])p.headersSent||(c+=1);return{unanswered:c+V(r),streams:Math.max(0,r.inflight-c),work:M(r.workGen).count}},"owedBy"),ne=a((r,c,p=`${c}s`)=>`${r} ${r===1?c:p}`,"plural");async function We(){if(Z<=0)return;const r=Date.now();let c=!1;for(;!(F.size<ke);){const p=F.values().next().value;if(!p||p.closed)break;const h=oe(p);if(h.unanswered===0&&h.work===0)break;const E=(p.drainingSince??r)+Z-Date.now();if(E<=0)break;c||(c=!0,console.log(`[child] swap held \u2014 the app replaced ${Math.round((Date.now()-(p.drainingSince??r))/100)/10}s ago is still `+[h.unanswered?`answering ${ne(h.unanswered,"request")}`:"",h.work?`running ${ne(h.work,"background job")}`:""].filter(Boolean).join(" and ")+`, and this pod keeps at most ${ke} replaced app(s) alive (LENSMCP_SWAP_MAX_DRAINING). The new build is applied when it is done \u2014 in ${Math.ceil(E/1e3)}s at the latest (LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS).`)),await new Promise(S=>{setTimeout(S,Math.min(100,E)).unref?.()})}c&&console.log(`[child] swap resumed after ${Date.now()-r}ms`)}u(We,"He"),a(We,"holdForOwedWork");const O=(0,swap_recycle_1.swapRecyclePolicy)();let ge,se=0;const Je=(()=>{const r=Number(process.env.LENSMCP_POD_RETIRE_NOTICE_MS);return Number.isFinite(r)&&r>=0?r:3500})();let g=!1,b=!1;const v=(0,pod_memory_1.podMemoryPolicy)();let K=0;const x=new Set;let we=!1;const B=a(()=>{if(!we)return;let r=0;for(const c of x)c.deref()===void 0?x.delete(c):r+=1;return r},"liveContainers"),k=(0,pod_memory_1.createPodMemoryMonitor)({policy:v,state:a(()=>({gen:j.gen??0,swaps:se,...ge===void 0?{}:{baseline:ge},busy:m||re||J.size>0,lastBusyAt:D}),"state"),send:a(r=>{tell(process,r)},"send"),containers:B,counter:(0,pod_memory_1.createLiveObjectCounter)(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH)),onRetained:a(()=>Te(),"onRetained"),gc:a(()=>(0,gc_notice_1.withGcNotice)(I,pod_memory_1.fullGc),"gc")}),H=a(()=>((0,gc_notice_1.withGcNotice)(I,pod_memory_1.fullGc)&&k.tracker.noteGc(),process.memoryUsage().heapUsed),"liveHeap"),U=(()=>{if(!(0,error_stack_release_1.errorFrameReleaseEnabled)())return null;try{const r=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH))+path.sep,c=`${path.sep}node_modules${path.sep}`,p=new Set(Object.keys(require.cache));return(0,error_stack_release_1.createErrorFrameReleaser)(require.cache,{skip:a(h=>p.has(h)||h.startsWith(r)&&!h.slice(r.length).includes(c)&&!h.slice(r.length).startsWith(`node_modules${path.sep}`),"skip")})}catch{return null}})();let ie=!1;function Oe(){if(!(!U||ie))try{const r=U();r.errors>0&&console.log(`[child] read the stack of ${r.errors} Error object(s) that libraries created while loading and keep for good \u2014 unread, each held the functions that were on its stack, this bundle's included`)}catch(r){console.error("[child] could not release library error frames:",r),ie=!0}}u(Oe,"De"),a(Oe,"releaseLibraryErrorFrames");const J=new Map;let D=Date.now();const Fe=a(()=>O.settleMs<=0||!m&&!re&&J.size===0&&Date.now()-D>=O.settleMs,"settled");let Y;function ae(r){if(!(!O.enabled||g||b)){if(O.settleMs<=0){X(r);return}Y&&clearTimeout(Y),Y=setTimeout(()=>{Y=void 0,Fe()?X(r):ae(r)},O.settleMs),Y.unref?.()}}u(ae,"ue"),a(ae,"recycleCheckWhenSettled");const be=a(()=>{if(O.stuckCloseMs<=0)return 0;const r=Date.now();let c=0;for(const p of J.values())r-p>=O.stuckCloseMs&&(c+=1);return c},"stuckCloses");function X(r){if(!O.enabled||g||b||!process.send)return;const c=v8.getHeapStatistics().heap_size_limit,p=a(E=>{const S=k.oldestRetained();return{swaps:se,usedBytes:E,limitBytes:c,stuckCloses:be(),settled:Fe(),...ge===void 0?{}:{baselineBytes:ge},...S?{retained:{generation:S.gen,ageMs:Date.now()-S.closedAt,gcs:S.gcs}}:{}}},"state");if(!(0,swap_recycle_1.recycleReason)(O,p(process.memoryUsage().heapUsed)))return;const h=(0,swap_recycle_1.recycleReason)(O,p(H()));h&&(g=!0,console.log(`[child] asking for a fresh pod ${r} \u2014 ${h}. This pod keeps serving until its successor is ready. Size the bound with LENSMCP_SWAP_RECYCLE_HEAP_FACTOR / _HEAP_RATIO / _MIN_MB / _RETAINED_MS, or turn it off with LENSMCP_SWAP_RECYCLE=0.`),tell(process,{type:"recycle-request",reason:h}))}u(X,"Q"),a(X,"considerRecycle");let me;function Te(){if(!O.enabled||O.retainedMs<=0||g||b)return;const r=k.oldestRetained();if(!r)return;const c=r.closedAt+O.retainedMs-Date.now();if(c<=0){X("with a closed generation still in memory");return}me||(me=setTimeout(()=>{me=void 0,k.measure("retention-check").catch(()=>{})},c),me.unref?.())}u(Te,"je"),a(Te,"retainedRecycleCheck");function ye(r,c){const p={};c&&(p.module=c),r&&(p.app=r);try{const h=r?.app;if(h&&typeof h=="object"&&(p.nestApp=h,h.container&&typeof h.container=="object")){p.container=h.container;const E=rootModuleOf(h.container);E&&(p.rootModule=E)}}catch{}return p}u(ye,"Ne"),a(ye,"generationTargets");async function ce(r,c){if(r.closed||(r.closed=!0,F.delete(r),c&&console.error(`[child] ${c}`),!r.app))return;J.set(r,Date.now());const p=O.enabled&&O.stuckCloseMs>0?setTimeout(()=>{J.has(r)&&(console.error(`[child] a previous app has been closing for ${Math.round(O.stuckCloseMs/1e3)}s and its close() has not returned \u2014 one of its shutdown hooks is waiting on something that does not end (a queue worker, a connection, a stream). It stays in memory until this pod is replaced.`),X("with a previous app stuck in close()"))},O.stuckCloseMs):void 0;p?.unref?.();const h=r.app;try{await r.app.close()}catch(E){console.error("[child] error closing a previous app:",E)}finally{J.delete(r),D=Date.now(),p&&clearTimeout(p),r.app=null,r.abandoned=void 0,r.handler=(E,S)=>{S.statusCode=503,S.end("closed")},r.gen!==void 0&&k.closed(r.gen,se,ye(h,r.module)),r.module=void 0}if(r.superseded){try{he((0,hot_swap_registries_1.pruneRegistries)(r.superseded,"serve"),"after closing the previous app")}catch(E){console.error("[child] could not release the previous app's class registrations:",E)}r.superseded=void 0}ae("after closing the previous app")}u(ce,"me"),a(ce,"closeGeneration");async function le(r){const c=Date.now();r.drainingSince=c;const p=a(()=>({inflight:r.inflight+V(r),work:M(r.workGen).count}),"busy"),h=p();if(h.inflight>0||h.work>0){for(;F.size>=ke;){const C=F.values().next().value;if(!C)break;const N=oe(C),z=Math.round((Date.now()-(C.drainingSince??c))/1e3);if(N.unanswered===0&&N.streams===0&&N.work===0){await ce(C);continue}await ce(C,`closing a still-draining generation early \u2014 ${F.size} were pending and the cap is ${ke} (each holds a whole app: DI container, DB pool, queue workers). `+(N.unanswered>0||N.work>0?`It was replaced ${z}s ago and had still not answered ${ne(N.unanswered,"request")}`+(N.work?` or finished ${ne(N.work,"background job")}`:"")+` \u2014 those fail now (a queue job keeps its lock until the TTL lapses). Raise LENSMCP_SWAP_EARLY_CLOSE_GRACE_MS (currently ${Z}ms) to wait longer for them. `:`It held only ${ne(N.streams,"open stream")}; their clients reconnect to the new app. `)+"Raise LENSMCP_SWAP_MAX_DRAINING if this pod legitimately needs more.")}F.add(r)}for(;fe>0&&Date.now()-c<fe;){if(r.closed)return;const C=p();if(C.inflight===0&&C.work===0)break;await new Promise(N=>{setTimeout(N,250).unref?.()})}if(r.closed)return;const E=p(),S=_e(r.workGen);E.inflight>0||E.work>0?console.error(`[child] swap drain expired after ${Date.now()-c}ms \u2014 closing the previous app with ${E.inflight} in-flight request(s) and ${E.work} background job(s) still running. `+(S?`Previous app still processing ${S.running} queue job(s); ${S.takenAfterStop} were taken after the swap. `:"")+`A queue job killed here keeps its lock until the TTL lapses. Raise LENSMCP_SWAP_DRAIN_MS (currently ${fe}ms) if this is legitimate work.`):(Date.now()-c>250||S?.runningAtStop||S?.takenAfterStop)&&console.log(`[child] previous app drained in ${Date.now()-c}ms \u2014 closing it`+(S?` (it finished ${S.finishedAfterStop} queue job(s) after the swap; ${S.takenAfterStop} were taken after the swap)`:"")),await ce(r)}u(le,"ye"),a(le,"drainThenClose");async function de(){if(m)return re=!0,console.log("[child] Reload deferred \u2014 will re-swap after current swap completes"),f;m=!0,D=Date.now(),await We(),process.removeAllListeners("uncaughtException"),process.removeAllListeners("unhandledRejection"),process.on("uncaughtException",(P,ee)=>{console.error(`[child] uncaughtException (${ee}):`,P)}),process.on("unhandledRejection",P=>{const ee=P instanceof Error?P.stack||P.message:String(P);ee.includes("FronteggContextScope")||ee.includes("populateLoggerMetadata")||console.error("[child] unhandledRejection:",P)});let r;if(Ve)try{r=(0,hot_swap_registries_1.captureRegistries)()}catch{r=void 0}const c=global.__lensmcpBeginWorkGeneration,p=typeof c=="function"?c():void 0;try{try{await importFresh(BUNDLE_PATH)}catch(P){if(!(P instanceof SyntaxError))throw P;console.warn(`[child] bundle was unreadable mid-write (${P.message}) \u2014 retrying the swap once`),await new Promise(ee=>setTimeout(ee,400)),await importFresh(BUNDLE_PATH)}}catch(P){throw m=!1,D=Date.now(),P}if(typeof global.createChildApp!="function")throw m=!1,D=Date.now(),new Error(`Bundle '${BUNDLE_PATH}' does not export createChildApp() and the zero-touch bridge is not active. Either install @lensmcp/node-instrumentation (a plain NestFactory.create + app.listen main.ts then just works) or set global.createChildApp in main.ts when DEVSERVER_MODE === '1'.`);let h;if(r)try{h=(0,hot_swap_registries_1.supersededSince)(r),he((0,hot_swap_registries_1.pruneRegistries)(h,"build"),"at the swap")}catch(P){console.error("[child] could not release superseded class registrations:",P)}let E;try{E=await global.createChildApp()}catch(P){throw m=!1,D=Date.now(),takeImportedModule(),P}const S=j;h?.size&&(S.app?S.superseded=h:he((0,hot_swap_registries_1.pruneRegistries)(h,"serve"),"at the swap")),f=E;const C=takeImportedModule();j={app:E,handler:E.handler,inflight:0,gen:++K,...C?{module:C}:{},...p===void 0?{}:{workGen:p}};const N=ye(E,void 0).container;N&&(x.add(new WeakRef(N)),we=!0);const z=S.app&&p!==void 0?$e(p):void 0;return console.log("[child] Swapped to fresh app (previous draining in background)"+(z?.workers?`; its ${z.workers} queue worker(s) stopped taking new jobs, previous app still processing ${z.runningAtStop} job(s)`:"")),Oe(),S.app&&(se+=1,le(S).catch(P=>console.error("[child] background close error:",P)),setTimeout(()=>X("30s after a hot swap"),3e4).unref?.(),k.swapped(S.gen,()=>S.closed===!0&&!J.has(S))),m=!1,D=Date.now(),re?(re=!1,de()):E}u(de,"Ee"),a(de,"swapNow");const Pe=debounce(async()=>{try{console.log("[child] /webpack/reload"),await de()}catch(r){console.error("[child] reload failed:",r)}},250),Ee=http.createServer((r,c)=>{if(r.method==="POST"&&r.url==="/webpack/reload"){c.writeHead(200,{"content-type":"application/json"}),c.end(JSON.stringify({ok:!0})),Pe();return}if(r.method==="GET"&&r.url==="/__lensmcp/alive"){const h=r.headers["x-internal-token"],E=process.env.LENSMCP_SERVICE_KEY;if(E&&h!==E){c.writeHead(404,{"content-type":"text/plain"}),c.end("not found");return}const S=M();c.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),c.end(JSON.stringify({ok:!0,pid:process.pid,swapping:m,inflight:j.inflight,oldestInflightAt:j.oldestAt,activeWork:S.count,oldestWorkAt:S.oldestStartedAt,keyFingerprint:serviceKeyFingerprint(),...W?{watcher:W}:{},...Number.isFinite(Number(process.env.LENSMCP_POD_GENERATION))&&process.env.LENSMCP_POD_GENERATION?{podGeneration:Number(process.env.LENSMCP_POD_GENERATION)}:{}}));return}const p=j;p.inflight+=1,(p.open??=new Set).add(c),p.oldestAt===void 0&&(p.oldestAt=Date.now()),c.on("close",()=>{p.inflight-=1,p.open?.delete(c),Z>0&&!p.closed&&!c.headersSent&&!c.writableEnded&&((p.abandoned??=new Map).set(c,Date.now()),p.abandoned.size>256&&V(p)),p.inflight===0&&(p.oldestAt=void 0),k.activity()}),p.handler(r,c)});Ee.keepAliveTimeout=0;const I=process.env.CHILD_SOCK_PATH;process.on("disconnect",()=>{cleanupSock(I),process.exit(0)});try{const r=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.join(__dirname,BUNDLE_PATH);if((0,schema_first_instance_1.schemaPrewarmEnabled)())try{const c=(0,schema_first_instance_1.prewarmZodFor)(r);c?.created&&console.log(`[child] zod${c.version?` ${c.version}`:""}: built ${c.created} throwaway schemas first, so none of the bundle's own is the first of its class`)}catch{}if((0,redis_disconnect_fix_1.redisDisconnectFixEnabled)())try{const c=(0,redis_disconnect_fix_1.finishStrandedDisconnectsFor)(r);c?.patched&&console.log(`[child] ioredis${c.versions.length?` ${c.versions.join(", ")}`:""}: a disconnect() between reconnect attempts now ends the client \u2014 it used to leave a queue worker's close() waiting for good`)}catch{}await de(),ge=(await k.booted()).live,console.log(`[child] Using bundle: ${r}`),claimSock(I),Ee.listen(I,()=>{console.log(`[child] Listening on ${I}`),tell(process,{type:"ready",socketPath:I})})}catch(r){console.error("[child] Startup error:",r),tell(process,{type:"boot-error",error:String(r?.stack||r)}),process.exitCode=1;return}process.on("message",async r=>{if(!(!r||typeof r!="object")){if(r.type==="debug-open"){const c=Number(r.port);l(Number.isInteger(c)&&c>1024?c:0);return}if(r.type==="watcher"){const c=r.testimony;c&&typeof c=="object"&&(W=c);return}if(r.type==="heap-snapshot"){Me(r);return}if(r.type==="recycle-declined"){g=!1;return}if(r.type==="retire"){q();return}if(r.type==="reload"){if(b)return;try{const c=Date.now();await de(),tell(process,{type:"reloaded",socketPath:I,swap:{generation:K,swaps:se,swapMs:Date.now()-c,draining:F.size}})}catch(c){console.error("[child] reload error:",c),tell(process,{type:"reload-error",error:String(c?.stack||c)})}}}});let Se=!1;async function Me(r){const c=a(p=>{tell(process,{type:"heap-snapshot-result",id:r.id,...p})},"reply");if(Se)return c({ok:!1,refused:"a snapshot of this pod is already being written"});Se=!0;try{const p=H(),h=k.tracker.views().map(N=>N.gen),E=(0,heap_snapshot_1.heapSnapshotPolicy)();r.maxHeapBytes&&(E.maxHeapBytes=r.maxHeapBytes);const S=(0,heap_snapshot_1.heapSnapshotRefusal)(E,{live:p,...r.available?{available:r.available}:{}});if(S)return c({ok:!1,refused:S,live:p});console.log(`[child] writing a heap snapshot (${Math.round(p/1048576)} MB live) \u2014 the pod pauses while V8 serialises it`);const C=await(0,heap_snapshot_1.writeHeapSnapshot)(r.file);c({ok:!0,file:r.file,bytes:C.bytes,ms:C.ms,live:p,gen:j.gen??0,closedAlive:h})}catch(p){c({ok:!1,error:p?.message??String(p)})}finally{Se=!1}}u(Me,"Ye"),a(Me,"takeHeapSnapshot");async function q(r="a fresh pod has taken over"){if(b)return;b=!0,k.stop(),console.log(`[child] retiring \u2014 ${r}; ${path.basename(I,".sock")} (pid ${process.pid}) is finishing in-flight work, then exiting`);const c=$e(Number.POSITIVE_INFINITY);c?.workers&&console.log(`[child] its ${c.workers} queue worker(s) stopped taking new jobs, still processing ${c.runningAtStop} job(s)`);try{fs.writeFileSync(sockRetiringPath(I),String(process.pid),{flag:"w",mode:384})}catch{}await new Promise(h=>{setTimeout(h,Je).unref?.()}),cleanupSock(I),Ee.close();const p=Date.now();for(;Date.now()-p<fe;){Ee.closeIdleConnections?.();let h=0;for(const E of F)h+=oe(E).unanswered;if(j.inflight+V(j)===0&&h===0&&M().count===0)break;await new Promise(E=>{setTimeout(E,250).unref?.()})}setTimeout(()=>process.exit(0),3e4).unref?.();try{await f?.close()}catch(h){console.error("[child] close error while retiring:",h)}process.exit(0)}u(q,"B"),a(q,"retire"),process.on("beforeExit",()=>{try{inspector?.close?.()}catch{}});const pe=a(async r=>{console.log(`[child ${r}] shutting down\u2026`);const c=f?.close().catch(h=>console.error("[child] close error:",h)),p=new Promise(h=>Ee.close(()=>h()));cleanupSock(I),setTimeout(()=>process.exit(0),700).unref(),await Promise.all([c,p]),process.exit(0)},"shutdown");["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(r=>{process.on(r,()=>{if(r==="SIGTERM"&&!b&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){q("this generation was handed over to a newer one");return}inspector?.close?.(),pe(r)})})})()}else{let l=u(function(g){V.push(g),V.length>Z&&V.splice(0,V.length-Z),ke?.write((0,inspector_secret_1.redactInspectorUrls)(g.replace(F,"")));for(const b of oe)try{const v=b.plain?g.replace(F,""):g;b.res.write(b.redact?(0,inspector_secret_1.redactInspectorUrls)(v):v)}catch{oe.delete(b)}},"we");a(l,"emitLogLine");const _=12,f=process.env.LENSMCP_PROJECT||SERVICE_NAME||"service",m=(0,pod_memory_events_1.createPodMemoryPublisher)(process.env.LENSMCP_EVENT_FILE),W=a(g=>({project:f,service:SERVICE_NAME||f,pod:g.id,pid:g.proc.pid??0,podGeneration:POD_GENERATION}),"podIdentity"),re=["\x1B[36m","\x1B[33m","\x1B[35m","\x1B[32m","\x1B[34m","\x1B[31m"],Ve="\x1B[0m",he=Math.max(1,Number(process.env.CHILD_COUNT||1)),j=LENSMCP_WS_KEY||path.basename(process.cwd()),fe=a(g=>(0,process_name_1.namedExecPath)((0,process_name_1.processName)(j,SERVICE_NAME||"service",g)),"execPathFor");let M=(()=>{const g=Number(process.env.LENSMCP_DEBUG_PORT||"");return Number.isInteger(g)&&g>1024?g:0})();const $e=20;M&&(console.warn("[parent] DEBUGGER ENABLED \u2014 pods and workers open a Node inspector. Node's inspector has NO authentication: the ws:// URL's UUID is the whole credential, and any account on this host that obtains it can run code as you. Do not enable this on a shared machine. (issues/closed/codex-security-06)"),console.warn(usesFixedInspectorPorts()?`[parent] ${exports.DEBUG_FIXED_PORTS_ENV} is set \u2014 inspectors bind PREDICTABLE ports (${M}+slot, workers ${M}+${$e}+i). Any account on this host can connect to 127.0.0.1:${M} and read the session UUID from /json/list. Unset it to use ephemeral ports.`:`[parent] Inspectors bind an EPHEMERAL loopback port; attach via the printed "Debugger listening" URL, or \`lensmcp debug <service>\` (control socket). Set ${exports.DEBUG_FIXED_PORTS_ENV}=1 for fixed ports if your IDE needs a pre-configured attach port \u2014 any account on this host can then reach them.`));const _e=process.env.LENSMCP_LOG_FILE||"",ke=_e?(()=>{try{fs.mkdirSync(path.dirname(_e),{recursive:!0});const g=fs.createWriteStream(_e,{flags:"a",mode:384});try{fs.chmodSync(_e,384)}catch{}return g}catch(g){return console.warn(`[parent] cannot open log file ${_e}:`,g.message),null}})():null,F=/\x1b\[[0-9;]*m/g,Z=2e3,V=[],oe=new Set,ne=(0,devserver_transport_1.gatewayManaged)();for(const g of["log","info","warn","error"]){const b=console[g].bind(console),v=g==="log"||g==="info"?process.stdout:process.stderr;console[g]=(...K)=>{b(...K.map(x=>typeof x=="string"?(0,inspector_secret_1.forStream)(v,ne,x):x)),l(K.map(x=>typeof x=="string"?x:util.inspect(x)).join(" ")+`
13
+ `)}}const We=a(g=>re[(g-1)%re.length],"colorFor"),O=a(g=>{if(he===1)return"";const b=`[child#${g}] `;return`${We(g)}${b}${Ve}`},"tagFor"),ge=a(g=>g.startsWith("{")&&g.endsWith("}"),"isJsonLog"),se=a((g,b,v)=>{const K=prettyFactory({sync:!0,colorize:!0,crlf:!0,messageKey:"message",errorLikeObjectKeys:["err","error"],errorProps:"type,message,stack",ignore:["logContext","context","hostname","req","res","err.driverError","module","cloudEnvironment","frontegg-application-id","frontegg-tenant-id","frontegg-trace-id","frontegg-vendor-id","host","service","version","err","error"].join(","),messageFormat:"{if module}[{module}] {end}{if context}[{context}] {end}{if logContext}[{logContext}] {end}{message}",customPrettifiers:{stack:a(B=>`
14
+ `+String(B),"stack")}}),x=a((B,k)=>{const H=B==="stdout"?process.stdout:process.stderr;try{v?.(k)}catch{}const U=ge(k)?K(k):`${k}
15
+ `;H.write((0,inspector_secret_1.forStream)(H,ne,`${b}${U}`)),l(`${b}${U}`)},"write"),we=a((B,k)=>{if(!B)return;const H=readline.createInterface({input:B});H.on("line",U=>x(k,U)),H.on("close",()=>{})},"attach");we(g.stdout,"stdout"),we(g.stderr,"stderr")},"wireProcLogging"),Je=a(g=>se(g.proc,O(g.id),b=>g.tail.push(b)),"wireChildLogging");(async()=>{ensureOwnerOnlyDir(SOCK_DIR);const g=httpProxy.createProxyServer({});let b=Number(process.env.PORT)||0;b||(b=9090);const v=[],K=new Set;function x(){let e=0;for(;K.has(e);)e++;return K.add(e),e}u(x,"D"),a(x,"allocDebugSlot");let we=1,B=0,k=!1,H=he,U=[],ie=0;const Oe=(0,swap_mode_1.swapMode)(),J=(()=>{const e=Number(process.env.LENSMCP_POD_BOOT_GRACE_MS);return Number.isFinite(e)&&e>=0?e:12e4})(),D=a(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"childExited"),Fe=a(e=>e.booting&&!D(e)&&Date.now()-e.spawnedAt<J,"stillBooting");function Y(){return v.filter(e=>e.healthy&&typeof e.socketPath=="string")}u(Y,"J"),a(Y,"healthyChildren");let ae,be=0,X;const me={project:f,service:SERVICE_NAME||f,podGeneration:POD_GENERATION};function Te(e){const t=(0,service_build_events_1.buildAccountOf)(e.building);t&&t.startedAt!==be&&(be=t.startedAt,m.publish((0,service_build_events_1.buildServiceBuildEvent)(me,"started",t,{root:process.cwd()})));const n=(0,service_build_events_1.buildAccountOf)(e.failed);n&&(be=0,m.publish((0,service_build_events_1.buildServiceBuildEvent)(me,"failed",n,{root:process.cwd()})))}u(Te,"je"),a(Te,"recordBuildProgress");function ye(e){if(!e||typeof e!="object")return;const t=e;if(t.schemaVersion===1){Te(t),"failed"in t&&delete t.failed,ae=t;for(const n of v)tell(n.proc,{type:"watcher",testimony:t})}}u(ye,"Ne"),a(ye,"recordWatcherTestimony");function ce(e,t=256*1024){return new Promise(n=>{let i="",s=!1;e.on("data",o=>{s||(i+=o,i.length>t&&(s=!0))}),e.on("end",()=>{if(s||!i)return n(void 0);try{n(JSON.parse(i))}catch{n(void 0)}}),e.on("error",()=>n(void 0))})}u(ce,"me"),a(ce,"readJsonBody");function le(){const e=Y();if(e.length===0)return null;const t=B%e.length;return B=(B+1)%e.length,e[t]}u(le,"ye"),a(le,"pickChild");function de(e,t){const n=`Child#${e.id}`,i=SERVICE_NAME||f,s=Date.now();if(t.type==="pod-memory"){const o=t.report;if(!o||typeof o.live!="number")return;e.memory.latest=o,e.memory.history.push(o),e.memory.history.length>12&&e.memory.history.splice(0,e.memory.history.length-12),console.log(`[parent] ${(0,pod_memory_1.describePodMemory)(n,o)}`),m.publish((0,pod_memory_events_1.buildPodMemoryEvent)(W(e),o))}else if(t.type==="pod-memory-retained"){const o=t.retained;if(!o||typeof o.gen!="number")return;e.memory.retained.set(o.gen,{...o,at:s}),console.warn(`[parent] ${(0,pod_memory_1.describeRetained)(n,i,o)}`),m.publish((0,pod_memory_events_1.buildPodRetainedEvent)(W(e),o,s))}else{const o=t.released;if(!o||typeof o.gen!="number")return;e.memory.retained.delete(o.gen),console.log(`[parent] ${(0,pod_memory_1.describeReleased)(n,i,o)}`),m.publish((0,pod_memory_events_1.buildPodReleasedEvent)(W(e),o,s))}}u(de,"Ee"),a(de,"recordPodMemory");const Pe=new Map;let Ee=0;async function I(){const e=we++,t=childSockPath(e);cleanupSock(t);const n=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&n.unshift("--require","@swc-node/register"),n.push(...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const i=M?x():-1,s=(0,node_child_process_1.fork)(__filename,{env:{...process.env,APP_RUNNER:"1",CHILD_SOCK_PATH:t,...i>=0&&{CHILD_DEBUG_PORT:String(inspectorPortFor(M,i))}},stdio:["inherit","pipe","pipe","ipc"],execArgv:n,execPath:fe("pod")}),o={id:e,proc:s,healthy:!1,lastError:null,debugSlot:i,tail:new exit_reason_1.TailBuffer,booting:!0,spawnedAt:Date.now(),bootReloadSeq:ie,memory:{history:[],retained:new Map}};return s.on("error",y=>console.error(`[parent] Child#${e}: ${y.message}`)),s.on("message",y=>{if(!y||typeof y!="object")return;const d=y;if(d.type==="ready")o.socketPath=String(d.socketPath),o.healthy=!0,o.booting=!1,console.log(`[parent] Child#${o.id} ready on socket ${o.socketPath}`),ae&&tell(s,{type:"watcher",testimony:ae}),ie!==o.bootReloadSeq&&(Oe==="process"?P():tell(s,{type:"reload"}));else if(d.type==="recycle-request")S(o,String(d.reason||"it has outgrown its bound"));else if(d.type==="inspector-url")o.inspectorUrl=String(d.url),console.log(`[parent] Child#${o.id} Debugger listening on ${d.url}`);else if(d.type==="reloaded"){if(q.has(o)){console.log(`[parent] Child#${o.id} finished a swap it began before it was retired \u2014 not serving it: a fresh pod has taken over`);return}o.socketPath=String(d.socketPath),o.healthy=!0,console.log(`[parent] Child#${o.id} hot-swapped on socket ${o.socketPath}`);const w=d.swap;w&&typeof w.generation=="number"&&typeof w.swaps=="number"&&m.publish((0,service_build_events_1.buildServiceSwapEvent)(W(o),{generation:w.generation,swaps:w.swaps,swapMs:typeof w.swapMs=="number"?w.swapMs:0,draining:typeof w.draining=="number"?w.draining:0},X,{root:process.cwd()}))}else d.type==="reload-error"?(o.lastError=String(d.error||"unknown reload error"),console.error(`[parent] Child#${o.id} reload error: ${o.lastError}`),o.healthy=!1):d.type==="boot-error"?(o.lastError=String(d.error||"unknown boot error"),console.error(`[parent] Child#${o.id} boot error: ${o.lastError}`),o.healthy=!1,o.booting=!1):d.type==="pod-memory"||d.type==="pod-memory-retained"||d.type==="pod-memory-released"?de(o,d):d.type==="heap-snapshot-result"&&Pe.get(Number(d.id))?.(d)}),s.on("exit",(y,d)=>{o.booting=!1;for(const A of o.memory.retained.values()){const T={gen:A.gen,closedAt:A.closedAt,ageMs:Date.now()-A.closedAt,reason:"pod-exited"};console.log(`[parent] ${(0,pod_memory_1.describeReleased)(`Child#${o.id}`,SERVICE_NAME||f,T)}`),m.publish((0,pod_memory_events_1.buildPodReleasedEvent)(W(o),T,Date.now()))}o.memory.retained.clear(),o.memory.latest&&m.publish((0,pod_memory_events_1.buildPodExitedEvent)(W(o),{code:y,signal:d},Date.now())),o.debugSlot>=0&&(K.delete(o.debugSlot),o.debugSlot=-1);const w=d==="SIGINT"||d==="SIGTERM"||y===0;if(w?console.log(`[parent] Child#${o.id} exited cleanly (code=${y}, signal=${d??"none"})`):(console.error((0,exit_reason_1.crashReport)(`[parent] Child#${o.id} crashed (code=${y}, signal=${d??"none"}, pid=${o.proc.pid}, ${o.healthy?"was serving":"was not ready"})`,y,d,o.tail.snapshot())),o.lastError||(o.lastError=`Child exited abnormally (code=${y}, signal=${d??"none"})`)),o.healthy=!1,cleanupSock(o.socketPath,o.proc.pid),o.socketPath=void 0,!w&&!k){const A=v.indexOf(o);A>=0&&v.splice(A,1);const T=Date.now();if(U=U.filter($=>T-$<3e4),U.length>=5){console.error(`[parent] crash-loop detected (${U.length} respawns/30s) \u2014 pausing auto-respawn; POST /webpack/reload to retry`);return}U.push(T),setTimeout(()=>{const $=v.filter(Q=>Q.proc.killed===!1).length;!k&&$<H&&(console.log(`[parent] respawning a crashed pod (${$}/${H} live)`),I().catch(()=>{}))},1500).unref?.()}}),v.push(o),Je(o),o}u(I,"C"),a(I,"spawnChild");async function Se(e){H=Math.max(H,e);const t=v.filter(i=>i.proc.killed===!1),n=e-t.length;for(let i=0;i<n;i++)await I()}u(Se,"be"),a(Se,"ensurePoolSize");async function Me(){const e=v.filter(t=>(!t.healthy||typeof t.socketPath!="string")&&!Fe(t));await Promise.all(e.map(async t=>{try{t.proc.kill("SIGTERM")}catch{}cleanupSock(t.socketPath,t.proc.pid),t.socketPath=void 0;const n=v.indexOf(t);n>=0&&v.splice(n,1),await I()}))}u(Me,"Ye"),a(Me,"respawnUnhealthy");const q=new Set;let pe=!1,r=0;const c=3e4,p=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return(Number.isFinite(e)&&e>=0?e:15*6e4)+6e4})();async function h(e,t={}){const n=Date.now(),i=await I(),s=Date.now()+J;for(;!i.healthy&&!i.lastError&&!D(i)&&Date.now()<s;){if(t.superseded?.()){const o=v.indexOf(i);o>=0&&v.splice(o,1);try{i.proc.kill("SIGTERM")}catch{}return{why:`a newer build landed while Child#${i.id} booted`,superseded:!0}}await new Promise(o=>{setTimeout(o,100).unref?.()})}if(k)return{why:"shutting down"};if(!i.healthy){const o=v.indexOf(i);o>=0&&v.splice(o,1);try{i.proc.kill("SIGTERM")}catch{}return{why:`its successor Child#${i.id} did not come up (${i.lastError??"no answer in time"})`}}return E(e),{fresh:i,readyMs:Date.now()-n}}u(h,"_"),a(h,"replacePod");function E(e){const t=v.indexOf(e);if(t>=0&&v.splice(t,1),e.healthy=!1,D(e))return;q.add(e),postRetiringNotice(e.socketPath,e.proc.pid);const n=setTimeout(()=>{if(!D(e)){console.error(`[parent] Child#${e.id} was still running ${p}ms after it was retired \u2014 killing it`);try{e.proc.kill("SIGKILL")}catch{}}},p);if(n.unref?.(),e.proc.once("exit",()=>{clearTimeout(n),q.delete(e)}),!tell(e.proc,{type:"retire"}))try{e.proc.kill("SIGTERM")}catch{}}u(E,"m"),a(E,"retirePod");async function S(e,t){const n=a(s=>{console.log(`[parent] Child#${e.id} asked for a fresh pod (${t}) \u2014 not now: ${s}`),tell(e.proc,{type:"recycle-declined"})},"decline");if(k||!v.includes(e))return;if(pe)return n("another pod is already being replaced");const i=Date.now()-r;if(i<c)return n(`a pod was replaced ${Math.round(i/1e3)}s ago`);pe=!0,console.log(`[parent] Child#${e.id} asked for a fresh pod \u2014 ${t}. Starting one; Child#${e.id} keeps serving until it is ready.`);try{const s=await h(e);if("why"in s){s.why!=="shutting down"&&n(s.why);return}r=Date.now(),console.log(`[parent] Child#${s.fresh.id} took over from Child#${e.id} (pid ${e.proc.pid} \u2192 ${s.fresh.proc.pid})`)}catch(s){n(`could not start a successor: ${s?.message??String(s)}`)}finally{pe=!1}}u(S,"y"),a(S,"recyclePod");let C,N=!1,z=0;function P(){if(C){N=!0;return}C=(async()=>{do{N=!1;const e=ie;for(;pe&&!k;)await new Promise(n=>{setTimeout(n,100).unref?.()});let t=!1;for(const n of Y().filter(i=>i.bootReloadSeq<e)){if(k)break;if(!(!v.includes(n)||!n.healthy)){pe=!0;try{ee(),console.log(`[parent] A new build \u2014 starting a fresh pod for it; Child#${n.id} keeps serving the previous build until it is ready.`);const i=await h(n,{superseded:a(()=>ie!==e&&(0,swap_mode_1.abandonSuperseded)(z),"superseded")});if("why"in i){if(i.superseded){z+=1,console.log(`[parent] ${i.why} \u2014 abandoned; one fresh pod for the newest build instead (${z} in a row). Child#${n.id} keeps serving.`),t=!0;break}i.why!=="shutting down"&&console.error(`[parent] Child#${n.id} keeps serving the previous build \u2014 ${i.why}`);continue}z=0,console.log(`[parent] Child#${i.fresh.id} took over from Child#${n.id} with the new build (pid ${n.proc.pid} \u2192 ${i.fresh.proc.pid}, ready in ${(i.readyMs/1e3).toFixed(1)}s while Child#${n.id} served)`),m.publish((0,service_build_events_1.buildServiceSwapEvent)(W(i.fresh),{generation:1,swaps:0,swapMs:i.readyMs,draining:q.size,handoff:{fromPid:n.proc.pid??0}},X,{root:process.cwd()}))}catch(i){console.error(`[parent] Child#${n.id} keeps serving the previous build \u2014 could not start a successor: ${i?.message??String(i)}`)}finally{pe=!1}}}t&&(N=!0)}while(N&&!k)})().finally(()=>{C=void 0})}u(P,"A"),a(P,"handoffForReload");function ee(){const e=(0,swap_mode_1.maxRetiring)(),t=[...q].filter(n=>!D(n));for(;t.length>=e;){const n=t.shift();console.error(`[parent] Child#${n.id} (pid ${n.proc.pid}) was still finishing its work when a newer build replaced its successor too \u2014 stopping it (LENSMCP_SWAP_MAX_RETIRING=${e})`);try{n.proc.kill("SIGTERM")}catch{}}}u(ee,"X"),a(ee,"capRetiring");const G=[],He=new Map,Ue=a(e=>{let t=He.get(e);return t||He.set(e,t={crashes:0,restarts:0}),t},"watchOf"),Xe=(0,worker_supervisor_1.workerBackoff)(),Ae=a((e,t)=>({project:f,service:SERVICE_NAME||f,worker:e,pid:t,podGeneration:POD_GENERATION}),"workerWho"),tt=[path.join(__dirname,"worker-guard.js"),path.join(__dirname,"worker-guard.ts")].find(e=>fs.existsSync(e));for(const e of WORKER_PROBLEMS)console.error(`[parent] ${e}`);function ze(e,t){const n=e.name,i=path.dirname(path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH)),s=path.join(i,`${n}.js`),o=Ue(n);if(!fs.existsSync(s))return console.error(`[parent] Worker "${n}" bundle not found: ${s}`),o.missing=s,m.publish((0,worker_supervisor_1.buildWorkerExitedEvent)(Ae(n,0),{ranMs:0,reason:`its bundle was not built (${path.basename(s)} is not in ${i})`})),null;o.missing=void 0;const y=(0,dev_devtool_1.sourceMapExecArgv)();__filename.endsWith(".ts")&&y.unshift("--require","@swc-node/register"),tt&&y.push("--require",tt);try{y.push("--require",require.resolve("@lensmcp/node-instrumentation/register"))}catch{}const d=inspectorPortFor(M||9229,$e+Math.max(0,WORKER_NAMES.indexOf(n)));y.push(M?`--inspect=127.0.0.1:${d}`:`--inspect-port=127.0.0.1:${d}`,...(0,inspector_secret_1.inspectorPublishExecArgv)(usesFixedInspectorPorts()));const w=(0,node_child_process_1.fork)(s,{env:(0,worker_supervisor_1.workerEnv)(process.env,e),stdio:["inherit","pipe","pipe","ipc"],execArgv:y,execPath:fe(`w-${n}`)}),A={name:n,spec:e,proc:w,debugPort:d,startedAt:Date.now(),tail:new exit_reason_1.TailBuffer,stopping:!1};G.push(A),w.on("error",$=>console.error(`[parent] Worker "${n}": ${$.message}`)),se(w,`\x1B[35m[worker:${n}] \x1B[0m`,$=>{A.tail.push($);const Q=/Debugger listening on (wss?:\/\/\S+)/.exec($);Q&&(A.inspectorUrl=Q[1])});const T=setTimeout(()=>{if(!(Re(A)||A.stopping)){if(o.crashes>0){const $=Date.now()-A.startedAt;console.log(`[parent] Worker "${n}" (pid=${w.pid}) is up again \u2014 ${(0,worker_supervisor_1.spanOf)($)} without a crash, after ${o.crashes} in a row`),m.publish((0,worker_supervisor_1.buildWorkerUpEvent)(Ae(n,w.pid??0),{ranMs:$,afterCrashes:o.crashes}))}o.crashes=0}},Xe.stableMs);return T.unref?.(),w.on("exit",($,Q)=>{clearTimeout(T);const ve=G.indexOf(A);ve>=0&&G.splice(ve,1),rt(A,$,Q)}),console.log(`[parent] Worker "${n}" started (pid=${w.pid}, PORT=${(0,worker_supervisor_1.workerEnv)(process.env,e).PORT}${t==="respawn"?`, restart ${o.restarts}`:""})`),m.publish((0,worker_supervisor_1.buildWorkerStartedEvent)(Ae(n,w.pid??0),{why:t,port:e.port,restarts:o.restarts})),A}u(ze,"Ze"),a(ze,"spawnWorkerProcess");function rt(e,t,n){const{name:i}=e,s=e.proc.pid??0,o=Date.now()-e.startedAt,y=(0,worker_supervisor_1.workerExitVerdict)(t,n,e.stopping||k);if(y.kind==="stopped")return;const d=Ue(i);if(y.kind==="exited"){d.lastEnd={at:Date.now(),pid:s,code:t,signal:n,ranMs:o,verdict:"exited"},console.warn(`[parent] Worker "${i}" (pid=${s}) exited on its own (code 0) after ${(0,worker_supervisor_1.spanOf)(o)} \u2014 not started again until the next build: a worker that ends is taken to have finished its work`),m.publish((0,worker_supervisor_1.buildWorkerExitedEvent)(Ae(i,s),{ranMs:o}));return}d.crashes+=1,d.lastEnd={at:Date.now(),pid:s,code:t,signal:n,ranMs:o,verdict:"crashed"};const w=(0,worker_supervisor_1.respawnDelay)(d.crashes,Xe),A=d.crashes>=worker_supervisor_1.CRASH_LOOP_AFTER;console.error((0,exit_reason_1.crashReport)(`[parent] Worker "${i}" crashed (code=${t}, signal=${n??"none"}, pid=${s}, after ${(0,worker_supervisor_1.spanOf)(o)})${y.external?" \u2014 stopped by a signal from outside its devserver":""}; starting it again in ${(0,worker_supervisor_1.spanOf)(w)}${A?` \u2014 ${d.crashes} crashes in a row: it is crash-looping (the wait doubles, up to ${(0,worker_supervisor_1.spanOf)(Xe.maxMs)})`:""}`,t,n,e.tail.snapshot())),m.publish((0,worker_supervisor_1.buildWorkerCrashedEvent)(Ae(i,s),{code:t,signal:n,ranMs:o,crashes:d.crashes,restarts:d.restarts,nextInMs:w,external:y.external,lines:e.tail.snapshot()})),clearTimeout(d.pending),d.nextAt=Date.now()+w,d.pending=setTimeout(()=>{d.pending=void 0,d.nextAt=void 0,!(k||G.some(T=>T.name===i))&&(d.restarts+=1,qe(e.spec,"respawn"))},w),d.pending.unref?.()}u(rt,"ct"),a(rt,"workerEnded");function qe(e,t){const n=Ue(e.name);n.waiting=void 0;const i=e.port>0?[...te].find(o=>o.name===e.name&&!Re(o)):void 0;if(!i){ze(e,t);return}console.log(`[parent] Worker "${e.name}" starts once its predecessor (pid=${i.proc.pid}) has finished its work \u2014 it holds port ${e.port}`);const s=a(()=>{n.waiting===s&&(n.waiting=void 0),!k&&!G.some(o=>o.name===e.name)&&ze(e,t)},"go");n.waiting=s,i.proc.once("exit",s)}u(qe,"Ve"),a(qe,"startWorker");const ot=(()=>{const e=Number(process.env.LENSMCP_SWAP_DRAIN_MS);return Number.isFinite(e)&&e>=0?e:15*6e4})(),nt=(()=>{const e=Number(process.env.LENSMCP_SWAP_MAX_DRAINING);return Number.isFinite(e)&&e>=1?Math.floor(e):1})(),te=new Set,Re=a(e=>e.proc.exitCode!==null||e.proc.signalCode!==null,"workerExited");function Be(e,t){if(te.delete(e),!Re(e)){console.error(`[parent] Worker "${e.name}" (pid=${e.proc.pid}) ${t} \u2014 killing it. A worker that returns from its SIGTERM handler but leaves a handle open (a Redis client handed to BullMQ is not closed by worker.close()) never exits on its own: close what it opened, or call process.exit().`);try{e.proc.kill("SIGKILL")}catch{}}}u(Be,"Je"),a(Be,"killDrainingWorker");function Qe(e){e.stopping=!0;try{e.proc.kill("SIGTERM")}catch{}if(Re(e))return;const t=[...te].filter(i=>i.name===e.name);for(;t.length>=nt;)Be(t.shift(),`was still running when a later reload replaced its successor (cap ${nt})`);te.add(e);const n=setTimeout(()=>Be(e,`was still running ${ot}ms after SIGTERM`),ot);n.unref?.(),e.proc.once("exit",()=>{clearTimeout(n),te.delete(e)})}u(Qe,"rt"),a(Qe,"retireWorker");function je(){for(const e of He.values())clearTimeout(e.pending),e.pending=void 0,e.nextAt=void 0,e.waiting=void 0}u(je,"Xe"),a(je,"cancelWorkerStarts");function st(){for(const e of[...G])Qe(e);G.length=0,je();for(const e of WORKER_SPECS)Ue(e.name).crashes=0,qe(e,"reload")}u(st,"lt"),a(st,"restartWorkers");function it(){const e=Date.now();return{workers:WORKER_SPECS.map(t=>{const n=G.find(o=>o.name===t.name),i=He.get(t.name),s=n?"running":i?.pending?(i.crashes??0)>=worker_supervisor_1.CRASH_LOOP_AFTER?"crash-looping":"restarting":i?.waiting?"waiting":i?.missing?"missing":i?.lastEnd?.verdict==="exited"?"exited":"stopped";return{name:t.name,state:s,port:t.port,env:Object.keys(t.env),...n?{pid:n.proc.pid,upMs:e-n.startedAt}:{},crashes:i?.crashes??0,restarts:i?.restarts??0,...i?.nextAt?{nextInMs:Math.max(0,i.nextAt-e)}:{},...i?.lastEnd?{lastEnd:i.lastEnd}:{},...i?.missing?{missing:i.missing}:{}}}),draining:[...te].filter(t=>!Re(t)).map(t=>({name:t.name,pid:t.proc.pid}))}}u(it,"dt"),a(it,"workersView");const ht=debounce(async()=>{ie+=1;const e=Y();if(e.length>0)if(Oe==="process")P();else{console.log(`[parent] Forwarding reload to ${e.length} child(ren)`);for(const t of e)tell(t.proc,{type:"reload"})}await Me(),WORKER_NAMES.length>0&&st()},200),at=a((e,t)=>{const n=(0,notice_generation_1.noticeGeneration)(e.headers);return n===void 0||n===POD_GENERATION?!1:(e.resume(),t.writeHead(409,{"content-type":"application/json"}),t.end(JSON.stringify({ok:!1,generation:POD_GENERATION,sentFor:n})),e.url==="/webpack/reload"&&console.log(`[parent] a build of generation g${n} reached generation g${POD_GENERATION} \u2014 not reloaded: it is not this generation's build`),!0)},"refusedForAnotherGeneration"),Ie=a(async(e,t)=>{if(e.method==="POST"&&e.url==="/webpack/reload"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,t);if(at(e,t))return;t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({ok:!0})),ce(e).then(s=>{const o=s;X=(0,service_build_events_1.buildAccountOf)(o?.build),be=0,ye(o?.watcher)}),ht();return}if(e.method==="POST"&&e.url==="/webpack/watching"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,t);if(at(e,t))return;const s=await ce(e);ye(s),t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({ok:!0,relayed:ae!==void 0}));return}if(e.method==="POST"&&e.url==="/webpack/scale"){if(!(0,devserver_transport_1.mayDriveThePool)(e))return refusePoolCommand(e,t);let s="";e.on("data",o=>{s+=o}),e.on("end",async()=>{let o=0;try{o=Number(JSON.parse(s||"{}").pods)||0}catch{}o=Math.max(1,Math.min(o,16)),await Se(o),t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({ok:!0,pods:o}))});return}if(e.method==="GET"&&e.url?.startsWith("/webpack/logs")){const s=new URL(e.url,"http://localhost").searchParams,o=Math.min(Math.max(Number(s.get("tail")??"100")||0,0),Z),y=s.get("follow")!=="0",d=s.get("plain")==="1",w=!(0,devserver_transport_1.isOwnerOnlyTransport)(e);t.writeHead(200,{"content-type":"text/plain; charset=utf-8","cache-control":"no-cache"});const A=o===0?"":V.slice(-o).join(""),T=d?A.replace(F,""):A;if(t.write(w?(0,inspector_secret_1.redactInspectorUrls)(T):T),!y){t.end();return}const $={res:t,plain:d,redact:w};oe.add($),e.on("close",()=>oe.delete($));return}if(e.method==="POST"&&e.url?.startsWith("/webpack/debug")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not found"}));return}const s=Number(new URL(e.url,"http://localhost").searchParams.get("port")||"");Number.isInteger(s)&&s>1024&&(M=s),M||(M=9229);const o=v.filter(d=>d.proc.exitCode===null&&d.proc.signalCode===null);for(const d of o)d.debugSlot<0&&(d.debugSlot=x()),tell(d.proc,{type:"debug-open",port:inspectorPortFor(M,d.debugSlot)});for(const d of G)try{d.proc.kill("SIGUSR1")}catch{}const y=Date.now()+2e3;for(;Date.now()<y&&o.some(d=>!d.inspectorUrl);)await new Promise(d=>setTimeout(d,50));t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({ok:!0,basePort:M,fixedPorts:usesFixedInspectorPorts(),pods:o.map(d=>({id:d.id,inspectorUrl:d.inspectorUrl??null})),workers:G.map(d=>({name:d.name,port:d.debugPort||(0,inspector_secret_1.inspectorPortOf)(d.inspectorUrl),inspectorUrl:d.inspectorUrl??null}))},null,2)+`
16
+ `);return}if(e.method==="GET"&&e.url==="/webpack/workers"){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not found"}));return}t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify(it(),null,2)+`
17
+ `);return}if(e.method==="GET"&&e.url==="/webpack/memory"){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not found"}));return}const s=path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),o=[...v,...q].map(y=>({id:y.id,pid:y.proc.pid??0,podGeneration:POD_GENERATION,healthy:y.healthy,retiring:q.has(y),latest:y.memory.latest??null,history:y.memory.history,retained:[...y.memory.retained.values()]}));t.writeHead(200,{"content-type":"application/json","cache-control":"no-store"}),t.end(JSON.stringify({ok:!0,service:SERVICE_NAME,project:f,bundle:{path:s},pods:o},null,2)+`
18
+ `);return}if(e.method==="POST"&&e.url?.startsWith("/webpack/heap")){if(!(0,devserver_transport_1.isOwnerOnlyTransport)(e)){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not found"}));return}const s=a((L,Le)=>{t.writeHead(L,{"content-type":"application/json"}),t.end(JSON.stringify(Le,null,2)+`
19
+ `)},"reply"),o=new URL(e.url,"http://localhost").searchParams,y=Number(o.get("pod")||""),d=o.has("maxMb")?Number(o.get("maxMb")):void 0;if(d!==void 0&&!(Number.isFinite(d)&&d>0)){s(400,{ok:!1,error:"maxMb takes a positive number of MB"});return}const w=Number.isInteger(y)&&y>0?v.find(L=>L.id===y):Y()[0];if(!w||D(w)){s(404,{ok:!1,error:y?`no pod #${y} \u2014 running: ${v.map(L=>`#${L.id}`).join(", ")||"none"}`:"no pod is serving"});return}if(Pe.size>0){s(409,{ok:!1,refused:"a heap snapshot is already being written for this service"});return}const A=(0,heap_snapshot_1.heapSnapshotPolicy)(),T=(0,heap_snapshot_1.heapSnapshotDir)();let $;try{(0,heap_snapshot_1.ensureHeapDir)(T);const L=(0,heap_snapshot_1.pruneHeapSnapshots)(T,A);L.length&&console.log(`[parent] removed ${L.length} older heap snapshot(s) from ${T}`),$=path.join(T,(0,heap_snapshot_1.heapSnapshotFileName)(SERVICE_NAME||f,w.id,w.proc.pid??0,w.memory.latest?.gen??0,Date.now()))}catch(L){s(500,{ok:!1,error:`cannot prepare ${T}: ${L.message}`});return}const Q=++Ee,ve=(0,heap_snapshot_1.availableSystemMemory)();let Ge;const R=await new Promise(L=>{const Le=setTimeout(()=>L(void 0),6e5);Le.unref?.(),Pe.set(Q,mt=>{clearTimeout(Le),L(mt)}),Ge=a(()=>{clearTimeout(Le),L(void 0)},"onExit"),w.proc.once("exit",Ge);const wt={type:"heap-snapshot",id:Q,file:$,...ve?{available:ve}:{},...d!==void 0?{maxHeapBytes:Math.floor(d*1048576)}:{}};tell(w.proc,wt)||Ge()}).finally(()=>{Pe.delete(Q),Ge&&w.proc.off("exit",Ge)});if(!R){s(504,{ok:!1,pod:w.id,error:"the pod did not finish the snapshot (it exited, or took longer than 10 minutes)"});return}R.ok?console.log(`[parent] Child#${w.id} wrote a ${Math.round((R.bytes??0)/1048576)} MB heap snapshot in ${R.ms} ms \u2192 ${R.file}`):console.warn(`[parent] Child#${w.id} heap snapshot not taken: ${R.refused??R.error}`),s(R.ok?200:R.refused?409:500,{ok:R.ok,pod:w.id,pid:w.proc.pid??0,service:SERVICE_NAME,bundle:path.isAbsolute(BUNDLE_PATH)?BUNDLE_PATH:path.resolve(BUNDLE_PATH),...ve?{available:ve}:{},...R.file?{file:R.file,bytes:R.bytes,ms:R.ms}:{},...R.live!==void 0?{live:R.live}:{},...R.gen!==void 0?{gen:R.gen,closedAlive:R.closedAlive??[]}:{},...R.refused?{refused:R.refused}:{},...R.error?{error:R.error}:{}});return}const n=matchGatewayRoute(e);if(n?.prependPrefix&&!e.url?.startsWith(n.prependPrefix)&&(e.url=n.prependPrefix+(e.url??"/")),n?.target){applyGatewayMiddleware(e),g.web(e,t,{target:n.target,autoRewrite:typeof n.target=="string",changeOrigin:!0},s=>{console.error(`[parent] proxy error to ${n.target}:`,s),t.statusCode=502,t.setHeader("content-type","text/plain; charset=utf-8"),t.end(`Upstream error from ${n.target}.`)});return}if(SERVICE_PREFIX){if(!e.url?.startsWith(SERVICE_PREFIX)){t.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),t.end(`Not found. This service is mounted at ${SERVICE_PREFIX}/`);return}e.url=e.url.slice(SERVICE_PREFIX.length)||"/"}applyGatewayMiddleware(e);const i=le();if(!i){t.statusCode=503,t.setHeader("content-type","text/plain; charset=utf-8");const s=v.map(o=>`#${o.id}: ${o.lastError??"no error recorded"}`).join(`
20
+ `);t.end(`No healthy children available. POST /webpack/reload to recover.
20
21
 
21
22
  Last errors:
22
- ${a}`);return}_.web(e,r,{target:{socketPath:c.socketPath},headers:{"x-proxy-child-id":String(c.id)}},a=>{console.error(`[parent] proxy error to Child#${c.id}:`,a),c.healthy=!1,c.lastError=String(a?.stack||a),r.statusCode=502,r.setHeader("content-type","text/plain; charset=utf-8"),r.end(`Upstream error from Child#${c.id}. Try /webpack/reload.
23
- ${c.lastError}`)})},"requestHandler");let de,$e,Ke;const Me=[];if(GATEWAY_HTTPS){const e=require("./basic-ssl"),r=GATEWAY_ROUTES.map(c=>c.host).filter(c=>!!c),s=(0,checkout_cache_1.checkoutCacheDir)(process.cwd(),"davnx-webpack");$e=e.getCertificateSync(s,SERVICE_NAME||"lensmcp.dev",r),Ke=e.caCertPath(),de=require("node:https").createServer({key:$e,cert:$e},Te)}else de=http.createServer(Te);const Ze=i((e,r,s)=>{const c=matchGatewayRoute(e);if(c?.prependPrefix&&!e.url?.startsWith(c.prependPrefix)&&(e.url=c.prependPrefix+(e.url??"/")),c?.target){_.ws(e,r,s,{target:c.target,changeOrigin:!0},()=>r.destroy());return}const a=ae();if(!a){r.destroy();return}_.ws(e,r,s,{target:{socketPath:a.socketPath}},()=>r.destroy())},"upgradeHandler");de.on("upgrade",Ze);const et=2e3;let tt=!1;de.on("error",e=>{if(e.code==="EADDRINUSE"){tt||(tt=!0,console.warn(`[parent] public port ${b} already in use \u2014 continuing on the unix-socket pool only (gateway routing is unaffected) and retrying the bind every ${et/1e3}s. Give this service a distinct cluster.port if this is not a rolling handoff.`)),setTimeout(()=>{!k&&!de.listening&&de.listen(b)},et).unref?.();return}console.error("[parent] public server error:",e)}),await we(pe);for(const e of WORKER_NAMES)Be(e);SOCKET_ONLY?console.log(`[parent] socket-only: no TCP listener (port ${b} is not bound \u2014 the gateway reaches this service through its socket pool)`):de.listen(b,()=>{const e=GATEWAY_HTTPS?"https":"http";console.log(`[parent] Listening on ${e}://localhost:${b}`),SERVICE_PREFIX&&console.log(`[parent] Service prefix: "${SERVICE_PREFIX}" (enforced \u2014 requests without it will get 404)`),gatewayMiddleware&&console.log(`[parent] Gateway middleware: ACTIVE (${GATEWAY_MIDDLEWARE_PATH})`),GATEWAY_ROUTES.length>0&&console.log(`[parent] Gateway routes: ${GATEWAY_ROUTES.map(r=>`${r.host??"*"}${r.prefix??"/"}\u2192${r.target??"children"}`).join(" ")}`),Ke&&(console.log("[parent] HTTPS dev CA (trust ONCE, then rotations/new hostnames stay green):"),console.log(`[parent] sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${Ke}`)),console.log(`POST ${e}://localhost:${b}/webpack/reload to trigger rolling swap/respawn`)});const We=Number(process.env.INTERNAL_PORT||0);if(We>0&&!SOCKET_ONLY){const e=i((s,c)=>{const a=ae();if(!a){c.statusCode=503,c.setHeader("content-type","text/plain; charset=utf-8"),c.end("No healthy children available.");return}_.web(s,c,{target:{socketPath:a.socketPath}},o=>{a.healthy=!1,a.lastError=String(o?.stack||o),c.statusCode=502,c.end(`Upstream error from Child#${a.id}.`)})},"internalHandler"),r=http.createServer(e);r.on("upgrade",(s,c,a)=>{const o=ae();if(!o){c.destroy();return}_.ws(s,c,a,{target:{socketPath:o.socketPath}},()=>c.destroy())}),r.on("error",s=>{console.warn(`[parent] internal port ${We} unavailable (${s.code}).`)}),r.listen(We,()=>{console.log(`[parent] Internal (service-to-service, no gateway middleware) on http://localhost:${We}`)}),Me.push(r)}const st=SOCKET_ONLY?[]:(()=>{try{return JSON.parse(process.env.GATEWAY_EXTRA_PORTS||"[]")}catch{return[]}})();for(const e of st){if(!Number.isInteger(e)||e===Number(b))continue;const r=GATEWAY_HTTPS?require("node:https").createServer({key:$e,cert:$e},Te):http.createServer(Te);r.on("upgrade",Ze),r.on("error",s=>{console.warn(`[parent] extra port ${e} unavailable (${s.code}) \u2014 main port still up.`)}),r.listen(e,()=>{console.log(`[parent] Also listening on ${GATEWAY_HTTPS?"https":"http"}://localhost:${e}`)}),Me.push(r)}const ke=path.join(SOCK_DIR,"parent.sock");claimSock(ke),(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);const Oe=http.createServer(Te);Oe.on("error",e=>{console.warn(`[parent] control socket unavailable (${e.code}) \u2014 lensmcp logs/debug attach disabled.`)}),Oe.listen(ke),Me.push(Oe);function rt(){k=!0;const e=[...S,...U];console.log(`[SIGTERM] [parent] generation g${POD_GENERATION} was handed over to a newer one \u2014 ${e.length} pod(s) finish their in-flight work, then it exits`);const r=sockOwnedByAnother(ke);cleanupSock(ke);for(const a of Me)if(!(a===Oe&&r))try{a.close()}catch{}try{de.close()}catch{}for(const a of[...X])Ye(a);X.length=0;for(const a of S)if(!tell(a.proc,{type:"retire"}))try{a.proc.kill("SIGTERM")}catch{}const s=setTimeout(()=>{for(const a of e)if(!I(a)){console.error(`[parent] Child#${a.id} was still running ${d}ms after its generation was retired \u2014 killing it`);try{a.proc.kill("SIGKILL")}catch{}}},d);s.unref?.();const c=i(()=>{if(!(e.some(a=>!I(a))||[...Ee].some(a=>!je(a)))){clearTimeout(s);for(const a of e)a.socketPath&&cleanupSock(a.socketPath,a.proc.pid);(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);try{fs.rmdirSync(SOCK_DIR)}catch{}console.log(`[parent] generation g${POD_GENERATION} retired`),process.exit(0)}},"finish");for(const a of e)a.proc.once("exit",c);for(const a of Ee)a.proc.once("exit",c);c()}h(rt,"nt"),i(rt,"retireGeneration");const ot=i(async e=>{k=!0,console.log(`[${e}] [parent] shutting down\u2026`);const r=sockOwnedByAnother(ke);cleanupSock(ke);for(const s of Me)if(!(s===Oe&&r))try{s.close()}catch{}for(const s of X)try{s.proc.kill("SIGTERM")}catch{}for(const s of[...Ee])Le(s,"was still draining when its devserver shut down");for(const s of U)try{s.proc.kill("SIGTERM")}catch{}for(const s of S){try{s.proc.kill("SIGTERM")}catch{}s.socketPath&&cleanupSock(s.socketPath,s.proc.pid)}try{fs.rmdirSync(SOCK_DIR)}catch{}setTimeout(()=>process.exit(0),700).unref()},"shutdown");let Ve=0;const it=2e3;["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(e=>process.on(e,()=>{if(e==="SIGTERM"){if(!k&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){Ve=Date.now(),rt();return}if(Ve>0&&Date.now()-Ve<it)return}ot(e)}));const Fe=Number(process.env.LENSMCP_GATEWAY_PID??0);if(Number.isInteger(Fe)&&Fe>0){const e=setInterval(()=>{try{process.kill(Fe,0)}catch(r){if(r.code==="EPERM")return;clearInterval(e),console.error(`[parent] gateway (pid ${Fe}) is gone \u2014 shutting the pod down to avoid an orphan tree.`),ot("gateway-gone")}},5e3);e.unref()}})()}
23
+ ${s}`);return}g.web(e,t,{target:{socketPath:i.socketPath},headers:{"x-proxy-child-id":String(i.id)}},s=>{console.error(`[parent] proxy error to Child#${i.id}:`,s),i.healthy=!1,i.lastError=String(s?.stack||s),t.statusCode=502,t.setHeader("content-type","text/plain; charset=utf-8"),t.end(`Upstream error from Child#${i.id}. Try /webpack/reload.
24
+ ${i.lastError}`)})},"requestHandler");let ue,Ce,Ze;const xe=[];if(GATEWAY_HTTPS){const e=require("./basic-ssl"),t=GATEWAY_ROUTES.map(i=>i.host).filter(i=>!!i),n=(0,checkout_cache_1.checkoutCacheDir)(process.cwd(),"davnx-webpack");Ce=e.getCertificateSync(n,SERVICE_NAME||"lensmcp.dev",t),Ze=e.caCertPath(),ue=require("node:https").createServer({key:Ce,cert:Ce},Ie)}else ue=http.createServer(Ie);const ct=a((e,t,n)=>{const i=matchGatewayRoute(e);if(i?.prependPrefix&&!e.url?.startsWith(i.prependPrefix)&&(e.url=i.prependPrefix+(e.url??"/")),i?.target){g.ws(e,t,n,{target:i.target,changeOrigin:!0},()=>t.destroy());return}const s=le();if(!s){t.destroy();return}g.ws(e,t,n,{target:{socketPath:s.socketPath}},()=>t.destroy())},"upgradeHandler");ue.on("upgrade",ct);const lt=2e3;let dt=!1;ue.on("error",e=>{if(e.code==="EADDRINUSE"){dt||(dt=!0,console.warn(`[parent] public port ${b} already in use \u2014 continuing on the unix-socket pool only (gateway routing is unaffected) and retrying the bind every ${lt/1e3}s. Give this service a distinct cluster.port if this is not a rolling handoff.`)),setTimeout(()=>{!k&&!ue.listening&&ue.listen(b)},lt).unref?.();return}console.error("[parent] public server error:",e)}),await Se(he);for(const e of WORKER_SPECS)qe(e,"boot");SOCKET_ONLY?console.log(`[parent] socket-only: no TCP listener (port ${b} is not bound \u2014 the gateway reaches this service through its socket pool)`):ue.listen(b,()=>{const e=GATEWAY_HTTPS?"https":"http";console.log(`[parent] Listening on ${e}://localhost:${b}`),SERVICE_PREFIX&&console.log(`[parent] Service prefix: "${SERVICE_PREFIX}" (enforced \u2014 requests without it will get 404)`),gatewayMiddleware&&console.log(`[parent] Gateway middleware: ACTIVE (${GATEWAY_MIDDLEWARE_PATH})`),GATEWAY_ROUTES.length>0&&console.log(`[parent] Gateway routes: ${GATEWAY_ROUTES.map(t=>`${t.host??"*"}${t.prefix??"/"}\u2192${t.target??"children"}`).join(" ")}`),Ze&&(console.log("[parent] HTTPS dev CA (trust ONCE, then rotations/new hostnames stay green):"),console.log(`[parent] sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${Ze}`)),console.log(`POST ${e}://localhost:${b}/webpack/reload to trigger rolling swap/respawn`)});const Ke=Number(process.env.INTERNAL_PORT||0);if(Ke>0&&!SOCKET_ONLY){const e=a((n,i)=>{const s=le();if(!s){i.statusCode=503,i.setHeader("content-type","text/plain; charset=utf-8"),i.end("No healthy children available.");return}g.web(n,i,{target:{socketPath:s.socketPath}},o=>{s.healthy=!1,s.lastError=String(o?.stack||o),i.statusCode=502,i.end(`Upstream error from Child#${s.id}.`)})},"internalHandler"),t=http.createServer(e);t.on("upgrade",(n,i,s)=>{const o=le();if(!o){i.destroy();return}g.ws(n,i,s,{target:{socketPath:o.socketPath}},()=>i.destroy())}),t.on("error",n=>{console.warn(`[parent] internal port ${Ke} unavailable (${n.code}).`)}),t.listen(Ke,()=>{console.log(`[parent] Internal (service-to-service, no gateway middleware) on http://localhost:${Ke}`)}),xe.push(t)}const ft=SOCKET_ONLY?[]:(()=>{try{return JSON.parse(process.env.GATEWAY_EXTRA_PORTS||"[]")}catch{return[]}})();for(const e of ft){if(!Number.isInteger(e)||e===Number(b))continue;const t=GATEWAY_HTTPS?require("node:https").createServer({key:Ce,cert:Ce},Ie):http.createServer(Ie);t.on("upgrade",ct),t.on("error",n=>{console.warn(`[parent] extra port ${e} unavailable (${n.code}) \u2014 main port still up.`)}),t.listen(e,()=>{console.log(`[parent] Also listening on ${GATEWAY_HTTPS?"https":"http"}://localhost:${e}`)}),xe.push(t)}const Ne=path.join(SOCK_DIR,"parent.sock");claimSock(Ne),(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);const De=http.createServer(Ie);De.on("error",e=>{console.warn(`[parent] control socket unavailable (${e.code}) \u2014 lensmcp logs/debug attach disabled.`)}),De.listen(Ne),xe.push(De);function pt(){k=!0;const e=[...v,...q];console.log(`[SIGTERM] [parent] generation g${POD_GENERATION} was handed over to a newer one \u2014 ${e.length} pod(s) finish their in-flight work, then it exits`);const t=sockOwnedByAnother(Ne);cleanupSock(Ne);for(const s of xe)if(!(s===De&&t))try{s.close()}catch{}try{ue.close()}catch{}je();for(const s of[...G])Qe(s);G.length=0;for(const s of v)if(!tell(s.proc,{type:"retire"}))try{s.proc.kill("SIGTERM")}catch{}const n=setTimeout(()=>{for(const s of e)if(!D(s)){console.error(`[parent] Child#${s.id} was still running ${p}ms after its generation was retired \u2014 killing it`);try{s.proc.kill("SIGKILL")}catch{}}},p);n.unref?.();const i=a(()=>{if(!(e.some(s=>!D(s))||[...te].some(s=>!Re(s)))){clearTimeout(n);for(const s of e)s.socketPath&&cleanupSock(s.socketPath,s.proc.pid);(0,handoff_retire_1.clearHandoffRetire)(SOCK_DIR,POD_GENERATION);try{fs.rmdirSync(SOCK_DIR)}catch{}console.log(`[parent] generation g${POD_GENERATION} retired`),process.exit(0)}},"finish");for(const s of e)s.proc.once("exit",i);for(const s of te)s.proc.once("exit",i);i()}u(pt,"ht"),a(pt,"retireGeneration");const ut=a(async e=>{k=!0,console.log(`[${e}] [parent] shutting down\u2026`);const t=sockOwnedByAnother(Ne);cleanupSock(Ne);for(const n of xe)if(!(n===De&&t))try{n.close()}catch{}je();for(const n of G){n.stopping=!0;try{n.proc.kill("SIGTERM")}catch{}}for(const n of WORKER_SPECS){const i=G.find(s=>s.name===n.name)?.proc.pid??0;m.publish((0,worker_supervisor_1.buildWorkerStoppedEvent)(Ae(n.name,i),{reason:`its devserver stopped (${e})`}))}for(const n of[...te])Be(n,"was still draining when its devserver shut down");for(const n of q)try{n.proc.kill("SIGTERM")}catch{}for(const n of v){try{n.proc.kill("SIGTERM")}catch{}n.socketPath&&cleanupSock(n.socketPath,n.proc.pid)}try{fs.rmdirSync(SOCK_DIR)}catch{}setTimeout(()=>process.exit(0),700).unref()},"shutdown");let et=0;const _t=2e3;["SIGINT","SIGTERM","SIGHUP","SIGQUIT","SIGUSR2"].forEach(e=>process.on(e,()=>{if(e==="SIGTERM"){if(!k&&(0,handoff_retire_1.handoffRetireRequested)(SOCK_DIR,POD_GENERATION)){et=Date.now(),pt();return}if(et>0&&Date.now()-et<_t)return}ut(e)}));const Ye=Number(process.env.LENSMCP_GATEWAY_PID??0);if(Number.isInteger(Ye)&&Ye>0){const e=setInterval(()=>{try{process.kill(Ye,0)}catch(t){if(t.code==="EPERM")return;clearInterval(e),console.error(`[parent] gateway (pid ${Ye}) is gone \u2014 shutting the pod down to avoid an orphan tree.`),ut("gateway-gone")}},5e3);e.unref()}})()}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/cluster",
3
- "version": "1.25.3",
3
+ "version": "1.25.5",
4
4
  "description": "Run your Nx workspace as a local production cluster: pods on unix sockets with true HMR, one https gateway with per-project domains, scale-from-zero, autoscale, idle-kill, local-CA TLS — observed by the LensMCP lens.",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -29,6 +29,7 @@
29
29
  "@nx/devkit": ">=20.0.0",
30
30
  "@nx/webpack": ">=20.0.0",
31
31
  "webpack": "^5.0.0",
32
+ "typescript": ">=5.0.0",
32
33
  "ioredis": "^5.0.0",
33
34
  "@opentelemetry/api": "^1.9.0",
34
35
  "@opentelemetry/core": "^2.9.0",
@@ -57,9 +58,9 @@
57
58
  }
58
59
  },
59
60
  "dependencies": {
60
- "@lensmcp/core": "1.25.3",
61
- "@lensmcp/node-instrumentation": "1.25.3",
62
- "@lensmcp/nx-plugin": "1.25.3",
61
+ "@lensmcp/core": "1.25.5",
62
+ "@lensmcp/node-instrumentation": "1.25.5",
63
+ "@lensmcp/nx-plugin": "1.25.5",
63
64
  "fastify": "^5.8.5",
64
65
  "@fastify/reply-from": "^12.6.2",
65
66
  "@typescript/native-preview": "^7.0.0-dev.20260707.2",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const orphanMs=(()=>{const e=Number(process.env.LENSMCP_WORKER_ORPHAN_MS);return Number.isFinite(e)&&e>=0&&process.env.LENSMCP_WORKER_ORPHAN_MS!==""?e:1e4})();typeof process.send=="function"&&process.channel&&(process.once("disconnect",()=>{for(const e of[process.stdout,process.stderr])e.on("error",()=>{});setTimeout(()=>process.exit(0),orphanMs).unref(),process.kill(process.pid,"SIGTERM")}),process.channel.unref());
@@ -0,0 +1,142 @@
1
+ /** One worker, as the devserver runs it. */
2
+ export interface WorkerSpec {
3
+ /** The bundle's entry name — `<bundle dir>/<name>.js`. */
4
+ name: string;
5
+ /** Merged over the devserver's environment. */
6
+ env: Record<string, string>;
7
+ /** The `PORT` the worker gets: 0 — the kernel picks a free one — unless one is declared. */
8
+ port: number;
9
+ }
10
+ /** A `workers` entry of the serve executor, as project.json declares it. */
11
+ export interface WorkerEntryOptions {
12
+ name: string;
13
+ env?: Record<string, unknown>;
14
+ port?: number;
15
+ }
16
+ /** What the serve executor hands the devserver in `WORKERS`: each worker's name, env and port. */
17
+ export declare function serializeWorkerSpecs(workers: readonly WorkerEntryOptions[]): string;
18
+ /**
19
+ * `WORKERS` read back: a list of names (what a devserver was handed before 1.25.3) or of `{ name, env?, port? }`. What
20
+ * cannot be used is left out and said in `problems` — a bad entry never stops the others.
21
+ */
22
+ export declare function parseWorkerSpecs(raw: string | undefined): {
23
+ specs: WorkerSpec[];
24
+ problems: string[];
25
+ };
26
+ /**
27
+ * The worker's environment: the devserver's, then its `PORT` — never the devserver's own, which the devserver is
28
+ * listening on — then what it declares. `LENSMCP_WORKER` names it, for a bundle shared by the pods and a worker.
29
+ */
30
+ export declare function workerEnv(base: NodeJS.ProcessEnv, spec: WorkerSpec): NodeJS.ProcessEnv;
31
+ /** How a worker that ended is started again. */
32
+ export interface WorkerBackoff {
33
+ /** The first wait; it doubles with each crash in a row. */
34
+ baseMs: number;
35
+ maxMs: number;
36
+ /** Up this long, a worker's crashes in a row start again from none. */
37
+ stableMs: number;
38
+ }
39
+ /** Crashes in a row from which a worker is called crash-looping. */
40
+ export declare const CRASH_LOOP_AFTER = 3;
41
+ /** The shortest wait before a crashed worker starts again, whatever is configured: a worker that dies at boot must not spin. */
42
+ export declare const MIN_RESPAWN_MS = 100;
43
+ /** `LENSMCP_WORKER_BACKOFF_MS` (1 s, at least {@link MIN_RESPAWN_MS}), `LENSMCP_WORKER_BACKOFF_MAX_MS` (60 s), `LENSMCP_WORKER_STABLE_MS` (30 s). */
44
+ export declare function workerBackoff(env?: NodeJS.ProcessEnv): WorkerBackoff;
45
+ /** The wait before the next start after `crashes` crashes in a row (1 → `baseMs`): doubling, up to `maxMs`. */
46
+ export declare function respawnDelay(crashes: number, b: WorkerBackoff): number;
47
+ /**
48
+ * Why a worker ended:
49
+ * - `stopped` — it was asked to: replaced by a new build's, or its devserver is stopping;
50
+ * - `exited` — it ended on its own with code 0: taken to have finished its work, and not started again until the
51
+ * next build (a one-shot worker must not be run in a loop);
52
+ * - `crashed` — anything else: an exit code, a signal — `external` when it is a stop signal nobody here sent
53
+ * (`kill <pid>`): started again either way, as a supervisor does.
54
+ */
55
+ export type WorkerExitVerdict = {
56
+ kind: 'stopped';
57
+ } | {
58
+ kind: 'exited';
59
+ } | {
60
+ kind: 'crashed';
61
+ external: boolean;
62
+ };
63
+ export declare function workerExitVerdict(code: number | null, signal: NodeJS.Signals | null, asked: boolean): WorkerExitVerdict;
64
+ /** `1.5 s`, `42 s`, `3 min`. */
65
+ export declare function spanOf(ms: number): string;
66
+ /**
67
+ * What the lens hears of a worker — `source: 'gateway'`, `category: 'cluster'`, the cluster's voice that the agent's
68
+ * cluster health and the dashboard's Cluster page fold:
69
+ * - `worker-started` — a worker process began: at boot, after a build (`reload`), or after it ended (`respawn`);
70
+ * - `worker-up` — one that had crashed has now stayed up `stableMs`: its crashes in a row are over;
71
+ * - `worker-crashed` — it ended unasked; when it starts again, and whether it is crash-looping;
72
+ * - `worker-exited` — it ended on its own with code 0, or never started (its bundle is missing): not started again
73
+ * until the next build;
74
+ * - `worker-stopped` — its devserver stopped.
75
+ * Every event names the worker's pid: a reader applies an end to the process it names, never to its successor.
76
+ */
77
+ export type WorkerEventKind = 'worker-started' | 'worker-up' | 'worker-crashed' | 'worker-exited' | 'worker-stopped';
78
+ /** Who a worker is — stamped into every event's `raw`. */
79
+ export interface WorkerIdentity {
80
+ project: string;
81
+ service: string;
82
+ worker: string;
83
+ pid: number;
84
+ /** The devserver tree's generation (`LENSMCP_POD_GENERATION`). */
85
+ podGeneration: number;
86
+ }
87
+ export interface WorkerBusEvent {
88
+ id: string;
89
+ sessionId: string;
90
+ timestamp: number;
91
+ source: 'gateway';
92
+ category: 'cluster';
93
+ severity: 'info' | 'warning' | 'error';
94
+ context: {
95
+ sessionId: string;
96
+ projectName: string;
97
+ };
98
+ fingerprint: string;
99
+ title: string;
100
+ message?: string;
101
+ raw: Record<string, unknown>;
102
+ }
103
+ export interface WorkerStarted {
104
+ why: 'boot' | 'reload' | 'respawn';
105
+ port: number;
106
+ restarts: number;
107
+ }
108
+ export interface WorkerCrashed {
109
+ code: number | null;
110
+ signal: NodeJS.Signals | null;
111
+ ranMs: number;
112
+ crashes: number;
113
+ restarts: number;
114
+ nextInMs: number;
115
+ external: boolean;
116
+ /** The worker's last lines of output, as it printed them ({@link crashLines} folds them). */
117
+ lines: string[];
118
+ }
119
+ export interface WorkerUp {
120
+ ranMs: number;
121
+ afterCrashes: number;
122
+ }
123
+ export interface WorkerExited {
124
+ ranMs: number;
125
+ reason?: string;
126
+ }
127
+ export interface WorkerStopped {
128
+ reason: string;
129
+ }
130
+ /** Lines a crash event carries — the end of what the worker said, its stack folded ({@link crashLines}). */
131
+ export declare const CRASH_LINES = 12;
132
+ /**
133
+ * The end of what a worker said before it died, for a reader: a stack's frames past the first few folded into one line
134
+ * — an uncaught error's message and what the app logged before it are what say why; twenty frames of module loader do
135
+ * not, and kept whole they pushed both out of the window.
136
+ */
137
+ export declare function crashLines(tail: readonly string[], max?: number): string[];
138
+ export declare function buildWorkerStartedEvent(who: WorkerIdentity, s: WorkerStarted, at?: number, id?: () => string): WorkerBusEvent;
139
+ export declare function buildWorkerUpEvent(who: WorkerIdentity, u: WorkerUp, at?: number, id?: () => string): WorkerBusEvent;
140
+ export declare function buildWorkerCrashedEvent(who: WorkerIdentity, c: WorkerCrashed, at?: number, id?: () => string): WorkerBusEvent;
141
+ export declare function buildWorkerExitedEvent(who: WorkerIdentity, e: WorkerExited, at?: number, id?: () => string): WorkerBusEvent;
142
+ export declare function buildWorkerStoppedEvent(who: WorkerIdentity, s: WorkerStopped, at?: number, id?: () => string): WorkerBusEvent;
@@ -0,0 +1,2 @@
1
+ "use strict";var k=Object.defineProperty;var a=(r,e)=>k(r,"name",{value:e,configurable:!0});var f=Object.defineProperty,i=a((r,e)=>f(r,"name",{value:e,configurable:!0}),"i");Object.defineProperty(exports,"__esModule",{value:!0}),exports.CRASH_LINES=exports.MIN_RESPAWN_MS=exports.CRASH_LOOP_AFTER=void 0,exports.serializeWorkerSpecs=serializeWorkerSpecs,exports.parseWorkerSpecs=parseWorkerSpecs,exports.workerEnv=workerEnv,exports.workerBackoff=workerBackoff,exports.respawnDelay=respawnDelay,exports.workerExitVerdict=workerExitVerdict,exports.spanOf=spanOf,exports.crashLines=crashLines,exports.buildWorkerStartedEvent=buildWorkerStartedEvent,exports.buildWorkerUpEvent=buildWorkerUpEvent,exports.buildWorkerCrashedEvent=buildWorkerCrashedEvent,exports.buildWorkerExitedEvent=buildWorkerExitedEvent,exports.buildWorkerStoppedEvent=buildWorkerStoppedEvent;const exit_reason_1=require("./exit-reason"),NAME_RE=/^[\w.-]+$/,ENV_KEY_RE=/^[A-Za-z_][A-Za-z0-9_]*$/;function serializeWorkerSpecs(r){return JSON.stringify(r.map(e=>({name:e.name,...e.env&&typeof e.env=="object"?{env:e.env}:{},...e.port!==void 0?{port:e.port}:{}})))}a(serializeWorkerSpecs,"serializeWorkerSpecs"),i(serializeWorkerSpecs,"serializeWorkerSpecs");function parseWorkerSpecs(r){const e=[];let t;try{t=JSON.parse(r||"[]")}catch{return{specs:[],problems:[`WORKERS is not JSON: ${String(r).slice(0,80)}`]}}if(!Array.isArray(t))return{specs:[],problems:["WORKERS is not a list"]};const n=[];for(const s of t){const o=typeof s=="string"?{name:s}:s,p=typeof o?.name=="string"?o.name:"";if(!NAME_RE.test(p)){e.push(`worker ${JSON.stringify(o?.name??s)} is not a plain file name \u2014 not started`);continue}if(n.some(d=>d.name===p)){e.push(`worker "${p}" is declared twice \u2014 started once`);continue}const u={};for(const[d,l]of Object.entries(o?.env&&typeof o.env=="object"?o.env:{})){if(!ENV_KEY_RE.test(d)){e.push(`worker "${p}": env ${JSON.stringify(d)} is not a variable name \u2014 left out`);continue}typeof l=="string"||typeof l=="number"||typeof l=="boolean"?u[d]=String(l):e.push(`worker "${p}": env ${d} is not a string, number or boolean \u2014 left out`)}let c=0;o?.port!==void 0&&(Number.isInteger(o.port)&&o.port>=0&&o.port<=65535?c=o.port:e.push(`worker "${p}": port ${JSON.stringify(o.port)} is not a port \u2014 it gets 0 (a free one)`)),n.push({name:p,env:u,port:c})}return{specs:n,problems:e}}a(parseWorkerSpecs,"parseWorkerSpecs"),i(parseWorkerSpecs,"parseWorkerSpecs");function workerEnv(r,e){const t={...r,PORT:String(e.port),...e.env,LENSMCP_WORKER:e.name};return delete t.WORKERS,t}a(workerEnv,"workerEnv"),i(workerEnv,"workerEnv"),exports.CRASH_LOOP_AFTER=3;function envMs(r,e,t){const n=Number(r[e]);return r[e]!==void 0&&r[e]!==""&&Number.isFinite(n)&&n>=0?Math.floor(n):t}a(envMs,"envMs"),i(envMs,"envMs"),exports.MIN_RESPAWN_MS=100;function workerBackoff(r=process.env){const e=Math.max(exports.MIN_RESPAWN_MS,envMs(r,"LENSMCP_WORKER_BACKOFF_MS",1e3));return{baseMs:e,maxMs:Math.max(e,envMs(r,"LENSMCP_WORKER_BACKOFF_MAX_MS",6e4)),stableMs:envMs(r,"LENSMCP_WORKER_STABLE_MS",3e4)}}a(workerBackoff,"workerBackoff"),i(workerBackoff,"workerBackoff");function respawnDelay(r,e){const t=Math.max(1,Math.floor(r));return Math.min(e.maxMs,e.baseMs*2**Math.min(t-1,30))}a(respawnDelay,"respawnDelay"),i(respawnDelay,"respawnDelay");function workerExitVerdict(r,e,t){return t?{kind:"stopped"}:r===0&&!e?{kind:"exited"}:{kind:"crashed",external:e==="SIGTERM"||e==="SIGINT"||e==="SIGHUP"}}a(workerExitVerdict,"workerExitVerdict"),i(workerExitVerdict,"workerExitVerdict");function spanOf(r){return r<1e4?`${Math.round(r/100)/10} s`:r<12e4?`${Math.round(r/1e3)} s`:`${Math.round(r/6e4)} min`}a(spanOf,"spanOf"),i(spanOf,"spanOf"),exports.CRASH_LINES=12;const STACK_FRAMES=3;function crashLines(r,e=exports.CRASH_LINES){const t=[];let n=0,s=0;const o=i(()=>{s&&t.push(` \u2026 ${s} more frame${s===1?"":"s"}`),s=0},"fold");for(const p of r){if(/^\s+at\s/.test(p)){if(n+=1,n>STACK_FRAMES){s+=1;continue}}else o(),n=0;t.push(p)}return o(),t.slice(-e)}a(crashLines,"crashLines"),i(crashLines,"crashLines");let idCounter=0;function makeId(){return idCounter=(idCounter+1)%65535,`${Date.now().toString(36)}${idCounter.toString(36)}${Math.random().toString(36).slice(2,8)}`}a(makeId,"makeId"),i(makeId,"makeId");function envelope(r,e,t,n,s,o,p,u){const c="pending";return{id:p(),sessionId:c,timestamp:o,source:"gateway",category:"cluster",severity:t,context:{sessionId:c,projectName:r.project},fingerprint:`cluster-${e}:${r.service}`,title:n,...u?{message:u}:{},raw:{kind:e,project:r.project,service:r.service,worker:r.worker,pid:r.pid,podGeneration:r.podGeneration,...s}}}a(envelope,"envelope"),i(envelope,"envelope");function buildWorkerStartedEvent(r,e,t=Date.now(),n=makeId){const s=e.why==="respawn"?`started again (restart ${e.restarts})`:e.why==="reload"?"started on the new build":"started";return envelope(r,"worker-started","info",`${r.service} worker ${r.worker} ${s} \u2014 pid ${r.pid}`,{why:e.why,port:e.port,restarts:e.restarts},t,n)}a(buildWorkerStartedEvent,"buildWorkerStartedEvent"),i(buildWorkerStartedEvent,"buildWorkerStartedEvent");function buildWorkerUpEvent(r,e,t=Date.now(),n=makeId){return envelope(r,"worker-up","info",`${r.service} worker ${r.worker} is up again \u2014 ${spanOf(e.ranMs)} without a crash, after ${e.afterCrashes} in a row`,{ranMs:e.ranMs,afterCrashes:e.afterCrashes},t,n)}a(buildWorkerUpEvent,"buildWorkerUpEvent"),i(buildWorkerUpEvent,"buildWorkerUpEvent");function buildWorkerCrashedEvent(r,e,t=Date.now(),n=makeId){const s=e.crashes>=exports.CRASH_LOOP_AFTER,o=e.signal?e.signal:`exit ${e.code}`,p=s?`${r.service} worker ${r.worker} is crash-looping \u2014 ${e.crashes} crashes in a row (${o}); next start in ${spanOf(e.nextInMs)}`:`${r.service} worker ${r.worker} crashed (${o}${e.external?", a signal from outside its devserver":""}) after ${spanOf(e.ranMs)} \u2014 starting it again in ${spanOf(e.nextInMs)}`,u=e.external?`stopped by ${e.signal} from outside its devserver (\`kill\`, Activity Monitor)`:(0,exit_reason_1.describeExit)(e.code,e.signal),c=crashLines(e.lines);return envelope(r,"worker-crashed","error",p,{exitCode:e.code,signal:e.signal,ranMs:e.ranMs,crashes:e.crashes,restarts:e.restarts,nextInMs:e.nextInMs,crashLooping:s,external:e.external,...u?{reading:u}:{},lines:c},t,n,c.length?c.join(`
2
+ `):void 0)}a(buildWorkerCrashedEvent,"buildWorkerCrashedEvent"),i(buildWorkerCrashedEvent,"buildWorkerCrashedEvent");function buildWorkerExitedEvent(r,e,t=Date.now(),n=makeId){const s=e.reason??`it ended on its own (code 0) after ${spanOf(e.ranMs)}`;return envelope(r,"worker-exited","warning",`${r.service} worker ${r.worker} is not running \u2014 ${s}; not started again until the next build`,{ranMs:e.ranMs,...e.reason?{reason:e.reason}:{}},t,n)}a(buildWorkerExitedEvent,"buildWorkerExitedEvent"),i(buildWorkerExitedEvent,"buildWorkerExitedEvent");function buildWorkerStoppedEvent(r,e,t=Date.now(),n=makeId){return envelope(r,"worker-stopped","info",`${r.service} worker ${r.worker} stopped \u2014 ${e.reason}`,{reason:e.reason},t,n)}a(buildWorkerStoppedEvent,"buildWorkerStoppedEvent"),i(buildWorkerStoppedEvent,"buildWorkerStoppedEvent");