daimon 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/dist/cli.js +178 -74
- package/dist/dashboard/browser/{chunk-YNCTXEXX.js → chunk-2BXIFQGQ.js} +1 -1
- package/dist/dashboard/browser/{chunk-6BDWIJ3G.js → chunk-3WKRVGPT.js} +1 -1
- package/dist/dashboard/browser/chunk-44JIQO3X.js +1 -0
- package/dist/dashboard/browser/chunk-4BAKWDAV.js +1 -0
- package/dist/dashboard/browser/chunk-4OCNYL7T.js +1 -0
- package/dist/dashboard/browser/chunk-6WZJCF24.js +1 -0
- package/dist/dashboard/browser/chunk-7C772RJ3.js +3 -0
- package/dist/dashboard/browser/{chunk-25VLDASM.js → chunk-7NPLP3QD.js} +1 -1
- package/dist/dashboard/browser/chunk-A4BNXJUT.js +1 -0
- package/dist/dashboard/browser/{chunk-YA4AZONZ.js → chunk-CM4RQF3A.js} +1 -1
- package/dist/dashboard/browser/chunk-CNSXWFDX.js +1 -0
- package/dist/dashboard/browser/chunk-CY5YRTQK.js +1 -0
- package/dist/dashboard/browser/{chunk-5PAHWCG5.js → chunk-EIWOTZT3.js} +1 -1
- package/dist/dashboard/browser/{chunk-ZEO5YLWG.js → chunk-GYWEXV2L.js} +1 -1
- package/dist/dashboard/browser/chunk-H2N3RBHF.js +1 -0
- package/dist/dashboard/browser/{chunk-RIDV4B55.js → chunk-H3L4MTG4.js} +1 -1
- package/dist/dashboard/browser/{chunk-ZVUH3ISD.js → chunk-I65I7J5Q.js} +1 -1
- package/dist/dashboard/browser/chunk-K7S4ITPJ.js +2 -0
- package/dist/dashboard/browser/chunk-KL6X73FV.js +1 -0
- package/dist/dashboard/browser/{chunk-Q3N4MMWW.js → chunk-LBL7Z5BE.js} +4 -4
- package/dist/dashboard/browser/chunk-LHAMBNO6.js +1 -0
- package/dist/dashboard/browser/chunk-NX6DTO32.js +1 -0
- package/dist/dashboard/browser/chunk-P5IE6DI6.js +2 -0
- package/dist/dashboard/browser/{chunk-SR5JAOLW.js → chunk-Q772THBA.js} +1 -1
- package/dist/dashboard/browser/{chunk-OUXULJ3Z.js → chunk-QSBOKS53.js} +1 -1
- package/dist/dashboard/browser/{chunk-HYGMRGYR.js → chunk-V2KNRAE4.js} +1 -1
- package/dist/dashboard/browser/{chunk-GDJOSLWM.js → chunk-VM2FOT77.js} +1 -1
- package/dist/dashboard/browser/index.html +1 -1
- package/dist/dashboard/browser/main-4CQTBXSB.js +1 -0
- package/dist/main.js +58 -48
- package/dist/mcp.js +3 -3
- package/package.json +2 -2
- package/src/templates/claude/skill.md.tmpl +4 -1
- package/src/templates/plugins/example-doctor.mjs +45 -0
- package/dist/dashboard/browser/chunk-6C6GHU3A.js +0 -1
- package/dist/dashboard/browser/chunk-BDYOKQF3.js +0 -1
- package/dist/dashboard/browser/chunk-HYIZMKSF.js +0 -1
- package/dist/dashboard/browser/chunk-IQZZO5IM.js +0 -3
- package/dist/dashboard/browser/chunk-J5UK77OJ.js +0 -1
- package/dist/dashboard/browser/chunk-JI63U3KC.js +0 -2
- package/dist/dashboard/browser/chunk-L2PHC6DL.js +0 -1
- package/dist/dashboard/browser/chunk-MHYQENOC.js +0 -1
- package/dist/dashboard/browser/chunk-UU5K6ZPO.js +0 -1
- package/dist/dashboard/browser/chunk-XXIJQBCQ.js +0 -2
- package/dist/dashboard/browser/chunk-ZDNBWNU5.js +0 -1
- package/dist/dashboard/browser/main-IDF27PFI.js +0 -1
package/dist/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,"utf8"),{kind:"stub-created",path:t}}var
|
|
3
|
-
`);return[...e.values()].filter(i=>!i.hidden)}var
|
|
1
|
+
var qn=Object.defineProperty;var rt=(r,t)=>()=>(r&&(t=r(r=0)),t);var Ft=(r,t)=>{for(var e in t)qn(r,e,{get:t[e],enumerable:!0})};var pr={};Ft(pr,{configLookupPaths:()=>dt,loadConfig:()=>Q,validateConfig:()=>It});import st from"node:fs";import nt from"node:path";import Et from"node:os";import{fileURLToPath as Jn}from"node:url";function ur(){return{searchRoots:[],portRange:[4200,4299],apiPort:4999,overrides:{},autoStart:[],profiles:{},tags:{},autoRestart:{enabled:!1,maxAttempts:5,windowMs:3e5},healthProbe:{enabled:!0,intervalMs:3e4,timeoutMs:2e3,path:"/",host:null,scheme:null,rejectUnauthorized:!1,fallbackHosts:["127.0.0.1","::1"]},logs:{enabled:!1,dir:nt.join(Et.homedir(),".daimon","logs"),maxFiles:5,maxBytesPerFile:1e7},depends:{},cascadeRestart:!1,history:{enabled:!0,path:nt.join(Et.homedir(),".daimon","history.db"),retentionDays:30},notifications:{enabled:!0,onError:!0,onUnhealthy:!0,tray:!1},staleDetect:{enabled:!0,silentMs:3e4},headless:!1,envFiles:{},requestLog:{enabled:!1,portOffset:1e3},metrics:{enabled:!1},editor:{scheme:"vscode"},apiToken:null,output:{format:"compact",ndjson:!1},doctor:{autoFix:{onInit:!1,permitted:["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"]}},dashboard:{theme:"auto",density:"comfortable"},errorRetention:{maxAgeMs:864e5},plugins:{dir:null}}}function ye(r){return r.startsWith("~/")||r.startsWith("~\\")?nt.join(Et.homedir(),r.slice(2)):r==="~"?Et.homedir():r}function It(r,t){return ve(r,t)}function ve(r,t){if(!r||typeof r!="object")throw new Error(`Config at ${t} is not a JSON object`);let e=r,n=ur();if(e.searchRoots!==void 0){if(!Array.isArray(e.searchRoots)||!e.searchRoots.every(s=>typeof s=="string"||s&&typeof s=="object"&&typeof s.path=="string"))throw new Error(`Config "searchRoots" must be an array of strings or { path, viteSubfolders? } objects (${t})`);n.searchRoots=e.searchRoots}if(e.portRange!==void 0){if(!Array.isArray(e.portRange)||e.portRange.length!==2||typeof e.portRange[0]!="number"||typeof e.portRange[1]!="number"||e.portRange[0]>e.portRange[1])throw new Error(`Config "portRange" must be [min, max] numbers (${t})`);n.portRange=[e.portRange[0],e.portRange[1]]}if(e.apiPort!==void 0){if(typeof e.apiPort!="number")throw new Error(`Config "apiPort" must be a number (${t})`);n.apiPort=e.apiPort}if(e.overrides!==void 0){if(typeof e.overrides!="object"||e.overrides===null||Array.isArray(e.overrides))throw new Error(`Config "overrides" must be an object (${t})`);n.overrides=e.overrides}if(e.autoStart!==void 0){if(!Array.isArray(e.autoStart)||!e.autoStart.every(s=>typeof s=="string"))throw new Error(`Config "autoStart" must be an array of strings (${t})`);n.autoStart=e.autoStart}if(e.profiles!==void 0){if(typeof e.profiles!="object"||e.profiles===null||Array.isArray(e.profiles))throw new Error(`Config "profiles" must be an object (${t})`);for(let[s,i]of Object.entries(e.profiles))if(!Array.isArray(i)||!i.every(o=>typeof o=="string"))throw new Error(`Config "profiles.${s}" must be an array of strings (${t})`);n.profiles=e.profiles}if(e.tags!==void 0){if(typeof e.tags!="object"||e.tags===null||Array.isArray(e.tags))throw new Error(`Config "tags" must be an object (${t})`);n.tags=e.tags}if(e.autoRestart&&typeof e.autoRestart=="object"&&(n.autoRestart={...n.autoRestart,...e.autoRestart}),e.healthProbe&&typeof e.healthProbe=="object"&&(n.healthProbe={...n.healthProbe,...e.healthProbe}),e.logs&&typeof e.logs=="object"&&(n.logs={...n.logs,...e.logs},n.logs.dir=ye(n.logs.dir)),e.depends&&typeof e.depends=="object"&&!Array.isArray(e.depends)){for(let[s,i]of Object.entries(e.depends))if(!Array.isArray(i)||!i.every(o=>typeof o=="string"))throw new Error(`Config "depends.${s}" must be an array of strings (${t})`);n.depends=e.depends}if(typeof e.cascadeRestart=="boolean"&&(n.cascadeRestart=e.cascadeRestart),e.history&&typeof e.history=="object"&&(n.history={...n.history,...e.history},n.history.path=ye(n.history.path)),e.notifications&&typeof e.notifications=="object"&&(n.notifications={...n.notifications,...e.notifications}),e.staleDetect&&typeof e.staleDetect=="object"&&(n.staleDetect={...n.staleDetect,...e.staleDetect}),typeof e.headless=="boolean"&&(n.headless=e.headless),e.envFiles&&typeof e.envFiles=="object"&&!Array.isArray(e.envFiles)&&(n.envFiles=e.envFiles),e.requestLog&&typeof e.requestLog=="object"&&(n.requestLog={...n.requestLog,...e.requestLog}),e.metrics&&typeof e.metrics=="object"&&(n.metrics={...n.metrics,...e.metrics}),e.editor&&typeof e.editor=="object"){let s=e.editor.scheme;typeof s=="string"&&s.trim()&&(n.editor={scheme:s.trim()})}if((typeof e.apiToken=="string"||e.apiToken===null)&&(n.apiToken=e.apiToken),e.output&&typeof e.output=="object"){let s=e.output;(s.format==="compact"||s.format==="full")&&(n.output.format=s.format),typeof s.ndjson=="boolean"&&(n.output.ndjson=s.ndjson)}if(e.doctor&&typeof e.doctor=="object"){let s=e.doctor.autoFix;s&&typeof s=="object"&&(typeof s.onInit=="boolean"&&(n.doctor.autoFix.onInit=s.onInit),Array.isArray(s.permitted)&&(n.doctor.autoFix.permitted=s.permitted.filter(i=>typeof i=="string")))}if(e.dashboard&&typeof e.dashboard=="object"){let s=e.dashboard;(s.theme==="auto"||s.theme==="light"||s.theme==="dark")&&(n.dashboard.theme=s.theme),(s.density==="comfortable"||s.density==="compact")&&(n.dashboard.density=s.density)}if(e.errorRetention&&typeof e.errorRetention=="object"){let s=e.errorRetention;typeof s.maxAgeMs=="number"&&s.maxAgeMs>0&&(n.errorRetention.maxAgeMs=s.maxAgeMs)}if(e.plugins&&typeof e.plugins=="object"){let s=e.plugins;typeof s.dir=="string"&&s.dir.trim()?n.plugins.dir=ye(s.dir):s.dir===null&&(n.plugins.dir=null)}return n}function dt(){return{local:nt.join(process.cwd(),"daimon.config.json"),user:nt.join(Et.homedir(),".daimon","config.json")}}function Q(){let{local:r,user:t}=dt();if(st.existsSync(r)){let s=JSON.parse(st.readFileSync(r,"utf8"));return{kind:"loaded",config:ve(s,r),path:r}}if(st.existsSync(t)){let s=JSON.parse(st.readFileSync(t,"utf8"));return{kind:"loaded",config:ve(s,t),path:t}}let n=[nt.resolve(lr,"..","daimon.config.example.json"),nt.resolve(lr,"..","..","daimon.config.example.json")].find(s=>st.existsSync(s));return st.mkdirSync(nt.dirname(t),{recursive:!0}),n?st.copyFileSync(n,t):st.writeFileSync(t,JSON.stringify(ur(),null,2)+`
|
|
2
|
+
`,"utf8"),{kind:"stub-created",path:t}}var Xn,lr,Rt=rt(()=>{"use strict";Xn=Jn(import.meta.url),lr=nt.dirname(Xn)});var ke={};Ft(ke,{discoverApps:()=>At});import z from"node:fs";import G from"node:path";import be from"fast-glob";function dr(r){try{return JSON.parse(z.readFileSync(r,"utf8"))}catch{return null}}function fr(r){return!r||typeof r!="object"?!1:!!(r.targets?.serve||r.architect?.serve)}function mr(r){if(!r||typeof r!="object")return[];let t=r.targets??r.architect??{};return Object.keys(t).filter(e=>e!=="serve").sort()}function we(r){return r.replace(/\\/g,"/")}function ht(r,t){r&&(r.rejected[t]=(r.rejected[t]??0)+1)}function Se(r,t){try{return t.test(z.readFileSync(r,"utf8"))}catch{return!1}}function Kn(r,t,e){let n=G.basename(r),s=!1,i=G.join(r,"manage.py");if(z.existsSync(i)&&Se(i,/\bdjango\b/i)){let v=n;e.has(v)||e.set(v,{name:v,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"django",command:"python manage.py runserver",hidden:!1,tags:[],workspaceLabel:t}),s=!0}let o=G.join(r,"bin","rails"),a=G.join(r,"Gemfile");if(z.existsSync(o)&&z.existsSync(a)){let v=n;e.has(v)||e.set(v,{name:v,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"rails",command:"bin/rails server",hidden:!1,tags:[],workspaceLabel:t}),s=!0}let c=G.join(r,"pyproject.toml"),u=G.join(r,"requirements.txt");(z.existsSync(c)&&Se(c,/\bfastapi\b/i)||z.existsSync(u)&&Se(u,/\bfastapi\b/i))&&!e.has(n)&&(e.set(n,{name:n,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"fastapi",command:"uvicorn main:app --reload",hidden:!1,tags:[],workspaceLabel:t}),s=!0),(z.existsSync(G.join(r,".air.toml"))||z.existsSync(G.join(r,"air.toml")))&&!e.has(n)&&(e.set(n,{name:n,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"go-air",command:"air",hidden:!1,tags:[],workspaceLabel:t}),s=!0);let y=G.join(r,"Trunk.toml");return z.existsSync(y)&&!e.has(n)&&(e.set(n,{name:n,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"rust-trunk",command:"trunk serve",hidden:!1,tags:[],workspaceLabel:t}),s=!0),s}function At(r,t={}){let e=new Map,n=t.warnings??[],s=t.warnings===void 0;for(let i of r.searchRoots){let o=typeof i=="string"?i:i.path,a=typeof i=="string"?!1:!!i.viteSubfolders,c=typeof i=="string"?void 0:i.label,u=G.resolve(o);if(!z.existsSync(u)){n.push(`searchRoot does not exist: ${u}`),ht(t.stats,"searchRoot missing");continue}let h=G.join(u,"nx.json"),p=G.join(u,"angular.json");if(z.existsSync(h)){let f=be.sync("**/project.json",{cwd:we(u),ignore:["**/node_modules/**","**/dist/**","**/.nx/**","**/.git/**"],absolute:!0,dot:!1});for(let m of f){t.stats&&(t.stats.scanned+=1);let d=dr(m);if(!d){ht(t.stats,"unreadable project.json");continue}if(!fr(d)){ht(t.stats,"no serve target");continue}let g=d.name||G.basename(G.dirname(m));if(!g){ht(t.stats,"project has no name");continue}if(e.has(g)){n.push(`duplicate project name "${g}" \u2014 keeping first`),ht(t.stats,"duplicate name");continue}e.set(g,{name:g,workspaceRoot:u,workspaceType:"nx",serverProfile:"nx",command:`npx nx serve ${g}`,hidden:!1,tags:[],tasks:mr(d),workspaceLabel:c})}continue}if(z.existsSync(p)){let m=dr(p)?.projects||{};for(let[d,g]of Object.entries(m))if(fr(g)){if(e.has(d)){n.push(`duplicate project name "${d}" \u2014 keeping first`);continue}e.set(d,{name:d,workspaceRoot:u,workspaceType:"angular",serverProfile:"angular",command:`npx ng serve ${d}`,hidden:!1,tags:[],tasks:mr(g),workspaceLabel:c})}continue}let y=be.sync("vite.config.{ts,js,mjs,cjs}",{cwd:we(u),absolute:!0,deep:1}),v=z.existsSync(G.join(u,".storybook")),l=!1;if(y.length>0){let f=G.basename(u);if(e.has(f)||e.set(f,{name:f,workspaceRoot:u,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:c}),l=!0,a){let m=be.sync("*/vite.config.{ts,js,mjs,cjs}",{cwd:we(u),absolute:!0});for(let d of m){let g=G.dirname(d),x=G.basename(g);x===f||e.has(x)||e.set(x,{name:x,workspaceRoot:g,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:c})}}}if(v){let f=`${G.basename(u)}-storybook`;e.has(f)||e.set(f,{name:f,workspaceRoot:u,workspaceType:"storybook",serverProfile:"storybook",command:"npx storybook dev --no-open",hidden:!1,tags:[],workspaceLabel:c}),l=!0}l||Kn(u,c,e)||(n.push(`searchRoot has none of nx.json/angular.json/vite.config.*/.storybook/polyglot markers: ${u}`),ht(t.stats,"no project markers"))}for(let[i,o]of Object.entries(r.overrides||{})){let a=e.get(i);a?(o.command&&(a.command=o.command),typeof o.hidden=="boolean"&&(a.hidden=o.hidden),typeof o.port=="number"&&(a.pinnedPort=o.port),o.env&&(a.env=o.env)):o.command&&e.set(i,{name:i,workspaceRoot:process.cwd(),workspaceType:"nx",command:o.command,hidden:o.hidden??!1,pinnedPort:o.port,env:o.env,tags:[]})}for(let i of e.values())i.tags=r.tags?.[i.name]??[];if(s&&n.length)for(let i of n)process.stderr.write(`[daimon] warning: ${i}
|
|
3
|
+
`);return[...e.values()].filter(i=>!i.hidden)}var Pt=rt(()=>{"use strict"});import Ts from"node:net";function yt(r){return new Promise(t=>{let e=Ts.createServer();e.unref(),e.once("error",()=>t(!1)),e.listen({port:r,host:"127.0.0.1",exclusive:!0},()=>{e.close(()=>t(!0))})})}var gt,Ht=rt(()=>{"use strict";gt=class{assigned=new Map;min;max;onChange;constructor(t,e={}){if(this.min=t[0],this.max=t[1],this.onChange=e.onChange,e.initial){let n=new Set;for(let[s,i]of Object.entries(e.initial))typeof i=="number"&&(i<this.min||i>this.max||n.has(i)||(n.add(i),this.assigned.set(s,i)))}}snapshot(){return Object.fromEntries(this.assigned)}getAssigned(t){return this.assigned.get(t)}pin(t,e){this.assigned.set(t,e),this.onChange?.(this.snapshot())}async allocate(t,e){let n=this.assigned.get(t);if(e!==void 0)return this.assigned.set(t,e),this.onChange?.(this.snapshot()),e;if(n!==void 0)return n;let s=new Set(this.assigned.values());for(let i=this.min;i<=this.max;i++){if(s.has(i))continue;if(await yt(i))return this.assigned.set(t,i),this.onChange?.(this.snapshot()),i}throw new Error(`No free ports in range ${this.min}-${this.max}`)}async isPortAvailableForUse(t){return yt(t)}}});function Sr(r){let s=new Map,i=new Map,o=null,a=c=>{if(!o){s.set(c,1);for(let u of r[c]||[]){let h=s.get(u)??0;if(h===1){let p=[u,c],y=i.get(c);for(;y&&y!==u;)p.push(y),y=i.get(y);y===u&&p.push(u),o=p.reverse();return}if(h===0&&(i.set(u,c),a(u),o))return}s.set(c,2)}};for(let c of Object.keys(r))if((s.get(c)??0)===0&&(i.set(c,null),a(c),o))return o;return null}function Wt(r,t){let e=new Set,n=[t];for(;n.length;){let s=n.pop();if(!e.has(s)){e.add(s);for(let i of r[s]||[])n.push(i)}}return[...e]}function Gt(r,t){let e=new Set(t),n=new Map,s=new Map;for(let a of t)n.set(a,0),s.set(a,[]);for(let a of t)for(let c of r[a]||[])e.has(c)&&(s.get(c).push(a),n.set(a,(n.get(a)??0)+1));let i=[],o=t.filter(a=>(n.get(a)??0)===0);for(;o.length;){i.push([...o].sort());let a=[];for(let c of o)for(let u of s.get(c)??[])n.set(u,(n.get(u)??1)-1),n.get(u)===0&&a.push(u);o=a}return i}function kr(r,t){let e=[];for(let[n,s]of Object.entries(r))s.includes(t)&&e.push(n);return e}var qt=rt(()=>{"use strict"});import Bs from"node:fs";import Ae from"node:path";import{fileURLToPath as Hs}from"node:url";function Us(){let r=[Ae.resolve(_r,"..","package.json"),Ae.resolve(_r,"..","..","package.json")];for(let t of r)try{return JSON.parse(Bs.readFileSync(t,"utf8"))}catch{}return{}}var _r,ot,Ct=rt(()=>{"use strict";_r=Ae.dirname(Hs(import.meta.url));ot=Us().version||"0.0.0"});import vt from"node:fs";import Jt from"node:path";import Ws from"node:os";import{spawn as Gs}from"node:child_process";import{fileURLToPath as qs}from"node:url";function it(){return Ce}function Xt(){return bt}function Pe(r){try{return process.kill(r,0),!0}catch(t){return t&&t.code==="EPERM"}}function wt(){try{let r=vt.readFileSync(bt,"utf8"),t=JSON.parse(r);if(!t||typeof t.pid!="number")return null;if(!Pe(t.pid)){try{vt.unlinkSync(bt)}catch{}return null}return t}catch{return null}}function $r(r){vt.mkdirSync(Ce,{recursive:!0});let t=bt+"."+process.pid+".tmp";vt.writeFileSync(t,JSON.stringify(r)),vt.renameSync(t,bt)}function Mt(){try{vt.unlinkSync(bt)}catch{}}function Js(){let r=Jt.dirname(qs(import.meta.url));return Jt.join(r,"main.js")}async function Me(r={}){let t={...process.env};r.port&&(t.DAIMON_PORT=String(r.port)),Gs(process.execPath,[Js(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let n=Date.now();for(;Date.now()-n<5e3;){let s=wt();if(s&&(!r.port||s.apiPort===r.port))return s;await new Promise(i=>setTimeout(i,100))}throw new Error("daemon failed to start within 5s")}async function Lr(r,t){let e=Date.now();for(;Date.now()-e<t;){if(!Pe(r))return!0;await new Promise(n=>setTimeout(n,100))}return!Pe(r)}function Dr(r,t,e){return{pid:process.pid,apiPort:r,version:ot,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var Ce,bt,ft=rt(()=>{"use strict";Ct();Ce=Jt.join(Ws.homedir(),".daimon"),bt=Jt.join(Ce,"daemon.lock")});import mo from"node:fs";import ho from"node:path";import{createRequire as go}from"node:module";var yo,vo,bo,wo,St,Fe=rt(()=>{"use strict";yo=go(import.meta.url),vo=200,bo=360*60*1e3,wo=1e4,St=class{constructor(t){this.cfg=t;if(t.enabled)try{mo.mkdirSync(ho.dirname(t.path),{recursive:!0});let e=yo("better-sqlite3");this.db=new e(t.path),this.db.pragma("journal_mode = WAL"),this.migrate(),this.flushTimer=setInterval(()=>this.flush(),vo),this.retentionStart=setTimeout(()=>this.runRetention(),wo),this.retentionTimer=setInterval(()=>this.runRetention(),bo)}catch(e){this.warnOnce(`failed to open history db: ${e?.message||e}`),this.db=null}}cfg;db=null;queue=[];flushTimer=null;retentionTimer=null;retentionStart=null;warned=!1;warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] history: ${t}
|
|
4
4
|
`))}migrate(){this.db&&this.db.exec(`
|
|
5
5
|
CREATE TABLE IF NOT EXISTS events (
|
|
6
6
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -38,56 +38,66 @@ var _n=Object.defineProperty;var rt=(n,t)=>()=>(n&&(t=n(n=0)),t);var Dt=(n,t)=>{
|
|
|
38
38
|
fileCount INTEGER NOT NULL
|
|
39
39
|
);
|
|
40
40
|
CREATE INDEX IF NOT EXISTS bundles_app_ts ON bundles(app, ts);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`,"utf8");let c=wt();if(c)try{fetch(`http://127.0.0.1:${c.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${a} dead searchRoot entr${a===1?"y":"ies"} from ${r} (${[...i].join(", ")}); triggered soft-reload. To undo: edit ${r} and re-add the path(s).`}async function wo(n){let t={ran:[],skipped:[],errors:[]};for(let e of tn){if(!n.permitted.includes(e))continue;let r=bo[e],s;try{s=await r.detect()}catch(i){t.errors.push({name:e,error:i?.message??String(i)});continue}if(!s.detected){t.skipped.push({name:e,detected:!1,description:s.description});continue}if(n.dryRun){t.ran.push({name:e,detected:!0,description:`(dry-run) would fix: ${s.description}`});continue}try{let i=await r.fix();t.ran.push({name:e,detected:!0,description:`${s.description} \u2014 ${i}`})}catch(i){t.errors.push({name:e,error:i?.message??String(i)})}}return t}var tn,bo,Nt=rt(()=>{"use strict";dt();Rt();$e();Bt();tn=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"];bo={"orphan-daemon":{detect:to,fix:eo},"stale-lock":{detect:ro,fix:no},"missing-search-root":{detect:so,fix:oo},"corrupt-history-db":{detect:io,fix:ao},"port-conflict-pred":{detect:co,fix:lo},"node-version-mismatch":{detect:uo,fix:po},"orphan-node-modules":{detect:en,fix:mo},"orphan-venv":{detect:rn,fix:ho},"orphan-bundler-cache":{detect:nn,fix:go},"orphan-cargo-target":{detect:sn,fix:yo},"dead-search-root":{detect:on,fix:vo}}});var Le={};Dt(Le,{orchestrateProfile:()=>ko});function an(n,t,e,r,s){let i=n.summary(t);if(!i)return!1;if(e==="serving")return i.status==="serving";if(e==="healthy")return i.status==="serving"&&i.health==="healthy";let o=Date.now()-r;return i.status==="serving"&&i.health==="healthy"&&o>=s}async function cn(n,t,e,r,s){let i=Date.now();if(e!=="stable"){let c=await n.waitFor(t,e==="serving"?"serving":"healthy",r);return{reached:!c.timedOut,waitedMs:c.waitedMs}}let o=Date.now(),a=c=>{c?.app===t&&(o=Date.now())};n.on("event",a);try{for(;Date.now()-i<r;){if(an(n,t,e,o,s))return{reached:!0,waitedMs:Date.now()-i};await new Promise(c=>setTimeout(c,500))}return{reached:an(n,t,e,o,s),waitedMs:Date.now()-i}}finally{n.off("event",a)}}async function ko(n,t,e){let r=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let i=s.filter(f=>n.summary(f)!=null),o=Array.from(new Set(i.flatMap(f=>Ut(t.depends??{},f)))).filter(f=>n.summary(f)!=null),a=Wt(t.depends??{},o),c=[];for(let f of o){let d=n.summary(f);d&&(e.goal==="serving"&&d.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&d.status==="serving"&&d.health==="healthy")&&c.push(f)}if(e.dryRun){let f=o.filter(d=>!c.includes(d));return{profile:e.profile,goal:e.goal,perApp:f.map(d=>({name:d,reached:!1,tries:0})),totalMs:Date.now()-r,allReached:f.length===0,dryRun:!0,plannedOrder:a,alreadyHealthy:c}}let u=Math.max(5e3,Math.floor(e.timeoutMs/2)),h=e.stableMs??5e3,p=new Map;for(let f of o)p.set(f,{name:f,reached:!1,tries:0});for(let f of a)await Promise.all(f.map(async d=>{let g=n.summary(d);if(!g){p.set(d,{name:d,reached:!1,tries:0,error:"unknown app"});return}if(c.includes(d)){p.set(d,{name:d,reached:!0,tries:0});return}g.status!=="starting"&&g.status!=="compiling"&&g.status!=="serving"&&await n.start(d)})),await Promise.all(f.map(async d=>{if(p.get(d)?.reached)return;let g=await cn(n,d,e.goal,u,h),T=p.get(d);T.tries=1,T.waitedMs=g.waitedMs,T.reached=g.reached,p.set(d,T)}));let v=[...p.values()].filter(f=>!f.reached);if(v.length>0){let{runAutoFix:f,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(Nt(),jt)),g=t.doctor?.autoFix?.permitted??d,T=Math.max(5e3,e.timeoutMs-(Date.now()-r)),E=Math.max(5e3,Math.floor(T/Math.max(v.length,1))),y={ran:[]};try{y=await f({permitted:g,dryRun:!1})}catch{}let N=(y.ran??[]).map(C=>C.name);await Promise.all(v.map(async C=>{let S=p.get(C.name);S.tries=2;try{let M=await n.restart(C.name);M?.ok||(S.error=M?.error??"restart failed")}catch(M){S.error=M?.message??String(M)}let R=await cn(n,C.name,e.goal,E,h);if(S.waitedMs=(S.waitedMs??0)+R.waitedMs,S.reached=R.reached,!S.reached){let M=n.errors(C.name)??[];S.stillFailing=M.slice(0,3).map(x=>({file:x.parsed?.file??null,line:x.parsed?.line??null,code:x.parsed?.code??null,tool:x.parsed?.tool??null,message:x.parsed?.message??x.message}))}S.fixed=N,p.set(C.name,S)}))}let b=[...p.values()],l=b.every(f=>f.reached),m={profile:e.profile,goal:e.goal,perApp:b,totalMs:Date.now()-r,allReached:l};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let f=e.budgetTokens,d=0,g=0;for(let T of b)if(T.stillFailing){let E=T.stillFailing.length*So;E>f?(d+=T.stillFailing.length,delete T.stillFailing):f-=E}for(;f<0||b.length*xo>Math.max(f,e.budgetTokens/4);){let T=b.findIndex(E=>E.reached);if(T===-1)break;b.splice(T,1),g++}(d||g)&&(m._meta={omitted:{}},d&&(m._meta.omitted.stillFailing=d),g&&(m._meta.omitted.perApp=g))}return m}var So,xo,De=rt(()=>{"use strict";Gt();So=60,xo=25});Rt();Ct();import bi from"react";import{render as wi}from"ink";import{pathToFileURL as Si}from"node:url";import{EventEmitter as Ms}from"node:events";import{spawn as ds}from"node:child_process";import hr from"tree-kill";import fs from"strip-ansi";import In from"node:crypto";var Bn=[/Local:\s+http/i,/Application bundle generation complete/i,/compiled successfully/i,/webpack compiled\s+(?:successfully|in\b)/i,/Angular Live Development Server is listening/i,/Storybook\s+[\d.]+\s+(?:for\s+\S+\s+)?started/i,/VITE\s+v[\d.]+\s+ready/i,/Quit the server with CONTROL-C/i,/Uvicorn running on http/i,/Application startup complete/i,/Puma starting in single mode/i,/Use Ctrl-C to stop/i,/Listening on tcp:\/\//i,/running on http/i,/serving HTTP on/i,/trunk serve.*at/i],Hn=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i,/Watching for file changes with StatReloader/i,/Performing system checks/i,/watching files for changes/i,/building\.{3}/i,/Compiling \(/i],Un=[/^\s*ERROR\b/,/\berror TS\d+/,/✘/,/\[ERROR\]/,/Cannot find module/i,/^FAIL\s+\S+/,/^\s*●\s+/,/^\s*>\s+NX\s+.*failed/i,/\bModule not found:/,/\[vite\]\s+(?:Internal server error|Pre-transform error)/i,/\[plugin:[^\]]+\]/i,/^\s*ERR!\s+/,/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):\s+/,/^Traceback \(most recent call last\):/,/^\s*[A-Z][a-zA-Z]*Error:\s+/,/^\s*\[error\]\s+/i,/^panic:\s+/,/^thread\s+'[^']+'\s+panicked at/,/^error\[E\d+\]:/,/^\S+\.(?:go|rb|py|rs):\d+:\d+:/,/^\s*[A-Z][a-zA-Z]*\.[A-Z][a-zA-Z]*:\s+/,/^[A-Z][a-zA-Z]+(?:::[A-Z][a-zA-Z]+)+\s*[(:]/,/^[A-Z][a-zA-Z]*Error\s*\(/],Wn=/\berror TS(\d+)/,Gn=/✘\s*\[ERROR\]\s*TS(\d+)/,Jn=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)/,pr=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)\)/,qn=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,dr=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,fr=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,Kn=/^([^\s:()]+\.rb):(\d+):in\b/,Xn=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,zn=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,Yn=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,Vn=[{tool:"vite",rx:/\[vite\]|\[plugin:vite:|transformWithEsbuild/i},{tool:"storybook",rx:/\bstorybook\b|^\s*ERR!\s|builder-vite/i},{tool:"jest",rx:/^FAIL\s|^\s*●\s+|\bjest\b/i},{tool:"nx",rx:/>\s+NX\s+|Failed tasks:|Nx errored/i},{tool:"webpack",rx:/\bModule not found:|webpack compiled|webpack-dev-server/i},{tool:"esbuild",rx:/✘\s*\[ERROR\]|esbuild/i},{tool:"typescript",rx:/\berror TS\d+/},{tool:"django",rx:/\bdjango\b|StatReloader|manage\.py runserver/i},{tool:"rails",rx:/\brails\b|Puma starting|Booting (?:Puma|Rails)|ActionController|NameError\s*\(|\.rb:\d+:in/i},{tool:"fastapi",rx:/\buvicorn\b|fastapi|ASGI/i},{tool:"go-air",rx:/\bair v\d|building\.{3}|\.go:\d+:\d+/i},{tool:"rust-trunk",rx:/\btrunk\b|^error\[E\d+\]|^\s*-->\s+\S+\.rs:/i},{tool:"python",rx:/^Traceback \(most recent call last\):|^\s*File "[^"]+\.py"|[A-Z][a-zA-Z]*Error:\s/},{tool:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];function Zn(n){for(let{tool:t,rx:e}of Vn)if(e.test(n))return t}var Qn=/Local:\s+(https?:\/\/\S+)/i,ts=/Server running at\s+(https?:\/\/\S+)/i,es=/listening on\s+(https?:\/\/\S+)/i,rs=/(?:listening|listen)\s+(https?:\/\/\S+)/i,ns=/Initial chunk files/i,ss=/Lazy chunk files/i,os=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,is=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i;function as(n){return In.createHash("sha1").update(n).digest("hex").slice(0,16)}function cs(n){let t={message:n},e=n.match(Gn)||n.match(Wn);e&&(t.code=`TS${e[1]}`);let r=n.match(qn)||n.match(pr)||n.match(Jn);if(r)t.file=r[1],t.line=Number(r[2]),t.col=Number(r[3]);else{let i=n.match(zn);if(i)t.file=i[1],i[2]&&(t.line=Number(i[2])),i[3]&&(t.col=Number(i[3]));else{let o=n.match(Xn);if(o)t.file=o[1];else{let a=n.match(fr);if(a)t.file=a[1],t.line=Number(a[2]),t.col=Number(a[3]);else{let c=n.match(dr);c&&(t.file=c[1],t.line=Number(c[2]))}}}}let s=Zn(n);return s&&(t.tool=s),t}function ls(n,t){try{let e=new URL(n);return e.hostname==="0.0.0.0"||e.hostname==="[::]"?(e.hostname=t.includes(":")?`[${t}]`:t,e.toString().replace(/\/$/,"")):n.replace(/\/$/,"")}catch{return n}}function us(n,t="127.0.0.1"){let e=n.match(Qn)||n.match(ts)||n.match(es)||n.match(rs);if(!e)return null;let r=e[1].replace(/[),.;]+$/,"");return ls(r,t)}function ps(n,t){if(ns.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="initial",!1;if(ss.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="lazy",!1;let e=t.match(os);if(e&&n.bundle){let s=parseFloat(e[2]),i=e[3].toUpperCase(),o=Math.round(i==="MB"?s*1024:i==="B"?s/1024:s);return/Initial/i.test(e[1])?n.bundle.initialKB=o:n.bundle.lazyKB=o,!0}let r=t.match(is);if(r&&n.bundle){let s=r[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let i=r[4].toUpperCase(),o=parseFloat(r[3]),a=i==="MB"?o*1024:i==="B"?o/1024:o;return n.bundle.files.push({name:s,sizeKB:Math.round(a*10)/10}),!1}return!1}function mr(n,t){let e=t.match(Yn),r=e?null:t.match(pr),s=!e&&!r?t.match(fr):null,i=e??r??s;if(i&&n.lastErrorHash){let l=n.errors.get(n.lastErrorHash);l&&!l.parsed?.file&&(l.parsed={...l.parsed??{message:l.message},file:i[1],line:Number(i[2]),col:Number(i[3])})}else if(n.lastErrorHash){let l=t.match(dr),m=l?null:t.match(Kn);if(l||m){let f=n.errors.get(n.lastErrorHash);if(f&&!f.parsed?.file){let d=l??m;f.parsed={...f.parsed??{message:f.message},file:d[1],line:Number(d[2])}}}}let o=t.trim();if(!o)return null;let a=n.status,c=!1,u,h=us(o);h&&!n.announcedUrl&&(n.announcedUrl=h,u=h);let p=ps(n,o),v;if(Bn.some(l=>l.test(o))){let l=n.status==="error"||!!n.recoveringFromError;if(n.status==="compiling"||n.status==="starting"||n.status==="error"){let m=Date.now();n.compileStartedAt!=null?(v=m-n.compileStartedAt,n.lastCompileMs=v,n.lastCompileAt=m,n.compileStartedAt=null,n.compileHistory.push(v),n.compileHistory.length>20&&n.compileHistory.splice(0,n.compileHistory.length-20)):n.lastCompileAt=m}n.status="serving",l&&(n.errors.clear(),n.recoveringFromError=!1)}else Hn.some(l=>l.test(o))&&(n.status==="starting"||n.status==="serving"||n.status==="error")&&(n.status==="error"&&(n.recoveringFromError=!0),n.compileStartedAt=Date.now(),n.status="compiling");let b;if(Un.some(l=>l.test(o))){let l=as(o),m=Date.now(),f=n.errors.get(l),d=!1,g;f?(f.count+=1,f.lastSeen=m,g=f):(g={message:o,count:1,firstSeen:m,lastSeen:m,parsed:cs(o)},n.errors.set(l,g),d=!0),n.lastErrorHash=l,b={entry:g,isNew:d},n.status="error"}return c=n.status!==a,{statusChanged:c,error:b,announcedUrl:u,bundleUpdated:p,compileMs:v}}var gr=500,It=class{child=null;stdoutBuf="";stderrBuf="";deps;stopping=!1;constructor(t){this.deps=t}isRunning(){return this.child!==null&&this.child.exitCode===null&&!this.stopping}start(){if(this.isRunning())return;let{app:t,port:e,state:r}=this.deps,s=Date.now();r.status="starting",r.startedAt=s,r.compileStartedAt=s,r.lastCompileMs=null,r.lastCompileAt=null,r.errors.clear(),r.logBuffer.length=0,r.lastStatusMessage=void 0;let o=`${this.deps.commandOverride||t.command} --port ${e}`,a={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},c=ds(o,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=c,r.pid=c.pid??null,r.port=e,c.stdout?.on("data",u=>this.handleChunk(u,"stdout")),c.stderr?.on("data",u=>this.handleChunk(u,"stderr")),c.on("exit",(u,h)=>{let p=r.status,v=this.stopping;v?(r.status="stopped",r.lastStatusMessage=`stopped (code=${u??"null"}${h?`, ${h}`:""})`):u!==0?(r.status="error",r.lastStatusMessage=`process exited with code ${u}${h?` (${h})`:""}`):r.status="stopped",r.pid=null,r.health="unknown",this.child=null,this.stopping=!1,p!==r.status&&this.deps.onStatusChange?.(p,r.status,r.lastStatusMessage),this.deps.onExit?.(u,h,v),this.deps.onStateChange()}),c.on("error",u=>{r.status="error",r.lastStatusMessage=`spawn error: ${u.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let r=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=r,i=s.lastIndexOf(`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
CREATE TABLE IF NOT EXISTS self_metrics (
|
|
42
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43
|
+
ts INTEGER NOT NULL,
|
|
44
|
+
rssMB REAL NOT NULL,
|
|
45
|
+
heapUsedMB REAL NOT NULL,
|
|
46
|
+
eventLoopLagMs REAL NOT NULL,
|
|
47
|
+
historyQueryP95Ms REAL NOT NULL
|
|
48
|
+
);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS self_metrics_ts ON self_metrics(ts);
|
|
50
|
+
`)}recordSelfMetric(t,e,n,s,i=Date.now()){if(this.db)try{this.db.prepare("INSERT INTO self_metrics (ts,rssMB,heapUsedMB,eventLoopLagMs,historyQueryP95Ms) VALUES (?,?,?,?,?)").run(i,t,e,n,s)}catch(o){this.warnOnce(`self_metrics write failed: ${o?.message||o}`)}}querySelfMetrics(t={}){if(!this.db)return[];let e=[],n=[];t.since!=null&&(e.push("ts >= ?"),n.push(t.since));let s=`SELECT ts, rssMB, heapUsedMB, eventLoopLagMs, historyQueryP95Ms FROM self_metrics ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return n.push(t.limit??60),this.db.prepare(s).all(...n)}recordEvent(t){this.db&&this.queue.push({kind:"event",row:{ts:t.ts,app:t.app,type:t.type,from_state:t.from??null,to_state:t.to??null,message:t.message??null}})}recordCompile(t,e,n=Date.now()){this.db&&this.queue.push({kind:"compile",row:{ts:n,app:t,ms:e}})}recordBundle(t,e,n,s,i=Date.now()){this.db&&this.queue.push({kind:"bundle",row:{ts:i,app:t,initialKB:e,lazyKB:n,fileCount:s}})}recordTaskRun(t,e,n,s,i,o=Date.now()){this.db&&this.queue.push({kind:"task",row:{ts:o,app:t,task:e,exit_code:n,duration_ms:s,summary:i==null?null:JSON.stringify(i)}})}flush(){if(!this.db||this.queue.length===0)return;let t=this.queue;this.queue=[];try{let e=this.db.prepare("INSERT INTO events (ts,app,type,from_state,to_state,message) VALUES (?,?,?,?,?,?)"),n=this.db.prepare("INSERT INTO compile_times (ts,app,ms) VALUES (?,?,?)"),s=this.db.prepare("INSERT INTO task_runs (ts,app,task,exit_code,duration_ms,summary) VALUES (?,?,?,?,?,?)"),i=this.db.prepare("INSERT INTO bundles (ts,app,initialKB,lazyKB,fileCount) VALUES (?,?,?,?,?)");this.db.transaction(a=>{for(let c of a)c.kind==="event"?e.run(c.row.ts,c.row.app,c.row.type,c.row.from_state,c.row.to_state,c.row.message):c.kind==="compile"?n.run(c.row.ts,c.row.app,c.row.ms):c.kind==="bundle"?i.run(c.row.ts,c.row.app,c.row.initialKB,c.row.lazyKB,c.row.fileCount):s.run(c.row.ts,c.row.app,c.row.task,c.row.exit_code,c.row.duration_ms,c.row.summary)})(t)}catch(e){this.warnOnce(`history write failed: ${e?.message||e}`)}}runRetention(){if(this.db)try{let t=Date.now()-this.cfg.retentionDays*864e5;this.db.prepare("DELETE FROM events WHERE ts < ?").run(t),this.db.prepare("DELETE FROM compile_times WHERE ts < ?").run(t),this.db.prepare("DELETE FROM task_runs WHERE ts < ?").run(t),this.db.prepare("DELETE FROM bundles WHERE ts < ?").run(t),this.db.prepare("DELETE FROM self_metrics WHERE ts < ?").run(t)}catch(t){this.warnOnce(`retention failed: ${t?.message||t}`)}}queryEvents(t){if(!this.db)return[];let e=[],n=[];t.app&&(e.push("app = ?"),n.push(t.app)),t.since!=null&&(e.push("ts >= ?"),n.push(t.since)),t.until!=null&&(e.push("ts <= ?"),n.push(t.until)),t.type&&(e.push("type = ?"),n.push(t.type));let s=`SELECT * FROM events ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return n.push(t.limit??500),this.db.prepare(s).all(...n)}queryCompiles(t){if(!this.db)return[];let e=[],n=[];t.app&&(e.push("app = ?"),n.push(t.app)),t.since!=null&&(e.push("ts >= ?"),n.push(t.since)),t.until!=null&&(e.push("ts <= ?"),n.push(t.until));let s=`SELECT * FROM compile_times ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return n.push(t.limit??1e3),this.db.prepare(s).all(...n)}queryBundles(t){if(!this.db)return[];let e=[],n=[];t.app&&(e.push("app = ?"),n.push(t.app)),t.since!=null&&(e.push("ts >= ?"),n.push(t.since)),t.until!=null&&(e.push("ts <= ?"),n.push(t.until));let s=`SELECT * FROM bundles ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return n.push(t.limit??1e3),this.db.prepare(s).all(...n)}trends(t){if(!this.db)return{points:[],count:0};let e=Date.now()-t.sinceMs,n=t.bucketMs,s=new Map,i=(h,p)=>{let y=Math.floor(h/n)*n,v=s.get(y)??{sum:0,n:0};v.sum+=p,v.n+=1,s.set(y,v)},o=h=>{let p=Math.floor(h/n)*n,y=s.get(p)??{sum:0,n:0};y.sum+=1,y.n+=1,s.set(p,y)},a=0;if(t.metric==="compile"){let h=this.queryCompiles({app:t.app,since:e,limit:1e4});a=h.length;for(let p of h)i(p.ts,p.ms)}else if(t.metric==="bundle"){let h=this.queryBundles({app:t.app,since:e,limit:1e4});a=h.length;for(let p of h){let y=Math.floor(p.ts/n)*n,v=s.get(y)??{sum:0,n:0,sum2:0};v.sum+=p.initialKB,v.sum2=(v.sum2??0)+p.lazyKB,v.n+=1,s.set(y,v)}}else if(t.metric==="errors"){let h=this.queryEvents({app:t.app,since:e,limit:1e4});for(let p of h)(p.type==="error-new"||p.type==="error-recur")&&(o(p.ts),a++)}else{let h=this.queryEvents({app:t.app,since:e,limit:1e4});for(let p of h)p.type==="status"&&p.to_state==="starting"&&(p.from_state==="error"||p.from_state==="serving"||p.from_state==="compiling")&&(o(p.ts),a++)}let c=[],u=[...s.entries()].sort((h,p)=>h[0]-p[0]);for(let[h,p]of u)t.metric==="compile"||t.metric==="bundle"?c.push({t:h,v:Math.round(p.sum/p.n),...p.sum2!=null?{v2:Math.round(p.sum2/p.n)}:{}}):c.push({t:h,v:p.sum});return{points:c,count:a}}queryTasks(t){if(!this.db)return[];let e=[],n=[];t.app&&(e.push("app = ?"),n.push(t.app)),t.task&&(e.push("task = ?"),n.push(t.task)),t.since!=null&&(e.push("ts >= ?"),n.push(t.since));let s=`SELECT * FROM task_runs ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return n.push(t.limit??200),this.db.prepare(s).all(...n)}summary(t){if(!this.db)return{uptimePct24h:0,restartCount24h:0,compileP50:null,compileP95:null,topErrors:[]};let e=Date.now()-24*3600*1e3,n=this.queryEvents({app:t,since:e,limit:5e3}),s=0,i=e,o=!1,a=null,c=[...n].sort((d,g)=>d.ts-g.ts);for(let d of c)d.type==="status"&&(d.to_state==="serving"&&!o?(o=!0,a=d.ts):o&&d.to_state!=="serving"&&a!=null&&(s+=d.ts-a,o=!1,a=null));o&&a!=null&&(s+=Date.now()-a);let u=Math.round(s/(24*3600*1e3)*1e3)/10,h=n.filter(d=>d.type==="status"&&d.to_state==="starting"&&(d.from_state==="serving"||d.from_state==="error"||d.from_state==="compiling")).length,p=this.queryCompiles({app:t,since:e,limit:1e3}).map(d=>d.ms).sort((d,g)=>d-g),y=(d,g)=>{if(d.length===0)return null;let x=Math.min(d.length-1,Math.floor((d.length-1)*g));return d[x]},v=y(p,.5),l=y(p,.95),f=new Map;for(let d of n)if(d.type==="error-new"||d.type==="error-recur"){let g=d.message??"";if(!g)continue;f.set(g,(f.get(g)??0)+1)}let m=[...f.entries()].sort((d,g)=>g[1]-d[1]).slice(0,5).map(([d,g])=>({message:d,count:g}));return{uptimePct24h:u,restartCount24h:h,compileP50:v,compileP95:l,topErrors:m}}why(t){let e=this.queryEvents({app:t,limit:200}),n=e.find(a=>a.type==="status"&&(a.to_state==="error"||a.from_state==="error"||a.to_state==="serving")),s=n?{ts:n.ts,app:n.app,type:n.type,from:n.from_state??void 0,to:n.to_state??void 0,message:n.message??void 0}:null,i=s?s.ts:Date.now(),o=e.filter(a=>a.ts<i).slice(0,5);return{trigger:s,preceding:o.map(a=>({ts:a.ts,app:a.app,type:a.type,from:a.from_state??void 0,to:a.to_state??void 0,message:a.message??void 0}))}}_flushForTest(){this.flush()}quickCheck(){if(!this.db)return!1;try{return this.db.prepare("PRAGMA quick_check").get()?.quick_check==="ok"}catch{return!1}}close(){if(this.flushTimer&&clearInterval(this.flushTimer),this.retentionTimer&&clearInterval(this.retentionTimer),this.retentionStart&&clearTimeout(this.retentionStart),this.flush(),this.db){try{this.db.close()}catch{}this.db=null}}}});var jt={};Ft(jt,{ALL_AUTO_FIX:()=>sn,runAutoFix:()=>Bo});import L from"node:fs";import H from"node:path";function So(){let r=wt();if(!r)return{detected:!1,description:"no daemon running"};let t=process.cwd(),e=H.join(t,"daimon.config.json");if(!L.existsSync(e))return{detected:!1,description:"no local daimon.config.json in cwd"};let n=r.cwd,s=r.configPath,i=n&&H.resolve(n)===H.resolve(t),o=s&&H.resolve(s)===H.resolve(e);return i||o?{detected:!1,description:"daemon already running from this cwd/config"}:{detected:!0,description:`daemon (pid ${r.pid}) is running from ${n??"(unknown)"} but local daimon.config.json exists at ${t}`,lockCwd:n}}async function ko(){let r=wt();if(!r)return"no daemon running; nothing to do";try{await fetch(`http://127.0.0.1:${r.apiPort}/api/snapshot-state`,{method:"POST"})}catch{}try{await fetch(`http://127.0.0.1:${r.apiPort}/api/shutdown`,{method:"POST"})}catch{}return await Lr(r.pid,5e3),Mt(),`respawned daemon at pid ${(await Me({})).pid} from ${process.cwd()}; previous pid ${r.pid} (cwd ${r.cwd??"unknown"}) was shut down with state handoff. To undo: stop with 'daimon daemon stop' and start from the prior directory.`}function xo(){let r;try{r=L.readFileSync(Xt(),"utf8")}catch{return{detected:!1,description:"no lock file present"}}let t;try{t=JSON.parse(r)}catch{return{detected:!0,description:"lock file is malformed JSON"}}if(!t||typeof t.pid!="number")return{detected:!0,description:"lock file has no pid"};try{return process.kill(t.pid,0),{detected:!1,description:`lock file owner pid ${t.pid} is alive`}}catch(e){return e?.code==="EPERM"?{detected:!1,description:`lock file owner pid ${t.pid} alive (EPERM)`}:{detected:!0,description:`lock file claims pid ${t.pid} but the process is gone`}}}async function To(){let r="(unknown)";try{let e=JSON.parse(L.readFileSync(Xt(),"utf8"));r=String(e?.pid??"?")}catch{}Mt();let t=await Me({});return`removed stale ${Xt()} (prior pid ${r} was dead); spawned fresh daemon at pid ${t.pid}.`}function Eo(){let r=process.cwd(),e=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs","vite.config.cjs",".storybook"].filter(o=>L.existsSync(H.join(r,o)));if(!e.length)return{detected:!1,description:"no nx.json/angular.json/vite.config.*/.storybook in cwd"};let n=Q();return n.kind!=="loaded"?{detected:!0,description:`${e.join(", ")} present but no config is loaded`,markerFiles:e}:n.config.searchRoots.map(o=>H.resolve(typeof o=="string"?o:o.path)).some(o=>r.startsWith(o))?{detected:!1,description:`${e.join(", ")} present and a configured searchRoot covers ${r}`}:{detected:!0,description:`${e.join(", ")} present in ${r} but no searchRoot covers it`,markerFiles:e}}function Ro(){let r=process.cwd(),{local:t,user:e}=dt(),n=L.existsSync(t)?t:e,s={};try{s=JSON.parse(L.readFileSync(n,"utf8"))}catch{}if(s.searchRoots=Array.isArray(s.searchRoots)?s.searchRoots:[],!s.searchRoots.some(o=>(typeof o=="string"?o:o?.path)===r)){let o;try{let a=JSON.parse(L.readFileSync(H.join(r,"package.json"),"utf8"));typeof a.name=="string"&&(o=a.name)}catch{}s.searchRoots.push(o?{path:r,label:o}:r)}L.mkdirSync(H.dirname(n),{recursive:!0}),L.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
51
|
+
`,"utf8");let i=wt();if(i)try{fetch(`http://127.0.0.1:${i.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`appended ${r} as a searchRoot in ${n}; triggered soft-reload of the running daemon.`}function Ao(){let r=Q();if(r.kind!=="loaded"||!r.config.history.enabled)return{detected:!1,description:"history disabled"};let t=r.config.history.path;if(!L.existsSync(t))return{detected:!1,description:"history db does not exist (will be created on next start)"};try{let e=new St(r.config.history),n=e.quickCheck();return e.close(),n?{detected:!1,description:"history db quick_check passed"}:{detected:!0,description:`quick_check failed on ${t}`,dbPath:t}}catch(e){return{detected:!0,description:`cannot open ${t}: ${e?.message??String(e)}`,dbPath:t}}}function Po(){let r=Q();if(r.kind!=="loaded")return"no config; cannot determine history path";let t=r.config.history.path,e=`${t}.corrupt-${Date.now()}`;for(let n of["","-wal","-shm"])try{L.renameSync(t+n,e+n)}catch{}return`rotated ${t} \u2192 ${e} (and -wal/-shm siblings). The daemon will rebuild an empty history db on next start.`}async function Co(){let r=Q();if(r.kind!=="loaded")return{detected:!1,description:"no config loaded"};let[t,e]=r.config.portRange??[4200,4299],n=r.config.overrides??{},s=Object.values(n).map(a=>a.port).filter(a=>typeof a=="number"),i=Array.from(new Set([...s,t,e])),o=[];for(let a of i)if(!(!Number.isFinite(a)||a<=0))try{await yt(a)||o.push(a)}catch{}return o.length?{detected:!0,description:`ports already LISTEN: ${o.join(", ")} (range ${t}-${e} + pinned overrides)`,conflicts:o}:{detected:!1,description:`all checked ports free (range ${t}-${e} + pinned)`}}function Mo(){return"no automated fix \u2014 predictive rule only. Run `daimon free-port <port>` to inspect the holder, or pick a different port in daimon.config.json. To undo: nothing was changed."}function Oo(){let r=process.cwd(),t=process.versions.node,e=H.join(r,".nvmrc");if(L.existsSync(e)){let s=L.readFileSync(e,"utf8").trim().replace(/^v/i,"");if(s&&!t.startsWith(s))return{detected:!0,description:`.nvmrc requires ${s}, running ${t}`,expected:s,actual:t}}let n=H.join(r,"package.json");if(L.existsSync(n))try{let i=JSON.parse(L.readFileSync(n,"utf8"))?.engines?.node;if(typeof i=="string"&&i.trim()){let o=i.match(/(\d+)(?:\.(\d+))?/);if(o){let a=Number(o[1]),c=Number(t.split(".")[0]);if(Number.isFinite(a)&&Number.isFinite(c)&&c<a)return{detected:!0,description:`package.json engines.node = "${i}" but running ${t}`,expected:i,actual:t}}}}catch{}return{detected:!1,description:`node ${t} satisfies .nvmrc / engines.node (or neither is present)`}}function No(){return"no automated fix \u2014 switching Node versions touches the user environment. Run `nvm use` (or your version manager equivalent) in this directory, then re-run daimon. To undo: nothing was changed."}function jo(){let r=Q();if(r.kind!=="loaded")return[];let t=[],e=new Set;for(let n of r.config.searchRoots){let s=typeof n=="string"?n:n.path;if(!s||!L.existsSync(s)||e.has(s))continue;e.add(s);let i=H.join(s,"package.json");if(!L.existsSync(i))continue;let o=null;for(let a of["package-lock.json","pnpm-lock.yaml","yarn.lock"]){let c=H.join(s,a);if(L.existsSync(c)){o=c;break}}t.push({name:H.basename(s),root:s,pkgPath:i,lockPath:o,nmPath:H.join(s,"node_modules")})}return t}function on(){let r=jo();if(!r.length)return{detected:!1,description:"no searchRoots with package.json found"};let t=[];for(let n of r){if(!L.existsSync(n.nmPath)){t.push({root:n.root,reason:"missing"});continue}if(n.lockPath)try{let s=L.statSync(n.lockPath).mtimeMs,i=L.statSync(n.nmPath).mtimeMs;s>i+1e3&&t.push({root:n.root,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`node_modules issues \u2014 ${t.map(n=>`${n.reason}: ${n.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every searchRoot package.json has a fresh node_modules"}}function _o(){let r=on();return!r.detected||!r.entries?"nothing to suggest":`would suggest: ${r.entries.map(e=>`(cd "${e.root}" && npm install)`).join(" && ")}. Daimon does not run package managers on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function Ie(){let r=Q();if(r.kind!=="loaded")return[];let t=[],e=new Set;for(let n of r.config.searchRoots){let s=typeof n=="string"?n:n?.path;!s||!L.existsSync(s)||e.has(s)||(e.add(s),t.push(s))}return t}function an(){let r=Ie();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=H.join(n,"pyproject.toml"),i=H.join(n,"requirements.txt"),o=H.join(n,"manage.py");if(!(L.existsSync(s)||L.existsSync(i)||L.existsSync(o)))continue;let c=[".venv","venv","env"].map(h=>H.join(n,h)).find(h=>L.existsSync(h));if(!c){t.push({root:n,reason:"missing"});continue}let u=[];for(let h of[s,i])if(L.existsSync(h))try{u.push(L.statSync(h).mtimeMs)}catch{}if(u.length)try{let h=L.statSync(c).mtimeMs;Math.max(...u)>h+1e3&&t.push({root:n,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`venv issues \u2014 ${t.map(n=>`${n.reason}: ${n.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Python searchRoot has a fresh venv (or no Python markers)"}}function $o(){let r=an();return!r.detected||!r.entries?"nothing to suggest":`would suggest: ${r.entries.map(e=>`(cd "${e.root}" && python -m venv .venv && .venv/Scripts/pip install -r requirements.txt)`).join(" && ")}. Daimon does not run pip on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function cn(){let r=Ie();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=H.join(n,"Gemfile");if(!L.existsSync(s))continue;let i=H.join(n,"Gemfile.lock"),o=H.join(n,"vendor","bundle"),a=H.join(n,".bundle"),c=L.existsSync(o)?o:L.existsSync(a)?a:null;if(!c){t.push({root:n,reason:"missing"});continue}if(L.existsSync(i))try{let u=L.statSync(i).mtimeMs,h=L.statSync(c).mtimeMs;u>h+1e3&&t.push({root:n,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`bundler cache issues \u2014 ${t.map(n=>`${n.reason}: ${n.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Ruby searchRoot has a fresh bundle cache (or no Gemfile)"}}function Lo(){let r=cn();return!r.detected||!r.entries?"nothing to suggest":`would suggest: ${r.entries.map(e=>`(cd "${e.root}" && bundle install)`).join(" && ")}. Daimon does not run bundle install on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function ln(){let r=Ie();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=H.join(n,"Cargo.toml");if(!L.existsSync(s))continue;let i=H.join(n,"Cargo.lock"),o=H.join(n,"target");if(!L.existsSync(o)){t.push({root:n,reason:"missing"});continue}if(L.existsSync(i))try{let a=L.statSync(i).mtimeMs,c=L.statSync(o).mtimeMs;a>c+1e3&&t.push({root:n,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`cargo target issues \u2014 ${t.map(n=>`${n.reason}: ${n.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Rust searchRoot has a fresh target/ (or no Cargo.toml)"}}function Do(){let r=ln();return!r.detected||!r.entries?"nothing to suggest":`would suggest: ${r.entries.map(e=>`(cd "${e.root}" && cargo build)`).join(" && ")}. Daimon does not run cargo on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function un(){let r=Q();if(r.kind!=="loaded")return{detected:!1,description:"no config loaded"};let t=[];for(let e of r.config.searchRoots){let n=typeof e=="string"?e:e.path;n&&(L.existsSync(n)||t.push(n))}return t.length?{detected:!0,description:`searchRoots no longer on disk: ${t.join(", ")}`,dead:t}:{detected:!1,description:"every configured searchRoot resolves on disk"}}function Fo(){let r=un();if(!r.detected||!r.dead||!r.dead.length)return"nothing to remove";let{local:t,user:e}=dt(),n=L.existsSync(t)?t:e,s={};try{s=JSON.parse(L.readFileSync(n,"utf8"))}catch{}if(!Array.isArray(s.searchRoots))return"config has no searchRoots array; nothing removed";let i=new Set(r.dead),o=s.searchRoots.length;s.searchRoots=s.searchRoots.filter(u=>{let h=typeof u=="string"?u:u?.path;return!i.has(h)});let a=o-s.searchRoots.length;L.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
52
|
+
`,"utf8");let c=wt();if(c)try{fetch(`http://127.0.0.1:${c.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${a} dead searchRoot entr${a===1?"y":"ies"} from ${n} (${[...i].join(", ")}); triggered soft-reload. To undo: edit ${n} and re-add the path(s).`}async function Bo(r){let t={ran:[],skipped:[],errors:[]};for(let e of sn){if(!r.permitted.includes(e))continue;let n=Io[e],s;try{s=await n.detect()}catch(i){t.errors.push({name:e,error:i?.message??String(i)});continue}if(!s.detected){t.skipped.push({name:e,detected:!1,description:s.description});continue}if(r.dryRun){t.ran.push({name:e,detected:!0,description:`(dry-run) would fix: ${s.description}`});continue}try{let i=await n.fix();t.ran.push({name:e,detected:!0,description:`${s.description} \u2014 ${i}`})}catch(i){t.errors.push({name:e,error:i?.message??String(i)})}}return t}var sn,Io,_t=rt(()=>{"use strict";ft();Rt();Fe();Ht();sn=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"];Io={"orphan-daemon":{detect:So,fix:ko},"stale-lock":{detect:xo,fix:To},"missing-search-root":{detect:Eo,fix:Ro},"corrupt-history-db":{detect:Ao,fix:Po},"port-conflict-pred":{detect:Co,fix:Mo},"node-version-mismatch":{detect:Oo,fix:No},"orphan-node-modules":{detect:on,fix:_o},"orphan-venv":{detect:an,fix:$o},"orphan-bundler-cache":{detect:cn,fix:Lo},"orphan-cargo-target":{detect:ln,fix:Do},"dead-search-root":{detect:un,fix:Fo}}});var Be={};Ft(Be,{orchestrateProfile:()=>Wo});function pn(r,t,e,n,s){let i=r.summary(t);if(!i)return!1;if(e==="serving")return i.status==="serving";if(e==="healthy")return i.status==="serving"&&i.health==="healthy";let o=Date.now()-n;return i.status==="serving"&&i.health==="healthy"&&o>=s}async function dn(r,t,e,n,s){let i=Date.now();if(e!=="stable"){let c=await r.waitFor(t,e==="serving"?"serving":"healthy",n);return{reached:!c.timedOut,waitedMs:c.waitedMs}}let o=Date.now(),a=c=>{c?.app===t&&(o=Date.now())};r.on("event",a);try{for(;Date.now()-i<n;){if(pn(r,t,e,o,s))return{reached:!0,waitedMs:Date.now()-i};await new Promise(c=>setTimeout(c,500))}return{reached:pn(r,t,e,o,s),waitedMs:Date.now()-i}}finally{r.off("event",a)}}async function Wo(r,t,e){let n=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let i=s.filter(m=>r.summary(m)!=null),o=Array.from(new Set(i.flatMap(m=>Wt(t.depends??{},m)))).filter(m=>r.summary(m)!=null),a=Gt(t.depends??{},o),c=[];for(let m of o){let d=r.summary(m);d&&(e.goal==="serving"&&d.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&d.status==="serving"&&d.health==="healthy")&&c.push(m)}if(e.dryRun){let m=o.filter(d=>!c.includes(d));return{profile:e.profile,goal:e.goal,perApp:m.map(d=>({name:d,reached:!1,tries:0})),totalMs:Date.now()-n,allReached:m.length===0,dryRun:!0,plannedOrder:a,alreadyHealthy:c}}let u=Math.max(5e3,Math.floor(e.timeoutMs/2)),h=e.stableMs??5e3,p=new Map;for(let m of o)p.set(m,{name:m,reached:!1,tries:0});for(let m of a)await Promise.all(m.map(async d=>{let g=r.summary(d);if(!g){p.set(d,{name:d,reached:!1,tries:0,error:"unknown app"});return}if(c.includes(d)){p.set(d,{name:d,reached:!0,tries:0});return}g.status!=="starting"&&g.status!=="compiling"&&g.status!=="serving"&&await r.start(d)})),await Promise.all(m.map(async d=>{if(p.get(d)?.reached)return;let g=await dn(r,d,e.goal,u,h),x=p.get(d);x.tries=1,x.waitedMs=g.waitedMs,x.reached=g.reached,p.set(d,x)}));let y=[...p.values()].filter(m=>!m.reached);if(y.length>0){let{runAutoFix:m,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(_t(),jt)),g=t.doctor?.autoFix?.permitted??d,x=Math.max(5e3,e.timeoutMs-(Date.now()-n)),E=Math.max(5e3,Math.floor(x/Math.max(y.length,1))),w={ran:[]};try{w=await m({permitted:g,dryRun:!1})}catch{}let _=(w.ran??[]).map(A=>A.name);await Promise.all(y.map(async A=>{let C=p.get(A.name);C.tries=2;try{let $=await r.restart(A.name);$?.ok||(C.error=$?.error??"restart failed")}catch($){C.error=$?.message??String($)}let P=await dn(r,A.name,e.goal,E,h);if(C.waitedMs=(C.waitedMs??0)+P.waitedMs,C.reached=P.reached,!C.reached){let $=r.errors(A.name)??[];C.stillFailing=$.slice(0,3).map(T=>({file:T.parsed?.file??null,line:T.parsed?.line??null,code:T.parsed?.code??null,tool:T.parsed?.tool??null,message:T.parsed?.message??T.message}))}C.fixed=_,p.set(A.name,C)}))}let v=[...p.values()],l=v.every(m=>m.reached),f={profile:e.profile,goal:e.goal,perApp:v,totalMs:Date.now()-n,allReached:l};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let m=e.budgetTokens,d=0,g=0;for(let x of v)if(x.stillFailing){let E=x.stillFailing.length*Ho;E>m?(d+=x.stillFailing.length,delete x.stillFailing):m-=E}for(;m<0||v.length*Uo>Math.max(m,e.budgetTokens/4);){let x=v.findIndex(E=>E.reached);if(x===-1)break;v.splice(x,1),g++}(d||g)&&(f._meta={omitted:{}},d&&(f._meta.omitted.stillFailing=d),g&&(f._meta.omitted.perApp=g))}return f}var Ho,Uo,He=rt(()=>{"use strict";qt();Ho=60,Uo=25});Rt();Pt();import Ji from"react";import Xi from"node:path";import{render as Ki}from"ink";import{pathToFileURL as zi}from"node:url";import{EventEmitter as Vs}from"node:events";import{spawn as ks}from"node:child_process";import br from"tree-kill";import xs from"strip-ansi";import zn from"node:crypto";var Yn=[/Local:\s+http/i,/Application bundle generation complete/i,/compiled successfully/i,/webpack compiled\s+(?:successfully|in\b)/i,/Angular Live Development Server is listening/i,/Storybook\s+[\d.]+\s+(?:for\s+\S+\s+)?started/i,/VITE\s+v[\d.]+\s+ready/i,/Quit the server with CONTROL-C/i,/Uvicorn running on http/i,/Application startup complete/i,/Puma starting in single mode/i,/Use Ctrl-C to stop/i,/Listening on tcp:\/\//i,/running on http/i,/serving HTTP on/i,/trunk serve.*at/i],Vn=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i,/Watching for file changes with StatReloader/i,/Performing system checks/i,/watching files for changes/i,/building\.{3}/i,/Compiling \(/i],Zn=[/^\s*ERROR\b/,/\berror TS\d+/,/✘/,/\[ERROR\]/,/Cannot find module/i,/^FAIL\s+\S+/,/^\s*●\s+/,/^\s*>\s+NX\s+.*failed/i,/\bModule not found:/,/\[vite\]\s+(?:Internal server error|Pre-transform error)/i,/\[plugin:[^\]]+\]/i,/^\s*ERR!\s+/,/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):\s+/,/^Traceback \(most recent call last\):/,/^\s*[A-Z][a-zA-Z]*Error:\s+/,/^\s*\[error\]\s+/i,/^panic:\s+/,/^thread\s+'[^']+'\s+panicked at/,/^error\[E\d+\]:/,/^\S+\.(?:go|rb|py|rs):\d+:\d+:/,/^\s*[A-Z][a-zA-Z]*\.[A-Z][a-zA-Z]*:\s+/,/^[A-Z][a-zA-Z]+(?:::[A-Z][a-zA-Z]+)+\s*[(:]/,/^[A-Z][a-zA-Z]*Error\s*\(/],Qn=/\berror TS(\d+)/,ts=/✘\s*\[ERROR\]\s*TS(\d+)/,es=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)/,hr=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)\)/,rs=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,gr=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,yr=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,ns=/^([^\s:()]+\.rb):(\d+):in\b/,ss=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,os=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,is=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,as=[{tool:"vite",rx:/\[vite\]|\[plugin:vite:|transformWithEsbuild/i},{tool:"storybook",rx:/\bstorybook\b|^\s*ERR!\s|builder-vite/i},{tool:"jest",rx:/^FAIL\s|^\s*●\s+|\bjest\b/i},{tool:"nx",rx:/>\s+NX\s+|Failed tasks:|Nx errored/i},{tool:"webpack",rx:/\bModule not found:|webpack compiled|webpack-dev-server/i},{tool:"esbuild",rx:/✘\s*\[ERROR\]|esbuild/i},{tool:"typescript",rx:/\berror TS\d+/},{tool:"django",rx:/\bdjango\b|StatReloader|manage\.py runserver/i},{tool:"rails",rx:/\brails\b|Puma starting|Booting (?:Puma|Rails)|ActionController|NameError\s*\(|\.rb:\d+:in/i},{tool:"fastapi",rx:/\buvicorn\b|fastapi|ASGI/i},{tool:"go-air",rx:/\bair v\d|building\.{3}|\.go:\d+:\d+/i},{tool:"rust-trunk",rx:/\btrunk\b|^error\[E\d+\]|^\s*-->\s+\S+\.rs:/i},{tool:"python",rx:/^Traceback \(most recent call last\):|^\s*File "[^"]+\.py"|[A-Z][a-zA-Z]*Error:\s/},{tool:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];function cs(r){for(let{tool:t,rx:e}of as)if(e.test(r))return t}var ls=/Local:\s+(https?:\/\/\S+)/i,us=/Server running at\s+(https?:\/\/\S+)/i,ps=/listening on\s+(https?:\/\/\S+)/i,ds=/(?:listening|listen)\s+(https?:\/\/\S+)/i,fs=/Initial chunk files/i,ms=/Lazy chunk files/i,hs=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,gs=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i;function ys(r){return zn.createHash("sha1").update(r).digest("hex").slice(0,16)}function vs(r){let t={message:r},e=r.match(ts)||r.match(Qn);e&&(t.code=`TS${e[1]}`);let n=r.match(rs)||r.match(hr)||r.match(es);if(n)t.file=n[1],t.line=Number(n[2]),t.col=Number(n[3]);else{let i=r.match(os);if(i)t.file=i[1],i[2]&&(t.line=Number(i[2])),i[3]&&(t.col=Number(i[3]));else{let o=r.match(ss);if(o)t.file=o[1];else{let a=r.match(yr);if(a)t.file=a[1],t.line=Number(a[2]),t.col=Number(a[3]);else{let c=r.match(gr);c&&(t.file=c[1],t.line=Number(c[2]))}}}}let s=cs(r);return s&&(t.tool=s),t}function bs(r,t){try{let e=new URL(r);return e.hostname==="0.0.0.0"||e.hostname==="[::]"?(e.hostname=t.includes(":")?`[${t}]`:t,e.toString().replace(/\/$/,"")):r.replace(/\/$/,"")}catch{return r}}function ws(r,t="127.0.0.1"){let e=r.match(ls)||r.match(us)||r.match(ps)||r.match(ds);if(!e)return null;let n=e[1].replace(/[),.;]+$/,"");return bs(n,t)}function Ss(r,t){if(fs.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="initial",!1;if(ms.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="lazy",!1;let e=t.match(hs);if(e&&r.bundle){let s=parseFloat(e[2]),i=e[3].toUpperCase(),o=Math.round(i==="MB"?s*1024:i==="B"?s/1024:s);return/Initial/i.test(e[1])?r.bundle.initialKB=o:r.bundle.lazyKB=o,!0}let n=t.match(gs);if(n&&r.bundle){let s=n[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let i=n[4].toUpperCase(),o=parseFloat(n[3]),a=i==="MB"?o*1024:i==="B"?o/1024:o;return r.bundle.files.push({name:s,sizeKB:Math.round(a*10)/10}),!1}return!1}function vr(r,t){let e=t.match(is),n=e?null:t.match(hr),s=!e&&!n?t.match(yr):null,i=e??n??s;if(i&&r.lastErrorHash){let l=r.errors.get(r.lastErrorHash);l&&!l.parsed?.file&&(l.parsed={...l.parsed??{message:l.message},file:i[1],line:Number(i[2]),col:Number(i[3])})}else if(r.lastErrorHash){let l=t.match(gr),f=l?null:t.match(ns);if(l||f){let m=r.errors.get(r.lastErrorHash);if(m&&!m.parsed?.file){let d=l??f;m.parsed={...m.parsed??{message:m.message},file:d[1],line:Number(d[2])}}}}let o=t.trim();if(!o)return null;let a=r.status,c=!1,u,h=ws(o);h&&!r.announcedUrl&&(r.announcedUrl=h,u=h);let p=Ss(r,o),y;if(Yn.some(l=>l.test(o))){let l=r.status==="error"||!!r.recoveringFromError;if(r.status==="compiling"||r.status==="starting"||r.status==="error"){let f=Date.now();r.compileStartedAt!=null?(y=f-r.compileStartedAt,r.lastCompileMs=y,r.lastCompileAt=f,r.compileStartedAt=null,r.compileHistory.push(y),r.compileHistory.length>20&&r.compileHistory.splice(0,r.compileHistory.length-20)):r.lastCompileAt=f}r.status="serving",l&&(r.errors.clear(),r.recoveringFromError=!1)}else Vn.some(l=>l.test(o))&&(r.status==="starting"||r.status==="serving"||r.status==="error")&&(r.status==="error"&&(r.recoveringFromError=!0),r.compileStartedAt=Date.now(),r.status="compiling");let v;if(Zn.some(l=>l.test(o))){let l=ys(o),f=Date.now(),m=r.errors.get(l),d=!1,g;m?(m.count+=1,m.lastSeen=f,g=m):(g={message:o,count:1,firstSeen:f,lastSeen:f,parsed:vs(o)},r.errors.set(l,g),d=!0),r.lastErrorHash=l,v={entry:g,isNew:d},r.status="error"}return c=r.status!==a,{statusChanged:c,error:v,announcedUrl:u,bundleUpdated:p,compileMs:y}}var wr=500,Bt=class{child=null;stdoutBuf="";stderrBuf="";deps;stopping=!1;constructor(t){this.deps=t}isRunning(){return this.child!==null&&this.child.exitCode===null&&!this.stopping}start(){if(this.isRunning())return;let{app:t,port:e,state:n}=this.deps,s=Date.now();n.status="starting",n.startedAt=s,n.compileStartedAt=s,n.lastCompileMs=null,n.lastCompileAt=null,n.errors.clear(),n.logBuffer.length=0,n.lastStatusMessage=void 0;let o=`${this.deps.commandOverride||t.command} --port ${e}`,a={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},c=ks(o,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=c,n.pid=c.pid??null,n.port=e,c.stdout?.on("data",u=>this.handleChunk(u,"stdout")),c.stderr?.on("data",u=>this.handleChunk(u,"stderr")),c.on("exit",(u,h)=>{let p=n.status,y=this.stopping;y?(n.status="stopped",n.lastStatusMessage=`stopped (code=${u??"null"}${h?`, ${h}`:""})`):u!==0?(n.status="error",n.lastStatusMessage=`process exited with code ${u}${h?` (${h})`:""}`):n.status="stopped",n.pid=null,n.health="unknown",this.child=null,this.stopping=!1,p!==n.status&&this.deps.onStatusChange?.(p,n.status,n.lastStatusMessage),this.deps.onExit?.(u,h,y),this.deps.onStateChange()}),c.on("error",u=>{n.status="error",n.lastStatusMessage=`spawn error: ${u.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let n=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=n,i=s.lastIndexOf(`
|
|
53
|
+
`);if(i<0)return;let o=s.slice(0,i),a=s.slice(i+1);e==="stdout"?this.stdoutBuf=a:this.stderrBuf=a;let{state:c}=this.deps,u=!1;for(let h of o.split(/\r?\n/)){if(!h.length)continue;let p=xs(h),y=Date.now();c.lastLogTs=y,c.stale&&(c.stale=!1),c.logBuffer.push({ts:y,line:p}),c.logBuffer.length>wr&&c.logBuffer.splice(0,c.logBuffer.length-wr),this.deps.onLogLine?.(p);let v=c.status,l=vr(c,p);l?.statusChanged&&(u=!0,this.deps.onStatusChange?.(v,c.status)),l?.error&&this.deps.onErrorRecorded?.(l.error.entry,l.error.isNew),l?.compileMs!=null&&this.deps.onCompile?.(l.compileMs),l?.bundleUpdated&&this.deps.onBundleUpdate?.()}(u||o.length>0)&&this.deps.onStateChange()}async stop(){if(!this.child||this.stopping)return;this.stopping=!0;let t=this.child.pid;if(!t){this.child=null,this.stopping=!1;return}await new Promise(e=>{let n=!1,s=()=>{n||(n=!0,e())},i=()=>s();this.child?.once("exit",i),br(t,"SIGTERM",()=>{});let o=setTimeout(()=>{br(t,"SIGKILL",()=>{})},2e3),a=setTimeout(()=>{clearTimeout(o),s()},3e3);this.child?.once("exit",()=>{clearTimeout(o),clearTimeout(a),s()})})}};Ht();import tt from"node:fs";import Es from"node:path";var Ut=class{constructor(t,e){this.appName=t;this.cfg=e;this.filePath=Es.join(e.dir,`${t}.log`),this.open()}appName;cfg;fd=null;bytes=0;warned=!1;filePath;open(){try{tt.mkdirSync(this.cfg.dir,{recursive:!0});try{this.bytes=tt.statSync(this.filePath).size}catch{this.bytes=0}this.fd=tt.openSync(this.filePath,"a")}catch(t){this.warn(`open failed: ${t.message}`),this.fd=null}}write(t){if(this.fd!=null)try{let e=`${new Date().toISOString()} ${t}
|
|
54
|
+
`,n=Buffer.from(e,"utf8");tt.writeSync(this.fd,n),this.bytes+=n.length,this.bytes>=this.cfg.maxBytesPerFile&&this.rotate()}catch(e){this.warn(`write failed: ${e.message}`)}}close(){if(this.fd!=null){try{tt.closeSync(this.fd)}catch{}this.fd=null}}rotate(){try{this.close();for(let t=this.cfg.maxFiles-1;t>=1;t--){let e=`${this.filePath}.${t}`,n=`${this.filePath}.${t+1}`;if(t+1>this.cfg.maxFiles-1){try{tt.rmSync(e,{force:!0})}catch{}continue}try{tt.existsSync(e)&&tt.renameSync(e,n)}catch{}}try{let t=`${this.filePath}.1`;tt.existsSync(this.filePath)&&tt.renameSync(this.filePath,t)}catch{}this.open()}catch(t){this.warn(`rotate failed: ${t.message}`)}}warn(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] warning: diskLogger(${this.appName}) ${t}
|
|
55
|
+
`))}};qt();import{spawn as Tr}from"node:child_process";import xr from"tree-kill";import Er from"strip-ansi";var Rs=/Tests:\s+(?:(\d+)\s+failed,\s+)?(?:(\d+)\s+skipped,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,As=/Test Suites:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Ps=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,Cs=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i,Ms=/Tests\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,Os=/Test Files\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,Ns=/(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+\d+\s+skipped)?\s+in\s+([\d.]+)s/,js=/(\d+)\s+examples?,\s+(\d+)\s+failures?/,_s=/^(ok|FAIL|---\s+FAIL)\s+\S+\s+([\d.]+)s/,$s=/test result:\s*(?:ok|FAILED)\.\s+(\d+)\s+passed;\s+(\d+)\s+failed/,Ls=/^\s*✕\s+(.+?)(?:\s+\((\d+)\s*ms\))?$/,Ds=/^\s*FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|spec\.[a-z]+))/,Fs=/^FAILED\s+(\S+)::([^\s]+)/;function xe(r){let t=[],e;for(let n of r.split(/\r?\n/)){let s=n.match(Ds);if(s){e=s[1];continue}let i=n.match(Ls);if(i){t.push({name:i[1].trim(),file:e});continue}let o=n.match(Fs);if(o){t.push({name:o[2],file:o[1]});continue}}return t.slice(0,50)}function Is(r){let t=r.match(Rs);if(t){let y=t[1]?Number(t[1]):0,v=Number(t[3]),l=t[4]?Number(t[4]):v+y,f=r.match(As);return{passed:v,failed:y,total:l,suites:f?Number(f[3]??f[2]):void 0,framework:"jest",failedTests:y>0?xe(r):void 0}}let e=r.match(Ms);if(e){let y=e[1]?Number(e[1]):0,v=Number(e[2]),l=e[3]?Number(e[3]):v+y,f=r.match(Os);return{passed:v,failed:y,total:l,suites:f?Number(f[3]??f[2]):void 0,framework:"vitest",failedTests:y>0?xe(r):void 0}}let n=r.match(Ps);if(n){let y=Number(n[1]),v=Number(n[2]),l=n[3]?Number(n[3]):0;return{passed:y-l,failed:l,total:v,framework:"karma"}}let s=r.match(Cs);if(s&&/playwright/i.test(r)){let y=Number(s[1]),v=s[2]?Number(s[2]):0;return{passed:y,failed:v,total:y+v,framework:"playwright"}}let i=r.match(Ns);if(i){let y=i[1]?Number(i[1]):0,v=Number(i[2]);return{passed:v,failed:y,total:v+y,durationMs:Math.round(Number(i[3])*1e3),framework:"pytest",failedTests:y>0?xe(r):void 0}}let o=r.match(js);if(o){let y=Number(o[1]),v=Number(o[2]);return{passed:y-v,failed:v,total:y,framework:"rspec"}}let a=r.match($s);if(a){let y=Number(a[1]),v=Number(a[2]);return{passed:y,failed:v,total:y+v,framework:"cargo"}}let c=0,u=0,h=0,p=!1;for(let y of r.split(/\r?\n/)){let v=y.match(_s);v&&(p=!0,h+=Math.round(Number(v[2])*1e3),v[1]==="ok"?c++:u++)}if(p)return{passed:c,failed:u,total:c+u,durationMs:h,framework:"go"};if(s){let y=Number(s[1]),v=s[2]?Number(s[2]):0;return{passed:y,failed:v,total:y+v,framework:"playwright"}}return null}function Rr(r,t,e){let n=e.length?" -- "+e.join(" "):"";return r.workspaceType==="nx"?`npx nx run ${r.name}:${t}${n}`:r.workspaceType==="angular"?`npx ng run ${r.name}:${t}${n}`:`npx ${t}${n}`}function Ar(r,t,e=[]){return new Promise(n=>{let s=Date.now(),i=Rr(r,t,e),o=Tr(i,[],{cwd:r.workspaceRoot,shell:!0,env:{...process.env,...r.env||{},FORCE_COLOR:"0"},windowsHide:!0}),a=[],c="",u=h=>{c+=h.toString("utf8");let p=c.lastIndexOf(`
|
|
56
|
+
`);if(p<0)return;let y=c.slice(0,p);c=c.slice(p+1);for(let v of y.split(/\r?\n/)){if(!v.length)continue;let l=Er(v);a.push(l),a.length>1e3&&a.splice(0,a.length-1e3)}};o.stdout?.on("data",u),o.stderr?.on("data",u),o.on("exit",h=>{let p=Date.now()-s,y=a.join(`
|
|
48
57
|
`)+(c?`
|
|
49
|
-
`+c:""),
|
|
50
|
-
`);if(h<0)return;let p=o.slice(0,h);o=o.slice(h+1);for(let
|
|
51
|
-
`;try{Ae.appendFileSync(this.file,e)}catch{}}};var Dr=500,zt=class extends Ms{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new Xt;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new ht(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.tags,s.workspaceLabel??null),proc:null})}getConfig(){return this.config}addDiscoveredApp(t){this.entries.has(t.name)||(this.entries.set(t.name,{app:t,state:this.freshState(t.name,t.tags,t.workspaceLabel??null),proc:null}),this.emit("change"))}updateDiscoveredApp(t){let e=this.entries.get(t.name);e&&(e.app=t,e.state.tags=t.tags,e.state.workspaceLabel=t.workspaceLabel??null,e.state.dependsOn=this.config.depends?.[t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r=null){return{name:t,status:"stopped",port:null,pid:null,startedAt:null,compileStartedAt:null,lastCompileMs:null,lastCompileAt:null,logBuffer:[],errors:new Map,compileHistory:[],health:"unknown",lastHealthAt:null,cpu:null,memMB:null,restartAttempts:0,restartWindowStart:null,nextRestartAt:null,tags:e,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[t]??[],workspaceLabel:r,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let r=e.state,s=r.startedAt&&(r.status==="serving"||r.status==="compiling"||r.status==="starting")?Date.now()-r.startedAt:null,o=this.config.overrides?.[t]?.url||e.resolvedUrl||r.announcedUrl||(r.port?`http://127.0.0.1:${r.port}`:null),a;for(let c=this.eventBuffer.length-1;c>=0;c--){let u=this.eventBuffer[c];if(u.app===t&&u.type==="status"){a=Date.now()-u.ts;break}}return{name:r.name,status:r.status,port:r.port,url:o,errorCount:[...r.errors.values()].reduce((c,u)=>c+u.count,0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,i)=>i.lastSeen-s.lastSeen):null}logs(t,e={}){let r=this.getState(t);if(!r)return null;let s=r.logBuffer;if(e.sinceMs&&e.sinceMs>0){let i=Date.now()-e.sinceMs;s=s.filter(o=>o.ts>=i)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(i=>i.line)}events(t={}){let e=t.sinceMs&&t.sinceMs>0?Date.now()-t.sinceMs:0;return this.eventBuffer.filter(r=>r.ts>=e&&(!t.app||r.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>Dr&&this.eventBuffer.splice(0,this.eventBuffer.length-Dr),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let r=this.entries.get(t);if(!r)return;let s=r.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let i=s.health;s.health=e,e==="healthy"&&(r.prevHealthyAt=Date.now(),r.cascadeArmed&&(r.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from:i,to:e}),this.emit("change")}armCascade(t){let e=this.entries.get(t);e&&this.config.cascadeRestart&&e.prevHealthyAt!=null&&(e.cascadeArmed=!0)}setLastHealthError(t,e){let r=this.getState(t);r&&r.lastHealthError!==e&&(r.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let r=this.entries.get(t);r&&r.resolvedUrl!==e&&(r.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let r=this.getState(t);r&&(r.cachedProbeHost=e)}setStale(t,e){let r=this.getState(t);r&&r.stale!==e&&(r.stale=e,this.emit("change"))}setSessionOverride(t,e){let r=this.getState(t);r&&(r.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let r=this.getState(t);r&&(r.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let r=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(b){return e.state.status="error",e.state.lastStatusMessage=b.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:b.message}),this.emit("change"),{ok:!1,status:"error",error:b.message}}if(!await gt(s)){let b=Er(s),l=Rr(s,b);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=l,this.recordEvent({app:t,type:"status",from:r,to:"error",message:l}),this.emit("change"),{ok:!1,status:"error",error:l}}e.state.health="unknown",e.state.lastHealthAt=null,e.state.announcedUrl=null,e.state.lastHealthError=null,e.state.cachedProbeHost=null,e.state.stale=!1,e.state.lastLogTs=null,e.resolvedUrl=void 0,!e.logger&&this.config.logs.enabled&&(e.logger=new Ht(t,this.config.logs));let o=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],c={};if(a.length){let b=e.state.activeEnvFile;(!b||!xe(e.app.workspaceRoot,[b]).length)&&(b=xe(e.app.workspaceRoot,a)[0]??null,b&&(e.state.activeEnvFile=b)),b&&(c=Pr(Se(e.app.workspaceRoot,b)))}let u={...c,...this.config.overrides?.[t]?.env??{},...o?.env??{}},h=$r(),p=_r(u,h),v=new It({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:o?.command,onStateChange:()=>this.emit("change"),onStatusChange:(b,l,m)=>{this.recordEvent({app:t,type:"status",from:b,to:l,message:m}),(l==="stopped"||l==="error")&&(b==="serving"||b==="compiling")&&this.armCascade(t)},onErrorRecorded:(b,l)=>this.recordEvent({app:t,type:l?"error-new":"error-recur",message:b.message}),onExit:(b,l,m)=>this.emit("childExit",{name:t,code:b,signal:l,stopping:m}),onLogLine:b=>{e.logger?.write(b),this.emit("log",{name:t,ts:Date.now(),line:b})},onCompile:b=>{this.history?.recordCompile(t,b);let l=this.getState(t),m=e.lastBundleInitialKB;if(l.bundle&&l.bundle.initialKB>0){if(m&&m>0){let f=(l.bundle.initialKB-m)/m*100;l.bundleRegressionPct=Math.round(f*10)/10,f>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${l.bundleRegressionPct}% (${m}->${l.bundle.initialKB})`})}else l.bundleRegressionPct=null;e.lastBundleInitialKB=l.bundle.initialKB}this.checkCompileRegression(t,b),this.emit("compile",{name:t,ms:b})},onBundleUpdate:()=>{let b=this.getState(t);b?.bundle&&(b.bundle.initialKB>0||b.bundle.lazyKB>0)&&this.history?.recordBundle(t,b.bundle.initialKB,b.bundle.lazyKB,b.bundle.files.length),this.emit("bundleUpdate",{name:t})}});return e.proc=v,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),v.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let r=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==r&&this.recordEvent({app:t,type:"status",from:r,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let r=Ut(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=Wt(this.config.depends??{},r),i=[],o=e.waitMs??6e4;for(let a of s){let c=await Promise.all(a.map(h=>this.start(h)));for(let h=0;h<a.length;h++){let p=c[h];if(!p.ok)return i.push({name:a[h],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:i}}let u=await Promise.all(a.map(h=>this.waitFor(h,"healthy",o)));for(let h=0;h<a.length;h++){let p=u[h],v=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(i.push({name:p.name,status:p.status,health:p.health,error:v?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!v)return{ok:!1,results:i}}}return{ok:!0,results:i}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=vr(this.config.depends??{},t);for(let r of e){let s=this.getState(r);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(r)}}async stopAll(t=3e3){let e=[];for(let r of this.entries.values())r.proc?.isRunning()&&e.push(r.proc.stop());for(let r of this.watchTasks.values())e.push(r.stop());await Promise.race([Promise.all(e),new Promise(r=>setTimeout(r,t))]);for(let r of this.entries.values())r.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,r=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:r});let s=this.getApp(t);if(!s)return{error:"unknown app"};let i=await kr(s,e,r);return this.history?.recordTaskRun(t,e,i.exitCode,i.durationMs,i.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${i.exitCode} duration=${i.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:i}),i}startWatchTask(t,e,r=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let i=`${t}::${e}`;if(this.watchTasks.has(i))return{ok:!0,pid:this.watchTasks.get(i).pid};let o=Tr(s,e,r);return this.watchTasks.set(i,o),o.child.on("exit",()=>this.watchTasks.delete(i)),{ok:!0,pid:o.pid}}async stopWatchTask(t,e){let r=`${t}::${e}`,s=this.watchTasks.get(r);return s?(await s.stop(),this.watchTasks.delete(r),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let r of this.watchTasks.values())t&&r.app!==t||e.push({app:r.app,task:r.task,pid:r.pid,startedAt:r.startedAt});return e}checkCompileRegression(t,e){let r=this.history;if(!r)return;let i=r.queryCompiles({app:t,limit:31}).filter(c=>c.ms!==e).slice(0,30).map(c=>c.ms);if(i.length<10)return;let o=[...i].sort((c,u)=>c-u),a=o[Math.floor((o.length-1)*.5)];e>2*a&&this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs p50 ${(a/1e3).toFixed(1)}s`})}watchTaskLogs(t,e,r){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let i=s.logs;return r?i.slice(-r):[...i]}waitFor(t,e,r){return new Promise(s=>{let i=Date.now(),o=this.entries.get(t),a=()=>{if(!o)return!0;let p=o.state;return e==="serving"&&p.status==="serving"||e==="healthy"&&p.status==="serving"&&p.health==="healthy"||e==="stopped"&&p.status==="stopped"||e==="error"&&p.status==="error"},c=p=>{this.off("change",u),clearTimeout(h);let v=o?.state;s({name:t,status:v?.status??"unknown",health:v?.health??"unknown",timedOut:p,waitedMs:Date.now()-i})},u=()=>{a()&&c(!1)};if(a()){s({name:t,status:o.state.status,health:o.state.health,timedOut:!1,waitedMs:0});return}let h=setTimeout(()=>c(!0),r);this.on("change",u)})}};Bt();import To from"node:http";import Eo from"node:crypto";import ft from"node:fs";import Y from"node:path";import{fileURLToPath as Ro}from"node:url";import Oe from"node:fs";import Fr from"node:path";import js from"node:os";var Me=Fr.join(js.homedir(),".daimon","cursors.json");function Ns(){try{let n=Oe.readFileSync(Me,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}var Ce=null,Pe=null;function $s(n){Pe=n,!Ce&&(Ce=setTimeout(()=>{Ce=null;let t=Pe;if(Pe=null,!!t)try{Oe.mkdirSync(Fr.dirname(Me),{recursive:!0}),Oe.writeFileSync(Me,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
52
|
-
`)}},500))}var Yt=class{data=
|
|
58
|
+
`+c:""),v=Is(y);n({app:r.name,task:t,exitCode:h,durationMs:p,summary:v,outputTail:a.slice(-50)})}),o.on("error",()=>{n({app:r.name,task:t,exitCode:-1,durationMs:Date.now()-s,summary:null,outputTail:[...a,"[daimon] task spawn error"]})})})}function Pr(r,t,e=[]){let n=Rr(r,t,e),s=Tr(n,[],{cwd:r.workspaceRoot,shell:!0,env:{...process.env,...r.env||{},FORCE_COLOR:"0"},windowsHide:!0}),i=[],o="",a=u=>{o+=u.toString("utf8");let h=o.lastIndexOf(`
|
|
59
|
+
`);if(h<0)return;let p=o.slice(0,h);o=o.slice(h+1);for(let y of p.split(/\r?\n/))y.length&&(i.push(Er(y)),i.length>500&&i.splice(0,i.length-500))};return s.stdout?.on("data",a),s.stderr?.on("data",a),{app:r.name,task:t,pid:s.pid??null,child:s,startedAt:Date.now(),logs:i,stop:()=>new Promise(u=>{if(!s.pid){u();return}let h=!1,p=()=>{h||(h=!0,u())};s.once("exit",p),xr(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&xr(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(p,3500)})}}import{spawnSync as Te}from"node:child_process";import Aa from"tree-kill";function Cr(r){if(process.platform==="win32"){let i=Te("powershell",["-NoProfile","-Command",`Get-NetTCPConnection -LocalPort ${r} -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty OwningProcess`],{encoding:"utf8",windowsHide:!0});if(i.status!==0)return null;let o=Number((i.stdout||"").trim().split(/\s+/)[0]);if(!Number.isFinite(o)||o<=0)return null;let a=Te("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${o}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),c,u;try{let h=JSON.parse((a.stdout||"").trim()||"{}");c=typeof h.Name=="string"?h.Name:void 0,u=typeof h.CommandLine=="string"?h.CommandLine:void 0}catch{}return{pid:o,name:c,cmd:u}}let t=Te("lsof",["-nP","-iTCP:"+r,"-sTCP:LISTEN"],{encoding:"utf8"});if(t.status!==0)return null;let e=(t.stdout||"").split(/\r?\n/).filter(i=>i.trim()&&!i.startsWith("COMMAND"));if(!e.length)return null;let n=e[0].split(/\s+/);return{pid:Number(n[1]),name:n[0]}}function Mr(r,t){if(!t)return`port ${r} already in use`;let e=[`port ${r} in use by`];return t.name&&e.push(t.name),e.push(`(pid ${t.pid}`),t.cmd&&(e[e.length-1]+=`, cmd: ${t.cmd.slice(0,120)}`),e[e.length-1]+=")",e.join(" ")}import Nr from"node:fs";import Or from"node:path";function jr(r){let t={},e;try{e=Nr.readFileSync(r,"utf8")}catch{return t}for(let n of e.split(/\r?\n/)){let s=n.trim();if(!s||s.startsWith("#"))continue;let i=s.indexOf("=");if(i<0)continue;let o=s.slice(0,i).trim(),a=s.slice(i+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),o&&(t[o]=a)}return t}function Ee(r,t){return Or.isAbsolute(t)?t:Or.join(r,t)}function Re(r,t){return t.filter(e=>Nr.existsSync(Ee(r,e)))}ft();import Xs from"node:fs";import Ks from"node:path";function zs(){return Ks.join(it(),"secrets.json")}function Fr(){try{let r=Xs.readFileSync(zs(),"utf8");r.charCodeAt(0)===65279&&(r=r.slice(1));let t=JSON.parse(r);if(!t||typeof t!="object")return{};let e={};for(let[n,s]of Object.entries(t))typeof s=="string"&&(e[n]=s);return e}catch{return{}}}function Ir(r,t){let e={};for(let[n,s]of Object.entries(r))e[n]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(i,o)=>t[o]??`\${${o}}`);return e}import Oe from"node:fs";import Ys from"node:os";import Br from"node:path";var Kt=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=Br.join(Ys.homedir(),".daimon","sessions");Oe.mkdirSync(t,{recursive:!0});let e=Br.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return Oe.writeFileSync(e,""),this.file=e,this.startTs=Date.now(),{path:e}}stop(){let t={path:this.file};return this.file=null,this.startTs=0,t}append(t){if(!this.file)return;let e=JSON.stringify({ts:Date.now()-this.startTs,...t})+`
|
|
60
|
+
`;try{Oe.appendFileSync(this.file,e)}catch{}}};var Hr=500,zt=class extends Vs{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new Kt;constructor(t,e,n){super(),this.config=t,this.portAlloc=n??new gt(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.tags,s.workspaceLabel??null),proc:null})}getConfig(){return this.config}addDiscoveredApp(t){this.entries.has(t.name)||(this.entries.set(t.name,{app:t,state:this.freshState(t.name,t.tags,t.workspaceLabel??null),proc:null}),this.emit("change"))}updateDiscoveredApp(t){let e=this.entries.get(t.name);e&&(e.app=t,e.state.tags=t.tags,e.state.workspaceLabel=t.workspaceLabel??null,e.state.dependsOn=this.config.depends?.[t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,n=null){return{name:t,status:"stopped",port:null,pid:null,startedAt:null,compileStartedAt:null,lastCompileMs:null,lastCompileAt:null,logBuffer:[],errors:new Map,compileHistory:[],health:"unknown",lastHealthAt:null,cpu:null,memMB:null,restartAttempts:0,restartWindowStart:null,nextRestartAt:null,tags:e,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[t]??[],workspaceLabel:n,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}pruneOldErrors(t=Date.now()){let e=this.config.errorRetention?.maxAgeMs??864e5,n=0;for(let s of this.entries.values())for(let[i,o]of s.state.errors)t-o.lastSeen>e&&(s.state.errors.delete(i),n++);return n}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let n=e.state,s=n.startedAt&&(n.status==="serving"||n.status==="compiling"||n.status==="starting")?Date.now()-n.startedAt:null,o=this.config.overrides?.[t]?.url||e.resolvedUrl||n.announcedUrl||(n.port?`http://127.0.0.1:${n.port}`:null),a;for(let c=this.eventBuffer.length-1;c>=0;c--){let u=this.eventBuffer[c];if(u.app===t&&u.type==="status"){a=Date.now()-u.ts;break}}return{name:n.name,status:n.status,port:n.port,url:o,errorCount:[...n.errors.values()].reduce((c,u)=>c+u.count,0),uptimeMs:s,lastCompileMs:n.lastCompileMs,health:n.health,lastHealthAt:n.lastHealthAt,cpu:n.cpu,memMB:n.memMB,compileHistoryMs:[...n.compileHistory],tags:[...n.tags],restartAttempts:n.restartAttempts,nextRestartAt:n.nextRestartAt,announcedUrl:n.announcedUrl,lastHealthError:n.lastHealthError,stale:n.stale,bundle:n.bundle,bundleRegressionPct:n.bundleRegressionPct,dependsOn:[...n.dependsOn],activeEnvFile:n.activeEnvFile,workspaceLabel:n.workspaceLabel,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((n,s)=>s.lastSeen-n.lastSeen):null}errorsSince(t,e){let n=this.getState(t);return n?[...n.errors.values()].filter(s=>s.lastSeen>e).sort((s,i)=>i.lastSeen-s.lastSeen):null}logs(t,e={}){let n=this.getState(t);if(!n)return null;let s=n.logBuffer;if(e.sinceMs&&e.sinceMs>0){let i=Date.now()-e.sinceMs;s=s.filter(o=>o.ts>=i)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(i=>i.line)}events(t={}){let e=t.sinceMs&&t.sinceMs>0?Date.now()-t.sinceMs:0;return this.eventBuffer.filter(n=>n.ts>=e&&(!t.app||n.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>Hr&&this.eventBuffer.splice(0,this.eventBuffer.length-Hr),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let n=this.entries.get(t);if(!n)return;let s=n.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let i=s.health;s.health=e,e==="healthy"&&(n.prevHealthyAt=Date.now(),n.cascadeArmed&&(n.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from:i,to:e}),this.emit("change")}armCascade(t){let e=this.entries.get(t);e&&this.config.cascadeRestart&&e.prevHealthyAt!=null&&(e.cascadeArmed=!0)}setLastHealthError(t,e){let n=this.getState(t);n&&n.lastHealthError!==e&&(n.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let n=this.entries.get(t);n&&n.resolvedUrl!==e&&(n.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let n=this.getState(t);n&&(n.cachedProbeHost=e)}setStale(t,e){let n=this.getState(t);n&&n.stale!==e&&(n.stale=e,this.emit("change"))}setSessionOverride(t,e){let n=this.getState(t);n&&(n.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let n=this.getState(t);n&&(n.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let n=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(v){return e.state.status="error",e.state.lastStatusMessage=v.message,this.recordEvent({app:t,type:"status",from:n,to:"error",message:v.message}),this.emit("change"),{ok:!1,status:"error",error:v.message}}if(!await yt(s)){let v=Cr(s),l=Mr(s,v);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=l,this.recordEvent({app:t,type:"status",from:n,to:"error",message:l}),this.emit("change"),{ok:!1,status:"error",error:l}}e.state.health="unknown",e.state.lastHealthAt=null,e.state.announcedUrl=null,e.state.lastHealthError=null,e.state.cachedProbeHost=null,e.state.stale=!1,e.state.lastLogTs=null,e.resolvedUrl=void 0,!e.logger&&this.config.logs.enabled&&(e.logger=new Ut(t,this.config.logs));let o=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],c={};if(a.length){let v=e.state.activeEnvFile;(!v||!Re(e.app.workspaceRoot,[v]).length)&&(v=Re(e.app.workspaceRoot,a)[0]??null,v&&(e.state.activeEnvFile=v)),v&&(c=jr(Ee(e.app.workspaceRoot,v)))}let u={...c,...this.config.overrides?.[t]?.env??{},...o?.env??{}},h=Fr(),p=Ir(u,h),y=new Bt({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:o?.command,onStateChange:()=>this.emit("change"),onStatusChange:(v,l,f)=>{this.recordEvent({app:t,type:"status",from:v,to:l,message:f}),(l==="stopped"||l==="error")&&(v==="serving"||v==="compiling")&&this.armCascade(t)},onErrorRecorded:(v,l)=>this.recordEvent({app:t,type:l?"error-new":"error-recur",message:v.message}),onExit:(v,l,f)=>this.emit("childExit",{name:t,code:v,signal:l,stopping:f}),onLogLine:v=>{e.logger?.write(v),this.emit("log",{name:t,ts:Date.now(),line:v})},onCompile:v=>{this.history?.recordCompile(t,v);let l=this.getState(t),f=e.lastBundleInitialKB;if(l.bundle&&l.bundle.initialKB>0){if(f&&f>0){let m=(l.bundle.initialKB-f)/f*100;l.bundleRegressionPct=Math.round(m*10)/10,m>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${l.bundleRegressionPct}% (${f}->${l.bundle.initialKB})`})}else l.bundleRegressionPct=null;e.lastBundleInitialKB=l.bundle.initialKB}this.checkCompileRegression(t,v),this.emit("compile",{name:t,ms:v})},onBundleUpdate:()=>{let v=this.getState(t);v?.bundle&&(v.bundle.initialKB>0||v.bundle.lazyKB>0)&&this.history?.recordBundle(t,v.bundle.initialKB,v.bundle.lazyKB,v.bundle.files.length),this.emit("bundleUpdate",{name:t})}});return e.proc=y,this.recordEvent({app:t,type:"status",from:n,to:"starting"}),y.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let n=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==n&&this.recordEvent({app:t,type:"status",from:n,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let n=Wt(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=Gt(this.config.depends??{},n),i=[],o=e.waitMs??6e4;for(let a of s){let c=await Promise.all(a.map(h=>this.start(h)));for(let h=0;h<a.length;h++){let p=c[h];if(!p.ok)return i.push({name:a[h],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:i}}let u=await Promise.all(a.map(h=>this.waitFor(h,"healthy",o)));for(let h=0;h<a.length;h++){let p=u[h],y=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(i.push({name:p.name,status:p.status,health:p.health,error:y?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!y)return{ok:!1,results:i}}}return{ok:!0,results:i}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=kr(this.config.depends??{},t);for(let n of e){let s=this.getState(n);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(n)}}async stopAll(t=3e3){let e=[];for(let n of this.entries.values())n.proc?.isRunning()&&e.push(n.proc.stop());for(let n of this.watchTasks.values())e.push(n.stop());await Promise.race([Promise.all(e),new Promise(n=>setTimeout(n,t))]);for(let n of this.entries.values())n.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,n=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:n});let s=this.getApp(t);if(!s)return{error:"unknown app"};let i=await Ar(s,e,n);return this.history?.recordTaskRun(t,e,i.exitCode,i.durationMs,i.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${i.exitCode} duration=${i.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:i}),i}startWatchTask(t,e,n=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let i=`${t}::${e}`;if(this.watchTasks.has(i))return{ok:!0,pid:this.watchTasks.get(i).pid};let o=Pr(s,e,n);return this.watchTasks.set(i,o),o.child.on("exit",()=>this.watchTasks.delete(i)),{ok:!0,pid:o.pid}}async stopWatchTask(t,e){let n=`${t}::${e}`,s=this.watchTasks.get(n);return s?(await s.stop(),this.watchTasks.delete(n),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let n of this.watchTasks.values())t&&n.app!==t||e.push({app:n.app,task:n.task,pid:n.pid,startedAt:n.startedAt});return e}checkCompileRegression(t,e){let n=this.history;if(!n)return;let i=n.queryCompiles({app:t,limit:31}).filter(c=>c.ms!==e).slice(0,30).map(c=>c.ms);if(i.length<10)return;let o=[...i].sort((c,u)=>c-u),a=o[Math.floor((o.length-1)*.5)];e>2*a&&this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs p50 ${(a/1e3).toFixed(1)}s`})}watchTaskLogs(t,e,n){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let i=s.logs;return n?i.slice(-n):[...i]}waitFor(t,e,n){return new Promise(s=>{let i=Date.now(),o=this.entries.get(t),a=()=>{if(!o)return!0;let p=o.state;return e==="serving"&&p.status==="serving"||e==="healthy"&&p.status==="serving"&&p.health==="healthy"||e==="stopped"&&p.status==="stopped"||e==="error"&&p.status==="error"},c=p=>{this.off("change",u),clearTimeout(h);let y=o?.state;s({name:t,status:y?.status??"unknown",health:y?.health??"unknown",timedOut:p,waitedMs:Date.now()-i})},u=()=>{a()&&c(!1)};if(a()){s({name:t,status:o.state.status,health:o.state.health,timedOut:!1,waitedMs:0});return}let h=setTimeout(()=>c(!0),n);this.on("change",u)})}};Ht();import Go from"node:http";import qo from"node:crypto";import mt from"node:fs";import Y from"node:path";import{fileURLToPath as Jo}from"node:url";import _e from"node:fs";import Ur from"node:path";import Zs from"node:os";var $e=Ur.join(Zs.homedir(),".daimon","cursors.json");function Qs(){try{let r=_e.readFileSync($e,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}var Ne=null,je=null;function to(r){je=r,!Ne&&(Ne=setTimeout(()=>{Ne=null;let t=je;if(je=null,!!t)try{_e.mkdirSync(Ur.dirname($e),{recursive:!0}),_e.writeFileSync($e,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
61
|
+
`)}},500))}var Yt=class{data=Qs();getErrorCursor(t,e){return this.data.errors[`${t}:${e}`]??0}setErrorCursor(t,e,n){this.data.errors[`${t}:${e}`]=n,to(this.data)}};import Wr from"node:fs";import eo from"node:os";import Gr from"node:path";var ro=/key|secret|token|password|api[-_]?key/i;function no(r){let t={};for(let[e,n]of Object.entries(r))typeof n=="string"&&(t[e]=ro.test(e)?"***":n);return t}function Le(r,t){let e=r.summary(t);if(!e)return null;let n=r.getState(t),s=r.getApp(t),i=r.getConfig(),o=i.overrides?.[t]??{},a={...process.env,...s.env??{},...n.sessionOverrides?.env??{}},c=r.getHistory(),u=c?c.queryEvents({app:t,limit:50}):[],h=c?c.queryBundles({app:t,limit:100}):[],p=c?c.querySelfMetrics({limit:60}):[];return{takenAt:new Date().toISOString(),summary:e,logs:n.logBuffer.slice(-500).map(y=>({ts:y.ts,line:y.line})),errors:[...n.errors.entries()].map(([y,v])=>({hash:y,message:v.message,count:v.count,firstSeen:v.firstSeen,lastSeen:v.lastSeen})),env:no(a),configSlice:{command:n.sessionOverrides?.command??o.command??s.command,port:n.sessionOverrides?.port??o.port??null,workspaceRoot:s.workspaceRoot,workspaceType:s.workspaceType,tags:s.tags,depends:i.depends?.[t]??[],envFiles:i.envFiles?.[t]??[]},events:u,bundles:h,selfMetrics:p}}function qr(r,t){let e=Le(r,t);if(!e)return null;let n=Gr.join(eo.homedir(),".daimon","snapshots");Wr.mkdirSync(n,{recursive:!0});let s=e.takenAt.replace(/[:.]/g,"-"),i=Gr.join(n,`${t}-${s}.json`);return Wr.writeFileSync(i,JSON.stringify(e,null,2)),{path:i,payload:e}}import Vt from"node:fs";import Jr from"node:path";var so=["dist",".angular/cache","tmp","out-tsc"],oo=["node_modules"];function Xr(r){let t=0;try{let e=Vt.readdirSync(r,{withFileTypes:!0});for(let n of e){let s=Jr.join(r,n.name);try{n.isDirectory()?t+=Xr(s):n.isFile()&&(t+=Vt.statSync(s).size)}catch{}}}catch{}return t}function De(r,t,e){let n=r.getApp(t);if(!n)return null;let s=r.getState(t),i=s?s.status==="serving"||s.status==="compiling"||s.status==="starting":!1,a=[...so,...e?oo:[]].map(c=>{let u=Jr.join(n.workspaceRoot,c),h=Vt.existsSync(u);return{path:u,exists:h,sizeBytes:h?Xr(u):0}});return{app:t,workspace:n.workspaceRoot,targets:a,ranOnServing:i}}function Kr(r,t,e){let n=De(r,t,e);if(!n)return{error:"unknown app"};if(n.ranOnServing)return{error:"app is currently running; stop it first"};let s=[],i=[];for(let o of n.targets)if(o.exists)try{Vt.rmSync(o.path,{recursive:!0,force:!0}),s.push(o.path)}catch(a){i.push({path:o.path,error:a?.message||String(a)})}return{ok:i.length===0,removed:s,failed:i}}function Ot(r){return r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}var io=["stopped","starting","compiling","serving","error"];function zr(r){let t=[];t.push("# HELP daimon_up daimon daemon up"),t.push("# TYPE daimon_up gauge"),t.push("daimon_up 1"),t.push("# HELP daimon_app_status app status one-hot"),t.push("# TYPE daimon_app_status gauge");let e=r.list();for(let n of e)for(let s of io)t.push(`daimon_app_status{name="${Ot(n.name)}",status="${s}"} ${n.status===s?1:0}`);t.push("# HELP daimon_compile_seconds last successful compile duration in seconds"),t.push("# TYPE daimon_compile_seconds gauge");for(let n of e)n.lastCompileMs!=null&&t.push(`daimon_compile_seconds{name="${Ot(n.name)}"} ${(n.lastCompileMs/1e3).toFixed(3)}`);t.push("# HELP daimon_error_total cumulative deduped error count"),t.push("# TYPE daimon_error_total counter");for(let n of e)t.push(`daimon_error_total{name="${Ot(n.name)}"} ${n.errorCount}`);t.push("# HELP daimon_cpu_percent app CPU percent"),t.push("# TYPE daimon_cpu_percent gauge");for(let n of e)n.cpu!=null&&t.push(`daimon_cpu_percent{name="${Ot(n.name)}"} ${n.cpu}`);t.push("# HELP daimon_mem_mb app resident memory MB"),t.push("# TYPE daimon_mem_mb gauge");for(let n of e)n.memMB!=null&&t.push(`daimon_mem_mb{name="${Ot(n.name)}"} ${n.memMB}`);return t.join(`
|
|
53
62
|
`)+`
|
|
54
|
-
`}
|
|
55
|
-
`;try{
|
|
56
|
-
`);let
|
|
57
|
-
`)};
|
|
58
|
-
`)}catch{}},3e4);i.on("close",()=>{
|
|
59
|
-
`);o.end();return}if(a.searchParams.get("explain")==="1"){let d=e.getConfig?.(),g={format:l};if(d){let{discoverApps:
|
|
63
|
+
`}ft();import Nt from"node:fs";import ao from"node:crypto";import Yr from"node:path";var co=1e6;function lo(){return Yr.join(it(),"audit.log")}function uo(r){try{if(Nt.statSync(r).size>co){let e=r+".1";try{Nt.unlinkSync(e)}catch{}Nt.renameSync(r,e)}}catch{}}function Vr(r,t,e,n){let s=lo();Nt.mkdirSync(Yr.dirname(s),{recursive:!0}),uo(s);let i=JSON.stringify({prev:t,next:e}),o=ao.createHash("sha1").update(i).digest("hex").slice(0,12),a=`${new Date().toISOString()} ${r} ${o} ${n.join(",")}
|
|
64
|
+
`;try{Nt.appendFileSync(s,a)}catch{}}import Zt from"node:fs";import Qt from"node:path";import{fileURLToPath as po}from"node:url";var Zr=Qt.dirname(po(import.meta.url));function fo(){let r=[Qt.resolve(Zr,"templates","presets"),Qt.resolve(Zr,"..","src","templates","presets")];for(let t of r)if(Zt.existsSync(t))return t;return r[0]}function Qr(){let r=fo();if(!Zt.existsSync(r))return[];let t=Zt.readdirSync(r).filter(n=>n.endsWith(".json")),e=[];for(let n of t)try{let s=Zt.readFileSync(Qt.join(r,n),"utf8");s.charCodeAt(0)===65279&&(s=s.slice(1)),e.push(JSON.parse(s))}catch{}return e}ft();import te from"node:fs";import tn from"node:path";function en(){return tn.join(it(),"state-handoff.json")}function rn(r){let t=[];for(let s of r.names()){let i=r.getState(s);i&&(i.status==="serving"||i.status==="compiling"||i.status==="starting")&&i.port&&t.push({name:s,port:i.port})}let e={ts:Date.now(),apps:t},n=en();return te.mkdirSync(tn.dirname(n),{recursive:!0}),te.writeFileSync(n,JSON.stringify(e)),n}function nn(r=6e4){let t=en();try{let e=te.readFileSync(t,"utf8"),n=JSON.parse(e);return te.unlinkSync(t),!n||typeof n.ts!="number"||Date.now()-n.ts>r?null:n}catch{return null}}Ct();var Xo=Jo(import.meta.url),ee=Y.dirname(Xo);function Ue(){let r=[Y.resolve(ee,"dashboard","browser"),Y.resolve(ee,"dashboard"),Y.resolve(ee,"..","dist","dashboard","browser"),Y.resolve(ee,"..","dist","dashboard")];for(let t of r)if(mt.existsSync(Y.join(t,"index.html")))return t;return null}var Ko={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".map":"application/json; charset=utf-8",".woff2":"font/woff2",".woff":"font/woff",".ttf":"font/ttf"};function $t(r,t){try{if(!mt.statSync(t).isFile())return!1;let n=Y.extname(t).toLowerCase(),s=Ko[n]??"application/octet-stream",i=mt.readFileSync(t);return r.writeHead(200,{"content-type":s,"content-length":i.length,"cache-control":n===".html"?"no-cache":"public, max-age=3600"}),r.end(i),!0}catch{return!1}}function b(r,t,e){let n=JSON.stringify(e);r.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(n)}),r.end(n)}function xt(r){if(!r)return;let t=r.match(/^(\d+)(ms|s|m|h)?$/);if(!t)return;let e=Number(t[1]);switch(t[2]||"ms"){case"ms":return e;case"s":return e*1e3;case"m":return e*60*1e3;case"h":return e*60*60*1e3}}function re(r,t){let e=(r.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function zo(r){return{name:r.name,status:r.status,port:r.port,health:r.health,errCount:r.errorCount,lastChangeMs:r.lastChangeMs??null}}function kt(r){return{name:r.name,status:r.status,port:r.port,url:r.url,health:r.health,errCount:r.errorCount,lastChangeMs:r.lastChangeMs??null,uptime:r.uptimeMs}}function We(r){let t=r.parsed;return t&&(t.file||t.code)?{file:t.file??null,line:t.line??null,col:t.col??null,code:t.code??null,message:t.message??r.message}:{file:null,line:null,col:null,code:null,message:r.message}}function fn(r){if(!r)return{};if(/^\d{10,}$/.test(r))return{sinceTs:Number(r)};let t=xt(r);return t!=null?{sinceMs:t}:{}}var Yo=/key|secret|token|password|pass/i;function Vo(r){let t=JSON.parse(JSON.stringify(r));if(t.apiToken&&(t.apiToken="***"),t.overrides&&typeof t.overrides=="object")for(let e of Object.keys(t.overrides)){let n=t.overrides[e]?.env;if(n&&typeof n=="object")for(let s of Object.keys(n))Yo.test(s)&&(n[s]="***")}return t}function Ge(r){if(!r)return"";try{let t=mt.readFileSync(r);return qo.createHash("sha1").update(t).digest("hex")}catch{return""}}function mn(r,t,e={}){let n=new Yt,s=Go.createServer(async(i,o)=>{try{let a=new URL(i.url||"/","http://127.0.0.1"),c=i.method||"GET",u=a.pathname.replace(/\/$/,"").split("/").filter(Boolean),h=()=>{let f=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!f)return!0;let m=i.headers.authorization;return typeof m=="string"&&m.toLowerCase().startsWith("bearer ")&&m.slice(7).trim()===f?!0:(b(o,401,{error:"unauthorized"}),!1)};if(c==="POST"&&a.pathname==="/api/shutdown"){if(!h())return;b(o,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(c==="GET"){let l=e.getConfig(),f=Ge(e.configPath);o.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:f}),o.end(JSON.stringify({etag:f,config:Vo(l)}));return}if(c==="PATCH"&&e.patchConfig){if(!h())return;let l=i.headers["if-match"]?.trim(),f=Ge(e.configPath);if(!l||l!==f){b(o,412,{error:"etag mismatch",current:f});return}let m={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(x=>{let E=[];i.on("data",w=>E.push(w)),i.on("end",()=>{try{m=JSON.parse(Buffer.concat(E).toString("utf8"))}catch{}x()})});let d=e.patchConfig(m);if(!d.ok){b(o,400,{error:d.error});return}let g=Ge(e.configPath);try{let x=i.socket.remoteAddress||"127.0.0.1";Vr(x,m,m,d.applied)}catch{}o.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:g}),o.end(JSON.stringify({etag:g,applied:d.applied,addedApps:d.addedApps,removedApps:d.removedApps,restartRequired:d.restartRequired}));return}b(o,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&c==="GET"){b(o,200,Qr());return}if(a.pathname==="/api/self"&&c==="GET"){if(!e.selfMetrics){b(o,503,{error:"self-metrics collector not attached"});return}b(o,200,e.selfMetrics.snapshot());return}if(a.pathname==="/api/plugins"&&c==="GET"){let l=e.getPlugins?e.getPlugins():[];b(o,200,l.map(f=>({name:f.name,description:f.description??null,file:f.file,status:f.status,error:f.error??null,findings:f.lastFindings??[]})));return}if(a.pathname==="/api/plugins/scan"&&c==="POST"){if(!h())return;if(!e.runPluginScans){b(o,503,{error:"plug-in scan not available"});return}try{await e.runPluginScans()}catch(f){b(o,500,{error:f?.message||String(f)});return}let l=e.getPlugins?e.getPlugins():[];b(o,200,l);return}if(a.pathname==="/api/self/history"&&c==="GET"){let l=fn(a.searchParams.get("since")),f=l.sinceMs??3600*1e3,m=l.sinceTs??Date.now()-f,d=r.getHistory(),g=d?d.querySelfMetrics({since:m,limit:1440}):[];b(o,200,g);return}if(a.pathname==="/api/snapshot-state"&&c==="POST"){if(!h())return;let l=rn(r);b(o,200,{ok:!0,path:l});return}if(a.pathname==="/api/config/reload"&&c==="POST"&&e.reloadConfig){if(!h())return;try{let l=await e.reloadConfig();b(o,200,l)}catch(l){b(o,400,{error:l?.message||String(l)})}return}if(c==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let l=zr(r);o.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(l)}),o.end(l);return}if(c!=="GET"&&a.pathname.startsWith("/api/")&&a.pathname!=="/api/shutdown"&&a.pathname!=="/api/config"&&a.pathname!=="/api/config/reload"&&!h())return;if(c==="GET"&&a.pathname==="/"){let l=Ue();if(l&&$t(o,Y.join(l,"index.html")))return;o.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(u[0]==="api"&&u[1]==="events"&&u.length===2){if(c!=="GET"){b(o,405,{error:"method not allowed"});return}let l=xt(a.searchParams.get("since")),f=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){o.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let g=r.events({sinceMs:l,app:f});for(let w of g)o.write(JSON.stringify(w)+`
|
|
65
|
+
`);let x=w=>{f&&w.app!==f||o.write(JSON.stringify(w)+`
|
|
66
|
+
`)};r.on("event",x);let E=setInterval(()=>{try{o.write(`
|
|
67
|
+
`)}catch{}},3e4);i.on("close",()=>{r.off("event",x),clearInterval(E);try{o.end()}catch{}});return}let m=r.events({sinceMs:l,app:f}),d=r.getHistory();if(d&&l&&m.length<500){let g=Date.now()-l,x=d.queryEvents({app:f,since:g,limit:1e3}),E=new Set(m.map(w=>`${w.ts}|${w.app}|${w.type}|${w.from??""}|${w.to??""}|${w.message??""}`));for(let w of x){let _=`${w.ts}|${w.app}|${w.type}|${w.from_state??""}|${w.to_state??""}|${w.message??""}`;E.has(_)||m.push({ts:w.ts,app:w.app,type:w.type,from:w.from_state??void 0,to:w.to_state??void 0,message:w.message??void 0})}m.sort((w,_)=>w.ts-_.ts)}b(o,200,m);return}if(u[0]==="api"&&u[1]==="session"){if(u[2]==="record"&&c==="POST"){let l=a.searchParams.get("action")||"toggle";if(l==="start"||l==="toggle"&&!r.sessionRecorder.isRecording()){let f=r.sessionRecorder.start();b(o,200,{recording:!0,path:f.path});return}if(l==="stop"||l==="toggle"&&r.sessionRecorder.isRecording()){let f=r.sessionRecorder.stop();b(o,200,{recording:!1,path:f.path});return}b(o,400,{error:"invalid action"});return}if(u[2]==="status"&&c==="GET"){b(o,200,{recording:r.sessionRecorder.isRecording()});return}b(o,404,{error:"not found"});return}if(u[0]==="api"&&u[1]==="history"){if(c!=="GET"){b(o,405,{error:"method not allowed"});return}let l=r.getHistory();if(!l){b(o,200,[]);return}let f=u[2],m=a.searchParams.get("app")||void 0,d=a.searchParams.get("since"),g=a.searchParams.get("until"),x=a.searchParams.get("limit"),E=d?/^\d{10,}$/.test(d)?Number(d):Date.now()-(xt(d)??0):void 0,w=g?/^\d{10,}$/.test(g)?Number(g):Date.now()-(xt(g)??0):void 0,_=x?Number(x):void 0;if(f==="events"){b(o,200,l.queryEvents({app:m,since:E,until:w,type:a.searchParams.get("type")||void 0,limit:_}));return}if(f==="compile-times"){b(o,200,l.queryCompiles({app:m,since:E,until:w,limit:_}));return}if(f==="tasks"){b(o,200,l.queryTasks({app:m,task:a.searchParams.get("task")||void 0,since:E,limit:_}));return}if(f==="bundles"){b(o,200,l.queryBundles({app:m,since:E,until:w,limit:_}));return}if(f==="trends"){let A=a.searchParams.get("metric")||"compile";if(!["compile","bundle","errors","restarts"].includes(A)){b(o,400,{error:"metric must be compile|bundle|errors|restarts"});return}let C=(a.searchParams.get("since")||"24h").toLowerCase(),P={"24h":24*3600*1e3,"7d":7*86400*1e3,"30d":30*86400*1e3},$=P[C]??P["24h"],T=C==="24h"?3600*1e3:86400*1e3,{points:S,count:D}=l.trends({app:m,metric:A,sinceMs:$,bucketMs:T});b(o,200,{app:m??null,metric:A,since:C,points:S,_meta:{aggregation:C==="24h"?"hour":"day",count:D}});return}if(f==="summary"&&u.length>=4){let A=decodeURIComponent(u[3]);b(o,200,l.summary(A));return}if(f==="why"&&u.length>=4){let A=decodeURIComponent(u[3]);b(o,200,l.why(A));return}b(o,404,{error:"not found"});return}if(u[0]==="api"&&u[1]==="profiles"&&u[3]==="ensure-up"&&c==="POST"){let l=decodeURIComponent(u[2]),f=e.getConfig?.(),m=f?.profiles?.[l];if(!m){b(o,404,{error:"unknown profile"});return}let d=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(d)){b(o,400,{error:"until must be serving|healthy"});return}let g=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),x=g?Number(g):3e5;(!Number.isFinite(x)||x<=0)&&(x=3e5),x=Math.min(x,12e5);let E=f?.healthProbe?.enabled??!0,w=d==="healthy"&&!E?"serving":d,_=Date.now();for(let C of m){let P=r.summary(C);P&&P.status!=="serving"&&P.status!=="starting"&&P.status!=="compiling"&&await r.startWithDeps(C)}let A=await Promise.all(m.map(async C=>{let P=Math.max(1e3,x-(Date.now()-_));if(!r.summary(C))return{name:C,state:null,until:w,reachedTargetMs:null,timedOut:!1,error:"unknown"};let T=await r.waitFor(C,w,P),S=r.summary(C);return{name:C,state:S?kt(S):null,until:w,reachedTargetMs:T.timedOut?null:T.waitedMs,timedOut:T.timedOut}}));b(o,200,{profile:l,apps:A,_meta:{totalMs:Date.now()-_,until:w}});return}if(u[0]==="api"&&u[1]==="orchestrate"&&c==="POST"){let l=e.getConfig?.();if(!l){b(o,500,{error:"no config loaded"});return}let f=a.searchParams.get("profile");if(!f){b(o,400,{error:"profile query param required"});return}let m=(a.searchParams.get("goal")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(m)){b(o,400,{error:"goal must be serving|healthy|stable"});return}let d=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),g=d?Number(d):3e5;(!Number.isFinite(g)||g<=0)&&(g=3e5),g=Math.min(g,12e5);let x=a.searchParams.get("dryRun")==="true"||a.searchParams.get("dry-run")==="true",E=a.searchParams.get("budget"),w=E&&Number.isFinite(Number(E))?Number(E):void 0,{orchestrateProfile:_}=await Promise.resolve().then(()=>(He(),Be)),A=await _(r,l,{profile:f,goal:m,timeoutMs:g,dryRun:x,budgetTokens:w});if(A.error){b(o,404,A);return}b(o,200,A);return}if(u[0]==="api"&&u[1]==="discovery"&&u[2]==="explain"&&c==="GET"){let l=e.getConfig?.();if(!l){b(o,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:f}=await Promise.resolve().then(()=>(Pt(),ke)),m={scanned:0,rejected:{}},d=[],g=f(l,{warnings:d,stats:m}),x=l.searchRoots.map(A=>typeof A=="string"?A:A.path),E=g.filter(A=>A.workspaceType==="polyglot"),w=g.map(A=>({name:A.name,workspaceType:A.workspaceType,serverProfile:A.serverProfile??A.workspaceType,workspaceRoot:A.workspaceRoot})),_=E.length>0?` \xB7 ${E.length} polyglot app${E.length===1?"":"s"} found (${[...new Set(E.map(A=>A.serverProfile))].join(", ")})`:"";b(o,200,{searchRoots:x,scanned:m.scanned,rejected:m.rejected,warnings:d,appsFound:g.length,apps:w,suggestion:g.length===0?x.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook / manage.py / Gemfile / pyproject.toml (fastapi) / .air.toml / Trunk.toml.":`${g.length} apps discovered${_}`});return}if(u[0]==="api"&&u[1]==="doctor"&&u[2]==="auto-fix"&&c==="POST"){if(!h())return;let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(E=>{let w=[];i.on("data",_=>w.push(_)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}E()})});let{runAutoFix:f,ALL_AUTO_FIX:m}=await Promise.resolve().then(()=>(_t(),jt)),g=e.getConfig?.()?.doctor?.autoFix?.permitted??m,x=Array.isArray(l.permitted)&&l.permitted.length?l.permitted:g;try{let E=await f({permitted:x,dryRun:!!l.dryRun});b(o,200,E)}catch(E){b(o,500,{error:E?.message??String(E)})}return}if(u[0]==="api"&&u[1]==="overview"&&c==="GET"){let l=e.getConfig?.(),f=r.list(),m=a.searchParams.get("workspace"),d=a.searchParams.get("profile"),g=f;if(m&&(g=g.filter(T=>T.workspaceLabel===m)),d){let T=l?.profiles?.[d]??null;T&&(g=g.filter(S=>T.includes(S.name)))}let x={apps:g.length,serving:g.filter(T=>T.status==="serving").length,errors:g.filter(T=>T.status==="error").length,stopped:g.filter(T=>T.status==="stopped").length,totalErrCount:g.reduce((T,S)=>T+S.errorCount,0),totalCpuPct:Math.round(g.reduce((T,S)=>T+(S.cpu??0),0)*10)/10,totalMemMb:Math.round(g.reduce((T,S)=>T+(S.memMB??0),0))},E={};for(let T of g)(E[T.status]??=[]).push(T.name);let w=g.filter(T=>T.status==="error"||T.errorCount>0).map(T=>{let S=r.errors(T.name)??[],D=S[S.length-1],N=D?.parsed;return{name:T.name,status:T.status,errCount:T.errorCount,firstError:N?{file:N.file??null,line:N.line??null,code:N.code??null,message:N.message??D?.message??""}:D?{file:null,line:null,code:null,message:D.message}:null}}),_=Date.now()-5*6e4,A=r.events({sinceMs:5*6e4}).filter(T=>T.type==="status"&&T.ts>=_).filter(T=>m?g.some(S=>S.name===T.app):!0).filter(T=>d?g.some(S=>S.name===T.app):!0).slice(-5).map(T=>({name:T.app,transition:`${T.from??"?"}\u2192${T.to??"?"}`,msAgo:Date.now()-T.ts})),C={ts:Date.now(),version:ot,totals:x,byStatus:E,needsAttention:w,recentlyChanged:A};x.apps===0&&(C._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let P=a.searchParams.get("budget"),$=P?Math.max(64,Number(P)|0):null;if($){let T=$*4,S=0,D=0;for(;JSON.stringify(C).length>T&&(C.needsAttention.length||C.recentlyChanged.length);)if(C.needsAttention.length>1)C.needsAttention.pop(),S++;else if(C.recentlyChanged.length)C.recentlyChanged.pop(),D++;else if(C.needsAttention.length===1)C.needsAttention.pop(),S++;else break;S||D?C._meta={...C._meta??{},budget:$,omitted:{needsAttention:S,recentlyChanged:D}}:C._meta={...C._meta??{},budget:$}}b(o,200,C);return}if(u[0]!=="api"||u[1]!=="apps"){if(c==="GET"&&!a.pathname.startsWith("/metrics")){let l=Ue();if(l){let f=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let m=Y.resolve(l,f);if(m.startsWith(l)&&$t(o,m))return}if(!Y.extname(f||"")&&$t(o,Y.join(l,"index.html")))return}}b(o,404,{error:"not found"});return}if(u.length===2){if(c!=="GET"){b(o,405,{error:"method not allowed"});return}let l=re(a,e.getConfig),f=r.list(),m=l==="full"?f:f.map(zo);if(a.searchParams.get("stream")==="ndjson"){o.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let d of m)o.write(JSON.stringify(d)+`
|
|
68
|
+
`);o.end();return}if(a.searchParams.get("explain")==="1"){let d=e.getConfig?.(),g={format:l};if(d){let{discoverApps:x}=await Promise.resolve().then(()=>(Pt(),ke)),E={scanned:0,rejected:{}},w=[];x(d,{warnings:w,stats:E});let _=d.searchRoots.map(A=>typeof A=="string"?A:A.path);g={format:l,searchRoots:_,scanned:E.scanned,rejected:E.rejected,warnings:w,suggestion:m.length===0?_.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder to add the current cwd.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook, then run 'daimon doctor'.":"apps discovered; _meta is informational."}}b(o,200,{apps:m,_meta:g});return}b(o,200,m);return}let p=decodeURIComponent(u[2]),y=u[3],v=u[4];if(!y){if(c!=="GET"){b(o,405,{error:"method not allowed"});return}let l=r.summary(p);if(!l){b(o,404,{error:"unknown app"});return}re(a,e.getConfig)==="full"?b(o,200,{...l,_meta:{format:"full"}}):b(o,200,{...kt(l),_meta:{format:"compact"}});return}if(y==="errors"&&v==="since-last"&&c==="GET"){let l=a.searchParams.get("client")||"default",f=n.getErrorCursor(l,p),m=r.errorsSince(p,f);if(m==null){b(o,404,{error:"unknown app"});return}let d=m.reduce((x,E)=>Math.max(x,E.lastSeen),f);d>f&&n.setErrorCursor(l,p,d);let g=re(a,e.getConfig);b(o,200,g==="full"?m:m.map(We));return}if(y==="errors"&&!v&&c==="GET"){let l=a.searchParams.get("since"),f=re(a,e.getConfig);if(l){let{sinceMs:d,sinceTs:g}=fn(l),x=g??(d!=null?Date.now()-d:0),E=r.errorsSince(p,x);if(E==null){b(o,404,{error:"unknown app"});return}b(o,200,f==="full"?E:E.map(We));return}let m=r.errors(p);if(m==null){b(o,404,{error:"unknown app"});return}b(o,200,f==="full"?m:m.map(We));return}if(y==="logs"&&u[4]==="stream"&&c==="GET"){if(!r.summary(p)){b(o,404,{error:"unknown app"});return}o.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let l=r.logs(p,{tail:50})??[];for(let E of l)o.write(`data: ${JSON.stringify({ts:Date.now(),line:E})}
|
|
60
69
|
|
|
61
|
-
`);let
|
|
70
|
+
`);let f=[],m=0,d=()=>{for(;f.length&&o.write(f.shift()););},g=E=>{E.name===p&&(f.length>=200&&(m++,f.shift()),f.push(`data: ${JSON.stringify({ts:E.ts,line:E.line})}
|
|
62
71
|
|
|
63
|
-
`),d())};
|
|
72
|
+
`),d())};r.on("log",g);let x=setInterval(()=>o.write(`: ping
|
|
64
73
|
|
|
65
|
-
`),3e4);i.on("close",()=>{
|
|
66
|
-
`)}catch{}};E({kind:"subscribed",app:p,until:
|
|
67
|
-
`)}catch{}},3e4),
|
|
68
|
-
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}w(o,200,{pinned:f,app:p,configPath:E,previous:N});return}if(v==="try-fix"&&c==="POST"){let l=n.summary(p);if(!l){w(o,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){w(o,400,{error:"until must be serving|healthy"});return}let f=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=f?Number(f):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g={status:l.status,health:l.health,errCount:l.errorCount,firstError:(n.errors(p)??[])[0]?.parsed??null},{runAutoFix:T,ALL_AUTO_FIX:E}=await Promise.resolve().then(()=>(Nt(),jt)),N=e.getConfig?.()?.doctor?.autoFix?.permitted??E,C={ran:[],skipped:[],errors:[]};try{C=await T({permitted:N,dryRun:!1})}catch(I){C.errors.push({name:"auto-fix",error:I?.message??String(I)})}let S=(C.ran??[]).map(I=>I.name),R=null;try{let I=await n.restart(p);I?.ok||(R=I?.error??"restart failed")}catch(I){R=I?.message??String(I)}let M=await n.waitFor(p,m,d),x=n.summary(p),H=(n.errors(p)??[]).slice(0,5).map(I=>({file:I.parsed?.file??null,line:I.parsed?.line??null,code:I.parsed?.code??null,tool:I.parsed?.tool??null,message:I.parsed?.message??I.message})),$=x?{status:x.status,health:x.health,errCount:x.errorCount}:{status:M.status,health:M.health,errCount:0},J=m==="serving"&&$.status==="serving"||m==="healthy"&&$.status==="serving"&&$.health==="healthy";w(o,200,{before:g,after:$,fixed:S,stillFailing:H,reached:J,waitedMs:M.waitedMs,_meta:{autoFix:C,restartErr:R,timedOut:M.timedOut}});return}if(v==="wait"&&c==="GET"){if(!n.summary(p)){w(o,404,{error:"unknown app"});return}let l=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(l)){w(o,400,{error:"until must be one of serving|healthy|stopped|error"});return}let m=a.searchParams.get("timeout"),f=m?Number(m):120;(!Number.isFinite(f)||f<=0)&&(f=120),f=Math.min(f,600);let d=await n.waitFor(p,l,f*1e3);w(o,200,d);return}if(v==="ensure"&&c==="POST"){let l=n.summary(p);if(!l){w(o,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){w(o,400,{error:"until must be serving|healthy"});return}let f=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=f?Number(f):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g=e.getConfig?.().healthProbe?.enabled??!0,T=m,E;if(T==="healthy"&&!g&&(T="serving",E="no health probe; treated serving as terminal"),T==="serving"&&l.status==="serving"||T==="healthy"&&l.status==="serving"&&l.health==="healthy"){w(o,200,{...xt(l),_meta:{format:"compact",startedFromState:null,warning:E,waitedMs:0}});return}let N=l.status;l.status!=="starting"&&l.status!=="compiling"&&await n.start(p);let C=await n.waitFor(p,T,d),S=n.summary(p),R=S?xt(S):{name:p,status:C.status,port:null,url:null,health:C.health,errCount:0,lastChangeMs:null,uptime:null};if(C.timedOut){w(o,200,{error:"timeout",state:R,_meta:{format:"compact",startedFromState:N,warning:E,waitedMs:C.waitedMs,timedOut:!0}});return}w(o,200,{...R,_meta:{format:"compact",startedFromState:N,warning:E,waitedMs:C.waitedMs}});return}if(v==="start"&&c==="POST"){if(a.searchParams.get("withDeps")==="1"){let f=await n.startWithDeps(p);w(o,f.ok?200:400,f);return}let m=await n.start(p);w(o,m.ok?200:400,m);return}if(v==="start-with-deps"&&c==="POST"){let l=await n.startWithDeps(p);w(o,l.ok?200:400,l);return}if(v==="tasks"&&c==="GET"&&!b){let l=n.listTasks(p);if(l==null){w(o,404,{error:"unknown app"});return}w(o,200,{tasks:l,watching:n.listWatchTasks(p)});return}if(v==="run"&&b&&c==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(d=>{let g=[];i.on("data",T=>g.push(T)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(g).toString("utf8"))}catch{}d()})});let m=Array.isArray(l.args)?l.args.map(String):[];if(l.watch){let d=n.startWatchTask(p,b,m);w(o,d.ok?200:400,d);return}let f=await n.runTask(p,b,m);if("error"in f){w(o,404,f);return}w(o,200,f);return}if(v==="run-stop"&&b&&c==="POST"){let l=await n.stopWatchTask(p,b);w(o,200,l);return}if(v==="env"&&c==="GET"){let m=n.getConfig().envFiles?.[p]??[],f=n.getState(p);w(o,200,{candidates:m,active:f?.activeEnvFile??null});return}if(v==="env"&&c==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(f=>{let d=[];i.on("data",g=>d.push(g)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(d).toString("utf8"))}catch{}f()})}),n.setActiveEnvFile(p,l.use??null);let m=n.getState(p);w(o,200,{active:m?.activeEnvFile??null});return}if(v==="requests"&&c==="GET"){if(!e.requestLog){w(o,200,[]);return}let l=kt(a.searchParams.get("since"));w(o,200,e.requestLog.requests(p,l));return}if(v==="clean"&&c==="POST"){let l=a.searchParams.get("deep")==="1",m=a.searchParams.get("yes")==="1",f=Ne(n,p,l);if(!f){w(o,404,{error:"unknown app"});return}if(f.ranOnServing){w(o,409,{error:"refusing: app is currently running",plan:f});return}if(!m){w(o,200,{plan:f,hint:"pass --yes to delete"});return}let d=Gr(n,p,l);w(o,200,d);return}if(v==="snapshot"&&c==="POST"){if(a.searchParams.get("write")==="1"){let f=Hr(n,p);if(!f){w(o,404,{error:"unknown app"});return}w(o,200,{snapshot:f.path});return}let m=je(n,p);if(!m){w(o,404,{error:"unknown app"});return}w(o,200,m);return}if(v==="stop"&&c==="POST"){let l=await n.stop(p);w(o,l.ok?200:400,l);return}if(v==="restart"&&c==="POST"){let l=await n.restart(p);w(o,l.ok?200:400,l);return}if(c==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let l=Fe();if(l){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let f=Y.resolve(l,m);if(f.startsWith(l)&&$t(o,f))return}if(!Y.extname(m||"")&&$t(o,Y.join(l,"index.html")))return}}w(o,404,{error:"not found"})}catch(a){w(o,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}import No from"node:http";import $o from"node:https";var _o=1e3,Lo=500,Do=["/","/health","/-/health","/api/health","/ready","/healthz"];function un(n,t,e,r,s){if(t)return[t];let i=n.path||"/",o=n.fallbackHosts&&n.fallbackHosts.length?n.fallbackHosts:["127.0.0.1"];if(n.host||n.scheme){let c=e?ne(e):null,u=n.scheme||c?.protocol?.replace(":","")||"http",h=n.host||c?.hostname||(r?o[0]:"127.0.0.1"),p=r??(c?.port?Number(c.port):null);return[pn(u,h,p,i)]}if(e){let c=ne(e);if(c)return c.pathname=i,[c.toString()]}let a=[];s&&a.push(s);for(let c of o)a.includes(c)||a.push(c);return a.map(c=>pn("http",c,r,i))}function ne(n){try{return new URL(n)}catch{return null}}function pn(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,i=e?`:${e}`:"";return`${n}://${s}${i}${r.startsWith("/")?r:"/"+r}`}var se=class{constructor(t,e,r){this.registry=t;this.cfg=e;this.fullConfig=r;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let r=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},Lo);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=this.fullConfig?.overrides?.[t]?.healthProbePath,i=this.cfg;s?i={...this.cfg,path:s}:e.discoveredHealthPath&&(i={...this.cfg,path:e.discoveredHealthPath});let o=un(i,r,e.announcedUrl,e.port,e.cachedProbeHost);if(!r&&!s&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),o.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let a=null;for(let u of o){let h=await this.tryProbe(u);if(h.ok){let p=ne(u);p&&this.registry.setCachedProbeHost(t,p.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,u),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}a||(a=`${h.error} ${u}`)}let c=this.freshness.get(t);if(c&&!c.retried){c.retried=!0,setTimeout(()=>{this.probe(t)},_o);return}this.registry.setLastHealthError(t,a||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let r of Do){let s={...this.cfg,path:r},i=un(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let o of i)if((await this.tryProbe(o,{strict2xx:!0})).ok){e.discoveredHealthPath=r,this.registry.recordEvent({app:t,type:"health",message:`discovered probe path: ${r} (pin via POST /api/apps/${encodeURIComponent(t)}/health/pin or daimon pin-health ${t} --accept)`});return}}}tryProbe(t,e={}){return new Promise(r=>{let s=!1,i=h=>{s||(s=!0,r(h))},o=t.startsWith("https://"),a=o?$o:No,c={timeout:this.cfg.timeoutMs};if(o){let p=ne(t)?.hostname?.replace(/^\[|\]$/g,"")??"",v=p==="127.0.0.1"||p==="::1"||p==="localhost";c.rejectUnauthorized=v?!1:!!this.cfg.rejectUnauthorized}let u=e.strict2xx?300:500;try{let h=a.get(t,c,p=>{let v=p.statusCode??0;p.resume(),v>=200&&v<u?i({ok:!0}):i({ok:!1,error:`http ${v}`})});h.on("timeout",()=>h.destroy(new Error("timeout"))),h.on("error",p=>i({ok:!1,error:p?.code||p?.message||"error"}))}catch(h){i({ok:!1,error:h?.message||"throw"})}})}};import Fo from"pidusage";var oe=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let r of this.registry.names()){let s=this.registry.getState(r);s?.pid&&t.push({name:r,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:r,pid:s})=>{try{let i=await Fo(s),o=this.registry.getState(r);if(!o)return;let a=Math.round(i.cpu*10)/10,c=Math.round(i.memory/(1024*1024));(o.cpu!==a||o.memMB!==c)&&(o.cpu=a,o.memMB=c,e=!0)}catch{let i=this.registry.getState(r);i&&(i.cpu!=null||i.memMB!=null)&&(i.cpu=null,i.memMB=null,e=!0)}})),e&&this.registry.emit("change")}};var ie=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,r,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!r)return;let i=this.registry.getState(t);if(!i)return;let o=Date.now();if((i.restartWindowStart==null||o-i.restartWindowStart>this.cfg.windowMs)&&(i.restartWindowStart=o,i.restartAttempts=0),i.restartAttempts+=1,i.restartAttempts>this.cfg.maxAttempts){i.lastStatusMessage=`auto-restart aborted (${i.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,i.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(i.restartAttempts-1)*1e3,3e4);i.nextRestartAt=o+a,i.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${i.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");let c=setTimeout(()=>{this.timers.delete(t);let u=this.registry.getState(t);u&&(u.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,c)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}};import We from"node:fs";import dn from"node:path";import Io from"node:os";var Ge=dn.join(Io.homedir(),".daimon","state.json");function fn(){try{let n=We.readFileSync(Ge,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}var He=null,Ue=null;function mn(n){Ue=n,!He&&(He=setTimeout(()=>{He=null;let t=Ue;if(Ue=null,!!t)try{We.mkdirSync(dn.dirname(Ge),{recursive:!0}),We.writeFileSync(Ge,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
69
|
-
`)}},500))}
|
|
70
|
-
`;try{
|
|
71
|
-
`))}stop(){this.registry.off("event",this.onEvent)}onEvent=t=>{this.notifier&&(t.type==="status"&&t.to==="error"&&this.cfg.onError?this.fire(t.app,"error",`${t.app} \u2192 error`,t.message||"app entered error state"):t.type==="health"&&t.to==="unhealthy"&&this.cfg.onUnhealthy?this.fire(t.app,"unhealthy",`${t.app} unhealthy`,"health probe failing"):t.type==="stale"?this.fire(t.app,"stale",`${t.app} stale`,t.message||"no output despite source changes"):t.type==="compile-regression"?this.fire(t.app,"compile-regression",`${t.app} slow compile`,t.message||"compile time regression"):t.type==="bundle-regression"?this.fire(t.app,"bundle-regression",`${t.app} bundle grew`,t.message||"bundle size regression"):t.type==="task-run"&&/exit=[1-9]/.test(t.message||"")&&this.fire(t.app,"task-fail",`${t.app} task failed`,t.message||""))};fire(t,e,
|
|
72
|
-
`),this.proxies.delete(t)}),i.listen(
|
|
73
|
-
`),{config:
|
|
74
|
-
`))}catch{}return s}function
|
|
75
|
-
`)}catch{}if(
|
|
76
|
-
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}import A,{useEffect as ui,useState as q}from"react";import ze from"node:fs";import pi from"node:os";import di from"node:path";import{Box as X,Text as j,useApp as fi,useInput as mi,useStdout as hi}from"ink";import Ye from"ink-text-input";import{spawn as Ve,spawnSync as gi}from"node:child_process";import G,{useEffect as si,useMemo as oi,useState as Tt}from"react";import{Box as _t,Text as Z,useInput as ii,useStdout as ai}from"ink";import ci from"ink-text-input";function Xe({registry:n,appName:t,onExit:e}){let{stdout:r}=ai(),[s,i]=Tt(0),[o,a]=Tt(!1),[c,u]=Tt(""),[h,p]=Tt(""),[v,b]=Tt(0),[l,m]=Tt(0);si(()=>{let R=()=>i(x=>x+1);n.on("change",R);let M=setInterval(()=>i(x=>x+1),500);return()=>{n.off("change",R),clearInterval(M)}},[n]);let d=n.getState(t)?.logBuffer.map(R=>R.line)??[],g=(r.rows||30)-4,T=oi(()=>{if(!h)return[];let R=h.toLowerCase();return d.reduce((M,x,L)=>(x.toLowerCase().includes(R)&&M.push(L),M),[])},[d,h,s]);ii((R,M)=>{if(o){if(M.escape){a(!1),u("");return}return}if(R==="q"||M.escape){e();return}if(R==="/"){a(!0);return}if(R==="g"){b(Math.max(0,d.length-g));return}if(R==="G"){b(0);return}if(M.pageUp){b(x=>Math.min(Math.max(0,d.length-g),x+g));return}if(M.pageDown){b(x=>Math.max(0,x-g));return}if(M.upArrow){b(x=>Math.min(Math.max(0,d.length-g),x+1));return}if(M.downArrow){b(x=>Math.max(0,x-1));return}if((R==="n"||R==="N")&&T.length){let x=R==="n"?(l+1)%T.length:(l-1+T.length)%T.length;m(x);let L=T[x],H=d.length-v,$=H-g;(L<$||L>=H)&&b(Math.max(0,d.length-L-Math.floor(g/2)));return}});let E=R=>{p(R),a(!1),u(""),m(0)},y=d.length-v,N=Math.max(0,y-g),C=d.slice(N,y),S=(R,M)=>{if(!h)return G.createElement(Z,{key:M},G.createElement(Z,{dimColor:!0},String(M+1).padStart(5)," "),R);let x=h,L=R.toLowerCase(),H=x.toLowerCase(),$=[],J=0,I=0;for(;J<R.length;){let et=L.indexOf(H,J);if(et<0){$.push(G.createElement(Z,{key:I++},R.slice(J)));break}et>J&&$.push(G.createElement(Z,{key:I++},R.slice(J,et))),$.push(G.createElement(Z,{key:I++,backgroundColor:"yellow",color:"black"},R.slice(et,et+x.length))),J=et+x.length}let it=T[l]===M;return G.createElement(Z,{key:M},G.createElement(Z,{color:it?"cyan":void 0,dimColor:!it},String(M+1).padStart(5)," "),$)};return G.createElement(_t,{flexDirection:"column"},G.createElement(_t,null,G.createElement(Z,{bold:!0},"full log: ",G.createElement(Z,{color:"cyan"},t)),G.createElement(Z,{dimColor:!0}," (",d.length," lines",h?`, ${T.length} matches for "${h}"`:"",", scroll=",v,")")),G.createElement(_t,{flexDirection:"column"},C.length===0?G.createElement(Z,{dimColor:!0},"(no log yet)"):C.map((R,M)=>S(R,N+M))),G.createElement(_t,null,o?G.createElement(_t,null,G.createElement(Z,null,"/"),G.createElement(ci,{value:c,onChange:u,onSubmit:E})):G.createElement(Z,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var En={stopped:1,serving:2,compiling:3,starting:3,error:4},li={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"};function Rn(n,t,e=Date.now()){let r=e-36e5,s=36e5/20,i=new Array(20).fill("");for(let o of n){if(o.type!=="status"||o.app!==t||!o.to||o.ts<r||o.ts>e)continue;let a=Math.min(19,Math.floor((o.ts-r)/s)),c=i[a];(!c||(En[o.to]??0)>(En[c]??0))&&(i[a]=o.to)}return i}function An(n){return n.map(t=>li[t]??"\xB7").join("")}function yi(n){try{process.platform==="win32"?Ve("cmd",["/c","start","",n],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?Ve("open",[n],{detached:!0,stdio:"ignore"}).unref():Ve("xdg-open",[n],{detached:!0,stdio:"ignore"}).unref()}catch{}}var Cn={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Pn={healthy:"green",unhealthy:"red",unknown:"gray"};function vi(n){if(n==null)return"";let t=Math.floor(n/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function Ze({registry:n,apiPort:t,onQuit:e}){let{exit:r}=fi(),{stdout:s}=hi(),[i,o]=q(n.list()),[a,c]=q(0),[u,h]=q(!1),[p,v]=q(0),[b,l]=q(!1),[m,f]=q([]),[d,g]=q(!1),[T,E]=q(""),[y,N]=q(null),[,C]=q(0),[S,R]=q(null),[M,x]=q(""),[L,H]=q(!1),[$,J]=q(null),[I,it]=q(""),[et,pe]=q(!1),[Qe,tr]=q(null),[On,er]=q(n.events({sinceMs:3600*1e3}));ui(()=>{let k=()=>o(n.list()),O=()=>er(n.events({sinceMs:36e5}));n.on("change",k),n.on("event",O);let D=setInterval(()=>{o(n.list()),er(n.events({sinceMs:3600*1e3})),C(P=>P+1)},1e3);return()=>{n.off("change",k),n.off("event",O),clearInterval(D)}},[n]),mi((k,O)=>{if(b)return;if(y){if(O.escape){N(null);return}if(O.tab){let P=y.field==="command"?"port":y.field==="port"?"env":"command";N({...y,field:P});return}return}if(d){if(O.escape){g(!1),E("");return}if(O.return){let P=T.trim();f(P?P.split(/[\s,]+/).filter(Boolean):[]),g(!1),E("");return}if(O.backspace||O.delete){E(P=>P.slice(0,-1));return}k&&!O.ctrl&&E(P=>P+k);return}if(L){if(O.escape){H(!1);return}if(O.return){H(!1);return}if(O.backspace||O.delete){x(P=>P.slice(0,-1));return}k&&!O.ctrl&&x(P=>P+k);return}if(et){if(O.escape){pe(!1),it("");return}if(O.return){let P=I.trim();pe(!1),it(""),P&&Nn(P);return}if(O.backspace||O.delete){it(P=>P.slice(0,-1));return}k&&!O.ctrl&&it(P=>P+k);return}if($){if(k==="y"||k==="Y"){let P=$;J(null),n.restart(P),K(`restarted ${P}`)}else(k==="n"||k==="N"||O.escape)&&J(null);return}if(k==="q"||O.ctrl&&k==="c"){e(),r();return}if(i.length===0)return;if(S==="g"){R(null);let P=k.toLowerCase();P==="a"?K("view: apps (only TUI view)"):P==="e"?K("view: errors \u2014 selected app errors shown in detail pane"):P==="v"?K("view: events \u2014 recent registry events shown in log pane"):P==="s"?K("view: settings \u2014 edit `daimon.config.json`"):P==="n"&&K("view: sessions \u2014 `daimon record` to toggle recording");return}if(O.upArrow||k==="k"){c(P=>Math.max(0,P-1)),v(0);return}if(O.downArrow||k==="j"){c(P=>Math.min(i.length-1,P+1)),v(0);return}let D=i[a];if(D){if(k==="g"){R("g"),setTimeout(()=>R(P=>P==="g"?null:P),1200);return}if(k==="/"){H(!0);return}if(k==="s")n.start(D.name);else if(k==="S")n.stop(D.name);else if(k==="r")J(D.name);else if(k==="f")jn(D.name);else if(k==="x")Mn(D.name);else if(k==="O")pe(!0);else if(k==="L")l(!0);else if(k==="t")g(!0),E(m.join(" "));else if(k==="e"){let P=n.getConfig(),U=n.getApp(D.name),V=n.getState(D.name)?.sessionOverrides??null,ct=V?.env??P.overrides?.[D.name]?.env??{},lt=Object.entries(ct).map(([fe,me])=>`${fe}=${me}`).join(`
|
|
77
|
-
`);
|
|
78
|
-
`)}),onSubmit:()=>{let k=Number(
|
|
79
|
-
`),process.exit(1)}if(
|
|
80
|
-
${
|
|
74
|
+
`),3e4);i.on("close",()=>{r.off("log",g),clearInterval(x)});return}if(y==="logs"&&c==="GET"){let l=a.searchParams.get("tail"),f=a.searchParams.get("since"),m=r.logs(p,{tail:l?Number(l):void 0,sinceMs:xt(f)});if(m==null){b(o,404,{error:"unknown app"});return}b(o,200,{lines:m});return}if(y==="focus"&&c==="POST"){let l=r.summary(p);if(!l){b(o,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(f)){b(o,400,{error:"until must be one of serving|healthy|stable"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g=a.searchParams.get("stableMs"),x=g&&Number.isFinite(Number(g))?Math.max(1e3,Number(g)):5e3;o.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache",connection:"keep-alive"});let E=N=>{try{o.write(JSON.stringify(N)+`
|
|
75
|
+
`)}catch{}};E({kind:"subscribed",app:p,until:f,ts:Date.now(),state:kt(l)});let w=Date.now(),_=Date.now(),A=!1,C=N=>{if(A)return;A=!0,r.off("event",$),clearInterval(T),clearInterval(S),clearTimeout(D);let U=r.summary(p);E({kind:"done",reason:N,ts:Date.now(),state:U?kt(U):null,waitedMs:Date.now()-w});try{o.end()}catch{}},P=()=>{let N=r.summary(p);if(!N)return!1;if(f==="serving")return N.status==="serving";if(f==="healthy")return N.status==="serving"&&N.health==="healthy";if(f==="stable"){let U=Date.now()-_;return N.status==="serving"&&N.health==="healthy"&&U>=x}return!1},$=N=>{if(N.app===p)if(_=Date.now(),N.type==="status")E({kind:"status",from:N.from,to:N.to,ts:N.ts}),f!=="stable"&&P()&&C("reached");else if(N.type==="error-new"||N.type==="error-recur"){let B=(r.errors(p)??[])[0];B&&E({kind:"error",message:B.message,parsed:B.parsed??null,ts:N.ts})}else N.type==="health"&&(E({kind:"health",from:N.from,to:N.to,ts:N.ts}),f!=="stable"&&P()&&C("reached"))};r.on("event",$);let T=setInterval(()=>{P()&&C("reached")},1e3),S=setInterval(()=>{try{o.write(`
|
|
76
|
+
`)}catch{}},3e4),D=setTimeout(()=>C("timeout"),d);i.on("close",()=>C("closed")),P()&&C("reached");return}if(y==="health"&&v==="pin"&&c==="POST"){let l=r.getState(p);if(!l){b(o,404,{error:"unknown app"});return}let f={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(A=>{let C=[];i.on("data",P=>C.push(P)),i.on("end",()=>{try{f=JSON.parse(Buffer.concat(C).toString("utf8"))}catch{}A()})});let m=typeof f.path=="string"&&f.path?f.path:l.discoveredHealthPath??null;if(!m){b(o,400,{error:"no path supplied and no discoveredHealthPath on app"});return}let{configLookupPaths:d}=await Promise.resolve().then(()=>(Rt(),pr)),{local:g,user:x}=d(),E=mt.existsSync(g)?g:x,w={};try{w=JSON.parse(mt.readFileSync(E,"utf8"))}catch{}(!w.overrides||typeof w.overrides!="object")&&(w.overrides={}),(!w.overrides[p]||typeof w.overrides[p]!="object")&&(w.overrides[p]={});let _=w.overrides[p].healthProbePath??null;if(w.overrides[p].healthProbePath=m,mt.writeFileSync(E,JSON.stringify(w,null,2)+`
|
|
77
|
+
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}b(o,200,{pinned:m,app:p,configPath:E,previous:_});return}if(y==="try-fix"&&c==="POST"){let l=r.summary(p);if(!l){b(o,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){b(o,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g={status:l.status,health:l.health,errCount:l.errorCount,firstError:(r.errors(p)??[])[0]?.parsed??null},{runAutoFix:x,ALL_AUTO_FIX:E}=await Promise.resolve().then(()=>(_t(),jt)),_=e.getConfig?.()?.doctor?.autoFix?.permitted??E,A={ran:[],skipped:[],errors:[]};try{A=await x({permitted:_,dryRun:!1})}catch(B){A.errors.push({name:"auto-fix",error:B?.message??String(B)})}let C=(A.ran??[]).map(B=>B.name),P=null;try{let B=await r.restart(p);B?.ok||(P=B?.error??"restart failed")}catch(B){P=B?.message??String(B)}let $=await r.waitFor(p,f,d),T=r.summary(p),D=(r.errors(p)??[]).slice(0,5).map(B=>({file:B.parsed?.file??null,line:B.parsed?.line??null,code:B.parsed?.code??null,tool:B.parsed?.tool??null,message:B.parsed?.message??B.message})),N=T?{status:T.status,health:T.health,errCount:T.errorCount}:{status:$.status,health:$.health,errCount:0},U=f==="serving"&&N.status==="serving"||f==="healthy"&&N.status==="serving"&&N.health==="healthy";b(o,200,{before:g,after:N,fixed:C,stillFailing:D,reached:U,waitedMs:$.waitedMs,_meta:{autoFix:A,restartErr:P,timedOut:$.timedOut}});return}if(y==="wait"&&c==="GET"){if(!r.summary(p)){b(o,404,{error:"unknown app"});return}let l=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(l)){b(o,400,{error:"until must be one of serving|healthy|stopped|error"});return}let f=a.searchParams.get("timeout"),m=f?Number(f):120;(!Number.isFinite(m)||m<=0)&&(m=120),m=Math.min(m,600);let d=await r.waitFor(p,l,m*1e3);b(o,200,d);return}if(y==="ensure"&&c==="POST"){let l=r.summary(p);if(!l){b(o,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){b(o,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g=e.getConfig?.().healthProbe?.enabled??!0,x=f,E;if(x==="healthy"&&!g&&(x="serving",E="no health probe; treated serving as terminal"),x==="serving"&&l.status==="serving"||x==="healthy"&&l.status==="serving"&&l.health==="healthy"){b(o,200,{...kt(l),_meta:{format:"compact",startedFromState:null,warning:E,waitedMs:0}});return}let _=l.status;l.status!=="starting"&&l.status!=="compiling"&&await r.start(p);let A=await r.waitFor(p,x,d),C=r.summary(p),P=C?kt(C):{name:p,status:A.status,port:null,url:null,health:A.health,errCount:0,lastChangeMs:null,uptime:null};if(A.timedOut){b(o,200,{error:"timeout",state:P,_meta:{format:"compact",startedFromState:_,warning:E,waitedMs:A.waitedMs,timedOut:!0}});return}b(o,200,{...P,_meta:{format:"compact",startedFromState:_,warning:E,waitedMs:A.waitedMs}});return}if(y==="start"&&c==="POST"){if(a.searchParams.get("withDeps")==="1"){let m=await r.startWithDeps(p);b(o,m.ok?200:400,m);return}let f=await r.start(p);b(o,f.ok?200:400,f);return}if(y==="start-with-deps"&&c==="POST"){let l=await r.startWithDeps(p);b(o,l.ok?200:400,l);return}if(y==="tasks"&&c==="GET"&&!v){let l=r.listTasks(p);if(l==null){b(o,404,{error:"unknown app"});return}b(o,200,{tasks:l,watching:r.listWatchTasks(p)});return}if(y==="run"&&v&&c==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(d=>{let g=[];i.on("data",x=>g.push(x)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(g).toString("utf8"))}catch{}d()})});let f=Array.isArray(l.args)?l.args.map(String):[];if(l.watch){let d=r.startWatchTask(p,v,f);b(o,d.ok?200:400,d);return}let m=await r.runTask(p,v,f);if("error"in m){b(o,404,m);return}b(o,200,m);return}if(y==="run-stop"&&v&&c==="POST"){let l=await r.stopWatchTask(p,v);b(o,200,l);return}if(y==="env"&&c==="GET"){let f=r.getConfig().envFiles?.[p]??[],m=r.getState(p);b(o,200,{candidates:f,active:m?.activeEnvFile??null});return}if(y==="env"&&c==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(m=>{let d=[];i.on("data",g=>d.push(g)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(d).toString("utf8"))}catch{}m()})}),r.setActiveEnvFile(p,l.use??null);let f=r.getState(p);b(o,200,{active:f?.activeEnvFile??null});return}if(y==="requests"&&c==="GET"){if(!e.requestLog){b(o,200,[]);return}let l=xt(a.searchParams.get("since"));b(o,200,e.requestLog.requests(p,l));return}if(y==="clean"&&c==="POST"){let l=a.searchParams.get("deep")==="1",f=a.searchParams.get("yes")==="1",m=De(r,p,l);if(!m){b(o,404,{error:"unknown app"});return}if(m.ranOnServing){b(o,409,{error:"refusing: app is currently running",plan:m});return}if(!f){b(o,200,{plan:m,hint:"pass --yes to delete"});return}let d=Kr(r,p,l);b(o,200,d);return}if(y==="snapshot"&&c==="POST"){if(a.searchParams.get("write")==="1"){let m=qr(r,p);if(!m){b(o,404,{error:"unknown app"});return}b(o,200,{snapshot:m.path});return}let f=Le(r,p);if(!f){b(o,404,{error:"unknown app"});return}b(o,200,f);return}if(y==="stop"&&c==="POST"){let l=await r.stop(p);b(o,l.ok?200:400,l);return}if(y==="restart"&&c==="POST"){let l=await r.restart(p);b(o,l.ok?200:400,l);return}if(c==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let l=Ue();if(l){let f=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let m=Y.resolve(l,f);if(m.startsWith(l)&&$t(o,m))return}if(!Y.extname(f||"")&&$t(o,Y.join(l,"index.html")))return}}b(o,404,{error:"not found"})}catch(a){b(o,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}import Zo from"node:http";import Qo from"node:https";var ti=1e3,ei=500,ri=["/","/health","/-/health","/api/health","/ready","/healthz"];function hn(r,t,e,n,s){if(t)return[t];let i=r.path||"/",o=r.fallbackHosts&&r.fallbackHosts.length?r.fallbackHosts:["127.0.0.1"];if(r.host||r.scheme){let c=e?ne(e):null,u=r.scheme||c?.protocol?.replace(":","")||"http",h=r.host||c?.hostname||(n?o[0]:"127.0.0.1"),p=n??(c?.port?Number(c.port):null);return[gn(u,h,p,i)]}if(e){let c=ne(e);if(c)return c.pathname=i,[c.toString()]}let a=[];s&&a.push(s);for(let c of o)a.includes(c)||a.push(c);return a.map(c=>gn("http",c,n,i))}function ne(r){try{return new URL(r)}catch{return null}}function gn(r,t,e,n){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,i=e?`:${e}`:"";return`${r}://${s}${i}${n.startsWith("/")?n:"/"+n}`}var se=class{constructor(t,e,n){this.registry=t;this.cfg=e;this.fullConfig=n;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let n=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},ei);this.starting.set(t,n)}else{let n=this.timers.get(t);n&&(clearInterval(n),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let n=this.fullConfig?.overrides?.[t]?.url,s=this.fullConfig?.overrides?.[t]?.healthProbePath,i=this.cfg;s?i={...this.cfg,path:s}:e.discoveredHealthPath&&(i={...this.cfg,path:e.discoveredHealthPath});let o=hn(i,n,e.announcedUrl,e.port,e.cachedProbeHost);if(!n&&!s&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),o.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let a=null;for(let u of o){let h=await this.tryProbe(u);if(h.ok){let p=ne(u);p&&this.registry.setCachedProbeHost(t,p.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,u),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}a||(a=`${h.error} ${u}`)}let c=this.freshness.get(t);if(c&&!c.retried){c.retried=!0,setTimeout(()=>{this.probe(t)},ti);return}this.registry.setLastHealthError(t,a||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let n of ri){let s={...this.cfg,path:n},i=hn(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let o of i)if((await this.tryProbe(o,{strict2xx:!0})).ok){e.discoveredHealthPath=n,this.registry.recordEvent({app:t,type:"health",message:`discovered probe path: ${n} (pin via POST /api/apps/${encodeURIComponent(t)}/health/pin or daimon pin-health ${t} --accept)`});return}}}tryProbe(t,e={}){return new Promise(n=>{let s=!1,i=h=>{s||(s=!0,n(h))},o=t.startsWith("https://"),a=o?Qo:Zo,c={timeout:this.cfg.timeoutMs};if(o){let p=ne(t)?.hostname?.replace(/^\[|\]$/g,"")??"",y=p==="127.0.0.1"||p==="::1"||p==="localhost";c.rejectUnauthorized=y?!1:!!this.cfg.rejectUnauthorized}let u=e.strict2xx?300:500;try{let h=a.get(t,c,p=>{let y=p.statusCode??0;p.resume(),y>=200&&y<u?i({ok:!0}):i({ok:!1,error:`http ${y}`})});h.on("timeout",()=>h.destroy(new Error("timeout"))),h.on("error",p=>i({ok:!1,error:p?.code||p?.message||"error"}))}catch(h){i({ok:!1,error:h?.message||"throw"})}})}};import ni from"pidusage";var oe=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let n of this.registry.names()){let s=this.registry.getState(n);s?.pid&&t.push({name:n,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:n,pid:s})=>{try{let i=await ni(s),o=this.registry.getState(n);if(!o)return;let a=Math.round(i.cpu*10)/10,c=Math.round(i.memory/(1024*1024));(o.cpu!==a||o.memMB!==c)&&(o.cpu=a,o.memMB=c,e=!0)}catch{let i=this.registry.getState(n);i&&(i.cpu!=null||i.memMB!=null)&&(i.cpu=null,i.memMB=null,e=!0)}})),e&&this.registry.emit("change")}};var ie=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,n,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!n)return;let i=this.registry.getState(t);if(!i)return;let o=Date.now();if((i.restartWindowStart==null||o-i.restartWindowStart>this.cfg.windowMs)&&(i.restartWindowStart=o,i.restartAttempts=0),i.restartAttempts+=1,i.restartAttempts>this.cfg.maxAttempts){i.lastStatusMessage=`auto-restart aborted (${i.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,i.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(i.restartAttempts-1)*1e3,3e4);i.nextRestartAt=o+a,i.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${i.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");let c=setTimeout(()=>{this.timers.delete(t);let u=this.registry.getState(t);u&&(u.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,c)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let n=this.registry.getState(t);n&&(n.restartAttempts=0,n.restartWindowStart=null,n.nextRestartAt=null)}};import Xe from"node:fs";import yn from"node:path";import si from"node:os";var Ke=yn.join(si.homedir(),".daimon","state.json");function vn(){try{let r=Xe.readFileSync(Ke,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}var qe=null,Je=null;function bn(r){Je=r,!qe&&(qe=setTimeout(()=>{qe=null;let t=Je;if(Je=null,!!t)try{Xe.mkdirSync(yn.dirname(Ke),{recursive:!0}),Xe.writeFileSync(Ke,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
78
|
+
`)}},500))}Fe();qt();import wn from"node:fs";import oi from"node:os";import Sn from"node:path";import{createRequire as ii}from"node:module";var ai=ii(import.meta.url),ci=6e4,ae=class{constructor(t,e){this.registry=t;this.cfg=e;this.logFile=Sn.join(oi.homedir(),".daimon","notifications.log");try{wn.mkdirSync(Sn.dirname(this.logFile),{recursive:!0})}catch{}if(!e.enabled){this.audit("init","disabled by config");return}try{let n=ai("node-notifier");if(this.notifier=n,process.platform==="win32")try{let s=n.WindowsToaster;s&&(this.toaster=new s({withFallback:!0}))}catch(s){this.audit("init",`WindowsToaster unavailable: ${s?.message||s}`)}this.audit("init",`node-notifier loaded${this.toaster?" (+WindowsToaster fallback)":""}`)}catch(n){this.warnOnce(`node-notifier unavailable: ${n?.message||n}`),this.audit("init",`node-notifier load failed: ${n?.message||n}`);return}t.on("event",this.onEvent)}registry;cfg;notifier=null;toaster=null;lastSent=new Map;warned=!1;logFile;audit(t,e){let n=`${new Date().toISOString()} ${t} ${e}
|
|
79
|
+
`;try{wn.appendFileSync(this.logFile,n)}catch{}}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] notifier: ${t}
|
|
80
|
+
`))}stop(){this.registry.off("event",this.onEvent)}onEvent=t=>{this.notifier&&(t.type==="status"&&t.to==="error"&&this.cfg.onError?this.fire(t.app,"error",`${t.app} \u2192 error`,t.message||"app entered error state"):t.type==="health"&&t.to==="unhealthy"&&this.cfg.onUnhealthy?this.fire(t.app,"unhealthy",`${t.app} unhealthy`,"health probe failing"):t.type==="stale"?this.fire(t.app,"stale",`${t.app} stale`,t.message||"no output despite source changes"):t.type==="compile-regression"?this.fire(t.app,"compile-regression",`${t.app} slow compile`,t.message||"compile time regression"):t.type==="bundle-regression"?this.fire(t.app,"bundle-regression",`${t.app} bundle grew`,t.message||"bundle size regression"):t.type==="task-run"&&/exit=[1-9]/.test(t.message||"")&&this.fire(t.app,"task-fail",`${t.app} task failed`,t.message||""))};fire(t,e,n,s){if(!this.notifier)return;let i=`${t}::${e}`,o=this.lastSent.get(i)??0,a=Date.now();if(a-o<ci){this.audit("throttled",`${i}`);return}this.lastSent.set(i,a);let c={title:`daimon: ${n}`,message:s,wait:!1,appID:"daimon"},u=(h,p)=>{h?(this.audit("fail",`${i} :: ${h?.message||h}`),this.warnOnce(`notify failed: ${h?.message||h}`)):this.audit("ok",`${i} :: ${n} :: ${p??"(no response)"}`)};try{this.audit("attempt",`${i} :: ${n}`),(this.toaster??this.notifier).notify(c,u)}catch(h){this.audit("throw",`${i} :: ${h?.message||h}`),this.warnOnce(`notify threw: ${h?.message||h}`)}}};import kn from"node:fs";import ze from"node:path";var li=5e3,ui=3e4,pi=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),di=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),ce=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),li),t.on("compile",this.onCompile))}registry;cfg;timer=null;caches=new Map;stop(){this.timer&&clearInterval(this.timer),this.registry.off("compile",this.onCompile)}onCompile=t=>{let e=this.registry.getApp(t.name);e&&this.caches.delete(e.workspaceRoot)};tick(){for(let t of this.registry.names())this.evaluate(t)}evaluate(t){let e=this.registry.getState(t),n=this.registry.getApp(t);if(!e||!n)return;if(e.status!=="serving"){e.stale&&this.registry.setStale(t,!1);return}if(e.startedAt==null)return;let s=e.lastLogTs??e.startedAt,i=Date.now()-s;if(i<this.cfg.silentMs){e.stale&&this.registry.setStale(t,!1);return}let o=e.lastCompileAt??e.startedAt;this.hasSourceChange(n.workspaceRoot,o,e.lastCompileAt)&&(e.stale||(this.registry.setStale(t,!0),this.registry.recordEvent({app:t,type:"stale",message:`no output in ${Math.round(i/1e3)}s despite source changes`})))}hasSourceChange(t,e,n){let s=this.caches.get(t);if(!s||Date.now()-s.ts>ui||n!=null&&s.ts<n){let a=this.scan(t);this.caches.set(t,{ts:Date.now(),files:a})}return this.caches.get(t).files.some(a=>a.mtime>e)}scan(t){let e=[],n=(s,i)=>{if(i>8||e.length>4e3)return;let o;try{o=kn.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of o)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(pi.has(a.name))continue;n(ze.join(s,a.name),i+1)}else if(a.isFile()){let c=ze.extname(a.name);if(!di.has(c))continue;try{let u=ze.join(s,a.name),h=kn.statSync(u);e.push({path:u,mtime:h.mtimeMs})}catch{}}}};return n(t,0),e}};import xn from"node:http";var le=200,ue=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(t.on("change",this.onChange),this.tick())}registry;cfg;proxies=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.proxies.values())try{t.server.close()}catch{}this.proxies.clear()}onChange=()=>{this.stopped||this.tick()};tick(){for(let t of this.registry.names()){let e=this.registry.getState(t);if(!e)continue;let n=this.proxies.has(t);e.status==="serving"&&e.port&&!n?this.startProxy(t,e.port):e.status!=="serving"&&n&&this.stopProxy(t)}}stopProxy(t){let e=this.proxies.get(t);if(e){try{e.server.close()}catch{}this.proxies.delete(t)}}startProxy(t,e){let n=e+this.cfg.portOffset,s=[],i=xn.createServer((o,a)=>{let c=Date.now(),u={hostname:"127.0.0.1",port:e,method:o.method,path:o.url,headers:{...o.headers,host:`127.0.0.1:${e}`}},h=xn.request(u,p=>{a.writeHead(p.statusCode||502,p.headers),p.pipe(a);let y=()=>{s.push({ts:Date.now(),method:o.method||"GET",path:o.url||"/",status:p.statusCode||0,durationMs:Date.now()-c}),s.length>le&&s.splice(0,s.length-le)};p.on("end",y),p.on("error",y)});h.on("error",()=>{a.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:o.method||"GET",path:o.url||"/",status:502,durationMs:Date.now()-c}),s.length>le&&s.splice(0,s.length-le)}),o.pipe(h)});i.on("error",o=>{o?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${n} in use for ${t}; disabling proxy
|
|
81
|
+
`),this.proxies.delete(t)}),i.listen(n,"127.0.0.1",()=>{this.proxies.set(t,{app:t,proxyPort:n,server:i,buffer:s})})}requests(t,e){let n=this.proxies.get(t);if(!n)return[];if(e){let s=Date.now()-e;return n.buffer.filter(i=>i.ts>=s)}return[...n.buffer]}proxyPortFor(t){return this.proxies.get(t)?.proxyPort??null}};ft();Rt();Pt();import Ye from"node:fs";var fi=new Set(["command","port","env","url"]);function Tn(r){let t=Ye.readFileSync(r,"utf8");t.charCodeAt(0)===65279&&(t=t.slice(1));let e=JSON.parse(t);if(!e||typeof e!="object"||Array.isArray(e))throw new Error("config must be a JSON object");return e}function En(r,t){if(t===null)return null;if(typeof t!="object"||Array.isArray(t))return t;let e=r&&typeof r=="object"&&!Array.isArray(r)?{...r}:{};for(let[n,s]of Object.entries(t))s===null?delete e[n]:e[n]=En(e[n],s);return e}function mi(r,t){let e=r+"."+process.pid+".tmp";Ye.writeFileSync(e,t,"utf8"),Ye.renameSync(e,r)}function hi(r,t){let e=new Set;for(let n of Object.keys(t))JSON.stringify(r?.[n])!==JSON.stringify(t[n])&&e.add(n);for(let n of Object.keys(r||{}))n in t||e.add(n);return[...e]}function Rn(r){let t=Tn(r.configPath),e=En(t,r.patch);if(!e||typeof e!="object")throw new Error("patch produced non-object config");let n=It(e,r.configPath);return mi(r.configPath,JSON.stringify(e,null,2)+`
|
|
82
|
+
`),{config:n,raw:e,applied:hi(t,e),prevRaw:t}}function Ve(r){let t=Tn(r.configPath),e=It(t,r.configPath);return gi(r.registry,e)}function gi(r,t){let e=r.getConfig();for(let u of Object.keys(e))e[u]=void 0;Object.assign(e,t);let n=new Set(r.names()),s=At(e),i=new Set(s.map(u=>u.name)),o=[],a=[];for(let u of s)n.has(u.name)?r.updateDiscoveredApp(u):(r.addDiscoveredApp(u),o.push(u.name));for(let u of n)i.has(u)||a.push(u);let c=[];for(let u of r.names()){let h=r.getState(u);if(h&&(h.status==="serving"||h.status==="compiling")){let p=e.overrides?.[u];if(!p)continue;for(let y of fi)if(y in p){c.push(u);break}}}return{addedApps:o,removedApps:a,restartRequired:c,config:e}}Ct();ft();import An from"node:fs";import yi from"node:os";import Pn from"node:path";var vi=/key|secret|token|password|pass/i;function bi(r){if(!r)return null;let t=JSON.parse(JSON.stringify(r));if(t.apiToken&&(t.apiToken="***"),t.overrides)for(let e of Object.keys(t.overrides)){let n=t.overrides[e]?.env;if(n)for(let s of Object.keys(n))vi.test(s)&&(n[s]="***")}return t}function wi(r,t=200){if(!r)return[];let e=[];for(let n of r.names()){let s=r.getState(n);if(s)for(let i of s.logBuffer)e.push({ts:i.ts,line:`[${n}] ${i.line}`})}return e.sort((n,s)=>n.ts-s.ts),e.slice(-t).map(n=>n.line)}function Si(){let r=Pn.join(it(),"crashes");return An.mkdirSync(r,{recursive:!0}),r}function ki(r,t,e){let n=new Date().toISOString().replace(/[:.]/g,"-"),s=Pn.join(Si(),`${n}.txt`),i=r,o=[`daimon crash dump @ ${new Date().toISOString()}`,`version: ${ot}`,`node: ${process.version}`,`platform: ${process.platform} ${yi.release()}`,`cwd: ${process.cwd()}`,`pid: ${process.pid}`,"","ERROR:",i?.stack||String(i),"","CONFIG (redacted):",JSON.stringify(bi(e),null,2),"","RECENT LOG (last 200 lines across apps):",...wi(t,200)];try{An.writeFileSync(s,o.join(`
|
|
83
|
+
`))}catch{}return s}function Cn(r){let t=e=>{let n=null;try{n=ki(e,r.getRegistry(),r.getConfig())}catch{}try{process.stderr.write(`[daimon] fatal: ${e?.stack||e}
|
|
84
|
+
`)}catch{}if(n)try{process.stderr.write(`[daimon] crash dump: ${n}
|
|
85
|
+
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}Ct();var Ze=1e3,xi=60,Ti=256;function pe(r,t){if(r.length===0)return 0;let e=[...r].sort((s,i)=>s-i),n=Math.min(e.length-1,Math.floor((e.length-1)*t));return Math.round(e[n]*100)/100}var de=class{constructor(t){this.history=t;this.start()}history;startMs=Date.now();lagTimer=null;lagSamples=[];querySamples=[];lockContentionCount=0;lastTickAt=Date.now();highLagStreak=0;warnedAtStreak=0;onSelfWarn=null;start(){let t=performance.now();this.lagTimer=setInterval(()=>{let e=performance.now(),n=Math.max(0,e-t-Ze);t=e,this.lagSamples.push(n),this.lagSamples.length>xi&&this.lagSamples.shift(),this.lastTickAt=Date.now(),n>100?(this.highLagStreak++,this.highLagStreak>=5&&this.highLagStreak>this.warnedAtStreak&&this.onSelfWarn&&(this.warnedAtStreak=this.highLagStreak,this.onSelfWarn(`event loop lag sustained: ${Math.round(n)}ms (${this.highLagStreak} consecutive ticks)`))):(this.highLagStreak=0,this.warnedAtStreak=0)},Ze),this.lagTimer.unref&&this.lagTimer.unref()}setSelfWarnHandler(t){this.onSelfWarn=t}recordQueryMs(t){this.querySamples.push(t),this.querySamples.length>Ti&&this.querySamples.shift()}incLockContention(){this.lockContentionCount++}snapshot(){let t=process.memoryUsage(),e=1024*1024;return{pid:process.pid,version:ot,uptimeMs:Date.now()-this.startMs,rssMB:Math.round(t.rss/e*10)/10,heapUsedMB:Math.round(t.heapUsed/e*10)/10,heapTotalMB:Math.round(t.heapTotal/e*10)/10,eventLoopLagMs:this.lagSamples.length?Math.round(this.lagSamples[this.lagSamples.length-1]*100)/100:0,eventLoopLagP95Ms:pe(this.lagSamples,.95),historyDbQueryMs:{p50:pe(this.querySamples,.5),p95:pe(this.querySamples,.95),p99:pe(this.querySamples,.99)},lockContentionCount:this.lockContentionCount,tickIntervalMs:Ze,lastTickAt:this.lastTickAt}}stop(){this.lagTimer&&clearInterval(this.lagTimer),this.lagTimer=null}};import Ei from"node:fs";import Mn from"node:path";import Ri from"node:os";import{pathToFileURL as Ai}from"node:url";function On(r){return r&&typeof r=="string"&&r.trim()?r:Mn.join(Ri.homedir(),".daimon","plugins")}function Pi(r){return r.startsWith("doctor-")&&r.endsWith(".mjs")}function Ci(r){if(!r||typeof r!="object")return{ok:!1,error:"module has no default export"};let t=r.default??r;return t?typeof t.name!="string"||!t.name.length?{ok:!1,error:"plugin.name must be a non-empty string"}:/^[a-z][a-z0-9-]*$/.test(t.name)?typeof t.scan!="function"?{ok:!1,error:"plugin.scan must be a function"}:t.fix!==void 0&&typeof t.fix!="function"?{ok:!1,error:"plugin.fix, if present, must be a function"}:t.undo!==void 0&&typeof t.undo!="function"?{ok:!1,error:"plugin.undo, if present, must be a function"}:{ok:!0,plugin:t}:{ok:!1,error:`plugin.name must be kebab-case (got "${t.name}")`}:{ok:!1,error:"plugin shape is null"}}var Mi=new Set(["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"]);async function Nn(r){let t=[],e;try{e=Ei.readdirSync(r).filter(Pi).sort()}catch{return t}let n=new Set;for(let s of e){let i=Mn.join(r,s);try{let o=await import(Ai(i).href+`?t=${Date.now()}`),a=Ci(o);if(!a.ok){t.push({name:s,file:i,status:"failed",error:a.error});continue}let c=a.plugin;if(Mi.has(c.name)){t.push({name:c.name,file:i,status:"failed",error:`name collides with built-in rule "${c.name}"`});continue}if(n.has(c.name)){t.push({name:c.name,file:i,status:"failed",error:"duplicate plug-in name"});continue}n.add(c.name),t.push({name:c.name,description:c.description,file:i,status:"ok",module:c})}catch(o){t.push({name:s,file:i,status:"failed",error:o?.message??String(o)})}}return t}async function jn(r,t){for(let e of r)if(!(e.status!=="ok"||!e.module))try{e.lastFindings=await e.module.scan(t),Array.isArray(e.lastFindings)||(e.lastFindings=[])}catch(n){e.status="failed",e.error=`scan failed: ${n?.message??String(n)}`,e.lastFindings=[]}return r}function _n(r){return{config:r.config,apps:r.apps,history:r.history&&typeof r.history.querySelfMetrics=="function"?{querySelfMetrics:r.history.querySelfMetrics.bind(r.history)}:null,mutations:{setOverride:()=>{throw new Error("mutations.setOverride is not implemented in v0.8 \u2014 fix functions are advisory until M44 wires the M36 patch surface")}}}}import R,{useEffect as Di,useState as J}from"react";import tr from"node:fs";import Fi from"node:os";import Ii from"node:path";import{Box as K,Text as j,useApp as Bi,useInput as Hi,useStdout as Ui}from"ink";import er from"ink-text-input";import{spawn as rr,spawnSync as Wi}from"node:child_process";import q,{useEffect as Oi,useMemo as Ni,useState as Tt}from"react";import{Box as Lt,Text as Z,useInput as ji,useStdout as _i}from"ink";import $i from"ink-text-input";function Qe({registry:r,appName:t,onExit:e}){let{stdout:n}=_i(),[s,i]=Tt(0),[o,a]=Tt(!1),[c,u]=Tt(""),[h,p]=Tt(""),[y,v]=Tt(0),[l,f]=Tt(0);Oi(()=>{let P=()=>i(T=>T+1);r.on("change",P);let $=setInterval(()=>i(T=>T+1),500);return()=>{r.off("change",P),clearInterval($)}},[r]);let d=r.getState(t)?.logBuffer.map(P=>P.line)??[],g=(n.rows||30)-4,x=Ni(()=>{if(!h)return[];let P=h.toLowerCase();return d.reduce(($,T,S)=>(T.toLowerCase().includes(P)&&$.push(S),$),[])},[d,h,s]);ji((P,$)=>{if(o){if($.escape){a(!1),u("");return}return}if(P==="q"||$.escape){e();return}if(P==="/"){a(!0);return}if(P==="g"){v(Math.max(0,d.length-g));return}if(P==="G"){v(0);return}if($.pageUp){v(T=>Math.min(Math.max(0,d.length-g),T+g));return}if($.pageDown){v(T=>Math.max(0,T-g));return}if($.upArrow){v(T=>Math.min(Math.max(0,d.length-g),T+1));return}if($.downArrow){v(T=>Math.max(0,T-1));return}if((P==="n"||P==="N")&&x.length){let T=P==="n"?(l+1)%x.length:(l-1+x.length)%x.length;f(T);let S=x[T],D=d.length-y,N=D-g;(S<N||S>=D)&&v(Math.max(0,d.length-S-Math.floor(g/2)));return}});let E=P=>{p(P),a(!1),u(""),f(0)},w=d.length-y,_=Math.max(0,w-g),A=d.slice(_,w),C=(P,$)=>{if(!h)return q.createElement(Z,{key:$},q.createElement(Z,{dimColor:!0},String($+1).padStart(5)," "),P);let T=h,S=P.toLowerCase(),D=T.toLowerCase(),N=[],U=0,B=0;for(;U<P.length;){let et=S.indexOf(D,U);if(et<0){N.push(q.createElement(Z,{key:B++},P.slice(U)));break}et>U&&N.push(q.createElement(Z,{key:B++},P.slice(U,et))),N.push(q.createElement(Z,{key:B++,backgroundColor:"yellow",color:"black"},P.slice(et,et+T.length))),U=et+T.length}let at=x[l]===$;return q.createElement(Z,{key:$},q.createElement(Z,{color:at?"cyan":void 0,dimColor:!at},String($+1).padStart(5)," "),N)};return q.createElement(Lt,{flexDirection:"column"},q.createElement(Lt,null,q.createElement(Z,{bold:!0},"full log: ",q.createElement(Z,{color:"cyan"},t)),q.createElement(Z,{dimColor:!0}," (",d.length," lines",h?`, ${x.length} matches for "${h}"`:"",", scroll=",y,")")),q.createElement(Lt,{flexDirection:"column"},A.length===0?q.createElement(Z,{dimColor:!0},"(no log yet)"):A.map((P,$)=>C(P,_+$))),q.createElement(Lt,null,o?q.createElement(Lt,null,q.createElement(Z,null,"/"),q.createElement($i,{value:c,onChange:u,onSubmit:E})):q.createElement(Z,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var $n={stopped:1,serving:2,compiling:3,starting:3,error:4},Li={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"};function Ln(r,t,e=Date.now()){let n=e-36e5,s=36e5/20,i=new Array(20).fill("");for(let o of r){if(o.type!=="status"||o.app!==t||!o.to||o.ts<n||o.ts>e)continue;let a=Math.min(19,Math.floor((o.ts-n)/s)),c=i[a];(!c||($n[o.to]??0)>($n[c]??0))&&(i[a]=o.to)}return i}function Dn(r){return r.map(t=>Li[t]??"\xB7").join("")}function Gi(r){try{process.platform==="win32"?rr("cmd",["/c","start","",r],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?rr("open",[r],{detached:!0,stdio:"ignore"}).unref():rr("xdg-open",[r],{detached:!0,stdio:"ignore"}).unref()}catch{}}var Fn={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},In={healthy:"green",unhealthy:"red",unknown:"gray"};function qi(r){if(r==null)return"";let t=Math.floor(r/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function nr({registry:r,apiPort:t,onQuit:e}){let{exit:n}=Bi(),{stdout:s}=Ui(),[i,o]=J(r.list()),[a,c]=J(0),[u,h]=J(!1),[p,y]=J(0),[v,l]=J(!1),[f,m]=J([]),[d,g]=J(!1),[x,E]=J(""),[w,_]=J(null),[,A]=J(0),[C,P]=J(null),[$,T]=J(""),[S,D]=J(!1),[N,U]=J(null),[B,at]=J(""),[et,fe]=J(!1),[sr,or]=J(null),[Bn,ir]=J(r.events({sinceMs:3600*1e3}));Di(()=>{let k=()=>o(r.list()),O=()=>ir(r.events({sinceMs:36e5}));r.on("change",k),r.on("event",O);let F=setInterval(()=>{o(r.list()),ir(r.events({sinceMs:3600*1e3})),A(M=>M+1)},1e3);return()=>{r.off("change",k),r.off("event",O),clearInterval(F)}},[r]),Hi((k,O)=>{if(v)return;if(w){if(O.escape){_(null);return}if(O.tab){let M=w.field==="command"?"port":w.field==="port"?"env":"command";_({...w,field:M});return}return}if(d){if(O.escape){g(!1),E("");return}if(O.return){let M=x.trim();m(M?M.split(/[\s,]+/).filter(Boolean):[]),g(!1),E("");return}if(O.backspace||O.delete){E(M=>M.slice(0,-1));return}k&&!O.ctrl&&E(M=>M+k);return}if(S){if(O.escape){D(!1);return}if(O.return){D(!1);return}if(O.backspace||O.delete){T(M=>M.slice(0,-1));return}k&&!O.ctrl&&T(M=>M+k);return}if(et){if(O.escape){fe(!1),at("");return}if(O.return){let M=B.trim();fe(!1),at(""),M&&Wn(M);return}if(O.backspace||O.delete){at(M=>M.slice(0,-1));return}k&&!O.ctrl&&at(M=>M+k);return}if(N){if(k==="y"||k==="Y"){let M=N;U(null),r.restart(M),X(`restarted ${M}`)}else(k==="n"||k==="N"||O.escape)&&U(null);return}if(k==="q"||O.ctrl&&k==="c"){e(),n();return}if(i.length===0)return;if(C==="g"){P(null);let M=k.toLowerCase();M==="a"?X("view: apps (only TUI view)"):M==="e"?X("view: errors \u2014 selected app errors shown in detail pane"):M==="v"?X("view: events \u2014 recent registry events shown in log pane"):M==="s"?X("view: settings \u2014 edit `daimon.config.json`"):M==="n"&&X("view: sessions \u2014 `daimon record` to toggle recording");return}if(O.upArrow||k==="k"){c(M=>Math.max(0,M-1)),y(0);return}if(O.downArrow||k==="j"){c(M=>Math.min(i.length-1,M+1)),y(0);return}let F=i[a];if(F){if(k==="g"){P("g"),setTimeout(()=>P(M=>M==="g"?null:M),1200);return}if(k==="/"){D(!0);return}if(k==="s")r.start(F.name);else if(k==="S")r.stop(F.name);else if(k==="r")U(F.name);else if(k==="f")Un(F.name);else if(k==="x")Hn(F.name);else if(k==="O")fe(!0);else if(k==="L")l(!0);else if(k==="t")g(!0),E(f.join(" "));else if(k==="e"){let M=r.getConfig(),W=r.getApp(F.name),V=r.getState(F.name)?.sessionOverrides??null,lt=V?.env??M.overrides?.[F.name]?.env??{},ut=Object.entries(lt).map(([he,ge])=>`${he}=${ge}`).join(`
|
|
86
|
+
`);_({name:F.name,field:"command",cmd:V?.command??W?.command??"",port:String(V?.port??M.overrides?.[F.name]?.port??F.port??""),env:ut})}else if(k==="E"){let W=r.getConfig().envFiles?.[F.name]??[];if(!W.length)return;let V=r.getState(F.name)?.activeEnvFile??null,lt=V?W.indexOf(V):-1,ut=W[(lt+1)%W.length];r.setActiveEnvFile(F.name,ut)}else if(k==="V"){let M=process.env.EDITOR||(process.platform==="win32"?"notepad":"vi"),W=Ii.join(Fi.tmpdir(),`daimon-${F.name}-${Date.now()}.json`),V=r.getConfig(),lt=r.getApp(F.name),ut=r.getState(F.name)?.sessionOverrides??null,he={command:ut?.command??lt?.command,port:ut?.port??V.overrides?.[F.name]?.port??null,env:ut?.env??V.overrides?.[F.name]?.env??{}};try{tr.writeFileSync(W,JSON.stringify(he,null,2)),Wi(M,[W],{stdio:"inherit",shell:!0});let ge=tr.readFileSync(W,"utf8"),pt=JSON.parse(ge);r.setSessionOverride(F.name,{command:typeof pt.command=="string"?pt.command:void 0,port:typeof pt.port=="number"?pt.port:void 0,env:pt.env&&typeof pt.env=="object"?pt.env:void 0}),tr.unlinkSync(W)}catch{}}else k==="l"?h(M=>!M):k==="o"?F.url&&Gi(F.url):O.pageUp?y(M=>M+5):O.pageDown&&y(M=>Math.max(0,M-5))}});let X=k=>{or(k),setTimeout(()=>or(O=>O===k?null:O),4e3)},Hn=async k=>{X(`try-fix ${k}\u2026`);try{let{runAutoFix:O,ALL_AUTO_FIX:F}=await Promise.resolve().then(()=>(_t(),jt)),W=r.getConfig().doctor?.autoFix?.permitted??F,V=await O({permitted:W,dryRun:!1});await r.restart(k);let lt=await r.waitFor(k,"healthy",6e4);X(`try-fix ${k}: ${lt.timedOut?"timeout":"reached"} \xB7 fixed ${V.ran.length}`)}catch(O){X(`try-fix ${k} failed: ${O?.message??O}`)}},Un=async k=>{X(`focus ${k} until stable\u2026`);try{let O=Date.now(),F=Date.now(),M=W=>{W.app===k&&(F=Date.now())};r.on("event",M);try{for(;Date.now()-O<18e4;){let W=r.summary(k);if(W&&W.status==="serving"&&W.health==="healthy"&&Date.now()-F>=5e3){X(`focus ${k}: stable after ${Math.round((Date.now()-O)/1e3)}s`);return}await new Promise(V=>setTimeout(V,500))}}finally{r.off("event",M)}X(`focus ${k}: timed out`)}catch(O){X(`focus ${k} failed: ${O?.message??O}`)}},Wn=async k=>{X(`orchestrate ${k}\u2026`);try{let{orchestrateProfile:O}=await Promise.resolve().then(()=>(He(),Be)),F=await O(r,r.getConfig(),{profile:k,goal:"healthy",timeoutMs:3e5});if(F.error){X(`orchestrate ${k}: ${F.error}`);return}let M=F.allReached;X(`orchestrate ${k}: ${M?"all reached":"some failing"} \xB7 ${Math.round(F.totalMs/1e3)}s`)}catch(O){X(`orchestrate ${k} failed: ${O?.message??O}`)}},ar=$.trim().toLowerCase(),Dt=(f.length===0?i:i.filter(k=>f.every(O=>k.tags.includes(O)))).filter(k=>!ar||k.name.toLowerCase().includes(ar)),I=Dt[Math.min(a,Math.max(0,Dt.length-1))],ct=I?r.getState(I.name):null,cr=ct?ct.logBuffer.slice(Math.max(0,ct.logBuffer.length-12-p),ct.logBuffer.length-p).map(k=>k.line):[],me=s.columns||100,Gn=Math.min(36,Math.floor(me*.4));return v&&I?R.createElement(Qe,{registry:r,appName:I.name,onExit:()=>l(!1)}):R.createElement(K,{flexDirection:"column",width:me},R.createElement(K,{borderStyle:"round",borderColor:"cyan",paddingX:1},R.createElement(j,{bold:!0,color:"cyan"},"daimon"),R.createElement(j,{dimColor:!0}," \u2022 api http://127.0.0.1:",t)),R.createElement(K,{flexDirection:"row"},R.createElement(K,{flexDirection:"column",width:Gn,borderStyle:"single",borderColor:"gray",paddingX:1},R.createElement(j,{bold:!0},"Apps ",f.length?R.createElement(j,{dimColor:!0},"(tags: ",f.join(", "),")"):null),Dt.length===0?R.createElement(j,{dimColor:!0},i.length===0?"(no apps discovered)":"(no apps match filter)"):Dt.map((k,O)=>{let F=O===a,M=Ln(Bn,k.name),W=Dn(M);return R.createElement(K,{key:k.name,flexDirection:"column"},R.createElement(K,null,R.createElement(j,{color:F?"cyan":void 0},F?"\u25B8 ":" "),R.createElement(j,{color:F?"cyan":void 0},((r.getState(k.name)?.sessionOverrides?"*":"")+k.name).padEnd(20).slice(0,20)),R.createElement(j,{color:Fn[k.status]}," ",k.status.padEnd(9)),R.createElement(j,{color:In[k.health]},k.status==="serving"?"\u25CF":" "),R.createElement(j,{dimColor:!0},k.port?` :${k.port}`:""),me>=100&&k.cpu!=null?R.createElement(j,{dimColor:!0}," ",String(k.cpu).padStart(5),"% ",String(k.memMB??0).padStart(5),"MB"):null),R.createElement(K,null,R.createElement(j,{dimColor:!0}," "),R.createElement(j,{dimColor:!0},W)))})),R.createElement(K,{flexDirection:"column",flexGrow:1,borderStyle:"single",borderColor:"gray",paddingX:1},I&&ct?R.createElement(R.Fragment,null,R.createElement(j,null,"Selected: ",R.createElement(j,{bold:!0},I.name)),R.createElement(j,null,"Status: ",R.createElement(j,{color:Fn[I.status]},I.status)," ",R.createElement(j,{color:In[I.health]},"\u25CF")," ",R.createElement(j,{dimColor:!0},I.health)),R.createElement(j,null,"Port: ",I.port??"-"),R.createElement(j,null,"URL: ",I.url??"-"),I.announcedUrl&&I.announcedUrl!==I.url?R.createElement(j,{dimColor:!0},"Announced: ",I.announcedUrl):null,I.lastHealthError?R.createElement(j,{color:"red"},"HealthErr: ",I.lastHealthError):null,I.stale?R.createElement(j,{color:"yellow"},"\u26A0 stale (best guess)"):null,R.createElement(j,null,"Errors: ",R.createElement(j,{color:I.errorCount?"red":void 0},I.errorCount)),R.createElement(j,null,"Uptime: ",qi(I.uptimeMs)),I.cpu!=null||I.memMB!=null?R.createElement(j,null,"Usage: ",I.cpu??"-","% ",I.memMB??"-"," MB"):null,I.compileHistoryMs.length>0?R.createElement(j,null,"Recent compile: ",I.compileHistoryMs.slice(-5).map(k=>(k/1e3).toFixed(1)+"s").join(" \xB7 ")):null,I.bundle?R.createElement(j,null,"Bundle: ",I.bundle.initialKB,"KB initial \xB7 ",I.bundle.lazyKB,"KB lazy",I.bundleRegressionPct!=null&&I.bundleRegressionPct>10?R.createElement(j,{color:"red"}," (+",I.bundleRegressionPct,"% \u26A0)"):null):null,ct.lastStatusMessage?R.createElement(j,{dimColor:!0},"Note: ",ct.lastStatusMessage):null,R.createElement(j,null,"\u2500\u2500\u2500\u2500 recent log ",u?"(focused)":""," \u2500\u2500\u2500\u2500"),cr.length===0?R.createElement(j,{dimColor:!0},"(no output yet)"):cr.map((k,O)=>R.createElement(j,{key:O,wrap:"truncate-end"},k))):R.createElement(j,{dimColor:!0},"No app selected."))),R.createElement(K,{flexDirection:"column"},d?R.createElement(j,null,"tag filter (space-separated, Enter to apply, Esc to cancel): ",R.createElement(j,{color:"cyan"},x)):null,w?R.createElement(K,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1},R.createElement(j,{bold:!0,color:"yellow"},"edit ",w.name," (session-only) Tab=next field Enter=save Esc=cancel"),R.createElement(K,null,R.createElement(j,null,w.field==="command"?"> ":" ","command: "),w.field==="command"?R.createElement(er,{value:w.cmd,onChange:k=>_({...w,cmd:k}),onSubmit:()=>_({...w,field:"port"})}):R.createElement(j,{dimColor:!0},w.cmd)),R.createElement(K,null,R.createElement(j,null,w.field==="port"?"> ":" ","port: "),w.field==="port"?R.createElement(er,{value:w.port,onChange:k=>_({...w,port:k}),onSubmit:()=>_({...w,field:"env"})}):R.createElement(j,{dimColor:!0},w.port)),R.createElement(K,null,R.createElement(j,null,w.field==="env"?"> ":" ","env (k=v;): "),w.field==="env"?R.createElement(er,{value:w.env.replace(/\n/g,";"),onChange:k=>_({...w,env:k.replace(/;/g,`
|
|
87
|
+
`)}),onSubmit:()=>{let k=Number(w.port),O={};for(let F of w.env.split(/\n/)){let M=F.match(/^\s*([^=]+)=(.*)$/);M&&(O[M[1].trim()]=M[2])}r.setSessionOverride(w.name,{command:w.cmd||void 0,port:Number.isFinite(k)&&k>0?k:void 0,env:Object.keys(O).length?O:void 0}),_(null)}}):R.createElement(j,{dimColor:!0},w.env))):null,N?R.createElement(K,{borderStyle:"round",borderColor:"yellow",paddingX:1},R.createElement(j,{color:"yellow",bold:!0},"Restart ",N,"? "),R.createElement(j,{dimColor:!0},"[y]es [n]o / Esc")):null,S?R.createElement(j,null,"filter (Enter to apply, Esc to clear): ",R.createElement(j,{color:"cyan"},$)):null,et?R.createElement(K,{borderStyle:"round",borderColor:"cyan",paddingX:1},R.createElement(j,{bold:!0,color:"cyan"},"orchestrate profile (Enter to run, Esc to cancel): "),R.createElement(j,{color:"cyan"},B)):null,sr?R.createElement(j,{color:"cyan"},"[i] ",sr):null,R.createElement(j,{dimColor:!0},"[j/k or \u2191/\u2193] move [s] start [S] stop [r] restart [f] focus [x] try-fix [O] orchestrate [o] open URL [/] filter [g a|e|v|s|n] view hint [e] edit [E] env [V] $EDITOR [l] log focus [Shift+L] full log [q] quit")))}async function Yi(r={}){let t=null,e=null;Cn({getRegistry:()=>t,getConfig:()=>e});let n;try{n=Q()}catch(S){process.stderr.write(`[daimon] config error: ${S.message}
|
|
88
|
+
`),process.exit(1)}if(n.kind==="stub-created"){let S=dt();process.stdout.write(`[daimon] no config found. Created stub at:
|
|
89
|
+
${n.path}
|
|
81
90
|
`),process.stdout.write(`[daimon] Edit it to add "searchRoots" pointing at your Nx/Angular workspace, then run again.
|
|
82
91
|
`),process.stdout.write(`[daimon] (Local override path: ${S.local})
|
|
83
|
-
`),process.exit(0)}let{config:s,path:i}=
|
|
84
|
-
`),s.depends&&Object.keys(s.depends).length){let S=
|
|
92
|
+
`),process.exit(0)}let{config:s,path:i}=n;if(process.stdout.write(`[daimon] config: ${i}
|
|
93
|
+
`),s.depends&&Object.keys(s.depends).length){let S=Sr(s.depends);S&&(process.stderr.write(`[daimon] config error: depends graph has a cycle: ${S.join(" -> ")}
|
|
85
94
|
`),process.exit(1))}let o=At(s);o.length===0&&process.stdout.write(`[daimon] no serveable projects discovered in: ${s.searchRoots.join(", ")||"(none)"}
|
|
86
|
-
`);let a=
|
|
87
|
-
`);for(let S of d.apps)c.pin(S.name,S.port);for(let S of d.apps)u.names().includes(S.name)&&u.start(S.name)}if(s.autoStart&&s.autoStart.length){let S=new Set(u.names());for(let
|
|
88
|
-
`);continue}s.depends&&s.depends[
|
|
89
|
-
`);try{
|
|
90
|
-
`)
|
|
91
|
-
`)
|
|
92
|
-
`)
|
|
93
|
-
`),process.
|
|
95
|
+
`);let a=vn(),c=new gt(s.portRange,{initial:a.ports,onChange:S=>bn({ports:S})}),u=new zt(s,o,c);t=u,e=s;let h=new St(s.history);u.setHistory(h);let p=new se(u,s.healthProbe,s),y=new oe(u),v=new ie(u,s.autoRestart),l=new ae(u,s.notifications),f=new ce(u,s.staleDetect),m=new ue(u,s.requestLog);u.on("childExit",({name:S,code:D,signal:N,stopping:U})=>v.onExit(S,D,N,U)),u.on("userStop",({name:S})=>v.onUserStop(S));let d=nn();if(d&&d.apps.length){process.stdout.write(`[daimon] state-handoff: restoring ${d.apps.map(S=>S.name).join(", ")}
|
|
96
|
+
`);for(let S of d.apps)c.pin(S.name,S.port);for(let S of d.apps)u.names().includes(S.name)&&u.start(S.name)}if(s.autoStart&&s.autoStart.length){let S=new Set(u.names());for(let D of s.autoStart){if(!S.has(D)){process.stderr.write(`[daimon] warning: autoStart references unknown app "${D}"
|
|
97
|
+
`);continue}s.depends&&s.depends[D]&&s.depends[D].length?u.startWithDeps(D):u.start(D)}}let g=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):s.apiPort,x=!!r.headless||!!s.headless||process.argv.includes("--headless"),E=setInterval(()=>{try{u.pruneOldErrors()}catch{}},3600*1e3),w=[];try{w=await Nn(On(s.plugins?.dir??void 0));for(let S of w)S.status==="failed"&&process.stderr.write(`[daimon] plug-in skipped: ${Xi.basename(S.file)} \u2014 ${S.error}
|
|
98
|
+
`)}catch{}let _=new de(h);_.setSelfWarnHandler(S=>{try{u.recordEvent({app:"__daemon__",type:"self-warn",message:S})}catch{}});let A=setInterval(()=>{let S=_.snapshot();h.recordSelfMetric(S.rssMB,S.heapUsedMB,S.eventLoopLagMs,S.historyDbQueryMs.p95)},60*1e3);A.unref&&A.unref();let C=!1,P=async()=>{if(!C){C=!0;try{clearInterval(E)}catch{}try{clearInterval(A)}catch{}try{_.stop()}catch{}try{p.stop()}catch{}try{y.stop()}catch{}try{v.stop()}catch{}try{l.stop()}catch{}try{f.stop()}catch{}try{m.stop()}catch{}try{h.close()}catch{}try{await u.stopAll(3e3)}catch{}try{$.close()}catch{}try{Mt()}catch{}process.exit(0)}},$=mn(u,g,{metricsEnabled:s.metrics.enabled,requestLog:m,onShutdown:()=>{P()},configPath:i,getConfig:()=>u.getConfig(),patchConfig:S=>{try{let D=Rn({configPath:i,patch:S}),N=Ve({configPath:i,registry:u});return{ok:!0,applied:D.applied,addedApps:N.addedApps,removedApps:N.removedApps,restartRequired:N.restartRequired}}catch(D){return{ok:!1,error:D?.message||String(D)}}},reloadConfig:async()=>{let S=Ve({configPath:i,registry:u});return{ok:!0,addedApps:S.addedApps,removedApps:S.removedApps,restartRequired:S.restartRequired}},selfMetrics:_,getPlugins:()=>w.map(S=>({name:S.name,description:S.description,file:S.file,status:S.status,error:S.error,lastFindings:S.lastFindings})),runPluginScans:async()=>{let S=_n({config:u.getConfig(),apps:u.names().map(D=>({name:D,workspaceRoot:u.getApp(D)?.workspaceRoot??""})),history:h});await jn(w,S)}});process.stdout.write(`[daimon] api: http://127.0.0.1:${g}
|
|
99
|
+
`);try{$r(Dr(g,x,i))}catch(S){process.stderr.write(`[daimon] warning: could not write daemon.lock: ${S?.message||S}
|
|
100
|
+
`)}if(process.on("SIGINT",()=>{P()}),process.on("SIGTERM",()=>{P()}),process.on("beforeExit",()=>{P()}),x){process.stdout.write(`[daimon] headless mode \u2014 TUI suppressed. Dashboard: http://127.0.0.1:${g}
|
|
101
|
+
`);let S="",D=setInterval(()=>{let N=u.list().map(B=>({name:B.name,status:B.status,health:B.health,port:B.port})),U=JSON.stringify(N);U!==S&&(process.stderr.write(U+`
|
|
102
|
+
`),S=U)},6e4);await new Promise(()=>{}),clearInterval(D);return}await Ki(Ji.createElement(nr,{registry:u,apiPort:g,onQuit:()=>{P()}})).waitUntilExit(),await P()}var Vi=(()=>{try{return import.meta.url===zi(process.argv[1]||"").href}catch{return!1}})();Vi&&Yi().catch(r=>{process.stderr.write(`[daimon] fatal: ${r?.stack||r}
|
|
103
|
+
`),process.exit(1)});export{Yi as startInProcess};
|