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