daimon 0.8.1 → 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 +152 -0
- package/README.md +48 -1
- package/dist/cli.js +100 -85
- package/dist/dashboard/browser/chunk-2LMH5KDX.js +5 -0
- package/dist/dashboard/browser/chunk-2QORICNU.js +1 -0
- package/dist/dashboard/browser/chunk-36JZZZCV.js +3 -0
- package/dist/dashboard/browser/{chunk-QSBOKS53.js → chunk-3S7OJ77P.js} +1 -1
- package/dist/dashboard/browser/chunk-42QQHEGP.js +2 -0
- package/dist/dashboard/browser/chunk-4L223A7A.js +1 -0
- package/dist/dashboard/browser/chunk-532NB4ME.js +1 -0
- package/dist/dashboard/browser/chunk-6CP6NCA6.js +4 -0
- package/dist/dashboard/browser/chunk-6OMBXV4F.js +1 -0
- package/dist/dashboard/browser/chunk-6YXOOFGY.js +1 -0
- package/dist/dashboard/browser/{chunk-6WZJCF24.js → chunk-AHO3BCLI.js} +1 -1
- package/dist/dashboard/browser/chunk-ASK7FG27.js +1 -0
- package/dist/dashboard/browser/{chunk-OHX55ZU4.js → chunk-BCGQJHY3.js} +1 -1
- package/dist/dashboard/browser/chunk-BDTAVYPH.js +1 -0
- package/dist/dashboard/browser/chunk-BFBXHJEF.js +1 -0
- package/dist/dashboard/browser/chunk-BKYXU3OY.js +1 -0
- package/dist/dashboard/browser/chunk-BPUIUSAU.js +2 -0
- package/dist/dashboard/browser/chunk-C6SNIY22.js +2 -0
- package/dist/dashboard/browser/{chunk-PJPGLT4T.js → chunk-CCRYWDXZ.js} +1 -1
- package/dist/dashboard/browser/chunk-DNHNU64I.js +2 -0
- package/dist/dashboard/browser/chunk-DRBVSI3B.js +1 -0
- package/dist/dashboard/browser/{chunk-7NRE3SNA.js → chunk-EXOJOB6H.js} +2 -2
- package/dist/dashboard/browser/chunk-EYOED3X7.js +2 -0
- package/dist/dashboard/browser/chunk-G3IBZZQH.js +2 -0
- package/dist/dashboard/browser/chunk-H3HRZLHG.js +4 -0
- package/dist/dashboard/browser/chunk-H5GKWN4K.js +1 -0
- package/dist/dashboard/browser/{chunk-NDSAQ2HK.js → chunk-HVK4GEK7.js} +1 -1
- package/dist/dashboard/browser/{chunk-7NPLP3QD.js → chunk-HYIZY5FQ.js} +1 -1
- package/dist/dashboard/browser/chunk-ITSOVQEA.js +1 -0
- package/dist/dashboard/browser/{chunk-Q772THBA.js → chunk-JODWQVMA.js} +1 -2
- package/dist/dashboard/browser/chunk-LAMOHX23.js +1 -0
- package/dist/dashboard/browser/chunk-NMKAKRON.js +1 -0
- package/dist/dashboard/browser/{chunk-LBRCWYRN.js → chunk-NY5IR366.js} +1 -1
- package/dist/dashboard/browser/chunk-OOQPWG6B.js +1 -0
- package/dist/dashboard/browser/chunk-P3Q7RWT5.js +2 -0
- package/dist/dashboard/browser/{chunk-P5IU57TV.js → chunk-PVPELZPO.js} +1 -1
- package/dist/dashboard/browser/{chunk-V2KNRAE4.js → chunk-QHXOUNPA.js} +1 -1
- package/dist/dashboard/browser/chunk-RMV7CR6Y.js +2 -0
- package/dist/dashboard/browser/chunk-RQSDQXNY.js +1 -0
- package/dist/dashboard/browser/chunk-RWX5JIT4.js +1 -0
- package/dist/dashboard/browser/{chunk-UC3XMN2Y.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-2BXIFQGQ.js → chunk-UXLEE3F2.js} +1 -1
- package/dist/dashboard/browser/chunk-XPP3TYS2.js +2 -0
- package/dist/dashboard/browser/{chunk-EIWOTZT3.js → chunk-YFYMS5EE.js} +1 -1
- package/dist/dashboard/browser/chunk-YPVVBWNF.js +1 -0
- package/dist/dashboard/browser/{chunk-3WKRVGPT.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 -50
- package/dist/mcp.js +3 -3
- package/package.json +8 -3
- package/dist/dashboard/browser/chunk-44JIQO3X.js +0 -1
- package/dist/dashboard/browser/chunk-4BAKWDAV.js +0 -1
- package/dist/dashboard/browser/chunk-4OCNYL7T.js +0 -1
- package/dist/dashboard/browser/chunk-7C772RJ3.js +0 -3
- package/dist/dashboard/browser/chunk-A4BNXJUT.js +0 -1
- package/dist/dashboard/browser/chunk-CILFSVSP.js +0 -2
- package/dist/dashboard/browser/chunk-CM4RQF3A.js +0 -5
- package/dist/dashboard/browser/chunk-CY5YRTQK.js +0 -1
- package/dist/dashboard/browser/chunk-GYWEXV2L.js +0 -3
- package/dist/dashboard/browser/chunk-H2N3RBHF.js +0 -1
- package/dist/dashboard/browser/chunk-H3L4MTG4.js +0 -5
- package/dist/dashboard/browser/chunk-I65I7J5Q.js +0 -2
- package/dist/dashboard/browser/chunk-K43KW4K2.js +0 -4
- package/dist/dashboard/browser/chunk-K7S4ITPJ.js +0 -2
- package/dist/dashboard/browser/chunk-KL6X73FV.js +0 -1
- package/dist/dashboard/browser/chunk-KLH6B22T.js +0 -1
- package/dist/dashboard/browser/chunk-LBL7Z5BE.js +0 -5
- package/dist/dashboard/browser/chunk-LHAMBNO6.js +0 -1
- package/dist/dashboard/browser/chunk-NX6DTO32.js +0 -1
- package/dist/dashboard/browser/chunk-P5IE6DI6.js +0 -2
- package/dist/dashboard/browser/chunk-PMAG4W5W.js +0 -1
- package/dist/dashboard/browser/chunk-VM2FOT77.js +0 -1
- package/dist/dashboard/browser/chunk-Y6B6X4Y6.js +0 -2
- package/dist/dashboard/browser/chunk-YYAZGY5M.js +0 -1
- package/dist/dashboard/browser/main-O76X7RMS.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 yi=Object.defineProperty;var F=(n,t)=>()=>(n&&(t=n(n=0)),t);var yt=(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,107 +50,110 @@ var yi=Object.defineProperty;var F=(n,t)=>()=>(n&&(t=n(n=0)),t);var yt=(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 l of a)l.kind==="event"?e.run(l.row.ts,l.row.app,l.row.type,l.row.from_state,l.row.to_state,l.row.message):l.kind==="compile"?r.run(l.row.ts,l.row.app,l.row.ms):l.kind==="bundle"?o.run(l.row.ts,l.row.app,l.row.initialKB,l.row.lazyKB,l.row.fileCount):s.run(l.row.ts,l.row.app,l.row.task,l.row.exit_code,l.row.duration_ms,l.row.summary)})(t)}catch(e){this.warnOnce(`history write failed: ${e?.message||e}`)}}runRetention(){if(this.db)try{let t=Date.now()-this.cfg.retentionDays*864e5;this.db.prepare("DELETE FROM events WHERE ts < ?").run(t),this.db.prepare("DELETE FROM compile_times WHERE ts < ?").run(t),this.db.prepare("DELETE FROM task_runs WHERE ts < ?").run(t),this.db.prepare("DELETE FROM bundles WHERE ts < ?").run(t),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=(d,u)=>{let g=Math.floor(d/r)*r,y=s.get(g)??{sum:0,n:0};y.sum+=u,y.n+=1,s.set(g,y)},i=d=>{let u=Math.floor(d/r)*r,g=s.get(u)??{sum:0,n:0};g.sum+=1,g.n+=1,s.set(u,g)},a=0;if(t.metric==="compile"){let d=this.queryCompiles({app:t.app,since:e,limit:1e4});a=d.length;for(let u of d)o(u.ts,u.ms)}else if(t.metric==="bundle"){let d=this.queryBundles({app:t.app,since:e,limit:1e4});a=d.length;for(let u of d){let g=Math.floor(u.ts/r)*r,y=s.get(g)??{sum:0,n:0,sum2:0};y.sum+=u.initialKB,y.sum2=(y.sum2??0)+u.lazyKB,y.n+=1,s.set(g,y)}}else if(t.metric==="errors"){let d=this.queryEvents({app:t.app,since:e,limit:1e4});for(let u of d)(u.type==="error-new"||u.type==="error-recur")&&(i(u.ts),a++)}else{let d=this.queryEvents({app:t.app,since:e,limit:1e4});for(let u of d)u.type==="status"&&u.to_state==="starting"&&(u.from_state==="error"||u.from_state==="serving"||u.from_state==="compiling")&&(i(u.ts),a++)}let l=[],c=[...s.entries()].sort((d,u)=>d[0]-u[0]);for(let[d,u]of c)t.metric==="compile"||t.metric==="bundle"?l.push({t:d,v:Math.round(u.sum/u.n),...u.sum2!=null?{v2:Math.round(u.sum2/u.n)}:{}}):l.push({t:d,v:u.sum});return{points:l,count:a}}queryTasks(t){if(!this.db)return[];let e=[],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,l=[...r].sort((f,w)=>f.ts-w.ts);for(let f of l)f.type==="status"&&(f.to_state==="serving"&&!i?(i=!0,a=f.ts):i&&f.to_state!=="serving"&&a!=null&&(s+=f.ts-a,i=!1,a=null));i&&a!=null&&(s+=Date.now()-a);let c=Math.round(s/(24*3600*1e3)*1e3)/10,d=r.filter(f=>f.type==="status"&&f.to_state==="starting"&&(f.from_state==="serving"||f.from_state==="error"||f.from_state==="compiling")).length,u=this.queryCompiles({app:t,since:e,limit:1e3}).map(f=>f.ms).sort((f,w)=>f-w),g=(f,w)=>{if(f.length===0)return null;let T=Math.min(f.length-1,Math.floor((f.length-1)*w));return f[T]},y=g(u,.5),p=g(u,.95),m=new Map;for(let f of r)if(f.type==="error-new"||f.type==="error-recur"){let w=f.message??"";if(!w)continue;m.set(w,(m.get(w)??0)+1)}let h=[...m.entries()].sort((f,w)=>w[1]-f[1]).slice(0,5).map(([f,w])=>({message:f,count:w}));return{uptimePct24h:c,restartCount24h:d,compileP50:y,compileP95:p,topErrors:h}}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 gn}from"node:child_process";import Tr from"tree-kill";function Ce(n){if(process.platform==="win32"){let o=gn("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=gn("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${i}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),l,c;try{let d=JSON.parse((a.stdout||"").trim()||"{}");l=typeof d.Name=="string"?d.Name:void 0,c=typeof d.CommandLine=="string"?d.CommandLine:void 0}catch{}return{pid:i,name:l,cmd:c}}let t=gn("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 Cr(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 Er(n){return new Promise(t=>{if(!n.pid||n.pid===process.pid){t(!1);return}Tr(n.pid,"SIGTERM",e=>{if(e){setTimeout(()=>Tr(n.pid,"SIGKILL",r=>t(!r)),500);return}t(!0)})})}var yn=F(()=>{"use strict"});import Ee from"node:fs";import Oi from"node:os";import Pr from"node:path";function Rr(n){return Ee.readFileSync(n,"utf8").split(/\r?\n/).filter(e=>e.trim()).map(e=>JSON.parse(e))}var Pe,wn=F(()=>{"use strict";Pe=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=Pr.join(Oi.homedir(),".daimon","sessions");Ee.mkdirSync(t,{recursive:!0});let e=Pr.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return Ee.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{Ee.appendFileSync(this.file,e)}catch{}}}});import Ni from"node:fs";import bn from"node:path";import{fileURLToPath as Mi}from"node:url";function $i(){let n=[bn.resolve(Ar,"..","package.json"),bn.resolve(Ar,"..","..","package.json")];for(let t of n)try{return JSON.parse(Ni.readFileSync(t,"utf8"))}catch{}return{}}var Ar,Z,Et=F(()=>{"use strict";Ar=bn.dirname(Mi(import.meta.url));Z=$i().version||"0.0.0"});import Zt from"node:fs";import Re from"node:path";import ji from"node:os";import{spawn as _i}from"node:child_process";import{fileURLToPath as Di}from"node:url";function ut(){return Sn}function Ae(){return Qt}function vn(n){try{return process.kill(n,0),!0}catch(t){return t&&t.code==="EPERM"}}function ot(){try{let n=Zt.readFileSync(Qt,"utf8"),t=JSON.parse(n);if(!t||typeof t.pid!="number")return null;if(!vn(t.pid)){try{Zt.unlinkSync(Qt)}catch{}return null}return t}catch{return null}}function Or(n){Zt.mkdirSync(Sn,{recursive:!0});let t=Qt+"."+process.pid+".tmp";Zt.writeFileSync(t,JSON.stringify(n)),Zt.renameSync(t,Qt)}function wt(){try{Zt.unlinkSync(Qt)}catch{}}function Li(){let n=Re.dirname(Di(import.meta.url));return Re.join(n,"main.js")}async function Pt(n={}){let t={...process.env};n.port&&(t.DAIMON_PORT=String(n.port)),_i(process.execPath,[Li(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let r=Date.now();for(;Date.now()-r<5e3;){let s=ot();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 Bt(n,t){let e=Date.now();for(;Date.now()-e<t;){if(!vn(n))return!0;await new Promise(r=>setTimeout(r,100))}return!vn(n)}function Nr(n,t,e){return{pid:process.pid,apiPort:n,version:Z,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var Sn,Qt,bt=F(()=>{"use strict";Et();Sn=Re.join(ji.homedir(),".daimon"),Qt=Re.join(Sn,"daemon.lock")});var Qr={};yt(Qr,{promptClaudeInstall:()=>Zi});import Jt,{useState as Vr}from"react";import{Box as Zr,render as Ki,Text as $e,useApp as zi,useInput as Yi}from"ink";function Vi({onDone:n}){let{exit:t}=zi(),[e,r]=Vr(0),[s,o]=Vr({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 Yi((a,l)=>{if(l.escape||a==="q"&&!l.shift){n(null),t();return}if(l.upArrow)r(c=>Math.max(0,c-1));else if(l.downArrow)r(c=>Math.min(i.length-1,c+1));else if(a===" "){let c=i[e].key;o(d=>({...d,[c]:!d[c]}))}else l.return&&(n(s),t())}),Jt.createElement(Zr,{flexDirection:"column",paddingX:1},Jt.createElement($e,{bold:!0,color:"cyan"},"Install Claude Code integration artifacts"),Jt.createElement($e,{dimColor:!0},"Space toggles \xB7 Enter confirms \xB7 Esc cancels"),i.map((a,l)=>Jt.createElement(Zr,{key:a.key},Jt.createElement($e,{color:l===e?"cyan":void 0},l===e?"\u25B8 ":" "),Jt.createElement($e,null,"[",s[a.key]?"x":" ","] ",a.label))))}async function Zi(){return new Promise(n=>{let t=!1;Ki(Jt.createElement(Vi,{onDone:r=>{t||(t=!0,n(r))}})).waitUntilExit().then(()=>{t||(t=!0,n(null))})})}var ts=F(()=>{"use strict"});import Qi from"node:crypto";function da(n){for(let{tool:t,rx:e}of pa)if(e.test(n))return t}function Sa(n){return Qi.createHash("sha1").update(n).digest("hex").slice(0,16)}function ka(n){let t={message:n},e=n.match(sa)||n.match(ra);e&&(t.code=`TS${e[1]}`);let r=n.match(ia)||n.match(es)||n.match(oa);if(r)t.file=r[1],t.line=Number(r[2]),t.col=Number(r[3]);else{let o=n.match(la);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(ca);if(i)t.file=i[1];else{let a=n.match(rs);if(a)t.file=a[1],t.line=Number(a[2]),t.col=Number(a[3]);else{let l=n.match(ns);l&&(t.file=l[1],t.line=Number(l[2]))}}}}let s=da(n);return s&&(t.tool=s),t}function xa(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 Ta(n,t="127.0.0.1"){let e=n.match(fa)||n.match(ma)||n.match(ha)||n.match(ga);if(!e)return null;let r=e[1].replace(/[),.;]+$/,"");return xa(r,t)}function Ca(n,t){if(ya.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="initial",!1;if(wa.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="lazy",!1;let e=t.match(ba);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(va);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 ss(n,t){let e=t.match(ua),r=e?null:t.match(es),s=!e&&!r?t.match(rs):null,o=e??r??s;if(o&&n.lastErrorHash){let p=n.errors.get(n.lastErrorHash);p&&!p.parsed?.file&&(p.parsed={...p.parsed??{message:p.message},file:o[1],line:Number(o[2]),col:Number(o[3])})}else if(n.lastErrorHash){let p=t.match(ns),m=p?null:t.match(aa);if(p||m){let h=n.errors.get(n.lastErrorHash);if(h&&!h.parsed?.file){let f=p??m;h.parsed={...h.parsed??{message:h.message},file:f[1],line:Number(f[2])}}}}let i=t.trim();if(!i)return null;let a=n.status,l=!1,c,d=Ta(i);d&&!n.announcedUrl&&(n.announcedUrl=d,c=d);let u=Ca(n,i),g;if(ta.some(p=>p.test(i))){let p=n.status==="error"||!!n.recoveringFromError;if(n.status==="compiling"||n.status==="starting"||n.status==="error"){let m=Date.now();n.compileStartedAt!=null?(g=m-n.compileStartedAt,n.lastCompileMs=g,n.lastCompileAt=m,n.compileStartedAt=null,n.compileHistory.push(g),n.compileHistory.length>20&&n.compileHistory.splice(0,n.compileHistory.length-20)):n.lastCompileAt=m}n.status="serving",p&&(n.errors.clear(),n.recoveringFromError=!1)}else ea.some(p=>p.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 y;if(na.some(p=>p.test(i))){let p=Sa(i),m=Date.now(),h=n.errors.get(p),f=!1,w;h?(h.count+=1,h.lastSeen=m,w=h):(w={message:i,count:1,firstSeen:m,lastSeen:m,parsed:ka(i)},n.errors.set(p,w),f=!0),n.lastErrorHash=p,y={entry:w,isNew:f},n.status="error"}return l=n.status!==a,{statusChanged:l,error:y,announcedUrl:c,bundleUpdated:u,compileMs:g}}var ta,ea,na,ra,sa,oa,es,ia,ns,rs,aa,ca,la,ua,pa,fa,ma,ha,ga,ya,wa,ba,va,os=F(()=>{"use strict";ta=[/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],ea=[/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],na=[/^\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*\(/],ra=/\berror TS(\d+)/,sa=/✘\s*\[ERROR\]\s*TS(\d+)/,oa=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)/,es=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte|py|rb|go|rs)):(\d+):(\d+)\)/,ia=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,ns=/File\s+"([^"]+\.py)",\s+line\s+(\d+)/,rs=/^\s*-->\s+([^\s:]+\.rs):(\d+):(\d+)/,aa=/^([^\s:()]+\.rb):(\d+):in\b/,ca=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,la=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,ua=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,pa=[{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):/}];fa=/Local:\s+(https?:\/\/\S+)/i,ma=/Server running at\s+(https?:\/\/\S+)/i,ha=/listening on\s+(https?:\/\/\S+)/i,ga=/(?:listening|listen)\s+(https?:\/\/\S+)/i,ya=/Initial chunk files/i,wa=/Lazy chunk files/i,ba=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,va=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i});import{spawn as Ea}from"node:child_process";import is from"tree-kill";import Pa from"strip-ansi";var as,je,cs=F(()=>{"use strict";os();as=500,je=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"},l=Ea(i,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=l,r.pid=l.pid??null,r.port=e,l.stdout?.on("data",c=>this.handleChunk(c,"stdout")),l.stderr?.on("data",c=>this.handleChunk(c,"stderr")),l.on("exit",(c,d)=>{let u=r.status,g=this.stopping;g?(r.status="stopped",r.lastStatusMessage=`stopped (code=${c??"null"}${d?`, ${d}`:""})`):c!==0?(r.status="error",r.lastStatusMessage=`process exited with code ${c}${d?` (${d})`:""}`):r.status="stopped",r.pid=null,r.health="unknown",this.child=null,this.stopping=!1,u!==r.status&&this.deps.onStatusChange?.(u,r.status,r.lastStatusMessage),this.deps.onExit?.(c,d,g),this.deps.onStateChange()}),l.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(`
|
|
53
|
-
`);if(o<0)return;let
|
|
54
|
-
`,r=Buffer.from(e,"utf8");
|
|
55
|
-
`))}}});import{spawn as
|
|
56
|
-
`);if(
|
|
57
|
-
`)+(
|
|
58
|
-
`+
|
|
59
|
-
`);if(d<0)return;let u=i.slice(0,d);i=i.slice(d+1);for(let g of u.split(/\r?\n/))g.length&&(o.push(ds(g)),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(c=>{if(!s.pid){c();return}let d=!1,u=()=>{d||(d=!0,c())};s.once("exit",u),us(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&us(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(u,3500)})}}var Aa,Oa,Na,Ma,$a,ja,_a,Da,La,Ia,Fa,Ba,Ua,gs=F(()=>{"use strict";Aa=/Tests:\s+(?:(\d+)\s+failed,\s+)?(?:(\d+)\s+skipped,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Oa=/Test Suites:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,Na=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,Ma=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i,$a=/Tests\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,ja=/Test Files\s+(?:(\d+)\s+failed\s*\|\s*)?(\d+)\s+passed(?:\s*\((\d+)\))?/,_a=/(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+\d+\s+skipped)?\s+in\s+([\d.]+)s/,Da=/(\d+)\s+examples?,\s+(\d+)\s+failures?/,La=/^(ok|FAIL|---\s+FAIL)\s+\S+\s+([\d.]+)s/,Ia=/test result:\s*(?:ok|FAILED)\.\s+(\d+)\s+passed;\s+(\d+)\s+failed/,Fa=/^\s*✕\s+(.+?)(?:\s+\((\d+)\s*ms\))?$/,Ba=/^\s*FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|spec\.[a-z]+))/,Ua=/^FAILED\s+(\S+)::([^\s]+)/});import ws from"node:fs";import ys from"node:path";function bs(n){let t={},e;try{e=ws.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 Pn(n,t){return ys.isAbsolute(t)?t:ys.join(n,t)}function Rn(n,t){return t.filter(e=>ws.existsSync(Pn(n,e)))}var vs=F(()=>{"use strict"});import Ja from"node:fs";import Wa from"node:path";function Ga(){return Wa.join(ut(),"secrets.json")}function Ss(){try{let n=Ja.readFileSync(Ga(),"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 ks(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 xs=F(()=>{"use strict";bt()});import{EventEmitter as qa}from"node:events";var Ts,De,Cs=F(()=>{"use strict";cs();fe();ls();de();gs();yn();vs();xs();wn();Ts=500,De=class extends qa{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new Pe;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new Yt(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.tags,s.workspaceLabel??null),proc:null})}getConfig(){return this.config}addDiscoveredApp(t){this.entries.has(t.name)||(this.entries.set(t.name,{app:t,state:this.freshState(t.name,t.tags,t.workspaceLabel??null),proc:null}),this.emit("change"))}updateDiscoveredApp(t){let e=this.entries.get(t.name);e&&(e.app=t,e.state.tags=t.tags,e.state.workspaceLabel=t.workspaceLabel??null,e.state.dependsOn=this.config.depends?.[t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r=null){return{name:t,status:"stopped",port:null,pid:null,startedAt:null,compileStartedAt:null,lastCompileMs:null,lastCompileAt:null,logBuffer:[],errors:new Map,compileHistory:[],health:"unknown",lastHealthAt:null,cpu:null,memMB:null,restartAttempts:0,restartWindowStart:null,nextRestartAt:null,tags:e,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[t]??[],workspaceLabel:r,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}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 l=this.eventBuffer.length-1;l>=0;l--){let c=this.eventBuffer[l];if(c.app===t&&c.type==="status"){a=Date.now()-c.ts;break}}return{name:r.name,status:r.status,port:r.port,url:i,errorCount:[...r.errors.values()].reduce((l,c)=>l+c.count,0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,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>Ts&&this.eventBuffer.splice(0,this.eventBuffer.length-Ts),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(y){return e.state.status="error",e.state.lastStatusMessage=y.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:y.message}),this.emit("change"),{ok:!1,status:"error",error:y.message}}if(!await Tt(s)){let y=Ce(s),p=Cr(s,y);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=p,this.recordEvent({app:t,type:"status",from:r,to:"error",message:p}),this.emit("change"),{ok:!1,status:"error",error:p}}e.state.health="unknown",e.state.lastHealthAt=null,e.state.announcedUrl=null,e.state.lastHealthError=null,e.state.cachedProbeHost=null,e.state.stale=!1,e.state.lastLogTs=null,e.resolvedUrl=void 0,!e.logger&&this.config.logs.enabled&&(e.logger=new _e(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],l={};if(a.length){let y=e.state.activeEnvFile;(!y||!Rn(e.app.workspaceRoot,[y]).length)&&(y=Rn(e.app.workspaceRoot,a)[0]??null,y&&(e.state.activeEnvFile=y)),y&&(l=bs(Pn(e.app.workspaceRoot,y)))}let c={...l,...this.config.overrides?.[t]?.env??{},...i?.env??{}},d=Ss(),u=ks(c,d),g=new je({state:e.state,app:e.app,port:s,envOverride:Object.keys(u).length?u:void 0,commandOverride:i?.command,onStateChange:()=>this.emit("change"),onStatusChange:(y,p,m)=>{this.recordEvent({app:t,type:"status",from:y,to:p,message:m}),(p==="stopped"||p==="error")&&(y==="serving"||y==="compiling")&&this.armCascade(t)},onErrorRecorded:(y,p)=>this.recordEvent({app:t,type:p?"error-new":"error-recur",message:y.message}),onExit:(y,p,m)=>this.emit("childExit",{name:t,code:y,signal:p,stopping:m}),onLogLine:y=>{e.logger?.write(y),this.emit("log",{name:t,ts:Date.now(),line:y})},onCompile:y=>{this.history?.recordCompile(t,y);let p=this.getState(t),m=e.lastBundleInitialKB;if(p.bundle&&p.bundle.initialKB>0){if(m&&m>0){let h=(p.bundle.initialKB-m)/m*100;p.bundleRegressionPct=Math.round(h*10)/10,h>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${p.bundleRegressionPct}% (${m}->${p.bundle.initialKB})`})}else p.bundleRegressionPct=null;e.lastBundleInitialKB=p.bundle.initialKB}this.checkCompileRegression(t,y),this.emit("compile",{name:t,ms:y})},onBundleUpdate:()=>{let y=this.getState(t);y?.bundle&&(y.bundle.initialKB>0||y.bundle.lazyKB>0)&&this.history?.recordBundle(t,y.bundle.initialKB,y.bundle.lazyKB,y.bundle.files.length),this.emit("bundleUpdate",{name:t})}});return e.proc=g,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),g.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let 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=ke(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=xe(this.config.depends??{},r),o=[],i=e.waitMs??6e4;for(let a of s){let l=await Promise.all(a.map(d=>this.start(d)));for(let d=0;d<a.length;d++){let u=l[d];if(!u.ok)return o.push({name:a[d],status:u.status,health:"unknown",error:u.error}),{ok:!1,results:o}}let c=await Promise.all(a.map(d=>this.waitFor(d,"healthy",i)));for(let d=0;d<a.length;d++){let u=c[d],g=!u.timedOut&&u.status==="serving"&&u.health==="healthy";if(o.push({name:u.name,status:u.status,health:u.health,error:g?void 0:u.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!g)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=kr(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 ms(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=hs(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(l=>l.ms!==e).slice(0,30).map(l=>l.ms);if(o.length<10)return;let i=[...o].sort((l,c)=>l-c),a=i[Math.floor((i.length-1)*.5)];e>2*a&&this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs p50 ${(a/1e3).toFixed(1)}s`})}watchTaskLogs(t,e,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 u=i.state;return e==="serving"&&u.status==="serving"||e==="healthy"&&u.status==="serving"&&u.health==="healthy"||e==="stopped"&&u.status==="stopped"||e==="error"&&u.status==="error"},l=u=>{this.off("change",c),clearTimeout(d);let g=i?.state;s({name:t,status:g?.status??"unknown",health:g?.health??"unknown",timedOut:u,waitedMs:Date.now()-o})},c=()=>{a()&&l(!1)};if(a()){s({name:t,status:i.state.status,health:i.state.health,timedOut:!1,waitedMs:0});return}let d=setTimeout(()=>l(!0),r);this.on("change",c)})}}});import Nn from"node:fs";import Es from"node:path";import Xa from"node:os";function Ka(){try{let n=Nn.readFileSync(Mn,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}function za(n){On=n,!An&&(An=setTimeout(()=>{An=null;let t=On;if(On=null,!!t)try{Nn.mkdirSync(Es.dirname(Mn),{recursive:!0}),Nn.writeFileSync(Mn,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 l=ot();if(l)try{fetch(`http://127.0.0.1:${l.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${a} dead searchRoot entr${a===1?"y":"ies"} from ${r} (${[...o].join(", ")}); triggered soft-reload. To undo: edit ${r} and re-add the path(s).`}async function Pc(n){let t={ran:[],skipped:[],errors:[]};for(let e of Ks){if(!n.permitted.includes(e))continue;let r=Ec[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 Ks,Ec,se=F(()=>{"use strict";bt();Xt();Te();fe();Ks=["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"];Ec={"orphan-daemon":{detect:cc,fix:lc},"stale-lock":{detect:uc,fix:pc},"missing-search-root":{detect:dc,fix:fc},"corrupt-history-db":{detect:mc,fix:hc},"port-conflict-pred":{detect:gc,fix:yc},"node-version-mismatch":{detect:wc,fix:bc},"orphan-node-modules":{detect:zs,fix:Sc},"orphan-venv":{detect:Ys,fix:kc},"orphan-bundler-cache":{detect:Vs,fix:xc},"orphan-cargo-target":{detect:Zs,fix:Tc},"dead-search-root":{detect:Qs,fix:Cc}}});var Ln={};yt(Ln,{orchestrateProfile:()=>Oc});function to(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 eo(n,t,e,r,s){let o=Date.now();if(e!=="stable"){let l=await n.waitFor(t,e==="serving"?"serving":"healthy",r);return{reached:!l.timedOut,waitedMs:l.waitedMs}}let i=Date.now(),a=l=>{l?.app===t&&(i=Date.now())};n.on("event",a);try{for(;Date.now()-o<r;){if(to(n,t,e,i,s))return{reached:!0,waitedMs:Date.now()-o};await new Promise(l=>setTimeout(l,500))}return{reached:to(n,t,e,i,s),waitedMs:Date.now()-o}}finally{n.off("event",a)}}async function Oc(n,t,e){let r=Date.now(),s=t.profiles?.[e.profile];if(!s)return{error:`unknown profile: ${e.profile}`};let o=s.filter(h=>n.summary(h)!=null),i=Array.from(new Set(o.flatMap(h=>ke(t.depends??{},h)))).filter(h=>n.summary(h)!=null),a=xe(t.depends??{},i),l=[];for(let h of i){let f=n.summary(h);f&&(e.goal==="serving"&&f.status==="serving"||(e.goal==="healthy"||e.goal==="stable")&&f.status==="serving"&&f.health==="healthy")&&l.push(h)}if(e.dryRun){let h=i.filter(f=>!l.includes(f));return{profile:e.profile,goal:e.goal,perApp:h.map(f=>({name:f,reached:!1,tries:0})),totalMs:Date.now()-r,allReached:h.length===0,dryRun:!0,plannedOrder:a,alreadyHealthy:l}}let c=Math.max(5e3,Math.floor(e.timeoutMs/2)),d=e.stableMs??5e3,u=new Map;for(let h of i)u.set(h,{name:h,reached:!1,tries:0});for(let h of a)await Promise.all(h.map(async f=>{let w=n.summary(f);if(!w){u.set(f,{name:f,reached:!1,tries:0,error:"unknown app"});return}if(l.includes(f)){u.set(f,{name:f,reached:!0,tries:0});return}w.status!=="starting"&&w.status!=="compiling"&&w.status!=="serving"&&await n.start(f)})),await Promise.all(h.map(async f=>{if(u.get(f)?.reached)return;let w=await eo(n,f,e.goal,c,d),T=u.get(f);T.tries=1,T.waitedMs=w.waitedMs,T.reached=w.reached,u.set(f,T)}));let g=[...u.values()].filter(h=>!h.reached);if(g.length>0){let{runAutoFix:h,ALL_AUTO_FIX:f}=await Promise.resolve().then(()=>(se(),re)),w=t.doctor?.autoFix?.permitted??f,T=Math.max(5e3,e.timeoutMs-(Date.now()-r)),E=Math.max(5e3,Math.floor(T/Math.max(g.length,1))),b={ran:[]};try{b=await h({permitted:w,dryRun:!1})}catch{}let _=(b.ran??[]).map(A=>A.name);await Promise.all(g.map(async A=>{let x=u.get(A.name);x.tries=2;try{let O=await n.restart(A.name);O?.ok||(x.error=O?.error??"restart failed")}catch(O){x.error=O?.message??String(O)}let P=await eo(n,A.name,e.goal,E,d);if(x.waitedMs=(x.waitedMs??0)+P.waitedMs,x.reached=P.reached,!x.reached){let O=n.errors(A.name)??[];x.stillFailing=O.slice(0,3).map(S=>({file:S.parsed?.file??null,line:S.parsed?.line??null,code:S.parsed?.code??null,tool:S.parsed?.tool??null,message:S.parsed?.message??S.message}))}x.fixed=_,u.set(A.name,x)}))}let y=[...u.values()],p=y.every(h=>h.reached),m={profile:e.profile,goal:e.goal,perApp:y,totalMs:Date.now()-r,allReached:p};if(typeof e.budgetTokens=="number"&&e.budgetTokens>0){let h=e.budgetTokens,f=0,w=0;for(let T of y)if(T.stillFailing){let E=T.stillFailing.length*Rc;E>h?(f+=T.stillFailing.length,delete T.stillFailing):h-=E}for(;h<0||y.length*Ac>Math.max(h,e.budgetTokens/4);){let T=y.findIndex(E=>E.reached);if(T===-1)break;y.splice(T,1),w++}(f||w)&&(m._meta={omitted:{}},f&&(m._meta.omitted.stillFailing=f),w&&(m._meta.omitted.perApp=w))}return m}var Rc,Ac,In=F(()=>{"use strict";de();Rc=60,Ac=25});import Nc from"node:http";import Mc from"node:crypto";import Wt from"node:fs";import pt from"node:path";import{fileURLToPath as $c}from"node:url";function Fn(){let n=[pt.resolve(He,"dashboard","browser"),pt.resolve(He,"dashboard"),pt.resolve(He,"..","dist","dashboard","browser"),pt.resolve(He,"..","dist","dashboard")];for(let t of n)if(Wt.existsSync(pt.join(t,"index.html")))return t;return null}function ye(n,t){try{if(!Wt.statSync(t).isFile())return!1;let r=pt.extname(t).toLowerCase(),s=_c[r]??"application/octet-stream",o=Wt.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 ie(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 Je(n,t){let e=(n.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function Dc(n){return{name:n.name,status:n.status,port:n.port,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null}}function oe(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 Bn(n){let t=n.parsed;return t&&(t.file||t.code)?{file:t.file??null,line:t.line??null,col:t.col??null,code:t.code??null,message:t.message??n.message}:{file:null,line:null,col:null,code:null,message:n.message}}function no(n){if(!n)return{};if(/^\d{10,}$/.test(n))return{sinceTs:Number(n)};let t=ie(n);return t!=null?{sinceMs:t}:{}}function Ic(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))Lc.test(s)&&(r[s]="***")}return t}function Un(n){if(!n)return"";try{let t=Wt.readFileSync(n);return Mc.createHash("sha1").update(t).digest("hex")}catch{return""}}function ro(n,t,e={}){let r=new Le,s=Nc.createServer(async(o,i)=>{try{let a=new URL(o.url||"/","http://127.0.0.1"),l=o.method||"GET",c=a.pathname.replace(/\/$/,"").split("/").filter(Boolean),d=()=>{let m=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!m)return!0;let h=o.headers.authorization;return typeof h=="string"&&h.toLowerCase().startsWith("bearer ")&&h.slice(7).trim()===m?!0:(v(i,401,{error:"unauthorized"}),!1)};if(l==="POST"&&a.pathname==="/api/shutdown"){if(!d())return;v(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(l==="GET"){let p=e.getConfig(),m=Un(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:m}),i.end(JSON.stringify({etag:m,config:Ic(p)}));return}if(l==="PATCH"&&e.patchConfig){if(!d())return;let p=o.headers["if-match"]?.trim(),m=Un(e.configPath);if(!p||p!==m){v(i,412,{error:"etag mismatch",current:m});return}let h={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(T=>{let E=[];o.on("data",b=>E.push(b)),o.on("end",()=>{try{h=JSON.parse(Buffer.concat(E).toString("utf8"))}catch{}T()})});let f=e.patchConfig(h);if(!f.ok){v(i,400,{error:f.error});return}let w=Un(e.configPath);try{let T=o.socket.remoteAddress||"127.0.0.1";Fs(T,h,h,f.applied)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:w}),i.end(JSON.stringify({etag:w,applied:f.applied,addedApps:f.addedApps,removedApps:f.removedApps,restartRequired:f.restartRequired}));return}v(i,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&l==="GET"){v(i,200,Hs());return}if(a.pathname==="/api/self"&&l==="GET"){if(!e.selfMetrics){v(i,503,{error:"self-metrics collector not attached"});return}v(i,200,e.selfMetrics.snapshot());return}if(a.pathname==="/api/plugins"&&l==="GET"){let p=e.getPlugins?e.getPlugins():[];v(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"&&l==="POST"){if(!d())return;if(!e.runPluginScans){v(i,503,{error:"plug-in scan not available"});return}try{await e.runPluginScans()}catch(m){v(i,500,{error:m?.message||String(m)});return}let p=e.getPlugins?e.getPlugins():[];v(i,200,p);return}if(a.pathname==="/api/self/history"&&l==="GET"){let p=no(a.searchParams.get("since")),m=p.sinceMs??3600*1e3,h=p.sinceTs??Date.now()-m,f=n.getHistory(),w=f?f.querySelfMetrics({since:h,limit:1440}):[];v(i,200,w);return}if(a.pathname==="/api/snapshot-state"&&l==="POST"){if(!d())return;let p=qs(n);v(i,200,{ok:!0,path:p});return}if(a.pathname==="/api/config/reload"&&l==="POST"&&e.reloadConfig){if(!d())return;try{let p=await e.reloadConfig();v(i,200,p)}catch(p){v(i,400,{error:p?.message||String(p)})}return}if(l==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let p=Ds(n);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(p)}),i.end(p);return}if(l!=="GET"&&a.pathname.startsWith("/api/")&&a.pathname!=="/api/shutdown"&&a.pathname!=="/api/config"&&a.pathname!=="/api/config/reload"&&!d())return;if(l==="GET"&&a.pathname==="/"){let p=Fn();if(p&&ye(i,pt.join(p,"index.html")))return;i.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(c[0]==="api"&&c[1]==="events"&&c.length===2){if(l!=="GET"){v(i,405,{error:"method not allowed"});return}let p=ie(a.searchParams.get("since")),m=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let w=n.events({sinceMs:p,app:m});for(let b of w)i.write(JSON.stringify(b)+`
|
|
66
|
-
`);let T=b=>{m&&b.app!==m||i.write(JSON.stringify(b)+`
|
|
67
|
-
`)
|
|
68
|
-
`)}
|
|
69
|
-
`);i.end();return}if(a.searchParams.get("explain")==="1"){let f=e.getConfig?.(),w={format:p};if(f){let{discoverApps:T}=await Promise.resolve().then(()=>(zt(),hn)),E={scanned:0,rejected:{}},b=[];T(f,{warnings:b,stats:E});let _=f.searchRoots.map(A=>typeof A=="string"?A:A.path);w={format:p,searchRoots:_,scanned:E.scanned,rejected:E.rejected,warnings:b,suggestion:h.length===0?_.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder to add the current cwd.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook, then run 'daimon doctor'.":"apps discovered; _meta is informational."}}v(i,200,{apps:h,_meta:w});return}v(i,200,h);return}let u=decodeURIComponent(c[2]),g=c[3],y=c[4];if(!g){if(l!=="GET"){v(i,405,{error:"method not allowed"});return}let p=n.summary(u);if(!p){v(i,404,{error:"unknown app"});return}Je(a,e.getConfig)==="full"?v(i,200,{...p,_meta:{format:"full"}}):v(i,200,{...oe(p),_meta:{format:"compact"}});return}if(g==="errors"&&y==="since-last"&&l==="GET"){let p=a.searchParams.get("client")||"default",m=r.getErrorCursor(p,u),h=n.errorsSince(u,m);if(h==null){v(i,404,{error:"unknown app"});return}let f=h.reduce((T,E)=>Math.max(T,E.lastSeen),m);f>m&&r.setErrorCursor(p,u,f);let w=Je(a,e.getConfig);v(i,200,w==="full"?h:h.map(Bn));return}if(g==="errors"&&!y&&l==="GET"){let p=a.searchParams.get("since"),m=Je(a,e.getConfig);if(p){let{sinceMs:f,sinceTs:w}=no(p),T=w??(f!=null?Date.now()-f:0),E=n.errorsSince(u,T);if(E==null){v(i,404,{error:"unknown app"});return}v(i,200,m==="full"?E:E.map(Bn));return}let h=n.errors(u);if(h==null){v(i,404,{error:"unknown app"});return}v(i,200,m==="full"?h:h.map(Bn));return}if(g==="logs"&&c[4]==="stream"&&l==="GET"){if(!n.summary(u)){v(i,404,{error:"unknown app"});return}i.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let p=n.logs(u,{tail:50})??[];for(let E of p)i.write(`data: ${JSON.stringify({ts:Date.now(),line:E})}
|
|
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})}
|
|
70
73
|
|
|
71
|
-
`);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})}
|
|
72
75
|
|
|
73
|
-
`),
|
|
76
|
+
`),b())};n.on("log",y);let P=setInterval(()=>i.write(`: ping
|
|
74
77
|
|
|
75
|
-
`),3e4);
|
|
76
|
-
`)}catch{}};
|
|
77
|
-
`)}catch{}},3e4),
|
|
78
|
-
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}v(i,200,{pinned:h,app:u,configPath:E,previous:_});return}if(g==="try-fix"&&l==="POST"){let p=n.summary(u);if(!p){v(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){v(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=h?Number(h):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let w={status:p.status,health:p.health,errCount:p.errorCount,firstError:(n.errors(u)??[])[0]?.parsed??null},{runAutoFix:T,ALL_AUTO_FIX:E}=await Promise.resolve().then(()=>(se(),re)),_=e.getConfig?.()?.doctor?.autoFix?.permitted??E,A={ran:[],skipped:[],errors:[]};try{A=await T({permitted:_,dryRun:!1})}catch(J){A.errors.push({name:"auto-fix",error:J?.message??String(J)})}let x=(A.ran??[]).map(J=>J.name),P=null;try{let J=await n.restart(u);J?.ok||(P=J?.error??"restart failed")}catch(J){P=J?.message??String(J)}let O=await n.waitFor(u,m,f),S=n.summary(u),I=(n.errors(u)??[]).slice(0,5).map(J=>({file:J.parsed?.file??null,line:J.parsed?.line??null,code:J.parsed?.code??null,tool:J.parsed?.tool??null,message:J.parsed?.message??J.message})),D=S?{status:S.status,health:S.health,errCount:S.errorCount}:{status:O.status,health:O.health,errCount:0},z=m==="serving"&&D.status==="serving"||m==="healthy"&&D.status==="serving"&&D.health==="healthy";v(i,200,{before:w,after:D,fixed:x,stillFailing:I,reached:z,waitedMs:O.waitedMs,_meta:{autoFix:A,restartErr:P,timedOut:O.timedOut}});return}if(g==="wait"&&l==="GET"){if(!n.summary(u)){v(i,404,{error:"unknown app"});return}let p=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(p)){v(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let m=a.searchParams.get("timeout"),h=m?Number(m):120;(!Number.isFinite(h)||h<=0)&&(h=120),h=Math.min(h,600);let f=await n.waitFor(u,p,h*1e3);v(i,200,f);return}if(g==="ensure"&&l==="POST"){let p=n.summary(u);if(!p){v(i,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){v(i,400,{error:"until must be serving|healthy"});return}let h=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),f=h?Number(h):18e4;(!Number.isFinite(f)||f<=0)&&(f=18e4),f=Math.min(f,6e5);let w=e.getConfig?.().healthProbe?.enabled??!0,T=m,E;if(T==="healthy"&&!w&&(T="serving",E="no health probe; treated serving as terminal"),T==="serving"&&p.status==="serving"||T==="healthy"&&p.status==="serving"&&p.health==="healthy"){v(i,200,{...oe(p),_meta:{format:"compact",startedFromState:null,warning:E,waitedMs:0}});return}let _=p.status;p.status!=="starting"&&p.status!=="compiling"&&await n.start(u);let A=await n.waitFor(u,T,f),x=n.summary(u),P=x?oe(x):{name:u,status:A.status,port:null,url:null,health:A.health,errCount:0,lastChangeMs:null,uptime:null};if(A.timedOut){v(i,200,{error:"timeout",state:P,_meta:{format:"compact",startedFromState:_,warning:E,waitedMs:A.waitedMs,timedOut:!0}});return}v(i,200,{...P,_meta:{format:"compact",startedFromState:_,warning:E,waitedMs:A.waitedMs}});return}if(g==="start"&&l==="POST"){if(a.searchParams.get("withDeps")==="1"){let h=await n.startWithDeps(u);v(i,h.ok?200:400,h);return}let m=await n.start(u);v(i,m.ok?200:400,m);return}if(g==="start-with-deps"&&l==="POST"){let p=await n.startWithDeps(u);v(i,p.ok?200:400,p);return}if(g==="tasks"&&l==="GET"&&!y){let p=n.listTasks(u);if(p==null){v(i,404,{error:"unknown app"});return}v(i,200,{tasks:p,watching:n.listWatchTasks(u)});return}if(g==="run"&&y&&l==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(f=>{let w=[];o.on("data",T=>w.push(T)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(w).toString("utf8"))}catch{}f()})});let m=Array.isArray(p.args)?p.args.map(String):[];if(p.watch){let f=n.startWatchTask(u,y,m);v(i,f.ok?200:400,f);return}let h=await n.runTask(u,y,m);if("error"in h){v(i,404,h);return}v(i,200,h);return}if(g==="run-stop"&&y&&l==="POST"){let p=await n.stopWatchTask(u,y);v(i,200,p);return}if(g==="env"&&l==="GET"){let m=n.getConfig().envFiles?.[u]??[],h=n.getState(u);v(i,200,{candidates:m,active:h?.activeEnvFile??null});return}if(g==="env"&&l==="POST"){let p={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(h=>{let f=[];o.on("data",w=>f.push(w)),o.on("end",()=>{try{p=JSON.parse(Buffer.concat(f).toString("utf8"))}catch{}h()})}),n.setActiveEnvFile(u,p.use??null);let m=n.getState(u);v(i,200,{active:m?.activeEnvFile??null});return}if(g==="requests"&&l==="GET"){if(!e.requestLog){v(i,200,[]);return}let p=ie(a.searchParams.get("since"));v(i,200,e.requestLog.requests(u,p));return}if(g==="clean"&&l==="POST"){let p=a.searchParams.get("deep")==="1",m=a.searchParams.get("yes")==="1",h=jn(n,u,p);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(!m){v(i,200,{plan:h,hint:"pass --yes to delete"});return}let f=js(n,u,p);v(i,200,f);return}if(g==="snapshot"&&l==="POST"){if(a.searchParams.get("write")==="1"){let h=Os(n,u);if(!h){v(i,404,{error:"unknown app"});return}v(i,200,{snapshot:h.path});return}let m=$n(n,u);if(!m){v(i,404,{error:"unknown app"});return}v(i,200,m);return}if(g==="stop"&&l==="POST"){let p=await n.stop(u);v(i,p.ok?200:400,p);return}if(g==="restart"&&l==="POST"){let p=await n.restart(u);v(i,p.ok?200:400,p);return}if(l==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let p=Fn();if(p){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let h=pt.resolve(p,m);if(h.startsWith(p)&&ye(i,h))return}if(!pt.extname(m||"")&&ye(i,pt.join(p,"index.html")))return}}v(i,404,{error:"not found"})}catch(a){v(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}var jc,He,_c,Lc,so=F(()=>{"use strict";Ps();Ns();_s();Ls();Bs();Js();_n();Et();jc=$c(import.meta.url),He=pt.dirname(jc);_c={".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"};Lc=/key|secret|token|password|pass/i});import Fc from"node:http";import Bc from"node:https";function oo(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 l=e?We(e):null,c=n.scheme||l?.protocol?.replace(":","")||"http",d=n.host||l?.hostname||(r?i[0]:"127.0.0.1"),u=r??(l?.port?Number(l.port):null);return[io(c,d,u,o)]}if(e){let l=We(e);if(l)return l.pathname=o,[l.toString()]}let a=[];s&&a.push(s);for(let l of i)a.includes(l)||a.push(l);return a.map(l=>io("http",l,r,o))}function We(n){try{return new URL(n)}catch{return null}}function io(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${n}://${s}${o}${r.startsWith("/")?r:"/"+r}`}var Uc,Hc,Jc,Ge,ao=F(()=>{"use strict";Uc=1e3,Hc=500,Jc=["/","/health","/-/health","/api/health","/ready","/healthz"];Ge=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)},Hc);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=this.fullConfig?.overrides?.[t]?.healthProbePath,o=this.cfg;s?o={...this.cfg,path:s}:e.discoveredHealthPath&&(o={...this.cfg,path:e.discoveredHealthPath});let i=oo(o,r,e.announcedUrl,e.port,e.cachedProbeHost);if(!r&&!s&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),i.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let a=null;for(let c of i){let d=await this.tryProbe(c);if(d.ok){let u=We(c);u&&this.registry.setCachedProbeHost(t,u.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,c),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}a||(a=`${d.error} ${c}`)}let l=this.freshness.get(t);if(l&&!l.retried){l.retried=!0,setTimeout(()=>{this.probe(t)},Uc);return}this.registry.setLastHealthError(t,a||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let r of Jc){let s={...this.cfg,path:r},o=oo(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=d=>{s||(s=!0,r(d))},i=t.startsWith("https://"),a=i?Bc:Fc,l={timeout:this.cfg.timeoutMs};if(i){let u=We(t)?.hostname?.replace(/^\[|\]$/g,"")??"",g=u==="127.0.0.1"||u==="::1"||u==="localhost";l.rejectUnauthorized=g?!1:!!this.cfg.rejectUnauthorized}let c=e.strict2xx?300:500;try{let d=a.get(t,l,u=>{let g=u.statusCode??0;u.resume(),g>=200&&g<c?o({ok:!0}):o({ok:!1,error:`http ${g}`})});d.on("timeout",()=>d.destroy(new Error("timeout"))),d.on("error",u=>o({ok:!1,error:u?.code||u?.message||"error"}))}catch(d){o({ok:!1,error:d?.message||"throw"})}})}}});import Wc from"pidusage";var qe,co=F(()=>{"use strict";qe=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 Wc(s),i=this.registry.getState(r);if(!i)return;let a=Math.round(o.cpu*10)/10,l=Math.round(o.memory/(1024*1024));(i.cpu!==a||i.memMB!==l)&&(i.cpu=a,i.memMB=l,e=!0)}catch{let o=this.registry.getState(r);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}}});var Xe,lo=F(()=>{"use strict";Xe=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 l=setTimeout(()=>{this.timers.delete(t);let c=this.registry.getState(t);c&&(c.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,l)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}}});import Wn from"node:fs";import uo from"node:path";import Gc from"node:os";function po(){try{let n=Wn.readFileSync(Gn,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}function fo(n){Jn=n,!Hn&&(Hn=setTimeout(()=>{Hn=null;let t=Jn;if(Jn=null,!!t)try{Wn.mkdirSync(uo.dirname(Gn),{recursive:!0}),Wn.writeFileSync(Gn,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
79
|
-
`)}},500))}var
|
|
80
|
-
`;try{
|
|
81
|
-
`))}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}`,
|
|
82
|
-
`),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
|
|
83
|
-
`),{config:r,raw:e,applied:
|
|
84
|
-
`))}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}
|
|
85
88
|
`)}catch{}if(r)try{process.stderr.write(`[daimon] crash dump: ${r}
|
|
86
|
-
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}var ol,Ao=F(()=>{"use strict";Et();bt();ol=/key|secret|token|password|pass/i});function Ze(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 zn,ul,pl,Qe,Oo=F(()=>{"use strict";Et();zn=1e3,ul=60,pl=256;Qe=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-zn);t=e,this.lagSamples.push(r),this.lagSamples.length>ul&&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)},zn),this.lagTimer.unref&&this.lagTimer.unref()}setSelfWarnHandler(t){this.onSelfWarn=t}recordQueryMs(t){this.querySamples.push(t),this.querySamples.length>pl&&this.querySamples.shift()}incLockContention(){this.lockContentionCount++}snapshot(){let t=process.memoryUsage(),e=1024*1024;return{pid:process.pid,version:Z,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:Ze(this.lagSamples,.95),historyDbQueryMs:{p50:Ze(this.querySamples,.5),p95:Ze(this.querySamples,.95),p99:Ze(this.querySamples,.99)},lockContentionCount:this.lockContentionCount,tickIntervalMs:zn,lastTickAt:this.lastTickAt}}stop(){this.lagTimer&&clearInterval(this.lagTimer),this.lagTimer=null}}});var _o={};yt(_o,{buildContext:()=>Qn,loadPlugins:()=>Vn,pluginsDir:()=>Yn,runPluginScans:()=>Zn,validatePluginFile:()=>hl});import dl from"node:fs";import No from"node:path";import fl from"node:os";import{pathToFileURL as Mo}from"node:url";function Yn(n){return n&&typeof n=="string"&&n.trim()?n:No.join(fl.homedir(),".daimon","plugins")}function ml(n){return n.startsWith("doctor-")&&n.endsWith(".mjs")}function $o(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 Vn(n){let t=[],e;try{e=dl.readdirSync(n).filter(ml).sort()}catch{return t}let r=new Set;for(let s of e){let o=No.join(n,s);try{let i=await import(Mo(o).href+`?t=${Date.now()}`),a=$o(i);if(!a.ok){t.push({name:s,file:o,status:"failed",error:a.error});continue}let l=a.plugin;if(jo.has(l.name)){t.push({name:l.name,file:o,status:"failed",error:`name collides with built-in rule "${l.name}"`});continue}if(r.has(l.name)){t.push({name:l.name,file:o,status:"failed",error:"duplicate plug-in name"});continue}r.add(l.name),t.push({name:l.name,description:l.description,file:o,status:"ok",module:l})}catch(i){t.push({name:s,file:o,status:"failed",error:i?.message??String(i)})}}return t}async function hl(n){try{let t=await import(Mo(n).href+`?t=${Date.now()}`),e=$o(t);return e.ok?jo.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 Zn(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 Qn(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 jo,tr=F(()=>{"use strict";jo=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 et,{useEffect as gl,useMemo as yl,useState as ae}from"react";import{Box as we,Text as ft,useInput as wl,useStdout as bl}from"ink";import vl from"ink-text-input";function er({registry:n,appName:t,onExit:e}){let{stdout:r}=bl(),[s,o]=ae(0),[i,a]=ae(!1),[l,c]=ae(""),[d,u]=ae(""),[g,y]=ae(0),[p,m]=ae(0);gl(()=>{let P=()=>o(S=>S+1);n.on("change",P);let O=setInterval(()=>o(S=>S+1),500);return()=>{n.off("change",P),clearInterval(O)}},[n]);let f=n.getState(t)?.logBuffer.map(P=>P.line)??[],w=(r.rows||30)-4,T=yl(()=>{if(!d)return[];let P=d.toLowerCase();return f.reduce((O,S,k)=>(S.toLowerCase().includes(P)&&O.push(k),O),[])},[f,d,s]);wl((P,O)=>{if(i){if(O.escape){a(!1),c("");return}return}if(P==="q"||O.escape){e();return}if(P==="/"){a(!0);return}if(P==="g"){y(Math.max(0,f.length-w));return}if(P==="G"){y(0);return}if(O.pageUp){y(S=>Math.min(Math.max(0,f.length-w),S+w));return}if(O.pageDown){y(S=>Math.max(0,S-w));return}if(O.upArrow){y(S=>Math.min(Math.max(0,f.length-w),S+1));return}if(O.downArrow){y(S=>Math.max(0,S-1));return}if((P==="n"||P==="N")&&T.length){let S=P==="n"?(p+1)%T.length:(p-1+T.length)%T.length;m(S);let k=T[S],I=f.length-g,D=I-w;(k<D||k>=I)&&y(Math.max(0,f.length-k-Math.floor(w/2)));return}});let E=P=>{u(P),a(!1),c(""),m(0)},b=f.length-g,_=Math.max(0,b-w),A=f.slice(_,b),x=(P,O)=>{if(!d)return et.createElement(ft,{key:O},et.createElement(ft,{dimColor:!0},String(O+1).padStart(5)," "),P);let S=d,k=P.toLowerCase(),I=S.toLowerCase(),D=[],z=0,J=0;for(;z<P.length;){let St=k.indexOf(I,z);if(St<0){D.push(et.createElement(ft,{key:J++},P.slice(z)));break}St>z&&D.push(et.createElement(ft,{key:J++},P.slice(z,St))),D.push(et.createElement(ft,{key:J++,backgroundColor:"yellow",color:"black"},P.slice(St,St+S.length))),z=St+S.length}let Mt=T[p]===O;return et.createElement(ft,{key:O},et.createElement(ft,{color:Mt?"cyan":void 0,dimColor:!Mt},String(O+1).padStart(5)," "),D)};return et.createElement(we,{flexDirection:"column"},et.createElement(we,null,et.createElement(ft,{bold:!0},"full log: ",et.createElement(ft,{color:"cyan"},t)),et.createElement(ft,{dimColor:!0}," (",f.length," lines",d?`, ${T.length} matches for "${d}"`:"",", scroll=",g,")")),et.createElement(we,{flexDirection:"column"},A.length===0?et.createElement(ft,{dimColor:!0},"(no log yet)"):A.map((P,O)=>x(P,_+O))),et.createElement(we,null,i?et.createElement(we,null,et.createElement(ft,null,"/"),et.createElement(vl,{value:l,onChange:c,onSubmit:E})):et.createElement(ft,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}var Do=F(()=>{"use strict"});function Io(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)),l=o[a];(!l||(Lo[i.to]??0)>(Lo[l]??0))&&(o[a]=i.to)}return o}function Fo(n){return n.map(t=>Sl[t]??"\xB7").join("")}var Lo,Sl,Bo=F(()=>{"use strict";Lo={stopped:1,serving:2,compiling:3,starting:3,error:4},Sl={"":"\xB7",stopped:"\u2591",serving:"\u2593",compiling:"\u2592",starting:"\u2592",error:"\u2588"}});import R,{useEffect as kl,useState as nt}from"react";import nr from"node:fs";import xl from"node:os";import Tl from"node:path";import{Box as at,Text as L,useApp as Cl,useInput as El,useStdout as Pl}from"ink";import rr from"ink-text-input";import{spawn as sr,spawnSync as Rl}from"node:child_process";function Al(n){try{process.platform==="win32"?sr("cmd",["/c","start","",n],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?sr("open",[n],{detached:!0,stdio:"ignore"}).unref():sr("xdg-open",[n],{detached:!0,stdio:"ignore"}).unref()}catch{}}function Ol(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 or({registry:n,apiPort:t,onQuit:e}){let{exit:r}=Cl(),{stdout:s}=Pl(),[o,i]=nt(n.list()),[a,l]=nt(0),[c,d]=nt(!1),[u,g]=nt(0),[y,p]=nt(!1),[m,h]=nt([]),[f,w]=nt(!1),[T,E]=nt(""),[b,_]=nt(null),[,A]=nt(0),[x,P]=nt(null),[O,S]=nt(""),[k,I]=nt(!1),[D,z]=nt(null),[J,Mt]=nt(""),[St,on]=nt(!1),[pr,dr]=nt(null),[di,fr]=nt(n.events({sinceMs:3600*1e3}));kl(()=>{let C=()=>i(n.list()),j=()=>fr(n.events({sinceMs:36e5}));n.on("change",C),n.on("event",j);let U=setInterval(()=>{i(n.list()),fr(n.events({sinceMs:3600*1e3})),A($=>$+1)},1e3);return()=>{n.off("change",C),n.off("event",j),clearInterval(U)}},[n]),El((C,j)=>{if(y)return;if(b){if(j.escape){_(null);return}if(j.tab){let $=b.field==="command"?"port":b.field==="port"?"env":"command";_({...b,field:$});return}return}if(f){if(j.escape){w(!1),E("");return}if(j.return){let $=T.trim();h($?$.split(/[\s,]+/).filter(Boolean):[]),w(!1),E("");return}if(j.backspace||j.delete){E($=>$.slice(0,-1));return}C&&!j.ctrl&&E($=>$+C);return}if(k){if(j.escape){I(!1);return}if(j.return){I(!1);return}if(j.backspace||j.delete){S($=>$.slice(0,-1));return}C&&!j.ctrl&&S($=>$+C);return}if(St){if(j.escape){on(!1),Mt("");return}if(j.return){let $=J.trim();on(!1),Mt(""),$&&hi($);return}if(j.backspace||j.delete){Mt($=>$.slice(0,-1));return}C&&!j.ctrl&&Mt($=>$+C);return}if(D){if(C==="y"||C==="Y"){let $=D;z(null),n.restart($),rt(`restarted ${$}`)}else(C==="n"||C==="N"||j.escape)&&z(null);return}if(C==="q"||j.ctrl&&C==="c"){e(),r();return}if(o.length===0)return;if(x==="g"){P(null);let $=C.toLowerCase();$==="a"?rt("view: apps (only TUI view)"):$==="e"?rt("view: errors \u2014 selected app errors shown in detail pane"):$==="v"?rt("view: events \u2014 recent registry events shown in log pane"):$==="s"?rt("view: settings \u2014 edit `daimon.config.json`"):$==="n"&&rt("view: sessions \u2014 `daimon record` to toggle recording");return}if(j.upArrow||C==="k"){l($=>Math.max(0,$-1)),g(0);return}if(j.downArrow||C==="j"){l($=>Math.min(o.length-1,$+1)),g(0);return}let U=o[a];if(U){if(C==="g"){P("g"),setTimeout(()=>P($=>$==="g"?null:$),1200);return}if(C==="/"){I(!0);return}if(C==="s")n.start(U.name);else if(C==="S")n.stop(U.name);else if(C==="r")z(U.name);else if(C==="f")mi(U.name);else if(C==="x")fi(U.name);else if(C==="O")on(!0);else if(C==="L")p(!0);else if(C==="t")w(!0),E(m.join(" "));else if(C==="e"){let $=n.getConfig(),Y=n.getApp(U.name),dt=n.getState(U.name)?.sessionOverrides??null,jt=dt?.env??$.overrides?.[U.name]?.env??{},_t=Object.entries(jt).map(([cn,ln])=>`${cn}=${ln}`).join(`
|
|
87
|
-
|
|
88
|
-
`)
|
|
89
|
-
`),
|
|
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:
|
|
90
94
|
${r.path}
|
|
91
95
|
`),process.stdout.write(`[daimon] Edit it to add "searchRoots" pointing at your Nx/Angular workspace, then run again.
|
|
92
|
-
`),process.stdout.write(`[daimon] (Local override path: ${
|
|
96
|
+
`),process.stdout.write(`[daimon] (Local override path: ${y.local})
|
|
93
97
|
`),process.exit(0)}let{config:s,path:o}=r;if(process.stdout.write(`[daimon] config: ${o}
|
|
94
|
-
`),s.depends&&Object.keys(s.depends).length){let
|
|
95
|
-
`),process.exit(1))}let
|
|
96
|
-
`);let
|
|
97
|
-
`);for(let
|
|
98
|
-
`);continue}s.depends&&s.depends[
|
|
99
|
-
`)}catch{}let
|
|
100
|
-
`);try{
|
|
101
|
-
`)
|
|
102
|
-
`)
|
|
103
|
-
`),
|
|
104
|
-
`),
|
|
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"?>
|
|
105
110
|
<!-- generated by daimon daemon install-service -->
|
|
106
111
|
<service>
|
|
107
112
|
<id>daimon</id>
|
|
108
113
|
<name>daimon daemon</name>
|
|
109
114
|
<description>Local Angular/Nx/Vite dev server manager (daimon headless daemon)</description>
|
|
110
|
-
<executable>${
|
|
111
|
-
<arguments>"${
|
|
115
|
+
<executable>${xn()}</executable>
|
|
116
|
+
<arguments>"${Tn()}" --headless</arguments>
|
|
112
117
|
<log mode="rotate"/>
|
|
113
118
|
<onfailure action="restart" delay="10 sec"/>
|
|
114
119
|
</service>
|
|
115
|
-
`,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"?>
|
|
116
121
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
117
122
|
<plist version="1.0">
|
|
118
123
|
<dict>
|
|
119
124
|
<key>Label</key><string>dev.daimon</string>
|
|
120
125
|
<key>ProgramArguments</key>
|
|
121
126
|
<array>
|
|
122
|
-
<string>${
|
|
123
|
-
<string>${
|
|
127
|
+
<string>${xn()}</string>
|
|
128
|
+
<string>${Tn()}</string>
|
|
124
129
|
<string>--headless</string>
|
|
125
130
|
</array>
|
|
126
131
|
<key>RunAtLoad</key><true/>
|
|
127
132
|
<key>KeepAlive</key><true/>
|
|
128
|
-
<key>StandardOutPath</key><string>${
|
|
129
|
-
<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>
|
|
130
135
|
</dict>
|
|
131
136
|
</plist>
|
|
132
|
-
`,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]
|
|
133
138
|
Description=daimon daemon (local dev-server manager)
|
|
134
139
|
After=network.target
|
|
135
140
|
|
|
136
141
|
[Service]
|
|
137
|
-
ExecStart=${
|
|
142
|
+
ExecStart=${xn()} ${Tn()} --headless
|
|
138
143
|
Restart=on-failure
|
|
139
144
|
RestartSec=10
|
|
140
145
|
|
|
141
146
|
[Install]
|
|
142
147
|
WantedBy=default.target
|
|
143
|
-
`,e=
|
|
144
|
-
`,"utf8"),{path:o,installClaude:!1,config:
|
|
145
|
-
`),(await
|
|
146
|
-
`,"utf8"),process.stdout.write(`[daimon init] wrote ${
|
|
147
|
-
`);let m=(await Gt(e,"Install Claude Code integration? [Y/n] ")||"y").toLowerCase().startsWith("y");return{path:g,installClaude:m,config:y}}finally{e.close()}}var Ql,oi=F(()=>{"use strict";Ql=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs",".storybook"]});Xt();zt();import li from"node:os";import ui from"node:path";de();fe();Te();import Ft from"node:fs";import Vt 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 d=typeof c=="string"?c:c.path,u=Vt.resolve(d);if(!Ft.existsSync(u)){e.push({name:`searchRoot exists: ${u}`,ok:!1,detail:"not found"});continue}let g=Ft.existsSync(Vt.join(u,"nx.json"))||Ft.existsSync(Vt.join(u,"angular.json"))||Ft.existsSync(Vt.join(u,".storybook"))||["ts","js","mjs","cjs"].some(y=>Ft.existsSync(Vt.join(u,`vite.config.${y}`)));e.push({name:`searchRoot has marker: ${u}`,ok:g,detail:g?void 0:"no nx.json/angular.json/vite.config.*/.storybook"})}for(let[c,d]of Object.entries(n.overrides??{})){let u=r.has(c),g=!!d.command,y=u||g;e.push({name:`override "${c}"`,ok:y,detail:y?void 0:"unknown app and no command override"})}let s=Object.entries(n.overrides??{}).filter(([,c])=>typeof c.port=="number").map(([c,d])=>({name:c,port:d.port})),o=new Map;for(let c of s)o.has(c.port)?e.push({name:`port pin ${c.port}`,ok:!1,detail:`collision: ${o.get(c.port)} and ${c.name}`}):o.set(c.port,c.name);s.length&&!e.some(c=>c.name.startsWith("port pin"))&&e.push({name:"pinned ports",ok:!0});for(let c of n.autoStart??[])e.push({name:`autoStart "${c}"`,ok:r.has(c),detail:r.has(c)?void 0:"unknown app"});for(let[c,d]of Object.entries(n.profiles??{}))for(let u of d)e.push({name:`profile "${c}" entry "${u}"`,ok:r.has(u),detail:r.has(u)?void 0:"unknown app"});if(n.depends&&Object.keys(n.depends).length){for(let[d,u]of Object.entries(n.depends))for(let g of u)r.has(g)||e.push({name:`depends "${d}" -> "${g}"`,ok:!1,detail:"unknown app"});let c=Se(n.depends);c?e.push({name:"depends DAG",ok:!1,detail:`cycle: ${c.join(" -> ")}`}):e.push({name:"depends DAG",ok:!0})}let i=new Set(t.map(c=>c.workspaceRoot));for(let c of i){let d=Vt.join(c,"node_modules");e.push({name:`node_modules: ${c}`,ok:Ft.existsSync(d),detail:Ft.existsSync(d)?void 0:"missing"})}let a=await Tt(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 c=!1,d;try{let u=new Ct(n.history);c=u.quickCheck(),u.close(),c||(d="quick_check failed")}catch(u){d=u?.message||String(u)}e.push({name:"history db",ok:c,detail:d})}return e.push({name:"agent token footprint",ok:!0,detail:Ai(t)}),{ok:e.every(c=>c.ok),checks:e}}function Ai(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}%`}yn();wn();bt();Et();var Mr=[{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"}],W=[{code:0,meaning:"success"},{code:1,meaning:"error"}],te=[...W,{code:2,meaning:"target state not reached within --timeout"}],mt=[{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:W},{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:W},{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:W},{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:W},{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:te},{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:te},{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:te},{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:W},{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:te},{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:te},{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:te},{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:W},{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:W},{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:W},{name:"stop",args:"<name>",summary:"Stop an app.",description:"Stop an app.",example:"daimon stop web-admin",needsDaemon:!0,group:"lifecycle",exitCodes:W},{name:"restart",args:"<name>",summary:"Restart an app.",description:"Restart an app.",example:"daimon restart web-admin",needsDaemon:!0,group:"lifecycle",exitCodes:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{name:"record",args:"",summary:"Toggle session recording.",description:"Toggle JSONL session recording (~/.daimon/sessions).",example:"daimon record",needsDaemon:!0,group:"introspection",exitCodes:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W},{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:W}],ht={};for(let n of mt)for(let t of n.aliases??[])ht[t]=n.name;function Oe(n){let t=ht[n]??n;return mt.find(e=>e.name===t)}function $r(){let n=Math.max(...mt.map(t=>t.name.length));return mt.map(t=>`${t.name.padEnd(n)} ${t.summary}`).join(`
|
|
148
|
-
`)}
|
|
149
|
-
`)}function
|
|
150
|
-
`)}function
|
|
151
|
-
`)}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
|
|
152
157
|
# daimon bash completion
|
|
153
158
|
# install: source <(daimon completion bash) (or copy to /etc/bash_completion.d/daimon)
|
|
154
159
|
_daimon_complete() {
|
|
@@ -156,7 +161,7 @@ _daimon_complete() {
|
|
|
156
161
|
COMPREPLY=()
|
|
157
162
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
158
163
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
159
|
-
verbs="${
|
|
164
|
+
verbs="${fs}"
|
|
160
165
|
if [ "$COMP_CWORD" -eq 1 ]; then
|
|
161
166
|
COMPREPLY=( $(compgen -W "$verbs" -- "$cur") )
|
|
162
167
|
return 0
|
|
@@ -174,12 +179,12 @@ _daimon_complete() {
|
|
|
174
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") )
|
|
175
180
|
}
|
|
176
181
|
complete -F _daimon_complete daimon
|
|
177
|
-
`}function
|
|
182
|
+
`}function Sa(){return`#compdef daimon
|
|
178
183
|
# daimon zsh completion
|
|
179
184
|
# install: daimon completion zsh > "\${fpath[1]}/_daimon" (or source it from .zshrc)
|
|
180
185
|
_daimon() {
|
|
181
186
|
local -a verbs
|
|
182
|
-
verbs=(${
|
|
187
|
+
verbs=(${Rt.map(n=>`'${n.name}:${n.summary.replace(/'/g,"''").replace(/:/g,"\\:").slice(0,80)}'`).join(" ")})
|
|
183
188
|
if (( CURRENT == 2 )); then
|
|
184
189
|
_describe 'command' verbs
|
|
185
190
|
return
|
|
@@ -204,15 +209,15 @@ _daimon() {
|
|
|
204
209
|
'--help[help]'
|
|
205
210
|
}
|
|
206
211
|
compdef _daimon daimon
|
|
207
|
-
`}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(`
|
|
208
213
|
`)+`
|
|
209
|
-
`}function
|
|
214
|
+
`}function xa(){return`# daimon PowerShell completion
|
|
210
215
|
# install: daimon completion powershell | Out-String | Invoke-Expression
|
|
211
216
|
# permanent: add the same line to $PROFILE
|
|
212
217
|
Register-ArgumentCompleter -Native -CommandName daimon -ScriptBlock {
|
|
213
218
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
214
219
|
$tokens = $commandAst.CommandElements
|
|
215
|
-
$verbs = @(${
|
|
220
|
+
$verbs = @(${fs.split(" ").map(t=>`'${t}'`).join(",")})
|
|
216
221
|
if ($tokens.Count -le 1) {
|
|
217
222
|
$verbs | Where-Object { $_ -like "$wordToComplete*" } |
|
|
218
223
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
@@ -234,20 +239,30 @@ Register-ArgumentCompleter -Native -CommandName daimon -ScriptBlock {
|
|
|
234
239
|
$flags | Where-Object { $_ -like "$wordToComplete*" } |
|
|
235
240
|
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_) }
|
|
236
241
|
}
|
|
237
|
-
`}function
|
|
238
|
-
`)}function
|
|
239
|
-
`);try{
|
|
240
|
-
`),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})+`
|
|
241
246
|
`):process.stderr.write(JSON.stringify({error:e.error,...e.hint?{hint:e.hint}:{},exit:r})+`
|
|
242
247
|
`),process.exit(r)}catch{}process.stderr.write(n.endsWith(`
|
|
243
248
|
`)?n:n+`
|
|
244
|
-
`),process.exit(t)}function
|
|
245
|
-
`):process.stderr.write(
|
|
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})+`
|
|
246
251
|
`),process.exit(e)}function N(n){process.stdout.write(JSON.stringify(n)+`
|
|
247
|
-
`)}async function
|
|
248
|
-
`);o=
|
|
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+`
|
|
249
254
|
`)}o.trim()&&process.stdout.write(o+`
|
|
250
|
-
`)}catch(e){M(JSON.stringify({error:e?.message||String(e)}))}}async function
|
|
251
|
-
`)
|
|
252
|
-
`)
|
|
253
|
-
`);return}if(t==="--about"){ru();return}if(ht[t]&&(t=ht[t]),cr){if(ci(t))return;rn();return}if(t==="completion"){let o=e[0];o||ct("missing shell","usage: daimon completion <bash|zsh|fish|powershell>");let i=Hr(o);i.ok||ct(i.error,"supported shells: bash, zsh, fish, powershell"),process.stdout.write(i.script);return}if(t==="self"){await Nt();let o=await G("/api/self");o.status===404&&ct("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||ct("missing subcommand","usage: daimon plugin <list|show <name>|validate <path>>"),o==="list"){await Nt();let i=await G("/api/plugins");N(i.body);return}if(o==="show"){let i=e[1];i||ct("missing plug-in name","usage: daimon plugin show <name>"),await Nt();let a=await G("/api/plugins"),c=(Array.isArray(a.body)?a.body:[]).find(d=>d.name===i);c||ct(`unknown plug-in: ${i}`,"list installed plug-ins with: daimon plugin list"),N(c);return}if(o==="validate"){let i=e[1];i||ct("missing file path","usage: daimon plugin validate <path>");let{validatePluginFile:a}=await Promise.resolve().then(()=>(tr(),_o)),l=await a(ui.resolve(i));N(l),l.ok||process.exit(1);return}ct(`unknown plugin subcommand: ${o}`,"usage: daimon plugin <list|show <name>|validate <path>>")}if(t==="daemon"){await iu(e);return}if(t==="claude"){await ou(e);return}if(t==="export-config"){let o=st();o.kind!=="loaded"&&M(JSON.stringify({error:"no config loaded"}));let i=sn(e),a=JSON.parse(JSON.stringify(o.config));if(i.redacted){let l=li.homedir().replace(/\\/g,"/"),c=d=>{if(typeof d!="string")return d;let u=d.replace(/\\/g,"/");return u.toLowerCase().startsWith(l.toLowerCase())?"~"+u.slice(l.length):d};a.apiToken!=null&&a.apiToken!==""&&(a.apiToken="<redacted>"),a.history?.path&&(a.history.path=c(a.history.path)),a.logs?.dir&&(a.logs.dir=c(a.logs.dir)),Array.isArray(a.searchRoots)&&(a.searchRoots=a.searchRoots.map(d=>typeof d=="string"?c(d):{...d,path:c(d.path)}))}N(a);return}if(t==="discover"){await Nt();let o=await G("/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(()=>(oi(),si)),i=sn(e);try{let a=await o({force:!!i.force,auto:!!i.auto});if(N({path:a.path,installClaude:a.installClaude,auto:a.auto}),a.installClaude){let c=ur(),d=Me({skill:!0,commands:!1,agent:!0,dir:me(),apiPort:c,onMigrationEvent:u=>{u.kind==="removed"?N({removed:u.file}):N({warning:`${u.file} was modified; backing up to ${u.file}.bak`})}});N({claudeInstalled:d.installed})}let l=ot();if(l){try{await fetch(`http://127.0.0.1:${l.apiPort}/api/snapshot-state`,{method:"POST",headers:gt()})}catch{}try{await fetch(`http://127.0.0.1:${l.apiPort}/api/shutdown`,{method:"POST",headers:gt()})}catch{}await Bt(l.pid,5e3),wt();try{let c=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):void 0,d=await Pt({port:Number.isFinite(c)&&c>0?c:void 0});N({daemonRestarted:!0,pid:d.pid,port:d.apiPort})}catch(c){N({daemonRestarted:!1,error:c?.message||String(c)})}}try{await Nt();let c=await fetch(ue()+"/api/discovery/explain",{headers:gt()});if(c.ok){let d=await c.json(),u={};try{let m=await(await fetch(ue()+"/api/apps?format=full",{headers:gt()})).json();if(Array.isArray(m))for(let h of m){let f=h.workspaceType??"unknown";u[f]=(u[f]??0)+1}}catch{}let g=d.appsFound??0,y={init:"ok",configPath:a.path,discovered:{apps:g,byKind:u}};g===0&&(y._meta={searchRoots:d.searchRoots,scanned:d.scanned,rejected:d.rejected,suggestion:d.suggestion},y.warning="discovery found 0 apps; see _meta.suggestion"),N(y)}}catch{}}catch(a){M(JSON.stringify({error:a?.message||String(a)}))}return}let r=sn(e);switch(Oe(t)?.needsDaemon&&await Nt(),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.stream){i.set("stream","ndjson");let d=i.toString();await lr("/api/apps"+(d?"?"+d:""));return}let a=i.toString(),l=await G("/api/apps"+(a?"?"+a:""));if(r.explain){N(l.body);return}let c=Array.isArray(l.body)?l.body:[];r.tags.length&&(c=c.filter(d=>r.tags.every(u=>(d.tags||[]).includes(u)))),r.workspace&&(c=c.filter(d=>d.workspaceLabel===r.workspace)),N(c);return}case"why-empty":{let o=await G("/api/apps?explain=1");N(o.body);return}case"status":case"stop":case"restart":{let o=r.positional[0];o||ct("missing app name",`usage: daimon ${t} <name>`);let i=t==="status"?"":"/"+t,a=t==="status"?"GET":"POST",l=t==="status"?nu(r):"",c=await G(`/api/apps/${encodeURIComponent(o)}${i}${l}`,a);c.status===404&&await ai(o),N(c.body);return}case"start":{let o=r.positional[0];o||ct("missing app name","usage: daimon start <name> [--with-deps]");let i=r.withDeps?"?withDeps=1":"",a=await G(`/api/apps/${encodeURIComponent(o)}/start${i}`,"POST");a.status===404&&await ai(o),N(a.body);return}case"history":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon history <name>"}));let i=await G(`/api/history/summary/${encodeURIComponent(o)}`);N(i.body);return}case"why":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon why <name>"}));let i=await G(`/api/history/why/${encodeURIComponent(o)}`);N(i.body);return}case"env":{let o=r.positional[0];if(o||M(JSON.stringify({error:"usage: daimon env <name> [--use <file>]"})),r.use){let a=await nn(`/api/apps/${encodeURIComponent(o)}/env`,"POST",{use:r.use});a.status===404&&M(JSON.stringify({error:"unknown app"})),N(a.body);return}let i=await G(`/api/apps/${encodeURIComponent(o)}/env`);i.status===404&&M(JSON.stringify({error:"unknown app"})),N(i.body);return}case"clean":{let o=r.positional[0];o||M(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&&M(JSON.stringify({error:"unknown app"})),a.status===409&&(N(a.body),process.exit(1)),N(a.body);return}case"record":{let o=await G("/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 i=r.speed&&r.speed>0?r.speed:1,a;try{a=Rr(o)}catch(c){M(JSON.stringify({error:c?.message||String(c)}))}let l=0;for(let c of a){let d=Math.max(0,(c.ts-l)/i);d>0&&await new Promise(u=>setTimeout(u,d)),l=c.ts,c.kind==="run"?await nn(`/api/apps/${encodeURIComponent(c.app)}/run/${encodeURIComponent(c.task||"")}`,"POST",{args:c.args||[]}):await G(`/api/apps/${encodeURIComponent(c.app)}/${c.kind}`,"POST")}N({replayed:a.length,file:o});return}case"doctor":{let o=st();if(o.kind!=="loaded"&&M(JSON.stringify({error:"no config loaded"})),r.self){await Nt();let c=await G("/api/self");c.status===503&&ct("self-metrics not available","daemon may need a restart: daimon daemon restart");let d=c.body??{},u=[],g=256,y=100,p=50;u.push({name:"heap",ok:d.heapUsedMB<g,detail:`heapUsed ${d.heapUsedMB}MB (warn at ${g}MB)`}),u.push({name:"event-loop-lag",ok:d.eventLoopLagP95Ms<y,detail:`p95 ${d.eventLoopLagP95Ms}ms (warn at ${y}ms)`}),u.push({name:"history-db-query",ok:(d.historyDbQueryMs?.p95??0)<p,detail:`p95 ${d.historyDbQueryMs?.p95??0}ms (warn at ${p}ms)`});let m=u.every(h=>h.ok);N({ok:m,checks:u,metrics:d}),m||process.exit(1);return}if(r.autoFix){let{runAutoFix:c,ALL_AUTO_FIX:d}=await Promise.resolve().then(()=>(se(),re)),u=o.config.doctor?.autoFix?.permitted??d,g=await c({permitted:u,dryRun:!!r.dryRun});N(g),g.errors.length&&process.exit(1);return}let i=[],a=It(o.config,{warnings:i}),l=await xr(o.config,a);for(let c of i)l.checks.unshift({name:`discovery: ${c}`,ok:!1,detail:c});i.length&&(l.ok=!1),N(l),l.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 i=Ce(o);if(!i){N({port:o,free:!0});return}if(!r.force){N({port:o,free:!1,holder:i});return}i.pid===process.pid&&M(JSON.stringify({error:"refuse to kill daimon itself",holder:i}));let a=await Er(i);N({port:o,killed:a,holder:i}),a||process.exit(1);return}case"snapshot":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon snapshot <name>"}));let i=await G(`/api/apps/${encodeURIComponent(o)}/snapshot?write=1`,"POST");i.status===404&&M(JSON.stringify({error:"unknown app"})),N(i.body);return}case"tasks":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon tasks <name>"}));let i=await G(`/api/apps/${encodeURIComponent(o)}/tasks`);i.status===404&&M(JSON.stringify({error:"unknown app"})),N(i.body);return}case"run":{let o=r.positional[0],i=r.positional[1];(!o||!i)&&M(JSON.stringify({error:"usage: daimon run <name> <task> [--watch] [-- args...]"}));let a={args:r.passthrough,watch:!!r.watch},l=await nn(`/api/apps/${encodeURIComponent(o)}/run/${encodeURIComponent(i)}`,"POST",a);l.status===404&&M(JSON.stringify({error:"unknown app"})),N(l.body),!r.watch&&typeof l.body?.exitCode=="number"&&process.exit(l.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]"}));let i=new URLSearchParams,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.full?i.set("format","full"):r.compact&&i.set("format","compact");let l=i.toString(),c=await G(a+(l?"?"+l:""));c.status===404&&M(JSON.stringify({error:"unknown app"}));let d=c.body;r.structured&&Array.isArray(d)&&(d=d.map(u=>u.parsed??{message:u.message})),N(d);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 l=o.toString();await lr("/api/events"+(l?"?"+l:""));return}let i=o.toString(),a=await G("/api/events"+(i?"?"+i:""));N(a.body);return}case"ensure":{let o=r.positional[0];o||M(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"&&M(JSON.stringify({error:"ensure --until must be serving|healthy"})),i.set("until",a);let l=180;if(r.timeout){let d=le(r.timeout);d==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(d,600)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await G(`/api/apps/${encodeURIComponent(o)}/ensure?${i.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 i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();a!=="serving"&&a!=="healthy"&&M(JSON.stringify({error:"ensure-up --until must be serving|healthy"})),i.set("until",a);let l=300;if(r.timeout){let u=le(r.timeout);u==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(u,1200)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await G(`/api/profiles/${encodeURIComponent(o)}/ensure-up?${i.toString()}`,"POST");c.status===404&&M(JSON.stringify({error:"unknown profile"})),N(c.body),Array.isArray(c.body?.apps)&&c.body.apps.some(u=>u.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:""));N(a.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 i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||M(JSON.stringify({error:"focus --until must be serving|healthy|stable"})),i.set("until",a);let l=180;if(r.timeout){let c=le(r.timeout);c==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(c,600)}i.set("timeoutMs",String(Math.ceil(l*1e3))),await lr(`/api/apps/${encodeURIComponent(o)}/focus?${i.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 i=await G(`/api/apps/${encodeURIComponent(o)}?format=full`);i.status===404&&M(JSON.stringify({error:"unknown app"}));let a=i.body?.discoveredHealthPath??null,l=r.path??a??null;if(!r.accept){N({app:o,discoveredHealthPath:a,candidate:l,hint:l?`re-run with --accept to persist ${l} to daimon.config.json`:"no path discovered yet; start the app and wait for first serving"});return}l||M(JSON.stringify({error:"no path to pin \u2014 pass --path or wait for auto-discovery"}));let c=await nn(`/api/apps/${encodeURIComponent(o)}/health/pin`,"POST",{path:l});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 i=new URLSearchParams;i.set("profile",o);let a=(r.goal||r.until||"healthy").toLowerCase();["serving","healthy","stable"].includes(a)||M(JSON.stringify({error:"orchestrate --goal must be serving|healthy|stable"})),i.set("goal",a);let l=300;if(r.timeout){let d=le(r.timeout);d==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(d,1200)}i.set("timeoutMs",String(Math.ceil(l*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 c=await G(`/api/orchestrate?${i.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 i=new URLSearchParams,a=(r.until||"healthy").toLowerCase();["serving","healthy"].includes(a)||M(JSON.stringify({error:"try-fix --until must be serving|healthy"})),i.set("until",a);let l=180;if(r.timeout){let d=le(r.timeout);d==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),l=Math.min(d,600)}i.set("timeoutMs",String(Math.ceil(l*1e3)));let c=await G(`/api/apps/${encodeURIComponent(o)}/try-fix?${i.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]"}));let i=new URLSearchParams;r.until&&i.set("until",r.until);let a=120;if(r.timeout){let c=le(r.timeout);c==null&&M(JSON.stringify({error:`invalid --timeout: ${r.timeout}`})),a=Math.min(c,600)}i.set("timeout",String(Math.ceil(a)));let l=await G(`/api/apps/${encodeURIComponent(o)}/wait?${i.toString()}`);l.status===404&&M(JSON.stringify({error:"unknown app"})),N(l.body),l.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:[],l=(await eu()).config,c;if(!o)c=l.autoStart||[],t==="up"&&c.length===0&&M(JSON.stringify({error:"no autoStart configured and no profile given"})),t==="down"&&c.length===0&&(c=a.map(p=>p.name));else{let p=l.profiles?.[o];p||M(JSON.stringify({error:`unknown profile: ${o}`})),c=p}let d=t==="up"?"start":"stop";if(t==="up"?await Promise.all(c.map(p=>G(`/api/apps/${encodeURIComponent(p)}/start?withDeps=1`,"POST"))):await Promise.all(c.map(p=>G(`/api/apps/${encodeURIComponent(p)}/${d}`,"POST"))),t==="up"){let m=Date.now(),h=()=>Math.max(5,Math.floor((12e4-(Date.now()-m))/1e3));await Promise.all(c.map(f=>G(`/api/apps/${encodeURIComponent(f)}/wait?until=serving&timeout=${h()}`)))}else await Promise.all(c.map(p=>G(`/api/apps/${encodeURIComponent(p)}/wait?until=stopped&timeout=10`)));let u=await G("/api/apps"),y=(Array.isArray(u.body)?u.body:[]).filter(p=>c.includes(p.name)).map(p=>({name:p.name,status:p.status,health:p.health}));N(y);return}case"logs":{let o=r.positional[0];o||M(JSON.stringify({error:"usage: daimon logs <name> [--tail N] [--since 30s]"}));let i=new URLSearchParams;r.tail!=null&&!Number.isNaN(r.tail)&&i.set("tail",String(r.tail)),r.since&&i.set("since",r.since);let a=i.toString(),l=await G(`/api/apps/${encodeURIComponent(o)}/logs${a?"?"+a:""}`);l.status===404&&M(JSON.stringify({error:"unknown app"})),N(l.body);return}default:{let o=Ir(t),i=o?`did you mean '${o}'? \u2014 run \`daimon --help\` to list commands`:"run `daimon --help` to list commands";ct(`unknown command: ${t}`,i)}}}au().catch(n=>M(JSON.stringify({error:n?.message||String(n)})));
|
|
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"}
|
|
256
|
+
`),n?.hint&&process.stderr.write(`hint: ${n.hint}
|
|
257
|
+
`),t.length){process.stderr.write(`candidates:
|
|
258
|
+
`);for(let e of t){let r=e.workspaceLabel?` [${e.workspaceLabel}]`:"";process.stderr.write(` - ${e.name}${r} (${e.workspaceRoot??"?"})
|
|
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)})));
|