daimon 0.5.0 → 0.6.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 +54 -0
- package/dist/cli.js +71 -67
- package/dist/dashboard/3rdpartylicenses.txt +4 -4
- package/dist/dashboard/browser/chunk-4VNZXWQZ.js +3 -0
- package/dist/dashboard/browser/chunk-4ZR4NTJW.js +1 -0
- package/dist/dashboard/browser/{chunk-HFJ25UTJ.js → chunk-7L4DWDGL.js} +4 -4
- package/dist/dashboard/browser/{chunk-C65CUT7O.js → chunk-BLNPJ4WD.js} +4 -4
- package/dist/dashboard/browser/chunk-E3HUMJ6S.js +6 -0
- package/dist/dashboard/browser/chunk-EBOHC6KX.js +1 -0
- package/dist/dashboard/browser/chunk-ESDYJ3BP.js +1 -0
- package/dist/dashboard/browser/chunk-JUZHAE4L.js +2 -0
- package/dist/dashboard/browser/chunk-K43KW4K2.js +4 -0
- package/dist/dashboard/browser/chunk-K46KCL6L.js +1 -0
- package/dist/dashboard/browser/chunk-KDCKLTCZ.js +1 -0
- package/dist/dashboard/browser/{chunk-JX3IOOXU.js → chunk-L63FHXGH.js} +1 -1
- package/dist/dashboard/browser/{chunk-Q7R63OUT.js → chunk-LBRCWYRN.js} +1 -1
- package/dist/dashboard/browser/chunk-MHOSWLRR.js +3 -0
- package/dist/dashboard/browser/{chunk-TSB6OOH2.js → chunk-N5GRSTMJ.js} +1 -1
- package/dist/dashboard/browser/{chunk-AEERNAF7.js → chunk-NDSAQ2HK.js} +1 -1
- package/dist/dashboard/browser/chunk-NN2YNLGP.js +3 -0
- package/dist/dashboard/browser/{chunk-3TYCIBMV.js → chunk-PJPGLT4T.js} +1 -1
- package/dist/dashboard/browser/chunk-R6J2WYUD.js +1 -0
- package/dist/dashboard/browser/chunk-T2YKGOEM.js +3 -0
- package/dist/dashboard/browser/chunk-U6AY7XZK.js +5 -0
- package/dist/dashboard/browser/{chunk-ZVU34B5S.js → chunk-UC3XMN2Y.js} +1 -1
- package/dist/dashboard/browser/chunk-UNT27XFJ.js +2 -0
- package/dist/dashboard/browser/chunk-V2CQL6W5.js +1 -0
- package/dist/dashboard/browser/chunk-VZ6E4VQY.js +2 -0
- package/dist/dashboard/browser/chunk-WJUGRIIZ.js +1 -0
- package/dist/dashboard/browser/{chunk-D4BFRQ63.js → chunk-WRBP4DQN.js} +4 -4
- package/dist/dashboard/browser/chunk-XUU4AY4M.js +2 -0
- package/dist/dashboard/browser/chunk-XYVF5I5T.js +1 -0
- package/dist/dashboard/browser/chunk-Y6B6X4Y6.js +2 -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/index.html +1 -1
- package/dist/dashboard/browser/main-ZADV4SOC.js +1 -0
- package/dist/main.js +48 -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-CNIZYK4A.js +0 -1
- 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-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 Xs=Object.defineProperty;var D=(r,t)=>()=>(r&&(t=r(r=0)),t);var ut=(r,t)=>{for(var e in t)Xs(r,e,{get:t[e],enumerable:!0})};var An={};ut(An,{configLookupPaths:()=>St,loadConfig:()=>Y,validateConfig:()=>Qt});import pt from"node:fs";import lt from"node:path";import Wt from"node:os";import{fileURLToPath as Ks}from"node:url";function En(){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:lt.join(Wt.homedir(),".daimon","logs"),maxFiles:5,maxBytesPerFile:1e7},depends:{},cascadeRestart:!1,history:{enabled:!0,path:lt.join(Wt.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","dead-search-root"]}},dashboard:{theme:"auto",density:"comfortable"}}}function Cn(r){return r.startsWith("~/")||r.startsWith("~\\")?lt.join(Wt.homedir(),r.slice(2)):r==="~"?Wt.homedir():r}function Qt(r,t){return Le(r,t)}function Le(r,t){if(!r||typeof r!="object")throw new Error(`Config at ${t} is not a JSON object`);let e=r,n=En();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=Cn(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=Cn(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 St(){return{local:lt.join(process.cwd(),"daimon.config.json"),user:lt.join(Wt.homedir(),".daimon","config.json")}}function Y(){let{local:r,user:t}=St();if(pt.existsSync(r)){let s=JSON.parse(pt.readFileSync(r,"utf8"));return{kind:"loaded",config:Le(s,r),path:r}}if(pt.existsSync(t)){let s=JSON.parse(pt.readFileSync(t,"utf8"));return{kind:"loaded",config:Le(s,t),path:t}}let n=[lt.resolve(Pn,"..","daimon.config.example.json"),lt.resolve(Pn,"..","..","daimon.config.example.json")].find(s=>pt.existsSync(s));return pt.mkdirSync(lt.dirname(t),{recursive:!0}),n?pt.copyFileSync(n,t):pt.writeFileSync(t,JSON.stringify(En(),null,2)+`
|
|
3
|
+
`,"utf8"),{kind:"stub-created",path:t}}var Ys,Pn,Rt=D(()=>{"use strict";Ys=Ks(import.meta.url),Pn=lt.dirname(Ys)});var He={};ut(He,{discoverApps:()=>kt});import Gt from"node:fs";import nt from"node:path";import Fe from"fast-glob";function Rn(r){try{return JSON.parse(Gt.readFileSync(r,"utf8"))}catch{return null}}function On(r){return!r||typeof r!="object"?!1:!!(r.targets?.serve||r.architect?.serve)}function Nn(r){if(!r||typeof r!="object")return[];let t=r.targets??r.architect??{};return Object.keys(t).filter(e=>e!=="serve").sort()}function Ue(r){return r.replace(/\\/g,"/")}function Ot(r,t){r&&(r.rejected[t]=(r.rejected[t]??0)+1)}function kt(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=nt.resolve(i);if(!Gt.existsSync(c)){n.push(`searchRoot does not exist: ${c}`),Ot(t.stats,"searchRoot missing");continue}let d=nt.join(c,"nx.json"),p=nt.join(c,"angular.json");if(Gt.existsSync(d)){let m=Fe.sync("**/project.json",{cwd:Ue(c),ignore:["**/node_modules/**","**/dist/**","**/.nx/**","**/.git/**"],absolute:!0,dot:!1});for(let h of m){t.stats&&(t.stats.scanned+=1);let f=Rn(h);if(!f){Ot(t.stats,"unreadable project.json");continue}if(!On(f)){Ot(t.stats,"no serve target");continue}let w=f.name||nt.basename(nt.dirname(h));if(!w){Ot(t.stats,"project has no name");continue}if(e.has(w)){n.push(`duplicate project name "${w}" \u2014 keeping first`),Ot(t.stats,"duplicate name");continue}e.set(w,{name:w,workspaceRoot:c,workspaceType:"nx",command:`npx nx serve ${w}`,hidden:!1,tags:[],tasks:Nn(f),workspaceLabel:l})}continue}if(Gt.existsSync(p)){let h=Rn(p)?.projects||{};for(let[f,w]of Object.entries(h))if(On(w)){if(e.has(f)){n.push(`duplicate project name "${f}" \u2014 keeping first`);continue}e.set(f,{name:f,workspaceRoot:c,workspaceType:"angular",command:`npx ng serve ${f}`,hidden:!1,tags:[],tasks:Nn(w),workspaceLabel:l})}continue}let v=Fe.sync("vite.config.{ts,js,mjs,cjs}",{cwd:Ue(c),absolute:!0,deep:1}),S=Gt.existsSync(nt.join(c,".storybook")),u=!1;if(v.length>0){let m=nt.basename(c);if(e.has(m)||e.set(m,{name:m,workspaceRoot:c,workspaceType:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:l}),u=!0,a){let h=Fe.sync("*/vite.config.{ts,js,mjs,cjs}",{cwd:Ue(c),absolute:!0});for(let f of h){let w=nt.dirname(f),E=nt.basename(w);E===m||e.has(E)||e.set(E,{name:E,workspaceRoot:w,workspaceType:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:l})}}}if(S){let m=`${nt.basename(c)}-storybook`;e.has(m)||e.set(m,{name:m,workspaceRoot:c,workspaceType:"storybook",command:"npx storybook dev --no-open",hidden:!1,tags:[],workspaceLabel:l}),u=!0}u||(n.push(`searchRoot has none of nx.json/angular.json/vite.config.*/.storybook: ${c}`),Ot(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 Nt=D(()=>{"use strict"});function te(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 p=[c,l],v=o.get(l);for(;v&&v!==c;)p.push(v),v=o.get(v);v===c&&p.push(c),i=p.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 $n(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 jn(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 Mn(r,t){let e=[];for(let[n,s]of Object.entries(r))s.includes(t)&&e.push(n);return e}var ee=D(()=>{"use strict"});import zs from"node:net";function dt(r){return new Promise(t=>{let e=zs.createServer();e.unref(),e.once("error",()=>t(!1)),e.listen({port:r,host:"127.0.0.1",exclusive:!0},()=>{e.close(()=>t(!0))})})}var $t,qt=D(()=>{"use strict";$t=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 dt(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 dt(t)}}});import Vs from"node:fs";import Zs from"node:path";import{createRequire as Qs}from"node:module";var to,eo,no,ro,ft,ne=D(()=>{"use strict";to=Qs(import.meta.url),eo=200,no=360*60*1e3,ro=1e4,ft=class{constructor(t){this.cfg=t;if(t.enabled)try{Vs.mkdirSync(Zs.dirname(t.path),{recursive:!0});let e=to("better-sqlite3");this.db=new e(t.path),this.db.pragma("journal_mode = WAL"),this.migrate(),this.flushTimer=setInterval(()=>this.flush(),eo),this.retentionStart=setTimeout(()=>this.runRetention(),ro),this.retentionTimer=setInterval(()=>this.runRetention(),no)}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,111 @@ 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
|
-
`)}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}})}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 (?,?,?,?,?,?)");this.db.transaction(i=>{for(let a of i)a.kind==="event"?e.run(a.row.ts,a.row.app,a.row.type,a.row.from_state,a.row.to_state,a.row.message):a.kind==="compile"?n.run(a.row.ts,a.row.app,a.row.ms):s.run(a.row.ts,a.row.app,a.row.task,a.row.exit_code,a.row.duration_ms,a.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)}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)}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((
|
|
34
|
-
`;try{
|
|
35
|
-
`);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 p=
|
|
36
|
-
`,n=Buffer.from(e,"utf8");
|
|
37
|
-
`))}}});import{spawn as
|
|
38
|
-
`);if(p<0)return;let
|
|
33
|
+
`)}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}})}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 (?,?,?,?,?,?)");this.db.transaction(i=>{for(let a of i)a.kind==="event"?e.run(a.row.ts,a.row.app,a.row.type,a.row.from_state,a.row.to_state,a.row.message):a.kind==="compile"?n.run(a.row.ts,a.row.app,a.row.ms):s.run(a.row.ts,a.row.app,a.row.task,a.row.exit_code,a.row.duration_ms,a.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)}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)}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,w)=>f.ts-w.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,p=this.queryCompiles({app:t,since:e,limit:1e3}).map(f=>f.ms).sort((f,w)=>f-w),v=(f,w)=>{if(f.length===0)return null;let E=Math.min(f.length-1,Math.floor((f.length-1)*w));return f[E]},S=v(p,.5),u=v(p,.95),m=new Map;for(let f of n)if(f.type==="error-new"||f.type==="error-recur"){let w=f.message??"";if(!w)continue;m.set(w,(m.get(w)??0)+1)}let h=[...m.entries()].sort((f,w)=>w[1]-f[1]).slice(0,5).map(([f,w])=>({message:f,count:w}));return{uptimePct24h:c,restartCount24h:d,compileP50:S,compileP95:u,topErrors:h}}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 Be}from"node:child_process";import _n from"tree-kill";function re(r){if(process.platform==="win32"){let o=Be("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=Be("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=Be("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 In(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 Ln(r){return new Promise(t=>{if(!r.pid||r.pid===process.pid){t(!1);return}_n(r.pid,"SIGTERM",e=>{if(e){setTimeout(()=>_n(r.pid,"SIGKILL",n=>t(!n)),500);return}t(!0)})})}var Je=D(()=>{"use strict"});import se from"node:fs";import oo from"node:os";import Fn from"node:path";function Un(r){return se.readFileSync(r,"utf8").split(/\r?\n/).filter(e=>e.trim()).map(e=>JSON.parse(e))}var oe,We=D(()=>{"use strict";oe=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=Fn.join(oo.homedir(),".daimon","sessions");se.mkdirSync(t,{recursive:!0});let e=Fn.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return se.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})+`
|
|
34
|
+
`;try{se.appendFileSync(this.file,e)}catch{}}}});import io from"node:fs";import Ge from"node:path";import{fileURLToPath as ao}from"node:url";function co(){let r=[Ge.resolve(Hn,"..","package.json"),Ge.resolve(Hn,"..","..","package.json")];for(let t of r)try{return JSON.parse(io.readFileSync(t,"utf8"))}catch{}return{}}var Hn,X,Mt=D(()=>{"use strict";Hn=Ge.dirname(ao(import.meta.url));X=co().version||"0.0.0"});import Dt from"node:fs";import ie from"node:path";import lo from"node:os";import{spawn as uo}from"node:child_process";import{fileURLToPath as po}from"node:url";function Z(){return Xe}function ae(){return _t}function qe(r){try{return process.kill(r,0),!0}catch(t){return t&&t.code==="EPERM"}}function z(){try{let r=Dt.readFileSync(_t,"utf8"),t=JSON.parse(r);if(!t||typeof t.pid!="number")return null;if(!qe(t.pid)){try{Dt.unlinkSync(_t)}catch{}return null}return t}catch{return null}}function Bn(r){Dt.mkdirSync(Xe,{recursive:!0});let t=_t+"."+process.pid+".tmp";Dt.writeFileSync(t,JSON.stringify(r)),Dt.renameSync(t,_t)}function rt(){try{Dt.unlinkSync(_t)}catch{}}function fo(){let r=ie.dirname(po(import.meta.url));return ie.join(r,"main.js")}async function mt(r={}){let t={...process.env};r.port&&(t.DAIMON_PORT=String(r.port)),uo(process.execPath,[fo(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let n=Date.now();for(;Date.now()-n<5e3;){let s=z();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 Tt(r,t){let e=Date.now();for(;Date.now()-e<t;){if(!qe(r))return!0;await new Promise(n=>setTimeout(n,100))}return!qe(r)}function Jn(r,t,e){return{pid:process.pid,apiPort:r,version:X,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var Xe,_t,st=D(()=>{"use strict";Mt();Xe=ie.join(lo.homedir(),".daimon"),_t=ie.join(Xe,"daemon.lock")});var rr={};ut(rr,{promptClaudeInstall:()=>To});import Pt,{useState as er}from"react";import{Box as nr,render as bo,Text as ue,useApp as So,useInput as ko}from"ink";function xo({onDone:r}){let{exit:t}=So(),[e,n]=er(0),[s,o]=er({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 ko((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())}),Pt.createElement(nr,{flexDirection:"column",paddingX:1},Pt.createElement(ue,{bold:!0,color:"cyan"},"Install Claude Code integration artifacts"),Pt.createElement(ue,{dimColor:!0},"Space toggles \xB7 Enter confirms \xB7 Esc cancels"),i.map((a,l)=>Pt.createElement(nr,{key:a.key},Pt.createElement(ue,{color:l===e?"cyan":void 0},l===e?"\u25B8 ":" "),Pt.createElement(ue,null,"[",s[a.key]?"x":" ","] ",a.label))))}async function To(){return new Promise(r=>{let t=!1;bo(Pt.createElement(xo,{onDone:n=>{t||(t=!0,r(n))}})).waitUntilExit().then(()=>{t||(t=!0,r(null))})})}var sr=D(()=>{"use strict"});import Po from"node:crypto";function Io(r){for(let{tool:t,rx:e}of _o)if(e.test(r))return t}function qo(r){return Po.createHash("sha1").update(r).digest("hex").slice(0,16)}function Xo(r){let t={message:r},e=r.match(Oo)||r.match(Ro);e&&(t.code=`TS${e[1]}`);let n=r.match($o)||r.match(or)||r.match(No);if(n)t.file=n[1],t.line=Number(n[2]),t.col=Number(n[3]);else{let o=r.match(Mo);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(jo);i&&(t.file=i[1])}}let s=Io(r);return s&&(t.tool=s),t}function Ko(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 Yo(r,t="127.0.0.1"){let e=r.match(Lo)||r.match(Fo)||r.match(Uo)||r.match(Ho);if(!e)return null;let n=e[1].replace(/[),.;]+$/,"");return Ko(n,t)}function zo(r,t){if(Bo.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="initial",!1;if(Jo.test(t))return r.bundle||(r.bundle={initialKB:0,lazyKB:0,files:[]}),r._bundleSection="lazy",!1;let e=t.match(Wo);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(Go);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 ir(r,t){let e=t.match(Do),n=e?null:t.match(or),s=e??n;if(s&&r.lastErrorHash){let S=r.errors.get(r.lastErrorHash);S&&!S.parsed?.file&&(S.parsed={...S.parsed??{message:S.message},file:s[1],line:Number(s[2]),col:Number(s[3])})}let o=t.trim();if(!o)return null;let i=r.status,a=!1,l,c=Yo(o);c&&!r.announcedUrl&&(r.announcedUrl=c,l=c);let d=zo(r,o),p;if(Co.some(S=>S.test(o))){let S=r.status==="error"||!!r.recoveringFromError;if(r.status==="compiling"||r.status==="starting"||r.status==="error"){let u=Date.now();r.compileStartedAt!=null?(p=u-r.compileStartedAt,r.lastCompileMs=p,r.lastCompileAt=u,r.compileStartedAt=null,r.compileHistory.push(p),r.compileHistory.length>20&&r.compileHistory.splice(0,r.compileHistory.length-20)):r.lastCompileAt=u}r.status="serving",S&&(r.errors.clear(),r.recoveringFromError=!1)}else Eo.some(S=>S.test(o))&&(r.status==="starting"||r.status==="serving"||r.status==="error")&&(r.status==="error"&&(r.recoveringFromError=!0),r.compileStartedAt=Date.now(),r.status="compiling");let v;if(Ao.some(S=>S.test(o))){let S=qo(o),u=Date.now(),m=r.errors.get(S),h=!1,f;m?(m.count+=1,m.lastSeen=u,f=m):(f={message:o,count:1,firstSeen:u,lastSeen:u,parsed:Xo(o)},r.errors.set(S,f),h=!0),r.lastErrorHash=S,v={entry:f,isNew:h},r.status="error"}return a=r.status!==i,{statusChanged:a,error:v,announcedUrl:l,bundleUpdated:d,compileMs:p}}var Co,Eo,Ao,Ro,Oo,No,or,$o,jo,Mo,Do,_o,Lo,Fo,Uo,Ho,Bo,Jo,Wo,Go,ar=D(()=>{"use strict";Co=[/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],Eo=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i],Ao=[/^\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+/],Ro=/\berror TS(\d+)/,Oo=/✘\s*\[ERROR\]\s*TS(\d+)/,No=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+)/,or=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+)\)/,$o=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,jo=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,Mo=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,Do=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,_o=[{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:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];Lo=/Local:\s+(https?:\/\/\S+)/i,Fo=/Server running at\s+(https?:\/\/\S+)/i,Uo=/listening on\s+(https?:\/\/\S+)/i,Ho=/(?:listening|listen)\s+(https?:\/\/\S+)/i,Bo=/Initial chunk files/i,Jo=/Lazy chunk files/i,Wo=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,Go=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i});import{spawn as Vo}from"node:child_process";import cr from"tree-kill";import Zo from"strip-ansi";var lr,pe,ur=D(()=>{"use strict";ar();lr=500,pe=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=Vo(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 p=n.status,v=this.stopping;v?(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,p!==n.status&&this.deps.onStatusChange?.(p,n.status,n.lastStatusMessage),this.deps.onExit?.(c,d,v),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(`
|
|
35
|
+
`);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 p=Zo(d),v=Date.now();l.lastLogTs=v,l.stale&&(l.stale=!1),l.logBuffer.push({ts:v,line:p}),l.logBuffer.length>lr&&l.logBuffer.splice(0,l.logBuffer.length-lr),this.deps.onLogLine?.(p);let S=l.status,u=ir(l,p);u?.statusChanged&&(c=!0,this.deps.onStatusChange?.(S,l.status)),u?.error&&this.deps.onErrorRecorded?.(u.error.entry,u.error.isNew),u?.compileMs!=null&&this.deps.onCompile?.(u.compileMs),u?.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),cr(t,"SIGTERM",()=>{});let i=setTimeout(()=>{cr(t,"SIGKILL",()=>{})},2e3),a=setTimeout(()=>{clearTimeout(i),s()},3e3);this.child?.once("exit",()=>{clearTimeout(i),clearTimeout(a),s()})})}}});import ot from"node:fs";import Qo from"node:path";var de,pr=D(()=>{"use strict";de=class{constructor(t,e){this.appName=t;this.cfg=e;this.filePath=Qo.join(e.dir,`${t}.log`),this.open()}appName;cfg;fd=null;bytes=0;warned=!1;filePath;open(){try{ot.mkdirSync(this.cfg.dir,{recursive:!0});try{this.bytes=ot.statSync(this.filePath).size}catch{this.bytes=0}this.fd=ot.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}
|
|
36
|
+
`,n=Buffer.from(e,"utf8");ot.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{ot.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{ot.rmSync(e,{force:!0})}catch{}continue}try{ot.existsSync(e)&&ot.renameSync(e,n)}catch{}}try{let t=`${this.filePath}.1`;ot.existsSync(this.filePath)&&ot.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}
|
|
37
|
+
`))}}});import{spawn as fr}from"node:child_process";import dr from"tree-kill";import mr from"strip-ansi";function ri(r){let t=r.match(ti);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(ei);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(ni);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 hr(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 gr(r,t,e=[]){return new Promise(n=>{let s=Date.now(),o=hr(r,t,e),i=fr(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 p=l.lastIndexOf(`
|
|
38
|
+
`);if(p<0)return;let v=l.slice(0,p);l=l.slice(p+1);for(let S of v.split(/\r?\n/)){if(!S.length)continue;let u=mr(S);a.push(u),a.length>1e3&&a.splice(0,a.length-1e3)}};i.stdout?.on("data",c),i.stderr?.on("data",c),i.on("exit",d=>{let p=Date.now()-s,v=a.join(`
|
|
39
39
|
`)+(l?`
|
|
40
|
-
`+l:""),S=
|
|
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
|
|
40
|
+
`+l:""),S=ri(v);n({app:r.name,task:t,exitCode:d,durationMs:p,summary:S,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 yr(r,t,e=[]){let n=hr(r,t,e),s=fr(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(`
|
|
41
|
+
`);if(d<0)return;let p=i.slice(0,d);i=i.slice(d+1);for(let v of p.split(/\r?\n/))v.length&&(o.push(mr(v)),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),dr(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&dr(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(p,3500)})}}var ti,ei,ni,wr=D(()=>{"use strict";ti=/Tests:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,ei=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,ni=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i});import br from"node:fs";import vr from"node:path";function Sr(r){let t={},e;try{e=br.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 ze(r,t){return vr.isAbsolute(t)?t:vr.join(r,t)}function Ve(r,t){return t.filter(e=>br.existsSync(ze(r,e)))}var kr=D(()=>{"use strict"});import si from"node:fs";import oi from"node:path";function ii(){return oi.join(Z(),"secrets.json")}function xr(){try{let r=si.readFileSync(ii(),"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 Tr(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 Pr=D(()=>{"use strict";st()});import{EventEmitter as ai}from"node:events";var Cr,fe,Er=D(()=>{"use strict";ur();qt();pr();ee();wr();Je();kr();Pr();We();Cr=500,fe=class extends ai{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new oe;constructor(t,e,n){super(),this.config=t,this.portAlloc=n??new $t(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>Cr&&this.eventBuffer.splice(0,this.eventBuffer.length-Cr),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 dt(s)){let S=re(s),u=In(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 de(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],l={};if(a.length){let S=e.state.activeEnvFile;(!S||!Ve(e.app.workspaceRoot,[S]).length)&&(S=Ve(e.app.workspaceRoot,a)[0]??null,S&&(e.state.activeEnvFile=S)),S&&(l=Sr(ze(e.app.workspaceRoot,S)))}let c={...l,...this.config.overrides?.[t]?.env??{},...i?.env??{}},d=xr(),p=Tr(c,d),v=new pe({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,m)=>{this.recordEvent({app:t,type:"status",from:S,to:u,message:m}),(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,m)=>this.emit("childExit",{name:t,code:S,signal:u,stopping:m}),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),m=e.lastBundleInitialKB;if(u.bundle&&u.bundle.initialKB>0){if(m&&m>0){let h=(u.bundle.initialKB-m)/m*100;u.bundleRegressionPct=Math.round(h*10)/10,h>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${u.bundleRegressionPct}% (${m}->${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=v,this.recordEvent({app:t,type:"status",from:n,to:"starting"}),v.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let 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=$n(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=jn(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],v=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(o.push({name:p.name,status:p.status,health:p.health,error:v?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!v)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=Mn(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 gr(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=yr(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 v=i?.state;s({name:t,status:v?.status??"unknown",health:v?.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 tn from"node:fs";import Ar from"node:path";import ci from"node:os";function li(){try{let r=tn.readFileSync(en,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function ui(r){Qe=r,!Ze&&(Ze=setTimeout(()=>{Ze=null;let t=Qe;if(Qe=null,!!t)try{tn.mkdirSync(Ar.dirname(en),{recursive:!0}),tn.writeFileSync(en,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
42
|
+
`)}},500))}var en,Ze,Qe,me,Rr=D(()=>{"use strict";en=Ar.join(ci.homedir(),".daimon","cursors.json");Ze=null,Qe=null;me=class{data=li();getErrorCursor(t,e){return this.data.errors[`${t}:${e}`]??0}setErrorCursor(t,e,n){this.data.errors[`${t}:${e}`]=n,ui(this.data)}}});import Or from"node:fs";import pi from"node:os";import Nr from"node:path";function fi(r){let t={};for(let[e,n]of Object.entries(r))typeof n=="string"&&(t[e]=di.test(e)?"***":n);return t}function nn(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}):[];return{takenAt:new Date().toISOString(),summary:e,logs:n.logBuffer.slice(-500).map(d=>({ts:d.ts,line:d.line})),errors:[...n.errors.entries()].map(([d,p])=>({hash:d,message:p.message,count:p.count,firstSeen:p.firstSeen,lastSeen:p.lastSeen})),env:fi(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}}function $r(r,t){let e=nn(r,t);if(!e)return null;let n=Nr.join(pi.homedir(),".daimon","snapshots");Or.mkdirSync(n,{recursive:!0});let s=e.takenAt.replace(/[:.]/g,"-"),o=Nr.join(n,`${t}-${s}.json`);return Or.writeFileSync(o,JSON.stringify(e,null,2)),{path:o,payload:e}}var di,jr=D(()=>{"use strict";di=/key|secret|token|password|api[-_]?key/i});import he from"node:fs";import Mr from"node:path";function Dr(r){let t=0;try{let e=he.readdirSync(r,{withFileTypes:!0});for(let n of e){let s=Mr.join(r,n.name);try{n.isDirectory()?t+=Dr(s):n.isFile()&&(t+=he.statSync(s).size)}catch{}}}catch{}return t}function rn(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=[...mi,...e?hi:[]].map(l=>{let c=Mr.join(n.workspaceRoot,l),d=he.existsSync(c);return{path:c,exists:d,sizeBytes:d?Dr(c):0}});return{app:t,workspace:n.workspaceRoot,targets:a,ranOnServing:o}}function _r(r,t,e){let n=rn(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{he.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 mi,hi,Ir=D(()=>{"use strict";mi=["dist",".angular/cache","tmp","out-tsc"],hi=["node_modules"]});function Xt(r){return r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}function Lr(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 gi)t.push(`daimon_app_status{name="${Xt(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="${Xt(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="${Xt(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="${Xt(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="${Xt(n.name)}"} ${n.memMB}`);return t.join(`
|
|
43
43
|
`)+`
|
|
44
|
-
`}var
|
|
45
|
-
`;try{
|
|
46
|
-
`,"utf8");let o=
|
|
47
|
-
`);let T=
|
|
48
|
-
`)
|
|
49
|
-
`)}
|
|
50
|
-
`);i.end();return}if(a.searchParams.get("
|
|
44
|
+
`}var gi,Fr=D(()=>{"use strict";gi=["stopped","starting","compiling","serving","error"]});import Kt from"node:fs";import yi from"node:crypto";import Ur from"node:path";function vi(){return Ur.join(Z(),"audit.log")}function bi(r){try{if(Kt.statSync(r).size>wi){let e=r+".1";try{Kt.unlinkSync(e)}catch{}Kt.renameSync(r,e)}}catch{}}function Hr(r,t,e,n){let s=vi();Kt.mkdirSync(Ur.dirname(s),{recursive:!0}),bi(s);let o=JSON.stringify({prev:t,next:e}),i=yi.createHash("sha1").update(o).digest("hex").slice(0,12),a=`${new Date().toISOString()} ${r} ${i} ${n.join(",")}
|
|
45
|
+
`;try{Kt.appendFileSync(s,a)}catch{}}var wi,Br=D(()=>{"use strict";st();wi=1e6});import ge from"node:fs";import ye from"node:path";import{fileURLToPath as Si}from"node:url";function ki(){let r=[ye.resolve(Jr,"templates","presets"),ye.resolve(Jr,"..","src","templates","presets")];for(let t of r)if(ge.existsSync(t))return t;return r[0]}function Wr(){let r=ki();if(!ge.existsSync(r))return[];let t=ge.readdirSync(r).filter(n=>n.endsWith(".json")),e=[];for(let n of t)try{let s=ge.readFileSync(ye.join(r,n),"utf8");s.charCodeAt(0)===65279&&(s=s.slice(1)),e.push(JSON.parse(s))}catch{}return e}var Jr,Gr=D(()=>{"use strict";Jr=ye.dirname(Si(import.meta.url))});import we from"node:fs";import qr from"node:path";function Xr(){return qr.join(Z(),"state-handoff.json")}function Kr(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=Xr();return we.mkdirSync(qr.dirname(n),{recursive:!0}),we.writeFileSync(n,JSON.stringify(e)),n}function Yr(r=6e4){let t=Xr();try{let e=we.readFileSync(t,"utf8"),n=JSON.parse(e);return we.unlinkSync(t),!n||typeof n.ts!="number"||Date.now()-n.ts>r?null:n}catch{return null}}var sn=D(()=>{"use strict";st()});var ve={};ut(ve,{ALL_AUTO_FIX:()=>zr,runAutoFix:()=>Fi});import H from"node:fs";import V from"node:path";function xi(){let r=z();if(!r)return{detected:!1,description:"no daemon running"};let t=process.cwd(),e=V.join(t,"daimon.config.json");if(!H.existsSync(e))return{detected:!1,description:"no local daimon.config.json in cwd"};let n=r.cwd,s=r.configPath,o=n&&V.resolve(n)===V.resolve(t),i=s&&V.resolve(s)===V.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 Ti(){let r=z();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 Tt(r.pid,5e3),rt(),`respawned daemon at pid ${(await mt({})).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 Pi(){let r;try{r=H.readFileSync(ae(),"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 Ci(){let r="(unknown)";try{let e=JSON.parse(H.readFileSync(ae(),"utf8"));r=String(e?.pid??"?")}catch{}rt();let t=await mt({});return`removed stale ${ae()} (prior pid ${r} was dead); spawned fresh daemon at pid ${t.pid}.`}function Ei(){let r=process.cwd(),e=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs","vite.config.cjs",".storybook"].filter(i=>H.existsSync(V.join(r,i)));if(!e.length)return{detected:!1,description:"no nx.json/angular.json/vite.config.*/.storybook in cwd"};let n=Y();return n.kind!=="loaded"?{detected:!0,description:`${e.join(", ")} present but no config is loaded`,markerFiles:e}:n.config.searchRoots.map(i=>V.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 Ai(){let r=process.cwd(),{local:t,user:e}=St(),n=H.existsSync(t)?t:e,s={};try{s=JSON.parse(H.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(H.readFileSync(V.join(r,"package.json"),"utf8"));typeof a.name=="string"&&(i=a.name)}catch{}s.searchRoots.push(i?{path:r,label:i}:r)}H.mkdirSync(V.dirname(n),{recursive:!0}),H.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
46
|
+
`,"utf8");let o=z();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 Ri(){let r=Y();if(r.kind!=="loaded"||!r.config.history.enabled)return{detected:!1,description:"history disabled"};let t=r.config.history.path;if(!H.existsSync(t))return{detected:!1,description:"history db does not exist (will be created on next start)"};try{let e=new ft(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 Oi(){let r=Y();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{H.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 Ni(){let r=Y();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 dt(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 $i(){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 ji(){let r=process.cwd(),t=process.versions.node,e=V.join(r,".nvmrc");if(H.existsSync(e)){let s=H.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=V.join(r,"package.json");if(H.existsSync(n))try{let o=JSON.parse(H.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 Mi(){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 Di(){let r=Y();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||!H.existsSync(s)||e.has(s))continue;e.add(s);let o=V.join(s,"package.json");if(!H.existsSync(o))continue;let i=null;for(let a of["package-lock.json","pnpm-lock.yaml","yarn.lock"]){let l=V.join(s,a);if(H.existsSync(l)){i=l;break}}t.push({name:V.basename(s),root:s,pkgPath:o,lockPath:i,nmPath:V.join(s,"node_modules")})}return t}function Vr(){let r=Di();if(!r.length)return{detected:!1,description:"no searchRoots with package.json found"};let t=[];for(let n of r){if(!H.existsSync(n.nmPath)){t.push({root:n.root,reason:"missing"});continue}if(n.lockPath)try{let s=H.statSync(n.lockPath).mtimeMs,o=H.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 _i(){let r=Vr();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 Zr(){let r=Y();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&&(H.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 Ii(){let r=Zr();if(!r.detected||!r.dead||!r.dead.length)return"nothing to remove";let{local:t,user:e}=St(),n=H.existsSync(t)?t:e,s={};try{s=JSON.parse(H.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;H.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
47
|
+
`,"utf8");let l=z();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 Fi(r){let t={ran:[],skipped:[],errors:[]};for(let e of zr){if(!r.permitted.includes(e))continue;let n=Li[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 zr,Li,be=D(()=>{"use strict";st();Rt();ne();qt();zr=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","dead-search-root"];Li={"orphan-daemon":{detect:xi,fix:Ti},"stale-lock":{detect:Pi,fix:Ci},"missing-search-root":{detect:Ei,fix:Ai},"corrupt-history-db":{detect:Ri,fix:Oi},"port-conflict-pred":{detect:Ni,fix:$i},"node-version-mismatch":{detect:ji,fix:Mi},"orphan-node-modules":{detect:Vr,fix:_i},"dead-search-root":{detect:Zr,fix:Ii}}});import Ui from"node:http";import Hi from"node:crypto";import Ct from"node:fs";import Q from"node:path";import{fileURLToPath as Bi}from"node:url";function on(){let r=[Q.resolve(Se,"dashboard","browser"),Q.resolve(Se,"dashboard"),Q.resolve(Se,"..","dist","dashboard","browser"),Q.resolve(Se,"..","dist","dashboard")];for(let t of r)if(Ct.existsSync(Q.join(t,"index.html")))return t;return null}function Yt(r,t){try{if(!Ct.statSync(t).isFile())return!1;let n=Q.extname(t).toLowerCase(),s=Wi[n]??"application/octet-stream",o=Ct.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 T(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 Ut(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 ke(r,t){let e=(r.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function Gi(r){return{name:r.name,status:r.status,port:r.port,health:r.health,errCount:r.errorCount,lastChangeMs:r.lastChangeMs??null}}function Ft(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 an(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 qi(r){if(!r)return{};if(/^\d{10,}$/.test(r))return{sinceTs:Number(r)};let t=Ut(r);return t!=null?{sinceMs:t}:{}}function Ki(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))Xi.test(s)&&(n[s]="***")}return t}function cn(r){if(!r)return"";try{let t=Ct.readFileSync(r);return Hi.createHash("sha1").update(t).digest("hex")}catch{return""}}function Qr(r,t,e={}){let n=new me,s=Ui.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 m=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!m)return!0;let h=o.headers.authorization;return typeof h=="string"&&h.toLowerCase().startsWith("bearer ")&&h.slice(7).trim()===m?!0:(T(i,401,{error:"unauthorized"}),!1)};if(l==="POST"&&a.pathname==="/api/shutdown"){if(!d())return;T(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(l==="GET"){let u=e.getConfig(),m=cn(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:m}),i.end(JSON.stringify({etag:m,config:Ki(u)}));return}if(l==="PATCH"&&e.patchConfig){if(!d())return;let u=o.headers["if-match"]?.trim(),m=cn(e.configPath);if(!u||u!==m){T(i,412,{error:"etag mismatch",current:m});return}let h={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(E=>{let P=[];o.on("data",b=>P.push(b)),o.on("end",()=>{try{h=JSON.parse(Buffer.concat(P).toString("utf8"))}catch{}E()})});let f=e.patchConfig(h);if(!f.ok){T(i,400,{error:f.error});return}let w=cn(e.configPath);try{let E=o.socket.remoteAddress||"127.0.0.1";Hr(E,h,h,f.applied)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:w}),i.end(JSON.stringify({etag:w,applied:f.applied,addedApps:f.addedApps,removedApps:f.removedApps,restartRequired:f.restartRequired}));return}T(i,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&l==="GET"){T(i,200,Wr());return}if(a.pathname==="/api/snapshot-state"&&l==="POST"){if(!d())return;let u=Kr(r);T(i,200,{ok:!0,path:u});return}if(a.pathname==="/api/config/reload"&&l==="POST"&&e.reloadConfig){if(!d())return;try{let u=await e.reloadConfig();T(i,200,u)}catch(u){T(i,400,{error:u?.message||String(u)})}return}if(l==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let u=Lr(r);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(u)}),i.end(u);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 u=on();if(u&&Yt(i,Q.join(u,"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"){T(i,405,{error:"method not allowed"});return}let u=Ut(a.searchParams.get("since")),m=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let w=r.events({sinceMs:u,app:m});for(let b of w)i.write(JSON.stringify(b)+`
|
|
48
|
+
`);let E=b=>{m&&b.app!==m||i.write(JSON.stringify(b)+`
|
|
49
|
+
`)};r.on("event",E);let P=setInterval(()=>{try{i.write(`
|
|
50
|
+
`)}catch{}},3e4);o.on("close",()=>{r.off("event",E),clearInterval(P);try{i.end()}catch{}});return}let h=r.events({sinceMs:u,app:m}),f=r.getHistory();if(f&&u&&h.length<500){let w=Date.now()-u,E=f.queryEvents({app:m,since:w,limit:1e3}),P=new Set(h.map(b=>`${b.ts}|${b.app}|${b.type}|${b.from??""}|${b.to??""}|${b.message??""}`));for(let b of E){let j=`${b.ts}|${b.app}|${b.type}|${b.from_state??""}|${b.to_state??""}|${b.message??""}`;P.has(j)||h.push({ts:b.ts,app:b.app,type:b.type,from:b.from_state??void 0,to:b.to_state??void 0,message:b.message??void 0})}h.sort((b,j)=>b.ts-j.ts)}T(i,200,h);return}if(c[0]==="api"&&c[1]==="session"){if(c[2]==="record"&&l==="POST"){let u=a.searchParams.get("action")||"toggle";if(u==="start"||u==="toggle"&&!r.sessionRecorder.isRecording()){let m=r.sessionRecorder.start();T(i,200,{recording:!0,path:m.path});return}if(u==="stop"||u==="toggle"&&r.sessionRecorder.isRecording()){let m=r.sessionRecorder.stop();T(i,200,{recording:!1,path:m.path});return}T(i,400,{error:"invalid action"});return}if(c[2]==="status"&&l==="GET"){T(i,200,{recording:r.sessionRecorder.isRecording()});return}T(i,404,{error:"not found"});return}if(c[0]==="api"&&c[1]==="history"){if(l!=="GET"){T(i,405,{error:"method not allowed"});return}let u=r.getHistory();if(!u){T(i,200,[]);return}let m=c[2],h=a.searchParams.get("app")||void 0,f=a.searchParams.get("since"),w=a.searchParams.get("until"),E=a.searchParams.get("limit"),P=f?/^\d{10,}$/.test(f)?Number(f):Date.now()-(Ut(f)??0):void 0,b=w?/^\d{10,}$/.test(w)?Number(w):Date.now()-(Ut(w)??0):void 0,j=E?Number(E):void 0;if(m==="events"){T(i,200,u.queryEvents({app:h,since:P,until:b,type:a.searchParams.get("type")||void 0,limit:j}));return}if(m==="compile-times"){T(i,200,u.queryCompiles({app:h,since:P,until:b,limit:j}));return}if(m==="tasks"){T(i,200,u.queryTasks({app:h,task:a.searchParams.get("task")||void 0,since:P,limit:j}));return}if(m==="summary"&&c.length>=4){let _=decodeURIComponent(c[3]);T(i,200,u.summary(_));return}if(m==="why"&&c.length>=4){let _=decodeURIComponent(c[3]);T(i,200,u.why(_));return}T(i,404,{error:"not found"});return}if(c[0]==="api"&&c[1]==="profiles"&&c[3]==="ensure-up"&&l==="POST"){let u=decodeURIComponent(c[2]),m=e.getConfig?.(),h=m?.profiles?.[u];if(!h){T(i,404,{error:"unknown profile"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){T(i,400,{error:"until must be serving|healthy"});return}let w=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),E=w?Number(w):3e5;(!Number.isFinite(E)||E<=0)&&(E=3e5),E=Math.min(E,12e5);let P=m?.healthProbe?.enabled??!0,b=f==="healthy"&&!P?"serving":f,j=Date.now();for(let y of h){let g=r.summary(y);g&&g.status!=="serving"&&g.status!=="starting"&&g.status!=="compiling"&&await r.startWithDeps(y)}let _=await Promise.all(h.map(async y=>{let g=Math.max(1e3,E-(Date.now()-j));if(!r.summary(y))return{name:y,state:null,until:b,reachedTargetMs:null,timedOut:!1,error:"unknown"};let k=await r.waitFor(y,b,g),$=r.summary(y);return{name:y,state:$?Ft($):null,until:b,reachedTargetMs:k.timedOut?null:k.waitedMs,timedOut:k.timedOut}}));T(i,200,{profile:u,apps:_,_meta:{totalMs:Date.now()-j,until:b}});return}if(c[0]==="api"&&c[1]==="discovery"&&c[2]==="explain"&&l==="GET"){let u=e.getConfig?.();if(!u){T(i,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:m}=await Promise.resolve().then(()=>(Nt(),He)),h={scanned:0,rejected:{}},f=[],w=m(u,{warnings:f,stats:h}),E=u.searchRoots.map(P=>typeof P=="string"?P:P.path);T(i,200,{searchRoots:E,scanned:h.scanned,rejected:h.rejected,warnings:f,appsFound:w.length,suggestion:w.length===0?E.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.":`${w.length} apps discovered`});return}if(c[0]==="api"&&c[1]==="doctor"&&c[2]==="auto-fix"&&l==="POST"){if(!d())return;let u={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(P=>{let b=[];o.on("data",j=>b.push(j)),o.on("end",()=>{try{u=JSON.parse(Buffer.concat(b).toString("utf8"))}catch{}P()})});let{runAutoFix:m,ALL_AUTO_FIX:h}=await Promise.resolve().then(()=>(be(),ve)),w=e.getConfig?.()?.doctor?.autoFix?.permitted??h,E=Array.isArray(u.permitted)&&u.permitted.length?u.permitted:w;try{let P=await m({permitted:E,dryRun:!!u.dryRun});T(i,200,P)}catch(P){T(i,500,{error:P?.message??String(P)})}return}if(c[0]==="api"&&c[1]==="overview"&&l==="GET"){let u=e.getConfig?.(),m=r.list(),h=a.searchParams.get("workspace"),f=a.searchParams.get("profile"),w=m;if(h&&(w=w.filter(k=>k.workspaceLabel===h)),f){let k=u?.profiles?.[f]??null;k&&(w=w.filter($=>k.includes($.name)))}let E={apps:w.length,serving:w.filter(k=>k.status==="serving").length,errors:w.filter(k=>k.status==="error").length,stopped:w.filter(k=>k.status==="stopped").length,totalErrCount:w.reduce((k,$)=>k+$.errorCount,0),totalCpuPct:Math.round(w.reduce((k,$)=>k+($.cpu??0),0)*10)/10,totalMemMb:Math.round(w.reduce((k,$)=>k+($.memMB??0),0))},P={};for(let k of w)(P[k.status]??=[]).push(k.name);let b=w.filter(k=>k.status==="error"||k.errorCount>0).map(k=>{let $=r.errors(k.name)??[],B=$[$.length-1],x=B?.parsed;return{name:k.name,status:k.status,errCount:k.errorCount,firstError:x?{file:x.file??null,line:x.line??null,code:x.code??null,message:x.message??B?.message??""}:B?{file:null,line:null,code:null,message:B.message}:null}}),j=Date.now()-5*6e4,_=r.events({sinceMs:5*6e4}).filter(k=>k.type==="status"&&k.ts>=j).filter(k=>h?w.some($=>$.name===k.app):!0).filter(k=>f?w.some($=>$.name===k.app):!0).slice(-5).map(k=>({name:k.app,transition:`${k.from??"?"}\u2192${k.to??"?"}`,msAgo:Date.now()-k.ts})),y={ts:Date.now(),version:X,totals:E,byStatus:P,needsAttention:b,recentlyChanged:_};E.apps===0&&(y._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let g=a.searchParams.get("budget"),C=g?Math.max(64,Number(g)|0):null;if(C){let k=C*4,$=0,B=0;for(;JSON.stringify(y).length>k&&(y.needsAttention.length||y.recentlyChanged.length);)if(y.needsAttention.length>1)y.needsAttention.pop(),$++;else if(y.recentlyChanged.length)y.recentlyChanged.pop(),B++;else if(y.needsAttention.length===1)y.needsAttention.pop(),$++;else break;$||B?y._meta={...y._meta??{},budget:C,omitted:{needsAttention:$,recentlyChanged:B}}:y._meta={...y._meta??{},budget:C}}T(i,200,y);return}if(c[0]!=="api"||c[1]!=="apps"){if(l==="GET"&&!a.pathname.startsWith("/metrics")){let u=on();if(u){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let h=Q.resolve(u,m);if(h.startsWith(u)&&Yt(i,h))return}if(!Q.extname(m||"")&&Yt(i,Q.join(u,"index.html")))return}}T(i,404,{error:"not found"});return}if(c.length===2){if(l!=="GET"){T(i,405,{error:"method not allowed"});return}let u=ke(a,e.getConfig),m=r.list(),h=u==="full"?m:m.map(Gi);if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let f of h)i.write(JSON.stringify(f)+`
|
|
51
|
+
`);i.end();return}if(a.searchParams.get("explain")==="1"){let f=e.getConfig?.(),w={format:u};if(f){let{discoverApps:E}=await Promise.resolve().then(()=>(Nt(),He)),P={scanned:0,rejected:{}},b=[];E(f,{warnings:b,stats:P});let j=f.searchRoots.map(_=>typeof _=="string"?_:_.path);w={format:u,searchRoots:j,scanned:P.scanned,rejected:P.rejected,warnings:b,suggestion:h.length===0?j.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."}}T(i,200,{apps:h,_meta:w});return}T(i,200,h);return}let p=decodeURIComponent(c[2]),v=c[3],S=c[4];if(!v){if(l!=="GET"){T(i,405,{error:"method not allowed"});return}let u=r.summary(p);if(!u){T(i,404,{error:"unknown app"});return}ke(a,e.getConfig)==="full"?T(i,200,{...u,_meta:{format:"full"}}):T(i,200,{...Ft(u),_meta:{format:"compact"}});return}if(v==="errors"&&S==="since-last"&&l==="GET"){let u=a.searchParams.get("client")||"default",m=n.getErrorCursor(u,p),h=r.errorsSince(p,m);if(h==null){T(i,404,{error:"unknown app"});return}let f=h.reduce((E,P)=>Math.max(E,P.lastSeen),m);f>m&&n.setErrorCursor(u,p,f);let w=ke(a,e.getConfig);T(i,200,w==="full"?h:h.map(an));return}if(v==="errors"&&!S&&l==="GET"){let u=a.searchParams.get("since"),m=ke(a,e.getConfig);if(u){let{sinceMs:f,sinceTs:w}=qi(u),E=w??(f!=null?Date.now()-f:0),P=r.errorsSince(p,E);if(P==null){T(i,404,{error:"unknown app"});return}T(i,200,m==="full"?P:P.map(an));return}let h=r.errors(p);if(h==null){T(i,404,{error:"unknown app"});return}T(i,200,m==="full"?h:h.map(an));return}if(v==="logs"&&c[4]==="stream"&&l==="GET"){if(!r.summary(p)){T(i,404,{error:"unknown app"});return}i.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let u=r.logs(p,{tail:50})??[];for(let P of u)i.write(`data: ${JSON.stringify({ts:Date.now(),line:P})}
|
|
51
52
|
|
|
52
|
-
`);let
|
|
53
|
+
`);let m=[],h=0,f=()=>{for(;m.length&&i.write(m.shift()););},w=P=>{P.name===p&&(m.length>=200&&(h++,m.shift()),m.push(`data: ${JSON.stringify({ts:P.ts,line:P.line})}
|
|
53
54
|
|
|
54
|
-
`),
|
|
55
|
+
`),f())};r.on("log",w);let E=setInterval(()=>i.write(`: ping
|
|
55
56
|
|
|
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}
|
|
57
|
+
`),3e4);o.on("close",()=>{r.off("log",w),clearInterval(E)});return}if(v==="logs"&&l==="GET"){let u=a.searchParams.get("tail"),m=a.searchParams.get("since"),h=r.logs(p,{tail:u?Number(u):void 0,sinceMs:Ut(m)});if(h==null){T(i,404,{error:"unknown app"});return}T(i,200,{lines:h});return}if(v==="focus"&&l==="POST"){let u=r.summary(p);if(!u){T(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(m)){T(i,400,{error:"until must be one of serving|healthy|stable"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=h?Number(h):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let w=a.searchParams.get("stableMs"),E=w&&Number.isFinite(Number(w))?Math.max(1e3,Number(w)):5e3;i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache",connection:"keep-alive"});let P=x=>{try{i.write(JSON.stringify(x)+`
|
|
58
|
+
`)}catch{}};P({kind:"subscribed",app:p,until:m,ts:Date.now(),state:Ft(u)});let b=Date.now(),j=Date.now(),_=!1,y=x=>{if(_)return;_=!0,r.off("event",C),clearInterval(k),clearInterval($),clearTimeout(B);let I=r.summary(p);P({kind:"done",reason:x,ts:Date.now(),state:I?Ft(I):null,waitedMs:Date.now()-b});try{i.end()}catch{}},g=()=>{let x=r.summary(p);if(!x)return!1;if(m==="serving")return x.status==="serving";if(m==="healthy")return x.status==="serving"&&x.health==="healthy";if(m==="stable"){let I=Date.now()-j;return x.status==="serving"&&x.health==="healthy"&&I>=E}return!1},C=x=>{if(x.app===p)if(j=Date.now(),x.type==="status")P({kind:"status",from:x.from,to:x.to,ts:x.ts}),m!=="stable"&&g()&&y("reached");else if(x.type==="error-new"||x.type==="error-recur"){let N=(r.errors(p)??[])[0];N&&P({kind:"error",message:N.message,parsed:N.parsed??null,ts:x.ts})}else x.type==="health"&&(P({kind:"health",from:x.from,to:x.to,ts:x.ts}),m!=="stable"&&g()&&y("reached"))};r.on("event",C);let k=setInterval(()=>{g()&&y("reached")},1e3),$=setInterval(()=>{try{i.write(`
|
|
59
|
+
`)}catch{}},3e4),B=setTimeout(()=>y("timeout"),f);o.on("close",()=>y("closed")),g()&&y("reached");return}if(v==="health"&&S==="pin"&&l==="POST"){let u=r.getState(p);if(!u){T(i,404,{error:"unknown app"});return}let m={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(_=>{let y=[];o.on("data",g=>y.push(g)),o.on("end",()=>{try{m=JSON.parse(Buffer.concat(y).toString("utf8"))}catch{}_()})});let h=typeof m.path=="string"&&m.path?m.path:u.discoveredHealthPath??null;if(!h){T(i,400,{error:"no path supplied and no discoveredHealthPath on app"});return}let{configLookupPaths:f}=await Promise.resolve().then(()=>(Rt(),An)),{local:w,user:E}=f(),P=Ct.existsSync(w)?w:E,b={};try{b=JSON.parse(Ct.readFileSync(P,"utf8"))}catch{}(!b.overrides||typeof b.overrides!="object")&&(b.overrides={}),(!b.overrides[p]||typeof b.overrides[p]!="object")&&(b.overrides[p]={});let j=b.overrides[p].healthProbePath??null;if(b.overrides[p].healthProbePath=h,Ct.writeFileSync(P,JSON.stringify(b,null,2)+`
|
|
60
|
+
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}T(i,200,{pinned:h,app:p,configPath:P,previous:j});return}if(v==="try-fix"&&l==="POST"){let u=r.summary(p);if(!u){T(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){T(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=h?Number(h):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let w={status:u.status,health:u.health,errCount:u.errorCount,firstError:(r.errors(p)??[])[0]?.parsed??null},{runAutoFix:E,ALL_AUTO_FIX:P}=await Promise.resolve().then(()=>(be(),ve)),j=e.getConfig?.()?.doctor?.autoFix?.permitted??P,_={ran:[],skipped:[],errors:[]};try{_=await E({permitted:j,dryRun:!1})}catch(N){_.errors.push({name:"auto-fix",error:N?.message??String(N)})}let y=(_.ran??[]).map(N=>N.name),g=null;try{let N=await r.restart(p);N?.ok||(g=N?.error??"restart failed")}catch(N){g=N?.message??String(N)}let C=await r.waitFor(p,m,f),k=r.summary(p),B=(r.errors(p)??[]).slice(0,5).map(N=>({file:N.parsed?.file??null,line:N.parsed?.line??null,code:N.parsed?.code??null,tool:N.parsed?.tool??null,message:N.parsed?.message??N.message})),x=k?{status:k.status,health:k.health,errCount:k.errorCount}:{status:C.status,health:C.health,errCount:0},I=m==="serving"&&x.status==="serving"||m==="healthy"&&x.status==="serving"&&x.health==="healthy";T(i,200,{before:w,after:x,fixed:y,stillFailing:B,reached:I,waitedMs:C.waitedMs,_meta:{autoFix:_,restartErr:g,timedOut:C.timedOut}});return}if(v==="wait"&&l==="GET"){if(!r.summary(p)){T(i,404,{error:"unknown app"});return}let u=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(u)){T(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let m=a.searchParams.get("timeout"),h=m?Number(m):120;(!Number.isFinite(h)||h<=0)&&(h=120),h=Math.min(h,600);let f=await r.waitFor(p,u,h*1e3);T(i,200,f);return}if(v==="ensure"&&l==="POST"){let u=r.summary(p);if(!u){T(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){T(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=h?Number(h):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let w=e.getConfig?.().healthProbe?.enabled??!0,E=m,P;if(E==="healthy"&&!w&&(E="serving",P="no health probe; treated serving as terminal"),E==="serving"&&u.status==="serving"||E==="healthy"&&u.status==="serving"&&u.health==="healthy"){T(i,200,{...Ft(u),_meta:{format:"compact",startedFromState:null,warning:P,waitedMs:0}});return}let j=u.status;u.status!=="starting"&&u.status!=="compiling"&&await r.start(p);let _=await r.waitFor(p,E,f),y=r.summary(p),g=y?Ft(y):{name:p,status:_.status,port:null,url:null,health:_.health,errCount:0,lastChangeMs:null,uptime:null};if(_.timedOut){T(i,200,{error:"timeout",state:g,_meta:{format:"compact",startedFromState:j,warning:P,waitedMs:_.waitedMs,timedOut:!0}});return}T(i,200,{...g,_meta:{format:"compact",startedFromState:j,warning:P,waitedMs:_.waitedMs}});return}if(v==="start"&&l==="POST"){if(a.searchParams.get("withDeps")==="1"){let h=await r.startWithDeps(p);T(i,h.ok?200:400,h);return}let m=await r.start(p);T(i,m.ok?200:400,m);return}if(v==="start-with-deps"&&l==="POST"){let u=await r.startWithDeps(p);T(i,u.ok?200:400,u);return}if(v==="tasks"&&l==="GET"&&!S){let u=r.listTasks(p);if(u==null){T(i,404,{error:"unknown app"});return}T(i,200,{tasks:u,watching:r.listWatchTasks(p)});return}if(v==="run"&&S&&l==="POST"){let u={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(f=>{let w=[];o.on("data",E=>w.push(E)),o.on("end",()=>{try{u=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}f()})});let m=Array.isArray(u.args)?u.args.map(String):[];if(u.watch){let f=r.startWatchTask(p,S,m);T(i,f.ok?200:400,f);return}let h=await r.runTask(p,S,m);if("error"in h){T(i,404,h);return}T(i,200,h);return}if(v==="run-stop"&&S&&l==="POST"){let u=await r.stopWatchTask(p,S);T(i,200,u);return}if(v==="env"&&l==="GET"){let m=r.getConfig().envFiles?.[p]??[],h=r.getState(p);T(i,200,{candidates:m,active:h?.activeEnvFile??null});return}if(v==="env"&&l==="POST"){let u={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(h=>{let f=[];o.on("data",w=>f.push(w)),o.on("end",()=>{try{u=JSON.parse(Buffer.concat(f).toString("utf8"))}catch{}h()})}),r.setActiveEnvFile(p,u.use??null);let m=r.getState(p);T(i,200,{active:m?.activeEnvFile??null});return}if(v==="requests"&&l==="GET"){if(!e.requestLog){T(i,200,[]);return}let u=Ut(a.searchParams.get("since"));T(i,200,e.requestLog.requests(p,u));return}if(v==="clean"&&l==="POST"){let u=a.searchParams.get("deep")==="1",m=a.searchParams.get("yes")==="1",h=rn(r,p,u);if(!h){T(i,404,{error:"unknown app"});return}if(h.ranOnServing){T(i,409,{error:"refusing: app is currently running",plan:h});return}if(!m){T(i,200,{plan:h,hint:"pass --yes to delete"});return}let f=_r(r,p,u);T(i,200,f);return}if(v==="snapshot"&&l==="POST"){if(a.searchParams.get("write")==="1"){let h=$r(r,p);if(!h){T(i,404,{error:"unknown app"});return}T(i,200,{snapshot:h.path});return}let m=nn(r,p);if(!m){T(i,404,{error:"unknown app"});return}T(i,200,m);return}if(v==="stop"&&l==="POST"){let u=await r.stop(p);T(i,u.ok?200:400,u);return}if(v==="restart"&&l==="POST"){let u=await r.restart(p);T(i,u.ok?200:400,u);return}if(l==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let u=on();if(u){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let h=Q.resolve(u,m);if(h.startsWith(u)&&Yt(i,h))return}if(!Q.extname(m||"")&&Yt(i,Q.join(u,"index.html")))return}}T(i,404,{error:"not found"})}catch(a){T(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}var Ji,Se,Wi,Xi,ts=D(()=>{"use strict";Rr();jr();Ir();Fr();Br();Gr();sn();Mt();Ji=Bi(import.meta.url),Se=Q.dirname(Ji);Wi={".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"};Xi=/key|secret|token|password|pass/i});import Yi from"node:http";import zi from"node:https";function es(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?xe(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[ns(c,d,p,o)]}if(e){let l=xe(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=>ns("http",l,n,o))}function xe(r){try{return new URL(r)}catch{return null}}function ns(r,t,e,n){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${r}://${s}${o}${n.startsWith("/")?n:"/"+n}`}var Vi,Zi,Qi,Te,rs=D(()=>{"use strict";Vi=1e3,Zi=500,Qi=["/","/health","/-/health","/api/health","/ready","/healthz"];Te=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)},Zi);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=es(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 p=xe(c);p&&this.registry.setCachedProbeHost(t,p.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)},Vi);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 Qi){let s={...this.cfg,path:n},o=es(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?zi:Yi,l={timeout:this.cfg.timeoutMs};if(i){let p=xe(t)?.hostname?.replace(/^\[|\]$/g,"")??"",v=p==="127.0.0.1"||p==="::1"||p==="localhost";l.rejectUnauthorized=v?!1:!!this.cfg.rejectUnauthorized}let c=e.strict2xx?300:500;try{let d=a.get(t,l,p=>{let v=p.statusCode??0;p.resume(),v>=200&&v<c?o({ok:!0}):o({ok:!1,error:`http ${v}`})});d.on("timeout",()=>d.destroy(new Error("timeout"))),d.on("error",p=>o({ok:!1,error:p?.code||p?.message||"error"}))}catch(d){o({ok:!1,error:d?.message||"throw"})}})}}});import ta from"pidusage";var Pe,ss=D(()=>{"use strict";Pe=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 ta(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 Ce,os=D(()=>{"use strict";Ce=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 pn from"node:fs";import is from"node:path";import ea from"node:os";function as(){try{let r=pn.readFileSync(dn,"utf8"),t=JSON.parse(r);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function cs(r){un=r,!ln&&(ln=setTimeout(()=>{ln=null;let t=un;if(un=null,!!t)try{pn.mkdirSync(is.dirname(dn),{recursive:!0}),pn.writeFileSync(dn,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
61
|
+
`)}},500))}var dn,ln,un,ls=D(()=>{"use strict";dn=is.join(ea.homedir(),".daimon","state.json");ln=null,un=null});import us from"node:fs";import na from"node:os";import ps from"node:path";import{createRequire as ra}from"node:module";var sa,oa,Ee,ds=D(()=>{"use strict";sa=ra(import.meta.url),oa=6e4,Ee=class{constructor(t,e){this.registry=t;this.cfg=e;this.logFile=ps.join(na.homedir(),".daimon","notifications.log");try{us.mkdirSync(ps.dirname(this.logFile),{recursive:!0})}catch{}if(!e.enabled){this.audit("init","disabled by config");return}try{let n=sa("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}
|
|
62
|
+
`;try{us.appendFileSync(this.logFile,n)}catch{}}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] notifier: ${t}
|
|
63
|
+
`))}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<oa){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 fs from"node:fs";import fn from"node:path";var ia,aa,ca,la,Ae,ms=D(()=>{"use strict";ia=5e3,aa=3e4,ca=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),la=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),Ae=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),ia),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>aa||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=fs.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of i)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(ca.has(a.name))continue;n(fn.join(s,a.name),o+1)}else if(a.isFile()){let l=fn.extname(a.name);if(!la.has(l))continue;try{let c=fn.join(s,a.name),d=fs.statSync(c);e.push({path:c,mtime:d.mtimeMs})}catch{}}}};return n(t,0),e}}});import hs from"node:http";var Re,Oe,gs=D(()=>{"use strict";Re=200,Oe=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,p=>{a.writeHead(p.statusCode||502,p.headers),p.pipe(a);let v=()=>{s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:p.statusCode||0,durationMs:Date.now()-l}),s.length>Re&&s.splice(0,s.length-Re)};p.on("end",v),p.on("error",v)});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>Re&&s.splice(0,s.length-Re)}),i.pipe(d)});o.on("error",i=>{i?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${n} in use for ${t}; disabling proxy
|
|
64
|
+
`),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 mn from"node:fs";function ys(r){let t=mn.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 pa(r,t){let e=r+"."+process.pid+".tmp";mn.writeFileSync(e,t,"utf8"),mn.renameSync(e,r)}function da(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 vs(r){let t=ys(r.configPath),e=ws(t,r.patch);if(!e||typeof e!="object")throw new Error("patch produced non-object config");let n=Qt(e,r.configPath);return pa(r.configPath,JSON.stringify(e,null,2)+`
|
|
65
|
+
`),{config:n,raw:e,applied:da(t,e),prevRaw:t}}function hn(r){let t=ys(r.configPath),e=Qt(t,r.configPath);return fa(r.registry,e)}function fa(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=kt(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 p=e.overrides?.[c];if(!p)continue;for(let v of ua)if(v in p){l.push(c);break}}}return{addedApps:i,removedApps:a,restartRequired:l,config:e}}var ua,bs=D(()=>{"use strict";Rt();Nt();ua=new Set(["command","port","env","url"])});import Ss from"node:fs";import ma from"node:os";import ks from"node:path";function ga(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))ha.test(s)&&(n[s]="***")}return t}function ya(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 wa(){let r=ks.join(Z(),"crashes");return Ss.mkdirSync(r,{recursive:!0}),r}function va(r,t,e){let n=new Date().toISOString().replace(/[:.]/g,"-"),s=ks.join(wa(),`${n}.txt`),o=r,i=[`daimon crash dump @ ${new Date().toISOString()}`,`version: ${X}`,`node: ${process.version}`,`platform: ${process.platform} ${ma.release()}`,`cwd: ${process.cwd()}`,`pid: ${process.pid}`,"","ERROR:",o?.stack||String(o),"","CONFIG (redacted):",JSON.stringify(ga(e),null,2),"","RECENT LOG (last 200 lines across apps):",...ya(t,200)];try{Ss.writeFileSync(s,i.join(`
|
|
66
|
+
`))}catch{}return s}function xs(r){let t=e=>{let n=null;try{n=va(e,r.getRegistry(),r.getConfig())}catch{}try{process.stderr.write(`[daimon] fatal: ${e?.stack||e}
|
|
63
67
|
`)}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
|
-
`);j({name:
|
|
66
|
-
`)}),onSubmit:()=>{let
|
|
67
|
-
`),process.exit(1)}if(n.kind==="stub-created"){let
|
|
68
|
+
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var ha,Ts=D(()=>{"use strict";Mt();st();ha=/key|secret|token|password|pass/i});import G,{useEffect as ba,useMemo as Sa,useState as Ht}from"react";import{Box as zt,Text as tt,useInput as ka,useStdout as xa}from"ink";import Ta from"ink-text-input";function gn({registry:r,appName:t,onExit:e}){let{stdout:n}=xa(),[s,o]=Ht(0),[i,a]=Ht(!1),[l,c]=Ht(""),[d,p]=Ht(""),[v,S]=Ht(0),[u,m]=Ht(0);ba(()=>{let g=()=>o(k=>k+1);r.on("change",g);let C=setInterval(()=>o(k=>k+1),500);return()=>{r.off("change",g),clearInterval(C)}},[r]);let f=r.getState(t)?.logBuffer.map(g=>g.line)??[],w=(n.rows||30)-4,E=Sa(()=>{if(!d)return[];let g=d.toLowerCase();return f.reduce((C,k,$)=>(k.toLowerCase().includes(g)&&C.push($),C),[])},[f,d,s]);ka((g,C)=>{if(i){if(C.escape){a(!1),c("");return}return}if(g==="q"||C.escape){e();return}if(g==="/"){a(!0);return}if(g==="g"){S(Math.max(0,f.length-w));return}if(g==="G"){S(0);return}if(C.pageUp){S(k=>Math.min(Math.max(0,f.length-w),k+w));return}if(C.pageDown){S(k=>Math.max(0,k-w));return}if(C.upArrow){S(k=>Math.min(Math.max(0,f.length-w),k+1));return}if(C.downArrow){S(k=>Math.max(0,k-1));return}if((g==="n"||g==="N")&&E.length){let k=g==="n"?(u+1)%E.length:(u-1+E.length)%E.length;m(k);let $=E[k],B=f.length-v,x=B-w;($<x||$>=B)&&S(Math.max(0,f.length-$-Math.floor(w/2)));return}});let P=g=>{p(g),a(!1),c(""),m(0)},b=f.length-v,j=Math.max(0,b-w),_=f.slice(j,b),y=(g,C)=>{if(!d)return G.createElement(tt,{key:C},G.createElement(tt,{dimColor:!0},String(C+1).padStart(5)," "),g);let k=d,$=g.toLowerCase(),B=k.toLowerCase(),x=[],I=0,N=0;for(;I<g.length;){let q=$.indexOf(B,I);if(q<0){x.push(G.createElement(tt,{key:N++},g.slice(I)));break}q>I&&x.push(G.createElement(tt,{key:N++},g.slice(I,q))),x.push(G.createElement(tt,{key:N++,backgroundColor:"yellow",color:"black"},g.slice(q,q+k.length))),I=q+k.length}let L=E[u]===C;return G.createElement(tt,{key:C},G.createElement(tt,{color:L?"cyan":void 0,dimColor:!L},String(C+1).padStart(5)," "),x)};return G.createElement(zt,{flexDirection:"column"},G.createElement(zt,null,G.createElement(tt,{bold:!0},"full log: ",G.createElement(tt,{color:"cyan"},t)),G.createElement(tt,{dimColor:!0}," (",f.length," lines",d?`, ${E.length} matches for "${d}"`:"",", scroll=",v,")")),G.createElement(zt,{flexDirection:"column"},_.length===0?G.createElement(tt,{dimColor:!0},"(no log yet)"):_.map((g,C)=>y(g,j+C))),G.createElement(zt,null,i?G.createElement(zt,null,G.createElement(tt,null,"/"),G.createElement(Ta,{value:l,onChange:c,onSubmit:P})):G.createElement(tt,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var Ps=D(()=>{"use strict"});import R,{useEffect as Pa,useState as it}from"react";import yn from"node:fs";import Ca from"node:os";import Ea from"node:path";import{Box as et,Text as M,useApp as Aa,useInput as Ra,useStdout as Oa}from"ink";import wn from"ink-text-input";import{spawn as vn,spawnSync as Na}from"node:child_process";function $a(r){try{process.platform==="win32"?vn("cmd",["/c","start","",r],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?vn("open",[r],{detached:!0,stdio:"ignore"}).unref():vn("xdg-open",[r],{detached:!0,stdio:"ignore"}).unref()}catch{}}function ja(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 bn({registry:r,apiPort:t,onQuit:e}){let{exit:n}=Aa(),{stdout:s}=Oa(),[o,i]=it(r.list()),[a,l]=it(0),[c,d]=it(!1),[p,v]=it(0),[S,u]=it(!1),[m,h]=it([]),[f,w]=it(!1),[E,P]=it(""),[b,j]=it(null),[,_]=it(0);Pa(()=>{let x=()=>i(r.list());r.on("change",x);let I=setInterval(()=>{i(r.list()),_(N=>N+1)},1e3);return()=>{r.off("change",x),clearInterval(I)}},[r]),Ra((x,I)=>{if(S)return;if(b){if(I.escape){j(null);return}if(I.tab){let L=b.field==="command"?"port":b.field==="port"?"env":"command";j({...b,field:L});return}return}if(f){if(I.escape){w(!1),P("");return}if(I.return){let L=E.trim();h(L?L.split(/[\s,]+/).filter(Boolean):[]),w(!1),P("");return}if(I.backspace||I.delete){P(L=>L.slice(0,-1));return}x&&!I.ctrl&&P(L=>L+x);return}if(x==="q"||I.ctrl&&x==="c"){e(),n();return}if(o.length===0)return;if(I.upArrow){l(L=>Math.max(0,L-1)),v(0);return}if(I.downArrow){l(L=>Math.min(o.length-1,L+1)),v(0);return}let N=o[a];if(N)if(x==="s")r.start(N.name);else if(x==="x")r.stop(N.name);else if(x==="r")r.restart(N.name);else if(x==="L")u(!0);else if(x==="t")w(!0),P(m.join(" "));else if(x==="e"){let L=r.getConfig(),q=r.getApp(N.name),ct=r.getState(N.name)?.sessionOverrides??null,Jt=ct?.env??L.overrides?.[N.name]?.env??{},vt=Object.entries(Jt).map(([_e,Ie])=>`${_e}=${Ie}`).join(`
|
|
69
|
+
`);j({name:N.name,field:"command",cmd:ct?.command??q?.command??"",port:String(ct?.port??L.overrides?.[N.name]?.port??N.port??""),env:vt})}else if(x==="E"){let q=r.getConfig().envFiles?.[N.name]??[];if(!q.length)return;let ct=r.getState(N.name)?.activeEnvFile??null,Jt=ct?q.indexOf(ct):-1,vt=q[(Jt+1)%q.length];r.setActiveEnvFile(N.name,vt)}else if(x==="V"){let L=process.env.EDITOR||(process.platform==="win32"?"notepad":"vi"),q=Ea.join(Ca.tmpdir(),`daimon-${N.name}-${Date.now()}.json`),ct=r.getConfig(),Jt=r.getApp(N.name),vt=r.getState(N.name)?.sessionOverrides??null,_e={command:vt?.command??Jt?.command,port:vt?.port??ct.overrides?.[N.name]?.port??null,env:vt?.env??ct.overrides?.[N.name]?.env??{}};try{yn.writeFileSync(q,JSON.stringify(_e,null,2)),Na(L,[q],{stdio:"inherit",shell:!0});let Ie=yn.readFileSync(q,"utf8"),bt=JSON.parse(Ie);r.setSessionOverride(N.name,{command:typeof bt.command=="string"?bt.command:void 0,port:typeof bt.port=="number"?bt.port:void 0,env:bt.env&&typeof bt.env=="object"?bt.env:void 0}),yn.unlinkSync(q)}catch{}}else x==="l"?d(L=>!L):x==="o"?N.url&&$a(N.url):I.pageUp?v(L=>L+5):I.pageDown&&v(L=>Math.max(0,L-5))});let y=m.length===0?o:o.filter(x=>m.every(I=>x.tags.includes(I))),g=y[Math.min(a,Math.max(0,y.length-1))],C=g?r.getState(g.name):null,k=C?C.logBuffer.slice(Math.max(0,C.logBuffer.length-12-p),C.logBuffer.length-p).map(x=>x.line):[],$=s.columns||100,B=Math.min(36,Math.floor($*.4));return S&&g?R.createElement(gn,{registry:r,appName:g.name,onExit:()=>u(!1)}):R.createElement(et,{flexDirection:"column",width:$},R.createElement(et,{borderStyle:"round",borderColor:"cyan",paddingX:1},R.createElement(M,{bold:!0,color:"cyan"},"daimon"),R.createElement(M,{dimColor:!0}," \u2022 api http://127.0.0.1:",t)),R.createElement(et,{flexDirection:"row"},R.createElement(et,{flexDirection:"column",width:B,borderStyle:"single",borderColor:"gray",paddingX:1},R.createElement(M,{bold:!0},"Apps ",m.length?R.createElement(M,{dimColor:!0},"(tags: ",m.join(", "),")"):null),y.length===0?R.createElement(M,{dimColor:!0},o.length===0?"(no apps discovered)":"(no apps match tag filter)"):y.map((x,I)=>{let N=I===a;return R.createElement(et,{key:x.name},R.createElement(M,{color:N?"cyan":void 0},N?"\u25B8 ":" "),R.createElement(M,{color:N?"cyan":void 0},((r.getState(x.name)?.sessionOverrides?"*":"")+x.name).padEnd(20).slice(0,20)),R.createElement(M,{color:Cs[x.status]}," ",x.status.padEnd(9)),R.createElement(M,{color:Es[x.health]},x.status==="serving"?"\u25CF":" "),R.createElement(M,{dimColor:!0},x.port?` :${x.port}`:""),$>=100&&x.cpu!=null?R.createElement(M,{dimColor:!0}," ",String(x.cpu).padStart(5),"% ",String(x.memMB??0).padStart(5),"MB"):null)})),R.createElement(et,{flexDirection:"column",flexGrow:1,borderStyle:"single",borderColor:"gray",paddingX:1},g&&C?R.createElement(R.Fragment,null,R.createElement(M,null,"Selected: ",R.createElement(M,{bold:!0},g.name)),R.createElement(M,null,"Status: ",R.createElement(M,{color:Cs[g.status]},g.status)," ",R.createElement(M,{color:Es[g.health]},"\u25CF")," ",R.createElement(M,{dimColor:!0},g.health)),R.createElement(M,null,"Port: ",g.port??"-"),R.createElement(M,null,"URL: ",g.url??"-"),g.announcedUrl&&g.announcedUrl!==g.url?R.createElement(M,{dimColor:!0},"Announced: ",g.announcedUrl):null,g.lastHealthError?R.createElement(M,{color:"red"},"HealthErr: ",g.lastHealthError):null,g.stale?R.createElement(M,{color:"yellow"},"\u26A0 stale (best guess)"):null,R.createElement(M,null,"Errors: ",R.createElement(M,{color:g.errorCount?"red":void 0},g.errorCount)),R.createElement(M,null,"Uptime: ",ja(g.uptimeMs)),g.cpu!=null||g.memMB!=null?R.createElement(M,null,"Usage: ",g.cpu??"-","% ",g.memMB??"-"," MB"):null,g.compileHistoryMs.length>0?R.createElement(M,null,"Recent compile: ",g.compileHistoryMs.slice(-5).map(x=>(x/1e3).toFixed(1)+"s").join(" \xB7 ")):null,g.bundle?R.createElement(M,null,"Bundle: ",g.bundle.initialKB,"KB initial \xB7 ",g.bundle.lazyKB,"KB lazy",g.bundleRegressionPct!=null&&g.bundleRegressionPct>10?R.createElement(M,{color:"red"}," (+",g.bundleRegressionPct,"% \u26A0)"):null):null,C.lastStatusMessage?R.createElement(M,{dimColor:!0},"Note: ",C.lastStatusMessage):null,R.createElement(M,null,"\u2500\u2500\u2500\u2500 recent log ",c?"(focused)":""," \u2500\u2500\u2500\u2500"),k.length===0?R.createElement(M,{dimColor:!0},"(no output yet)"):k.map((x,I)=>R.createElement(M,{key:I,wrap:"truncate-end"},x))):R.createElement(M,{dimColor:!0},"No app selected."))),R.createElement(et,{flexDirection:"column"},f?R.createElement(M,null,"tag filter (space-separated, Enter to apply, Esc to cancel): ",R.createElement(M,{color:"cyan"},E)):null,b?R.createElement(et,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1},R.createElement(M,{bold:!0,color:"yellow"},"edit ",b.name," (session-only) Tab=next field Enter=save Esc=cancel"),R.createElement(et,null,R.createElement(M,null,b.field==="command"?"> ":" ","command: "),b.field==="command"?R.createElement(wn,{value:b.cmd,onChange:x=>j({...b,cmd:x}),onSubmit:()=>j({...b,field:"port"})}):R.createElement(M,{dimColor:!0},b.cmd)),R.createElement(et,null,R.createElement(M,null,b.field==="port"?"> ":" ","port: "),b.field==="port"?R.createElement(wn,{value:b.port,onChange:x=>j({...b,port:x}),onSubmit:()=>j({...b,field:"env"})}):R.createElement(M,{dimColor:!0},b.port)),R.createElement(et,null,R.createElement(M,null,b.field==="env"?"> ":" ","env (k=v;): "),b.field==="env"?R.createElement(wn,{value:b.env.replace(/\n/g,";"),onChange:x=>j({...b,env:x.replace(/;/g,`
|
|
70
|
+
`)}),onSubmit:()=>{let x=Number(b.port),I={};for(let N of b.env.split(/\n/)){let L=N.match(/^\s*([^=]+)=(.*)$/);L&&(I[L[1].trim()]=L[2])}r.setSessionOverride(b.name,{command:b.cmd||void 0,port:Number.isFinite(x)&&x>0?x:void 0,env:Object.keys(I).length?I:void 0}),j(null)}}):R.createElement(M,{dimColor:!0},b.env))):null,R.createElement(M,{dimColor:!0},"[s] start [x] stop [r] restart [o] open URL [t] tag filter [e] edit [E] cycle env [V] $EDITOR [l] log focus [Shift+L] full log [PgUp/PgDn] scroll [q] quit")))}var Cs,Es,As=D(()=>{"use strict";Ps();Cs={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Es={healthy:"green",unhealthy:"red",unknown:"gray"}});var Os={};ut(Os,{startInProcess:()=>Rs});import Ma from"react";import{render as Da}from"ink";import{pathToFileURL as _a}from"node:url";async function Rs(r={}){let t=null,e=null;xs({getRegistry:()=>t,getConfig:()=>e});let n;try{n=Y()}catch(y){process.stderr.write(`[daimon] config error: ${y.message}
|
|
71
|
+
`),process.exit(1)}if(n.kind==="stub-created"){let y=St();process.stdout.write(`[daimon] no config found. Created stub at:
|
|
68
72
|
${n.path}
|
|
69
73
|
`),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: ${
|
|
74
|
+
`),process.stdout.write(`[daimon] (Local override path: ${y.local})
|
|
71
75
|
`),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",()=>{b()}),process.on("SIGTERM",()=>{b()}),process.on("beforeExit",()=>{b()}),
|
|
79
|
-
`);let
|
|
80
|
-
`),
|
|
81
|
-
`),process.exit(1)})});var
|
|
76
|
+
`),s.depends&&Object.keys(s.depends).length){let y=te(s.depends);y&&(process.stderr.write(`[daimon] config error: depends graph has a cycle: ${y.join(" -> ")}
|
|
77
|
+
`),process.exit(1))}let i=kt(s);i.length===0&&process.stdout.write(`[daimon] no serveable projects discovered in: ${s.searchRoots.join(", ")||"(none)"}
|
|
78
|
+
`);let a=as(),l=new $t(s.portRange,{initial:a.ports,onChange:y=>cs({ports:y})}),c=new fe(s,i,l);t=c,e=s;let d=new ft(s.history);c.setHistory(d);let p=new Te(c,s.healthProbe,s),v=new Pe(c),S=new Ce(c,s.autoRestart),u=new Ee(c,s.notifications),m=new Ae(c,s.staleDetect),h=new Oe(c,s.requestLog);c.on("childExit",({name:y,code:g,signal:C,stopping:k})=>S.onExit(y,g,C,k)),c.on("userStop",({name:y})=>S.onUserStop(y));let f=Yr();if(f&&f.apps.length){process.stdout.write(`[daimon] state-handoff: restoring ${f.apps.map(y=>y.name).join(", ")}
|
|
79
|
+
`);for(let y of f.apps)l.pin(y.name,y.port);for(let y of f.apps)c.names().includes(y.name)&&c.start(y.name)}if(s.autoStart&&s.autoStart.length){let y=new Set(c.names());for(let g of s.autoStart){if(!y.has(g)){process.stderr.write(`[daimon] warning: autoStart references unknown app "${g}"
|
|
80
|
+
`);continue}s.depends&&s.depends[g]&&s.depends[g].length?c.startWithDeps(g):c.start(g)}}let w=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):s.apiPort,E=!!r.headless||!!s.headless||process.argv.includes("--headless"),P=!1,b=async()=>{if(!P){P=!0;try{p.stop()}catch{}try{v.stop()}catch{}try{S.stop()}catch{}try{u.stop()}catch{}try{m.stop()}catch{}try{h.stop()}catch{}try{d.close()}catch{}try{await c.stopAll(3e3)}catch{}try{j.close()}catch{}try{rt()}catch{}process.exit(0)}},j=Qr(c,w,{metricsEnabled:s.metrics.enabled,requestLog:h,onShutdown:()=>{b()},configPath:o,getConfig:()=>c.getConfig(),patchConfig:y=>{try{let g=vs({configPath:o,patch:y}),C=hn({configPath:o,registry:c});return{ok:!0,applied:g.applied,addedApps:C.addedApps,removedApps:C.removedApps,restartRequired:C.restartRequired}}catch(g){return{ok:!1,error:g?.message||String(g)}}},reloadConfig:async()=>{let y=hn({configPath:o,registry:c});return{ok:!0,addedApps:y.addedApps,removedApps:y.removedApps,restartRequired:y.restartRequired}}});process.stdout.write(`[daimon] api: http://127.0.0.1:${w}
|
|
81
|
+
`);try{Bn(Jn(w,E,o))}catch(y){process.stderr.write(`[daimon] warning: could not write daemon.lock: ${y?.message||y}
|
|
82
|
+
`)}if(process.on("SIGINT",()=>{b()}),process.on("SIGTERM",()=>{b()}),process.on("beforeExit",()=>{b()}),E){process.stdout.write(`[daimon] headless mode \u2014 TUI suppressed. Dashboard: http://127.0.0.1:${w}
|
|
83
|
+
`);let y="",g=setInterval(()=>{let C=c.list().map($=>({name:$.name,status:$.status,health:$.health,port:$.port})),k=JSON.stringify(C);k!==y&&(process.stderr.write(k+`
|
|
84
|
+
`),y=k)},6e4);await new Promise(()=>{}),clearInterval(g);return}await Da(Ma.createElement(bn,{registry:c,apiPort:w,onQuit:()=>{b()}})).waitUntilExit(),await b()}var Ia,Ns=D(()=>{"use strict";Rt();Nt();Er();qt();ts();rs();ss();os();ls();ne();ee();ds();ms();gs();st();bs();Ts();sn();As();Ia=(()=>{try{return import.meta.url===_a(process.argv[1]||"").href}catch{return!1}})();Ia&&Rs().catch(r=>{process.stderr.write(`[daimon] fatal: ${r?.stack||r}
|
|
85
|
+
`),process.exit(1)})});var Ms={};ut(Ms,{attachToDaemon:()=>za});import F,{useEffect as $s,useState as gt}from"react";import Sn from"node:fs";import js from"node:path";import La from"node:os";import{Box as Bt,render as Fa,Text as J,useApp as Ua,useInput as Ha,useStdout as Ba}from"ink";import Ja from"ink-text-input";function qa(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 kn(r){return js.join(La.homedir(),".daimon",`attach-token.${r}`)}function Xa(r){try{return Sn.readFileSync(kn(r),"utf8").trim()||null}catch{return null}}function Ka(r,t){try{Sn.mkdirSync(js.dirname(kn(r)),{recursive:!0}),Sn.writeFileSync(kn(r),t,"utf8")}catch{}}function Ya({port:r,onExit:t}){let{exit:e}=Ua(),{stdout:n}=Ba(),[s,o]=gt([]),[i,a]=gt(0),[l,c]=gt(!1),[d,p]=gt([]),[v,S]=gt(null),[u,m]=gt(()=>Xa(r)),[h,f]=gt(!1),[w,E]=gt(""),P=`http://127.0.0.1:${r}`;async function b(y,g={}){try{let C={...g.headers||{}};u&&(C.authorization=`Bearer ${u}`);let k=await fetch(P+y,{...g,headers:C}),$=await k.text(),B=$;try{B=JSON.parse($)}catch{}return{status:k.status,body:B}}catch(C){return{status:0,body:{error:C?.message||String(C)}}}}if($s(()=>{let y=!1,g=async()=>{let k=await b("/api/apps?format=full");if(!y){if(k.status===0){S(k.body?.error||"daemon unreachable");return}if(k.status===401){f(!0);return}S(null),o(Array.isArray(k.body)?k.body:[])}};g();let C=setInterval(g,1e3);return()=>{y=!0,clearInterval(C)}},[u]),$s(()=>{if(!l){p([]);return}let y=!1,g=s[i];if(!g)return;let C=async()=>{let $=await b(`/api/apps/${encodeURIComponent(g.name)}/logs?tail=12`);y||Array.isArray($.body?.lines)&&p($.body.lines)};C();let k=setInterval(C,1e3);return()=>{y=!0,clearInterval(k)}},[l,i,s.length,u]),Ha((y,g)=>{if(h){if(g.escape){f(!1);return}return}if(y==="q"||g.ctrl&&y==="c"){t(),e();return}if(g.upArrow)a(C=>Math.max(0,C-1));else if(g.downArrow)a(C=>Math.min(Math.max(0,s.length-1),C+1));else if(g.return||y===" ")c(C=>!C);else if(y==="s"||y==="x"||y==="r"){let C=s[i];if(!C)return;let k=y==="s"?"start":y==="x"?"stop":"restart";b(`/api/apps/${encodeURIComponent(C.name)}/${k}`,{method:"POST"})}}),h)return F.createElement(Bt,{flexDirection:"column",paddingX:1},F.createElement(J,{color:"yellow"},"daemon requires a bearer token. Enter token (Esc to cancel):"),F.createElement(Ja,{value:w,onChange:E,mask:"*",onSubmit:()=>{let y=w.trim();y&&(m(y),Ka(r,y)),E(""),f(!1)}}));let j=n.columns||100,_=s[i];return F.createElement(Bt,{flexDirection:"column",width:j},F.createElement(Bt,{borderStyle:"round",borderColor:"cyan",paddingX:1},F.createElement(J,{bold:!0,color:"cyan"},"daimon attach"),F.createElement(J,{dimColor:!0}," \u2022 http://127.0.0.1:",r," \u2022 HTTP-client TUI (q detaches, daemon keeps running)")),v?F.createElement(J,{color:"red"},v):null,F.createElement(Bt,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},F.createElement(J,{bold:!0},"Apps (",s.length,")"),s.length===0?F.createElement(J,{dimColor:!0},"(no apps)"):s.map((y,g)=>{let C=g===i;return F.createElement(Bt,{key:y.name},F.createElement(J,{color:C?"cyan":void 0},C?"\u25B8 ":" "),F.createElement(J,{color:C?"cyan":void 0},y.name.padEnd(20).slice(0,20)),F.createElement(J,{color:Wa[y.status]}," ",y.status.padEnd(9)),F.createElement(J,{color:Ga[y.health]},y.status==="serving"?"\u25CF":" "),F.createElement(J,{dimColor:!0},y.port?` :${y.port}`:""),F.createElement(J,{dimColor:!0}," errs=",y.errorCount," up=",qa(y.uptimeMs)))})),_?F.createElement(Bt,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},F.createElement(J,null,"Selected: ",F.createElement(J,{bold:!0},_.name)),F.createElement(J,null,"URL: ",_.url??"-"),_.lastHealthError?F.createElement(J,{color:"red"},"HealthErr: ",_.lastHealthError):null,F.createElement(J,{dimColor:!0},"\u2500\u2500\u2500\u2500 recent log (Enter/Space toggles) \u2500\u2500\u2500\u2500"),l?d.length===0?F.createElement(J,{dimColor:!0},"(loading\u2026)"):d.map((y,g)=>F.createElement(J,{key:g,wrap:"truncate-end"},y)):F.createElement(J,{dimColor:!0},"(press Enter to fetch logs)")):null,F.createElement(J,{dimColor:!0},"[s] start [x] stop [r] restart [Enter] toggle log [q] detach (daemon keeps running)"))}async function za(r){let t,e=new Promise(s=>{t=s});await Fa(F.createElement(Ya,{port:r,onExit:()=>t()})).waitUntilExit(),await e}var Wa,Ga,Ds=D(()=>{"use strict";Wa={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Ga={healthy:"green",unhealthy:"red",unknown:"gray"}});var Fs={};ut(Fs,{buildServiceArtifact:()=>Ls,installServiceArtifact:()=>Za});import _s from"node:fs";import Is from"node:os";import yt from"node:path";import{fileURLToPath as Va}from"node:url";function Ne(){return process.execPath}function $e(){let r=yt.dirname(Va(import.meta.url));return yt.join(r,"main.js")}function Ls(){let r=process.platform;if(r==="win32"){let n=`<?xml version="1.0" encoding="UTF-8"?>
|
|
82
86
|
<!-- generated by daimon daemon install-service -->
|
|
83
87
|
<service>
|
|
84
88
|
<id>daimon</id>
|
|
85
89
|
<name>daimon daemon</name>
|
|
86
90
|
<description>Local Angular/Nx/Vite dev server manager (daimon headless daemon)</description>
|
|
87
|
-
<executable>${
|
|
88
|
-
<arguments>"${
|
|
91
|
+
<executable>${Ne()}</executable>
|
|
92
|
+
<arguments>"${$e()}" --headless</arguments>
|
|
89
93
|
<log mode="rotate"/>
|
|
90
94
|
<onfailure action="restart" delay="10 sec"/>
|
|
91
95
|
</service>
|
|
92
|
-
`,s=
|
|
96
|
+
`,s=yt.join(Z(),"daimon-daemon.xml");return{platform:r,path:s,body:n,installCmd:`nssm install daimon "${Ne()}" "${$e()}" --headless`}}if(r==="darwin"){let n=`<?xml version="1.0" encoding="UTF-8"?>
|
|
93
97
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
94
98
|
<plist version="1.0">
|
|
95
99
|
<dict>
|
|
96
100
|
<key>Label</key><string>dev.daimon</string>
|
|
97
101
|
<key>ProgramArguments</key>
|
|
98
102
|
<array>
|
|
99
|
-
<string>${
|
|
100
|
-
<string>${
|
|
103
|
+
<string>${Ne()}</string>
|
|
104
|
+
<string>${$e()}</string>
|
|
101
105
|
<string>--headless</string>
|
|
102
106
|
</array>
|
|
103
107
|
<key>RunAtLoad</key><true/>
|
|
104
108
|
<key>KeepAlive</key><true/>
|
|
105
|
-
<key>StandardOutPath</key><string>${
|
|
106
|
-
<key>StandardErrorPath</key><string>${
|
|
109
|
+
<key>StandardOutPath</key><string>${yt.join(Z(),"service.out.log")}</string>
|
|
110
|
+
<key>StandardErrorPath</key><string>${yt.join(Z(),"service.err.log")}</string>
|
|
107
111
|
</dict>
|
|
108
112
|
</plist>
|
|
109
|
-
`,s=
|
|
113
|
+
`,s=yt.join(Is.homedir(),"Library","LaunchAgents","dev.daimon.plist");return{platform:r,path:s,body:n,installCmd:`launchctl load ${s}`}}let t=`[Unit]
|
|
110
114
|
Description=daimon daemon (local dev-server manager)
|
|
111
115
|
After=network.target
|
|
112
116
|
|
|
113
117
|
[Service]
|
|
114
|
-
ExecStart=${
|
|
118
|
+
ExecStart=${Ne()} ${$e()} --headless
|
|
115
119
|
Restart=on-failure
|
|
116
120
|
RestartSec=10
|
|
117
121
|
|
|
118
122
|
[Install]
|
|
119
123
|
WantedBy=default.target
|
|
120
|
-
`,e=
|
|
121
|
-
`,"utf8"),{path:o,installClaude:!1,config:i,auto:!0}}async function
|
|
122
|
-
`),(await
|
|
123
|
-
`,"utf8"),process.stdout.write(`[daimon init] wrote ${
|
|
124
|
-
`);let
|
|
125
|
-
`)}function
|
|
126
|
-
`)}function
|
|
127
|
-
`);try{
|
|
128
|
-
`),process.exit(1));var
|
|
124
|
+
`,e=yt.join(Is.homedir(),".config","systemd","user","daimon.service");return{platform:r,path:e,body:t,installCmd:"systemctl --user enable daimon && systemctl --user start daimon"}}function Za(){let r=Ls();return _s.mkdirSync(yt.dirname(r.path),{recursive:!0}),_s.writeFileSync(r.path,r.body,"utf8"),{path:r.path,installCmd:r.installCmd,platform:r.platform}}var Us=D(()=>{"use strict";st()});var Js={};ut(Js,{runInit:()=>nc,runInitAuto:()=>Bs});import wt from"node:fs";import Qa from"node:os";import At from"node:path";import tc from"node:readline";function Et(r,t){return new Promise(e=>r.question(t,n=>e(n.trim())))}function Hs(r){let t=[];for(let e of ec)wt.existsSync(At.join(r,e))&&t.push(e);return t}async function Bs(r={}){let t=r.cwd??process.cwd(),e=Hs(t),n=[],s;try{let a=JSON.parse(wt.readFileSync(At.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=At.join(t,"daimon.config.json");if(wt.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 wt.mkdirSync(At.dirname(o),{recursive:!0}),wt.writeFileSync(o,JSON.stringify(i,null,2)+`
|
|
125
|
+
`,"utf8"),{path:o,installClaude:!1,config:i,auto:!0}}async function nc(r={}){if(r.auto)return Bs(r);let t=r.cwd??process.cwd(),e=tc.createInterface({input:process.stdin,output:process.stdout});try{let n=Hs(t),s=[];if(n.length&&(process.stdout.write(`[daimon init] detected in ${t}: ${n.join(", ")}
|
|
126
|
+
`),(await Et(e,"Add this folder as a searchRoot? [Y/n] ")||"y").toLowerCase().startsWith("y"))){let f=await Et(e,"Optional label for this workspace (blank = none): ");s.push(f?{path:t,label:f}:t)}let o=await Et(e,"Additional searchRoots (comma-separated absolute paths, blank to skip): ");if(o)for(let h of o.split(",").map(f=>f.trim()).filter(Boolean))s.push(h);let a=(await Et(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 Et(e,"apiPort [4999]: ")||"4999",d=Number(c)||4999,v=(await Et(e,"Write to (1) ./daimon.config.json or (2) ~/.daimon/config.json? [1] ")||"1").trim()==="2"?At.join(Qa.homedir(),".daimon","config.json"):At.join(t,"daimon.config.json");if(wt.existsSync(v)&&!r.force)throw new Error(`refusing to overwrite ${v} (pass --force to overwrite)`);let S={searchRoots:s,portRange:l,apiPort:d};wt.mkdirSync(At.dirname(v),{recursive:!0}),wt.writeFileSync(v,JSON.stringify(S,null,2)+`
|
|
127
|
+
`,"utf8"),process.stdout.write(`[daimon init] wrote ${v}
|
|
128
|
+
`);let m=(await Et(e,"Install Claude Code integration? [Y/n] ")||"y").toLowerCase().startsWith("y");return{path:v,installClaude:m,config:S}}finally{e.close()}}var ec,Ws=D(()=>{"use strict";ec=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs",".storybook"]});Rt();Nt();import rc from"node:os";ee();qt();ne();import xt from"node:fs";import jt from"node:path";async function Dn(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,p=jt.resolve(d);if(!xt.existsSync(p)){e.push({name:`searchRoot exists: ${p}`,ok:!1,detail:"not found"});continue}let v=xt.existsSync(jt.join(p,"nx.json"))||xt.existsSync(jt.join(p,"angular.json"))||xt.existsSync(jt.join(p,".storybook"))||["ts","js","mjs","cjs"].some(S=>xt.existsSync(jt.join(p,`vite.config.${S}`)));e.push({name:`searchRoot has marker: ${p}`,ok:v,detail:v?void 0:"no nx.json/angular.json/vite.config.*/.storybook"})}for(let[c,d]of Object.entries(r.overrides??{})){let p=n.has(c),v=!!d.command,S=p||v;e.push({name:`override "${c}"`,ok:S,detail:S?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 p of d)e.push({name:`profile "${c}" entry "${p}"`,ok:n.has(p),detail:n.has(p)?void 0:"unknown app"});if(r.depends&&Object.keys(r.depends).length){for(let[d,p]of Object.entries(r.depends))for(let v of p)n.has(v)||e.push({name:`depends "${d}" -> "${v}"`,ok:!1,detail:"unknown app"});let c=te(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:xt.existsSync(d),detail:xt.existsSync(d)?void 0:"missing"})}let a=await dt(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 p=new ft(r.history);c=p.quickCheck(),p.close(),c||(d="quick_check failed")}catch(p){d=p?.message||String(p)}e.push({name:"history db",ok:c,detail:d})}return e.push({name:"agent token footprint",ok:!0,detail:so(t)}),{ok:e.every(c=>c.ok),checks:e}}function so(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}%`}Je();We();st();Mt();var ht=[{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:"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 Wn(r){return ht.find(t=>t.name===r)}function Gn(){let r=Math.max(...ht.map(t=>t.name.length));return ht.map(t=>`${t.name.padEnd(r)} ${t.summary}`).join(`
|
|
129
|
+
`)}function qn(){return"usage: daimon <"+ht.map(r=>r.name).join("|")+">"}Mt();import K from"node:fs";import mo from"node:os";import W from"node:path";import{fileURLToPath as ho}from"node:url";st();var Xn=W.dirname(ho(import.meta.url)),zn=["status","start","stop","restart","errors","logs","up","doctor","why","wait"],go=["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 ce(){return W.join(mo.homedir(),".claude")}function It(r){return W.join(r,"daimon.installed.json")}function yo(){let r=[W.resolve(Xn,"templates","claude"),W.resolve(Xn,"..","src","templates","claude")];for(let t of r)if(K.existsSync(t))return t;throw new Error("claude templates directory not found")}function Kn(r){return K.readFileSync(W.join(yo(),r),"utf8")}function Yn(r,t){let e=new Date().toISOString();return r.replace(/\{\{daimon_version\}\}/g,X).replace(/\{\{api_port\}\}/g,String(t)).replace(/\{\{generated_at\}\}/g,e).replace(/\{\{commands_table\}\}/g,Gn())}function Ye(r,t){K.mkdirSync(W.dirname(r),{recursive:!0}),K.writeFileSync(r,t,"utf8")}function Lt(r){try{let t=K.readFileSync(It(r),"utf8");return t.charCodeAt(0)===65279&&(t=t.slice(1)),JSON.parse(t)}catch{return null}}function Vn(r,t){Ye(It(r),JSON.stringify(t,null,2)+`
|
|
130
|
+
`)}function wo(r){let t=[],e=[],n=r.priorInstalledAt?Date.parse(r.priorInstalledAt):0;for(let s of go){let o=W.join(r.dir,"commands",s),i;try{i=K.statSync(o)}catch{continue}if(!i.isFile())continue;let a=n>0?i.mtimeMs>n+5e3:!1;try{a?(K.renameSync(o,o+".bak"),e.push(s),r.onEvent?.({kind:"backed-up",file:s})):(K.rmSync(o,{force:!0}),t.push(s),r.onEvent?.({kind:"removed",file:s}))}catch{}}return{removed:t,backedUp:e}}function le(r){let t=[],e=Lt(r.dir),n=e??{"daimon-version":X,"installed-at":new Date().toISOString()};n["daimon-version"]=X,n["installed-at"]=new Date().toISOString();let s=wo({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=W.join("skills","daimon","SKILL.md");Ye(W.join(r.dir,o),Yn(Kn("skill.md.tmpl"),r.apiPort)),n.skill={path:o.replace(/\\/g,"/")},t.push(o)}if(r.agent){let o=W.join("agents","daimon-runner.md");Ye(W.join(r.dir,o),Yn(Kn("agent.md.tmpl"),r.apiPort)),n.agent={path:o.replace(/\\/g,"/")},t.push(o)}return Vn(r.dir,n),{installed:t,manifestPath:It(r.dir),migrated:s}}function Zn(r){let t=[],e=Lt(r.dir);if(!e)return{removed:t,manifestPath:null};let n=r.selection.all;if((n||r.selection.skill)&&e.skill){let s=W.join(r.dir,e.skill.path);try{K.rmSync(s,{force:!0}),t.push(e.skill.path)}catch{}try{K.rmdirSync(W.dirname(s))}catch{}e.skill=null}if((n||r.selection.commands)&&e.commands){for(let s of e.commands){let o=W.join("commands",`daimon-${s}.md`);try{K.rmSync(W.join(r.dir,o),{force:!0}),t.push(o)}catch{}}e.commands=[]}if((n||r.selection.agent)&&e.agent){try{K.rmSync(W.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{K.unlinkSync(It(r.dir))}catch{}return{removed:t,manifestPath:null}}return Vn(r.dir,e),{removed:t,manifestPath:It(r.dir)}}function Qn(r){let t=Lt(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:It(r)}:{skill:{installed:!1,version:null,path:null},commands:{installed:!1,version:null,names:[]},agent:{installed:!1,version:null,path:null},manifestPath:null}}var Ke=W.join(Z(),".claude-nudge"),vo=1440*60*1e3;function tr(){if(process.env.DAIMON_NO_CLAUDE_NUDGE==="1")return;let r=ce(),t=Lt(r);if(t&&t["daimon-version"]!==X){try{let e=K.statSync(Ke);if(Date.now()-e.mtimeMs<vo)return}catch{}process.stderr.write(`[daimon] claude integration is from v${t["daimon-version"]} \u2014 run \`daimon claude update\` to refresh
|
|
131
|
+
`);try{K.mkdirSync(W.dirname(Ke),{recursive:!0}),K.writeFileSync(Ke,String(Date.now()))}catch{}}}var Gs=Number((process.versions.node||"0").split(".")[0]);Gs&&Gs<20&&(process.stderr.write(`daimon requires Node >= 20
|
|
132
|
+
`),process.exit(1));var qs=!1;function A(r,t=1){process.stderr.write(r.endsWith(`
|
|
129
133
|
`)?r:r+`
|
|
130
|
-
`),process.exit(t)}function
|
|
131
|
-
`)}function
|
|
132
|
-
`);
|
|
133
|
-
`)}
|
|
134
|
-
`)}catch(
|
|
134
|
+
`),process.exit(t)}function O(r){process.stdout.write(JSON.stringify(r)+`
|
|
135
|
+
`)}function Tn(){if(process.env.DAIMON_PORT){let t=Number(process.env.DAIMON_PORT);if(Number.isFinite(t)&&t>0)return t}let r=z();if(r)return r.apiPort;try{let t=Y();if(t.kind==="loaded")return t.config.apiPort}catch{}return 4999}async function sc(){try{let r=Y();if(r.kind==="loaded")return{config:r.config}}catch{}return{config:{}}}function Zt(){return`http://127.0.0.1:${Tn()}`}async function Me(){if(!(qs||process.env.DAIMON_NO_SPAWN==="1")&&!z())try{let r=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0;await mt({port:Number.isFinite(r)&&r>0?r:void 0})}catch{}}function at(){let r=process.env.DAIMON_TOKEN;return r?{authorization:`Bearer ${r}`}:{}}async function xn(r,t="GET"){try{let e=await fetch(Zt()+r,{method:t,headers:at()});(!e.ok||!e.body)&&A(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(`
|
|
136
|
+
`);o=l.pop()??"";for(let c of l)c.trim()&&process.stdout.write(c+`
|
|
137
|
+
`)}o.trim()&&process.stdout.write(o+`
|
|
138
|
+
`)}catch(e){A(JSON.stringify({error:e?.message||String(e)}))}}async function U(r,t="GET"){try{let e=await fetch(Zt()+r,{method:t,headers:at()}),n=await e.text(),s=n;try{s=JSON.parse(n)}catch{}return{status:e.status,body:s}}catch{A(JSON.stringify({error:"daimon is not running \u2014 start it with: daimon daemon start --detach"}))}}async function je(r,t,e){try{let n=await fetch(Zt()+r,{method:t,headers:{"content-type":"application/json",...at()},body:JSON.stringify(e)}),s=await n.text(),o=s;try{o=JSON.parse(s)}catch{}return{status:n.status,body:o}}catch{A(JSON.stringify({error:"daimon is not running \u2014 start it with: daimon daemon start --detach"}))}}function De(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]:t.positional.push(s)}return t}function oc(r){return r.full?"?format=full":r.compact?"?format=compact":""}function Vt(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 ic(){let r=Math.max(...ht.map(e=>e.name.length)),t=[`daimon v${X}`,"usage: daimon <command> [args]",""];for(let e of ht)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
139
|
`)+`
|
|
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)})));
|
|
140
|
+
`)}function ac(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 cc(r){let t=r[0];t||A(JSON.stringify({error:"usage: daimon claude <install|update|uninstall|status> [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]"}));let{flags:e}=ac(r.slice(1)),n=e.dir??ce(),s=Tn();if(t==="status"){O(Qn(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(()=>(sr(),rr)),c=await l();if(!c){O({cancelled:!0});return}o={skill:c.skill,commands:!1,agent:c.agent}}let a=le({...o,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?O({removed:l.file}):O({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});O({installed:a.installed,manifest:a.manifestPath,version:X});return}if(t==="update"){let o=Lt(n);o||A(JSON.stringify({error:"no manifest at "+n+" \u2014 run `daimon claude install` first"}));let i={skill:!!o.skill,commands:!1,agent:!!o.agent},a=le({...i,dir:n,apiPort:s,onMigrationEvent:l=>{l.kind==="removed"?O({removed:l.file}):O({warning:`${l.file} was modified; backing up to ${l.file}.bak`})}});O({updated:a.installed,manifest:a.manifestPath,version:X});return}if(t==="uninstall"){e.skill||e.commands||e.agent||e.all||A(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}});O({removed:i.removed,manifest:i.manifestPath});return}A(JSON.stringify({error:`unknown claude subcommand: ${t}`}))}async function lc(r){let t=r[0],e=De(r.slice(1));switch(t){case"status":{let n=z();if(!n){O({running:!1});return}let s=Date.now()-n.startedAt;O({running:!0,pid:n.pid,port:n.apiPort,uptime:s,version:n.version,headless:n.headless});return}case"start":{if(e.detach){let s=z();if(s){O({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 mt({port:Number.isFinite(o)&&o>0?o:void 0});O({ok:!0,pid:i.pid,port:i.apiPort})}catch(o){A(JSON.stringify({error:o?.message||String(o)}))}return}let{startInProcess:n}=await Promise.resolve().then(()=>(Ns(),Os));await n({headless:!!e.headless});return}case"stop":{let n=z();if(!n){O({ok:!0,wasRunning:!1});return}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:at()})}catch{}if(await Tt(n.pid,5e3))rt(),O({ok:!0,wasRunning:!0});else{try{process.kill(n.pid,"SIGTERM")}catch{}await Tt(n.pid,2e3),rt(),O({ok:!0,wasRunning:!0,forced:!0})}return}case"restart":{let n=z();if(n){try{await fetch(`http://127.0.0.1:${n.apiPort}/api/snapshot-state`,{method:"POST",headers:at()})}catch{}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST",headers:at()})}catch{}await Tt(n.pid,5e3),rt()}let s=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,o=await mt({port:Number.isFinite(s)&&s>0?s:void 0});O({ok:!0,pid:o.pid,port:o.apiPort,handoff:!0});return}case"attach":{await Me();let n=z();n||A(JSON.stringify({error:"no daemon running and auto-spawn failed"}));let{attachToDaemon:s}=await Promise.resolve().then(()=>(Ds(),Ms));await s(n.apiPort);return}case"install-service":{let{installServiceArtifact:n}=await Promise.resolve().then(()=>(Us(),Fs)),s=n();O({platform:s.platform,artifact:s.path,installCmd:s.installCmd});return}default:A(JSON.stringify({error:"usage: daimon daemon <start|stop|status|restart|attach|install-service> [--detach] [--headless]"}))}}async function uc(){let r=process.argv.slice(2).filter(o=>o==="--no-spawn"?(qs=!0,!1):!0),[t,...e]=r;try{tr()}catch{}if(!t||t==="--help"||t==="-h"||t==="help"){ic();return}if(t==="--version"||t==="-v"){O({version:X});return}if(t==="daemon"){await lc(e);return}if(t==="claude"){await cc(e);return}if(t==="export-config"){let o=Y();o.kind!=="loaded"&&A(JSON.stringify({error:"no config loaded"}));let i=De(e),a=JSON.parse(JSON.stringify(o.config));if(i.redacted){let l=rc.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)}))}O(a);return}if(t==="discover"){await Me();let o=await U("/api/discovery/explain");o.status!==200&&A(JSON.stringify({error:"discovery failed",status:o.status})),O(o.body);return}if(t==="init"){let{runInit:o}=await Promise.resolve().then(()=>(Ws(),Js)),i=De(e);try{let a=await o({force:!!i.force,auto:!!i.auto});if(O({path:a.path,installClaude:a.installClaude,auto:a.auto}),a.installClaude){let c=Tn(),d=le({skill:!0,commands:!1,agent:!0,dir:ce(),apiPort:c,onMigrationEvent:p=>{p.kind==="removed"?O({removed:p.file}):O({warning:`${p.file} was modified; backing up to ${p.file}.bak`})}});O({claudeInstalled:d.installed})}let l=z();if(l){try{await fetch(`http://127.0.0.1:${l.apiPort}/api/snapshot-state`,{method:"POST",headers:at()})}catch{}try{await fetch(`http://127.0.0.1:${l.apiPort}/api/shutdown`,{method:"POST",headers:at()})}catch{}await Tt(l.pid,5e3),rt();try{let c=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,d=await mt({port:Number.isFinite(c)&&c>0?c:void 0});O({daemonRestarted:!0,pid:d.pid,port:d.apiPort})}catch(c){O({daemonRestarted:!1,error:c?.message||String(c)})}}try{await Me();let c=await fetch(Zt()+"/api/discovery/explain",{headers:at()});if(c.ok){let d=await c.json(),p={};try{let m=await(await fetch(Zt()+"/api/apps?format=full",{headers:at()})).json();if(Array.isArray(m))for(let h of m){let f=h.workspaceType??"unknown";p[f]=(p[f]??0)+1}}catch{}let v=d.appsFound??0,S={init:"ok",configPath:a.path,discovered:{apps:v,byKind:p}};v===0&&(S._meta={searchRoots:d.searchRoots,scanned:d.scanned,rejected:d.rejected,suggestion:d.suggestion},S.warning="discovery found 0 apps; see _meta.suggestion"),O(S)}}catch{}}catch(a){A(JSON.stringify({error:a?.message||String(a)}))}return}let n=De(e);switch(Wn(t)?.needsDaemon&&await Me(),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 xn("/api/apps"+(d?"?"+d:""));return}let a=i.toString(),l=await U("/api/apps"+(a?"?"+a:""));if(n.explain){O(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)),O(c);return}case"why-empty":{let o=await U("/api/apps?explain=1");O(o.body);return}case"status":case"stop":case"restart":{let o=n.positional[0];o||A(JSON.stringify({error:`usage: daimon ${t} <name>`}));let i=t==="status"?"":"/"+t,a=t==="status"?"GET":"POST",l=t==="status"?oc(n):"",c=await U(`/api/apps/${encodeURIComponent(o)}${i}${l}`,a);c.status===404&&A(JSON.stringify({error:"unknown app"})),O(c.body);return}case"start":{let o=n.positional[0];o||A(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&&A(JSON.stringify({error:"unknown app"})),O(a.body);return}case"history":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon history <name>"}));let i=await U(`/api/history/summary/${encodeURIComponent(o)}`);O(i.body);return}case"why":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon why <name>"}));let i=await U(`/api/history/why/${encodeURIComponent(o)}`);O(i.body);return}case"env":{let o=n.positional[0];if(o||A(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),n.use){let a=await je(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:n.use});a.status===404&&A(JSON.stringify({error:"unknown app"})),O(a.body);return}let i=await U(`/api/apps/${encodeURIComponent(o)}/env`);i.status===404&&A(JSON.stringify({error:"unknown app"})),O(i.body);return}case"clean":{let o=n.positional[0];o||A(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&&A(JSON.stringify({error:"unknown app"})),a.status===409&&(O(a.body),process.exit(1)),O(a.body);return}case"record":{let o=await U("/api/session/record?action=toggle","POST");O(o.body);return}case"replay":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon replay <session.jsonl> [--speed N]"}));let i=n.speed&&n.speed>0?n.speed:1,a;try{a=Un(o)}catch(c){A(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 je(`/api/apps/${encodeURIComponent(c.app)}/run/${encodeURIComponent(c.task||"")}`,"POST",{args:c.args||[]}):await U(`/api/apps/${encodeURIComponent(c.app)}/${c.kind}`,"POST")}O({replayed:a.length,file:o});return}case"doctor":{let o=Y();if(o.kind!=="loaded"&&A(JSON.stringify({error:"no config loaded"})),n.autoFix){let{runAutoFix:c,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(be(),ve)),p=o.config.doctor?.autoFix?.permitted??d,v=await c({permitted:p,dryRun:!!n.dryRun});O(v),v.errors.length&&process.exit(1);return}let i=[],a=kt(o.config,{warnings:i}),l=await Dn(o.config,a);for(let c of i)l.checks.unshift({name:`discovery: ${c}`,ok:!1,detail:c});i.length&&(l.ok=!1),O(l),l.ok||process.exit(1);return}case"free-port":{let o=Number(n.positional[0]);(!Number.isFinite(o)||o<=0)&&A(JSON.stringify({error:"usage: daimon free-port <port> [--force]"}));let i=re(o);if(!i){O({port:o,free:!0});return}if(!n.force){O({port:o,free:!1,holder:i});return}i.pid===process.pid&&A(JSON.stringify({error:"refuse to kill daimon itself",holder:i}));let a=await Ln(i);O({port:o,killed:a,holder:i}),a||process.exit(1);return}case"snapshot":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon snapshot <name>"}));let i=await U(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");i.status===404&&A(JSON.stringify({error:"unknown app"})),O(i.body);return}case"tasks":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon tasks <name>"}));let i=await U(`/api/apps/${encodeURIComponent(o)}/tasks`);i.status===404&&A(JSON.stringify({error:"unknown app"})),O(i.body);return}case"run":{let o=n.positional[0],i=n.positional[1];(!o||!i)&&A(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"}));let a={args:n.passthrough,watch:!!n.watch},l=await je(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(i)}`,"POST",a);l.status===404&&A(JSON.stringify({error:"unknown app"})),O(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||A(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&&A(JSON.stringify({error:"unknown app"}));let d=c.body;n.structured&&Array.isArray(d)&&(d=d.map(p=>p.parsed??{message:p.message})),O(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 xn("/api/events"+(l?"?"+l:""));return}let i=o.toString(),a=await U("/api/events"+(i?"?"+i:""));O(a.body);return}case"ensure":{let o=n.positional[0];o||A(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"&&A(JSON.stringify({error:"ensure --until must be serving|healthy"})),i.set("until",a);let l=180;if(n.timeout){let d=Vt(n.timeout);d==null&&A(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&&A(JSON.stringify({error:"unknown app"})),O(c.body),c.body?.error==="timeout"&&process.exit(2);return}case"ensure-up":{let o=n.positional[0];o||A(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"&&A(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),i.set("until",a);let l=300;if(n.timeout){let p=Vt(n.timeout);p==null&&A(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&&A(JSON.stringify({error:"unknown profile"})),O(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),n.budget&&Number.isFinite(n.budget)&&n.budget>0&&o.set("budget",String(Math.floor(n.budget)));let i=o.toString(),a=await U("/api/overview"+(i?"?"+i:""));O(a.body);return}case"focus":{let o=n.positional[0];o||A(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)||A(JSON.stringify({error:"focus --until must be serving|healthy|stable"})),i.set("until",a);let l=180;if(n.timeout){let c=Vt(n.timeout);c==null&&A(JSON.stringify({error:`invalid --timeout: ${n.timeout}`})),l=Math.min(c,600)}i.set("timeoutMs",String(Math.ceil(l*1e3))),await xn(`/api/apps/${encodeURIComponent(o)}/focus?${i.toString()}`,"POST");return}case"pin-health":{let o=n.positional[0];o||A(JSON.stringify({error:"usage: daimon pin-health <name> [--accept] [--path <p>]"}));let i=await U(`/api/apps/${encodeURIComponent(o)}?format=full`);i.status===404&&A(JSON.stringify({error:"unknown app"}));let a=i.body?.discoveredHealthPath??null,l=n.path??a??null;if(!n.accept){O({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||A(JSON.stringify({error:"no path to pin \u2014 pass --path or wait for auto-discovery"}));let c=await je(`/api/apps/${encodeURIComponent(o)}/health/pin`,"POST",{path:l});c.status===404&&A(JSON.stringify({error:"unknown app"})),O(c.body);return}case"try-fix":{let o=n.positional[0];o||A(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)||A(JSON.stringify({error:"try-fix --until must be serving|healthy"})),i.set("until",a);let l=180;if(n.timeout){let d=Vt(n.timeout);d==null&&A(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)}/try-fix?${i.toString()}`,"POST");c.status===404&&A(JSON.stringify({error:"unknown app"})),O(c.body),c.body&&c.body.reached===!1&&process.exit(2);return}case"wait":{let o=n.positional[0];o||A(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=Vt(n.timeout);c==null&&A(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&&A(JSON.stringify({error:"unknown app"})),O(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 sc()).config,c;if(!o)c=l.autoStart||[],t==="up"&&c.length===0&&A(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||A(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 m=Date.now(),h=()=>Math.max(5,Math.floor((12e4-(Date.now()-m))/1e3));await Promise.all(c.map(f=>U(`/api/apps/${encodeURIComponent(f)}/wait?until=serving&timeout=${h()}`)))}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}));O(S);return}case"logs":{let o=n.positional[0];o||A(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&&A(JSON.stringify({error:"unknown app"})),O(l.body);return}default:A(JSON.stringify({error:`unknown command: ${t}. ${qn()}`}))}}uc().catch(r=>A(JSON.stringify({error:r?.message||String(r)})));
|