daimon 0.9.0 → 0.10.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 +83 -0
- package/dist/cli.js +98 -88
- package/dist/dashboard/browser/chunk-2LMH5KDX.js +5 -0
- package/dist/dashboard/browser/{chunk-6Z4FDREI.js → chunk-2QORICNU.js} +1 -1
- package/dist/dashboard/browser/{chunk-UUJWPV5O.js → chunk-36JZZZCV.js} +1 -1
- package/dist/dashboard/browser/{chunk-4KVYA2AQ.js → chunk-3S7OJ77P.js} +1 -1
- package/dist/dashboard/browser/{chunk-TGSV7ZHM.js → chunk-42QQHEGP.js} +1 -1
- package/dist/dashboard/browser/chunk-4L223A7A.js +1 -0
- package/dist/dashboard/browser/{chunk-EBGPIJ7S.js → chunk-532NB4ME.js} +1 -1
- package/dist/dashboard/browser/{chunk-X4RGWMLE.js → chunk-6CP6NCA6.js} +2 -2
- package/dist/dashboard/browser/chunk-6OMBXV4F.js +1 -0
- package/dist/dashboard/browser/chunk-6YXOOFGY.js +1 -0
- package/dist/dashboard/browser/{chunk-VMW35ZNT.js → chunk-AHO3BCLI.js} +1 -1
- package/dist/dashboard/browser/{chunk-CIQNXWDY.js → chunk-ASK7FG27.js} +1 -1
- package/dist/dashboard/browser/{chunk-AGN2F6JP.js → chunk-BCGQJHY3.js} +1 -1
- package/dist/dashboard/browser/{chunk-ACPSBF55.js → chunk-BDTAVYPH.js} +1 -1
- package/dist/dashboard/browser/{chunk-FZLMX6EY.js → chunk-BFBXHJEF.js} +1 -1
- package/dist/dashboard/browser/{chunk-B2DPS6BL.js → chunk-BKYXU3OY.js} +1 -1
- package/dist/dashboard/browser/{chunk-UC7AWK4C.js → chunk-BPUIUSAU.js} +1 -1
- package/dist/dashboard/browser/{chunk-6MTVWBQQ.js → chunk-C6SNIY22.js} +1 -1
- package/dist/dashboard/browser/{chunk-3ZFFKHPU.js → chunk-CCRYWDXZ.js} +1 -1
- package/dist/dashboard/browser/{chunk-JWXROQJJ.js → chunk-DNHNU64I.js} +1 -1
- package/dist/dashboard/browser/{chunk-FRKUCFVI.js → chunk-DRBVSI3B.js} +1 -1
- package/dist/dashboard/browser/{chunk-RNUJZTKS.js → chunk-EXOJOB6H.js} +2 -2
- package/dist/dashboard/browser/chunk-EYOED3X7.js +2 -0
- package/dist/dashboard/browser/{chunk-3EPFSBJ2.js → chunk-G3IBZZQH.js} +1 -1
- package/dist/dashboard/browser/chunk-H3HRZLHG.js +4 -0
- package/dist/dashboard/browser/chunk-H5GKWN4K.js +1 -0
- package/dist/dashboard/browser/{chunk-KRC72WWY.js → chunk-HVK4GEK7.js} +1 -1
- package/dist/dashboard/browser/{chunk-7LKM244H.js → chunk-HYIZY5FQ.js} +1 -1
- package/dist/dashboard/browser/chunk-ITSOVQEA.js +1 -0
- package/dist/dashboard/browser/{chunk-WOMCRDMJ.js → chunk-JODWQVMA.js} +1 -1
- package/dist/dashboard/browser/chunk-LAMOHX23.js +1 -0
- package/dist/dashboard/browser/chunk-NMKAKRON.js +1 -0
- package/dist/dashboard/browser/{chunk-F3FCHBFQ.js → chunk-NY5IR366.js} +1 -1
- package/dist/dashboard/browser/{chunk-NVL5HFLU.js → chunk-OOQPWG6B.js} +1 -1
- package/dist/dashboard/browser/{chunk-SR4HVFOB.js → chunk-P3Q7RWT5.js} +1 -1
- package/dist/dashboard/browser/{chunk-YHBNUNU3.js → chunk-PVPELZPO.js} +1 -1
- package/dist/dashboard/browser/{chunk-66VYPESU.js → chunk-QHXOUNPA.js} +1 -1
- package/dist/dashboard/browser/{chunk-VHALTUPL.js → chunk-RMV7CR6Y.js} +1 -1
- package/dist/dashboard/browser/chunk-RQSDQXNY.js +1 -0
- package/dist/dashboard/browser/chunk-RWX5JIT4.js +1 -0
- package/dist/dashboard/browser/{chunk-R7VSXL63.js → chunk-SXE7REUK.js} +1 -1
- package/dist/dashboard/browser/chunk-TLCLILNG.js +4 -0
- package/dist/dashboard/browser/chunk-UAIWZYHN.js +1 -0
- package/dist/dashboard/browser/chunk-UFTWVSEC.js +2 -0
- package/dist/dashboard/browser/{chunk-RWXAGDGT.js → chunk-UXLEE3F2.js} +1 -1
- package/dist/dashboard/browser/{chunk-K6PUQAFE.js → chunk-XPP3TYS2.js} +1 -1
- package/dist/dashboard/browser/{chunk-PRLUGTKR.js → chunk-YFYMS5EE.js} +1 -1
- package/dist/dashboard/browser/chunk-YPVVBWNF.js +1 -0
- package/dist/dashboard/browser/{chunk-BBTQXZIS.js → chunk-Z3XFJOYG.js} +1 -1
- package/dist/dashboard/browser/index.html +2 -2
- package/dist/dashboard/browser/main-EENULCI5.js +1 -0
- package/dist/main.js +55 -51
- package/dist/mcp.js +3 -3
- package/package.json +4 -2
- package/dist/dashboard/browser/chunk-55AO3FMG.js +0 -1
- package/dist/dashboard/browser/chunk-FD3BW2ZN.js +0 -1
- package/dist/dashboard/browser/chunk-GMEW64AS.js +0 -1
- package/dist/dashboard/browser/chunk-HXX2OUOE.js +0 -1
- package/dist/dashboard/browser/chunk-HZNVO3JE.js +0 -1
- package/dist/dashboard/browser/chunk-K2SFF47Z.js +0 -5
- package/dist/dashboard/browser/chunk-K5WKBG55.js +0 -1
- package/dist/dashboard/browser/chunk-LBWOIG7N.js +0 -5
- package/dist/dashboard/browser/chunk-O76B43BY.js +0 -4
- package/dist/dashboard/browser/chunk-QYIYT4YU.js +0 -1
- package/dist/dashboard/browser/chunk-RXOAYCKI.js +0 -2
- package/dist/dashboard/browser/chunk-WRX32YWH.js +0 -1
- package/dist/dashboard/browser/main-YAROJLJV.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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 Ki=Object.defineProperty;var H=(n,t)=>()=>(n&&(t=n(n=0)),t);var Ct=(n,t)=>{for(var e in t)Ki(n,e,{get:t[e],enumerable:!0})};var Ur={};Ct(Ur,{configLookupPaths:()=>Ft,loadConfig:()=>ft,validateConfig:()=>Ie});import It from"node:fs";import Dt from"node:path";import Pe from"node:os";import{fileURLToPath as zi}from"node:url";function Br(){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:Dt.join(Pe.homedir(),".daimon","logs"),maxFiles:5,maxBytesPerFile:1e7},depends:{},cascadeRestart:!1,history:{enabled:!0,path:Dt.join(Pe.homedir(),".daimon","history.db"),retentionDays:30},notifications:{enabled:!0,onError:!0,onUnhealthy:!0,tray:!1},staleDetect:{enabled:!0,silentMs:3e4},headless:!1,envFiles:{},requestLog:{enabled:!1,portOffset:1e3},metrics:{enabled:!1},editor:{scheme:"vscode"},apiToken:null,output:{format:"compact",ndjson:!1},doctor:{autoFix:{onInit:!1,permitted:["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"]}},dashboard:{theme:"auto",density:"comfortable"},errorRetention:{maxAgeMs:864e5},plugins:{dir:null},webhooks:[]}}function On(n){return n.startsWith("~/")||n.startsWith("~\\")?Dt.join(Pe.homedir(),n.slice(2)):n==="~"?Pe.homedir():n}function Ie(n,t){return Nn(n,t)}function Nn(n,t){if(!n||typeof n!="object")throw new Error(`Config at ${t} is not a JSON object`);let e=n,r=Br();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})`);r.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})`);r.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})`);r.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})`);r.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})`);r.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(a=>typeof a=="string"))throw new Error(`Config "profiles.${s}" must be an array of strings (${t})`);r.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})`);r.tags=e.tags}if(e.autoRestart&&typeof e.autoRestart=="object"&&(r.autoRestart={...r.autoRestart,...e.autoRestart}),e.healthProbe&&typeof e.healthProbe=="object"&&(r.healthProbe={...r.healthProbe,...e.healthProbe}),e.logs&&typeof e.logs=="object"&&(r.logs={...r.logs,...e.logs},r.logs.dir=On(r.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(a=>typeof a=="string"))throw new Error(`Config "depends.${s}" must be an array of strings (${t})`);r.depends=e.depends}if(typeof e.cascadeRestart=="boolean"&&(r.cascadeRestart=e.cascadeRestart),e.history&&typeof e.history=="object"&&(r.history={...r.history,...e.history},r.history.path=On(r.history.path)),e.notifications&&typeof e.notifications=="object"&&(r.notifications={...r.notifications,...e.notifications}),e.staleDetect&&typeof e.staleDetect=="object"&&(r.staleDetect={...r.staleDetect,...e.staleDetect}),typeof e.headless=="boolean"&&(r.headless=e.headless),e.envFiles&&typeof e.envFiles=="object"&&!Array.isArray(e.envFiles)&&(r.envFiles=e.envFiles),e.requestLog&&typeof e.requestLog=="object"&&(r.requestLog={...r.requestLog,...e.requestLog}),e.metrics&&typeof e.metrics=="object"&&(r.metrics={...r.metrics,...e.metrics}),e.editor&&typeof e.editor=="object"){let s=e.editor.scheme;typeof s=="string"&&s.trim()&&(r.editor={scheme:s.trim()})}if((typeof e.apiToken=="string"||e.apiToken===null)&&(r.apiToken=e.apiToken),e.output&&typeof e.output=="object"){let s=e.output;(s.format==="compact"||s.format==="full")&&(r.output.format=s.format),typeof s.ndjson=="boolean"&&(r.output.ndjson=s.ndjson)}if(e.doctor&&typeof e.doctor=="object"){let s=e.doctor.autoFix;s&&typeof s=="object"&&(typeof s.onInit=="boolean"&&(r.doctor.autoFix.onInit=s.onInit),Array.isArray(s.permitted)&&(r.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")&&(r.dashboard.theme=s.theme),(s.density==="comfortable"||s.density==="compact")&&(r.dashboard.density=s.density)}if(e.errorRetention&&typeof e.errorRetention=="object"){let s=e.errorRetention;typeof s.maxAgeMs=="number"&&s.maxAgeMs>0&&(r.errorRetention.maxAgeMs=s.maxAgeMs)}if(e.plugins&&typeof e.plugins=="object"){let s=e.plugins;typeof s.dir=="string"&&s.dir.trim()?r.plugins.dir=On(s.dir):s.dir===null&&(r.plugins.dir=null)}if(Array.isArray(e.webhooks)){let s=[];for(let o of e.webhooks){if(!o||typeof o!="object")continue;let a=o;if(typeof a.url!="string"||!a.url.trim())continue;let l={url:a.url};if(Array.isArray(a.events)&&(l.events=a.events.filter(i=>typeof i=="string")),a.headers&&typeof a.headers=="object"){let i={};for(let[c,u]of Object.entries(a.headers))typeof u=="string"&&(i[c]=u);l.headers=i}if(a.filter&&typeof a.filter=="object"){let i={};for(let c of["to","from","app"])Array.isArray(a.filter[c])&&(i[c]=a.filter[c].filter(u=>typeof u=="string"));l.filter=i}s.push(l)}r.webhooks=s}return r}function Ft(){return{local:Dt.join(process.cwd(),"daimon.config.json"),user:Dt.join(Pe.homedir(),".daimon","config.json")}}function ft(){let{local:n,user:t}=Ft();if(It.existsSync(n)){let s=JSON.parse(It.readFileSync(n,"utf8"));return{kind:"loaded",config:Nn(s,n),path:n}}if(It.existsSync(t)){let s=JSON.parse(It.readFileSync(t,"utf8"));return{kind:"loaded",config:Nn(s,t),path:t}}let r=[Dt.resolve(Fr,"..","daimon.config.example.json"),Dt.resolve(Fr,"..","..","daimon.config.example.json")].find(s=>It.existsSync(s));return It.mkdirSync(Dt.dirname(t),{recursive:!0}),r?It.copyFileSync(r,t):It.writeFileSync(t,JSON.stringify(Br(),null,2)+`
|
|
3
|
+
`,"utf8"),{kind:"stub-created",path:t}}var Yi,Fr,de=H(()=>{"use strict";Yi=zi(import.meta.url),Fr=Dt.dirname(Yi)});var Dn={};Ct(Dn,{discoverApps:()=>jt});import wt from"node:fs";import lt from"node:path";import $n from"fast-glob";function Hr(n){try{return JSON.parse(wt.readFileSync(n,"utf8"))}catch{return null}}function Jr(n){return!n||typeof n!="object"?!1:!!(n.targets?.serve||n.architect?.serve)}function Wr(n){if(!n||typeof n!="object")return[];let t=n.targets??n.architect??{};return Object.keys(t).filter(e=>e!=="serve").sort()}function Mn(n){return n.replace(/\\/g,"/")}function fe(n,t){n&&(n.rejected[t]=(n.rejected[t]??0)+1)}function Vi(n,t,e,r){if(!n.has(t))return{key:t,collided:!1};if(n.get(t).workspaceRoot===r)return{key:t,collided:!0};let o=e||lt.basename(r),a=`${t}@${o}`,l=2;for(;n.has(a);)a=`${t}@${o}-${l++}`;return{key:a,collided:!1}}function _n(n,t){try{return t.test(wt.readFileSync(n,"utf8"))}catch{return!1}}function Et(n,t,e){let{key:r,collided:s}=Vi(n,t,e.workspaceLabel,e.workspaceRoot);return s?!1:(n.set(r,{name:r,baseName:t,...e}),!0)}function Qi(n,t,e){let r=lt.basename(n),s=!1,o=lt.join(n,"manage.py");wt.existsSync(o)&&_n(o,/\bdjango\b/i)&&(Et(e,r,{workspaceRoot:n,workspaceType:"polyglot",serverProfile:"django",command:"python manage.py runserver",hidden:!1,tags:[],workspaceLabel:t}),s=!0);let a=lt.join(n,"bin","rails"),l=lt.join(n,"Gemfile");wt.existsSync(a)&&wt.existsSync(l)&&(Et(e,r,{workspaceRoot:n,workspaceType:"polyglot",serverProfile:"rails",command:"bin/rails server",hidden:!1,tags:[],workspaceLabel:t}),s=!0);let i=lt.join(n,"pyproject.toml"),c=lt.join(n,"requirements.txt");(wt.existsSync(i)&&_n(i,/\bfastapi\b/i)||wt.existsSync(c)&&_n(c,/\bfastapi\b/i))&&(Et(e,r,{workspaceRoot:n,workspaceType:"polyglot",serverProfile:"fastapi",command:"uvicorn main:app --reload",hidden:!1,tags:[],workspaceLabel:t}),s=!0),(wt.existsSync(lt.join(n,".air.toml"))||wt.existsSync(lt.join(n,"air.toml")))&&(Et(e,r,{workspaceRoot:n,workspaceType:"polyglot",serverProfile:"go-air",command:"air",hidden:!1,tags:[],workspaceLabel:t}),s=!0);let m=lt.join(n,"Trunk.toml");return wt.existsSync(m)&&(Et(e,r,{workspaceRoot:n,workspaceType:"polyglot",serverProfile:"rust-trunk",command:"trunk serve",hidden:!1,tags:[],workspaceLabel:t}),s=!0),s}function jt(n,t={}){let e=new Map,r=t.warnings??[],s=t.warnings===void 0;for(let o of n.searchRoots){let a=typeof o=="string"?o:o.path,l=typeof o=="string"?!1:!!o.viteSubfolders,i=typeof o=="string"?void 0:o.label,c=lt.resolve(a);if(!wt.existsSync(c)){r.push(`searchRoot does not exist: ${c}`),fe(t.stats,"searchRoot missing");continue}let u=lt.join(c,"nx.json"),p=lt.join(c,"angular.json");if(wt.existsSync(u)){let x=$n.sync("**/project.json",{cwd:Mn(c),ignore:["**/node_modules/**","**/dist/**","**/.nx/**","**/.git/**"],absolute:!0,dot:!1});for(let T of x){t.stats&&(t.stats.scanned+=1);let w=Hr(T);if(!w){fe(t.stats,"unreadable project.json");continue}if(!Jr(w)){fe(t.stats,"no serve target");continue}let E=w.name||lt.basename(lt.dirname(T));if(!E){fe(t.stats,"project has no name");continue}Et(e,E,{workspaceRoot:c,workspaceType:"nx",serverProfile:"nx",command:`npx nx serve ${E}`,hidden:!1,tags:[],tasks:Wr(w),workspaceLabel:i})||(r.push(`duplicate project name "${E}" within ${c} \u2014 keeping first`),fe(t.stats,"duplicate name"))}continue}if(wt.existsSync(p)){let T=Hr(p)?.projects||{};for(let[w,E]of Object.entries(T)){if(!Jr(E))continue;Et(e,w,{workspaceRoot:c,workspaceType:"angular",serverProfile:"angular",command:`npx ng serve ${w}`,hidden:!1,tags:[],tasks:Wr(E),workspaceLabel:i})||r.push(`duplicate project name "${w}" within ${c} \u2014 keeping first`)}continue}let m=$n.sync("vite.config.{ts,js,mjs,cjs}",{cwd:Mn(c),absolute:!0,deep:1}),g=wt.existsSync(lt.join(c,".storybook")),S=!1;if(m.length>0){let x=lt.basename(c);if(Et(e,x,{workspaceRoot:c,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:i}),S=!0,l){let T=$n.sync("*/vite.config.{ts,js,mjs,cjs}",{cwd:Mn(c),absolute:!0});for(let w of T){let E=lt.dirname(w),B=lt.basename(E);B!==x&&Et(e,B,{workspaceRoot:E,workspaceType:"vite",serverProfile:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:i})}}}if(g){let x=`${lt.basename(c)}-storybook`;Et(e,x,{workspaceRoot:c,workspaceType:"storybook",serverProfile:"storybook",command:"npx storybook dev --no-open",hidden:!1,tags:[],workspaceLabel:i}),S=!0}S||Qi(c,i,e)||(r.push(`searchRoot has none of nx.json/angular.json/vite.config.*/.storybook/polyglot markers: ${c}`),fe(t.stats,"no project markers"))}for(let[o,a]of Object.entries(n.overrides||{})){let l=[...e.values()].filter(i=>(i.baseName??i.name)===o);if(l.length>0)for(let i of l)a.command&&(i.command=a.command),typeof a.hidden=="boolean"&&(i.hidden=a.hidden),typeof a.port=="number"&&(i.pinnedPort=a.port),a.env&&(i.env=a.env);else a.command&&e.set(o,{name:o,baseName:o,workspaceRoot:process.cwd(),workspaceType:"nx",command:a.command,hidden:a.hidden??!1,pinnedPort:a.port,env:a.env,tags:[]})}for(let o of e.values())o.tags=n.tags?.[o.baseName??o.name]??[];if(s&&r.length)for(let o of r)process.stderr.write(`[daimon] warning: ${o}
|
|
4
|
+
`);return[...e.values()].filter(o=>!o.hidden)}var Zt=H(()=>{"use strict"});function Fe(n){let s=new Map,o=new Map,a=null,l=i=>{if(!a){s.set(i,1);for(let c of n[i]||[]){let u=s.get(c)??0;if(u===1){let p=[c,i],m=o.get(i);for(;m&&m!==c;)p.push(m),m=o.get(m);m===c&&p.push(c),a=p.reverse();return}if(u===0&&(o.set(c,i),l(c),a))return}s.set(i,2)}};for(let i of Object.keys(n))if((s.get(i)??0)===0&&(o.set(i,null),l(i),a))return a;return null}function Be(n,t){let e=new Set,r=[t];for(;r.length;){let s=r.pop();if(!e.has(s)){e.add(s);for(let o of n[s]||[])r.push(o)}}return[...e]}function Ue(n,t){let e=new Set(t),r=new Map,s=new Map;for(let l of t)r.set(l,0),s.set(l,[]);for(let l of t)for(let i of n[l]||[])e.has(i)&&(s.get(i).push(l),r.set(l,(r.get(l)??0)+1));let o=[],a=t.filter(l=>(r.get(l)??0)===0);for(;a.length;){o.push([...a].sort());let l=[];for(let i of a)for(let c of s.get(i)??[])r.set(c,(r.get(c)??1)-1),r.get(c)===0&&l.push(c);a=l}return o}function qr(n,t){let e=[];for(let[r,s]of Object.entries(n))s.includes(t)&&e.push(r);return e}var Ae=H(()=>{"use strict"});import Zi from"node:net";function Bt(n){return new Promise(t=>{let e=Zi.createServer();e.unref(),e.once("error",()=>t(!1)),e.listen({port:n,host:"127.0.0.1",exclusive:!0},()=>{e.close(()=>t(!0))})})}var me,Ee=H(()=>{"use strict";me=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 r=new Set;for(let[s,o]of Object.entries(e.initial))typeof o=="number"&&(o<this.min||o>this.max||r.has(o)||(r.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 r=this.assigned.get(t);if(e!==void 0)return this.assigned.set(t,e),this.onChange?.(this.snapshot()),e;if(r!==void 0)return r;let s=new Set(this.assigned.values());for(let o=this.min;o<=this.max;o++){if(s.has(o))continue;if(await Bt(o))return this.assigned.set(t,o),this.onChange?.(this.snapshot()),o}throw new Error(`No free ports in range ${this.min}-${this.max}`)}async isPortAvailableForUse(t){return Bt(t)}}});import Oe from"node:fs";import ta from"node:path";import{createRequire as ea}from"node:module";var na,ra,sa,oa,Lt,He=H(()=>{"use strict";na=ea(import.meta.url),ra=200,sa=360*60*1e3,oa=1e4,Lt=class{constructor(t){this.cfg=t;if(t.enabled)try{Oe.mkdirSync(ta.dirname(t.path),{recursive:!0});let e=na("better-sqlite3"),r,s=o=>{let a=new Date().toISOString().replace(/[:.]/g,"-"),l=`${t.path}.corrupt-${a}`;try{Oe.existsSync(t.path)&&Oe.renameSync(t.path,l);try{Oe.unlinkSync(t.path+"-wal")}catch{}try{Oe.unlinkSync(t.path+"-shm")}catch{}this.archivedCorruptPath=l,process.stderr.write(`[daimon] history: archived corrupt db (${o}) -> ${l}
|
|
5
|
+
`)}catch(i){this.warnOnce(`failed to archive corrupt history db: ${i?.message||i}`)}};try{r=new e(t.path);let o=r.prepare("PRAGMA integrity_check").get();if(!(o&&(o.integrity_check==="ok"||o.integrity_check==="ok"))){try{r.close()}catch{}s("integrity_check failed"),r=new e(t.path)}}catch(o){s(`open failed: ${o?.message||o}`),r=new e(t.path)}this.db=r,this.db.pragma("journal_mode = WAL"),this.migrate(),this.flushTimer=setInterval(()=>this.flush(),ra),this.retentionStart=setTimeout(()=>this.runRetention(),oa),this.retentionTimer=setInterval(()=>this.runRetention(),sa)}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;archivedCorruptPath=null;archivedCorruptDbPath(){return this.archivedCorruptPath}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] history: ${t}
|
|
5
6
|
`))}migrate(){this.db&&this.db.exec(`
|
|
6
7
|
CREATE TABLE IF NOT EXISTS events (
|
|
7
8
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -13,6 +14,7 @@ var Oi=Object.defineProperty;var U=(n,t)=>()=>(n&&(t=n(n=0)),t);var kt=(n,t)=>{f
|
|
|
13
14
|
message TEXT
|
|
14
15
|
);
|
|
15
16
|
CREATE INDEX IF NOT EXISTS events_ts_app ON events(ts, app);
|
|
17
|
+
CREATE INDEX IF NOT EXISTS events_app_ts ON events(app, ts);
|
|
16
18
|
CREATE TABLE IF NOT EXISTS compile_times (
|
|
17
19
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
20
|
ts INTEGER NOT NULL,
|
|
@@ -48,108 +50,110 @@ var Oi=Object.defineProperty;var U=(n,t)=>()=>(n&&(t=n(n=0)),t);var kt=(n,t)=>{f
|
|
|
48
50
|
historyQueryP95Ms REAL NOT NULL
|
|
49
51
|
);
|
|
50
52
|
CREATE INDEX IF NOT EXISTS self_metrics_ts ON self_metrics(ts);
|
|
51
|
-
`)}recordSelfMetric(t,e,r,s,o=Date.now()){if(this.db)try{this.db.prepare("INSERT INTO self_metrics (ts,rssMB,heapUsedMB,eventLoopLagMs,historyQueryP95Ms) VALUES (?,?,?,?,?)").run(o,t,e,r,s)}catch(i){this.warnOnce(`self_metrics write failed: ${i?.message||i}`)}}querySelfMetrics(t={}){if(!this.db)return[];let e=[],r=[];t.since!=null&&(e.push("ts >= ?"),r.push(t.since));let s=`SELECT ts, rssMB, heapUsedMB, eventLoopLagMs, historyQueryP95Ms FROM self_metrics ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??60),this.db.prepare(s).all(...r)}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,r=Date.now()){this.db&&this.queue.push({kind:"compile",row:{ts:r,app:t,ms:e}})}recordBundle(t,e,r,s,o=Date.now()){this.db&&this.queue.push({kind:"bundle",row:{ts:o,app:t,initialKB:e,lazyKB:r,fileCount:s}})}recordTaskRun(t,e,r,s,o,i=Date.now()){this.db&&this.queue.push({kind:"task",row:{ts:i,app:t,task:e,exit_code:r,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 (?,?,?,?,?,?)"),r=this.db.prepare("INSERT INTO compile_times (ts,app,ms) VALUES (?,?,?)"),s=this.db.prepare("INSERT INTO task_runs (ts,app,task,exit_code,duration_ms,summary) VALUES (?,?,?,?,?,?)"),o=this.db.prepare("INSERT INTO bundles (ts,app,initialKB,lazyKB,fileCount) VALUES (?,?,?,?,?)");this.db.transaction(a=>{for(let c of a)c.kind==="event"?e.run(c.row.ts,c.row.app,c.row.type,c.row.from_state,c.row.to_state,c.row.message):c.kind==="compile"?r.run(c.row.ts,c.row.app,c.row.ms):c.kind==="bundle"?o.run(c.row.ts,c.row.app,c.row.initialKB,c.row.lazyKB,c.row.fileCount):s.run(c.row.ts,c.row.app,c.row.task,c.row.exit_code,c.row.duration_ms,c.row.summary)})(t)}catch(e){this.warnOnce(`history write failed: ${e?.message||e}`)}}runRetention(){if(this.db)try{let t=Date.now()-this.cfg.retentionDays*864e5;this.db.prepare("DELETE FROM events WHERE ts < ?").run(t),this.db.prepare("DELETE FROM compile_times WHERE ts < ?").run(t),this.db.prepare("DELETE FROM task_runs WHERE ts < ?").run(t),this.db.prepare("DELETE FROM bundles WHERE ts < ?").run(t),this.db.prepare("DELETE FROM self_metrics WHERE ts < ?").run(t)}catch(t){this.warnOnce(`retention failed: ${t?.message||t}`)}}queryEvents(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until)),t.type&&(e.push("type = ?"),r.push(t.type));let s=`SELECT * FROM events ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??500),this.db.prepare(s).all(...r)}queryCompiles(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until));let s=`SELECT * FROM compile_times ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??1e3),this.db.prepare(s).all(...r)}queryBundles(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until));let s=`SELECT * FROM bundles ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??1e3),this.db.prepare(s).all(...r)}trends(t){if(!this.db)return{points:[],count:0};let e=Date.now()-t.sinceMs,r=t.bucketMs,s=new Map,o=(u,d)=>{let f=Math.floor(u/r)*r,g=s.get(f)??{sum:0,n:0};g.sum+=d,g.n+=1,s.set(f,g)},i=u=>{let d=Math.floor(u/r)*r,f=s.get(d)??{sum:0,n:0};f.sum+=1,f.n+=1,s.set(d,f)},a=0;if(t.metric==="compile"){let u=this.queryCompiles({app:t.app,since:e,limit:1e4});a=u.length;for(let d of u)o(d.ts,d.ms)}else if(t.metric==="bundle"){let u=this.queryBundles({app:t.app,since:e,limit:1e4});a=u.length;for(let d of u){let f=Math.floor(d.ts/r)*r,g=s.get(f)??{sum:0,n:0,sum2:0};g.sum+=d.initialKB,g.sum2=(g.sum2??0)+d.lazyKB,g.n+=1,s.set(f,g)}}else if(t.metric==="errors"){let u=this.queryEvents({app:t.app,since:e,limit:1e4});for(let d of u)(d.type==="error-new"||d.type==="error-recur")&&(i(d.ts),a++)}else{let u=this.queryEvents({app:t.app,since:e,limit:1e4});for(let d of u)d.type==="status"&&d.to_state==="starting"&&(d.from_state==="error"||d.from_state==="serving"||d.from_state==="compiling")&&(i(d.ts),a++)}let c=[],l=[...s.entries()].sort((u,d)=>u[0]-d[0]);for(let[u,d]of l)t.metric==="compile"||t.metric==="bundle"?c.push({t:u,v:Math.round(d.sum/d.n),...d.sum2!=null?{v2:Math.round(d.sum2/d.n)}:{}}):c.push({t:u,v:d.sum});return{points:c,count:a}}queryTimeline(t){if(!this.db)return[];let e=t.limit??5e3,r=t.since,s=t.kinds,o=[],i=!s||s.has("status"),a=!s||s.has("error"),c=!s||s.has("warning"),l=!s||s.has("lint"),u=!s||s.has("health"),d=!s||s.has("bundle"),f=!s||s.has("task"),g=!s||s.has("restart");if(i||a||c||l||u||g){let C=this.queryEvents({app:t.app,since:r,limit:e});for(let R of C){let y=null;if(R.type==="status"&&i?y="status":(R.type==="error-new"||R.type==="error-recur")&&a?y="error":(R.type==="warning-new"||R.type==="warning-recur")&&c?y="warning":(R.type==="lint-new"||R.type==="lint-recur")&&l?y="lint":R.type==="health"&&u?y="health":(R.type==="restart-scheduled"||R.type==="bundle-regression"||R.type==="compile-regression"||R.type==="stale"||R.type==="self-warn")&&g&&(y="restart"),!y)continue;let b=y==="status"?`${R.from_state??"?"} \u2192 ${R.to_state??"?"}`:R.message??R.type;o.push({ts:R.ts,app:R.app,kind:y,summary:b,payload:R})}}if(d){let C=this.queryBundles({app:t.app,since:r,limit:e});for(let R of C)o.push({ts:R.ts,app:R.app,kind:"bundle",summary:`initial ${R.initialKB}KB \xB7 lazy ${R.lazyKB}KB`,payload:R})}if(f){let C=this.queryCompiles({app:t.app,since:r,limit:e});for(let y of C)o.push({ts:y.ts,app:y.app,kind:"compile",summary:`compile ${(y.ms/1e3).toFixed(1)}s`,payload:y});let R=this.queryTasks({app:t.app,since:r,limit:e});for(let y of R){let b=y.duration_ms??0;o.push({ts:y.ts,app:y.app,kind:"task",summary:`${y.task} exit=${y.exit_code} ${(b/1e3).toFixed(1)}s`,payload:y})}}return o.sort((C,R)=>R.ts-C.ts),o.slice(0,e)}queryTasks(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.task&&(e.push("task = ?"),r.push(t.task)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since));let s=`SELECT * FROM task_runs ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??200),this.db.prepare(s).all(...r)}summary(t){if(!this.db)return{uptimePct24h:0,restartCount24h:0,compileP50:null,compileP95:null,topErrors:[]};let e=Date.now()-24*3600*1e3,r=this.queryEvents({app:t,since:e,limit:5e3}),s=0,o=e,i=!1,a=null,c=[...r].sort((b,N)=>b.ts-N.ts);for(let b of c)b.type==="status"&&(b.to_state==="serving"&&!i?(i=!0,a=b.ts):i&&b.to_state!=="serving"&&a!=null&&(s+=b.ts-a,i=!1,a=null));i&&a!=null&&(s+=Date.now()-a);let l=Math.round(s/(24*3600*1e3)*1e3)/10,u=r.filter(b=>b.type==="status"&&b.to_state==="starting"&&(b.from_state==="serving"||b.from_state==="error"||b.from_state==="compiling")).length,d=this.queryCompiles({app:t,since:e,limit:1e3}).map(b=>b.ms).sort((b,N)=>b-N),f=(b,N)=>{if(b.length===0)return null;let p=Math.min(b.length-1,Math.floor((b.length-1)*N));return b[p]},g=f(d,.5),C=f(d,.95),R=new Map;for(let b of r)if(b.type==="error-new"||b.type==="error-recur"){let N=b.message??"";if(!N)continue;R.set(N,(R.get(N)??0)+1)}let y=[...R.entries()].sort((b,N)=>N[1]-b[1]).slice(0,5).map(([b,N])=>({message:b,count:N}));return{uptimePct24h:l,restartCount24h:u,compileP50:g,compileP95:C,topErrors:y}}why(t){let e=this.queryEvents({app:t,limit:200}),r=e.find(a=>a.type==="status"&&(a.to_state==="error"||a.from_state==="error"||a.to_state==="serving")),s=r?{ts:r.ts,app:r.app,type:r.type,from:r.from_state??void 0,to:r.to_state??void 0,message:r.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}))}}_flushForTest(){this.flush()}quickCheck(){if(!this.db)return!1;try{return this.db.prepare("PRAGMA quick_check").get()?.quick_check==="ok"}catch{return!1}}close(){if(this.flushTimer&&clearInterval(this.flushTimer),this.retentionTimer&&clearInterval(this.retentionTimer),this.retentionStart&&clearTimeout(this.retentionStart),this.flush(),this.db){try{this.db.close()}catch{}this.db=null}}}});import{spawnSync as An}from"node:child_process";import Dr from"tree-kill";function Fe(n){if(process.platform==="win32"){let o=An("powershell",["-NoProfile","-Command",`Get-NetTCPConnection -LocalPort ${n} -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=An("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${i}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),c,l;try{let u=JSON.parse((a.stdout||"").trim()||"{}");c=typeof u.Name=="string"?u.Name:void 0,l=typeof u.CommandLine=="string"?u.CommandLine:void 0}catch{}return{pid:i,name:c,cmd:l}}let t=An("lsof",["-nP","-iTCP:"+n,"-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 r=e[0].split(/\s+/);return{pid:Number(r[1]),name:r[0]}}function Lr(n,t){if(!t)return`port ${n} already in use`;let e=[`port ${n} 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 Ir(n){return new Promise(t=>{if(!n.pid||n.pid===process.pid){t(!1);return}Dr(n.pid,"SIGTERM",e=>{if(e){setTimeout(()=>Dr(n.pid,"SIGKILL",r=>t(!r)),500);return}t(!0)})})}var On=U(()=>{"use strict"});import Be from"node:fs";import Wi from"node:os";import Fr from"node:path";function Br(n){return Be.readFileSync(n,"utf8").split(/\r?\n/).filter(e=>e.trim()).map(e=>JSON.parse(e))}var Ue,Nn=U(()=>{"use strict";Ue=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=Fr.join(Wi.homedir(),".daimon","sessions");Be.mkdirSync(t,{recursive:!0});let e=Fr.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return Be.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})+`
|
|
52
|
-
`;try{Be.appendFileSync(this.file,e)}catch{}}}});import qi from"node:fs";import $n from"node:path";import{fileURLToPath as Gi}from"node:url";function Xi(){let n=[$n.resolve(Ur,"..","package.json"),$n.resolve(Ur,"..","..","package.json")];for(let t of n)try{return JSON.parse(qi.readFileSync(t,"utf8"))}catch{}return{}}var Ur,st,_t=U(()=>{"use strict";Ur=$n.dirname(Gi(import.meta.url));st=Xi().version||"0.0.0"});import oe from"node:fs";import He from"node:path";import Ki from"node:os";import{spawn as zi}from"node:child_process";import{fileURLToPath as Yi}from"node:url";function mt(){return jn}function Je(){return ie}function Mn(n){try{return process.kill(n,0),!0}catch(t){return t&&t.code==="EPERM"}}function ct(){try{let n=oe.readFileSync(ie,"utf8"),t=JSON.parse(n);if(!t||typeof t.pid!="number")return null;if(!Mn(t.pid)){try{oe.unlinkSync(ie)}catch{}return null}return t}catch{return null}}function Hr(n){oe.mkdirSync(jn,{recursive:!0});let t=ie+"."+process.pid+".tmp";oe.writeFileSync(t,JSON.stringify(n)),oe.renameSync(t,ie)}function Tt(){try{oe.unlinkSync(ie)}catch{}}function Vi(){let n=He.dirname(Yi(import.meta.url));return He.join(n,"main.js")}async function Dt(n={}){let t={...process.env};n.port&&(t.DAIMON_PORT=String(n.port)),zi(process.execPath,[Vi(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let r=Date.now();for(;Date.now()-r<5e3;){let s=ct();if(s&&(!n.port||s.apiPort===n.port))return s;await new Promise(o=>setTimeout(o,100))}throw new Error("daemon failed to start within 5s")}async function Xt(n,t){let e=Date.now();for(;Date.now()-e<t;){if(!Mn(n))return!0;await new Promise(r=>setTimeout(r,100))}return!Mn(n)}function Jr(n,t,e){return{pid:process.pid,apiPort:n,version:st,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var jn,ie,Pt=U(()=>{"use strict";_t();jn=He.join(Ki.homedir(),".daimon"),ie=He.join(jn,"daemon.lock")});var ps={};kt(ps,{promptClaudeInstall:()=>da});import Yt,{useState as ls}from"react";import{Box as us,render as ca,Text as Xe,useApp as la,useInput as ua}from"ink";function pa({onDone:n}){let{exit:t}=la(),[e,r]=ls(0),[s,o]=ls({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 ua((a,c)=>{if(c.escape||a==="q"&&!c.shift){n(null),t();return}if(c.upArrow)r(l=>Math.max(0,l-1));else if(c.downArrow)r(l=>Math.min(i.length-1,l+1));else if(a===" "){let l=i[e].key;o(u=>({...u,[l]:!u[l]}))}else c.return&&(n(s),t())}),Yt.createElement(us,{flexDirection:"column",paddingX:1},Yt.createElement(Xe,{bold:!0,color:"cyan"},"Install Claude Code integration artifacts"),Yt.createElement(Xe,{dimColor:!0},"Space toggles \xB7 Enter confirms \xB7 Esc cancels"),i.map((a,c)=>Yt.createElement(us,{key:a.key},Yt.createElement(Xe,{color:c===e?"cyan":void 0},c===e?"\u25B8 ":" "),Yt.createElement(Xe,null,"[",s[a.key]?"x":" ","] ",a.label))))}async function da(){return new Promise(n=>{let t=!1;ca(Yt.createElement(pa,{onDone:r=>{t||(t=!0,n(r))}})).waitUntilExit().then(()=>{t||(t=!0,n(null))})})}var ds=U(()=>{"use strict"});import Fn from"node:path";function fs(n){let t=Fn.resolve(n);return process.platform==="win32"?t.toLowerCase():t}function Ct(n,t){let e=fs(n),r=fs(t);if(e===r)return!0;let s=r.endsWith(Fn.sep)?r:r+Fn.sep;return e.startsWith(s)}var Bn=U(()=>{"use strict"});import fa from"node:crypto";function Ea(n){for(let{tool:t,rx:e}of Ra)if(e.test(n))return t}function La(n){return fa.createHash("sha1").update(n).digest("hex").slice(0,16)}function Ia(n){let t={message:n},e=n.match(va)||n.match(ba);e&&(t.code=`TS${e[1]}`);let r=n.match(ka)||n.match(ms)||n.match(Sa);if(r)t.file=r[1],t.line=Number(r[2]),t.col=Number(r[3]);else{let o=n.match(Pa);if(o)t.file=o[1],o[2]&&(t.line=Number(o[2])),o[3]&&(t.col=Number(o[3]));else{let i=n.match(Ta);if(i)t.file=i[1];else{let a=n.match(gs);if(a)t.file=a[1],t.line=Number(a[2]),t.col=Number(a[3]);else{let c=n.match(hs);c&&(t.file=c[1],t.line=Number(c[2]))}}}}let s=Ea(n);return s&&(t.tool=s),t}function Fa(n,t){try{let e=new URL(n);return e.hostname==="0.0.0.0"||e.hostname==="[::]"?(e.hostname=t.includes(":")?`[${t}]`:t,e.toString().replace(/\/$/,"")):n.replace(/\/$/,"")}catch{return n}}function Ba(n,t="127.0.0.1"){let e=n.match(Aa)||n.match(Oa)||n.match(Na)||n.match($a);if(!e)return null;let r=e[1].replace(/[),.;]+$/,"");return Fa(r,t)}function Ua(n,t){if(Ma.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="initial",!1;if(ja.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="lazy",!1;let e=t.match(_a);if(e&&n.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])?n.bundle.initialKB=i:n.bundle.lazyKB=i,!0}let r=t.match(Da);if(r&&n.bundle){let s=r[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let o=r[4].toUpperCase(),i=parseFloat(r[3]),a=o==="MB"?i*1024:o==="B"?i/1024:i;return n.bundle.files.push({name:s,sizeKB:Math.round(a*10)/10}),!1}return!1}function ys(n,t){let e=t.match(Ca),r=e?null:t.match(ms),s=!e&&!r?t.match(gs):null,o=e??r??s;if(o&&n.lastErrorHash){let b=n.errors.get(n.lastErrorHash);b&&!b.parsed?.file&&(b.parsed={...b.parsed??{message:b.message},file:o[1],line:Number(o[2]),col:Number(o[3])})}else if(n.lastErrorHash){let b=t.match(hs),N=b?null:t.match(xa);if(b||N){let p=n.errors.get(n.lastErrorHash);if(p&&!p.parsed?.file){let m=b??N;p.parsed={...p.parsed??{message:p.message},file:m[1],line:Number(m[2])}}}}let i=t.trim();if(!i)return null;let a=n.status,c=!1,l,u=Ba(i);u&&!n.announcedUrl&&(n.announcedUrl=u,l=u);let d=Ua(n,i),f;if(ma.some(b=>b.test(i))){let b=n.status==="error"||!!n.recoveringFromError;if(n.status==="compiling"||n.status==="starting"||n.status==="error"){let N=Date.now();n.compileStartedAt!=null?(f=N-n.compileStartedAt,n.lastCompileMs=f,n.lastCompileAt=N,n.compileStartedAt=null,n.compileHistory.push(f),n.compileHistory.length>20&&n.compileHistory.splice(0,n.compileHistory.length-20)):n.lastCompileAt=N}n.status="serving",b&&(n.errors.clear(),n.recoveringFromError=!1)}else ha.some(b=>b.test(i))&&(n.status==="starting"||n.status==="serving"||n.status==="error")&&(n.status==="error"&&(n.recoveringFromError=!0),n.compileStartedAt=Date.now(),n.status="compiling");let g,C=ga.some(b=>b.test(t)),R=!C&&wa.some(b=>b.test(i)),y=!C&&!R&&ya.some(b=>b.test(i));if(R||y||C){let b=La(i),N=Date.now(),p=n.errors.get(b),m=!1,h;p?(p.count+=1,p.lastSeen=N,h=p):(h={message:i,count:1,firstSeen:N,lastSeen:N,parsed:Ia(i),level:C?"lint":y?"warning":"error"},n.errors.set(b,h),m=!0),n.lastErrorHash=b,g={entry:h,isNew:m},R&&(n.status="error")}return c=n.status!==a,{statusChanged:c,error:g,announcedUrl:l,bundleUpdated:d,compileMs:f}}var ma,ha,ga,ya,wa,ba,va,Sa,ms,ka,hs,gs,xa,Ta,Pa,Ca,Ra,Aa,Oa,Na,$a,Ma,ja,_a,Da,ws=U(()=>{"use strict";ma=[/Local:\s+http/i,/Application bundle generation complete/i,/compiled successfully/i,/webpack compiled\s+(?:successfully|in\b)/i,/Angular Live Development Server is listening/i,/Storybook\s+[\d.]+\s+(?:for\s+\S+\s+)?started/i,/VITE\s+v[\d.]+\s+ready/i,/Quit the server with CONTROL-C/i,/Uvicorn running on http/i,/Application startup complete/i,/Puma starting in single mode/i,/Use Ctrl-C to stop/i,/Listening on tcp:\/\//i,/running on http/i,/serving HTTP on/i,/trunk serve.*at/i],ha=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i,/Watching for file changes with StatReloader/i,/Performing system checks/i,/watching files for changes/i,/building\.{3}/i,/Compiling \(/i],ga=[/^\s+\d+:\d+\s{2,}(?:warning|error)\s{2,}\S/i,/\blint\/[a-z][a-z0-9-]+\/[a-z][a-zA-Z0-9-]+\b/,/^\s*\S+\.py:\d+:\d+:\s+[A-Z]\d{3,}\b/,/^warning:\s.*clippy::/i,/^\s*=\s+note:\s+`#\[warn\(clippy::/],ya=[/^\s*(?:▲\s*)?\[WARNING\]/,/\bwarning TS\d+/i,/^\s*\[(?:warning|warn)\]\s+/i,/^\s*warning\s+\S+\s+is\s+/i,/^\s*\S+:\d+:\s*(?:Deprecation|User|Future|Pending|Resource|Runtime|Syntax)Warning:/,/^WARNING in\s+/,/^\s*\[vite\]\s+warning/i],wa=[/^\s*ERROR\b/,/\berror TS\d+/,/✘/,/\[ERROR\]/,/Cannot find module/i,/^FAIL\s+\S+/,/^\s*●\s+/,/^\s*(?:>\s+)?NX\s+.*failed/i,/^\s*Failed tasks:/,/^\s*Task\s+"[^"]+"\s+is continuous but exited with code\s+\d+/,/\bModule not found:/,/\[vite\]\s+(?:Internal server error|Pre-transform error)/i,/\[plugin:[^\]]+\]/i,/^\s*ERR!\s+/,/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):\s+/,/^Traceback \(most recent call last\):/,/^\s*[A-Z][a-zA-Z]*Error:\s+/,/^\s*\[error\]\s+/i,/^panic:\s+/,/^thread\s+'[^']+'\s+panicked at/,/^error\[E\d+\]:/,/^\S+\.(?:go|rb|py|rs):\d+:\d+:/,/^\s*[A-Z][a-zA-Z]*\.[A-Z][a-zA-Z]*:\s+/,/^[A-Z][a-zA-Z]+(?:::[A-Z][a-zA-Z]+)+\s*[(:]/,/^[A-Z][a-zA-Z]*Error\s*\(/],ba=/\berror TS(\d+)/,va=/✘\s*\[ERROR\]\s*TS(\d+)/,Sa=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)/,ms=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)\)/,ka=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,hs=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,gs=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,xa=/^([^\s:()]+\.rb):(\d+):in\b/,Ta=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,Pa=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,Ca=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,Ra=[{tool:"vite",rx:/\[vite\]|\[plugin:vite:|transformWithEsbuild/i},{tool:"storybook",rx:/\bstorybook\b|^\s*ERR!\s|builder-vite/i},{tool:"jest",rx:/^FAIL\s|^\s*●\s+|\bjest\b/i},{tool:"nx",rx:/(?:>\s+)?NX\s+(?:\w|.*failed)|Failed tasks:|Nx errored|exited with code\s+\d+/i},{tool:"webpack",rx:/\bModule not found:|webpack compiled|webpack-dev-server/i},{tool:"esbuild",rx:/✘\s*\[ERROR\]|esbuild/i},{tool:"typescript",rx:/\berror TS\d+/},{tool:"django",rx:/\bdjango\b|StatReloader|manage\.py runserver/i},{tool:"rails",rx:/\brails\b|Puma starting|Booting (?:Puma|Rails)|ActionController|NameError\s*\(|\.rb:\d+:in/i},{tool:"fastapi",rx:/\buvicorn\b|fastapi|ASGI/i},{tool:"go-air",rx:/\bair v\d|building\.{3}|\.go:\d+:\d+/i},{tool:"rust-trunk",rx:/\btrunk\b|^error\[E\d+\]|^\s*-->\s+\S+\.rs:/i},{tool:"python",rx:/^Traceback \(most recent call last\):|^\s*File "[^"]+\.py"|[A-Z][a-zA-Z]*Error:\s/},{tool:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];Aa=/Local:\s+(https?:\/\/\S+)/i,Oa=/Server running at\s+(https?:\/\/\S+)/i,Na=/listening on\s+(https?:\/\/\S+)/i,$a=/(?:listening|listen)\s+(https?:\/\/\S+)/i,Ma=/Initial chunk files/i,ja=/Lazy chunk files/i,_a=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,Da=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i});import{spawn as Ha}from"node:child_process";import bs from"tree-kill";import Ja from"strip-ansi";var vs,Ke,Ss=U(()=>{"use strict";ws();vs=500,Ke=class{child=null;stdoutBuf="";stderrBuf="";deps;stopping=!1;constructor(t){this.deps=t}isRunning(){return this.child!==null&&this.child.exitCode===null&&!this.stopping}start(){if(this.isRunning())return;let{app:t,port:e,state:r}=this.deps,s=Date.now();r.status="starting",r.startedAt=s,r.compileStartedAt=s,r.lastCompileMs=null,r.lastCompileAt=null,r.errors.clear(),r.logBuffer.length=0,r.lastStatusMessage=void 0;let i=`${this.deps.commandOverride||t.command} --port ${e}`,a={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},c=Ha(i,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=c,r.pid=c.pid??null,r.port=e,c.stdout?.on("data",l=>this.handleChunk(l,"stdout")),c.stderr?.on("data",l=>this.handleChunk(l,"stderr")),c.on("exit",(l,u)=>{let d=r.status,f=this.stopping;f?(r.status="stopped",r.lastStatusMessage=`stopped (code=${l??"null"}${u?`, ${u}`:""})`):l!==0?(r.status="error",r.lastStatusMessage=`process exited with code ${l}${u?` (${u})`:""}`):r.status="stopped",r.pid=null,r.health="unknown",this.child=null,this.stopping=!1,d!==r.status&&this.deps.onStatusChange?.(d,r.status,r.lastStatusMessage),this.deps.onExit?.(l,u,f),this.deps.onStateChange()}),c.on("error",l=>{r.status="error",r.lastStatusMessage=`spawn error: ${l.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let r=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=r,o=s.lastIndexOf(`
|
|
53
|
-
`);if(o<0)return;let
|
|
54
|
-
`,r=Buffer.from(e,"utf8");
|
|
55
|
-
`))}}});import{spawn as
|
|
56
|
-
`);if(
|
|
57
|
-
`)+(
|
|
58
|
-
`+
|
|
59
|
-
`);if(u<0)return;let d=i.slice(0,u);i=i.slice(u+1);for(let f of d.split(/\r?\n/))f.length&&(o.push(Ps(f)),o.length>500&&o.splice(0,o.length-500))};return s.stdout?.on("data",a),s.stderr?.on("data",a),{app:n.name,task:t,pid:s.pid??null,child:s,startedAt:Date.now(),logs:o,stop:()=>new Promise(l=>{if(!s.pid){l();return}let u=!1,d=()=>{u||(u=!0,l())};s.once("exit",d),xs(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&xs(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(d,3500)})}}var qa,Ga,Xa,Ka,za,Ya,Va,Za,Qa,tc,ec,nc,rc,As=U(()=>{"use strict";qa=/Tests:\s+(?:(\d+)\s+failed,\s+)?(?:(\d+)\s+skipped,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Ga=/Test Suites:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Xa=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,Ka=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i,za=/Tests\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,Ya=/Test Files\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,Va=/(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+\d+\s+skipped)?\s+in\s+([\d.]+)s/,Za=/(\d+)\s+examples?,\s+(\d+)\s+failures?/,Qa=/^(ok|FAIL|---\s+FAIL)\s+\S+\s+([\d.]+)s/,tc=/test result:\s*(?:ok|FAILED)\.\s+(\d+)\s+passed;\s+(\d+)\s+failed/,ec=/^\s*✕\s+(.+?)(?:\s+\((\d+)\s*ms\))?$/,nc=/^\s*FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|spec\.[a-z]+))/,rc=/^FAILED\s+(\S+)::([^\s]+)/});import Ns from"node:fs";import Os from"node:path";function $s(n){let t={},e;try{e=Ns.readFileSync(n,"utf8")}catch{return t}for(let r of e.split(/\r?\n/)){let s=r.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 Hn(n,t){return Os.isAbsolute(t)?t:Os.join(n,t)}function Jn(n,t){return t.filter(e=>Ns.existsSync(Hn(n,e)))}var Ms=U(()=>{"use strict"});import oc from"node:fs";import ic from"node:path";function ac(){return ic.join(mt(),"secrets.json")}function js(){try{let n=oc.readFileSync(ac(),"utf8");n.charCodeAt(0)===65279&&(n=n.slice(1));let t=JSON.parse(n);if(!t||typeof t!="object")return{};let e={};for(let[r,s]of Object.entries(t))typeof s=="string"&&(e[r]=s);return e}catch{return{}}}function _s(n,t){let e={};for(let[r,s]of Object.entries(n))e[r]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(o,i)=>t[i]??`\${${i}}`);return e}var Ds=U(()=>{"use strict";Pt()});import{EventEmitter as cc}from"node:events";var Ls,Ye,Is=U(()=>{"use strict";Bn();Ss();xe();ks();ke();As();On();Ms();Ds();Nn();Ls=500,Ye=class extends cc{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new Ue;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new re(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.baseName??s.name,s.tags,s.workspaceLabel??null,s.workspaceRoot??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.baseName??t.name,t.tags,t.workspaceLabel??null,t.workspaceRoot??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.workspaceRoot=t.workspaceRoot??null,e.state.baseName=t.baseName??t.name,e.state.dependsOn=this.config.depends?.[t.baseName??t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r,s=null,o=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:r,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[e]??[],workspaceLabel:s,workspaceRoot:o,baseName:e,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}resolveByCwd(t,e){let s=[...this.entries.values()].filter(i=>i.state.name===t||(i.state.baseName??i.state.name)===t);e&&(s=s.filter(i=>{let a=i.app.workspaceRoot;return a?Ct(a,e)||Ct(e,a):!1}));let o=s.map(i=>({name:i.state.name,baseName:i.state.baseName??i.state.name,workspaceLabel:i.state.workspaceLabel,workspaceRoot:i.state.workspaceRoot??i.app.workspaceRoot??null}));return s.length===0?{kind:"none",candidates:o}:s.length>1?{kind:"collision",candidates:o}:{kind:"unique",key:s[0].state.name,candidates:o}}pruneOldErrors(t=Date.now()){let e=this.config.errorRetention?.maxAgeMs??864e5,r=0;for(let s of this.entries.values())for(let[o,i]of s.state.errors)t-i.lastSeen>e&&(s.state.errors.delete(o),r++);return r}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let r=e.state,s=r.startedAt&&(r.status==="serving"||r.status==="compiling"||r.status==="starting")?Date.now()-r.startedAt:null,i=this.config.overrides?.[t]?.url||e.resolvedUrl||r.announcedUrl||(r.port?`http://127.0.0.1:${r.port}`:null),a;for(let c=this.eventBuffer.length-1;c>=0;c--){let l=this.eventBuffer[c];if(l.app===t&&l.type==="status"){a=Date.now()-l.ts;break}}return{name:r.name,status:r.status,port:r.port,url:i,errorCount:[...r.errors.values()].reduce((c,l)=>{let u=l.level??"error";return c+(u==="error"?l.count:0)},0),warningCount:[...r.errors.values()].reduce((c,l)=>c+(l.level==="warning"?l.count:0),0),lintCount:[...r.errors.values()].reduce((c,l)=>c+(l.level==="lint"?l.count:0),0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,workspaceRoot:r.workspaceRoot,baseName:r.baseName??r.name,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,o)=>o.lastSeen-s.lastSeen):null}logs(t,e={}){let r=this.getState(t);if(!r)return null;let s=r.logBuffer;if(e.sinceMs&&e.sinceMs>0){let 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(r=>r.ts>=e&&(!t.app||r.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>Ls&&this.eventBuffer.splice(0,this.eventBuffer.length-Ls),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let r=this.entries.get(t);if(!r)return;let s=r.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let o=s.health;s.health=e,e==="healthy"&&(r.prevHealthyAt=Date.now(),r.cascadeArmed&&(r.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from: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 r=this.getState(t);r&&r.lastHealthError!==e&&(r.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let r=this.entries.get(t);r&&r.resolvedUrl!==e&&(r.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let r=this.getState(t);r&&(r.cachedProbeHost=e)}setStale(t,e){let r=this.getState(t);r&&r.stale!==e&&(r.stale=e,this.emit("change"))}setSessionOverride(t,e){let r=this.getState(t);r&&(r.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let r=this.getState(t);r&&(r.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let r=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(g){return e.state.status="error",e.state.lastStatusMessage=g.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:g.message}),this.emit("change"),{ok:!1,status:"error",error:g.message}}if(!await Mt(s)){let g=Fe(s),C=Lr(s,g);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=C,this.recordEvent({app:t,type:"status",from:r,to:"error",message:C}),this.emit("change"),{ok:!1,status:"error",error:C}}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 ze(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],c={};if(a.length){let g=e.state.activeEnvFile;(!g||!Jn(e.app.workspaceRoot,[g]).length)&&(g=Jn(e.app.workspaceRoot,a)[0]??null,g&&(e.state.activeEnvFile=g)),g&&(c=$s(Hn(e.app.workspaceRoot,g)))}let l={...c,...this.config.overrides?.[t]?.env??{},...i?.env??{}},u=js(),d=_s(l,u),f=new Ke({state:e.state,app:e.app,port:s,envOverride:Object.keys(d).length?d:void 0,commandOverride:i?.command,onStateChange:()=>this.emit("change"),onStatusChange:(g,C,R)=>{this.recordEvent({app:t,type:"status",from:g,to:C,message:R}),(C==="stopped"||C==="error")&&(g==="serving"||g==="compiling")&&this.armCascade(t)},onErrorRecorded:(g,C)=>{let R=g.level??"error",y;R==="lint"?y=C?"lint-new":"lint-recur":R==="warning"?y=C?"warning-new":"warning-recur":y=C?"error-new":"error-recur",this.recordEvent({app:t,type:y,message:g.message})},onExit:(g,C,R)=>this.emit("childExit",{name:t,code:g,signal:C,stopping:R}),onLogLine:g=>{e.logger?.write(g),this.emit("log",{name:t,ts:Date.now(),line:g})},onCompile:g=>{this.history?.recordCompile(t,g);let C=this.getState(t),R=e.lastBundleInitialKB;if(C.bundle&&C.bundle.initialKB>0){if(R&&R>0){let y=(C.bundle.initialKB-R)/R*100;C.bundleRegressionPct=Math.round(y*10)/10,y>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${C.bundleRegressionPct}% (${R}->${C.bundle.initialKB})`})}else C.bundleRegressionPct=null;e.lastBundleInitialKB=C.bundle.initialKB}this.checkCompileRegression(t,g),this.emit("compile",{name:t,ms:g})},onBundleUpdate:()=>{let g=this.getState(t);g?.bundle&&(g.bundle.initialKB>0||g.bundle.lazyKB>0)&&this.history?.recordBundle(t,g.bundle.initialKB,g.bundle.lazyKB,g.bundle.files.length),this.emit("bundleUpdate",{name:t})}});return e.proc=f,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),f.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let r=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==r&&this.recordEvent({app:t,type:"status",from:r,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let r=De(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=Le(this.config.depends??{},r),o=[],i=e.waitMs??6e4;for(let a of s){let c=await Promise.all(a.map(u=>this.start(u)));for(let u=0;u<a.length;u++){let d=c[u];if(!d.ok)return o.push({name:a[u],status:d.status,health:"unknown",error:d.error}),{ok:!1,results:o}}let l=await Promise.all(a.map(u=>this.waitFor(u,"healthy",i)));for(let u=0;u<a.length;u++){let d=l[u],f=!d.timedOut&&d.status==="serving"&&d.health==="healthy";if(o.push({name:d.name,status:d.status,health:d.health,error:f?void 0:d.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!f)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=jr(this.config.depends??{},t);for(let r of e){let s=this.getState(r);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(r)}}async stopAll(t=3e3){let e=[];for(let r of this.entries.values())r.proc?.isRunning()&&e.push(r.proc.stop());for(let r of this.watchTasks.values())e.push(r.stop());await Promise.race([Promise.all(e),new Promise(r=>setTimeout(r,t))]);for(let r of this.entries.values())r.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,r=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:r});let s=this.getApp(t);if(!s)return{error:"unknown app"};let o=await Rs(s,e,r);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,r=[]){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=Es(s,e,r);return this.watchTasks.set(o,i),i.child.on("exit",()=>this.watchTasks.delete(o)),{ok:!0,pid:i.pid}}async stopWatchTask(t,e){let r=`${t}::${e}`,s=this.watchTasks.get(r);return s?(await s.stop(),this.watchTasks.delete(r),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let r of this.watchTasks.values())t&&r.app!==t||e.push({app:r.app,task:r.task,pid:r.pid,startedAt:r.startedAt});return e}checkCompileRegression(t,e){let r=this.history;if(!r)return;let o=r.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,r){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let o=s.logs;return r?o.slice(-r):[...o]}waitFor(t,e,r){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(u);let f=i?.state;s({name:t,status:f?.status??"unknown",health:f?.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 u=setTimeout(()=>c(!0),r);this.on("change",l)})}}});import Gn from"node:fs";import Fs from"node:path";import lc from"node:os";function uc(){try{let n=Gn.readFileSync(Xn,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function pc(n){qn=n,!Wn&&(Wn=setTimeout(()=>{Wn=null;let t=qn;if(qn=null,!!t)try{Gn.mkdirSync(Fs.dirname(Xn),{recursive:!0}),Gn.writeFileSync(Xn,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
60
|
-
`)}},500))}var
|
|
53
|
+
`)}recordSelfMetric(t,e,r,s,o=Date.now()){if(this.db)try{this.db.prepare("INSERT INTO self_metrics (ts,rssMB,heapUsedMB,eventLoopLagMs,historyQueryP95Ms) VALUES (?,?,?,?,?)").run(o,t,e,r,s)}catch(a){this.warnOnce(`self_metrics write failed: ${a?.message||a}`)}}querySelfMetrics(t={}){if(!this.db)return[];let e=[],r=[];t.since!=null&&(e.push("ts >= ?"),r.push(t.since));let s=`SELECT ts, rssMB, heapUsedMB, eventLoopLagMs, historyQueryP95Ms FROM self_metrics ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??60),this.db.prepare(s).all(...r)}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,r=Date.now()){this.db&&this.queue.push({kind:"compile",row:{ts:r,app:t,ms:e}})}recordBundle(t,e,r,s,o=Date.now()){this.db&&this.queue.push({kind:"bundle",row:{ts:o,app:t,initialKB:e,lazyKB:r,fileCount:s}})}recordTaskRun(t,e,r,s,o,a=Date.now()){this.db&&this.queue.push({kind:"task",row:{ts:a,app:t,task:e,exit_code:r,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 (?,?,?,?,?,?)"),r=this.db.prepare("INSERT INTO compile_times (ts,app,ms) VALUES (?,?,?)"),s=this.db.prepare("INSERT INTO task_runs (ts,app,task,exit_code,duration_ms,summary) VALUES (?,?,?,?,?,?)"),o=this.db.prepare("INSERT INTO bundles (ts,app,initialKB,lazyKB,fileCount) VALUES (?,?,?,?,?)");this.db.transaction(l=>{for(let i of l)i.kind==="event"?e.run(i.row.ts,i.row.app,i.row.type,i.row.from_state,i.row.to_state,i.row.message):i.kind==="compile"?r.run(i.row.ts,i.row.app,i.row.ms):i.kind==="bundle"?o.run(i.row.ts,i.row.app,i.row.initialKB,i.row.lazyKB,i.row.fileCount):s.run(i.row.ts,i.row.app,i.row.task,i.row.exit_code,i.row.duration_ms,i.row.summary)})(t)}catch(e){this.warnOnce(`history write failed: ${e?.message||e}`)}}runRetention(){if(this.db)try{let t=Date.now()-this.cfg.retentionDays*864e5;this.db.prepare("DELETE FROM events WHERE ts < ?").run(t),this.db.prepare("DELETE FROM compile_times WHERE ts < ?").run(t),this.db.prepare("DELETE FROM task_runs WHERE ts < ?").run(t),this.db.prepare("DELETE FROM bundles WHERE ts < ?").run(t),this.db.prepare("DELETE FROM self_metrics WHERE ts < ?").run(t)}catch(t){this.warnOnce(`retention failed: ${t?.message||t}`)}}queryEvents(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until)),t.type&&(e.push("type = ?"),r.push(t.type));let s=`SELECT * FROM events ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??500),this.db.prepare(s).all(...r)}queryCompiles(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until));let s=`SELECT * FROM compile_times ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??1e3),this.db.prepare(s).all(...r)}queryBundles(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until));let s=`SELECT * FROM bundles ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??1e3),this.db.prepare(s).all(...r)}trends(t){if(!this.db)return{points:[],count:0};let e=Date.now()-t.sinceMs,r=t.bucketMs,s=new Map,o=(u,p)=>{let m=Math.floor(u/r)*r,g=s.get(m)??{sum:0,n:0};g.sum+=p,g.n+=1,s.set(m,g)},a=u=>{let p=Math.floor(u/r)*r,m=s.get(p)??{sum:0,n:0};m.sum+=1,m.n+=1,s.set(p,m)},l=0;if(t.metric==="compile"){let u=this.queryCompiles({app:t.app,since:e,limit:1e4});l=u.length;for(let p of u)o(p.ts,p.ms)}else if(t.metric==="bundle"){let u=this.queryBundles({app:t.app,since:e,limit:1e4});l=u.length;for(let p of u){let m=Math.floor(p.ts/r)*r,g=s.get(m)??{sum:0,n:0,sum2:0};g.sum+=p.initialKB,g.sum2=(g.sum2??0)+p.lazyKB,g.n+=1,s.set(m,g)}}else if(t.metric==="errors"){let u=this.queryEvents({app:t.app,since:e,limit:1e4});for(let p of u)(p.type==="error-new"||p.type==="error-recur")&&(a(p.ts),l++)}else{let u=this.queryEvents({app:t.app,since:e,limit:1e4});for(let p of u)p.type==="status"&&p.to_state==="starting"&&(p.from_state==="error"||p.from_state==="serving"||p.from_state==="compiling")&&(a(p.ts),l++)}let i=[],c=[...s.entries()].sort((u,p)=>u[0]-p[0]);for(let[u,p]of c)t.metric==="compile"||t.metric==="bundle"?i.push({t:u,v:Math.round(p.sum/p.n),...p.sum2!=null?{v2:Math.round(p.sum2/p.n)}:{}}):i.push({t:u,v:p.sum});return{points:i,count:l}}queryTimeline(t){if(!this.db)return[];let e=t.limit??5e3,r=t.since,s=t.kinds,o=[],a=!s||s.has("status"),l=!s||s.has("error"),i=!s||s.has("warning"),c=!s||s.has("lint"),u=!s||s.has("health"),p=!s||s.has("bundle"),m=!s||s.has("task"),g=!s||s.has("restart");if(a||l||i||c||u||g){let S=this.queryEvents({app:t.app,since:r,limit:e});for(let x of S){let T=null;if(x.type==="status"&&a?T="status":(x.type==="error-new"||x.type==="error-recur")&&l?T="error":(x.type==="warning-new"||x.type==="warning-recur")&&i?T="warning":(x.type==="lint-new"||x.type==="lint-recur")&&c?T="lint":x.type==="health"&&u?T="health":(x.type==="restart-scheduled"||x.type==="bundle-regression"||x.type==="compile-regression"||x.type==="stale"||x.type==="self-warn")&&g&&(T="restart"),!T)continue;let w=T==="status"?`${x.from_state??"?"} \u2192 ${x.to_state??"?"}`:x.message??x.type;o.push({ts:x.ts,app:x.app,kind:T,summary:w,payload:x})}}if(p){let S=this.queryBundles({app:t.app,since:r,limit:e});for(let x of S)o.push({ts:x.ts,app:x.app,kind:"bundle",summary:`initial ${x.initialKB}KB \xB7 lazy ${x.lazyKB}KB`,payload:x})}if(m){let S=this.queryCompiles({app:t.app,since:r,limit:e});for(let T of S)o.push({ts:T.ts,app:T.app,kind:"compile",summary:`compile ${(T.ms/1e3).toFixed(1)}s`,payload:T});let x=this.queryTasks({app:t.app,since:r,limit:e});for(let T of x){let w=T.duration_ms??0;o.push({ts:T.ts,app:T.app,kind:"task",summary:`${T.task} exit=${T.exit_code} ${(w/1e3).toFixed(1)}s`,payload:T})}}return o.sort((S,x)=>x.ts-S.ts),o.slice(0,e)}queryTasks(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.task&&(e.push("task = ?"),r.push(t.task)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since));let s=`SELECT * FROM task_runs ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??200),this.db.prepare(s).all(...r)}summary(t){if(!this.db)return{uptimePct24h:0,restartCount24h:0,compileP50:null,compileP95:null,topErrors:[]};let e=Date.now()-24*3600*1e3,r=this.queryEvents({app:t,since:e,limit:5e3}),s=0,o=e,a=!1,l=null,i=[...r].sort((w,E)=>w.ts-E.ts);for(let w of i)w.type==="status"&&(w.to_state==="serving"&&!a?(a=!0,l=w.ts):a&&w.to_state!=="serving"&&l!=null&&(s+=w.ts-l,a=!1,l=null));a&&l!=null&&(s+=Date.now()-l);let c=Math.round(s/(24*3600*1e3)*1e3)/10,u=r.filter(w=>w.type==="status"&&w.to_state==="starting"&&(w.from_state==="serving"||w.from_state==="error"||w.from_state==="compiling")).length,p=this.queryCompiles({app:t,since:e,limit:1e3}).map(w=>w.ms).sort((w,E)=>w-E),m=(w,E)=>{if(w.length===0)return null;let B=Math.min(w.length-1,Math.floor((w.length-1)*E));return w[B]},g=m(p,.5),S=m(p,.95),x=new Map;for(let w of r)if(w.type==="error-new"||w.type==="error-recur"){let E=w.message??"";if(!E)continue;x.set(E,(x.get(E)??0)+1)}let T=[...x.entries()].sort((w,E)=>E[1]-w[1]).slice(0,5).map(([w,E])=>({message:w,count:E}));return{uptimePct24h:c,restartCount24h:u,compileP50:g,compileP95:S,topErrors:T}}why(t){let e=this.queryEvents({app:t,limit:200}),r=e.find(l=>l.type==="status"&&(l.to_state==="error"||l.from_state==="error"||l.to_state==="serving")),s=r?{ts:r.ts,app:r.app,type:r.type,from:r.from_state??void 0,to:r.to_state??void 0,message:r.message??void 0}:null,o=s?s.ts:Date.now(),a=e.filter(l=>l.ts<o).slice(0,5);return{trigger:s,preceding:a.map(l=>({ts:l.ts,app:l.app,type:l.type,from:l.from_state??void 0,to:l.to_state??void 0,message:l.message??void 0}))}}_flushForTest(){this.flush()}quickCheck(){if(!this.db)return!1;try{return this.db.prepare("PRAGMA quick_check").get()?.quick_check==="ok"}catch{return!1}}close(){if(this.flushTimer&&clearInterval(this.flushTimer),this.retentionTimer&&clearInterval(this.retentionTimer),this.retentionStart&&clearTimeout(this.retentionStart),this.flush(),this.db){try{this.db.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{this.db.close()}catch{}this.db=null}}}});var Gr={};Ct(Gr,{analyseRestartCadence:()=>jn,suggestProfiles:()=>ia});function ia(n,t={}){let e=t.windowMs??6e4,r=t.minOccurrences??5,s=t.minApps??2,o=t.existingProfiles??{},a=n.filter(p=>p.type==="status"&&(p.to_state==="starting"||p.to==="starting")).sort((p,m)=>p.ts-m.ts),l=[];for(let p of a){let m=l[l.length-1];m&&p.ts-m.lastTs<=e?(m.apps.includes(p.app)||m.apps.push(p.app),m.lastTs=p.ts):l.push({apps:[p.app],firstTs:p.ts,lastTs:p.ts})}let i=new Map;for(let p of l){if(p.apps.length<s)continue;let m=[...p.apps].sort().join("\0"),g=i.get(m);g?(g.count++,g.lastSeen=Math.max(g.lastSeen,p.lastTs)):i.set(m,{apps:[...p.apps].sort(),count:1,lastSeen:p.lastTs})}let c=new Set;for(let p of Object.values(o))c.add([...p].sort().join("\0"));let u=[];for(let[p,m]of i)m.count<r||c.has(p)||u.push({name:aa(m.apps,o),apps:m.apps,cooccurrences:m.count,lastSeenMs:m.lastSeen,reason:`started together within ${Math.round(e/1e3)}s \xB7 ${m.count} times`});return u.sort((p,m)=>m.cooccurrences-p.cooccurrences),u}function aa(n,t){let s=n.map(l=>l.split(/[-_\s.]/).filter(Boolean)).reduce((l,i,c)=>c===0?i:l.filter(u=>i.includes(u)),[])[0]??`stack-${n.length}`;s||(s=`stack-${n.length}`),s=s.toLowerCase();let o=s,a=2;for(;t[o];)o=`${s}-${a++}`;return o}function jn(n,t=7,e=5,r=Date.now()){let s=r-t*24*60*6e4,o=new Map;for(let l of n){if(l.ts<s||l.type!=="status")continue;let i=l.to_state??l.to,c=l.from_state??l.from;(i==="starting"||i==="compiling")&&c&&c!=="stopped"&&o.set(l.app,(o.get(l.app)??0)+1)}let a=[];for(let[l,i]of o){let c=i/t;c>=e&&a.push({app:l,restartsPerDay:Math.round(c*10)/10,totalRestarts:i,windowDays:t,reason:`${i} restarts in last ${t}d (~${Math.round(c)}\xD7 / day) \u2014 review restartPolicy / autoRestart for this app`})}return a.sort((l,i)=>i.restartsPerDay-l.restartsPerDay)}var Ln=H(()=>{"use strict"});import{spawnSync as In}from"node:child_process";import Kr from"tree-kill";function Je(n){if(process.platform==="win32"){let o=In("powershell",["-NoProfile","-Command",`Get-NetTCPConnection -LocalPort ${n} -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty OwningProcess`],{encoding:"utf8",windowsHide:!0});if(o.status!==0)return null;let a=Number((o.stdout||"").trim().split(/\s+/)[0]);if(!Number.isFinite(a)||a<=0)return null;let l=In("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${a}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),i,c;try{let u=JSON.parse((l.stdout||"").trim()||"{}");i=typeof u.Name=="string"?u.Name:void 0,c=typeof u.CommandLine=="string"?u.CommandLine:void 0}catch{}return{pid:a,name:i,cmd:c}}let t=In("lsof",["-nP","-iTCP:"+n,"-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 r=e[0].split(/\s+/);return{pid:Number(r[1]),name:r[0]}}function zr(n,t){if(!t)return`port ${n} already in use`;let e=[`port ${n} 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 Yr(n){return new Promise(t=>{if(!n.pid||n.pid===process.pid){t(!1);return}Kr(n.pid,"SIGTERM",e=>{if(e){setTimeout(()=>Kr(n.pid,"SIGKILL",r=>t(!r)),500);return}t(!0)})})}var Fn=H(()=>{"use strict"});import We from"node:fs";import la from"node:os";import Vr from"node:path";function Qr(n){return We.readFileSync(n,"utf8").split(/\r?\n/).filter(e=>e.trim()).map(e=>JSON.parse(e))}var qe,Bn=H(()=>{"use strict";qe=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=Vr.join(la.homedir(),".daimon","sessions");We.mkdirSync(t,{recursive:!0});let e=Vr.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return We.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})+`
|
|
54
|
+
`;try{We.appendFileSync(this.file,e)}catch{}}}});import ua from"node:fs";import Un from"node:path";import{fileURLToPath as pa}from"node:url";function da(){let n=[Un.resolve(Zr,"..","package.json"),Un.resolve(Zr,"..","..","package.json")];for(let t of n)try{return JSON.parse(ua.readFileSync(t,"utf8"))}catch{}return{}}var Zr,ut,Jt=H(()=>{"use strict";Zr=Un.dirname(pa(import.meta.url));ut=da().version||"0.0.0"});import he from"node:fs";import Ge from"node:path";import fa from"node:os";import{spawn as ma}from"node:child_process";import{fileURLToPath as ha}from"node:url";function bt(){return Jn}function Xe(){return ge}function Hn(n){try{return process.kill(n,0),!0}catch(t){return t&&t.code==="EPERM"}}function mt(){try{let n=he.readFileSync(ge,"utf8"),t=JSON.parse(n);if(!t||typeof t.pid!="number")return null;if(!Hn(t.pid)){try{he.unlinkSync(ge)}catch{}return null}return t}catch{return null}}function ts(n){he.mkdirSync(Jn,{recursive:!0});let t=ge+"."+process.pid+".tmp";he.writeFileSync(t,JSON.stringify(n)),he.renameSync(t,ge)}function Ot(){try{he.unlinkSync(ge)}catch{}}function ga(){let n=Ge.dirname(ha(import.meta.url));return Ge.join(n,"main.js")}async function Wt(n={}){let t={...process.env};n.port&&(t.DAIMON_PORT=String(n.port)),ma(process.execPath,[ga(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let r=Date.now();for(;Date.now()-r<5e3;){let s=mt();if(s&&(!n.port||s.apiPort===n.port))return s;await new Promise(o=>setTimeout(o,100))}throw new Error("daemon failed to start within 5s")}async function te(n,t){let e=Date.now();for(;Date.now()-e<t;){if(!Hn(n))return!0;await new Promise(r=>setTimeout(r,100))}return!Hn(n)}function es(n,t,e){return{pid:process.pid,apiPort:n,version:ut,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var Jn,ge,Nt=H(()=>{"use strict";Jt();Jn=Ge.join(fa.homedir(),".daimon"),ge=Ge.join(Jn,"daemon.lock")});import ya from"node:os";import wa from"node:crypto";function rs(){let n=process.env.DAIMON_AGENT_ID;if(n&&n.trim())return n.trim();let t=(ya.hostname()||"unknown").split(".")[0].toLowerCase().replace(/[^a-z0-9-]/g,"").slice(0,24)||"host",e=process.pid,r=wa.randomBytes(2).toString("hex"),s=`${t}-${e}-${r}`;return process.env.DAIMON_AGENT_ID=s,s}var ns,ba,Ke,ze,Wn=H(()=>{"use strict";ns=5*6e4,ba=3e4;Ke=class{agents=new Map;touch(t,e,r=Date.now()){let s=this.agents.get(t);return s||(s={id:t,firstSeen:r,lastSeen:r,cwd:e,callCount:0},this.agents.set(t,s)),s.lastSeen=r,e&&(s.cwd=e),s.callCount++,s}list(t=Date.now()){let e=[];for(let r of this.agents.values())t-r.lastSeen<=ns&&e.push({...r});return e.sort((r,s)=>s.lastSeen-r.lastSeen)}prune(t=Date.now()){let e=0;for(let[r,s]of this.agents)t-s.lastSeen>ns*2&&(this.agents.delete(r),e++);return e}},ze=class{constructor(t=ba){this.ttlMs=t}ttlMs;locks=new Map;history=new Map;acquire(t,e,r,s=Date.now()){this.recordInteraction(t,e,r,s);let o=this.locks.get(t);if(o&&o.expiresAt>s&&o.agent!==e)return{...o};let a={app:t,agent:e,lockedAt:s,expiresAt:s+this.ttlMs};return this.locks.set(t,a),null}steal(t,e,r,s=Date.now()){this.recordInteraction(t,e,r,s);let o={app:t,agent:e,lockedAt:s,expiresAt:s+this.ttlMs};return this.locks.set(t,o),o}handoff(t,e,r,s=Date.now()){this.recordInteraction(t,e,`handoff${r?`<-${r}`:""}`,s);let o={app:t,agent:e,lockedAt:s,expiresAt:s+this.ttlMs};return this.locks.set(t,o),o}current(t,e=Date.now()){let r=this.locks.get(t);return r?r.expiresAt<=e?(this.locks.delete(t),null):{...r}:null}list(t=Date.now()){let e=[];for(let r of this.locks.values())r.expiresAt>t&&e.push({...r});return e}recentInteractions(t,e=3){return(this.history.get(t)??[]).slice(-e).reverse()}recordInteraction(t,e,r,s){let o=this.history.get(t)??[];for(o.push({agent:e,at:s,action:r});o.length>16;)o.shift();this.history.set(t,o)}}});var Cs={};Ct(Cs,{promptClaudeInstall:()=>_a});import se,{useState as xs}from"react";import{Box as Ts,render as Oa,Text as Ze,useApp as Na,useInput as $a}from"ink";function Ma({onDone:n}){let{exit:t}=Na(),[e,r]=xs(0),[s,o]=xs({skill:!0,commands:!1,agent:!0}),a=[{key:"skill",label:"Skill (~/.claude/skills/daimon/SKILL.md)"},{key:"agent",label:"Subagent (~/.claude/agents/daimon-runner.md)"}];return $a((l,i)=>{if(i.escape||l==="q"&&!i.shift){n(null),t();return}if(i.upArrow)r(c=>Math.max(0,c-1));else if(i.downArrow)r(c=>Math.min(a.length-1,c+1));else if(l===" "){let c=a[e].key;o(u=>({...u,[c]:!u[c]}))}else i.return&&(n(s),t())}),se.createElement(Ts,{flexDirection:"column",paddingX:1},se.createElement(Ze,{bold:!0,color:"cyan"},"Install Claude Code integration artifacts"),se.createElement(Ze,{dimColor:!0},"Space toggles \xB7 Enter confirms \xB7 Esc cancels"),a.map((l,i)=>se.createElement(Ts,{key:l.key},se.createElement(Ze,{color:i===e?"cyan":void 0},i===e?"\u25B8 ":" "),se.createElement(Ze,null,"[",s[l.key]?"x":" ","] ",l.label))))}async function _a(){return new Promise(n=>{let t=!1;Oa(se.createElement(Ma,{onDone:r=>{t||(t=!0,n(r))}})).waitUntilExit().then(()=>{t||(t=!0,n(null))})})}var Rs=H(()=>{"use strict"});import zn from"node:path";function Ps(n){let t=zn.resolve(n);return process.platform==="win32"?t.toLowerCase():t}function $t(n,t){let e=Ps(n),r=Ps(t);if(e===r)return!0;let s=r.endsWith(zn.sep)?r:r+zn.sep;return e.startsWith(s)}var Yn=H(()=>{"use strict"});import Da from"node:crypto";function Ya(n){for(let{tool:t,rx:e}of za)if(e.test(n))return t}function oc(n){return Da.createHash("sha1").update(n).digest("hex").slice(0,16)}function ic(n){let t={message:n},e=n.match(Ha)||n.match(Ua);e&&(t.code=`TS${e[1]}`);let r=n.match(Wa)||n.match(As)||n.match(Ja);if(r)t.file=r[1],t.line=Number(r[2]),t.col=Number(r[3]);else{let o=n.match(Xa);if(o)t.file=o[1],o[2]&&(t.line=Number(o[2])),o[3]&&(t.col=Number(o[3]));else{let a=n.match(Ga);if(a)t.file=a[1];else{let l=n.match(Os);if(l)t.file=l[1],t.line=Number(l[2]),t.col=Number(l[3]);else{let i=n.match(Es);i&&(t.file=i[1],t.line=Number(i[2]))}}}}let s=Ya(n);return s&&(t.tool=s),t}function ac(n,t){try{let e=new URL(n);return e.hostname==="0.0.0.0"||e.hostname==="[::]"?(e.hostname=t.includes(":")?`[${t}]`:t,e.toString().replace(/\/$/,"")):n.replace(/\/$/,"")}catch{return n}}function cc(n,t="127.0.0.1"){let e=n.match(Va)||n.match(Qa)||n.match(Za)||n.match(tc);if(!e)return null;let r=e[1].replace(/[),.;]+$/,"");return ac(r,t)}function lc(n,t){if(ec.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="initial",!1;if(nc.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="lazy",!1;let e=t.match(rc);if(e&&n.bundle){let s=parseFloat(e[2]),o=e[3].toUpperCase(),a=Math.round(o==="MB"?s*1024:o==="B"?s/1024:s);return/Initial/i.test(e[1])?n.bundle.initialKB=a:n.bundle.lazyKB=a,!0}let r=t.match(sc);if(r&&n.bundle){let s=r[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let o=r[4].toUpperCase(),a=parseFloat(r[3]),l=o==="MB"?a*1024:o==="B"?a/1024:a;return n.bundle.files.push({name:s,sizeKB:Math.round(l*10)/10}),!1}return!1}function Ns(n,t){let e=t.match(Ka),r=e?null:t.match(As),s=!e&&!r?t.match(Os):null,o=e??r??s;if(o&&n.lastErrorHash){let w=n.errors.get(n.lastErrorHash);w&&!w.parsed?.file&&(w.parsed={...w.parsed??{message:w.message},file:o[1],line:Number(o[2]),col:Number(o[3])})}else if(n.lastErrorHash){let w=t.match(Es),E=w?null:t.match(qa);if(w||E){let B=n.errors.get(n.lastErrorHash);if(B&&!B.parsed?.file){let Q=w??E;B.parsed={...B.parsed??{message:B.message},file:Q[1],line:Number(Q[2])}}}}let a=t.trim();if(!a)return null;let l=n.status,i=!1,c,u=cc(a);u&&!n.announcedUrl&&(n.announcedUrl=u,c=u);let p=lc(n,a),m;if(ja.some(w=>w.test(a))){let w=n.status==="error"||!!n.recoveringFromError;if(n.status==="compiling"||n.status==="starting"||n.status==="error"){let E=Date.now();n.compileStartedAt!=null?(m=E-n.compileStartedAt,n.lastCompileMs=m,n.lastCompileAt=E,n.compileStartedAt=null,n.compileHistory.push(m),n.compileHistory.length>20&&n.compileHistory.splice(0,n.compileHistory.length-20)):n.lastCompileAt=E}n.status="serving",w&&(n.errors.clear(),n.recoveringFromError=!1)}else La.some(w=>w.test(a))&&(n.status==="starting"||n.status==="serving"||n.status==="error")&&(n.status==="error"&&(n.recoveringFromError=!0),n.compileStartedAt=Date.now(),n.status="compiling");let g,S=Ia.some(w=>w.test(t)),x=!S&&Ba.some(w=>w.test(a)),T=!S&&!x&&Fa.some(w=>w.test(a));if(x||T||S){let w=oc(a),E=Date.now(),B=n.errors.get(w),Q=!1,k;B?(B.count+=1,B.lastSeen=E,k=B):(k={message:a,count:1,firstSeen:E,lastSeen:E,parsed:ic(a),level:S?"lint":T?"warning":"error"},n.errors.set(w,k),Q=!0),n.lastErrorHash=w,g={entry:k,isNew:Q},x&&(n.status="error")}return i=n.status!==l,{statusChanged:i,error:g,announcedUrl:c,bundleUpdated:p,compileMs:m}}var ja,La,Ia,Fa,Ba,Ua,Ha,Ja,As,Wa,Es,Os,qa,Ga,Xa,Ka,za,Va,Qa,Za,tc,ec,nc,rc,sc,$s=H(()=>{"use strict";ja=[/Local:\s+http/i,/Application bundle generation complete/i,/compiled successfully/i,/webpack compiled\s+(?:successfully|in\b)/i,/Angular Live Development Server is listening/i,/Storybook\s+[\d.]+\s+(?:for\s+\S+\s+)?started/i,/VITE\s+v[\d.]+\s+ready/i,/Quit the server with CONTROL-C/i,/Uvicorn running on http/i,/Application startup complete/i,/Puma starting in single mode/i,/Use Ctrl-C to stop/i,/Listening on tcp:\/\//i,/running on http/i,/serving HTTP on/i,/trunk serve.*at/i],La=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i,/Watching for file changes with StatReloader/i,/Performing system checks/i,/watching files for changes/i,/building\.{3}/i,/Compiling \(/i],Ia=[/^\s+\d+:\d+\s{2,}(?:warning|error)\s{2,}\S/i,/\blint\/[a-z][a-z0-9-]+\/[a-z][a-zA-Z0-9-]+\b/,/^\s*\S+\.py:\d+:\d+:\s+[A-Z]\d{3,}\b/,/^warning:\s.*clippy::/i,/^\s*=\s+note:\s+`#\[warn\(clippy::/],Fa=[/^\s*(?:▲\s*)?\[WARNING\]/,/\bwarning TS\d+/i,/^\s*\[(?:warning|warn)\]\s+/i,/^\s*warning\s+\S+\s+is\s+/i,/^\s*\S+:\d+:\s*(?:Deprecation|User|Future|Pending|Resource|Runtime|Syntax)Warning:/,/^WARNING in\s+/,/^\s*\[vite\]\s+warning/i],Ba=[/^\s*ERROR\b/,/\berror TS\d+/,/✘/,/\[ERROR\]/,/Cannot find module/i,/^FAIL\s+\S+/,/^\s*●\s+/,/^\s*(?:>\s+)?NX\s+.*failed/i,/^\s*Failed tasks:/,/^\s*Task\s+"[^"]+"\s+is continuous but exited with code\s+\d+/,/\bModule not found:/,/\[vite\]\s+(?:Internal server error|Pre-transform error)/i,/\[plugin:[^\]]+\]/i,/^\s*ERR!\s+/,/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):\s+/,/^Traceback \(most recent call last\):/,/^\s*[A-Z][a-zA-Z]*Error:\s+/,/^\s*\[error\]\s+/i,/^panic:\s+/,/^thread\s+'[^']+'\s+panicked at/,/^error\[E\d+\]:/,/^\S+\.(?:go|rb|py|rs):\d+:\d+:/,/^\s*[A-Z][a-zA-Z]*\.[A-Z][a-zA-Z]*:\s+/,/^[A-Z][a-zA-Z]+(?:::[A-Z][a-zA-Z]+)+\s*[(:]/,/^[A-Z][a-zA-Z]*Error\s*\(/],Ua=/\berror TS(\d+)/,Ha=/✘\s*\[ERROR\]\s*TS(\d+)/,Ja=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)/,As=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)\)/,Wa=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,Es=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,Os=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,qa=/^([^\s:()]+\.rb):(\d+):in\b/,Ga=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,Xa=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,Ka=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,za=[{tool:"vite",rx:/\[vite\]|\[plugin:vite:|transformWithEsbuild/i},{tool:"storybook",rx:/\bstorybook\b|^\s*ERR!\s|builder-vite/i},{tool:"jest",rx:/^FAIL\s|^\s*●\s+|\bjest\b/i},{tool:"nx",rx:/(?:>\s+)?NX\s+(?:\w|.*failed)|Failed tasks:|Nx errored|exited with code\s+\d+/i},{tool:"webpack",rx:/\bModule not found:|webpack compiled|webpack-dev-server/i},{tool:"esbuild",rx:/✘\s*\[ERROR\]|esbuild/i},{tool:"typescript",rx:/\berror TS\d+/},{tool:"django",rx:/\bdjango\b|StatReloader|manage\.py runserver/i},{tool:"rails",rx:/\brails\b|Puma starting|Booting (?:Puma|Rails)|ActionController|NameError\s*\(|\.rb:\d+:in/i},{tool:"fastapi",rx:/\buvicorn\b|fastapi|ASGI/i},{tool:"go-air",rx:/\bair v\d|building\.{3}|\.go:\d+:\d+/i},{tool:"rust-trunk",rx:/\btrunk\b|^error\[E\d+\]|^\s*-->\s+\S+\.rs:/i},{tool:"python",rx:/^Traceback \(most recent call last\):|^\s*File "[^"]+\.py"|[A-Z][a-zA-Z]*Error:\s/},{tool:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];Va=/Local:\s+(https?:\/\/\S+)/i,Qa=/Server running at\s+(https?:\/\/\S+)/i,Za=/listening on\s+(https?:\/\/\S+)/i,tc=/(?:listening|listen)\s+(https?:\/\/\S+)/i,ec=/Initial chunk files/i,nc=/Lazy chunk files/i,rc=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,sc=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i});import{spawn as uc}from"node:child_process";import Ms from"tree-kill";import pc from"strip-ansi";var _s,tn,Ds=H(()=>{"use strict";$s();_s=500,tn=class{child=null;stdoutBuf="";stderrBuf="";deps;stopping=!1;constructor(t){this.deps=t}isRunning(){return this.child!==null&&this.child.exitCode===null&&!this.stopping}start(){if(this.isRunning())return;let{app:t,port:e,state:r}=this.deps,s=Date.now();r.status="starting",r.startedAt=s,r.compileStartedAt=s,r.lastCompileMs=null,r.lastCompileAt=null,r.errors.clear(),r.logBuffer.length=0,r.lastStatusMessage=void 0;let a=`${this.deps.commandOverride||t.command} --port ${e}`,l={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},i=uc(a,[],{cwd:t.workspaceRoot,shell:!0,env:l,windowsHide:!0});this.child=i,r.pid=i.pid??null,r.port=e,i.stdout?.on("data",c=>this.handleChunk(c,"stdout")),i.stderr?.on("data",c=>this.handleChunk(c,"stderr")),i.on("exit",(c,u)=>{let p=r.status,m=this.stopping;m?(r.status="stopped",r.lastStatusMessage=`stopped (code=${c??"null"}${u?`, ${u}`:""})`):c!==0?(r.status="error",r.lastStatusMessage=`process exited with code ${c}${u?` (${u})`:""}`):r.status="stopped",r.pid=null,r.health="unknown",this.child=null,this.stopping=!1,p!==r.status&&this.deps.onStatusChange?.(p,r.status,r.lastStatusMessage),this.deps.onExit?.(c,u,m),this.deps.onStateChange()}),i.on("error",c=>{r.status="error",r.lastStatusMessage=`spawn error: ${c.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let r=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=r,o=s.lastIndexOf(`
|
|
55
|
+
`);if(o<0)return;let a=s.slice(0,o),l=s.slice(o+1);e==="stdout"?this.stdoutBuf=l:this.stderrBuf=l;let{state:i}=this.deps,c=!1;for(let u of a.split(/\r?\n/)){if(!u.length)continue;let p=pc(u),m=Date.now();i.lastLogTs=m,i.stale&&(i.stale=!1),i.logBuffer.push({ts:m,line:p}),i.logBuffer.length>_s&&i.logBuffer.splice(0,i.logBuffer.length-_s),this.deps.onLogLine?.(p);let g=i.status,S=Ns(i,p);S?.statusChanged&&(c=!0,this.deps.onStatusChange?.(g,i.status)),S?.error&&this.deps.onErrorRecorded?.(S.error.entry,S.error.isNew),S?.compileMs!=null&&this.deps.onCompile?.(S.compileMs),S?.bundleUpdated&&this.deps.onBundleUpdate?.()}(c||a.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 r=!1,s=()=>{r||(r=!0,e())},o=()=>s();this.child?.once("exit",o),Ms(t,"SIGTERM",()=>{});let a=setTimeout(()=>{Ms(t,"SIGKILL",()=>{})},2e3),l=setTimeout(()=>{clearTimeout(a),s()},3e3);this.child?.once("exit",()=>{clearTimeout(a),clearTimeout(l),s()})})}}});import Mt from"node:fs";import dc from"node:path";var en,js=H(()=>{"use strict";en=class{constructor(t,e){this.appName=t;this.cfg=e;this.filePath=dc.join(e.dir,`${t}.log`),this.open()}appName;cfg;fd=null;bytes=0;warned=!1;filePath;open(){try{Mt.mkdirSync(this.cfg.dir,{recursive:!0});try{this.bytes=Mt.statSync(this.filePath).size}catch{this.bytes=0}this.fd=Mt.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}
|
|
56
|
+
`,r=Buffer.from(e,"utf8");Mt.writeSync(this.fd,r),this.bytes+=r.length,this.bytes>=this.cfg.maxBytesPerFile&&this.rotate()}catch(e){this.warn(`write failed: ${e.message}`)}}close(){if(this.fd!=null){try{Mt.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}`,r=`${this.filePath}.${t+1}`;if(t+1>this.cfg.maxFiles-1){try{Mt.rmSync(e,{force:!0})}catch{}continue}try{Mt.existsSync(e)&&Mt.renameSync(e,r)}catch{}}try{let t=`${this.filePath}.1`;Mt.existsSync(this.filePath)&&Mt.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}
|
|
57
|
+
`))}}});import{spawn as Is}from"node:child_process";import Ls from"tree-kill";import Fs from"strip-ansi";function Vn(n){let t=[],e;for(let r of n.split(/\r?\n/)){let s=r.match(Tc);if(s){e=s[1];continue}let o=r.match(xc);if(o){t.push({name:o[1].trim(),file:e});continue}let a=r.match(Cc);if(a){t.push({name:a[2],file:a[1]});continue}}return t.slice(0,50)}function Rc(n){let t=n.match(fc);if(t){let m=t[1]?Number(t[1]):0,g=Number(t[3]),S=t[4]?Number(t[4]):g+m,x=n.match(mc);return{passed:g,failed:m,total:S,suites:x?Number(x[3]??x[2]):void 0,framework:"jest",failedTests:m>0?Vn(n):void 0}}let e=n.match(yc);if(e){let m=e[1]?Number(e[1]):0,g=Number(e[2]),S=e[3]?Number(e[3]):g+m,x=n.match(wc);return{passed:g,failed:m,total:S,suites:x?Number(x[3]??x[2]):void 0,framework:"vitest",failedTests:m>0?Vn(n):void 0}}let r=n.match(hc);if(r){let m=Number(r[1]),g=Number(r[2]),S=r[3]?Number(r[3]):0;return{passed:m-S,failed:S,total:g,framework:"karma"}}let s=n.match(gc);if(s&&/playwright/i.test(n)){let m=Number(s[1]),g=s[2]?Number(s[2]):0;return{passed:m,failed:g,total:m+g,framework:"playwright"}}let o=n.match(bc);if(o){let m=o[1]?Number(o[1]):0,g=Number(o[2]);return{passed:g,failed:m,total:g+m,durationMs:Math.round(Number(o[3])*1e3),framework:"pytest",failedTests:m>0?Vn(n):void 0}}let a=n.match(vc);if(a){let m=Number(a[1]),g=Number(a[2]);return{passed:m-g,failed:g,total:m,framework:"rspec"}}let l=n.match(kc);if(l){let m=Number(l[1]),g=Number(l[2]);return{passed:m,failed:g,total:m+g,framework:"cargo"}}let i=0,c=0,u=0,p=!1;for(let m of n.split(/\r?\n/)){let g=m.match(Sc);g&&(p=!0,u+=Math.round(Number(g[2])*1e3),g[1]==="ok"?i++:c++)}if(p)return{passed:i,failed:c,total:i+c,durationMs:u,framework:"go"};if(s){let m=Number(s[1]),g=s[2]?Number(s[2]):0;return{passed:m,failed:g,total:m+g,framework:"playwright"}}return null}function Bs(n,t,e){let r=e.length?" -- "+e.join(" "):"";return n.workspaceType==="nx"?`npx nx run ${n.name}:${t}${r}`:n.workspaceType==="angular"?`npx ng run ${n.name}:${t}${r}`:`npx ${t}${r}`}function Us(n,t,e=[]){return new Promise(r=>{let s=Date.now(),o=Bs(n,t,e),a=Is(o,[],{cwd:n.workspaceRoot,shell:!0,env:{...process.env,...n.env||{},FORCE_COLOR:"0"},windowsHide:!0}),l=[],i="",c=u=>{i+=u.toString("utf8");let p=i.lastIndexOf(`
|
|
58
|
+
`);if(p<0)return;let m=i.slice(0,p);i=i.slice(p+1);for(let g of m.split(/\r?\n/)){if(!g.length)continue;let S=Fs(g);l.push(S),l.length>1e3&&l.splice(0,l.length-1e3)}};a.stdout?.on("data",c),a.stderr?.on("data",c),a.on("exit",u=>{let p=Date.now()-s,m=l.join(`
|
|
59
|
+
`)+(i?`
|
|
60
|
+
`+i:""),g=Rc(m);r({app:n.name,task:t,exitCode:u,durationMs:p,summary:g,outputTail:l.slice(-50)})}),a.on("error",()=>{r({app:n.name,task:t,exitCode:-1,durationMs:Date.now()-s,summary:null,outputTail:[...l,"[daimon] task spawn error"]})})})}function Hs(n,t,e=[]){let r=Bs(n,t,e),s=Is(r,[],{cwd:n.workspaceRoot,shell:!0,env:{...process.env,...n.env||{},FORCE_COLOR:"0"},windowsHide:!0}),o=[],a="",l=c=>{a+=c.toString("utf8");let u=a.lastIndexOf(`
|
|
61
|
+
`);if(u<0)return;let p=a.slice(0,u);a=a.slice(u+1);for(let m of p.split(/\r?\n/))m.length&&(o.push(Fs(m)),o.length>500&&o.splice(0,o.length-500))};return s.stdout?.on("data",l),s.stderr?.on("data",l),{app:n.name,task:t,pid:s.pid??null,child:s,startedAt:Date.now(),logs:o,stop:()=>new Promise(c=>{if(!s.pid){c();return}let u=!1,p=()=>{u||(u=!0,c())};s.once("exit",p),Ls(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&Ls(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(p,3500)})}}var fc,mc,hc,gc,yc,wc,bc,vc,Sc,kc,xc,Tc,Cc,Js=H(()=>{"use strict";fc=/Tests:\s+(?:(\d+)\s+failed,\s+)?(?:(\d+)\s+skipped,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,mc=/Test Suites:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,hc=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,gc=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i,yc=/Tests\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,wc=/Test Files\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,bc=/(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+\d+\s+skipped)?\s+in\s+([\d.]+)s/,vc=/(\d+)\s+examples?,\s+(\d+)\s+failures?/,Sc=/^(ok|FAIL|---\s+FAIL)\s+\S+\s+([\d.]+)s/,kc=/test result:\s*(?:ok|FAILED)\.\s+(\d+)\s+passed;\s+(\d+)\s+failed/,xc=/^\s*✕\s+(.+?)(?:\s+\((\d+)\s*ms\))?$/,Tc=/^\s*FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|spec\.[a-z]+))/,Cc=/^FAILED\s+(\S+)::([^\s]+)/});import qs from"node:fs";import Ws from"node:path";function Gs(n){let t={},e;try{e=qs.readFileSync(n,"utf8")}catch{return t}for(let r of e.split(/\r?\n/)){let s=r.trim();if(!s||s.startsWith("#"))continue;let o=s.indexOf("=");if(o<0)continue;let a=s.slice(0,o).trim(),l=s.slice(o+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),a&&(t[a]=l)}return t}function Qn(n,t){return Ws.isAbsolute(t)?t:Ws.join(n,t)}function Zn(n,t){return t.filter(e=>qs.existsSync(Qn(n,e)))}var Xs=H(()=>{"use strict"});import Pc from"node:fs";import Ac from"node:path";function Ec(){return Ac.join(bt(),"secrets.json")}function Ks(){try{let n=Pc.readFileSync(Ec(),"utf8");n.charCodeAt(0)===65279&&(n=n.slice(1));let t=JSON.parse(n);if(!t||typeof t!="object")return{};let e={};for(let[r,s]of Object.entries(t))typeof s=="string"&&(e[r]=s);return e}catch{return{}}}function zs(n,t){let e={};for(let[r,s]of Object.entries(n))e[r]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(o,a)=>t[a]??`\${${a}}`);return e}var Ys=H(()=>{"use strict";Nt()});import{execFileSync as Oc}from"node:child_process";function Vs(n,t,e=2){if(n.length<10)return null;let r=[...n].sort((a,l)=>a-l),s=r[Math.floor((r.length-1)*.5)];if(s<=0)return null;let o=t/s;return o<e?null:{kind:"compile",factor:Math.round(o*100)/100,baseline:s,current:t}}function Qs(n,t,e=1.1){if(n==null||n<=0)return null;let r=t/n;return r<e?null:{kind:"bundle",factor:Math.round(r*100)/100,baseline:n,current:t}}function tr(n){if(!n)return null;try{let t=Oc("git",["log","-1","--format=%h:%s"],{cwd:n,stdio:["ignore","pipe","ignore"],timeout:1500,maxBuffer:4096}).toString("utf8").trim();return t?t.slice(0,160):null}catch{return null}}var Zs=H(()=>{"use strict"});import{EventEmitter as Nc}from"node:events";var to,nn,eo=H(()=>{"use strict";Yn();Ds();Ee();js();Ae();Js();Fn();Xs();Ys();Bn();Zs();to=500,nn=class extends Nc{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new qe;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new me(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.baseName??s.name,s.tags,s.workspaceLabel??null,s.workspaceRoot??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.baseName??t.name,t.tags,t.workspaceLabel??null,t.workspaceRoot??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.workspaceRoot=t.workspaceRoot??null,e.state.baseName=t.baseName??t.name,e.state.dependsOn=this.config.depends?.[t.baseName??t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r,s=null,o=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:r,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[e]??[],workspaceLabel:s,workspaceRoot:o,baseName:e,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}resolveByCwd(t,e){let s=[...this.entries.values()].filter(a=>a.state.name===t||(a.state.baseName??a.state.name)===t);e&&(s=s.filter(a=>{let l=a.app.workspaceRoot;return l?$t(l,e)||$t(e,l):!1}));let o=s.map(a=>({name:a.state.name,baseName:a.state.baseName??a.state.name,workspaceLabel:a.state.workspaceLabel,workspaceRoot:a.state.workspaceRoot??a.app.workspaceRoot??null}));return s.length===0?{kind:"none",candidates:o}:s.length>1?{kind:"collision",candidates:o}:{kind:"unique",key:s[0].state.name,candidates:o}}pruneOldErrors(t=Date.now()){let e=this.config.errorRetention?.maxAgeMs??864e5,r=0;for(let s of this.entries.values())for(let[o,a]of s.state.errors)t-a.lastSeen>e&&(s.state.errors.delete(o),r++);return r}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let r=e.state,s=r.startedAt&&(r.status==="serving"||r.status==="compiling"||r.status==="starting")?Date.now()-r.startedAt:null,a=this.config.overrides?.[t]?.url||e.resolvedUrl||r.announcedUrl||(r.port?`http://127.0.0.1:${r.port}`:null),l;for(let c=this.eventBuffer.length-1;c>=0;c--){let u=this.eventBuffer[c];if(u.app===t&&u.type==="status"){l=Date.now()-u.ts;break}}let i;if(r.status==="compiling"&&r.compileStartedAt&&r.compileHistory.length>=3){let c=r.compileHistory.slice(-10).slice().sort((p,m)=>p-m),u=c[Math.floor((c.length-1)*.5)];u>0&&(i=r.compileStartedAt+u)}return{name:r.name,status:r.status,port:r.port,url:a,errorCount:[...r.errors.values()].reduce((c,u)=>{let p=u.level??"error";return c+(p==="error"?u.count:0)},0),warningCount:[...r.errors.values()].reduce((c,u)=>c+(u.level==="warning"?u.count:0),0),lintCount:[...r.errors.values()].reduce((c,u)=>c+(u.level==="lint"?u.count:0),0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,workspaceRoot:r.workspaceRoot,baseName:r.baseName??r.name,lastChangeMs:l,estimatedReadyAtMs:i}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,o)=>o.lastSeen-s.lastSeen):null}logs(t,e={}){let r=this.getState(t);if(!r)return null;let s=r.logBuffer;if(e.sinceMs&&e.sinceMs>0){let o=Date.now()-e.sinceMs;s=s.filter(a=>a.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(r=>r.ts>=e&&(!t.app||r.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>to&&this.eventBuffer.splice(0,this.eventBuffer.length-to),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let r=this.entries.get(t);if(!r)return;let s=r.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let o=s.health;s.health=e,e==="healthy"&&(r.prevHealthyAt=Date.now(),r.cascadeArmed&&(r.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from: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 r=this.getState(t);r&&r.lastHealthError!==e&&(r.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let r=this.entries.get(t);r&&r.resolvedUrl!==e&&(r.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let r=this.getState(t);r&&(r.cachedProbeHost=e)}setStale(t,e){let r=this.getState(t);r&&r.stale!==e&&(r.stale=e,this.emit("change"))}setSessionOverride(t,e){let r=this.getState(t);r&&(r.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let r=this.getState(t);r&&(r.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let r=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(g){return e.state.status="error",e.state.lastStatusMessage=g.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:g.message}),this.emit("change"),{ok:!1,status:"error",error:g.message}}if(!await Bt(s)){let g=Je(s),S=zr(s,g);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=S,this.recordEvent({app:t,type:"status",from:r,to:"error",message:S}),this.emit("change"),{ok:!1,status:"error",error:S}}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 en(t,this.config.logs));let a=e.state.sessionOverrides,l=this.config.envFiles?.[t]??[],i={};if(l.length){let g=e.state.activeEnvFile;(!g||!Zn(e.app.workspaceRoot,[g]).length)&&(g=Zn(e.app.workspaceRoot,l)[0]??null,g&&(e.state.activeEnvFile=g)),g&&(i=Gs(Qn(e.app.workspaceRoot,g)))}let c={...i,...this.config.overrides?.[t]?.env??{},...a?.env??{}},u=Ks(),p=zs(c,u),m=new tn({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:a?.command,onStateChange:()=>this.emit("change"),onStatusChange:(g,S,x)=>{this.recordEvent({app:t,type:"status",from:g,to:S,message:x}),(S==="stopped"||S==="error")&&(g==="serving"||g==="compiling")&&this.armCascade(t)},onErrorRecorded:(g,S)=>{let x=g.level??"error",T;x==="lint"?T=S?"lint-new":"lint-recur":x==="warning"?T=S?"warning-new":"warning-recur":T=S?"error-new":"error-recur",this.recordEvent({app:t,type:T,message:g.message})},onExit:(g,S,x)=>this.emit("childExit",{name:t,code:g,signal:S,stopping:x}),onLogLine:g=>{e.logger?.write(g),this.emit("log",{name:t,ts:Date.now(),line:g})},onCompile:g=>{this.history?.recordCompile(t,g);let S=this.getState(t),x=e.lastBundleInitialKB;if(S.bundle&&S.bundle.initialKB>0){if(x&&x>0){let T=(S.bundle.initialKB-x)/x*100;S.bundleRegressionPct=Math.round(T*10)/10;let w=Qs(x,S.bundle.initialKB,1.1);if(w){this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${S.bundleRegressionPct}% (${x}->${S.bundle.initialKB})`});let E=tr(e.app.workspaceRoot);this.recordEvent({app:t,type:"regression-detected",message:JSON.stringify({...w,suspectCommit:E})})}}else S.bundleRegressionPct=null;e.lastBundleInitialKB=S.bundle.initialKB}this.checkCompileRegression(t,g),this.emit("compile",{name:t,ms:g})},onBundleUpdate:()=>{let g=this.getState(t);g?.bundle&&(g.bundle.initialKB>0||g.bundle.lazyKB>0)&&this.history?.recordBundle(t,g.bundle.initialKB,g.bundle.lazyKB,g.bundle.files.length),this.emit("bundleUpdate",{name:t})}});return e.proc=m,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),m.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let r=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==r&&this.recordEvent({app:t,type:"status",from:r,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let r=Be(this.config.depends??{},t).filter(l=>this.entries.has(l)),s=Ue(this.config.depends??{},r),o=[],a=e.waitMs??6e4;for(let l of s){let i=await Promise.all(l.map(u=>this.start(u)));for(let u=0;u<l.length;u++){let p=i[u];if(!p.ok)return o.push({name:l[u],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:o}}let c=await Promise.all(l.map(u=>this.waitFor(u,"healthy",a)));for(let u=0;u<l.length;u++){let p=c[u],m=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(o.push({name:p.name,status:p.status,health:p.health,error:m?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!m)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=qr(this.config.depends??{},t);for(let r of e){let s=this.getState(r);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(r)}}async stopAll(t=3e3){let e=[];for(let r of this.entries.values())r.proc?.isRunning()&&e.push(r.proc.stop());for(let r of this.watchTasks.values())e.push(r.stop());await Promise.race([Promise.all(e),new Promise(r=>setTimeout(r,t))]);for(let r of this.entries.values())r.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,r=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:r});let s=this.getApp(t);if(!s)return{error:"unknown app"};let o=await Us(s,e,r);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,r=[]){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 a=Hs(s,e,r);return this.watchTasks.set(o,a),a.child.on("exit",()=>this.watchTasks.delete(o)),{ok:!0,pid:a.pid}}async stopWatchTask(t,e){let r=`${t}::${e}`,s=this.watchTasks.get(r);return s?(await s.stop(),this.watchTasks.delete(r),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let r of this.watchTasks.values())t&&r.app!==t||e.push({app:r.app,task:r.task,pid:r.pid,startedAt:r.startedAt});return e}checkCompileRegression(t,e){let r=this.history;if(!r)return;let o=r.queryCompiles({app:t,limit:21}).filter(c=>c.ms!==e).slice(0,20).map(c=>c.ms),a=Vs(o,e,2);if(!a)return;this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs baseline ${(a.baseline/1e3).toFixed(1)}s (\xD7${a.factor})`});let l=this.getApp(t),i=tr(l?.workspaceRoot??null);this.recordEvent({app:t,type:"regression-detected",message:JSON.stringify({...a,suspectCommit:i})})}watchTaskLogs(t,e,r){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let o=s.logs;return r?o.slice(-r):[...o]}waitFor(t,e,r){return new Promise(s=>{let o=Date.now(),a=this.entries.get(t),l=()=>{if(!a)return!0;let p=a.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"},i=p=>{this.off("change",c),clearTimeout(u);let m=a?.state;s({name:t,status:m?.status??"unknown",health:m?.health??"unknown",timedOut:p,waitedMs:Date.now()-o})},c=()=>{l()&&i(!1)};if(l()){s({name:t,status:a.state.status,health:a.state.health,timedOut:!1,waitedMs:0});return}let u=setTimeout(()=>i(!0),r);this.on("change",c)})}}});import rr from"node:fs";import no from"node:path";import $c from"node:os";function Mc(){try{let n=rr.readFileSync(sr,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function _c(n){nr=n,!er&&(er=setTimeout(()=>{er=null;let t=nr;if(nr=null,!!t)try{rr.mkdirSync(no.dirname(sr),{recursive:!0}),rr.writeFileSync(sr,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
62
|
+
`)}},500))}var sr,er,nr,rn,ro=H(()=>{"use strict";sr=no.join($c.homedir(),".daimon","cursors.json");er=null,nr=null;rn=class{data=Mc();getErrorCursor(t,e){return this.data.errors[`${t}:${e}`]??0}setErrorCursor(t,e,r){this.data.errors[`${t}:${e}`]=r,_c(this.data)}}});import so from"node:fs";import Dc from"node:os";import oo from"node:path";function Lc(n){let t={};for(let[e,r]of Object.entries(n))typeof r=="string"&&(t[e]=jc.test(e)?"***":r);return t}function or(n,t){let e=n.summary(t);if(!e)return null;let r=n.getState(t),s=n.getApp(t),o=n.getConfig(),a=o.overrides?.[t]??{},l={...process.env,...s.env??{},...r.sessionOverrides?.env??{}},i=n.getHistory(),c=i?i.queryEvents({app:t,limit:50}):[],u=i?i.queryBundles({app:t,limit:100}):[],p=i?i.querySelfMetrics({limit:60}):[];return{takenAt:new Date().toISOString(),summary:e,logs:r.logBuffer.slice(-500).map(m=>({ts:m.ts,line:m.line})),errors:[...r.errors.entries()].map(([m,g])=>({hash:m,message:g.message,count:g.count,firstSeen:g.firstSeen,lastSeen:g.lastSeen})),env:Lc(l),configSlice:{command:r.sessionOverrides?.command??a.command??s.command,port:r.sessionOverrides?.port??a.port??null,workspaceRoot:s.workspaceRoot,workspaceType:s.workspaceType,tags:s.tags,depends:o.depends?.[t]??[],envFiles:o.envFiles?.[t]??[]},events:c,bundles:u,selfMetrics:p}}function io(n,t){let e=or(n,t);if(!e)return null;let r=oo.join(Dc.homedir(),".daimon","snapshots");so.mkdirSync(r,{recursive:!0});let s=e.takenAt.replace(/[:.]/g,"-"),o=oo.join(r,`${t}-${s}.json`);return so.writeFileSync(o,JSON.stringify(e,null,2)),{path:o,payload:e}}var jc,ao=H(()=>{"use strict";jc=/key|secret|token|password|api[-_]?key/i});import sn from"node:fs";import co from"node:path";function lo(n){let t=0;try{let e=sn.readdirSync(n,{withFileTypes:!0});for(let r of e){let s=co.join(n,r.name);try{r.isDirectory()?t+=lo(s):r.isFile()&&(t+=sn.statSync(s).size)}catch{}}}catch{}return t}function ir(n,t,e){let r=n.getApp(t);if(!r)return null;let s=n.getState(t),o=s?s.status==="serving"||s.status==="compiling"||s.status==="starting":!1,l=[...Ic,...e?Fc:[]].map(i=>{let c=co.join(r.workspaceRoot,i),u=sn.existsSync(c);return{path:c,exists:u,sizeBytes:u?lo(c):0}});return{app:t,workspace:r.workspaceRoot,targets:l,ranOnServing:o}}function uo(n,t,e){let r=ir(n,t,e);if(!r)return{error:"unknown app"};if(r.ranOnServing)return{error:"app is currently running; stop it first"};let s=[],o=[];for(let a of r.targets)if(a.exists)try{sn.rmSync(a.path,{recursive:!0,force:!0}),s.push(a.path)}catch(l){o.push({path:a.path,error:l?.message||String(l)})}return{ok:o.length===0,removed:s,failed:o}}var Ic,Fc,po=H(()=>{"use strict";Ic=["dist",".angular/cache","tmp","out-tsc"],Fc=["node_modules"]});function $e(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}function fo(n){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=n.list();for(let r of e)for(let s of Bc)t.push(`daimon_app_status{name="${$e(r.name)}",status="${s}"} ${r.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 r of e)r.lastCompileMs!=null&&t.push(`daimon_compile_seconds{name="${$e(r.name)}"} ${(r.lastCompileMs/1e3).toFixed(3)}`);t.push("# HELP daimon_error_total cumulative deduped error count"),t.push("# TYPE daimon_error_total counter");for(let r of e)t.push(`daimon_error_total{name="${$e(r.name)}"} ${r.errorCount}`);t.push("# HELP daimon_cpu_percent app CPU percent"),t.push("# TYPE daimon_cpu_percent gauge");for(let r of e)r.cpu!=null&&t.push(`daimon_cpu_percent{name="${$e(r.name)}"} ${r.cpu}`);t.push("# HELP daimon_mem_mb app resident memory MB"),t.push("# TYPE daimon_mem_mb gauge");for(let r of e)r.memMB!=null&&t.push(`daimon_mem_mb{name="${$e(r.name)}"} ${r.memMB}`);return t.join(`
|
|
61
63
|
`)+`
|
|
62
|
-
`}var
|
|
63
|
-
`;try{
|
|
64
|
-
`,"utf8");let o=
|
|
65
|
-
`,"utf8");let
|
|
66
|
-
`,"utf8");let i=ct();if(i)try{fetch(`http://127.0.0.1:${i.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`wrote healthProbePath to overrides in ${r} for: ${o.join(", ")}; triggered soft-reload. To undo: edit ${r}.`}async function qc(n){let t={ran:[],skipped:[],errors:[]};for(let e of lo){if(!n.permitted.includes(e))continue;let r=Wc[e],s;try{s=await r.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(n.dryRun){t.ran.push({name:e,detected:!0,description:`(dry-run) would fix: ${s.description}`});continue}try{let o=await r.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 lo,Wc,pe=U(()=>{"use strict";Pt();ee();Ie();xe();qt();Vn();lo=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root","health-probe-missing"];Wc={"orphan-daemon":{detect:Pc,fix:Cc},"stale-lock":{detect:Rc,fix:Ec},"missing-search-root":{detect:Ac,fix:Oc},"corrupt-history-db":{detect:Nc,fix:$c},"port-conflict-pred":{detect:Mc,fix:jc},"node-version-mismatch":{detect:_c,fix:Dc},"orphan-node-modules":{detect:uo,fix:Ic},"orphan-venv":{detect:po,fix:Fc},"orphan-bundler-cache":{detect:fo,fix:Bc},"orphan-cargo-target":{detect:mo,fix:Uc},"dead-search-root":{detect:ho,fix:Hc},"health-probe-missing":{detect:go,fix:Jc}}});var Qn={};kt(Qn,{orchestrateProfile:()=>Kc});function yo(n,t,e,r,s){let o=n.summary(t);if(!o)return!1;if(e==="serving")return o.status==="serving";if(e==="healthy")return o.status==="serving"&&o.health==="healthy";let i=Date.now()-r;return o.status==="serving"&&o.health==="healthy"&&i>=s}async function wo(n,t,e,r,s){let o=Date.now();if(e!=="stable"){let c=await n.waitFor(t,e==="serving"?"serving":"healthy",r);return{reached:!c.timedOut,waitedMs:c.waitedMs}}let i=Date.now(),a=c=>{c?.app===t&&(i=Date.now())};n.on("event",a);try{for(;Date.now()-o<r;){if(yo(n,t,e,i,s))return{reached:!0,waitedMs:Date.now()-o};await new Promise(c=>setTimeout(c,500))}return{reached:yo(n,t,e,i,s),waitedMs:Date.now()-o}}finally{n.off("event",a)}}async function Kc(n,t,e){let r=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let o=s.filter(y=>n.summary(y)!=null),i=Array.from(new Set(o.flatMap(y=>De(t.depends??{},y)))).filter(y=>n.summary(y)!=null),a=Le(t.depends??{},i),c=[];for(let y of i){let b=n.summary(y);b&&(e.goal==="serving"&&b.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&b.status==="serving"&&b.health==="healthy")&&c.push(y)}if(e.dryRun){let y=i.filter(b=>!c.includes(b));return{profile:e.profile,goal:e.goal,perApp:y.map(b=>({name:b,reached:!1,tries:0})),totalMs:Date.now()-r,allReached:y.length===0,dryRun:!0,plannedOrder:a,alreadyHealthy:c}}let l=Math.max(5e3,Math.floor(e.timeoutMs/2)),u=e.stableMs??5e3,d=new Map;for(let y of i)d.set(y,{name:y,reached:!1,tries:0});for(let y of a)await Promise.all(y.map(async b=>{let N=n.summary(b);if(!N){d.set(b,{name:b,reached:!1,tries:0,error:"unknown app"});return}if(c.includes(b)){d.set(b,{name:b,reached:!0,tries:0});return}N.status!=="starting"&&N.status!=="compiling"&&N.status!=="serving"&&await n.start(b)})),await Promise.all(y.map(async b=>{if(d.get(b)?.reached)return;let N=await wo(n,b,e.goal,l,u),p=d.get(b);p.tries=1,p.waitedMs=N.waitedMs,p.reached=N.reached,d.set(b,p)}));let f=[...d.values()].filter(y=>!y.reached);if(f.length>0){let{runAutoFix:y,ALL_AUTO_FIX:b}=await Promise.resolve().then(()=>(pe(),ue)),N=t.doctor?.autoFix?.permitted??b,p=Math.max(5e3,e.timeoutMs-(Date.now()-r)),m=Math.max(5e3,Math.floor(p/Math.max(f.length,1))),h={ran:[]};try{h=await y({permitted:N,dryRun:!1})}catch{}let k=(h.ran??[]).map(T=>T.name);await Promise.all(f.map(async T=>{let P=d.get(T.name);P.tries=2;try{let w=await n.restart(T.name);w?.ok||(P.error=w?.error??"restart failed")}catch(w){P.error=w?.message??String(w)}let v=await wo(n,T.name,e.goal,m,u);if(P.waitedMs=(P.waitedMs??0)+v.waitedMs,P.reached=v.reached,!P.reached){let w=n.errors(T.name)??[];P.stillFailing=w.slice(0,3).map(E=>({file:E.parsed?.file??null,line:E.parsed?.line??null,code:E.parsed?.code??null,tool:E.parsed?.tool??null,message:E.parsed?.message??E.message}))}P.fixed=k,d.set(T.name,P)}))}let g=[...d.values()],C=g.every(y=>y.reached),R={profile:e.profile,goal:e.goal,perApp:g,totalMs:Date.now()-r,allReached:C};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let y=e.budgetTokens,b=0,N=0;for(let p of g)if(p.stillFailing){let m=p.stillFailing.length*Gc;m>y?(b+=p.stillFailing.length,delete p.stillFailing):y-=m}for(;y<0||g.length*Xc>Math.max(y,e.budgetTokens/4);){let p=g.findIndex(m=>m.reached);if(p===-1)break;g.splice(p,1),N++}(b||N)&&(R._meta={omitted:{}},b&&(R._meta.omitted.stillFailing=b),N&&(R._meta.omitted.perApp=N))}return R}var Gc,Xc,tr=U(()=>{"use strict";ke();Gc=60,Xc=25});import zc from"node:http";import Yc from"node:crypto";import Lt from"node:fs";import ht from"node:path";import{fileURLToPath as Vc}from"node:url";function er(){let n=[ht.resolve(rn,"dashboard","browser"),ht.resolve(rn,"dashboard"),ht.resolve(rn,"..","dist","dashboard","browser"),ht.resolve(rn,"..","dist","dashboard")];for(let t of n)if(Lt.existsSync(ht.join(t,"index.html")))return t;return null}function Re(n,t){try{if(!Lt.statSync(t).isFile())return!1;let r=ht.extname(t).toLowerCase(),s=Qc[r]??"application/octet-stream",o=Lt.readFileSync(t);return n.writeHead(200,{"content-type":s,"content-length":o.length,"cache-control":r===".html"?"no-cache":"public, max-age=3600"}),n.end(o),!0}catch{return!1}}function x(n,t,e){let r=JSON.stringify(e);n.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(r)}),n.end(r)}function fe(n){if(!n)return;let t=n.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 sn(n,t){let e=(n.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function tl(n){return{name:n.name,status:n.status,port:n.port,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null}}function de(n){return{name:n.name,status:n.status,port:n.port,url:n.url,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null,uptime:n.uptimeMs}}function nr(n){let t=n.parsed,e=n.level??"error";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??n.message,level:e}:{file:null,line:null,col:null,code:null,message:n.message,level:e}}function bo(n){if(!n)return{};if(/^\d{10,}$/.test(n))return{sinceTs:Number(n)};let t=fe(n);return t!=null?{sinceMs:t}:{}}function nl(n){let t=JSON.parse(JSON.stringify(n));if(t.apiToken&&(t.apiToken="***"),t.overrides&&typeof t.overrides=="object")for(let e of Object.keys(t.overrides)){let r=t.overrides[e]?.env;if(r&&typeof r=="object")for(let s of Object.keys(r))el.test(s)&&(r[s]="***")}return t}function rr(n){if(!n)return"";try{let t=Lt.readFileSync(n);return Yc.createHash("sha1").update(t).digest("hex")}catch{return""}}function vo(n,t,e={}){let r=new Ve,s=zc.createServer(async(o,i)=>{try{let a=new URL(o.url||"/","http://127.0.0.1"),c=o.method||"GET",l=a.pathname.replace(/\/$/,"").split("/").filter(Boolean),u=()=>{let m=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!m)return!0;let h=o.headers.authorization;return typeof h=="string"&&h.toLowerCase().startsWith("bearer ")&&h.slice(7).trim()===m?!0:(x(i,401,{error:"unauthorized"}),!1)};if(c==="POST"&&a.pathname==="/api/shutdown"){if(!u())return;x(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(c==="GET"){let p=e.getConfig(),m=rr(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:m}),i.end(JSON.stringify({etag:m,config:nl(p)}));return}if(c==="PATCH"&&e.patchConfig){if(!u())return;let p=o.headers["if-match"]?.trim(),m=rr(e.configPath);if(!p||p!==m){x(i,412,{error:"etag mismatch",current:m});return}let h={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(P=>{let v=[];o.on("data",w=>v.push(w)),o.on("end",()=>{try{h=JSON.parse(Buffer.concat(v).toString("utf8"))}catch{}P()})});let k=e.patchConfig(h);if(!k.ok){x(i,400,{error:k.error});return}let T=rr(e.configPath);try{let P=o.socket.remoteAddress||"127.0.0.1",v=o.headers["x-daimon-cwd"]||null;Zs(P,h,h,k.applied,v)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:T}),i.end(JSON.stringify({etag:T,applied:k.applied,addedApps:k.addedApps,removedApps:k.removedApps,restartRequired:k.restartRequired}));return}x(i,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&c==="GET"){x(i,200,eo());return}if(a.pathname==="/api/self"&&c==="GET"){if(!e.selfMetrics){x(i,503,{error:"self-metrics collector not attached"});return}x(i,200,e.selfMetrics.snapshot());return}if(a.pathname==="/api/plugins"&&c==="GET"){let p=e.getPlugins?e.getPlugins():[];x(i,200,p.map(m=>({name:m.name,description:m.description??null,file:m.file,status:m.status,error:m.error??null,findings:m.lastFindings??[]})));return}if(a.pathname==="/api/plugins/scan"&&c==="POST"){if(!u())return;if(!e.runPluginScans){x(i,503,{error:"plug-in scan not available"});return}try{await e.runPluginScans()}catch(m){x(i,500,{error:m?.message||String(m)});return}let p=e.getPlugins?e.getPlugins():[];x(i,200,p);return}if(a.pathname==="/api/self/history"&&c==="GET"){let p=bo(a.searchParams.get("since")),m=p.sinceMs??3600*1e3,h=p.sinceTs??Date.now()-m,k=n.getHistory(),T=k?k.querySelfMetrics({since:h,limit:1440}):[];x(i,200,T);return}if(a.pathname==="/api/snapshot-state"&&c==="POST"){if(!u())return;let p=oo(n);x(i,200,{ok:!0,path:p});return}if(a.pathname==="/api/config/reload"&&c==="POST"&&e.reloadConfig){if(!u())return;try{let p=await e.reloadConfig();x(i,200,p)}catch(p){x(i,400,{error:p?.message||String(p)})}return}if(a.pathname==="/api/workspaces"&&c==="GET"&&e.getConfig){let p=e.getConfig(),m=n.list(),h=p.searchRoots.map(k=>{let T=typeof k=="string"?k:k.path,P=typeof k=="string"?null:k.label??null,v=m.filter(w=>{let E=w.workspaceRoot;return!!E&&Ct(E,T)});return{path:T,label:P,appCount:v.length,apps:v.map(w=>w.name)}});x(i,200,h);return}if(a.pathname==="/api/workspaces/resolve"&&c==="GET"&&e.getConfig){let p=a.searchParams.get("cwd");if(!p){x(i,400,{error:"cwd query param required"});return}let k=e.getConfig().searchRoots.map(T=>typeof T=="string"?{path:T,label:null}:{path:T.path,label:T.label??null}).find(T=>Ct(p,T.path));if(!k){x(i,404,{error:"no workspace covers cwd",cwd:p});return}x(i,200,{path:k.path,label:k.label,cwd:p});return}if(a.pathname==="/api/workspaces/remove"&&c==="POST"&&e.getConfig&&e.patchConfig){if(!u())return;let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(w=>{let E=[];o.on("data",S=>E.push(S)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(E).toString("utf8"))}catch{}w()})});let m=typeof p?.path=="string"?p.path:"";if(!m){x(i,400,{error:"path is required"});return}let h=e.getConfig(),k=w=>typeof w=="string"?w:w.path,T=h.searchRoots.map(k),P=h.searchRoots.filter(w=>k(w)!==m);if(P.length===T.length){x(i,404,{error:`not a registered searchRoot: ${m}`});return}let v=e.patchConfig({searchRoots:P});if(!v.ok){x(i,400,{error:v.error});return}x(i,200,{removed:m,removedApps:v.removedApps??[]});return}if(a.pathname==="/api/workspaces/ensure"&&c==="POST"&&e.getConfig&&e.patchConfig){if(!u())return;let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(S=>{let O=[];o.on("data",I=>O.push(I)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(O).toString("utf8"))}catch{}S()})});let m=typeof p?.path=="string"?p.path:"",h=typeof p?.label=="string"&&p.label?p.label:null;if(!m){x(i,400,{error:"path is required"});return}if(!Lt.existsSync(m)){x(i,400,{error:`path does not exist: ${m}`});return}let k=e.getConfig(),T=k.searchRoots.map(S=>typeof S=="string"?S:S.path);if(T.some(S=>Ct(m,S))){let S=T.find(O=>Ct(m,O));x(i,200,{added:!1,root:S,reason:"already covered"});return}let v=h?{path:m,label:h}:m,w=[...k.searchRoots,v],E=e.patchConfig({searchRoots:w});if(!E.ok){x(i,400,{error:E.error});return}x(i,200,{added:!0,root:m,label:h,addedApps:E.addedApps??[]});return}if(c==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let p=zs(n);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(p)}),i.end(p);return}if(c!=="GET"&&a.pathname.startsWith("/api/")&&a.pathname!=="/api/shutdown"&&a.pathname!=="/api/config"&&a.pathname!=="/api/config/reload"&&!u())return;if(c==="GET"&&a.pathname==="/"){let p=er();if(p&&Re(i,ht.join(p,"index.html")))return;i.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(l[0]==="api"&&l[1]==="events"&&l.length===2){if(c!=="GET"){x(i,405,{error:"method not allowed"});return}let p=fe(a.searchParams.get("since")),m=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let T=n.events({sinceMs:p,app:m});for(let w of T)i.write(JSON.stringify(w)+`
|
|
67
|
-
`);let P=
|
|
68
|
-
`)};n.on("event",P);let
|
|
69
|
-
`)}catch{}},3e4);o.on("close",()=>{n.off("event",P),clearInterval(v);try{i.end()}catch{}});return}let h=n.events({sinceMs:p,app:m}),k=n.getHistory();if(k&&p&&h.length<500){let T=Date.now()-p,P=k.queryEvents({app:m,since:T,limit:1e3}),v=new Set(h.map(w=>`${w.ts}|${w.app}|${w.type}|${w.from??""}|${w.to??""}|${w.message??""}`));for(let w of P){let E=`${w.ts}|${w.app}|${w.type}|${w.from_state??""}|${w.to_state??""}|${w.message??""}`;v.has(E)||h.push({ts:w.ts,app:w.app,type:w.type,from:w.from_state??void 0,to:w.to_state??void 0,message:w.message??void 0})}h.sort((w,E)=>w.ts-E.ts)}x(i,200,h);return}if(l[0]==="api"&&l[1]==="session"){if(l[2]==="record"&&c==="POST"){let p=a.searchParams.get("action")||"toggle";if(p==="start"||p==="toggle"&&!n.sessionRecorder.isRecording()){let m=n.sessionRecorder.start();x(i,200,{recording:!0,path:m.path});return}if(p==="stop"||p==="toggle"&&n.sessionRecorder.isRecording()){let m=n.sessionRecorder.stop();x(i,200,{recording:!1,path:m.path});return}x(i,400,{error:"invalid action"});return}if(l[2]==="status"&&c==="GET"){x(i,200,{recording:n.sessionRecorder.isRecording()});return}x(i,404,{error:"not found"});return}if(l[0]==="api"&&l[1]==="history"){if(c!=="GET"){x(i,405,{error:"method not allowed"});return}let p=n.getHistory();if(!p){x(i,200,[]);return}let m=l[2],h=a.searchParams.get("app")||void 0,k=a.searchParams.get("since"),T=a.searchParams.get("until"),P=a.searchParams.get("limit"),v=k?/^\d{10,}$/.test(k)?Number(k):Date.now()-(fe(k)??0):void 0,w=T?/^\d{10,}$/.test(T)?Number(T):Date.now()-(fe(T)??0):void 0,E=P?Number(P):void 0;if(m==="events"){x(i,200,p.queryEvents({app:h,since:v,until:w,type:a.searchParams.get("type")||void 0,limit:E}));return}if(m==="compile-times"){x(i,200,p.queryCompiles({app:h,since:v,until:w,limit:E}));return}if(m==="tasks"){x(i,200,p.queryTasks({app:h,task:a.searchParams.get("task")||void 0,since:v,limit:E}));return}if(m==="timeline"){let S=a.searchParams.get("kinds"),O=S?new Set(S.split(",").map(X=>X.trim()).filter(Boolean)):void 0,I=p.queryTimeline({app:h,since:v,kinds:O,limit:E??5e3});x(i,200,I);return}if(m==="bundles"){x(i,200,p.queryBundles({app:h,since:v,until:w,limit:E}));return}if(m==="trends"){let S=(a.searchParams.get("since")||"24h").toLowerCase(),O={"24h":24*3600*1e3,"7d":7*86400*1e3,"30d":30*86400*1e3},I=O[S]??O["24h"],X=S==="24h"?3600*1e3:86400*1e3,j=a.searchParams.get("metrics");if(j){let wt=j.split(",").map(tt=>tt.trim()).filter(Boolean),Z=["compile","bundle","errors","restarts"],Ne=wt.filter(tt=>Z.includes(tt));if(!Ne.length){x(i,400,{error:"metrics must include at least one of compile|bundle|errors|restarts"});return}let ve={};for(let tt of Ne){let $e=p.trends({app:h,metric:tt,sinceMs:I,bucketMs:X});ve[tt]={points:$e.points,count:$e.count}}x(i,200,{app:h??null,since:S,metrics:ve,_meta:{aggregation:S==="24h"?"hour":"day"}});return}let W=a.searchParams.get("metric")||"compile";if(!["compile","bundle","errors","restarts"].includes(W)){x(i,400,{error:"metric must be compile|bundle|errors|restarts"});return}let{points:Q,count:J}=p.trends({app:h,metric:W,sinceMs:I,bucketMs:X});x(i,200,{app:h??null,metric:W,since:S,points:Q,_meta:{aggregation:S==="24h"?"hour":"day",count:J}});return}if(m==="summary"&&l.length>=4){let S=decodeURIComponent(l[3]);x(i,200,p.summary(S));return}if(m==="why"&&l.length>=4){let S=decodeURIComponent(l[3]);x(i,200,p.why(S));return}x(i,404,{error:"not found"});return}if(l[0]==="api"&&l[1]==="profiles"&&l[3]==="ensure-up"&&c==="POST"){let p=decodeURIComponent(l[2]),m=e.getConfig?.(),h=m?.profiles?.[p];if(!h){x(i,404,{error:"unknown profile"});return}let k=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(k)){x(i,400,{error:"until must be serving|healthy"});return}let T=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),P=T?Number(T):3e5;(!Number.isFinite(P)||P<=0)&&(P=3e5),P=Math.min(P,12e5);let v=m?.healthProbe?.enabled??!0,w=k==="healthy"&&!v?"serving":k,E=Date.now();for(let O of h){let I=n.summary(O);I&&I.status!=="serving"&&I.status!=="starting"&&I.status!=="compiling"&&await n.startWithDeps(O)}let S=await Promise.all(h.map(async O=>{let I=Math.max(1e3,P-(Date.now()-E));if(!n.summary(O))return{name:O,state:null,until:w,reachedTargetMs:null,timedOut:!1,error:"unknown"};let j=await n.waitFor(O,w,I),W=n.summary(O);return{name:O,state:W?de(W):null,until:w,reachedTargetMs:j.timedOut?null:j.waitedMs,timedOut:j.timedOut}}));x(i,200,{profile:p,apps:S,_meta:{totalMs:Date.now()-E,until:w}});return}if(l[0]==="api"&&l[1]==="orchestrate"&&c==="POST"){let p=e.getConfig?.();if(!p){x(i,500,{error:"no config loaded"});return}let m=a.searchParams.get("profile");if(!m){x(i,400,{error:"profile query param required"});return}let h=(a.searchParams.get("goal")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(h)){x(i,400,{error:"goal must be serving|healthy|stable"});return}let k=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),T=k?Number(k):3e5;(!Number.isFinite(T)||T<=0)&&(T=3e5),T=Math.min(T,12e5);let P=a.searchParams.get("dryRun")==="true"||a.searchParams.get("dry-run")==="true",v=a.searchParams.get("budget"),w=v&&Number.isFinite(Number(v))?Number(v):void 0,{orchestrateProfile:E}=await Promise.resolve().then(()=>(tr(),Qn)),S=await E(n,p,{profile:m,goal:h,timeoutMs:T,dryRun:P,budgetTokens:w});if(S.error){x(i,404,S);return}x(i,200,S);return}if(l[0]==="api"&&l[1]==="discovery"&&l[2]==="explain"&&c==="GET"){let p=e.getConfig?.();if(!p){x(i,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:m}=await Promise.resolve().then(()=>(qt(),En)),h={scanned:0,rejected:{}},k=[],T=m(p,{warnings:k,stats:h}),P=p.searchRoots.map(S=>typeof S=="string"?S:S.path),v=T.filter(S=>S.workspaceType==="polyglot"),w=T.map(S=>({name:S.name,workspaceType:S.workspaceType,serverProfile:S.serverProfile??S.workspaceType,workspaceRoot:S.workspaceRoot})),E=v.length>0?` \xB7 ${v.length} polyglot app${v.length===1?"":"s"} found (${[...new Set(v.map(S=>S.serverProfile))].join(", ")})`:"";x(i,200,{searchRoots:P,scanned:h.scanned,rejected:h.rejected,warnings:k,appsFound:T.length,apps:w,suggestion:T.length===0?P.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook / manage.py / Gemfile / pyproject.toml (fastapi) / .air.toml / Trunk.toml.":`${T.length} apps discovered${E}`});return}if(l[0]==="api"&&l[1]==="doctor"&&l[2]==="auto-fix"&&c==="POST"){if(!u())return;let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(v=>{let w=[];o.on("data",E=>w.push(E)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}v()})});let{runAutoFix:m,ALL_AUTO_FIX:h}=await Promise.resolve().then(()=>(pe(),ue)),T=e.getConfig?.()?.doctor?.autoFix?.permitted??h,P=Array.isArray(p.permitted)&&p.permitted.length?p.permitted:T;try{let v=await m({permitted:P,dryRun:!!p.dryRun});x(i,200,v)}catch(v){x(i,500,{error:v?.message??String(v)})}return}if(l[0]==="api"&&l[1]==="overview"&&c==="GET"){let p=e.getConfig?.(),m=n.list(),h=a.searchParams.get("workspace"),k=a.searchParams.get("profile"),T=m;if(h&&(T=T.filter(j=>j.workspaceLabel===h)),k){let j=p?.profiles?.[k]??null;j&&(T=T.filter(W=>j.includes(W.name)))}let P={apps:T.length,serving:T.filter(j=>j.status==="serving").length,errors:T.filter(j=>j.status==="error").length,stopped:T.filter(j=>j.status==="stopped").length,totalErrCount:T.reduce((j,W)=>j+W.errorCount,0),totalCpuPct:Math.round(T.reduce((j,W)=>j+(W.cpu??0),0)*10)/10,totalMemMb:Math.round(T.reduce((j,W)=>j+(W.memMB??0),0))},v={};for(let j of T)(v[j.status]??=[]).push(j.name);let w=T.filter(j=>j.status==="error"||j.errorCount>0).map(j=>{let W=n.errors(j.name)??[],Q=W[W.length-1],J=Q?.parsed;return{name:j.name,status:j.status,errCount:j.errorCount,firstError:J?{file:J.file??null,line:J.line??null,code:J.code??null,message:J.message??Q?.message??""}:Q?{file:null,line:null,code:null,message:Q.message}:null}}),E=Date.now()-5*6e4,S=n.events({sinceMs:5*6e4}).filter(j=>j.type==="status"&&j.ts>=E).filter(j=>h?T.some(W=>W.name===j.app):!0).filter(j=>k?T.some(W=>W.name===j.app):!0).slice(-5).map(j=>({name:j.app,transition:`${j.from??"?"}\u2192${j.to??"?"}`,msAgo:Date.now()-j.ts})),O={ts:Date.now(),version:st,totals:P,byStatus:v,needsAttention:w,recentlyChanged:S};P.apps===0&&(O._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let I=a.searchParams.get("budget"),X=I?Math.max(64,Number(I)|0):null;if(X){let j=X*4,W=0,Q=0;for(;JSON.stringify(O).length>j&&(O.needsAttention.length||O.recentlyChanged.length);)if(O.needsAttention.length>1)O.needsAttention.pop(),W++;else if(O.recentlyChanged.length)O.recentlyChanged.pop(),Q++;else if(O.needsAttention.length===1)O.needsAttention.pop(),W++;else break;W||Q?O._meta={...O._meta??{},budget:X,omitted:{needsAttention:W,recentlyChanged:Q}}:O._meta={...O._meta??{},budget:X}}x(i,200,O);return}if(l[0]!=="api"||l[1]!=="apps"){if(c==="GET"&&!a.pathname.startsWith("/metrics")){let p=er();if(p){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let h=ht.resolve(p,m);if(h.startsWith(p)&&Re(i,h))return}if(!ht.extname(m||"")&&Re(i,ht.join(p,"index.html")))return}}x(i,404,{error:"not found"});return}if(l.length===2){if(c!=="GET"){x(i,405,{error:"method not allowed"});return}let p=sn(a,e.getConfig),m=n.list(),h=a.searchParams.get("cwd"),k=h&&h.length>0?h:null;k&&(m=m.filter(P=>{let v=n.getApp(P.name);return v?Ct(v.workspaceRoot,k)||Ct(k,v.workspaceRoot):!1}));let T=p==="full"?m:m.map(tl);if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let P of T)i.write(JSON.stringify(P)+`
|
|
70
|
-
`);i.end();return}if(
|
|
64
|
+
`}var Bc,mo=H(()=>{"use strict";Bc=["stopped","starting","compiling","serving","error"]});import Me from"node:fs";import Uc from"node:crypto";import ho from"node:path";function Jc(){return ho.join(bt(),"audit.log")}function Wc(n){try{if(Me.statSync(n).size>Hc){let e=n+".1";try{Me.unlinkSync(e)}catch{}Me.renameSync(n,e)}}catch{}}function go(n,t,e,r,s=null,o=null){let a=Jc();Me.mkdirSync(ho.dirname(a),{recursive:!0}),Wc(a);let l=JSON.stringify({prev:t,next:e}),i=Uc.createHash("sha1").update(l).digest("hex").slice(0,12),c=`${new Date().toISOString()} ${n} ${i} ${r.join(",")} ${s??""} ${o??""}
|
|
65
|
+
`;try{Me.appendFileSync(a,c)}catch{}}var Hc,yo=H(()=>{"use strict";Nt();Hc=1e6});import on from"node:fs";import an from"node:path";import{fileURLToPath as qc}from"node:url";function Gc(){let n=[an.resolve(wo,"templates","presets"),an.resolve(wo,"..","src","templates","presets")];for(let t of n)if(on.existsSync(t))return t;return n[0]}function bo(){let n=Gc();if(!on.existsSync(n))return[];let t=on.readdirSync(n).filter(r=>r.endsWith(".json")),e=[];for(let r of t)try{let s=on.readFileSync(an.join(n,r),"utf8");s.charCodeAt(0)===65279&&(s=s.slice(1)),e.push(JSON.parse(s))}catch{}return e}var wo,vo=H(()=>{"use strict";wo=an.dirname(qc(import.meta.url))});import cn from"node:fs";import So from"node:path";function ko(){return So.join(bt(),"state-handoff.json")}function xo(n){let t=[];for(let s of n.names()){let o=n.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},r=ko();return cn.mkdirSync(So.dirname(r),{recursive:!0}),cn.writeFileSync(r,JSON.stringify(e)),r}function To(n=6e4){let t=ko();try{let e=cn.readFileSync(t,"utf8"),r=JSON.parse(e);return cn.unlinkSync(t),!r||typeof r.ts!="number"||Date.now()-r.ts>n?null:r}catch{return null}}var ar=H(()=>{"use strict";Nt()});function ln(n){return n?Xc[n]??null:null}function Co(n){return n===200||n===301||n===302||n===304||n===307||n===308||n===401}function Ro(n){return n?n==="ECONNREFUSED"||n==="ECONNRESET"||n==="EHOSTUNREACH":!1}var Xc,cr=H(()=>{"use strict";Xc={django:"/admin/login/",rails:"/up",fastapi:"/docs","go-air":"/","rust-trunk":"/"}});var be={};Ct(be,{ALL_AUTO_FIX:()=>Po,runAutoFix:()=>ml});import J from"node:fs";import nt from"node:path";function Kc(){let n=mt();if(!n)return{detected:!1,description:"no daemon running"};let t=process.cwd(),e=nt.join(t,"daimon.config.json");if(!J.existsSync(e))return{detected:!1,description:"no local daimon.config.json in cwd"};let r=n.cwd,s=n.configPath,o=r&&nt.resolve(r)===nt.resolve(t),a=s&&nt.resolve(s)===nt.resolve(e);return o||a?{detected:!1,description:"daemon already running from this cwd/config"}:{detected:!0,description:`daemon (pid ${n.pid}) is running from ${r??"(unknown)"} but local daimon.config.json exists at ${t}`,lockCwd:r}}async function zc(){let n=mt();if(!n)return"no daemon running; nothing to do";try{await fetch(`http://127.0.0.1:${n.apiPort}/api/snapshot-state`,{method:"POST"})}catch{}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST"})}catch{}return await te(n.pid,5e3),Ot(),`respawned daemon at pid ${(await Wt({})).pid} from ${process.cwd()}; previous pid ${n.pid} (cwd ${n.cwd??"unknown"}) was shut down with state handoff. To undo: stop with 'daimon daemon stop' and start from the prior directory.`}function Yc(){let n;try{n=J.readFileSync(Xe(),"utf8")}catch{return{detected:!1,description:"no lock file present"}}let t;try{t=JSON.parse(n)}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 Vc(){let n="(unknown)";try{let e=JSON.parse(J.readFileSync(Xe(),"utf8"));n=String(e?.pid??"?")}catch{}Ot();let t=await Wt({});return`removed stale ${Xe()} (prior pid ${n} was dead); spawned fresh daemon at pid ${t.pid}.`}function Qc(){let n=process.cwd(),e=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs","vite.config.cjs",".storybook"].filter(a=>J.existsSync(nt.join(n,a)));if(!e.length)return{detected:!1,description:"no nx.json/angular.json/vite.config.*/.storybook in cwd"};let r=ft();return r.kind!=="loaded"?{detected:!0,description:`${e.join(", ")} present but no config is loaded`,markerFiles:e}:r.config.searchRoots.map(a=>nt.resolve(typeof a=="string"?a:a.path)).some(a=>n.startsWith(a))?{detected:!1,description:`${e.join(", ")} present and a configured searchRoot covers ${n}`}:{detected:!0,description:`${e.join(", ")} present in ${n} but no searchRoot covers it`,markerFiles:e}}function Zc(){let n=process.cwd(),{local:t,user:e}=Ft(),r=J.existsSync(t)?t:e,s={};try{s=JSON.parse(J.readFileSync(r,"utf8"))}catch{}if(s.searchRoots=Array.isArray(s.searchRoots)?s.searchRoots:[],!s.searchRoots.some(a=>(typeof a=="string"?a:a?.path)===n)){let a;try{let l=JSON.parse(J.readFileSync(nt.join(n,"package.json"),"utf8"));typeof l.name=="string"&&(a=l.name)}catch{}s.searchRoots.push(a?{path:n,label:a}:n)}J.mkdirSync(nt.dirname(r),{recursive:!0}),J.writeFileSync(r,JSON.stringify(s,null,2)+`
|
|
66
|
+
`,"utf8");let o=mt();if(o)try{fetch(`http://127.0.0.1:${o.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`appended ${n} as a searchRoot in ${r}; triggered soft-reload of the running daemon.`}function tl(){let n=ft();if(n.kind!=="loaded"||!n.config.history.enabled)return{detected:!1,description:"history disabled"};let t=n.config.history.path;if(!J.existsSync(t))return{detected:!1,description:"history db does not exist (will be created on next start)"};try{let e=new Lt(n.config.history),r=e.quickCheck();return e.close(),r?{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 el(){let n=ft();if(n.kind!=="loaded")return"no config; cannot determine history path";let t=n.config.history.path,e=`${t}.corrupt-${Date.now()}`;for(let r of["","-wal","-shm"])try{J.renameSync(t+r,e+r)}catch{}return`rotated ${t} \u2192 ${e} (and -wal/-shm siblings). The daemon will rebuild an empty history db on next start.`}async function nl(){let n=ft();if(n.kind!=="loaded")return{detected:!1,description:"no config loaded"};let[t,e]=n.config.portRange??[4200,4299],r=n.config.overrides??{},s=Object.values(r).map(l=>l.port).filter(l=>typeof l=="number"),o=Array.from(new Set([...s,t,e])),a=[];for(let l of o)if(!(!Number.isFinite(l)||l<=0))try{await Bt(l)||a.push(l)}catch{}return a.length?{detected:!0,description:`ports already LISTEN: ${a.join(", ")} (range ${t}-${e} + pinned overrides)`,conflicts:a}:{detected:!1,description:`all checked ports free (range ${t}-${e} + pinned)`}}function rl(){return"no automated fix \u2014 predictive rule only. Run `daimon free-port <port>` to inspect the holder, or pick a different port in daimon.config.json. To undo: nothing was changed."}function sl(){let n=process.cwd(),t=process.versions.node,e=nt.join(n,".nvmrc");if(J.existsSync(e)){let s=J.readFileSync(e,"utf8").trim().replace(/^v/i,"");if(s&&!t.startsWith(s))return{detected:!0,description:`.nvmrc requires ${s}, running ${t}`,expected:s,actual:t}}let r=nt.join(n,"package.json");if(J.existsSync(r))try{let o=JSON.parse(J.readFileSync(r,"utf8"))?.engines?.node;if(typeof o=="string"&&o.trim()){let a=o.match(/(\d+)(?:\.(\d+))?/);if(a){let l=Number(a[1]),i=Number(t.split(".")[0]);if(Number.isFinite(l)&&Number.isFinite(i)&&i<l)return{detected:!0,description:`package.json engines.node = "${o}" but running ${t}`,expected:o,actual:t}}}}catch{}return{detected:!1,description:`node ${t} satisfies .nvmrc / engines.node (or neither is present)`}}function ol(){return"no automated fix \u2014 switching Node versions touches the user environment. Run `nvm use` (or your version manager equivalent) in this directory, then re-run daimon. To undo: nothing was changed."}function il(){let n=ft();if(n.kind!=="loaded")return[];let t=[],e=new Set;for(let r of n.config.searchRoots){let s=typeof r=="string"?r:r.path;if(!s||!J.existsSync(s)||e.has(s))continue;e.add(s);let o=nt.join(s,"package.json");if(!J.existsSync(o))continue;let a=null;for(let l of["package-lock.json","pnpm-lock.yaml","yarn.lock"]){let i=nt.join(s,l);if(J.existsSync(i)){a=i;break}}t.push({name:nt.basename(s),root:s,pkgPath:o,lockPath:a,nmPath:nt.join(s,"node_modules")})}return t}function Ao(){let n=il();if(!n.length)return{detected:!1,description:"no searchRoots with package.json found"};let t=[];for(let r of n){if(!J.existsSync(r.nmPath)){t.push({root:r.root,reason:"missing"});continue}if(r.lockPath)try{let s=J.statSync(r.lockPath).mtimeMs,o=J.statSync(r.nmPath).mtimeMs;s>o+1e3&&t.push({root:r.root,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`node_modules issues \u2014 ${t.map(r=>`${r.reason}: ${r.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every searchRoot package.json has a fresh node_modules"}}function al(){let n=Ao();return!n.detected||!n.entries?"nothing to suggest":`would suggest: ${n.entries.map(e=>`(cd "${e.root}" && npm install)`).join(" && ")}. Daimon does not run package managers on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function lr(){let n=ft();if(n.kind!=="loaded")return[];let t=[],e=new Set;for(let r of n.config.searchRoots){let s=typeof r=="string"?r:r?.path;!s||!J.existsSync(s)||e.has(s)||(e.add(s),t.push(s))}return t}function Eo(){let n=lr();if(!n.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let r of n){let s=nt.join(r,"pyproject.toml"),o=nt.join(r,"requirements.txt"),a=nt.join(r,"manage.py");if(!(J.existsSync(s)||J.existsSync(o)||J.existsSync(a)))continue;let i=[".venv","venv","env"].map(u=>nt.join(r,u)).find(u=>J.existsSync(u));if(!i){t.push({root:r,reason:"missing"});continue}let c=[];for(let u of[s,o])if(J.existsSync(u))try{c.push(J.statSync(u).mtimeMs)}catch{}if(c.length)try{let u=J.statSync(i).mtimeMs;Math.max(...c)>u+1e3&&t.push({root:r,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`venv issues \u2014 ${t.map(r=>`${r.reason}: ${r.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Python searchRoot has a fresh venv (or no Python markers)"}}function cl(){let n=Eo();return!n.detected||!n.entries?"nothing to suggest":`would suggest: ${n.entries.map(e=>`(cd "${e.root}" && python -m venv .venv && .venv/Scripts/pip install -r requirements.txt)`).join(" && ")}. Daimon does not run pip on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function Oo(){let n=lr();if(!n.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let r of n){let s=nt.join(r,"Gemfile");if(!J.existsSync(s))continue;let o=nt.join(r,"Gemfile.lock"),a=nt.join(r,"vendor","bundle"),l=nt.join(r,".bundle"),i=J.existsSync(a)?a:J.existsSync(l)?l:null;if(!i){t.push({root:r,reason:"missing"});continue}if(J.existsSync(o))try{let c=J.statSync(o).mtimeMs,u=J.statSync(i).mtimeMs;c>u+1e3&&t.push({root:r,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`bundler cache issues \u2014 ${t.map(r=>`${r.reason}: ${r.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Ruby searchRoot has a fresh bundle cache (or no Gemfile)"}}function ll(){let n=Oo();return!n.detected||!n.entries?"nothing to suggest":`would suggest: ${n.entries.map(e=>`(cd "${e.root}" && bundle install)`).join(" && ")}. Daimon does not run bundle install on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function No(){let n=lr();if(!n.length)return{detected:!1,description:"no searchRoots resolved on disk"};let t=[];for(let r of n){let s=nt.join(r,"Cargo.toml");if(!J.existsSync(s))continue;let o=nt.join(r,"Cargo.lock"),a=nt.join(r,"target");if(!J.existsSync(a)){t.push({root:r,reason:"missing"});continue}if(J.existsSync(o))try{let l=J.statSync(o).mtimeMs,i=J.statSync(a).mtimeMs;l>i+1e3&&t.push({root:r,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`cargo target issues \u2014 ${t.map(r=>`${r.reason}: ${r.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every Rust searchRoot has a fresh target/ (or no Cargo.toml)"}}function ul(){let n=No();return!n.detected||!n.entries?"nothing to suggest":`would suggest: ${n.entries.map(e=>`(cd "${e.root}" && cargo build)`).join(" && ")}. Daimon does not run cargo on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function $o(){let n=ft();if(n.kind!=="loaded")return{detected:!1,description:"no config loaded"};let t=[];for(let e of n.config.searchRoots){let r=typeof e=="string"?e:e.path;r&&(J.existsSync(r)||t.push(r))}return t.length?{detected:!0,description:`searchRoots no longer on disk: ${t.join(", ")}`,dead:t}:{detected:!1,description:"every configured searchRoot resolves on disk"}}function pl(){let n=$o();if(!n.detected||!n.dead||!n.dead.length)return"nothing to remove";let{local:t,user:e}=Ft(),r=J.existsSync(t)?t:e,s={};try{s=JSON.parse(J.readFileSync(r,"utf8"))}catch{}if(!Array.isArray(s.searchRoots))return"config has no searchRoots array; nothing removed";let o=new Set(n.dead),a=s.searchRoots.length;s.searchRoots=s.searchRoots.filter(c=>{let u=typeof c=="string"?c:c?.path;return!o.has(u)});let l=a-s.searchRoots.length;J.writeFileSync(r,JSON.stringify(s,null,2)+`
|
|
67
|
+
`,"utf8");let i=mt();if(i)try{fetch(`http://127.0.0.1:${i.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${l} dead searchRoot entr${l===1?"y":"ies"} from ${r} (${[...o].join(", ")}); triggered soft-reload. To undo: edit ${r} and re-add the path(s).`}function Mo(){let n=ft();if(n.kind!=="loaded")return{detected:!1,description:"no config loaded"};let t=jt(n.config,{}),e=n.config.overrides??{},r=[];for(let o of t){if(!o.serverProfile)continue;let a=o.baseName??o.name;if(e[o.name]?.healthProbePath??e[a]?.healthProbePath)continue;let i=ln(o.serverProfile);!i||i==="/"||r.push({name:o.name,profile:o.serverProfile,path:i})}return r.length?{detected:!0,description:`apps missing a profile-aware health probe path: ${r.map(o=>`${o.name} (${o.profile} \u2192 ${o.path})`).join(" \xB7 ")}`,entries:r}:{detected:!1,description:"every app with a known framework profile already has a probe path resolved"}}function dl(){let n=Mo();if(!n.detected||!n.entries)return"nothing to set";let{local:t,user:e}=Ft(),r=J.existsSync(t)?t:e,s={};try{s=JSON.parse(J.readFileSync(r,"utf8"))}catch{}(!s.overrides||typeof s.overrides!="object")&&(s.overrides={});let o=[];for(let l of n.entries)(!s.overrides[l.name]||typeof s.overrides[l.name]!="object")&&(s.overrides[l.name]={}),!s.overrides[l.name].healthProbePath&&(s.overrides[l.name].healthProbePath=l.path,o.push(`${l.name} \u2192 ${l.path}`));if(!o.length)return"every detected app already had a healthProbePath in overrides; nothing changed.";J.mkdirSync(nt.dirname(r),{recursive:!0}),J.writeFileSync(r,JSON.stringify(s,null,2)+`
|
|
68
|
+
`,"utf8");let a=mt();if(a)try{fetch(`http://127.0.0.1:${a.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`wrote healthProbePath to overrides in ${r} for: ${o.join(", ")}; triggered soft-reload. To undo: edit ${r}.`}async function ml(n){let t={ran:[],skipped:[],errors:[]};for(let e of Po){if(!n.permitted.includes(e))continue;let r=fl[e],s;try{s=await r.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(n.dryRun){t.ran.push({name:e,detected:!0,description:`(dry-run) would fix: ${s.description}`});continue}try{let o=await r.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 Po,fl,ve=H(()=>{"use strict";Nt();de();He();Ee();Zt();cr();Po=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root","health-probe-missing"];fl={"orphan-daemon":{detect:Kc,fix:zc},"stale-lock":{detect:Yc,fix:Vc},"missing-search-root":{detect:Qc,fix:Zc},"corrupt-history-db":{detect:tl,fix:el},"port-conflict-pred":{detect:nl,fix:rl},"node-version-mismatch":{detect:sl,fix:ol},"orphan-node-modules":{detect:Ao,fix:al},"orphan-venv":{detect:Eo,fix:cl},"orphan-bundler-cache":{detect:Oo,fix:ll},"orphan-cargo-target":{detect:No,fix:ul},"dead-search-root":{detect:$o,fix:pl},"health-probe-missing":{detect:Mo,fix:dl}}});var ur={};Ct(ur,{orchestrateProfile:()=>yl});function _o(n,t,e,r,s){let o=n.summary(t);if(!o)return!1;if(e==="serving")return o.status==="serving";if(e==="healthy")return o.status==="serving"&&o.health==="healthy";let a=Date.now()-r;return o.status==="serving"&&o.health==="healthy"&&a>=s}async function Do(n,t,e,r,s){let o=Date.now();if(e!=="stable"){let i=await n.waitFor(t,e==="serving"?"serving":"healthy",r);return{reached:!i.timedOut,waitedMs:i.waitedMs}}let a=Date.now(),l=i=>{i?.app===t&&(a=Date.now())};n.on("event",l);try{for(;Date.now()-o<r;){if(_o(n,t,e,a,s))return{reached:!0,waitedMs:Date.now()-o};await new Promise(i=>setTimeout(i,500))}return{reached:_o(n,t,e,a,s),waitedMs:Date.now()-o}}finally{n.off("event",l)}}async function yl(n,t,e){let r=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let o=s.filter(T=>n.summary(T)!=null),a=Array.from(new Set(o.flatMap(T=>Be(t.depends??{},T)))).filter(T=>n.summary(T)!=null),l=Ue(t.depends??{},a),i=[];for(let T of a){let w=n.summary(T);w&&(e.goal==="serving"&&w.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&w.status==="serving"&&w.health==="healthy")&&i.push(T)}if(e.dryRun){let T=a.filter(w=>!i.includes(w));return{profile:e.profile,goal:e.goal,perApp:T.map(w=>({name:w,reached:!1,tries:0})),totalMs:Date.now()-r,allReached:T.length===0,dryRun:!0,plannedOrder:l,alreadyHealthy:i}}let c=Math.max(5e3,Math.floor(e.timeoutMs/2)),u=e.stableMs??5e3,p=new Map;for(let T of a)p.set(T,{name:T,reached:!1,tries:0});for(let T of l)await Promise.all(T.map(async w=>{let E=n.summary(w);if(!E){p.set(w,{name:w,reached:!1,tries:0,error:"unknown app"});return}if(i.includes(w)){p.set(w,{name:w,reached:!0,tries:0});return}E.status!=="starting"&&E.status!=="compiling"&&E.status!=="serving"&&await n.start(w)})),await Promise.all(T.map(async w=>{if(p.get(w)?.reached)return;let E=await Do(n,w,e.goal,c,u),B=p.get(w);B.tries=1,B.waitedMs=E.waitedMs,B.reached=E.reached,p.set(w,B)}));let m=[...p.values()].filter(T=>!T.reached);if(m.length>0){let{runAutoFix:T,ALL_AUTO_FIX:w}=await Promise.resolve().then(()=>(ve(),be)),E=t.doctor?.autoFix?.permitted??w,B=Math.max(5e3,e.timeoutMs-(Date.now()-r)),Q=Math.max(5e3,Math.floor(B/Math.max(m.length,1))),k={ran:[]};try{k=await T({permitted:E,dryRun:!1})}catch{}let ot=(k.ran??[]).map(et=>et.name);await Promise.all(m.map(async et=>{let j=p.get(et.name);j.tries=2;try{let f=await n.restart(et.name);f?.ok||(j.error=f?.error??"restart failed")}catch(f){j.error=f?.message??String(f)}let d=await Do(n,et.name,e.goal,Q,u);if(j.waitedMs=(j.waitedMs??0)+d.waitedMs,j.reached=d.reached,!j.reached){let f=n.errors(et.name)??[];j.stillFailing=f.slice(0,3).map(h=>({file:h.parsed?.file??null,line:h.parsed?.line??null,code:h.parsed?.code??null,tool:h.parsed?.tool??null,message:h.parsed?.message??h.message}))}j.fixed=ot,p.set(et.name,j)}))}let g=[...p.values()],S=g.every(T=>T.reached),x={profile:e.profile,goal:e.goal,perApp:g,totalMs:Date.now()-r,allReached:S};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let T=e.budgetTokens,w=0,E=0;for(let B of g)if(B.stillFailing){let Q=B.stillFailing.length*hl;Q>T?(w+=B.stillFailing.length,delete B.stillFailing):T-=Q}for(;T<0||g.length*gl>Math.max(T,e.budgetTokens/4);){let B=g.findIndex(Q=>Q.reached);if(B===-1)break;g.splice(B,1),E++}(w||E)&&(x._meta={omitted:{}},w&&(x._meta.omitted.stillFailing=w),E&&(x._meta.omitted.perApp=E))}return x}var hl,gl,pr=H(()=>{"use strict";Ae();hl=60,gl=25});import wl from"node:http";import bl from"node:crypto";import qt from"node:fs";import vt from"node:path";import{fileURLToPath as vl}from"node:url";function dr(){let n=[vt.resolve(un,"dashboard","browser"),vt.resolve(un,"dashboard"),vt.resolve(un,"..","dist","dashboard","browser"),vt.resolve(un,"..","dist","dashboard")];for(let t of n)if(qt.existsSync(vt.join(t,"index.html")))return t;return null}function _e(n,t){try{if(!qt.statSync(t).isFile())return!1;let r=vt.extname(t).toLowerCase(),s=kl[r]??"application/octet-stream",o=qt.readFileSync(t);return n.writeHead(200,{"content-type":s,"content-length":o.length,"cache-control":r===".html"?"no-cache":"public, max-age=3600"}),n.end(o),!0}catch{return!1}}function v(n,t,e){let r=JSON.stringify(e);n.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(r)}),n.end(r)}function oe(n){if(!n)return;let t=n.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 pn(n,t){let e=(n.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function xl(n){return{name:n.name,status:n.status,port:n.port,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null}}function Se(n){let t={name:n.name,status:n.status,port:n.port,url:n.url,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null,uptime:n.uptimeMs};return n.estimatedReadyAtMs!=null&&(t.estimatedReadyAtMs=n.estimatedReadyAtMs),t}function fr(n){let t=n.parsed,e=n.level??"error";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??n.message,level:e}:{file:null,line:null,col:null,code:null,message:n.message,level:e}}function jo(n){if(!n)return{};if(/^\d{10,}$/.test(n))return{sinceTs:Number(n)};let t=oe(n);return t!=null?{sinceMs:t}:{}}function Cl(n){let t=JSON.parse(JSON.stringify(n));if(t.apiToken&&(t.apiToken="***"),t.overrides&&typeof t.overrides=="object")for(let e of Object.keys(t.overrides)){let r=t.overrides[e]?.env;if(r&&typeof r=="object")for(let s of Object.keys(r))Tl.test(s)&&(r[s]="***")}return t}function mr(n){if(!n)return"";try{let t=qt.readFileSync(n);return bl.createHash("sha1").update(t).digest("hex")}catch{return""}}function Lo(n,t,e={}){let r=new rn,s=new Ke,o=new ze,a=wl.createServer(async(l,i)=>{try{let c=new URL(l.url||"/","http://127.0.0.1"),u=l.method||"GET",p=c.pathname.replace(/\/$/,"").split("/").filter(Boolean),m=l.headers["x-daimon-agent"]?.trim(),g=l.headers["x-daimon-cwd"]?.trim()||null,S=m&&m.length?m:"unknown";s.touch(S,g);let x=()=>{let f=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!f)return!0;let h=l.headers.authorization;return typeof h=="string"&&h.toLowerCase().startsWith("bearer ")&&h.slice(7).trim()===f?!0:(v(i,401,{error:"unauthorized"}),!1)};if(u==="POST"&&c.pathname==="/api/shutdown"){if(!x())return;v(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(c.pathname==="/api/config"&&e.getConfig){if(u==="GET"){let d=e.getConfig(),f=mr(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:f}),i.end(JSON.stringify({etag:f,config:Cl(d)}));return}if(u==="PATCH"&&e.patchConfig){if(!x())return;let d=l.headers["if-match"]?.trim(),f=mr(e.configPath);if(!d||d!==f){v(i,412,{error:"etag mismatch",current:f});return}let h={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(P=>{let C=[];l.on("data",R=>C.push(R)),l.on("end",()=>{try{h=JSON.parse(Buffer.concat(C).toString("utf8"))}catch{}P()})});let b=e.patchConfig(h);if(!b.ok){v(i,400,{error:b.error});return}let y=mr(e.configPath);try{let P=l.socket.remoteAddress||"127.0.0.1";go(P,h,h,b.applied,g,S==="unknown"?null:S)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:y}),i.end(JSON.stringify({etag:y,applied:b.applied,addedApps:b.addedApps,removedApps:b.removedApps,restartRequired:b.restartRequired}));return}v(i,405,{error:"method not allowed"});return}if(c.pathname==="/api/presets"&&u==="GET"){v(i,200,bo());return}if(c.pathname==="/api/self"&&u==="GET"){if(!e.selfMetrics){v(i,503,{error:"self-metrics collector not attached"});return}v(i,200,e.selfMetrics.snapshot());return}if(c.pathname==="/api/plugins"&&u==="GET"){let d=e.getPlugins?e.getPlugins():[];v(i,200,d.map(f=>({name:f.name,description:f.description??null,file:f.file,status:f.status,error:f.error??null,findings:f.lastFindings??[]})));return}if(c.pathname==="/api/plugins/scan"&&u==="POST"){if(!x())return;if(!e.runPluginScans){v(i,503,{error:"plug-in scan not available"});return}try{await e.runPluginScans()}catch(f){v(i,500,{error:f?.message||String(f)});return}let d=e.getPlugins?e.getPlugins():[];v(i,200,d);return}if(c.pathname==="/api/agents"&&u==="GET"){let d=s.list(),f=o.list(),h={};for(let b of f)h[b.app]={agent:b.agent,lockedAt:b.lockedAt,expiresAt:b.expiresAt};v(i,200,{agents:d,locks:h,self:S==="unknown"?null:S});return}if(c.pathname==="/api/self/history"&&u==="GET"){let d=jo(c.searchParams.get("since")),f=d.sinceMs??3600*1e3,h=d.sinceTs??Date.now()-f,b=n.getHistory(),y=b?b.querySelfMetrics({since:h,limit:1440}):[];v(i,200,y);return}if(c.pathname==="/api/snapshot-state"&&u==="POST"){if(!x())return;let d=xo(n);v(i,200,{ok:!0,path:d});return}if(c.pathname==="/api/config/reload"&&u==="POST"&&e.reloadConfig){if(!x())return;try{let d=await e.reloadConfig();v(i,200,d)}catch(d){v(i,400,{error:d?.message||String(d)})}return}if(c.pathname==="/api/workspaces"&&u==="GET"&&e.getConfig){let d=e.getConfig(),f=n.list(),h=d.searchRoots.map(b=>{let y=typeof b=="string"?b:b.path,P=typeof b=="string"?null:b.label??null,C=f.filter(R=>{let D=R.workspaceRoot;return!!D&&$t(D,y)});return{path:y,label:P,appCount:C.length,apps:C.map(R=>R.name)}});v(i,200,h);return}if(c.pathname==="/api/workspaces/resolve"&&u==="GET"&&e.getConfig){let d=c.searchParams.get("cwd");if(!d){v(i,400,{error:"cwd query param required"});return}let b=e.getConfig().searchRoots.map(y=>typeof y=="string"?{path:y,label:null}:{path:y.path,label:y.label??null}).find(y=>$t(d,y.path));if(!b){v(i,404,{error:"no workspace covers cwd",cwd:d});return}v(i,200,{path:b.path,label:b.label,cwd:d});return}if(c.pathname==="/api/workspaces/remove"&&u==="POST"&&e.getConfig&&e.patchConfig){if(!x())return;let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(R=>{let D=[];l.on("data",O=>D.push(O)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(D).toString("utf8"))}catch{}R()})});let f=typeof d?.path=="string"?d.path:"";if(!f){v(i,400,{error:"path is required"});return}let h=e.getConfig(),b=R=>typeof R=="string"?R:R.path,y=h.searchRoots.map(b),P=h.searchRoots.filter(R=>b(R)!==f);if(P.length===y.length){v(i,404,{error:`not a registered searchRoot: ${f}`});return}let C=e.patchConfig({searchRoots:P});if(!C.ok){v(i,400,{error:C.error});return}v(i,200,{removed:f,removedApps:C.removedApps??[]});return}if(c.pathname==="/api/workspaces/ensure"&&u==="POST"&&e.getConfig&&e.patchConfig){if(!x())return;let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(O=>{let I=[];l.on("data",z=>I.push(z)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(I).toString("utf8"))}catch{}O()})});let f=typeof d?.path=="string"?d.path:"",h=typeof d?.label=="string"&&d.label?d.label:null;if(!f){v(i,400,{error:"path is required"});return}if(!qt.existsSync(f)){v(i,400,{error:`path does not exist: ${f}`});return}let b=e.getConfig(),y=b.searchRoots.map(O=>typeof O=="string"?O:O.path);if(y.some(O=>$t(f,O))){let O=y.find(I=>$t(f,I));v(i,200,{added:!1,root:O,reason:"already covered"});return}let C=h?{path:f,label:h}:f,R=[...b.searchRoots,C],D=e.patchConfig({searchRoots:R});if(!D.ok){v(i,400,{error:D.error});return}v(i,200,{added:!0,root:f,label:h,addedApps:D.addedApps??[]});return}if(u==="GET"&&c.pathname==="/metrics"&&e.metricsEnabled){let d=fo(n);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(d)}),i.end(d);return}if(u!=="GET"&&c.pathname.startsWith("/api/")&&c.pathname!=="/api/shutdown"&&c.pathname!=="/api/config"&&c.pathname!=="/api/config/reload"&&!x())return;if(u==="GET"&&c.pathname==="/"){let d=dr();if(d&&_e(i,vt.join(d,"index.html")))return;i.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(p[0]==="api"&&p[1]==="events"&&p.length===2){if(u!=="GET"){v(i,405,{error:"method not allowed"});return}let d=oe(c.searchParams.get("since")),f=c.searchParams.get("app")||void 0;if(c.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let y=n.events({sinceMs:d,app:f});for(let R of y)i.write(JSON.stringify(R)+`
|
|
69
|
+
`);let P=R=>{f&&R.app!==f||i.write(JSON.stringify(R)+`
|
|
70
|
+
`)};n.on("event",P);let C=setInterval(()=>{try{i.write(`
|
|
71
|
+
`)}catch{}},3e4);l.on("close",()=>{n.off("event",P),clearInterval(C);try{i.end()}catch{}});return}let h=n.events({sinceMs:d,app:f}),b=n.getHistory();if(b&&d&&h.length<500){let y=Date.now()-d,P=b.queryEvents({app:f,since:y,limit:1e3}),C=new Set(h.map(R=>`${R.ts}|${R.app}|${R.type}|${R.from??""}|${R.to??""}|${R.message??""}`));for(let R of P){let D=`${R.ts}|${R.app}|${R.type}|${R.from_state??""}|${R.to_state??""}|${R.message??""}`;C.has(D)||h.push({ts:R.ts,app:R.app,type:R.type,from:R.from_state??void 0,to:R.to_state??void 0,message:R.message??void 0})}h.sort((R,D)=>R.ts-D.ts)}v(i,200,h);return}if(p[0]==="api"&&p[1]==="session"){if(p[2]==="record"&&u==="POST"){let d=c.searchParams.get("action")||"toggle";if(d==="start"||d==="toggle"&&!n.sessionRecorder.isRecording()){let f=n.sessionRecorder.start();v(i,200,{recording:!0,path:f.path});return}if(d==="stop"||d==="toggle"&&n.sessionRecorder.isRecording()){let f=n.sessionRecorder.stop();v(i,200,{recording:!1,path:f.path});return}v(i,400,{error:"invalid action"});return}if(p[2]==="status"&&u==="GET"){v(i,200,{recording:n.sessionRecorder.isRecording()});return}v(i,404,{error:"not found"});return}if(p[0]==="api"&&p[1]==="history"){if(u!=="GET"){v(i,405,{error:"method not allowed"});return}let d=n.getHistory();if(!d){v(i,200,[]);return}let f=p[2],h=c.searchParams.get("app")||void 0,b=c.searchParams.get("since"),y=c.searchParams.get("until"),P=c.searchParams.get("limit"),C=b?/^\d{10,}$/.test(b)?Number(b):Date.now()-(oe(b)??0):void 0,R=y?/^\d{10,}$/.test(y)?Number(y):Date.now()-(oe(y)??0):void 0,D=P?Number(P):void 0;if(f==="events"){v(i,200,d.queryEvents({app:h,since:C,until:R,type:c.searchParams.get("type")||void 0,limit:D}));return}if(f==="compile-times"){v(i,200,d.queryCompiles({app:h,since:C,until:R,limit:D}));return}if(f==="tasks"){v(i,200,d.queryTasks({app:h,task:c.searchParams.get("task")||void 0,since:C,limit:D}));return}if(f==="timeline"){let O=c.searchParams.get("kinds"),I=O?new Set(O.split(",").map(it=>it.trim()).filter(Boolean)):void 0,z=d.queryTimeline({app:h,since:C,kinds:I,limit:D??5e3});v(i,200,z);return}if(f==="bundles"){v(i,200,d.queryBundles({app:h,since:C,until:R,limit:D}));return}if(f==="trends"){let O=(c.searchParams.get("since")||"24h").toLowerCase(),I={"24h":24*3600*1e3,"7d":7*86400*1e3,"30d":30*86400*1e3},z=I[O]??I["24h"],it=O==="24h"?3600*1e3:86400*1e3,L=c.searchParams.get("metrics");if(L){let Tt=L.split(",").map(W=>W.trim()).filter(Boolean),rt=["compile","bundle","errors","restarts"],Re=Tt.filter(W=>rt.includes(W));if(!Re.length){v(i,400,{error:"metrics must include at least one of compile|bundle|errors|restarts"});return}let zt={};for(let W of Re){let At=d.trends({app:h,metric:W,sinceMs:z,bucketMs:it});zt[W]={points:At.points,count:At.count}}v(i,200,{app:h??null,since:O,metrics:zt,_meta:{aggregation:O==="24h"?"hour":"day"}});return}let Y=c.searchParams.get("metric")||"compile";if(!["compile","bundle","errors","restarts"].includes(Y)){v(i,400,{error:"metric must be compile|bundle|errors|restarts"});return}let{points:V,count:K}=d.trends({app:h,metric:Y,sinceMs:z,bucketMs:it});v(i,200,{app:h??null,metric:Y,since:O,points:V,_meta:{aggregation:O==="24h"?"hour":"day",count:K}});return}if(f==="summary"&&p.length>=4){let O=decodeURIComponent(p[3]);v(i,200,d.summary(O));return}if(f==="why"&&p.length>=4){let O=decodeURIComponent(p[3]);v(i,200,d.why(O));return}v(i,404,{error:"not found"});return}if(p[0]==="api"&&p[1]==="profiles"&&p[3]==="ensure-up"&&u==="POST"){let d=decodeURIComponent(p[2]),f=e.getConfig?.(),h=f?.profiles?.[d];if(!h){v(i,404,{error:"unknown profile"});return}let b=(c.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(b)){v(i,400,{error:"until must be serving|healthy"});return}let y=c.searchParams.get("timeoutMs")||c.searchParams.get("timeout"),P=y?Number(y):3e5;(!Number.isFinite(P)||P<=0)&&(P=3e5),P=Math.min(P,12e5);let C=f?.healthProbe?.enabled??!0,R=b==="healthy"&&!C?"serving":b,D=Date.now();for(let I of h){let z=n.summary(I);z&&z.status!=="serving"&&z.status!=="starting"&&z.status!=="compiling"&&await n.startWithDeps(I)}let O=await Promise.all(h.map(async I=>{let z=Math.max(1e3,P-(Date.now()-D));if(!n.summary(I))return{name:I,state:null,until:R,reachedTargetMs:null,timedOut:!1,error:"unknown"};let L=await n.waitFor(I,R,z),Y=n.summary(I);return{name:I,state:Y?Se(Y):null,until:R,reachedTargetMs:L.timedOut?null:L.waitedMs,timedOut:L.timedOut}}));v(i,200,{profile:d,apps:O,_meta:{totalMs:Date.now()-D,until:R}});return}if(p[0]==="api"&&p[1]==="profiles"&&p[2]==="suggest"&&u==="GET"){let d=e.getConfig?.(),f=n.getHistory();if(!f){v(i,200,{suggestions:[],reason:"history disabled"});return}let h=oe(c.searchParams.get("since"))??720*60*6e4,b=Number(c.searchParams.get("minOccurrences")??5)||5,y=f.queryEvents({since:Date.now()-h,type:"status",limit:2e4}),{suggestProfiles:P}=await Promise.resolve().then(()=>(Ln(),Gr)),C=P(y.map(R=>({ts:R.ts,app:R.app,to_state:R.to_state,type:R.type})),{minOccurrences:b,existingProfiles:d?.profiles??{}});v(i,200,{suggestions:C,windowDays:Math.round(h/(1440*6e4))});return}if(p[0]==="api"&&p[1]==="orchestrate"&&u==="POST"){let d=e.getConfig?.();if(!d){v(i,500,{error:"no config loaded"});return}let f=c.searchParams.get("profile");if(!f){v(i,400,{error:"profile query param required"});return}let h=(c.searchParams.get("goal")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(h)){v(i,400,{error:"goal must be serving|healthy|stable"});return}let b=c.searchParams.get("timeoutMs")||c.searchParams.get("timeout"),y=b?Number(b):3e5;(!Number.isFinite(y)||y<=0)&&(y=3e5),y=Math.min(y,12e5);let P=c.searchParams.get("dryRun")==="true"||c.searchParams.get("dry-run")==="true",C=c.searchParams.get("budget"),R=C&&Number.isFinite(Number(C))?Number(C):void 0,{orchestrateProfile:D}=await Promise.resolve().then(()=>(pr(),ur)),O=await D(n,d,{profile:f,goal:h,timeoutMs:y,dryRun:P,budgetTokens:R});if(O.error){v(i,404,O);return}v(i,200,O);return}if(p[0]==="api"&&p[1]==="discovery"&&p[2]==="explain"&&u==="GET"){let d=e.getConfig?.();if(!d){v(i,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:f}=await Promise.resolve().then(()=>(Zt(),Dn)),h={scanned:0,rejected:{}},b=[],y=f(d,{warnings:b,stats:h}),P=d.searchRoots.map(O=>typeof O=="string"?O:O.path),C=y.filter(O=>O.workspaceType==="polyglot"),R=y.map(O=>({name:O.name,workspaceType:O.workspaceType,serverProfile:O.serverProfile??O.workspaceType,workspaceRoot:O.workspaceRoot})),D=C.length>0?` \xB7 ${C.length} polyglot app${C.length===1?"":"s"} found (${[...new Set(C.map(O=>O.serverProfile))].join(", ")})`:"";v(i,200,{searchRoots:P,scanned:h.scanned,rejected:h.rejected,warnings:b,appsFound:y.length,apps:R,suggestion:y.length===0?P.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook / manage.py / Gemfile / pyproject.toml (fastapi) / .air.toml / Trunk.toml.":`${y.length} apps discovered${D}`});return}if(p[0]==="api"&&p[1]==="doctor"&&p[2]==="auto-fix"&&u==="POST"){if(!x())return;let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(C=>{let R=[];l.on("data",D=>R.push(D)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(R).toString("utf8"))}catch{}C()})});let{runAutoFix:f,ALL_AUTO_FIX:h}=await Promise.resolve().then(()=>(ve(),be)),y=e.getConfig?.()?.doctor?.autoFix?.permitted??h,P=Array.isArray(d.permitted)&&d.permitted.length?d.permitted:y;try{let C=await f({permitted:P,dryRun:!!d.dryRun});v(i,200,C)}catch(C){v(i,500,{error:C?.message??String(C)})}return}if(p[0]==="api"&&p[1]==="overview"&&u==="GET"){let d=e.getConfig?.(),f=n.list(),h=c.searchParams.get("workspace"),b=c.searchParams.get("profile"),y=f;if(h&&(y=y.filter(L=>L.workspaceLabel===h)),b){let L=d?.profiles?.[b]??null;L&&(y=y.filter(Y=>L.includes(Y.name)))}let P={apps:y.length,serving:y.filter(L=>L.status==="serving").length,errors:y.filter(L=>L.status==="error").length,stopped:y.filter(L=>L.status==="stopped").length,totalErrCount:y.reduce((L,Y)=>L+Y.errorCount,0),totalCpuPct:Math.round(y.reduce((L,Y)=>L+(Y.cpu??0),0)*10)/10,totalMemMb:Math.round(y.reduce((L,Y)=>L+(Y.memMB??0),0))},C={};for(let L of y)(C[L.status]??=[]).push(L.name);let R=y.filter(L=>L.status==="error"||L.errorCount>0).map(L=>{let Y=n.errors(L.name)??[],V=Y[Y.length-1],K=V?.parsed;return{name:L.name,status:L.status,errCount:L.errorCount,firstError:K?{file:K.file??null,line:K.line??null,code:K.code??null,message:K.message??V?.message??""}:V?{file:null,line:null,code:null,message:V.message}:null}}),D=Date.now()-5*6e4,O=n.events({sinceMs:5*6e4}).filter(L=>L.type==="status"&&L.ts>=D).filter(L=>h?y.some(Y=>Y.name===L.app):!0).filter(L=>b?y.some(Y=>Y.name===L.app):!0).slice(-5).map(L=>({name:L.app,transition:`${L.from??"?"}\u2192${L.to??"?"}`,msAgo:Date.now()-L.ts})),I={ts:Date.now(),version:ut,totals:P,byStatus:C,needsAttention:R,recentlyChanged:O};P.apps===0&&(I._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let z=c.searchParams.get("budget"),it=z?Math.max(64,Number(z)|0):null;if(it){let L=it*4,Y=0,V=0;for(;JSON.stringify(I).length>L&&(I.needsAttention.length||I.recentlyChanged.length);)if(I.needsAttention.length>1)I.needsAttention.pop(),Y++;else if(I.recentlyChanged.length)I.recentlyChanged.pop(),V++;else if(I.needsAttention.length===1)I.needsAttention.pop(),Y++;else break;Y||V?I._meta={...I._meta??{},budget:it,omitted:{needsAttention:Y,recentlyChanged:V}}:I._meta={...I._meta??{},budget:it}}v(i,200,I);return}if(p[0]!=="api"||p[1]!=="apps"){if(u==="GET"&&!c.pathname.startsWith("/metrics")){let d=dr();if(d){let f=c.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let h=vt.resolve(d,f);if(h.startsWith(d)&&_e(i,h))return}if(!vt.extname(f||"")&&_e(i,vt.join(d,"index.html")))return}}v(i,404,{error:"not found"});return}if(p.length===2){if(u!=="GET"){v(i,405,{error:"method not allowed"});return}let d=pn(c,e.getConfig),f=n.list(),h=c.searchParams.get("cwd"),b=h&&h.length>0?h:null;b&&(f=f.filter(P=>{let C=n.getApp(P.name);return C?$t(C.workspaceRoot,b)||$t(b,C.workspaceRoot):!1}));let y=d==="full"?f:f.map(xl);if(c.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let P of y)i.write(JSON.stringify(P)+`
|
|
72
|
+
`);i.end();return}if(c.searchParams.get("explain")==="1"){let P=e.getConfig?.(),C={format:d};if(P){let{discoverApps:R}=await Promise.resolve().then(()=>(Zt(),Dn)),D={scanned:0,rejected:{}},O=[];R(P,{warnings:O,stats:D});let I=P.searchRoots.map(z=>typeof z=="string"?z:z.path);C={format:d,searchRoots:I,scanned:D.scanned,rejected:D.rejected,warnings:O,...b?{cwdScope:b}:{},suggestion:y.length===0?I.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder to add the current cwd.":b?`no apps under cwd '${b}'. Run 'daimon list --all' to see apps from other workspaces, or 'daimon init --auto' to register this dir.`:"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook, then run 'daimon doctor'.":"apps discovered; _meta is informational."}}v(i,200,{apps:y,_meta:C});return}v(i,200,y);return}let T=decodeURIComponent(p[2]),w=p[3],E=p[4],B=c.searchParams.get("cwd")||null,Q=n.resolveByCwd(T,B),k=T;if(Q.kind==="unique"&&Q.key)k=Q.key;else if(Q.kind==="none"&&B){v(i,404,{error:`no app named '${T}' under cwd '${B}'`,hint:"use --all (or omit cwd) to broaden the search, or --workspace <label> to target a specific workspace"});return}else if(Q.kind==="collision"){v(i,412,{error:"name-collision",candidates:Q.candidates,hint:B?"multiple apps under that cwd share this name \u2014 use --workspace <label> to disambiguate":"multiple workspaces share this app name \u2014 pass --cwd or --workspace <label>"});return}if(!w){if(u!=="GET"){v(i,405,{error:"method not allowed"});return}let d=n.summary(k);if(!d){v(i,404,{error:"unknown app"});return}pn(c,e.getConfig)==="full"?v(i,200,{...d,_meta:{format:"full"}}):v(i,200,{...Se(d),_meta:{format:"compact"}});return}let ot=(c.searchParams.get("level")||"error").toLowerCase(),et=d=>{let f=d.level??"error";return ot==="all"?!0:ot==="warning"?f==="warning":ot==="lint"?f==="lint":f==="error"};if(w==="errors"&&E==="since-last"&&u==="GET"){let d=c.searchParams.get("client")||"default",f=r.getErrorCursor(d,k),h=n.errorsSince(k,f);if(h==null){v(i,404,{error:"unknown app"});return}let b=h.filter(et),y=b.reduce((C,R)=>Math.max(C,R.lastSeen),f);y>f&&r.setErrorCursor(d,k,y);let P=pn(c,e.getConfig);v(i,200,P==="full"?b:b.map(fr));return}if(w==="errors"&&!E&&u==="GET"){let d=c.searchParams.get("since"),f=pn(c,e.getConfig);if(d){let{sinceMs:y,sinceTs:P}=jo(d),C=P??(y!=null?Date.now()-y:0),R=n.errorsSince(k,C);if(R==null){v(i,404,{error:"unknown app"});return}let D=R.filter(et);v(i,200,f==="full"?D:D.map(fr));return}let h=n.errors(k);if(h==null){v(i,404,{error:"unknown app"});return}let b=h.filter(et);v(i,200,f==="full"?b:b.map(fr));return}if(w==="logs"&&p[4]==="stream"&&u==="GET"){if(!n.summary(k)){v(i,404,{error:"unknown app"});return}i.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let d=n.logs(k,{tail:50})??[];for(let C of d)i.write(`data: ${JSON.stringify({ts:Date.now(),line:C})}
|
|
71
73
|
|
|
72
|
-
`);let
|
|
74
|
+
`);let f=[],h=0,b=()=>{for(;f.length&&i.write(f.shift()););},y=C=>{C.name===k&&(f.length>=200&&(h++,f.shift()),f.push(`data: ${JSON.stringify({ts:C.ts,line:C.line})}
|
|
73
75
|
|
|
74
|
-
`),
|
|
76
|
+
`),b())};n.on("log",y);let P=setInterval(()=>i.write(`: ping
|
|
75
77
|
|
|
76
|
-
`),3e4);
|
|
77
|
-
`)}catch{}};
|
|
78
|
-
`)}catch{}},3e4),
|
|
79
|
-
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}x(i,200,{pinned:h,app:y,configPath:v,previous:E});return}if(f==="try-fix"&&c==="POST"){let p=n.summary(y);if(!p){x(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){x(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),k=h?Number(h):18e4;(!Number.isFinite(k)||k<=0)&&(k=18e4),k=Math.min(k,6e5);let T={status:p.status,health:p.health,errCount:p.errorCount,firstError:(n.errors(y)??[])[0]?.parsed??null},{runAutoFix:P,ALL_AUTO_FIX:v}=await Promise.resolve().then(()=>(pe(),ue)),E=e.getConfig?.()?.doctor?.autoFix?.permitted??v,S={ran:[],skipped:[],errors:[]};try{S=await P({permitted:E,dryRun:!1})}catch(Z){S.errors.push({name:"auto-fix",error:Z?.message??String(Z)})}let O=(S.ran??[]).map(Z=>Z.name),I=null;try{let Z=await n.restart(y);Z?.ok||(I=Z?.error??"restart failed")}catch(Z){I=Z?.message??String(Z)}let X=await n.waitFor(y,m,k),j=n.summary(y),Q=(n.errors(y)??[]).slice(0,5).map(Z=>({file:Z.parsed?.file??null,line:Z.parsed?.line??null,code:Z.parsed?.code??null,tool:Z.parsed?.tool??null,message:Z.parsed?.message??Z.message})),J=j?{status:j.status,health:j.health,errCount:j.errorCount}:{status:X.status,health:X.health,errCount:0},wt=m==="serving"&&J.status==="serving"||m==="healthy"&&J.status==="serving"&&J.health==="healthy";x(i,200,{before:T,after:J,fixed:O,stillFailing:Q,reached:wt,waitedMs:X.waitedMs,_meta:{autoFix:S,restartErr:I,timedOut:X.timedOut}});return}if(f==="wait"&&c==="GET"){if(!n.summary(y)){x(i,404,{error:"unknown app"});return}let p=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(p)){x(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let m=a.searchParams.get("timeout"),h=m?Number(m):120;(!Number.isFinite(h)||h<=0)&&(h=120),h=Math.min(h,600);let k=await n.waitFor(y,p,h*1e3);x(i,200,k);return}if(f==="ensure"&&c==="POST"){let p=n.summary(y);if(!p){x(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){x(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),k=h?Number(h):18e4;(!Number.isFinite(k)||k<=0)&&(k=18e4),k=Math.min(k,6e5);let T=e.getConfig?.().healthProbe?.enabled??!0,P=m,v;if(P==="healthy"&&!T&&(P="serving",v="no health probe; treated serving as terminal"),P==="serving"&&p.status==="serving"||P==="healthy"&&p.status==="serving"&&p.health==="healthy"){x(i,200,{...de(p),_meta:{format:"compact",startedFromState:null,warning:v,waitedMs:0}});return}let E=p.status;p.status!=="starting"&&p.status!=="compiling"&&await n.start(y);let S=await n.waitFor(y,P,k),O=n.summary(y),I=O?de(O):{name:y,status:S.status,port:null,url:null,health:S.health,errCount:0,lastChangeMs:null,uptime:null};if(S.timedOut){x(i,200,{error:"timeout",state:I,_meta:{format:"compact",startedFromState:E,warning:v,waitedMs:S.waitedMs,timedOut:!0}});return}x(i,200,{...I,_meta:{format:"compact",startedFromState:E,warning:v,waitedMs:S.waitedMs}});return}if(f==="start"&&c==="POST"){if(a.searchParams.get("withDeps")==="1"){let h=await n.startWithDeps(y);x(i,h.ok?200:400,h);return}let m=await n.start(y);x(i,m.ok?200:400,m);return}if(f==="start-with-deps"&&c==="POST"){let p=await n.startWithDeps(y);x(i,p.ok?200:400,p);return}if(f==="tasks"&&c==="GET"&&!g){let p=n.listTasks(y);if(p==null){x(i,404,{error:"unknown app"});return}x(i,200,{tasks:p,watching:n.listWatchTasks(y)});return}if(f==="run"&&g&&c==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(k=>{let T=[];o.on("data",P=>T.push(P)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(T).toString("utf8"))}catch{}k()})});let m=Array.isArray(p.args)?p.args.map(String):[];if(p.watch){let k=n.startWatchTask(y,g,m);x(i,k.ok?200:400,k);return}let h=await n.runTask(y,g,m);if("error"in h){x(i,404,h);return}x(i,200,h);return}if(f==="run-stop"&&g&&c==="POST"){let p=await n.stopWatchTask(y,g);x(i,200,p);return}if(f==="env"&&c==="GET"){let m=n.getConfig().envFiles?.[y]??[],h=n.getState(y);x(i,200,{candidates:m,active:h?.activeEnvFile??null});return}if(f==="env"&&c==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(h=>{let k=[];o.on("data",T=>k.push(T)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(k).toString("utf8"))}catch{}h()})}),n.setActiveEnvFile(y,p.use??null);let m=n.getState(y);x(i,200,{active:m?.activeEnvFile??null});return}if(f==="requests"&&c==="GET"){if(!e.requestLog){x(i,200,[]);return}let p=fe(a.searchParams.get("since"));x(i,200,e.requestLog.requests(y,p));return}if(f==="clean"&&c==="POST"){let p=a.searchParams.get("deep")==="1",m=a.searchParams.get("yes")==="1",h=zn(n,y,p);if(!h){x(i,404,{error:"unknown app"});return}if(h.ranOnServing){x(i,409,{error:"refusing: app is currently running",plan:h});return}if(!m){x(i,200,{plan:h,hint:"pass --yes to delete"});return}let k=Xs(n,y,p);x(i,200,k);return}if(f==="snapshot"&&c==="POST"){if(a.searchParams.get("write")==="1"){let h=Js(n,y);if(!h){x(i,404,{error:"unknown app"});return}x(i,200,{snapshot:h.path});return}let m=Kn(n,y);if(!m){x(i,404,{error:"unknown app"});return}x(i,200,m);return}if(f==="stop"&&c==="POST"){let p=await n.stop(y);x(i,p.ok?200:400,p);return}if(f==="restart"&&c==="POST"){let p=await n.restart(y);x(i,p.ok?200:400,p);return}if(c==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let p=er();if(p){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let h=ht.resolve(p,m);if(h.startsWith(p)&&Re(i,h))return}if(!ht.extname(m||"")&&Re(i,ht.join(p,"index.html")))return}}x(i,404,{error:"not found"})}catch(a){x(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}var Zc,rn,Qc,el,So=U(()=>{"use strict";Bs();Ws();Ks();Ys();Qs();no();Yn();_t();Bn();Zc=Vc(import.meta.url),rn=ht.dirname(Zc);Qc={".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"};el=/key|secret|token|password|pass/i});import rl from"node:http";import sl from"node:https";function ko(n,t,e,r,s){if(t)return[t];let o=n.path||"/",i=n.fallbackHosts&&n.fallbackHosts.length?n.fallbackHosts:["127.0.0.1"];if(n.host||n.scheme){let c=e?on(e):null,l=n.scheme||c?.protocol?.replace(":","")||"http",u=n.host||c?.hostname||(r?i[0]:"127.0.0.1"),d=r??(c?.port?Number(c.port):null);return[xo(l,u,d,o)]}if(e){let c=on(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=>xo("http",c,r,o))}function on(n){try{return new URL(n)}catch{return null}}function xo(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${n}://${s}${o}${r.startsWith("/")?r:"/"+r}`}var ol,il,al,an,To=U(()=>{"use strict";Vn();ol=1e3,il=500,al=["/","/health","/-/health","/api/health","/ready","/healthz"];an=class{constructor(t,e,r){this.registry=t;this.cfg=e;this.fullConfig=r;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let r=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},il);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=this.registry.getApp(t),o=e.baseName??t,i=this.fullConfig?.overrides?.[t]?.healthProbePath??this.fullConfig?.overrides?.[o]?.healthProbePath,a=nn(s?.serverProfile),c=this.cfg;i?c={...this.cfg,path:i}:e.discoveredHealthPath?c={...this.cfg,path:e.discoveredHealthPath}:a&&(this.cfg.path==="/"||!this.cfg.path)&&(c={...this.cfg,path:a});let l=ko(c,r,e.announcedUrl,e.port,e.cachedProbeHost);if(!r&&!i&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),l.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let u=null;for(let f of l){let g=await this.tryProbe(f);if(g.ok){let C=on(f);C&&this.registry.setCachedProbeHost(t,C.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,f),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}u||(u=`${g.error} ${f}`)}let d=this.freshness.get(t);if(d&&!d.retried){d.retried=!0,setTimeout(()=>{this.probe(t)},ol);return}this.registry.setLastHealthError(t,u||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let r of al){let s={...this.cfg,path:r},o=ko(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let i of o)if((await this.tryProbe(i,{strict2xx:!0})).ok){e.discoveredHealthPath=r,this.registry.recordEvent({app:t,type:"health",message:`discovered probe path: ${r} (pin via POST /api/apps/${encodeURIComponent(t)}/health/pin or daimon pin-health ${t} --accept)`});return}}}tryProbe(t,e={}){return new Promise(r=>{let s=!1,o=u=>{s||(s=!0,r(u))},i=t.startsWith("https://"),a=i?sl:rl,c={timeout:this.cfg.timeoutMs};if(i){let d=on(t)?.hostname?.replace(/^\[|\]$/g,"")??"",f=d==="127.0.0.1"||d==="::1"||d==="localhost";c.rejectUnauthorized=f?!1:!!this.cfg.rejectUnauthorized}let l=e.strict2xx?300:500;try{let u=a.get(t,c,d=>{let f=d.statusCode??0;d.resume(),e.strict2xx?f>=200&&f<l?o({ok:!0}):o({ok:!1,error:`http ${f}`}):ao(f)||f>=200&&f<l?o({ok:!0}):o({ok:!1,error:`http ${f}`})});u.on("timeout",()=>u.destroy(new Error("timeout"))),u.on("error",d=>{let f=d?.code||d?.message||"error";co(d?.code)?o({ok:!1,error:`${f} (server not responding)`}):o({ok:!1,error:f})})}catch(u){o({ok:!1,error:u?.message||"throw"})}})}}});import cl from"pidusage";var cn,Po=U(()=>{"use strict";cn=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let r of this.registry.names()){let s=this.registry.getState(r);s?.pid&&t.push({name:r,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:r,pid:s})=>{try{let o=await cl(s),i=this.registry.getState(r);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(r);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}}});var ln,Co=U(()=>{"use strict";ln=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,r,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!r)return;let 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 r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}}});import ir from"node:fs";import Ro from"node:path";import ll from"node:os";function Eo(){try{let n=ir.readFileSync(ar,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function Ao(n){or=n,!sr&&(sr=setTimeout(()=>{sr=null;let t=or;if(or=null,!!t)try{ir.mkdirSync(Ro.dirname(ar),{recursive:!0}),ir.writeFileSync(ar,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
80
|
-
`)}},500))}var
|
|
81
|
-
`;try{
|
|
82
|
-
`))}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,r,s){if(!this.notifier)return;let o=`${t}::${e}`,
|
|
83
|
-
`),this.proxies.delete(t)}),o.listen(r,"127.0.0.1",()=>{this.proxies.set(t,{app:t,proxyPort:r,server:o,buffer:s})})}requests(t,e){let r=this.proxies.get(t);if(!r)return[];if(e){let s=Date.now()-e;return r.buffer.filter(o=>o.ts>=s)}return[...r.buffer]}proxyPortFor(t){return this.proxies.get(t)?.proxyPort??null}}});import
|
|
84
|
-
`),{config:r,raw:e,applied:
|
|
85
|
-
`))}catch{}return s}function
|
|
78
|
+
`),3e4);l.on("close",()=>{n.off("log",y),clearInterval(P)});return}if(w==="logs"&&u==="GET"){let d=c.searchParams.get("tail"),f=c.searchParams.get("since"),h=n.logs(k,{tail:d?Number(d):void 0,sinceMs:oe(f)});if(h==null){v(i,404,{error:"unknown app"});return}v(i,200,{lines:h});return}if(w==="focus"&&u==="POST"){let d=n.summary(k);if(!d){v(i,404,{error:"unknown app"});return}let f=(c.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(f)){v(i,400,{error:"until must be one of serving|healthy|stable"});return}let h=c.searchParams.get("timeoutMs")||c.searchParams.get("timeout"),b=h?Number(h):18e4;(!Number.isFinite(b)||b<=0)&&(b=18e4),b=Math.min(b,6e5);let y=c.searchParams.get("stableMs"),P=y&&Number.isFinite(Number(y))?Math.max(1e3,Number(y)):5e3;i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache",connection:"keep-alive"});let C=K=>{try{i.write(JSON.stringify(K)+`
|
|
79
|
+
`)}catch{}};C({kind:"subscribed",app:k,until:f,ts:Date.now(),state:Se(d)});let R=Date.now(),D=Date.now(),O=!1,I=K=>{if(O)return;O=!0,n.off("event",it),clearInterval(L),clearInterval(Y),clearTimeout(V);let Tt=n.summary(k);C({kind:"done",reason:K,ts:Date.now(),state:Tt?Se(Tt):null,waitedMs:Date.now()-R});try{i.end()}catch{}},z=()=>{let K=n.summary(k);if(!K)return!1;if(f==="serving")return K.status==="serving";if(f==="healthy")return K.status==="serving"&&K.health==="healthy";if(f==="stable"){let Tt=Date.now()-D;return K.status==="serving"&&K.health==="healthy"&&Tt>=P}return!1},it=K=>{if(K.app===k)if(D=Date.now(),K.type==="status")C({kind:"status",from:K.from,to:K.to,ts:K.ts}),f!=="stable"&&z()&&I("reached");else if(K.type==="error-new"||K.type==="error-recur"){let rt=(n.errors(k)??[])[0];rt&&C({kind:"error",message:rt.message,parsed:rt.parsed??null,ts:K.ts})}else K.type==="health"&&(C({kind:"health",from:K.from,to:K.to,ts:K.ts}),f!=="stable"&&z()&&I("reached"))};n.on("event",it);let L=setInterval(()=>{z()&&I("reached")},1e3),Y=setInterval(()=>{try{i.write(`
|
|
80
|
+
`)}catch{}},3e4),V=setTimeout(()=>I("timeout"),b);l.on("close",()=>I("closed")),z()&&I("reached");return}if(w==="health"&&E==="pin"&&u==="POST"){let d=n.getState(k);if(!d){v(i,404,{error:"unknown app"});return}let f={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(O=>{let I=[];l.on("data",z=>I.push(z)),l.on("end",()=>{try{f=JSON.parse(Buffer.concat(I).toString("utf8"))}catch{}O()})});let h=typeof f.path=="string"&&f.path?f.path:d.discoveredHealthPath??null;if(!h){v(i,400,{error:"no path supplied and no discoveredHealthPath on app"});return}let{configLookupPaths:b}=await Promise.resolve().then(()=>(de(),Ur)),{local:y,user:P}=b(),C=qt.existsSync(y)?y:P,R={};try{R=JSON.parse(qt.readFileSync(C,"utf8"))}catch{}(!R.overrides||typeof R.overrides!="object")&&(R.overrides={}),(!R.overrides[k]||typeof R.overrides[k]!="object")&&(R.overrides[k]={});let D=R.overrides[k].healthProbePath??null;if(R.overrides[k].healthProbePath=h,qt.writeFileSync(C,JSON.stringify(R,null,2)+`
|
|
81
|
+
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}v(i,200,{pinned:h,app:k,configPath:C,previous:D});return}if(w==="try-fix"&&u==="POST"){let d=n.summary(k);if(!d){v(i,404,{error:"unknown app"});return}let f=(c.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){v(i,400,{error:"until must be serving|healthy"});return}let h=c.searchParams.get("timeoutMs")||c.searchParams.get("timeout"),b=h?Number(h):18e4;(!Number.isFinite(b)||b<=0)&&(b=18e4),b=Math.min(b,6e5);let y={status:d.status,health:d.health,errCount:d.errorCount,firstError:(n.errors(k)??[])[0]?.parsed??null},{runAutoFix:P,ALL_AUTO_FIX:C}=await Promise.resolve().then(()=>(ve(),be)),D=e.getConfig?.()?.doctor?.autoFix?.permitted??C,O={ran:[],skipped:[],errors:[]};try{O=await P({permitted:D,dryRun:!1})}catch(rt){O.errors.push({name:"auto-fix",error:rt?.message??String(rt)})}let I=(O.ran??[]).map(rt=>rt.name),z=null;try{let rt=await n.restart(k);rt?.ok||(z=rt?.error??"restart failed")}catch(rt){z=rt?.message??String(rt)}let it=await n.waitFor(k,f,b),L=n.summary(k),V=(n.errors(k)??[]).slice(0,5).map(rt=>({file:rt.parsed?.file??null,line:rt.parsed?.line??null,code:rt.parsed?.code??null,tool:rt.parsed?.tool??null,message:rt.parsed?.message??rt.message})),K=L?{status:L.status,health:L.health,errCount:L.errorCount}:{status:it.status,health:it.health,errCount:0},Tt=f==="serving"&&K.status==="serving"||f==="healthy"&&K.status==="serving"&&K.health==="healthy";v(i,200,{before:y,after:K,fixed:I,stillFailing:V,reached:Tt,waitedMs:it.waitedMs,_meta:{autoFix:O,restartErr:z,timedOut:it.timedOut}});return}if(w==="wait"&&u==="GET"){if(!n.summary(k)){v(i,404,{error:"unknown app"});return}let d=(c.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(d)){v(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let f=c.searchParams.get("timeout"),h=f?Number(f):120;(!Number.isFinite(h)||h<=0)&&(h=120),h=Math.min(h,600);let b=await n.waitFor(k,d,h*1e3);v(i,200,b);return}if(w==="ensure"&&u==="POST"){let d=n.summary(k);if(!d){v(i,404,{error:"unknown app"});return}let f=(c.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){v(i,400,{error:"until must be serving|healthy"});return}let h=c.searchParams.get("timeoutMs")||c.searchParams.get("timeout"),b=h?Number(h):18e4;(!Number.isFinite(b)||b<=0)&&(b=18e4),b=Math.min(b,6e5);let y=e.getConfig?.().healthProbe?.enabled??!0,P=f,C;if(P==="healthy"&&!y&&(P="serving",C="no health probe; treated serving as terminal"),P==="serving"&&d.status==="serving"||P==="healthy"&&d.status==="serving"&&d.health==="healthy"){v(i,200,{...Se(d),_meta:{format:"compact",startedFromState:null,warning:C,waitedMs:0}});return}let D=d.status;d.status!=="starting"&&d.status!=="compiling"&&await n.start(k);let O=await n.waitFor(k,P,b),I=n.summary(k),z=I?Se(I):{name:k,status:O.status,port:null,url:null,health:O.health,errCount:0,lastChangeMs:null,uptime:null};if(O.timedOut){v(i,200,{error:"timeout",state:z,_meta:{format:"compact",startedFromState:D,warning:C,waitedMs:O.waitedMs,timedOut:!0}});return}v(i,200,{...z,_meta:{format:"compact",startedFromState:D,warning:C,waitedMs:O.waitedMs}});return}let j=d=>{let f=c.searchParams.get("steal");if(f==="1"||f==="true")return o.steal(k,S,d),!0;let b=o.acquire(k,S,d);return b?(v(i,409,{error:"locked-by-other-agent",agent:b.agent,lockedAt:b.lockedAt,expiresAt:b.expiresAt,hint:"pass ?steal=1 to override, or wait for the lock to expire"}),!1):!0};if(w==="lock"&&u==="GET"){if(!n.summary(k)){v(i,404,{error:"unknown app"});return}let d=o.current(k),f=o.recentInteractions(k,3);v(i,200,{app:k,current:d,recent:f});return}if(w==="handoff"&&u==="POST"){if(!n.summary(k)){v(i,404,{error:"unknown app"});return}let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(y=>{let P=[];l.on("data",C=>P.push(C)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(P).toString("utf8"))}catch{}y()})});let f=typeof d?.to=="string"?d.to.trim():"";if(!f){v(i,400,{error:"body { to: <agentId> } required"});return}let h=o.current(k),b=o.handoff(k,f,S==="unknown"?null:S);v(i,200,{handedOff:k,from:h?.agent??null,to:b.agent,lockedAt:b.lockedAt,expiresAt:b.expiresAt});return}if(w==="start"&&u==="POST"){if(!j("start"))return;if(c.searchParams.get("withDeps")==="1"){let h=await n.startWithDeps(k);v(i,h.ok?200:400,h);return}let f=await n.start(k);v(i,f.ok?200:400,f);return}if(w==="start-with-deps"&&u==="POST"){if(!j("start-with-deps"))return;let d=await n.startWithDeps(k);v(i,d.ok?200:400,d);return}if(w==="tasks"&&u==="GET"&&!E){let d=n.listTasks(k);if(d==null){v(i,404,{error:"unknown app"});return}v(i,200,{tasks:d,watching:n.listWatchTasks(k)});return}if(w==="run"&&E&&u==="POST"){let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(b=>{let y=[];l.on("data",P=>y.push(P)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(y).toString("utf8"))}catch{}b()})});let f=Array.isArray(d.args)?d.args.map(String):[];if(d.watch){let b=n.startWatchTask(k,E,f);v(i,b.ok?200:400,b);return}let h=await n.runTask(k,E,f);if("error"in h){v(i,404,h);return}v(i,200,h);return}if(w==="run-stop"&&E&&u==="POST"){let d=await n.stopWatchTask(k,E);v(i,200,d);return}if(w==="env"&&u==="GET"){let f=n.getConfig().envFiles?.[k]??[],h=n.getState(k);v(i,200,{candidates:f,active:h?.activeEnvFile??null});return}if(w==="env"&&u==="POST"){let d={};l.headers["content-length"]&&l.headers["content-length"]!=="0"&&await new Promise(h=>{let b=[];l.on("data",y=>b.push(y)),l.on("end",()=>{try{d=JSON.parse(Buffer.concat(b).toString("utf8"))}catch{}h()})}),n.setActiveEnvFile(k,d.use??null);let f=n.getState(k);v(i,200,{active:f?.activeEnvFile??null});return}if(w==="requests"&&u==="GET"){if(!e.requestLog){v(i,200,[]);return}let d=oe(c.searchParams.get("since"));v(i,200,e.requestLog.requests(k,d));return}if(w==="clean"&&u==="POST"){let d=c.searchParams.get("deep")==="1",f=c.searchParams.get("yes")==="1",h=ir(n,k,d);if(!h){v(i,404,{error:"unknown app"});return}if(h.ranOnServing){v(i,409,{error:"refusing: app is currently running",plan:h});return}if(!f){v(i,200,{plan:h,hint:"pass --yes to delete"});return}let b=uo(n,k,d);v(i,200,b);return}if(w==="snapshot"&&u==="POST"){if(c.searchParams.get("write")==="1"){let h=io(n,k);if(!h){v(i,404,{error:"unknown app"});return}v(i,200,{snapshot:h.path});return}let f=or(n,k);if(!f){v(i,404,{error:"unknown app"});return}v(i,200,f);return}if(w==="stop"&&u==="POST"){if(!j("stop"))return;let d=await n.stop(k);v(i,d.ok?200:400,d);return}if(w==="restart"&&u==="POST"){if(!j("restart"))return;let d=await n.restart(k);v(i,d.ok?200:400,d);return}if(u==="GET"&&!c.pathname.startsWith("/api/")&&!c.pathname.startsWith("/metrics")){let d=dr();if(d){let f=c.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let h=vt.resolve(d,f);if(h.startsWith(d)&&_e(i,h))return}if(!vt.extname(f||"")&&_e(i,vt.join(d,"index.html")))return}}v(i,404,{error:"not found"})}catch(c){v(i,500,{error:c?.message||String(c)})}});return a.listen(t,"127.0.0.1"),a}var Sl,un,kl,Tl,Io=H(()=>{"use strict";ro();ao();po();mo();yo();vo();ar();Jt();Yn();Wn();Sl=vl(import.meta.url),un=vt.dirname(Sl);kl={".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"};Tl=/key|secret|token|password|pass/i});import Rl from"node:http";import Pl from"node:https";function Fo(n,t,e,r,s){if(t)return[t];let o=n.path||"/",a=n.fallbackHosts&&n.fallbackHosts.length?n.fallbackHosts:["127.0.0.1"];if(n.host||n.scheme){let i=e?dn(e):null,c=n.scheme||i?.protocol?.replace(":","")||"http",u=n.host||i?.hostname||(r?a[0]:"127.0.0.1"),p=r??(i?.port?Number(i.port):null);return[Bo(c,u,p,o)]}if(e){let i=dn(e);if(i)return i.pathname=o,[i.toString()]}let l=[];s&&l.push(s);for(let i of a)l.includes(i)||l.push(i);return l.map(i=>Bo("http",i,r,o))}function dn(n){try{return new URL(n)}catch{return null}}function Bo(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${n}://${s}${o}${r.startsWith("/")?r:"/"+r}`}var Al,El,Ol,fn,Uo=H(()=>{"use strict";cr();Al=1e3,El=500,Ol=["/","/health","/-/health","/api/health","/ready","/healthz"];fn=class{constructor(t,e,r){this.registry=t;this.cfg=e;this.fullConfig=r;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let r=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},El);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=this.registry.getApp(t),o=e.baseName??t,a=this.fullConfig?.overrides?.[t]?.healthProbePath??this.fullConfig?.overrides?.[o]?.healthProbePath,l=ln(s?.serverProfile),i=this.cfg;a?i={...this.cfg,path:a}:e.discoveredHealthPath?i={...this.cfg,path:e.discoveredHealthPath}:l&&(this.cfg.path==="/"||!this.cfg.path)&&(i={...this.cfg,path:l});let c=Fo(i,r,e.announcedUrl,e.port,e.cachedProbeHost);if(!r&&!a&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),c.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let u=null;for(let m of c){let g=await this.tryProbe(m);if(g.ok){let S=dn(m);S&&this.registry.setCachedProbeHost(t,S.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,m),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}u||(u=`${g.error} ${m}`)}let p=this.freshness.get(t);if(p&&!p.retried){p.retried=!0,setTimeout(()=>{this.probe(t)},Al);return}this.registry.setLastHealthError(t,u||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let r of Ol){let s={...this.cfg,path:r},o=Fo(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let a of o)if((await this.tryProbe(a,{strict2xx:!0})).ok){e.discoveredHealthPath=r,this.registry.recordEvent({app:t,type:"health",message:`discovered probe path: ${r} (pin via POST /api/apps/${encodeURIComponent(t)}/health/pin or daimon pin-health ${t} --accept)`});return}}}tryProbe(t,e={}){return new Promise(r=>{let s=!1,o=u=>{s||(s=!0,r(u))},a=t.startsWith("https://"),l=a?Pl:Rl,i={timeout:this.cfg.timeoutMs};if(a){let p=dn(t)?.hostname?.replace(/^\[|\]$/g,"")??"",m=p==="127.0.0.1"||p==="::1"||p==="localhost";i.rejectUnauthorized=m?!1:!!this.cfg.rejectUnauthorized}let c=e.strict2xx?300:500;try{let u=l.get(t,i,p=>{let m=p.statusCode??0;p.resume(),e.strict2xx?m>=200&&m<c?o({ok:!0}):o({ok:!1,error:`http ${m}`}):Co(m)||m>=200&&m<c?o({ok:!0}):o({ok:!1,error:`http ${m}`})});u.on("timeout",()=>u.destroy(new Error("timeout"))),u.on("error",p=>{let m=p?.code||p?.message||"error";Ro(p?.code)?o({ok:!1,error:`${m} (server not responding)`}):o({ok:!1,error:m})})}catch(u){o({ok:!1,error:u?.message||"throw"})}})}}});import Nl from"pidusage";var mn,Ho=H(()=>{"use strict";mn=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let r of this.registry.names()){let s=this.registry.getState(r);s?.pid&&t.push({name:r,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:r,pid:s})=>{try{let o=await Nl(s),a=this.registry.getState(r);if(!a)return;let l=Math.round(o.cpu*10)/10,i=Math.round(o.memory/(1024*1024));(a.cpu!==l||a.memMB!==i)&&(a.cpu=l,a.memMB=i,e=!0)}catch{let o=this.registry.getState(r);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}}});var hn,Jo=H(()=>{"use strict";hn=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,r,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!r)return;let o=this.registry.getState(t);if(!o)return;let a=Date.now();if((o.restartWindowStart==null||a-o.restartWindowStart>this.cfg.windowMs)&&(o.restartWindowStart=a,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 l=Math.min(2**(o.restartAttempts-1)*1e3,3e4);o.nextRestartAt=a+l,o.lastStatusMessage=`restarting in ${Math.round(l/1e3)}s (attempt ${o.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");let i=setTimeout(()=>{this.timers.delete(t);let c=this.registry.getState(t);c&&(c.nextRestartAt=null),this.registry.start(t)},l);this.timers.set(t,i)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}}});import yr from"node:fs";import Wo from"node:path";import $l from"node:os";function qo(){try{let n=yr.readFileSync(wr,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function Go(n){gr=n,!hr&&(hr=setTimeout(()=>{hr=null;let t=gr;if(gr=null,!!t)try{yr.mkdirSync(Wo.dirname(wr),{recursive:!0}),yr.writeFileSync(wr,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
82
|
+
`)}},500))}var wr,hr,gr,Xo=H(()=>{"use strict";wr=Wo.join($l.homedir(),".daimon","state.json");hr=null,gr=null});import Ko from"node:fs";import Ml from"node:os";import zo from"node:path";import{createRequire as _l}from"node:module";var Dl,jl,gn,Yo=H(()=>{"use strict";Dl=_l(import.meta.url),jl=6e4,gn=class{constructor(t,e){this.registry=t;this.cfg=e;this.logFile=zo.join(Ml.homedir(),".daimon","notifications.log");try{Ko.mkdirSync(zo.dirname(this.logFile),{recursive:!0})}catch{}if(!e.enabled){this.audit("init","disabled by config");return}try{let r=Dl("node-notifier");if(this.notifier=r,process.platform==="win32")try{let s=r.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(r){this.warnOnce(`node-notifier unavailable: ${r?.message||r}`),this.audit("init",`node-notifier load failed: ${r?.message||r}`);return}t.on("event",this.onEvent)}registry;cfg;notifier=null;toaster=null;lastSent=new Map;warned=!1;logFile;audit(t,e){let r=`${new Date().toISOString()} ${t} ${e}
|
|
83
|
+
`;try{Ko.appendFileSync(this.logFile,r)}catch{}}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] notifier: ${t}
|
|
84
|
+
`))}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,r,s){if(!this.notifier)return;let o=`${t}::${e}`,a=this.lastSent.get(o)??0,l=Date.now();if(l-a<jl){this.audit("throttled",`${o}`);return}this.lastSent.set(o,l);let i={title:`daimon: ${r}`,message:s,wait:!1,appID:"daimon"},c=(u,p)=>{u?(this.audit("fail",`${o} :: ${u?.message||u}`),this.warnOnce(`notify failed: ${u?.message||u}`)):this.audit("ok",`${o} :: ${r} :: ${p??"(no response)"}`)};try{this.audit("attempt",`${o} :: ${r}`),(this.toaster??this.notifier).notify(i,c)}catch(u){this.audit("throw",`${o} :: ${u?.message||u}`),this.warnOnce(`notify threw: ${u?.message||u}`)}}}});import Vo from"node:fs";import br from"node:path";var Ll,Il,Fl,Bl,yn,Qo=H(()=>{"use strict";Ll=5e3,Il=3e4,Fl=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),Bl=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),yn=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),Ll),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),r=this.registry.getApp(t);if(!e||!r)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 a=e.lastCompileAt??e.startedAt;this.hasSourceChange(r.workspaceRoot,a,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,r){let s=this.caches.get(t);if(!s||Date.now()-s.ts>Il||r!=null&&s.ts<r){let l=this.scan(t);this.caches.set(t,{ts:Date.now(),files:l})}return this.caches.get(t).files.some(l=>l.mtime>e)}scan(t){let e=[],r=(s,o)=>{if(o>8||e.length>4e3)return;let a;try{a=Vo.readdirSync(s,{withFileTypes:!0})}catch{return}for(let l of a)if(!l.name.startsWith(".git")){if(l.isDirectory()){if(Fl.has(l.name))continue;r(br.join(s,l.name),o+1)}else if(l.isFile()){let i=br.extname(l.name);if(!Bl.has(i))continue;try{let c=br.join(s,l.name),u=Vo.statSync(c);e.push({path:c,mtime:u.mtimeMs})}catch{}}}};return r(t,0),e}}});import Zo from"node:http";var wn,bn,ti=H(()=>{"use strict";wn=200,bn=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 r=this.proxies.has(t);e.status==="serving"&&e.port&&!r?this.startProxy(t,e.port):e.status!=="serving"&&r&&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 r=e+this.cfg.portOffset,s=[],o=Zo.createServer((a,l)=>{let i=Date.now(),c={hostname:"127.0.0.1",port:e,method:a.method,path:a.url,headers:{...a.headers,host:`127.0.0.1:${e}`}},u=Zo.request(c,p=>{l.writeHead(p.statusCode||502,p.headers),p.pipe(l);let m=()=>{s.push({ts:Date.now(),method:a.method||"GET",path:a.url||"/",status:p.statusCode||0,durationMs:Date.now()-i}),s.length>wn&&s.splice(0,s.length-wn)};p.on("end",m),p.on("error",m)});u.on("error",()=>{l.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:a.method||"GET",path:a.url||"/",status:502,durationMs:Date.now()-i}),s.length>wn&&s.splice(0,s.length-wn)}),a.pipe(u)});o.on("error",a=>{a?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${r} in use for ${t}; disabling proxy
|
|
85
|
+
`),this.proxies.delete(t)}),o.listen(r,"127.0.0.1",()=>{this.proxies.set(t,{app:t,proxyPort:r,server:o,buffer:s})})}requests(t,e){let r=this.proxies.get(t);if(!r)return[];if(e){let s=Date.now()-e;return r.buffer.filter(o=>o.ts>=s)}return[...r.buffer]}proxyPortFor(t){return this.proxies.get(t)?.proxyPort??null}}});import vr from"node:fs";function ei(n){let t=vr.readFileSync(n,"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 ni(n,t){if(t===null)return null;if(typeof t!="object"||Array.isArray(t))return t;let e=n&&typeof n=="object"&&!Array.isArray(n)?{...n}:{};for(let[r,s]of Object.entries(t))s===null?delete e[r]:e[r]=ni(e[r],s);return e}function Hl(n,t){let e=n+"."+process.pid+".tmp";vr.writeFileSync(e,t,"utf8"),vr.renameSync(e,n)}function Jl(n,t){let e=new Set;for(let r of Object.keys(t))JSON.stringify(n?.[r])!==JSON.stringify(t[r])&&e.add(r);for(let r of Object.keys(n||{}))r in t||e.add(r);return[...e]}function ri(n){let t=ei(n.configPath),e=ni(t,n.patch);if(!e||typeof e!="object")throw new Error("patch produced non-object config");let r=Ie(e,n.configPath);return Hl(n.configPath,JSON.stringify(e,null,2)+`
|
|
86
|
+
`),{config:r,raw:e,applied:Jl(t,e),prevRaw:t}}function Sr(n){let t=ei(n.configPath),e=Ie(t,n.configPath);return Wl(n.registry,e)}function Wl(n,t){let e=n.getConfig();for(let c of Object.keys(e))e[c]=void 0;Object.assign(e,t);let r=new Set(n.names()),s=jt(e),o=new Set(s.map(c=>c.name)),a=[],l=[];for(let c of s)r.has(c.name)?n.updateDiscoveredApp(c):(n.addDiscoveredApp(c),a.push(c.name));for(let c of r)o.has(c)||l.push(c);let i=[];for(let c of n.names()){let u=n.getState(c);if(u&&(u.status==="serving"||u.status==="compiling")){let p=e.overrides?.[c];if(!p)continue;for(let m of Ul)if(m in p){i.push(c);break}}}return{addedApps:a,removedApps:l,restartRequired:i,config:e}}var Ul,si=H(()=>{"use strict";de();Zt();Ul=new Set(["command","port","env","url"])});import oi from"node:fs";import ql from"node:os";import ii from"node:path";function Xl(n){if(!n)return null;let t=JSON.parse(JSON.stringify(n));if(t.apiToken&&(t.apiToken="***"),t.overrides)for(let e of Object.keys(t.overrides)){let r=t.overrides[e]?.env;if(r)for(let s of Object.keys(r))Gl.test(s)&&(r[s]="***")}return t}function Kl(n,t=200){if(!n)return[];let e=[];for(let r of n.names()){let s=n.getState(r);if(s)for(let o of s.logBuffer)e.push({ts:o.ts,line:`[${r}] ${o.line}`})}return e.sort((r,s)=>r.ts-s.ts),e.slice(-t).map(r=>r.line)}function zl(){let n=ii.join(bt(),"crashes");return oi.mkdirSync(n,{recursive:!0}),n}function Yl(n,t,e){let r=new Date().toISOString().replace(/[:.]/g,"-"),s=ii.join(zl(),`${r}.txt`),o=n,a=[`daimon crash dump @ ${new Date().toISOString()}`,`version: ${ut}`,`node: ${process.version}`,`platform: ${process.platform} ${ql.release()}`,`cwd: ${process.cwd()}`,`pid: ${process.pid}`,"","ERROR:",o?.stack||String(o),"","CONFIG (redacted):",JSON.stringify(Xl(e),null,2),"","RECENT LOG (last 200 lines across apps):",...Kl(t,200)];try{oi.writeFileSync(s,a.join(`
|
|
87
|
+
`))}catch{}return s}function ai(n){let t=e=>{let r=null;try{r=Yl(e,n.getRegistry(),n.getConfig())}catch{}try{process.stderr.write(`[daimon] fatal: ${e?.stack||e}
|
|
86
88
|
`)}catch{}if(r)try{process.stderr.write(`[daimon] crash dump: ${r}
|
|
87
|
-
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var xl,qo=U(()=>{"use strict";_t();Pt();xl=/key|secret|token|password|pass/i});function mn(n,t){if(n.length===0)return 0;let e=[...n].sort((s,o)=>s-o),r=Math.min(e.length-1,Math.floor((e.length-1)*t));return Math.round(e[r]*100)/100}var pr,El,Al,hn,Go=U(()=>{"use strict";_t();pr=1e3,El=60,Al=256;hn=class{constructor(t){this.history=t;this.start()}history;startMs=Date.now();lagTimer=null;lagSamples=[];querySamples=[];lockContentionCount=0;lastTickAt=Date.now();highLagStreak=0;warnedAtStreak=0;onSelfWarn=null;start(){let t=performance.now();this.lagTimer=setInterval(()=>{let e=performance.now(),r=Math.max(0,e-t-pr);t=e,this.lagSamples.push(r),this.lagSamples.length>El&&this.lagSamples.shift(),this.lastTickAt=Date.now(),r>100?(this.highLagStreak++,this.highLagStreak>=5&&this.highLagStreak>this.warnedAtStreak&&this.onSelfWarn&&(this.warnedAtStreak=this.highLagStreak,this.onSelfWarn(`event loop lag sustained: ${Math.round(r)}ms (${this.highLagStreak} consecutive ticks)`))):(this.highLagStreak=0,this.warnedAtStreak=0)},pr),this.lagTimer.unref&&this.lagTimer.unref()}setSelfWarnHandler(t){this.onSelfWarn=t}recordQueryMs(t){this.querySamples.push(t),this.querySamples.length>Al&&this.querySamples.shift()}incLockContention(){this.lockContentionCount++}snapshot(){let t=process.memoryUsage(),e=1024*1024;return{pid:process.pid,version:st,uptimeMs:Date.now()-this.startMs,rssMB:Math.round(t.rss/e*10)/10,heapUsedMB:Math.round(t.heapUsed/e*10)/10,heapTotalMB:Math.round(t.heapTotal/e*10)/10,eventLoopLagMs:this.lagSamples.length?Math.round(this.lagSamples[this.lagSamples.length-1]*100)/100:0,eventLoopLagP95Ms:mn(this.lagSamples,.95),historyDbQueryMs:{p50:mn(this.querySamples,.5),p95:mn(this.querySamples,.95),p99:mn(this.querySamples,.99)},lockContentionCount:this.lockContentionCount,tickIntervalMs:pr,lastTickAt:this.lastTickAt}}stop(){this.lagTimer&&clearInterval(this.lagTimer),this.lagTimer=null}}});var Vo={};kt(Vo,{buildContext:()=>hr,loadPlugins:()=>fr,pluginsDir:()=>dr,runPluginScans:()=>mr,validatePluginFile:()=>Ml});import Ol from"node:fs";import Xo from"node:path";import Nl from"node:os";import{pathToFileURL as Ko}from"node:url";function dr(n){return n&&typeof n=="string"&&n.trim()?n:Xo.join(Nl.homedir(),".daimon","plugins")}function $l(n){return n.startsWith("doctor-")&&n.endsWith(".mjs")}function zo(n){if(!n||typeof n!="object")return{ok:!1,error:"module has no default export"};let t=n.default??n;return t?typeof t.name!="string"||!t.name.length?{ok:!1,error:"plugin.name must be a non-empty string"}:/^[a-z][a-z0-9-]*$/.test(t.name)?typeof t.scan!="function"?{ok:!1,error:"plugin.scan must be a function"}:t.fix!==void 0&&typeof t.fix!="function"?{ok:!1,error:"plugin.fix, if present, must be a function"}:t.undo!==void 0&&typeof t.undo!="function"?{ok:!1,error:"plugin.undo, if present, must be a function"}:{ok:!0,plugin:t}:{ok:!1,error:`plugin.name must be kebab-case (got "${t.name}")`}:{ok:!1,error:"plugin shape is null"}}async function fr(n){let t=[],e;try{e=Ol.readdirSync(n).filter($l).sort()}catch{return t}let r=new Set;for(let s of e){let o=Xo.join(n,s);try{let i=await import(Ko(o).href+`?t=${Date.now()}`),a=zo(i);if(!a.ok){t.push({name:s,file:o,status:"failed",error:a.error});continue}let c=a.plugin;if(Yo.has(c.name)){t.push({name:c.name,file:o,status:"failed",error:`name collides with built-in rule "${c.name}"`});continue}if(r.has(c.name)){t.push({name:c.name,file:o,status:"failed",error:"duplicate plug-in name"});continue}r.add(c.name),t.push({name:c.name,description:c.description,file:o,status:"ok",module:c})}catch(i){t.push({name:s,file:o,status:"failed",error:i?.message??String(i)})}}return t}async function Ml(n){try{let t=await import(Ko(n).href+`?t=${Date.now()}`),e=zo(t);return e.ok?Yo.has(e.plugin.name)?{ok:!1,error:`name collides with built-in rule "${e.plugin.name}"`}:{ok:!0,name:e.plugin.name,description:e.plugin.description}:{ok:!1,error:e.error}}catch(t){return{ok:!1,error:t?.message??String(t)}}}async function mr(n,t){for(let e of n)if(!(e.status!=="ok"||!e.module))try{e.lastFindings=await e.module.scan(t),Array.isArray(e.lastFindings)||(e.lastFindings=[])}catch(r){e.status="failed",e.error=`scan failed: ${r?.message??String(r)}`,e.lastFindings=[]}return n}function hr(n){return{config:n.config,apps:n.apps,history:n.history&&typeof n.history.querySelfMetrics=="function"?{querySelfMetrics:n.history.querySelfMetrics.bind(n.history)}:null,mutations:{setOverride:()=>{throw new Error("mutations.setOverride is not implemented in v0.8 \u2014 fix functions are advisory until M44 wires the M36 patch surface")}}}}var Yo,gr=U(()=>{"use strict";Yo=new Set(["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"])});import it,{useEffect as jl,useMemo as _l,useState as me}from"react";import{Box as Ee,Text as yt,useInput as Dl,useStdout as Ll}from"ink";import Il from"ink-text-input";function yr({registry:n,appName:t,onExit:e}){let{stdout:r}=Ll(),[s,o]=me(0),[i,a]=me(!1),[c,l]=me(""),[u,d]=me(""),[f,g]=me(0),[C,R]=me(0);jl(()=>{let v=()=>o(E=>E+1);n.on("change",v);let w=setInterval(()=>o(E=>E+1),500);return()=>{n.off("change",v),clearInterval(w)}},[n]);let b=n.getState(t)?.logBuffer.map(v=>v.line)??[],N=(r.rows||30)-4,p=_l(()=>{if(!u)return[];let v=u.toLowerCase();return b.reduce((w,E,S)=>(E.toLowerCase().includes(v)&&w.push(S),w),[])},[b,u,s]);Dl((v,w)=>{if(i){if(w.escape){a(!1),l("");return}return}if(v==="q"||w.escape){e();return}if(v==="/"){a(!0);return}if(v==="g"){g(Math.max(0,b.length-N));return}if(v==="G"){g(0);return}if(w.pageUp){g(E=>Math.min(Math.max(0,b.length-N),E+N));return}if(w.pageDown){g(E=>Math.max(0,E-N));return}if(w.upArrow){g(E=>Math.min(Math.max(0,b.length-N),E+1));return}if(w.downArrow){g(E=>Math.max(0,E-1));return}if((v==="n"||v==="N")&&p.length){let E=v==="n"?(C+1)%p.length:(C-1+p.length)%p.length;R(E);let S=p[E],O=b.length-f,I=O-N;(S<I||S>=O)&&g(Math.max(0,b.length-S-Math.floor(N/2)));return}});let m=v=>{d(v),a(!1),l(""),R(0)},h=b.length-f,k=Math.max(0,h-N),T=b.slice(k,h),P=(v,w)=>{if(!u)return it.createElement(yt,{key:w},it.createElement(yt,{dimColor:!0},String(w+1).padStart(5)," "),v);let E=u,S=v.toLowerCase(),O=E.toLowerCase(),I=[],X=0,j=0;for(;X<v.length;){let Q=S.indexOf(O,X);if(Q<0){I.push(it.createElement(yt,{key:j++},v.slice(X)));break}Q>X&&I.push(it.createElement(yt,{key:j++},v.slice(X,Q))),I.push(it.createElement(yt,{key:j++,backgroundColor:"yellow",color:"black"},v.slice(Q,Q+E.length))),X=Q+E.length}let W=p[C]===w;return it.createElement(yt,{key:w},it.createElement(yt,{color:W?"cyan":void 0,dimColor:!W},String(w+1).padStart(5)," "),I)};return it.createElement(Ee,{flexDirection:"column"},it.createElement(Ee,null,it.createElement(yt,{bold:!0},"full log: ",it.createElement(yt,{color:"cyan"},t)),it.createElement(yt,{dimColor:!0}," (",b.length," lines",u?`, ${p.length} matches for "${u}"`:"",", scroll=",f,")")),it.createElement(Ee,{flexDirection:"column"},T.length===0?it.createElement(yt,{dimColor:!0},"(no log yet)"):T.map((v,w)=>P(v,k+w))),it.createElement(Ee,null,i?it.createElement(Ee,null,it.createElement(yt,null,"/"),it.createElement(Il,{value:c,onChange:l,onSubmit:m})):it.createElement(yt,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var Zo=U(()=>{"use strict"});function ti(n,t,e=Date.now()){let r=e-36e5,s=36e5/20,o=new Array(20).fill("");for(let i of n){if(i.type!=="status"||i.app!==t||!i.to||i.ts<r||i.ts>e)continue;let a=Math.min(19,Math.floor((i.ts-r)/s)),c=o[a];(!c||(Qo[i.to]??0)>(Qo[c]??0))&&(o[a]=i.to)}return o}function ei(n){return n.map(t=>Fl[t]??"\xB7").join("")}var Qo,Fl,ni=U(()=>{"use strict";Qo={stopped:1,serving:2,compiling:3,starting:3,error:4},Fl={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"}});import $,{useEffect as Bl,useState as lt}from"react";import wr from"node:fs";import Ul from"node:os";import Hl from"node:path";import{Box as dt,Text as F,useApp as Jl,useInput as Wl,useStdout as ql}from"ink";import br from"ink-text-input";import{spawn as vr,spawnSync as Gl}from"node:child_process";function Xl(n){try{process.platform==="win32"?vr("cmd",["/c","start","",n],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?vr("open",[n],{detached:!0,stdio:"ignore"}).unref():vr("xdg-open",[n],{detached:!0,stdio:"ignore"}).unref()}catch{}}function Kl(n){if(n==null)return"";let t=Math.floor(n/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function Sr({registry:n,apiPort:t,onQuit:e}){let{exit:r}=Jl(),{stdout:s}=ql(),[o,i]=lt(n.list()),[a,c]=lt(0),[l,u]=lt(!1),[d,f]=lt(0),[g,C]=lt(!1),[R,y]=lt([]),[b,N]=lt(!1),[p,m]=lt(""),[h,k]=lt(null),[,T]=lt(0),[P,v]=lt(null),[w,E]=lt(""),[S,O]=lt(!1),[I,X]=lt(null),[j,W]=lt(""),[Q,J]=lt(!1),[wt,Z]=lt(null),[Ne,ve]=lt(n.events({sinceMs:3600*1e3}));Bl(()=>{let A=()=>i(n.list()),L=()=>ve(n.events({sinceMs:36e5}));n.on("change",A),n.on("event",L);let H=setInterval(()=>{i(n.list()),ve(n.events({sinceMs:3600*1e3})),T(D=>D+1)},1e3);return()=>{n.off("change",A),n.off("event",L),clearInterval(H)}},[n]),Wl((A,L)=>{if(g)return;if(h){if(L.escape){k(null);return}if(L.tab){let D=h.field==="command"?"port":h.field==="port"?"env":"command";k({...h,field:D});return}return}if(b){if(L.escape){N(!1),m("");return}if(L.return){let D=p.trim();y(D?D.split(/[\s,]+/).filter(Boolean):[]),N(!1),m("");return}if(L.backspace||L.delete){m(D=>D.slice(0,-1));return}A&&!L.ctrl&&m(D=>D+A);return}if(S){if(L.escape){O(!1);return}if(L.return){O(!1);return}if(L.backspace||L.delete){E(D=>D.slice(0,-1));return}A&&!L.ctrl&&E(D=>D+A);return}if(Q){if(L.escape){J(!1),W("");return}if(L.return){let D=j.trim();J(!1),W(""),D&&Ei(D);return}if(L.backspace||L.delete){W(D=>D.slice(0,-1));return}A&&!L.ctrl&&W(D=>D+A);return}if(I){if(A==="y"||A==="Y"){let D=I;X(null),n.restart(D),tt(`restarted ${D}`)}else(A==="n"||A==="N"||L.escape)&&X(null);return}if(A==="q"||L.ctrl&&A==="c"){e(),r();return}if(o.length===0)return;if(P==="g"){v(null);let D=A.toLowerCase();D==="a"?tt("view: apps (only TUI view)"):D==="e"?tt("view: errors \u2014 selected app errors shown in detail pane"):D==="v"?tt("view: events \u2014 recent registry events shown in log pane"):D==="s"?tt("view: settings \u2014 edit `daimon.config.json`"):D==="n"&&tt("view: sessions \u2014 `daimon record` to toggle recording");return}if(L.upArrow||A==="k"){c(D=>Math.max(0,D-1)),f(0);return}if(L.downArrow||A==="j"){c(D=>Math.min(o.length-1,D+1)),f(0);return}let H=o[a];if(H){if(A==="g"){v("g"),setTimeout(()=>v(D=>D==="g"?null:D),1200);return}if(A==="/"){O(!0);return}if(A==="s")n.start(H.name);else if(A==="S")n.stop(H.name);else if(A==="r")X(H.name);else if(A==="f")Ri(H.name);else if(A==="x")$e(H.name);else if(A==="O")J(!0);else if(A==="L")C(!0);else if(A==="t")N(!0),m(R.join(" "));else if(A==="e"){let D=n.getConfig(),et=n.getApp(H.name),gt=n.getState(H.name)?.sessionOverrides??null,Ht=gt?.env??D.overrides?.[H.name]?.env??{},Jt=Object.entries(Ht).map(([Sn,kn])=>`${Sn}=${kn}`).join(`
|
|
88
|
-
|
|
89
|
-
`)
|
|
90
|
-
`),
|
|
89
|
+
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var Gl,ci=H(()=>{"use strict";Jt();Nt();Gl=/key|secret|token|password|pass/i});function vn(n,t){if(n.length===0)return 0;let e=[...n].sort((s,o)=>s-o),r=Math.min(e.length-1,Math.floor((e.length-1)*t));return Math.round(e[r]*100)/100}var kr,Vl,Ql,Sn,li=H(()=>{"use strict";Jt();kr=1e3,Vl=60,Ql=256;Sn=class{constructor(t){this.history=t;this.start()}history;startMs=Date.now();lagTimer=null;lagSamples=[];querySamples=[];lockContentionCount=0;lastTickAt=Date.now();highLagStreak=0;warnedAtStreak=0;onSelfWarn=null;start(){let t=performance.now();this.lagTimer=setInterval(()=>{let e=performance.now(),r=Math.max(0,e-t-kr);t=e,this.lagSamples.push(r),this.lagSamples.length>Vl&&this.lagSamples.shift(),this.lastTickAt=Date.now(),r>100?(this.highLagStreak++,this.highLagStreak>=5&&this.highLagStreak>this.warnedAtStreak&&this.onSelfWarn&&(this.warnedAtStreak=this.highLagStreak,this.onSelfWarn(`event loop lag sustained: ${Math.round(r)}ms (${this.highLagStreak} consecutive ticks)`))):(this.highLagStreak=0,this.warnedAtStreak=0)},kr),this.lagTimer.unref&&this.lagTimer.unref()}setSelfWarnHandler(t){this.onSelfWarn=t}recordQueryMs(t){this.querySamples.push(t),this.querySamples.length>Ql&&this.querySamples.shift()}incLockContention(){this.lockContentionCount++}snapshot(){let t=process.memoryUsage(),e=1024*1024;return{pid:process.pid,version:ut,uptimeMs:Date.now()-this.startMs,rssMB:Math.round(t.rss/e*10)/10,heapUsedMB:Math.round(t.heapUsed/e*10)/10,heapTotalMB:Math.round(t.heapTotal/e*10)/10,eventLoopLagMs:this.lagSamples.length?Math.round(this.lagSamples[this.lagSamples.length-1]*100)/100:0,eventLoopLagP95Ms:vn(this.lagSamples,.95),historyDbQueryMs:{p50:vn(this.querySamples,.5),p95:vn(this.querySamples,.95),p99:vn(this.querySamples,.99)},lockContentionCount:this.lockContentionCount,tickIntervalMs:kr,lastTickAt:this.lastTickAt}}stop(){this.lagTimer&&clearInterval(this.lagTimer),this.lagTimer=null}}});var mi={};Ct(mi,{buildContext:()=>Rr,loadPlugins:()=>Tr,pluginsDir:()=>xr,runPluginScans:()=>Cr,validatePluginFile:()=>nu});import Zl from"node:fs";import ui from"node:path";import tu from"node:os";import{pathToFileURL as pi}from"node:url";function xr(n){return n&&typeof n=="string"&&n.trim()?n:ui.join(tu.homedir(),".daimon","plugins")}function eu(n){return n.startsWith("doctor-")&&n.endsWith(".mjs")}function di(n){if(!n||typeof n!="object")return{ok:!1,error:"module has no default export"};let t=n.default??n;return t?typeof t.name!="string"||!t.name.length?{ok:!1,error:"plugin.name must be a non-empty string"}:/^[a-z][a-z0-9-]*$/.test(t.name)?typeof t.scan!="function"?{ok:!1,error:"plugin.scan must be a function"}:t.fix!==void 0&&typeof t.fix!="function"?{ok:!1,error:"plugin.fix, if present, must be a function"}:t.undo!==void 0&&typeof t.undo!="function"?{ok:!1,error:"plugin.undo, if present, must be a function"}:{ok:!0,plugin:t}:{ok:!1,error:`plugin.name must be kebab-case (got "${t.name}")`}:{ok:!1,error:"plugin shape is null"}}async function Tr(n){let t=[],e;try{e=Zl.readdirSync(n).filter(eu).sort()}catch{return t}let r=new Set;for(let s of e){let o=ui.join(n,s);try{let a=await import(pi(o).href+`?t=${Date.now()}`),l=di(a);if(!l.ok){t.push({name:s,file:o,status:"failed",error:l.error});continue}let i=l.plugin;if(fi.has(i.name)){t.push({name:i.name,file:o,status:"failed",error:`name collides with built-in rule "${i.name}"`});continue}if(r.has(i.name)){t.push({name:i.name,file:o,status:"failed",error:"duplicate plug-in name"});continue}r.add(i.name),t.push({name:i.name,description:i.description,file:o,status:"ok",module:i})}catch(a){t.push({name:s,file:o,status:"failed",error:a?.message??String(a)})}}return t}async function nu(n){try{let t=await import(pi(n).href+`?t=${Date.now()}`),e=di(t);return e.ok?fi.has(e.plugin.name)?{ok:!1,error:`name collides with built-in rule "${e.plugin.name}"`}:{ok:!0,name:e.plugin.name,description:e.plugin.description}:{ok:!1,error:e.error}}catch(t){return{ok:!1,error:t?.message??String(t)}}}async function Cr(n,t){for(let e of n)if(!(e.status!=="ok"||!e.module))try{e.lastFindings=await e.module.scan(t),Array.isArray(e.lastFindings)||(e.lastFindings=[])}catch(r){e.status="failed",e.error=`scan failed: ${r?.message??String(r)}`,e.lastFindings=[]}return n}function Rr(n){return{config:n.config,apps:n.apps,history:n.history&&typeof n.history.querySelfMetrics=="function"?{querySelfMetrics:n.history.querySelfMetrics.bind(n.history)}:null,mutations:{setOverride:()=>{throw new Error("mutations.setOverride is not implemented in v0.8 \u2014 fix functions are advisory until M44 wires the M36 patch surface")}}}}var fi,Pr=H(()=>{"use strict";fi=new Set(["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","orphan-venv","orphan-bundler-cache","orphan-cargo-target","dead-search-root"])});import ru from"node:http";import su from"node:https";import{URL as yi}from"node:url";function lu(n){return n==="error-new"||n==="error-recur"?"error":n==="warning-new"||n==="warning-recur"?"warning":n==="lint-new"||n==="lint-recur"?"lint":n}function uu(n,t){let e={event:t.type,app:t.app,ts:t.ts,from:t.from??null,to:t.to??null,message:t.message??null},r="";try{r=new yi(n).hostname}catch{return e}if(r.endsWith("slack.com")){let s=`*[${t.app}]* ${t.type}${t.to?` \u2192 ${t.to}`:""}`,o=t.message??"";return{text:o?`${s}
|
|
90
|
+
${o}`:s,attachments:[{color:gi(t.type),fields:[{title:"app",value:t.app,short:!0},{title:"type",value:t.type,short:!0},...t.from?[{title:"from",value:t.from,short:!0}]:[],...t.to?[{title:"to",value:t.to,short:!0}]:[],...o?[{title:"message",value:o,short:!1}]:[]],ts:Math.round(t.ts/1e3)}]}}if(r.endsWith("discord.com")||r.endsWith("discordapp.com")){let s=`${t.app} \xB7 ${t.type}${t.to?` \u2192 ${t.to}`:""}`;return{content:s,embeds:[{title:s,description:t.message??void 0,color:parseInt(gi(t.type).replace("#",""),16)||void 0,timestamp:new Date(t.ts).toISOString()}]}}return e}function gi(n){return n==="error-new"||n==="error-recur"||n==="regression-detected"?"#ef4444":n==="warning-new"||n==="warning-recur"?"#f59e0b":n==="status"?"#3b82f6":"#94a3b8"}function pu(n,t,e){return new Promise((r,s)=>{let o;try{o=new yi(n)}catch(c){s(c);return}let a=Buffer.from(JSON.stringify(t)),i=(o.protocol==="https:"?su:ru).request({method:"POST",hostname:o.hostname,port:o.port||(o.protocol==="https:"?443:80),path:o.pathname+(o.search||""),headers:{"content-type":"application/json","content-length":a.length,"user-agent":"daimon-webhooks/1",...e},timeout:cu},c=>{c.resume(),c.on("end",()=>r({status:c.statusCode||0}))});i.on("timeout",()=>i.destroy(new Error("delivery timeout"))),i.on("error",s),i.write(a),i.end()})}var hi,ou,iu,au,cu,kn,wi=H(()=>{"use strict";hi=3,ou=1,iu=64,au=1e3/ou,cu=5e3,kn=class{constructor(t,e,r={}){this.registry=t;this.webhooks=e;this.opts=r;this.listener=s=>this.handleEvent(s),t.on("event",this.listener),this.timer=setInterval(()=>this.tick(),au),this.timer.unref&&this.timer.unref()}registry;webhooks;opts;queue=[];timer=null;droppedCount=0;deliveries=0;failures=0;listener;setWebhooks(t){this.webhooks=t}stats(){return{queued:this.queue.length,dropped:this.droppedCount,deliveries:this.deliveries,failures:this.failures}}stop(){this.timer&&(clearInterval(this.timer),this.timer=null),this.registry.off("event",this.listener)}handleEvent(t){for(let e of this.webhooks)this.matches(e,t)&&(this.queue.length>=iu&&(this.queue.shift(),this.droppedCount++,this.opts.onLog?.(`webhooks: dropped oldest (queue full, total dropped=${this.droppedCount})`)),this.queue.push({cfg:e,event:t,enqueuedAt:Date.now()}))}matches(t,e){if(t.events&&t.events.length){let r=lu(e.type);if(!t.events.includes(e.type)&&!t.events.includes(r))return!1}return!(t.filter&&(t.filter.app&&t.filter.app.length&&!t.filter.app.includes(e.app)||t.filter.to&&t.filter.to.length&&(!e.to||!t.filter.to.includes(e.to))||t.filter.from&&t.filter.from.length&&(!e.from||!t.filter.from.includes(e.from))))}tick(){let t=this.queue.shift();if(!t)return;let e=this.opts.sendFn??pu,r=uu(t.cfg.url,t.event);this.attemptDelivery(e,t.cfg,r,0).then(s=>{s?this.deliveries++:this.failures++})}async attemptDelivery(t,e,r,s){try{let o=await t(e.url,r,e.headers??{});if(o.status>=200&&o.status<300)return!0;if(s>=hi)return this.opts.onLog?.(`webhooks: ${e.url} -> HTTP ${o.status} (after ${s+1} attempts)`),!1;let a=500*Math.pow(2,s);return await new Promise(l=>setTimeout(l,a)),this.attemptDelivery(t,e,r,s+1)}catch(o){if(s>=hi)return this.opts.onLog?.(`webhooks: ${e.url} -> ${o?.message||o} (after ${s+1} attempts)`),!1;let a=500*Math.pow(2,s);return await new Promise(l=>setTimeout(l,a)),this.attemptDelivery(t,e,r,s+1)}}}});import dt,{useEffect as du,useMemo as fu,useState as ke}from"react";import{Box as De,Text as kt,useInput as mu,useStdout as hu}from"ink";import gu from"ink-text-input";function Ar({registry:n,appName:t,onExit:e}){let{stdout:r}=hu(),[s,o]=ke(0),[a,l]=ke(!1),[i,c]=ke(""),[u,p]=ke(""),[m,g]=ke(0),[S,x]=ke(0);du(()=>{let d=()=>o(h=>h+1);n.on("change",d);let f=setInterval(()=>o(h=>h+1),500);return()=>{n.off("change",d),clearInterval(f)}},[n]);let w=n.getState(t)?.logBuffer.map(d=>d.line)??[],E=(r.rows||30)-4,B=fu(()=>{if(!u)return[];let d=u.toLowerCase();return w.reduce((f,h,b)=>(h.toLowerCase().includes(d)&&f.push(b),f),[])},[w,u,s]);mu((d,f)=>{if(a){if(f.escape){l(!1),c("");return}return}if(d==="q"||f.escape){e();return}if(d==="/"){l(!0);return}if(d==="g"){g(Math.max(0,w.length-E));return}if(d==="G"){g(0);return}if(f.pageUp){g(h=>Math.min(Math.max(0,w.length-E),h+E));return}if(f.pageDown){g(h=>Math.max(0,h-E));return}if(f.upArrow){g(h=>Math.min(Math.max(0,w.length-E),h+1));return}if(f.downArrow){g(h=>Math.max(0,h-1));return}if((d==="n"||d==="N")&&B.length){let h=d==="n"?(S+1)%B.length:(S-1+B.length)%B.length;x(h);let b=B[h],y=w.length-m,P=y-E;(b<P||b>=y)&&g(Math.max(0,w.length-b-Math.floor(E/2)));return}});let Q=d=>{p(d),l(!1),c(""),x(0)},k=w.length-m,ot=Math.max(0,k-E),et=w.slice(ot,k),j=(d,f)=>{if(!u)return dt.createElement(kt,{key:f},dt.createElement(kt,{dimColor:!0},String(f+1).padStart(5)," "),d);let h=u,b=d.toLowerCase(),y=h.toLowerCase(),P=[],C=0,R=0;for(;C<d.length;){let O=b.indexOf(y,C);if(O<0){P.push(dt.createElement(kt,{key:R++},d.slice(C)));break}O>C&&P.push(dt.createElement(kt,{key:R++},d.slice(C,O))),P.push(dt.createElement(kt,{key:R++,backgroundColor:"yellow",color:"black"},d.slice(O,O+h.length))),C=O+h.length}let D=B[S]===f;return dt.createElement(kt,{key:f},dt.createElement(kt,{color:D?"cyan":void 0,dimColor:!D},String(f+1).padStart(5)," "),P)};return dt.createElement(De,{flexDirection:"column"},dt.createElement(De,null,dt.createElement(kt,{bold:!0},"full log: ",dt.createElement(kt,{color:"cyan"},t)),dt.createElement(kt,{dimColor:!0}," (",w.length," lines",u?`, ${B.length} matches for "${u}"`:"",", scroll=",m,")")),dt.createElement(De,{flexDirection:"column"},et.length===0?dt.createElement(kt,{dimColor:!0},"(no log yet)"):et.map((d,f)=>j(d,ot+f))),dt.createElement(De,null,a?dt.createElement(De,null,dt.createElement(kt,null,"/"),dt.createElement(gu,{value:i,onChange:c,onSubmit:Q})):dt.createElement(kt,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var bi=H(()=>{"use strict"});function Si(n,t,e=Date.now()){let r=e-36e5,s=36e5/20,o=new Array(20).fill("");for(let a of n){if(a.type!=="status"||a.app!==t||!a.to||a.ts<r||a.ts>e)continue;let l=Math.min(19,Math.floor((a.ts-r)/s)),i=o[l];(!i||(vi[a.to]??0)>(vi[i]??0))&&(o[l]=a.to)}return o}function ki(n){return n.map(t=>yu[t]??"\xB7").join("")}var vi,yu,xi=H(()=>{"use strict";vi={stopped:1,serving:2,compiling:3,starting:3,error:4},yu={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"}});import $,{useEffect as wu,useState as ht}from"react";import Er from"node:fs";import bu from"node:os";import vu from"node:path";import{Box as yt,Text as U,useApp as Su,useInput as ku,useStdout as xu}from"ink";import Or from"ink-text-input";import{spawn as Nr,spawnSync as Tu}from"node:child_process";function Cu(n){try{process.platform==="win32"?Nr("cmd",["/c","start","",n],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?Nr("open",[n],{detached:!0,stdio:"ignore"}).unref():Nr("xdg-open",[n],{detached:!0,stdio:"ignore"}).unref()}catch{}}function Ru(n){if(n==null)return"";let t=Math.floor(n/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function $r({registry:n,apiPort:t,onQuit:e}){let{exit:r}=Su(),{stdout:s}=xu(),[o,a]=ht(n.list()),[l,i]=ht(0),[c,u]=ht(!1),[p,m]=ht(0),[g,S]=ht(!1),[x,T]=ht([]),[w,E]=ht(!1),[B,Q]=ht(""),[k,ot]=ht(null),[,et]=ht(0),[j,d]=ht(null),[f,h]=ht(""),[b,y]=ht(!1),[P,C]=ht(null),[R,D]=ht(""),[O,I]=ht(!1),[z,it]=ht(null),[L,Y]=ht(n.events({sinceMs:3600*1e3}));wu(()=>{let A=()=>a(n.list()),F=()=>Y(n.events({sinceMs:36e5}));n.on("change",A),n.on("event",F);let q=setInterval(()=>{a(n.list()),Y(n.events({sinceMs:3600*1e3})),et(_=>_+1)},1e3);return()=>{n.off("change",A),n.off("event",F),clearInterval(q)}},[n]),ku((A,F)=>{if(g)return;if(k){if(F.escape){ot(null);return}if(F.tab){let _=k.field==="command"?"port":k.field==="port"?"env":"command";ot({...k,field:_});return}return}if(w){if(F.escape){E(!1),Q("");return}if(F.return){let _=B.trim();T(_?_.split(/[\s,]+/).filter(Boolean):[]),E(!1),Q("");return}if(F.backspace||F.delete){Q(_=>_.slice(0,-1));return}A&&!F.ctrl&&Q(_=>_+A);return}if(b){if(F.escape){y(!1);return}if(F.return){y(!1);return}if(F.backspace||F.delete){h(_=>_.slice(0,-1));return}A&&!F.ctrl&&h(_=>_+A);return}if(O){if(F.escape){I(!1),D("");return}if(F.return){let _=R.trim();I(!1),D(""),_&&rt(_);return}if(F.backspace||F.delete){D(_=>_.slice(0,-1));return}A&&!F.ctrl&&D(_=>_+A);return}if(P){if(A==="y"||A==="Y"){let _=P;C(null),n.restart(_),V(`restarted ${_}`)}else(A==="n"||A==="N"||F.escape)&&C(null);return}if(A==="q"||F.ctrl&&A==="c"){e(),r();return}if(o.length===0)return;if(j==="g"){d(null);let _=A.toLowerCase();_==="a"?V("view: apps (only TUI view)"):_==="e"?V("view: errors \u2014 selected app errors shown in detail pane"):_==="v"?V("view: events \u2014 recent registry events shown in log pane"):_==="s"?V("view: settings \u2014 edit `daimon.config.json`"):_==="n"&&V("view: sessions \u2014 `daimon record` to toggle recording");return}if(F.upArrow||A==="k"){i(_=>Math.max(0,_-1)),m(0);return}if(F.downArrow||A==="j"){i(_=>Math.min(o.length-1,_+1)),m(0);return}let q=o[l];if(q){if(A==="g"){d("g"),setTimeout(()=>d(_=>_==="g"?null:_),1200);return}if(A==="/"){y(!0);return}if(A==="s")n.start(q.name);else if(A==="S")n.stop(q.name);else if(A==="r")C(q.name);else if(A==="f")Tt(q.name);else if(A==="x")K(q.name);else if(A==="O")I(!0);else if(A==="L")S(!0);else if(A==="t")E(!0),Q(x.join(" "));else if(A==="e"){let _=n.getConfig(),at=n.getApp(q.name),St=n.getState(q.name)?.sessionOverrides??null,Yt=St?.env??_.overrides?.[q.name]?.env??{},Vt=Object.entries(Yt).map(([An,En])=>`${An}=${En}`).join(`
|
|
91
|
+
`);ot({name:q.name,field:"command",cmd:St?.command??at?.command??"",port:String(St?.port??_.overrides?.[q.name]?.port??q.port??""),env:Vt})}else if(A==="E"){let at=n.getConfig().envFiles?.[q.name]??[];if(!at.length)return;let St=n.getState(q.name)?.activeEnvFile??null,Yt=St?at.indexOf(St):-1,Vt=at[(Yt+1)%at.length];n.setActiveEnvFile(q.name,Vt)}else if(A==="V"){let _=process.env.EDITOR||(process.platform==="win32"?"notepad":"vi"),at=vu.join(bu.tmpdir(),`daimon-${q.name}-${Date.now()}.json`),St=n.getConfig(),Yt=n.getApp(q.name),Vt=n.getState(q.name)?.sessionOverrides??null,An={command:Vt?.command??Yt?.command,port:Vt?.port??St.overrides?.[q.name]?.port??null,env:Vt?.env??St.overrides?.[q.name]?.env??{}};try{Er.writeFileSync(at,JSON.stringify(An,null,2)),Tu(_,[at],{stdio:"inherit",shell:!0});let En=Er.readFileSync(at,"utf8"),Qt=JSON.parse(En);n.setSessionOverride(q.name,{command:typeof Qt.command=="string"?Qt.command:void 0,port:typeof Qt.port=="number"?Qt.port:void 0,env:Qt.env&&typeof Qt.env=="object"?Qt.env:void 0}),Er.unlinkSync(at)}catch{}}else A==="l"?u(_=>!_):A==="o"?q.url&&Cu(q.url):F.pageUp?m(_=>_+5):F.pageDown&&m(_=>Math.max(0,_-5))}});let V=A=>{it(A),setTimeout(()=>it(F=>F===A?null:F),4e3)},K=async A=>{V(`try-fix ${A}\u2026`);try{let{runAutoFix:F,ALL_AUTO_FIX:q}=await Promise.resolve().then(()=>(ve(),be)),at=n.getConfig().doctor?.autoFix?.permitted??q,St=await F({permitted:at,dryRun:!1});await n.restart(A);let Yt=await n.waitFor(A,"healthy",6e4);V(`try-fix ${A}: ${Yt.timedOut?"timeout":"reached"} \xB7 fixed ${St.ran.length}`)}catch(F){V(`try-fix ${A} failed: ${F?.message??F}`)}},Tt=async A=>{V(`focus ${A} until stable\u2026`);try{let F=Date.now(),q=Date.now(),_=at=>{at.app===A&&(q=Date.now())};n.on("event",_);try{for(;Date.now()-F<18e4;){let at=n.summary(A);if(at&&at.status==="serving"&&at.health==="healthy"&&Date.now()-q>=5e3){V(`focus ${A}: stable after ${Math.round((Date.now()-F)/1e3)}s`);return}await new Promise(St=>setTimeout(St,500))}}finally{n.off("event",_)}V(`focus ${A}: timed out`)}catch(F){V(`focus ${A} failed: ${F?.message??F}`)}},rt=async A=>{V(`orchestrate ${A}\u2026`);try{let{orchestrateProfile:F}=await Promise.resolve().then(()=>(pr(),ur)),q=await F(n,n.getConfig(),{profile:A,goal:"healthy",timeoutMs:3e5});if(q.error){V(`orchestrate ${A}: ${q.error}`);return}let _=q.allReached;V(`orchestrate ${A}: ${_?"all reached":"some failing"} \xB7 ${Math.round(q.totalMs/1e3)}s`)}catch(F){V(`orchestrate ${A} failed: ${F?.message??F}`)}},Re=f.trim().toLowerCase(),zt=(x.length===0?o:o.filter(A=>x.every(F=>A.tags.includes(F)))).filter(A=>!Re||A.name.toLowerCase().includes(Re)),W=zt[Math.min(l,Math.max(0,zt.length-1))],At=W?n.getState(W.name):null,Ir=At?At.logBuffer.slice(Math.max(0,At.logBuffer.length-12-p),At.logBuffer.length-p).map(A=>A.line):[],Pn=s.columns||100,Xi=Math.min(36,Math.floor(Pn*.4));return g&&W?$.createElement(Ar,{registry:n,appName:W.name,onExit:()=>S(!1)}):$.createElement(yt,{flexDirection:"column",width:Pn},$.createElement(yt,{borderStyle:"round",borderColor:"cyan",paddingX:1},$.createElement(U,{bold:!0,color:"cyan"},"daimon"),$.createElement(U,{dimColor:!0}," \u2022 api http://127.0.0.1:",t)),$.createElement(yt,{flexDirection:"row"},$.createElement(yt,{flexDirection:"column",width:Xi,borderStyle:"single",borderColor:"gray",paddingX:1},$.createElement(U,{bold:!0},"Apps ",x.length?$.createElement(U,{dimColor:!0},"(tags: ",x.join(", "),")"):null),zt.length===0?$.createElement(U,{dimColor:!0},o.length===0?"(no apps discovered)":"(no apps match filter)"):zt.map((A,F)=>{let q=F===l,_=Si(L,A.name),at=ki(_);return $.createElement(yt,{key:A.name,flexDirection:"column"},$.createElement(yt,null,$.createElement(U,{color:q?"cyan":void 0},q?"\u25B8 ":" "),$.createElement(U,{color:q?"cyan":void 0},((n.getState(A.name)?.sessionOverrides?"*":"")+A.name).padEnd(20).slice(0,20)),$.createElement(U,{color:Ti[A.status]}," ",A.status.padEnd(9)),$.createElement(U,{color:Ci[A.health]},A.status==="serving"?"\u25CF":" "),$.createElement(U,{dimColor:!0},A.port?` :${A.port}`:""),Pn>=100&&A.cpu!=null?$.createElement(U,{dimColor:!0}," ",String(A.cpu).padStart(5),"% ",String(A.memMB??0).padStart(5),"MB"):null),$.createElement(yt,null,$.createElement(U,{dimColor:!0}," "),$.createElement(U,{dimColor:!0},at)))})),$.createElement(yt,{flexDirection:"column",flexGrow:1,borderStyle:"single",borderColor:"gray",paddingX:1},W&&At?$.createElement($.Fragment,null,$.createElement(U,null,"Selected: ",$.createElement(U,{bold:!0},W.name)),$.createElement(U,null,"Status: ",$.createElement(U,{color:Ti[W.status]},W.status)," ",$.createElement(U,{color:Ci[W.health]},"\u25CF")," ",$.createElement(U,{dimColor:!0},W.health)),$.createElement(U,null,"Port: ",W.port??"-"),$.createElement(U,null,"URL: ",W.url??"-"),W.announcedUrl&&W.announcedUrl!==W.url?$.createElement(U,{dimColor:!0},"Announced: ",W.announcedUrl):null,W.lastHealthError?$.createElement(U,{color:"red"},"HealthErr: ",W.lastHealthError):null,W.stale?$.createElement(U,{color:"yellow"},"\u26A0 stale (best guess)"):null,$.createElement(U,null,"Errors: ",$.createElement(U,{color:W.errorCount?"red":void 0},W.errorCount)),$.createElement(U,null,"Uptime: ",Ru(W.uptimeMs)),W.cpu!=null||W.memMB!=null?$.createElement(U,null,"Usage: ",W.cpu??"-","% ",W.memMB??"-"," MB"):null,W.compileHistoryMs.length>0?$.createElement(U,null,"Recent compile: ",W.compileHistoryMs.slice(-5).map(A=>(A/1e3).toFixed(1)+"s").join(" \xB7 ")):null,W.bundle?$.createElement(U,null,"Bundle: ",W.bundle.initialKB,"KB initial \xB7 ",W.bundle.lazyKB,"KB lazy",W.bundleRegressionPct!=null&&W.bundleRegressionPct>10?$.createElement(U,{color:"red"}," (+",W.bundleRegressionPct,"% \u26A0)"):null):null,At.lastStatusMessage?$.createElement(U,{dimColor:!0},"Note: ",At.lastStatusMessage):null,$.createElement(U,null,"\u2500\u2500\u2500\u2500 recent log ",c?"(focused)":""," \u2500\u2500\u2500\u2500"),Ir.length===0?$.createElement(U,{dimColor:!0},"(no output yet)"):Ir.map((A,F)=>$.createElement(U,{key:F,wrap:"truncate-end"},A))):$.createElement(U,{dimColor:!0},"No app selected."))),$.createElement(yt,{flexDirection:"column"},w?$.createElement(U,null,"tag filter (space-separated, Enter to apply, Esc to cancel): ",$.createElement(U,{color:"cyan"},B)):null,k?$.createElement(yt,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1},$.createElement(U,{bold:!0,color:"yellow"},"edit ",k.name," (session-only) Tab=next field Enter=save Esc=cancel"),$.createElement(yt,null,$.createElement(U,null,k.field==="command"?"> ":" ","command: "),k.field==="command"?$.createElement(Or,{value:k.cmd,onChange:A=>ot({...k,cmd:A}),onSubmit:()=>ot({...k,field:"port"})}):$.createElement(U,{dimColor:!0},k.cmd)),$.createElement(yt,null,$.createElement(U,null,k.field==="port"?"> ":" ","port: "),k.field==="port"?$.createElement(Or,{value:k.port,onChange:A=>ot({...k,port:A}),onSubmit:()=>ot({...k,field:"env"})}):$.createElement(U,{dimColor:!0},k.port)),$.createElement(yt,null,$.createElement(U,null,k.field==="env"?"> ":" ","env (k=v;): "),k.field==="env"?$.createElement(Or,{value:k.env.replace(/\n/g,";"),onChange:A=>ot({...k,env:A.replace(/;/g,`
|
|
92
|
+
`)}),onSubmit:()=>{let A=Number(k.port),F={};for(let q of k.env.split(/\n/)){let _=q.match(/^\s*([^=]+)=(.*)$/);_&&(F[_[1].trim()]=_[2])}n.setSessionOverride(k.name,{command:k.cmd||void 0,port:Number.isFinite(A)&&A>0?A:void 0,env:Object.keys(F).length?F:void 0}),ot(null)}}):$.createElement(U,{dimColor:!0},k.env))):null,P?$.createElement(yt,{borderStyle:"round",borderColor:"yellow",paddingX:1},$.createElement(U,{color:"yellow",bold:!0},"Restart ",P,"? "),$.createElement(U,{dimColor:!0},"[y]es [n]o / Esc")):null,b?$.createElement(U,null,"filter (Enter to apply, Esc to clear): ",$.createElement(U,{color:"cyan"},f)):null,O?$.createElement(yt,{borderStyle:"round",borderColor:"cyan",paddingX:1},$.createElement(U,{bold:!0,color:"cyan"},"orchestrate profile (Enter to run, Esc to cancel): "),$.createElement(U,{color:"cyan"},R)):null,z?$.createElement(U,{color:"cyan"},"[i] ",z):null,$.createElement(U,{dimColor:!0},"[j/k or \u2191/\u2193] move [s] start [S] stop [r] restart [f] focus [x] try-fix [O] orchestrate [o] open URL [/] filter [g a|e|v|s|n] view hint [e] edit [E] env [V] $EDITOR [l] log focus [Shift+L] full log [q] quit")))}var Ti,Ci,Ri=H(()=>{"use strict";bi();xi();Ti={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Ci={healthy:"green",unhealthy:"red",unknown:"gray"}});var Ai={};Ct(Ai,{startInProcess:()=>Pi});import Pu from"react";import Au from"node:path";import{render as Eu}from"ink";import{pathToFileURL as Ou}from"node:url";async function Pi(n={}){let t=null,e=null;ai({getRegistry:()=>t,getConfig:()=>e});let r;try{r=ft()}catch(y){process.stderr.write(`[daimon] config error: ${y.message}
|
|
93
|
+
`),process.exit(1)}if(r.kind==="stub-created"){let y=Ft();process.stdout.write(`[daimon] no config found. Created stub at:
|
|
91
94
|
${r.path}
|
|
92
95
|
`),process.stdout.write(`[daimon] Edit it to add "searchRoots" pointing at your Nx/Angular workspace, then run again.
|
|
93
|
-
`),process.stdout.write(`[daimon] (Local override path: ${
|
|
96
|
+
`),process.stdout.write(`[daimon] (Local override path: ${y.local})
|
|
94
97
|
`),process.exit(0)}let{config:s,path:o}=r;if(process.stdout.write(`[daimon] config: ${o}
|
|
95
|
-
`),s.depends&&Object.keys(s.depends).length){let
|
|
96
|
-
`),process.exit(1))}let
|
|
97
|
-
`);let
|
|
98
|
-
`);for(let
|
|
99
|
-
`);continue}s.depends&&s.depends[
|
|
100
|
-
`)}catch{}let
|
|
101
|
-
`);try{
|
|
102
|
-
`)
|
|
103
|
-
`)
|
|
104
|
-
`),
|
|
105
|
-
`),
|
|
98
|
+
`),s.depends&&Object.keys(s.depends).length){let y=Fe(s.depends);y&&(process.stderr.write(`[daimon] config error: depends graph has a cycle: ${y.join(" -> ")}
|
|
99
|
+
`),process.exit(1))}let a=jt(s);a.length===0&&process.stdout.write(`[daimon] no serveable projects discovered in: ${s.searchRoots.join(", ")||"(none)"}
|
|
100
|
+
`);let l=qo(),i=new me(s.portRange,{initial:l.ports,onChange:y=>Go({ports:y})}),c=new nn(s,a,i);t=c,e=s;let u=new Lt(s.history);c.setHistory(u);let p=new fn(c,s.healthProbe,s),m=new mn(c),g=new hn(c,s.autoRestart),S=new gn(c,s.notifications),x=new yn(c,s.staleDetect),T=new bn(c,s.requestLog);c.on("childExit",({name:y,code:P,signal:C,stopping:R})=>g.onExit(y,P,C,R)),c.on("userStop",({name:y})=>g.onUserStop(y));let w=To();if(w&&w.apps.length){process.stdout.write(`[daimon] state-handoff: restoring ${w.apps.map(y=>y.name).join(", ")}
|
|
101
|
+
`);for(let y of w.apps)i.pin(y.name,y.port);for(let y of w.apps)c.names().includes(y.name)&&c.start(y.name)}if(s.autoStart&&s.autoStart.length){let y=new Set(c.names());for(let P of s.autoStart){if(!y.has(P)){process.stderr.write(`[daimon] warning: autoStart references unknown app "${P}"
|
|
102
|
+
`);continue}s.depends&&s.depends[P]&&s.depends[P].length?c.startWithDeps(P):c.start(P)}}let E=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):s.apiPort,B=!!n.headless||!!s.headless||process.argv.includes("--headless"),Q=setInterval(()=>{try{c.pruneOldErrors()}catch{}},3600*1e3),k=[];try{k=await Tr(xr(s.plugins?.dir??void 0));for(let y of k)y.status==="failed"&&process.stderr.write(`[daimon] plug-in skipped: ${Au.basename(y.file)} \u2014 ${y.error}
|
|
103
|
+
`)}catch{}let ot=s.webhooks&&s.webhooks.length?new kn(c,s.webhooks,{onLog:y=>process.stderr.write(`[daimon] ${y}
|
|
104
|
+
`)}):null,et=new Sn(u);et.setSelfWarnHandler(y=>{try{c.recordEvent({app:"__daemon__",type:"self-warn",message:y})}catch{}});let j=setInterval(()=>{let y=et.snapshot();u.recordSelfMetric(y.rssMB,y.heapUsedMB,y.eventLoopLagMs,y.historyDbQueryMs.p95)},60*1e3);j.unref&&j.unref();let d=!1,f=async()=>{if(!d){d=!0;try{clearInterval(Q)}catch{}try{clearInterval(j)}catch{}try{et.stop()}catch{}try{p.stop()}catch{}try{m.stop()}catch{}try{g.stop()}catch{}try{S.stop()}catch{}try{x.stop()}catch{}try{T.stop()}catch{}try{ot?.stop()}catch{}try{u.close()}catch{}try{await c.stopAll(3e3)}catch{}try{h.close()}catch{}try{Ot()}catch{}process.exit(0)}},h=Lo(c,E,{metricsEnabled:s.metrics.enabled,requestLog:T,onShutdown:()=>{f()},configPath:o,getConfig:()=>c.getConfig(),patchConfig:y=>{try{let P=ri({configPath:o,patch:y}),C=Sr({configPath:o,registry:c});return{ok:!0,applied:P.applied,addedApps:C.addedApps,removedApps:C.removedApps,restartRequired:C.restartRequired}}catch(P){return{ok:!1,error:P?.message||String(P)}}},reloadConfig:async()=>{let y=Sr({configPath:o,registry:c});return{ok:!0,addedApps:y.addedApps,removedApps:y.removedApps,restartRequired:y.restartRequired}},selfMetrics:et,getPlugins:()=>k.map(y=>({name:y.name,description:y.description,file:y.file,status:y.status,error:y.error,lastFindings:y.lastFindings})),runPluginScans:async()=>{let y=Rr({config:c.getConfig(),apps:c.names().map(P=>({name:P,workspaceRoot:c.getApp(P)?.workspaceRoot??""})),history:u});await Cr(k,y)}});process.stdout.write(`[daimon] api: http://127.0.0.1:${E}
|
|
105
|
+
`);try{ts(es(E,B,o))}catch(y){process.stderr.write(`[daimon] warning: could not write daemon.lock: ${y?.message||y}
|
|
106
|
+
`)}if(process.on("SIGINT",()=>{f()}),process.on("SIGTERM",()=>{f()}),process.on("beforeExit",()=>{f()}),B){process.stdout.write(`[daimon] headless mode \u2014 TUI suppressed. Dashboard: http://127.0.0.1:${E}
|
|
107
|
+
`);let y="",P=setInterval(()=>{let C=c.list().map(D=>({name:D.name,status:D.status,health:D.health,port:D.port})),R=JSON.stringify(C);R!==y&&(process.stderr.write(R+`
|
|
108
|
+
`),y=R)},6e4);await new Promise(()=>{}),clearInterval(P);return}await Eu(Pu.createElement($r,{registry:c,apiPort:E,onQuit:()=>{f()}})).waitUntilExit(),await f()}var Nu,Ei=H(()=>{"use strict";de();Zt();eo();Ee();Io();Uo();Ho();Jo();Xo();He();Ae();Yo();Qo();ti();Nt();si();ci();ar();li();Pr();wi();Ri();Nu=(()=>{try{return import.meta.url===Ou(process.argv[1]||"").href}catch{return!1}})();Nu&&Pi().catch(n=>{process.stderr.write(`[daimon] fatal: ${n?.stack||n}
|
|
109
|
+
`),process.exit(1)})});var $i={};Ct($i,{attachToDaemon:()=>Wu});import tt,{useEffect as Oi,useState as Gt}from"react";import Mr from"node:fs";import Ni from"node:path";import $u from"node:os";import{Box as xe,render as Mu,Text as ct,useApp as _u,useInput as Du,useStdout as ju}from"ink";import Lu from"ink-text-input";function Bu(n){if(n==null)return"";let t=Math.floor(n/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function _r(n){return Ni.join($u.homedir(),".daimon",`attach-token.${n}`)}function Uu(n){try{return Mr.readFileSync(_r(n),"utf8").trim()||null}catch{return null}}function Hu(n,t){try{Mr.mkdirSync(Ni.dirname(_r(n)),{recursive:!0}),Mr.writeFileSync(_r(n),t,"utf8")}catch{}}function Ju({port:n,onExit:t}){let{exit:e}=_u(),{stdout:r}=ju(),[s,o]=Gt([]),[a,l]=Gt(0),[i,c]=Gt(!1),[u,p]=Gt([]),[m,g]=Gt(null),[S,x]=Gt(()=>Uu(n)),[T,w]=Gt(!1),[E,B]=Gt(""),Q=`http://127.0.0.1:${n}`;async function k(j,d={}){try{let f={...d.headers||{}};S&&(f.authorization=`Bearer ${S}`);let h=await fetch(Q+j,{...d,headers:f}),b=await h.text(),y=b;try{y=JSON.parse(b)}catch{}return{status:h.status,body:y}}catch(f){return{status:0,body:{error:f?.message||String(f)}}}}if(Oi(()=>{let j=!1,d=async()=>{let h=await k("/api/apps?format=full");if(!j){if(h.status===0){g(h.body?.error||"daemon unreachable");return}if(h.status===401){w(!0);return}g(null),o(Array.isArray(h.body)?h.body:[])}};d();let f=setInterval(d,1e3);return()=>{j=!0,clearInterval(f)}},[S]),Oi(()=>{if(!i){p([]);return}let j=!1,d=s[a];if(!d)return;let f=async()=>{let b=await k(`/api/apps/${encodeURIComponent(d.name)}/logs?tail=12`);j||Array.isArray(b.body?.lines)&&p(b.body.lines)};f();let h=setInterval(f,1e3);return()=>{j=!0,clearInterval(h)}},[i,a,s.length,S]),Du((j,d)=>{if(T){if(d.escape){w(!1);return}return}if(j==="q"||d.ctrl&&j==="c"){t(),e();return}if(d.upArrow)l(f=>Math.max(0,f-1));else if(d.downArrow)l(f=>Math.min(Math.max(0,s.length-1),f+1));else if(d.return||j===" ")c(f=>!f);else if(j==="s"||j==="x"||j==="r"){let f=s[a];if(!f)return;let h=j==="s"?"start":j==="x"?"stop":"restart";k(`/api/apps/${encodeURIComponent(f.name)}/${h}`,{method:"POST"})}}),T)return tt.createElement(xe,{flexDirection:"column",paddingX:1},tt.createElement(ct,{color:"yellow"},"daemon requires a bearer token. Enter token (Esc to cancel):"),tt.createElement(Lu,{value:E,onChange:B,mask:"*",onSubmit:()=>{let j=E.trim();j&&(x(j),Hu(n,j)),B(""),w(!1)}}));let ot=r.columns||100,et=s[a];return tt.createElement(xe,{flexDirection:"column",width:ot},tt.createElement(xe,{borderStyle:"round",borderColor:"cyan",paddingX:1},tt.createElement(ct,{bold:!0,color:"cyan"},"daimon attach"),tt.createElement(ct,{dimColor:!0}," \u2022 http://127.0.0.1:",n," \u2022 HTTP-client TUI (q detaches, daemon keeps running)")),m?tt.createElement(ct,{color:"red"},m):null,tt.createElement(xe,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},tt.createElement(ct,{bold:!0},"Apps (",s.length,")"),s.length===0?tt.createElement(ct,{dimColor:!0},"(no apps)"):s.map((j,d)=>{let f=d===a;return tt.createElement(xe,{key:j.name},tt.createElement(ct,{color:f?"cyan":void 0},f?"\u25B8 ":" "),tt.createElement(ct,{color:f?"cyan":void 0},j.name.padEnd(20).slice(0,20)),tt.createElement(ct,{color:Iu[j.status]}," ",j.status.padEnd(9)),tt.createElement(ct,{color:Fu[j.health]},j.status==="serving"?"\u25CF":" "),tt.createElement(ct,{dimColor:!0},j.port?` :${j.port}`:""),tt.createElement(ct,{dimColor:!0}," errs=",j.errorCount," up=",Bu(j.uptimeMs)))})),et?tt.createElement(xe,{flexDirection:"column",borderStyle:"single",borderColor:"gray",paddingX:1},tt.createElement(ct,null,"Selected: ",tt.createElement(ct,{bold:!0},et.name)),tt.createElement(ct,null,"URL: ",et.url??"-"),et.lastHealthError?tt.createElement(ct,{color:"red"},"HealthErr: ",et.lastHealthError):null,tt.createElement(ct,{dimColor:!0},"\u2500\u2500\u2500\u2500 recent log (Enter/Space toggles) \u2500\u2500\u2500\u2500"),i?u.length===0?tt.createElement(ct,{dimColor:!0},"(loading\u2026)"):u.map((j,d)=>tt.createElement(ct,{key:d,wrap:"truncate-end"},j)):tt.createElement(ct,{dimColor:!0},"(press Enter to fetch logs)")):null,tt.createElement(ct,{dimColor:!0},"[s] start [x] stop [r] restart [Enter] toggle log [q] detach (daemon keeps running)"))}async function Wu(n){let t,e=new Promise(s=>{t=s});await Mu(tt.createElement(Ju,{port:n,onExit:()=>t()})).waitUntilExit(),await e}var Iu,Fu,Mi=H(()=>{"use strict";Iu={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Fu={healthy:"green",unhealthy:"red",unknown:"gray"}});var Li={};Ct(Li,{buildServiceArtifact:()=>ji,installServiceArtifact:()=>Gu});import _i from"node:fs";import Di from"node:os";import Xt from"node:path";import{fileURLToPath as qu}from"node:url";function xn(){return process.execPath}function Tn(){let n=Xt.dirname(qu(import.meta.url));return Xt.join(n,"main.js")}function ji(){let n=process.platform;if(n==="win32"){let r=`<?xml version="1.0" encoding="UTF-8"?>
|
|
106
110
|
<!-- generated by daimon daemon install-service -->
|
|
107
111
|
<service>
|
|
108
112
|
<id>daimon</id>
|
|
109
113
|
<name>daimon daemon</name>
|
|
110
114
|
<description>Local Angular/Nx/Vite dev server manager (daimon headless daemon)</description>
|
|
111
|
-
<executable>${
|
|
112
|
-
<arguments>"${
|
|
115
|
+
<executable>${xn()}</executable>
|
|
116
|
+
<arguments>"${Tn()}" --headless</arguments>
|
|
113
117
|
<log mode="rotate"/>
|
|
114
118
|
<onfailure action="restart" delay="10 sec"/>
|
|
115
119
|
</service>
|
|
116
|
-
`,s=
|
|
120
|
+
`,s=Xt.join(bt(),"daimon-daemon.xml");return{platform:n,path:s,body:r,installCmd:`nssm install daimon "${xn()}" "${Tn()}" --headless`}}if(n==="darwin"){let r=`<?xml version="1.0" encoding="UTF-8"?>
|
|
117
121
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
118
122
|
<plist version="1.0">
|
|
119
123
|
<dict>
|
|
120
124
|
<key>Label</key><string>dev.daimon</string>
|
|
121
125
|
<key>ProgramArguments</key>
|
|
122
126
|
<array>
|
|
123
|
-
<string>${
|
|
124
|
-
<string>${
|
|
127
|
+
<string>${xn()}</string>
|
|
128
|
+
<string>${Tn()}</string>
|
|
125
129
|
<string>--headless</string>
|
|
126
130
|
</array>
|
|
127
131
|
<key>RunAtLoad</key><true/>
|
|
128
132
|
<key>KeepAlive</key><true/>
|
|
129
|
-
<key>StandardOutPath</key><string>${
|
|
130
|
-
<key>StandardErrorPath</key><string>${
|
|
133
|
+
<key>StandardOutPath</key><string>${Xt.join(bt(),"service.out.log")}</string>
|
|
134
|
+
<key>StandardErrorPath</key><string>${Xt.join(bt(),"service.err.log")}</string>
|
|
131
135
|
</dict>
|
|
132
136
|
</plist>
|
|
133
|
-
`,s=
|
|
137
|
+
`,s=Xt.join(Di.homedir(),"Library","LaunchAgents","dev.daimon.plist");return{platform:n,path:s,body:r,installCmd:`launchctl load ${s}`}}let t=`[Unit]
|
|
134
138
|
Description=daimon daemon (local dev-server manager)
|
|
135
139
|
After=network.target
|
|
136
140
|
|
|
137
141
|
[Service]
|
|
138
|
-
ExecStart=${
|
|
142
|
+
ExecStart=${xn()} ${Tn()} --headless
|
|
139
143
|
Restart=on-failure
|
|
140
144
|
RestartSec=10
|
|
141
145
|
|
|
142
146
|
[Install]
|
|
143
147
|
WantedBy=default.target
|
|
144
|
-
`,e=
|
|
145
|
-
`,"utf8"),{path:o,installClaude:!1,config:
|
|
146
|
-
`),(await
|
|
147
|
-
`,"utf8"),process.stdout.write(`[daimon init] wrote ${
|
|
148
|
-
`);let R=(await Vt(e,"Install Claude Code integration? [Y/n] ")||"y").toLowerCase().startsWith("y");return{path:f,installClaude:R,config:g}}finally{e.close()}}var yu,Si=U(()=>{"use strict";yu=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs",".storybook"]});ee();qt();import Pi from"node:os";import Ae from"node:path";ke();xe();Ie();import Gt from"node:fs";import se from"node:path";async function _r(n,t){let e=[],r=new Set(t.map(l=>l.name));for(let l of n.searchRoots){let u=typeof l=="string"?l:l.path,d=se.resolve(u);if(!Gt.existsSync(d)){e.push({name:`searchRoot exists: ${d}`,ok:!1,detail:"not found"});continue}let f=Gt.existsSync(se.join(d,"nx.json"))||Gt.existsSync(se.join(d,"angular.json"))||Gt.existsSync(se.join(d,".storybook"))||["ts","js","mjs","cjs"].some(g=>Gt.existsSync(se.join(d,`vite.config.${g}`)));e.push({name:`searchRoot has marker: ${d}`,ok:f,detail:f?void 0:"no nx.json/angular.json/vite.config.*/.storybook"})}for(let[l,u]of Object.entries(n.overrides??{})){let d=r.has(l),f=!!u.command,g=d||f;e.push({name:`override "${l}"`,ok:g,detail:g?void 0:"unknown app and no command override"})}let s=Object.entries(n.overrides??{}).filter(([,l])=>typeof l.port=="number").map(([l,u])=>({name:l,port:u.port})),o=new Map;for(let l of s)o.has(l.port)?e.push({name:`port pin ${l.port}`,ok:!1,detail:`collision: ${o.get(l.port)} and ${l.name}`}):o.set(l.port,l.name);s.length&&!e.some(l=>l.name.startsWith("port pin"))&&e.push({name:"pinned ports",ok:!0});for(let l of n.autoStart??[])e.push({name:`autoStart "${l}"`,ok:r.has(l),detail:r.has(l)?void 0:"unknown app"});for(let[l,u]of Object.entries(n.profiles??{}))for(let d of u)e.push({name:`profile "${l}" entry "${d}"`,ok:r.has(d),detail:r.has(d)?void 0:"unknown app"});if(n.depends&&Object.keys(n.depends).length){for(let[u,d]of Object.entries(n.depends))for(let f of d)r.has(f)||e.push({name:`depends "${u}" -> "${f}"`,ok:!1,detail:"unknown app"});let l=_e(n.depends);l?e.push({name:"depends DAG",ok:!1,detail:`cycle: ${l.join(" -> ")}`}):e.push({name:"depends DAG",ok:!0})}let i=new Set(t.map(l=>l.workspaceRoot));for(let l of i){let u=se.join(l,"node_modules");e.push({name:`node_modules: ${l}`,ok:Gt.existsSync(u),detail:Gt.existsSync(u)?void 0:"missing"})}let a=await Mt(n.apiPort);if(e.push({name:`apiPort ${n.apiPort}`,ok:a,detail:a?void 0:"in use (may be held by us)"}),n.history.enabled){let l=!1,u;try{let d=new jt(n.history);l=d.quickCheck(),d.close(),l||(u="quick_check failed")}catch(d){u=d?.message||String(d)}e.push({name:"history db",ok:l,detail:u})}return e.push({name:"agent token footprint",ok:!0,detail:Ji(t)}),{ok:e.every(l=>l.ok),checks:e}}function Ji(n){let t=n.length,e=120,r=34,s=285,o=e+t*r,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}%`}On();Nn();Pt();_t();var Wr=[{id:"lifecycle",title:"lifecycle"},{id:"queries",title:"queries"},{id:"agent",title:"agent verbs"},{id:"introspection",title:"introspection"},{id:"config",title:"config"},{id:"claude",title:"claude"},{id:"plugin",title:"plugin"}],q=[{code:0,meaning:"success"},{code:1,meaning:"error"}],ae=[...q,{code:2,meaning:"target state not reached within --timeout"}],vt=[{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).",description:"List discovered apps. Compact JSON is the default; pass --full for the v0.4-shape full snapshot. --stream emits NDJSON until SIGINT. --explain wraps the response with _meta describing discovery.",example:"daimon list",examples:["daimon list","daimon list --tag web","daimon list --full --workspace fullstack","daimon list --stream"],options:[{flag:"--tag",arg:"<name>",description:"Filter to apps carrying this tag (repeatable)."},{flag:"--workspace",arg:"<label>",description:"Filter to a workspace label."},{flag:"--full",description:"Emit the full v0.4-shape snapshot per app."},{flag:"--compact",description:"Emit compact JSON (default)."},{flag:"--stream",description:"NDJSON stream until SIGINT."},{flag:"--explain",description:"Wrap with discovery _meta (searchRoots, scanned, rejected, suggestion)."}],needsDaemon:!0,group:"queries",aliases:["ls"],exitCodes:q},{name:"status",args:"<name> [--full|--compact]",summary:"Get the current status of one app. Compact by default.",description:"Show the current status of one app. Compact JSON is the default.",example:"daimon status web-admin",options:[{flag:"--full",description:"Full v0.4-shape snapshot."},{flag:"--compact",description:"Compact JSON (default)."}],needsDaemon:!0,group:"queries",aliases:["ps"],exitCodes:q},{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}).",description:"Deduplicated parsed errors for an app. Compact JSON by default.",example:"daimon errors web-admin --since 5m",options:[{flag:"--since",arg:"<duration>",description:"Time window (e.g. 30s, 5m, 1h)."},{flag:"--since-last",description:"Only errors since the previous --since-last call (per --client)."},{flag:"--client",arg:"<id>",description:"Cursor identity for --since-last."},{flag:"--structured",description:"Emit only parsed {file,line,col,code,message} rows."},{flag:"--full",description:"Full per-error entries."},{flag:"--compact",description:"Compact JSON (default)."}],needsDaemon:!0,group:"queries",exitCodes:q},{name:"events",args:"[--since 1h] [--app <name>] [--stream]",summary:"Get the event log. --stream emits NDJSON until SIGINT.",description:"Get the global event log. --stream emits NDJSON until SIGINT. Filter to a single app with --app.",example:"daimon events --since 1h",options:[{flag:"--since",arg:"<duration>",description:"Time window."},{flag:"--app",arg:"<name>",description:"Filter to a single app."},{flag:"--stream",description:"NDJSON stream."}],needsDaemon:!0,group:"queries",exitCodes:q},{name:"wait",args:"<name> [--until serving|healthy|stopped|error] [--timeout 60s]",summary:"Block until app reaches the given state.",description:"Block until an app reaches the given terminal state. Exits 2 on timeout.",example:"daimon wait web-admin --until healthy",options:[{flag:"--until",arg:"<state>",description:"Target state (serving|healthy|stopped|error). Default: serving."},{flag:"--timeout",arg:"<duration>",description:"Max wait, parsed as 60s/5m (default 60s)."}],needsDaemon:!0,group:"agent",exitCodes:ae},{name:"ensure",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"One-call: start if needed, block to target state, return terminal state. Idempotent.",description:"Idempotent start+wait: starts the app if not already serving, then blocks until --until is reached.",example:"daimon ensure web-admin",options:[{flag:"--until",arg:"<state>",description:"Target state (serving|healthy). Default: healthy."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ae},{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.",description:"Cascade-start every app in the profile and wait for each to reach the target state.",example:"daimon ensure-up fullstack",options:[{flag:"--until",arg:"<state>",description:"serving|healthy (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Global budget (default 300s)."}],needsDaemon:!0,group:"agent",exitCodes:ae},{name:"overview",args:"[--workspace <label>] [--profile <name>] [--budget <tokens>]",summary:"Decision-ready snapshot: totals, byStatus, needsAttention (with first parsed error), recentlyChanged. First call in a session. --budget caps the response size for agents; overflow collapses to _meta.omitted.",description:"Decision-ready snapshot \u2014 totals, byStatus, needsAttention (with first parsed error), recentlyChanged. Designed as the first call in an agent session.",example:"daimon overview --budget 1500",options:[{flag:"--workspace",arg:"<label>",description:"Filter to one workspace label."},{flag:"--profile",arg:"<name>",description:"Filter to apps in this profile."},{flag:"--budget",arg:"<tokens>",description:"Cap response size; overflow collapses to _meta.omitted."}],needsDaemon:!0,group:"agent",exitCodes:q},{name:"focus",args:"<name> [--until serving|healthy|stable] [--timeout 180s]",summary:"One round-trip subscribe-then-act: streams NDJSON of status/error/url events for one app until target state or timeout. Designed for agents.",description:"Subscribe-then-act: stream NDJSON of status/error/url events for one app until --until or --timeout.",example:"daimon focus web-admin --until stable",options:[{flag:"--until",arg:"<state>",description:"serving|healthy|stable (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ae},{name:"try-fix",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"Composite: run doctor --auto-fix on permitted rules, restart the app, wait for target, return {before,after,fixed,stillFailing}. Never edits user source.",description:"Run doctor --auto-fix on permitted rules, restart the app, wait for target. Never edits user source.",example:"daimon try-fix web-admin",options:[{flag:"--until",arg:"<state>",description:"serving|healthy (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ae},{name:"orchestrate",args:"<profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]",summary:"Bring up a whole profile in one call: cascade-start, wait for goal, run ONE try-fix round on stragglers. Returns {profile, goal, perApp, totalMs, allReached}. --dry-run reports planned order only. Designed for agents.",description:"Bring up a whole profile in one call: cascade-start, wait, one try-fix round on stragglers.",example:"daimon orchestrate fullstack --goal stable",options:[{flag:"--goal",arg:"<state>",description:"serving|healthy|stable (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Global budget (default 300s)."},{flag:"--dry-run",description:"Print planned order without executing."},{flag:"--budget",arg:"<tokens>",description:"Cap response size."}],needsDaemon:!0,group:"agent",exitCodes:ae},{name:"pin-health",args:"<name> [--accept] [--path <p>]",summary:"Show the auto-discovered health-probe path for an app; --accept persists it as overrides.<name>.healthProbePath in daimon.config.json and soft-reloads. Default behaviour is opt-in: nothing is written without --accept.",description:"Show the auto-discovered health-probe path for an app. --accept persists it to daimon.config.json.",example:"daimon pin-health api --accept",options:[{flag:"--accept",description:"Persist the candidate path to overrides.<name>.healthProbePath."},{flag:"--path",arg:"<p>",description:"Override the candidate path explicitly."}],needsDaemon:!0,group:"config",exitCodes:q},{name:"logs",args:"<name> [--tail N] [--since 30s]",summary:"Recent log lines for an app.",description:"Recent log lines for an app.",example:"daimon logs web-admin --tail 100",options:[{flag:"--tail",arg:"<N>",description:"Last N lines (default 50)."},{flag:"--since",arg:"<duration>",description:"Time window."}],needsDaemon:!0,group:"queries",aliases:["log"],exitCodes:q},{name:"start",args:"<name> [--with-deps]",summary:"Start an app.",description:"Start an app.",example:"daimon start web-admin",options:[{flag:"--with-deps",description:"Also start declared dependencies."}],needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"stop",args:"<name>",summary:"Stop an app.",description:"Stop an app.",example:"daimon stop web-admin",needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"restart",args:"<name>",summary:"Restart an app.",description:"Restart an app.",example:"daimon restart web-admin",needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"up",args:"[<profile>]",summary:"Start a profile (or autoStart). Waits for each to reach serving.",description:"Start a profile (or autoStart). Waits for each to reach serving.",example:"daimon up fullstack",needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"down",args:"[<profile>]",summary:"Stop a profile (or all apps).",description:"Stop a profile (or all apps).",example:"daimon down",needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"history",args:"<name>",summary:"Summary metrics (uptime%, restarts, compile p50/p95, top errors).",description:"Summary metrics for an app (uptime%, restarts, compile p50/p95, top errors).",example:"daimon history web-admin",needsDaemon:!0,group:"queries",exitCodes:q},{name:"why",args:"<name>",summary:"Last status transition + 5 preceding events.",description:"Explain the most recent state transition with the 5 events leading up to it.",example:"daimon why web-admin",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"why-empty",args:"",summary:"Explain why `daimon list` is empty: configured searchRoots, scanned/rejected counts, suggested next step.",description:"Explain why `daimon list` is empty \u2014 search roots, scanned/rejected counts, suggestion.",example:"daimon why-empty",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"discover",args:"[--dry-run]",summary:"Run discovery without changing state. Prints _meta: searchRoots, scanned, rejected per folder, suggestion.",description:"Run discovery without changing state. Emits per-folder scanned/rejected and suggestion.",example:"daimon discover --dry-run",options:[{flag:"--dry-run",description:"Report planned discovery without persisting."}],needsDaemon:!0,group:"introspection",exitCodes:q},{name:"export-config",args:"[--redacted]",summary:'Emit the active config to stdout. --redacted replaces apiToken with "<redacted>" and rewrites home paths to ~/...',description:'Emit the active config to stdout. --redacted replaces apiToken with "<redacted>" and home paths with ~/...',example:"daimon export-config --redacted",options:[{flag:"--redacted",description:"Replace apiToken and home paths."}],needsDaemon:!1,group:"config",exitCodes:q},{name:"tasks",args:"<name>",summary:"List discovered non-serve tasks.",description:"List discovered non-serve tasks for an app.",example:"daimon tasks web-admin",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"run",args:"<name> <task> [--watch] [-- args...]",summary:"Run a discovered task.",description:"Run a discovered task. Pass extra args after `--`.",example:"daimon run web-admin test",options:[{flag:"--watch",description:"Keep running and stream output."}],needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"snapshot",args:"<name>",summary:"Write a snapshot of app state to ~/.daimon/snapshots.",description:"Write a diagnostic snapshot of app state to ~/.daimon/snapshots.",example:"daimon snapshot web-admin",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"env",args:"<name> [--use <file>]",summary:"List or set the active env file for an app.",description:"List or set the active env file for an app.",example:"daimon env web-admin --use .env.staging",options:[{flag:"--use",arg:"<file>",description:"Activate an env file for the app."}],needsDaemon:!0,group:"config",exitCodes:q},{name:"clean",args:"<name> [--deep] [--yes]",summary:"Remove build artifacts for an app.",description:"Remove build artifacts for an app. --deep also removes node_modules; --yes skips the confirmation prompt.",example:"daimon clean web-admin --yes",options:[{flag:"--deep",description:"Also remove node_modules / language-specific deps caches."},{flag:"--yes",description:"Skip confirmation prompt."}],needsDaemon:!0,group:"lifecycle",exitCodes:q},{name:"record",args:"",summary:"Toggle session recording.",description:"Toggle JSONL session recording (~/.daimon/sessions).",example:"daimon record",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"replay",args:"<session.jsonl> [--speed N]",summary:"Replay a recorded session.",description:"Replay a recorded session.",example:"daimon replay session.jsonl",options:[{flag:"--speed",arg:"<N>",description:"Speed multiplier (default 1)."}],needsDaemon:!0,group:"introspection",exitCodes:q},{name:"doctor",args:"[--auto-fix] [--dry-run] [--self]",summary:"Sanity-check config + env. --auto-fix repairs orphan daemon, stale lock, missing search root, corrupt history db. --self checks daimon's own metrics.",description:"Sanity-check config + env. --auto-fix repairs known issues; --dry-run shows what would change. --self runs the self-observability checks (heap, event-loop lag, history.db query p95).",example:"daimon doctor --auto-fix",options:[{flag:"--auto-fix",description:"Apply permitted repairs."},{flag:"--dry-run",description:"Report planned changes without writing."},{flag:"--self",description:"Run self-observability checks against the running daemon."}],needsDaemon:!1,group:"introspection",exitCodes:q},{name:"free-port",args:"<port> [--force]",summary:"Diagnose / free a port.",description:"Show which process is holding a port. --force kills it.",example:"daimon free-port 4200 --force",options:[{flag:"--force",description:"Kill the holder."}],needsDaemon:!1,group:"introspection",exitCodes:q},{name:"daemon",args:"start|stop|status|restart|attach|install-service [--detach] [--headless]",summary:"Manage the daimon daemon.",description:"Manage the daimon daemon lifecycle.",example:"daimon daemon status",options:[{flag:"--detach",description:"Spawn detached (for `start`)."},{flag:"--headless",description:"Start without the TUI (for `start`)."}],needsDaemon:!1,group:"lifecycle",exitCodes:q},{name:"claude",args:"install|update|uninstall|status [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]",summary:"Install/update Claude Code integration artifacts.",description:"Install/update/uninstall the Claude Code integration artifacts.",example:"daimon claude install --all",needsDaemon:!1,group:"claude",exitCodes:q},{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.",description:"Create a daimon config in cwd. --auto picks safe defaults for known workspace markers.",example:"daimon init --auto",options:[{flag:"--force",description:"Overwrite an existing daimon.config.json."},{flag:"--auto",description:"Skip prompts; pick safe defaults."}],needsDaemon:!1,group:"config",exitCodes:q},{name:"completion",args:"<bash|zsh|fish|powershell>",summary:"Emit a shell completion script for the given shell.",description:"Emit a shell-completion script for bash, zsh, fish, or PowerShell. Pipe the output to the appropriate per-shell location (see README).",example:"daimon completion bash > /etc/bash_completion.d/daimon",needsDaemon:!1,group:"config",exitCodes:q},{name:"plugin",args:"list|show <name>|validate <path>",summary:"Manage doctor plug-ins.",description:"Manage doctor plug-ins. `list` shows installed plug-ins with status; `show <name>` prints a plug-in manifest; `validate <path>` sanity-checks a plug-in file.",example:"daimon plugin list",needsDaemon:!0,group:"plugin",exitCodes:q},{name:"self",args:"",summary:"Print daimon's own runtime metrics (pid, version, uptime, rss, heap, event-loop lag, history-db p95).",description:"Print daimon's own runtime metrics. Useful for bug reports.",example:"daimon self",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"workspaces",args:"list|add [path] [--label <name>] | rm <path> | show [path]",summary:"Manage the workspace registry (searchRoots).",description:"List, add, remove, and inspect workspaces. `add` ensures the given path (defaults to cwd) is a registered searchRoot. `show` reports which workspace covers a cwd.",example:"daimon workspaces list",needsDaemon:!0,group:"config",exitCodes:q},{name:"dashboard",args:"",summary:"Open the dashboard in your default browser, scoped to the current cwd.",description:"Open http://127.0.0.1:4999/?cwd=<process.cwd()> in the default browser. The dashboard pre-selects the workspace pill covering cwd.",example:"daimon dashboard",needsDaemon:!0,group:"introspection",exitCodes:q},{name:"timeline",args:"[--since 7d] [--app <name>] [--kinds status,error,warning,lint,bundle,task]",summary:"Print a unified chronological event timeline.",description:"Merge status / error / warning / lint / bundle / task / health rows into one chronological stream. JSON output suits piping; use `daimon dashboard` then /timeline for the visual view.",example:"daimon timeline --since 24h --kinds status,error",needsDaemon:!0,group:"introspection",exitCodes:q}],St={};for(let n of vt)for(let t of n.aliases??[])St[t]=n.name;function We(n){let t=St[n]??n;return vt.find(e=>e.name===t)}function qr(){let n=Math.max(...vt.map(t=>t.name.length));return vt.map(t=>`${t.name.padEnd(n)} ${t.summary}`).join(`
|
|
149
|
-
`)}
|
|
150
|
-
`)}function
|
|
151
|
-
`)}function
|
|
152
|
-
`)}var
|
|
148
|
+
`,e=Xt.join(Di.homedir(),".config","systemd","user","daimon.service");return{platform:n,path:e,body:t,installCmd:"systemctl --user enable daimon && systemctl --user start daimon"}}function Gu(){let n=ji();return _i.mkdirSync(Xt.dirname(n.path),{recursive:!0}),_i.writeFileSync(n.path,n.body,"utf8"),{path:n.path,installCmd:n.installCmd,platform:n.platform}}var Ii=H(()=>{"use strict";Nt()});var Ui={};Ct(Ui,{runInit:()=>Yu,runInitAuto:()=>Bi});import Kt from"node:fs";import Xu from"node:os";import ae from"node:path";import Ku from"node:readline";function ie(n,t){return new Promise(e=>n.question(t,r=>e(r.trim())))}function Fi(n){let t=[];for(let e of zu)Kt.existsSync(ae.join(n,e))&&t.push(e);return t}async function Bi(n={}){let t=n.cwd??process.cwd(),e=Fi(t),r=[],s;try{let l=JSON.parse(Kt.readFileSync(ae.join(t,"package.json"),"utf8"));typeof l.name=="string"&&(s=l.name)}catch{}e.length&&r.push(s?{path:t,label:s}:t);let o=ae.join(t,"daimon.config.json");if(Kt.existsSync(o)&&!n.force)throw new Error(`refusing to overwrite ${o} (pass --force to overwrite)`);let a={searchRoots:r,portRange:[4200,4299],apiPort:4999};return Kt.mkdirSync(ae.dirname(o),{recursive:!0}),Kt.writeFileSync(o,JSON.stringify(a,null,2)+`
|
|
149
|
+
`,"utf8"),{path:o,installClaude:!1,config:a,auto:!0}}async function Yu(n={}){if(n.auto)return Bi(n);let t=n.cwd??process.cwd(),e=Ku.createInterface({input:process.stdin,output:process.stdout});try{let r=Fi(t),s=[];if(r.length&&(process.stdout.write(`[daimon init] detected in ${t}: ${r.join(", ")}
|
|
150
|
+
`),(await ie(e,"Add this folder as a searchRoot? [Y/n] ")||"y").toLowerCase().startsWith("y"))){let w=await ie(e,"Optional label for this workspace (blank = none): ");s.push(w?{path:t,label:w}:t)}let o=await ie(e,"Additional searchRoots (comma-separated absolute paths, blank to skip): ");if(o)for(let T of o.split(",").map(w=>w.trim()).filter(Boolean))s.push(T);let l=(await ie(e,"Port range [4200-4299]: ")||"4200-4299").match(/^(\d+)\s*[-,\s]\s*(\d+)$/),i=l?[Number(l[1]),Number(l[2])]:[4200,4299],c=await ie(e,"apiPort [4999]: ")||"4999",u=Number(c)||4999,m=(await ie(e,"Write to (1) ./daimon.config.json or (2) ~/.daimon/config.json? [1] ")||"1").trim()==="2"?ae.join(Xu.homedir(),".daimon","config.json"):ae.join(t,"daimon.config.json");if(Kt.existsSync(m)&&!n.force)throw new Error(`refusing to overwrite ${m} (pass --force to overwrite)`);let g={searchRoots:s,portRange:i,apiPort:u};Kt.mkdirSync(ae.dirname(m),{recursive:!0}),Kt.writeFileSync(m,JSON.stringify(g,null,2)+`
|
|
151
|
+
`,"utf8"),process.stdout.write(`[daimon init] wrote ${m}
|
|
152
|
+
`);let x=(await ie(e,"Install Claude Code integration? [Y/n] ")||"y").toLowerCase().startsWith("y");return{path:m,installClaude:x,config:g}}finally{e.close()}}var zu,Hi=H(()=>{"use strict";zu=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs",".storybook"]});de();Zt();import qi from"node:os";import je from"node:path";Ae();Ee();He();Ln();import Ut from"node:fs";import Ht from"node:path";async function Xr(n,t){let e=[],r=new Set(t.map(c=>c.name));for(let c of n.searchRoots){let u=typeof c=="string"?c:c.path,p=Ht.resolve(u);if(!Ut.existsSync(p)){e.push({name:`searchRoot exists: ${p}`,ok:!1,detail:"not found"});continue}let m=Ut.existsSync(Ht.join(p,"nx.json"))||Ut.existsSync(Ht.join(p,"angular.json"))||Ut.existsSync(Ht.join(p,".storybook"))||["ts","js","mjs","cjs"].some(g=>Ut.existsSync(Ht.join(p,`vite.config.${g}`)));e.push({name:`searchRoot has marker: ${p}`,ok:m,detail:m?void 0:"no nx.json/angular.json/vite.config.*/.storybook"})}for(let[c,u]of Object.entries(n.overrides??{})){let p=r.has(c),m=!!u.command,g=p||m;e.push({name:`override "${c}"`,ok:g,detail:g?void 0:"unknown app and no command override"})}let s=Object.entries(n.overrides??{}).filter(([,c])=>typeof c.port=="number").map(([c,u])=>({name:c,port:u.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 n.autoStart??[])e.push({name:`autoStart "${c}"`,ok:r.has(c),detail:r.has(c)?void 0:"unknown app"});for(let[c,u]of Object.entries(n.profiles??{}))for(let p of u)e.push({name:`profile "${c}" entry "${p}"`,ok:r.has(p),detail:r.has(p)?void 0:"unknown app"});if(n.depends&&Object.keys(n.depends).length){for(let[u,p]of Object.entries(n.depends))for(let m of p)r.has(m)||e.push({name:`depends "${u}" -> "${m}"`,ok:!1,detail:"unknown app"});let c=Fe(n.depends);c?e.push({name:"depends DAG",ok:!1,detail:`cycle: ${c.join(" -> ")}`}):e.push({name:"depends DAG",ok:!0})}let a=new Set(t.map(c=>c.workspaceRoot));for(let c of a){let u=Ht.join(c,"node_modules");e.push({name:`node_modules: ${c}`,ok:Ut.existsSync(u),detail:Ut.existsSync(u)?void 0:"missing"})}let l=await Bt(n.apiPort);if(e.push({name:`apiPort ${n.apiPort}`,ok:l,detail:l?void 0:"in use (may be held by us)"}),n.history.enabled){let c=!1,u;try{let p=new Lt(n.history);c=p.quickCheck();let m=p.archivedCorruptDbPath();p.close(),c?m&&(u=`rebuilt fresh; previous db archived at ${m}`):u="quick_check failed"}catch(p){u=p?.message||String(p)}e.push({name:"history db",ok:c,detail:u});try{let p=Ht.dirname(n.history.path),m=Ht.basename(n.history.path),g=Ut.readdirSync(p).filter(S=>S.startsWith(m+".corrupt-"));g.length>0?e.push({name:"history-db-healthy",ok:!0,detail:`${g.length} archived corrupt snapshot${g.length===1?"":"s"} present (${g.slice(0,2).join(", ")}${g.length>2?", \u2026":""}). Safe to delete after review.`}):e.push({name:"history-db-healthy",ok:!0})}catch{e.push({name:"history-db-healthy",ok:!0})}}if(n.history.enabled)try{let c=new Lt(n.history),u=Date.now()-10080*6e4,p=c.queryEvents({since:u,type:"status",limit:2e4});c.close();let m=jn(p.map(g=>({ts:g.ts,app:g.app,type:g.type,to_state:g.to_state,from_state:g.from_state})),7,5);if(m.length===0)e.push({name:"smart-restart-tune",ok:!0});else for(let g of m)e.push({name:`smart-restart-tune: ${g.app}`,ok:!1,detail:g.reason})}catch(c){e.push({name:"smart-restart-tune",ok:!0,detail:`skipped: ${c?.message||c}`})}return e.push({name:"agent token footprint",ok:!0,detail:ca(t)}),{ok:e.every(c=>c.ok),checks:e}}function ca(n){let t=n.length,e=120,r=34,s=285,o=e+t*r,a=e+t*s,l=t>0?Math.round((1-o/a)*100):0;return`skill=${e} tokens \xB7 daimon list (${t} apps) \u2248 ${o} tokens compact / ${a} tokens full \xB7 savings: ~${l}%`}Fn();Bn();Nt();Jt();Wn();var ss=[{id:"lifecycle",title:"lifecycle"},{id:"queries",title:"queries"},{id:"agent",title:"agent verbs"},{id:"introspection",title:"introspection"},{id:"config",title:"config"},{id:"claude",title:"claude"},{id:"plugin",title:"plugin"}],G=[{code:0,meaning:"success"},{code:1,meaning:"error"}],ee=[...G,{code:2,meaning:"target state not reached within --timeout"}],Rt=[{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).",description:"List discovered apps. Compact JSON is the default; pass --full for the v0.4-shape full snapshot. --stream emits NDJSON until SIGINT. --explain wraps the response with _meta describing discovery.",example:"daimon list",examples:["daimon list","daimon list --tag web","daimon list --full --workspace fullstack","daimon list --stream"],options:[{flag:"--tag",arg:"<name>",description:"Filter to apps carrying this tag (repeatable)."},{flag:"--workspace",arg:"<label>",description:"Filter to a workspace label."},{flag:"--full",description:"Emit the full v0.4-shape snapshot per app."},{flag:"--compact",description:"Emit compact JSON (default)."},{flag:"--stream",description:"NDJSON stream until SIGINT."},{flag:"--explain",description:"Wrap with discovery _meta (searchRoots, scanned, rejected, suggestion)."}],needsDaemon:!0,group:"queries",aliases:["ls"],exitCodes:G},{name:"status",args:"<name> [--full|--compact]",summary:"Get the current status of one app. Compact by default.",description:"Show the current status of one app. Compact JSON is the default.",example:"daimon status web-admin",options:[{flag:"--full",description:"Full v0.4-shape snapshot."},{flag:"--compact",description:"Compact JSON (default)."}],needsDaemon:!0,group:"queries",aliases:["ps"],exitCodes:G},{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}).",description:"Deduplicated parsed errors for an app. Compact JSON by default.",example:"daimon errors web-admin --since 5m",options:[{flag:"--since",arg:"<duration>",description:"Time window (e.g. 30s, 5m, 1h)."},{flag:"--since-last",description:"Only errors since the previous --since-last call (per --client)."},{flag:"--client",arg:"<id>",description:"Cursor identity for --since-last."},{flag:"--structured",description:"Emit only parsed {file,line,col,code,message} rows."},{flag:"--full",description:"Full per-error entries."},{flag:"--compact",description:"Compact JSON (default)."}],needsDaemon:!0,group:"queries",exitCodes:G},{name:"events",args:"[--since 1h] [--app <name>] [--stream]",summary:"Get the event log. --stream emits NDJSON until SIGINT.",description:"Get the global event log. --stream emits NDJSON until SIGINT. Filter to a single app with --app.",example:"daimon events --since 1h",options:[{flag:"--since",arg:"<duration>",description:"Time window."},{flag:"--app",arg:"<name>",description:"Filter to a single app."},{flag:"--stream",description:"NDJSON stream."}],needsDaemon:!0,group:"queries",exitCodes:G},{name:"wait",args:"<name> [--until serving|healthy|stopped|error] [--timeout 60s]",summary:"Block until app reaches the given state.",description:"Block until an app reaches the given terminal state. Exits 2 on timeout.",example:"daimon wait web-admin --until healthy",options:[{flag:"--until",arg:"<state>",description:"Target state (serving|healthy|stopped|error). Default: serving."},{flag:"--timeout",arg:"<duration>",description:"Max wait, parsed as 60s/5m (default 60s)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"ensure",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"One-call: start if needed, block to target state, return terminal state. Idempotent.",description:"Idempotent start+wait: starts the app if not already serving, then blocks until --until is reached.",example:"daimon ensure web-admin",options:[{flag:"--until",arg:"<state>",description:"Target state (serving|healthy). Default: healthy."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{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.",description:"Cascade-start every app in the profile and wait for each to reach the target state.",example:"daimon ensure-up fullstack",options:[{flag:"--until",arg:"<state>",description:"serving|healthy (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Global budget (default 300s)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"overview",args:"[--workspace <label>] [--profile <name>] [--budget <tokens>]",summary:"Decision-ready snapshot: totals, byStatus, needsAttention (with first parsed error), recentlyChanged. First call in a session. --budget caps the response size for agents; overflow collapses to _meta.omitted.",description:"Decision-ready snapshot \u2014 totals, byStatus, needsAttention (with first parsed error), recentlyChanged. Designed as the first call in an agent session.",example:"daimon overview --budget 1500",options:[{flag:"--workspace",arg:"<label>",description:"Filter to one workspace label."},{flag:"--profile",arg:"<name>",description:"Filter to apps in this profile."},{flag:"--budget",arg:"<tokens>",description:"Cap response size; overflow collapses to _meta.omitted."}],needsDaemon:!0,group:"agent",exitCodes:G},{name:"focus",args:"<name> [--until serving|healthy|stable] [--timeout 180s]",summary:"One round-trip subscribe-then-act: streams NDJSON of status/error/url events for one app until target state or timeout. Designed for agents.",description:"Subscribe-then-act: stream NDJSON of status/error/url events for one app until --until or --timeout.",example:"daimon focus web-admin --until stable",options:[{flag:"--until",arg:"<state>",description:"serving|healthy|stable (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"try-fix",args:"<name> [--until serving|healthy] [--timeout 180s]",summary:"Composite: run doctor --auto-fix on permitted rules, restart the app, wait for target, return {before,after,fixed,stillFailing}. Never edits user source.",description:"Run doctor --auto-fix on permitted rules, restart the app, wait for target. Never edits user source.",example:"daimon try-fix web-admin",options:[{flag:"--until",arg:"<state>",description:"serving|healthy (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Max wait (default 180s)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"orchestrate",args:"<profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]",summary:"Bring up a whole profile in one call: cascade-start, wait for goal, run ONE try-fix round on stragglers. Returns {profile, goal, perApp, totalMs, allReached}. --dry-run reports planned order only. Designed for agents.",description:"Bring up a whole profile in one call: cascade-start, wait, one try-fix round on stragglers.",example:"daimon orchestrate fullstack --goal stable",options:[{flag:"--goal",arg:"<state>",description:"serving|healthy|stable (default: healthy)."},{flag:"--timeout",arg:"<duration>",description:"Global budget (default 300s)."},{flag:"--dry-run",description:"Print planned order without executing."},{flag:"--budget",arg:"<tokens>",description:"Cap response size."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"pin-health",args:"<name> [--accept] [--path <p>]",summary:"Show the auto-discovered health-probe path for an app; --accept persists it as overrides.<name>.healthProbePath in daimon.config.json and soft-reloads. Default behaviour is opt-in: nothing is written without --accept.",description:"Show the auto-discovered health-probe path for an app. --accept persists it to daimon.config.json.",example:"daimon pin-health api --accept",options:[{flag:"--accept",description:"Persist the candidate path to overrides.<name>.healthProbePath."},{flag:"--path",arg:"<p>",description:"Override the candidate path explicitly."}],needsDaemon:!0,group:"config",exitCodes:G},{name:"logs",args:"<name> [--tail N] [--since 30s]",summary:"Recent log lines for an app.",description:"Recent log lines for an app.",example:"daimon logs web-admin --tail 100",options:[{flag:"--tail",arg:"<N>",description:"Last N lines (default 50)."},{flag:"--since",arg:"<duration>",description:"Time window."}],needsDaemon:!0,group:"queries",aliases:["log"],exitCodes:G},{name:"start",args:"<name> [--with-deps] [--steal]",summary:"Start an app. --steal overrides another agent's soft-lock.",description:"Start an app. If another agent holds the soft-lock, this exits 5 unless --steal is passed.",example:"daimon start web-admin",options:[{flag:"--with-deps",description:"Also start declared dependencies."},{flag:"--steal",description:"Override another agent's soft-lock."}],needsDaemon:!0,group:"lifecycle",exitCodes:[...G,{code:5,meaning:"soft-lock held by another agent (pass --steal to override)"}]},{name:"stop",args:"<name> [--steal]",summary:"Stop an app. --steal overrides another agent's soft-lock.",description:"Stop an app. If another agent holds the soft-lock, this exits 5 unless --steal is passed.",example:"daimon stop web-admin",options:[{flag:"--steal",description:"Override another agent's soft-lock."}],needsDaemon:!0,group:"lifecycle",exitCodes:[...G,{code:5,meaning:"soft-lock held by another agent (pass --steal to override)"}]},{name:"restart",args:"<name> [--steal]",summary:"Restart an app. --steal overrides another agent's soft-lock.",description:"Restart an app. If another agent holds the soft-lock, this exits 5 unless --steal is passed.",example:"daimon restart web-admin",options:[{flag:"--steal",description:"Override another agent's soft-lock (default: refuse with exit 5)."}],needsDaemon:!0,group:"lifecycle",exitCodes:[...G,{code:5,meaning:"soft-lock held by another agent (pass --steal to override)"}]},{name:"agents",args:"",summary:"List active agents touching this daemon and any current per-app soft-locks.",description:"Print active agents (id, lastSeen, cwd, callCount) and any per-app soft-locks. Each agent gets a stable per-session id sent on every request; the same id is recorded in the audit log's 6th column.",example:"daimon agents",needsDaemon:!0,group:"agent",exitCodes:G},{name:"handoff",args:"<app> <agentId>",summary:"Transfer the soft-lock on <app> to another agent.",description:`Transfer the per-app soft-lock from this agent (or any holder) to <agentId>. Useful to tell another agent "I'm done \u2014 you can take this".`,example:"daimon handoff web-admin claude-host-1234-abcd",needsDaemon:!0,group:"agent",exitCodes:G},{name:"profiles suggest",args:"[--since 30d] [--min 5]",summary:"Suggest profile candidates from recurring co-starts.",description:"Scan recent status events for app sets the user repeatedly starts together within a short window. Returns suggested profiles with name, apps, cooccurrence count, and last-seen time. Skips clusters that already match an existing profile.",example:"daimon profiles suggest --since 30d --min 5",needsDaemon:!0,group:"agent",exitCodes:G},{name:"up",args:"[<profile>]",summary:"Start a profile (or autoStart). Waits for each to reach serving.",description:"Start a profile (or autoStart). Waits for each to reach serving.",example:"daimon up fullstack",needsDaemon:!0,group:"lifecycle",exitCodes:G},{name:"down",args:"[<profile>]",summary:"Stop a profile (or all apps).",description:"Stop a profile (or all apps).",example:"daimon down",needsDaemon:!0,group:"lifecycle",exitCodes:G},{name:"history",args:"<name>",summary:"Summary metrics (uptime%, restarts, compile p50/p95, top errors).",description:"Summary metrics for an app (uptime%, restarts, compile p50/p95, top errors).",example:"daimon history web-admin",needsDaemon:!0,group:"queries",exitCodes:G},{name:"why",args:"<name>",summary:"Last status transition + 5 preceding events.",description:"Explain the most recent state transition with the 5 events leading up to it.",example:"daimon why web-admin",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"why-empty",args:"",summary:"Explain why `daimon list` is empty: configured searchRoots, scanned/rejected counts, suggested next step.",description:"Explain why `daimon list` is empty \u2014 search roots, scanned/rejected counts, suggestion.",example:"daimon why-empty",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"discover",args:"[--dry-run]",summary:"Run discovery without changing state. Prints _meta: searchRoots, scanned, rejected per folder, suggestion.",description:"Run discovery without changing state. Emits per-folder scanned/rejected and suggestion.",example:"daimon discover --dry-run",options:[{flag:"--dry-run",description:"Report planned discovery without persisting."}],needsDaemon:!0,group:"introspection",exitCodes:G},{name:"export-config",args:"[--redacted]",summary:'Emit the active config to stdout. --redacted replaces apiToken with "<redacted>" and rewrites home paths to ~/...',description:'Emit the active config to stdout. --redacted replaces apiToken with "<redacted>" and home paths with ~/...',example:"daimon export-config --redacted",options:[{flag:"--redacted",description:"Replace apiToken and home paths."}],needsDaemon:!1,group:"config",exitCodes:G},{name:"tasks",args:"<name>",summary:"List discovered non-serve tasks.",description:"List discovered non-serve tasks for an app.",example:"daimon tasks web-admin",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"run",args:"<name> <task> [--watch] [-- args...]",summary:"Run a discovered task.",description:"Run a discovered task. Pass extra args after `--`.",example:"daimon run web-admin test",options:[{flag:"--watch",description:"Keep running and stream output."}],needsDaemon:!0,group:"lifecycle",exitCodes:G},{name:"snapshot",args:"<name>",summary:"Write a snapshot of app state to ~/.daimon/snapshots.",description:"Write a diagnostic snapshot of app state to ~/.daimon/snapshots.",example:"daimon snapshot web-admin",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"env",args:"<name> [--use <file>]",summary:"List or set the active env file for an app.",description:"List or set the active env file for an app.",example:"daimon env web-admin --use .env.staging",options:[{flag:"--use",arg:"<file>",description:"Activate an env file for the app."}],needsDaemon:!0,group:"config",exitCodes:G},{name:"clean",args:"<name> [--deep] [--yes]",summary:"Remove build artifacts for an app.",description:"Remove build artifacts for an app. --deep also removes node_modules; --yes skips the confirmation prompt.",example:"daimon clean web-admin --yes",options:[{flag:"--deep",description:"Also remove node_modules / language-specific deps caches."},{flag:"--yes",description:"Skip confirmation prompt."}],needsDaemon:!0,group:"lifecycle",exitCodes:G},{name:"record",args:"",summary:"Toggle session recording.",description:"Toggle JSONL session recording (~/.daimon/sessions).",example:"daimon record",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"replay",args:"<session.jsonl> [--speed N]",summary:"Replay a recorded session.",description:"Replay a recorded session.",example:"daimon replay session.jsonl",options:[{flag:"--speed",arg:"<N>",description:"Speed multiplier (default 1)."}],needsDaemon:!0,group:"introspection",exitCodes:G},{name:"doctor",args:"[--auto-fix] [--dry-run] [--self]",summary:"Sanity-check config + env. --auto-fix repairs orphan daemon, stale lock, missing search root, corrupt history db. --self checks daimon's own metrics.",description:"Sanity-check config + env. --auto-fix repairs known issues; --dry-run shows what would change. --self runs the self-observability checks (heap, event-loop lag, history.db query p95).",example:"daimon doctor --auto-fix",options:[{flag:"--auto-fix",description:"Apply permitted repairs."},{flag:"--dry-run",description:"Report planned changes without writing."},{flag:"--self",description:"Run self-observability checks against the running daemon."}],needsDaemon:!1,group:"introspection",exitCodes:G},{name:"free-port",args:"<port> [--force]",summary:"Diagnose / free a port.",description:"Show which process is holding a port. --force kills it.",example:"daimon free-port 4200 --force",options:[{flag:"--force",description:"Kill the holder."}],needsDaemon:!1,group:"introspection",exitCodes:G},{name:"daemon",args:"start|stop|status|restart|attach|install-service [--detach] [--headless]",summary:"Manage the daimon daemon.",description:"Manage the daimon daemon lifecycle.",example:"daimon daemon status",options:[{flag:"--detach",description:"Spawn detached (for `start`)."},{flag:"--headless",description:"Start without the TUI (for `start`)."}],needsDaemon:!1,group:"lifecycle",exitCodes:G},{name:"claude",args:"install|update|uninstall|status [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]",summary:"Install/update Claude Code integration artifacts.",description:"Install/update/uninstall the Claude Code integration artifacts.",example:"daimon claude install --all",needsDaemon:!1,group:"claude",exitCodes:G},{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.",description:"Create a daimon config in cwd. --auto picks safe defaults for known workspace markers.",example:"daimon init --auto",options:[{flag:"--force",description:"Overwrite an existing daimon.config.json."},{flag:"--auto",description:"Skip prompts; pick safe defaults."}],needsDaemon:!1,group:"config",exitCodes:G},{name:"completion",args:"<bash|zsh|fish|powershell>",summary:"Emit a shell completion script for the given shell.",description:"Emit a shell-completion script for bash, zsh, fish, or PowerShell. Pipe the output to the appropriate per-shell location (see README).",example:"daimon completion bash > /etc/bash_completion.d/daimon",needsDaemon:!1,group:"config",exitCodes:G},{name:"plugin",args:"list|show <name>|validate <path>",summary:"Manage doctor plug-ins.",description:"Manage doctor plug-ins. `list` shows installed plug-ins with status; `show <name>` prints a plug-in manifest; `validate <path>` sanity-checks a plug-in file.",example:"daimon plugin list",needsDaemon:!0,group:"plugin",exitCodes:G},{name:"self",args:"",summary:"Print daimon's own runtime metrics (pid, version, uptime, rss, heap, event-loop lag, history-db p95).",description:"Print daimon's own runtime metrics. Useful for bug reports.",example:"daimon self",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"workspaces",args:"list|add [path] [--label <name>] | rm <path> | show [path]",summary:"Manage the workspace registry (searchRoots).",description:"List, add, remove, and inspect workspaces. `add` ensures the given path (defaults to cwd) is a registered searchRoot. `show` reports which workspace covers a cwd.",example:"daimon workspaces list",needsDaemon:!0,group:"config",exitCodes:G},{name:"dashboard",args:"",summary:"Open the dashboard in your default browser, scoped to the current cwd.",description:"Open http://127.0.0.1:4999/?cwd=<process.cwd()> in the default browser. The dashboard pre-selects the workspace pill covering cwd.",example:"daimon dashboard",needsDaemon:!0,group:"introspection",exitCodes:G},{name:"ci",args:"start <profile> [--until ready|healthy] [--timeout 5m] [--json]",summary:"CI helper: start a profile and block until all apps are healthy. Designed for GitHub Actions / Jenkins steps.",description:"Start a profile in CI mode and block until each app reaches the target state. Exit 0 on full success, 2 on timeout, 1 on other failure. With --json (default for ci), emits a structured report on stdout: { profile, until, allReached, perApp:[{name, state, reachedTargetMs, timedOut}], totalMs }.",example:"daimon ci start fullstack --until ready --timeout 5m --json",options:[{flag:"--until",arg:"<state>",description:"serving|healthy|ready (alias for healthy). Default: healthy."},{flag:"--timeout",arg:"<duration>",description:"Total budget (default 5m, max 20m)."},{flag:"--json",description:"Force structured JSON report (default for ci)."}],needsDaemon:!0,group:"agent",exitCodes:ee},{name:"timeline",args:"[--since 7d] [--app <name>] [--kinds status,error,warning,lint,bundle,task]",summary:"Print a unified chronological event timeline.",description:"Merge status / error / warning / lint / bundle / task / health rows into one chronological stream. JSON output suits piping; use `daimon dashboard` then /timeline for the visual view.",example:"daimon timeline --since 24h --kinds status,error",needsDaemon:!0,group:"introspection",exitCodes:G}],Pt={};for(let n of Rt)for(let t of n.aliases??[])Pt[t]=n.name;function Ye(n){let t=Pt[n]??n;return Rt.find(e=>e.name===t)}function os(){let n=Math.max(...Rt.map(t=>t.name.length));return Rt.map(t=>`${t.name.padEnd(n)} ${t.summary}`).join(`
|
|
153
|
+
`)}Jt();var qn=null;function is(n){qn=n}function Ve(){return qn==="off"?!1:qn==="on"?!0:process.env.NO_COLOR&&process.env.NO_COLOR!==""?!1:process.env.FORCE_COLOR==="1"||process.env.FORCE_COLOR==="2"||process.env.FORCE_COLOR==="3"?!0:!!process.stdout.isTTY}var ne={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m"};function ye(n,t){return Ve()?t+n+ne.reset:n}var Z={bold:n=>ye(n,ne.bold),dim:n=>ye(n,ne.dim),red:n=>ye(n,ne.red),green:n=>ye(n,ne.green),yellow:n=>ye(n,ne.yellow),cyan:n=>ye(n,ne.cyan)};function as(){let n=[];n.push(`${Z.bold("daimon")} v${ut}`),n.push("usage: daimon <command> [args]"),n.push("");for(let e of ss){let r=Rt.filter(o=>o.group===e.id);if(!r.length)continue;n.push(Z.bold(e.title));let s=Math.max(...r.map(o=>o.name.length));for(let o of r)n.push(" "+Z.cyan(o.name.padEnd(s))+" "+Z.dim(o.summary));n.push("")}let t=Object.entries(Pt);if(t.length){n.push(Z.bold("aliases"));for(let[e,r]of t)n.push(" "+Z.cyan(e.padEnd(6))+" "+Z.dim(`\u2192 ${r}`));n.push("")}return n.push(Z.bold("global flags")),n.push(" --help, -h Show this help (or per-command help when used after a verb)."),n.push(" --version, -v Print the daimon version and exit."),n.push(" --about Print {version,nodeVersion,platform,configPath,lockPath,claudeArtifacts}."),n.push(" --no-color Disable ANSI color (also: NO_COLOR=1)."),n.push(" --no-spawn Do not auto-spawn the daemon (also: DAIMON_NO_SPAWN=1)."),n.push(" DAIMON_PORT=N Target a non-default daemon port."),n.push(""),n.push(Z.bold("flag conventions")),n.push(Z.dim(" --timeout <duration> 60s, 5m, 2h")),n.push(Z.dim(" --since <duration> duration window for queries")),n.push(Z.dim(" --budget <tokens> cap response size for agents")),n.push(Z.dim(" --until <state> target state for blocking calls")),n.push(Z.dim(" --app <name> filter to one app")),n.push(Z.dim(" --profile <name> target/filter profile")),n.push(Z.dim(" --full / --compact output shape (compact = default)")),n.push(Z.dim(" --stream NDJSON stream")),n.push(Z.dim(" --explain wrap with _meta diagnostics")),n.push(Z.dim(" --dry-run report planned actions, do not execute")),n.push(Z.dim(" --yes skip interactive confirmations")),n.join(`
|
|
154
|
+
`)}function cs(n){let t=[];if(t.push(Z.bold(`daimon ${n.name}`)+" "+Z.dim(n.args)),t.push(""),t.push(n.description),n.options?.length){t.push(""),t.push(Z.bold("options"));let r=Math.max(...n.options.map(s=>(s.flag+(s.arg?" "+s.arg:"")).length));for(let s of n.options){let o=(s.flag+(s.arg?" "+s.arg:"")).padEnd(r);t.push(" "+Z.cyan(o)+" "+Z.dim(s.description))}}let e=n.examples??(n.example?[n.example]:[]);if(e.length){t.push(""),t.push(Z.bold("examples"));for(let r of e)t.push(" "+r)}if(n.exitCodes?.length){t.push(""),t.push(Z.bold("exit codes"));for(let r of n.exitCodes)t.push(" "+String(r.code).padStart(2)+" "+Z.dim(r.meaning))}return n.aliases?.length&&(t.push(""),t.push(Z.bold("aliases")+" "+n.aliases.join(", "))),t.join(`
|
|
155
|
+
`)}function ls(n,t){if(n===t)return 0;if(!n.length)return t.length;if(!t.length)return n.length;let e=new Array(t.length+1);for(let r=0;r<=t.length;r++)e[r]=r;for(let r=1;r<=n.length;r++){let s=e[0];e[0]=r;for(let o=1;o<=t.length;o++){let a=e[o];e[o]=n[r-1]===t[o-1]?s:1+Math.min(s,e[o],e[o-1]),s=a}}return e[t.length]}function us(n){let t=Rt.map(r=>r.name).concat(Object.keys(Pt)),e=null;for(let r of t){let s=ls(n,r);s<=2&&(!e||s<e.d)&&(e={name:r,d:s})}return e?.name??null}function ps(n,t){let e=null;for(let r of t){let s=ls(n,r);s<=2&&(!e||s<e.d)&&(e={name:r,d:s})}return e?.name??null}function ds(n){return JSON.stringify({error:n.error,...n.hint?{hint:n.hint}:{},exit:n.exit??1})}function Gn(n){let t=[Z.red("error: ")+n.error];return n.hint&&t.push(Z.dim(" hint: ")+n.hint),t.join(`
|
|
156
|
+
`)}var fs=Rt.map(n=>n.name).concat(Object.keys(Pt)).sort().join(" ");function va(){return`#!/usr/bin/env bash
|
|
153
157
|
# daimon bash completion
|
|
154
158
|
# install: source <(daimon completion bash) (or copy to /etc/bash_completion.d/daimon)
|
|
155
159
|
_daimon_complete() {
|
|
@@ -157,7 +161,7 @@ _daimon_complete() {
|
|
|
157
161
|
COMPREPLY=()
|
|
158
162
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
159
163
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
160
|
-
verbs="${
|
|
164
|
+
verbs="${fs}"
|
|
161
165
|
if [ "$COMP_CWORD" -eq 1 ]; then
|
|
162
166
|
COMPREPLY=( $(compgen -W "$verbs" -- "$cur") )
|
|
163
167
|
return 0
|
|
@@ -175,12 +179,12 @@ _daimon_complete() {
|
|
|
175
179
|
COMPREPLY=( $(compgen -W "--full --compact --stream --explain --tag --workspace --since --until --timeout --tail --app --budget --dry-run --yes --no-color --no-spawn --help" -- "$cur") )
|
|
176
180
|
}
|
|
177
181
|
complete -F _daimon_complete daimon
|
|
178
|
-
`}function
|
|
182
|
+
`}function Sa(){return`#compdef daimon
|
|
179
183
|
# daimon zsh completion
|
|
180
184
|
# install: daimon completion zsh > "\${fpath[1]}/_daimon" (or source it from .zshrc)
|
|
181
185
|
_daimon() {
|
|
182
186
|
local -a verbs
|
|
183
|
-
verbs=(${
|
|
187
|
+
verbs=(${Rt.map(n=>`'${n.name}:${n.summary.replace(/'/g,"''").replace(/:/g,"\\:").slice(0,80)}'`).join(" ")})
|
|
184
188
|
if (( CURRENT == 2 )); then
|
|
185
189
|
_describe 'command' verbs
|
|
186
190
|
return
|
|
@@ -205,15 +209,15 @@ _daimon() {
|
|
|
205
209
|
'--help[help]'
|
|
206
210
|
}
|
|
207
211
|
compdef _daimon daimon
|
|
208
|
-
`}function
|
|
212
|
+
`}function ka(){let n=["# daimon fish completion"];n.push("# install: daimon completion fish > ~/.config/fish/completions/daimon.fish"),n.push("complete -c daimon -f");for(let t of Rt){let e=t.summary.replace(/'/g,"\\'").slice(0,100);n.push(`complete -c daimon -n "__fish_use_subcommand" -a "${t.name}" -d '${e}'`)}for(let t of Object.keys(Pt))n.push(`complete -c daimon -n "__fish_use_subcommand" -a "${t}" -d 'alias \u2192 ${Pt[t]}'`);for(let t of["--full","--compact","--stream","--explain","--dry-run","--yes","--no-color","--no-spawn","--help"])n.push(`complete -c daimon -l ${t.replace(/^--/,"")}`);for(let t of["tag","workspace","since","until","timeout","tail","app","budget"])n.push(`complete -c daimon -l ${t} -x`);return n.join(`
|
|
209
213
|
`)+`
|
|
210
|
-
`}function
|
|
214
|
+
`}function xa(){return`# daimon PowerShell completion
|
|
211
215
|
# install: daimon completion powershell | Out-String | Invoke-Expression
|
|
212
216
|
# permanent: add the same line to $PROFILE
|
|
213
217
|
Register-ArgumentCompleter -Native -CommandName daimon -ScriptBlock {
|
|
214
218
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
215
219
|
$tokens = $commandAst.CommandElements
|
|
216
|
-
$verbs = @(${
|
|
220
|
+
$verbs = @(${fs.split(" ").map(t=>`'${t}'`).join(",")})
|
|
217
221
|
if ($tokens.Count -le 1) {
|
|
218
222
|
$verbs | Where-Object { $_ -like "$wordToComplete*" } |
|
|
219
223
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
@@ -235,24 +239,30 @@ Register-ArgumentCompleter -Native -CommandName daimon -ScriptBlock {
|
|
|
235
239
|
$flags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
236
240
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_) }
|
|
237
241
|
}
|
|
238
|
-
`}function
|
|
239
|
-
`)}function
|
|
240
|
-
`);try{
|
|
241
|
-
`),process.exit(1));var
|
|
242
|
+
`}function ms(n){switch(n){case"bash":return{ok:!0,script:va()};case"zsh":return{ok:!0,script:Sa()};case"fish":return{ok:!0,script:ka()};case"powershell":case"pwsh":case"ps":return{ok:!0,script:xa()};default:return{ok:!1,error:`unknown shell: ${n}`}}}Jt();import gt from"node:fs";import Ta from"node:os";import pt from"node:path";import{fileURLToPath as Ca}from"node:url";Nt();var hs=pt.dirname(Ca(import.meta.url)),ws=["status","start","stop","restart","errors","logs","up","doctor","why","wait"],Ra=["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 Ne(){return pt.join(Ta.homedir(),".claude")}function we(n){return pt.join(n,"daimon.installed.json")}function Pa(){let n=[pt.resolve(hs,"templates","claude"),pt.resolve(hs,"..","src","templates","claude")];for(let t of n)if(gt.existsSync(t))return t;throw new Error("claude templates directory not found")}function gs(n){return gt.readFileSync(pt.join(Pa(),n),"utf8")}function ys(n,t){let e=new Date().toISOString();return n.replace(/\{\{daimon_version\}\}/g,ut).replace(/\{\{api_port\}\}/g,String(t)).replace(/\{\{generated_at\}\}/g,e).replace(/\{\{commands_table\}\}/g,os())}function Kn(n,t){gt.mkdirSync(pt.dirname(n),{recursive:!0}),gt.writeFileSync(n,t,"utf8")}function re(n){try{let t=gt.readFileSync(we(n),"utf8");return t.charCodeAt(0)===65279&&(t=t.slice(1)),JSON.parse(t)}catch{return null}}function bs(n,t){Kn(we(n),JSON.stringify(t,null,2)+`
|
|
243
|
+
`)}function Aa(n){let t=[],e=[],r=n.priorInstalledAt?Date.parse(n.priorInstalledAt):0;for(let s of Ra){let o=pt.join(n.dir,"commands",s),a;try{a=gt.statSync(o)}catch{continue}if(!a.isFile())continue;let l=r>0?a.mtimeMs>r+5e3:!1;try{l?(gt.renameSync(o,o+".bak"),e.push(s),n.onEvent?.({kind:"backed-up",file:s})):(gt.rmSync(o,{force:!0}),t.push(s),n.onEvent?.({kind:"removed",file:s}))}catch{}}return{removed:t,backedUp:e}}function Qe(n){let t=[],e=re(n.dir),r=e??{"daimon-version":ut,"installed-at":new Date().toISOString()};r["daimon-version"]=ut,r["installed-at"]=new Date().toISOString();let s=Aa({dir:n.dir,priorInstalledAt:e?.["installed-at"],onEvent:n.onMigrationEvent});if(r.commands=[],(s.removed.length||s.backedUp.length)&&(r.migrated={removedCommands:s.removed,backedUpCommands:s.backedUp}),n.skill){let o=pt.join("skills","daimon","SKILL.md");Kn(pt.join(n.dir,o),ys(gs("skill.md.tmpl"),n.apiPort)),r.skill={path:o.replace(/\\/g,"/")},t.push(o)}if(n.agent){let o=pt.join("agents","daimon-runner.md");Kn(pt.join(n.dir,o),ys(gs("agent.md.tmpl"),n.apiPort)),r.agent={path:o.replace(/\\/g,"/")},t.push(o)}return bs(n.dir,r),{installed:t,manifestPath:we(n.dir),migrated:s}}function vs(n){let t=[],e=re(n.dir);if(!e)return{removed:t,manifestPath:null};let r=n.selection.all;if((r||n.selection.skill)&&e.skill){let s=pt.join(n.dir,e.skill.path);try{gt.rmSync(s,{force:!0}),t.push(e.skill.path)}catch{}try{gt.rmdirSync(pt.dirname(s))}catch{}e.skill=null}if((r||n.selection.commands)&&e.commands){for(let s of e.commands){let o=pt.join("commands",`daimon-${s}.md`);try{gt.rmSync(pt.join(n.dir,o),{force:!0}),t.push(o)}catch{}}e.commands=[]}if((r||n.selection.agent)&&e.agent){try{gt.rmSync(pt.join(n.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{gt.unlinkSync(we(n.dir))}catch{}return{removed:t,manifestPath:null}}return bs(n.dir,e),{removed:t,manifestPath:we(n.dir)}}function Ss(n){let t=re(n);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:we(n)}:{skill:{installed:!1,version:null,path:null},commands:{installed:!1,version:null,names:[]},agent:{installed:!1,version:null,path:null},manifestPath:null}}var Xn=pt.join(bt(),".claude-nudge"),Ea=1440*60*1e3;function ks(){if(process.env.DAIMON_NO_CLAUDE_NUDGE==="1")return;let n=Ne(),t=re(n);if(t&&t["daimon-version"]!==ut){try{let e=gt.statSync(Xn);if(Date.now()-e.mtimeMs<Ea)return}catch{}process.stderr.write(`[daimon] claude integration is from v${t["daimon-version"]} \u2014 run \`daimon claude update\` to refresh
|
|
244
|
+
`);try{gt.mkdirSync(pt.dirname(Xn),{recursive:!0}),gt.writeFileSync(Xn,String(Date.now()))}catch{}}}var Vu=rs(),Ji=Number((process.versions.node||"0").split(".")[0]);Ji&&Ji<20&&(process.stderr.write(`daimon requires Node >= 20
|
|
245
|
+
`),process.exit(1));var Gi=!1,Dr=!1;function M(n,t=1){if(n.startsWith("{"))try{let e=JSON.parse(n),r=typeof e.exit=="number"?e.exit:t;Ve()?process.stderr.write(Gn({error:e.error??n,hint:e.hint})+`
|
|
242
246
|
`):process.stderr.write(JSON.stringify({error:e.error,...e.hint?{hint:e.hint}:{},exit:r})+`
|
|
243
247
|
`),process.exit(r)}catch{}process.stderr.write(n.endsWith(`
|
|
244
248
|
`)?n:n+`
|
|
245
|
-
`),process.exit(t)}function
|
|
246
|
-
`):process.stderr.write(
|
|
247
|
-
`),process.exit(e)}function
|
|
248
|
-
`)}async function
|
|
249
|
-
`);o=
|
|
249
|
+
`),process.exit(t)}function st(n,t,e=1){Ve()?process.stderr.write(Gn({error:n,hint:t})+`
|
|
250
|
+
`):process.stderr.write(ds({error:n,hint:t,exit:e})+`
|
|
251
|
+
`),process.exit(e)}function N(n){process.stdout.write(JSON.stringify(n)+`
|
|
252
|
+
`)}async function jr(n){let t=[];try{let s=await fetch(pe()+"/api/apps",{headers:xt()});if(s.ok){let o=await s.json();Array.isArray(o)&&(t=o.map(a=>a.name).filter(Boolean))}}catch{}let e=ps(n,t),r=e?`did you mean '${e}'? \u2014 list apps with \`daimon list\``:"list available with `daimon list`";st(`unknown app: ${n}`,r)}function Rn(){if(process.env.DAIMON_PORT){let t=Number(process.env.DAIMON_PORT);if(Number.isFinite(t)&&t>0)return t}let n=mt();if(n)return n.apiPort;try{let t=ft();if(t.kind==="loaded")return t.config.apiPort}catch{}return 4999}async function Qu(){try{let n=ft();if(n.kind==="loaded")return{config:n.config}}catch{}return{config:{}}}function pe(){return`http://127.0.0.1:${Rn()}`}async function _t(){if(!(Gi||process.env.DAIMON_NO_SPAWN==="1")&&!mt())try{let n=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0;await Wt({port:Number.isFinite(n)&&n>0?n:void 0})}catch{}}async function ce(){try{let n=await fetch(pe()+"/api/workspaces/ensure",{method:"POST",headers:{"content-type":"application/json",...xt()},body:JSON.stringify({path:process.cwd()})})}catch{}}function xt(){let n=process.env.DAIMON_TOKEN,t={"x-daimon-cwd":process.cwd(),"x-daimon-agent":Vu};return n&&(t.authorization=`Bearer ${n}`),t}async function Lr(n,t="GET"){try{let e=await fetch(pe()+n,{method:t,headers:xt()});(!e.ok||!e.body)&&M(JSON.stringify({error:`stream failed: HTTP ${e.status}`}));let r=e.body.getReader(),s=new TextDecoder,o="";for(;;){let{done:a,value:l}=await r.read();if(a)break;o+=s.decode(l,{stream:!0});let i=o.split(`
|
|
253
|
+
`);o=i.pop()??"";for(let c of i)c.trim()&&process.stdout.write(c+`
|
|
250
254
|
`)}o.trim()&&process.stdout.write(o+`
|
|
251
|
-
`)}catch(e){
|
|
255
|
+
`)}catch(e){M(JSON.stringify({error:e?.message||String(e)}))}}async function X(n,t="GET"){try{let e=await fetch(pe()+n,{method:t,headers:xt()}),r=await e.text(),s=r;try{s=JSON.parse(r)}catch{}return{status:e.status,body:s}}catch{st("daimon is not running","start it with: daimon daemon start --detach")}}async function le(n,t,e){try{let r=await fetch(pe()+n,{method:t,headers:{"content-type":"application/json",...xt()},body:JSON.stringify(e)}),s=await r.text(),o=s;try{o=JSON.parse(s)}catch{}return{status:r.status,body:o}}catch{st("daimon is not running","start it with: daimon daemon start --detach")}}function Le(n){let t={tags:[],positional:[],passthrough:[]},e=!1;for(let r=0;r<n.length;r++){let s=n[r];if(e){t.passthrough.push(s);continue}if(s==="--"){e=!0;continue}s==="--tail"?t.tail=Number(n[++r]):s==="--since"?t.since=n[++r]:s==="--min"||s==="--min-occurrences"?t.min=Number(n[++r]):s==="--since-last"?t.sinceLast=!0:s==="--client"?t.client=n[++r]:s==="--structured"?t.structured=!0:s==="--until"?t.until=n[++r]:s==="--timeout"?t.timeout=n[++r]:s==="--app"?t.app=n[++r]:s==="--tag"?t.tags.push(n[++r]):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=n[++r]:s==="--speed"?t.speed=Number(n[++r]):s==="--task"?t.task=n[++r]:s==="--headless"?t.headless=!0:s==="--detach"?t.detach=!0:s==="--workspace"?t.workspace=n[++r]:s==="--full"?t.full=!0:s==="--compact"?t.compact=!0:s==="--profile"?t.profile=n[++r]:s==="--stream"?t.stream=!0:s==="--explain"?t.explain=!0:s==="--auto-fix"?t.autoFix=!0:s==="--dry-run"?t.dryRun=!0:s==="--auto"?t.auto=!0:s==="--redacted"?t.redacted=!0:s==="--budget"?t.budget=Number(n[++r]):s==="--accept"?t.accept=!0:s==="--path"?t.path=n[++r]:s==="--goal"?t.goal=n[++r]:s==="--self"?t.self=!0:s==="--all"?t.all=!0:s==="--level"?t.level=n[++r]:s==="--label"?t.label=n[++r]:s==="--kinds"?t.kinds=n[++r]:s==="--open"?t.open=!0:s==="--steal"?t.steal=!0:s==="--json"?t.json=!0:t.positional.push(s)}return t}function Te(n){let t=new URLSearchParams;return!n.all&&!n.workspace&&t.set("cwd",process.cwd()),t}function Ce(n){let t=Array.isArray(n?.candidates)?n.candidates:[];if(process.stderr.write(`error: ${n?.error||"name-collision"}
|
|
252
256
|
`),n?.hint&&process.stderr.write(`hint: ${n.hint}
|
|
253
257
|
`),t.length){process.stderr.write(`candidates:
|
|
254
258
|
`);for(let e of t){let r=e.workspaceLabel?` [${e.workspaceLabel}]`:"";process.stderr.write(` - ${e.name}${r} (${e.workspaceRoot??"?"})
|
|
255
|
-
`)}}
|
|
256
|
-
`)}function
|
|
257
|
-
`),!0):!1}function
|
|
258
|
-
`);return}if(t==="--about"){vu();return}if(St[t]&&(t=St[t]),Tr){if(Ti(t))return;wn();return}if(t==="completion"){let o=e[0];o||ut("missing shell","usage: daimon completion <bash|zsh|fish|powershell>");let i=ts(o);i.ok||ut(i.error,"supported shells: bash, zsh, fish, powershell"),process.stdout.write(i.script);return}if(t==="self"){await Et();let o=await G("/api/self");o.status===404&&ut("self endpoint not available","daemon may be from an older daimon version \u2014 run `daimon daemon restart`"),M(o.body);return}if(t==="plugin"){let o=e[0];if(o||ut("missing subcommand","usage: daimon plugin <list|show <name>|validate <path>>"),o==="list"){await Et();let i=await G("/api/plugins");M(i.body);return}if(o==="show"){let i=e[1];i||ut("missing plug-in name","usage: daimon plugin show <name>"),await Et();let a=await G("/api/plugins"),l=(Array.isArray(a.body)?a.body:[]).find(u=>u.name===i);l||ut(`unknown plug-in: ${i}`,"list installed plug-ins with: daimon plugin list"),M(l);return}if(o==="validate"){let i=e[1];i||ut("missing file path","usage: daimon plugin validate <path>");let{validatePluginFile:a}=await Promise.resolve().then(()=>(gr(),Vo)),c=await a(Ae.resolve(i));M(c),c.ok||process.exit(1);return}ut(`unknown plugin subcommand: ${o}`,"usage: daimon plugin <list|show <name>|validate <path>>")}if(t==="workspaces"){await Et();let o=e[0],i=Oe(e.slice(1));if(!o||o==="list"){let a=await G("/api/workspaces");M(a.body);return}if(o==="add"){let a=i.positional[0]||process.cwd(),c={path:Ae.resolve(a)};i.label&&(c.label=i.label);let l=await ge("/api/workspaces/ensure","POST",c);M(l.body);return}if(o==="rm"||o==="remove"){let a=i.positional[0];a||ut("missing path","usage: daimon workspaces rm <path>");let c=await ge("/api/workspaces/remove","POST",{path:Ae.resolve(a)});c.status===404&&ut(`not registered: ${a}`,"run 'daimon workspaces list' to see registered searchRoots"),M(c.body);return}if(o==="show"){let a=i.positional[0]||process.cwd(),c=await G("/api/workspaces/resolve?cwd="+encodeURIComponent(Ae.resolve(a)));M(c.body);return}ut(`unknown workspaces subcommand: ${o}`,"usage: daimon workspaces <list|add|rm|show> [--label <name>]")}if(t==="dashboard"){await Et();let a=`http://127.0.0.1:${ct()?.apiPort??bn()}/?cwd=${encodeURIComponent(process.cwd())}`,c=process.platform==="win32"?"start":process.platform==="darwin"?"open":"xdg-open";try{let{spawn:l}=await import("node:child_process");process.platform==="win32"?l("cmd",["/c","start","",a],{detached:!0,stdio:"ignore"}).unref():l(c,[a],{detached:!0,stdio:"ignore"}).unref()}catch{}M({url:a,cwd:process.cwd()});return}if(t==="daemon"){await xu(e);return}if(t==="claude"){await ku(e);return}if(t==="export-config"){let o=at();o.kind!=="loaded"&&_(JSON.stringify({error:"no config loaded"}));let i=Oe(e),a=JSON.parse(JSON.stringify(o.config));if(i.redacted){let c=Pi.homedir().replace(/\\/g,"/"),l=u=>{if(typeof u!="string")return u;let d=u.replace(/\\/g,"/");return d.toLowerCase().startsWith(c.toLowerCase())?"~"+d.slice(c.length):u};a.apiToken!=null&&a.apiToken!==""&&(a.apiToken="<redacted>"),a.history?.path&&(a.history.path=l(a.history.path)),a.logs?.dir&&(a.logs.dir=l(a.logs.dir)),Array.isArray(a.searchRoots)&&(a.searchRoots=a.searchRoots.map(u=>typeof u=="string"?l(u):{...u,path:l(u.path)}))}M(a);return}if(t==="discover"){await Et();let o=await G("/api/discovery/explain");o.status!==200&&_(JSON.stringify({error:"discovery failed",status:o.status})),M(o.body);return}if(t==="init"){let{runInit:o}=await Promise.resolve().then(()=>(Si(),vi)),i=Oe(e);try{let a=await o({force:!!i.force,auto:!!i.auto});if(M({path:a.path,installClaude:a.installClaude,auto:a.auto}),a.installClaude){let l=bn(),u=Ge({skill:!0,commands:!1,agent:!0,dir:Te(),apiPort:l,onMigrationEvent:d=>{d.kind==="removed"?M({removed:d.file}):M({warning:`${d.file} was modified; backing up to ${d.file}.bak`})}});M({claudeInstalled:u.installed})}let c=ct();if(c){try{await fetch(`http://127.0.0.1:${c.apiPort}/api/snapshot-state`,{method:"POST",headers:bt()})}catch{}try{await fetch(`http://127.0.0.1:${c.apiPort}/api/shutdown`,{method:"POST",headers:bt()})}catch{}await Xt(c.pid,5e3),Tt();try{let l=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,u=await Dt({port:Number.isFinite(l)&&l>0?l:void 0});M({daemonRestarted:!0,pid:u.pid,port:u.apiPort})}catch(l){M({daemonRestarted:!1,error:l?.message||String(l)})}}try{await Et();let l=await fetch(te()+"/api/discovery/explain",{headers:bt()});if(l.ok){let u=await l.json(),d={};try{let R=await(await fetch(te()+"/api/apps?format=full",{headers:bt()})).json();if(Array.isArray(R))for(let y of R){let b=y.workspaceType??"unknown";d[b]=(d[b]??0)+1}}catch{}let f=u.appsFound??0,g={init:"ok",configPath:a.path,discovered:{apps:f,byKind:d}};f===0&&(g._meta={searchRoots:u.searchRoots,scanned:u.scanned,rejected:u.rejected,suggestion:u.suggestion},g.warning="discovery found 0 apps; see _meta.suggestion"),M(g)}}catch{}}catch(a){_(JSON.stringify({error:a?.message||String(a)}))}return}let r=Oe(e);switch(We(t)?.needsDaemon&&await Et(),t){case"list":{let o=r.full||(r.tags.length||r.workspace)&&!r.compact,i=new URLSearchParams;if(o?i.set("format","full"):r.compact&&i.set("format","compact"),r.explain&&i.set("explain","1"),r.all||(await Qt(),i.set("cwd",process.cwd())),r.stream){i.set("stream","ndjson");let u=i.toString();await Pr("/api/apps"+(u?"?"+u:""));return}let a=i.toString(),c=await G("/api/apps"+(a?"?"+a:""));if(r.explain){M(c.body);return}let l=Array.isArray(c.body)?c.body:[];r.tags.length&&(l=l.filter(u=>r.tags.every(d=>(u.tags||[]).includes(d)))),r.workspace&&(l=l.filter(u=>u.workspaceLabel===r.workspace)),M(l);return}case"why-empty":{let o=await G("/api/apps?explain=1");M(o.body);return}case"status":case"stop":case"restart":{let o=r.positional[0];o||ut("missing app name",`usage: daimon ${t} <name>`),r.all||await Qt();let i=t==="status"?"":"/"+t,a=t==="status"?"GET":"POST",c=ye(r);t==="status"&&r.full?c.set("format","full"):t==="status"&&r.compact&&c.set("format","compact");let l=c.toString(),u=await G(`/api/apps/${encodeURIComponent(o)}${i}${l?"?"+l:""}`,a);u.status===412&&we(u.body),u.status===404&&await xi(o),M(u.body);return}case"start":{let o=r.positional[0];o||ut("missing app name","usage: daimon start <name> [--with-deps]"),r.all||await Qt();let i=ye(r);r.withDeps&&i.set("withDeps","1");let a=i.toString(),c=await G(`/api/apps/${encodeURIComponent(o)}/start${a?"?"+a:""}`,"POST");c.status===412&&we(c.body),c.status===404&&await xi(o),M(c.body);return}case"history":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon history <name>"}));let i=await G(`/api/history/summary/${encodeURIComponent(o)}`);M(i.body);return}case"why":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon why <name>"}));let i=await G(`/api/history/why/${encodeURIComponent(o)}`);M(i.body);return}case"env":{let o=r.positional[0];if(o||_(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),r.use){let a=await ge(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:r.use});a.status===404&&_(JSON.stringify({error:"unknown app"})),M(a.body);return}let i=await G(`/api/apps/${encodeURIComponent(o)}/env`);i.status===404&&_(JSON.stringify({error:"unknown app"})),M(i.body);return}case"clean":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon clean <name> [--deep] [--yes]"}));let i=new URLSearchParams;r.deep&&i.set("deep","1"),r.yes&&i.set("yes","1");let a=await G(`/api/apps/${encodeURIComponent(o)}/clean${i.toString()?"?"+i.toString():""}`,"POST");a.status===404&&_(JSON.stringify({error:"unknown app"})),a.status===409&&(M(a.body),process.exit(1)),M(a.body);return}case"record":{let o=await G("/api/session/record?action=toggle","POST");M(o.body);return}case"replay":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon replay <session.jsonl> [--speed N]"}));let i=r.speed&&r.speed>0?r.speed:1,a;try{a=Br(o)}catch(l){_(JSON.stringify({error:l?.message||String(l)}))}let c=0;for(let l of a){let u=Math.max(0,(l.ts-c)/i);u>0&&await new Promise(d=>setTimeout(d,u)),c=l.ts,l.kind==="run"?await ge(`/api/apps/${encodeURIComponent(l.app)}/run/${encodeURIComponent(l.task||"")}`,"POST",{args:l.args||[]}):await G(`/api/apps/${encodeURIComponent(l.app)}/${l.kind}`,"POST")}M({replayed:a.length,file:o});return}case"doctor":{let o=at();if(o.kind!=="loaded"&&_(JSON.stringify({error:"no config loaded"})),r.self){await Et();let l=await G("/api/self");l.status===503&&ut("self-metrics not available","daemon may need a restart: daimon daemon restart");let u=l.body??{},d=[],f=256,g=100,C=50;d.push({name:"heap",ok:u.heapUsedMB<f,detail:`heapUsed ${u.heapUsedMB}MB (warn at ${f}MB)`}),d.push({name:"event-loop-lag",ok:u.eventLoopLagP95Ms<g,detail:`p95 ${u.eventLoopLagP95Ms}ms (warn at ${g}ms)`}),d.push({name:"history-db-query",ok:(u.historyDbQueryMs?.p95??0)<C,detail:`p95 ${u.historyDbQueryMs?.p95??0}ms (warn at ${C}ms)`});let R=d.every(y=>y.ok);M({ok:R,checks:d,metrics:u}),R||process.exit(1);return}if(r.autoFix){let{runAutoFix:l,ALL_AUTO_FIX:u}=await Promise.resolve().then(()=>(pe(),ue)),d=o.config.doctor?.autoFix?.permitted??u,f=await l({permitted:d,dryRun:!!r.dryRun});M(f),f.errors.length&&process.exit(1);return}let i=[],a=Ot(o.config,{warnings:i}),c=await _r(o.config,a);for(let l of i)c.checks.unshift({name:`discovery: ${l}`,ok:!1,detail:l});i.length&&(c.ok=!1),M(c),c.ok||process.exit(1);return}case"free-port":{let o=Number(r.positional[0]);(!Number.isFinite(o)||o<=0)&&_(JSON.stringify({error:"usage: daimon free-port <port> [--force]"}));let i=Fe(o);if(!i){M({port:o,free:!0});return}if(!r.force){M({port:o,free:!1,holder:i});return}i.pid===process.pid&&_(JSON.stringify({error:"refuse to kill daimon itself",holder:i}));let a=await Ir(i);M({port:o,killed:a,holder:i}),a||process.exit(1);return}case"snapshot":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon snapshot <name>"}));let i=await G(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");i.status===404&&_(JSON.stringify({error:"unknown app"})),M(i.body);return}case"tasks":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon tasks <name>"}));let i=await G(`/api/apps/${encodeURIComponent(o)}/tasks`);i.status===404&&_(JSON.stringify({error:"unknown app"})),M(i.body);return}case"run":{let o=r.positional[0],i=r.positional[1];(!o||!i)&&_(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"})),r.all||await Qt();let a={args:r.passthrough,watch:!!r.watch},l=ye(r).toString(),u=await ge(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(i)}${l?"?"+l:""}`,"POST",a);u.status===412&&we(u.body),u.status===404&&_(JSON.stringify({error:"unknown app"})),M(u.body),!r.watch&&typeof u.body?.exitCode=="number"&&process.exit(u.body.exitCode===0?0:1);return}case"errors":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon errors <name> [--since 2m] [--since-last] [--client <id>] [--structured] [--full|--compact] [--level error|warning|lint|all]"})),r.all||await Qt();let i=ye(r),a=`/api/apps/${encodeURIComponent(o)}/errors`;r.sinceLast?(a+="/since-last",r.client&&i.set("client",r.client)):r.since&&i.set("since",r.since),r.level&&i.set("level",r.level),r.full?i.set("format","full"):r.compact&&i.set("format","compact");let c=i.toString(),l=await G(a+(c?"?"+c:""));l.status===412&&we(l.body),l.status===404&&_(JSON.stringify({error:"unknown app"}));let u=l.body;r.structured&&Array.isArray(u)&&(u=u.map(d=>d.parsed??{message:d.message})),M(u);return}case"events":{let o=new URLSearchParams;if(r.since&&o.set("since",r.since),r.app&&o.set("app",r.app),r.stream){o.set("stream","ndjson");let c=o.toString();await Pr("/api/events"+(c?"?"+c:""));return}let i=o.toString(),a=await G("/api/events"+(i?"?"+i:""));M(a.body);return}case"ensure":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon ensure <name> [--until serving|healthy] [--timeout 180s]"}));let i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&_(JSON.stringify({error:"ensure --until must be serving|healthy"})),i.set("until",a);let c=180;if(r.timeout){let u=be(r.timeout);u==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),c=Math.min(u,600)}i.set("timeoutMs",String(Math.ceil(c*1e3)));let l=await G(`/api/apps/${encodeURIComponent(o)}/ensure?${i.toString()}`,"POST");l.status===404&&_(JSON.stringify({error:"unknown app"})),M(l.body),l.body?.error==="timeout"&&process.exit(2);return}case"ensure-up":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon ensure-up <profile> [--until serving|healthy] [--timeout 300s]"}));let i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&_(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),i.set("until",a);let c=300;if(r.timeout){let d=be(r.timeout);d==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),c=Math.min(d,1200)}i.set("timeoutMs",String(Math.ceil(c*1e3)));let l=await G(`/api/profiles/${encodeURIComponent(o)}/ensure-up?${i.toString()}`,"POST");l.status===404&&_(JSON.stringify({error:"unknown profile"})),M(l.body),Array.isArray(l.body?.apps)&&l.body.apps.some(d=>d.timedOut)&&process.exit(2);return}case"overview":{let o=new URLSearchParams;r.workspace&&o.set("workspace",r.workspace),r.profile&&o.set("profile",r.profile),r.budget&&Number.isFinite(r.budget)&&r.budget>0&&o.set("budget",String(Math.floor(r.budget)));let i=o.toString(),a=await G("/api/overview"+(i?"?"+i:""));M(a.body);return}case"focus":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon focus <name> [--until serving|healthy|stable] [--timeout 180s]"}));let i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||_(JSON.stringify({error:"focus --until must be serving|healthy|stable"})),i.set("until",a);let c=180;if(r.timeout){let l=be(r.timeout);l==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),c=Math.min(l,600)}i.set("timeoutMs",String(Math.ceil(c*1e3))),await Pr(`/api/apps/${encodeURIComponent(o)}/focus?${i.toString()}`,"POST");return}case"pin-health":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon pin-health <name> [--accept] [--path <p>]"}));let i=await G(`/api/apps/${encodeURIComponent(o)}?format=full`);i.status===404&&_(JSON.stringify({error:"unknown app"}));let a=i.body?.discoveredHealthPath??null,c=r.path??a??null;if(!r.accept){M({app:o,discoveredHealthPath:a,candidate:c,hint:c?`re-run with --accept to persist ${c} to daimon.config.json`:"no path discovered yet; start the app and wait for first serving"});return}c||_(JSON.stringify({error:"no path to pin \u2014 pass --path or wait for auto-discovery"}));let l=await ge(`/api/apps/${encodeURIComponent(o)}/health/pin`,"POST",{path:c});l.status===404&&_(JSON.stringify({error:"unknown app"})),M(l.body);return}case"orchestrate":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon orchestrate <profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]"}));let i=new URLSearchParams;i.set("profile",o);let a=(r.goal||r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||_(JSON.stringify({error:"orchestrate --goal must be serving|healthy|stable"})),i.set("goal",a);let c=300;if(r.timeout){let u=be(r.timeout);u==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),c=Math.min(u,1200)}i.set("timeoutMs",String(Math.ceil(c*1e3))),r.dryRun&&i.set("dryRun","true"),r.budget&&Number.isFinite(r.budget)&&r.budget>0&&i.set("budget",String(Math.floor(r.budget)));let l=await G(`/api/orchestrate?${i.toString()}`,"POST");l.status===404&&_(JSON.stringify(l.body)),l.status===400&&_(JSON.stringify(l.body)),M(l.body),l.body&&l.body.allReached===!1&&process.exit(2);return}case"try-fix":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon try-fix <name> [--until serving|healthy] [--timeout 180s]"}));let i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();["serving","healthy"].includes(a)||_(JSON.stringify({error:"try-fix --until must be serving|healthy"})),i.set("until",a);let c=180;if(r.timeout){let u=be(r.timeout);u==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),c=Math.min(u,600)}i.set("timeoutMs",String(Math.ceil(c*1e3)));let l=await G(`/api/apps/${encodeURIComponent(o)}/try-fix?${i.toString()}`,"POST");l.status===404&&_(JSON.stringify({error:"unknown app"})),M(l.body),l.body&&l.body.reached===!1&&process.exit(2);return}case"wait":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon wait <name> [--until serving|healthy|stopped|error] [--timeout 60s]"})),r.all||await Qt();let i=ye(r);r.until&&i.set("until",r.until);let a=120;if(r.timeout){let l=be(r.timeout);l==null&&_(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),a=Math.min(l,600)}i.set("timeout",String(Math.ceil(a)));let c=await G(`/api/apps/${encodeURIComponent(o)}/wait?${i.toString()}`);c.status===412&&we(c.body),c.status===404&&_(JSON.stringify({error:"unknown app"})),M(c.body),c.body?.timedOut&&process.exit(2);return}case"up":case"down":{let o=r.positional[0],i=await G("/api/apps"),a=Array.isArray(i.body)?i.body:[],c=(await bu()).config,l;if(!o)l=c.autoStart||[],t==="up"&&l.length===0&&_(JSON.stringify({error:"no autoStart configured and no profile given"})),t==="down"&&l.length===0&&(l=a.map(C=>C.name));else{let C=c.profiles?.[o];C||_(JSON.stringify({error:`unknown profile: ${o}`})),l=C}let u=t==="up"?"start":"stop";if(t==="up"?await Promise.all(l.map(C=>G(`/api/apps/${encodeURIComponent(C)}/start?withDeps=1`,"POST"))):await Promise.all(l.map(C=>G(`/api/apps/${encodeURIComponent(C)}/${u}`,"POST"))),t==="up"){let R=Date.now(),y=()=>Math.max(5,Math.floor((12e4-(Date.now()-R))/1e3));await Promise.all(l.map(b=>G(`/api/apps/${encodeURIComponent(b)}/wait?until=serving&timeout=${y()}`)))}else await Promise.all(l.map(C=>G(`/api/apps/${encodeURIComponent(C)}/wait?until=stopped&timeout=10`)));let d=await G("/api/apps"),g=(Array.isArray(d.body)?d.body:[]).filter(C=>l.includes(C.name)).map(C=>({name:C.name,status:C.status,health:C.health}));M(g);return}case"timeline":{let o=new URLSearchParams;r.since&&o.set("since",r.since),r.app&&o.set("app",r.app),r.kinds&&o.set("kinds",r.kinds);let i=o.toString(),a=await G("/api/history/timeline"+(i?"?"+i:""));M(a.body);return}case"logs":{let o=r.positional[0];o||_(JSON.stringify({error:"usage: daimon logs <name> [--tail N] [--since 30s]"})),r.all||await Qt();let i=ye(r);r.tail!=null&&!Number.isNaN(r.tail)&&i.set("tail",String(r.tail)),r.since&&i.set("since",r.since);let a=i.toString(),c=await G(`/api/apps/${encodeURIComponent(o)}/logs${a?"?"+a:""}`);c.status===412&&we(c.body),c.status===404&&_(JSON.stringify({error:"unknown app"})),M(c.body);return}default:{let o=Yr(t),i=o?`did you mean '${o}'? \u2014 run \`daimon --help\` to list commands`:"run `daimon --help` to list commands";ut(`unknown command: ${t}`,i)}}}Tu().catch(n=>_(JSON.stringify({error:n?.message||String(n)})));
|
|
259
|
+
`)}}N({error:n?.error||"name-collision",candidates:t}),process.exit(4)}function ue(n){let t=n.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 Cn(){process.stdout.write(as()+`
|
|
260
|
+
`)}function Wi(n){let t=Ye(n);return t?(process.stdout.write(cs(t)+`
|
|
261
|
+
`),!0):!1}function Zu(){let n=mt(),t=null;try{let s=ft();s.kind==="loaded"&&(t=s.path)}catch{}let e=je.join(qi.homedir(),".daimon","lock.json"),r=[];try{let s=re(Ne());s&&(s.skill&&r.push("skill"),s.agent&&r.push("agent"),Array.isArray(s.commands)&&s.commands.length&&r.push("commands"))}catch{}N({version:ut,nodeVersion:process.versions.node,platform:process.platform,configPath:t,lockPath:e,running:!!n,runningPid:n?.pid??null,runningPort:n?.apiPort??null,claudeArtifacts:r})}function tp(n){let t={},e=[];for(let r=0;r<n.length;r++){let s=n[r];s==="--skill"?t.skill=!0:s==="--commands"?t.commands=!0:s==="--agent"?t.agent=!0:s==="--all"?t.all=!0:s==="--dir"?t.dir=n[++r]:s==="--yes"?t.yes=!0:e.push(s)}return{positional:e,flags:t}}async function ep(n){let t=n[0];t||M(JSON.stringify({error:"usage: daimon claude <install|update|uninstall|status> [--skill] [--commands] [--agent] [--all] [--dir <path>] [--yes]"}));let{flags:e}=tp(n.slice(1)),r=e.dir??Ne(),s=Rn();if(t==="status"){N(Ss(r));return}if(t==="install"){let o,a=e.skill||e.commands||e.agent||e.all;if(e.all||e.yes||!a&&!process.stdin.isTTY)o={skill:!0,commands:!1,agent:!0};else if(a)o={skill:!!e.skill,commands:!1,agent:!!e.agent};else{let{promptClaudeInstall:i}=await Promise.resolve().then(()=>(Rs(),Cs)),c=await i();if(!c){N({cancelled:!0});return}o={skill:c.skill,commands:!1,agent:c.agent}}let l=Qe({...o,dir:r,apiPort:s,onMigrationEvent:i=>{i.kind==="removed"?N({removed:i.file}):N({warning:`${i.file} was modified; backing up to ${i.file}.bak`})}});N({installed:l.installed,manifest:l.manifestPath,version:ut});return}if(t==="update"){let o=re(r);o||M(JSON.stringify({error:"no manifest at "+r+" \u2014 run `daimon claude install` first"}));let a={skill:!!o.skill,commands:!1,agent:!!o.agent},l=Qe({...a,dir:r,apiPort:s,onMigrationEvent:i=>{i.kind==="removed"?N({removed:i.file}):N({warning:`${i.file} was modified; backing up to ${i.file}.bak`})}});N({updated:l.installed,manifest:l.manifestPath,version:ut});return}if(t==="uninstall"){e.skill||e.commands||e.agent||e.all||M(JSON.stringify({error:"usage: daimon claude uninstall [--all|--skill|--commands|--agent]"}));let a=vs({dir:r,selection:{all:e.all,skill:e.skill,commands:e.commands,agent:e.agent}});N({removed:a.removed,manifest:a.manifestPath});return}M(JSON.stringify({error:`unknown claude subcommand: ${t}`}))}async function np(n){let t=n[0],e=Le(n.slice(1));switch(t){case"status":{let r=mt();if(!r){N({running:!1});return}let s=Date.now()-r.startedAt;N({running:!0,pid:r.pid,port:r.apiPort,uptime:s,version:r.version,headless:r.headless});return}case"start":{if(e.detach){let s=mt();if(s){N({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,a=await Wt({port:Number.isFinite(o)&&o>0?o:void 0});N({ok:!0,pid:a.pid,port:a.apiPort})}catch(o){M(JSON.stringify({error:o?.message||String(o)}))}return}let{startInProcess:r}=await Promise.resolve().then(()=>(Ei(),Ai));await r({headless:!!e.headless});return}case"stop":{let r=mt();if(!r){N({ok:!0,wasRunning:!1});return}try{await fetch(`http://127.0.0.1:${r.apiPort}/api/shutdown`,{method:"POST",headers:xt()})}catch{}if(await te(r.pid,5e3))Ot(),N({ok:!0,wasRunning:!0});else{try{process.kill(r.pid,"SIGTERM")}catch{}await te(r.pid,2e3),Ot(),N({ok:!0,wasRunning:!0,forced:!0})}return}case"restart":{let r=mt();if(r){try{await fetch(`http://127.0.0.1:${r.apiPort}/api/snapshot-state`,{method:"POST",headers:xt()})}catch{}try{await fetch(`http://127.0.0.1:${r.apiPort}/api/shutdown`,{method:"POST",headers:xt()})}catch{}await te(r.pid,5e3),Ot()}let s=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,o=await Wt({port:Number.isFinite(s)&&s>0?s:void 0});N({ok:!0,pid:o.pid,port:o.apiPort,handoff:!0});return}case"attach":{await _t();let r=mt();r||M(JSON.stringify({error:"no daemon running and auto-spawn failed"}));let{attachToDaemon:s}=await Promise.resolve().then(()=>(Mi(),$i));await s(r.apiPort);return}case"install-service":{let{installServiceArtifact:r}=await Promise.resolve().then(()=>(Ii(),Li)),s=r();N({platform:s.platform,artifact:s.path,installCmd:s.installCmd});return}default:M(JSON.stringify({error:"usage: daimon daemon <start|stop|status|restart|attach|install-service> [--detach] [--headless]"}))}}async function rp(){let n=process.argv.slice(2).filter(o=>o==="--no-spawn"?(Gi=!0,!1):o==="--no-color"?(is("off"),!1):o==="--help"||o==="-h"?(Dr=!0,!1):!0),[t,...e]=n;try{ks()}catch{}if(!t&&Dr){Cn();return}if(!t){Cn();return}if(t==="help"){let o=e[0];if(o&&Wi(o))return;Cn();return}if(t==="--version"||t==="-v"){process.stdout.write(ut+`
|
|
262
|
+
`);return}if(t==="--about"){Zu();return}if(Pt[t]&&(t=Pt[t]),Dr){if(Wi(t))return;Cn();return}if(t==="completion"){let o=e[0];o||st("missing shell","usage: daimon completion <bash|zsh|fish|powershell>");let a=ms(o);a.ok||st(a.error,"supported shells: bash, zsh, fish, powershell"),process.stdout.write(a.script);return}if(t==="self"){await _t();let o=await X("/api/self");o.status===404&&st("self endpoint not available","daemon may be from an older daimon version \u2014 run `daimon daemon restart`"),N(o.body);return}if(t==="plugin"){let o=e[0];if(o||st("missing subcommand","usage: daimon plugin <list|show <name>|validate <path>>"),o==="list"){await _t();let a=await X("/api/plugins");N(a.body);return}if(o==="show"){let a=e[1];a||st("missing plug-in name","usage: daimon plugin show <name>"),await _t();let l=await X("/api/plugins"),c=(Array.isArray(l.body)?l.body:[]).find(u=>u.name===a);c||st(`unknown plug-in: ${a}`,"list installed plug-ins with: daimon plugin list"),N(c);return}if(o==="validate"){let a=e[1];a||st("missing file path","usage: daimon plugin validate <path>");let{validatePluginFile:l}=await Promise.resolve().then(()=>(Pr(),mi)),i=await l(je.resolve(a));N(i),i.ok||process.exit(1);return}st(`unknown plugin subcommand: ${o}`,"usage: daimon plugin <list|show <name>|validate <path>>")}if(t==="workspaces"){await _t();let o=e[0],a=Le(e.slice(1));if(!o||o==="list"){let l=await X("/api/workspaces");N(l.body);return}if(o==="add"){let l=a.positional[0]||process.cwd(),i={path:je.resolve(l)};a.label&&(i.label=a.label);let c=await le("/api/workspaces/ensure","POST",i);N(c.body);return}if(o==="rm"||o==="remove"){let l=a.positional[0];l||st("missing path","usage: daimon workspaces rm <path>");let i=await le("/api/workspaces/remove","POST",{path:je.resolve(l)});i.status===404&&st(`not registered: ${l}`,"run 'daimon workspaces list' to see registered searchRoots"),N(i.body);return}if(o==="show"){let l=a.positional[0]||process.cwd(),i=await X("/api/workspaces/resolve?cwd="+encodeURIComponent(je.resolve(l)));N(i.body);return}st(`unknown workspaces subcommand: ${o}`,"usage: daimon workspaces <list|add|rm|show> [--label <name>]")}if(t==="dashboard"){await _t();let l=`http://127.0.0.1:${mt()?.apiPort??Rn()}/?cwd=${encodeURIComponent(process.cwd())}`,i=process.platform==="win32"?"start":process.platform==="darwin"?"open":"xdg-open";try{let{spawn:c}=await import("node:child_process");process.platform==="win32"?c("cmd",["/c","start","",l],{detached:!0,stdio:"ignore"}).unref():c(i,[l],{detached:!0,stdio:"ignore"}).unref()}catch{}N({url:l,cwd:process.cwd()});return}if(t==="daemon"){await np(e);return}if(t==="claude"){await ep(e);return}if(t==="export-config"){let o=ft();o.kind!=="loaded"&&M(JSON.stringify({error:"no config loaded"}));let a=Le(e),l=JSON.parse(JSON.stringify(o.config));if(a.redacted){let i=qi.homedir().replace(/\\/g,"/"),c=u=>{if(typeof u!="string")return u;let p=u.replace(/\\/g,"/");return p.toLowerCase().startsWith(i.toLowerCase())?"~"+p.slice(i.length):u};l.apiToken!=null&&l.apiToken!==""&&(l.apiToken="<redacted>"),l.history?.path&&(l.history.path=c(l.history.path)),l.logs?.dir&&(l.logs.dir=c(l.logs.dir)),Array.isArray(l.searchRoots)&&(l.searchRoots=l.searchRoots.map(u=>typeof u=="string"?c(u):{...u,path:c(u.path)}))}N(l);return}if(t==="discover"){await _t();let o=await X("/api/discovery/explain");o.status!==200&&M(JSON.stringify({error:"discovery failed",status:o.status})),N(o.body);return}if(t==="init"){let{runInit:o}=await Promise.resolve().then(()=>(Hi(),Ui)),a=Le(e);try{let l=await o({force:!!a.force,auto:!!a.auto});if(N({path:l.path,installClaude:l.installClaude,auto:l.auto}),l.installClaude){let c=Rn(),u=Qe({skill:!0,commands:!1,agent:!0,dir:Ne(),apiPort:c,onMigrationEvent:p=>{p.kind==="removed"?N({removed:p.file}):N({warning:`${p.file} was modified; backing up to ${p.file}.bak`})}});N({claudeInstalled:u.installed})}let i=mt();if(i){try{await fetch(`http://127.0.0.1:${i.apiPort}/api/snapshot-state`,{method:"POST",headers:xt()})}catch{}try{await fetch(`http://127.0.0.1:${i.apiPort}/api/shutdown`,{method:"POST",headers:xt()})}catch{}await te(i.pid,5e3),Ot();try{let c=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,u=await Wt({port:Number.isFinite(c)&&c>0?c:void 0});N({daemonRestarted:!0,pid:u.pid,port:u.apiPort})}catch(c){N({daemonRestarted:!1,error:c?.message||String(c)})}}try{await _t();let c=await fetch(pe()+"/api/discovery/explain",{headers:xt()});if(c.ok){let u=await c.json(),p={};try{let x=await(await fetch(pe()+"/api/apps?format=full",{headers:xt()})).json();if(Array.isArray(x))for(let T of x){let w=T.workspaceType??"unknown";p[w]=(p[w]??0)+1}}catch{}let m=u.appsFound??0,g={init:"ok",configPath:l.path,discovered:{apps:m,byKind:p}};m===0&&(g._meta={searchRoots:u.searchRoots,scanned:u.scanned,rejected:u.rejected,suggestion:u.suggestion},g.warning="discovery found 0 apps; see _meta.suggestion"),N(g)}}catch{}}catch(l){M(JSON.stringify({error:l?.message||String(l)}))}return}let r=Le(e);switch(Ye(t)?.needsDaemon&&await _t(),t){case"list":{let o=r.full||(r.tags.length||r.workspace)&&!r.compact,a=new URLSearchParams;if(o?a.set("format","full"):r.compact&&a.set("format","compact"),r.explain&&a.set("explain","1"),r.all||(await ce(),a.set("cwd",process.cwd())),r.stream){a.set("stream","ndjson");let u=a.toString();await Lr("/api/apps"+(u?"?"+u:""));return}let l=a.toString(),i=await X("/api/apps"+(l?"?"+l:""));if(r.explain){N(i.body);return}let c=Array.isArray(i.body)?i.body:[];r.tags.length&&(c=c.filter(u=>r.tags.every(p=>(u.tags||[]).includes(p)))),r.workspace&&(c=c.filter(u=>u.workspaceLabel===r.workspace)),N(c);return}case"why-empty":{let o=await X("/api/apps?explain=1");N(o.body);return}case"status":case"stop":case"restart":{let o=r.positional[0];o||st("missing app name",`usage: daimon ${t} <name>`),r.all||await ce();let a=t==="status"?"":"/"+t,l=t==="status"?"GET":"POST",i=Te(r);t==="status"&&r.full?i.set("format","full"):t==="status"&&r.compact&&i.set("format","compact"),t!=="status"&&r.steal&&i.set("steal","1");let c=i.toString(),u=await X(`/api/apps/${encodeURIComponent(o)}${a}${c?"?"+c:""}`,l);u.status===412&&Ce(u.body),u.status===409&&u.body?.error==="locked-by-other-agent"&&(process.stderr.write(`error: app '${o}' is locked by agent ${u.body.agent} (expires ${new Date(u.body.expiresAt).toISOString()})
|
|
263
|
+
`),process.stderr.write(`hint: pass --steal to override, or wait
|
|
264
|
+
`),process.exit(5)),u.status===404&&await jr(o),N(u.body);return}case"start":{let o=r.positional[0];o||st("missing app name","usage: daimon start <name> [--with-deps]"),r.all||await ce();let a=Te(r);r.withDeps&&a.set("withDeps","1"),r.steal&&a.set("steal","1");let l=a.toString(),i=await X(`/api/apps/${encodeURIComponent(o)}/start${l?"?"+l:""}`,"POST");i.status===412&&Ce(i.body),i.status===409&&i.body?.error==="locked-by-other-agent"&&(process.stderr.write(`error: app '${o}' is locked by agent ${i.body.agent} (expires ${new Date(i.body.expiresAt).toISOString()})
|
|
265
|
+
`),process.stderr.write(`hint: pass --steal to override, or wait
|
|
266
|
+
`),process.exit(5)),i.status===404&&await jr(o),N(i.body);return}case"agents":{let o=await X("/api/agents");N(o.body);return}case"profiles":{r.positional[0]!=="suggest"&&st("usage: daimon profiles suggest [--since 30d] [--min 5]");let a=new URLSearchParams;r.since&&a.set("since",r.since),r.min!=null&&a.set("minOccurrences",String(r.min));let l=a.toString(),i=await X("/api/profiles/suggest"+(l?"?"+l:""));N(i.body);return}case"handoff":{let o=r.positional[0],a=r.positional[1];(!o||!a)&&st("missing args","usage: daimon handoff <app> <agentId>");let l=await le(`/api/apps/${encodeURIComponent(o)}/handoff`,"POST",{to:a});l.status===404&&await jr(o),N(l.body);return}case"history":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon history <name>"}));let a=await X(`/api/history/summary/${encodeURIComponent(o)}`);N(a.body);return}case"why":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon why <name>"}));let a=await X(`/api/history/why/${encodeURIComponent(o)}`);N(a.body);return}case"env":{let o=r.positional[0];if(o||M(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),r.use){let l=await le(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:r.use});l.status===404&&M(JSON.stringify({error:"unknown app"})),N(l.body);return}let a=await X(`/api/apps/${encodeURIComponent(o)}/env`);a.status===404&&M(JSON.stringify({error:"unknown app"})),N(a.body);return}case"clean":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon clean <name> [--deep] [--yes]"}));let a=new URLSearchParams;r.deep&&a.set("deep","1"),r.yes&&a.set("yes","1");let l=await X(`/api/apps/${encodeURIComponent(o)}/clean${a.toString()?"?"+a.toString():""}`,"POST");l.status===404&&M(JSON.stringify({error:"unknown app"})),l.status===409&&(N(l.body),process.exit(1)),N(l.body);return}case"record":{let o=await X("/api/session/record?action=toggle","POST");N(o.body);return}case"replay":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon replay <session.jsonl> [--speed N]"}));let a=r.speed&&r.speed>0?r.speed:1,l;try{l=Qr(o)}catch(c){M(JSON.stringify({error:c?.message||String(c)}))}let i=0;for(let c of l){let u=Math.max(0,(c.ts-i)/a);u>0&&await new Promise(p=>setTimeout(p,u)),i=c.ts,c.kind==="run"?await le(`/api/apps/${encodeURIComponent(c.app)}/run/${encodeURIComponent(c.task||"")}`,"POST",{args:c.args||[]}):await X(`/api/apps/${encodeURIComponent(c.app)}/${c.kind}`,"POST")}N({replayed:l.length,file:o});return}case"doctor":{let o=ft();if(o.kind!=="loaded"&&M(JSON.stringify({error:"no config loaded"})),r.self){await _t();let c=await X("/api/self");c.status===503&&st("self-metrics not available","daemon may need a restart: daimon daemon restart");let u=c.body??{},p=[],m=256,g=100,S=50;p.push({name:"heap",ok:u.heapUsedMB<m,detail:`heapUsed ${u.heapUsedMB}MB (warn at ${m}MB)`}),p.push({name:"event-loop-lag",ok:u.eventLoopLagP95Ms<g,detail:`p95 ${u.eventLoopLagP95Ms}ms (warn at ${g}ms)`}),p.push({name:"history-db-query",ok:(u.historyDbQueryMs?.p95??0)<S,detail:`p95 ${u.historyDbQueryMs?.p95??0}ms (warn at ${S}ms)`});let x=p.every(T=>T.ok);N({ok:x,checks:p,metrics:u}),x||process.exit(1);return}if(r.autoFix){let{runAutoFix:c,ALL_AUTO_FIX:u}=await Promise.resolve().then(()=>(ve(),be)),p=o.config.doctor?.autoFix?.permitted??u,m=await c({permitted:p,dryRun:!!r.dryRun});N(m),m.errors.length&&process.exit(1);return}let a=[],l=jt(o.config,{warnings:a}),i=await Xr(o.config,l);for(let c of a)i.checks.unshift({name:`discovery: ${c}`,ok:!1,detail:c});a.length&&(i.ok=!1),N(i),i.ok||process.exit(1);return}case"free-port":{let o=Number(r.positional[0]);(!Number.isFinite(o)||o<=0)&&M(JSON.stringify({error:"usage: daimon free-port <port> [--force]"}));let a=Je(o);if(!a){N({port:o,free:!0});return}if(!r.force){N({port:o,free:!1,holder:a});return}a.pid===process.pid&&M(JSON.stringify({error:"refuse to kill daimon itself",holder:a}));let l=await Yr(a);N({port:o,killed:l,holder:a}),l||process.exit(1);return}case"snapshot":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon snapshot <name>"}));let a=await X(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");a.status===404&&M(JSON.stringify({error:"unknown app"})),N(a.body);return}case"tasks":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon tasks <name>"}));let a=await X(`/api/apps/${encodeURIComponent(o)}/tasks`);a.status===404&&M(JSON.stringify({error:"unknown app"})),N(a.body);return}case"run":{let o=r.positional[0],a=r.positional[1];(!o||!a)&&M(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"})),r.all||await ce();let l={args:r.passthrough,watch:!!r.watch},c=Te(r).toString(),u=await le(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(a)}${c?"?"+c:""}`,"POST",l);u.status===412&&Ce(u.body),u.status===404&&M(JSON.stringify({error:"unknown app"})),N(u.body),!r.watch&&typeof u.body?.exitCode=="number"&&process.exit(u.body.exitCode===0?0:1);return}case"errors":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon errors <name> [--since 2m] [--since-last] [--client <id>] [--structured] [--full|--compact] [--level error|warning|lint|all]"})),r.all||await ce();let a=Te(r),l=`/api/apps/${encodeURIComponent(o)}/errors`;r.sinceLast?(l+="/since-last",r.client&&a.set("client",r.client)):r.since&&a.set("since",r.since),r.level&&a.set("level",r.level),r.full?a.set("format","full"):r.compact&&a.set("format","compact");let i=a.toString(),c=await X(l+(i?"?"+i:""));c.status===412&&Ce(c.body),c.status===404&&M(JSON.stringify({error:"unknown app"}));let u=c.body;r.structured&&Array.isArray(u)&&(u=u.map(p=>p.parsed??{message:p.message})),N(u);return}case"events":{let o=new URLSearchParams;if(r.since&&o.set("since",r.since),r.app&&o.set("app",r.app),r.stream){o.set("stream","ndjson");let i=o.toString();await Lr("/api/events"+(i?"?"+i:""));return}let a=o.toString(),l=await X("/api/events"+(a?"?"+a:""));N(l.body);return}case"ensure":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon ensure <name> [--until serving|healthy] [--timeout 180s]"}));let a=new URLSearchParams,l=(r.until||"healthy").toLowerCase();l!=="serving"&&l!=="healthy"&&M(JSON.stringify({error:"ensure --until must be serving|healthy"})),a.set("until",l);let i=180;if(r.timeout){let u=ue(r.timeout);u==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),i=Math.min(u,600)}a.set("timeoutMs",String(Math.ceil(i*1e3)));let c=await X(`/api/apps/${encodeURIComponent(o)}/ensure?${a.toString()}`,"POST");c.status===404&&M(JSON.stringify({error:"unknown app"})),N(c.body),c.body?.error==="timeout"&&process.exit(2);return}case"ensure-up":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon ensure-up <profile> [--until serving|healthy] [--timeout 300s]"}));let a=new URLSearchParams,l=(r.until||"healthy").toLowerCase();l!=="serving"&&l!=="healthy"&&M(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),a.set("until",l);let i=300;if(r.timeout){let p=ue(r.timeout);p==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),i=Math.min(p,1200)}a.set("timeoutMs",String(Math.ceil(i*1e3)));let c=await X(`/api/profiles/${encodeURIComponent(o)}/ensure-up?${a.toString()}`,"POST");c.status===404&&M(JSON.stringify({error:"unknown profile"})),N(c.body),Array.isArray(c.body?.apps)&&c.body.apps.some(p=>p.timedOut)&&process.exit(2);return}case"ci":{r.positional[0]!=="start"&&st("usage: daimon ci start <profile> [--until ready|healthy] [--timeout 5m] [--json]");let a=r.positional[1];a||st("usage: daimon ci start <profile> [--until ready|healthy] [--timeout 5m] [--json]");let l=(r.until||"healthy").toLowerCase(),i=l==="ready"?"healthy":l;i!=="serving"&&i!=="healthy"&&st(`ci --until must be serving|healthy|ready (got: ${l})`);let c=300;if(r.timeout){let T=ue(r.timeout);T==null&&st(`invalid --timeout: ${r.timeout}`),c=Math.min(T,1200)}let u=new URLSearchParams({until:i,timeoutMs:String(Math.ceil(c*1e3))}),p=await X(`/api/profiles/${encodeURIComponent(a)}/ensure-up?${u.toString()}`,"POST");p.status===404&&(process.stdout.write(JSON.stringify({profile:a,error:"unknown profile",allReached:!1})+`
|
|
267
|
+
`),process.exit(1));let m=p.body||{},g=Array.isArray(m.apps)?m.apps:[],S=g.length>0&&g.every(T=>!T.timedOut),x={profile:a,until:i,allReached:S,perApp:g.map(T=>({name:T.name,state:T.state,reachedTargetMs:T.reachedTargetMs??null,timedOut:!!T.timedOut})),totalMs:m._meta?.totalMs??null};process.stdout.write(JSON.stringify(x)+`
|
|
268
|
+
`),S||process.exit(2);return}case"overview":{let o=new URLSearchParams;r.workspace&&o.set("workspace",r.workspace),r.profile&&o.set("profile",r.profile),r.budget&&Number.isFinite(r.budget)&&r.budget>0&&o.set("budget",String(Math.floor(r.budget)));let a=o.toString(),l=await X("/api/overview"+(a?"?"+a:""));N(l.body);return}case"focus":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon focus <name> [--until serving|healthy|stable] [--timeout 180s]"}));let a=new URLSearchParams,l=(r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(l)||M(JSON.stringify({error:"focus --until must be serving|healthy|stable"})),a.set("until",l);let i=180;if(r.timeout){let c=ue(r.timeout);c==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),i=Math.min(c,600)}a.set("timeoutMs",String(Math.ceil(i*1e3))),await Lr(`/api/apps/${encodeURIComponent(o)}/focus?${a.toString()}`,"POST");return}case"pin-health":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon pin-health <name> [--accept] [--path <p>]"}));let a=await X(`/api/apps/${encodeURIComponent(o)}?format=full`);a.status===404&&M(JSON.stringify({error:"unknown app"}));let l=a.body?.discoveredHealthPath??null,i=r.path??l??null;if(!r.accept){N({app:o,discoveredHealthPath:l,candidate:i,hint:i?`re-run with --accept to persist ${i} to daimon.config.json`:"no path discovered yet; start the app and wait for first serving"});return}i||M(JSON.stringify({error:"no path to pin \u2014 pass --path or wait for auto-discovery"}));let c=await le(`/api/apps/${encodeURIComponent(o)}/health/pin`,"POST",{path:i});c.status===404&&M(JSON.stringify({error:"unknown app"})),N(c.body);return}case"orchestrate":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon orchestrate <profile> [--goal serving|healthy|stable] [--timeout 300s] [--dry-run] [--budget <tokens>]"}));let a=new URLSearchParams;a.set("profile",o);let l=(r.goal||r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(l)||M(JSON.stringify({error:"orchestrate --goal must be serving|healthy|stable"})),a.set("goal",l);let i=300;if(r.timeout){let u=ue(r.timeout);u==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),i=Math.min(u,1200)}a.set("timeoutMs",String(Math.ceil(i*1e3))),r.dryRun&&a.set("dryRun","true"),r.budget&&Number.isFinite(r.budget)&&r.budget>0&&a.set("budget",String(Math.floor(r.budget)));let c=await X(`/api/orchestrate?${a.toString()}`,"POST");c.status===404&&M(JSON.stringify(c.body)),c.status===400&&M(JSON.stringify(c.body)),N(c.body),c.body&&c.body.allReached===!1&&process.exit(2);return}case"try-fix":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon try-fix <name> [--until serving|healthy] [--timeout 180s]"}));let a=new URLSearchParams,l=(r.until||"healthy").toLowerCase();["serving","healthy"].includes(l)||M(JSON.stringify({error:"try-fix --until must be serving|healthy"})),a.set("until",l);let i=180;if(r.timeout){let u=ue(r.timeout);u==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),i=Math.min(u,600)}a.set("timeoutMs",String(Math.ceil(i*1e3)));let c=await X(`/api/apps/${encodeURIComponent(o)}/try-fix?${a.toString()}`,"POST");c.status===404&&M(JSON.stringify({error:"unknown app"})),N(c.body),c.body&&c.body.reached===!1&&process.exit(2);return}case"wait":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon wait <name> [--until serving|healthy|stopped|error] [--timeout 60s]"})),r.all||await ce();let a=Te(r);r.until&&a.set("until",r.until);let l=120;if(r.timeout){let c=ue(r.timeout);c==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(c,600)}a.set("timeout",String(Math.ceil(l)));let i=await X(`/api/apps/${encodeURIComponent(o)}/wait?${a.toString()}`);i.status===412&&Ce(i.body),i.status===404&&M(JSON.stringify({error:"unknown app"})),N(i.body),i.body?.timedOut&&process.exit(2);return}case"up":case"down":{let o=r.positional[0],a=await X("/api/apps"),l=Array.isArray(a.body)?a.body:[],i=(await Qu()).config,c;if(!o)c=i.autoStart||[],t==="up"&&c.length===0&&M(JSON.stringify({error:"no autoStart configured and no profile given"})),t==="down"&&c.length===0&&(c=l.map(S=>S.name));else{let S=i.profiles?.[o];S||M(JSON.stringify({error:`unknown profile: ${o}`})),c=S}let u=t==="up"?"start":"stop";if(t==="up"?await Promise.all(c.map(S=>X(`/api/apps/${encodeURIComponent(S)}/start?withDeps=1`,"POST"))):await Promise.all(c.map(S=>X(`/api/apps/${encodeURIComponent(S)}/${u}`,"POST"))),t==="up"){let x=Date.now(),T=()=>Math.max(5,Math.floor((12e4-(Date.now()-x))/1e3));await Promise.all(c.map(w=>X(`/api/apps/${encodeURIComponent(w)}/wait?until=serving&timeout=${T()}`)))}else await Promise.all(c.map(S=>X(`/api/apps/${encodeURIComponent(S)}/wait?until=stopped&timeout=10`)));let p=await X("/api/apps"),g=(Array.isArray(p.body)?p.body:[]).filter(S=>c.includes(S.name)).map(S=>({name:S.name,status:S.status,health:S.health}));N(g);return}case"timeline":{let o=new URLSearchParams;r.since&&o.set("since",r.since),r.app&&o.set("app",r.app),r.kinds&&o.set("kinds",r.kinds);let a=o.toString(),l=await X("/api/history/timeline"+(a?"?"+a:""));N(l.body);return}case"logs":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon logs <name> [--tail N] [--since 30s]"})),r.all||await ce();let a=Te(r);r.tail!=null&&!Number.isNaN(r.tail)&&a.set("tail",String(r.tail)),r.since&&a.set("since",r.since);let l=a.toString(),i=await X(`/api/apps/${encodeURIComponent(o)}/logs${l?"?"+l:""}`);i.status===412&&Ce(i.body),i.status===404&&M(JSON.stringify({error:"unknown app"})),N(i.body);return}default:{let o=us(t),a=o?`did you mean '${o}'? \u2014 run \`daimon --help\` to list commands`:"run `daimon --help` to list commands";st(`unknown command: ${t}`,a)}}}rp().catch(n=>M(JSON.stringify({error:n?.message||String(n)})));
|