daimon 0.5.0 → 0.7.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 +106 -0
- package/README.md +43 -29
- package/dist/cli.js +79 -66
- package/dist/dashboard/3rdpartylicenses.txt +4 -4
- package/dist/dashboard/browser/{chunk-HFJ25UTJ.js → chunk-25VLDASM.js} +4 -4
- package/dist/dashboard/browser/chunk-5PAHWCG5.js +1 -0
- package/dist/dashboard/browser/chunk-6BDWIJ3G.js +3 -0
- package/dist/dashboard/browser/chunk-6C6GHU3A.js +1 -0
- package/dist/dashboard/browser/{chunk-JX3IOOXU.js → chunk-7NRE3SNA.js} +3 -3
- package/dist/dashboard/browser/chunk-BDYOKQF3.js +1 -0
- package/dist/dashboard/browser/chunk-CILFSVSP.js +2 -0
- package/dist/dashboard/browser/chunk-GDJOSLWM.js +1 -0
- package/dist/dashboard/browser/chunk-HYGMRGYR.js +4 -0
- package/dist/dashboard/browser/chunk-HYIZMKSF.js +1 -0
- package/dist/dashboard/browser/chunk-IQZZO5IM.js +3 -0
- package/dist/dashboard/browser/chunk-J5UK77OJ.js +1 -0
- package/dist/dashboard/browser/chunk-JI63U3KC.js +2 -0
- package/dist/dashboard/browser/chunk-K43KW4K2.js +4 -0
- package/dist/dashboard/browser/chunk-KLH6B22T.js +1 -0
- package/dist/dashboard/browser/chunk-L2PHC6DL.js +1 -0
- package/dist/dashboard/browser/{chunk-Q7R63OUT.js → chunk-LBRCWYRN.js} +1 -1
- package/dist/dashboard/browser/chunk-MHYQENOC.js +1 -0
- package/dist/dashboard/browser/{chunk-AEERNAF7.js → chunk-NDSAQ2HK.js} +1 -1
- package/dist/dashboard/browser/chunk-OHX55ZU4.js +2 -0
- package/dist/dashboard/browser/chunk-OUXULJ3Z.js +3 -0
- package/dist/dashboard/browser/chunk-P5IU57TV.js +2 -0
- package/dist/dashboard/browser/{chunk-3TYCIBMV.js → chunk-PJPGLT4T.js} +1 -1
- package/dist/dashboard/browser/chunk-Q3N4MMWW.js +5 -0
- package/dist/dashboard/browser/chunk-RIDV4B55.js +5 -0
- package/dist/dashboard/browser/chunk-SR5JAOLW.js +2 -0
- package/dist/dashboard/browser/{chunk-ZVU34B5S.js → chunk-UC3XMN2Y.js} +1 -1
- package/dist/dashboard/browser/chunk-UU5K6ZPO.js +1 -0
- package/dist/dashboard/browser/chunk-XXIJQBCQ.js +2 -0
- package/dist/dashboard/browser/chunk-Y6B6X4Y6.js +2 -0
- package/dist/dashboard/browser/chunk-YA4AZONZ.js +5 -0
- package/dist/dashboard/browser/chunk-YNCTXEXX.js +3 -0
- package/dist/dashboard/browser/chunk-YNQPX5G6.js +1 -0
- package/dist/dashboard/browser/{chunk-SLQ2WBUA.js → chunk-YYAZGY5M.js} +1 -1
- package/dist/dashboard/browser/chunk-ZDNBWNU5.js +1 -0
- package/dist/dashboard/browser/chunk-ZEO5YLWG.js +3 -0
- package/dist/dashboard/browser/chunk-ZVUH3ISD.js +2 -0
- package/dist/dashboard/browser/index.html +1 -1
- package/dist/dashboard/browser/main-IDF27PFI.js +1 -0
- package/dist/main.js +57 -44
- package/dist/mcp.js +3 -2
- package/package.json +2 -2
- package/dist/dashboard/browser/chunk-5UAN6ETO.js +0 -1
- package/dist/dashboard/browser/chunk-AX3RJNG4.js +0 -1
- package/dist/dashboard/browser/chunk-BADBUP5C.js +0 -3
- package/dist/dashboard/browser/chunk-BF6RQFHS.js +0 -2
- package/dist/dashboard/browser/chunk-C65CUT7O.js +0 -4
- package/dist/dashboard/browser/chunk-CNIZYK4A.js +0 -1
- package/dist/dashboard/browser/chunk-D4BFRQ63.js +0 -4
- package/dist/dashboard/browser/chunk-E235WGFQ.js +0 -3
- package/dist/dashboard/browser/chunk-F2EDJ6FT.js +0 -4
- package/dist/dashboard/browser/chunk-HFAARBWL.js +0 -1
- package/dist/dashboard/browser/chunk-LQNYSOSZ.js +0 -1
- package/dist/dashboard/browser/chunk-MBVVV35N.js +0 -1
- package/dist/dashboard/browser/chunk-NC2VPB4Y.js +0 -2
- package/dist/dashboard/browser/chunk-NXNVIINH.js +0 -1
- package/dist/dashboard/browser/chunk-QLKOKZDG.js +0 -9
- package/dist/dashboard/browser/chunk-QQSPJIPQ.js +0 -1
- package/dist/dashboard/browser/chunk-SCAIGUJL.js +0 -6
- package/dist/dashboard/browser/chunk-TSB6OOH2.js +0 -6
- package/dist/dashboard/browser/chunk-WWUKM5OG.js +0 -1
- package/dist/dashboard/browser/chunk-ZYE3XQS4.js +0 -2
- package/dist/dashboard/browser/main-Z6L5VPBT.js +0 -4
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`,"utf8"),{kind:"stub-created",path:t}}var
|
|
4
|
-
`);return[...e.values()].filter(o=>!o.hidden)}var
|
|
2
|
+
var Oo=Object.defineProperty;var F=(r,t)=>()=>(r&&(t=r(r=0)),t);var gt=(r,t)=>{for(var e in t)Oo(r,e,{get:t[e],enumerable:!0})};var Yn={};gt(Yn,{configLookupPaths:()=>Nt,loadConfig:()=>et,validateConfig:()=>pe});import wt from"node:fs";import yt from"node:path";import ne from"node:os";import{fileURLToPath as No}from"node:url";function zn(){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:yt.join(ne.homedir(),".daimon","logs"),maxFiles:5,maxBytesPerFile:1e7},depends:{},cascadeRestart:!1,history:{enabled:!0,path:yt.join(ne.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"}}}function Xn(r){return r.startsWith("~/")||r.startsWith("~\\")?yt.join(ne.homedir(),r.slice(2)):r==="~"?ne.homedir():r}function pe(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=zn();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,o]of Object.entries(e.profiles))if(!Array.isArray(o)||!o.every(i=>typeof i=="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=Xn(n.logs.dir)),e.depends&&typeof e.depends=="object"&&!Array.isArray(e.depends)){for(let[s,o]of Object.entries(e.depends))if(!Array.isArray(o)||!o.every(i=>typeof i=="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=Xn(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(o=>typeof o=="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)}return n}function Nt(){return{local:yt.join(process.cwd(),"daimon.config.json"),user:yt.join(ne.homedir(),".daimon","config.json")}}function et(){let{local:r,user:t}=Nt();if(wt.existsSync(r)){let s=JSON.parse(wt.readFileSync(r,"utf8"));return{kind:"loaded",config:Ve(s,r),path:r}}if(wt.existsSync(t)){let s=JSON.parse(wt.readFileSync(t,"utf8"));return{kind:"loaded",config:Ve(s,t),path:t}}let n=[yt.resolve(Kn,"..","daimon.config.example.json"),yt.resolve(Kn,"..","..","daimon.config.example.json")].find(s=>wt.existsSync(s));return wt.mkdirSync(yt.dirname(t),{recursive:!0}),n?wt.copyFileSync(n,t):wt.writeFileSync(t,JSON.stringify(zn(),null,2)+`
|
|
3
|
+
`,"utf8"),{kind:"stub-created",path:t}}var $o,Kn,Ft=F(()=>{"use strict";$o=No(import.meta.url),Kn=yt.dirname($o)});var en={};gt(en,{discoverApps:()=>$t});import it from"node:fs";import z from"node:path";import Ze from"fast-glob";function Vn(r){try{return JSON.parse(it.readFileSync(r,"utf8"))}catch{return null}}function Zn(r){return!r||typeof r!="object"?!1:!!(r.targets?.serve||r.architect?.serve)}function Qn(r){if(!r||typeof r!="object")return[];let t=r.targets??r.architect??{};return Object.keys(t).filter(e=>e!=="serve").sort()}function Qe(r){return r.replace(/\\/g,"/")}function Bt(r,t){r&&(r.rejected[t]=(r.rejected[t]??0)+1)}function tn(r,t){try{return t.test(it.readFileSync(r,"utf8"))}catch{return!1}}function Mo(r,t,e){let n=z.basename(r),s=!1,o=z.join(r,"manage.py");if(it.existsSync(o)&&tn(o,/\bdjango\b/i)){let b=n;e.has(b)||e.set(b,{name:b,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"django",command:"python manage.py runserver",hidden:!1,tags:[],workspaceLabel:t}),s=!0}let i=z.join(r,"bin","rails"),a=z.join(r,"Gemfile");if(it.existsSync(i)&&it.existsSync(a)){let b=n;e.has(b)||e.set(b,{name:b,workspaceRoot:r,workspaceType:"polyglot",serverProfile:"rails",command:"bin/rails server",hidden:!1,tags:[],workspaceLabel:t}),s=!0}let l=z.join(r,"pyproject.toml"),c=z.join(r,"requirements.txt");(it.existsSync(l)&&tn(l,/\bfastapi\b/i)||it.existsSync(c)&&tn(c,/\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),(it.existsSync(z.join(r,".air.toml"))||it.existsSync(z.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=z.join(r,"Trunk.toml");return it.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 $t(r,t={}){let e=new Map,n=t.warnings??[],s=t.warnings===void 0;for(let o of r.searchRoots){let i=typeof o=="string"?o:o.path,a=typeof o=="string"?!1:!!o.viteSubfolders,l=typeof o=="string"?void 0:o.label,c=z.resolve(i);if(!it.existsSync(c)){n.push(`searchRoot does not exist: ${c}`),Bt(t.stats,"searchRoot missing");continue}let d=z.join(c,"nx.json"),u=z.join(c,"angular.json");if(it.existsSync(d)){let h=Ze.sync("**/project.json",{cwd:Qe(c),ignore:["**/node_modules/**","**/dist/**","**/.nx/**","**/.git/**"],absolute:!0,dot:!1});for(let m of h){t.stats&&(t.stats.scanned+=1);let f=Vn(m);if(!f){Bt(t.stats,"unreadable project.json");continue}if(!Zn(f)){Bt(t.stats,"no serve target");continue}let g=f.name||z.basename(z.dirname(m));if(!g){Bt(t.stats,"project has no name");continue}if(e.has(g)){n.push(`duplicate project name "${g}" \u2014 keeping first`),Bt(t.stats,"duplicate name");continue}e.set(g,{name:g,workspaceRoot:c,workspaceType:"nx",serverProfile:"nx",command:`npx nx serve ${g}`,hidden:!1,tags:[],tasks:Qn(f),workspaceLabel:l})}continue}if(it.existsSync(u)){let m=Vn(u)?.projects||{};for(let[f,g]of Object.entries(m))if(Zn(g)){if(e.has(f)){n.push(`duplicate project name "${f}" \u2014 keeping first`);continue}e.set(f,{name:f,workspaceRoot:c,workspaceType:"angular",serverProfile:"angular",command:`npx ng serve ${f}`,hidden:!1,tags:[],tasks:Qn(g),workspaceLabel:l})}continue}let y=Ze.sync("vite.config.{ts,js,mjs,cjs}",{cwd:Qe(c),absolute:!0,deep:1}),b=it.existsSync(z.join(c,".storybook")),p=!1;if(y.length>0){let h=z.basename(c);if(e.has(h)||e.set(h,{name:h,workspaceRoot:c,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:l}),p=!0,a){let m=Ze.sync("*/vite.config.{ts,js,mjs,cjs}",{cwd:Qe(c),absolute:!0});for(let f of m){let g=z.dirname(f),T=z.basename(g);T===h||e.has(T)||e.set(T,{name:T,workspaceRoot:g,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:l})}}}if(b){let h=`${z.basename(c)}-storybook`;e.has(h)||e.set(h,{name:h,workspaceRoot:c,workspaceType:"storybook",serverProfile:"storybook",command:"npx storybook dev --no-open",hidden:!1,tags:[],workspaceLabel:l}),p=!0}p||Mo(c,l,e)||(n.push(`searchRoot has none of nx.json/angular.json/vite.config.*/.storybook/polyglot markers: ${c}`),Bt(t.stats,"no project markers"))}for(let[o,i]of Object.entries(r.overrides||{})){let a=e.get(o);a?(i.command&&(a.command=i.command),typeof i.hidden=="boolean"&&(a.hidden=i.hidden),typeof i.port=="number"&&(a.pinnedPort=i.port),i.env&&(a.env=i.env)):i.command&&e.set(o,{name:o,workspaceRoot:process.cwd(),workspaceType:"nx",command:i.command,hidden:i.hidden??!1,pinnedPort:i.port,env:i.env,tags:[]})}for(let o of e.values())o.tags=r.tags?.[o.name]??[];if(s&&n.length)for(let o of n)process.stderr.write(`[daimon] warning: ${o}
|
|
4
|
+
`);return[...e.values()].filter(o=>!o.hidden)}var Ut=F(()=>{"use strict"});function de(r){let s=new Map,o=new Map,i=null,a=l=>{if(!i){s.set(l,1);for(let c of r[l]||[]){let d=s.get(c)??0;if(d===1){let u=[c,l],y=o.get(l);for(;y&&y!==c;)u.push(y),y=o.get(y);y===c&&u.push(c),i=u.reverse();return}if(d===0&&(o.set(c,l),a(c),i))return}s.set(l,2)}};for(let l of Object.keys(r))if((s.get(l)??0)===0&&(o.set(l,null),a(l),i))return i;return null}function fe(r,t){let e=new Set,n=[t];for(;n.length;){let s=n.pop();if(!e.has(s)){e.add(s);for(let o of r[s]||[])n.push(o)}}return[...e]}function me(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 l of r[a]||[])e.has(l)&&(s.get(l).push(a),n.set(a,(n.get(a)??0)+1));let o=[],i=t.filter(a=>(n.get(a)??0)===0);for(;i.length;){o.push([...i].sort());let a=[];for(let l of i)for(let c of s.get(l)??[])n.set(c,(n.get(c)??1)-1),n.get(c)===0&&a.push(c);i=a}return o}function tr(r,t){let e=[];for(let[n,s]of Object.entries(r))s.includes(t)&&e.push(n);return e}var re=F(()=>{"use strict"});import jo from"node:net";function bt(r){return new Promise(t=>{let e=jo.createServer();e.unref(),e.once("error",()=>t(!1)),e.listen({port:r,host:"127.0.0.1",exclusive:!0},()=>{e.close(()=>t(!0))})})}var Ht,se=F(()=>{"use strict";Ht=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,o]of Object.entries(e.initial))typeof o=="number"&&(o<this.min||o>this.max||n.has(o)||(n.add(o),this.assigned.set(s,o)))}}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 o=this.min;o<=this.max;o++){if(s.has(o))continue;if(await bt(o))return this.assigned.set(t,o),this.onChange?.(this.snapshot()),o}throw new Error(`No free ports in range ${this.min}-${this.max}`)}async isPortAvailableForUse(t){return bt(t)}}});import Do from"node:fs";import _o from"node:path";import{createRequire as Io}from"node:module";var Lo,Fo,Bo,Uo,vt,he=F(()=>{"use strict";Lo=Io(import.meta.url),Fo=200,Bo=360*60*1e3,Uo=1e4,vt=class{constructor(t){this.cfg=t;if(t.enabled)try{Do.mkdirSync(_o.dirname(t.path),{recursive:!0});let e=Lo("better-sqlite3");this.db=new e(t.path),this.db.pragma("journal_mode = WAL"),this.migrate(),this.flushTimer=setInterval(()=>this.flush(),Fo),this.retentionStart=setTimeout(()=>this.runRetention(),Uo),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}
|
|
5
5
|
`))}migrate(){this.db&&this.db.exec(`
|
|
6
6
|
CREATE TABLE IF NOT EXISTS events (
|
|
7
7
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -30,107 +30,120 @@ var Hs=Object.defineProperty;var $=(r,t)=>()=>(r&&(t=r(r=0)),t);var vt=(r,t)=>{f
|
|
|
30
30
|
summary TEXT
|
|
31
31
|
);
|
|
32
32
|
CREATE INDEX IF NOT EXISTS task_runs_app_ts ON task_runs(app, ts);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
CREATE TABLE IF NOT EXISTS bundles (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
ts INTEGER NOT NULL,
|
|
36
|
+
app TEXT NOT NULL,
|
|
37
|
+
initialKB INTEGER NOT NULL,
|
|
38
|
+
lazyKB INTEGER NOT NULL,
|
|
39
|
+
fileCount INTEGER NOT NULL
|
|
40
|
+
);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS bundles_app_ts ON bundles(app, ts);
|
|
42
|
+
`)}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,o=Date.now()){this.db&&this.queue.push({kind:"bundle",row:{ts:o,app:t,initialKB:e,lazyKB:n,fileCount:s}})}recordTaskRun(t,e,n,s,o,i=Date.now()){this.db&&this.queue.push({kind:"task",row:{ts:i,app:t,task:e,exit_code:n,duration_ms:s,summary:o==null?null:JSON.stringify(o)}})}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 (?,?,?,?,?,?)"),o=this.db.prepare("INSERT INTO bundles (ts,app,initialKB,lazyKB,fileCount) VALUES (?,?,?,?,?)");this.db.transaction(a=>{for(let l of a)l.kind==="event"?e.run(l.row.ts,l.row.app,l.row.type,l.row.from_state,l.row.to_state,l.row.message):l.kind==="compile"?n.run(l.row.ts,l.row.app,l.row.ms):l.kind==="bundle"?o.run(l.row.ts,l.row.app,l.row.initialKB,l.row.lazyKB,l.row.fileCount):s.run(l.row.ts,l.row.app,l.row.task,l.row.exit_code,l.row.duration_ms,l.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)}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,o=(d,u)=>{let y=Math.floor(d/n)*n,b=s.get(y)??{sum:0,n:0};b.sum+=u,b.n+=1,s.set(y,b)},i=d=>{let u=Math.floor(d/n)*n,y=s.get(u)??{sum:0,n:0};y.sum+=1,y.n+=1,s.set(u,y)},a=0;if(t.metric==="compile"){let d=this.queryCompiles({app:t.app,since:e,limit:1e4});a=d.length;for(let u of d)o(u.ts,u.ms)}else if(t.metric==="bundle"){let d=this.queryBundles({app:t.app,since:e,limit:1e4});a=d.length;for(let u of d){let y=Math.floor(u.ts/n)*n,b=s.get(y)??{sum:0,n:0,sum2:0};b.sum+=u.initialKB,b.sum2=(b.sum2??0)+u.lazyKB,b.n+=1,s.set(y,b)}}else if(t.metric==="errors"){let d=this.queryEvents({app:t.app,since:e,limit:1e4});for(let u of d)(u.type==="error-new"||u.type==="error-recur")&&(i(u.ts),a++)}else{let d=this.queryEvents({app:t.app,since:e,limit:1e4});for(let u of d)u.type==="status"&&u.to_state==="starting"&&(u.from_state==="error"||u.from_state==="serving"||u.from_state==="compiling")&&(i(u.ts),a++)}let l=[],c=[...s.entries()].sort((d,u)=>d[0]-u[0]);for(let[d,u]of c)t.metric==="compile"||t.metric==="bundle"?l.push({t:d,v:Math.round(u.sum/u.n),...u.sum2!=null?{v2:Math.round(u.sum2/u.n)}:{}}):l.push({t:d,v:u.sum});return{points:l,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,o=e,i=!1,a=null,l=[...n].sort((f,g)=>f.ts-g.ts);for(let f of l)f.type==="status"&&(f.to_state==="serving"&&!i?(i=!0,a=f.ts):i&&f.to_state!=="serving"&&a!=null&&(s+=f.ts-a,i=!1,a=null));i&&a!=null&&(s+=Date.now()-a);let c=Math.round(s/(24*3600*1e3)*1e3)/10,d=n.filter(f=>f.type==="status"&&f.to_state==="starting"&&(f.from_state==="serving"||f.from_state==="error"||f.from_state==="compiling")).length,u=this.queryCompiles({app:t,since:e,limit:1e3}).map(f=>f.ms).sort((f,g)=>f-g),y=(f,g)=>{if(f.length===0)return null;let T=Math.min(f.length-1,Math.floor((f.length-1)*g));return f[T]},b=y(u,.5),p=y(u,.95),h=new Map;for(let f of n)if(f.type==="error-new"||f.type==="error-recur"){let g=f.message??"";if(!g)continue;h.set(g,(h.get(g)??0)+1)}let m=[...h.entries()].sort((f,g)=>g[1]-f[1]).slice(0,5).map(([f,g])=>({message:f,count:g}));return{uptimePct24h:c,restartCount24h:d,compileP50:b,compileP95:p,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,o=s?s.ts:Date.now(),i=e.filter(a=>a.ts<o).slice(0,5);return{trigger:s,preceding:i.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}))}}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}}}});import{spawnSync as nn}from"node:child_process";import nr from"tree-kill";function ge(r){if(process.platform==="win32"){let o=nn("powershell",["-NoProfile","-Command",`Get-NetTCPConnection -LocalPort ${r} -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty OwningProcess`],{encoding:"utf8",windowsHide:!0});if(o.status!==0)return null;let i=Number((o.stdout||"").trim().split(/\s+/)[0]);if(!Number.isFinite(i)||i<=0)return null;let a=nn("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${i}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),l,c;try{let d=JSON.parse((a.stdout||"").trim()||"{}");l=typeof d.Name=="string"?d.Name:void 0,c=typeof d.CommandLine=="string"?d.CommandLine:void 0}catch{}return{pid:i,name:l,cmd:c}}let t=nn("lsof",["-nP","-iTCP:"+r,"-sTCP:LISTEN"],{encoding:"utf8"});if(t.status!==0)return null;let e=(t.stdout||"").split(/\r?\n/).filter(o=>o.trim()&&!o.startsWith("COMMAND"));if(!e.length)return null;let n=e[0].split(/\s+/);return{pid:Number(n[1]),name:n[0]}}function rr(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(" ")}function sr(r){return new Promise(t=>{if(!r.pid||r.pid===process.pid){t(!1);return}nr(r.pid,"SIGTERM",e=>{if(e){setTimeout(()=>nr(r.pid,"SIGKILL",n=>t(!n)),500);return}t(!0)})})}var rn=F(()=>{"use strict"});import ye from"node:fs";import Jo from"node:os";import or from"node:path";function ir(r){return ye.readFileSync(r,"utf8").split(/\r?\n/).filter(e=>e.trim()).map(e=>JSON.parse(e))}var we,sn=F(()=>{"use strict";we=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=or.join(Jo.homedir(),".daimon","sessions");ye.mkdirSync(t,{recursive:!0});let e=or.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return ye.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})+`
|
|
43
|
+
`;try{ye.appendFileSync(this.file,e)}catch{}}}});import Go from"node:fs";import on from"node:path";import{fileURLToPath as Wo}from"node:url";function qo(){let r=[on.resolve(ar,"..","package.json"),on.resolve(ar,"..","..","package.json")];for(let t of r)try{return JSON.parse(Go.readFileSync(t,"utf8"))}catch{}return{}}var ar,nt,Gt=F(()=>{"use strict";ar=on.dirname(Wo(import.meta.url));nt=qo().version||"0.0.0"});import Wt from"node:fs";import be from"node:path";import Ko from"node:os";import{spawn as Xo}from"node:child_process";import{fileURLToPath as zo}from"node:url";function at(){return cn}function ve(){return qt}function an(r){try{return process.kill(r,0),!0}catch(t){return t&&t.code==="EPERM"}}function st(){try{let r=Wt.readFileSync(qt,"utf8"),t=JSON.parse(r);if(!t||typeof t.pid!="number")return null;if(!an(t.pid)){try{Wt.unlinkSync(qt)}catch{}return null}return t}catch{return null}}function cr(r){Wt.mkdirSync(cn,{recursive:!0});let t=qt+"."+process.pid+".tmp";Wt.writeFileSync(t,JSON.stringify(r)),Wt.renameSync(t,qt)}function pt(){try{Wt.unlinkSync(qt)}catch{}}function Yo(){let r=be.dirname(zo(import.meta.url));return be.join(r,"main.js")}async function St(r={}){let t={...process.env};r.port&&(t.DAIMON_PORT=String(r.port)),Xo(process.execPath,[Yo(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let n=Date.now();for(;Date.now()-n<5e3;){let s=st();if(s&&(!r.port||s.apiPort===r.port))return s;await new Promise(o=>setTimeout(o,100))}throw new Error("daemon failed to start within 5s")}async function jt(r,t){let e=Date.now();for(;Date.now()-e<t;){if(!an(r))return!0;await new Promise(n=>setTimeout(n,100))}return!an(r)}function lr(r,t,e){return{pid:process.pid,apiPort:r,version:nt,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var cn,qt,dt=F(()=>{"use strict";Gt();cn=be.join(Ko.homedir(),".daimon"),qt=be.join(cn,"daemon.lock")});var xr={};gt(xr,{promptClaudeInstall:()=>ai});import Dt,{useState as Sr}from"react";import{Box as kr,render as ri,Text as xe,useApp as si,useInput as oi}from"ink";function ii({onDone:r}){let{exit:t}=si(),[e,n]=Sr(0),[s,o]=Sr({skill:!0,commands:!1,agent:!0}),i=[{key:"skill",label:"Skill (~/.claude/skills/daimon/SKILL.md)"},{key:"agent",label:"Subagent (~/.claude/agents/daimon-runner.md)"}];return oi((a,l)=>{if(l.escape||a==="q"&&!l.shift){r(null),t();return}if(l.upArrow)n(c=>Math.max(0,c-1));else if(l.downArrow)n(c=>Math.min(i.length-1,c+1));else if(a===" "){let c=i[e].key;o(d=>({...d,[c]:!d[c]}))}else l.return&&(r(s),t())}),Dt.createElement(kr,{flexDirection:"column",paddingX:1},Dt.createElement(xe,{bold:!0,color:"cyan"},"Install Claude Code integration artifacts"),Dt.createElement(xe,{dimColor:!0},"Space toggles \xB7 Enter confirms \xB7 Esc cancels"),i.map((a,l)=>Dt.createElement(kr,{key:a.key},Dt.createElement(xe,{color:l===e?"cyan":void 0},l===e?"\u25B8 ":" "),Dt.createElement(xe,null,"[",s[a.key]?"x":" ","] ",a.label))))}async function ai(){return new Promise(r=>{let t=!1;ri(Dt.createElement(ii,{onDone:n=>{t||(t=!0,r(n))}})).waitUntilExit().then(()=>{t||(t=!0,r(null))})})}var Tr=F(()=>{"use strict"});import ci from"node:crypto";function Si(r){for(let{tool:t,rx:e}of vi)if(e.test(r))return t}function Oi(r){return ci.createHash("sha1").update(r).digest("hex").slice(0,16)}function Ni(r){let t={message:r},e=r.match(fi)||r.match(di);e&&(t.code=`TS${e[1]}`);let n=r.match(hi)||r.match(Pr)||r.match(mi);if(n)t.file=n[1],t.line=Number(n[2]),t.col=Number(n[3]);else{let o=r.match(wi);if(o)t.file=o[1],o[2]&&(t.line=Number(o[2])),o[3]&&(t.col=Number(o[3]));else{let i=r.match(yi);if(i)t.file=i[1];else{let a=r.match(Er);if(a)t.file=a[1],t.line=Number(a[2]),t.col=Number(a[3]);else{let l=r.match(Rr);l&&(t.file=l[1],t.line=Number(l[2]))}}}}let s=Si(r);return s&&(t.tool=s),t}function $i(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 Mi(r,t="127.0.0.1"){let e=r.match(ki)||r.match(xi)||r.match(Ti)||r.match(Pi);if(!e)return null;let n=e[1].replace(/[),.;]+$/,"");return $i(n,t)}function ji(r,t){if(Ri.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="initial",!1;if(Ei.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="lazy",!1;let e=t.match(Ai);if(e&&r.bundle){let s=parseFloat(e[2]),o=e[3].toUpperCase(),i=Math.round(o==="MB"?s*1024:o==="B"?s/1024:s);return/Initial/i.test(e[1])?r.bundle.initialKB=i:r.bundle.lazyKB=i,!0}let n=t.match(Ci);if(n&&r.bundle){let s=n[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let o=n[4].toUpperCase(),i=parseFloat(n[3]),a=o==="MB"?i*1024:o==="B"?i/1024:i;return r.bundle.files.push({name:s,sizeKB:Math.round(a*10)/10}),!1}return!1}function Ar(r,t){let e=t.match(bi),n=e?null:t.match(Pr),s=!e&&!n?t.match(Er):null,o=e??n??s;if(o&&r.lastErrorHash){let p=r.errors.get(r.lastErrorHash);p&&!p.parsed?.file&&(p.parsed={...p.parsed??{message:p.message},file:o[1],line:Number(o[2]),col:Number(o[3])})}else if(r.lastErrorHash){let p=t.match(Rr),h=p?null:t.match(gi);if(p||h){let m=r.errors.get(r.lastErrorHash);if(m&&!m.parsed?.file){let f=p??h;m.parsed={...m.parsed??{message:m.message},file:f[1],line:Number(f[2])}}}}let i=t.trim();if(!i)return null;let a=r.status,l=!1,c,d=Mi(i);d&&!r.announcedUrl&&(r.announcedUrl=d,c=d);let u=ji(r,i),y;if(li.some(p=>p.test(i))){let p=r.status==="error"||!!r.recoveringFromError;if(r.status==="compiling"||r.status==="starting"||r.status==="error"){let h=Date.now();r.compileStartedAt!=null?(y=h-r.compileStartedAt,r.lastCompileMs=y,r.lastCompileAt=h,r.compileStartedAt=null,r.compileHistory.push(y),r.compileHistory.length>20&&r.compileHistory.splice(0,r.compileHistory.length-20)):r.lastCompileAt=h}r.status="serving",p&&(r.errors.clear(),r.recoveringFromError=!1)}else ui.some(p=>p.test(i))&&(r.status==="starting"||r.status==="serving"||r.status==="error")&&(r.status==="error"&&(r.recoveringFromError=!0),r.compileStartedAt=Date.now(),r.status="compiling");let b;if(pi.some(p=>p.test(i))){let p=Oi(i),h=Date.now(),m=r.errors.get(p),f=!1,g;m?(m.count+=1,m.lastSeen=h,g=m):(g={message:i,count:1,firstSeen:h,lastSeen:h,parsed:Ni(i)},r.errors.set(p,g),f=!0),r.lastErrorHash=p,b={entry:g,isNew:f},r.status="error"}return l=r.status!==a,{statusChanged:l,error:b,announcedUrl:c,bundleUpdated:u,compileMs:y}}var li,ui,pi,di,fi,mi,Pr,hi,Rr,Er,gi,yi,wi,bi,vi,ki,xi,Ti,Pi,Ri,Ei,Ai,Ci,Cr=F(()=>{"use strict";li=[/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],ui=[/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],pi=[/^\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*\(/],di=/\berror TS(\d+)/,fi=/✘\s*\[ERROR\]\s*TS(\d+)/,mi=/([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+)\)/,hi=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,Rr=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,Er=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,gi=/^([^\s:()]+\.rb):(\d+):in\b/,yi=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,wi=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,bi=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,vi=[{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):/}];ki=/Local:\s+(https?:\/\/\S+)/i,xi=/Server running at\s+(https?:\/\/\S+)/i,Ti=/listening on\s+(https?:\/\/\S+)/i,Pi=/(?:listening|listen)\s+(https?:\/\/\S+)/i,Ri=/Initial chunk files/i,Ei=/Lazy chunk files/i,Ai=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,Ci=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i});import{spawn as Di}from"node:child_process";import Or from"tree-kill";import _i from"strip-ansi";var Nr,Te,$r=F(()=>{"use strict";Cr();Nr=500,Te=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 i=`${this.deps.commandOverride||t.command} --port ${e}`,a={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},l=Di(i,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=l,n.pid=l.pid??null,n.port=e,l.stdout?.on("data",c=>this.handleChunk(c,"stdout")),l.stderr?.on("data",c=>this.handleChunk(c,"stderr")),l.on("exit",(c,d)=>{let u=n.status,y=this.stopping;y?(n.status="stopped",n.lastStatusMessage=`stopped (code=${c??"null"}${d?`, ${d}`:""})`):c!==0?(n.status="error",n.lastStatusMessage=`process exited with code ${c}${d?` (${d})`:""}`):n.status="stopped",n.pid=null,n.health="unknown",this.child=null,this.stopping=!1,u!==n.status&&this.deps.onStatusChange?.(u,n.status,n.lastStatusMessage),this.deps.onExit?.(c,d,y),this.deps.onStateChange()}),l.on("error",c=>{n.status="error",n.lastStatusMessage=`spawn error: ${c.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let n=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=n,o=s.lastIndexOf(`
|
|
44
|
+
`);if(o<0)return;let i=s.slice(0,o),a=s.slice(o+1);e==="stdout"?this.stdoutBuf=a:this.stderrBuf=a;let{state:l}=this.deps,c=!1;for(let d of i.split(/\r?\n/)){if(!d.length)continue;let u=_i(d),y=Date.now();l.lastLogTs=y,l.stale&&(l.stale=!1),l.logBuffer.push({ts:y,line:u}),l.logBuffer.length>Nr&&l.logBuffer.splice(0,l.logBuffer.length-Nr),this.deps.onLogLine?.(u);let b=l.status,p=Ar(l,u);p?.statusChanged&&(c=!0,this.deps.onStatusChange?.(b,l.status)),p?.error&&this.deps.onErrorRecorded?.(p.error.entry,p.error.isNew),p?.compileMs!=null&&this.deps.onCompile?.(p.compileMs),p?.bundleUpdated&&this.deps.onBundleUpdate?.()}(c||i.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())},o=()=>s();this.child?.once("exit",o),Or(t,"SIGTERM",()=>{});let i=setTimeout(()=>{Or(t,"SIGKILL",()=>{})},2e3),a=setTimeout(()=>{clearTimeout(i),s()},3e3);this.child?.once("exit",()=>{clearTimeout(i),clearTimeout(a),s()})})}}});import ft from"node:fs";import Ii from"node:path";var Pe,Mr=F(()=>{"use strict";Pe=class{constructor(t,e){this.appName=t;this.cfg=e;this.filePath=Ii.join(e.dir,`${t}.log`),this.open()}appName;cfg;fd=null;bytes=0;warned=!1;filePath;open(){try{ft.mkdirSync(this.cfg.dir,{recursive:!0});try{this.bytes=ft.statSync(this.filePath).size}catch{this.bytes=0}this.fd=ft.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}
|
|
45
|
+
`,n=Buffer.from(e,"utf8");ft.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{ft.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{ft.rmSync(e,{force:!0})}catch{}continue}try{ft.existsSync(e)&&ft.renameSync(e,n)}catch{}}try{let t=`${this.filePath}.1`;ft.existsSync(this.filePath)&&ft.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}
|
|
46
|
+
`))}}});import{spawn as Dr}from"node:child_process";import jr from"tree-kill";import _r from"strip-ansi";function Ui(r){let t=r.match(Li);if(t){let s=t[1]?Number(t[1]):0,o=Number(t[2]),i=t[3]?Number(t[3]):o+s;return{passed:o,failed:s,total:i}}let e=r.match(Fi);if(e){let s=Number(e[1]),o=Number(e[2]),i=e[3]?Number(e[3]):0;return{passed:s-i,failed:i,total:o}}let n=r.match(Bi);if(n){let s=Number(n[1]),o=n[2]?Number(n[2]):0;return{passed:s,failed:o,total:s+o}}return null}function Ir(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 Lr(r,t,e=[]){return new Promise(n=>{let s=Date.now(),o=Ir(r,t,e),i=Dr(o,[],{cwd:r.workspaceRoot,shell:!0,env:{...process.env,...r.env||{},FORCE_COLOR:"0"},windowsHide:!0}),a=[],l="",c=d=>{l+=d.toString("utf8");let u=l.lastIndexOf(`
|
|
47
|
+
`);if(u<0)return;let y=l.slice(0,u);l=l.slice(u+1);for(let b of y.split(/\r?\n/)){if(!b.length)continue;let p=_r(b);a.push(p),a.length>1e3&&a.splice(0,a.length-1e3)}};i.stdout?.on("data",c),i.stderr?.on("data",c),i.on("exit",d=>{let u=Date.now()-s,y=a.join(`
|
|
39
48
|
`)+(l?`
|
|
40
|
-
`+l:""),
|
|
41
|
-
`);if(d<0)return;let p=i.slice(0,d);i=i.slice(d+1);for(let y of p.split(/\r?\n/))y.length&&(o.push(pr(y)),o.length>500&&o.splice(0,o.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:o,stop:()=>new Promise(c=>{if(!s.pid){c();return}let d=!1,p=()=>{d||(d=!0,c())};s.once("exit",p),lr(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&lr(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(p,3500)})}}var Wo,Go,qo,hr=$(()=>{"use strict";Wo=/Tests:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Go=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,qo=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i});import yr from"node:fs";import gr from"node:path";function wr(r){let t={},e;try{e=yr.readFileSync(r,"utf8")}catch{return t}for(let n of e.split(/\r?\n/)){let s=n.trim();if(!s||s.startsWith("#"))continue;let o=s.indexOf("=");if(o<0)continue;let i=s.slice(0,o).trim(),a=s.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(t[i]=a)}return t}function qe(r,t){return gr.isAbsolute(t)?t:gr.join(r,t)}function Xe(r,t){return t.filter(e=>yr.existsSync(qe(r,e)))}var vr=$(()=>{"use strict"});import Ko from"node:fs";import Yo from"node:path";function zo(){return Yo.join(X(),"secrets.json")}function br(){try{let r=Ko.readFileSync(zo(),"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 Sr(r,t){let e={};for(let[n,s]of Object.entries(r))e[n]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(o,i)=>t[i]??`\${${i}}`);return e}var kr=$(()=>{"use strict";nt()});import{EventEmitter as Vo}from"node:events";var xr,le,Tr=$(()=>{"use strict";ar();Vt();cr();zt();hr();Fe();vr();kr();Ue();xr=500,le=class extends Vo{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new ee;constructor(t,e,n){super(),this.config=t,this.portAlloc=n??new Pt(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}}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 n=e.state,s=n.startedAt&&(n.status==="serving"||n.status==="compiling"||n.status==="starting")?Date.now()-n.startedAt:null,i=this.config.overrides?.[t]?.url||e.resolvedUrl||n.announcedUrl||(n.port?`http://127.0.0.1:${n.port}`:null),a;for(let l=this.eventBuffer.length-1;l>=0;l--){let c=this.eventBuffer[l];if(c.app===t&&c.type==="status"){a=Date.now()-c.ts;break}}return{name:n.name,status:n.status,port:n.port,url:i,errorCount:[...n.errors.values()].reduce((l,c)=>l+c.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,o)=>o.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 o=Date.now()-e.sinceMs;s=s.filter(i=>i.ts>=o)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(o=>o.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>xr&&this.eventBuffer.splice(0,this.eventBuffer.length-xr),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 o=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:o,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(S){return e.state.status="error",e.state.lastStatusMessage=S.message,this.recordEvent({app:t,type:"status",from:n,to:"error",message:S.message}),this.emit("change"),{ok:!1,status:"error",error:S.message}}if(!await Rt(s)){let S=Zt(s),u=Mn(s,S);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=u,this.recordEvent({app:t,type:"status",from:n,to:"error",message:u}),this.emit("change"),{ok:!1,status:"error",error:u}}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 ce(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],l={};if(a.length){let S=e.state.activeEnvFile;(!S||!Xe(e.app.workspaceRoot,[S]).length)&&(S=Xe(e.app.workspaceRoot,a)[0]??null,S&&(e.state.activeEnvFile=S)),S&&(l=wr(qe(e.app.workspaceRoot,S)))}let c={...l,...this.config.overrides?.[t]?.env??{},...i?.env??{}},d=br(),p=Sr(c,d),y=new ae({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:i?.command,onStateChange:()=>this.emit("change"),onStatusChange:(S,u,h)=>{this.recordEvent({app:t,type:"status",from:S,to:u,message:h}),(u==="stopped"||u==="error")&&(S==="serving"||S==="compiling")&&this.armCascade(t)},onErrorRecorded:(S,u)=>this.recordEvent({app:t,type:u?"error-new":"error-recur",message:S.message}),onExit:(S,u,h)=>this.emit("childExit",{name:t,code:S,signal:u,stopping:h}),onLogLine:S=>{e.logger?.write(S),this.emit("log",{name:t,ts:Date.now(),line:S})},onCompile:S=>{this.history?.recordCompile(t,S);let u=this.getState(t),h=e.lastBundleInitialKB;if(u.bundle&&u.bundle.initialKB>0){if(h&&h>0){let g=(u.bundle.initialKB-h)/h*100;u.bundleRegressionPct=Math.round(g*10)/10,g>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${u.bundleRegressionPct}% (${h}->${u.bundle.initialKB})`})}else u.bundleRegressionPct=null;e.lastBundleInitialKB=u.bundle.initialKB}this.checkCompileRegression(t,S),this.emit("compile",{name:t,ms:S})},onBundleUpdate:()=>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=On(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=Nn(this.config.depends??{},n),o=[],i=e.waitMs??6e4;for(let a of s){let l=await Promise.all(a.map(d=>this.start(d)));for(let d=0;d<a.length;d++){let p=l[d];if(!p.ok)return o.push({name:a[d],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:o}}let c=await Promise.all(a.map(d=>this.waitFor(d,"healthy",i)));for(let d=0;d<a.length;d++){let p=c[d],y=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(o.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:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=$n(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 o=await fr(s,e,n);return this.history?.recordTaskRun(t,e,o.exitCode,o.durationMs,o.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${o.exitCode} duration=${o.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:o}),o}startWatchTask(t,e,n=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let o=`${t}::${e}`;if(this.watchTasks.has(o))return{ok:!0,pid:this.watchTasks.get(o).pid};let i=mr(s,e,n);return this.watchTasks.set(o,i),i.child.on("exit",()=>this.watchTasks.delete(o)),{ok:!0,pid:i.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 o=n.queryCompiles({app:t,limit:31}).filter(l=>l.ms!==e).slice(0,30).map(l=>l.ms);if(o.length<10)return;let i=[...o].sort((l,c)=>l-c),a=i[Math.floor((i.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 o=s.logs;return n?o.slice(-n):[...o]}waitFor(t,e,n){return new Promise(s=>{let o=Date.now(),i=this.entries.get(t),a=()=>{if(!i)return!0;let p=i.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"},l=p=>{this.off("change",c),clearTimeout(d);let y=i?.state;s({name:t,status:y?.status??"unknown",health:y?.health??"unknown",timedOut:p,waitedMs:Date.now()-o})},c=()=>{a()&&l(!1)};if(a()){s({name:t,status:i.state.status,health:i.state.health,timedOut:!1,waitedMs:0});return}let d=setTimeout(()=>l(!0),n);this.on("change",c)})}}});import ze from"node:fs";import Cr from"node:path";import Qo from"node:os";function Zo(){try{let r=ze.readFileSync(Ve,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function ti(r){Ye=r,!Ke&&(Ke=setTimeout(()=>{Ke=null;let t=Ye;if(Ye=null,!!t)try{ze.mkdirSync(Cr.dirname(Ve),{recursive:!0}),ze.writeFileSync(Ve,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
42
|
-
`)}},500))}var
|
|
49
|
+
`+l:""),b=Ui(y);n({app:r.name,task:t,exitCode:d,durationMs:u,summary:b,outputTail:a.slice(-50)})}),i.on("error",()=>{n({app:r.name,task:t,exitCode:-1,durationMs:Date.now()-s,summary:null,outputTail:[...a,"[daimon] task spawn error"]})})})}function Fr(r,t,e=[]){let n=Ir(r,t,e),s=Dr(n,[],{cwd:r.workspaceRoot,shell:!0,env:{...process.env,...r.env||{},FORCE_COLOR:"0"},windowsHide:!0}),o=[],i="",a=c=>{i+=c.toString("utf8");let d=i.lastIndexOf(`
|
|
50
|
+
`);if(d<0)return;let u=i.slice(0,d);i=i.slice(d+1);for(let y of u.split(/\r?\n/))y.length&&(o.push(_r(y)),o.length>500&&o.splice(0,o.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:o,stop:()=>new Promise(c=>{if(!s.pid){c();return}let d=!1,u=()=>{d||(d=!0,c())};s.once("exit",u),jr(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&jr(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(u,3500)})}}var Li,Fi,Bi,Br=F(()=>{"use strict";Li=/Tests:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Fi=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,Bi=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i});import Hr from"node:fs";import Ur from"node:path";function Jr(r){let t={},e;try{e=Hr.readFileSync(r,"utf8")}catch{return t}for(let n of e.split(/\r?\n/)){let s=n.trim();if(!s||s.startsWith("#"))continue;let o=s.indexOf("=");if(o<0)continue;let i=s.slice(0,o).trim(),a=s.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(t[i]=a)}return t}function pn(r,t){return Ur.isAbsolute(t)?t:Ur.join(r,t)}function dn(r,t){return t.filter(e=>Hr.existsSync(pn(r,e)))}var Gr=F(()=>{"use strict"});import Hi from"node:fs";import Ji from"node:path";function Gi(){return Ji.join(at(),"secrets.json")}function Wr(){try{let r=Hi.readFileSync(Gi(),"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 qr(r,t){let e={};for(let[n,s]of Object.entries(r))e[n]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(o,i)=>t[i]??`\${${i}}`);return e}var Kr=F(()=>{"use strict";dt()});import{EventEmitter as Wi}from"node:events";var Xr,Re,zr=F(()=>{"use strict";$r();se();Mr();re();Br();rn();Gr();Kr();sn();Xr=500,Re=class extends Wi{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new we;constructor(t,e,n){super(),this.config=t,this.portAlloc=n??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,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()]}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,i=this.config.overrides?.[t]?.url||e.resolvedUrl||n.announcedUrl||(n.port?`http://127.0.0.1:${n.port}`:null),a;for(let l=this.eventBuffer.length-1;l>=0;l--){let c=this.eventBuffer[l];if(c.app===t&&c.type==="status"){a=Date.now()-c.ts;break}}return{name:n.name,status:n.status,port:n.port,url:i,errorCount:[...n.errors.values()].reduce((l,c)=>l+c.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,o)=>o.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 o=Date.now()-e.sinceMs;s=s.filter(i=>i.ts>=o)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(o=>o.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>Xr&&this.eventBuffer.splice(0,this.eventBuffer.length-Xr),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 o=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:o,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(b){return e.state.status="error",e.state.lastStatusMessage=b.message,this.recordEvent({app:t,type:"status",from:n,to:"error",message:b.message}),this.emit("change"),{ok:!1,status:"error",error:b.message}}if(!await bt(s)){let b=ge(s),p=rr(s,b);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=p,this.recordEvent({app:t,type:"status",from:n,to:"error",message:p}),this.emit("change"),{ok:!1,status:"error",error:p}}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 Pe(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],l={};if(a.length){let b=e.state.activeEnvFile;(!b||!dn(e.app.workspaceRoot,[b]).length)&&(b=dn(e.app.workspaceRoot,a)[0]??null,b&&(e.state.activeEnvFile=b)),b&&(l=Jr(pn(e.app.workspaceRoot,b)))}let c={...l,...this.config.overrides?.[t]?.env??{},...i?.env??{}},d=Wr(),u=qr(c,d),y=new Te({state:e.state,app:e.app,port:s,envOverride:Object.keys(u).length?u:void 0,commandOverride:i?.command,onStateChange:()=>this.emit("change"),onStatusChange:(b,p,h)=>{this.recordEvent({app:t,type:"status",from:b,to:p,message:h}),(p==="stopped"||p==="error")&&(b==="serving"||b==="compiling")&&this.armCascade(t)},onErrorRecorded:(b,p)=>this.recordEvent({app:t,type:p?"error-new":"error-recur",message:b.message}),onExit:(b,p,h)=>this.emit("childExit",{name:t,code:b,signal:p,stopping:h}),onLogLine:b=>{e.logger?.write(b),this.emit("log",{name:t,ts:Date.now(),line:b})},onCompile:b=>{this.history?.recordCompile(t,b);let p=this.getState(t),h=e.lastBundleInitialKB;if(p.bundle&&p.bundle.initialKB>0){if(h&&h>0){let m=(p.bundle.initialKB-h)/h*100;p.bundleRegressionPct=Math.round(m*10)/10,m>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${p.bundleRegressionPct}% (${h}->${p.bundle.initialKB})`})}else p.bundleRegressionPct=null;e.lastBundleInitialKB=p.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=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=fe(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=me(this.config.depends??{},n),o=[],i=e.waitMs??6e4;for(let a of s){let l=await Promise.all(a.map(d=>this.start(d)));for(let d=0;d<a.length;d++){let u=l[d];if(!u.ok)return o.push({name:a[d],status:u.status,health:"unknown",error:u.error}),{ok:!1,results:o}}let c=await Promise.all(a.map(d=>this.waitFor(d,"healthy",i)));for(let d=0;d<a.length;d++){let u=c[d],y=!u.timedOut&&u.status==="serving"&&u.health==="healthy";if(o.push({name:u.name,status:u.status,health:u.health,error:y?void 0:u.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!y)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=tr(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 o=await Lr(s,e,n);return this.history?.recordTaskRun(t,e,o.exitCode,o.durationMs,o.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${o.exitCode} duration=${o.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:o}),o}startWatchTask(t,e,n=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let o=`${t}::${e}`;if(this.watchTasks.has(o))return{ok:!0,pid:this.watchTasks.get(o).pid};let i=Fr(s,e,n);return this.watchTasks.set(o,i),i.child.on("exit",()=>this.watchTasks.delete(o)),{ok:!0,pid:i.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 o=n.queryCompiles({app:t,limit:31}).filter(l=>l.ms!==e).slice(0,30).map(l=>l.ms);if(o.length<10)return;let i=[...o].sort((l,c)=>l-c),a=i[Math.floor((i.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 o=s.logs;return n?o.slice(-n):[...o]}waitFor(t,e,n){return new Promise(s=>{let o=Date.now(),i=this.entries.get(t),a=()=>{if(!i)return!0;let u=i.state;return e==="serving"&&u.status==="serving"||e==="healthy"&&u.status==="serving"&&u.health==="healthy"||e==="stopped"&&u.status==="stopped"||e==="error"&&u.status==="error"},l=u=>{this.off("change",c),clearTimeout(d);let y=i?.state;s({name:t,status:y?.status??"unknown",health:y?.health??"unknown",timedOut:u,waitedMs:Date.now()-o})},c=()=>{a()&&l(!1)};if(a()){s({name:t,status:i.state.status,health:i.state.health,timedOut:!1,waitedMs:0});return}let d=setTimeout(()=>l(!0),n);this.on("change",c)})}}});import hn from"node:fs";import Yr from"node:path";import qi from"node:os";function Ki(){try{let r=hn.readFileSync(gn,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function Xi(r){mn=r,!fn&&(fn=setTimeout(()=>{fn=null;let t=mn;if(mn=null,!!t)try{hn.mkdirSync(Yr.dirname(gn),{recursive:!0}),hn.writeFileSync(gn,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
51
|
+
`)}},500))}var gn,fn,mn,Ee,Vr=F(()=>{"use strict";gn=Yr.join(qi.homedir(),".daimon","cursors.json");fn=null,mn=null;Ee=class{data=Ki();getErrorCursor(t,e){return this.data.errors[`${t}:${e}`]??0}setErrorCursor(t,e,n){this.data.errors[`${t}:${e}`]=n,Xi(this.data)}}});import Zr from"node:fs";import zi from"node:os";import Qr from"node:path";function Vi(r){let t={};for(let[e,n]of Object.entries(r))typeof n=="string"&&(t[e]=Yi.test(e)?"***":n);return t}function yn(r,t){let e=r.summary(t);if(!e)return null;let n=r.getState(t),s=r.getApp(t),o=r.getConfig(),i=o.overrides?.[t]??{},a={...process.env,...s.env??{},...n.sessionOverrides?.env??{}},l=r.getHistory(),c=l?l.queryEvents({app:t,limit:50}):[],d=l?l.queryBundles({app:t,limit:100}):[];return{takenAt:new Date().toISOString(),summary:e,logs:n.logBuffer.slice(-500).map(u=>({ts:u.ts,line:u.line})),errors:[...n.errors.entries()].map(([u,y])=>({hash:u,message:y.message,count:y.count,firstSeen:y.firstSeen,lastSeen:y.lastSeen})),env:Vi(a),configSlice:{command:n.sessionOverrides?.command??i.command??s.command,port:n.sessionOverrides?.port??i.port??null,workspaceRoot:s.workspaceRoot,workspaceType:s.workspaceType,tags:s.tags,depends:o.depends?.[t]??[],envFiles:o.envFiles?.[t]??[]},events:c,bundles:d}}function ts(r,t){let e=yn(r,t);if(!e)return null;let n=Qr.join(zi.homedir(),".daimon","snapshots");Zr.mkdirSync(n,{recursive:!0});let s=e.takenAt.replace(/[:.]/g,"-"),o=Qr.join(n,`${t}-${s}.json`);return Zr.writeFileSync(o,JSON.stringify(e,null,2)),{path:o,payload:e}}var Yi,es=F(()=>{"use strict";Yi=/key|secret|token|password|api[-_]?key/i});import Ae from"node:fs";import ns from"node:path";function rs(r){let t=0;try{let e=Ae.readdirSync(r,{withFileTypes:!0});for(let n of e){let s=ns.join(r,n.name);try{n.isDirectory()?t+=rs(s):n.isFile()&&(t+=Ae.statSync(s).size)}catch{}}}catch{}return t}function wn(r,t,e){let n=r.getApp(t);if(!n)return null;let s=r.getState(t),o=s?s.status==="serving"||s.status==="compiling"||s.status==="starting":!1,a=[...Zi,...e?Qi:[]].map(l=>{let c=ns.join(n.workspaceRoot,l),d=Ae.existsSync(c);return{path:c,exists:d,sizeBytes:d?rs(c):0}});return{app:t,workspace:n.workspaceRoot,targets:a,ranOnServing:o}}function ss(r,t,e){let n=wn(r,t,e);if(!n)return{error:"unknown app"};if(n.ranOnServing)return{error:"app is currently running; stop it first"};let s=[],o=[];for(let i of n.targets)if(i.exists)try{Ae.rmSync(i.path,{recursive:!0,force:!0}),s.push(i.path)}catch(a){o.push({path:i.path,error:a?.message||String(a)})}return{ok:o.length===0,removed:s,failed:o}}var Zi,Qi,os=F(()=>{"use strict";Zi=["dist",".angular/cache","tmp","out-tsc"],Qi=["node_modules"]});function oe(r){return r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}function is(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 ta)t.push(`daimon_app_status{name="${oe(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="${oe(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="${oe(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="${oe(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="${oe(n.name)}"} ${n.memMB}`);return t.join(`
|
|
43
52
|
`)+`
|
|
44
|
-
`}var
|
|
45
|
-
`;try{
|
|
46
|
-
`,"utf8");let o=
|
|
47
|
-
`);let T=b=>{h&&b.app!==h||i.write(JSON.stringify(b)+`
|
|
48
|
-
`)
|
|
49
|
-
`)}
|
|
50
|
-
`);i.end();return}if(a.searchParams.get("
|
|
53
|
+
`}var ta,as=F(()=>{"use strict";ta=["stopped","starting","compiling","serving","error"]});import ie from"node:fs";import ea from"node:crypto";import cs from"node:path";function ra(){return cs.join(at(),"audit.log")}function sa(r){try{if(ie.statSync(r).size>na){let e=r+".1";try{ie.unlinkSync(e)}catch{}ie.renameSync(r,e)}}catch{}}function ls(r,t,e,n){let s=ra();ie.mkdirSync(cs.dirname(s),{recursive:!0}),sa(s);let o=JSON.stringify({prev:t,next:e}),i=ea.createHash("sha1").update(o).digest("hex").slice(0,12),a=`${new Date().toISOString()} ${r} ${i} ${n.join(",")}
|
|
54
|
+
`;try{ie.appendFileSync(s,a)}catch{}}var na,us=F(()=>{"use strict";dt();na=1e6});import Ce from"node:fs";import Oe from"node:path";import{fileURLToPath as oa}from"node:url";function ia(){let r=[Oe.resolve(ps,"templates","presets"),Oe.resolve(ps,"..","src","templates","presets")];for(let t of r)if(Ce.existsSync(t))return t;return r[0]}function ds(){let r=ia();if(!Ce.existsSync(r))return[];let t=Ce.readdirSync(r).filter(n=>n.endsWith(".json")),e=[];for(let n of t)try{let s=Ce.readFileSync(Oe.join(r,n),"utf8");s.charCodeAt(0)===65279&&(s=s.slice(1)),e.push(JSON.parse(s))}catch{}return e}var ps,fs=F(()=>{"use strict";ps=Oe.dirname(oa(import.meta.url))});import Ne from"node:fs";import ms from"node:path";function hs(){return ms.join(at(),"state-handoff.json")}function gs(r){let t=[];for(let s of r.names()){let o=r.getState(s);o&&(o.status==="serving"||o.status==="compiling"||o.status==="starting")&&o.port&&t.push({name:s,port:o.port})}let e={ts:Date.now(),apps:t},n=hs();return Ne.mkdirSync(ms.dirname(n),{recursive:!0}),Ne.writeFileSync(n,JSON.stringify(e)),n}function ys(r=6e4){let t=hs();try{let e=Ne.readFileSync(t,"utf8"),n=JSON.parse(e);return Ne.unlinkSync(t),!n||typeof n.ts!="number"||Date.now()-n.ts>r?null:n}catch{return null}}var bn=F(()=>{"use strict";dt()});var zt={};gt(zt,{ALL_AUTO_FIX:()=>ws,runAutoFix:()=>Ra});import L from"node:fs";import q from"node:path";function aa(){let r=st();if(!r)return{detected:!1,description:"no daemon running"};let t=process.cwd(),e=q.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,o=n&&q.resolve(n)===q.resolve(t),i=s&&q.resolve(s)===q.resolve(e);return o||i?{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 ca(){let r=st();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 jt(r.pid,5e3),pt(),`respawned daemon at pid ${(await St({})).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 la(){let r;try{r=L.readFileSync(ve(),"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 ua(){let r="(unknown)";try{let e=JSON.parse(L.readFileSync(ve(),"utf8"));r=String(e?.pid??"?")}catch{}pt();let t=await St({});return`removed stale ${ve()} (prior pid ${r} was dead); spawned fresh daemon at pid ${t.pid}.`}function pa(){let r=process.cwd(),e=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs","vite.config.cjs",".storybook"].filter(i=>L.existsSync(q.join(r,i)));if(!e.length)return{detected:!1,description:"no nx.json/angular.json/vite.config.*/.storybook in cwd"};let n=et();return n.kind!=="loaded"?{detected:!0,description:`${e.join(", ")} present but no config is loaded`,markerFiles:e}:n.config.searchRoots.map(i=>q.resolve(typeof i=="string"?i:i.path)).some(i=>r.startsWith(i))?{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 da(){let r=process.cwd(),{local:t,user:e}=Nt(),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(i=>(typeof i=="string"?i:i?.path)===r)){let i;try{let a=JSON.parse(L.readFileSync(q.join(r,"package.json"),"utf8"));typeof a.name=="string"&&(i=a.name)}catch{}s.searchRoots.push(i?{path:r,label:i}:r)}L.mkdirSync(q.dirname(n),{recursive:!0}),L.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
55
|
+
`,"utf8");let o=st();if(o)try{fetch(`http://127.0.0.1:${o.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`appended ${r} as a searchRoot in ${n}; triggered soft-reload of the running daemon.`}function fa(){let r=et();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 vt(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 ma(){let r=et();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 ha(){let r=et();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"),o=Array.from(new Set([...s,t,e])),i=[];for(let a of o)if(!(!Number.isFinite(a)||a<=0))try{await bt(a)||i.push(a)}catch{}return i.length?{detected:!0,description:`ports already LISTEN: ${i.join(", ")} (range ${t}-${e} + pinned overrides)`,conflicts:i}:{detected:!1,description:`all checked ports free (range ${t}-${e} + pinned)`}}function ga(){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 ya(){let r=process.cwd(),t=process.versions.node,e=q.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=q.join(r,"package.json");if(L.existsSync(n))try{let o=JSON.parse(L.readFileSync(n,"utf8"))?.engines?.node;if(typeof o=="string"&&o.trim()){let i=o.match(/(\d+)(?:\.(\d+))?/);if(i){let a=Number(i[1]),l=Number(t.split(".")[0]);if(Number.isFinite(a)&&Number.isFinite(l)&&l<a)return{detected:!0,description:`package.json engines.node = "${o}" but running ${t}`,expected:o,actual:t}}}}catch{}return{detected:!1,description:`node ${t} satisfies .nvmrc / engines.node (or neither is present)`}}function wa(){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 ba(){let r=et();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 o=q.join(s,"package.json");if(!L.existsSync(o))continue;let i=null;for(let a of["package-lock.json","pnpm-lock.yaml","yarn.lock"]){let l=q.join(s,a);if(L.existsSync(l)){i=l;break}}t.push({name:q.basename(s),root:s,pkgPath:o,lockPath:i,nmPath:q.join(s,"node_modules")})}return t}function bs(){let r=ba();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,o=L.statSync(n.nmPath).mtimeMs;s>o+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 va(){let r=bs();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 vn(){let r=et();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 vs(){let r=vn();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=q.join(n,"pyproject.toml"),o=q.join(n,"requirements.txt"),i=q.join(n,"manage.py");if(!(L.existsSync(s)||L.existsSync(o)||L.existsSync(i)))continue;let l=[".venv","venv","env"].map(d=>q.join(n,d)).find(d=>L.existsSync(d));if(!l){t.push({root:n,reason:"missing"});continue}let c=[];for(let d of[s,o])if(L.existsSync(d))try{c.push(L.statSync(d).mtimeMs)}catch{}if(c.length)try{let d=L.statSync(l).mtimeMs;Math.max(...c)>d+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 Sa(){let r=vs();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 Ss(){let r=vn();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=q.join(n,"Gemfile");if(!L.existsSync(s))continue;let o=q.join(n,"Gemfile.lock"),i=q.join(n,"vendor","bundle"),a=q.join(n,".bundle"),l=L.existsSync(i)?i:L.existsSync(a)?a:null;if(!l){t.push({root:n,reason:"missing"});continue}if(L.existsSync(o))try{let c=L.statSync(o).mtimeMs,d=L.statSync(l).mtimeMs;c>d+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 ka(){let r=Ss();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 ks(){let r=vn();if(!r.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let n of r){let s=q.join(n,"Cargo.toml");if(!L.existsSync(s))continue;let o=q.join(n,"Cargo.lock"),i=q.join(n,"target");if(!L.existsSync(i)){t.push({root:n,reason:"missing"});continue}if(L.existsSync(o))try{let a=L.statSync(o).mtimeMs,l=L.statSync(i).mtimeMs;a>l+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 xa(){let r=ks();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 xs(){let r=et();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 Ta(){let r=xs();if(!r.detected||!r.dead||!r.dead.length)return"nothing to remove";let{local:t,user:e}=Nt(),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 o=new Set(r.dead),i=s.searchRoots.length;s.searchRoots=s.searchRoots.filter(c=>{let d=typeof c=="string"?c:c?.path;return!o.has(d)});let a=i-s.searchRoots.length;L.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
56
|
+
`,"utf8");let l=st();if(l)try{fetch(`http://127.0.0.1:${l.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${a} dead searchRoot entr${a===1?"y":"ies"} from ${n} (${[...o].join(", ")}); triggered soft-reload. To undo: edit ${n} and re-add the path(s).`}async function Ra(r){let t={ran:[],skipped:[],errors:[]};for(let e of ws){if(!r.permitted.includes(e))continue;let n=Pa[e],s;try{s=await n.detect()}catch(o){t.errors.push({name:e,error:o?.message??String(o)});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 o=await n.fix();t.ran.push({name:e,detected:!0,description:`${s.description} \u2014 ${o}`})}catch(o){t.errors.push({name:e,error:o?.message??String(o)})}}return t}var ws,Pa,Yt=F(()=>{"use strict";dt();Ft();he();se();ws=["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"];Pa={"orphan-daemon":{detect:aa,fix:ca},"stale-lock":{detect:la,fix:ua},"missing-search-root":{detect:pa,fix:da},"corrupt-history-db":{detect:fa,fix:ma},"port-conflict-pred":{detect:ha,fix:ga},"node-version-mismatch":{detect:ya,fix:wa},"orphan-node-modules":{detect:bs,fix:va},"orphan-venv":{detect:vs,fix:Sa},"orphan-bundler-cache":{detect:Ss,fix:ka},"orphan-cargo-target":{detect:ks,fix:xa},"dead-search-root":{detect:xs,fix:Ta}}});var Sn={};gt(Sn,{orchestrateProfile:()=>Ca});function Ts(r,t,e,n,s){let o=r.summary(t);if(!o)return!1;if(e==="serving")return o.status==="serving";if(e==="healthy")return o.status==="serving"&&o.health==="healthy";let i=Date.now()-n;return o.status==="serving"&&o.health==="healthy"&&i>=s}async function Ps(r,t,e,n,s){let o=Date.now();if(e!=="stable"){let l=await r.waitFor(t,e==="serving"?"serving":"healthy",n);return{reached:!l.timedOut,waitedMs:l.waitedMs}}let i=Date.now(),a=l=>{l?.app===t&&(i=Date.now())};r.on("event",a);try{for(;Date.now()-o<n;){if(Ts(r,t,e,i,s))return{reached:!0,waitedMs:Date.now()-o};await new Promise(l=>setTimeout(l,500))}return{reached:Ts(r,t,e,i,s),waitedMs:Date.now()-o}}finally{r.off("event",a)}}async function Ca(r,t,e){let n=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let o=s.filter(m=>r.summary(m)!=null),i=Array.from(new Set(o.flatMap(m=>fe(t.depends??{},m)))).filter(m=>r.summary(m)!=null),a=me(t.depends??{},i),l=[];for(let m of i){let f=r.summary(m);f&&(e.goal==="serving"&&f.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&f.status==="serving"&&f.health==="healthy")&&l.push(m)}if(e.dryRun){let m=i.filter(f=>!l.includes(f));return{profile:e.profile,goal:e.goal,perApp:m.map(f=>({name:f,reached:!1,tries:0})),totalMs:Date.now()-n,allReached:m.length===0,dryRun:!0,plannedOrder:a,alreadyHealthy:l}}let c=Math.max(5e3,Math.floor(e.timeoutMs/2)),d=e.stableMs??5e3,u=new Map;for(let m of i)u.set(m,{name:m,reached:!1,tries:0});for(let m of a)await Promise.all(m.map(async f=>{let g=r.summary(f);if(!g){u.set(f,{name:f,reached:!1,tries:0,error:"unknown app"});return}if(l.includes(f)){u.set(f,{name:f,reached:!0,tries:0});return}g.status!=="starting"&&g.status!=="compiling"&&g.status!=="serving"&&await r.start(f)})),await Promise.all(m.map(async f=>{if(u.get(f)?.reached)return;let g=await Ps(r,f,e.goal,c,d),T=u.get(f);T.tries=1,T.waitedMs=g.waitedMs,T.reached=g.reached,u.set(f,T)}));let y=[...u.values()].filter(m=>!m.reached);if(y.length>0){let{runAutoFix:m,ALL_AUTO_FIX:f}=await Promise.resolve().then(()=>(Yt(),zt)),g=t.doctor?.autoFix?.permitted??f,T=Math.max(5e3,e.timeoutMs-(Date.now()-n)),R=Math.max(5e3,Math.floor(T/Math.max(y.length,1))),v={ran:[]};try{v=await m({permitted:g,dryRun:!1})}catch{}let D=(v.ran??[]).map(O=>O.name);await Promise.all(y.map(async O=>{let w=u.get(O.name);w.tries=2;try{let E=await r.restart(O.name);E?.ok||(w.error=E?.error??"restart failed")}catch(E){w.error=E?.message??String(E)}let x=await Ps(r,O.name,e.goal,R,d);if(w.waitedMs=(w.waitedMs??0)+x.waitedMs,w.reached=x.reached,!w.reached){let E=r.errors(O.name)??[];w.stillFailing=E.slice(0,3).map(S=>({file:S.parsed?.file??null,line:S.parsed?.line??null,code:S.parsed?.code??null,tool:S.parsed?.tool??null,message:S.parsed?.message??S.message}))}w.fixed=D,u.set(O.name,w)}))}let b=[...u.values()],p=b.every(m=>m.reached),h={profile:e.profile,goal:e.goal,perApp:b,totalMs:Date.now()-n,allReached:p};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let m=e.budgetTokens,f=0,g=0;for(let T of b)if(T.stillFailing){let R=T.stillFailing.length*Ea;R>m?(f+=T.stillFailing.length,delete T.stillFailing):m-=R}for(;m<0||b.length*Aa>Math.max(m,e.budgetTokens/4);){let T=b.findIndex(R=>R.reached);if(T===-1)break;b.splice(T,1),g++}(f||g)&&(h._meta={omitted:{}},f&&(h._meta.omitted.stillFailing=f),g&&(h._meta.omitted.perApp=g))}return h}var Ea,Aa,kn=F(()=>{"use strict";re();Ea=60,Aa=25});import Oa from"node:http";import Na from"node:crypto";import _t from"node:fs";import ct from"node:path";import{fileURLToPath as $a}from"node:url";function xn(){let r=[ct.resolve($e,"dashboard","browser"),ct.resolve($e,"dashboard"),ct.resolve($e,"..","dist","dashboard","browser"),ct.resolve($e,"..","dist","dashboard")];for(let t of r)if(_t.existsSync(ct.join(t,"index.html")))return t;return null}function ae(r,t){try{if(!_t.statSync(t).isFile())return!1;let n=ct.extname(t).toLowerCase(),s=ja[n]??"application/octet-stream",o=_t.readFileSync(t);return r.writeHead(200,{"content-type":s,"content-length":o.length,"cache-control":n===".html"?"no-cache":"public, max-age=3600"}),r.end(o),!0}catch{return!1}}function k(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 Zt(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 Me(r,t){let e=(r.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function Da(r){return{name:r.name,status:r.status,port:r.port,health:r.health,errCount:r.errorCount,lastChangeMs:r.lastChangeMs??null}}function Vt(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 Tn(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 _a(r){if(!r)return{};if(/^\d{10,}$/.test(r))return{sinceTs:Number(r)};let t=Zt(r);return t!=null?{sinceMs:t}:{}}function La(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))Ia.test(s)&&(n[s]="***")}return t}function Pn(r){if(!r)return"";try{let t=_t.readFileSync(r);return Na.createHash("sha1").update(t).digest("hex")}catch{return""}}function Rs(r,t,e={}){let n=new Ee,s=Oa.createServer(async(o,i)=>{try{let a=new URL(o.url||"/","http://127.0.0.1"),l=o.method||"GET",c=a.pathname.replace(/\/$/,"").split("/").filter(Boolean),d=()=>{let h=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!h)return!0;let m=o.headers.authorization;return typeof m=="string"&&m.toLowerCase().startsWith("bearer ")&&m.slice(7).trim()===h?!0:(k(i,401,{error:"unauthorized"}),!1)};if(l==="POST"&&a.pathname==="/api/shutdown"){if(!d())return;k(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(l==="GET"){let p=e.getConfig(),h=Pn(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:h}),i.end(JSON.stringify({etag:h,config:La(p)}));return}if(l==="PATCH"&&e.patchConfig){if(!d())return;let p=o.headers["if-match"]?.trim(),h=Pn(e.configPath);if(!p||p!==h){k(i,412,{error:"etag mismatch",current:h});return}let m={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(T=>{let R=[];o.on("data",v=>R.push(v)),o.on("end",()=>{try{m=JSON.parse(Buffer.concat(R).toString("utf8"))}catch{}T()})});let f=e.patchConfig(m);if(!f.ok){k(i,400,{error:f.error});return}let g=Pn(e.configPath);try{let T=o.socket.remoteAddress||"127.0.0.1";ls(T,m,m,f.applied)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:g}),i.end(JSON.stringify({etag:g,applied:f.applied,addedApps:f.addedApps,removedApps:f.removedApps,restartRequired:f.restartRequired}));return}k(i,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&l==="GET"){k(i,200,ds());return}if(a.pathname==="/api/snapshot-state"&&l==="POST"){if(!d())return;let p=gs(r);k(i,200,{ok:!0,path:p});return}if(a.pathname==="/api/config/reload"&&l==="POST"&&e.reloadConfig){if(!d())return;try{let p=await e.reloadConfig();k(i,200,p)}catch(p){k(i,400,{error:p?.message||String(p)})}return}if(l==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let p=is(r);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(p)}),i.end(p);return}if(l!=="GET"&&a.pathname.startsWith("/api/")&&a.pathname!=="/api/shutdown"&&a.pathname!=="/api/config"&&a.pathname!=="/api/config/reload"&&!d())return;if(l==="GET"&&a.pathname==="/"){let p=xn();if(p&&ae(i,ct.join(p,"index.html")))return;i.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(c[0]==="api"&&c[1]==="events"&&c.length===2){if(l!=="GET"){k(i,405,{error:"method not allowed"});return}let p=Zt(a.searchParams.get("since")),h=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let g=r.events({sinceMs:p,app:h});for(let v of g)i.write(JSON.stringify(v)+`
|
|
57
|
+
`);let T=v=>{h&&v.app!==h||i.write(JSON.stringify(v)+`
|
|
58
|
+
`)};r.on("event",T);let R=setInterval(()=>{try{i.write(`
|
|
59
|
+
`)}catch{}},3e4);o.on("close",()=>{r.off("event",T),clearInterval(R);try{i.end()}catch{}});return}let m=r.events({sinceMs:p,app:h}),f=r.getHistory();if(f&&p&&m.length<500){let g=Date.now()-p,T=f.queryEvents({app:h,since:g,limit:1e3}),R=new Set(m.map(v=>`${v.ts}|${v.app}|${v.type}|${v.from??""}|${v.to??""}|${v.message??""}`));for(let v of T){let D=`${v.ts}|${v.app}|${v.type}|${v.from_state??""}|${v.to_state??""}|${v.message??""}`;R.has(D)||m.push({ts:v.ts,app:v.app,type:v.type,from:v.from_state??void 0,to:v.to_state??void 0,message:v.message??void 0})}m.sort((v,D)=>v.ts-D.ts)}k(i,200,m);return}if(c[0]==="api"&&c[1]==="session"){if(c[2]==="record"&&l==="POST"){let p=a.searchParams.get("action")||"toggle";if(p==="start"||p==="toggle"&&!r.sessionRecorder.isRecording()){let h=r.sessionRecorder.start();k(i,200,{recording:!0,path:h.path});return}if(p==="stop"||p==="toggle"&&r.sessionRecorder.isRecording()){let h=r.sessionRecorder.stop();k(i,200,{recording:!1,path:h.path});return}k(i,400,{error:"invalid action"});return}if(c[2]==="status"&&l==="GET"){k(i,200,{recording:r.sessionRecorder.isRecording()});return}k(i,404,{error:"not found"});return}if(c[0]==="api"&&c[1]==="history"){if(l!=="GET"){k(i,405,{error:"method not allowed"});return}let p=r.getHistory();if(!p){k(i,200,[]);return}let h=c[2],m=a.searchParams.get("app")||void 0,f=a.searchParams.get("since"),g=a.searchParams.get("until"),T=a.searchParams.get("limit"),R=f?/^\d{10,}$/.test(f)?Number(f):Date.now()-(Zt(f)??0):void 0,v=g?/^\d{10,}$/.test(g)?Number(g):Date.now()-(Zt(g)??0):void 0,D=T?Number(T):void 0;if(h==="events"){k(i,200,p.queryEvents({app:m,since:R,until:v,type:a.searchParams.get("type")||void 0,limit:D}));return}if(h==="compile-times"){k(i,200,p.queryCompiles({app:m,since:R,until:v,limit:D}));return}if(h==="tasks"){k(i,200,p.queryTasks({app:m,task:a.searchParams.get("task")||void 0,since:R,limit:D}));return}if(h==="bundles"){k(i,200,p.queryBundles({app:m,since:R,until:v,limit:D}));return}if(h==="trends"){let O=a.searchParams.get("metric")||"compile";if(!["compile","bundle","errors","restarts"].includes(O)){k(i,400,{error:"metric must be compile|bundle|errors|restarts"});return}let w=(a.searchParams.get("since")||"24h").toLowerCase(),x={"24h":24*3600*1e3,"7d":7*86400*1e3,"30d":30*86400*1e3},E=x[w]??x["24h"],S=w==="24h"?3600*1e3:86400*1e3,{points:_,count:W}=p.trends({app:m,metric:O,sinceMs:E,bucketMs:S});k(i,200,{app:m??null,metric:O,since:w,points:_,_meta:{aggregation:w==="24h"?"hour":"day",count:W}});return}if(h==="summary"&&c.length>=4){let O=decodeURIComponent(c[3]);k(i,200,p.summary(O));return}if(h==="why"&&c.length>=4){let O=decodeURIComponent(c[3]);k(i,200,p.why(O));return}k(i,404,{error:"not found"});return}if(c[0]==="api"&&c[1]==="profiles"&&c[3]==="ensure-up"&&l==="POST"){let p=decodeURIComponent(c[2]),h=e.getConfig?.(),m=h?.profiles?.[p];if(!m){k(i,404,{error:"unknown profile"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){k(i,400,{error:"until must be serving|healthy"});return}let g=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),T=g?Number(g):3e5;(!Number.isFinite(T)||T<=0)&&(T=3e5),T=Math.min(T,12e5);let R=h?.healthProbe?.enabled??!0,v=f==="healthy"&&!R?"serving":f,D=Date.now();for(let w of m){let x=r.summary(w);x&&x.status!=="serving"&&x.status!=="starting"&&x.status!=="compiling"&&await r.startWithDeps(w)}let O=await Promise.all(m.map(async w=>{let x=Math.max(1e3,T-(Date.now()-D));if(!r.summary(w))return{name:w,state:null,until:v,reachedTargetMs:null,timedOut:!1,error:"unknown"};let S=await r.waitFor(w,v,x),_=r.summary(w);return{name:w,state:_?Vt(_):null,until:v,reachedTargetMs:S.timedOut?null:S.waitedMs,timedOut:S.timedOut}}));k(i,200,{profile:p,apps:O,_meta:{totalMs:Date.now()-D,until:v}});return}if(c[0]==="api"&&c[1]==="orchestrate"&&l==="POST"){let p=e.getConfig?.();if(!p){k(i,500,{error:"no config loaded"});return}let h=a.searchParams.get("profile");if(!h){k(i,400,{error:"profile query param required"});return}let m=(a.searchParams.get("goal")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(m)){k(i,400,{error:"goal must be serving|healthy|stable"});return}let f=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),g=f?Number(f):3e5;(!Number.isFinite(g)||g<=0)&&(g=3e5),g=Math.min(g,12e5);let T=a.searchParams.get("dryRun")==="true"||a.searchParams.get("dry-run")==="true",R=a.searchParams.get("budget"),v=R&&Number.isFinite(Number(R))?Number(R):void 0,{orchestrateProfile:D}=await Promise.resolve().then(()=>(kn(),Sn)),O=await D(r,p,{profile:h,goal:m,timeoutMs:g,dryRun:T,budgetTokens:v});if(O.error){k(i,404,O);return}k(i,200,O);return}if(c[0]==="api"&&c[1]==="discovery"&&c[2]==="explain"&&l==="GET"){let p=e.getConfig?.();if(!p){k(i,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:h}=await Promise.resolve().then(()=>(Ut(),en)),m={scanned:0,rejected:{}},f=[],g=h(p,{warnings:f,stats:m}),T=p.searchRoots.map(O=>typeof O=="string"?O:O.path),R=g.filter(O=>O.workspaceType==="polyglot"),v=g.map(O=>({name:O.name,workspaceType:O.workspaceType,serverProfile:O.serverProfile??O.workspaceType,workspaceRoot:O.workspaceRoot})),D=R.length>0?` \xB7 ${R.length} polyglot app${R.length===1?"":"s"} found (${[...new Set(R.map(O=>O.serverProfile))].join(", ")})`:"";k(i,200,{searchRoots:T,scanned:m.scanned,rejected:m.rejected,warnings:f,appsFound:g.length,apps:v,suggestion:g.length===0?T.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${D}`});return}if(c[0]==="api"&&c[1]==="doctor"&&c[2]==="auto-fix"&&l==="POST"){if(!d())return;let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(R=>{let v=[];o.on("data",D=>v.push(D)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(v).toString("utf8"))}catch{}R()})});let{runAutoFix:h,ALL_AUTO_FIX:m}=await Promise.resolve().then(()=>(Yt(),zt)),g=e.getConfig?.()?.doctor?.autoFix?.permitted??m,T=Array.isArray(p.permitted)&&p.permitted.length?p.permitted:g;try{let R=await h({permitted:T,dryRun:!!p.dryRun});k(i,200,R)}catch(R){k(i,500,{error:R?.message??String(R)})}return}if(c[0]==="api"&&c[1]==="overview"&&l==="GET"){let p=e.getConfig?.(),h=r.list(),m=a.searchParams.get("workspace"),f=a.searchParams.get("profile"),g=h;if(m&&(g=g.filter(S=>S.workspaceLabel===m)),f){let S=p?.profiles?.[f]??null;S&&(g=g.filter(_=>S.includes(_.name)))}let T={apps:g.length,serving:g.filter(S=>S.status==="serving").length,errors:g.filter(S=>S.status==="error").length,stopped:g.filter(S=>S.status==="stopped").length,totalErrCount:g.reduce((S,_)=>S+_.errorCount,0),totalCpuPct:Math.round(g.reduce((S,_)=>S+(_.cpu??0),0)*10)/10,totalMemMb:Math.round(g.reduce((S,_)=>S+(_.memMB??0),0))},R={};for(let S of g)(R[S.status]??=[]).push(S.name);let v=g.filter(S=>S.status==="error"||S.errorCount>0).map(S=>{let _=r.errors(S.name)??[],W=_[_.length-1],I=W?.parsed;return{name:S.name,status:S.status,errCount:S.errorCount,firstError:I?{file:I.file??null,line:I.line??null,code:I.code??null,message:I.message??W?.message??""}:W?{file:null,line:null,code:null,message:W.message}:null}}),D=Date.now()-5*6e4,O=r.events({sinceMs:5*6e4}).filter(S=>S.type==="status"&&S.ts>=D).filter(S=>m?g.some(_=>_.name===S.app):!0).filter(S=>f?g.some(_=>_.name===S.app):!0).slice(-5).map(S=>({name:S.app,transition:`${S.from??"?"}\u2192${S.to??"?"}`,msAgo:Date.now()-S.ts})),w={ts:Date.now(),version:nt,totals:T,byStatus:R,needsAttention:v,recentlyChanged:O};T.apps===0&&(w._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let x=a.searchParams.get("budget"),E=x?Math.max(64,Number(x)|0):null;if(E){let S=E*4,_=0,W=0;for(;JSON.stringify(w).length>S&&(w.needsAttention.length||w.recentlyChanged.length);)if(w.needsAttention.length>1)w.needsAttention.pop(),_++;else if(w.recentlyChanged.length)w.recentlyChanged.pop(),W++;else if(w.needsAttention.length===1)w.needsAttention.pop(),_++;else break;_||W?w._meta={...w._meta??{},budget:E,omitted:{needsAttention:_,recentlyChanged:W}}:w._meta={...w._meta??{},budget:E}}k(i,200,w);return}if(c[0]!=="api"||c[1]!=="apps"){if(l==="GET"&&!a.pathname.startsWith("/metrics")){let p=xn();if(p){let h=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(h){let m=ct.resolve(p,h);if(m.startsWith(p)&&ae(i,m))return}if(!ct.extname(h||"")&&ae(i,ct.join(p,"index.html")))return}}k(i,404,{error:"not found"});return}if(c.length===2){if(l!=="GET"){k(i,405,{error:"method not allowed"});return}let p=Me(a,e.getConfig),h=r.list(),m=p==="full"?h:h.map(Da);if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let f of m)i.write(JSON.stringify(f)+`
|
|
60
|
+
`);i.end();return}if(a.searchParams.get("explain")==="1"){let f=e.getConfig?.(),g={format:p};if(f){let{discoverApps:T}=await Promise.resolve().then(()=>(Ut(),en)),R={scanned:0,rejected:{}},v=[];T(f,{warnings:v,stats:R});let D=f.searchRoots.map(O=>typeof O=="string"?O:O.path);g={format:p,searchRoots:D,scanned:R.scanned,rejected:R.rejected,warnings:v,suggestion:m.length===0?D.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."}}k(i,200,{apps:m,_meta:g});return}k(i,200,m);return}let u=decodeURIComponent(c[2]),y=c[3],b=c[4];if(!y){if(l!=="GET"){k(i,405,{error:"method not allowed"});return}let p=r.summary(u);if(!p){k(i,404,{error:"unknown app"});return}Me(a,e.getConfig)==="full"?k(i,200,{...p,_meta:{format:"full"}}):k(i,200,{...Vt(p),_meta:{format:"compact"}});return}if(y==="errors"&&b==="since-last"&&l==="GET"){let p=a.searchParams.get("client")||"default",h=n.getErrorCursor(p,u),m=r.errorsSince(u,h);if(m==null){k(i,404,{error:"unknown app"});return}let f=m.reduce((T,R)=>Math.max(T,R.lastSeen),h);f>h&&n.setErrorCursor(p,u,f);let g=Me(a,e.getConfig);k(i,200,g==="full"?m:m.map(Tn));return}if(y==="errors"&&!b&&l==="GET"){let p=a.searchParams.get("since"),h=Me(a,e.getConfig);if(p){let{sinceMs:f,sinceTs:g}=_a(p),T=g??(f!=null?Date.now()-f:0),R=r.errorsSince(u,T);if(R==null){k(i,404,{error:"unknown app"});return}k(i,200,h==="full"?R:R.map(Tn));return}let m=r.errors(u);if(m==null){k(i,404,{error:"unknown app"});return}k(i,200,h==="full"?m:m.map(Tn));return}if(y==="logs"&&c[4]==="stream"&&l==="GET"){if(!r.summary(u)){k(i,404,{error:"unknown app"});return}i.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let p=r.logs(u,{tail:50})??[];for(let R of p)i.write(`data: ${JSON.stringify({ts:Date.now(),line:R})}
|
|
51
61
|
|
|
52
|
-
`);let h=[],
|
|
62
|
+
`);let h=[],m=0,f=()=>{for(;h.length&&i.write(h.shift()););},g=R=>{R.name===u&&(h.length>=200&&(m++,h.shift()),h.push(`data: ${JSON.stringify({ts:R.ts,line:R.line})}
|
|
53
63
|
|
|
54
|
-
`),
|
|
64
|
+
`),f())};r.on("log",g);let T=setInterval(()=>i.write(`: ping
|
|
55
65
|
|
|
56
|
-
`),3e4);o.on("close",()=>{r.off("log",w),clearInterval(T)});return}if(y==="logs"&&l==="GET"){let u=a.searchParams.get("tail"),h=a.searchParams.get("since"),g=r.logs(p,{tail:u?Number(u):void 0,sinceMs:It(h)});if(g==null){k(i,404,{error:"unknown app"});return}k(i,200,{lines:g});return}if(y==="wait"&&l==="GET"){if(!r.summary(p)){k(i,404,{error:"unknown app"});return}let u=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(u)){k(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let h=a.searchParams.get("timeout"),g=h?Number(h):120;(!Number.isFinite(g)||g<=0)&&(g=120),g=Math.min(g,600);let m=await r.waitFor(p,u,g*1e3);k(i,200,m);return}if(y==="ensure"&&l==="POST"){let u=r.summary(p);if(!u){k(i,404,{error:"unknown app"});return}let h=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(h)){k(i,400,{error:"until must be serving|healthy"});return}let g=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),m=g?Number(g):18e4;(!Number.isFinite(m)||m<=0)&&(m=18e4),m=Math.min(m,6e5);let w=e.getConfig?.().healthProbe?.enabled??!0,T=h,C;if(T==="healthy"&&!w&&(T="serving",C="no health probe; treated serving as terminal"),T==="serving"&&u.status==="serving"||T==="healthy"&&u.status==="serving"&&u.health==="healthy"){k(i,200,{...ye(u),_meta:{format:"compact",startedFromState:null,warning:C,waitedMs:0}});return}let j=u.status;u.status!=="starting"&&u.status!=="compiling"&&await r.start(p);let _=await r.waitFor(p,T,m),v=r.summary(p),f=v?ye(v):{name:p,status:_.status,port:null,url:null,health:_.health,errCount:0,lastChangeMs:null,uptime:null};if(_.timedOut){k(i,200,{error:"timeout",state:f,_meta:{format:"compact",startedFromState:j,warning:C,waitedMs:_.waitedMs,timedOut:!0}});return}k(i,200,{...f,_meta:{format:"compact",startedFromState:j,warning:C,waitedMs:_.waitedMs}});return}if(y==="start"&&l==="POST"){if(a.searchParams.get("withDeps")==="1"){let g=await r.startWithDeps(p);k(i,g.ok?200:400,g);return}let h=await r.start(p);k(i,h.ok?200:400,h);return}if(y==="start-with-deps"&&l==="POST"){let u=await r.startWithDeps(p);k(i,u.ok?200:400,u);return}if(y==="tasks"&&l==="GET"&&!S){let u=r.listTasks(p);if(u==null){k(i,404,{error:"unknown app"});return}k(i,200,{tasks:u,watching:r.listWatchTasks(p)});return}if(y==="run"&&S&&l==="POST"){let u={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(m=>{let w=[];o.on("data",T=>w.push(T)),o.on("end",()=>{try{u=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}m()})});let h=Array.isArray(u.args)?u.args.map(String):[];if(u.watch){let m=r.startWatchTask(p,S,h);k(i,m.ok?200:400,m);return}let g=await r.runTask(p,S,h);if("error"in g){k(i,404,g);return}k(i,200,g);return}if(y==="run-stop"&&S&&l==="POST"){let u=await r.stopWatchTask(p,S);k(i,200,u);return}if(y==="env"&&l==="GET"){let h=r.getConfig().envFiles?.[p]??[],g=r.getState(p);k(i,200,{candidates:h,active:g?.activeEnvFile??null});return}if(y==="env"&&l==="POST"){let u={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(g=>{let m=[];o.on("data",w=>m.push(w)),o.on("end",()=>{try{u=JSON.parse(Buffer.concat(m).toString("utf8"))}catch{}g()})}),r.setActiveEnvFile(p,u.use??null);let h=r.getState(p);k(i,200,{active:h?.activeEnvFile??null});return}if(y==="requests"&&l==="GET"){if(!e.requestLog){k(i,200,[]);return}let u=It(a.searchParams.get("since"));k(i,200,e.requestLog.requests(p,u));return}if(y==="clean"&&l==="POST"){let u=a.searchParams.get("deep")==="1",h=a.searchParams.get("yes")==="1",g=Ze(r,p,u);if(!g){k(i,404,{error:"unknown app"});return}if(g.ranOnServing){k(i,409,{error:"refusing: app is currently running",plan:g});return}if(!h){k(i,200,{plan:g,hint:"pass --yes to delete"});return}let m=jr(r,p,u);k(i,200,m);return}if(y==="snapshot"&&l==="POST"){if(a.searchParams.get("write")==="1"){let g=Rr(r,p);if(!g){k(i,404,{error:"unknown app"});return}k(i,200,{snapshot:g.path});return}let h=Qe(r,p);if(!h){k(i,404,{error:"unknown app"});return}k(i,200,h);return}if(y==="stop"&&l==="POST"){let u=await r.stop(p);k(i,u.ok?200:400,u);return}if(y==="restart"&&l==="POST"){let u=await r.restart(p);k(i,u.ok?200:400,u);return}if(l==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let u=rn();if(u){let h=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(h){let g=Y.resolve(u,h);if(g.startsWith(u)&&qt(i,g))return}if(!Y.extname(h||"")&&qt(i,Y.join(u,"index.html")))return}}k(i,404,{error:"not found"})}catch(a){k(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}var Ai,he,Ei,Oi,Yr=$(()=>{"use strict";Ar();Or();Dr();Ir();Fr();Hr();tn();Nt();Ai=Ci(import.meta.url),he=Y.dirname(Ai);Ei={".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"};Oi=/key|secret|token|password|pass/i});import $i from"node:http";import ji from"node:https";function Ii(r,t,e,n,s){if(t)return[t];let o=r.path||"/",i=r.fallbackHosts&&r.fallbackHosts.length?r.fallbackHosts:["127.0.0.1"];if(r.host||r.scheme){let l=e?ve(e):null,c=r.scheme||l?.protocol?.replace(":","")||"http",d=r.host||l?.hostname||(n?i[0]:"127.0.0.1"),p=n??(l?.port?Number(l.port):null);return[zr(c,d,p,o)]}if(e){let l=ve(e);if(l)return l.pathname=o,[l.toString()]}let a=[];s&&a.push(s);for(let l of i)a.includes(l)||a.push(l);return a.map(l=>zr("http",l,n,o))}function ve(r){try{return new URL(r)}catch{return null}}function zr(r,t,e,n){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${r}://${s}${o}${n.startsWith("/")?n:"/"+n}`}var Di,Mi,be,Vr=$(()=>{"use strict";Di=1e3,Mi=500;be=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)},Mi);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=Ii(this.cfg,n,e.announcedUrl,e.port,e.cachedProbeHost);if(s.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let o=null;for(let a of s){let l=await this.tryProbe(a);if(l.ok){let c=ve(a);c&&this.registry.setCachedProbeHost(t,c.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,a),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}o||(o=`${l.error} ${a}`)}let i=this.freshness.get(t);if(i&&!i.retried){i.retried=!0,setTimeout(()=>{this.probe(t)},Di);return}this.registry.setLastHealthError(t,o||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}tryProbe(t){return new Promise(e=>{let n=!1,s=l=>{n||(n=!0,e(l))},o=t.startsWith("https://"),i=o?ji:$i,a={timeout:this.cfg.timeoutMs};if(o){let c=ve(t)?.hostname?.replace(/^\[|\]$/g,"")??"",d=c==="127.0.0.1"||c==="::1"||c==="localhost";a.rejectUnauthorized=d?!1:!!this.cfg.rejectUnauthorized}try{let l=i.get(t,a,c=>{let d=c.statusCode??0;c.resume(),d>=200&&d<500?s({ok:!0}):s({ok:!1,error:`http ${d}`})});l.on("timeout",()=>l.destroy(new Error("timeout"))),l.on("error",c=>s({ok:!1,error:c?.code||c?.message||"error"}))}catch(l){s({ok:!1,error:l?.message||"throw"})}})}}});import Li from"pidusage";var Se,Qr=$(()=>{"use strict";Se=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 o=await Li(s),i=this.registry.getState(n);if(!i)return;let a=Math.round(o.cpu*10)/10,l=Math.round(o.memory/(1024*1024));(i.cpu!==a||i.memMB!==l)&&(i.cpu=a,i.memMB=l,e=!0)}catch{let o=this.registry.getState(n);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}}});var ke,Zr=$(()=>{"use strict";ke=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 o=this.registry.getState(t);if(!o)return;let i=Date.now();if((o.restartWindowStart==null||i-o.restartWindowStart>this.cfg.windowMs)&&(o.restartWindowStart=i,o.restartAttempts=0),o.restartAttempts+=1,o.restartAttempts>this.cfg.maxAttempts){o.lastStatusMessage=`auto-restart aborted (${o.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,o.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(o.restartAttempts-1)*1e3,3e4);o.nextRestartAt=i+a,o.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${o.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");let l=setTimeout(()=>{this.timers.delete(t);let c=this.registry.getState(t);c&&(c.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,l)}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 ln from"node:fs";import ts from"node:path";import _i from"node:os";function es(){try{let r=ln.readFileSync(un,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function ns(r){cn=r,!an&&(an=setTimeout(()=>{an=null;let t=cn;if(cn=null,!!t)try{ln.mkdirSync(ts.dirname(un),{recursive:!0}),ln.writeFileSync(un,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
57
|
-
`)}}
|
|
58
|
-
|
|
59
|
-
`))}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 o=`${t}::${e}`,i=this.lastSent.get(o)??0,a=Date.now();if(a-i<Hi){this.audit("throttled",`${o}`);return}this.lastSent.set(o,a);let l={title:`daimon: ${n}`,message:s,wait:!1,appID:"daimon"},c=(d,p)=>{d?(this.audit("fail",`${o} :: ${d?.message||d}`),this.warnOnce(`notify failed: ${d?.message||d}`)):this.audit("ok",`${o} :: ${n} :: ${p??"(no response)"}`)};try{this.audit("attempt",`${o} :: ${n}`),(this.toaster??this.notifier).notify(l,c)}catch(d){this.audit("throw",`${o} :: ${d?.message||d}`),this.warnOnce(`notify threw: ${d?.message||d}`)}}}});import as from"node:fs";import pn from"node:path";var Ji,Wi,Gi,qi,Te,cs=$(()=>{"use strict";Ji=5e3,Wi=3e4,Gi=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),qi=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),Te=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),Ji),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,o=Date.now()-s;if(o<this.cfg.silentMs){e.stale&&this.registry.setStale(t,!1);return}let i=e.lastCompileAt??e.startedAt;this.hasSourceChange(n.workspaceRoot,i,e.lastCompileAt)&&(e.stale||(this.registry.setStale(t,!0),this.registry.recordEvent({app:t,type:"stale",message:`no output in ${Math.round(o/1e3)}s despite source changes`})))}hasSourceChange(t,e,n){let s=this.caches.get(t);if(!s||Date.now()-s.ts>Wi||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,o)=>{if(o>8||e.length>4e3)return;let i;try{i=as.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of i)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(Gi.has(a.name))continue;n(pn.join(s,a.name),o+1)}else if(a.isFile()){let l=pn.extname(a.name);if(!qi.has(l))continue;try{let c=pn.join(s,a.name),d=as.statSync(c);e.push({path:c,mtime:d.mtimeMs})}catch{}}}};return n(t,0),e}}});import ls from"node:http";var Ce,Ae,us=$(()=>{"use strict";Ce=200,Ae=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=[],o=ls.createServer((i,a)=>{let l=Date.now(),c={hostname:"127.0.0.1",port:e,method:i.method,path:i.url,headers:{...i.headers,host:`127.0.0.1:${e}`}},d=ls.request(c,p=>{a.writeHead(p.statusCode||502,p.headers),p.pipe(a);let y=()=>{s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:p.statusCode||0,durationMs:Date.now()-l}),s.length>Ce&&s.splice(0,s.length-Ce)};p.on("end",y),p.on("error",y)});d.on("error",()=>{a.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:502,durationMs:Date.now()-l}),s.length>Ce&&s.splice(0,s.length-Ce)}),i.pipe(d)});o.on("error",i=>{i?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${n} in use for ${t}; disabling proxy
|
|
60
|
-
`),
|
|
61
|
-
|
|
62
|
-
`))}catch{}return s}
|
|
66
|
+
`),3e4);o.on("close",()=>{r.off("log",g),clearInterval(T)});return}if(y==="logs"&&l==="GET"){let p=a.searchParams.get("tail"),h=a.searchParams.get("since"),m=r.logs(u,{tail:p?Number(p):void 0,sinceMs:Zt(h)});if(m==null){k(i,404,{error:"unknown app"});return}k(i,200,{lines:m});return}if(y==="focus"&&l==="POST"){let p=r.summary(u);if(!p){k(i,404,{error:"unknown app"});return}let h=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(h)){k(i,400,{error:"until must be one of serving|healthy|stable"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=m?Number(m):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let g=a.searchParams.get("stableMs"),T=g&&Number.isFinite(Number(g))?Math.max(1e3,Number(g)):5e3;i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache",connection:"keep-alive"});let R=I=>{try{i.write(JSON.stringify(I)+`
|
|
67
|
+
`)}catch{}};R({kind:"subscribed",app:u,until:h,ts:Date.now(),state:Vt(p)});let v=Date.now(),D=Date.now(),O=!1,w=I=>{if(O)return;O=!0,r.off("event",E),clearInterval(S),clearInterval(_),clearTimeout(W);let Z=r.summary(u);R({kind:"done",reason:I,ts:Date.now(),state:Z?Vt(Z):null,waitedMs:Date.now()-v});try{i.end()}catch{}},x=()=>{let I=r.summary(u);if(!I)return!1;if(h==="serving")return I.status==="serving";if(h==="healthy")return I.status==="serving"&&I.health==="healthy";if(h==="stable"){let Z=Date.now()-D;return I.status==="serving"&&I.health==="healthy"&&Z>=T}return!1},E=I=>{if(I.app===u)if(D=Date.now(),I.type==="status")R({kind:"status",from:I.from,to:I.to,ts:I.ts}),h!=="stable"&&x()&&w("reached");else if(I.type==="error-new"||I.type==="error-recur"){let G=(r.errors(u)??[])[0];G&&R({kind:"error",message:G.message,parsed:G.parsed??null,ts:I.ts})}else I.type==="health"&&(R({kind:"health",from:I.from,to:I.to,ts:I.ts}),h!=="stable"&&x()&&w("reached"))};r.on("event",E);let S=setInterval(()=>{x()&&w("reached")},1e3),_=setInterval(()=>{try{i.write(`
|
|
68
|
+
`)}catch{}},3e4),W=setTimeout(()=>w("timeout"),f);o.on("close",()=>w("closed")),x()&&w("reached");return}if(y==="health"&&b==="pin"&&l==="POST"){let p=r.getState(u);if(!p){k(i,404,{error:"unknown app"});return}let h={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(O=>{let w=[];o.on("data",x=>w.push(x)),o.on("end",()=>{try{h=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}O()})});let m=typeof h.path=="string"&&h.path?h.path:p.discoveredHealthPath??null;if(!m){k(i,400,{error:"no path supplied and no discoveredHealthPath on app"});return}let{configLookupPaths:f}=await Promise.resolve().then(()=>(Ft(),Yn)),{local:g,user:T}=f(),R=_t.existsSync(g)?g:T,v={};try{v=JSON.parse(_t.readFileSync(R,"utf8"))}catch{}(!v.overrides||typeof v.overrides!="object")&&(v.overrides={}),(!v.overrides[u]||typeof v.overrides[u]!="object")&&(v.overrides[u]={});let D=v.overrides[u].healthProbePath??null;if(v.overrides[u].healthProbePath=m,_t.writeFileSync(R,JSON.stringify(v,null,2)+`
|
|
69
|
+
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}k(i,200,{pinned:m,app:u,configPath:R,previous:D});return}if(y==="try-fix"&&l==="POST"){let p=r.summary(u);if(!p){k(i,404,{error:"unknown app"});return}let h=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(h)){k(i,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=m?Number(m):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let g={status:p.status,health:p.health,errCount:p.errorCount,firstError:(r.errors(u)??[])[0]?.parsed??null},{runAutoFix:T,ALL_AUTO_FIX:R}=await Promise.resolve().then(()=>(Yt(),zt)),D=e.getConfig?.()?.doctor?.autoFix?.permitted??R,O={ran:[],skipped:[],errors:[]};try{O=await T({permitted:D,dryRun:!1})}catch(G){O.errors.push({name:"auto-fix",error:G?.message??String(G)})}let w=(O.ran??[]).map(G=>G.name),x=null;try{let G=await r.restart(u);G?.ok||(x=G?.error??"restart failed")}catch(G){x=G?.message??String(G)}let E=await r.waitFor(u,h,f),S=r.summary(u),W=(r.errors(u)??[]).slice(0,5).map(G=>({file:G.parsed?.file??null,line:G.parsed?.line??null,code:G.parsed?.code??null,tool:G.parsed?.tool??null,message:G.parsed?.message??G.message})),I=S?{status:S.status,health:S.health,errCount:S.errorCount}:{status:E.status,health:E.health,errCount:0},Z=h==="serving"&&I.status==="serving"||h==="healthy"&&I.status==="serving"&&I.health==="healthy";k(i,200,{before:g,after:I,fixed:w,stillFailing:W,reached:Z,waitedMs:E.waitedMs,_meta:{autoFix:O,restartErr:x,timedOut:E.timedOut}});return}if(y==="wait"&&l==="GET"){if(!r.summary(u)){k(i,404,{error:"unknown app"});return}let p=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(p)){k(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let h=a.searchParams.get("timeout"),m=h?Number(h):120;(!Number.isFinite(m)||m<=0)&&(m=120),m=Math.min(m,600);let f=await r.waitFor(u,p,m*1e3);k(i,200,f);return}if(y==="ensure"&&l==="POST"){let p=r.summary(u);if(!p){k(i,404,{error:"unknown app"});return}let h=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(h)){k(i,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=m?Number(m):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let g=e.getConfig?.().healthProbe?.enabled??!0,T=h,R;if(T==="healthy"&&!g&&(T="serving",R="no health probe; treated serving as terminal"),T==="serving"&&p.status==="serving"||T==="healthy"&&p.status==="serving"&&p.health==="healthy"){k(i,200,{...Vt(p),_meta:{format:"compact",startedFromState:null,warning:R,waitedMs:0}});return}let D=p.status;p.status!=="starting"&&p.status!=="compiling"&&await r.start(u);let O=await r.waitFor(u,T,f),w=r.summary(u),x=w?Vt(w):{name:u,status:O.status,port:null,url:null,health:O.health,errCount:0,lastChangeMs:null,uptime:null};if(O.timedOut){k(i,200,{error:"timeout",state:x,_meta:{format:"compact",startedFromState:D,warning:R,waitedMs:O.waitedMs,timedOut:!0}});return}k(i,200,{...x,_meta:{format:"compact",startedFromState:D,warning:R,waitedMs:O.waitedMs}});return}if(y==="start"&&l==="POST"){if(a.searchParams.get("withDeps")==="1"){let m=await r.startWithDeps(u);k(i,m.ok?200:400,m);return}let h=await r.start(u);k(i,h.ok?200:400,h);return}if(y==="start-with-deps"&&l==="POST"){let p=await r.startWithDeps(u);k(i,p.ok?200:400,p);return}if(y==="tasks"&&l==="GET"&&!b){let p=r.listTasks(u);if(p==null){k(i,404,{error:"unknown app"});return}k(i,200,{tasks:p,watching:r.listWatchTasks(u)});return}if(y==="run"&&b&&l==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(f=>{let g=[];o.on("data",T=>g.push(T)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(g).toString("utf8"))}catch{}f()})});let h=Array.isArray(p.args)?p.args.map(String):[];if(p.watch){let f=r.startWatchTask(u,b,h);k(i,f.ok?200:400,f);return}let m=await r.runTask(u,b,h);if("error"in m){k(i,404,m);return}k(i,200,m);return}if(y==="run-stop"&&b&&l==="POST"){let p=await r.stopWatchTask(u,b);k(i,200,p);return}if(y==="env"&&l==="GET"){let h=r.getConfig().envFiles?.[u]??[],m=r.getState(u);k(i,200,{candidates:h,active:m?.activeEnvFile??null});return}if(y==="env"&&l==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(m=>{let f=[];o.on("data",g=>f.push(g)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(f).toString("utf8"))}catch{}m()})}),r.setActiveEnvFile(u,p.use??null);let h=r.getState(u);k(i,200,{active:h?.activeEnvFile??null});return}if(y==="requests"&&l==="GET"){if(!e.requestLog){k(i,200,[]);return}let p=Zt(a.searchParams.get("since"));k(i,200,e.requestLog.requests(u,p));return}if(y==="clean"&&l==="POST"){let p=a.searchParams.get("deep")==="1",h=a.searchParams.get("yes")==="1",m=wn(r,u,p);if(!m){k(i,404,{error:"unknown app"});return}if(m.ranOnServing){k(i,409,{error:"refusing: app is currently running",plan:m});return}if(!h){k(i,200,{plan:m,hint:"pass --yes to delete"});return}let f=ss(r,u,p);k(i,200,f);return}if(y==="snapshot"&&l==="POST"){if(a.searchParams.get("write")==="1"){let m=ts(r,u);if(!m){k(i,404,{error:"unknown app"});return}k(i,200,{snapshot:m.path});return}let h=yn(r,u);if(!h){k(i,404,{error:"unknown app"});return}k(i,200,h);return}if(y==="stop"&&l==="POST"){let p=await r.stop(u);k(i,p.ok?200:400,p);return}if(y==="restart"&&l==="POST"){let p=await r.restart(u);k(i,p.ok?200:400,p);return}if(l==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let p=xn();if(p){let h=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(h){let m=ct.resolve(p,h);if(m.startsWith(p)&&ae(i,m))return}if(!ct.extname(h||"")&&ae(i,ct.join(p,"index.html")))return}}k(i,404,{error:"not found"})}catch(a){k(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}var Ma,$e,ja,Ia,Es=F(()=>{"use strict";Vr();es();os();as();us();fs();bn();Gt();Ma=$a(import.meta.url),$e=ct.dirname(Ma);ja={".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"};Ia=/key|secret|token|password|pass/i});import Fa from"node:http";import Ba from"node:https";function As(r,t,e,n,s){if(t)return[t];let o=r.path||"/",i=r.fallbackHosts&&r.fallbackHosts.length?r.fallbackHosts:["127.0.0.1"];if(r.host||r.scheme){let l=e?je(e):null,c=r.scheme||l?.protocol?.replace(":","")||"http",d=r.host||l?.hostname||(n?i[0]:"127.0.0.1"),u=n??(l?.port?Number(l.port):null);return[Cs(c,d,u,o)]}if(e){let l=je(e);if(l)return l.pathname=o,[l.toString()]}let a=[];s&&a.push(s);for(let l of i)a.includes(l)||a.push(l);return a.map(l=>Cs("http",l,n,o))}function je(r){try{return new URL(r)}catch{return null}}function Cs(r,t,e,n){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${r}://${s}${o}${n.startsWith("/")?n:"/"+n}`}var Ua,Ha,Ja,De,Os=F(()=>{"use strict";Ua=1e3,Ha=500,Ja=["/","/health","/-/health","/api/health","/ready","/healthz"];De=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)},Ha);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,o=this.cfg;s?o={...this.cfg,path:s}:e.discoveredHealthPath&&(o={...this.cfg,path:e.discoveredHealthPath});let i=As(o,n,e.announcedUrl,e.port,e.cachedProbeHost);if(!n&&!s&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),i.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let a=null;for(let c of i){let d=await this.tryProbe(c);if(d.ok){let u=je(c);u&&this.registry.setCachedProbeHost(t,u.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,c),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}a||(a=`${d.error} ${c}`)}let l=this.freshness.get(t);if(l&&!l.retried){l.retried=!0,setTimeout(()=>{this.probe(t)},Ua);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 Ja){let s={...this.cfg,path:n},o=As(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let i of o)if((await this.tryProbe(i,{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,o=d=>{s||(s=!0,n(d))},i=t.startsWith("https://"),a=i?Ba:Fa,l={timeout:this.cfg.timeoutMs};if(i){let u=je(t)?.hostname?.replace(/^\[|\]$/g,"")??"",y=u==="127.0.0.1"||u==="::1"||u==="localhost";l.rejectUnauthorized=y?!1:!!this.cfg.rejectUnauthorized}let c=e.strict2xx?300:500;try{let d=a.get(t,l,u=>{let y=u.statusCode??0;u.resume(),y>=200&&y<c?o({ok:!0}):o({ok:!1,error:`http ${y}`})});d.on("timeout",()=>d.destroy(new Error("timeout"))),d.on("error",u=>o({ok:!1,error:u?.code||u?.message||"error"}))}catch(d){o({ok:!1,error:d?.message||"throw"})}})}}});import Ga from"pidusage";var _e,Ns=F(()=>{"use strict";_e=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 o=await Ga(s),i=this.registry.getState(n);if(!i)return;let a=Math.round(o.cpu*10)/10,l=Math.round(o.memory/(1024*1024));(i.cpu!==a||i.memMB!==l)&&(i.cpu=a,i.memMB=l,e=!0)}catch{let o=this.registry.getState(n);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}}});var Ie,$s=F(()=>{"use strict";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 o=this.registry.getState(t);if(!o)return;let i=Date.now();if((o.restartWindowStart==null||i-o.restartWindowStart>this.cfg.windowMs)&&(o.restartWindowStart=i,o.restartAttempts=0),o.restartAttempts+=1,o.restartAttempts>this.cfg.maxAttempts){o.lastStatusMessage=`auto-restart aborted (${o.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,o.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(o.restartAttempts-1)*1e3,3e4);o.nextRestartAt=i+a,o.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${o.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");let l=setTimeout(()=>{this.timers.delete(t);let c=this.registry.getState(t);c&&(c.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,l)}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 An from"node:fs";import Ms from"node:path";import Wa from"node:os";function js(){try{let r=An.readFileSync(Cn,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function Ds(r){En=r,!Rn&&(Rn=setTimeout(()=>{Rn=null;let t=En;if(En=null,!!t)try{An.mkdirSync(Ms.dirname(Cn),{recursive:!0}),An.writeFileSync(Cn,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
70
|
+
`)}},500))}var Cn,Rn,En,_s=F(()=>{"use strict";Cn=Ms.join(Wa.homedir(),".daimon","state.json");Rn=null,En=null});import Is from"node:fs";import qa from"node:os";import Ls from"node:path";import{createRequire as Ka}from"node:module";var Xa,za,Le,Fs=F(()=>{"use strict";Xa=Ka(import.meta.url),za=6e4,Le=class{constructor(t,e){this.registry=t;this.cfg=e;this.logFile=Ls.join(qa.homedir(),".daimon","notifications.log");try{Is.mkdirSync(Ls.dirname(this.logFile),{recursive:!0})}catch{}if(!e.enabled){this.audit("init","disabled by config");return}try{let n=Xa("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}
|
|
71
|
+
`;try{Is.appendFileSync(this.logFile,n)}catch{}}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] notifier: ${t}
|
|
72
|
+
`))}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 o=`${t}::${e}`,i=this.lastSent.get(o)??0,a=Date.now();if(a-i<za){this.audit("throttled",`${o}`);return}this.lastSent.set(o,a);let l={title:`daimon: ${n}`,message:s,wait:!1,appID:"daimon"},c=(d,u)=>{d?(this.audit("fail",`${o} :: ${d?.message||d}`),this.warnOnce(`notify failed: ${d?.message||d}`)):this.audit("ok",`${o} :: ${n} :: ${u??"(no response)"}`)};try{this.audit("attempt",`${o} :: ${n}`),(this.toaster??this.notifier).notify(l,c)}catch(d){this.audit("throw",`${o} :: ${d?.message||d}`),this.warnOnce(`notify threw: ${d?.message||d}`)}}}});import Bs from"node:fs";import On from"node:path";var Ya,Va,Za,Qa,Fe,Us=F(()=>{"use strict";Ya=5e3,Va=3e4,Za=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),Qa=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),Fe=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),Ya),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,o=Date.now()-s;if(o<this.cfg.silentMs){e.stale&&this.registry.setStale(t,!1);return}let i=e.lastCompileAt??e.startedAt;this.hasSourceChange(n.workspaceRoot,i,e.lastCompileAt)&&(e.stale||(this.registry.setStale(t,!0),this.registry.recordEvent({app:t,type:"stale",message:`no output in ${Math.round(o/1e3)}s despite source changes`})))}hasSourceChange(t,e,n){let s=this.caches.get(t);if(!s||Date.now()-s.ts>Va||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,o)=>{if(o>8||e.length>4e3)return;let i;try{i=Bs.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of i)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(Za.has(a.name))continue;n(On.join(s,a.name),o+1)}else if(a.isFile()){let l=On.extname(a.name);if(!Qa.has(l))continue;try{let c=On.join(s,a.name),d=Bs.statSync(c);e.push({path:c,mtime:d.mtimeMs})}catch{}}}};return n(t,0),e}}});import Hs from"node:http";var Be,Ue,Js=F(()=>{"use strict";Be=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=[],o=Hs.createServer((i,a)=>{let l=Date.now(),c={hostname:"127.0.0.1",port:e,method:i.method,path:i.url,headers:{...i.headers,host:`127.0.0.1:${e}`}},d=Hs.request(c,u=>{a.writeHead(u.statusCode||502,u.headers),u.pipe(a);let y=()=>{s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:u.statusCode||0,durationMs:Date.now()-l}),s.length>Be&&s.splice(0,s.length-Be)};u.on("end",y),u.on("error",y)});d.on("error",()=>{a.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:502,durationMs:Date.now()-l}),s.length>Be&&s.splice(0,s.length-Be)}),i.pipe(d)});o.on("error",i=>{i?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${n} in use for ${t}; disabling proxy
|
|
73
|
+
`),this.proxies.delete(t)}),o.listen(n,"127.0.0.1",()=>{this.proxies.set(t,{app:t,proxyPort:n,server:o,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(o=>o.ts>=s)}return[...n.buffer]}proxyPortFor(t){return this.proxies.get(t)?.proxyPort??null}}});import Nn from"node:fs";function Gs(r){let t=Nn.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 Ws(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]=Ws(e[n],s);return e}function ec(r,t){let e=r+"."+process.pid+".tmp";Nn.writeFileSync(e,t,"utf8"),Nn.renameSync(e,r)}function nc(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 qs(r){let t=Gs(r.configPath),e=Ws(t,r.patch);if(!e||typeof e!="object")throw new Error("patch produced non-object config");let n=pe(e,r.configPath);return ec(r.configPath,JSON.stringify(e,null,2)+`
|
|
74
|
+
`),{config:n,raw:e,applied:nc(t,e),prevRaw:t}}function $n(r){let t=Gs(r.configPath),e=pe(t,r.configPath);return rc(r.registry,e)}function rc(r,t){let e=r.getConfig();for(let c of Object.keys(e))e[c]=void 0;Object.assign(e,t);let n=new Set(r.names()),s=$t(e),o=new Set(s.map(c=>c.name)),i=[],a=[];for(let c of s)n.has(c.name)?r.updateDiscoveredApp(c):(r.addDiscoveredApp(c),i.push(c.name));for(let c of n)o.has(c)||a.push(c);let l=[];for(let c of r.names()){let d=r.getState(c);if(d&&(d.status==="serving"||d.status==="compiling")){let u=e.overrides?.[c];if(!u)continue;for(let y of tc)if(y in u){l.push(c);break}}}return{addedApps:i,removedApps:a,restartRequired:l,config:e}}var tc,Ks=F(()=>{"use strict";Ft();Ut();tc=new Set(["command","port","env","url"])});import Xs from"node:fs";import sc from"node:os";import zs from"node:path";function ic(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))oc.test(s)&&(n[s]="***")}return t}function ac(r,t=200){if(!r)return[];let e=[];for(let n of r.names()){let s=r.getState(n);if(s)for(let o of s.logBuffer)e.push({ts:o.ts,line:`[${n}] ${o.line}`})}return e.sort((n,s)=>n.ts-s.ts),e.slice(-t).map(n=>n.line)}function cc(){let r=zs.join(at(),"crashes");return Xs.mkdirSync(r,{recursive:!0}),r}function lc(r,t,e){let n=new Date().toISOString().replace(/[:.]/g,"-"),s=zs.join(cc(),`${n}.txt`),o=r,i=[`daimon crash dump @ ${new Date().toISOString()}`,`version: ${nt}`,`node: ${process.version}`,`platform: ${process.platform} ${sc.release()}`,`cwd: ${process.cwd()}`,`pid: ${process.pid}`,"","ERROR:",o?.stack||String(o),"","CONFIG (redacted):",JSON.stringify(ic(e),null,2),"","RECENT LOG (last 200 lines across apps):",...ac(t,200)];try{Xs.writeFileSync(s,i.join(`
|
|
75
|
+
`))}catch{}return s}function Ys(r){let t=e=>{let n=null;try{n=lc(e,r.getRegistry(),r.getConfig())}catch{}try{process.stderr.write(`[daimon] fatal: ${e?.stack||e}
|
|
63
76
|
`)}catch{}if(n)try{process.stderr.write(`[daimon] crash dump: ${n}
|
|
64
|
-
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var
|
|
65
|
-
`);
|
|
66
|
-
`)}),onSubmit:()=>{let P=Number(
|
|
67
|
-
`),process.exit(1)}if(n.kind==="stub-created"){let
|
|
77
|
+
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var oc,Vs=F(()=>{"use strict";Gt();dt();oc=/key|secret|token|password|pass/i});import V,{useEffect as uc,useMemo as pc,useState as Qt}from"react";import{Box as ce,Text as ut,useInput as dc,useStdout as fc}from"ink";import mc from"ink-text-input";function Mn({registry:r,appName:t,onExit:e}){let{stdout:n}=fc(),[s,o]=Qt(0),[i,a]=Qt(!1),[l,c]=Qt(""),[d,u]=Qt(""),[y,b]=Qt(0),[p,h]=Qt(0);uc(()=>{let x=()=>o(S=>S+1);r.on("change",x);let E=setInterval(()=>o(S=>S+1),500);return()=>{r.off("change",x),clearInterval(E)}},[r]);let f=r.getState(t)?.logBuffer.map(x=>x.line)??[],g=(n.rows||30)-4,T=pc(()=>{if(!d)return[];let x=d.toLowerCase();return f.reduce((E,S,_)=>(S.toLowerCase().includes(x)&&E.push(_),E),[])},[f,d,s]);dc((x,E)=>{if(i){if(E.escape){a(!1),c("");return}return}if(x==="q"||E.escape){e();return}if(x==="/"){a(!0);return}if(x==="g"){b(Math.max(0,f.length-g));return}if(x==="G"){b(0);return}if(E.pageUp){b(S=>Math.min(Math.max(0,f.length-g),S+g));return}if(E.pageDown){b(S=>Math.max(0,S-g));return}if(E.upArrow){b(S=>Math.min(Math.max(0,f.length-g),S+1));return}if(E.downArrow){b(S=>Math.max(0,S-1));return}if((x==="n"||x==="N")&&T.length){let S=x==="n"?(p+1)%T.length:(p-1+T.length)%T.length;h(S);let _=T[S],W=f.length-y,I=W-g;(_<I||_>=W)&&b(Math.max(0,f.length-_-Math.floor(g/2)));return}});let R=x=>{u(x),a(!1),c(""),h(0)},v=f.length-y,D=Math.max(0,v-g),O=f.slice(D,v),w=(x,E)=>{if(!d)return V.createElement(ut,{key:E},V.createElement(ut,{dimColor:!0},String(E+1).padStart(5)," "),x);let S=d,_=x.toLowerCase(),W=S.toLowerCase(),I=[],Z=0,G=0;for(;Z<x.length;){let ht=_.indexOf(W,Z);if(ht<0){I.push(V.createElement(ut,{key:G++},x.slice(Z)));break}ht>Z&&I.push(V.createElement(ut,{key:G++},x.slice(Z,ht))),I.push(V.createElement(ut,{key:G++,backgroundColor:"yellow",color:"black"},x.slice(ht,ht+S.length))),Z=ht+S.length}let Rt=T[p]===E;return V.createElement(ut,{key:E},V.createElement(ut,{color:Rt?"cyan":void 0,dimColor:!Rt},String(E+1).padStart(5)," "),I)};return V.createElement(ce,{flexDirection:"column"},V.createElement(ce,null,V.createElement(ut,{bold:!0},"full log: ",V.createElement(ut,{color:"cyan"},t)),V.createElement(ut,{dimColor:!0}," (",f.length," lines",d?`, ${T.length} matches for "${d}"`:"",", scroll=",y,")")),V.createElement(ce,{flexDirection:"column"},O.length===0?V.createElement(ut,{dimColor:!0},"(no log yet)"):O.map((x,E)=>w(x,D+E))),V.createElement(ce,null,i?V.createElement(ce,null,V.createElement(ut,null,"/"),V.createElement(mc,{value:l,onChange:c,onSubmit:R})):V.createElement(ut,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var Zs=F(()=>{"use strict"});function to(r,t,e=Date.now()){let n=e-36e5,s=36e5/20,o=new Array(20).fill("");for(let i of r){if(i.type!=="status"||i.app!==t||!i.to||i.ts<n||i.ts>e)continue;let a=Math.min(19,Math.floor((i.ts-n)/s)),l=o[a];(!l||(Qs[i.to]??0)>(Qs[l]??0))&&(o[a]=i.to)}return o}function eo(r){return r.map(t=>hc[t]??"\xB7").join("")}var Qs,hc,no=F(()=>{"use strict";Qs={stopped:1,serving:2,compiling:3,starting:3,error:4},hc={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"}});import A,{useEffect as gc,useState as Q}from"react";import jn from"node:fs";import yc from"node:os";import wc from"node:path";import{Box as ot,Text as j,useApp as bc,useInput as vc,useStdout as Sc}from"ink";import Dn from"ink-text-input";import{spawn as _n,spawnSync as kc}from"node:child_process";function xc(r){try{process.platform==="win32"?_n("cmd",["/c","start","",r],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?_n("open",[r],{detached:!0,stdio:"ignore"}).unref():_n("xdg-open",[r],{detached:!0,stdio:"ignore"}).unref()}catch{}}function Tc(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 In({registry:r,apiPort:t,onQuit:e}){let{exit:n}=bc(),{stdout:s}=Sc(),[o,i]=Q(r.list()),[a,l]=Q(0),[c,d]=Q(!1),[u,y]=Q(0),[b,p]=Q(!1),[h,m]=Q([]),[f,g]=Q(!1),[T,R]=Q(""),[v,D]=Q(null),[,O]=Q(0),[w,x]=Q(null),[E,S]=Q(""),[_,W]=Q(!1),[I,Z]=Q(null),[G,Rt]=Q(""),[ht,Ke]=Q(!1),[Hn,Jn]=Q(null),[Po,Gn]=Q(r.events({sinceMs:3600*1e3}));gc(()=>{let P=()=>i(r.list()),M=()=>Gn(r.events({sinceMs:36e5}));r.on("change",P),r.on("event",M);let B=setInterval(()=>{i(r.list()),Gn(r.events({sinceMs:3600*1e3})),O(N=>N+1)},1e3);return()=>{r.off("change",P),r.off("event",M),clearInterval(B)}},[r]),vc((P,M)=>{if(b)return;if(v){if(M.escape){D(null);return}if(M.tab){let N=v.field==="command"?"port":v.field==="port"?"env":"command";D({...v,field:N});return}return}if(f){if(M.escape){g(!1),R("");return}if(M.return){let N=T.trim();m(N?N.split(/[\s,]+/).filter(Boolean):[]),g(!1),R("");return}if(M.backspace||M.delete){R(N=>N.slice(0,-1));return}P&&!M.ctrl&&R(N=>N+P);return}if(_){if(M.escape){W(!1);return}if(M.return){W(!1);return}if(M.backspace||M.delete){S(N=>N.slice(0,-1));return}P&&!M.ctrl&&S(N=>N+P);return}if(ht){if(M.escape){Ke(!1),Rt("");return}if(M.return){let N=G.trim();Ke(!1),Rt(""),N&&Ao(N);return}if(M.backspace||M.delete){Rt(N=>N.slice(0,-1));return}P&&!M.ctrl&&Rt(N=>N+P);return}if(I){if(P==="y"||P==="Y"){let N=I;Z(null),r.restart(N),tt(`restarted ${N}`)}else(P==="n"||P==="N"||M.escape)&&Z(null);return}if(P==="q"||M.ctrl&&P==="c"){e(),n();return}if(o.length===0)return;if(w==="g"){x(null);let N=P.toLowerCase();N==="a"?tt("view: apps (only TUI view)"):N==="e"?tt("view: errors \u2014 selected app errors shown in detail pane"):N==="v"?tt("view: events \u2014 recent registry events shown in log pane"):N==="s"?tt("view: settings \u2014 edit `daimon.config.json`"):N==="n"&&tt("view: sessions \u2014 `daimon record` to toggle recording");return}if(M.upArrow||P==="k"){l(N=>Math.max(0,N-1)),y(0);return}if(M.downArrow||P==="j"){l(N=>Math.min(o.length-1,N+1)),y(0);return}let B=o[a];if(B){if(P==="g"){x("g"),setTimeout(()=>x(N=>N==="g"?null:N),1200);return}if(P==="/"){W(!0);return}if(P==="s")r.start(B.name);else if(P==="S")r.stop(B.name);else if(P==="r")Z(B.name);else if(P==="f")Eo(B.name);else if(P==="x")Ro(B.name);else if(P==="O")Ke(!0);else if(P==="L")p(!0);else if(P==="t")g(!0),R(h.join(" "));else if(P==="e"){let N=r.getConfig(),K=r.getApp(B.name),lt=r.getState(B.name)?.sessionOverrides??null,At=lt?.env??N.overrides?.[B.name]?.env??{},Ct=Object.entries(At).map(([ze,Ye])=>`${ze}=${Ye}`).join(`
|
|
78
|
+
`);D({name:B.name,field:"command",cmd:lt?.command??K?.command??"",port:String(lt?.port??N.overrides?.[B.name]?.port??B.port??""),env:Ct})}else if(P==="E"){let K=r.getConfig().envFiles?.[B.name]??[];if(!K.length)return;let lt=r.getState(B.name)?.activeEnvFile??null,At=lt?K.indexOf(lt):-1,Ct=K[(At+1)%K.length];r.setActiveEnvFile(B.name,Ct)}else if(P==="V"){let N=process.env.EDITOR||(process.platform==="win32"?"notepad":"vi"),K=wc.join(yc.tmpdir(),`daimon-${B.name}-${Date.now()}.json`),lt=r.getConfig(),At=r.getApp(B.name),Ct=r.getState(B.name)?.sessionOverrides??null,ze={command:Ct?.command??At?.command,port:Ct?.port??lt.overrides?.[B.name]?.port??null,env:Ct?.env??lt.overrides?.[B.name]?.env??{}};try{jn.writeFileSync(K,JSON.stringify(ze,null,2)),kc(N,[K],{stdio:"inherit",shell:!0});let Ye=jn.readFileSync(K,"utf8"),Ot=JSON.parse(Ye);r.setSessionOverride(B.name,{command:typeof Ot.command=="string"?Ot.command:void 0,port:typeof Ot.port=="number"?Ot.port:void 0,env:Ot.env&&typeof Ot.env=="object"?Ot.env:void 0}),jn.unlinkSync(K)}catch{}}else P==="l"?d(N=>!N):P==="o"?B.url&&xc(B.url):M.pageUp?y(N=>N+5):M.pageDown&&y(N=>Math.max(0,N-5))}});let tt=P=>{Jn(P),setTimeout(()=>Jn(M=>M===P?null:M),4e3)},Ro=async P=>{tt(`try-fix ${P}\u2026`);try{let{runAutoFix:M,ALL_AUTO_FIX:B}=await Promise.resolve().then(()=>(Yt(),zt)),K=r.getConfig().doctor?.autoFix?.permitted??B,lt=await M({permitted:K,dryRun:!1});await r.restart(P);let At=await r.waitFor(P,"healthy",6e4);tt(`try-fix ${P}: ${At.timedOut?"timeout":"reached"} \xB7 fixed ${lt.ran.length}`)}catch(M){tt(`try-fix ${P} failed: ${M?.message??M}`)}},Eo=async P=>{tt(`focus ${P} until stable\u2026`);try{let M=Date.now(),B=Date.now(),N=K=>{K.app===P&&(B=Date.now())};r.on("event",N);try{for(;Date.now()-M<18e4;){let K=r.summary(P);if(K&&K.status==="serving"&&K.health==="healthy"&&Date.now()-B>=5e3){tt(`focus ${P}: stable after ${Math.round((Date.now()-M)/1e3)}s`);return}await new Promise(lt=>setTimeout(lt,500))}}finally{r.off("event",N)}tt(`focus ${P}: timed out`)}catch(M){tt(`focus ${P} failed: ${M?.message??M}`)}},Ao=async P=>{tt(`orchestrate ${P}\u2026`);try{let{orchestrateProfile:M}=await Promise.resolve().then(()=>(kn(),Sn)),B=await M(r,r.getConfig(),{profile:P,goal:"healthy",timeoutMs:3e5});if(B.error){tt(`orchestrate ${P}: ${B.error}`);return}let N=B.allReached;tt(`orchestrate ${P}: ${N?"all reached":"some failing"} \xB7 ${Math.round(B.totalMs/1e3)}s`)}catch(M){tt(`orchestrate ${P} failed: ${M?.message??M}`)}},Wn=E.trim().toLowerCase(),ue=(h.length===0?o:o.filter(P=>h.every(M=>P.tags.includes(M)))).filter(P=>!Wn||P.name.toLowerCase().includes(Wn)),U=ue[Math.min(a,Math.max(0,ue.length-1))],Et=U?r.getState(U.name):null,qn=Et?Et.logBuffer.slice(Math.max(0,Et.logBuffer.length-12-u),Et.logBuffer.length-u).map(P=>P.line):[],Xe=s.columns||100,Co=Math.min(36,Math.floor(Xe*.4));return b&&U?A.createElement(Mn,{registry:r,appName:U.name,onExit:()=>p(!1)}):A.createElement(ot,{flexDirection:"column",width:Xe},A.createElement(ot,{borderStyle:"round",borderColor:"cyan",paddingX:1},A.createElement(j,{bold:!0,color:"cyan"},"daimon"),A.createElement(j,{dimColor:!0}," \u2022 api http://127.0.0.1:",t)),A.createElement(ot,{flexDirection:"row"},A.createElement(ot,{flexDirection:"column",width:Co,borderStyle:"single",borderColor:"gray",paddingX:1},A.createElement(j,{bold:!0},"Apps ",h.length?A.createElement(j,{dimColor:!0},"(tags: ",h.join(", "),")"):null),ue.length===0?A.createElement(j,{dimColor:!0},o.length===0?"(no apps discovered)":"(no apps match filter)"):ue.map((P,M)=>{let B=M===a,N=to(Po,P.name),K=eo(N);return A.createElement(ot,{key:P.name,flexDirection:"column"},A.createElement(ot,null,A.createElement(j,{color:B?"cyan":void 0},B?"\u25B8 ":" "),A.createElement(j,{color:B?"cyan":void 0},((r.getState(P.name)?.sessionOverrides?"*":"")+P.name).padEnd(20).slice(0,20)),A.createElement(j,{color:ro[P.status]}," ",P.status.padEnd(9)),A.createElement(j,{color:so[P.health]},P.status==="serving"?"\u25CF":" "),A.createElement(j,{dimColor:!0},P.port?` :${P.port}`:""),Xe>=100&&P.cpu!=null?A.createElement(j,{dimColor:!0}," ",String(P.cpu).padStart(5),"% ",String(P.memMB??0).padStart(5),"MB"):null),A.createElement(ot,null,A.createElement(j,{dimColor:!0}," "),A.createElement(j,{dimColor:!0},K)))})),A.createElement(ot,{flexDirection:"column",flexGrow:1,borderStyle:"single",borderColor:"gray",paddingX:1},U&&Et?A.createElement(A.Fragment,null,A.createElement(j,null,"Selected: ",A.createElement(j,{bold:!0},U.name)),A.createElement(j,null,"Status: ",A.createElement(j,{color:ro[U.status]},U.status)," ",A.createElement(j,{color:so[U.health]},"\u25CF")," ",A.createElement(j,{dimColor:!0},U.health)),A.createElement(j,null,"Port: ",U.port??"-"),A.createElement(j,null,"URL: ",U.url??"-"),U.announcedUrl&&U.announcedUrl!==U.url?A.createElement(j,{dimColor:!0},"Announced: ",U.announcedUrl):null,U.lastHealthError?A.createElement(j,{color:"red"},"HealthErr: ",U.lastHealthError):null,U.stale?A.createElement(j,{color:"yellow"},"\u26A0 stale (best guess)"):null,A.createElement(j,null,"Errors: ",A.createElement(j,{color:U.errorCount?"red":void 0},U.errorCount)),A.createElement(j,null,"Uptime: ",Tc(U.uptimeMs)),U.cpu!=null||U.memMB!=null?A.createElement(j,null,"Usage: ",U.cpu??"-","% ",U.memMB??"-"," MB"):null,U.compileHistoryMs.length>0?A.createElement(j,null,"Recent compile: ",U.compileHistoryMs.slice(-5).map(P=>(P/1e3).toFixed(1)+"s").join(" \xB7 ")):null,U.bundle?A.createElement(j,null,"Bundle: ",U.bundle.initialKB,"KB initial \xB7 ",U.bundle.lazyKB,"KB lazy",U.bundleRegressionPct!=null&&U.bundleRegressionPct>10?A.createElement(j,{color:"red"}," (+",U.bundleRegressionPct,"% \u26A0)"):null):null,Et.lastStatusMessage?A.createElement(j,{dimColor:!0},"Note: ",Et.lastStatusMessage):null,A.createElement(j,null,"\u2500\u2500\u2500\u2500 recent log ",c?"(focused)":""," \u2500\u2500\u2500\u2500"),qn.length===0?A.createElement(j,{dimColor:!0},"(no output yet)"):qn.map((P,M)=>A.createElement(j,{key:M,wrap:"truncate-end"},P))):A.createElement(j,{dimColor:!0},"No app selected."))),A.createElement(ot,{flexDirection:"column"},f?A.createElement(j,null,"tag filter (space-separated, Enter to apply, Esc to cancel): ",A.createElement(j,{color:"cyan"},T)):null,v?A.createElement(ot,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1},A.createElement(j,{bold:!0,color:"yellow"},"edit ",v.name," (session-only) Tab=next field Enter=save Esc=cancel"),A.createElement(ot,null,A.createElement(j,null,v.field==="command"?"> ":" ","command: "),v.field==="command"?A.createElement(Dn,{value:v.cmd,onChange:P=>D({...v,cmd:P}),onSubmit:()=>D({...v,field:"port"})}):A.createElement(j,{dimColor:!0},v.cmd)),A.createElement(ot,null,A.createElement(j,null,v.field==="port"?"> ":" ","port: "),v.field==="port"?A.createElement(Dn,{value:v.port,onChange:P=>D({...v,port:P}),onSubmit:()=>D({...v,field:"env"})}):A.createElement(j,{dimColor:!0},v.port)),A.createElement(ot,null,A.createElement(j,null,v.field==="env"?"> ":" ","env (k=v;): "),v.field==="env"?A.createElement(Dn,{value:v.env.replace(/\n/g,";"),onChange:P=>D({...v,env:P.replace(/;/g,`
|
|
79
|
+
`)}),onSubmit:()=>{let P=Number(v.port),M={};for(let B of v.env.split(/\n/)){let N=B.match(/^\s*([^=]+)=(.*)$/);N&&(M[N[1].trim()]=N[2])}r.setSessionOverride(v.name,{command:v.cmd||void 0,port:Number.isFinite(P)&&P>0?P:void 0,env:Object.keys(M).length?M:void 0}),D(null)}}):A.createElement(j,{dimColor:!0},v.env))):null,I?A.createElement(ot,{borderStyle:"round",borderColor:"yellow",paddingX:1},A.createElement(j,{color:"yellow",bold:!0},"Restart ",I,"? "),A.createElement(j,{dimColor:!0},"[y]es [n]o / Esc")):null,_?A.createElement(j,null,"filter (Enter to apply, Esc to clear): ",A.createElement(j,{color:"cyan"},E)):null,ht?A.createElement(ot,{borderStyle:"round",borderColor:"cyan",paddingX:1},A.createElement(j,{bold:!0,color:"cyan"},"orchestrate profile (Enter to run, Esc to cancel): "),A.createElement(j,{color:"cyan"},G)):null,Hn?A.createElement(j,{color:"cyan"},"[i] ",Hn):null,A.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")))}var ro,so,oo=F(()=>{"use strict";Zs();no();ro={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},so={healthy:"green",unhealthy:"red",unknown:"gray"}});var ao={};gt(ao,{startInProcess:()=>io});import Pc from"react";import{render as Rc}from"ink";import{pathToFileURL as Ec}from"node:url";async function io(r={}){let t=null,e=null;Ys({getRegistry:()=>t,getConfig:()=>e});let n;try{n=et()}catch(w){process.stderr.write(`[daimon] config error: ${w.message}
|
|
80
|
+
`),process.exit(1)}if(n.kind==="stub-created"){let w=Nt();process.stdout.write(`[daimon] no config found. Created stub at:
|
|
68
81
|
${n.path}
|
|
69
82
|
`),process.stdout.write(`[daimon] Edit it to add "searchRoots" pointing at your Nx/Angular workspace, then run again.
|
|
70
|
-
`),process.stdout.write(`[daimon] (Local override path: ${
|
|
83
|
+
`),process.stdout.write(`[daimon] (Local override path: ${w.local})
|
|
71
84
|
`),process.exit(0)}let{config:s,path:o}=n;if(process.stdout.write(`[daimon] config: ${o}
|
|
72
|
-
`),s.depends&&Object.keys(s.depends).length){let
|
|
73
|
-
`),process.exit(1))}let i
|
|
74
|
-
`);let a=
|
|
75
|
-
`);for(let
|
|
76
|
-
`);continue}s.depends&&s.depends[
|
|
77
|
-
`);try{
|
|
78
|
-
`)}if(process.on("SIGINT",()=>{
|
|
79
|
-
`);let
|
|
80
|
-
`),
|
|
81
|
-
`),process.exit(1)})});var
|
|
85
|
+
`),s.depends&&Object.keys(s.depends).length){let w=de(s.depends);w&&(process.stderr.write(`[daimon] config error: depends graph has a cycle: ${w.join(" -> ")}
|
|
86
|
+
`),process.exit(1))}let i=$t(s);i.length===0&&process.stdout.write(`[daimon] no serveable projects discovered in: ${s.searchRoots.join(", ")||"(none)"}
|
|
87
|
+
`);let a=js(),l=new Ht(s.portRange,{initial:a.ports,onChange:w=>Ds({ports:w})}),c=new Re(s,i,l);t=c,e=s;let d=new vt(s.history);c.setHistory(d);let u=new De(c,s.healthProbe,s),y=new _e(c),b=new Ie(c,s.autoRestart),p=new Le(c,s.notifications),h=new Fe(c,s.staleDetect),m=new Ue(c,s.requestLog);c.on("childExit",({name:w,code:x,signal:E,stopping:S})=>b.onExit(w,x,E,S)),c.on("userStop",({name:w})=>b.onUserStop(w));let f=ys();if(f&&f.apps.length){process.stdout.write(`[daimon] state-handoff: restoring ${f.apps.map(w=>w.name).join(", ")}
|
|
88
|
+
`);for(let w of f.apps)l.pin(w.name,w.port);for(let w of f.apps)c.names().includes(w.name)&&c.start(w.name)}if(s.autoStart&&s.autoStart.length){let w=new Set(c.names());for(let x of s.autoStart){if(!w.has(x)){process.stderr.write(`[daimon] warning: autoStart references unknown app "${x}"
|
|
89
|
+
`);continue}s.depends&&s.depends[x]&&s.depends[x].length?c.startWithDeps(x):c.start(x)}}let g=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):s.apiPort,T=!!r.headless||!!s.headless||process.argv.includes("--headless"),R=!1,v=async()=>{if(!R){R=!0;try{u.stop()}catch{}try{y.stop()}catch{}try{b.stop()}catch{}try{p.stop()}catch{}try{h.stop()}catch{}try{m.stop()}catch{}try{d.close()}catch{}try{await c.stopAll(3e3)}catch{}try{D.close()}catch{}try{pt()}catch{}process.exit(0)}},D=Rs(c,g,{metricsEnabled:s.metrics.enabled,requestLog:m,onShutdown:()=>{v()},configPath:o,getConfig:()=>c.getConfig(),patchConfig:w=>{try{let x=qs({configPath:o,patch:w}),E=$n({configPath:o,registry:c});return{ok:!0,applied:x.applied,addedApps:E.addedApps,removedApps:E.removedApps,restartRequired:E.restartRequired}}catch(x){return{ok:!1,error:x?.message||String(x)}}},reloadConfig:async()=>{let w=$n({configPath:o,registry:c});return{ok:!0,addedApps:w.addedApps,removedApps:w.removedApps,restartRequired:w.restartRequired}}});process.stdout.write(`[daimon] api: http://127.0.0.1:${g}
|
|
90
|
+
`);try{cr(lr(g,T,o))}catch(w){process.stderr.write(`[daimon] warning: could not write daemon.lock: ${w?.message||w}
|
|
91
|
+
`)}if(process.on("SIGINT",()=>{v()}),process.on("SIGTERM",()=>{v()}),process.on("beforeExit",()=>{v()}),T){process.stdout.write(`[daimon] headless mode \u2014 TUI suppressed. Dashboard: http://127.0.0.1:${g}
|
|
92
|
+
`);let w="",x=setInterval(()=>{let E=c.list().map(_=>({name:_.name,status:_.status,health:_.health,port:_.port})),S=JSON.stringify(E);S!==w&&(process.stderr.write(S+`
|
|
93
|
+
`),w=S)},6e4);await new Promise(()=>{}),clearInterval(x);return}await Rc(Pc.createElement(In,{registry:c,apiPort:g,onQuit:()=>{v()}})).waitUntilExit(),await v()}var Ac,co=F(()=>{"use strict";Ft();Ut();zr();se();Es();Os();Ns();$s();_s();he();re();Fs();Us();Js();dt();Ks();Vs();bn();oo();Ac=(()=>{try{return import.meta.url===Ec(process.argv[1]||"").href}catch{return!1}})();Ac&&io().catch(r=>{process.stderr.write(`[daimon] fatal: ${r?.stack||r}
|
|
94
|
+
`),process.exit(1)})});var po={};gt(po,{attachToDaemon:()=>Uc});import H,{useEffect as lo,useState as xt}from"react";import Ln from"node:fs";import uo from"node:path";import Cc from"node:os";import{Box as te,render as Oc,Text as X,useApp as Nc,useInput as $c,useStdout as Mc}from"ink";import jc from"ink-text-input";function Ic(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 Fn(r){return uo.join(Cc.homedir(),".daimon",`attach-token.${r}`)}function Lc(r){try{return Ln.readFileSync(Fn(r),"utf8").trim()||null}catch{return null}}function Fc(r,t){try{Ln.mkdirSync(uo.dirname(Fn(r)),{recursive:!0}),Ln.writeFileSync(Fn(r),t,"utf8")}catch{}}function Bc({port:r,onExit:t}){let{exit:e}=Nc(),{stdout:n}=Mc(),[s,o]=xt([]),[i,a]=xt(0),[l,c]=xt(!1),[d,u]=xt([]),[y,b]=xt(null),[p,h]=xt(()=>Lc(r)),[m,f]=xt(!1),[g,T]=xt(""),R=`http://127.0.0.1:${r}`;async function v(w,x={}){try{let E={...x.headers||{}};p&&(E.authorization=`Bearer ${p}`);let S=await fetch(R+w,{...x,headers:E}),_=await S.text(),W=_;try{W=JSON.parse(_)}catch{}return{status:S.status,body:W}}catch(E){return{status:0,body:{error:E?.message||String(E)}}}}if(lo(()=>{let w=!1,x=async()=>{let S=await v("/api/apps?format=full");if(!w){if(S.status===0){b(S.body?.error||"daemon unreachable");return}if(S.status===401){f(!0);return}b(null),o(Array.isArray(S.body)?S.body:[])}};x();let E=setInterval(x,1e3);return()=>{w=!0,clearInterval(E)}},[p]),lo(()=>{if(!l){u([]);return}let w=!1,x=s[i];if(!x)return;let E=async()=>{let _=await v(`/api/apps/${encodeURIComponent(x.name)}/logs?tail=12`);w||Array.isArray(_.body?.lines)&&u(_.body.lines)};E();let S=setInterval(E,1e3);return()=>{w=!0,clearInterval(S)}},[l,i,s.length,p]),$c((w,x)=>{if(m){if(x.escape){f(!1);return}return}if(w==="q"||x.ctrl&&w==="c"){t(),e();return}if(x.upArrow)a(E=>Math.max(0,E-1));else if(x.downArrow)a(E=>Math.min(Math.max(0,s.length-1),E+1));else if(x.return||w===" ")c(E=>!E);else if(w==="s"||w==="x"||w==="r"){let E=s[i];if(!E)return;let S=w==="s"?"start":w==="x"?"stop":"restart";v(`/api/apps/${encodeURIComponent(E.name)}/${S}`,{method:"POST"})}}),m)return H.createElement(te,{flexDirection:"column",paddingX:1},H.createElement(X,{color:"yellow"},"daemon requires a bearer token. Enter token (Esc to cancel):"),H.createElement(jc,{value:g,onChange:T,mask:"*",onSubmit:()=>{let w=g.trim();w&&(h(w),Fc(r,w)),T(""),f(!1)}}));let D=n.columns||100,O=s[i];return H.createElement(te,{flexDirection:"column",width:D},H.createElement(te,{borderStyle:"round",borderColor:"cyan",paddingX:1},H.createElement(X,{bold:!0,color:"cyan"},"daimon attach"),H.createElement(X,{dimColor:!0}," \u2022 http://127.0.0.1:",r," \u2022 HTTP-client TUI (q detaches, daemon keeps running)")),y?H.createElement(X,{color:"red"},y):null,H.createElement(te,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},H.createElement(X,{bold:!0},"Apps (",s.length,")"),s.length===0?H.createElement(X,{dimColor:!0},"(no apps)"):s.map((w,x)=>{let E=x===i;return H.createElement(te,{key:w.name},H.createElement(X,{color:E?"cyan":void 0},E?"\u25B8 ":" "),H.createElement(X,{color:E?"cyan":void 0},w.name.padEnd(20).slice(0,20)),H.createElement(X,{color:Dc[w.status]}," ",w.status.padEnd(9)),H.createElement(X,{color:_c[w.health]},w.status==="serving"?"\u25CF":" "),H.createElement(X,{dimColor:!0},w.port?` :${w.port}`:""),H.createElement(X,{dimColor:!0}," errs=",w.errorCount," up=",Ic(w.uptimeMs)))})),O?H.createElement(te,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},H.createElement(X,null,"Selected: ",H.createElement(X,{bold:!0},O.name)),H.createElement(X,null,"URL: ",O.url??"-"),O.lastHealthError?H.createElement(X,{color:"red"},"HealthErr: ",O.lastHealthError):null,H.createElement(X,{dimColor:!0},"\u2500\u2500\u2500\u2500 recent log (Enter/Space toggles) \u2500\u2500\u2500\u2500"),l?d.length===0?H.createElement(X,{dimColor:!0},"(loading\u2026)"):d.map((w,x)=>H.createElement(X,{key:x,wrap:"truncate-end"},w)):H.createElement(X,{dimColor:!0},"(press Enter to fetch logs)")):null,H.createElement(X,{dimColor:!0},"[s] start [x] stop [r] restart [Enter] toggle log [q] detach (daemon keeps running)"))}async function Uc(r){let t,e=new Promise(s=>{t=s});await Oc(H.createElement(Bc,{port:r,onExit:()=>t()})).waitUntilExit(),await e}var Dc,_c,fo=F(()=>{"use strict";Dc={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},_c={healthy:"green",unhealthy:"red",unknown:"gray"}});var yo={};gt(yo,{buildServiceArtifact:()=>go,installServiceArtifact:()=>Jc});import mo from"node:fs";import ho from"node:os";import Tt from"node:path";import{fileURLToPath as Hc}from"node:url";function He(){return process.execPath}function Je(){let r=Tt.dirname(Hc(import.meta.url));return Tt.join(r,"main.js")}function go(){let r=process.platform;if(r==="win32"){let n=`<?xml version="1.0" encoding="UTF-8"?>
|
|
82
95
|
<!-- generated by daimon daemon install-service -->
|
|
83
96
|
<service>
|
|
84
97
|
<id>daimon</id>
|
|
85
98
|
<name>daimon daemon</name>
|
|
86
99
|
<description>Local Angular/Nx/Vite dev server manager (daimon headless daemon)</description>
|
|
87
|
-
<executable>${
|
|
88
|
-
<arguments>"${
|
|
100
|
+
<executable>${He()}</executable>
|
|
101
|
+
<arguments>"${Je()}" --headless</arguments>
|
|
89
102
|
<log mode="rotate"/>
|
|
90
103
|
<onfailure action="restart" delay="10 sec"/>
|
|
91
104
|
</service>
|
|
92
|
-
`,s=
|
|
105
|
+
`,s=Tt.join(at(),"daimon-daemon.xml");return{platform:r,path:s,body:n,installCmd:`nssm install daimon "${He()}" "${Je()}" --headless`}}if(r==="darwin"){let n=`<?xml version="1.0" encoding="UTF-8"?>
|
|
93
106
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
94
107
|
<plist version="1.0">
|
|
95
108
|
<dict>
|
|
96
109
|
<key>Label</key><string>dev.daimon</string>
|
|
97
110
|
<key>ProgramArguments</key>
|
|
98
111
|
<array>
|
|
99
|
-
<string>${
|
|
100
|
-
<string>${
|
|
112
|
+
<string>${He()}</string>
|
|
113
|
+
<string>${Je()}</string>
|
|
101
114
|
<string>--headless</string>
|
|
102
115
|
</array>
|
|
103
116
|
<key>RunAtLoad</key><true/>
|
|
104
117
|
<key>KeepAlive</key><true/>
|
|
105
|
-
<key>StandardOutPath</key><string>${
|
|
106
|
-
<key>StandardErrorPath</key><string>${
|
|
118
|
+
<key>StandardOutPath</key><string>${Tt.join(at(),"service.out.log")}</string>
|
|
119
|
+
<key>StandardErrorPath</key><string>${Tt.join(at(),"service.err.log")}</string>
|
|
107
120
|
</dict>
|
|
108
121
|
</plist>
|
|
109
|
-
`,s=
|
|
122
|
+
`,s=Tt.join(ho.homedir(),"Library","LaunchAgents","dev.daimon.plist");return{platform:r,path:s,body:n,installCmd:`launchctl load ${s}`}}let t=`[Unit]
|
|
110
123
|
Description=daimon daemon (local dev-server manager)
|
|
111
124
|
After=network.target
|
|
112
125
|
|
|
113
126
|
[Service]
|
|
114
|
-
ExecStart=${
|
|
127
|
+
ExecStart=${He()} ${Je()} --headless
|
|
115
128
|
Restart=on-failure
|
|
116
129
|
RestartSec=10
|
|
117
130
|
|
|
118
131
|
[Install]
|
|
119
132
|
WantedBy=default.target
|
|
120
|
-
`,e=
|
|
121
|
-
`,"utf8"),{path:o,installClaude:!1,config:i,auto:!0}}async function
|
|
122
|
-
`),(await
|
|
133
|
+
`,e=Tt.join(ho.homedir(),".config","systemd","user","daimon.service");return{platform:r,path:e,body:t,installCmd:"systemctl --user enable daimon && systemctl --user start daimon"}}function Jc(){let r=go();return mo.mkdirSync(Tt.dirname(r.path),{recursive:!0}),mo.writeFileSync(r.path,r.body,"utf8"),{path:r.path,installCmd:r.installCmd,platform:r.platform}}var wo=F(()=>{"use strict";dt()});var So={};gt(So,{runInit:()=>Kc,runInitAuto:()=>vo});import Pt from"node:fs";import Gc from"node:os";import Lt from"node:path";import Wc from"node:readline";function It(r,t){return new Promise(e=>r.question(t,n=>e(n.trim())))}function bo(r){let t=[];for(let e of qc)Pt.existsSync(Lt.join(r,e))&&t.push(e);return t}async function vo(r={}){let t=r.cwd??process.cwd(),e=bo(t),n=[],s;try{let a=JSON.parse(Pt.readFileSync(Lt.join(t,"package.json"),"utf8"));typeof a.name=="string"&&(s=a.name)}catch{}e.length&&n.push(s?{path:t,label:s}:t);let o=Lt.join(t,"daimon.config.json");if(Pt.existsSync(o)&&!r.force)throw new Error(`refusing to overwrite ${o} (pass --force to overwrite)`);let i={searchRoots:n,portRange:[4200,4299],apiPort:4999};return Pt.mkdirSync(Lt.dirname(o),{recursive:!0}),Pt.writeFileSync(o,JSON.stringify(i,null,2)+`
|
|
134
|
+
`,"utf8"),{path:o,installClaude:!1,config:i,auto:!0}}async function Kc(r={}){if(r.auto)return vo(r);let t=r.cwd??process.cwd(),e=Wc.createInterface({input:process.stdin,output:process.stdout});try{let n=bo(t),s=[];if(n.length&&(process.stdout.write(`[daimon init] detected in ${t}: ${n.join(", ")}
|
|
135
|
+
`),(await It(e,"Add this folder as a searchRoot? [Y/n] ")||"y").toLowerCase().startsWith("y"))){let f=await It(e,"Optional label for this workspace (blank = none): ");s.push(f?{path:t,label:f}:t)}let o=await It(e,"Additional searchRoots (comma-separated absolute paths, blank to skip): ");if(o)for(let m of o.split(",").map(f=>f.trim()).filter(Boolean))s.push(m);let a=(await It(e,"Port range [4200-4299]: ")||"4200-4299").match(/^(\d+)\s*[-,\s]\s*(\d+)$/),l=a?[Number(a[1]),Number(a[2])]:[4200,4299],c=await It(e,"apiPort [4999]: ")||"4999",d=Number(c)||4999,y=(await It(e,"Write to (1) ./daimon.config.json or (2) ~/.daimon/config.json? [1] ")||"1").trim()==="2"?Lt.join(Gc.homedir(),".daimon","config.json"):Lt.join(t,"daimon.config.json");if(Pt.existsSync(y)&&!r.force)throw new Error(`refusing to overwrite ${y} (pass --force to overwrite)`);let b={searchRoots:s,portRange:l,apiPort:d};Pt.mkdirSync(Lt.dirname(y),{recursive:!0}),Pt.writeFileSync(y,JSON.stringify(b,null,2)+`
|
|
123
136
|
`,"utf8"),process.stdout.write(`[daimon init] wrote ${y}
|
|
124
|
-
`);let h=(await
|
|
125
|
-
`)}function
|
|
126
|
-
`)}function
|
|
127
|
-
`);try{
|
|
128
|
-
`),process.exit(1));var
|
|
137
|
+
`);let h=(await It(e,"Install Claude Code integration? [Y/n] ")||"y").toLowerCase().startsWith("y");return{path:y,installClaude:h,config:b}}finally{e.close()}}var qc,ko=F(()=>{"use strict";qc=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs",".storybook"]});Ft();Ut();import Xc from"node:os";re();se();he();import Mt from"node:fs";import Jt from"node:path";async function er(r,t){let e=[],n=new Set(t.map(c=>c.name));for(let c of r.searchRoots){let d=typeof c=="string"?c:c.path,u=Jt.resolve(d);if(!Mt.existsSync(u)){e.push({name:`searchRoot exists: ${u}`,ok:!1,detail:"not found"});continue}let y=Mt.existsSync(Jt.join(u,"nx.json"))||Mt.existsSync(Jt.join(u,"angular.json"))||Mt.existsSync(Jt.join(u,".storybook"))||["ts","js","mjs","cjs"].some(b=>Mt.existsSync(Jt.join(u,`vite.config.${b}`)));e.push({name:`searchRoot has marker: ${u}`,ok:y,detail:y?void 0:"no nx.json/angular.json/vite.config.*/.storybook"})}for(let[c,d]of Object.entries(r.overrides??{})){let u=n.has(c),y=!!d.command,b=u||y;e.push({name:`override "${c}"`,ok:b,detail:b?void 0:"unknown app and no command override"})}let s=Object.entries(r.overrides??{}).filter(([,c])=>typeof c.port=="number").map(([c,d])=>({name:c,port:d.port})),o=new Map;for(let c of s)o.has(c.port)?e.push({name:`port pin ${c.port}`,ok:!1,detail:`collision: ${o.get(c.port)} and ${c.name}`}):o.set(c.port,c.name);s.length&&!e.some(c=>c.name.startsWith("port pin"))&&e.push({name:"pinned ports",ok:!0});for(let c of r.autoStart??[])e.push({name:`autoStart "${c}"`,ok:n.has(c),detail:n.has(c)?void 0:"unknown app"});for(let[c,d]of Object.entries(r.profiles??{}))for(let u of d)e.push({name:`profile "${c}" entry "${u}"`,ok:n.has(u),detail:n.has(u)?void 0:"unknown app"});if(r.depends&&Object.keys(r.depends).length){for(let[d,u]of Object.entries(r.depends))for(let y of u)n.has(y)||e.push({name:`depends "${d}" -> "${y}"`,ok:!1,detail:"unknown app"});let c=de(r.depends);c?e.push({name:"depends DAG",ok:!1,detail:`cycle: ${c.join(" -> ")}`}):e.push({name:"depends DAG",ok:!0})}let i=new Set(t.map(c=>c.workspaceRoot));for(let c of i){let d=Jt.join(c,"node_modules");e.push({name:`node_modules: ${c}`,ok:Mt.existsSync(d),detail:Mt.existsSync(d)?void 0:"missing"})}let a=await bt(r.apiPort);if(e.push({name:`apiPort ${r.apiPort}`,ok:a,detail:a?void 0:"in use (may be held by us)"}),r.history.enabled){let c=!1,d;try{let u=new vt(r.history);c=u.quickCheck(),u.close(),c||(d="quick_check failed")}catch(u){d=u?.message||String(u)}e.push({name:"history db",ok:c,detail:d})}return e.push({name:"agent token footprint",ok:!0,detail:Ho(t)}),{ok:e.every(c=>c.ok),checks:e}}function Ho(r){let t=r.length,e=120,n=34,s=285,o=e+t*n,i=e+t*s,a=t>0?Math.round((1-o/i)*100):0;return`skill=${e} tokens \xB7 daimon list (${t} apps) \u2248 ${o} tokens compact / ${i} tokens full \xB7 savings: ~${a}%`}rn();sn();dt();Gt();var kt=[{name:"list",args:"[--tag <name>] [--workspace <label>] [--full|--compact] [--stream] [--explain]",summary:"List apps. Compact by default; --full for v0.4 shape; --stream for NDJSON; --explain wraps with _meta (searchRoots, scanned, rejected, suggestion).",example:"daimon list",needsDaemon:!0},{name:"status",args:"<name> [--full|--compact]",summary:"Get the current status of one app. Compact by default.",example:"daimon status web-admin",needsDaemon:!0},{name:"errors",args:"<name> [--since 2m] [--since-last] [--client <id>] [--structured] [--full|--compact]",summary:"Get deduplicated errors for an app. Compact by default ({file,line,col,code,message}).",example:"daimon errors web-admin --since 5m",needsDaemon:!0},{name:"events",args:"[--since 1h] [--app <name>] [--stream]",summary:"Get the event log. --stream emits NDJSON until SIGINT.",example:"daimon events --since 1h",needsDaemon:!0},{name:"wait",args:"<name> [--until serving|healthy|stopped|error] [--timeout 60s]",summary:"Block until app reaches the given state.",example:"daimon wait web-admin --until healthy",needsDaemon:!0},{name:"ensure",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"One-call: start if needed, block to target state, return terminal state. Idempotent.",example:"daimon ensure web-admin",needsDaemon:!0},{name:"ensure-up",args:"<profile> [--until serving|healthy] [--timeout 300s]",summary:"One-call: cascade-start every app in the profile and wait for each to reach target.",example:"daimon ensure-up fullstack",needsDaemon:!0},{name:"overview",args:"[--workspace <label>] [--profile <name>] [--budget <tokens>]",summary:"Decision-ready snapshot: totals, byStatus, needsAttention (with first parsed error), recentlyChanged. First call in a session. --budget caps the response size for agents; overflow collapses to _meta.omitted.",example:"daimon overview --budget 1500",needsDaemon:!0},{name:"focus",args:"<name> [--until serving|healthy|stable] [--timeout 180s]",summary:"One round-trip subscribe-then-act: streams NDJSON of status/error/url events for one app until target state or timeout. Designed for agents.",example:"daimon focus web-admin --until stable",needsDaemon:!0},{name:"try-fix",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"Composite: run doctor --auto-fix on permitted rules, restart the app, wait for target, return {before,after,fixed,stillFailing}. Never edits user source.",example:"daimon try-fix web-admin",needsDaemon:!0},{name:"orchestrate",args:"<profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]",summary:"Bring up a whole profile in one call: cascade-start, wait for goal, run ONE try-fix round on stragglers. Returns {profile, goal, perApp, totalMs, allReached}. --dry-run reports planned order only. Designed for agents.",example:"daimon orchestrate fullstack --goal stable",needsDaemon:!0},{name:"pin-health",args:"<name> [--accept] [--path <p>]",summary:"Show the auto-discovered health-probe path for an app; --accept persists it as overrides.<name>.healthProbePath in daimon.config.json and soft-reloads. Default behaviour is opt-in: nothing is written without --accept.",example:"daimon pin-health api --accept",needsDaemon:!0},{name:"logs",args:"<name> [--tail N] [--since 30s]",summary:"Recent log lines for an app.",example:"daimon logs web-admin --tail 100",needsDaemon:!0},{name:"start",args:"<name> [--with-deps]",summary:"Start an app.",example:"daimon start web-admin",needsDaemon:!0},{name:"stop",args:"<name>",summary:"Stop an app.",example:"daimon stop web-admin",needsDaemon:!0},{name:"restart",args:"<name>",summary:"Restart an app.",example:"daimon restart web-admin",needsDaemon:!0},{name:"up",args:"[<profile>]",summary:"Start a profile (or autoStart). Waits for each to reach serving.",example:"daimon up fullstack",needsDaemon:!0},{name:"down",args:"[<profile>]",summary:"Stop a profile (or all apps).",example:"daimon down",needsDaemon:!0},{name:"history",args:"<name>",summary:"Summary metrics (uptime%, restarts, compile p50/p95, top errors).",example:"daimon history web-admin",needsDaemon:!0},{name:"why",args:"<name>",summary:"Last status transition + 5 preceding events.",example:"daimon why web-admin",needsDaemon:!0},{name:"why-empty",args:"",summary:"Explain why `daimon list` is empty: configured searchRoots, scanned/rejected counts, suggested next step.",example:"daimon why-empty",needsDaemon:!0},{name:"discover",args:"[--dry-run]",summary:"Run discovery without changing state. Prints _meta: searchRoots, scanned, rejected per folder, suggestion.",example:"daimon discover --dry-run",needsDaemon:!0},{name:"export-config",args:"[--redacted]",summary:'Emit the active config to stdout. --redacted replaces apiToken with "<redacted>" and rewrites home paths to ~/...',example:"daimon export-config --redacted",needsDaemon:!1},{name:"tasks",args:"<name>",summary:"List discovered non-serve tasks.",example:"daimon tasks web-admin",needsDaemon:!0},{name:"run",args:"<name> <task> [--watch] [-- args...]",summary:"Run a discovered task.",example:"daimon run web-admin test",needsDaemon:!0},{name:"snapshot",args:"<name>",summary:"Write a snapshot of app state to ~/.daimon/snapshots.",example:"daimon snapshot web-admin",needsDaemon:!0},{name:"env",args:"<name> [--use <file>]",summary:"List or set the active env file for an app.",example:"daimon env web-admin --use .env.staging",needsDaemon:!0},{name:"clean",args:"<name> [--deep] [--yes]",summary:"Remove build artifacts for an app.",example:"daimon clean web-admin --yes",needsDaemon:!0},{name:"record",args:"",summary:"Toggle session recording.",example:"daimon record",needsDaemon:!0},{name:"replay",args:"<session.jsonl> [--speed N]",summary:"Replay a recorded session.",example:"daimon replay session.jsonl",needsDaemon:!0},{name:"doctor",args:"[--auto-fix] [--dry-run]",summary:"Sanity-check config + env. --auto-fix repairs orphan daemon, stale lock, missing search root, corrupt history db.",example:"daimon doctor --auto-fix",needsDaemon:!1},{name:"free-port",args:"<port> [--force]",summary:"Diagnose / free a port.",example:"daimon free-port 4200 --force",needsDaemon:!1},{name:"daemon",args:"start|stop|status|restart|attach|install-service [--detach] [--headless]",summary:"Manage the daimon daemon.",example:"daimon daemon status",needsDaemon:!1},{name:"claude",args:"install|update|uninstall|status [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]",summary:"Install/update Claude Code integration artifacts.",example:"daimon claude install --all",needsDaemon:!1},{name:"init",args:"[--force] [--auto]",summary:"Create a daimon config in cwd; --auto picks safe defaults (no prompts) for workspaces with nx/angular/vite markers.",example:"daimon init --auto",needsDaemon:!1}];function ur(r){return kt.find(t=>t.name===r)}function pr(){let r=Math.max(...kt.map(t=>t.name.length));return kt.map(t=>`${t.name.padEnd(r)} ${t.summary}`).join(`
|
|
138
|
+
`)}function dr(){return"usage: daimon <"+kt.map(r=>r.name).join("|")+">"}Gt();import rt from"node:fs";import Vo from"node:os";import Y from"node:path";import{fileURLToPath as Zo}from"node:url";dt();var fr=Y.dirname(Zo(import.meta.url)),gr=["status","start","stop","restart","errors","logs","up","doctor","why","wait"],Qo=["daimon-status.md","daimon-start.md","daimon-stop.md","daimon-restart.md","daimon-errors.md","daimon-logs.md","daimon-up.md","daimon-doctor.md","daimon-why.md","daimon-wait.md"];function Se(){return Y.join(Vo.homedir(),".claude")}function Kt(r){return Y.join(r,"daimon.installed.json")}function ti(){let r=[Y.resolve(fr,"templates","claude"),Y.resolve(fr,"..","src","templates","claude")];for(let t of r)if(rt.existsSync(t))return t;throw new Error("claude templates directory not found")}function mr(r){return rt.readFileSync(Y.join(ti(),r),"utf8")}function hr(r,t){let e=new Date().toISOString();return r.replace(/\{\{daimon_version\}\}/g,nt).replace(/\{\{api_port\}\}/g,String(t)).replace(/\{\{generated_at\}\}/g,e).replace(/\{\{commands_table\}\}/g,pr())}function un(r,t){rt.mkdirSync(Y.dirname(r),{recursive:!0}),rt.writeFileSync(r,t,"utf8")}function Xt(r){try{let t=rt.readFileSync(Kt(r),"utf8");return t.charCodeAt(0)===65279&&(t=t.slice(1)),JSON.parse(t)}catch{return null}}function yr(r,t){un(Kt(r),JSON.stringify(t,null,2)+`
|
|
139
|
+
`)}function ei(r){let t=[],e=[],n=r.priorInstalledAt?Date.parse(r.priorInstalledAt):0;for(let s of Qo){let o=Y.join(r.dir,"commands",s),i;try{i=rt.statSync(o)}catch{continue}if(!i.isFile())continue;let a=n>0?i.mtimeMs>n+5e3:!1;try{a?(rt.renameSync(o,o+".bak"),e.push(s),r.onEvent?.({kind:"backed-up",file:s})):(rt.rmSync(o,{force:!0}),t.push(s),r.onEvent?.({kind:"removed",file:s}))}catch{}}return{removed:t,backedUp:e}}function ke(r){let t=[],e=Xt(r.dir),n=e??{"daimon-version":nt,"installed-at":new Date().toISOString()};n["daimon-version"]=nt,n["installed-at"]=new Date().toISOString();let s=ei({dir:r.dir,priorInstalledAt:e?.["installed-at"],onEvent:r.onMigrationEvent});if(n.commands=[],(s.removed.length||s.backedUp.length)&&(n.migrated={removedCommands:s.removed,backedUpCommands:s.backedUp}),r.skill){let o=Y.join("skills","daimon","SKILL.md");un(Y.join(r.dir,o),hr(mr("skill.md.tmpl"),r.apiPort)),n.skill={path:o.replace(/\\/g,"/")},t.push(o)}if(r.agent){let o=Y.join("agents","daimon-runner.md");un(Y.join(r.dir,o),hr(mr("agent.md.tmpl"),r.apiPort)),n.agent={path:o.replace(/\\/g,"/")},t.push(o)}return yr(r.dir,n),{installed:t,manifestPath:Kt(r.dir),migrated:s}}function wr(r){let t=[],e=Xt(r.dir);if(!e)return{removed:t,manifestPath:null};let n=r.selection.all;if((n||r.selection.skill)&&e.skill){let s=Y.join(r.dir,e.skill.path);try{rt.rmSync(s,{force:!0}),t.push(e.skill.path)}catch{}try{rt.rmdirSync(Y.dirname(s))}catch{}e.skill=null}if((n||r.selection.commands)&&e.commands){for(let s of e.commands){let o=Y.join("commands",`daimon-${s}.md`);try{rt.rmSync(Y.join(r.dir,o),{force:!0}),t.push(o)}catch{}}e.commands=[]}if((n||r.selection.agent)&&e.agent){try{rt.rmSync(Y.join(r.dir,e.agent.path),{force:!0}),t.push(e.agent.path)}catch{}e.agent=null}if(!e.skill&&(!e.commands||e.commands.length===0)&&!e.agent){try{rt.unlinkSync(Kt(r.dir))}catch{}return{removed:t,manifestPath:null}}return yr(r.dir,e),{removed:t,manifestPath:Kt(r.dir)}}function br(r){let t=Xt(r);return t?{skill:{installed:!!t.skill,version:t.skill?t["daimon-version"]:null,path:t.skill?.path??null},commands:{installed:!!(t.commands&&t.commands.length),version:t.commands&&t.commands.length?t["daimon-version"]:null,names:t.commands??[]},agent:{installed:!!t.agent,version:t.agent?t["daimon-version"]:null,path:t.agent?.path??null},manifestPath:Kt(r)}:{skill:{installed:!1,version:null,path:null},commands:{installed:!1,version:null,names:[]},agent:{installed:!1,version:null,path:null},manifestPath:null}}var ln=Y.join(at(),".claude-nudge"),ni=1440*60*1e3;function vr(){if(process.env.DAIMON_NO_CLAUDE_NUDGE==="1")return;let r=Se(),t=Xt(r);if(t&&t["daimon-version"]!==nt){try{let e=rt.statSync(ln);if(Date.now()-e.mtimeMs<ni)return}catch{}process.stderr.write(`[daimon] claude integration is from v${t["daimon-version"]} \u2014 run \`daimon claude update\` to refresh
|
|
140
|
+
`);try{rt.mkdirSync(Y.dirname(ln),{recursive:!0}),rt.writeFileSync(ln,String(Date.now()))}catch{}}}var xo=Number((process.versions.node||"0").split(".")[0]);xo&&xo<20&&(process.stderr.write(`daimon requires Node >= 20
|
|
141
|
+
`),process.exit(1));var To=!1;function C(r,t=1){process.stderr.write(r.endsWith(`
|
|
129
142
|
`)?r:r+`
|
|
130
|
-
`),process.exit(t)}function
|
|
131
|
-
`)}function
|
|
132
|
-
`);
|
|
133
|
-
`)}
|
|
134
|
-
`)}catch(
|
|
143
|
+
`),process.exit(t)}function $(r){process.stdout.write(JSON.stringify(r)+`
|
|
144
|
+
`)}function Un(){if(process.env.DAIMON_PORT){let t=Number(process.env.DAIMON_PORT);if(Number.isFinite(t)&&t>0)return t}let r=st();if(r)return r.apiPort;try{let t=et();if(t.kind==="loaded")return t.config.apiPort}catch{}return 4999}async function zc(){try{let r=et();if(r.kind==="loaded")return{config:r.config}}catch{}return{config:{}}}function le(){return`http://127.0.0.1:${Un()}`}async function We(){if(!(To||process.env.DAIMON_NO_SPAWN==="1")&&!st())try{let r=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0;await St({port:Number.isFinite(r)&&r>0?r:void 0})}catch{}}function mt(){let r=process.env.DAIMON_TOKEN;return r?{authorization:`Bearer ${r}`}:{}}async function Bn(r,t="GET"){try{let e=await fetch(le()+r,{method:t,headers:mt()});(!e.ok||!e.body)&&C(JSON.stringify({error:`stream failed: HTTP ${e.status}`}));let n=e.body.getReader(),s=new TextDecoder,o="";for(;;){let{done:i,value:a}=await n.read();if(i)break;o+=s.decode(a,{stream:!0});let l=o.split(`
|
|
145
|
+
`);o=l.pop()??"";for(let c of l)c.trim()&&process.stdout.write(c+`
|
|
146
|
+
`)}o.trim()&&process.stdout.write(o+`
|
|
147
|
+
`)}catch(e){C(JSON.stringify({error:e?.message||String(e)}))}}async function J(r,t="GET"){try{let e=await fetch(le()+r,{method:t,headers:mt()}),n=await e.text(),s=n;try{s=JSON.parse(n)}catch{}return{status:e.status,body:s}}catch{C(JSON.stringify({error:"daimon is not running \u2014 start it with: daimon daemon start --detach"}))}}async function Ge(r,t,e){try{let n=await fetch(le()+r,{method:t,headers:{"content-type":"application/json",...mt()},body:JSON.stringify(e)}),s=await n.text(),o=s;try{o=JSON.parse(s)}catch{}return{status:n.status,body:o}}catch{C(JSON.stringify({error:"daimon is not running \u2014 start it with: daimon daemon start --detach"}))}}function qe(r){let t={tags:[],positional:[],passthrough:[]},e=!1;for(let n=0;n<r.length;n++){let s=r[n];if(e){t.passthrough.push(s);continue}if(s==="--"){e=!0;continue}s==="--tail"?t.tail=Number(r[++n]):s==="--since"?t.since=r[++n]:s==="--since-last"?t.sinceLast=!0:s==="--client"?t.client=r[++n]:s==="--structured"?t.structured=!0:s==="--until"?t.until=r[++n]:s==="--timeout"?t.timeout=r[++n]:s==="--app"?t.app=r[++n]:s==="--tag"?t.tags.push(r[++n]):s==="--with-deps"?t.withDeps=!0:s==="--watch"?t.watch=!0:s==="--force"?t.force=!0:s==="--yes"?t.yes=!0:s==="--deep"?t.deep=!0:s==="--use"?t.use=r[++n]:s==="--speed"?t.speed=Number(r[++n]):s==="--task"?t.task=r[++n]:s==="--headless"?t.headless=!0:s==="--detach"?t.detach=!0:s==="--workspace"?t.workspace=r[++n]:s==="--full"?t.full=!0:s==="--compact"?t.compact=!0:s==="--profile"?t.profile=r[++n]:s==="--stream"?t.stream=!0:s==="--explain"?t.explain=!0:s==="--auto-fix"?t.autoFix=!0:s==="--dry-run"?t.dryRun=!0:s==="--auto"?t.auto=!0:s==="--redacted"?t.redacted=!0:s==="--budget"?t.budget=Number(r[++n]):s==="--accept"?t.accept=!0:s==="--path"?t.path=r[++n]:s==="--goal"?t.goal=r[++n]:t.positional.push(s)}return t}function Yc(r){return r.full?"?format=full":r.compact?"?format=compact":""}function ee(r){let t=r.match(/^(\d+)(ms|s|m|h)?$/);if(!t)return null;let e=Number(t[1]);switch(t[2]||"s"){case"ms":return e/1e3;case"s":return e;case"m":return e*60;case"h":return e*60*60}return null}function Vc(){let r=Math.max(...kt.map(e=>e.name.length)),t=[`daimon v${nt}`,"usage: daimon <command> [args]",""];for(let e of kt)t.push(` ${e.name.padEnd(r)} ${e.summary}`);t.push(""),t.push("Flags: --no-spawn (skip auto-spawn), DAIMON_PORT=N (target a non-default daemon), DAIMON_NO_SPAWN=1"),process.stdout.write(t.join(`
|
|
135
148
|
`)+`
|
|
136
|
-
`)}function Wa(r){let t={},e=[];for(let n=0;n<r.length;n++){let s=r[n];s==="--skill"?t.skill=!0:s==="--commands"?t.commands=!0:s==="--agent"?t.agent=!0:s==="--all"?t.all=!0:s==="--dir"?t.dir=r[++n]:s==="--yes"?t.yes=!0:e.push(s)}return{positional:e,flags:t}}async function Ga(r){let t=r[0];t||R(JSON.stringify({error:"usage: daimon claude <install|update|uninstall|status> [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]"}));let{flags:e}=Wa(r.slice(1)),n=e.dir??se(),s=xn();if(t==="status"){E(Vn(n));return}if(t==="install"){let o,i=e.skill||e.commands||e.agent||e.all;if(e.all||e.yes||!i&&!process.stdin.isTTY)o={skill:!0,commands:!1,agent:!0};else if(i)o={skill:!!e.skill,commands:!1,agent:!!e.agent};else{let{promptClaudeInstall:l}=await Promise.resolve().then(()=>(nr(),er)),c=await l();if(!c){E({cancelled:!0});return}o={skill:c.skill,commands:!1,agent:c.agent}}let a=oe({...o,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?E({removed:l.file}):E({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});E({installed:a.installed,manifest:a.manifestPath,version:G});return}if(t==="update"){let o=Mt(n);o||R(JSON.stringify({error:"no manifest at "+n+" \u2014 run `daimon claude install` first"}));let i={skill:!!o.skill,commands:!1,agent:!!o.agent},a=oe({...i,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?E({removed:l.file}):E({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});E({updated:a.installed,manifest:a.manifestPath,version:G});return}if(t==="uninstall"){e.skill||e.commands||e.agent||e.all||R(JSON.stringify({error:"usage: daimon claude uninstall [--all|--skill|--commands|--agent]"}));let i=zn({dir:n,selection:{all:e.all,skill:e.skill,commands:e.commands,agent:e.agent}});E({removed:i.removed,manifest:i.manifestPath});return}R(JSON.stringify({error:`unknown claude subcommand: ${t}`}))}async function qa(r){let t=r[0],e=Oe(r.slice(1));switch(t){case"status":{let n=K();if(!n){E({running:!1});return}let s=Date.now()-n.startedAt;E({running:!0,pid:n.pid,port:n.apiPort,uptime:s,version:n.version,headless:n.headless});return}case"start":{if(e.detach){let s=K();if(s){E({ok:!0,alreadyRunning:!0,pid:s.pid,port:s.apiPort});return}try{let o=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,i=await dt({port:Number.isFinite(o)&&o>0?o:void 0});E({ok:!0,pid:i.pid,port:i.apiPort})}catch(o){R(JSON.stringify({error:o?.message||String(o)}))}return}let{startInProcess:n}=await Promise.resolve().then(()=>(Cs(),Ts));await n({headless:!!e.headless});return}case"stop":{let n=K();if(!n){E({ok:!0,wasRunning:!1});return}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:ot()})}catch{}if(await kt(n.pid,5e3))et(),E({ok:!0,wasRunning:!0});else{try{process.kill(n.pid,"SIGTERM")}catch{}await kt(n.pid,2e3),et(),E({ok:!0,wasRunning:!0,forced:!0})}return}case"restart":{let n=K();if(n){try{await fetch(`http://127.0.0.1:${n.apiPort}/api/snapshot-state`,{method:"POST",headers:ot()})}catch{}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:ot()})}catch{}await kt(n.pid,5e3),et()}let s=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,o=await dt({port:Number.isFinite(s)&&s>0?s:void 0});E({ok:!0,pid:o.pid,port:o.apiPort,handoff:!0});return}case"attach":{await Re();let n=K();n||R(JSON.stringify({error:"no daemon running and auto-spawn failed"}));let{attachToDaemon:s}=await Promise.resolve().then(()=>(Rs(),Ps));await s(n.apiPort);return}case"install-service":{let{installServiceArtifact:n}=await Promise.resolve().then(()=>(Ds(),js)),s=n();E({platform:s.platform,artifact:s.path,installCmd:s.installCmd});return}default:R(JSON.stringify({error:"usage: daimon daemon <start|stop|status|restart|attach|install-service> [--detach] [--headless]"}))}}async function Xa(){let r=process.argv.slice(2).filter(o=>o==="--no-spawn"?(Bs=!0,!1):!0),[t,...e]=r;try{Qn()}catch{}if(!t||t==="--help"||t==="-h"||t==="help"){Ja();return}if(t==="--version"||t==="-v"){E({version:G});return}if(t==="daemon"){await qa(e);return}if(t==="claude"){await Ga(e);return}if(t==="export-config"){let o=V();o.kind!=="loaded"&&R(JSON.stringify({error:"no config loaded"}));let i=Oe(e),a=JSON.parse(JSON.stringify(o.config));if(i.redacted){let l=Ua.homedir().replace(/\\/g,"/"),c=d=>{if(typeof d!="string")return d;let p=d.replace(/\\/g,"/");return p.toLowerCase().startsWith(l.toLowerCase())?"~"+p.slice(l.length):d};a.apiToken!=null&&a.apiToken!==""&&(a.apiToken="<redacted>"),a.history?.path&&(a.history.path=c(a.history.path)),a.logs?.dir&&(a.logs.dir=c(a.logs.dir)),Array.isArray(a.searchRoots)&&(a.searchRoots=a.searchRoots.map(d=>typeof d=="string"?c(d):{...d,path:c(d.path)}))}E(a);return}if(t==="discover"){await Re();let o=await U("/api/discovery/explain");o.status!==200&&R(JSON.stringify({error:"discovery failed",status:o.status})),E(o.body);return}if(t==="init"){let{runInit:o}=await Promise.resolve().then(()=>(_s(),Ls)),i=Oe(e);try{let a=await o({force:!!i.force,auto:!!i.auto});if(E({path:a.path,installClaude:a.installClaude,auto:a.auto}),a.installClaude){let c=xn(),d=oe({skill:!0,commands:!1,agent:!0,dir:se(),apiPort:c,onMigrationEvent:p=>{p.kind==="removed"?E({removed:p.file}):E({warning:`${p.file} was modified; backing up to ${p.file}.bak`})}});E({claudeInstalled:d.installed})}let l=K();if(l){try{await fetch(`http://127.0.0.1:${l.apiPort}/api/snapshot-state`,{method:"POST",headers:ot()})}catch{}try{await fetch(`http://127.0.0.1:${l.apiPort}/api/shutdown`,{method:"POST",headers:ot()})}catch{}await kt(l.pid,5e3),et();try{let c=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,d=await dt({port:Number.isFinite(c)&&c>0?c:void 0});E({daemonRestarted:!0,pid:d.pid,port:d.apiPort})}catch(c){E({daemonRestarted:!1,error:c?.message||String(c)})}}try{await Re();let c=await fetch(Kt()+"/api/discovery/explain",{headers:ot()});if(c.ok){let d=await c.json(),p={};try{let h=await(await fetch(Kt()+"/api/apps?format=full",{headers:ot()})).json();if(Array.isArray(h))for(let g of h){let m=g.workspaceType??"unknown";p[m]=(p[m]??0)+1}}catch{}let y=d.appsFound??0,S={init:"ok",configPath:a.path,discovered:{apps:y,byKind:p}};y===0&&(S._meta={searchRoots:d.searchRoots,scanned:d.scanned,rejected:d.rejected,suggestion:d.suggestion},S.warning="discovery found 0 apps; see _meta.suggestion"),E(S)}}catch{}}catch(a){R(JSON.stringify({error:a?.message||String(a)}))}return}let n=Oe(e);switch(Hn(t)?.needsDaemon&&await Re(),t){case"list":{let o=n.full||(n.tags.length||n.workspace)&&!n.compact,i=new URLSearchParams;if(o?i.set("format","full"):n.compact&&i.set("format","compact"),n.explain&&i.set("explain","1"),n.stream){i.set("stream","ndjson");let d=i.toString();await Us("/api/apps"+(d?"?"+d:""));return}let a=i.toString(),l=await U("/api/apps"+(a?"?"+a:""));if(n.explain){E(l.body);return}let c=Array.isArray(l.body)?l.body:[];n.tags.length&&(c=c.filter(d=>n.tags.every(p=>(d.tags||[]).includes(p)))),n.workspace&&(c=c.filter(d=>d.workspaceLabel===n.workspace)),E(c);return}case"why-empty":{let o=await U("/api/apps?explain=1");E(o.body);return}case"status":case"stop":case"restart":{let o=n.positional[0];o||R(JSON.stringify({error:`usage: daimon ${t} <name>`}));let i=t==="status"?"":"/"+t,a=t==="status"?"GET":"POST",l=t==="status"?Ha(n):"",c=await U(`/api/apps/${encodeURIComponent(o)}${i}${l}`,a);c.status===404&&R(JSON.stringify({error:"unknown app"})),E(c.body);return}case"start":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon start <name> [--with-deps]"}));let i=n.withDeps?"?withDeps=1":"",a=await U(`/api/apps/${encodeURIComponent(o)}/start${i}`,"POST");a.status===404&&R(JSON.stringify({error:"unknown app"})),E(a.body);return}case"history":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon history <name>"}));let i=await U(`/api/history/summary/${encodeURIComponent(o)}`);E(i.body);return}case"why":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon why <name>"}));let i=await U(`/api/history/why/${encodeURIComponent(o)}`);E(i.body);return}case"env":{let o=n.positional[0];if(o||R(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),n.use){let a=await Sn(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:n.use});a.status===404&&R(JSON.stringify({error:"unknown app"})),E(a.body);return}let i=await U(`/api/apps/${encodeURIComponent(o)}/env`);i.status===404&&R(JSON.stringify({error:"unknown app"})),E(i.body);return}case"clean":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon clean <name> [--deep] [--yes]"}));let i=new URLSearchParams;n.deep&&i.set("deep","1"),n.yes&&i.set("yes","1");let a=await U(`/api/apps/${encodeURIComponent(o)}/clean${i.toString()?"?"+i.toString():""}`,"POST");a.status===404&&R(JSON.stringify({error:"unknown app"})),a.status===409&&(E(a.body),process.exit(1)),E(a.body);return}case"record":{let o=await U("/api/session/record?action=toggle","POST");E(o.body);return}case"replay":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon replay <session.jsonl> [--speed N]"}));let i=n.speed&&n.speed>0?n.speed:1,a;try{a=_n(o)}catch(c){R(JSON.stringify({error:c?.message||String(c)}))}let l=0;for(let c of a){let d=Math.max(0,(c.ts-l)/i);d>0&&await new Promise(p=>setTimeout(p,d)),l=c.ts,c.kind==="run"?await Sn(`/api/apps/${encodeURIComponent(c.app)}/run/${encodeURIComponent(c.task||"")}`,"POST",{args:c.args||[]}):await U(`/api/apps/${encodeURIComponent(c.app)}/${c.kind}`,"POST")}E({replayed:a.length,file:o});return}case"doctor":{let o=V();if(o.kind!=="loaded"&&R(JSON.stringify({error:"no config loaded"})),n.autoFix){let{runAutoFix:c,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(nn(),en)),p=o.config.doctor?.autoFix?.permitted??d,y=await c({permitted:p,dryRun:!!n.dryRun});E(y),y.errors.length&&process.exit(1);return}let i=[],a=bt(o.config,{warnings:i}),l=await jn(o.config,a);for(let c of i)l.checks.unshift({name:`discovery: ${c}`,ok:!1,detail:c});i.length&&(l.ok=!1),E(l),l.ok||process.exit(1);return}case"free-port":{let o=Number(n.positional[0]);(!Number.isFinite(o)||o<=0)&&R(JSON.stringify({error:"usage: daimon free-port <port> [--force]"}));let i=Zt(o);if(!i){E({port:o,free:!0});return}if(!n.force){E({port:o,free:!1,holder:i});return}i.pid===process.pid&&R(JSON.stringify({error:"refuse to kill daimon itself",holder:i}));let a=await In(i);E({port:o,killed:a,holder:i}),a||process.exit(1);return}case"snapshot":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon snapshot <name>"}));let i=await U(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");i.status===404&&R(JSON.stringify({error:"unknown app"})),E(i.body);return}case"tasks":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon tasks <name>"}));let i=await U(`/api/apps/${encodeURIComponent(o)}/tasks`);i.status===404&&R(JSON.stringify({error:"unknown app"})),E(i.body);return}case"run":{let o=n.positional[0],i=n.positional[1];(!o||!i)&&R(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"}));let a={args:n.passthrough,watch:!!n.watch},l=await Sn(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(i)}`,"POST",a);l.status===404&&R(JSON.stringify({error:"unknown app"})),E(l.body),!n.watch&&typeof l.body?.exitCode=="number"&&process.exit(l.body.exitCode===0?0:1);return}case"errors":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon errors <name> [--since 2m] [--since-last] [--client <id>] [--structured] [--full|--compact]"}));let i=new URLSearchParams,a=`/api/apps/${encodeURIComponent(o)}/errors`;n.sinceLast?(a+="/since-last",n.client&&i.set("client",n.client)):n.since&&i.set("since",n.since),n.full?i.set("format","full"):n.compact&&i.set("format","compact");let l=i.toString(),c=await U(a+(l?"?"+l:""));c.status===404&&R(JSON.stringify({error:"unknown app"}));let d=c.body;n.structured&&Array.isArray(d)&&(d=d.map(p=>p.parsed??{message:p.message})),E(d);return}case"events":{let o=new URLSearchParams;if(n.since&&o.set("since",n.since),n.app&&o.set("app",n.app),n.stream){o.set("stream","ndjson");let l=o.toString();await Us("/api/events"+(l?"?"+l:""));return}let i=o.toString(),a=await U("/api/events"+(i?"?"+i:""));E(a.body);return}case"ensure":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon ensure <name> [--until serving|healthy] [--timeout 180s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&R(JSON.stringify({error:"ensure --until must be serving|healthy"})),i.set("until",a);let l=180;if(n.timeout){let d=kn(n.timeout);d==null&&R(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(d,600)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await U(`/api/apps/${encodeURIComponent(o)}/ensure?${i.toString()}`,"POST");c.status===404&&R(JSON.stringify({error:"unknown app"})),E(c.body),c.body?.error==="timeout"&&process.exit(2);return}case"ensure-up":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon ensure-up <profile> [--until serving|healthy] [--timeout 300s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&R(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),i.set("until",a);let l=300;if(n.timeout){let p=kn(n.timeout);p==null&&R(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(p,1200)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await U(`/api/profiles/${encodeURIComponent(o)}/ensure-up?${i.toString()}`,"POST");c.status===404&&R(JSON.stringify({error:"unknown profile"})),E(c.body),Array.isArray(c.body?.apps)&&c.body.apps.some(p=>p.timedOut)&&process.exit(2);return}case"overview":{let o=new URLSearchParams;n.workspace&&o.set("workspace",n.workspace),n.profile&&o.set("profile",n.profile);let i=o.toString(),a=await U("/api/overview"+(i?"?"+i:""));E(a.body);return}case"wait":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon wait <name> [--until serving|healthy|stopped|error] [--timeout 60s]"}));let i=new URLSearchParams;n.until&&i.set("until",n.until);let a=120;if(n.timeout){let c=kn(n.timeout);c==null&&R(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),a=Math.min(c,600)}i.set("timeout",String(Math.ceil(a)));let l=await U(`/api/apps/${encodeURIComponent(o)}/wait?${i.toString()}`);l.status===404&&R(JSON.stringify({error:"unknown app"})),E(l.body),l.body?.timedOut&&process.exit(2);return}case"up":case"down":{let o=n.positional[0],i=await U("/api/apps"),a=Array.isArray(i.body)?i.body:[],l=(await Ba()).config,c;if(!o)c=l.autoStart||[],t==="up"&&c.length===0&&R(JSON.stringify({error:"no autoStart configured and no profile given"})),t==="down"&&c.length===0&&(c=a.map(u=>u.name));else{let u=l.profiles?.[o];u||R(JSON.stringify({error:`unknown profile: ${o}`})),c=u}let d=t==="up"?"start":"stop";if(t==="up"?await Promise.all(c.map(u=>U(`/api/apps/${encodeURIComponent(u)}/start?withDeps=1`,"POST"))):await Promise.all(c.map(u=>U(`/api/apps/${encodeURIComponent(u)}/${d}`,"POST"))),t==="up"){let h=Date.now(),g=()=>Math.max(5,Math.floor((12e4-(Date.now()-h))/1e3));await Promise.all(c.map(m=>U(`/api/apps/${encodeURIComponent(m)}/wait?until=serving&timeout=${g()}`)))}else await Promise.all(c.map(u=>U(`/api/apps/${encodeURIComponent(u)}/wait?until=stopped&timeout=10`)));let p=await U("/api/apps"),S=(Array.isArray(p.body)?p.body:[]).filter(u=>c.includes(u.name)).map(u=>({name:u.name,status:u.status,health:u.health}));E(S);return}case"logs":{let o=n.positional[0];o||R(JSON.stringify({error:"usage: daimon logs <name> [--tail N] [--since 30s]"}));let i=new URLSearchParams;n.tail!=null&&!Number.isNaN(n.tail)&&i.set("tail",String(n.tail)),n.since&&i.set("since",n.since);let a=i.toString(),l=await U(`/api/apps/${encodeURIComponent(o)}/logs${a?"?"+a:""}`);l.status===404&&R(JSON.stringify({error:"unknown app"})),E(l.body);return}default:R(JSON.stringify({error:`unknown command: ${t}. ${Wn()}`}))}}Xa().catch(r=>R(JSON.stringify({error:r?.message||String(r)})));
|
|
149
|
+
`)}function Zc(r){let t={},e=[];for(let n=0;n<r.length;n++){let s=r[n];s==="--skill"?t.skill=!0:s==="--commands"?t.commands=!0:s==="--agent"?t.agent=!0:s==="--all"?t.all=!0:s==="--dir"?t.dir=r[++n]:s==="--yes"?t.yes=!0:e.push(s)}return{positional:e,flags:t}}async function Qc(r){let t=r[0];t||C(JSON.stringify({error:"usage: daimon claude <install|update|uninstall|status> [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]"}));let{flags:e}=Zc(r.slice(1)),n=e.dir??Se(),s=Un();if(t==="status"){$(br(n));return}if(t==="install"){let o,i=e.skill||e.commands||e.agent||e.all;if(e.all||e.yes||!i&&!process.stdin.isTTY)o={skill:!0,commands:!1,agent:!0};else if(i)o={skill:!!e.skill,commands:!1,agent:!!e.agent};else{let{promptClaudeInstall:l}=await Promise.resolve().then(()=>(Tr(),xr)),c=await l();if(!c){$({cancelled:!0});return}o={skill:c.skill,commands:!1,agent:c.agent}}let a=ke({...o,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?$({removed:l.file}):$({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});$({installed:a.installed,manifest:a.manifestPath,version:nt});return}if(t==="update"){let o=Xt(n);o||C(JSON.stringify({error:"no manifest at "+n+" \u2014 run `daimon claude install` first"}));let i={skill:!!o.skill,commands:!1,agent:!!o.agent},a=ke({...i,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?$({removed:l.file}):$({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});$({updated:a.installed,manifest:a.manifestPath,version:nt});return}if(t==="uninstall"){e.skill||e.commands||e.agent||e.all||C(JSON.stringify({error:"usage: daimon claude uninstall [--all|--skill|--commands|--agent]"}));let i=wr({dir:n,selection:{all:e.all,skill:e.skill,commands:e.commands,agent:e.agent}});$({removed:i.removed,manifest:i.manifestPath});return}C(JSON.stringify({error:`unknown claude subcommand: ${t}`}))}async function tl(r){let t=r[0],e=qe(r.slice(1));switch(t){case"status":{let n=st();if(!n){$({running:!1});return}let s=Date.now()-n.startedAt;$({running:!0,pid:n.pid,port:n.apiPort,uptime:s,version:n.version,headless:n.headless});return}case"start":{if(e.detach){let s=st();if(s){$({ok:!0,alreadyRunning:!0,pid:s.pid,port:s.apiPort});return}try{let o=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,i=await St({port:Number.isFinite(o)&&o>0?o:void 0});$({ok:!0,pid:i.pid,port:i.apiPort})}catch(o){C(JSON.stringify({error:o?.message||String(o)}))}return}let{startInProcess:n}=await Promise.resolve().then(()=>(co(),ao));await n({headless:!!e.headless});return}case"stop":{let n=st();if(!n){$({ok:!0,wasRunning:!1});return}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:mt()})}catch{}if(await jt(n.pid,5e3))pt(),$({ok:!0,wasRunning:!0});else{try{process.kill(n.pid,"SIGTERM")}catch{}await jt(n.pid,2e3),pt(),$({ok:!0,wasRunning:!0,forced:!0})}return}case"restart":{let n=st();if(n){try{await fetch(`http://127.0.0.1:${n.apiPort}/api/snapshot-state`,{method:"POST",headers:mt()})}catch{}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:mt()})}catch{}await jt(n.pid,5e3),pt()}let s=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,o=await St({port:Number.isFinite(s)&&s>0?s:void 0});$({ok:!0,pid:o.pid,port:o.apiPort,handoff:!0});return}case"attach":{await We();let n=st();n||C(JSON.stringify({error:"no daemon running and auto-spawn failed"}));let{attachToDaemon:s}=await Promise.resolve().then(()=>(fo(),po));await s(n.apiPort);return}case"install-service":{let{installServiceArtifact:n}=await Promise.resolve().then(()=>(wo(),yo)),s=n();$({platform:s.platform,artifact:s.path,installCmd:s.installCmd});return}default:C(JSON.stringify({error:"usage: daimon daemon <start|stop|status|restart|attach|install-service> [--detach] [--headless]"}))}}async function el(){let r=process.argv.slice(2).filter(o=>o==="--no-spawn"?(To=!0,!1):!0),[t,...e]=r;try{vr()}catch{}if(!t||t==="--help"||t==="-h"||t==="help"){Vc();return}if(t==="--version"||t==="-v"){$({version:nt});return}if(t==="daemon"){await tl(e);return}if(t==="claude"){await Qc(e);return}if(t==="export-config"){let o=et();o.kind!=="loaded"&&C(JSON.stringify({error:"no config loaded"}));let i=qe(e),a=JSON.parse(JSON.stringify(o.config));if(i.redacted){let l=Xc.homedir().replace(/\\/g,"/"),c=d=>{if(typeof d!="string")return d;let u=d.replace(/\\/g,"/");return u.toLowerCase().startsWith(l.toLowerCase())?"~"+u.slice(l.length):d};a.apiToken!=null&&a.apiToken!==""&&(a.apiToken="<redacted>"),a.history?.path&&(a.history.path=c(a.history.path)),a.logs?.dir&&(a.logs.dir=c(a.logs.dir)),Array.isArray(a.searchRoots)&&(a.searchRoots=a.searchRoots.map(d=>typeof d=="string"?c(d):{...d,path:c(d.path)}))}$(a);return}if(t==="discover"){await We();let o=await J("/api/discovery/explain");o.status!==200&&C(JSON.stringify({error:"discovery failed",status:o.status})),$(o.body);return}if(t==="init"){let{runInit:o}=await Promise.resolve().then(()=>(ko(),So)),i=qe(e);try{let a=await o({force:!!i.force,auto:!!i.auto});if($({path:a.path,installClaude:a.installClaude,auto:a.auto}),a.installClaude){let c=Un(),d=ke({skill:!0,commands:!1,agent:!0,dir:Se(),apiPort:c,onMigrationEvent:u=>{u.kind==="removed"?$({removed:u.file}):$({warning:`${u.file} was modified; backing up to ${u.file}.bak`})}});$({claudeInstalled:d.installed})}let l=st();if(l){try{await fetch(`http://127.0.0.1:${l.apiPort}/api/snapshot-state`,{method:"POST",headers:mt()})}catch{}try{await fetch(`http://127.0.0.1:${l.apiPort}/api/shutdown`,{method:"POST",headers:mt()})}catch{}await jt(l.pid,5e3),pt();try{let c=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,d=await St({port:Number.isFinite(c)&&c>0?c:void 0});$({daemonRestarted:!0,pid:d.pid,port:d.apiPort})}catch(c){$({daemonRestarted:!1,error:c?.message||String(c)})}}try{await We();let c=await fetch(le()+"/api/discovery/explain",{headers:mt()});if(c.ok){let d=await c.json(),u={};try{let h=await(await fetch(le()+"/api/apps?format=full",{headers:mt()})).json();if(Array.isArray(h))for(let m of h){let f=m.workspaceType??"unknown";u[f]=(u[f]??0)+1}}catch{}let y=d.appsFound??0,b={init:"ok",configPath:a.path,discovered:{apps:y,byKind:u}};y===0&&(b._meta={searchRoots:d.searchRoots,scanned:d.scanned,rejected:d.rejected,suggestion:d.suggestion},b.warning="discovery found 0 apps; see _meta.suggestion"),$(b)}}catch{}}catch(a){C(JSON.stringify({error:a?.message||String(a)}))}return}let n=qe(e);switch(ur(t)?.needsDaemon&&await We(),t){case"list":{let o=n.full||(n.tags.length||n.workspace)&&!n.compact,i=new URLSearchParams;if(o?i.set("format","full"):n.compact&&i.set("format","compact"),n.explain&&i.set("explain","1"),n.stream){i.set("stream","ndjson");let d=i.toString();await Bn("/api/apps"+(d?"?"+d:""));return}let a=i.toString(),l=await J("/api/apps"+(a?"?"+a:""));if(n.explain){$(l.body);return}let c=Array.isArray(l.body)?l.body:[];n.tags.length&&(c=c.filter(d=>n.tags.every(u=>(d.tags||[]).includes(u)))),n.workspace&&(c=c.filter(d=>d.workspaceLabel===n.workspace)),$(c);return}case"why-empty":{let o=await J("/api/apps?explain=1");$(o.body);return}case"status":case"stop":case"restart":{let o=n.positional[0];o||C(JSON.stringify({error:`usage: daimon ${t} <name>`}));let i=t==="status"?"":"/"+t,a=t==="status"?"GET":"POST",l=t==="status"?Yc(n):"",c=await J(`/api/apps/${encodeURIComponent(o)}${i}${l}`,a);c.status===404&&C(JSON.stringify({error:"unknown app"})),$(c.body);return}case"start":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon start <name> [--with-deps]"}));let i=n.withDeps?"?withDeps=1":"",a=await J(`/api/apps/${encodeURIComponent(o)}/start${i}`,"POST");a.status===404&&C(JSON.stringify({error:"unknown app"})),$(a.body);return}case"history":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon history <name>"}));let i=await J(`/api/history/summary/${encodeURIComponent(o)}`);$(i.body);return}case"why":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon why <name>"}));let i=await J(`/api/history/why/${encodeURIComponent(o)}`);$(i.body);return}case"env":{let o=n.positional[0];if(o||C(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),n.use){let a=await Ge(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:n.use});a.status===404&&C(JSON.stringify({error:"unknown app"})),$(a.body);return}let i=await J(`/api/apps/${encodeURIComponent(o)}/env`);i.status===404&&C(JSON.stringify({error:"unknown app"})),$(i.body);return}case"clean":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon clean <name> [--deep] [--yes]"}));let i=new URLSearchParams;n.deep&&i.set("deep","1"),n.yes&&i.set("yes","1");let a=await J(`/api/apps/${encodeURIComponent(o)}/clean${i.toString()?"?"+i.toString():""}`,"POST");a.status===404&&C(JSON.stringify({error:"unknown app"})),a.status===409&&($(a.body),process.exit(1)),$(a.body);return}case"record":{let o=await J("/api/session/record?action=toggle","POST");$(o.body);return}case"replay":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon replay <session.jsonl> [--speed N]"}));let i=n.speed&&n.speed>0?n.speed:1,a;try{a=ir(o)}catch(c){C(JSON.stringify({error:c?.message||String(c)}))}let l=0;for(let c of a){let d=Math.max(0,(c.ts-l)/i);d>0&&await new Promise(u=>setTimeout(u,d)),l=c.ts,c.kind==="run"?await Ge(`/api/apps/${encodeURIComponent(c.app)}/run/${encodeURIComponent(c.task||"")}`,"POST",{args:c.args||[]}):await J(`/api/apps/${encodeURIComponent(c.app)}/${c.kind}`,"POST")}$({replayed:a.length,file:o});return}case"doctor":{let o=et();if(o.kind!=="loaded"&&C(JSON.stringify({error:"no config loaded"})),n.autoFix){let{runAutoFix:c,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(Yt(),zt)),u=o.config.doctor?.autoFix?.permitted??d,y=await c({permitted:u,dryRun:!!n.dryRun});$(y),y.errors.length&&process.exit(1);return}let i=[],a=$t(o.config,{warnings:i}),l=await er(o.config,a);for(let c of i)l.checks.unshift({name:`discovery: ${c}`,ok:!1,detail:c});i.length&&(l.ok=!1),$(l),l.ok||process.exit(1);return}case"free-port":{let o=Number(n.positional[0]);(!Number.isFinite(o)||o<=0)&&C(JSON.stringify({error:"usage: daimon free-port <port> [--force]"}));let i=ge(o);if(!i){$({port:o,free:!0});return}if(!n.force){$({port:o,free:!1,holder:i});return}i.pid===process.pid&&C(JSON.stringify({error:"refuse to kill daimon itself",holder:i}));let a=await sr(i);$({port:o,killed:a,holder:i}),a||process.exit(1);return}case"snapshot":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon snapshot <name>"}));let i=await J(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");i.status===404&&C(JSON.stringify({error:"unknown app"})),$(i.body);return}case"tasks":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon tasks <name>"}));let i=await J(`/api/apps/${encodeURIComponent(o)}/tasks`);i.status===404&&C(JSON.stringify({error:"unknown app"})),$(i.body);return}case"run":{let o=n.positional[0],i=n.positional[1];(!o||!i)&&C(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"}));let a={args:n.passthrough,watch:!!n.watch},l=await Ge(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(i)}`,"POST",a);l.status===404&&C(JSON.stringify({error:"unknown app"})),$(l.body),!n.watch&&typeof l.body?.exitCode=="number"&&process.exit(l.body.exitCode===0?0:1);return}case"errors":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon errors <name> [--since 2m] [--since-last] [--client <id>] [--structured] [--full|--compact]"}));let i=new URLSearchParams,a=`/api/apps/${encodeURIComponent(o)}/errors`;n.sinceLast?(a+="/since-last",n.client&&i.set("client",n.client)):n.since&&i.set("since",n.since),n.full?i.set("format","full"):n.compact&&i.set("format","compact");let l=i.toString(),c=await J(a+(l?"?"+l:""));c.status===404&&C(JSON.stringify({error:"unknown app"}));let d=c.body;n.structured&&Array.isArray(d)&&(d=d.map(u=>u.parsed??{message:u.message})),$(d);return}case"events":{let o=new URLSearchParams;if(n.since&&o.set("since",n.since),n.app&&o.set("app",n.app),n.stream){o.set("stream","ndjson");let l=o.toString();await Bn("/api/events"+(l?"?"+l:""));return}let i=o.toString(),a=await J("/api/events"+(i?"?"+i:""));$(a.body);return}case"ensure":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon ensure <name> [--until serving|healthy] [--timeout 180s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&C(JSON.stringify({error:"ensure --until must be serving|healthy"})),i.set("until",a);let l=180;if(n.timeout){let d=ee(n.timeout);d==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(d,600)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await J(`/api/apps/${encodeURIComponent(o)}/ensure?${i.toString()}`,"POST");c.status===404&&C(JSON.stringify({error:"unknown app"})),$(c.body),c.body?.error==="timeout"&&process.exit(2);return}case"ensure-up":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon ensure-up <profile> [--until serving|healthy] [--timeout 300s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&C(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),i.set("until",a);let l=300;if(n.timeout){let u=ee(n.timeout);u==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(u,1200)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await J(`/api/profiles/${encodeURIComponent(o)}/ensure-up?${i.toString()}`,"POST");c.status===404&&C(JSON.stringify({error:"unknown profile"})),$(c.body),Array.isArray(c.body?.apps)&&c.body.apps.some(u=>u.timedOut)&&process.exit(2);return}case"overview":{let o=new URLSearchParams;n.workspace&&o.set("workspace",n.workspace),n.profile&&o.set("profile",n.profile),n.budget&&Number.isFinite(n.budget)&&n.budget>0&&o.set("budget",String(Math.floor(n.budget)));let i=o.toString(),a=await J("/api/overview"+(i?"?"+i:""));$(a.body);return}case"focus":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon focus <name> [--until serving|healthy|stable] [--timeout 180s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||C(JSON.stringify({error:"focus --until must be serving|healthy|stable"})),i.set("until",a);let l=180;if(n.timeout){let c=ee(n.timeout);c==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(c,600)}i.set("timeoutMs",String(Math.ceil(l*1e3))),await Bn(`/api/apps/${encodeURIComponent(o)}/focus?${i.toString()}`,"POST");return}case"pin-health":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon pin-health <name> [--accept] [--path <p>]"}));let i=await J(`/api/apps/${encodeURIComponent(o)}?format=full`);i.status===404&&C(JSON.stringify({error:"unknown app"}));let a=i.body?.discoveredHealthPath??null,l=n.path??a??null;if(!n.accept){$({app:o,discoveredHealthPath:a,candidate:l,hint:l?`re-run with --accept to persist ${l} to daimon.config.json`:"no path discovered yet; start the app and wait for first serving"});return}l||C(JSON.stringify({error:"no path to pin \u2014 pass --path or wait for auto-discovery"}));let c=await Ge(`/api/apps/${encodeURIComponent(o)}/health/pin`,"POST",{path:l});c.status===404&&C(JSON.stringify({error:"unknown app"})),$(c.body);return}case"orchestrate":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon orchestrate <profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]"}));let i=new URLSearchParams;i.set("profile",o);let a=(n.goal||n.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||C(JSON.stringify({error:"orchestrate --goal must be serving|healthy|stable"})),i.set("goal",a);let l=300;if(n.timeout){let d=ee(n.timeout);d==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(d,1200)}i.set("timeoutMs",String(Math.ceil(l*1e3))),n.dryRun&&i.set("dryRun","true"),n.budget&&Number.isFinite(n.budget)&&n.budget>0&&i.set("budget",String(Math.floor(n.budget)));let c=await J(`/api/orchestrate?${i.toString()}`,"POST");c.status===404&&C(JSON.stringify(c.body)),c.status===400&&C(JSON.stringify(c.body)),$(c.body),c.body&&c.body.allReached===!1&&process.exit(2);return}case"try-fix":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon try-fix <name> [--until serving|healthy] [--timeout 180s]"}));let i=new URLSearchParams,a=(n.until||"healthy").toLowerCase();["serving","healthy"].includes(a)||C(JSON.stringify({error:"try-fix --until must be serving|healthy"})),i.set("until",a);let l=180;if(n.timeout){let d=ee(n.timeout);d==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(d,600)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await J(`/api/apps/${encodeURIComponent(o)}/try-fix?${i.toString()}`,"POST");c.status===404&&C(JSON.stringify({error:"unknown app"})),$(c.body),c.body&&c.body.reached===!1&&process.exit(2);return}case"wait":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon wait <name> [--until serving|healthy|stopped|error] [--timeout 60s]"}));let i=new URLSearchParams;n.until&&i.set("until",n.until);let a=120;if(n.timeout){let c=ee(n.timeout);c==null&&C(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),a=Math.min(c,600)}i.set("timeout",String(Math.ceil(a)));let l=await J(`/api/apps/${encodeURIComponent(o)}/wait?${i.toString()}`);l.status===404&&C(JSON.stringify({error:"unknown app"})),$(l.body),l.body?.timedOut&&process.exit(2);return}case"up":case"down":{let o=n.positional[0],i=await J("/api/apps"),a=Array.isArray(i.body)?i.body:[],l=(await zc()).config,c;if(!o)c=l.autoStart||[],t==="up"&&c.length===0&&C(JSON.stringify({error:"no autoStart configured and no profile given"})),t==="down"&&c.length===0&&(c=a.map(p=>p.name));else{let p=l.profiles?.[o];p||C(JSON.stringify({error:`unknown profile: ${o}`})),c=p}let d=t==="up"?"start":"stop";if(t==="up"?await Promise.all(c.map(p=>J(`/api/apps/${encodeURIComponent(p)}/start?withDeps=1`,"POST"))):await Promise.all(c.map(p=>J(`/api/apps/${encodeURIComponent(p)}/${d}`,"POST"))),t==="up"){let h=Date.now(),m=()=>Math.max(5,Math.floor((12e4-(Date.now()-h))/1e3));await Promise.all(c.map(f=>J(`/api/apps/${encodeURIComponent(f)}/wait?until=serving&timeout=${m()}`)))}else await Promise.all(c.map(p=>J(`/api/apps/${encodeURIComponent(p)}/wait?until=stopped&timeout=10`)));let u=await J("/api/apps"),b=(Array.isArray(u.body)?u.body:[]).filter(p=>c.includes(p.name)).map(p=>({name:p.name,status:p.status,health:p.health}));$(b);return}case"logs":{let o=n.positional[0];o||C(JSON.stringify({error:"usage: daimon logs <name> [--tail N] [--since 30s]"}));let i=new URLSearchParams;n.tail!=null&&!Number.isNaN(n.tail)&&i.set("tail",String(n.tail)),n.since&&i.set("since",n.since);let a=i.toString(),l=await J(`/api/apps/${encodeURIComponent(o)}/logs${a?"?"+a:""}`);l.status===404&&C(JSON.stringify({error:"unknown app"})),$(l.body);return}default:C(JSON.stringify({error:`unknown command: ${t}. ${dr()}`}))}}el().catch(r=>C(JSON.stringify({error:r?.message||String(r)})));
|