@amr-m-abdelgawad/devctl 0.1.4 → 0.1.5
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/dist/devctl.js +84 -65
- package/package.json +1 -1
package/dist/devctl.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
4
|
-
`)}function Xp(e,t){let r=uw(e);if(Rr(r)){let n=gw(r);if(n&&Rt(n.pid))throw Error(`supervisor already running (pid ${n.pid})`);try{Wc(r)}catch{}}return $t(r,JSON.stringify({pid:process.pid,socket:t})),{release:()=>{try{Wc(r)}catch{}}}}function gw(e){if(!Rr(e))return;try{let t=JSON.parse(Kc(e,"utf8"));if(typeof t.pid==="number"&&typeof t.socket==="string")return{pid:t.pid,socket:t.socket}}catch{return}return}function Rt(e){if(e<=0)return!1;if(process.platform==="win32")return mw(e);try{return process.kill(e,0),!0}catch{return!1}}function Yc(e){try{let t=Qb("cmd.exe",["/d","/c",`tasklist /FO CSV /NH /FI "PID eq ${e}"`],{encoding:"buffer",windowsHide:!0,timeout:5000});return hw(t.stdout)}catch{return""}}function mw(e){try{return process.kill(e,0),!0}catch{}let t=Yc(e).toLowerCase();if(t===""||t.includes("no tasks")||t.includes("no matching"))return!1;return t.includes(String(e))}function hw(e){if(!e)return"";if(typeof e==="string")return e;if(e.length>=2&&e[0]===255&&e[1]===254)return e.toString("utf16le");if(e.length>=4&&e[1]===0&&e[3]===0)return e.toString("utf16le");return e.toString("utf8")}function zc(){return Uc(24).toString("hex")}function yw(e){return st($n(e),"mcp-token")}function Qp(e){let t=yw(e);if(Rr(t)){let n=Kc(t,"utf8").trim();if(n!=="")return n}let r=zc();return $t(t,r),r}var cw=448,lw=384,dw=16,pw=5,Jp="bootstrap-";var Ye=()=>{};function ms(){return{args:[],shell:!1}}function Qc(){return{vars:{},required:[],defaults:{}}}function Zc(){return{type:"",url:"",address:"",command:ms(),interval_seconds:0,timeout_seconds:0}}function el(){return{type:"",mode:"",service_account:""}}function Nn(){return{extends:"",description:"",command:ms(),shell:!1,working_dir:"",dependencies:[],ports:[],environment:Qc(),health:Zc(),identity:el(),logs:{stdout:!1,stderr:!1},restart:{policy:"",max_retries:0,backoff_seconds:0},startup:{wait_for_healthy:!1,timeout_seconds:0},capabilities:[],proxy:[]}}function Jr(){return{version:1,project:{name:""},google:{project_id:"",region:""},profiles:{},templates:{},services:{},proxy:{enabled:!1,listen:{host:"127.0.0.1",port:0},token_endpoint:{enabled:!1,host:"",port:0},routes:[]},logs:{max_memory_events:50000,persistence:{enabled:!0,directory:"~/.devctl/logs",retention_days:14,max_session_logs:0}},auth:{refresh_threshold_seconds:300},shutdown:{grace_seconds:10},ui:{theme:"system",keymap:{}},secrets:{extra_markers:[],extra_patterns:[]},doctor:{tools:[]},plugins:[],environment:{sources:[],secrets:{}},repoRoot:"",configPath:""}}function tl(e){return e.args.length===0||e.args.length===1&&(e.args[0]??"").trim()===""}function Ko(e){if(e.type!=="")return e.type;return e.mode}function ar(e){let t=Ko(e).toLowerCase();return t==="service"||t==="service_account"}function rf(e){let t=Ko(e).toLowerCase();return t==="user"||t===""}function nf(e){if(e.policy!==""){if(e.policy==="always"||e.policy==="on_failure"||e.policy==="never")return e.policy;return e.policy}if(e.enabled===!0)return"on_failure";return"never"}function Yr(e){let t=e.host===""?"127.0.0.1":e.host;if(e.port===0)return t;return`${t}:${e.port}`}function hs(e){if(e.refresh_threshold_seconds<=0)return 300;return e.refresh_threshold_seconds}function ys(e){if(e.stop_services_on_exit===void 0)return!0;return e.stop_services_on_exit}function vs(e){if(e.grace_seconds<=0)return 10;return e.grace_seconds}function of(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stdout}function sf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stderr}function rl(e,t){return e.find((r)=>r.name===t)}function af(e){return e[0]}var Fn=1,Zp="never",ef="on_failure",tf="always",gs=8080,Xc="127.0.0.1";function G(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ol(e){return G(e)?new Set(Object.keys(e)):new Set}function q(e){if(typeof e==="string")return e;if(typeof e==="number"||typeof e==="boolean")return String(e);return""}function Ve(e){if(typeof e==="number")return e;if(typeof e==="string"){let t=Number(e);return Number.isNaN(t)?0:t}return 0}function ft(e){return e===!0}function Dt(e){if(!Array.isArray(e))return[];return e.map((t)=>q(t))}function Xr(e){if(!G(e))return{};let t={};for(let[r,n]of Object.entries(e))t[r]=q(n);return t}function qo(e){if(typeof e==="string")return{args:e.split(/\s+/).filter((t)=>t!==""),shell:!1};if(Array.isArray(e))return{args:e.map((t)=>q(t)),shell:!1};return ms()}function il(e){if(e===void 0||e===null)return[];if(typeof e==="string"||typeof e==="number")return[nl(e,"http")];if(Array.isArray(e))return e.map((t,r)=>nl(t,`port_${r}`));if(G(e))return Object.entries(e).map(([t,r])=>nl(r,t));return[]}function nl(e,t){if(typeof e==="string"&&e.toLowerCase()==="auto")return{name:t,value:0,auto:!0};return{name:t,value:Ve(e),auto:!1}}function vw(e){if(!G(e))return Qc();let t={},r=[],n={};for(let[o,i]of Object.entries(e))if(o==="required")r=Dt(i);else if(o==="defaults")n=Xr(i);else t[o]=q(i);return{vars:t,required:r,defaults:n}}function xw(e){if(!G(e))return el();return{type:q(e.type),mode:q(e.mode),service_account:q(e.service_account)}}function bw(e){if(!G(e))return Zc();return{type:q(e.type),url:q(e.url),address:q(e.address),command:qo(e.command),interval_seconds:Ve(e.interval_seconds),timeout_seconds:Ve(e.timeout_seconds)}}function ww(e){if(!G(e))return{policy:"",max_retries:0,backoff_seconds:0};return{enabled:e.enabled===void 0?void 0:ft(e.enabled),policy:q(e.policy),max_retries:Ve(e.max_retries),backoff_seconds:Ve(e.backoff_seconds)}}function Sw(e){if(!G(e))return{wait_for_healthy:!1,timeout_seconds:0};return{wait_for_healthy:ft(e.wait_for_healthy),timeout_seconds:Ve(e.timeout_seconds)}}function Vo(e){if(!G(e))return Nn();let t=G(e.logs)?e.logs:{};return{extends:q(e.extends),description:q(e.description),command:qo(e.command),shell:ft(e.shell),working_dir:q(e.working_dir),dependencies:Dt(e.dependencies),ports:il(e.ports),environment:vw(e.environment),health:bw(e.health),identity:xw(e.identity),logs:{stdout:ft(t.stdout),stderr:ft(t.stderr)},restart:ww(e.restart),startup:Sw(e.startup),capabilities:Dt(e.capabilities),proxy:sl(e.proxy)}}function sl(e){if(e===void 0||e===null)return[];if(Array.isArray(e))return e.map((t)=>zr(t));if(G(e))return[zr(e)];return[]}function xs(e){if(!G(e))return{services:[],environment:{}};return{services:Dt(e.services),environment:Xr(e.environment)}}function kw(e){if(typeof e==="string")return{type:e,service_account:""};if(!G(e))return{type:"",service_account:""};return{type:q(e.type),service_account:q(e.service_account)}}function Cw(e){if(!G(e))return{type:"",identity:{type:"",service_account:""},audience:"",service_account:""};return{type:q(e.type),identity:kw(e.identity),audience:q(e.audience),service_account:q(e.service_account)}}function zr(e){if(!G(e))return{name:"",match:{host:"",path:""},upstream:{url:""},auth:{type:"",identity:{type:"",service_account:""},audience:"",service_account:""}};let t=G(e.match)?e.match:{},r=G(e.upstream)?e.upstream:{};return{name:q(e.name),match:{host:q(t.host),path:q(t.path)},upstream:{url:q(r.url)},auth:Cw(e.auth)}}var al=()=>{};import{existsSync as _w,statSync as lf}from"fs";import{basename as cf,dirname as bs,isAbsolute as Rw,join as ws,resolve as df}from"path";function Pr(e,t){if(t!=="")return Pw(t);let r=e===""?process.cwd():e;r=Rw(r)?r:df(r);for(;;){let n=ws(r,wt,Ft);if(Jo(n))return{repoRoot:r,configPath:n};let o=ws(r,"devctl.yaml");if(Jo(o))return{repoRoot:r,configPath:o};let i=bs(r);if(i===r)break;r=i}throw be(Kr,"no devctl configuration found","run `devctl setup` or create a .devctl/config.yaml in the repository root")}function Pw(e){let t=df(e),r;try{r=lf(t)}catch(o){throw ye(Kr,"config path not found",o)}if(r.isDirectory()){if(cf(t)===wt)return{repoRoot:bs(t),configPath:ws(t,Ft)};return{repoRoot:t,configPath:ws(t,Ft)}}let n=bs(t);if(cf(n)===wt)n=bs(n);return{repoRoot:n,configPath:t}}function Jo(e){return _w(e)&&!lf(e).isDirectory()}var wt=".devctl",Ft="config.yaml";var Yo=T(()=>{_e()});function Cs(){return{services:{},templates:{}}}function Ss(e,t,r){let n=ol(r);if(G(r))for(let i of Ew){let s=r[i];if(G(s))for(let a of Object.keys(s))n.add(`${i}.${a}`)}let o=e[t];e[t]=o?new Set([...o,...n]):n}function uf(e,t,r=Cs()){if(t.version!==void 0)e.version=Ve(t.version);if(G(t.project)&&t.project.name!==void 0)e.project.name=q(t.project.name);if(G(t.google)){if(t.google.project_id!==void 0)e.google.project_id=q(t.google.project_id);if(t.google.region!==void 0)e.google.region=q(t.google.region)}if(G(t.profiles))for(let[n,o]of Object.entries(t.profiles)){let i=e.profiles[n];e.profiles[n]=i?Aw(i,o):xs(o)}if(G(t.templates))for(let[n,o]of Object.entries(t.templates)){let i=e.templates[n];e.templates[n]=i?ks(i,o):Vo(o),Ss(r.templates,n,o)}if(G(t.services))for(let[n,o]of Object.entries(t.services)){let i=e.services[n];e.services[n]=i?ks(i,o):Vo(o),Ss(r.services,n,o)}if(G(t.proxy))Tw(e.proxy,t.proxy);if(G(t.logs)){if(t.logs.max_memory_events!==void 0)e.logs.max_memory_events=Ve(t.logs.max_memory_events);if(G(t.logs.persistence)){let n=t.logs.persistence;if(n.enabled!==void 0)e.logs.persistence.enabled=ft(n.enabled);if(n.directory!==void 0)e.logs.persistence.directory=q(n.directory);if(n.retention_days!==void 0)e.logs.persistence.retention_days=Ve(n.retention_days);if(n.max_session_logs!==void 0)e.logs.persistence.max_session_logs=Ve(n.max_session_logs)}}if(G(t.auth)&&t.auth.refresh_threshold_seconds!==void 0)e.auth.refresh_threshold_seconds=Ve(t.auth.refresh_threshold_seconds);if(G(t.shutdown)){if(t.shutdown.stop_services_on_exit!==void 0)e.shutdown.stop_services_on_exit=ft(t.shutdown.stop_services_on_exit);if(t.shutdown.grace_seconds!==void 0)e.shutdown.grace_seconds=Ve(t.shutdown.grace_seconds)}if(G(t.ui)){if(t.ui.theme!==void 0)e.ui.theme=q(t.ui.theme);if(t.ui.keymap!==void 0)e.ui.keymap=Xr(t.ui.keymap)}if(G(t.secrets)){if(t.secrets.extra_markers!==void 0)e.secrets.extra_markers=Dt(t.secrets.extra_markers);if(t.secrets.extra_patterns!==void 0)e.secrets.extra_patterns=Dt(t.secrets.extra_patterns)}if(G(t.doctor)&&Array.isArray(t.doctor.tools))e.doctor.tools=t.doctor.tools.filter(G).map((n)=>({name:q(n.name),command:q(n.command)}));if(Array.isArray(t.plugins))e.plugins=t.plugins.filter(G).map((n)=>({path:q(n.path)})).filter((n)=>n.path!=="");if(G(t.environment)){if(Array.isArray(t.environment.sources))e.environment.sources=Dt(t.environment.sources);if(G(t.environment.secrets))e.environment.secrets={...e.environment.secrets,...Xr(t.environment.secrets)}}}function Tw(e,t){if(t.enabled!==void 0)e.enabled=ft(t.enabled);if(G(t.listen)){if(t.listen.host!==void 0)e.listen.host=q(t.listen.host);if(t.listen.port!==void 0)e.listen.port=Ve(t.listen.port)}if(G(t.token_endpoint)){let r=t.token_endpoint;if(r.enabled!==void 0)e.token_endpoint.enabled=ft(r.enabled);if(r.host!==void 0)e.token_endpoint.host=q(r.host);if(r.port!==void 0)e.token_endpoint.port=Ve(r.port)}if(Array.isArray(t.routes))e.routes=t.routes.map((r)=>zr(r))}function Aw(e,t){if(!G(t))return e;return{services:t.services!==void 0?Dt(t.services):e.services,environment:t.environment!==void 0?{...e.environment,...Xr(t.environment)}:e.environment}}function ks(e,t){if(!G(t))return e;let r=ol(t),n={...e,environment:Lw(e.environment,t.environment),health:Dw(e.health,t.health),identity:Mw(e.identity,t.identity),logs:Ow(e.logs,t.logs),restart:Iw(e.restart,t.restart),startup:$w(e.startup,t.startup)};if(r.has("extends"))n.extends=q(t.extends);if(r.has("description"))n.description=q(t.description);if(r.has("command"))n.command=qo(t.command);if(r.has("shell"))n.shell=ft(t.shell);if(r.has("working_dir"))n.working_dir=q(t.working_dir);if(r.has("dependencies"))n.dependencies=Dt(t.dependencies);if(r.has("ports"))n.ports=il(t.ports);if(r.has("capabilities"))n.capabilities=Dt(t.capabilities);if(r.has("proxy"))n.proxy=sl(t.proxy);return n}function Lw(e,t){if(!G(t))return e;let r={...e.vars},n={...e.defaults},o=e.required;for(let[i,s]of Object.entries(t))if(i==="required")o=Dt(s);else if(i==="defaults")Object.assign(n,Xr(s));else r[i]=q(s);return{vars:r,required:o,defaults:n}}function Dw(e,t){if(!G(t))return e;return{type:t.type!==void 0?q(t.type):e.type,url:t.url!==void 0?q(t.url):e.url,address:t.address!==void 0?q(t.address):e.address,command:t.command!==void 0?qo(t.command):e.command,interval_seconds:t.interval_seconds!==void 0?Ve(t.interval_seconds):e.interval_seconds,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function Mw(e,t){if(!G(t))return e;return{type:t.type!==void 0?q(t.type):e.type,mode:t.mode!==void 0?q(t.mode):e.mode,service_account:t.service_account!==void 0?q(t.service_account):e.service_account}}function Ow(e,t){if(!G(t))return e;return{stdout:t.stdout!==void 0?ft(t.stdout):e.stdout,stderr:t.stderr!==void 0?ft(t.stderr):e.stderr}}function Iw(e,t){if(!G(t))return e;return{enabled:t.enabled!==void 0?ft(t.enabled):e.enabled,policy:t.policy!==void 0?q(t.policy):e.policy,max_retries:t.max_retries!==void 0?Ve(t.max_retries):e.max_retries,backoff_seconds:t.backoff_seconds!==void 0?Ve(t.backoff_seconds):e.backoff_seconds}}function $w(e,t){if(!G(t))return e;return{wait_for_healthy:t.wait_for_healthy!==void 0?ft(t.wait_for_healthy):e.wait_for_healthy,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function pf(e){let t=Object.keys(e.services).sort();for(let r of t){let n=e.services[r]?.proxy??[];if(n.length===0)continue;n.forEach((o,i)=>{let s=n.length===1?r:`${r}-${i+1}`;e.proxy.routes.push({name:s,match:o.match,upstream:o.upstream,auth:o.auth})})}}function ff(e,t=Cs()){if(Object.keys(e.templates).length===0)return;let r={};for(let[n,o]of Object.entries(e.services))r[n]=gf(e,o,t.services[n]??new Set,t,{});e.services=r}function gf(e,t,r,n,o){if(t.extends==="")return t;if(o[t.extends])throw Error(`template cycle involving "${t.extends}"`);let i=e.templates[t.extends]??Nn();if(!e.templates[t.extends])throw Error(`service extends unknown template "${t.extends}"`);let s={...o,[t.extends]:!0},a=n.templates[t.extends]??new Set,c=gf(e,i,a,n,s),l=Fw(c,t,r);return l.extends=t.extends,l}function Fw(e,t,r){let n={...e};if(r.has("extends"))n.extends=t.extends;if(r.has("description"))n.description=t.description;if(r.has("command"))n.command=t.command;if(r.has("shell"))n.shell=t.shell;if(r.has("working_dir"))n.working_dir=t.working_dir;if(r.has("dependencies"))n.dependencies=t.dependencies;if(r.has("ports"))n.ports=t.ports;if(r.has("capabilities"))n.capabilities=t.capabilities;if(r.has("proxy"))n.proxy=t.proxy;return n.health={type:r.has("health.type")?t.health.type:e.health.type,url:r.has("health.url")?t.health.url:e.health.url,address:r.has("health.address")?t.health.address:e.health.address,command:r.has("health.command")?t.health.command:e.health.command,interval_seconds:r.has("health.interval_seconds")?t.health.interval_seconds:e.health.interval_seconds,timeout_seconds:r.has("health.timeout_seconds")?t.health.timeout_seconds:e.health.timeout_seconds},n.identity={type:r.has("identity.type")?t.identity.type:e.identity.type,mode:r.has("identity.mode")?t.identity.mode:e.identity.mode,service_account:r.has("identity.service_account")?t.identity.service_account:e.identity.service_account},n.logs={stdout:r.has("logs.stdout")?t.logs.stdout:e.logs.stdout,stderr:r.has("logs.stderr")?t.logs.stderr:e.logs.stderr},n.restart={enabled:r.has("restart.enabled")?t.restart.enabled:e.restart.enabled,policy:r.has("restart.policy")?t.restart.policy:e.restart.policy,max_retries:r.has("restart.max_retries")?t.restart.max_retries:e.restart.max_retries,backoff_seconds:r.has("restart.backoff_seconds")?t.restart.backoff_seconds:e.restart.backoff_seconds},n.startup={wait_for_healthy:r.has("startup.wait_for_healthy")?t.startup.wait_for_healthy:e.startup.wait_for_healthy,timeout_seconds:r.has("startup.timeout_seconds")?t.startup.timeout_seconds:e.startup.timeout_seconds},n.environment={vars:{...e.environment.vars,...t.environment.vars},defaults:{...e.environment.defaults,...t.environment.defaults},required:r.has("environment.required")?t.environment.required:e.environment.required},n}var Ew;var mf=T(()=>{al();Ew=["environment","restart","startup","health","logs","identity"]});function cl(e){if(e.version===0)throw M(X,"version is required");if(e.version===Fn)return e;throw M(X,`unsupported config version ${e.version} (expected ${Fn}); no migration is available`)}var ll=T(()=>{_e()});var hf,yf,vf,xf,bf,wf,Sf,kf,dl,ul,pl,fl,Cf,_f,Rf,Pf,Ef,Tf,Af,Lf,Df,Mf,Of,If,$f,Ff,Nf,Hf,jf,Bf;var gl=T(()=>{hf=["version","project","google","profiles","templates","services","proxy","logs","auth","shutdown","ui","secrets","doctor","plugins","environment"],yf=["extends","description","command","shell","working_dir","dependencies","ports","environment","health","identity","logs","restart","startup","capabilities","proxy"],vf=["type","url","address","command","interval_seconds","timeout_seconds"],xf=["type","mode","service_account"],bf=["enabled","policy","max_retries","backoff_seconds"],wf=["wait_for_healthy","timeout_seconds"],Sf=["enabled","listen","token_endpoint","routes"],kf=["host","port"],dl=["name","match","upstream","auth"],ul=["host","path"],pl=["url"],fl=["type","identity","audience","service_account"],Cf=["max_memory_events","persistence"],_f=["enabled","directory","retention_days","max_session_logs"],Rf=["refresh_threshold_seconds"],Pf=["stop_services_on_exit","grace_seconds"],Ef=["theme","keymap"],Tf=["name"],Af=["project_id","region"],Lf=["services","environment"],Df=["required","defaults"],Mf=["stdout","stderr"],Of=["extra_markers","extra_patterns"],If=["tools"],$f=["name","command"],Ff=["enabled","host","port"],Nf=["path"],Hf=["sources","secrets"],jf=["google","google_api","iap","network","service_identity","local_http"],Bf=["|","||","&&",";",">",">>","<","&"]});function Qr(e,t){if(!qw(e))return[];let r=jw(t),n=[];for(let o of Object.keys(e)){let i=Kw(t,o);if(r.length>0&&!r.includes(o)&&!Hw(t))n.push(i);n.push(...Qr(e[o],i))}return n}function Hw(e){if(e==="services"||e==="profiles"||e==="templates")return!0;if(e.endsWith(".environment")||e.endsWith(".defaults")||e.endsWith(".keymap"))return!0;return e.includes(".environment.")&&!e.endsWith(".environment")}function jw(e){switch(e){case"":return hf;case"project":return Tf;case"google":return Af;case"proxy":return Sf;case"proxy.listen":return kf;case"proxy.token_endpoint":return Ff;case"logs":return Cf;case"logs.persistence":return _f;case"auth":return Rf;case"shutdown":return Pf;case"ui":return Ef;case"secrets":return Of;case"doctor":return If;case"environment":return Hf;default:return Bw(e)}}function Bw(e){if(e==="services"||e==="profiles"||e==="templates")return[];if(e.startsWith("services.")||e.startsWith("templates."))return Ww(e);if(e.startsWith("profiles.")){if(e.split(".").length===2)return Lf}if(e.includes("routes"))return Uw(e);if(e.startsWith("doctor.tools")&&e.split(".").length>=3)return $f;if(e==="plugins")return[];if(e.startsWith("plugins.")&&e.split(".").length===2)return Nf;return[]}function Ww(e){let t=e.split(".");if(t.length===2)return yf;if(t.length>=3)switch(t[2]){case"health":return vf;case"identity":return xf;case"restart":return bf;case"startup":return wf;case"logs":return Mf;case"environment":return Df;case"proxy":return Gw(t);default:return[]}return[]}function Gw(e){let t=e.slice(3),r=t[0]!==void 0&&/^\d+$/.test(t[0])?1:0,n=t[r]??"";if(n==="match")return ul;if(n==="upstream")return pl;if(n==="auth")return fl;return dl}function Uw(e){if(e==="proxy.routes")return[];if(e.endsWith(".match"))return ul;if(e.endsWith(".upstream"))return pl;if(e.endsWith(".auth"))return fl;if(e.includes("proxy.routes")&&e.split(".").length===Nw+1)return dl;return[]}function Kw(e,t){if(e==="")return t;return`${e}.${t}`}function qw(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Hn(e){return`unknown fields: ${e.join(", ")}`}var Nw=2;var Wf=T(()=>{gl()});function Gf(e,t,r){let n=e,o="";for(;;){let i=n.indexOf("${");if(i<0)return o+n;o+=n.slice(0,i);let s=n.slice(i).indexOf("}");if(s<0)throw Error(`unclosed environment reference in "${e}"`);let a=n.slice(i+2,i+s);o+=Vw(a,t,r),n=n.slice(i+s+1)}}function Vw(e,t,r){let n=e.split(".");if(n.length<3||n[0]!=="services")throw Error(`unsupported reference \${${e}}`);let o=n[1]??"",i=t.services[o];if(!i)throw Error(`reference \${${e}}: unknown service`);let s=r[o];if(n[2]==="port"){if(s){if(s.http!==void 0)return String(s.http);let c=Object.values(s)[0];if(c!==void 0)return String(c)}let a=af(i.ports);if(a&&!a.auto)return String(a.value)}if(n[2]==="ports"){let a=n[3];if(!a)throw Error(`reference \${${e}}: missing port name`);if(s&&s[a]!==void 0)return String(s[a]);let c=rl(i.ports,a);if(c&&!c.auto)return String(c.value);let l=Number.parseInt(a,10);if(!Number.isNaN(l)&&l>=0&&l<i.ports.length){let d=i.ports[l];if(d&&!d.auto)return String(d.value)}}throw Error(`unresolvable reference \${${e}}`)}function ml(e,t,r){let n={};for(let[o,i]of Object.entries(e))n[o]=Gf(i,t,r);return n}function Uf(e){let t=[],r=e;for(;;){let n=r.indexOf("${");if(n<0)return t;let o=r.slice(n).indexOf("}");if(o<0)return t;t.push(r.slice(n+2,n+o)),r=r.slice(n+o+1)}}function Kf(e,t){let r=e.split(".");if(r.length<2)return!1;if(r[0]!=="services"||r.length<3)return!1;let n=t.services[r[1]??""];if(!n)return!1;if(r[2]==="port"||r[2]==="ports"){if(r.length===3)return n.ports.length>0;if(r.length>=4){let o=r[3]??"";if(!Number.isNaN(Number.parseInt(o,10)))return!0;return rl(n.ports,o)!==void 0}}return!0}var hl=()=>{};function xl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=n.health.type;if(o!==""&&!Jf.includes(o.toLowerCase()))t.push({service:r,type:o})}return t}function Ut(e){let t=[];if(e.version===0)t.push("version is required");else if(e.version!==Fn)t.push(`unsupported config version ${e.version} (expected ${Fn}); no migration is available`);if(Object.keys(e.services).length===0)t.push("at least one service must be defined");if(t.push(...Yw(e)),t.push(...Zw(e)),t.push(...tS(e)),t.push(...rS(e)),e.logs.max_memory_events<0)t.push("logs.max_memory_events must be >= 0");return t}function Yw(e){let t=[],r={};for(let[n,o]of Object.entries(e.services)){let i=`services.${n}`;if(tl(o.command))t.push(`${i}.command is required`);t.push(...oS(i,o.command,o.shell)),t.push(...iS(i,o.capabilities));for(let c of o.dependencies){if(!e.services[c])t.push(`${i}.dependencies: unknown service "${c}"`);if(c===n)t.push(`${i}.dependencies: service cannot depend on itself`)}if(o.extends!==""&&!e.templates[o.extends])t.push(`${i}.extends: unknown template "${o.extends}"`);for(let c of o.ports.filter((l)=>!l.auto))if(c.value<vl||c.value>yl)t.push(`${i}.ports.${c.name}: invalid port ${c.value}`);else if(r[c.value])t.push(`duplicate port ${c.value} used by ${r[c.value]} and ${n}`);else r[c.value]=n;let s=Qw(`${i}.identity`,o.identity,e.plugins.length>0);if(s!=="")t.push(s);t.push(...zw(i,o,e.plugins.length>0));let a=nf(o.restart);if(a!==Zp&&a!==ef&&a!==tf)t.push(`${i}.restart.policy must be never, on_failure, or always`);t.push(...eS(`${i}.environment`,o.environment,e))}return t}function zw(e,t,r){let n=[];if(t.health.type==="")return n;let o=t.health.type.toLowerCase();if(!Jf.includes(o)&&!r)n.push(`${e}.health.type must be http, tcp, process, or command`);if(o==="http"&&t.health.url==="")n.push(`${e}.health.url is required for http health checks`);if(o==="tcp"&&t.health.address===""&&t.ports.length===0)n.push(`${e}.health.address is required for tcp health checks without ports`);if(o==="command"&&tl({args:t.health.command.args,shell:!1}))n.push(`${e}.health.command is required for command health checks`);return n}function Qw(e,t,r){let n=Ko(t).toLowerCase();if(n===""||n==="user")return"";if(n==="service"||n==="service_account"){if(t.service_account==="")return`${e}.service_account is required for service identity`;if(!t.service_account.includes("@"))return`${e}.service_account must be an email`;return""}if(r)return"";return`${e}.type must be user or service_account`}function bl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=Ko(n.identity).toLowerCase();if(!Xw.includes(o))t.push({service:r,type:o})}return t}function Zw(e){let t={},r=[],n=[],o=(i)=>{let s=t[i]??Jw;if(s===Vf)return;if(s===qf){r.push(`dependency cycle: ${[...n,i].join(" \u2192 ")}`);return}t[i]=qf,n.push(i);let a=e.services[i];if(a){for(let c of a.dependencies)if(e.services[c])o(c)}n.pop(),t[i]=Vf};for(let i of Object.keys(e.services))o(i);return r}function eS(e,t,r){let n=[],o=(i,s)=>{for(let a of Uf(s))if(!Kf(a,r))n.push(`${e}.${i}: unresolvable reference \${${a}}`)};for(let[i,s]of Object.entries(t.vars))o(i,s);for(let[i,s]of Object.entries(t.defaults))o(i,s);return n}function tS(e){let t=[];for(let[r,n]of Object.entries(e.profiles))for(let o of n.services)if(!e.services[o])t.push(`profiles.${r} references unknown service "${o}"`);return t}function rS(e){let t=[];if(e.proxy.listen.host!==""&&!sS(e.proxy.listen.host))t.push("proxy.listen.host must be an IP address or localhost");if(e.proxy.enabled&&e.proxy.listen.port===0)t.push("proxy.listen.port is required when proxy.enabled is true");if(e.proxy.listen.port!==0&&(e.proxy.listen.port<vl||e.proxy.listen.port>yl))t.push("proxy.listen.port is invalid");let r={};return e.proxy.routes.forEach((n,o)=>{let i=`proxy.routes[${o}]`;if(n.name==="")t.push(`${i}.name is required`);else if(r[n.name])t.push(`${i}: duplicate route name ${n.name}`);if(r[n.name]=!0,n.upstream.url==="")t.push(`${i}.upstream.url is required`);if(n.auth.type.toLowerCase()==="iap"){if(n.auth.audience.trim()==="")t.push(`${i}.auth.audience is required when auth.type is iap`);if(n.auth.identity.type.trim()==="")t.push(`${i}.auth.identity.type is required when auth.type is iap`)}let s=n.auth.identity.type.toLowerCase();if(s==="service"||s==="service_account"||ar({type:s,mode:"",service_account:""})){if((n.auth.identity.service_account||n.auth.service_account)==="")t.push(`${i}.auth.identity.service_account is required`)}}),t.push(...nS(e)),t}function nS(e){let t=[],r=e.proxy.token_endpoint;if(!r.enabled)return t;let n=r.host||Xc;if(n==="0.0.0.0")t.push("proxy.token_endpoint.host must be a loopback address");else if(n!==""&&n!==Xc&&n!=="localhost"&&!n.startsWith("127."))t.push("proxy.token_endpoint.host must be a loopback address");if(r.port!==0&&(r.port<vl||r.port>yl))t.push("proxy.token_endpoint.port is invalid");return t}function oS(e,t,r){if(t.shell||r)return[];for(let n of t.args)if(Bf.includes(n)||n.includes("|")||n.includes(";")||n.includes("&&"))return[`${e}.command contains shell metacharacters; set shell: true to run via a shell`];return[]}function iS(e,t){let r=[];for(let n of t)if(!jf.includes(n))r.push(`${e}.capabilities: unknown capability "${n}"`);return r}function sS(e){if(e==="localhost")return!0;return aS(e)}function aS(e){if(/^(\d{1,3}\.){3}\d{1,3}$/.test(e))return e.split(".").every((r)=>{let n=Number(r);return n>=0&&n<=255});return e.includes(":")}var yl=65535,vl=1,Jf,Jw=0,qf=1,Vf=2,Xw;var _s=T(()=>{gl();hl();Jf=["http","tcp","process","command"];Xw=["","user","service","service_account"]});import{readdirSync as cS,readFileSync as lS}from"fs";import{basename as zf,dirname as dS,extname as uS,join as Zr,resolve as pS}from"path";import{parse as fS}from"yaml";function jn(e,t,r){try{return Xo(e,t,{candidateText:r}),[]}catch(n){if(n instanceof Te){let o=`${n.kind}: `;return[n.message.startsWith(o)?n.message.slice(o.length):n.message]}return[n instanceof Error?n.message:String(n)]}}function gt(e,t){let{repoRoot:r,configPath:n}=Pr(e,t);return Xo(r,n)}function zo(e,t){try{return gt(e,t)}catch(r){if(!ds(r,Kr))throw r;let n=e===""?process.cwd():pS(e),o=Jr();return o.repoRoot=n,o.configPath=Zr(n,wt,Ft),o}}function Xo(e,t,r){let n=Jr(),o=Cs();Xf(t,n,o,r?.candidateText),n.repoRoot=e,n.configPath=t;let i=dS(t);if(zf(i)===wt)mS(i,n,o);n=gS(n,e,t,o),n=cl(n);try{ff(n,o)}catch(a){throw ye(X,"template merge failed",a)}pf(n);let s=Ut(n);if(s.length>0)throw M(X,s.join(`
|
|
5
|
-
`));return n}function
|
|
6
|
-
`);this.buf=r.pop()??"";for(let n of r){if(n.trim()==="")continue;this.onLine(n)}}),e.on("error",(t)=>this.rejectPending(t instanceof Error?t:Error(String(t)))),e.on("close",()=>this.rejectPending(Error("supervisor connection closed")))}onLine(e){let t;try{t=JSON.parse(e)}catch{return}if(t.event){for(let n of this.listeners)n(t.event);return}let r=t.id?this.pending.get(t.id):void 0;if(!r)return;if(this.pending.delete(t.id??""),clearTimeout(r.timer),t.error){r.reject(
|
|
7
|
-
`)})}close(){this.rejectPending(Error("supervisor connection closed")),this.socket.destroy()}rejectPending(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}}function
|
|
8
|
-
`)}async function Ll(e,t,r=""){let n=Rs(e,t,r);if(!n)throw be(nt,"no devctl configuration found","run `devctl setup`, create a .devctl/config.yaml in the repository root, or pass --repo");let o=await en(n.repoRoot);return ti(o),{repoRoot:n.repoRoot,client:o}}async function Mt(e,t,r,n){let o=n?.allowMissingConfig===!0?zo(e,t):gt(e,t),i=new Es(o);if(!r)return i.client=await en(o.repoRoot),ti(i.client),i;return i.client=await lg(o.repoRoot,o.configPath),ti(i.client),i}async function dg(e){let t=new Es(Jr());return t.client=e,ti(t.client),t.cfg=await t.configSnapshot(),t}async function ug(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(!n)throw be(nt,"supervisor is not running","run `devctl start` before `devctl attach`");return dg(n)}async function pg(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(n)return dg(n);let o=gt(e,t),i=new Es(o);return i.client=await lg(o.repoRoot,o.configPath),ti(i.client),i.cfg=await i.configSnapshot(),i}var DS=50,sg=8000,MS=200,OS=30000,IS;var Dl=T(()=>{St();rg();Tl();_e();Ye();IS=new Set(["logs","logs_page","logs_stats"])});function As(e){if(ar(e))return Nt({kind:tn,serviceAccount:e.service_account});if(rf(e)&&(e.type!==""||e.mode!==""))return Nt({kind:Ts});return Nt({kind:Bn})}function Wn(e){if(e.type.toLowerCase()==="none")return Nt({kind:Bn});let t=e.identity.type.toLowerCase(),r=e.identity.service_account||e.service_account;if(t==="service"||t==="service_account"||e.type==="service_account")return Nt({kind:tn,serviceAccount:r});if(e.type.toLowerCase()==="iap"&&t==="")return Nt({kind:Bn});if(e.type===""&&t==="")return Nt({kind:Bn});return Nt({kind:Ts})}function Ls(e){return e.kind===Ts||e.kind===tn}function ri(e){if(e.kind===tn)return`sa:${e.serviceAccount}`;if(e.email!=="")return`user:${e.email}`;return"user"}function Nt(e={}){return{kind:Bn,email:"",serviceAccount:"",project:"",projectSource:"",adcAvailable:!1,...e}}function Ml(e){let t=new Map,r=(n,o)=>{if(n!=="")t.set(n,(t.get(n)??!1)||o)};for(let n of Object.values(e.services))if(ar(n.identity)&&n.identity.service_account!=="")r(n.identity.service_account,!0);for(let n of e.proxy.routes){let o=n.auth.type.toLowerCase(),i=n.auth.identity.type.toLowerCase(),s=n.auth.identity.service_account||n.auth.service_account;if(i==="service"||i==="service_account"||o==="service_account")r(s,o!=="none")}return[...t.entries()].map(([n,o])=>({email:n,active:o})).sort((n,o)=>n.email.localeCompare(o.email))}function Er(e){return Ml(e).filter((t)=>t.active).map((t)=>t.email)}function fg(e,t,r){let n=[];for(let o of t){let i=e.services[o];if(!i)continue;let s=As(i.identity);if(ar(i.identity)&&i.identity.service_account===""){n.push({name:o,message:"service account identity is not configured"});continue}if((Ls(s)||i.capabilities.some((c)=>c==="google_api"||c==="iap"||c==="service_identity"))&&!r)n.push({name:o,message:"ADC unavailable"})}return n}function ni(e){if(Er(e).length>0)return!0;if(e.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap"))return!0;return Object.values(e.services).some((t)=>{if(Ls(As(t.identity)))return!0;return t.capabilities.some((r)=>r==="google_api"||r==="iap"||r==="service_identity")})}function Ol(){return{name:"user",accepts:(e)=>!ar(e),resolve:async(e,t)=>{if(e.type===""&&e.mode==="")return Nt({kind:Bn});return{...await t(),kind:Ts}}}}function Il(){return{name:"service_account",accepts:(e)=>ar(e),resolve:async(e,t)=>{if(e.service_account==="")throw M(ls,"service account identity is not configured");return{...await t(),kind:tn,serviceAccount:e.service_account}}}}async function gg(e,t,r){if(r)for(let n=r.length-1;n>=0;n-=1){let o=r[n];if(o?.accepts(e))return o.resolve(e,t)}if(ar(e))return Il().resolve(e,t);return Ol().resolve(e,t)}var Ts="user",tn="service_account",Bn="none";var rn=T(()=>{St();_e()});import{existsSync as Ds,readFileSync as BS}from"fs";import{homedir as hg}from"os";import{join as $l}from"path";var{spawn:Fl}=globalThis.Bun;function Un(){let e=globalThis;if(e.window&&typeof e.window.fetch!=="function")e.window.fetch=fetch}function Nl(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS||$l(hg(),".config","gcloud","application_default_credentials.json");if(!Ds(e))return"";try{let t=JSON.parse(BS(e,"utf8"));return typeof t.quota_project_id==="string"?t.quota_project_id:""}catch{return""}}async function Ht(e){let t={gcloudInstalled:await Hl("gcloud"),adcAvailable:!1,userEmail:"",projectID:"",projectSource:""};if(e!=="")t.projectID=e,t.projectSource="configuration";else{let r=JS("GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_PROJECT");if(r!=="")t.projectID=r,t.projectSource="environment variable";else if(t.gcloudInstalled){let n=await mg("core/project");if(n!=="")t.projectID=n,t.projectSource="gcloud configuration"}}if(oi())try{await wg(US(t),GS)}catch(r){t.adcAvailable=!1,t.error=Kn(r)}if(t.userEmail===""&&t.gcloudInstalled)t.userEmail=await mg("core/account");return t}async function US(e){Un();let{GoogleAuth:t}=await import("google-auth-library"),r=new t({scopes:[WS]});await r.getClient(),e.adcAvailable=!0;let n=await r.getProjectId().catch(()=>"");if(e.projectID===""&&n)e.projectID=n,e.projectSource="application default credentials";let o=await KS(r);if(o!=="")e.userEmail=o}async function KS(e){try{let t=await e.getCredentials();if(t.client_email)return t.client_email}catch{}try{let t=await e.getClient(),r=typeof t.credentials?.id_token==="string"?t.credentials.id_token:"";if(r!==""){let n=qS(r);if(n!=="")return n}}catch{return""}return""}function qS(e){let t=e.split(".");if(t.length<2||!t[1])return"";try{let r=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));return typeof r.email==="string"?r.email:""}catch{return""}}async function vg(e){let t=await Ht(e);return Nt({kind:"user",email:t.userEmail,project:t.projectID,projectSource:t.projectSource,adcAvailable:t.adcAvailable})}async function Ms(){if(await Fl({cmd:["gcloud","auth","application-default","login"],stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited!==0)throw be(In,"application-default login failed","run `gcloud auth application-default login`")}async function xg(){if(await Fl({cmd:["gcloud","auth","application-default","revoke","--quiet"],stdout:"ignore",stderr:"pipe"}).exited!==0)throw be(In,"failed to revoke application-default credentials","run `gcloud auth application-default revoke`")}function Kn(e){let t=VS(e).toLowerCase();if(Gn(t,["unauth","invalid_grant","token has been expired","expired"]))return be(In,"credential expired or invalid","run `devctl auth login` or `gcloud auth application-default login`");if(Gn(t,["api has not been used","has not been enabled","access not configured","service_disabled"]))return be(qr,"required Google API is not enabled","enable the API in the target service account project; devctl will not enable APIs automatically");if(Gn(t,["permission","forbidden","iam"])){if(Gn(t,["serviceaccounttoken","iamcredentials","token creator","getaccesstoken"]))return be(ls,"cannot impersonate service account","ask an administrator to grant roles/iam.serviceAccountTokenCreator on the target service account");return be(qr,"authorization failure","verify IAM permissions for the current user on this project")}if(t.includes("audience"))return be(jc,"IAP audience is incorrect","set auth.audience on the proxy route to the IAP OAuth client ID");if(t.includes("iap"))return ye(jc,"IAP authentication failure",e);if(t.includes("project"))return be(X,"wrong or missing Google project","set google.project_id in .devctl/config.yaml");if(Gn(t,["timeout","network","connection refused","no such host"]))return ye(nt,"network problem reaching Google Cloud",e);if(Gn(t,["adc","default credentials","could not find"]))return be(In,"application default credentials unavailable","run `gcloud auth application-default login`");return ye(In,"Google authentication failed",e)}function VS(e){let t=[],r=new Set,n=(o,i)=>{if(o===null||o===void 0||i>8||r.has(o))return;if(typeof o==="string"){t.push(o);return}if(typeof o!=="object")return;r.add(o);let s=o;for(let a of["message","reason","status","code","error_description","permission","service"])n(s[a],i+1);for(let a of["error","errors","details","response","data","cause","metadata"]){let c=s[a];if(Array.isArray(c))c.forEach((l)=>n(l,i+1));else n(c,i+1)}};return n(e,0),t.length>0?t.join(" "):String(e)}function Gn(e,t){return t.some((r)=>e.includes(r))}function JS(...e){for(let t of e){let r=process.env[t];if(r)return r}return""}async function Hl(e){try{return(await bg(process.platform==="win32"?["where",e]:["which",e],yg)).code===0}catch{return!1}}function oi(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS;if(e&&Ds(e))return!0;if(Ds($l(hg(),".config","gcloud","application_default_credentials.json")))return!0;let t=process.env.APPDATA;return Boolean(t&&Ds($l(t,"gcloud","application_default_credentials.json")))}async function mg(e){try{let t=await bg(["gcloud","config","get-value",e],yg);if(t.code!==0)return"";let r=t.stdout.trim();if(r===""||r==="(unset)")return"";return r}catch{return""}}async function bg(e,t){let r=Fl({cmd:e,stdout:"pipe",stderr:"ignore",env:{...process.env,CLOUDSDK_CORE_DISABLE_PROMPTS:"1",CLOUDSDK_CORE_DISABLE_USAGE_REPORTING:"true"}}),n=r.stdout?new Response(r.stdout).text():Promise.resolve("");try{let[o,i]=await wg(Promise.all([n,r.exited]),t);return{code:i??1,stdout:o}}catch{return r.kill(),{code:1,stdout:""}}}function wg(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("timeout")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}var WS="https://www.googleapis.com/auth/cloud-platform",yg=1500,GS=2000;var nn=T(()=>{On();_e();rn()});var{spawn:jl}=globalThis.Bun;import{createServer as Sg}from"net";async function kg(e,t,r={}){let n={};for(let[i,s]of Object.entries(r))for(let a of Object.values(s))n[a]=i;let o={};for(let[i,s]of Object.entries(e.services)){if(t.length>0&&!t.includes(i))continue;let a={};for(let c of s.ports){let l=r[i]?.[c.name],d=l&&l>=Bl?l:c.value;if(l===void 0&&c.auto)d=await zS();if(d<Bl||d>YS)throw new Te(X,`invalid port ${d} on service ${i}`,{service:i});if(n[d]&&n[d]!==i)throw new Te(X,`duplicate port ${d} used by ${n[d]} and ${i}`,{service:i});if(l!==d&&!c.auto&&!await qn(d))throw await XS(i,c.name,d);n[d]=i,a[c.name]=d}o[i]=a}return o}function zS(){return new Promise((e,t)=>{let r=Sg();r.listen(0,"127.0.0.1",()=>{let n=r.address();r.close(()=>{if(n&&typeof n==="object")e(n.port);else t(ye(X,"unable to allocate dynamic port",Error("no address")))})}),r.on("error",(n)=>t(ye(X,"unable to allocate dynamic port",n)))})}async function Os(e){let t=e.ports.filter((n)=>!n.auto&&n.value>=Bl);if(t.length===0)return;let r={};for(let n of t){if(await qn(n.value))return;r[n.name]=n.value}return r}function qn(e){return new Promise((t)=>{let r=Sg();r.listen(e,"127.0.0.1",()=>{r.close(()=>t(!0))}),r.on("error",()=>t(!1))})}async function XS(e,t,r){let n=await Vn(r);return QS(e,t,r,n)}function QS(e,t,r,n){let o=t===""?`${e} port`:`${e} ports.${t}`;if(n&&n.pid===process.pid)return be(bt,`${e} blocked: this TUI already holds port ${r}`,`Stop the proxy from the Proxy screen, or change ${o} in .devctl.`,e);if(n)return be(bt,`${e} blocked: ${n.command} (pid ${n.pid}) is using port ${r}`,`Open Doctor and press enter to free port ${r}, or change ${o} in .devctl.`,e);return be(bt,`${e} blocked: port ${r} is already in use`,`Something is listening on ${r}. Open Doctor to free it, or change ${o} in .devctl.`,e)}function ZS(e,t){let r=e.split(`
|
|
9
|
-
`).filter((n)=>n.trim()!==""&&!n.startsWith("COMMAND"));for(let n of r){let o=n.trim().split(/\s+/),i=o[0]??"",s=Number(o[1]);if(i!==""&&Number.isInteger(s)&&s>0)return{port:t,pid:s,command:i}}return}async function
|
|
10
|
-
`)){if(!r.includes("LISTENING")&&!r.includes("LISTEN"))continue;if(!r.includes(`:${t}`)&&!r.includes(` ${t} `))continue;let n=r.trim().match(/(\d+)\s*$/),o=n?Number(n[1]):0;if(Number.isInteger(o)&&o>0)return{port:t,pid:o,command:"process"}}return}async function
|
|
11
|
-
`)}async delete(e){let t=
|
|
12
|
-
`)}function
|
|
13
|
-
`)}function
|
|
14
|
-
`)}function Pk(e){return{identity:e.identity,audience:e.audience,scopes:e.scopes,accessToken:e.accessToken,tokenType:e.tokenType,expiresAt:e.expiresAt.toISOString()}}function Ek(e){return{accessToken:e.accessToken,tokenType:e.tokenType||"Bearer",expiresAt:new Date(e.expiresAt),audience:e.audience,identity:e.identity,scopes:e.scopes}}function an(){return[Dk(),Lk(),Ak()]}function Tk(e){return{name:"static",accepts:(t,r)=>(e.identity===""||t===e.identity)&&(e.audience===""||r===e.audience),fetch:async(t,r,n)=>({...e,identity:t,audience:r,scopes:n})}}function Ak(){return{name:"user",accepts:(e,t)=>!e.startsWith("sa:")&&t==="",fetch:async(e,t,r)=>{if(e.startsWith("sa:"))throw M(ir,"user provider cannot mint service-account tokens");return $k(e,t,r)}}}function Lk(){return{name:"service_account",accepts:(e,t)=>e.startsWith("sa:")&&t==="",fetch:async(e,t,r)=>{if(!e.startsWith("sa:"))throw M(ir,"service-account provider cannot mint user tokens");return Mk(e,t,r)}}}function Dk(){return{name:"iap",accepts:(e,t)=>t!=="",fetch:async(e,t,r)=>{if(t==="")throw M(ir,"IAP audience is required");if(e.startsWith("sa:"))return Ok(e,t,r);return Ik(e,t,r)}}}async function Mk(e,t,r){let n=e.slice(3);try{Un();let i=await new Gs({scopes:r.length>0?r:[Ws]}).getClient(),s=new wk({sourceClient:i,targetPrincipal:n,targetScopes:r.length>0?r:[Ws],lifetime:3600}),a=await s.getAccessToken(),c=typeof a==="string"?a:a?.token;if(!c)throw M(ir,"empty impersonated token");return{accessToken:c,tokenType:"Bearer",expiresAt:Us(c,s),audience:t,identity:e,scopes:r}}catch(o){throw Kn(o)}}async function Ok(e,t,r){let n=e.slice(3);try{Un();let i=await new Gs({scopes:[Ws]}).getClient(),s=`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(n)}:generateIdToken`,c=(await i.request({url:s,method:"POST",data:{audience:t,includeEmail:!0}})).data.token;if(!c)throw M(ir,"empty impersonated IAP id token");return{accessToken:c,tokenType:"Bearer",expiresAt:Us(c),audience:t,identity:e,scopes:r}}catch(o){throw Kn(o)}}async function Ik(e,t,r){try{Un();let i=await(await new Gs({scopes:r.length>0?r:[_k]}).getIdTokenClient(t)).idTokenProvider.fetchIdToken(t);return{accessToken:i,tokenType:"Bearer",expiresAt:Us(i),audience:t,identity:e,scopes:r}}catch(n){throw Kn(n)}}async function $k(e,t,r){try{Un();let o=await new Gs({scopes:r.length>0?r:[Ws]}).getClient(),i=await o.getAccessToken();if(!i.token)throw M(ir,"empty access token");return{accessToken:i.token,tokenType:"Bearer",expiresAt:Fk(o,i.token),audience:t,identity:e,scopes:r}}catch(n){throw Kn(n)}}function Us(e,t){if(t?.credentials?.expiry_date)return new Date(t.credentials.expiry_date);return Nk(e)??new Date(Date.now()+Sk)}function Fk(e,t){return Us(t,e)}function Nk(e){let t=e.split(".");if(t.length<2||!t[1])return;try{let r=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));if(typeof r.exp==="number")return new Date(r.exp*1000)}catch{return}return}function Hk(e){if(e instanceof Te)return e.kind!==X&&e.kind!==qr;let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("network")||t.includes("econnreset")||t.includes("etimedout")||t.includes("503")||t.includes("429")}var ed=300000,Sk=3000000,kk=3,Ck=200,Ws="https://www.googleapis.com/auth/cloud-platform",_k="https://www.googleapis.com/auth/userinfo.email";var ci=T(()=>{On();Yl();_e();nn();Fg();Ye()});async function Tr(e,t=Bk,r,n){let o={checks:[],issues:0},i="Preparing diagnostics",s=()=>r?.({active:i,checks:[...o.checks]}),a=(f)=>{i=f,s()},c=(f)=>{if(o.checks.push(f),f.severity==="error")o.issues+=1;s()};if(a("Google CLI installed"),await t.hasCommand("gcloud"))c({name:"Google CLI installed",severity:"ok",message:"gcloud found"});else c({name:"Google CLI installed",severity:ni(e)?"error":"warn",message:"gcloud not installed",hint:"install the Google Cloud CLI from https://cloud.google.com/sdk/docs/install"});a("Google environment");let l=await t.detectGoogle(e.google.project_id);if(l.adcAvailable)c({name:"Google authentication available",severity:"ok",message:"Application Default Credentials found"});else c({name:"Google authentication available",severity:ni(e)?"error":"warn",message:"ADC unavailable",hint:"run `gcloud auth application-default login`"});if(l.projectID!=="")c({name:"Project configured",severity:"ok",message:`${l.projectID} (source: ${l.projectSource})`});else c({name:"Project configured",severity:ni(e)?"error":"warn",message:"no Google project configured",hint:"set google.project_id in .devctl/config.yaml"});if(ni(e)||Object.values(e.services).some((f)=>f.capabilities.includes("google")||f.identity.type!=="")){a("Live Google access");let f=!0,h=(y)=>{if(f)c(y)};try{await di((async()=>{await Gk(e,h,t,l.userEmail),await Wk(e,h,t)})(),t.liveDeadlineMs??jk)}catch(y){h({name:"Live Google probes",severity:"warn",message:H(y),hint:"network or timeout \u2014 retry when online"})}finally{f=!1}}for(let f of e.doctor.tools){let h=f.command||f.name;if(a(`${f.name} installed`),await t.hasCommand(h))c({name:`${f.name} installed`,severity:"ok",message:`${h} found`});else c({name:`${f.name} installed`,severity:"error",message:`${h} not found`,hint:`install ${f.name} and ensure it is on PATH`})}if(a("Repository configuration"),n?.repositoryConfigError!==void 0)if(n.repositoryConfigError==="")c({name:"Repository configuration",severity:"ok",message:"valid"});else c({name:"Repository configuration",severity:"error",message:n.repositoryConfigError});else try{let f=Ut(e);if(f.length>0)c({name:"Repository configuration",severity:"error",message:f.join("; ")});else c({name:"Repository configuration",severity:"ok",message:"valid"})}catch(f){c({name:"Repository configuration",severity:"error",message:H(f)})}let g={};for(let[f,h]of Object.entries(e.services))for(let y of h.ports){if(y.auto)continue;let b=`Port ${y.value}`;if(a(b),g[y.value])c({name:b,severity:"error",message:`configured on both ${g[y.value]} and ${f}`});else{g[y.value]=f;let w=n?.services?.[f];if(Boolean(w&&w.pid>0&&Object.values(w.ports).includes(y.value)))c({name:b,severity:"ok",message:`in use by running service ${f}`});else if(await t.portAvailable(y.value))c({name:b,severity:"ok",message:"available"});else c(await Gg(b,y.value,`services.${f}.ports`))}}if(e.proxy.listen.port>0){let f=`Port ${e.proxy.listen.port}`;if(a(f),n?.proxyRunning)c({name:f,severity:"ok",message:"in use by the running proxy"});else if(await t.portAvailable(e.proxy.listen.port))c({name:f,severity:"ok",message:"proxy listen port available"});else c(await Gg(f,e.proxy.listen.port,"proxy.listen.port"))}return i="Diagnostics complete",s(),o}async function Wk(e,t,r){let n=e.google.project_id,o=r.hasLocalAdc??oi;if(n===""||!o())return;let i=r.probeServiceUsage??qg,s=[{name:"IAM Credentials API",service:"iamcredentials.googleapis.com"},{name:"Resource Manager API",service:"cloudresourcemanager.googleapis.com"},{name:"IAP API",service:"iap.googleapis.com"}];(await Promise.allSettled(s.map((c)=>di(i(n,c.service),li)))).forEach((c,l)=>{let d=s[l];if(!d)return;if(c.status==="fulfilled"){t({name:d.name,severity:c.value?"ok":"warn",message:c.value?"enabled":"not enabled or unreachable",hint:c.value?void 0:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`});return}t({name:d.name,severity:"warn",message:H(c.reason),hint:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`})})}async function Ug(){if(!td)td=Promise.resolve().then(() => (ci(),Bg)).then(({TokenManager:e,googleTokenProviders:t})=>new e(60000,t(),void 0,Ns("file")));return td}async function Kg(e,t){await(await Ug()).get(e,t,[])}async function qg(e,t){let r=await Ug(),n=await di(r.get("user","",[]),li),o=`https://serviceusage.googleapis.com/v1/projects/${e}/services/${t}`,i=await fetch(o,{headers:{Authorization:`Bearer ${n.accessToken}`},signal:AbortSignal.timeout(li)});if(!i.ok)return!1;return(await i.json().catch(()=>{return}))?.state==="ENABLED"}async function Gk(e,t,r,n){let o=Er(e),i=e.proxy.routes.filter((g)=>g.auth.type.toLowerCase()==="iap"),s=i.filter((g)=>g.auth.audience.trim()!=="");for(let g of i)if(g.auth.audience.trim()==="")t({name:`IAP audience ${g.name}`,severity:"error",message:"missing audience",hint:"set auth.audience to the IAP OAuth client ID"});if(o.length===0&&s.length===0)return;if(!(r.hasLocalAdc??oi)())return;let c=r.mintToken??Kg,l=o.map(async(g)=>{try{await di(c(`sa:${g}`,""),li),t({name:`Impersonate ${g}`,severity:"ok",message:"token minted"})}catch(f){let h=(r.adcQuotaProject??Nl)(),y=n||"the ADC principal",b=h===""?"unknown":h,w=Wg(`Impersonate ${g}`,f,`grant roles/iam.serviceAccountTokenCreator to ${y} on ${g}; ADC quota project: ${b}`);if(h!==""&&w.message.toLowerCase().includes("api is not enabled"))w.message=`IAM Credentials API is disabled in ADC quota project ${h}`,w.hint=`enable iamcredentials.googleapis.com in ${h}, or set the ADC quota project to ${e.google.project_id}`;else if(w.message.toLowerCase()==="google authentication failed")w.message=`access-token mint failed: ${y} \u2192 ${g}`,w.hint=`verify roles/iam.serviceAccountTokenCreator for ${y} on this service account; ADC quota project: ${b}`;t(w)}}),d=s.map(async(g)=>{let f=Wn(g.auth).kind===tn?`sa:${Wn(g.auth).serviceAccount}`:"user";try{await di(c(f,g.auth.audience),li),t({name:`IAP ${g.name}`,severity:"ok",message:"id token minted"})}catch(h){t(Wg(`IAP ${g.name}`,h,"check IAP OAuth client ID and ADC"))}});await Promise.all([...l,...d])}function Wg(e,t,r){let n=H(t),o=n.toLowerCase();if(o.includes("timeout")||o.includes("network")||o.includes("econnrefused")||o.includes("enotfound"))return{name:e,severity:"warn",message:n,hint:"network or timeout \u2014 retry when online"};if(t instanceof Te&&t.hint!==""){let i=`${t.kind}: `,s=t.message.startsWith(i)?t.message.slice(i.length):t.message;return{name:e,severity:"error",message:s,hint:t.hint}}return{name:e,severity:"error",message:n,hint:r}}function di(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("timeout")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}async function Gg(e,t,r){let n=await Vn(t);if(!n)return{name:e,severity:"error",message:"already in use",hint:`stop the process using port ${t} or change ${r}`};if(n.pid===process.pid)return{name:e,severity:"error",message:`in use by this TUI (${n.command} pid ${n.pid})`,hint:"stop the proxy from the proxy screen (x), then rerun doctor"};return{name:e,severity:"error",message:`in use by ${n.command} (pid ${n.pid})`,hint:"enter stop that process after a confirmation",action:{kind:"free-port",holder:n}}}function Ks(e){let t=[`${Pt()} doctor`,""];for(let r of e.checks){let n=r.severity==="error"?"\u2717":r.severity==="warn"?"!":"\u2713";if(t.push(`${n} ${r.name}`),r.severity!=="ok"){if(t.push(` ${r.message}`),r.hint)t.push(` \u2192 ${r.hint}`)}}return t.push("",`${e.issues} issue(s) found.`),t.join(`
|
|
3
|
+
var Vb=Object.defineProperty;var Jb=(e)=>e;function Yb(e,t){this[e]=Jb.bind(null,t)}var as=(e,t)=>{for(var r in t)Vb(e,r,{get:t[r],enumerable:!0,configurable:!0,set:Yb.bind(t,r)})};var A=(e,t)=>()=>(e&&(t=e(e=0)),t);var zb=import.meta.require;var In=A(()=>{if(process.env.METADATA_SERVER_DETECTION===void 0)process.env.METADATA_SERVER_DETECTION="bios-only";if(process.env.GCE_METADATA_TIMEOUT===void 0)process.env.GCE_METADATA_TIMEOUT="0"});function Wp(e,t=""){if(t===jp)return!0;return e.includes(jp)||e.startsWith(Xb)}function cs(){if(Bp)return;Bp=!0;let e=process.emitWarning.bind(process);process.emitWarning=(t,...r)=>{let n=Zb(r[0]),o=Qb(t);if(Wp(o,n))return;e(t,...r)}}function Gp(){let e=process.stderr.write.bind(process.stderr);return process.stderr.write=(t,r,n)=>{let o=ew(t);if(Wp(o)){let i=typeof r==="function"?r:typeof n==="function"?n:void 0;if(typeof i==="function")i();return!0}if(typeof r==="function")return e(t,r);return e(t,r,n)},()=>{process.stderr.write=e}}function Qb(e){if(typeof e==="string")return e;if(e instanceof Error)return e.message;return String(e)}function Zb(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&"type"in e&&typeof e.type==="string")return e.type;return""}function ew(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return new TextDecoder().decode(e);return""}var jp="MetadataLookupWarning",Xb="received unexpected error =",Bp=!1;var Bc=A(()=>{In()});function M(e,t){return new Te(e,t)}function ye(e,t,r){let n=r instanceof Error?r:Error(String(r));return new Te(e,t,{cause:n})}function we(e,t,r,n=""){return new Te(e,t,{hint:r,service:n})}function us(e,t){return e instanceof Te&&e.kind===t}function qp(e){if(e instanceof Te)return e.exitCode();return 1}function Vp(e){if(e instanceof Te)return{error:H(e),kind:e.kind,hint:e.hint,service:e.service};return{error:H(e)}}function Jp(e){if(typeof e==="string")return M("general",e);if(e.kind)return new Te(e.kind,e.error.replace(`${e.kind}: `,""),{hint:e.hint,service:e.service});return M("general",e.error)}function H(e){if(e instanceof Te){if(e.hint!=="")return`${Up(e)} \u2014 ${e.hint}`;return Up(e)}if(e instanceof Error)return e.message;return String(e)}function Up(e){let t=`${e.kind}: `;if(e.message.startsWith(t)){let r=e.message.slice(t.length),n=e.causeError?`: ${e.causeError.message}`:"";if(n!==""&&r.endsWith(n))return r.slice(0,r.length-n.length);return r}return e.message}var X="configuration",Kr="configuration_missing",ls="service_not_found",Kp="dependency",bt="process_start",$n="authentication",qr="authorization",ir="token",ds="impersonation",Wc="iap",_r="proxy",Gc="health_check",nt="general",Te;var _e=A(()=>{Te=class Te extends Error{kind;hint;service;causeError;constructor(e,t,r){super(r?.cause?`${e}: ${t}: ${r.cause.message}`:`${e}: ${t}`);this.name="DevctlError",this.kind=e,this.hint=r?.hint??"",this.service=r?.service??"",this.causeError=r?.cause}exitCode(){switch(this.kind){case"configuration":case"configuration_missing":case"service_not_found":case"dependency":return 2;case"authentication":case"token":case"iap":return 3;case"authorization":case"impersonation":return 4;case"process_start":return 5;case"health_check":return 6;case"proxy":return 7;default:return 1}}}});import{spawnSync as tw}from"child_process";import{createHash as rw,randomBytes as qc}from"crypto";import{copyFileSync as nw,existsSync as Pr,mkdirSync as ow,readdirSync as iw,readFileSync as Vc,renameSync as Jc,statSync as sw,unlinkSync as Uc,writeFileSync as aw}from"fs";import{homedir as cw}from"os";import{basename as lw,dirname as Kc,join as st,resolve as dw}from"path";function Lt(){let e=process.env.DEVCTL_HOME;if(e&&e!=="")return e;return st(cw(),".devctl")}function Gt(e){ow(e,{recursive:!0,mode:uw})}function Go(e){let t=dw(e),r=process.platform==="win32"?t.toLowerCase():t;return rw("sha256").update(r).digest("hex").slice(0,fw)}function Fn(e){let t=st(Lt(),"state",Go(e)),r=st(Lt(),"sessions",Go(e));if(!Pr(t)&&Pr(r)){Gt(Kc(t));try{Jc(r,t)}catch{Gt(t);for(let n of["state.json","devctl.lock","devctl.sock"]){let o=st(r,n);if(Pr(o))nw(o,st(t,n))}}}return Gt(t),t}function ps(){let e=st(Lt(),"logs");return Gt(e),e}function Vr(){let e=st(Lt(),"exports");return Gt(e),e}function It(){let e=st(Lt(),"credentials");return Gt(e),e}function fs(e,t=process.platform){if(t==="win32")return`\\\\.\\pipe\\devctl-${Go(e)}`;return st(Fn(e),"devctl.sock")}function gw(e){return st(Fn(e),"devctl.lock")}function Yp(e){return st(Fn(e),"state.json")}function Uo(e){return st(Fn(e),"bootstrap.log")}function Xp(e){let t=Uo(e);if(!Pr(t))return;let r=Fn(e),n=st(r,`${zp}${Yc()}.log`);try{Jc(t,n)}catch{return}hw(r)}function hw(e){let t;try{t=iw(e).filter((n)=>n.startsWith(zp)&&n.endsWith(".log"))}catch{return}let r=t.map((n)=>{let o=st(e,n);try{return{path:o,mtime:sw(o).mtimeMs}}catch{return}}).filter((n)=>n!==void 0).sort((n,o)=>o.mtime-n.mtime);for(let n=mw;n<r.length;n++)try{Uc(r[n].path)}catch{}}function $t(e,t){Gt(Kc(e));let r=st(Kc(e),`.${lw(e)}.tmp-${process.pid}-${qc(4).toString("hex")}`);aw(r,t,{mode:pw}),Jc(r,e)}function Yc(e=new Date){return`${e.toISOString().slice(0,19).replace(/:/g,"-")+"Z"}-${qc(3).toString("hex")}`}function gs(e){let t=e.indexOf("Z-"),r=t>=0?e.slice(0,t+1):e,n=r.indexOf("T");if(n<0||!r.endsWith("Z"))return;let o=r.slice(0,n),i=r.slice(n+1,-1).replace(/-/g,":"),s=new Date(`${o}T${i}Z`);return Number.isNaN(s.getTime())?void 0:s}function Ko(e){return zc(Yp(e))}function zc(e){if(!Pr(e))return;try{let t=JSON.parse(Vc(e,"utf8"));if(Array.isArray(t.processes)&&typeof t.repo_root==="string")return t;return}catch{return}}function Qp(e,t){$t(Yp(e),`${JSON.stringify(t,null,2)}
|
|
4
|
+
`)}function Zp(e,t){let r=gw(e);if(Pr(r)){let n=yw(r);if(n&&Pt(n.pid))throw Error(`supervisor already running (pid ${n.pid})`);try{Uc(r)}catch{}}return $t(r,JSON.stringify({pid:process.pid,socket:t})),{release:()=>{try{Uc(r)}catch{}}}}function yw(e){if(!Pr(e))return;try{let t=JSON.parse(Vc(e,"utf8"));if(typeof t.pid==="number"&&typeof t.socket==="string")return{pid:t.pid,socket:t.socket}}catch{return}return}function Pt(e){if(e<=0)return!1;if(process.platform==="win32")return vw(e);try{return process.kill(e,0),!0}catch{return!1}}function Xc(e){try{let t=tw("cmd.exe",["/d","/c",`tasklist /FO CSV /NH /FI "PID eq ${e}"`],{encoding:"buffer",windowsHide:!0,timeout:5000});return xw(t.stdout)}catch{return""}}function vw(e){try{return process.kill(e,0),!0}catch{}let t=Xc(e).toLowerCase();if(t===""||t.includes("no tasks")||t.includes("no matching"))return!1;return t.includes(String(e))}function xw(e){if(!e)return"";if(typeof e==="string")return e;if(e.length>=2&&e[0]===255&&e[1]===254)return e.toString("utf16le");if(e.length>=4&&e[1]===0&&e[3]===0)return e.toString("utf16le");return e.toString("utf8")}function Qc(){return qc(24).toString("hex")}function bw(e){return st(Fn(e),"mcp-token")}function ef(e){let t=bw(e);if(Pr(t)){let n=Vc(t,"utf8").trim();if(n!=="")return n}let r=Qc();return $t(t,r),r}var uw=448,pw=384,fw=16,mw=5,zp="bootstrap-";var Ye=()=>{};function hs(){return{args:[],shell:!1}}function el(){return{vars:{},required:[],defaults:{}}}function tl(){return{type:"",url:"",address:"",command:hs(),interval_seconds:0,timeout_seconds:0}}function rl(){return{type:"",mode:"",service_account:""}}function Hn(){return{extends:"",description:"",command:hs(),shell:!1,working_dir:"",dependencies:[],ports:[],environment:el(),health:tl(),identity:rl(),logs:{stdout:!1,stderr:!1},restart:{policy:"",max_retries:0,backoff_seconds:0},startup:{wait_for_healthy:!1,timeout_seconds:0},capabilities:[],proxy:[]}}function Jr(){return{version:1,project:{name:""},google:{project_id:"",region:""},profiles:{},templates:{},services:{},proxy:{enabled:!1,listen:{host:"127.0.0.1",port:0},token_endpoint:{enabled:!1,host:"",port:0},routes:[]},logs:{max_memory_events:50000,persistence:{enabled:!0,directory:"~/.devctl/logs",retention_days:14,max_session_logs:0}},auth:{refresh_threshold_seconds:300},shutdown:{grace_seconds:10},ui:{theme:"system",keymap:{}},secrets:{extra_markers:[],extra_patterns:[]},doctor:{tools:[]},plugins:[],environment:{sources:[],secrets:{}},repoRoot:"",configPath:""}}function nl(e){return e.args.length===0||e.args.length===1&&(e.args[0]??"").trim()===""}function qo(e){if(e.type!=="")return e.type;return e.mode}function ar(e){let t=qo(e).toLowerCase();return t==="service"||t==="service_account"}function of(e){let t=qo(e).toLowerCase();return t==="user"||t===""}function sf(e){if(e.policy!==""){if(e.policy==="always"||e.policy==="on_failure"||e.policy==="never")return e.policy;return e.policy}if(e.enabled===!0)return"on_failure";return"never"}function Yr(e){let t=e.host===""?"127.0.0.1":e.host;if(e.port===0)return t;return`${t}:${e.port}`}function ys(e){if(e.refresh_threshold_seconds<=0)return 300;return e.refresh_threshold_seconds}function vs(e){if(e.stop_services_on_exit===void 0)return!0;return e.stop_services_on_exit}function xs(e){if(e.grace_seconds<=0)return 10;return e.grace_seconds}function af(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stdout}function cf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stderr}function ol(e,t){return e.find((r)=>r.name===t)}function lf(e){return e[0]}var Nn=1,tf="never",rf="on_failure",nf="always",ms=8080,Zc="127.0.0.1";function G(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function sl(e){return G(e)?new Set(Object.keys(e)):new Set}function V(e){if(typeof e==="string")return e;if(typeof e==="number"||typeof e==="boolean")return String(e);return""}function Ve(e){if(typeof e==="number")return e;if(typeof e==="string"){let t=Number(e);return Number.isNaN(t)?0:t}return 0}function ft(e){return e===!0}function Dt(e){if(!Array.isArray(e))return[];return e.map((t)=>V(t))}function Xr(e){if(!G(e))return{};let t={};for(let[r,n]of Object.entries(e))t[r]=V(n);return t}function Vo(e){if(typeof e==="string")return{args:e.split(/\s+/).filter((t)=>t!==""),shell:!1};if(Array.isArray(e))return{args:e.map((t)=>V(t)),shell:!1};return hs()}function al(e){if(e===void 0||e===null)return[];if(typeof e==="string"||typeof e==="number")return[il(e,"http")];if(Array.isArray(e))return e.map((t,r)=>il(t,`port_${r}`));if(G(e))return Object.entries(e).map(([t,r])=>il(r,t));return[]}function il(e,t){if(typeof e==="string"&&e.toLowerCase()==="auto")return{name:t,value:0,auto:!0};return{name:t,value:Ve(e),auto:!1}}function ww(e){if(!G(e))return el();let t={},r=[],n={};for(let[o,i]of Object.entries(e))if(o==="required")r=Dt(i);else if(o==="defaults")n=Xr(i);else t[o]=V(i);return{vars:t,required:r,defaults:n}}function Sw(e){if(!G(e))return rl();return{type:V(e.type),mode:V(e.mode),service_account:V(e.service_account)}}function kw(e){if(!G(e))return tl();return{type:V(e.type),url:V(e.url),address:V(e.address),command:Vo(e.command),interval_seconds:Ve(e.interval_seconds),timeout_seconds:Ve(e.timeout_seconds)}}function Cw(e){if(!G(e))return{policy:"",max_retries:0,backoff_seconds:0};return{enabled:e.enabled===void 0?void 0:ft(e.enabled),policy:V(e.policy),max_retries:Ve(e.max_retries),backoff_seconds:Ve(e.backoff_seconds)}}function _w(e){if(!G(e))return{wait_for_healthy:!1,timeout_seconds:0};return{wait_for_healthy:ft(e.wait_for_healthy),timeout_seconds:Ve(e.timeout_seconds)}}function Jo(e){if(!G(e))return Hn();let t=G(e.logs)?e.logs:{};return{extends:V(e.extends),description:V(e.description),command:Vo(e.command),shell:ft(e.shell),working_dir:V(e.working_dir),dependencies:Dt(e.dependencies),ports:al(e.ports),environment:ww(e.environment),health:kw(e.health),identity:Sw(e.identity),logs:{stdout:ft(t.stdout),stderr:ft(t.stderr)},restart:Cw(e.restart),startup:_w(e.startup),capabilities:Dt(e.capabilities),proxy:cl(e.proxy)}}function cl(e){if(e===void 0||e===null)return[];if(Array.isArray(e))return e.map((t)=>zr(t));if(G(e))return[zr(e)];return[]}function bs(e){if(!G(e))return{services:[],environment:{}};return{services:Dt(e.services),environment:Xr(e.environment)}}function Pw(e){if(typeof e==="string")return{type:e,service_account:""};if(!G(e))return{type:"",service_account:""};return{type:V(e.type),service_account:V(e.service_account)}}function Rw(e){if(!G(e))return{type:"",identity:{type:"",service_account:""},audience:"",service_account:""};return{type:V(e.type),identity:Pw(e.identity),audience:V(e.audience),service_account:V(e.service_account)}}function zr(e){if(!G(e))return{name:"",match:{host:"",path:""},upstream:{url:""},auth:{type:"",identity:{type:"",service_account:""},audience:"",service_account:""}};let t=G(e.match)?e.match:{},r=G(e.upstream)?e.upstream:{};return{name:V(e.name),match:{host:V(t.host),path:V(t.path)},upstream:{url:V(r.url)},auth:Rw(e.auth)}}var ll=()=>{};import{existsSync as Ew,statSync as uf}from"fs";import{basename as df,dirname as ws,isAbsolute as Tw,join as Ss,resolve as pf}from"path";function Rr(e,t){if(t!=="")return Aw(t);let r=e===""?process.cwd():e;r=Tw(r)?r:pf(r);for(;;){let n=Ss(r,wt,Ft);if(Yo(n))return{repoRoot:r,configPath:n};let o=Ss(r,"devctl.yaml");if(Yo(o))return{repoRoot:r,configPath:o};let i=ws(r);if(i===r)break;r=i}throw we(Kr,"no devctl configuration found","run `devctl setup` or create a .devctl/config.yaml in the repository root")}function Aw(e){let t=pf(e),r;try{r=uf(t)}catch(o){throw ye(Kr,"config path not found",o)}if(r.isDirectory()){if(df(t)===wt)return{repoRoot:ws(t),configPath:Ss(t,Ft)};return{repoRoot:t,configPath:Ss(t,Ft)}}let n=ws(t);if(df(n)===wt)n=ws(n);return{repoRoot:n,configPath:t}}function Yo(e){return Ew(e)&&!uf(e).isDirectory()}var wt=".devctl",Ft="config.yaml";var zo=A(()=>{_e()});function _s(){return{services:{},templates:{}}}function ks(e,t,r){let n=sl(r);if(G(r))for(let i of Lw){let s=r[i];if(G(s))for(let a of Object.keys(s))n.add(`${i}.${a}`)}let o=e[t];e[t]=o?new Set([...o,...n]):n}function ff(e,t,r=_s()){if(t.version!==void 0)e.version=Ve(t.version);if(G(t.project)&&t.project.name!==void 0)e.project.name=V(t.project.name);if(G(t.google)){if(t.google.project_id!==void 0)e.google.project_id=V(t.google.project_id);if(t.google.region!==void 0)e.google.region=V(t.google.region)}if(G(t.profiles))for(let[n,o]of Object.entries(t.profiles)){let i=e.profiles[n];e.profiles[n]=i?Mw(i,o):bs(o)}if(G(t.templates))for(let[n,o]of Object.entries(t.templates)){let i=e.templates[n];e.templates[n]=i?Cs(i,o):Jo(o),ks(r.templates,n,o)}if(G(t.services))for(let[n,o]of Object.entries(t.services)){let i=e.services[n];e.services[n]=i?Cs(i,o):Jo(o),ks(r.services,n,o)}if(G(t.proxy))Dw(e.proxy,t.proxy);if(G(t.logs)){if(t.logs.max_memory_events!==void 0)e.logs.max_memory_events=Ve(t.logs.max_memory_events);if(G(t.logs.persistence)){let n=t.logs.persistence;if(n.enabled!==void 0)e.logs.persistence.enabled=ft(n.enabled);if(n.directory!==void 0)e.logs.persistence.directory=V(n.directory);if(n.retention_days!==void 0)e.logs.persistence.retention_days=Ve(n.retention_days);if(n.max_session_logs!==void 0)e.logs.persistence.max_session_logs=Ve(n.max_session_logs)}}if(G(t.auth)&&t.auth.refresh_threshold_seconds!==void 0)e.auth.refresh_threshold_seconds=Ve(t.auth.refresh_threshold_seconds);if(G(t.shutdown)){if(t.shutdown.stop_services_on_exit!==void 0)e.shutdown.stop_services_on_exit=ft(t.shutdown.stop_services_on_exit);if(t.shutdown.grace_seconds!==void 0)e.shutdown.grace_seconds=Ve(t.shutdown.grace_seconds)}if(G(t.ui)){if(t.ui.theme!==void 0)e.ui.theme=V(t.ui.theme);if(t.ui.keymap!==void 0)e.ui.keymap=Xr(t.ui.keymap)}if(G(t.secrets)){if(t.secrets.extra_markers!==void 0)e.secrets.extra_markers=Dt(t.secrets.extra_markers);if(t.secrets.extra_patterns!==void 0)e.secrets.extra_patterns=Dt(t.secrets.extra_patterns)}if(G(t.doctor)&&Array.isArray(t.doctor.tools))e.doctor.tools=t.doctor.tools.filter(G).map((n)=>({name:V(n.name),command:V(n.command)}));if(Array.isArray(t.plugins))e.plugins=t.plugins.filter(G).map((n)=>({path:V(n.path)})).filter((n)=>n.path!=="");if(G(t.environment)){if(Array.isArray(t.environment.sources))e.environment.sources=Dt(t.environment.sources);if(G(t.environment.secrets))e.environment.secrets={...e.environment.secrets,...Xr(t.environment.secrets)}}}function Dw(e,t){if(t.enabled!==void 0)e.enabled=ft(t.enabled);if(G(t.listen)){if(t.listen.host!==void 0)e.listen.host=V(t.listen.host);if(t.listen.port!==void 0)e.listen.port=Ve(t.listen.port)}if(G(t.token_endpoint)){let r=t.token_endpoint;if(r.enabled!==void 0)e.token_endpoint.enabled=ft(r.enabled);if(r.host!==void 0)e.token_endpoint.host=V(r.host);if(r.port!==void 0)e.token_endpoint.port=Ve(r.port)}if(Array.isArray(t.routes))e.routes=t.routes.map((r)=>zr(r))}function Mw(e,t){if(!G(t))return e;return{services:t.services!==void 0?Dt(t.services):e.services,environment:t.environment!==void 0?{...e.environment,...Xr(t.environment)}:e.environment}}function Cs(e,t){if(!G(t))return e;let r=sl(t),n={...e,environment:Ow(e.environment,t.environment),health:Iw(e.health,t.health),identity:$w(e.identity,t.identity),logs:Fw(e.logs,t.logs),restart:Nw(e.restart,t.restart),startup:Hw(e.startup,t.startup)};if(r.has("extends"))n.extends=V(t.extends);if(r.has("description"))n.description=V(t.description);if(r.has("command"))n.command=Vo(t.command);if(r.has("shell"))n.shell=ft(t.shell);if(r.has("working_dir"))n.working_dir=V(t.working_dir);if(r.has("dependencies"))n.dependencies=Dt(t.dependencies);if(r.has("ports"))n.ports=al(t.ports);if(r.has("capabilities"))n.capabilities=Dt(t.capabilities);if(r.has("proxy"))n.proxy=cl(t.proxy);return n}function Ow(e,t){if(!G(t))return e;let r={...e.vars},n={...e.defaults},o=e.required;for(let[i,s]of Object.entries(t))if(i==="required")o=Dt(s);else if(i==="defaults")Object.assign(n,Xr(s));else r[i]=V(s);return{vars:r,required:o,defaults:n}}function Iw(e,t){if(!G(t))return e;return{type:t.type!==void 0?V(t.type):e.type,url:t.url!==void 0?V(t.url):e.url,address:t.address!==void 0?V(t.address):e.address,command:t.command!==void 0?Vo(t.command):e.command,interval_seconds:t.interval_seconds!==void 0?Ve(t.interval_seconds):e.interval_seconds,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function $w(e,t){if(!G(t))return e;return{type:t.type!==void 0?V(t.type):e.type,mode:t.mode!==void 0?V(t.mode):e.mode,service_account:t.service_account!==void 0?V(t.service_account):e.service_account}}function Fw(e,t){if(!G(t))return e;return{stdout:t.stdout!==void 0?ft(t.stdout):e.stdout,stderr:t.stderr!==void 0?ft(t.stderr):e.stderr}}function Nw(e,t){if(!G(t))return e;return{enabled:t.enabled!==void 0?ft(t.enabled):e.enabled,policy:t.policy!==void 0?V(t.policy):e.policy,max_retries:t.max_retries!==void 0?Ve(t.max_retries):e.max_retries,backoff_seconds:t.backoff_seconds!==void 0?Ve(t.backoff_seconds):e.backoff_seconds}}function Hw(e,t){if(!G(t))return e;return{wait_for_healthy:t.wait_for_healthy!==void 0?ft(t.wait_for_healthy):e.wait_for_healthy,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function gf(e){let t=Object.keys(e.services).sort();for(let r of t){let n=e.services[r]?.proxy??[];if(n.length===0)continue;n.forEach((o,i)=>{let s=n.length===1?r:`${r}-${i+1}`;e.proxy.routes.push({name:s,match:o.match,upstream:o.upstream,auth:o.auth})})}}function mf(e,t=_s()){if(Object.keys(e.templates).length===0)return;let r={};for(let[n,o]of Object.entries(e.services))r[n]=hf(e,o,t.services[n]??new Set,t,{});e.services=r}function hf(e,t,r,n,o){if(t.extends==="")return t;if(o[t.extends])throw Error(`template cycle involving "${t.extends}"`);let i=e.templates[t.extends]??Hn();if(!e.templates[t.extends])throw Error(`service extends unknown template "${t.extends}"`);let s={...o,[t.extends]:!0},a=n.templates[t.extends]??new Set,c=hf(e,i,a,n,s),l=jw(c,t,r);return l.extends=t.extends,l}function jw(e,t,r){let n={...e};if(r.has("extends"))n.extends=t.extends;if(r.has("description"))n.description=t.description;if(r.has("command"))n.command=t.command;if(r.has("shell"))n.shell=t.shell;if(r.has("working_dir"))n.working_dir=t.working_dir;if(r.has("dependencies"))n.dependencies=t.dependencies;if(r.has("ports"))n.ports=t.ports;if(r.has("capabilities"))n.capabilities=t.capabilities;if(r.has("proxy"))n.proxy=t.proxy;return n.health={type:r.has("health.type")?t.health.type:e.health.type,url:r.has("health.url")?t.health.url:e.health.url,address:r.has("health.address")?t.health.address:e.health.address,command:r.has("health.command")?t.health.command:e.health.command,interval_seconds:r.has("health.interval_seconds")?t.health.interval_seconds:e.health.interval_seconds,timeout_seconds:r.has("health.timeout_seconds")?t.health.timeout_seconds:e.health.timeout_seconds},n.identity={type:r.has("identity.type")?t.identity.type:e.identity.type,mode:r.has("identity.mode")?t.identity.mode:e.identity.mode,service_account:r.has("identity.service_account")?t.identity.service_account:e.identity.service_account},n.logs={stdout:r.has("logs.stdout")?t.logs.stdout:e.logs.stdout,stderr:r.has("logs.stderr")?t.logs.stderr:e.logs.stderr},n.restart={enabled:r.has("restart.enabled")?t.restart.enabled:e.restart.enabled,policy:r.has("restart.policy")?t.restart.policy:e.restart.policy,max_retries:r.has("restart.max_retries")?t.restart.max_retries:e.restart.max_retries,backoff_seconds:r.has("restart.backoff_seconds")?t.restart.backoff_seconds:e.restart.backoff_seconds},n.startup={wait_for_healthy:r.has("startup.wait_for_healthy")?t.startup.wait_for_healthy:e.startup.wait_for_healthy,timeout_seconds:r.has("startup.timeout_seconds")?t.startup.timeout_seconds:e.startup.timeout_seconds},n.environment={vars:{...e.environment.vars,...t.environment.vars},defaults:{...e.environment.defaults,...t.environment.defaults},required:r.has("environment.required")?t.environment.required:e.environment.required},n}var Lw;var yf=A(()=>{ll();Lw=["environment","restart","startup","health","logs","identity"]});function dl(e){if(e.version===0)throw M(X,"version is required");if(e.version===Nn)return e;throw M(X,`unsupported config version ${e.version} (expected ${Nn}); no migration is available`)}var ul=A(()=>{_e()});var vf,xf,bf,wf,Sf,kf,Cf,_f,pl,fl,gl,ml,Pf,Rf,Ef,Tf,Af,Lf,Df,Mf,Of,If,$f,Ff,Nf,Hf,jf,Bf,Wf,Gf;var hl=A(()=>{vf=["version","project","google","profiles","templates","services","proxy","logs","auth","shutdown","ui","secrets","doctor","plugins","environment"],xf=["extends","description","command","shell","working_dir","dependencies","ports","environment","health","identity","logs","restart","startup","capabilities","proxy"],bf=["type","url","address","command","interval_seconds","timeout_seconds"],wf=["type","mode","service_account"],Sf=["enabled","policy","max_retries","backoff_seconds"],kf=["wait_for_healthy","timeout_seconds"],Cf=["enabled","listen","token_endpoint","routes"],_f=["host","port"],pl=["name","match","upstream","auth"],fl=["host","path"],gl=["url"],ml=["type","identity","audience","service_account"],Pf=["max_memory_events","persistence"],Rf=["enabled","directory","retention_days","max_session_logs"],Ef=["refresh_threshold_seconds"],Tf=["stop_services_on_exit","grace_seconds"],Af=["theme","keymap"],Lf=["name"],Df=["project_id","region"],Mf=["services","environment"],Of=["required","defaults"],If=["stdout","stderr"],$f=["extra_markers","extra_patterns"],Ff=["tools"],Nf=["name","command"],Hf=["enabled","host","port"],jf=["path"],Bf=["sources","secrets"],Wf=["google","google_api","iap","network","service_identity","local_http"],Gf=["|","||","&&",";",">",">>","<","&"]});function Qr(e,t){if(!Yw(e))return[];let r=Gw(t),n=[];for(let o of Object.keys(e)){let i=Jw(t,o);if(r.length>0&&!r.includes(o)&&!Ww(t))n.push(i);n.push(...Qr(e[o],i))}return n}function Ww(e){if(e==="services"||e==="profiles"||e==="templates")return!0;if(e.endsWith(".environment")||e.endsWith(".defaults")||e.endsWith(".keymap"))return!0;return e.includes(".environment.")&&!e.endsWith(".environment")}function Gw(e){switch(e){case"":return vf;case"project":return Lf;case"google":return Df;case"proxy":return Cf;case"proxy.listen":return _f;case"proxy.token_endpoint":return Hf;case"logs":return Pf;case"logs.persistence":return Rf;case"auth":return Ef;case"shutdown":return Tf;case"ui":return Af;case"secrets":return $f;case"doctor":return Ff;case"environment":return Bf;default:return Uw(e)}}function Uw(e){if(e==="services"||e==="profiles"||e==="templates")return[];if(e.startsWith("services.")||e.startsWith("templates."))return Kw(e);if(e.startsWith("profiles.")){if(e.split(".").length===2)return Mf}if(e.includes("routes"))return Vw(e);if(e.startsWith("doctor.tools")&&e.split(".").length>=3)return Nf;if(e==="plugins")return[];if(e.startsWith("plugins.")&&e.split(".").length===2)return jf;return[]}function Kw(e){let t=e.split(".");if(t.length===2)return xf;if(t.length>=3)switch(t[2]){case"health":return bf;case"identity":return wf;case"restart":return Sf;case"startup":return kf;case"logs":return If;case"environment":return Of;case"proxy":return qw(t);default:return[]}return[]}function qw(e){let t=e.slice(3),r=t[0]!==void 0&&/^\d+$/.test(t[0])?1:0,n=t[r]??"";if(n==="match")return fl;if(n==="upstream")return gl;if(n==="auth")return ml;return pl}function Vw(e){if(e==="proxy.routes")return[];if(e.endsWith(".match"))return fl;if(e.endsWith(".upstream"))return gl;if(e.endsWith(".auth"))return ml;if(e.includes("proxy.routes")&&e.split(".").length===Bw+1)return pl;return[]}function Jw(e,t){if(e==="")return t;return`${e}.${t}`}function Yw(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function jn(e){return`unknown fields: ${e.join(", ")}`}var Bw=2;var Uf=A(()=>{hl()});function Kf(e,t,r){let n=e,o="";for(;;){let i=n.indexOf("${");if(i<0)return o+n;o+=n.slice(0,i);let s=n.slice(i).indexOf("}");if(s<0)throw Error(`unclosed environment reference in "${e}"`);let a=n.slice(i+2,i+s);o+=zw(a,t,r),n=n.slice(i+s+1)}}function zw(e,t,r){let n=e.split(".");if(n.length<3||n[0]!=="services")throw Error(`unsupported reference \${${e}}`);let o=n[1]??"",i=t.services[o];if(!i)throw Error(`reference \${${e}}: unknown service`);let s=r[o];if(n[2]==="port"){if(s){if(s.http!==void 0)return String(s.http);let c=Object.values(s)[0];if(c!==void 0)return String(c)}let a=lf(i.ports);if(a&&!a.auto)return String(a.value)}if(n[2]==="ports"){let a=n[3];if(!a)throw Error(`reference \${${e}}: missing port name`);if(s&&s[a]!==void 0)return String(s[a]);let c=ol(i.ports,a);if(c&&!c.auto)return String(c.value);let l=Number.parseInt(a,10);if(!Number.isNaN(l)&&l>=0&&l<i.ports.length){let d=i.ports[l];if(d&&!d.auto)return String(d.value)}}throw Error(`unresolvable reference \${${e}}`)}function yl(e,t,r){let n={};for(let[o,i]of Object.entries(e))n[o]=Kf(i,t,r);return n}function qf(e){let t=[],r=e;for(;;){let n=r.indexOf("${");if(n<0)return t;let o=r.slice(n).indexOf("}");if(o<0)return t;t.push(r.slice(n+2,n+o)),r=r.slice(n+o+1)}}function Vf(e,t){let r=e.split(".");if(r.length<2)return!1;if(r[0]!=="services"||r.length<3)return!1;let n=t.services[r[1]??""];if(!n)return!1;if(r[2]==="port"||r[2]==="ports"){if(r.length===3)return n.ports.length>0;if(r.length>=4){let o=r[3]??"";if(!Number.isNaN(Number.parseInt(o,10)))return!0;return ol(n.ports,o)!==void 0}}return!0}var vl=()=>{};function wl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=n.health.type;if(o!==""&&!zf.includes(o.toLowerCase()))t.push({service:r,type:o})}return t}function Ut(e){let t=[];if(e.version===0)t.push("version is required");else if(e.version!==Nn)t.push(`unsupported config version ${e.version} (expected ${Nn}); no migration is available`);if(Object.keys(e.services).length===0)t.push("at least one service must be defined");if(t.push(...Qw(e)),t.push(...rS(e)),t.push(...oS(e)),t.push(...iS(e)),e.logs.max_memory_events<0)t.push("logs.max_memory_events must be >= 0");return t}function Qw(e){let t=[],r={};for(let[n,o]of Object.entries(e.services)){let i=`services.${n}`;if(nl(o.command))t.push(`${i}.command is required`);t.push(...aS(i,o.command,o.shell)),t.push(...cS(i,o.capabilities));for(let c of o.dependencies){if(!e.services[c])t.push(`${i}.dependencies: unknown service "${c}"`);if(c===n)t.push(`${i}.dependencies: service cannot depend on itself`)}if(o.extends!==""&&!e.templates[o.extends])t.push(`${i}.extends: unknown template "${o.extends}"`);for(let c of o.ports.filter((l)=>!l.auto))if(c.value<bl||c.value>xl)t.push(`${i}.ports.${c.name}: invalid port ${c.value}`);else if(r[c.value])t.push(`duplicate port ${c.value} used by ${r[c.value]} and ${n}`);else r[c.value]=n;let s=tS(`${i}.identity`,o.identity,e.plugins.length>0);if(s!=="")t.push(s);t.push(...Zw(i,o,e.plugins.length>0));let a=sf(o.restart);if(a!==tf&&a!==rf&&a!==nf)t.push(`${i}.restart.policy must be never, on_failure, or always`);t.push(...nS(`${i}.environment`,o.environment,e))}return t}function Zw(e,t,r){let n=[];if(t.health.type==="")return n;let o=t.health.type.toLowerCase();if(!zf.includes(o)&&!r)n.push(`${e}.health.type must be http, tcp, process, or command`);if(o==="http"&&t.health.url==="")n.push(`${e}.health.url is required for http health checks`);if(o==="tcp"&&t.health.address===""&&t.ports.length===0)n.push(`${e}.health.address is required for tcp health checks without ports`);if(o==="command"&&nl({args:t.health.command.args,shell:!1}))n.push(`${e}.health.command is required for command health checks`);return n}function tS(e,t,r){let n=qo(t).toLowerCase();if(n===""||n==="user")return"";if(n==="service"||n==="service_account"){if(t.service_account==="")return`${e}.service_account is required for service identity`;if(!t.service_account.includes("@"))return`${e}.service_account must be an email`;return""}if(r)return"";return`${e}.type must be user or service_account`}function Sl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=qo(n.identity).toLowerCase();if(!eS.includes(o))t.push({service:r,type:o})}return t}function rS(e){let t={},r=[],n=[],o=(i)=>{let s=t[i]??Xw;if(s===Yf)return;if(s===Jf){r.push(`dependency cycle: ${[...n,i].join(" \u2192 ")}`);return}t[i]=Jf,n.push(i);let a=e.services[i];if(a){for(let c of a.dependencies)if(e.services[c])o(c)}n.pop(),t[i]=Yf};for(let i of Object.keys(e.services))o(i);return r}function nS(e,t,r){let n=[],o=(i,s)=>{for(let a of qf(s))if(!Vf(a,r))n.push(`${e}.${i}: unresolvable reference \${${a}}`)};for(let[i,s]of Object.entries(t.vars))o(i,s);for(let[i,s]of Object.entries(t.defaults))o(i,s);return n}function oS(e){let t=[];for(let[r,n]of Object.entries(e.profiles))for(let o of n.services)if(!e.services[o])t.push(`profiles.${r} references unknown service "${o}"`);return t}function iS(e){let t=[];if(e.proxy.listen.host!==""&&!lS(e.proxy.listen.host))t.push("proxy.listen.host must be an IP address or localhost");if(e.proxy.enabled&&e.proxy.listen.port===0)t.push("proxy.listen.port is required when proxy.enabled is true");if(e.proxy.listen.port!==0&&(e.proxy.listen.port<bl||e.proxy.listen.port>xl))t.push("proxy.listen.port is invalid");let r={};return e.proxy.routes.forEach((n,o)=>{let i=`proxy.routes[${o}]`;if(n.name==="")t.push(`${i}.name is required`);else if(r[n.name])t.push(`${i}: duplicate route name ${n.name}`);if(r[n.name]=!0,n.upstream.url==="")t.push(`${i}.upstream.url is required`);if(n.auth.type.toLowerCase()==="iap"){if(n.auth.audience.trim()==="")t.push(`${i}.auth.audience is required when auth.type is iap`);if(n.auth.identity.type.trim()==="")t.push(`${i}.auth.identity.type is required when auth.type is iap`)}let s=n.auth.identity.type.toLowerCase();if(s==="service"||s==="service_account"||ar({type:s,mode:"",service_account:""})){if((n.auth.identity.service_account||n.auth.service_account)==="")t.push(`${i}.auth.identity.service_account is required`)}}),t.push(...sS(e)),t}function sS(e){let t=[],r=e.proxy.token_endpoint;if(!r.enabled)return t;let n=r.host||Zc;if(n==="0.0.0.0")t.push("proxy.token_endpoint.host must be a loopback address");else if(n!==""&&n!==Zc&&n!=="localhost"&&!n.startsWith("127."))t.push("proxy.token_endpoint.host must be a loopback address");if(r.port!==0&&(r.port<bl||r.port>xl))t.push("proxy.token_endpoint.port is invalid");return t}function aS(e,t,r){if(t.shell||r)return[];for(let n of t.args)if(Gf.includes(n)||n.includes("|")||n.includes(";")||n.includes("&&"))return[`${e}.command contains shell metacharacters; set shell: true to run via a shell`];return[]}function cS(e,t){let r=[];for(let n of t)if(!Wf.includes(n))r.push(`${e}.capabilities: unknown capability "${n}"`);return r}function lS(e){if(e==="localhost")return!0;return dS(e)}function dS(e){if(/^(\d{1,3}\.){3}\d{1,3}$/.test(e))return e.split(".").every((r)=>{let n=Number(r);return n>=0&&n<=255});return e.includes(":")}var xl=65535,bl=1,zf,Xw=0,Jf=1,Yf=2,eS;var Ps=A(()=>{hl();vl();zf=["http","tcp","process","command"];eS=["","user","service","service_account"]});import{readdirSync as uS,readFileSync as pS}from"fs";import{basename as Qf,dirname as fS,extname as gS,join as Zr,resolve as mS}from"path";import{parse as hS}from"yaml";function Bn(e,t,r){try{return Qo(e,t,{candidateText:r}),[]}catch(n){if(n instanceof Te){let o=`${n.kind}: `;return[n.message.startsWith(o)?n.message.slice(o.length):n.message]}return[n instanceof Error?n.message:String(n)]}}function gt(e,t){let{repoRoot:r,configPath:n}=Rr(e,t);return Qo(r,n)}function Xo(e,t){try{return gt(e,t)}catch(r){if(!us(r,Kr))throw r;let n=e===""?process.cwd():mS(e),o=Jr();return o.repoRoot=n,o.configPath=Zr(n,wt,Ft),o}}function Qo(e,t,r){let n=Jr(),o=_s();Zf(t,n,o,r?.candidateText),n.repoRoot=e,n.configPath=t;let i=fS(t);if(Qf(i)===wt)vS(i,n,o);n=yS(n,e,t,o),n=dl(n);try{mf(n,o)}catch(a){throw ye(X,"template merge failed",a)}gf(n);let s=Ut(n);if(s.length>0)throw M(X,s.join(`
|
|
5
|
+
`));return n}function yS(e,t,r,n){let o=Zr(Lt(),"config.local.yaml"),i=Zr(t,wt,"config.local.yaml");for(let s of[o,i]){if(s===r||!Yo(s))continue;Zf(s,e,n)}return e}function Zf(e,t,r,n){let o=n!==void 0?eg(n,e):kl(e),i=Qr(o,"");if(i.length>0)throw M(X,jn(i));ff(t,o,r)}function vS(e,t,r){Xf(Zr(e,"services"),(o,i)=>{let s=Qr(i,`services.${o}`);if(s.length>0)throw M(X,jn(s));let a=t.services[o];t.services[o]=a?Cs(a,i):Jo(i),ks(r.services,o,i)}),Xf(Zr(e,"profiles"),(o,i)=>{let s=Qr(i,`profiles.${o}`);if(s.length>0)throw M(X,jn(s));t.profiles[o]=bs(i)});let n=Zr(e,"proxy","routes.yaml");if(Yo(n))xS(n,t)}function xS(e,t){let r=kl(e);if(G(r.proxy)){let n=Qr({proxy:r.proxy},"");if(n.length>0)throw M(X,jn(n))}if(Array.isArray(r.routes))r.routes.forEach((n,o)=>{let i=Qr(n,`proxy.routes.${o}`);if(i.length>0)throw M(X,jn(i))});if(G(r.proxy)){if(Array.isArray(r.proxy.routes))t.proxy.routes.push(...r.proxy.routes.map((n)=>zr(n)));if(G(r.proxy.listen)){if(typeof r.proxy.listen.host==="string"&&r.proxy.listen.host!=="")t.proxy.listen.host=r.proxy.listen.host;if(typeof r.proxy.listen.port==="number"&&r.proxy.listen.port!==0)t.proxy.listen.port=r.proxy.listen.port}}if(Array.isArray(r.routes))t.proxy.routes.push(...r.routes.map((n)=>zr(n)))}function Xf(e,t){let r;try{r=uS(e)}catch(n){if(bS(n))return;throw n}for(let n of r){let o=gS(n);if(o!==".yaml"&&o!==".yml")continue;let i=Zr(e,n),s=kl(i);t(Qf(n,o),s)}}function kl(e){let t;try{t=pS(e,"utf8")}catch(r){throw ye(X,"unable to read config",r)}return eg(t,e)}function eg(e,t){let r;try{r=hS(e)}catch(n){throw ye(X,`invalid YAML in ${t}`,n)}if(r===null||r===void 0)return{};if(!G(r))throw M(X,`unable to decode config: ${t} is not a mapping`);return r}function bS(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var tg=A(()=>{_e();Ye();ll();zo();yf();ul();Uf();Ps();zo();Ps()});var St=A(()=>{tg();zo();Ps();ul();vl()});import{readdirSync as wS}from"fs";import{join as rg,resolve as Cl,sep as _l}from"path";function SS(e){let t=rg(Lt(),"state"),r;try{r=wS(t)}catch{return}let n=ng(Cl(e)),o;for(let i of r){let s=zc(rg(t,i,"state.json"));if(!s)continue;let a=ng(Cl(s.repo_root));if(!kS(a,n))continue;if(!o||a.length>o.length)o=a}return o}function Rs(e,t,r=""){if(t!=="")return{repoRoot:Cl(t),source:"explicit"};let n=e===""?process.cwd():e;try{let{repoRoot:i}=Rr(n,r);return{repoRoot:i,source:"config"}}catch{if(r!=="")return}let o=SS(n);return o?{repoRoot:o,source:"state-scan"}:void 0}function ng(e){let t=e.length>1&&e.endsWith(_l)?e.slice(0,-1):e;return process.platform==="win32"?t.toLowerCase():t}function kS(e,t){return t===e||t.startsWith(e.endsWith(_l)?e:`${e}${_l}`)}var og=A(()=>{zo();Ye()});import{existsSync as sg,readFileSync as ag}from"fs";import{isAbsolute as CS,join as Rl}from"path";import{parse as _S}from"dotenv";function ES(){return{name:"dotenv",load:(e)=>{let t=ig(e.repoRoot,e.profile);if(e.workDir!=="")Object.assign(t,ig(e.workDir,e.profile));return t}}}function El(e){return async(t)=>{let r=t.includes("/versions/")?t:`${t}/versions/latest`,n=await e(),o=await fetch(`https://secretmanager.googleapis.com/v1/${r}:access`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)throw M(X,`secret manager request failed for ${t}: HTTP ${o.status}`);let i=await o.json();if(!i.payload?.data)throw M(X,`secret manager response for ${t} had no payload`);return Buffer.from(i.payload.data,"base64").toString("utf8")}}function TS(e){let t=e?.environment.sources??[];if(t.length===0)return[...Pl];let r=new Set([...RS,...t]),n=new Set(Pl),o=t.filter((s)=>!n.has(s)),i=[];for(let s of Pl){if(s==="defaults")i.push(...o);if(r.has(s))i.push(s)}return i}async function Tl(e,t){let r={},n=t.serviceCfg.working_dir;if(n!==""&&!CS(n))n=Rl(e,n);let o={repoRoot:e,profile:t.profile,service:t.service,serviceCfg:t.serviceCfg,workDir:n,cfg:t.cfg},i=AS(t),s={process:t.clientEnv??Es(),profile:Zo(t.profileEnv,t.cfg,i),dotenv:Zo(await ES().load(o),t.cfg,i),generated:{},keychain:t.sourceValues?.keychain??LS(o),secret_manager:t.sourceValues?.secret_manager??await DS(o,t.fetchSecret),defaults:Zo(t.serviceCfg.environment.defaults,t.cfg,i),vars:Zo(t.serviceCfg.environment.vars,t.cfg,i),runtime:t.runtime};for(let a of TS(t.cfg)){if(s[a]!==void 0){Object.assign(r,s[a]);continue}let c=t.pluginSources?.find((l)=>l.name===a);if(c)Object.assign(r,Zo(await c.load(o),t.cfg,i))}for(let a of t.serviceCfg.environment.required)if((r[a]??"").trim()==="")throw M(X,`service ${t.service} missing required environment variable ${a}`);return r}function AS(e){let t={};if(e.cfg)for(let[r,n]of Object.entries(e.cfg.services)){let o={};for(let i of n.ports)if(!i.auto)o[i.name]=i.value;t[r]=o}if(e.assignedPorts)t[e.service]=e.assignedPorts;return t}function Zo(e,t,r){if(!t||Object.keys(e).length===0)return e;return yl(e,t,r)}function LS(e){let t=e.cfg?.environment.sources??[];if(t.length>0&&!t.includes("keychain"))return{};let r={},n=new Set([...Object.keys(e.serviceCfg.environment.defaults),...Object.keys(e.serviceCfg.environment.vars),...e.serviceCfg.environment.required]);for(let o of n){let i=Rl(It(),"env",o);if(!sg(i))continue;try{r[o]=ag(i,"utf8").replace(/\n$/,"")}catch(s){throw ye(X,`unable to read keychain env ${o}`,s)}}return r}async function DS(e,t){if(!(e.cfg?.environment.sources??[]).includes("secret_manager"))return{};let n=e.cfg?.environment.secrets??{},o={};for(let[i,s]of Object.entries(n)){if(!PS.test(s))throw M(X,`environment.secrets.${i} is not a Secret Manager resource`);if(!t)throw M(X,"environment source secret_manager is not configured \u2014 set credentials or remove it from environment.sources");o[i]=await t(s)}return o}function ig(e,t){let r={},n=[".env",".env.development",".env.local"];if(t!=="")n.push(`.env.${t}`);for(let o of n){let i=Rl(e,o);if(!sg(i))continue;try{let s=_S(ag(i));Object.assign(r,s)}catch(s){throw ye(X,`unable to read ${i}`,s)}}return r}function Es(){let e={};for(let[t,r]of Object.entries(process.env))if(r!==void 0)e[t]=r;return e}function Al(e,t,r,n,o){let i={DEVCTL_SERVICE_NAME:e,DEVCTL_ENVIRONMENT:o,SERVICE_HOST:t};if(n!=="")i.DEVCTL_PROXY_URL=n;if(r.http!==void 0)i.SERVICE_PORT=String(r.http);else{let s=Object.values(r)[0];if(s!==void 0)i.SERVICE_PORT=String(s)}for(let[s,a]of Object.entries(r))i[`${s.toUpperCase()}_PORT`]=String(a);return i}function ei(e){return{...process.env,...e}}var Pl,PS,RS;var Ll=A(()=>{St();_e();Ye();Pl=["process","profile","dotenv","generated","keychain","secret_manager","defaults","vars","runtime"],PS=/^projects\/[^/]+\/secrets\/[^/]+(?:\/versions\/[^/]+)?$/,RS=["process","defaults","vars","runtime"]});function Rt(){return"devctl 0.1.5"}var at="0.1.5",ti=1;import{createConnection as MS}from"net";var{spawn:OS}=globalThis.Bun;function HS(e){if(e.legacy)return"attached daemon predates the client/daemon compatibility handshake";return`attached daemon speaks RPC protocol ${e.daemonProtocol??"unknown"}; this client speaks ${ti}`}function jS(e){if(e.compatible&&e.daemonVersion!==void 0&&e.daemonVersion!==at)return`attached daemon is devctl ${e.daemonVersion}; this client is ${at} (run \`devctl down\` then start again to update it)`;return}function Dl(e,t){if(!e.compat.compatible&&!NS.has(t))throw we(nt,HS(e.compat),"run `devctl down` to stop it, then start again")}class lg{socket;buf="";pending=new Map;listeners=[];nextID=0;compat={compatible:!0,legacy:!1};session="";constructor(e){this.socket=e,e.on("data",(t)=>{this.buf+=t.toString("utf8");let r=this.buf.split(`
|
|
6
|
+
`);this.buf=r.pop()??"";for(let n of r){if(n.trim()==="")continue;this.onLine(n)}}),e.on("error",(t)=>this.rejectPending(t instanceof Error?t:Error(String(t)))),e.on("close",()=>this.rejectPending(Error("supervisor connection closed")))}onLine(e){let t;try{t=JSON.parse(e)}catch{return}if(t.event){for(let n of this.listeners)n(t.event);return}let r=t.id?this.pending.get(t.id):void 0;if(!r)return;if(this.pending.delete(t.id??""),clearTimeout(r.timer),t.error){r.reject(Jp({error:t.error,kind:t.kind,hint:t.hint,service:t.service}));return}r.resolve(t.result)}onEvent(e){return this.listeners.push(e),()=>{let t=this.listeners.indexOf(e);if(t>=0)this.listeners.splice(t,1)}}call(e,t,r=FS){this.nextID+=1;let n=String(this.nextID);return new Promise((o,i)=>{let s=setTimeout(()=>{this.pending.delete(n),i(Error(`${e} timed out after ${r}ms`))},r);this.pending.set(n,{resolve:o,reject:i,timer:s}),this.socket.write(JSON.stringify({id:n,method:e,params:t})+`
|
|
7
|
+
`)})}close(){this.rejectPending(Error("supervisor connection closed")),this.socket.destroy()}rejectPending(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}}function dg(e,t){let r=fs(e),n=Date.now()+t;return new Promise((o,i)=>{let s=()=>{let a=MS(r);a.once("connect",()=>{let c=new lg(a);BS(c).finally(()=>o(c))}),a.once("error",(c)=>{if(a.destroy(),Date.now()>=n){i(we(nt,"supervisor is not running","run `devctl start` or `devctl attach` after starting services"));return}setTimeout(s,IS)})};s()})}async function BS(e){let t;try{t=await e.call("ping",null,cg)}catch{return}let r=WS(t)?t:{};if(typeof r.session==="string")e.session=r.session;let n=typeof r.protocol==="number"?r.protocol:void 0,o=typeof r.version==="string"?r.version:void 0;if(n===void 0){e.compat={compatible:!1,legacy:!0,daemonVersion:o};return}e.compat={compatible:n===ti,legacy:!1,daemonVersion:o,daemonProtocol:n}}function WS(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}async function en(e){try{return await dg(e,$S)}catch{return}}function GS(e,t,r,n){return r?[e,...n]:[e,t,...n]}async function ug(e,t){let r=await en(e);if(r)return r;Xp(e);let n=Uo(e),o=GS(process.execPath,process.argv[1]??"",Bun.isStandaloneExecutable===!0,["--config",t,"_supervisor","--repo",e]);OS({cmd:o,env:process.env,stdout:"ignore",stderr:Bun.file(n),stdin:"ignore",detached:!0}).unref();try{return await dg(e,cg)}catch{throw we(nt,"supervisor failed to start",`see ${n} for details`)}}class Ts{cfg;client;constructor(e){this.cfg=e}async start(e){return await this.call("start",{...e,client_env:Es()})}async stop(e){await this.call("stop",{services:e})}async restart(e,t){await this.call("restart",{services:e,cascade:t===!0,client_env:Es()})}async status(){return await this.call("status",null)}async refreshAuth(){return await this.call("auth_refresh",null)}async configSnapshot(){return await this.call("config_snapshot",null)}async logs(e){return(await this.call("logs",e)).events??[]}async logsPage(e){return await this.call("logs_page",e)}async logsStats(e){return await this.call("logs_stats",e)}async proxyStart(){await this.call("proxy_start",null)}async proxyStop(){await this.call("proxy_stop",null)}async mcpStart(e){await this.call("mcp_start",e??null)}async mcpStop(){await this.call("mcp_stop",null)}async mcpSetTools(e){return(await this.call("mcp_set_tools",{disabled:[...e]})).disabled_tools??[]}async reload(){return await this.call("reload",null)}async invalidateAuth(){await this.call("auth_invalidate",null)}onEvent(e){if(this.client)return this.client.onEvent(e);return()=>{return}}async close(e){if(!this.client)return;try{if(e?.shutdownSupervisor===!0&&e.detach!==!0){let t=Math.max(5000,this.cfg.shutdown.grace_seconds*1000+2000);await this.client.call("shutdown",{stop_services:!0},t)}}finally{this.client.close()}}async call(e,t){if(!this.client)throw ye(nt,"supervisor is not running",Error("no client"));return Dl(this.client,e),this.client.call(e,t)}}function ri(e){let t=e&&jS(e.compat);if(t)process.stderr.write(`warning: ${t}
|
|
8
|
+
`)}async function Ml(e,t,r=""){let n=Rs(e,t,r);if(!n)throw we(nt,"no devctl configuration found","run `devctl setup`, create a .devctl/config.yaml in the repository root, or pass --repo");let o=await en(n.repoRoot);return ri(o),{repoRoot:n.repoRoot,client:o}}async function Mt(e,t,r,n){let o=n?.allowMissingConfig===!0?Xo(e,t):gt(e,t),i=new Ts(o);if(!r)return i.client=await en(o.repoRoot),ri(i.client),i;return i.client=await ug(o.repoRoot,o.configPath),ri(i.client),i}async function pg(e){let t=new Ts(Jr());return t.client=e,ri(t.client),t.cfg=await t.configSnapshot(),t}async function fg(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(!n)throw we(nt,"supervisor is not running","run `devctl start` before `devctl attach`");return pg(n)}async function gg(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(n)return pg(n);let o=gt(e,t),i=new Ts(o);return i.client=await ug(o.repoRoot,o.configPath),ri(i.client),i.cfg=await i.configSnapshot(),i}var IS=50,cg=8000,$S=200,FS=30000,NS;var Ol=A(()=>{St();og();Ll();_e();Ye();NS=new Set(["logs","logs_page","logs_stats"])});function Ls(e){if(ar(e))return Nt({kind:tn,serviceAccount:e.service_account});if(of(e)&&(e.type!==""||e.mode!==""))return Nt({kind:As});return Nt({kind:Wn})}function rn(e){if(e.type.toLowerCase()==="none")return Nt({kind:Wn});let t=e.identity.type.toLowerCase(),r=e.identity.service_account||e.service_account;if(t==="service"||t==="service_account"||e.type==="service_account")return Nt({kind:tn,serviceAccount:r});if(e.type.toLowerCase()==="iap"&&t==="")return Nt({kind:Wn});if(e.type===""&&t==="")return Nt({kind:Wn});return Nt({kind:As})}function Ds(e){return e.kind===As||e.kind===tn}function Gn(e){if(e.kind===tn)return`sa:${e.serviceAccount}`;if(e.email!=="")return`user:${e.email}`;return"user"}function Nt(e={}){return{kind:Wn,email:"",serviceAccount:"",project:"",projectSource:"",adcAvailable:!1,...e}}function Il(e){let t=new Map,r=(n,o)=>{if(n!=="")t.set(n,(t.get(n)??!1)||o)};for(let n of Object.values(e.services))if(ar(n.identity)&&n.identity.service_account!=="")r(n.identity.service_account,!0);for(let n of e.proxy.routes){let o=n.auth.type.toLowerCase(),i=n.auth.identity.type.toLowerCase(),s=n.auth.identity.service_account||n.auth.service_account;if(i==="service"||i==="service_account"||o==="service_account")r(s,o!=="none")}return[...t.entries()].map(([n,o])=>({email:n,active:o})).sort((n,o)=>n.email.localeCompare(o.email))}function Er(e){return Il(e).filter((t)=>t.active).map((t)=>t.email)}function mg(e,t,r){let n=[];for(let o of t){let i=e.services[o];if(!i)continue;let s=Ls(i.identity);if(ar(i.identity)&&i.identity.service_account===""){n.push({name:o,message:"service account identity is not configured"});continue}if((Ds(s)||i.capabilities.some((c)=>c==="google_api"||c==="iap"||c==="service_identity"))&&!r)n.push({name:o,message:"ADC unavailable"})}return n}function ni(e){if(Er(e).length>0)return!0;if(e.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap"))return!0;return Object.values(e.services).some((t)=>{if(Ds(Ls(t.identity)))return!0;return t.capabilities.some((r)=>r==="google_api"||r==="iap"||r==="service_identity")})}function $l(){return{name:"user",accepts:(e)=>!ar(e),resolve:async(e,t)=>{if(e.type===""&&e.mode==="")return Nt({kind:Wn});return{...await t(),kind:As}}}}function Fl(){return{name:"service_account",accepts:(e)=>ar(e),resolve:async(e,t)=>{if(e.service_account==="")throw M(ds,"service account identity is not configured");return{...await t(),kind:tn,serviceAccount:e.service_account}}}}async function hg(e,t,r){if(r)for(let n=r.length-1;n>=0;n-=1){let o=r[n];if(o?.accepts(e))return o.resolve(e,t)}if(ar(e))return Fl().resolve(e,t);return $l().resolve(e,t)}var As="user",tn="service_account",Wn="none";var nn=A(()=>{St();_e()});import{existsSync as Ms,readFileSync as US}from"fs";import{homedir as vg}from"os";import{join as Nl}from"path";var{spawn:Hl}=globalThis.Bun;function Kn(){let e=globalThis;if(e.window&&typeof e.window.fetch!=="function")e.window.fetch=fetch}function jl(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS||Nl(vg(),".config","gcloud","application_default_credentials.json");if(!Ms(e))return"";try{let t=JSON.parse(US(e,"utf8"));return typeof t.quota_project_id==="string"?t.quota_project_id:""}catch{return""}}async function Ht(e){let t={gcloudInstalled:await Bl("gcloud"),adcAvailable:!1,userEmail:"",projectID:"",projectSource:""};if(e!=="")t.projectID=e,t.projectSource="configuration";else{let r=XS("GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_PROJECT");if(r!=="")t.projectID=r,t.projectSource="environment variable";else if(t.gcloudInstalled){let n=await yg("core/project");if(n!=="")t.projectID=n,t.projectSource="gcloud configuration"}}if(oi())try{await kg(VS(t),qS)}catch(r){t.adcAvailable=!1,t.error=qn(r)}if(t.userEmail===""&&t.gcloudInstalled)t.userEmail=await yg("core/account");return t}async function VS(e){Kn();let{GoogleAuth:t}=await import("google-auth-library"),r=new t({scopes:[KS]});await r.getClient(),e.adcAvailable=!0;let n=await r.getProjectId().catch(()=>"");if(e.projectID===""&&n)e.projectID=n,e.projectSource="application default credentials";let o=await JS(r);if(o!=="")e.userEmail=o}async function JS(e){try{let t=await e.getCredentials();if(t.client_email)return t.client_email}catch{}try{let t=await e.getClient(),r=typeof t.credentials?.id_token==="string"?t.credentials.id_token:"";if(r!==""){let n=YS(r);if(n!=="")return n}}catch{return""}return""}function YS(e){let t=e.split(".");if(t.length<2||!t[1])return"";try{let r=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));return typeof r.email==="string"?r.email:""}catch{return""}}async function bg(e){let t=await Ht(e);return Nt({kind:"user",email:t.userEmail,project:t.projectID,projectSource:t.projectSource,adcAvailable:t.adcAvailable})}async function Os(){if(await Hl({cmd:["gcloud","auth","application-default","login"],stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited!==0)throw we($n,"application-default login failed","run `gcloud auth application-default login`")}async function wg(){if(await Hl({cmd:["gcloud","auth","application-default","revoke","--quiet"],stdout:"ignore",stderr:"pipe"}).exited!==0)throw we($n,"failed to revoke application-default credentials","run `gcloud auth application-default revoke`")}function qn(e){let t=zS(e).toLowerCase();if(Un(t,["unauth","invalid_grant","token has been expired","expired"]))return we($n,"credential expired or invalid","run `devctl auth login` or `gcloud auth application-default login`");if(Un(t,["api has not been used","has not been enabled","access not configured","service_disabled"]))return we(qr,"required Google API is not enabled","enable the API in the target service account project; devctl will not enable APIs automatically");if(Un(t,["permission","forbidden","iam"])){if(Un(t,["serviceaccounttoken","iamcredentials","token creator","getaccesstoken"]))return we(ds,"cannot impersonate service account","ask an administrator to grant roles/iam.serviceAccountTokenCreator on the target service account");return we(qr,"authorization failure","verify IAM permissions for the current user on this project")}if(t.includes("audience"))return we(Wc,"IAP audience is incorrect","set auth.audience on the proxy route to the IAP OAuth client ID");if(t.includes("iap"))return ye(Wc,"IAP authentication failure",e);if(t.includes("project"))return we(X,"wrong or missing Google project","set google.project_id in .devctl/config.yaml");if(Un(t,["timeout","network","connection refused","no such host"]))return ye(nt,"network problem reaching Google Cloud",e);if(Un(t,["adc","default credentials","could not find"]))return we($n,"application default credentials unavailable","run `gcloud auth application-default login`");return ye($n,"Google authentication failed",e)}function zS(e){let t=[],r=new Set,n=(o,i)=>{if(o===null||o===void 0||i>8||r.has(o))return;if(typeof o==="string"){t.push(o);return}if(typeof o!=="object")return;r.add(o);let s=o;for(let a of["message","reason","status","code","error_description","permission","service"])n(s[a],i+1);for(let a of["error","errors","details","response","data","cause","metadata"]){let c=s[a];if(Array.isArray(c))c.forEach((l)=>n(l,i+1));else n(c,i+1)}};return n(e,0),t.length>0?t.join(" "):String(e)}function Un(e,t){return t.some((r)=>e.includes(r))}function XS(...e){for(let t of e){let r=process.env[t];if(r)return r}return""}async function Bl(e){try{return(await Sg(process.platform==="win32"?["where",e]:["which",e],xg)).code===0}catch{return!1}}function oi(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS;if(e&&Ms(e))return!0;if(Ms(Nl(vg(),".config","gcloud","application_default_credentials.json")))return!0;let t=process.env.APPDATA;return Boolean(t&&Ms(Nl(t,"gcloud","application_default_credentials.json")))}async function yg(e){try{let t=await Sg(["gcloud","config","get-value",e],xg);if(t.code!==0)return"";let r=t.stdout.trim();if(r===""||r==="(unset)")return"";return r}catch{return""}}async function Sg(e,t){let r=Hl({cmd:e,stdout:"pipe",stderr:"ignore",env:{...process.env,CLOUDSDK_CORE_DISABLE_PROMPTS:"1",CLOUDSDK_CORE_DISABLE_USAGE_REPORTING:"true"}}),n=r.stdout?new Response(r.stdout).text():Promise.resolve("");try{let[o,i]=await kg(Promise.all([n,r.exited]),t);return{code:i??1,stdout:o}}catch{return r.kill(),{code:1,stdout:""}}}function kg(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("timeout")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}var KS="https://www.googleapis.com/auth/cloud-platform",xg=1500,qS=2000;var on=A(()=>{In();_e();nn()});var{spawn:Wl}=globalThis.Bun;import{createServer as Cg}from"net";async function _g(e,t,r={}){let n={};for(let[i,s]of Object.entries(r))for(let a of Object.values(s))n[a]=i;let o={};for(let[i,s]of Object.entries(e.services)){if(t.length>0&&!t.includes(i))continue;let a={};for(let c of s.ports){let l=r[i]?.[c.name],d=l&&l>=Gl?l:c.value;if(l===void 0&&c.auto)d=await ZS();if(d<Gl||d>QS)throw new Te(X,`invalid port ${d} on service ${i}`,{service:i});if(n[d]&&n[d]!==i)throw new Te(X,`duplicate port ${d} used by ${n[d]} and ${i}`,{service:i});if(l!==d&&!c.auto&&!await Vn(d))throw await ek(i,c.name,d);n[d]=i,a[c.name]=d}o[i]=a}return o}function ZS(){return new Promise((e,t)=>{let r=Cg();r.listen(0,"127.0.0.1",()=>{let n=r.address();r.close(()=>{if(n&&typeof n==="object")e(n.port);else t(ye(X,"unable to allocate dynamic port",Error("no address")))})}),r.on("error",(n)=>t(ye(X,"unable to allocate dynamic port",n)))})}async function Is(e){let t=e.ports.filter((n)=>!n.auto&&n.value>=Gl);if(t.length===0)return;let r={};for(let n of t){if(await Vn(n.value))return;r[n.name]=n.value}return r}function Vn(e){return new Promise((t)=>{let r=Cg();r.listen(e,"127.0.0.1",()=>{r.close(()=>t(!0))}),r.on("error",()=>t(!1))})}async function ek(e,t,r){let n=await Jn(r);return tk(e,t,r,n)}function tk(e,t,r,n){let o=t===""?`${e} port`:`${e} ports.${t}`;if(n&&n.pid===process.pid)return we(bt,`${e} blocked: this TUI already holds port ${r}`,`Stop the proxy from the Proxy screen, or change ${o} in .devctl.`,e);if(n)return we(bt,`${e} blocked: ${n.command} (pid ${n.pid}) is using port ${r}`,`Open Doctor and press enter to free port ${r}, or change ${o} in .devctl.`,e);return we(bt,`${e} blocked: port ${r} is already in use`,`Something is listening on ${r}. Open Doctor to free it, or change ${o} in .devctl.`,e)}function rk(e,t){let r=e.split(`
|
|
9
|
+
`).filter((n)=>n.trim()!==""&&!n.startsWith("COMMAND"));for(let n of r){let o=n.trim().split(/\s+/),i=o[0]??"",s=Number(o[1]);if(i!==""&&Number.isInteger(s)&&s>0)return{port:t,pid:s,command:i}}return}async function Jn(e){if(process.platform==="win32")return ok(e);let t=Wl({cmd:["lsof","-nP",`-iTCP:${e}`,"-sTCP:LISTEN"],stdout:"pipe",stderr:"ignore"}),r=await new Response(t.stdout).text();await t.exited;let n=rk(r,e);if(n)return n;let o=Wl({cmd:["fuser","-n","tcp",String(e)],stdout:"pipe",stderr:"pipe"}),i=`${await new Response(o.stdout).text()} ${await new Response(o.stderr).text()}`;await o.exited;let s=i.match(/(\d+)/),a=s?Number(s[1]):0;if(!Number.isInteger(a)||a<=0)return;return{port:e,pid:a,command:"process"}}function nk(e,t){for(let r of e.split(`
|
|
10
|
+
`)){if(!r.includes("LISTENING")&&!r.includes("LISTEN"))continue;if(!r.includes(`:${t}`)&&!r.includes(` ${t} `))continue;let n=r.trim().match(/(\d+)\s*$/),o=n?Number(n[1]):0;if(Number.isInteger(o)&&o>0)return{port:t,pid:o,command:"process"}}return}async function ok(e){let t=Wl({cmd:["netstat","-ano"],stdout:"pipe",stderr:"ignore"}),r=t.stdout?await new Response(t.stdout).text():"";return await t.exited,nk(r,e)}async function $s(e){if(e.pid===process.pid)throw we(bt,`port ${e.port} is held by this TUI`,"stop the proxy from the proxy screen, or quit the TUI");try{process.kill(e.pid,"SIGTERM")}catch(t){throw ye(bt,`could not stop pid ${e.pid} on port ${e.port}`,t)}await sk(ik);try{process.kill(e.pid,0),process.kill(e.pid,"SIGKILL")}catch{return}}function sk(e){return new Promise((t)=>{setTimeout(t,e)})}var QS=65535,Gl=1,ik=400;var ii=A(()=>{_e()});var{spawn:Vl}=globalThis.Bun;import{existsSync as Ns,readdirSync as ak,readFileSync as Pg,unlinkSync as ck}from"fs";import{join as si}from"path";function ql(e){return si(It(),`${js(e)}${Kl}`)}function Hs(e){if(e==="file"||process.env.DEVCTL_HOME&&e!=="keychain")return new Fs;if(e==="keychain"||process.platform==="darwin"||process.platform==="win32"||process.platform==="linux")return new Rg(new Fs);return new Fs}class Fs{backend="file";async get(e){let t=pk(e);if(!t||t.accessToken==="")return;return t}async set(e,t){$t(ql(e),`${JSON.stringify({...uk(t),key:e})}
|
|
11
|
+
`)}async delete(e){let t=ql(e);if(Ns(t))ck(t)}async list(){let e=It();if(!Ns(e))return[];let t=[];for(let r of ak(e)){if(!r.endsWith(Kl))continue;let n=r.slice(0,-Kl.length),o=Eg(si(It(),r));if(!o)continue;t.push(Tg(o.key??n,o.record))}return t.sort((r,n)=>r.identity.localeCompare(n.identity))}}class Rg{backend="keychain";fallback;constructor(e){this.fallback=e}async get(e){let t=await fk(e);if(t)return t;return this.fallback.get(e)}async set(e,t){if(!await gk(e,t))await this.fallback.set(e,t);lk(e)}async delete(e){await mk(e),await this.fallback.delete(e),dk(e)}async list(){let e=new Set(Yl()),t=await this.fallback.list(),r=new Map;for(let n of t)r.set(n.key,n);for(let n of e){let o=await this.get(n);if(o)r.set(n,Tg(n,o))}return[...r.values()].sort((n,o)=>n.identity.localeCompare(o.identity))}}function lk(e){let t=Yl();if(!t.includes(e))$t(si(It(),Jl),`${JSON.stringify([...t,e])}
|
|
12
|
+
`)}function dk(e){let t=Yl(),r=t.filter((n)=>n!==e);if(r.length!==t.length)$t(si(It(),Jl),`${JSON.stringify(r)}
|
|
13
|
+
`)}function Yl(){let e=si(It(),Jl);if(!Ns(e))return[];try{let t=JSON.parse(Pg(e,"utf8"));return Array.isArray(t)?t.filter((r)=>typeof r==="string"):[]}catch{return[]}}function uk(e){return{...e,accessToken:""}}function pk(e){return Eg(ql(e))?.record}function Eg(e){if(!Ns(e))return;try{let t=JSON.parse(Pg(e,"utf8"));if(typeof t.identity!=="string")return;return{key:typeof t.key==="string"&&t.key!==""?t.key:void 0,record:{identity:t.identity,audience:typeof t.audience==="string"?t.audience:"",scopes:Array.isArray(t.scopes)?t.scopes.filter((r)=>typeof r==="string"):[],accessToken:typeof t.accessToken==="string"?t.accessToken:"",tokenType:typeof t.tokenType==="string"?t.tokenType:"Bearer",expiresAt:typeof t.expiresAt==="string"?t.expiresAt:""}}}catch{return}}function Tg(e,t){let r=Date.parse(t.expiresAt);return{key:e,identity:t.identity,audience:t.audience,scopes:t.scopes,expires_at:t.expiresAt,valid:Number.isFinite(r)&&r-Date.now()>0}}function js(e){return e.replace(/[^A-Za-z0-9._-]+/g,"_").slice(0,80)||"token"}async function fk(e){let t=await hk(e);if(!t)return;try{return JSON.parse(t)}catch{return}}async function gk(e,t){let r=JSON.stringify(t);if(process.platform==="darwin")return await Yn(["security","delete-generic-password","-s",sn,"-a",e]),await Yn(["security","add-generic-password","-s",sn,"-a",e,"-w",r,"-U"])===0;if(process.platform==="linux")return await yk(["secret-tool","store","--label",`devctl ${e}`,"service",sn,"account",e],r)===0;if(process.platform==="win32"){let o=`Add-Type -AssemblyName System.Security; $bytes = [Convert]::FromBase64String('${Buffer.from(r,"utf8").toString("base64")}'); $enc = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser'); [IO.File]::WriteAllBytes($env:LOCALAPPDATA + '\\devctl-cred-${js(e)}.bin', $enc)`;return await Yn(["powershell","-NoProfile","-Command",o])===0}return!1}async function mk(e){if(process.platform==="darwin"){await Yn(["security","delete-generic-password","-s",sn,"-a",e]);return}if(process.platform==="linux"){await Yn(["secret-tool","clear","service",sn,"account",e]);return}if(process.platform==="win32")await Yn(["powershell","-NoProfile","-Command",`Remove-Item -ErrorAction SilentlyContinue ($env:LOCALAPPDATA + '\\devctl-cred-${js(e)}.bin')`])}async function hk(e){if(process.platform==="darwin"){let t=await Ul(["security","find-generic-password","-s",sn,"-a",e,"-w"]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="linux"){let t=await Ul(["secret-tool","lookup","service",sn,"account",e]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="win32"){let t=`$p = $env:LOCALAPPDATA + '\\devctl-cred-${js(e)}.bin'; if (-not (Test-Path $p)) { exit 1 }; Add-Type -AssemblyName System.Security; $raw = [IO.File]::ReadAllBytes($p); $dec = [System.Security.Cryptography.ProtectedData]::Unprotect($raw, $null, 'CurrentUser'); [Text.Encoding]::UTF8.GetString($dec)`,r=await Ul(["powershell","-NoProfile","-Command",t]);return r.code===0&&r.stdout!==""?r.stdout:void 0}return}async function Yn(e){try{return await Vl({cmd:e,stdout:"ignore",stderr:"ignore",timeout:zl}).exited}catch{return 1}}async function yk(e,t){try{return await Vl({cmd:e,stdin:new TextEncoder().encode(t),stdout:"ignore",stderr:"ignore",timeout:zl}).exited}catch{return 1}}async function Ul(e){try{let t=Vl({cmd:e,stdout:"pipe",stderr:"ignore",timeout:zl}),r=t.stdout?await new Response(t.stdout).text():"";return{code:await t.exited,stdout:r.trim()}}catch{return{code:1,stdout:""}}}var Jl="keychain-index.json",sn="devctl.credentials",Kl=".cred.json",zl=3000;var Xl=A(()=>{Ye()});function Ae(e,t,r){return{type:e,timestamp:new Date().toISOString(),service:t,payload:r}}class td{subs=new Map;nextID=0;buffer=[];maxBuf;constructor(e){this.maxBuf=e>0?e:1024}subscribe(e,t=[]){this.nextID+=1;let r=this.nextID;return this.subs.set(r,{types:new Set(t),handler:e}),()=>{this.subs.delete(r)}}publish(e){let t=e.timestamp===""?{...e,timestamp:new Date().toISOString()}:e;if(this.buffer.length>=this.maxBuf)this.buffer=this.buffer.slice(1);this.buffer.push(t);for(let r of this.subs.values())if(r.types.size===0||r.types.has(t.type))r.handler(t)}recent(){return[...this.buffer]}}var Ag="ServiceStarted",Ql="ServiceStopped",Lg="ServiceFailed",Dg="ServiceStateChanged",Mg="ServiceHealthChanged",Bs="LogReceived",zn="TokenRefreshed",an="TokenRefreshFailed",Zl="AuthenticationChanged",Og="ProxyStarted",Ig="ProxyStopped",ed="ProxyRequest",Ws="ConfigurationChanged",ai="ConfigurationReloadFailed",$g="SessionRecovered";async function Fg(e,t={}){let r=t.attempts??vk,n=t.backoffMs??xk,o=t.retry??bk,i=Error("retry exhausted");for(let s=0;s<r;s+=1)try{return await e()}catch(a){if(i=a,!o(a)||s===r-1)throw a;await wk(n*(s+1))}throw i}function bk(e){if(e instanceof Te)return e.kind!==X&&e.kind!==qr;return!0}function wk(e){return new Promise((t)=>{setTimeout(t,e)})}var vk=3,xk=200;var Ng=A(()=>{_e()});var Wg={};as(Wg,{TokenManager:()=>Xn,expiresSoonToken:()=>jg,googleTokenProviders:()=>cn,isValidToken:()=>Hg,staticTokenProvider:()=>Dk,tokenCacheKey:()=>rd,tokenMetaPath:()=>Bg});import{createHash as Sk}from"crypto";import{join as kk}from"path";import{GoogleAuth as Us,Impersonated as Ck}from"google-auth-library";function rd(e,t,r){return`${e}|${t}|${r.join(",")}`}function Hg(e,t=nd){if(e.accessToken==="")return!1;return e.expiresAt.getTime()-Date.now()>=t}function jg(e,t=nd){if(e.accessToken==="")return!0;let r=e.expiresAt.getTime()-Date.now();return r>0&&r<t}class Xn{cache=new Map;inflight=new Map;providers;thresholdMs;bus;store;constructor(e,t,r,n){this.thresholdMs=e>0?e:nd,this.providers=[...t],this.bus=r,this.store=n??Hs(process.env.DEVCTL_CREDENTIAL_BACKEND==="file"?"file":void 0)}replaceProviders(e){this.providers.splice(0,this.providers.length,...e)}isValid(e){return Hg(e,this.thresholdMs)}expiresSoon(e){return jg(e,this.thresholdMs)}invalidate(e){if(e===void 0||e===""){this.cache.clear(),this.clearStore();return}this.cache.delete(e),this.store.delete(e)}async listStatus(){return this.store.list()}storeBackend(){return this.store.backend}async get(e,t,r){let n=rd(e,t,r),o=this.cache.get(n)??await this.loadStored(n);if(o&&this.isValid(o))return this.cache.set(n,o),o;return this.refresh(e,t,r)}async refresh(e,t,r){let n=rd(e,t,r),o=this.inflight.get(n);if(o)return o;let i=this.refreshOnce(n,e,t,r);this.inflight.set(n,i);try{return await i}finally{this.inflight.delete(n)}}async refreshOnce(e,t,r,n){let o=this.providers.filter((s)=>!s.accepts||s.accepts(t,r,n));if(o.length===0)throw M(ir,`no token provider accepts identity ${t}`);let i=M(ir,"no token provider available");for(let s of o)try{let a=await Fg(()=>s.fetch(t,r,n),{attempts:Pk,backoffMs:Rk,retry:Wk});return this.cache.set(e,a),Tk(e,a),await this.store.set(e,Ak(a)),this.bus?.publish(Ae(zn,"",{identity:a.identity,audience:a.audience})),a}catch(a){i=a instanceof Error?a:Error(String(a))}throw this.bus?.publish(Ae(an,"",{identity:t,audience:r,error:H(i)})),i}async loadStored(e){let t=await this.store.get(e);if(!t||t.accessToken==="")return;return Lk(t)}async clearStore(){let e=await this.store.list();await Promise.all(e.map((t)=>this.store.delete(t.key)))}}function Bg(e){let t=Sk("sha256").update(e).digest("hex").slice(0,16);return kk(It(),`${t}.json`)}function Tk(e,t){let r={identity:t.identity,audience:t.audience,expires_at:t.expiresAt.toISOString(),scopes:t.scopes};$t(Bg(e),`${JSON.stringify(r)}
|
|
14
|
+
`)}function Ak(e){return{identity:e.identity,audience:e.audience,scopes:e.scopes,accessToken:e.accessToken,tokenType:e.tokenType,expiresAt:e.expiresAt.toISOString()}}function Lk(e){return{accessToken:e.accessToken,tokenType:e.tokenType||"Bearer",expiresAt:new Date(e.expiresAt),audience:e.audience,identity:e.identity,scopes:e.scopes}}function cn(){return[Ik(),Ok(),Mk()]}function Dk(e){return{name:"static",accepts:(t,r)=>(e.identity===""||t===e.identity)&&(e.audience===""||r===e.audience),fetch:async(t,r,n)=>({...e,identity:t,audience:r,scopes:n})}}function Mk(){return{name:"user",accepts:(e,t)=>!e.startsWith("sa:")&&t==="",fetch:async(e,t,r)=>{if(e.startsWith("sa:"))throw M(ir,"user provider cannot mint service-account tokens");return Hk(e,t,r)}}}function Ok(){return{name:"service_account",accepts:(e,t)=>e.startsWith("sa:")&&t==="",fetch:async(e,t,r)=>{if(!e.startsWith("sa:"))throw M(ir,"service-account provider cannot mint user tokens");return $k(e,t,r)}}}function Ik(){return{name:"iap",accepts:(e,t)=>t!=="",fetch:async(e,t,r)=>{if(t==="")throw M(ir,"IAP audience is required");if(e.startsWith("sa:"))return Fk(e,t,r);return Nk(e,t,r)}}}async function $k(e,t,r){let n=e.slice(3);try{Kn();let i=await new Us({scopes:r.length>0?r:[Gs]}).getClient(),s=new Ck({sourceClient:i,targetPrincipal:n,targetScopes:r.length>0?r:[Gs],lifetime:3600}),a=await s.getAccessToken(),c=typeof a==="string"?a:a?.token;if(!c)throw M(ir,"empty impersonated token");return{accessToken:c,tokenType:"Bearer",expiresAt:Ks(c,s),audience:t,identity:e,scopes:r}}catch(o){throw qn(o)}}async function Fk(e,t,r){let n=e.slice(3);try{Kn();let i=await new Us({scopes:[Gs]}).getClient(),s=`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(n)}:generateIdToken`,c=(await i.request({url:s,method:"POST",data:{audience:t,includeEmail:!0}})).data.token;if(!c)throw M(ir,"empty impersonated IAP id token");return{accessToken:c,tokenType:"Bearer",expiresAt:Ks(c),audience:t,identity:e,scopes:r}}catch(o){throw qn(o)}}async function Nk(e,t,r){try{Kn();let i=await(await new Us({scopes:r.length>0?r:[Ek]}).getIdTokenClient(t)).idTokenProvider.fetchIdToken(t);return{accessToken:i,tokenType:"Bearer",expiresAt:Ks(i),audience:t,identity:e,scopes:r}}catch(n){throw qn(n)}}async function Hk(e,t,r){try{Kn();let o=await new Us({scopes:r.length>0?r:[Gs]}).getClient(),i=await o.getAccessToken();if(!i.token)throw M(ir,"empty access token");return{accessToken:i.token,tokenType:"Bearer",expiresAt:jk(o,i.token),audience:t,identity:e,scopes:r}}catch(n){throw qn(n)}}function Ks(e,t){if(t?.credentials?.expiry_date)return new Date(t.credentials.expiry_date);return Bk(e)??new Date(Date.now()+_k)}function jk(e,t){return Ks(t,e)}function Bk(e){let t=e.split(".");if(t.length<2||!t[1])return;try{let r=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));if(typeof r.exp==="number")return new Date(r.exp*1000)}catch{return}return}function Wk(e){if(e instanceof Te)return e.kind!==X&&e.kind!==qr;let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();return t.includes("network")||t.includes("econnreset")||t.includes("etimedout")||t.includes("503")||t.includes("429")}var nd=300000,_k=3000000,Pk=3,Rk=200,Gs="https://www.googleapis.com/auth/cloud-platform",Ek="https://www.googleapis.com/auth/userinfo.email";var ci=A(()=>{In();Xl();_e();on();Ng();Ye()});async function Tr(e,t=Uk,r,n){let o={checks:[],issues:0},i="Preparing diagnostics",s=()=>r?.({active:i,checks:[...o.checks]}),a=(f)=>{i=f,s()},c=(f)=>{if(o.checks.push(f),f.severity==="error")o.issues+=1;s()};if(a("Google CLI installed"),await t.hasCommand("gcloud"))c({name:"Google CLI installed",severity:"ok",message:"gcloud found"});else c({name:"Google CLI installed",severity:ni(e)?"error":"warn",message:"gcloud not installed",hint:"install the Google Cloud CLI from https://cloud.google.com/sdk/docs/install"});a("Google environment");let l=await t.detectGoogle(e.google.project_id);if(l.adcAvailable)c({name:"Google authentication available",severity:"ok",message:"Application Default Credentials found"});else c({name:"Google authentication available",severity:ni(e)?"error":"warn",message:"ADC unavailable",hint:"run `gcloud auth application-default login`"});if(l.projectID!=="")c({name:"Project configured",severity:"ok",message:`${l.projectID} (source: ${l.projectSource})`});else c({name:"Project configured",severity:ni(e)?"error":"warn",message:"no Google project configured",hint:"set google.project_id in .devctl/config.yaml"});if(ni(e)||Object.values(e.services).some((f)=>f.capabilities.includes("google")||f.identity.type!=="")){a("Live Google access");let f=!0,h=(x)=>{if(f)c(x)};try{await di((async()=>{await qk(e,h,t,l.userEmail),await Kk(e,h,t)})(),t.liveDeadlineMs??Gk)}catch(x){h({name:"Live Google probes",severity:"warn",message:H(x),hint:"network or timeout \u2014 retry when online"})}finally{f=!1}}for(let f of e.doctor.tools){let h=f.command||f.name;if(a(`${f.name} installed`),await t.hasCommand(h))c({name:`${f.name} installed`,severity:"ok",message:`${h} found`});else c({name:`${f.name} installed`,severity:"error",message:`${h} not found`,hint:`install ${f.name} and ensure it is on PATH`})}if(a("Repository configuration"),n?.repositoryConfigError!==void 0)if(n.repositoryConfigError==="")c({name:"Repository configuration",severity:"ok",message:"valid"});else c({name:"Repository configuration",severity:"error",message:n.repositoryConfigError});else try{let f=Ut(e);if(f.length>0)c({name:"Repository configuration",severity:"error",message:f.join("; ")});else c({name:"Repository configuration",severity:"ok",message:"valid"})}catch(f){c({name:"Repository configuration",severity:"error",message:H(f)})}let g={};for(let[f,h]of Object.entries(e.services))for(let x of h.ports){if(x.auto)continue;let v=`Port ${x.value}`;if(a(v),g[x.value])c({name:v,severity:"error",message:`configured on both ${g[x.value]} and ${f}`});else{g[x.value]=f;let b=n?.services?.[f];if(Boolean(b&&b.pid>0&&Object.values(b.ports).includes(x.value)))c({name:v,severity:"ok",message:`in use by running service ${f}`});else if(await t.portAvailable(x.value))c({name:v,severity:"ok",message:"available"});else c(await Ug(v,x.value,`services.${f}.ports`))}}if(e.proxy.listen.port>0){let f=`Port ${e.proxy.listen.port}`;if(a(f),n?.proxyRunning)c({name:f,severity:"ok",message:"in use by the running proxy"});else if(await t.portAvailable(e.proxy.listen.port))c({name:f,severity:"ok",message:"proxy listen port available"});else c(await Ug(f,e.proxy.listen.port,"proxy.listen.port"))}return i="Diagnostics complete",s(),o}async function Kk(e,t,r){let n=e.google.project_id,o=r.hasLocalAdc??oi;if(n===""||!o())return;let i=r.probeServiceUsage??Vg,s=[{name:"IAM Credentials API",service:"iamcredentials.googleapis.com"},{name:"Resource Manager API",service:"cloudresourcemanager.googleapis.com"},{name:"IAP API",service:"iap.googleapis.com"}];(await Promise.allSettled(s.map((c)=>di(i(n,c.service),li)))).forEach((c,l)=>{let d=s[l];if(!d)return;if(c.status==="fulfilled"){t({name:d.name,severity:c.value?"ok":"warn",message:c.value?"enabled":"not enabled or unreachable",hint:c.value?void 0:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`});return}t({name:d.name,severity:"warn",message:H(c.reason),hint:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`})})}async function Kg(){if(!od)od=Promise.resolve().then(() => (ci(),Wg)).then(({TokenManager:e,googleTokenProviders:t})=>new e(60000,t(),void 0,Hs("file")));return od}async function qg(e,t){await(await Kg()).get(e,t,[])}async function Vg(e,t){let r=await Kg(),n=await di(r.get("user","",[]),li),o=`https://serviceusage.googleapis.com/v1/projects/${e}/services/${t}`,i=await fetch(o,{headers:{Authorization:`Bearer ${n.accessToken}`},signal:AbortSignal.timeout(li)});if(!i.ok)return!1;return(await i.json().catch(()=>{return}))?.state==="ENABLED"}async function qk(e,t,r,n){let o=Er(e),i=e.proxy.routes.filter((g)=>g.auth.type.toLowerCase()==="iap"),s=i.filter((g)=>g.auth.audience.trim()!=="");for(let g of i)if(g.auth.audience.trim()==="")t({name:`IAP audience ${g.name}`,severity:"error",message:"missing audience",hint:"set auth.audience to the IAP OAuth client ID"});if(o.length===0&&s.length===0)return;if(!(r.hasLocalAdc??oi)())return;let c=r.mintToken??qg,l=o.map(async(g)=>{try{await di(c(`sa:${g}`,""),li),t({name:`Impersonate ${g}`,severity:"ok",message:"token minted"})}catch(f){let h=(r.adcQuotaProject??jl)(),x=n||"the ADC principal",v=h===""?"unknown":h,b=Gg(`Impersonate ${g}`,f,`grant roles/iam.serviceAccountTokenCreator to ${x} on ${g}; ADC quota project: ${v}`);if(h!==""&&b.message.toLowerCase().includes("api is not enabled"))b.message=`IAM Credentials API is disabled in ADC quota project ${h}`,b.hint=`enable iamcredentials.googleapis.com in ${h}, or set the ADC quota project to ${e.google.project_id}`;else if(b.message.toLowerCase()==="google authentication failed")b.message=`access-token mint failed: ${x} \u2192 ${g}`,b.hint=`verify roles/iam.serviceAccountTokenCreator for ${x} on this service account; ADC quota project: ${v}`;t(b)}}),d=s.map(async(g)=>{let f=rn(g.auth).kind===tn?`sa:${rn(g.auth).serviceAccount}`:"user";try{await di(c(f,g.auth.audience),li),t({name:`IAP ${g.name}`,severity:"ok",message:"id token minted"})}catch(h){t(Gg(`IAP ${g.name}`,h,"check IAP OAuth client ID and ADC"))}});await Promise.all([...l,...d])}function Gg(e,t,r){let n=H(t),o=n.toLowerCase();if(o.includes("timeout")||o.includes("network")||o.includes("econnrefused")||o.includes("enotfound"))return{name:e,severity:"warn",message:n,hint:"network or timeout \u2014 retry when online"};if(t instanceof Te&&t.hint!==""){let i=`${t.kind}: `,s=t.message.startsWith(i)?t.message.slice(i.length):t.message;return{name:e,severity:"error",message:s,hint:t.hint}}return{name:e,severity:"error",message:n,hint:r}}function di(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("timeout")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}async function Ug(e,t,r){let n=await Jn(t);if(!n)return{name:e,severity:"error",message:"already in use",hint:`stop the process using port ${t} or change ${r}`};if(n.pid===process.pid)return{name:e,severity:"error",message:`in use by this TUI (${n.command} pid ${n.pid})`,hint:"stop the proxy from the proxy screen (x), then rerun doctor"};return{name:e,severity:"error",message:`in use by ${n.command} (pid ${n.pid})`,hint:"enter stop that process after a confirmation",action:{kind:"free-port",holder:n}}}function qs(e){let t=[`${Rt()} doctor`,""];for(let r of e.checks){let n=r.severity==="error"?"\u2717":r.severity==="warn"?"!":"\u2713";if(t.push(`${n} ${r.name}`),r.severity!=="ok"){if(t.push(` ${r.message}`),r.hint)t.push(` \u2192 ${r.hint}`)}}return t.push("",`${e.issues} issue(s) found.`),t.join(`
|
|
15
15
|
`)+`
|
|
16
|
-
`}var li=4000,
|
|
16
|
+
`}var li=4000,Gk=8000,Uk,od;var ui=A(()=>{In();St();_e();on();nn();ii();Xl();Uk={detectGoogle:Ht,hasCommand:Bl,portAvailable:Vn,hasLocalAdc:oi,adcQuotaProject:jl,mintToken:qg,probeServiceUsage:Vg}});function eo(e){if(e.state===Kt&&e.health===Et)return ln;if(e.state===Kt&&e.health===Le)return Qn;return e.state}function Vs(e){return{name:e,state:Zn,health:jt,pid:0,ports:{},restarts:0,last_error:"",identity:"",startTime:void 0,cpuPercent:void 0,memoryKB:void 0,profile:"",env_source:"daemon",orphaned:!1}}function Yg(e,t){let r={},n={};for(let a of Object.keys(t))r[a]=0;for(let a of Object.keys(t)){let c=e.services[a]?.dependencies??[];for(let l of c){if(!t[l])continue;n[l]=[...n[l]??[],a],r[a]=(r[a]??0)+1}}let o=[],i=Object.keys(t).length,s={};while(i>0){let a=Object.entries(r).filter(([c,l])=>l===0&&!s[c]).map(([c])=>c).sort();if(a.length===0)throw M(Kp,"dependency cycle detected while planning startup");o.push(a);for(let c of a){s[c]=!0,i-=1;for(let l of n[c]??[])r[l]=(r[l]??0)-1}}return o}function ad(e,t){if(!e.services[t])throw M(ls,`unknown service "${t}"`)}function fi(e,t,r){let n={},o=(a)=>{if(n[a])return;ad(e,a),n[a]=!0;for(let c of e.services[a]?.dependencies??[])o(c)};for(let a of t)o(a);let i=Yg(e,n),s=[];return i.forEach((a,c)=>{for(let l of a)s.push({name:l,wave:c+1,dependencies:[...e.services[l]?.dependencies??[]]})}),{profile:r,steps:s,waves:i,blockers:[]}}function cd(e,t){let r={};for(let[i,s]of Object.entries(e.services))for(let a of s.dependencies)r[a]=[...r[a]??[],i];let n={},o=(i)=>{if(n[i])return;ad(e,i),n[i]=!0;for(let s of r[i]??[])o(s)};for(let i of t)o(i);return Object.keys(n)}function zg(e,t){let r=[...Yg(e,t)].reverse().map((o)=>[...o].sort()),n=[];return r.forEach((o,i)=>{for(let s of o)n.push({name:s,wave:i+1,dependencies:e.services[s]?.dependencies??[]})}),{steps:n,waves:r,profile:"",blockers:[]}}function gi(e,t){let r=Object.fromEntries(cd(e,t).map((n)=>[n,!0]));return zg(e,r)}function Xg(e,t){let r={};for(let n of t)ad(e,n),r[n]=!0;return zg(e,r)}function ld(e){let t="";if(e.profile!=="")t+=`Profile: ${e.profile}
|
|
17
17
|
|
|
18
18
|
`;t+=`Plan:
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ var Ub=Object.defineProperty;var Kb=(e)=>e;function qb(e,t){this[e]=Kb.bind(null
|
|
|
21
21
|
`,r+=1;if((e.blockers??[]).length>0){t+=`
|
|
22
22
|
Blocked:
|
|
23
23
|
`;for(let n of e.blockers??[])t+=`- ${n.name}: ${n.message}
|
|
24
|
-
`}return t}function
|
|
24
|
+
`}return t}function Js(e){return`${e.join(", ")} changed and only take effect after a full \`devctl down && devctl start\`, not a reload`}function Vk(e,t,r){let n={};if(t!==""){let o=e.profiles[t];if(!o)throw M("configuration",`unknown profile "${t}"`);Object.assign(n,o.environment)}if(r.length>0)return{services:Jg(e,r),env:n};if(t==="")return{services:Object.keys(e.services),env:n};return{services:Jg(e,e.profiles[t]?.services??[]),env:n}}function Jk(e){return Object.keys(e.profiles).sort()[0]??""}function Ys(e,t){let r=t.services??[],n=t.profile??"";if(r.length===0&&n===""){if(n=t.activeProfile||Jk(e),n==="")throw M(X,"no profile or services given; pass service names or add a profile")}let o=Vk(e,n,r);return{services:o.services,env:o.env,profile:n}}function Jg(e,t){let r={},n=[];for(let o of t){if(r[o])continue;if(!e.services[o])throw M("service_not_found",`unknown service "${o}"`);r[o]=!0,n.push(o)}return n}var id="STARTING",Kt="RUNNING",ln="HEALTHY",Qn="UNHEALTHY",sd="STOPPING",Zn="STOPPED",dn="FAILED",pi="RESTARTING",jt="UNKNOWN",Et="HEALTHY",Le="UNHEALTHY";var un=A(()=>{_e()});var em={};as(em,{createStarterConfig:()=>tC,resolveSetupTarget:()=>Qg,runSetup:()=>fd});import{existsSync as pd,mkdirSync as dd,statSync as Yk,writeFileSync as zk}from"fs";import{createInterface as Xk}from"readline/promises";import{stdin as Qk,stdout as Zk}from"process";import{basename as zs,dirname as ud,join as cr,resolve as eC}from"path";function Qg(e,t){let r=e===""?process.cwd():e;if(t==="")return{repo:r,cfgPath:cr(r,wt,Ft)};let n=eC(t);if(!(pd(n)?Yk(n).isDirectory():!/\.ya?ml$/i.test(n))){let i=ud(n);return{repo:zs(i)===wt?ud(i):i,cfgPath:n}}if(zs(n)===wt)return{repo:ud(n),cfgPath:cr(n,Ft)};return{repo:n,cfgPath:cr(n,wt,Ft)}}function tC(e,t=zs(e),r="",n="",o=!1){let i=cr(e,wt,Ft);if(!o&&pd(i))throw M(X,`configuration already exists at ${i}; not overwriting`);return Zg(e,t,r,n),i}async function fd(e,t="",r=!1){let{repo:n,cfgPath:o}=Qg(e,t);if(!r&&pd(o)){mt(`Found existing configuration at ${o}; nothing written.`),mt("Pass --force to overwrite it, or edit it directly.");return}let i=Xk({input:Qk,output:Zk}),s=async(S,N)=>{let U=N!==""?` [${N}]`:"",y=(await i.question(`${S}${U}: `)).trim();return y===""?N:y},a=t===""?9:8,c=0,l=()=>(c+=1,c);if(mt(`devctl setup \u2014 ${a} steps`),mt(""),t==="")await s(`${l()}. Repository root`,n);let d=await s(`${l()}. Environment / project name`,zs(n)),g=await Ht(""),f=await s(`${l()}. Google Cloud project`,g.projectID);if(mt(`${l()}. Authentication`),!g.adcAvailable){if(mt(" ADC is not available. Run: gcloud auth application-default login"),(await s(" Run login now? (y/N)","n")).toLowerCase()==="y")try{await Os()}catch(N){mt(` login failed: ${N instanceof Error?N.message:String(N)}`)}}else if(mt(" \u2713 Application Default Credentials available"),g.userEmail!=="")mt(` user: ${g.userEmail}`);let h=await s(`${l()}. Service account email to record (optional, never hard-coded at runtime)`,""),x=await s(`${l()}. IAP audience to record on a sample route (optional)`,""),v=await s(`${l()}. Proxy listen port`,String(ms)),b=Number(v)||ms,P=await s(`${l()}. Default profile name (optional)`,"");i.close(),Zg(n,d,f,P,{sa:h,audience:x,proxyPort:b}),mt(""),mt(`Wrote starter configuration to ${o}`),mt(`${l()}. Validation`);try{let S=gt(n,""),N=await Tr(S);mt(qs(N))}catch(S){mt(` configuration is not valid yet: ${S instanceof Error?S.message:String(S)}`),mt(" edit .devctl/config.yaml and run `devctl config validate`")}}function Zg(e,t,r,n,o={sa:"",audience:"",proxyPort:ms}){let i=cr(e,".devctl");dd(cr(i,"services"),{recursive:!0}),dd(cr(i,"profiles"),{recursive:!0}),dd(cr(i,"proxy"),{recursive:!0}),zk(cr(i,"config.yaml"),`# yaml-language-server: $schema=https://raw.githubusercontent.com/amr-m-abdelgawad/devctl/main/schema/devctl.config.schema.json
|
|
25
25
|
version: 1
|
|
26
26
|
|
|
27
27
|
project:
|
|
@@ -69,12 +69,12 @@ shutdown:
|
|
|
69
69
|
stop_services_on_exit: true
|
|
70
70
|
grace_seconds: 10
|
|
71
71
|
`)}function mt(e){process.stdout.write(`${e}
|
|
72
|
-
`)}var
|
|
73
|
-
`,o=
|
|
72
|
+
`)}var gd=A(()=>{St();ui();_e();on()});var hm={};as(hm,{DEFAULT_LOG_PAGE_SIZE:()=>dm,LevelDebug:()=>wd,LevelError:()=>Zs,LevelFatal:()=>ea,LevelInfo:()=>Sd,LevelTrace:()=>bd,LevelUnknown:()=>Cd,LevelWarn:()=>kd,LogManager:()=>ra,MAX_LOG_PAGE_SIZE:()=>um,clampLogPageSize:()=>pm,compileLogSearch:()=>ta,defaultExportPath:()=>fm,defaultLogParser:()=>_d,listSessions:()=>jC,loadSessionEvents:()=>BC,matchLog:()=>pn,openInFileManager:()=>oa,parseLevel:()=>Pd,parseRequestID:()=>Rd,pruneSessions:()=>mm,resolveExportPath:()=>ro,safeServiceFile:()=>gm,writeLogExport:()=>na});import{spawn as hd}from"child_process";import{createWriteStream as bC,existsSync as mi,mkdirSync as wC,readdirSync as xd,readFileSync as SC,rmSync as kC,statSync as vd,writeFileSync as CC}from"fs";import{homedir as _C}from"os";import{dirname as am,isAbsolute as PC,join as fn,resolve as RC}from"path";function _d(){return{name:"default",parse:(e)=>({level:Pd(e),request_id:Rd(e)||void 0})}}function Pd(e){return TC.find((r)=>r.re.test(e))?.level??Cd}function Rd(e){return EC.exec(e)?.[1]??""}function pn(e,t){if(e.services&&e.services.length>0&&!e.services.includes(t.service))return!1;if(e.level&&(im[t.level]??2)<(im[e.level]??2))return!1;if(e.source&&t.source!==e.source)return!1;if(e.since&&t.timestamp<e.since)return!1;if(e.until&&t.timestamp>e.until)return!1;if(!e.search)return!0;if(e.regex){let r=ta(e.search);if(r)return r.test(t.message)}return t.message.toLowerCase().includes(e.search.toLowerCase())}function ta(e){let t=MC(e);if(t===void 0)return;return new RegExp(t)}function MC(e){if(e.length===0||e.length>AC)return;let t={raw:e,i:0,out:[],quantifiers:0,depth:0,lastAtom:"none",groupQuant:[]};if(!cm(t)||t.i!==e.length||t.depth!==0)return;return t.out.join("")}function cm(e){while(e.i<e.raw.length){if(e.raw[e.i]===")")return!0;if(!OC(e))return!1}return!0}function OC(e){let t=e.raw[e.i]??"";if(t==="|")return Qs(e,"|","none");if(t==="^")return Qs(e,"^","none");if(t==="$")return Qs(e,"$","none");if(t===".")return Qs(e,".","atom");if(t==="(")return IC(e);if(t==="[")return FC(e);if(t==="*"||t==="+"||t==="?"||t==="{")return $C(e);if(t==="\\")return lm(e);return e.out.push(RegExp.escape(t)),e.i+=1,e.lastAtom="atom",!0}function Qs(e,t,r){return e.out.push(t),e.i+=1,e.lastAtom=r,!0}function IC(e){if(e.i+=1,e.depth+=1,e.depth>DC)return!1;if(e.groupQuant.push(!1),e.out.push("(?:"),!cm(e)||e.raw[e.i]!==")")return!1;e.out.push(")"),e.i+=1,e.depth-=1;let t=e.groupQuant.pop()===!0;return e.lastAtom=t?"quantified-group":"atom",!0}function $C(e){let t=e.raw[e.i]??"";if(t==="{"||e.lastAtom==="none"||e.lastAtom==="quant"||e.lastAtom==="quantified-group")return!1;if(e.quantifiers>=LC)return!1;if(t==="*")e.out.push("*");else if(t==="+")e.out.push("+");else if(t==="?")e.out.push("?");else return!1;e.i+=1,e.quantifiers+=1;let r=e.groupQuant.length-1;if(r>=0)e.groupQuant[r]=!0;if(e.raw[e.i]==="?")e.out.push("?"),e.i+=1;return e.lastAtom="quant",!0}function FC(e){if(e.i+=1,e.out.push("["),e.raw[e.i]==="^")e.out.push("^"),e.i+=1;if(e.raw[e.i]==="]")e.out.push(RegExp.escape("]")),e.i+=1;while(e.i<e.raw.length&&e.raw[e.i]!=="]"){let t=e.raw[e.i]??"";if(t==="\\"){if(!lm(e))return!1}else if(t==="-")e.out.push("-"),e.i+=1;else e.out.push(RegExp.escape(t)),e.i+=1}if(e.raw[e.i]!=="]")return!1;return e.out.push("]"),e.i+=1,e.lastAtom="atom",!0}function lm(e){let t=e.raw[e.i+1];if(t===void 0)return!1;if(t==="d")e.out.push("\\d");else if(t==="D")e.out.push("\\D");else if(t==="w")e.out.push("\\w");else if(t==="W")e.out.push("\\W");else if(t==="s")e.out.push("\\s");else if(t==="S")e.out.push("\\S");else if(t==="n")e.out.push("\\n");else if(t==="t")e.out.push("\\t");else if(t==="r")e.out.push("\\r");else if(t==="b")e.out.push("\\b");else if(t==="B")e.out.push("\\B");else e.out.push(RegExp.escape(t));return e.i+=2,e.lastAtom="atom",!0}function sm(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64url")}function HC(e){try{let t=JSON.parse(Buffer.from(e,"base64url").toString("utf8"));if(typeof t==="object"&&t!==null&&typeof t.session==="string"&&typeof t.seq==="number")return t}catch{}return}function yd(e,t){let r={...e};return r[t]=void 0,r}function pm(e){if(!Number.isInteger(e)||(e??0)<=0)return dm;return Math.min(e,um)}class ra{events=[];eventStart=0;nextSeq=1;max;bus;detector;persistDir;persist;sessionID;streams=new Map;lastWrite=new Map;parsers=[];constructor(e,t,r,n,o,i,s=0,a=0){this.max=e>0?e:NC,this.bus=t,this.detector=r,this.sessionID=i;let c=o===""||o.startsWith("~/")?ps():o;if(this.persist=n&&i!=="",this.persistDir=this.persist?fn(c,`${Ed}${i}`):"",this.persist)wC(this.persistDir,{recursive:!0,mode:448}),mm(c,s,a)}sessionDir(){return this.persistDir}setParsers(e){this.parsers=e}append(e){let t=this.parseLine(e.message),r={...e,timestamp:e.timestamp||new Date().toISOString(),level:e.level||t.level||Pd(e.message),request_id:e.request_id||t.request_id||Rd(e.message),message:this.detector?this.detector.redactText(e.message):e.message,seq:this.nextSeq++};if(this.events.length<this.max)this.events.push(r);else this.events[this.eventStart]=r,this.eventStart=(this.eventStart+1)%this.max;if(this.bus?.publish(Ae(Bs,r.service,{event:r,level:r.level})),this.persist){let n=`${r.timestamp} ${r.service} ${r.level} ${r.message}
|
|
73
|
+
`,o=gm(r.service),i=this.streamFor(o);this.lastWrite.set(o,new Promise((s)=>{i.write(n,()=>s())}))}}async flush(){await Promise.all([...this.lastWrite.values()])}parseLine(e){let t={};for(let r of this.parsers)try{let n=r.parse(e);if(n)t={...t,...n}}catch{}return t}streamFor(e){let t=this.streams.get(e);if(t===void 0)t=bC(fn(this.persistDir,`${e}.log`),{flags:"a",mode:384}),t.on("error",()=>{}),this.streams.set(e,t);return t}async close(){await this.flush(),await Promise.all([...this.streams.values()].map((e)=>new Promise((t)=>{e.end(()=>t())}))),this.streams.clear(),this.lastWrite.clear()}query(e){let t=[];return this.forEachEvent((r)=>{if(pn(e,r))t.push(r)}),t}queryPage(e,t={}){let r=pm(t.limit),n=t.cursor?HC(t.cursor):void 0,o=n!==void 0&&n.session!==this.sessionID,i=o?void 0:n,s=i?t.direction??"backward":"backward",a=[];this.forEachEvent((h)=>{if(pn(e,h))a.push(h)});let c;if(!i)c=a.slice(Math.max(0,a.length-r));else if(s==="forward")c=a.filter((h)=>h.seq>i.seq).slice(0,r);else{let h=a.filter((x)=>x.seq<i.seq);c=h.slice(Math.max(0,h.length-r))}let l=c[0]?.seq,d=c[c.length-1]?.seq,g=l!==void 0&&a.some((h)=>h.seq<l),f=d!==void 0&&a.some((h)=>h.seq>d);return{events:c,prevCursor:sm({session:this.sessionID,seq:l??i?.seq??0}),nextCursor:sm({session:this.sessionID,seq:d??i?.seq??this.nextSeq-1}),hasNext:f,hasPrev:g,sessionChanged:o}}queryFacets(e){let t=yd(e,"services"),r=yd(e,"level"),n=yd(e,"source"),o=0,i={},s={},a={};return this.forEachEvent((c)=>{if(pn(e,c))o+=1;if(pn(t,c))i[c.service]=(i[c.service]??0)+1;if(pn(r,c))s[c.level]=(s[c.level]??0)+1;if(pn(n,c))a[c.source]=(a[c.source]??0)+1}),{total:o,byService:i,byLevel:s,bySource:a}}snapshot(){let e={},t=0;return this.forEachEvent((r)=>{if(e[r.service]=(e[r.service]??0)+1,r.level===Zs||r.level===ea)t+=1}),{total:this.events.length,errors:t,counts:e}}forEachEvent(e){let t=this.events.length;for(let r=0;r<t;r+=1){let n=this.events[(this.eventStart+r)%t];if(n)e(n)}}exportTo(e,t){na(e,this.query(t))}}function fm(e=new Date){let t=e.toISOString().replace(/[:.]/g,"-");return fn(Vr(),`devctl-logs-${t}.log`)}function ro(e=""){if(e==="")return fm();let t=e.startsWith("~/")?fn(_C(),e.slice(2)):e;return PC(t)?t:RC(process.cwd(),t)}function na(e,t){Gt(am(e));let r=t.map((n)=>`${n.timestamp} ${n.service} ${n.level} ${n.message}`);CC(e,`${r.join(`
|
|
74
74
|
`)}
|
|
75
|
-
`,{mode:384})}function
|
|
76
|
-
`)){if(a.trim()==="")continue;let c=a.split(" ");n.push({timestamp:c[0]??"",service:c[1]??i.replace(/\.log$/,""),source:"history",level:c[2]??"INFO",message:c.slice(3).join(" "),pid:0,seq:0})}}let o=n.sort((i,s)=>i.timestamp.localeCompare(s.timestamp));return o.forEach((i,s)=>{i.seq=s+1}),o}function
|
|
77
|
-
`||e==="\r"}var
|
|
75
|
+
`,{mode:384})}function oa(e){let t=mi(e)&&vd(e).isDirectory()?e:am(e);if(Gt(t),process.platform==="darwin"){let r=mi(e)&&vd(e).isFile()?["-R",e]:[t];hd("open",r,{detached:!0,stdio:"ignore"}).unref();return}if(process.platform==="win32"){hd("explorer",[t],{detached:!0,stdio:"ignore"}).unref();return}hd("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref()}function jC(e=ps()){if(!mi(e))return[];return xd(e).filter((t)=>t.startsWith(Ed)).sort().reverse()}function BC(e,t=ps()){let r=fn(t,e);if(!mi(r))return[];let n=[];for(let i of xd(r)){if(!i.endsWith(".log"))continue;let s=SC(fn(r,i),"utf8");for(let a of s.split(`
|
|
76
|
+
`)){if(a.trim()==="")continue;let c=a.split(" ");n.push({timestamp:c[0]??"",service:c[1]??i.replace(/\.log$/,""),source:"history",level:c[2]??"INFO",message:c.slice(3).join(" "),pid:0,seq:0})}}let o=n.sort((i,s)=>i.timestamp.localeCompare(s.timestamp));return o.forEach((i,s)=>{i.seq=s+1}),o}function gm(e){let t=e.replace(/[^A-Za-z0-9._-]+/g,"_");return t===""?"service":t}function mm(e,t,r){if(!mi(e))return;let n=xd(e).filter((i)=>i.startsWith(Ed)).map((i)=>{let s=fn(e,i),a=vd(s);return{path:s,mtime:a.mtimeMs}}).sort((i,s)=>s.mtime-i.mtime),o=t>0?Date.now()-t*86400000:0;n.forEach((i,s)=>{let a=o>0&&i.mtime<o,c=r>0&&s>=r;if(a||c)kC(i.path,{recursive:!0,force:!0})})}var bd="TRACE",wd="DEBUG",Sd="INFO",kd="WARN",Zs="ERROR",ea="FATAL",Cd="UNKNOWN",im,EC,TC,AC=200,LC=8,DC=2,NC=50000,Ed="session-",dm=500,um=5000;var gn=A(()=>{Ye();im={[bd]:0,[wd]:1,[Sd]:2,[kd]:3,[Zs]:4,[ea]:5,[Cd]:2};EC=/(?:x-devctl-request-id|request[_-]?id)[=: ]+([A-Za-z0-9-]+)/i,TC=[{re:/\b(fatal|critical)\b/i,level:ea},{re:/\b(error|err)\b/i,level:Zs},{re:/\b(warn|warning)\b/i,level:kd},{re:/\b(debug|dbg)\b/i,level:wd},{re:/\b(trace)\b/i,level:bd},{re:/\b(info|information)\b/i,level:Sd}]});class mn{nameMarkers;patterns;constructor(e,t){this.nameMarkers=[...Nm,...e],this.patterns=t.flatMap((r)=>{try{return[new RegExp(r)]}catch{return[]}})}update(e,t){this.nameMarkers=[...Nm,...e],this.patterns=t.flatMap((r)=>{try{return[new RegExp(r)]}catch{return[]}})}isSecretName(e){let t=e.toUpperCase();return this.nameMarkers.some((r)=>t.includes(r.toUpperCase()))}redactValue(e,t){if(t==="")return t;if(this.isSecretName(e))return"********";if(this.patterns.some((r)=>r.test(t)))return"********";return t}redactMap(e){let t={};for(let[r,n]of Object.entries(e))t[r]=this.redactValue(r,n);return t}redactText(e){if(e==="")return e;let t=e;for(let r of this.patterns)t=t.replace(r,"********");return f0(t)}}function f0(e){let t=e.toLowerCase(),r="authorization: bearer ",n=t.indexOf("authorization: bearer ");if(n>=0)return Hm(e,n+22);let o=t.indexOf("bearer ");if(o<0)return e;return Hm(e,o+7)}function Hm(e,t){let r=t;while(r<e.length&&!g0(e[r]??""))r+=1;return e.slice(0,t)+"********"+e.slice(r)}function g0(e){return e===" "||e==="\t"||e===`
|
|
77
|
+
`||e==="\r"}var Nm;var ua=A(()=>{Nm=["PASSWORD","SECRET","TOKEN","PRIVATE_KEY","CLIENT_SECRET","API_KEY","CREDENTIAL","ACCESS_KEY","AUTH_KEY"]});var pa;var jm=A(()=>{pa={procedure:`---
|
|
78
78
|
name: devctl-onboard
|
|
79
79
|
description: Survey a repository \u2014 its runnable services, docker-compose, Terraform, Kubernetes manifests, .env files, task runners \u2014 and author a validated .devctl configuration for it. Use when asked to onboard a repo to devctl, add or fix .devctl/config.yaml, generate devctl services/profiles/proxy routes, or diagnose why a devctl config fails to load.
|
|
80
80
|
---
|
|
@@ -603,27 +603,46 @@ Rules for turning that into YAML:
|
|
|
603
603
|
a full one. Remember that a bare \`devctl start\` falls back to the first
|
|
604
604
|
configured profile, and the TUI's default is the first profile
|
|
605
605
|
alphabetically \u2014 so name them with that in mind.
|
|
606
|
-
`}});import{existsSync as g0,readFileSync as m0}from"fs";function Ar(e,t){return!(t??[]).includes(e)}function Nm(e){return ua.filter((t)=>Ar(t.name,e))}function pa(e){return ua.some((t)=>t.name===e)}function Hm(e){return new gn(e.secrets.extra_markers,e.secrets.extra_patterns)}function jm(e){return Object.values(e.services).map((t)=>({name:t.name,state:t.state,health:t.health,ports:t.ports,pid:t.pid,last_error:t.last_error}))}function y0(e,t){let r=e.config(),n=r.services[t];if(!n)throw Error(`unknown service ${t}`);let i=e.status().services[t],s=Hm(r);return{name:t,state:i?.state,health:i?.health,pid:i?.pid,last_error:i?.last_error,command:n.command.args,cwd:n.working_dir,ports:i?.ports??Object.fromEntries(n.ports.map((a)=>[a.name,a.value])),environment:s.redactMap({...n.environment.defaults,...n.environment.vars})}}function Bm(e){return{session_id:e.session_id,repo_root:e.repo_root,profile:e.profile,setup_mode:e.setup_mode===!0?!0:void 0,identity:{user:e.identity.user,project:e.identity.project,adc:e.identity.adc,iap:e.identity.iap,service_accounts:e.identity.service_accounts,service_account_status:e.identity.service_account_status},proxy:{running:e.proxy.running,address:e.proxy.address,routes:e.proxy.routes},logs:e.logs,mcp:e.mcp?{running:e.mcp.running,address:e.mcp.address,port:e.mcp.port}:{running:!1}}}async function Wm(e,t){let r=typeof t.service==="string"?t.service:"",n=typeof t.since==="string"?t.since:"",o=typeof t.cursor==="string"?t.cursor:void 0,i=await e.logsPage({services:r===""?[]:[r],level:typeof t.level==="string"?t.level:"",search:typeof t.search==="string"?t.search:"",source:typeof t.source==="string"?t.source:"",since:n,until:typeof t.until==="string"?t.until:"",cursor:o,direction:o?"forward":void 0,limit:h0}),s=Hm(e.config());return{events:i.events.map((a)=>({timestamp:a.timestamp,service:a.service,source:a.source,level:a.level,message:s.redactText(a.message),pid:a.pid})),truncated:i.hasPrev,has_more:i.hasNext,next_since:i.events[i.events.length-1]?.timestamp??n,next_cursor:i.nextCursor,session_changed:i.sessionChanged}}function v0(e){return Object.entries(e.profiles).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>({name:t,services:r.services}))}function Gm(e){let t=Object.entries(e.services).map(([r,n])=>({name:r,description:n.description,command:n.command.args,cwd:n.working_dir,ports:n.ports.map((o)=>({name:o.name,value:o.auto?0:o.value,auto:o.auto})),dependencies:n.dependencies}));return{project:e.project.name,config_path:e.configPath,repo_root:e.repoRoot,services:t,proxy:{enabled:e.proxy.enabled,listen:{host:e.proxy.listen.host,port:e.proxy.listen.port},routes:e.proxy.routes.map((r)=>({name:r.name,match:r.match,upstream:r.upstream.url,auth:r.auth.type}))}}}function Dd(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}async function Um(e,t,r){switch(t){case"list_services":return jm(e.status());case"get_service":if(typeof r.name!=="string"||r.name==="")throw Error("name is required");return y0(e,r.name);case"get_status":return Bm(e.status());case"get_logs":return Wm(e,r);case"list_profiles":return v0(e.config());case"get_config":return Gm(e.config());case"run_doctor":return e.doctor();case"start_services":return e.start({services:Dd(r.services),profile:typeof r.profile==="string"?r.profile:""});case"stop_services":return await e.stop(Dd(r.services)),{ok:!0};case"restart_services":return await e.restart(Dd(r.services),r.cascade===!0),{ok:!0};case"reload_config":return e.reload();case"get_setup_guide":return x0(r);case"validate_config":return b0(e,r);default:throw Error(`unknown tool ${t}`)}}function x0(e){let t=typeof e.section==="string"?e.section:"procedure",r=t in da?t:"procedure";return{section:r,text:da[r],sections:Object.keys(da)}}function b0(e,t){let r=e.config();if(typeof t.text==="string"){let o=jn(r.repoRoot,r.configPath,t.text);return{valid:o.length===0,issues:o,source:"candidate",config_path:r.configPath}}if(!g0(r.configPath))return{valid:!1,issues:[`no configuration at ${r.configPath}`],source:"disk",config_path:r.configPath,setup_mode:!0};let n=jn(r.repoRoot,r.configPath,m0(r.configPath,"utf8"));return{valid:n.length===0,issues:n,source:"disk",config_path:r.configPath}}function Km(e){return Md.includes(e)}async function qm(e,t){switch(t){case"devctl://status":return Bm(e.status());case"devctl://services":return jm(e.status());case"devctl://logs":return Wm(e,{});case"devctl://config":return Gm(e.config());case"devctl://doctor":return e.doctor();default:throw Error(`unknown resource ${t}`)}}var h0=200,Md,Od,ua;var yi=T(()=>{St();la();Fm();Md=["devctl://status","devctl://services","devctl://logs","devctl://config","devctl://doctor"],Od=["inspect","logs","diagnostics","control","setup"],ua=[{name:"list_services",label:"List services",summary:"Name, state, health, ports, pid",category:"inspect",description:"List services with state, health, ports, pid, and last error",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_service",label:"Service detail",summary:"One service with command, cwd, ports",category:"inspect",description:"One service plus command, cwd, and ports. Environment values are redacted.",inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"],additionalProperties:!1}},{name:"get_status",label:"Status",summary:"Profile, identity, proxy, log counts",category:"inspect",description:"Profile, session, identity flags (no tokens), proxy, and log counts",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_logs",label:"Read logs",summary:"Filtered log pages, secrets redacted",category:"logs",description:"Recent log lines, optionally filtered. Capped at 200 events per page. Secrets are redacted. Pass cursor=next_cursor to page forward with no duplicate or same-millisecond-lost events; since/until are plain timestamp filters for a fresh query, not a follow cursor.",inputSchema:{type:"object",properties:{service:{type:"string"},level:{type:"string"},search:{type:"string"},source:{type:"string"},since:{type:"string",description:"Only events at or after this timestamp"},until:{type:"string",description:"Only events at or before this timestamp"},cursor:{type:"string",description:"Opaque cursor from a previous response's next_cursor; continues forward from exactly there"}},additionalProperties:!1}},{name:"list_profiles",label:"List profiles",summary:"Configured profiles and their members",category:"inspect",description:"Configured profiles and their member services",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_config",label:"Read config",summary:"Merged project summary, no secret values",category:"inspect",description:"Merged project summary: services, routes, and proxy listen paths. No secret env values.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"run_doctor",label:"Run doctor",summary:"Environment diagnostics",category:"diagnostics",description:"Run environment diagnostics",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"start_services",label:"Start services",summary:"Start named services or a profile",category:"control",mutates:!0,description:"Start named services, or a profile when names are omitted. Empty start uses profile, then the active session profile, then the first configured profile \u2014 never every service.",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}},profile:{type:"string",description:"Profile to start when services is omitted"}},additionalProperties:!1}},{name:"stop_services",label:"Stop services",summary:"Stop services and their dependents",category:"control",mutates:!0,description:"Stop named services, or all started services when names are omitted. Also stops every service that transitively depends on a named one (never a named service's own dependencies, which other running services may still need).",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}}},additionalProperties:!1}},{name:"restart_services",label:"Restart services",summary:"Restart services, optionally cascading",category:"control",mutates:!0,description:"Restart named services. By default this touches only the named services, not anything that depends on them. Pass cascade=true to also restart their transitive dependents (the same set stop_services would affect).",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}},cascade:{type:"boolean",description:"Also restart transitive dependents; default false restarts only the named services"}},additionalProperties:!1}},{name:"reload_config",label:"Reload config",summary:"Re-read .devctl configuration",category:"control",mutates:!0,description:"Reload .devctl configuration",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_setup_guide",label:"Setup guide",summary:"How to author a .devctl for this repo",category:"setup",description:"The devctl onboarding guide: how to survey a repository and author a .devctl configuration for it. Read section=procedure first; read section=authoring BEFORE writing any YAML (it carries the rules the loader rejects on, which the JSON Schema does not state); read section=discovery for mapping compose/package.json/pyproject/Terraform/k8s/.env to services. Write the files with your own editing tools \u2014 this server does not write them \u2014 then check your work with validate_config.",inputSchema:{type:"object",properties:{section:{type:"string",enum:["procedure","authoring","discovery"],description:"Which part of the guide to return; defaults to procedure"}},additionalProperties:!1}},{name:"validate_config",label:"Validate config",summary:"Check configuration or a draft for errors",category:"setup",description:"Validate devctl configuration and return the exact issues the loader would report. With no arguments, validates what is on disk. Pass text to validate a candidate config.yaml before writing it \u2014 the candidate is run through the real load pipeline (modular services/profiles, overlays, templates), so it works even when no configuration exists yet. This is the only way to validate over MCP; there is no CLI round-trip needed.",inputSchema:{type:"object",properties:{text:{type:"string",description:"Candidate config.yaml contents to validate instead of the file on disk"}},additionalProperties:!1}}]});function mn(e){if(!Number.isInteger(e))return $d;return Math.min(Zm,Math.max(D0,e))}function eh(e,t){if(t.length!==1||t<"0"||t>"9")return e;if(e.length>=M0)return t;return`${e}${t}`}function th(e){return e.slice(0,-1)}function rh(e,t){if(e==="")return mn(t);let r=Number(e);if(!Number.isInteger(r))return mn(t);return mn(r)}function io(e){let t=Number.parseInt(Wo(e).slice(0,A0),16),r=Number.isFinite(t)?t%Qm:0;return $d+r}function nh(e,t){return t===io(e)}async function oh(e,t){let r=Number.isInteger(t)&&(t??0)>0?t:io(e);for(let n=0;n<L0;n+=1){let o=r+n;if(o>Zm)break;if(await qn(o))return o}throw M(X,`no free MCP port starting at ${r}`)}var $d=18700,Qm=600,KD,A0=8,L0=600,Zm=65535,D0=1024,M0=5;var ga=T(()=>{_e();ii();Ye();KD=$d+Qm-1});import{existsSync as va,readFileSync as ma}from"fs";import{dirname as O0,isAbsolute as ih,join as ya,resolve as I0}from"path";function lr(){return process.platform==="darwin"?"cmd+c":"ctrl+shift+c"}function B0(){return{theme:"devctl",leader_timeout:xa,font_size:yn,keybinds:{...j0},scroll_speed:$0,scroll_acceleration:{enabled:!1},diff_style:"auto",cursor:{style:"block",blinking:!0},mouse:!0,attention:{enabled:!1,notifications:!0,sound:!0,volume:F0,sound_pack:"default",sounds:{}},log_timestamps:!0,log_metadata:!0,mcp_enabled:!1}}function ba(){return ya(Lt(),"tui.json")}function wi(e=""){for(let t of[N0,H0]){let r=process.env[t];if(!r||r==="")continue;let n=ih(r)?r:I0(e||process.cwd(),r);if(va(n))return n}return}function W0(e,t){if(!t||Object.keys(t).length===0)return e;return{...e,keybinds:{...e.keybinds,...t}}}function qt(e,t){let r=W0(B0(),t),n=wi(e);if(n)return Fd(r,ha(ma(n,"utf8")),n);let o=G0(e),i=o?Fd(r,ha(ma(o,"utf8")),o):r,s=ba();if(!va(s)||o===s)return i;return Fd(i,ha(ma(s,"utf8")),s)}function sh(e){let t=ba(),r={};if(va(t)){let o=ha(ma(t,"utf8"));if(hn(o))r=o}let n={...r};if(e.theme!==void 0)n.theme=e.theme;if(e.mouse!==void 0)n.mouse=e.mouse;if(e.leader_timeout!==void 0)n.leader_timeout=e.leader_timeout;if(e.font_size!==void 0)n.font_size=e.font_size;if(e.log_timestamps!==void 0)n.log_timestamps=e.log_timestamps;if(e.log_metadata!==void 0)n.log_metadata=e.log_metadata;if(e.mcp_enabled!==void 0)n.mcp_enabled=e.mcp_enabled;if(e.mcp_port===null)delete n.mcp_port;else if(e.mcp_port!==void 0)n.mcp_port=e.mcp_port;if(e.mcp_disabled_tools!==void 0)n.mcp_disabled_tools=e.mcp_disabled_tools;return $t(t,`${JSON.stringify(n,null,2)}
|
|
607
|
-
`),t}function
|
|
606
|
+
`}});import{existsSync as m0,readFileSync as h0}from"fs";function Ar(e,t){return!(t??[]).includes(e)}function Bm(e){return fa.filter((t)=>Ar(t.name,e))}function ga(e){return fa.some((t)=>t.name===e)}function Wm(e){return new mn(e.secrets.extra_markers,e.secrets.extra_patterns)}function Gm(e){return Object.values(e.services).map((t)=>({name:t.name,state:t.state,health:t.health,ports:t.ports,pid:t.pid,last_error:t.last_error}))}function v0(e,t){let r=e.config(),n=r.services[t];if(!n)throw Error(`unknown service ${t}`);let i=e.status().services[t],s=Wm(r);return{name:t,state:i?.state,health:i?.health,pid:i?.pid,last_error:i?.last_error,command:n.command.args,cwd:n.working_dir,ports:i?.ports??Object.fromEntries(n.ports.map((a)=>[a.name,a.value])),environment:s.redactMap({...n.environment.defaults,...n.environment.vars})}}function Um(e){return{session_id:e.session_id,repo_root:e.repo_root,profile:e.profile,setup_mode:e.setup_mode===!0?!0:void 0,identity:{user:e.identity.user,project:e.identity.project,adc:e.identity.adc,iap:e.identity.iap,service_accounts:e.identity.service_accounts,service_account_status:e.identity.service_account_status},proxy:{running:e.proxy.running,address:e.proxy.address,routes:e.proxy.routes},logs:e.logs,mcp:e.mcp?{running:e.mcp.running,address:e.mcp.address,port:e.mcp.port}:{running:!1}}}async function Km(e,t){let r=typeof t.service==="string"?t.service:"",n=typeof t.since==="string"?t.since:"",o=typeof t.cursor==="string"?t.cursor:void 0,i=await e.logsPage({services:r===""?[]:[r],level:typeof t.level==="string"?t.level:"",search:typeof t.search==="string"?t.search:"",source:typeof t.source==="string"?t.source:"",since:n,until:typeof t.until==="string"?t.until:"",cursor:o,direction:o?"forward":void 0,limit:y0}),s=Wm(e.config());return{events:i.events.map((a)=>({timestamp:a.timestamp,service:a.service,source:a.source,level:a.level,message:s.redactText(a.message),pid:a.pid})),truncated:i.hasPrev,has_more:i.hasNext,next_since:i.events[i.events.length-1]?.timestamp??n,next_cursor:i.nextCursor,session_changed:i.sessionChanged}}function x0(e){return Object.entries(e.profiles).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>({name:t,services:r.services}))}function qm(e){let t=Object.entries(e.services).map(([r,n])=>({name:r,description:n.description,command:n.command.args,cwd:n.working_dir,ports:n.ports.map((o)=>({name:o.name,value:o.auto?0:o.value,auto:o.auto})),dependencies:n.dependencies}));return{project:e.project.name,config_path:e.configPath,repo_root:e.repoRoot,services:t,proxy:{enabled:e.proxy.enabled,listen:{host:e.proxy.listen.host,port:e.proxy.listen.port},routes:e.proxy.routes.map((r)=>({name:r.name,match:r.match,upstream:r.upstream.url,auth:r.auth.type}))}}}function Od(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}async function Vm(e,t,r){switch(t){case"list_services":return Gm(e.status());case"get_service":if(typeof r.name!=="string"||r.name==="")throw Error("name is required");return v0(e,r.name);case"get_status":return Um(e.status());case"get_logs":return Km(e,r);case"list_profiles":return x0(e.config());case"get_config":return qm(e.config());case"run_doctor":return e.doctor();case"start_services":return e.start({services:Od(r.services),profile:typeof r.profile==="string"?r.profile:""});case"stop_services":return await e.stop(Od(r.services)),{ok:!0};case"restart_services":return await e.restart(Od(r.services),r.cascade===!0),{ok:!0};case"reload_config":return e.reload();case"get_setup_guide":return b0(r);case"validate_config":return w0(e,r);default:throw Error(`unknown tool ${t}`)}}function b0(e){let t=typeof e.section==="string"?e.section:"procedure",r=t in pa?t:"procedure";return{section:r,text:pa[r],sections:Object.keys(pa)}}function w0(e,t){let r=e.config();if(typeof t.text==="string"){let o=Bn(r.repoRoot,r.configPath,t.text);return{valid:o.length===0,issues:o,source:"candidate",config_path:r.configPath}}if(!m0(r.configPath))return{valid:!1,issues:[`no configuration at ${r.configPath}`],source:"disk",config_path:r.configPath,setup_mode:!0};let n=Bn(r.repoRoot,r.configPath,h0(r.configPath,"utf8"));return{valid:n.length===0,issues:n,source:"disk",config_path:r.configPath}}function Jm(e){return Id.includes(e)}async function Ym(e,t){switch(t){case"devctl://status":return Um(e.status());case"devctl://services":return Gm(e.status());case"devctl://logs":return Km(e,{});case"devctl://config":return qm(e.config());case"devctl://doctor":return e.doctor();default:throw Error(`unknown resource ${t}`)}}var y0=200,Id,$d,fa;var vi=A(()=>{St();ua();jm();Id=["devctl://status","devctl://services","devctl://logs","devctl://config","devctl://doctor"],$d=["inspect","logs","diagnostics","control","setup"],fa=[{name:"list_services",label:"List services",summary:"Name, state, health, ports, pid",category:"inspect",description:"List services with state, health, ports, pid, and last error",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_service",label:"Service detail",summary:"One service with command, cwd, ports",category:"inspect",description:"One service plus command, cwd, and ports. Environment values are redacted.",inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"],additionalProperties:!1}},{name:"get_status",label:"Status",summary:"Profile, identity, proxy, log counts",category:"inspect",description:"Profile, session, identity flags (no tokens), proxy, and log counts",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_logs",label:"Read logs",summary:"Filtered log pages, secrets redacted",category:"logs",description:"Recent log lines, optionally filtered. Capped at 200 events per page. Secrets are redacted. Pass cursor=next_cursor to page forward with no duplicate or same-millisecond-lost events; since/until are plain timestamp filters for a fresh query, not a follow cursor.",inputSchema:{type:"object",properties:{service:{type:"string"},level:{type:"string"},search:{type:"string"},source:{type:"string"},since:{type:"string",description:"Only events at or after this timestamp"},until:{type:"string",description:"Only events at or before this timestamp"},cursor:{type:"string",description:"Opaque cursor from a previous response's next_cursor; continues forward from exactly there"}},additionalProperties:!1}},{name:"list_profiles",label:"List profiles",summary:"Configured profiles and their members",category:"inspect",description:"Configured profiles and their member services",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_config",label:"Read config",summary:"Merged project summary, no secret values",category:"inspect",description:"Merged project summary: services, routes, and proxy listen paths. No secret env values.",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"run_doctor",label:"Run doctor",summary:"Environment diagnostics",category:"diagnostics",description:"Run environment diagnostics",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"start_services",label:"Start services",summary:"Start named services or a profile",category:"control",mutates:!0,description:"Start named services, or a profile when names are omitted. Empty start uses profile, then the active session profile, then the first configured profile \u2014 never every service.",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}},profile:{type:"string",description:"Profile to start when services is omitted"}},additionalProperties:!1}},{name:"stop_services",label:"Stop services",summary:"Stop services and their dependents",category:"control",mutates:!0,description:"Stop named services, or all started services when names are omitted. Also stops every service that transitively depends on a named one (never a named service's own dependencies, which other running services may still need).",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}}},additionalProperties:!1}},{name:"restart_services",label:"Restart services",summary:"Restart services, optionally cascading",category:"control",mutates:!0,description:"Restart named services. By default this touches only the named services, not anything that depends on them. Pass cascade=true to also restart their transitive dependents (the same set stop_services would affect).",inputSchema:{type:"object",properties:{services:{type:"array",items:{type:"string"}},cascade:{type:"boolean",description:"Also restart transitive dependents; default false restarts only the named services"}},additionalProperties:!1}},{name:"reload_config",label:"Reload config",summary:"Re-read .devctl configuration",category:"control",mutates:!0,description:"Reload .devctl configuration",inputSchema:{type:"object",properties:{},additionalProperties:!1}},{name:"get_setup_guide",label:"Setup guide",summary:"How to author a .devctl for this repo",category:"setup",description:"The devctl onboarding guide: how to survey a repository and author a .devctl configuration for it. Read section=procedure first; read section=authoring BEFORE writing any YAML (it carries the rules the loader rejects on, which the JSON Schema does not state); read section=discovery for mapping compose/package.json/pyproject/Terraform/k8s/.env to services. Write the files with your own editing tools \u2014 this server does not write them \u2014 then check your work with validate_config.",inputSchema:{type:"object",properties:{section:{type:"string",enum:["procedure","authoring","discovery"],description:"Which part of the guide to return; defaults to procedure"}},additionalProperties:!1}},{name:"validate_config",label:"Validate config",summary:"Check configuration or a draft for errors",category:"setup",description:"Validate devctl configuration and return the exact issues the loader would report. With no arguments, validates what is on disk. Pass text to validate a candidate config.yaml before writing it \u2014 the candidate is run through the real load pipeline (modular services/profiles, overlays, templates), so it works even when no configuration exists yet. This is the only way to validate over MCP; there is no CLI round-trip needed.",inputSchema:{type:"object",properties:{text:{type:"string",description:"Candidate config.yaml contents to validate instead of the file on disk"}},additionalProperties:!1}}]});function hn(e){if(!Number.isInteger(e))return Nd;return Math.min(rh,Math.max(M0,e))}function nh(e,t){if(t.length!==1||t<"0"||t>"9")return e;if(e.length>=O0)return t;return`${e}${t}`}function oh(e){return e.slice(0,-1)}function ih(e,t){if(e==="")return hn(t);let r=Number(e);if(!Number.isInteger(r))return hn(t);return hn(r)}function so(e){let t=Number.parseInt(Go(e).slice(0,L0),16),r=Number.isFinite(t)?t%th:0;return Nd+r}function sh(e,t){return t===so(e)}async function ah(e,t){let r=Number.isInteger(t)&&(t??0)>0?t:so(e);for(let n=0;n<D0;n+=1){let o=r+n;if(o>rh)break;if(await Vn(o))return o}throw M(X,`no free MCP port starting at ${r}`)}var Nd=18700,th=600,qD,L0=8,D0=600,rh=65535,M0=1024,O0=5;var ha=A(()=>{_e();ii();Ye();qD=Nd+th-1});import{existsSync as ba,readFileSync as ya}from"fs";import{dirname as I0,isAbsolute as ch,join as xa,resolve as $0}from"path";function lr(){return process.platform==="darwin"?"cmd+c":"ctrl+shift+c"}function W0(){return{theme:"devctl",leader_timeout:wa,font_size:vn,keybinds:{...B0},scroll_speed:F0,scroll_acceleration:{enabled:!1},diff_style:"auto",cursor:{style:"block",blinking:!0},mouse:!0,attention:{enabled:!1,notifications:!0,sound:!0,volume:N0,sound_pack:"default",sounds:{}},log_timestamps:!0,log_metadata:!0,mcp_enabled:!1}}function Sa(){return xa(Lt(),"tui.json")}function Si(e=""){for(let t of[H0,j0]){let r=process.env[t];if(!r||r==="")continue;let n=ch(r)?r:$0(e||process.cwd(),r);if(ba(n))return n}return}function G0(e,t){if(!t||Object.keys(t).length===0)return e;return{...e,keybinds:{...e.keybinds,...t}}}function qt(e,t){let r=G0(W0(),t),n=Si(e);if(n)return Hd(r,va(ya(n,"utf8")),n);let o=U0(e),i=o?Hd(r,va(ya(o,"utf8")),o):r,s=Sa();if(!ba(s)||o===s)return i;return Hd(i,va(ya(s,"utf8")),s)}function lh(e){let t=Sa(),r={};if(ba(t)){let o=va(ya(t,"utf8"));if(yn(o))r=o}let n={...r};if(e.theme!==void 0)n.theme=e.theme;if(e.mouse!==void 0)n.mouse=e.mouse;if(e.leader_timeout!==void 0)n.leader_timeout=e.leader_timeout;if(e.font_size!==void 0)n.font_size=e.font_size;if(e.log_timestamps!==void 0)n.log_timestamps=e.log_timestamps;if(e.log_metadata!==void 0)n.log_metadata=e.log_metadata;if(e.mcp_enabled!==void 0)n.mcp_enabled=e.mcp_enabled;if(e.mcp_port===null)delete n.mcp_port;else if(e.mcp_port!==void 0)n.mcp_port=e.mcp_port;if(e.mcp_disabled_tools!==void 0)n.mcp_disabled_tools=e.mcp_disabled_tools;return $t(t,`${JSON.stringify(n,null,2)}
|
|
607
|
+
`),t}function U0(e){let t=Si(e);if(t)return t;let r=[e||process.cwd(),xa(e||process.cwd(),".devctl"),Lt()],n=["tui.json","tui.jsonc"];for(let o of r)for(let i of n){let s=xa(o,i);if(ba(s))return s}return}function Hd(e,t,r){let n=yn(t)?t:{},o={...e.keybinds};if(yn(n.keybinds)){for(let[c,l]of Object.entries(n.keybinds))if(typeof l==="string")o[c]=l}let i={...e.cursor};if(yn(n.cursor)){if(q0(n.cursor.style))i.style=n.cursor.style;if(typeof n.cursor.blinking==="boolean")i.blinking=n.cursor.blinking}let s={...e.scroll_acceleration};if(yn(n.scroll_acceleration)&&typeof n.scroll_acceleration.enabled==="boolean")s.enabled=n.scroll_acceleration.enabled;let a={...e.attention,sounds:{...e.attention.sounds}};if(yn(n.attention)){if(typeof n.attention.enabled==="boolean")a.enabled=n.attention.enabled;if(typeof n.attention.notifications==="boolean")a.notifications=n.attention.notifications;if(typeof n.attention.sound==="boolean")a.sound=n.attention.sound;if(typeof n.attention.volume==="number")a.volume=n.attention.volume;if(typeof n.attention.sound_pack==="string")a.sound_pack=n.attention.sound_pack;if(yn(n.attention.sounds)){for(let[c,l]of Object.entries(n.attention.sounds))if(typeof l==="string")a.sounds[c]=K0(l,r)}}return{theme:typeof n.theme==="string"?n.theme:e.theme,leader_timeout:typeof n.leader_timeout==="number"?n.leader_timeout:e.leader_timeout,font_size:typeof n.font_size==="number"&&Number.isFinite(n.font_size)?Math.round(n.font_size):e.font_size,keybinds:o,scroll_speed:typeof n.scroll_speed==="number"?n.scroll_speed:e.scroll_speed,scroll_acceleration:s,diff_style:n.diff_style==="stacked"?"stacked":"auto",cursor:i,mouse:typeof n.mouse==="boolean"?n.mouse:e.mouse,attention:a,log_timestamps:typeof n.log_timestamps==="boolean"?n.log_timestamps:e.log_timestamps,log_metadata:typeof n.log_metadata==="boolean"?n.log_metadata:e.log_metadata,mcp_enabled:typeof n.mcp_enabled==="boolean"?n.mcp_enabled:e.mcp_enabled,mcp_port:typeof n.mcp_port==="number"&&Number.isInteger(n.mcp_port)?n.mcp_port:e.mcp_port,mcp_disabled_tools:Array.isArray(n.mcp_disabled_tools)?n.mcp_disabled_tools.filter((c)=>typeof c==="string"):e.mcp_disabled_tools,path:r}}function K0(e,t){if(e.startsWith("file://")||ch(e))return e;return xa(I0(t),e)}function q0(e){return e==="block"||e==="underline"||e==="line"||e==="default"}function yn(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function va(e){let t=e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"");return JSON.parse(t)}function V0(e){if(e===""||e==="none")return[];return e.split(",").flatMap((t)=>{let r=t.trim();if(r===""||r==="none"||/\s/.test(r))return[];let n=r.toLowerCase().split("+"),o=n[n.length-1]??"";return[{name:o==="return"?"return":o,ctrl:n.includes("ctrl")||n.includes("control"),shift:n.includes("shift"),meta:n.includes("meta")||n.includes("cmd")||n.includes("super"),alt:n.includes("alt")||n.includes("option")}]})}function dr(e,t){return V0(t).some((n)=>(e.name??"").toLowerCase()===n.name&&Boolean(e.ctrl)===n.ctrl&&Boolean(e.shift)===n.shift&&Boolean(e.meta||e.super)===n.meta&&Boolean(e.option??e.alt)===n.alt)}var wa=2000,vn=14,F0=3,N0=0.4,H0="DEVCTL_TUI_CONFIG",j0="OPENCODE_TUI_CONFIG",B0;var Vt=A(()=>{Ye();B0={leader:"ctrl+x",command_list:"ctrl+p",command:"/",help:"?",search:"f",quit:"q",services:"s",logs:"l",auth:"a",proxy:"p",doctor:"d",config:"c",setup:"u",refresh:"r",restart:"R",find:"f",fullscreen:"z",confirm:"enter",cancel:"esc",select:"space",interrupt:"ctrl+c",copy:lr()}});function co(e){return`http://127.0.0.1:${e}/mcp`}function Gd(e){if(e==="")return{};return{Authorization:`Bearer ${e}`}}function Ud(e,t){return JSON.stringify({mcpServers:{devctl:{type:"http",url:e,headers:Gd(t)}}},null,2)}function Kd(e,t){return JSON.stringify({mcpServers:{devctl:{url:e,headers:Gd(t)}}},null,2)}function qd(e,t){return JSON.stringify({mcp:{devctl:{type:"remote",url:e,headers:Gd(t),enabled:!0}}},null,2)}function Vd(e,t){let r=t===""?"":`
|
|
608
608
|
http_headers = { Authorization = "Bearer ${t}" }`;return`[mcp_servers.devctl]
|
|
609
609
|
url = "${e}"${r}
|
|
610
|
-
`}function
|
|
611
|
-
`)}function co(){return[{name:"start",aliases:["up"],desc:"Start selected services or the current profile",leader:"n",group:"services"},{name:"stop",aliases:["down"],desc:"Stop selected services",leader:"x",group:"services"},{name:"restart",aliases:[],desc:"Restart selected services",leader:"R",group:"services"},{name:"services",aliases:["s"],desc:"Open the services screen",leader:"s",group:"nav"},{name:"logs",aliases:["l"],desc:"Open the log viewer",leader:"l",group:"nav"},{name:"auth",aliases:["identity","a"],desc:"Open identity; add refresh to probe accounts",leader:"a",group:"nav"},{name:"credentials",aliases:["creds"],desc:"Open credential store status",leader:"",group:"nav"},{name:"reload",aliases:[],desc:"Reload configuration",leader:"",group:"ui"},{name:"proxy",aliases:["p"],desc:"Open the proxy screen",leader:"p",group:"nav"},{name:"mcp",aliases:["agent"],desc:"Open the MCP server screen for coding agents",leader:"",group:"nav"},{name:"doctor",aliases:["d"],desc:"Run environment diagnostics",leader:"d",group:"nav"},{name:"stats",aliases:["metrics"],desc:"View system and service statistics",leader:"m",group:"nav"},{name:"config",aliases:["c"],desc:"View merged configuration",leader:"c",group:"nav"},{name:"profiles",aliases:["o"],desc:"Select a development profile",leader:"o",group:"nav"},{name:"setup",aliases:["init"],desc:"Open setup guidance",leader:"i",group:"nav"},{name:"dashboard",aliases:["home"],desc:"Return to the dashboard",leader:"h",group:"nav"},{name:"themes",aliases:["theme"],desc:"List available themes",leader:"t",group:"ui"},{name:"settings",aliases:["prefs","preferences"],desc:"Open TUI settings (theme, mouse, MCP page)",leader:"",group:"ui"},{name:"help",aliases:["?"],desc:"Show the help dialog",leader:"",group:"ui"},{name:"refresh",aliases:[],desc:"Refresh status and logs",leader:"r",group:"ui"},{name:"regex",aliases:[],desc:"Toggle regex log search",leader:"",group:"logs"},{name:"since",aliases:[],desc:"Filter logs after an ISO timestamp",leader:"",group:"logs"},{name:"until",aliases:[],desc:"Filter logs before an ISO timestamp",leader:"",group:"logs"},{name:"history",aliases:[],desc:"Load a persisted log session",leader:"",group:"logs"},{name:"edit",aliases:[],desc:"Open configuration in $EDITOR",leader:"",group:"ui"},{name:"buffer",aliases:[],desc:"Edit configuration in a validate/save buffer",leader:"",group:"ui"},{name:"pause",aliases:[],desc:"Pause or resume live logs",leader:"",group:"logs"},{name:"fullscreen",aliases:["zen","expand"],desc:"Expand logs to fill the terminal",leader:"z",group:"logs"},{name:"filter",aliases:[],desc:"Toggle ERROR+ log filter",leader:"",group:"logs"},{name:"system",aliases:["internal"],desc:"Show or hide internal auth/mcp/devctl/proxy logs",leader:"",group:"logs"},{name:"reveal",aliases:[],desc:"Reveal or hide secret environment values",leader:"",group:"ui"},{name:"wrap",aliases:[],desc:"Cycle log wrap: selected, all lines, or clip",leader:"",group:"logs"},{name:"copy",aliases:[],desc:"Copy visible logs to the clipboard",leader:"",group:"logs"},{name:"export",aliases:[],desc:"Write filtered logs to ~/.devctl/exports",leader:"e",group:"logs"},{name:"exports",aliases:["open-exports"],desc:"Open the log export folder",leader:"",group:"logs"},{name:"clear",aliases:["new"],desc:"Clear the on-screen log buffer",leader:"",group:"logs"},{name:"version",aliases:["v"],desc:"Show the current devctl version",leader:"",group:"app"},{name:"exit",aliases:["quit","q"],desc:"Exit",leader:"q",group:"app"}]}function gh(e){let t=e.trim().toLowerCase().replace(/^\//,"");return co().filter((r)=>t===""||g_(r,t))}function g_(e,t){if(e.name.startsWith(t)||e.name.includes(t)||e.desc.toLowerCase().includes(t))return!0;return e.aliases.some((r)=>r.startsWith(t)||r===t)}function ki(e){let t=e.trim().toLowerCase().replace(/^\//,"").split(" ")[0]??"";return co().find((r)=>r.name===t||r.aliases.includes(t))}function mh(e){return e.trim().replace(/^\//,"").split(/\s+/).slice(1).filter((r)=>r!=="")}function hh(e){return co().find((r)=>r.leader===e)?.name??""}function wa(e){let t=e.toLowerCase().trim(),r=m_[t];if(r)return r;return ht.includes(t)?t:"devctl"}function h_(){if(process.env.DEVCTL_THEME_LIGHT==="1")return!0;if(process.env.DEVCTL_THEME_LIGHT==="0")return!1;if(process.platform==="darwin")try{let t=Bun.spawnSync(["defaults","read","-g","AppleInterfaceStyle"],{stdout:"pipe",stderr:"pipe"}),r=t.stdout.toString();if(t.exitCode===0&&r.toLowerCase().includes("dark"))return!1;if(t.exitCode!==0)return!0}catch{}let e=process.env.COLORFGBG??"";if(e.includes(";15")||e.endsWith(";7"))return!0;if(e.includes(";0")||e.endsWith(";8"))return!1;return!1}function yh(e){let t=wa(e);if(t==="system"){if(h_())return{...qd["solarized-light"],name:"system"};return qd.system}return qd[t]}function Tt(e){switch(e.toUpperCase()){case"HEALTHY":case"OK":return"\u2713";case"UNHEALTHY":case"WARNING":case"WARN":return"!";case"FAILED":case"ERROR":return"\u2717";case"STOPPED":case"UNKNOWN":return"\u25CB";case"RUNNING":case"STARTING":case"RESTARTING":return"\u25CF";default:return"\u25CB"}}function vn(e,t){return _i(e)>=Ci?Sa:t}function _i(e){let t=e.startsWith("#")?e.slice(1):e,r=Number.parseInt(t,__);if(Number.isNaN(r))return 0;let n=r>>R_&Vd,o=r>>P_&Vd,i=r&Vd;return(n*w_+o*S_+i*k_)/C_}function E_(e){let t=x_;for(let r=0;r<e.length;r+=1)t^=e.charCodeAt(r),t=Math.imul(t,b_);return t>>>0}function ka(e){return _i(e.background)>=Ci}function Yd(e){if(!e||!/^#[0-9a-f]{6}$/i.test(e))return!1;return _i(e)<Ci}function Ca(e,t){let r=T_[e];return ka(t)?r.light:r.dark}function vh(e,t){return _i(Ca(e,t))>=Ci?A_:L_}function He(e,t){if(e===""||e==="all")return t.muted;let r=_i(t.background)>=Ci?v_:y_;return r[E_(e)%r.length]??t.info}function D_(e,t){switch(t.toUpperCase()){case"ERROR":case"FATAL":return e.error;case"WARN":case"WARNING":return e.warning;case"INFO":return e.text;case"DEBUG":case"TRACE":return e.muted;default:return e.text}}function xh(e,t,r){if(r==="string")return e.accent;if(r==="number")return e.info;if(r==="keyword")return e.error;return D_(e,t)}function Re(e,t){switch(t.toUpperCase()){case"HEALTHY":case"OK":return e.success;case"UNHEALTHY":case"WARNING":case"WARN":return e.warning;case"FAILED":case"ERROR":return e.error;case"RUNNING":case"STARTING":case"RESTARTING":return e.primary;case"INFO":return e.info;case"FATAL":return e.error;case"DEBUG":case"TRACE":case"UNKNOWN":return e.muted;default:return e.muted}}var ht,Jd,qd,m_,y_,v_,x_=2166136261,b_=16777619,w_=299,S_=587,k_=114,C_=1000,Ci=160,__=16,Vd=255,R_=16,P_=8,Sa="#1A1A1A",T_,A_="#1A1A1A",L_="#F5F5F5";var ze=T(()=>{ht=["devctl","ember","tokyonight","catppuccin","catppuccin-latte","nord","gruvbox","kanagawa","dracula","onedark","monokai","solarized-dark","solarized-light","rose-pine","everforest","github-dark","iceberg","ayu-dark","oxocarbon","night-owl","terminal","voltage","voltage-light","ironclad","ironclad-light","signal","signal-light","system"],Jd={devctl:"amber + cyan, product theme",ember:"warm orange",tokyonight:"Tokyo Night storm blues",catppuccin:"Catppuccin Mocha","catppuccin-latte":"Catppuccin Latte (light)",nord:"Arctic Nord frost",gruvbox:"Gruvbox dark hard",kanagawa:"Kanagawa wave / gold",dracula:"classic Dracula purple",onedark:"Atom / VS Code One Dark",monokai:"Monokai Sublime","solarized-dark":"Solarized dark","solarized-light":"Solarized light","rose-pine":"Ros\xE9 Pine moon",everforest:"Everforest dark medium","github-dark":"GitHub dimmed canvas",iceberg:"Iceberg navy","ayu-dark":"Ayu Mirage-adjacent dark",oxocarbon:"IBM Oxocarbon","night-owl":"Sarah Drasner Night Owl",terminal:"black + VGA ANSI chrome",voltage:"max contrast, electric neon (dark)","voltage-light":"max contrast, electric neon (light)",ironclad:"max contrast, steel & amber (dark)","ironclad-light":"max contrast, steel & amber (light)",signal:"max contrast, traffic-light semantics (dark)","signal-light":"max contrast, traffic-light semantics (light)",system:"neutral dark (system default)"},qd={tokyonight:{name:"tokyonight",primary:"#82AAFF",accent:"#C792EA",error:"#FF5370",warning:"#FFCB6B",success:"#C3E88D",info:"#89DDFF",text:"#F4F7FF",muted:"#A8B2CC",background:"#0F111A",panel:"#1A1B2E",element:"#24283B",highlight:"#2E3350",inverse:"#0F111A",border:"#3D4466",borderActive:"#82AAFF"},catppuccin:{name:"catppuccin",primary:"#89B4FA",accent:"#F5C2E7",error:"#F38BA8",warning:"#F9E2AF",success:"#A6E3A1",info:"#89DCEB",text:"#E4E8F7",muted:"#A6A9BE",background:"#11111B",panel:"#1E1E2E",element:"#313244",highlight:"#45475A",inverse:"#11111B",border:"#585B70",borderActive:"#89B4FA"},"catppuccin-latte":{name:"catppuccin-latte",primary:"#1E66F5",accent:"#EA76CB",error:"#D20F39",warning:"#DF8E1D",success:"#40A02B",info:"#179299",text:"#4C4F69",muted:"#6C6F85",background:"#EFF1F5",panel:"#E6E9EF",element:"#DCE0E8",highlight:"#CCD0DA",inverse:"#EFF1F5",border:"#9CA0B0",borderActive:"#1E66F5"},nord:{name:"nord",primary:"#88C0D0",accent:"#B48EAD",error:"#BF616A",warning:"#EBCB8B",success:"#A3BE8C",info:"#8FBCBB",text:"#F2F5FA",muted:"#A4AEBF",background:"#2E3440",panel:"#3B4252",element:"#434C5E",highlight:"#4C566A",inverse:"#2E3440",border:"#5E6A7D",borderActive:"#88C0D0"},gruvbox:{name:"gruvbox",primary:"#FE8019",accent:"#FABD2F",error:"#FB4934",warning:"#FE8019",success:"#B8BB26",info:"#8EC07C",text:"#F2E5BC",muted:"#C4B394",background:"#1D2021",panel:"#282828",element:"#3C3836",highlight:"#504945",inverse:"#1D2021",border:"#665C54",borderActive:"#FE8019"},kanagawa:{name:"kanagawa",primary:"#7FB4CA",accent:"#E6C384",error:"#E82424",warning:"#FFA066",success:"#98BB6C",info:"#7FB4CA",text:"#E8E4C9",muted:"#B4C0D6",background:"#16161D",panel:"#1F1F28",element:"#2A2A37",highlight:"#363646",inverse:"#16161D",border:"#54546D",borderActive:"#E6C384"},dracula:{name:"dracula",primary:"#BD93F9",accent:"#FF79C6",error:"#FF5555",warning:"#F1FA8C",success:"#50FA7B",info:"#8BE9FD",text:"#F8F8F2",muted:"#6272A4",background:"#21222C",panel:"#282A36",element:"#343746",highlight:"#44475A",inverse:"#21222C",border:"#6272A4",borderActive:"#BD93F9"},onedark:{name:"onedark",primary:"#61AFEF",accent:"#C678DD",error:"#E06C75",warning:"#E5C07B",success:"#98C379",info:"#56B6C2",text:"#ABB2BF",muted:"#5C6370",background:"#21252B",panel:"#282C34",element:"#2C323C",highlight:"#3E4451",inverse:"#21252B",border:"#4B5263",borderActive:"#61AFEF"},monokai:{name:"monokai",primary:"#66D9EF",accent:"#AE81FF",error:"#F92672",warning:"#E6DB74",success:"#A6E22E",info:"#66D9EF",text:"#F8F8F2",muted:"#75715E",background:"#1D1E19",panel:"#272822",element:"#3E3D32",highlight:"#49483E",inverse:"#1D1E19",border:"#75715E",borderActive:"#F92672"},"solarized-dark":{name:"solarized-dark",primary:"#268BD2",accent:"#6C71C4",error:"#DC322F",warning:"#B58900",success:"#859900",info:"#2AA198",text:"#93A1A1",muted:"#586E75",background:"#002B36",panel:"#073642",element:"#0A4A58",highlight:"#1A5A68",inverse:"#002B36",border:"#586E75",borderActive:"#268BD2"},"solarized-light":{name:"solarized-light",primary:"#268BD2",accent:"#D33682",error:"#DC322F",warning:"#CB4B16",success:"#859900",info:"#2AA198",text:"#586E75",muted:"#839496",background:"#FDF6E3",panel:"#EEE8D5",element:"#E4DCC8",highlight:"#D5CDB6",inverse:"#FDF6E3",border:"#93A1A1",borderActive:"#268BD2"},"rose-pine":{name:"rose-pine",primary:"#C4A7E7",accent:"#EBBCBA",error:"#EB6F92",warning:"#F6C177",success:"#31748F",info:"#9CCFD8",text:"#E0DEF4",muted:"#908CAA",background:"#191724",panel:"#1F1D2E",element:"#26233A",highlight:"#403D52",inverse:"#191724",border:"#6E6A86",borderActive:"#C4A7E7"},everforest:{name:"everforest",primary:"#7FBBB3",accent:"#D699B6",error:"#E67E80",warning:"#DBBC7F",success:"#A7C080",info:"#83C092",text:"#D3C6AA",muted:"#9DA9A0",background:"#232A2E",panel:"#2D353B",element:"#343F44",highlight:"#3D484D",inverse:"#232A2E",border:"#4F585E",borderActive:"#A7C080"},"github-dark":{name:"github-dark",primary:"#58A6FF",accent:"#A371F7",error:"#F85149",warning:"#D29922",success:"#3FB950",info:"#79C0FF",text:"#E6EDF3",muted:"#8B949E",background:"#0D1117",panel:"#161B22",element:"#21262D",highlight:"#30363D",inverse:"#0D1117",border:"#30363D",borderActive:"#58A6FF"},iceberg:{name:"iceberg",primary:"#84A0C6",accent:"#A093C7",error:"#E27878",warning:"#E2A478",success:"#B4BE82",info:"#89B8C2",text:"#C6C8D1",muted:"#6B7089",background:"#161821",panel:"#1E2132",element:"#2A3150",highlight:"#3D425B",inverse:"#161821",border:"#444B71",borderActive:"#84A0C6"},"ayu-dark":{name:"ayu-dark",primary:"#59C2FF",accent:"#FFB454",error:"#D95757",warning:"#FF8F40",success:"#C2D94C",info:"#95E6CB",text:"#B3B1AD",muted:"#626A73",background:"#0A0E14",panel:"#0D1017",element:"#131721",highlight:"#1B212C",inverse:"#0A0E14",border:"#2D3640",borderActive:"#FFB454"},oxocarbon:{name:"oxocarbon",primary:"#78A9FF",accent:"#EE5396",error:"#FA4D56",warning:"#F1C21B",success:"#42BE65",info:"#3DDBD9",text:"#F2F4F8",muted:"#A8A8A8",background:"#161616",panel:"#262626",element:"#393939",highlight:"#525252",inverse:"#161616",border:"#6F6F6F",borderActive:"#78A9FF"},"night-owl":{name:"night-owl",primary:"#82AAFF",accent:"#C792EA",error:"#EF5350",warning:"#ECC48D",success:"#ADDB67",info:"#7FDBCA",text:"#D6DEEB",muted:"#637777",background:"#011627",panel:"#0B2942",element:"#1D3B53",highlight:"#1E4B6B",inverse:"#011627",border:"#5F7E97",borderActive:"#82AAFF"},terminal:{name:"terminal",primary:"#55FFFF",accent:"#FF55FF",error:"#FF5555",warning:"#FFFF55",success:"#55FF55",info:"#5555FF",text:"#C0C0C0",muted:"#808080",background:"#000000",panel:"#000000",element:"#000000",highlight:"#1A1A1A",inverse:"#000000",border:"#555555",borderActive:"#55FFFF"},voltage:{name:"voltage",primary:"#00E5FF",accent:"#FF3EA5",error:"#FF1744",warning:"#FFEA00",success:"#00E676",info:"#40C4FF",text:"#FFFFFF",muted:"#C0C0C0",background:"#000000",panel:"#000000",element:"#0D0D0D",highlight:"#262626",inverse:"#000000",border:"#808080",borderActive:"#FFFFFF"},"voltage-light":{name:"voltage-light",primary:"#0057B7",accent:"#C2185B",error:"#D50000",warning:"#FF6D00",success:"#2E7D32",info:"#00838F",text:"#000000",muted:"#424242",background:"#FFFFFF",panel:"#FFFFFF",element:"#EDEDED",highlight:"#D6D6D6",inverse:"#FFFFFF",border:"#616161",borderActive:"#000000"},ironclad:{name:"ironclad",primary:"#4FC3F7",accent:"#FFD54F",error:"#FF5252",warning:"#FFB300",success:"#69F0AE",info:"#64B5F6",text:"#FFFFFF",muted:"#BDBDBD",background:"#000000",panel:"#000000",element:"#101010",highlight:"#242424",inverse:"#000000",border:"#757575",borderActive:"#4FC3F7"},"ironclad-light":{name:"ironclad-light",primary:"#01579B",accent:"#E65100",error:"#B71C1C",warning:"#EF6C00",success:"#1B5E20",info:"#0277BD",text:"#000000",muted:"#4A4A4A",background:"#FFFFFF",panel:"#FFFFFF",element:"#EFEFEF",highlight:"#DADADA",inverse:"#FFFFFF",border:"#6E6E6E",borderActive:"#01579B"},signal:{name:"signal",primary:"#29B6F6",accent:"#AB47BC",error:"#FF0000",warning:"#FFC400",success:"#00E400",info:"#00B8D4",text:"#FFFFFF",muted:"#B3B3B3",background:"#000000",panel:"#000000",element:"#0A0A0A",highlight:"#202020",inverse:"#000000",border:"#8A8A8A",borderActive:"#29B6F6"},"signal-light":{name:"signal-light",primary:"#01579B",accent:"#6A1B9A",error:"#C62828",warning:"#F9A825",success:"#2E7D32",info:"#00796B",text:"#000000",muted:"#3D3D3D",background:"#FFFFFF",panel:"#FFFFFF",element:"#ECECEC",highlight:"#D2D2D2",inverse:"#FFFFFF",border:"#5C5C5C",borderActive:"#01579B"},system:{name:"system",primary:"#60A5FA",accent:"#C084FC",error:"#F87171",warning:"#FBBF24",success:"#34D399",info:"#22D3EE",text:"#F9FAFB",muted:"#C4CAD3",background:"#030712",panel:"#111827",element:"#1F2937",highlight:"#374151",inverse:"#030712",border:"#4B5563",borderActive:"#60A5FA"},devctl:{name:"devctl",primary:"#FFB020",accent:"#3DE0FF",error:"#FF5C7A",warning:"#FFD166",success:"#3DFF9A",info:"#3DE0FF",text:"#F7FAFD",muted:"#B7C3D0",background:"#070B10",panel:"#121A22",element:"#1C2833",highlight:"#243444",inverse:"#0A1016",border:"#334556",borderActive:"#FFB020"},ember:{name:"ember",primary:"#FF9F43",accent:"#2EE6FF",error:"#FF4D6D",warning:"#FFE566",success:"#3DFF9A",info:"#2EE6FF",text:"#F7F9FF",muted:"#B0B8CC",background:"#07090F",panel:"#12161F",element:"#1A2130",highlight:"#243044",inverse:"#0B0D12",border:"#334155",borderActive:"#FF9F43"}},m_={opencode:"ember",light:"system",mocha:"catppuccin",latte:"catppuccin-latte","one-dark":"onedark","one dark":"onedark",solarized:"solarized-dark",rosepine:"rose-pine","rose pine":"rose-pine",github:"github-dark",ayu:"ayu-dark","night owl":"night-owl",ansi:"terminal",xterm:"terminal",console:"terminal",classic:"terminal",vga:"terminal",contrast:"voltage","contrast-light":"voltage-light",hc:"voltage","hc-light":"voltage-light",a11y:"voltage","a11y-light":"voltage-light"};y_=["#7AA2F7","#9ECE6A","#E0AF68","#BB9AF7","#2AC3DE","#FF9E64","#F7768E","#73DACA","#C0CAF5","#FF79C6","#7DCFFF","#C3E88D"],v_=["#2E5AAC","#3D7A1F","#9A6B12","#6B3FA0","#0E7A86","#B85C1A","#B4234A","#1A7A6D","#4A5080","#9A3480","#1565C0","#4A7C19"];T_={claude:{dark:"#E08A6A",light:"#B54328"},cursor:{dark:"#B8D4FF",light:"#1E4EBF"},kilo:{dark:"#F0C94A",light:"#8A6400"},codex:{dark:"#4ADE80",light:"#0B7A4B"}}});function Sh(){return wi()!==void 0}function bh(e){let t=e/1000;if(Number.isInteger(t))return`${t}s`;return`${e}ms`}function Qd(e,t,r){let n=e.indexOf(t),i=((n<0?0:n)+r+e.length)%e.length;return e[i]??e[0]}function kh(e,t){let r=[...ht],n=r.includes(e)?e:Xd;return Qd(r,n,t)}function Ch(e,t){let r=[...M_],n=r.reduce((o,i)=>Math.abs(i-e)<Math.abs(o-e)?i:o,r[0]);return Qd(r,n,t)}function Ri(e){let t=[...zd];return t.reduce((r,n)=>Math.abs(n-e)<Math.abs(r-e)?n:r,t[0])}function Ra(e,t){return Qd([...zd],Ri(e),t)}function Pi(e){let t=Ri(e),r=wh[t]??wh[yn];return{px:t,...r}}function ur(e){return e.label==="compact"}function Ei(e){return e.steps<=2}function _h(e){return zd.map((r,n)=>n<e?"\u2588":"\u2591").join(" ")}function _a(e){return Pi(e).label}function Rh(e){let t=e.locked?"Applies this session only. DEVCTL_TUI_CONFIG overrides the user file.":`Saved to ${e.configPath}.`;return[{id:"theme",group:"Appearance",kind:"cycle",name:"Theme",value:e.themeName,hint:"\u2190 \u2192 save enter picker",detail:`Arrows write the theme to the user file. Enter opens the picker. ${t}`},{id:"font",group:"Appearance",kind:"cycle",name:"Display size",value:_a(e.fontSize),hint:"\u2190 \u2192 save",detail:`Scales content padding and list-row height. Default keeps a thin rule between chrome and panes. Compact sits toolbars flush against borders. Header, nav, and status stay one line. Does not change the terminal font. ${t}`},{id:"mouse",group:"Input",kind:"toggle",name:"Mouse",value:e.mouse?"on":"off",hint:"space or enter toggle",detail:`Clicks on nav and lists. Restart the TUI after a change. ${t}`},{id:"leader",group:"Input",kind:"cycle",name:"Leader",value:bh(e.leaderMs),hint:"\u2190 \u2192 save",detail:`How long ctrl+x waits for the next key. ${t}`},{id:"mcp",group:"MCP",kind:"page",name:"Settings page",value:e.mcpRunning?"running \u2192 /mcp":"off \u2192 /mcp",hint:"enter open the MCP page",detail:"Opens a dedicated MCP page (also /mcp or /agent). Start or stop the localhost server, change the port, and copy Claude, Cursor, Codex, and Kilo Code config."},{id:"file",group:"About",kind:"info",name:"File",value:e.configPath,hint:"read-only",detail:e.locked?`Using ${e.configPath} from DEVCTL_TUI_CONFIG.`:`User preferences live in ${e.configPath}.`},{id:"version",group:"About",kind:"info",name:"Version",value:at,hint:"read-only",detail:Pt()},{id:"reset",group:"About",kind:"action",name:"Reset",value:"defaults",hint:"enter confirm reset",detail:`Restore theme ${Xd}, display ${_a(yn)}, mouse on, leader ${bh(xa)}. Enter asks first. ${t}`}]}function Zd(){return{theme:Xd,mouse:!0,leader_timeout:xa,font_size:yn}}function Ph(e){return["Appearance","Input","MCP","About"].flatMap((r)=>{let n=e.filter((o)=>o.group===r);if(n.length===0)return[];return[{group:r,items:n}]})}function eu(e,t){if(e.length===0)return 0;return Math.min(Math.max(t,0),e.length-1)}function lo(e,t){return e[eu(e,t)]}function tu(){return wi()??ba()}var M_,zd,Xd="devctl",wh;var pr=T(()=>{ze();Vt();M_=[1000,2000,3000],zd=[12,14,16,18,20,22];wh={12:{pad:0,rowH:1,gap:0,steps:1,label:"compact"},14:{pad:0,rowH:1,gap:0,steps:2,label:"default"},16:{pad:1,rowH:1,gap:1,steps:3,label:"comfortable"},18:{pad:1,rowH:2,gap:1,steps:4,label:"large"},20:{pad:2,rowH:2,gap:1,steps:5,label:"xl"},22:{pad:2,rowH:2,gap:2,steps:6,label:"xxl"}}});import{createContext as O_,useContext as I_}from"react";function re(){return I_(ru)}var ru;var ot=T(()=>{pr();Vt();ru=O_(Pi(yn))});function $h(e,t=!0){let r=e<Ia?Eh+1:Eh,n=t?z_:0;return r+n+V_+n+J_+n+Y_+n}function Lr(e){return e.length+X_}function Fh(e,t){if(t<Z_)return ce(e,3);if(t<Q_)return ce(e,4);return e}function Nh(e,t,r){let n=e.length;if(n===0||r<=0)return{start:0,end:-1};let o=t>=0&&t<n?t:0,i=nu(e,o,r);if(i.start===0&&i.end===n-1)return i;let s=o>0?Pa:0,a=o<n-1?Pa:0,c=s+a,l=nu(e,o,Math.max(e[o]??0,r-c)),d=(s>0&&l.start===0?Pa:0)+(a>0&&l.end===n-1?Pa:0);if(d===0)return l;return nu(e,o,Math.max(e[o]??0,r-c+d))}function nu(e,t,r){let n=e.length,o=t,i=t,s=e[t]??0;if(s>=r)return{start:t,end:t};while(o>0||i<n-1){let a=o>0?e[o-1]??0:Number.POSITIVE_INFINITY,c=i<n-1?e[i+1]??0:Number.POSITIVE_INFINITY,l=o>0&&s+a<=r,d=i<n-1&&s+c<=r;if(!l&&!d)break;let g=t-(o-1),f=i+1-t;if(l&&(!d||g<=f))o-=1,s+=a;else if(d)i+=1,s+=c;else break}return{start:o,end:i}}function Hh(e){if(e==="detail")return Dr.findIndex((t)=>t.id==="services");return Dr.findIndex((t)=>t.id===e)}function ce(e,t){if(t<=0)return"";if(e.length<=t)return e;if(t===1)return"\u2026";return`${e.slice(0,t-1)}\u2026`}function uu(e){return e>=N_}function pu(e){return e>=H_}function fu(e){return e>=j_}function Fa(e,t=0){return Math.max(1,e-Ih-t*2)}function jh(e){let t=Mh+Jt+yt;if(uu(e))t+=fr;if(pu(e))t+=La;if(fu(e))t+=Mr;return Math.max(du,e-t)}function Uh(e,t,r){let n=r?Ah:eR+Ah+Math.max(0,t)*2;return Math.max(1,e-n)}function oR(e){if(e.startsWith('"')||e.startsWith("'"))return"string";if(/^\d+$/.test(e))return"number";return"keyword"}function ja(e,t){let r=Math.max(1,t),n=e.replace(/\r\n/g,`
|
|
610
|
+
`}function g_(e){return`codex mcp add --url ${e}`}function ki(e,t){return[{kind:"claude",title:"Claude",path:".mcp.json",language:"json",text:Ud(e,t),hint:"claude mcp add-json"},{kind:"cursor",title:"Cursor",path:".cursor/mcp.json",language:"json",text:Kd(e,t)},{kind:"kilo",title:"Kilo Code",path:"kilo.jsonc",language:"json",text:qd(e,t)},{kind:"codex",title:"Codex",path:"~/.codex/config.toml",language:"toml",text:Vd(e,t),hint:g_(e)}]}function hh(e,t){let r=[`URL ${e}`,""];for(let n of ki(e,t))r.push(`# ${n.title} ${n.path}${n.hint?` (${n.hint})`:""}`),r.push(n.text.trimEnd()),r.push("");return r.join(`
|
|
611
|
+
`)}function lo(){return[{name:"start",aliases:["up"],desc:"Start selected services or the current profile",leader:"n",group:"services"},{name:"stop",aliases:["down"],desc:"Stop selected services",leader:"x",group:"services"},{name:"restart",aliases:[],desc:"Restart selected services",leader:"R",group:"services"},{name:"services",aliases:["s"],desc:"Open the services screen",leader:"s",group:"nav"},{name:"logs",aliases:["l"],desc:"Open the log viewer",leader:"l",group:"nav"},{name:"auth",aliases:["identity","a"],desc:"Open identity; add refresh to probe accounts",leader:"a",group:"nav"},{name:"credentials",aliases:["creds"],desc:"Open credential store status",leader:"",group:"nav"},{name:"reload",aliases:[],desc:"Reload configuration",leader:"",group:"ui"},{name:"proxy",aliases:["p"],desc:"Open the proxy screen",leader:"p",group:"nav"},{name:"mcp",aliases:["agent"],desc:"Open the MCP server screen for coding agents",leader:"",group:"nav"},{name:"doctor",aliases:["d"],desc:"Run environment diagnostics",leader:"d",group:"nav"},{name:"stats",aliases:["metrics"],desc:"View system and service statistics",leader:"m",group:"nav"},{name:"config",aliases:["c"],desc:"View merged configuration",leader:"c",group:"nav"},{name:"profiles",aliases:["o"],desc:"Select a development profile",leader:"o",group:"nav"},{name:"setup",aliases:["init"],desc:"Open setup guidance",leader:"i",group:"nav"},{name:"dashboard",aliases:["home"],desc:"Return to the dashboard",leader:"h",group:"nav"},{name:"themes",aliases:["theme"],desc:"List available themes",leader:"t",group:"ui"},{name:"settings",aliases:["prefs","preferences"],desc:"Open TUI settings (theme, mouse, MCP page)",leader:"",group:"ui"},{name:"help",aliases:["?"],desc:"Show the help dialog",leader:"",group:"ui"},{name:"refresh",aliases:[],desc:"Refresh status and logs",leader:"r",group:"ui"},{name:"regex",aliases:[],desc:"Toggle regex log search",leader:"",group:"logs"},{name:"since",aliases:[],desc:"Filter logs after an ISO timestamp",leader:"",group:"logs"},{name:"until",aliases:[],desc:"Filter logs before an ISO timestamp",leader:"",group:"logs"},{name:"history",aliases:[],desc:"Load a persisted log session",leader:"",group:"logs"},{name:"edit",aliases:[],desc:"Open configuration in $EDITOR",leader:"",group:"ui"},{name:"buffer",aliases:[],desc:"Edit configuration in a validate/save buffer",leader:"",group:"ui"},{name:"pause",aliases:[],desc:"Pause or resume live logs",leader:"",group:"logs"},{name:"fullscreen",aliases:["zen","expand"],desc:"Expand logs to fill the terminal",leader:"z",group:"logs"},{name:"filter",aliases:[],desc:"Toggle ERROR+ log filter",leader:"",group:"logs"},{name:"system",aliases:["internal"],desc:"Show or hide internal auth/mcp/devctl/proxy logs",leader:"",group:"logs"},{name:"reveal",aliases:[],desc:"Reveal or hide secret environment values",leader:"",group:"ui"},{name:"wrap",aliases:[],desc:"Cycle log wrap: selected, all lines, or clip",leader:"",group:"logs"},{name:"copy",aliases:[],desc:"Copy visible logs to the clipboard",leader:"",group:"logs"},{name:"export",aliases:[],desc:"Write filtered logs to ~/.devctl/exports",leader:"e",group:"logs"},{name:"exports",aliases:["open-exports"],desc:"Open the log export folder",leader:"",group:"logs"},{name:"clear",aliases:["new"],desc:"Clear the on-screen log buffer",leader:"",group:"logs"},{name:"version",aliases:["v"],desc:"Show the current devctl version",leader:"",group:"app"},{name:"exit",aliases:["quit","q"],desc:"Exit",leader:"q",group:"app"}]}function yh(e){let t=e.trim().toLowerCase().replace(/^\//,"");return lo().filter((r)=>t===""||m_(r,t))}function m_(e,t){if(e.name.startsWith(t)||e.name.includes(t)||e.desc.toLowerCase().includes(t))return!0;return e.aliases.some((r)=>r.startsWith(t)||r===t)}function Ci(e){let t=e.trim().toLowerCase().replace(/^\//,"").split(" ")[0]??"";return lo().find((r)=>r.name===t||r.aliases.includes(t))}function vh(e){return e.trim().replace(/^\//,"").split(/\s+/).slice(1).filter((r)=>r!=="")}function xh(e){return lo().find((r)=>r.leader===e)?.name??""}function ka(e){let t=e.toLowerCase().trim(),r=h_[t];if(r)return r;return ht.includes(t)?t:"devctl"}function y_(){if(process.env.DEVCTL_THEME_LIGHT==="1")return!0;if(process.env.DEVCTL_THEME_LIGHT==="0")return!1;if(process.platform==="darwin")try{let t=Bun.spawnSync(["defaults","read","-g","AppleInterfaceStyle"],{stdout:"pipe",stderr:"pipe"}),r=t.stdout.toString();if(t.exitCode===0&&r.toLowerCase().includes("dark"))return!1;if(t.exitCode!==0)return!0}catch{}let e=process.env.COLORFGBG??"";if(e.includes(";15")||e.endsWith(";7"))return!0;if(e.includes(";0")||e.endsWith(";8"))return!1;return!1}function bh(e){let t=ka(e);if(t==="system"){if(y_())return{...Jd["solarized-light"],name:"system"};return Jd.system}return Jd[t]}function Tt(e){switch(e.toUpperCase()){case"HEALTHY":case"OK":return"\u2713";case"UNHEALTHY":case"WARNING":case"WARN":return"!";case"FAILED":case"ERROR":return"\u2717";case"STOPPED":case"UNKNOWN":return"\u25CB";case"RUNNING":case"STARTING":case"RESTARTING":return"\u25CF";default:return"\u25CB"}}function xn(e,t){return Pi(e)>=_i?Ca:t}function Pi(e){let t=e.startsWith("#")?e.slice(1):e,r=Number.parseInt(t,P_);if(Number.isNaN(r))return 0;let n=r>>R_&Yd,o=r>>E_&Yd,i=r&Yd;return(n*S_+o*k_+i*C_)/__}function T_(e){let t=b_;for(let r=0;r<e.length;r+=1)t^=e.charCodeAt(r),t=Math.imul(t,w_);return t>>>0}function _a(e){return Pi(e.background)>=_i}function Xd(e){if(!e||!/^#[0-9a-f]{6}$/i.test(e))return!1;return Pi(e)<_i}function Pa(e,t){let r=A_[e];return _a(t)?r.light:r.dark}function wh(e,t){return Pi(Pa(e,t))>=_i?L_:D_}function He(e,t){if(e===""||e==="all")return t.muted;let r=Pi(t.background)>=_i?x_:v_;return r[T_(e)%r.length]??t.info}function M_(e,t){switch(t.toUpperCase()){case"ERROR":case"FATAL":return e.error;case"WARN":case"WARNING":return e.warning;case"INFO":return e.text;case"DEBUG":case"TRACE":return e.muted;default:return e.text}}function Sh(e,t,r){if(r==="string")return e.accent;if(r==="number")return e.info;if(r==="keyword")return e.error;return M_(e,t)}function Pe(e,t){switch(t.toUpperCase()){case"HEALTHY":case"OK":return e.success;case"UNHEALTHY":case"WARNING":case"WARN":return e.warning;case"FAILED":case"ERROR":return e.error;case"RUNNING":case"STARTING":case"RESTARTING":return e.primary;case"INFO":return e.info;case"FATAL":return e.error;case"DEBUG":case"TRACE":case"UNKNOWN":return e.muted;default:return e.muted}}var ht,zd,Jd,h_,v_,x_,b_=2166136261,w_=16777619,S_=299,k_=587,C_=114,__=1000,_i=160,P_=16,Yd=255,R_=16,E_=8,Ca="#1A1A1A",A_,L_="#1A1A1A",D_="#F5F5F5";var ze=A(()=>{ht=["devctl","ember","tokyonight","catppuccin","catppuccin-latte","nord","gruvbox","kanagawa","dracula","onedark","monokai","solarized-dark","solarized-light","rose-pine","everforest","github-dark","iceberg","ayu-dark","oxocarbon","night-owl","terminal","voltage","voltage-light","ironclad","ironclad-light","signal","signal-light","system"],zd={devctl:"amber + cyan, product theme",ember:"warm orange",tokyonight:"Tokyo Night storm blues",catppuccin:"Catppuccin Mocha","catppuccin-latte":"Catppuccin Latte (light)",nord:"Arctic Nord frost",gruvbox:"Gruvbox dark hard",kanagawa:"Kanagawa wave / gold",dracula:"classic Dracula purple",onedark:"Atom / VS Code One Dark",monokai:"Monokai Sublime","solarized-dark":"Solarized dark","solarized-light":"Solarized light","rose-pine":"Ros\xE9 Pine moon",everforest:"Everforest dark medium","github-dark":"GitHub dimmed canvas",iceberg:"Iceberg navy","ayu-dark":"Ayu Mirage-adjacent dark",oxocarbon:"IBM Oxocarbon","night-owl":"Sarah Drasner Night Owl",terminal:"black + VGA ANSI chrome",voltage:"max contrast, electric neon (dark)","voltage-light":"max contrast, electric neon (light)",ironclad:"max contrast, steel & amber (dark)","ironclad-light":"max contrast, steel & amber (light)",signal:"max contrast, traffic-light semantics (dark)","signal-light":"max contrast, traffic-light semantics (light)",system:"neutral dark (system default)"},Jd={tokyonight:{name:"tokyonight",primary:"#82AAFF",accent:"#C792EA",error:"#FF5370",warning:"#FFCB6B",success:"#C3E88D",info:"#89DDFF",text:"#F4F7FF",muted:"#A8B2CC",background:"#0F111A",panel:"#1A1B2E",element:"#24283B",highlight:"#2E3350",inverse:"#0F111A",border:"#3D4466",borderActive:"#82AAFF"},catppuccin:{name:"catppuccin",primary:"#89B4FA",accent:"#F5C2E7",error:"#F38BA8",warning:"#F9E2AF",success:"#A6E3A1",info:"#89DCEB",text:"#E4E8F7",muted:"#A6A9BE",background:"#11111B",panel:"#1E1E2E",element:"#313244",highlight:"#45475A",inverse:"#11111B",border:"#585B70",borderActive:"#89B4FA"},"catppuccin-latte":{name:"catppuccin-latte",primary:"#1E66F5",accent:"#EA76CB",error:"#D20F39",warning:"#DF8E1D",success:"#40A02B",info:"#179299",text:"#4C4F69",muted:"#6C6F85",background:"#EFF1F5",panel:"#E6E9EF",element:"#DCE0E8",highlight:"#CCD0DA",inverse:"#EFF1F5",border:"#9CA0B0",borderActive:"#1E66F5"},nord:{name:"nord",primary:"#88C0D0",accent:"#B48EAD",error:"#BF616A",warning:"#EBCB8B",success:"#A3BE8C",info:"#8FBCBB",text:"#F2F5FA",muted:"#A4AEBF",background:"#2E3440",panel:"#3B4252",element:"#434C5E",highlight:"#4C566A",inverse:"#2E3440",border:"#5E6A7D",borderActive:"#88C0D0"},gruvbox:{name:"gruvbox",primary:"#FE8019",accent:"#FABD2F",error:"#FB4934",warning:"#FE8019",success:"#B8BB26",info:"#8EC07C",text:"#F2E5BC",muted:"#C4B394",background:"#1D2021",panel:"#282828",element:"#3C3836",highlight:"#504945",inverse:"#1D2021",border:"#665C54",borderActive:"#FE8019"},kanagawa:{name:"kanagawa",primary:"#7FB4CA",accent:"#E6C384",error:"#E82424",warning:"#FFA066",success:"#98BB6C",info:"#7FB4CA",text:"#E8E4C9",muted:"#B4C0D6",background:"#16161D",panel:"#1F1F28",element:"#2A2A37",highlight:"#363646",inverse:"#16161D",border:"#54546D",borderActive:"#E6C384"},dracula:{name:"dracula",primary:"#BD93F9",accent:"#FF79C6",error:"#FF5555",warning:"#F1FA8C",success:"#50FA7B",info:"#8BE9FD",text:"#F8F8F2",muted:"#6272A4",background:"#21222C",panel:"#282A36",element:"#343746",highlight:"#44475A",inverse:"#21222C",border:"#6272A4",borderActive:"#BD93F9"},onedark:{name:"onedark",primary:"#61AFEF",accent:"#C678DD",error:"#E06C75",warning:"#E5C07B",success:"#98C379",info:"#56B6C2",text:"#ABB2BF",muted:"#5C6370",background:"#21252B",panel:"#282C34",element:"#2C323C",highlight:"#3E4451",inverse:"#21252B",border:"#4B5263",borderActive:"#61AFEF"},monokai:{name:"monokai",primary:"#66D9EF",accent:"#AE81FF",error:"#F92672",warning:"#E6DB74",success:"#A6E22E",info:"#66D9EF",text:"#F8F8F2",muted:"#75715E",background:"#1D1E19",panel:"#272822",element:"#3E3D32",highlight:"#49483E",inverse:"#1D1E19",border:"#75715E",borderActive:"#F92672"},"solarized-dark":{name:"solarized-dark",primary:"#268BD2",accent:"#6C71C4",error:"#DC322F",warning:"#B58900",success:"#859900",info:"#2AA198",text:"#93A1A1",muted:"#586E75",background:"#002B36",panel:"#073642",element:"#0A4A58",highlight:"#1A5A68",inverse:"#002B36",border:"#586E75",borderActive:"#268BD2"},"solarized-light":{name:"solarized-light",primary:"#268BD2",accent:"#D33682",error:"#DC322F",warning:"#CB4B16",success:"#859900",info:"#2AA198",text:"#586E75",muted:"#839496",background:"#FDF6E3",panel:"#EEE8D5",element:"#E4DCC8",highlight:"#D5CDB6",inverse:"#FDF6E3",border:"#93A1A1",borderActive:"#268BD2"},"rose-pine":{name:"rose-pine",primary:"#C4A7E7",accent:"#EBBCBA",error:"#EB6F92",warning:"#F6C177",success:"#31748F",info:"#9CCFD8",text:"#E0DEF4",muted:"#908CAA",background:"#191724",panel:"#1F1D2E",element:"#26233A",highlight:"#403D52",inverse:"#191724",border:"#6E6A86",borderActive:"#C4A7E7"},everforest:{name:"everforest",primary:"#7FBBB3",accent:"#D699B6",error:"#E67E80",warning:"#DBBC7F",success:"#A7C080",info:"#83C092",text:"#D3C6AA",muted:"#9DA9A0",background:"#232A2E",panel:"#2D353B",element:"#343F44",highlight:"#3D484D",inverse:"#232A2E",border:"#4F585E",borderActive:"#A7C080"},"github-dark":{name:"github-dark",primary:"#58A6FF",accent:"#A371F7",error:"#F85149",warning:"#D29922",success:"#3FB950",info:"#79C0FF",text:"#E6EDF3",muted:"#8B949E",background:"#0D1117",panel:"#161B22",element:"#21262D",highlight:"#30363D",inverse:"#0D1117",border:"#30363D",borderActive:"#58A6FF"},iceberg:{name:"iceberg",primary:"#84A0C6",accent:"#A093C7",error:"#E27878",warning:"#E2A478",success:"#B4BE82",info:"#89B8C2",text:"#C6C8D1",muted:"#6B7089",background:"#161821",panel:"#1E2132",element:"#2A3150",highlight:"#3D425B",inverse:"#161821",border:"#444B71",borderActive:"#84A0C6"},"ayu-dark":{name:"ayu-dark",primary:"#59C2FF",accent:"#FFB454",error:"#D95757",warning:"#FF8F40",success:"#C2D94C",info:"#95E6CB",text:"#B3B1AD",muted:"#626A73",background:"#0A0E14",panel:"#0D1017",element:"#131721",highlight:"#1B212C",inverse:"#0A0E14",border:"#2D3640",borderActive:"#FFB454"},oxocarbon:{name:"oxocarbon",primary:"#78A9FF",accent:"#EE5396",error:"#FA4D56",warning:"#F1C21B",success:"#42BE65",info:"#3DDBD9",text:"#F2F4F8",muted:"#A8A8A8",background:"#161616",panel:"#262626",element:"#393939",highlight:"#525252",inverse:"#161616",border:"#6F6F6F",borderActive:"#78A9FF"},"night-owl":{name:"night-owl",primary:"#82AAFF",accent:"#C792EA",error:"#EF5350",warning:"#ECC48D",success:"#ADDB67",info:"#7FDBCA",text:"#D6DEEB",muted:"#637777",background:"#011627",panel:"#0B2942",element:"#1D3B53",highlight:"#1E4B6B",inverse:"#011627",border:"#5F7E97",borderActive:"#82AAFF"},terminal:{name:"terminal",primary:"#55FFFF",accent:"#FF55FF",error:"#FF5555",warning:"#FFFF55",success:"#55FF55",info:"#5555FF",text:"#C0C0C0",muted:"#808080",background:"#000000",panel:"#000000",element:"#000000",highlight:"#1A1A1A",inverse:"#000000",border:"#555555",borderActive:"#55FFFF"},voltage:{name:"voltage",primary:"#00E5FF",accent:"#FF3EA5",error:"#FF1744",warning:"#FFEA00",success:"#00E676",info:"#40C4FF",text:"#FFFFFF",muted:"#C0C0C0",background:"#000000",panel:"#000000",element:"#0D0D0D",highlight:"#262626",inverse:"#000000",border:"#808080",borderActive:"#FFFFFF"},"voltage-light":{name:"voltage-light",primary:"#0057B7",accent:"#C2185B",error:"#D50000",warning:"#FF6D00",success:"#2E7D32",info:"#00838F",text:"#000000",muted:"#424242",background:"#FFFFFF",panel:"#FFFFFF",element:"#EDEDED",highlight:"#D6D6D6",inverse:"#FFFFFF",border:"#616161",borderActive:"#000000"},ironclad:{name:"ironclad",primary:"#4FC3F7",accent:"#FFD54F",error:"#FF5252",warning:"#FFB300",success:"#69F0AE",info:"#64B5F6",text:"#FFFFFF",muted:"#BDBDBD",background:"#000000",panel:"#000000",element:"#101010",highlight:"#242424",inverse:"#000000",border:"#757575",borderActive:"#4FC3F7"},"ironclad-light":{name:"ironclad-light",primary:"#01579B",accent:"#E65100",error:"#B71C1C",warning:"#EF6C00",success:"#1B5E20",info:"#0277BD",text:"#000000",muted:"#4A4A4A",background:"#FFFFFF",panel:"#FFFFFF",element:"#EFEFEF",highlight:"#DADADA",inverse:"#FFFFFF",border:"#6E6E6E",borderActive:"#01579B"},signal:{name:"signal",primary:"#29B6F6",accent:"#AB47BC",error:"#FF0000",warning:"#FFC400",success:"#00E400",info:"#00B8D4",text:"#FFFFFF",muted:"#B3B3B3",background:"#000000",panel:"#000000",element:"#0A0A0A",highlight:"#202020",inverse:"#000000",border:"#8A8A8A",borderActive:"#29B6F6"},"signal-light":{name:"signal-light",primary:"#01579B",accent:"#6A1B9A",error:"#C62828",warning:"#F9A825",success:"#2E7D32",info:"#00796B",text:"#000000",muted:"#3D3D3D",background:"#FFFFFF",panel:"#FFFFFF",element:"#ECECEC",highlight:"#D2D2D2",inverse:"#FFFFFF",border:"#5C5C5C",borderActive:"#01579B"},system:{name:"system",primary:"#60A5FA",accent:"#C084FC",error:"#F87171",warning:"#FBBF24",success:"#34D399",info:"#22D3EE",text:"#F9FAFB",muted:"#C4CAD3",background:"#030712",panel:"#111827",element:"#1F2937",highlight:"#374151",inverse:"#030712",border:"#4B5563",borderActive:"#60A5FA"},devctl:{name:"devctl",primary:"#FFB020",accent:"#3DE0FF",error:"#FF5C7A",warning:"#FFD166",success:"#3DFF9A",info:"#3DE0FF",text:"#F7FAFD",muted:"#B7C3D0",background:"#070B10",panel:"#121A22",element:"#1C2833",highlight:"#243444",inverse:"#0A1016",border:"#334556",borderActive:"#FFB020"},ember:{name:"ember",primary:"#FF9F43",accent:"#2EE6FF",error:"#FF4D6D",warning:"#FFE566",success:"#3DFF9A",info:"#2EE6FF",text:"#F7F9FF",muted:"#B0B8CC",background:"#07090F",panel:"#12161F",element:"#1A2130",highlight:"#243044",inverse:"#0B0D12",border:"#334155",borderActive:"#FF9F43"}},h_={opencode:"ember",light:"system",mocha:"catppuccin",latte:"catppuccin-latte","one-dark":"onedark","one dark":"onedark",solarized:"solarized-dark",rosepine:"rose-pine","rose pine":"rose-pine",github:"github-dark",ayu:"ayu-dark","night owl":"night-owl",ansi:"terminal",xterm:"terminal",console:"terminal",classic:"terminal",vga:"terminal",contrast:"voltage","contrast-light":"voltage-light",hc:"voltage","hc-light":"voltage-light",a11y:"voltage","a11y-light":"voltage-light"};v_=["#7AA2F7","#9ECE6A","#E0AF68","#BB9AF7","#2AC3DE","#FF9E64","#F7768E","#73DACA","#C0CAF5","#FF79C6","#7DCFFF","#C3E88D"],x_=["#2E5AAC","#3D7A1F","#9A6B12","#6B3FA0","#0E7A86","#B85C1A","#B4234A","#1A7A6D","#4A5080","#9A3480","#1565C0","#4A7C19"];A_={claude:{dark:"#E08A6A",light:"#B54328"},cursor:{dark:"#B8D4FF",light:"#1E4EBF"},kilo:{dark:"#F0C94A",light:"#8A6400"},codex:{dark:"#4ADE80",light:"#0B7A4B"}}});function _h(){return Si()!==void 0}function kh(e){let t=e/1000;if(Number.isInteger(t))return`${t}s`;return`${e}ms`}function eu(e,t,r){let n=e.indexOf(t),i=((n<0?0:n)+r+e.length)%e.length;return e[i]??e[0]}function Ph(e,t){let r=[...ht],n=r.includes(e)?e:Zd;return eu(r,n,t)}function Rh(e,t){let r=[...O_],n=r.reduce((o,i)=>Math.abs(i-e)<Math.abs(o-e)?i:o,r[0]);return eu(r,n,t)}function Ri(e){let t=[...Qd];return t.reduce((r,n)=>Math.abs(n-e)<Math.abs(r-e)?n:r,t[0])}function Ea(e,t){return eu([...Qd],Ri(e),t)}function Ei(e){let t=Ri(e),r=Ch[t]??Ch[vn];return{px:t,...r}}function ur(e){return e.label==="compact"}function Ti(e){return e.steps<=2}function Eh(e){return Qd.map((r,n)=>n<e?"\u2588":"\u2591").join(" ")}function Ra(e){return Ei(e).label}function Th(e){let t=e.locked?"Applies this session only. DEVCTL_TUI_CONFIG overrides the user file.":`Saved to ${e.configPath}.`;return[{id:"theme",group:"Appearance",kind:"cycle",name:"Theme",value:e.themeName,hint:"\u2190 \u2192 save enter picker",detail:`Arrows write the theme to the user file. Enter opens the picker. ${t}`},{id:"font",group:"Appearance",kind:"cycle",name:"Display size",value:Ra(e.fontSize),hint:"\u2190 \u2192 save",detail:`Scales content padding and list-row height. Default keeps a thin rule between chrome and panes. Compact sits toolbars flush against borders. Header, nav, and status stay one line. Does not change the terminal font. ${t}`},{id:"mouse",group:"Input",kind:"toggle",name:"Mouse",value:e.mouse?"on":"off",hint:"space or enter toggle",detail:`Clicks on nav and lists. Restart the TUI after a change. ${t}`},{id:"leader",group:"Input",kind:"cycle",name:"Leader",value:kh(e.leaderMs),hint:"\u2190 \u2192 save",detail:`How long ctrl+x waits for the next key. ${t}`},{id:"mcp",group:"MCP",kind:"page",name:"Settings page",value:e.mcpRunning?"running \u2192 /mcp":"off \u2192 /mcp",hint:"enter open the MCP page",detail:"Opens a dedicated MCP page (also /mcp or /agent). Start or stop the localhost server, change the port, and copy Claude, Cursor, Codex, and Kilo Code config."},{id:"file",group:"About",kind:"info",name:"File",value:e.configPath,hint:"read-only",detail:e.locked?`Using ${e.configPath} from DEVCTL_TUI_CONFIG.`:`User preferences live in ${e.configPath}.`},{id:"version",group:"About",kind:"info",name:"Version",value:at,hint:"read-only",detail:Rt()},{id:"reset",group:"About",kind:"action",name:"Reset",value:"defaults",hint:"enter confirm reset",detail:`Restore theme ${Zd}, display ${Ra(vn)}, mouse on, leader ${kh(wa)}. Enter asks first. ${t}`}]}function tu(){return{theme:Zd,mouse:!0,leader_timeout:wa,font_size:vn}}function Ah(e){return["Appearance","Input","MCP","About"].flatMap((r)=>{let n=e.filter((o)=>o.group===r);if(n.length===0)return[];return[{group:r,items:n}]})}function ru(e,t){if(e.length===0)return 0;return Math.min(Math.max(t,0),e.length-1)}function uo(e,t){return e[ru(e,t)]}function nu(){return Si()??Sa()}var O_,Qd,Zd="devctl",Ch;var pr=A(()=>{ze();Vt();O_=[1000,2000,3000],Qd=[12,14,16,18,20,22];Ch={12:{pad:0,rowH:1,gap:0,steps:1,label:"compact"},14:{pad:0,rowH:1,gap:0,steps:2,label:"default"},16:{pad:1,rowH:1,gap:1,steps:3,label:"comfortable"},18:{pad:1,rowH:2,gap:1,steps:4,label:"large"},20:{pad:2,rowH:2,gap:1,steps:5,label:"xl"},22:{pad:2,rowH:2,gap:2,steps:6,label:"xxl"}}});import{createContext as I_,useContext as $_}from"react";function re(){return $_(ou)}var ou;var ot=A(()=>{pr();Vt();ou=I_(Ei(vn))});function Hh(e,t=!0){let r=e<Fa?Lh+1:Lh,n=t?X_:0;return r+n+J_+n+Y_+n+z_+n}function Lr(e){return e.length+Q_}function jh(e,t){if(t<eP)return le(e,3);if(t<Z_)return le(e,4);return e}function Bh(e,t,r){let n=e.length;if(n===0||r<=0)return{start:0,end:-1};let o=t>=0&&t<n?t:0,i=iu(e,o,r);if(i.start===0&&i.end===n-1)return i;let s=o>0?Ta:0,a=o<n-1?Ta:0,c=s+a,l=iu(e,o,Math.max(e[o]??0,r-c)),d=(s>0&&l.start===0?Ta:0)+(a>0&&l.end===n-1?Ta:0);if(d===0)return l;return iu(e,o,Math.max(e[o]??0,r-c+d))}function iu(e,t,r){let n=e.length,o=t,i=t,s=e[t]??0;if(s>=r)return{start:t,end:t};while(o>0||i<n-1){let a=o>0?e[o-1]??0:Number.POSITIVE_INFINITY,c=i<n-1?e[i+1]??0:Number.POSITIVE_INFINITY,l=o>0&&s+a<=r,d=i<n-1&&s+c<=r;if(!l&&!d)break;let g=t-(o-1),f=i+1-t;if(l&&(!d||g<=f))o-=1,s+=a;else if(d)i+=1,s+=c;else break}return{start:o,end:i}}function Wh(e){if(e==="detail")return Dr.findIndex((t)=>t.id==="services");return Dr.findIndex((t)=>t.id===e)}function le(e,t){if(t<=0)return"";if(e.length<=t)return e;if(t===1)return"\u2026";return`${e.slice(0,t-1)}\u2026`}function fu(e){return e>=H_}function gu(e){return e>=j_}function mu(e){return e>=B_}function Ha(e,t=0){return Math.max(1,e-Nh-t*2)}function Gh(e){let t=$h+Jt+yt;if(fu(e))t+=fr;if(gu(e))t+=Ma;if(mu(e))t+=Mr;return Math.max(pu,e-t)}function Vh(e,t,r){let n=r?Mh:tP+Mh+Math.max(0,t)*2;return Math.max(1,e-n)}function iP(e){if(e.startsWith('"')||e.startsWith("'"))return"string";if(/^\d+$/.test(e))return"number";return"keyword"}function Wa(e,t){let r=Math.max(1,t),n=e.replace(/\r\n/g,`
|
|
612
612
|
`).replace(/\r/g,`
|
|
613
613
|
`).split(`
|
|
614
|
-
`),o=[];for(let i of n)if(i.length<=r)o.push(i);else o.push(...iR(i,r));return o.length>0?o:[""]}function Kh(e,t,r){let n=e.length>0?[...e]:[""];if(r||n.length<=1)return{visible:n,mark:"",folded:!1,hidden:0};let o=n.length-1,i=` ${tR}${o}`,s=Math.max(1,t-i.length);return{visible:[ce(n[0]??"",s)],mark:i,folded:!0,hidden:o}}function qh(e,t){return e==="all"||e==="focus"&&t}function gu(e){if(e==="clip")return"focus";if(e==="focus")return"all";return"clip"}function Vh(e,t,r,n=bn){if(e.length===0)return{start:0,items:[],newer:0};if(!t){let a=Math.max(0,e.length-n);return{start:a,items:e.slice(a),newer:0}}let o=e.length-1,i=Math.max(0,Math.min(r,o)),s=e.slice(i,i+n);return{start:i,items:s,newer:Math.max(0,e.length-i-s.length)}}function mu(e,t=bn){return Math.max(0,e-t)}function hu(e,t,r,n){let o=Math.max(t-1,0);if(e<0&&r>0)return{selected:0,startDelta:Math.max(-r,e)};if(e>o&&n>0)return{selected:o,startDelta:Math.min(n,e-o)};return{selected:Math.min(o,Math.max(0,e)),startDelta:0}}function Ai(e){if(e==="all")return"wrap all";if(e==="focus")return"wrap selected";return"clip"}function iR(e,t){let r=[],n=e;while(n.length>t){let o=n.slice(0,t),i=sR(o);if(i>0)r.push(n.slice(0,i).trimEnd()),n=n.slice(i).trimStart();else r.push(n.slice(0,t)),n=n.slice(t)}if(n.length>0)r.push(n);return r}function sR(e){let t=e.lastIndexOf(" "),r=e.lastIndexOf("\t"),n=e.lastIndexOf(","),o=Math.max(t,r,n);if(o<Math.floor(e.length*rR))return-1;return e[o]===","?o+1:o}function Jh(e){let t=[],r=new RegExp(nR.source,"gi"),n=0,o=r.exec(e);while(o){let i=o[0]??"";if(o.index>n)t.push({text:e.slice(n,o.index),kind:"text"});t.push({text:i,kind:oR(i)}),n=o.index+i.length,o=r.exec(e)}if(n<e.length)t.push({text:e.slice(n),kind:"text"});if(t.length===0)return[{text:e,kind:"text"}];return t}function Yh(e){let t=e.showTimestamps?Na:0,r=e.showMeta?$a:0;return Math.max(Bh,e.width-t-e.serviceWidth-Ha-r-Wh-Ti*Gh)}function Li(e){return Math.max(U_,e-K_*2)}function zh(e){let t=e.width<W_,r=e.proxyOn?`\u25CF ${ce(e.proxyAddress,t?10:18)}`:t?"":"\u25CB off";return[{label:t?`${e.running}/${e.total}`:vu(e.running,e.total),tone:e.running>0?"success":"idle"},{label:r,tone:e.proxyOn?"info":"idle",hide:t&&!e.proxyOn},{label:"MCP",tone:"info",hide:!e.mcpOn},{label:e.adc?t?"ADC":"ADC ok":t?"!ADC":"ADC missing",tone:e.adc?"success":"error"},{label:t?"sec":"secrets shown",tone:"warning",hide:!e.reveal}]}function Xh(e,t){let r=t.reduce((s,a)=>Math.max(s,a.length),0),n=Na+Ha+Wh+Bh+Ti*Gh,o=Math.max(Th,e-n),i=Math.max(Th,r);return Math.min(Oh,o,i)}function Ba(e,t,r){if(r)return e;let n=t.reduce((a,c)=>Math.max(a,c.length),0),o=Math.min(Oh,Math.max(du,n+$_)),i=Mh+Jt+yt+o+Ih+F_,s=Math.max(Ta,Math.floor(e*B_));return Math.min(s,Math.max(Ta,i))}function Y(e,t){if(t<=0)return"";if(e.length>=t)return ce(e,t);return e.padEnd(t)}function po(e,t){let r=[],n=0;for(let o of e){let i=o.key.length+o.label.length+3;if(n+i>t)break;r.push(o),n+=i}return r}function Qh(e){return e<q_}function fo(e,t,r,n,o="center",i=!0){let s=Math.min(r,Math.max(1,e-4)),a=Math.min($h(e,i),Math.max(0,t-1)),c=Math.min(n,Math.max(1,t-a)),l=Math.max(0,Math.min(Math.floor((e-s)/2),Math.max(0,e-s))),d=o==="bottom"?t-2-c:Math.floor((t-c)/2),g=Math.max(0,Math.min(d,t-c));return{left:l,top:g,width:s,height:c}}function Zh(e){if(e==="")return"idle";if(cR.test(e))return"error";if(e.includes("session only"))return"warning";if(aR.test(e))return"success";return"info"}function ey(e,t,r){let n=r!==""&&e.profiles[r]?r:"";if(t.length>0)return{services:t,profile:n};if(n!=="")return{services:[...e.profiles[r]?.services??[]],profile:n};return{services:Object.keys(e.services),profile:""}}function ty(e,t){if(e==="doctor")return t.doctor;if(e==="settings")return t.settings;if(e==="profiles")return t.profiles;if(e==="dashboard"||e==="services")return t.services;if(e==="logs")return t.logs??0;if(e==="mcp")return t.mcp??0;if(e==="setup")return G_;return 0}function ry(e){if(e==="0")return Dr[9]?.id;if(e.length===1&&e>="1"&&e<="9")return Dr[Number(e)-1]?.id;return}function Wa(e){if(!e)return"";return Object.keys(e.profiles).sort()[0]??""}function Ga(e){return lR.has(e)}function Di(e){if(!e)return!1;return Ga(e.state)}function Ua(e,t){let r=t??Object.keys(e?.services??{});return{running:r.filter((o)=>Di(e?.services[o])).length,total:r.length}}function ny(e,t){let r=0,n=0,o=0,i=0,s=0,a=0;for(let c of e){let l=t?.services[c];if(l?.health==="HEALTHY")o+=1;let d=l?.state??"STOPPED";if(d==="FAILED")i+=1;else if(d==="STOPPING")s+=1;else if(d==="STARTING"||d==="RESTARTING")n+=1;else if(Ga(d))r+=1;else a+=1}return{total:e.length,live:r+n,running:r,starting:n,healthy:o,failed:i,stopping:s,stopped:a}}function oy(e,t){if(!Number.isFinite(e)||!Number.isFinite(t)||t<=0)return 0;return e/t}function mR(e,t,r){if(!Number.isFinite(e))return"success";if(e>r)return"error";if(e>t)return"warning";return"success"}function hR(e,t){return mR(oy(e,t),dR,uR)}function yR(e,t){let r=t>0?e/t:1;if(r<fR)return"error";if(r<pR)return"warning";return"success"}function ou(e){if(!Number.isFinite(e)||e<0)return"\u2014";return e.toFixed(2)}function vR(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${Math.round(e*100)}%`}function iy(e,t=Date.now()){if(!e?.startTime)return"\u2014";let r=new Date(e.startTime).getTime();if(!Number.isFinite(r))return"\u2014";return mo(t-r)}function sy(e,t=gR){return Object.entries(e).sort((r,n)=>n[1]-r[1]||r[0].localeCompare(n[0])).slice(0,t)}function ay(e,t=1){return Math.max(24,e-_R-t*2-RR-PR-ER)}function cy(e){let t=e>=xR,r=e>=bR,n=e>=wR,o=e>=SR,i=e>=kR,s=e>=CR,a=Jt+yt;if(t)a+=fr+yt;if(r)a+=Ma+yt;if(n)a+=Oa+yt;if(o)a+=Da+yt;if(i)a+=Ka+yt;if(s)a+=Mr;return{name:Math.max(du,e-a),health:t,cpu:r,mem:n,up:o,rst:i,pid:s}}function ly(e){let t=Number.isFinite(e)&&e>0?e:0;return{ratio:Math.min(1,t),label:vR(t)}}function dy(e,t=LR){return`[${Mi(e.ratio,t)}] ${e.label.padStart(4)}`}function yu(e,t){let r=e.reduce((l,d)=>Math.max(l,d.what.length),4),n=e.reduce((l,d)=>Math.max(l,d.reading.length),7),o=e.some((l)=>l.meter)?DR:0,i=go*(o>0?3:2),s=Math.min(TR,Math.max(iu,r)),a=Math.min(AR,Math.max(su,n)),c=t-s-a-o-i;if(c<Ea&&a>su)a=Math.max(su,a-(Ea-c)),c=t-s-a-o-i;if(c<Ea&&s>iu)s=Math.max(iu,s-(Ea-c)),c=t-s-a-o-i;return{what:s,reading:a,meaning:Math.max(0,c),meter:o}}function uy(e){return MR.has((e?.health.type??"").toLowerCase())}function py(e){if(e==="darwin")return"macOS";if(e==="win32")return"Windows";if(e==="linux")return"Linux";return e||"this computer"}function fy(e,t){let r=Math.max(1,t),n=hR(e,r),o=n==="error"?"overloaded":n==="warning"?"busy":"not busy",i=n==="error"?`${r} cores are queued up \u2014 last minute ${ou(e)}`:n==="warning"?`${r} cores nearly full \u2014 last minute ${ou(e)}`:`${r} cores. Last minute ${ou(e)} (under ${r} is fine)`;return{what:"CPU work",reading:o,meaning:i,tone:n,meter:ly(oy(e,r))}}function gy(e,t){let r=yR(e,t),n=`${Aa(e)} of ${Aa(t)}`,o=r==="error"?"Almost no RAM left for new work":r==="warning"?"RAM is getting tight":"RAM the computer can still give out",i=t>0?Math.max(0,(t-e)/t):0;return{what:"RAM leftover",reading:n,meaning:o,tone:r,meter:ly(i)}}function my(e){let t=e?.state??"STOPPED";if(t==="FAILED")return"crashed";if(t==="STOPPING")return"stopping";if(t==="STARTING"||t==="RESTARTING")return"starting";if(Ga(t))return"up";return"off"}function hy(e){if(!e||!Ga(e.state))return"\u2014";if(e.health==="HEALTHY")return"ready";if(e.health==="UNHEALTHY")return"failing";if(e.state==="STARTING"||e.state==="RESTARTING")return"waiting";return"checking"}function yy(e){if(e==="keychain")return"password store";if(e==="file")return"local file";return e||"unknown store"}function vy(e,t){let r=[{what:"Started",reading:String(e.live),meaning:e.live===0?"nothing is running yet":"process is up",tone:e.live>0?"success":"muted"}];if(t)r.push({what:"Ready",reading:String(e.healthy),meaning:e.live===0?"start services first":"passed their health check",tone:e.live>0&&e.healthy<e.live?"warning":e.healthy>0?"success":"muted"});if(e.starting>0)r.push({what:"Still starting",reading:String(e.starting),meaning:"not ready for traffic yet",tone:"warning"});if(e.stopping>0)r.push({what:"Stopping",reading:String(e.stopping),meaning:"shutting down",tone:"warning"});return r.push({what:"Crashed",reading:String(e.failed),meaning:e.failed>0?"open the service for the error":"none",tone:e.failed>0?"error":"muted"}),r.push({what:"Not started",reading:String(e.stopped),meaning:e.stopped>0?"off until you start them":"all are up",tone:"muted"}),r}function Mi(e,t=20){let r=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0,n=Math.round(r*t);return"\u2588".repeat(n)+"\u2591".repeat(Math.max(0,t-n))}function mo(e){if(!Number.isFinite(e)||e<au)return"< 1s";let t=Math.floor(e/Lh),r=Math.floor(e%Lh/lu),n=Math.floor(e%lu/cu),o=Math.floor(e%cu/au);if(t>0)return`${t}d ${r}h`;if(r>0)return`${r}h ${n}m`;if(n>0)return`${n}m ${String(o).padStart(2,"0")}s`;return`${o}s`}function Aa(e){if(!Number.isFinite(e)||e<0)return"\u2014";let t=e/OR;if(t>=Dh)return`${(t/Dh).toFixed(1)}G`;if(t>=1)return`${Math.round(t)}M`;return`${Math.round(e)}K`}function xy(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${e.toFixed(1)}%`}function ho(e){if(!e)return!0;let t=Object.values(e.services);if(t.length===0)return!0;return!t.some((r)=>Di(r))}function by(e,t){if(e.length>0)return e;return[...t]}function qa(e,t){if(e.length>0)return[...e];return t===""?[]:[t]}function Oi(e){return IR.has(e)}function Sy(e,t,r,n){let o=r===""?t:t.filter((a)=>a.timestamp>=r);if(o.length===0)return e;let i=Math.max(1,n);if(o.length>=i)return o.slice(-i);let s=Math.max(0,e.length+o.length-i);return e.slice(s).concat(o)}function ky(e,t){let r=t.length>0?t[t.length-1].seq:-1,n=e.filter((o)=>o.seq>r);return[...t,...n]}function Cy(e,t){if(t.length===0)return e;let r=new Set(e.map((o)=>o.seq)),n=t.filter((o)=>!r.has(o.seq));return n.length===0?e:[...n,...e]}function _y(e,t,r){return e&&t<=0&&r}function Ry(e){return e.filter((t)=>t.level==="ERROR"||t.level==="FATAL").length}function $R(e){return`${e.timestamp} ${e.service} ${e.level} ${e.message}`}function Py(e){return[e.message,`time ${e.timestamp}`,`service ${e.service}`,`source ${e.source}${e.stream?` / ${e.stream}`:""}`,`level ${e.level}`,`pid ${e.pid||"\u2014"}`,`request ${e.request_id||"\u2014"}`,`identity ${e.identity||"\u2014"}`].join(`
|
|
615
|
-
`)}function
|
|
616
|
-
`)}function yo(e,t){let r=t.services?.filter((l)=>l!=="")??[],n=t.service??"",o=(t.search??"").trim(),i=t.source??"",s=t.since??"",a=t.until??"",c;if(o!=="")if(t.regex===!0){let l=ea(o);if(l)c=(d)=>l.test(d);else c=(d)=>d.toLowerCase().includes(o.toLowerCase())}else{let l=o.toLowerCase();c=(d)=>d.toLowerCase().includes(l)}return e.filter((l)=>{if(r.length>0&&!r.includes(l.service))return!1;if(n!==""&&l.service!==n)return!1;if(i!==""&&l.source!==i)return!1;if(t.systemLogs===!1&&Oi(l.source))return!1;if(s!==""&&l.timestamp<s)return!1;if(a!==""&&l.timestamp>a)return!1;if(t.errorOnly===!0&&l.level!=="ERROR"&&l.level!=="FATAL")return!1;if(!c)return!0;return c(l.message)||c(l.service)})}function FR(e,t){let r={};for(let i of e)r[i.service]=(r[i.service]??0)+1;let n=t.map((i)=>({name:i,count:r[i]??0})),o=Object.keys(r).filter((i)=>!t.includes(i)).sort().map((i)=>({name:i,count:r[i]??0}));return[...n,...o]}function Ty(e,t,r=[]){let n=Ii(e,t,r);return[{name:"",count:t.length},...FR(t,n)]}function NR(e,t){let r=e.map((o)=>({name:o,count:t[o]??0})),n=Object.keys(t).filter((o)=>!e.includes(o)).sort().map((o)=>({name:o,count:t[o]??0}));return[...r,...n]}function Ay(e,t,r=[]){let n=Object.keys(t.byService).map((i)=>({service:i})),o=Ii(e,n,r);return[{name:"",count:t.total},...NR(o,t.byService)]}function vu(e,t){if(e<=0)return"none started";return`${e}/${t} running`}function Ii(e,t,r=[]){let n=[...e],o=(i)=>{if(i!==""&&!n.includes(i))n.push(i)};for(let i of r)o(i);for(let i of t)o(i.service);return n}function Ly(e,t,r){let n=["",...Ii(e,t)];if(r<1||r>n.length)return;return n[r-1]}function xu(e,t,r){let n=["",...e],o=n.indexOf(t),s=((o<0?0:o)+r+n.length)%n.length;return n[s]??""}function $i(e){return e.waves.flat().join(" \u2192 ")}function Dy(e){let t=$i(e);if(t==="")return"Started selected services";return`Started ${t}`}function My(e){let t=$i(e);if(t==="")return"Stopped running services";return`Stopped ${t}`}function Oy(e,t,r,n="start"){let o=r?.services[e],i=Ot(o);if(o?.last_error&&n!=="stop")return o.last_error;if(n==="stop"){if(i==="STOPPED")return"stopped";if(i==="STOPPING")return"stopping now";if(i==="FAILED")return"already failed";return"queued"}if(i==="HEALTHY")return"ready";if(i==="STARTING")return"starting now";if(i==="RUNNING")return"up, waiting for health";if(i==="UNHEALTHY")return"unhealthy \u2014 retrying health check";if(i==="STOPPING")return"stopping first";if(i==="FAILED")return"failed \u2014 later waves will not start";let a=(t.steps.find((c)=>c.name===e)?.dependencies??[]).filter((c)=>Ot(r?.services[c])!=="HEALTHY");if(a.length>0)return`waits for ${a.join(", ")}`;return"queued"}function Fi(e,t,r="start"){if(e.length===0)return"completed";let n=e.map((i)=>t?.services[i]);if(n.some((i)=>i?.state==="FAILED"))return"failed";if(r==="stop"){if(n.every((i)=>!i||i.state==="STOPPED"||i.state==="UNKNOWN"))return"completed";if(n.some((i)=>i?.state==="STOPPING"))return"active";return"queued"}let o=(i)=>Boolean(i&&(i.state==="HEALTHY"||i.health==="HEALTHY"||i.state==="RUNNING"&&i.health!=="UNHEALTHY"));if(n.every(o))return"completed";if(n.some((i)=>i?.state==="UNHEALTHY"||i?.health==="UNHEALTHY"))return"unhealthy";if(n.some((i)=>i?.state==="STARTING"||i?.state==="RUNNING"||i?.state==="RESTARTING"))return"active";return"queued"}function Iy(e,t,r="start"){let o=e.waves.flat().length,i=0,s=0,a=0,c=0;for(let y=0;y<e.waves.length;y++){let b=e.waves[y]??[],w=Fi(b,t,r);if(w==="active"||w==="unhealthy"||w==="failed")c=y;else if(w==="completed"&&c===y&&y<e.waves.length-1)c=y+1;for(let R of b){let S=t?.services[R];if(r==="stop"?!S||S.state==="STOPPED"||S.state==="UNKNOWN":Boolean(S&&(S.state==="HEALTHY"||S.health==="HEALTHY"||S.state==="RUNNING"&&S.health!=="UNHEALTHY")))i++;else if(S?.state==="FAILED")s++;else if(S?.state==="STARTING"||S?.state==="RUNNING"||S?.state==="UNHEALTHY"||S?.health==="UNHEALTHY"||S?.state==="STOPPING"||S?.state==="RESTARTING")a++}}let l=o>0?Math.round(i/o*100):100,d=16,g=Math.round(l/100*d),f="\u2588".repeat(g)+"\u2591".repeat(Math.max(0,d-g)),h=i===o&&o>0;return{total:o,ready:i,active:a,failed:s,percent:l,progressBar:f,currentWaveIndex:c,totalWaves:e.waves.length,isComplete:h}}function $y(e,t,r){let n=r==="completed"?"\u2713 Completed":r==="failed"?"\u2717 Failed":r==="unhealthy"?"\u26A0 Unhealthy":r==="active"?"\u23F3 In Progress":"\u25CB Queued";return`${e==="stop"?t===0?"Wave 1 (Stop First)":`Wave ${t+1}`:t===0?"Wave 1 (Start First)":`Wave ${t+1}`} \xB7 ${n}`}function Fy(e,t,r,n){let o=n?` \xB7 Profile ${n}`:"";if(r)return`${e==="stop"?"Shutdown":"Startup"} Failed (${r})`;if(t)return`${e==="stop"?"Stopping Services":e==="restart"?"Restarting Pipeline":"Starting Pipeline"}${o}`;return`${e==="stop"?"Shutdown Complete":"Startup Complete"}${o}`}function Ny(e,t){if(e)return{primary:"Working\u2026 esc hide this panel (keeps running in background)",secondary:"Services are transitioning. You can dismiss anytime without stopping them."};if(t)return{primary:"enter or esc back to dashboard",secondary:"Execution stopped. Check logs or open Doctor to resolve errors."};return{primary:"enter or esc back to dashboard",secondary:"All waves finished. Click here or press enter to continue."}}function Hy(e){let t=xn.indexOf(e);if(t<0)return"dashboard";return xn[(t+1)%xn.length]??"dashboard"}function jy(e){let t=xn.indexOf(e);if(t<0)return"dashboard";return xn[(t-1+xn.length)%xn.length]??"dashboard"}function By(e){return["services","nav","logs","ui","app"].flatMap((r)=>{let n=e.filter((o)=>o.group===r);if(n.length===0)return[];return[{group:r,items:n}]})}function Wy(e){let t=e.trim().toLowerCase().replace(/^\//,""),r=co().filter((n)=>t===""||n.name.includes(t)||n.desc.toLowerCase().includes(t)||n.aliases.some((o)=>o.startsWith(t)));return By(r).flatMap((n)=>n.items)}function Gy(e){return By(e).flatMap((t)=>t.items.map((r)=>({name:`/${r.name}`,description:`${t.group} \xB7 ${r.desc}`,value:r.name})))}function Uy(e,t,r=lr()){if(t==="slash")return[{key:"\u2191\u2193",label:"suggest"},{key:"tab",label:"complete"},{key:"enter",label:"run"},{key:"esc",label:"cancel"}];if(t==="palette"||t==="themes")return[{key:"\u2191\u2193",label:"move"},{key:"enter",label:t==="themes"?"save":"select"},{key:"esc",label:t==="themes"?"revert":"close"}];if(t==="help")return[{key:"j/k",label:"scroll"},{key:"esc",label:"close"}];if(t==="log-details")return[{key:"j/k",label:"scroll"},{key:r,label:"copy"},{key:"esc",label:"close"}];if(t==="confirm")return[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}];if(t==="plan")return[{key:"esc",label:"back to dashboard"},{key:"enter",label:"done"}];if(t==="leader")return bu();if(t==="config-edit")return[{key:"ctrl+s",label:"save"},{key:"esc",label:"discard"}];return HR(e,r)}function bu(){return[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"s",label:"services"},{key:"l",label:"logs"},{key:"t",label:"themes"},{key:"q",label:"quit"}]}function HR(e,t){let r=[{key:"/",label:"command"},{key:"ctrl+p",label:"palette"},{key:"?",label:"help"}];switch(e){case"dashboard":return[{key:"space",label:"select"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"enter",label:"start or open"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"},{key:"\u2190\u2192",label:"log filter"},{key:"g",label:"latest"},{key:"z",label:"full logs"},{key:"i",label:"internal logs"},{key:"ctrl+l",label:"clear logs"},{key:t,label:"copy logs"},{key:"j/k",label:"move"},...r];case"services":return[{key:"enter",label:"detail"},{key:"space",label:"select"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"},...r];case"detail":return[{key:"j/k",label:"scroll env"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"o",label:"config"},{key:"l",label:"logs"},{key:"esc",label:"back"},...r];case"logs":return[{key:"\u2190\u2192",label:"filter"},{key:"1-9",label:"source"},{key:"e",label:"errors"},{key:"i",label:"internal logs"},{key:"ctrl+l",label:"clear logs"},{key:"g",label:"latest"},{key:"f",label:"search"},{key:"t",label:"time"},{key:"m",label:"meta"},{key:"w",label:"wrap"},{key:"j/k",label:"move"},{key:t,label:"copy"},{key:"p",label:"pause"},{key:"z",label:"full screen"},{key:"/exports",label:"open folder"},...r];case"profiles":return[{key:"space",label:"set current"},{key:"enter",label:"set and start"},{key:"j/k",label:"move"},...r];case"proxy":return[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"},...r];case"mcp":return[{key:"j/k",label:"move"},{key:"space",label:"start or copy"},{key:"\u2190\u2192",label:"change port"},{key:"enter",label:"start or copy"},...r];case"config":return[{key:"v",label:"buffer"},{key:"e",label:"editor"},{key:"/reload",label:"reload"},{key:"j/k",label:"scroll"},...r];case"setup":return[{key:"j/k",label:"steps"},{key:"enter",label:"continue"},{key:"esc",label:"back or exit"},...r];case"doctor":return[{key:"r",label:"run doctor again"},{key:"j/k",label:"move"},{key:"enter",label:"fix port"},...r];case"auth":return[{key:"r",label:"probe identities"},{key:"/auth refresh",label:"probe"},...r];case"settings":return[{key:"j/k",label:"move"},{key:"\u2190\u2192",label:"save"},{key:"enter",label:"apply or open page"},{key:"space",label:"toggle"},...r];default:return[{key:"tab",label:"screens"},...r]}}function Ky(e,t,r){if(r<=t||e<t)return 0;return Math.min(e-t+1,r-t)}function wn(e,t){if(e.length===0)return;let r=Math.min(Math.max(t,0),e.length-1);return e[r]}function Va(e){return e.command.args.join(" ")||"\u2014"}function Ni(e,t){let r=Sn(t);if(r!=="")return r;if(e.ports.length===0)return"\u2014";return e.ports.map((n)=>`${n.name}:${n.auto?"auto":n.value}`).join(" ")}function Ja(e){let t=e.health.type||"none",r=e.health.url||e.health.address;return r===""?t:`${t} ${r}`}function Ya(e,t){if(t?.identity)return t.identity;let r=e.identity.type||"none",n=e.identity.service_account;return n===""?r:`${r} ${n}`}function za(e){let t=e.restart.policy||"none";if(e.restart.max_retries>0)return`${t} \xD7${e.restart.max_retries}`;return t}function qy(e,t,r,n){let o={...e.environment.defaults,...e.environment.vars},i=KR(o,t,r,n);return[...new Set([...Object.keys(i),...e.environment.required])].sort().map((a)=>({key:a,value:i[a]??"",required:e.environment.required.includes(a)}))}function Vy(e){let t=Math.max(UR,e-GR);return Math.min(BR,Math.max(jR,Math.floor(t*WR)))}function Sn(e){if(!e)return"";if(e.ports.http!==void 0)return String(e.ports.http);let t=Object.values(e.ports)[0];return t!==void 0?String(t):""}function Ot(e){if(!e)return"STOPPED";return Zn(e)}function Jy(e,t,r){if(e==="quit")return{title:"Quit",body:"Stop managed services and leave the TUI? Press d to detach and leave them running."};if(e==="reload")return{title:"Reload applied",body:t===""?"Configuration changed. Restart marked services?":`Restart required: ${t}`};if(e==="reset-prefs")return{title:"Reset preferences",body:"Restore theme, display size, mouse, and leader timeout to defaults? This overwrites your saved tui.json values."};if(e==="free-port"){let n=r?.port??0,o=r?.process||"process",i=r?.pid??0;return{title:`Free port ${n}`,body:`Stop ${o} (pid ${i}) so port ${n} can be used? This sends SIGTERM, then SIGKILL if it stays up.`}}return{title:"Start profile",body:t===""?"Start the configured services?":`Start profile ${t}?`}}function KR(e,t,r,n){if(t)return e;return new gn(r,n).redactMap(e)}function Yy(e,t){if(!e)return"";return(e.profiles[t]?.services??[]).join(", ")}function vo(e,t,r){let n=e?.google?.project_id??"";if(n!=="")return{project:n,source:"configuration"};let o=t?.project||r?.projectID||"",i=t?.project_source||r?.projectSource||"";return{project:o,source:i}}function zy(e,t,r,n){let o=Math.max(8,n-2),i=`logs ${r}`,s=Lr(i),a=e||"(no user)",c=t||"";if(o<=s+6){let f=Math.max(2,o-s-2);return[{label:ce(a,f),tone:"idle"},{label:ce(i,s-2),tone:"muted"}]}let l=o-s;if(c&&l>=36){let f=ce(c,14),h=Lr(f),y=l-h-2,b=y>=a.length+9?`identity ${a}`:a;return[{label:ce(b,y),tone:"idle"},{label:f,tone:"muted"},{label:i,tone:"muted"}]}if(c&&l>=28&&c.length<=10){let f=ce(c,10),h=Lr(f),y=l-h-2;return[{label:ce(a,y),tone:"idle"},{label:f,tone:"muted"},{label:i,tone:"muted"}]}let d=l>=a.length+9?`identity ${a}`:a;return[{label:ce(d,l-2),tone:"idle"},{label:i,tone:"muted"}]}function Xy(e){let t=e.payload?.error;return typeof t==="string"&&t!==""?t:"configuration reload failed"}var uo=100,Mh=8,Jt=12,fr=10,La=8,Mr=8,Da=9,Ma=7,Oa=8,du=12,Oh=40,yt=2,$_=2,Ih=2,F_=2,Ta=34,N_=48,H_=60,j_=72,B_=0.48,Ia=90,W_=60,G_=9,$a=8,U_=8,K_=6,q_=20,Eh=1,V_=1,J_=1,Y_=1,z_=1,BM,X_=2,Pa=2,Q_=80,Z_=56,Na=9,Ha=7,Th=10,Bh=16,Wh=2,Ti=1,bn=200,eR=2,Ah=1,tR="\u25B8",Gh=2,rR=0.4,nR,aR,cR,Dr,xn,lR,dR=0.85,uR=1.5,pR=0.2,fR=0.1,gR=5,xR=52,bR=64,wR=72,SR=82,kR=90,CR=100,_R=2,RR=2,PR=2,ER=1,Ka=8,iu=8,TR=22,su=6,AR=28,Ea=12,go=2,LR=10,DR=18,MR,au=1000,cu,lu,Lh,OR=1024,Dh=1024,IR,wy,jR=10,BR=28,WR=0.42,GR=2,UR=20;var Pe=T(()=>{fn();la();dn();Vt();BM=$h(Ia-1);nR=/("[^"]*"|'[^']*'|\b(?:ERROR|FATAL|WARN(?:ING)?|FAIL(?:ED)?)\b|\b\d{3,5}\b)/gi;aR=/^(started|stopped|restarted|refreshed|cleared|copied|exported|jumped|proxy started|proxy stopped|secrets|re-running|theme |mouse |leader |display |restored)/i,cR=/\b(fail|error|unknown|not found|no configuration|blocked|already in use|is using port)\b/i;Dr=[{id:"dashboard",label:"dashboard"},{id:"services",label:"services"},{id:"logs",label:"logs"},{id:"auth",label:"identity"},{id:"credentials",label:"credentials"},{id:"proxy",label:"proxy"},{id:"doctor",label:"doctor"},{id:"config",label:"config"},{id:"profiles",label:"profiles"},{id:"setup",label:"setup"},{id:"stats",label:"stats"},{id:"settings",label:"settings"}];xn=Dr.map((e)=>e.id);lR=new Set(["RUNNING","STARTING","RESTARTING","HEALTHY","UNHEALTHY"]);MR=new Set(["http","tcp","command"]);cu=60*au,lu=60*cu,Lh=24*lu;IR=new Set(["auth","devctl","proxy"]),wy=["devctl","mcp","auth"]});import{useEffect as qR,useRef as VR}from"react";import{jsxDEV as ne,Fragment as YR}from"@opentui/react/jsx-dev-runtime";function JR(e,t){switch(t){case"primary":return{bg:e.primary,fg:vn(e.primary,e.inverse)};case"accent":return{bg:e.accent,fg:ka(e)?Sa:vn(e.accent,e.inverse)};case"success":return{bg:e.success,fg:vn(e.success,e.inverse)};case"warning":return{bg:e.warning,fg:ka(e)?Sa:vn(e.warning,e.inverse)};case"error":return{bg:e.error,fg:vn(e.error,e.inverse)};case"info":return{bg:e.info,fg:vn(e.info,e.inverse)};case"muted":return{bg:e.element,fg:e.text};default:return{bg:e.element,fg:e.text}}}function Qy(e){let{palette:t,dir:r}=e;return ne("box",{width:2,height:1,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,children:r==="left"?"\u2039":"\u203A"},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function je(e){let{palette:t,children:r,backgroundColor:n,edge:o="bottom"}=e,i=re(),s=e.ruled??!ur(i),a=n??t.element,c=ne("box",{flexShrink:0,flexDirection:"column",backgroundColor:a,overflow:"hidden",children:r},void 0,!1,void 0,this);if(!s)return c;return ne("box",{flexShrink:0,flexDirection:"column",overflow:"hidden",border:[...o==="both"?["top","bottom"]:[o]],borderStyle:"single",borderColor:t.border,children:c},void 0,!1,void 0,this)}function Xa(e){let{palette:t,items:r,active:n,width:o,onPick:i}=e,s=r.map((d)=>Lr(d.label)),a=Nh(s,n,Math.max(1,o)),c=a.start>0,l=a.end>=0&&a.end<r.length-1;return ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[c?ne(Qy,{palette:t,dir:"left"},void 0,!1,void 0,this):null,r.map((d,g)=>{if(g<a.start||g>a.end)return null;let f=g===n;return ne(ue,{palette:t,label:d.label,tone:f?"primary":"muted",fg:f?void 0:d.color,onMouseDown:()=>i(g)},d.id,!1,void 0,this)}),l?ne(Qy,{palette:t,dir:"right"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function ue(e){let{palette:t,label:r,tone:n="idle",fg:o,bg:i,onMouseDown:s}=e,a=JR(t,n);return ne("box",{height:1,paddingLeft:1,paddingRight:1,backgroundColor:i??a.bg,overflow:"hidden",flexShrink:0,onMouseDown:s,children:ne("text",{fg:o??a.fg,children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ee(e){let{palette:t,hints:r}=e;return ne("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:r.map((n)=>ne("box",{height:1,paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ne("text",{wrapMode:"none",children:[ne("span",{fg:t.primary,children:n.key},void 0,!1,void 0,this),ne("span",{fg:t.muted,children:` ${n.label}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},`${n.key}-${n.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function Be(e){let{palette:t,items:r,hints:n,ruled:o=!0}=e,i=ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[r.map((s,a)=>ne(ue,{palette:t,label:s.text,tone:s.tone,onMouseDown:s.onMouseDown},`${s.text}-${a}`,!1,void 0,this)),n&&n.length>0?ne(YR,{children:[ne("box",{flexGrow:1,backgroundColor:t.element},void 0,!1,void 0,this),ne(Ee,{palette:t,hints:n},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this);if(!o)return i;return ne(je,{palette:t,backgroundColor:t.element,children:i},void 0,!1,void 0,this)}function Ze(e){let{palette:t,title:r,termW:n,termH:o,preferW:i,preferH:s,anchor:a="center",borderColor:c,bottomTitle:l,gap:d,children:g}=e,f=ur(re()),h=fo(n,o,i,s,a,!f);return ne("box",{position:"absolute",left:h.left,top:h.top,width:h.width,height:h.height,border:!0,borderStyle:wu,borderColor:c??t.borderActive,backgroundColor:t.panel,padding:f?0:1,title:r,titleColor:t.primary,bottomTitle:l,gap:f?0:d,flexDirection:"column",overflow:"hidden",children:g},void 0,!1,void 0,this)}function Le(e){return{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:e.panel},viewportOptions:{backgroundColor:e.panel},contentOptions:{backgroundColor:e.panel},scrollbarOptions:{trackOptions:{foregroundColor:e.primary,backgroundColor:e.element}}}}function We(e,t){if(!e)return;e.scrollBy({x:0,y:t})}function xo(e,t){let r=VR(null);return qR(()=>{let n=r.current;if(!n||e<0)return;let o=requestAnimationFrame(()=>{n.scrollChildIntoView(`${t}-${e}`)});return()=>cancelAnimationFrame(o)},[t,e]),r}function et(e){let t=re(),r=Ei(t),n=e.scroll?ne("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Le(e.palette),children:ne("box",{flexDirection:"column",overflow:"hidden",children:e.children},void 0,!1,void 0,this)},void 0,!1,void 0,this):e.children;return ne("box",{flexGrow:1,border:!0,borderStyle:wu,borderColor:e.borderColor??e.palette.border,title:e.title,titleColor:e.palette.primary,paddingLeft:t.pad,paddingRight:t.pad,paddingTop:r?0:t.pad,paddingBottom:r?0:t.pad,backgroundColor:e.palette.panel,flexDirection:"column",overflow:"hidden",children:n},void 0,!1,void 0,this)}function kn(e){let{palette:t,label:r,value:n,tone:o="text"}=e,i=re(),s=o==="success"?t.success:o==="warning"?t.warning:o==="error"?t.error:o==="muted"?t.muted:t.text;return ne("box",{height:i.rowH,flexDirection:"row",overflow:"hidden",children:[ne("box",{width:14,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{flexGrow:1,overflow:"hidden",children:ne("text",{fg:s,wrapMode:"none",children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Qa(e){let{palette:t,title:r,body:n,hint:o}=e;return ne("box",{height:o?5:4,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:wu,borderColor:t.borderActive,titleColor:t.primary,children:[ne("text",{fg:t.primary,children:r},void 0,!1,void 0,this),ne("text",{fg:t.text,wrapMode:"word",children:n},void 0,!1,void 0,this),o?ne("text",{fg:t.muted,wrapMode:"word",children:o},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var wu="rounded";var ve=T(()=>{ot();pr();ze();Pe()});import{jsxDEV as se,Fragment as Zy}from"@opentui/react/jsx-dev-runtime";function ev(e){let{palette:t,cfg:r,snap:n,google:o,profile:i,reveal:s,width:a}=e,c=Ua(n,r?Object.keys(r.services):void 0),l=n?.proxy.running===!0,d=o?.adcAvailable===!0,g=a<Ia,f=ce(r?.project.name||"local",g?18:22),h=ce(i||n?.profile||"no profile",16),y=se(Zy,{children:zh({width:a,running:c.running,total:c.total,proxyOn:l,proxyAddress:n?.proxy.address??"",mcpOn:n?.mcp?.running===!0,adc:d,reveal:s}).filter((w)=>!w.hide&&w.label!=="").map((w)=>se(ue,{palette:t,label:w.label,tone:w.tone},w.label,!1,void 0,this))},void 0,!1,void 0,this),b=Ei(re());return se(je,{palette:t,backgroundColor:t.panel,ruled:!b,children:se("box",{height:g?2:1,flexDirection:"column",backgroundColor:t.panel,overflow:"hidden",children:[se("box",{height:1,flexDirection:"row",overflow:"hidden",children:[se(ue,{palette:t,label:Pt(),tone:"primary"},void 0,!1,void 0,this),se(ue,{palette:t,label:f,tone:"idle"},void 0,!1,void 0,this),se(ue,{palette:t,label:h,tone:"accent"},void 0,!1,void 0,this),g?null:se(Zy,{children:[se("box",{flexGrow:1,backgroundColor:t.panel},void 0,!1,void 0,this),y]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g?se("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.panel,children:y},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function tv(e){let{palette:t,screen:r,width:n,onSelect:o}=e,i=Dr.map((a)=>({id:a.id,label:Fh(a.label,n)})),s=Hh(r);return se(je,{palette:t,backgroundColor:t.element,children:se(Xa,{palette:t,items:i,active:s,width:n,onPick:(a)=>{let c=Dr[a];if(c)o(c.id)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function rv(e){let{palette:t,overlay:r,query:n,onQuery:o,onSubmit:i}=e;if(r==="slash"||r==="palette"){let c=r==="slash"?"/":"> ";return se(je,{palette:t,backgroundColor:t.highlight,edge:"top",children:se("box",{height:1,backgroundColor:t.highlight,paddingLeft:1,flexDirection:"row",overflow:"hidden",children:[se("box",{width:2,flexShrink:0,children:se("text",{fg:t.primary,children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),se("box",{flexGrow:1,overflow:"hidden",children:se("input",{focused:!0,value:n,placeholder:r==="slash"?"start auth":"filter commands",onInput:o,onSubmit:()=>i(n),backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}let a=r==="leader"?[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"s",label:"services"},{key:"l",label:"logs"},{key:"t",label:"themes"},{key:"q",label:"quit"}]:[{key:"/",label:"command"},{key:"ctrl+p",label:"palette"},{key:"ctrl+x",label:"leader"},{key:"?",label:"help"}];return se(je,{palette:t,backgroundColor:t.element,edge:"top",children:se("box",{height:1,backgroundColor:t.element,overflow:"hidden",children:se(Ee,{palette:t,hints:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function nv(e){let{palette:t,screen:r,overlay:n,status:o,paused:i,errorOnly:s,width:a,copyKey:c}=e,l=Ei(re()),d=Math.max(18,Math.floor(a*0.42)),g=po(Uy(r,n,c),d),f=Zh(o);return se(je,{palette:t,backgroundColor:t.panel,edge:"top",ruled:!l,children:se("box",{height:1,backgroundColor:t.panel,overflow:"hidden",children:se(Be,{ruled:!1,palette:t,items:[{text:r,tone:"primary"},{text:i?"PAUSED":"LIVE",tone:i?"warning":"success"},...s?[{text:"ERROR+",tone:"error"}]:[],...o===""?[]:[{text:ce(o,Math.max(16,a-d-28)),tone:f}]],hints:g},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function De(e){return se("box",{flexGrow:1,padding:1,overflow:"hidden",children:se(Qa,{palette:e.palette,title:e.title,body:e.body,hint:e.hint},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Za(e){return se("box",{flexGrow:1,padding:1,overflow:"hidden",children:se("text",{fg:e.palette.text,children:e.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ov(e){return se("box",{flexGrow:1,padding:1,flexDirection:"column",overflow:"hidden",children:[se("text",{fg:e.palette.error,children:e.title},void 0,!1,void 0,this),se("text",{fg:e.palette.text,wrapMode:"word",children:e.body},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var kt=T(()=>{ot();Pe();ve();pr();ze()});function zR(){if(process.platform==="darwin")return[["pbcopy"]];if(process.platform==="win32")return[["clip"]];return[["wl-copy"],["xclip","-selection","clipboard"],["xsel","--clipboard","--input"]]}function XR(){return zR().filter((e)=>{let t=e[0];return typeof t==="string"&&Bun.which(t)!==null})}function QR(e){return`\x1B]52;c;${Buffer.from(e,"utf8").toString("base64")}\x07`}function iv(){if(process.platform==="linux")return"install wl-clipboard (Wayland) or xclip (X11)";return"no clipboard helper found"}async function Su(e){let t=XR(),r;for(let n of t)try{await eP(n,e);return}catch(o){r=o instanceof Error?o:Error(String(o))}if(process.platform!=="win32")try{await ZR(e);return}catch(n){r=n instanceof Error?n:Error(String(n))}throw be(nt,"clipboard unavailable",r?`${iv()} (${r.message})`:iv())}async function ZR(e){let t=QR(e);try{await Bun.write("/dev/tty",t)}catch{if(!process.stderr.write(t))throw Error("terminal clipboard write failed")}}async function eP(e,t){let r=Bun.spawn(e,{stdin:"pipe",stdout:"ignore",stderr:"ignore"});r.stdin.write(t),await r.stdin.end();let n=await r.exited;if(n!==0)throw Error(`${e[0]} exited ${n}`)}var sv=T(()=>{_e()});function av(e){return e==="slash"||e==="palette"||e==="config-edit"}function cv(e,t){return dr(e,t.keybinds.leader??"ctrl+x")}function lv(e,t){return dr(e,t.keybinds.command_list??"ctrl+p")}function dv(e,t){return dr(e,t.keybinds.command??"/")||e.name==="/"}function uv(e,t){return dr(e,t.keybinds.help??"?")||e.sequence==="?"}function pv(e,t){return dr(e,t.keybinds.search??"f")}function fv(e){let t=e.name??"";return t==="R"||e.shift===!0&&t.toLowerCase()==="r"}function gv(e){return e.ctrl===!0&&(e.name??"").toLowerCase()==="l"}function mv(e,t){if(t&&dr(e,t.keybinds.interrupt??"ctrl+c"))return!0;return e.ctrl===!0&&(e.name??"").toLowerCase()==="c"}function hv(e,t){return dr(e,t.keybinds.copy??lr())}function yv(e,t,r=tP){return t>0&&e-t<=r}function Or(e,t,r,n){return dr(e,t.keybinds[r]??n)}function ec(e){let t=(e.name??"").toLowerCase();return t==="pagedown"||e.ctrl===!0&&t==="d"&&!e.meta}function tc(e){let t=(e.name??"").toLowerCase();return t==="pageup"||e.ctrl===!0&&t==="u"&&!e.meta}var tP=2000;var vv=T(()=>{Vt()});import{jsxDEV as Ir}from"@opentui/react/jsx-dev-runtime";function xv(e){let{palette:t,path:r,initialValue:n,error:o,termW:i,termH:s,textareaRef:a}=e;return Ir(Ze,{palette:t,title:"config buffer",bottomTitle:"ctrl+s save \xB7 esc discard \xB7 e still opens $EDITOR",termW:i,termH:s,preferW:88,preferH:28,gap:1,children:[Ir("box",{height:1,overflow:"hidden",children:Ir("text",{fg:t.muted,wrapMode:"none",children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this),Ir("textarea",{ref:a,focused:!0,initialValue:n,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this),o!==""?Ir("box",{height:2,overflow:"hidden",children:Ir("text",{fg:t.error,wrapMode:"word",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this):Ir("box",{height:1,overflow:"hidden",children:Ir("text",{fg:t.muted,children:"validate, then write. invalid YAML is not saved."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var bv=T(()=>{ve()});import{jsxDEV as ku}from"@opentui/react/jsx-dev-runtime";function wv(e){let{palette:t,title:r,body:n,termW:o,termH:i}=e;return ku(Ze,{palette:t,title:r,bottomTitle:"enter confirm \xB7 esc stay",termW:o,termH:i,preferW:52,preferH:8,borderColor:t.warning,gap:1,children:[ku("text",{fg:t.text,wrapMode:"word",children:n},void 0,!1,void 0,this),ku(Ee,{palette:t,hints:[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Sv=T(()=>{ve()});import{jsxDEV as Bt}from"@opentui/react/jsx-dev-runtime";function kv(e){let{palette:t,event:r,termW:n,termH:o,scrollRef:i}=e;if(!r)return null;let s=r.message.length>120||r.message.includes(`
|
|
617
|
-
`);return Bt(Ze,{palette:t,title:"log details",bottomTitle:"j/k scroll \xB7 esc close",termW:n,termH:o,preferW:s?84:72,preferH:s?22:14,gap:1,children:Bt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:Bt("box",{flexDirection:"column",overflow:"hidden",children:[Bt("text",{fg:t.text,wrapMode:"word",children:r.message},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`time ${r.timestamp}`},void 0,!1,void 0,this),Bt("text",{fg:He(r.service,t),children:`service ${r.service}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`source ${r.source}${r.stream?` / ${r.stream}`:""}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`level ${r.level}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`pid ${r.pid||"\u2014"}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`request ${r.request_id||"\u2014"}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`identity ${r.identity||"\u2014"}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Cv=T(()=>{ve();ze()});import{jsxDEV as xe,Fragment as Rv}from"@opentui/react/jsx-dev-runtime";function lP(e){return[{key:"\u2190\u2192",label:"filter services"},{key:"1-9",label:"jump to source"},{key:"e",label:"ERROR+ only"},{key:"g",label:"jump to latest"},{key:"p",label:"pause stream"},{key:"z",label:"full-screen logs"},{key:"f",label:"search"},{key:"t",label:"timestamps"},{key:"m",label:"metadata"},{key:"w",label:"clip / wrap selected / wrap all"},{key:"j/k",label:"move and unfold"},{key:e,label:"copy visible logs"},{key:"/export",label:"write ~/.devctl/exports"},{key:"/exports",label:"open export folder"},{key:"ctrl+c \xD72",label:"quit"}]}function Fr(e){return e+oP}function Pv(e){let t=Fr(_u.length),r=Fr(Ru.length),n=Fr(e.logCount),o=Fr(Pu.length),i=Fr(Eu.length),s=Tu+e.pad*2;if(e.stacked)return s+t+r+n+o+i+Cu+(aP-1)*e.gap;let a=Math.max(t,r),c=Math.max(o,i);return s+a+n+c+Cu+(cP-1)*e.gap}function dP(e){return Pv(e)-Tu-e.pad*2}function uP(e){return e-Tu*2<nP}function Ev(e){let{palette:t,termW:r,termH:n,copyKey:o=lr(),scrollRef:i}=e,s=ur(re()),a=uP(r),c=s?0:1,l=s?0:1,d=lP(o),g={stacked:a,logCount:d.length,pad:c,gap:l},f=Pv(g),h=dP(g);return xe(Ze,{palette:t,title:"help",bottomTitle:`${Pt()} \xB7 j/k scroll \xB7 esc close`,termW:r,termH:n,preferW:rP,preferH:f,gap:0,children:xe("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:xe("box",{height:h,flexDirection:"column",flexShrink:0,overflow:"hidden",gap:l,children:[a?xe(Rv,{children:[xe($r,{palette:t,title:"navigation",bindings:_u},void 0,!1,void 0,this),xe($r,{palette:t,title:"services",bindings:Ru},void 0,!1,void 0,this),xe($r,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),xe($r,{palette:t,title:"commands",bindings:Pu},void 0,!1,void 0,this),xe($r,{palette:t,title:"display",bindings:Eu},void 0,!1,void 0,this)]},void 0,!0,void 0,this):xe(Rv,{children:[xe(_v,{palette:t,left:{title:"navigation",bindings:_u},right:{title:"services",bindings:Ru}},void 0,!1,void 0,this),xe($r,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),xe(_v,{palette:t,left:{title:"commands",bindings:Pu},right:{title:"display",bindings:Eu}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),xe("box",{height:Cu,flexShrink:0,overflow:"hidden",paddingLeft:1,children:xe("text",{fg:t.muted,wrapMode:"none",children:"~/.devctl/tui.json \xB7 DEVCTL_TUI_CONFIG"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function _v(e){let{palette:t,left:r,right:n}=e,o=Math.max(Fr(r.bindings.length),Fr(n.bindings.length));return xe("box",{height:o,flexDirection:"row",flexShrink:0,overflow:"hidden",gap:sP,children:[xe($r,{palette:t,title:r.title,bindings:r.bindings,height:o,stretch:!0},void 0,!1,void 0,this),xe($r,{palette:t,title:n.title,bindings:n.bindings,height:o,stretch:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $r(e){let{palette:t,title:r,bindings:n,stretch:o=!1}=e,i=e.height??Fr(n.length);return xe("box",{height:i,flexGrow:o?1:0,flexBasis:o?0:void 0,flexShrink:0,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:"rounded",borderColor:t.border,title:r,titleColor:t.accent,children:n.map((s)=>xe("box",{height:1,flexShrink:0,overflow:"hidden",paddingLeft:1,paddingRight:1,children:xe(pP,{palette:t,binding:s},void 0,!1,void 0,this)},`${s.key}-${s.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function pP(e){let{palette:t,binding:r}=e;return xe("box",{height:1,flexDirection:"row",overflow:"hidden",children:[xe("box",{width:iP,flexShrink:0,overflow:"hidden",children:xe("text",{fg:t.primary,wrapMode:"none",children:r.key},void 0,!1,void 0,this)},void 0,!1,void 0,this),xe("box",{flexGrow:1,overflow:"hidden",children:xe("text",{fg:t.text,wrapMode:"none",children:r.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var rP=78,nP=56,oP=2,Tu=2,Cu=1,Au=8,iP=16,sP=2,aP=6,cP=4,_u,Ru,Pu,Eu;var Tv=T(()=>{ot();ve();pr();Vt();_u=[{key:"tab",label:"next screen"},{key:"1-9,0",label:"jump to screen"},{key:"s/l/a/p/d/c/u",label:"letter jump (config, setup)"},{key:"j/k",label:"move selection"},{key:"esc",label:"back / close"}],Ru=[{key:"enter",label:"start profile or open"},{key:"space",label:"multi-select"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"}];Pu=[{key:"/",label:"slash command"},{key:"ctrl+p",label:"command palette"},{key:"ctrl+x",label:"leader chord"},{key:"/settings",label:"preferences \xB7 MCP page"},{key:"/themes",label:"preview themes"},{key:"/mcp",label:"agent MCP server"}],Eu=[{key:"ctrl+=",label:"larger"},{key:"ctrl+-",label:"smaller"},{key:"?",label:"this overlay"}]});import{jsxDEV as Av}from"@opentui/react/jsx-dev-runtime";function Lv(e){let{palette:t,termW:r,termH:n}=e,o=bu();return Av(Ze,{palette:t,title:"leader",termW:r,termH:n,preferW:68,preferH:5,anchor:"bottom",children:Av(Ee,{palette:t,hints:o},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Dv=T(()=>{Pe();ve()});import{jsxDEV as Mv}from"@opentui/react/jsx-dev-runtime";function Ov(e){let{palette:t,items:r,selected:n,termW:o,termH:i,onIndex:s,onPick:a}=e,c=Gy(r),l=fo(o,i,64,18,"center",!ur(re()));return Mv(Ze,{palette:t,title:"commands",bottomTitle:"enter select \xB7 esc close",termW:o,termH:i,preferW:64,preferH:18,children:Mv("select",{height:Math.max(4,l.height-3),options:c,selectedIndex:n,showDescription:!0,showSelectionIndicator:!0,wrapSelection:!0,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,selectedBackgroundColor:t.highlight,selectedTextColor:t.primary,descriptionColor:t.muted,selectedDescriptionColor:t.accent,onChange:(d)=>s(d),onSelect:(d,g)=>{let f=g?.value;if(typeof f==="string"&&f!=="")a(f)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Iv=T(()=>{ot();Pe();ve();pr()});import{jsxDEV as I}from"@opentui/react/jsx-dev-runtime";function Lu(e,t){switch(e){case"completed":return{icon:"\u2713",label:"Completed",tone:"success",color:t.success};case"failed":return{icon:"\u2717",label:"Failed",tone:"error",color:t.error};case"unhealthy":return{icon:"\u26A0",label:"Unhealthy",tone:"warning",color:t.warning};case"active":return{icon:"\u25CF",label:"In progress",tone:"primary",color:t.primary};default:return{icon:"\u25CB",label:"Queued",tone:"muted",color:t.muted}}}function fP(e,t,r,n){if(t!=="")return{icon:"\u2717",label:"Failed",tone:"error",color:n.error};if(!e)return{icon:"\u2713",label:"Finished",tone:"success",color:n.success};if(r==="unhealthy")return{icon:"\u26A0",label:"Waiting on health",tone:"warning",color:n.warning};return{icon:"\u25CF",label:"Running",tone:"primary",color:n.primary}}function $v(e){return I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:I("text",{wrapMode:"none",children:[I("span",{fg:e.palette.primary,children:e.label.toUpperCase()},void 0,!1,void 0,this),e.detail?I("span",{fg:e.palette.muted,children:` ${e.detail}`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Fv(e){let{palette:t,plan:r,snap:n,busy:o,failed:i,kind:s,termW:a=80,termH:c=24,scrollRef:l,initiallyRunning:d=[],onDismiss:g}=e,f=new Set(d),h=r.waves.map((ae,Oe)=>({wave:ae.filter((Ke)=>!f.has(Ke)),waveIdx:Oe})).filter(({wave:ae})=>ae.length>0),y=Iy(r,n,s),b=r.waves[y.currentWaveIndex]??[],w=Fi(b,n,s),R=Lu(w,t),S=fP(o,i,w,t),N=Fy(s,o,i,r.profile),J=Ny(o,i),v=i?t.inverse:t.text,A=i?t.error:t.element,m=Math.min(92,Math.max(40,a-8)),_=m>=82?22:m>=66?17:13,F=12,Z=9,he=m>=56,ke=m>=72,Je=m<72||r.waves.length>3,Ue=r.profile?`PROFILE ${r.profile}`:s.toUpperCase();return I(Ze,{palette:t,title:N,bottomTitle:"enter close \xB7 esc hide (operation continues)",termW:a,termH:c,preferW:98,preferH:28,borderColor:S.color,gap:0,children:[I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[I(ue,{palette:t,label:`${S.icon} ${S.label.toUpperCase()}`,tone:S.tone},void 0,!1,void 0,this),I("box",{paddingLeft:1,flexGrow:1,overflow:"hidden",children:I("text",{fg:t.text,wrapMode:"none",children:Ue},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(ue,{palette:t,label:`${y.ready}/${y.total} READY`,tone:y.isComplete?"success":"info"},void 0,!1,void 0,this),I(ue,{palette:t,label:`WAVE ${Math.min(y.currentWaveIndex+1,Math.max(1,y.totalWaves))}/${Math.max(1,y.totalWaves)}`,tone:R.tone},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{height:2,flexDirection:"column",overflow:"hidden",flexShrink:0,paddingLeft:1,paddingRight:1,children:[I("box",{height:1,flexDirection:"row",overflow:"hidden",children:[I("text",{wrapMode:"none",children:[I("span",{fg:t.muted,children:"PROGRESS "},void 0,!1,void 0,this),I("span",{fg:S.color,children:`[${y.progressBar}]`},void 0,!1,void 0,this),I("span",{fg:t.text,children:` ${y.percent}%`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{flexGrow:1},void 0,!1,void 0,this),I("text",{wrapMode:"none",children:I("span",{fg:R.color,children:`${R.icon} ${R.label}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{height:1,overflow:"hidden",children:I("text",{fg:t.muted,wrapMode:"none",children:o?s==="stop"?"Dependents stop first; each wave waits for the previous wave.":"Each wave waits until its services are healthy before the next wave starts.":J.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I($v,{palette:t,label:"Pipeline",detail:`${r.waves.length} execution wave${r.waves.length===1?"":"s"}`},void 0,!1,void 0,this),I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:r.waves.map((ae,Oe)=>{let Ke=Fi(ae,n,s),de=Lu(Ke,t),we=Je?`W${Oe+1} ${de.icon} ${ae.length}`:`W${Oe+1} ${de.icon} ${de.label} \xB7 ${ae.length}`;return I("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:[I(ue,{palette:t,label:we,tone:de.tone},void 0,!1,void 0,this),Oe<r.waves.length-1?I("box",{width:3,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:" \u2500\u25BA"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},`step-${Oe}`,!0,void 0,this)})},void 0,!1,void 0,this),(r.blockers??[]).length>0?I("box",{minHeight:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:I("text",{fg:t.error,wrapMode:"word",children:`BLOCKED ${r.blockers?.map((ae)=>`${ae.name}: ${ae.message}`).join(" \xB7 ")}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,d.length>0?I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,paddingLeft:1,children:I("text",{wrapMode:"none",children:[I("span",{fg:t.success,children:"\u2713 ALREADY READY"},void 0,!1,void 0,this),I("span",{fg:t.muted,children:` ${d.join(", ")}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this):null,I($v,{palette:t,label:"Wave details",detail:"live process and health state"},void 0,!1,void 0,this),I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:[I("box",{width:2,flexShrink:0},void 0,!1,void 0,this),I("box",{width:_,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("SERVICE",_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:12,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("STATE",12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),he?I("box",{width:9,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("PORT",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ke?I("box",{flexGrow:1,overflow:"hidden",children:I("text",{fg:t.muted,children:"DETAIL"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),I("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:I("box",{flexDirection:"column",overflow:"hidden",gap:1,children:h.map(({wave:ae,waveIdx:Oe})=>{let Ke=Fi(ae,n,s),de=Lu(Ke,t),we=`${$y(s,Oe,Ke)} \xB7 ${ae.length} service${ae.length===1?"":"s"}`;return I("box",{border:!0,borderStyle:"rounded",borderColor:de.color,title:we,titleColor:de.color,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ae.map((Ce)=>{let W=n?.services[Ce],Ie=Ot(W),lt=Oy(Ce,r,n,s),$e=Ce===i||Ie==="FAILED",_t=Ie==="UNHEALTHY",dt=Ie==="HEALTHY"||s==="stop"&&Ie==="STOPPED",zt=Sn(W),ut=$e?"\u2717":dt?"\u2713":_t?"\u26A0":Ie==="STARTING"||Ie==="RUNNING"||Ie==="STOPPING"||Ie==="RESTARTING"?"\u25CF":"\u25CB",Xt=$e?t.error:Re(t,Ie),pt=$e?t.error:_t?t.warning:dt?t.success:t.muted;return I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[I("box",{width:2,flexShrink:0,overflow:"hidden",children:I("text",{fg:Xt,children:ut},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:_,flexShrink:0,overflow:"hidden",children:I("text",{fg:He(Ce,t),wrapMode:"none",children:Y(Ce,_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:12,flexShrink:0,overflow:"hidden",children:I("text",{fg:Re(t,Ie),wrapMode:"none",children:Y(Ie,12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),he?I("box",{width:9,flexShrink:0,overflow:"hidden",children:I("text",{fg:zt?t.info:t.muted,wrapMode:"none",children:Y(zt?`:${zt}`:"\u2014",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ke?I("box",{flexGrow:1,overflow:"hidden",children:I("text",{fg:pt,wrapMode:"none",children:lt},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},Ce,!0,void 0,this)})},`wave-card-${Oe}`,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{height:3,flexShrink:0,flexDirection:"column",backgroundColor:A,border:["top"],borderStyle:"single",borderColor:S.color,paddingLeft:1,paddingRight:1,overflow:"hidden",onMouseDown:g,children:[I("text",{fg:v,wrapMode:"none",children:J.primary},void 0,!1,void 0,this),I("text",{fg:i?t.inverse:t.muted,wrapMode:"none",children:J.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Nv=T(()=>{Pe();ve();ze()});import{jsxDEV as Yt}from"@opentui/react/jsx-dev-runtime";function Hv(e){let{palette:t,route:r,termW:n,termH:o,scrollRef:i}=e;if(!r)return null;return Yt(Ze,{palette:t,title:r.name,bottomTitle:"j/k scroll \xB7 esc close",termW:n,termH:o,preferW:78,preferH:16,gap:1,children:Yt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:Yt("box",{flexDirection:"column",overflow:"hidden",children:[Yt("text",{fg:t.muted,children:`auth ${r.authType||"none"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`identity ${r.identityType||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`account ${r.serviceAccount||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`audience ${r.audience||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`match host ${r.matchHost||"*"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`match path ${r.matchPath||"*"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`upstream ${r.upstream}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var jv=T(()=>{ve()});import{jsxDEV as At}from"@opentui/react/jsx-dev-runtime";function Wv(e){let{palette:t,items:r,query:n,selected:o,onQuery:i,onSubmit:s}=e,a=Ky(o,Bv,r.length),c=r.slice(a,a+Bv),l=Math.max(c.length,1),d=wn(r,o);return At("box",{height:l+3,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,titleColor:t.primary,backgroundColor:t.panel,title:"commands",flexDirection:"column",overflow:"hidden",children:[c.length===0?At("box",{height:1,paddingLeft:1,overflow:"hidden",children:At("text",{fg:t.muted,children:"no matching command"},void 0,!1,void 0,this)},void 0,!1,void 0,this):c.map((g)=>{let f=g.name===d?.name;return At("box",{height:1,flexDirection:"row",overflow:"hidden",paddingLeft:1,paddingRight:1,backgroundColor:f?t.highlight:t.panel,children:[At("box",{width:14,flexShrink:0,overflow:"hidden",children:At("text",{fg:f?t.primary:t.text,wrapMode:"none",children:`${f?"\u203A":" "} /${g.name}`},void 0,!1,void 0,this)},void 0,!1,void 0,this),At("box",{flexGrow:1,overflow:"hidden",children:At("text",{fg:f?t.accent:t.muted,wrapMode:"none",children:g.desc},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},g.name,!0,void 0,this)}),At("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.highlight,paddingLeft:1,children:[At("box",{width:2,flexShrink:0,children:At("text",{fg:t.primary,children:"/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),At("box",{flexGrow:1,overflow:"hidden",children:At("input",{focused:!0,value:n,placeholder:"start auth",onInput:i,onSubmit:()=>s(),backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Bv=8;var Gv=T(()=>{Pe()});import{jsxDEV as qv}from"@opentui/react/jsx-dev-runtime";function Vv(e){let{palette:t,themeName:r,selected:n,termW:o,termH:i,onIndex:s,onPreview:a,onPick:c}=e,l=ht.map((g)=>({name:g===r?`${g} (active)`:g,description:g===r?`${Jd[g]} \xB7 current`:Jd[g],value:g})),d=fo(o,i,Uv,Kv,"center",!ur(re()));return qv(Ze,{palette:t,title:"/themes",bottomTitle:"enter save \xB7 esc revert",termW:o,termH:i,preferW:Uv,preferH:Kv,children:qv("select",{height:Math.max(4,d.height-3),options:l,selectedIndex:n,showDescription:!0,showSelectionIndicator:!0,wrapSelection:!0,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,selectedBackgroundColor:t.highlight,selectedTextColor:t.primary,descriptionColor:t.muted,selectedDescriptionColor:t.accent,onChange:(g)=>{s(g);let f=ht[g];if(f)a(f)},onSelect:(g,f)=>{let h=f?.value;if(typeof h==="string"&&h!=="")c(h)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Uv=52,Kv=22;var Jv=T(()=>{ot();Pe();ve();pr();ze()});import{jsxDEV as Ge}from"@opentui/react/jsx-dev-runtime";function rc(e){let{palette:t,title:r,tone:n="muted",children:o}=e,i=n==="success"?t.success:n==="warning"?t.warning:n==="error"?t.error:t.border;return Ge("box",{border:!0,borderStyle:"rounded",borderColor:i,title:r,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Yv(e){let{palette:t,cfg:r,google:n,identity:o}=e;if(!n&&!o)return Ge(Za,{palette:t,label:"Checking Application Default Credentials\u2026"},void 0,!1,void 0,this);let i=gP(r,o),s=o?.user||n?.userEmail||"",{project:a,source:c}=vo(r,o,n),l=o?.adc??n?.adcAvailable===!0,d=o?.iap??(r?.proxy.routes??[]).some((b)=>b.auth.type.toLowerCase()==="iap"),g=i.filter((b)=>b.inactive!==!0),f=g.some((b)=>b.ok===!0),h=g.some((b)=>b.ok===!1),y=f?"AVAILABLE":h?"UNAVAILABLE":g.length>0?"NOT PROBED":i.length>0?"not required":"not configured";return Ge(et,{palette:t,title:"identity",scroll:!0,children:[Ge(rc,{palette:t,title:"Google identity",tone:l?"success":"warning",children:[Ge(kn,{palette:t,label:"user",value:s||"(unknown)"},void 0,!1,void 0,this),Ge(kn,{palette:t,label:"project",value:a||"(unset)"},void 0,!1,void 0,this),Ge(kn,{palette:t,label:"source",value:c||"\u2014"},void 0,!1,void 0,this),Ge(kn,{palette:t,label:"ADC",value:l?"\u2713 available":"\u2717 missing",tone:l?"success":"error"},void 0,!1,void 0,this),Ge(kn,{palette:t,label:"gcloud",value:n?.gcloudInstalled?"\u2713 installed":"\u2717 not installed",tone:n?.gcloudInstalled?"success":"error"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(rc,{palette:t,title:`Service accounts (${i.length})`,tone:g.length===0?"muted":f?"success":"warning",children:[i.length===0?Ge("text",{fg:t.muted,wrapMode:"word",children:"none configured \u2014 identities come from config, never hard-coded"},void 0,!1,void 0,this):i.map((b)=>Ge("text",{fg:b.inactive?t.muted:b.ok===!0?t.success:b.ok===!1?t.error:t.text,wrapMode:"none",children:`${b.inactive?"\u2013":b.ok===!0?"\u2713":b.ok===!1?"\u2717":"\u25CB"} ${b.email}${b.inactive?" \u2014 inactive (route auth is none)":""}`},b.email,!1,void 0,this)),Ge("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Ge(kn,{palette:t,label:"impersonation",value:y,tone:f?"success":g.length>0?"warning":"muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(rc,{palette:t,title:"IAP",tone:d?"success":"muted",children:[Ge("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:Ge(ue,{palette:t,label:d?"routes present":"no IAP routes",tone:d?"success":"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),d?Ge("text",{fg:t.muted,wrapMode:"word",children:"each route needs its own audience"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),!l?Ge(rc,{palette:t,title:"ADC unavailable",tone:"warning",children:[Ge("text",{fg:t.text,wrapMode:"word",children:"Local services still start. Cloud identity, impersonation, and IAP need ADC."},void 0,!1,void 0,this),Ge("text",{fg:t.muted,wrapMode:"word",children:"run `gcloud auth application-default login` or /auth"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)}function gP(e,t){let r=new Map((e?Ml(e):[]).map((i)=>[i.email,i.active])),n=t?.service_account_status??{};return[...new Set([...r.keys(),...Object.keys(n)])].sort((i,s)=>i.localeCompare(s)).map((i)=>{let s=n[i]??"unknown",a=r.get(i)===!1;return{email:i,inactive:a,ok:a||s==="unknown"?void 0:s==="available"}})}var zv=T(()=>{kt();Pe();ve();rn()});import{jsxDEV as ct}from"@opentui/react/jsx-dev-runtime";function Xv(e){let{palette:t,credentials:r}=e;if(!r)return ct(Za,{palette:t,label:"Reading credential store\u2026"},void 0,!1,void 0,this);let n=r.entries.filter((i)=>i.valid).length,o=r.entries.length-n;return ct(et,{palette:t,title:"credentials",scroll:!0,children:[ct("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[ct(ue,{palette:t,label:`backend: ${r.backend}`,tone:"info"},void 0,!1,void 0,this),r.entries.length>0?ct(ue,{palette:t,label:`${n} valid`,tone:"success"},void 0,!1,void 0,this):null,o>0?ct(ue,{palette:t,label:`${o} expired`,tone:"warning"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ct("text",{fg:t.muted,wrapMode:"word",children:"Tokens stay in the OS keychain or ~/.devctl/credentials (0600). They are never shown here."},void 0,!1,void 0,this),ct("box",{height:1,flexShrink:0},void 0,!1,void 0,this),r.entries.length===0?ct("text",{fg:t.muted,children:"no cached credentials"},void 0,!1,void 0,this):ct("box",{flexDirection:"column",overflow:"hidden",gap:1,children:r.entries.map((i)=>ct("box",{border:!0,borderStyle:"rounded",borderColor:i.valid?t.success:t.warning,title:i.identity,titleColor:i.valid?t.success:t.warning,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[ct("text",{wrapMode:"none",children:[ct("span",{fg:i.valid?t.success:t.warning,children:i.valid?"\u2713 valid":"\u2717 expired"},void 0,!1,void 0,this),ct("span",{fg:t.muted,children:` \xB7 expires ${i.expires_at}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ct("text",{fg:t.muted,wrapMode:"none",children:`audience: ${i.audience||"(none)"}`},void 0,!1,void 0,this)]},`${i.identity}|${i.audience}`,!0,void 0,this))},void 0,!1,void 0,this),ct(Qa,{palette:t,title:"Actions",body:"Use /refresh to mint again or auth refresh on the CLI. Invalidate clears the store without printing tokens.",hint:"/refresh /auth"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Qv=T(()=>{kt();ve()});function Zv(e){let t=Object.keys(e.services).length,r=Object.keys(e.profiles).length,n=e.proxy.routes.length,o=[{text:e.project.name||"unnamed",tone:"primary"},{text:`schema ${e.version}`,tone:"muted"},{text:`${t} service${t===1?"":"s"}`,tone:t>0?"info":"idle"},{text:`${r} profile${r===1?"":"s"}`,tone:r>0?"info":"idle"},{text:e.proxy.enabled?"proxy on":"proxy off",tone:e.proxy.enabled?"success":"idle"}];if(n>0)o.push({text:`${n} route${n===1?"":"s"}`,tone:"info"});return o}function ex(e,t){return[{label:"path",value:e.configPath||"\u2014"},{label:"repo",value:e.repoRoot||"\u2014"},{label:"devctl",value:t},{label:"schema",value:String(e.version)}]}function tx(e){return[{label:"project",value:e.google.project_id||"(unset)",tone:e.google.project_id?"text":"muted"},{label:"region",value:e.google.region||"(unset)",tone:e.google.region?"text":"muted"}]}function rx(e){let t=mP(e);return[{label:"exit",value:t,tone:t==="ask on quit"?"warning":"text"},{label:"grace",value:`${e.shutdown.grace_seconds}s`},{label:"refresh",value:`${hs(e.auth)}s`},{label:"env",value:e.environment.sources.join(", ")||"\u2014",tone:e.environment.sources.length>0?"text":"muted"},{label:"theme",value:e.ui.theme||"system"}]}function nx(e){let t=e.logs.persistence;return[{label:"memory",value:`${e.logs.max_memory_events} events`},{label:"persist",value:t.enabled?t.directory:"off",tone:t.enabled?"text":"muted"},{label:"keep",value:t.enabled?`${t.retention_days}d \xB7 ${t.max_session_logs||"\u221E"} sessions`:"\u2014"}]}function ox(e){return[{label:"listen",value:Yr(e.proxy.listen),tone:e.proxy.enabled?"text":"muted"},{label:"token",value:vP(e),tone:e.proxy.token_endpoint.enabled?"text":"muted"}]}function ix(e){return Object.keys(e.services).sort().map((t)=>{let r=e.services[t]??Nn();return{name:t,extends:r.extends||"\u2014",command:Va(r),ports:Ni(r),identity:Ya(r),health:Ja(r),depends:r.dependencies.join(", ")||"\u2014",restart:za(r)}})}function sx(e){return e.proxy.routes.map((t)=>({name:t.name||t.match.host||"(unnamed)",match:xP(t),upstream:t.upstream.url||"\u2014",auth:t.auth.type||"none",identity:bP(t)}))}function ax(e){return Object.keys(e.profiles).sort().map((t)=>{let r=e.profiles[t],n=Object.keys(r?.environment??{}).sort();return{name:t,services:r?.services.join(", ")||"\u2014",env:n.length>0?n.join(", "):"\u2014"}})}function cx(e){return Object.keys(e.templates).sort().map((t)=>({name:t,summary:wP(e.templates[t])}))}function lx(e){let t=e.doctor.tools.map((i)=>i.name||i.command).filter((i)=>i!==""),r=e.plugins.map((i)=>i.path).filter((i)=>i!==""),n=Object.keys(e.ui.keymap),o=[...e.secrets.extra_markers,...e.secrets.extra_patterns];return[{label:"doctor",value:t.join(", ")||"\u2014",tone:t.length>0?"text":"muted"},{label:"plugins",value:r.join(", ")||"\u2014",tone:r.length>0?"text":"muted"},{label:"keymap",value:n.length>0?`${n.length} override${n.length===1?"":"s"}`:"defaults",tone:n.length>0?"text":"muted"},{label:"secrets",value:o.length>0?o.join(", "):"defaults",tone:o.length>0?"text":"muted"}]}function mP(e){if(e.shutdown.stop_services_on_exit===void 0)return"ask on quit";return e.shutdown.stop_services_on_exit?"stop services":"detach"}function dx(e){let t=e.reduce((r,n)=>Math.max(r,n.name.length),0);return Math.min(yP,Math.max(hP,t))}function vP(e){let t=e.proxy.token_endpoint;if(!t.enabled)return"off";let r=t.host===""?"127.0.0.1":t.host;if(t.port===0)return r;return`${r}:${t.port}`}function xP(e){let t=e.match.host||"*",r=e.match.path;if(r==="")return t;return`${t}${r.startsWith("/")?r:`/${r}`}`}function bP(e){if(e.auth.identity.service_account!=="")return e.auth.identity.service_account;if(e.auth.service_account!=="")return e.auth.service_account;return e.auth.identity.type||"user"}function wP(e){if(!e)return"empty";let t=[];if(e.health.type!=="")t.push(`health ${e.health.type}`);if(e.restart.policy!=="")t.push(`restart ${e.restart.policy}`);if(e.logs.stdout||e.logs.stderr)t.push("logs");return t.join(" \xB7 ")||"empty"}var hP=8,yP=20,ux=80,bo=10;var px=T(()=>{St();Pe()});import{jsxDEV as P}from"@opentui/react/jsx-dev-runtime";function mx(e){let{palette:t,cfg:r,width:n}=e,o=re();if(!r)return P(De,{palette:t,title:"No configuration",body:"Create .devctl/config.yaml or run setup."},void 0,!1,void 0,this);let i=Math.max(bo+8,n-6-o.pad*2),s=i>=ux,a=s?Math.floor((i-fx)/2):i,c=ix(r),l=sx(r),d=ax(r),g=cx(r);return P(et,{palette:t,title:`config ${r.project.name||"unnamed"}`,children:[P(Be,{palette:t,items:Zv(r)},void 0,!1,void 0,this),P("box",{flexGrow:1,overflow:"hidden",children:P("scrollbox",{ref:e.scrollRef,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:P("box",{flexDirection:"column",overflow:"hidden",gap:gx,children:[P(Du,{wide:s,left:P(gr,{palette:t,title:"project",children:P(wo,{palette:t,facts:ex(r,at),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:P(gr,{palette:t,title:"google",children:P(wo,{palette:t,facts:tx(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(Du,{wide:s,left:P(gr,{palette:t,title:"runtime",children:P(wo,{palette:t,facts:rx(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:P(gr,{palette:t,title:"logs",children:P(wo,{palette:t,facts:nx(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(gr,{palette:t,title:`proxy ${r.proxy.enabled?"enabled":"disabled"}`,children:[P(wo,{palette:t,facts:ox(r),width:i},void 0,!1,void 0,this),P(kP,{palette:t,routes:l,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(gr,{palette:t,title:`services ${c.length}`,children:P(SP,{palette:t,rows:c,width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(Du,{wide:s,left:P(gr,{palette:t,title:`profiles ${d.length}`,children:P(CP,{palette:t,rows:d,width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:P(gr,{palette:t,title:`templates ${g.length}`,children:P(_P,{palette:t,rows:g,empty:"no templates",width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(gr,{palette:t,title:"extras",children:P(wo,{palette:t,facts:lx(r),width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(je,{palette:t,backgroundColor:t.element,edge:"top",children:P(Ee,{palette:t,hints:[{key:"v",label:"validate/save buffer"},{key:"e",label:"open in $EDITOR"},{key:"/reload",label:"re-read .devctl after editing"},{key:"j/k",label:"scroll"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Du(e){let{wide:t,left:r,right:n}=e;if(!t)return P("box",{flexDirection:"column",overflow:"hidden",gap:gx,flexShrink:0,children:[r,n]},void 0,!0,void 0,this);return P("box",{flexDirection:"row",overflow:"hidden",gap:fx,flexShrink:0,children:[P("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:r},void 0,!1,void 0,this),P("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:n},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function gr(e){let{palette:t,title:r,children:n}=e;return P("box",{border:!0,borderStyle:"rounded",borderColor:t.border,title:r,titleColor:t.accent,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",flexShrink:0,children:n},void 0,!1,void 0,this)}function wo(e){let{palette:t,facts:r,width:n}=e,o=Math.max(4,n-bo-4);return P("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((i)=>P("box",{height:1,flexDirection:"row",overflow:"hidden",children:[P("box",{width:bo,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.muted,wrapMode:"none",children:Y(i.label,bo)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P("box",{width:o,flexShrink:0,overflow:"hidden",children:P("text",{fg:EP(t,i.tone),wrapMode:"none",children:Y(i.value,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},i.label,!0,void 0,this))},void 0,!1,void 0,this)}function SP(e){let{palette:t,rows:r,width:n}=e;if(r.length===0)return P(nc,{palette:t,text:"no services"},void 0,!1,void 0,this);let o=dx(r),i=Math.max(8,n-o-6);return P("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>P("box",{height:1,flexDirection:"row",overflow:"hidden",children:[P("box",{width:o,flexShrink:0,overflow:"hidden",children:P("text",{fg:He(s.name,t),wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P("box",{width:i,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.text,wrapMode:"none",children:ce(RP(s),i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},s.name,!0,void 0,this))},void 0,!1,void 0,this)}function kP(e){let{palette:t,routes:r,width:n}=e;if(r.length===0)return P(nc,{palette:t,text:"no routes"},void 0,!1,void 0,this);let o=Math.min(bo+4,Math.max(8,...r.map((s)=>s.name.length))),i=Math.max(8,n-o-6);return P("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>P("box",{height:1,flexDirection:"row",overflow:"hidden",children:[P("box",{width:o,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.primary,wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P("box",{width:i,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.text,wrapMode:"none",children:ce(PP(s),i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${s.name}-${s.match}`,!0,void 0,this))},void 0,!1,void 0,this)}function CP(e){let{palette:t,rows:r,width:n}=e;if(r.length===0)return P(nc,{palette:t,text:"no profiles"},void 0,!1,void 0,this);let o=Math.min(12,Math.max(8,...r.map((s)=>s.name.length))),i=Math.max(8,n-o-6);return P("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>P("box",{height:1,flexDirection:"row",overflow:"hidden",children:[P("box",{width:o,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.primary,wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P("box",{width:i,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.text,wrapMode:"none",children:ce(s.env==="\u2014"?s.services:`${s.services} env ${s.env}`,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},s.name,!0,void 0,this))},void 0,!1,void 0,this)}function _P(e){let{palette:t,rows:r,empty:n,width:o}=e;if(r.length===0)return P(nc,{palette:t,text:n},void 0,!1,void 0,this);let i=Math.min(14,Math.max(8,...r.map((a)=>a.name.length))),s=Math.max(8,o-i-6);return P("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((a)=>P("box",{height:1,flexDirection:"row",overflow:"hidden",children:[P("box",{width:i,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.text,wrapMode:"none",children:Y(a.name,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this),P("box",{width:s,flexShrink:0,overflow:"hidden",children:P("text",{fg:t.muted,wrapMode:"none",children:ce(a.summary,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},a.name,!0,void 0,this))},void 0,!1,void 0,this)}function nc(e){return P("box",{height:1,overflow:"hidden",children:P("text",{fg:e.palette.muted,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function RP(e){let t=e.extends==="\u2014"?"":` ${e.extends}`;return` ${e.ports} ${e.identity} ${e.health} ${e.restart} \u2190 ${e.depends}${t}`}function PP(e){return` ${e.auth} ${e.identity} ${e.match} \u2192 ${e.upstream}`}function EP(e,t){if(t==="success")return e.success;if(t==="warning")return e.warning;if(t==="error")return e.error;if(t==="muted")return e.muted;return e.text}var fx=1,gx=1;var hx=T(()=>{kt();px();ot();Pe();ve();ze()});import{useRef as TP}from"react";import{jsxDEV as pe}from"@opentui/react/jsx-dev-runtime";function oc(e){let{palette:t,names:r,snap:n,selected:o,checked:i,width:s,onOpen:a,onSelectIndex:c,onToggle:l}=e,d=re(),g=TP(!1),f=new Set(i),h=fu(s),y=pu(s),b=uu(s),w=jh(s);return pe("box",{flexDirection:"column",flexGrow:1,overflow:"hidden",children:[pe("box",{height:1,flexDirection:"row",overflow:"hidden",children:[pe(vt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),pe(vt,{width:4,fg:t.accent,text:"sel"},void 0,!1,void 0,this),pe(vt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),pe(vt,{width:w,fg:t.muted,text:"name"},void 0,!1,void 0,this),pe(vt,{width:yt,fg:t.muted,text:""},void 0,!1,void 0,this),pe(vt,{width:Jt,fg:t.muted,text:"state"},void 0,!1,void 0,this),b?pe(vt,{width:fr,fg:t.muted,text:"health"},void 0,!1,void 0,this):null,y?pe(vt,{width:La,fg:t.muted,text:"port"},void 0,!1,void 0,this):null,h?pe(vt,{width:Mr,fg:t.muted,text:"pid"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),r.map((R,S)=>{let N=n?.services[R],J=Ot(N),v=N?.health??"UNKNOWN",A=f.has(R),m=S===o,_=A?"[x]":"[ ]",F=m?"\u203A":" ";return pe("box",{height:d.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:m?t.highlight:A?t.element:void 0,onMouseDown:()=>{if(g.current)return;if(m){a(R);return}c(S)},children:[pe("box",{width:2,flexShrink:0,children:pe("text",{fg:t.primary,children:F},void 0,!1,void 0,this)},void 0,!1,void 0,this),pe("box",{width:4,flexShrink:0,onMouseDown:()=>{g.current=!0,l?.(R),setTimeout(()=>{g.current=!1},0)},children:pe("text",{fg:AP(t,A,m),children:_},void 0,!1,void 0,this)},void 0,!1,void 0,this),pe("box",{width:2,flexShrink:0,children:pe("text",{fg:Re(t,J),children:Tt(J)},void 0,!1,void 0,this)},void 0,!1,void 0,this),pe(vt,{width:w,fg:m?t.primary:He(R,t),text:Y(R,w)},void 0,!1,void 0,this),pe(vt,{width:yt,fg:t.muted,text:""},void 0,!1,void 0,this),pe(vt,{width:Jt,fg:Re(t,J),text:J},void 0,!1,void 0,this),b?pe(vt,{width:fr,fg:Re(t,v),text:v},void 0,!1,void 0,this):null,y?pe(vt,{width:La,fg:t.text,text:Sn(N)},void 0,!1,void 0,this):null,h?pe(vt,{width:Mr,fg:t.text,text:N?.pid?String(N.pid):""},void 0,!1,void 0,this):null]},R,!0,void 0,this)})]},void 0,!0,void 0,this)}function ic(e){let{palette:t,checked:r,idle:n,profileName:o}=e,i=r.length;if(i>0)return pe(Be,{palette:t,items:[{text:`${i} selected`,tone:"primary"}],hints:[{key:"space",label:"unmark"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"n",label:"start these"},{key:"x",label:"stop these"}]},void 0,!1,void 0,this);if(n)return pe(Be,{palette:t,items:[{text:"none started",tone:"idle"}],hints:[{key:"space",label:"select"},{key:"enter",label:o?`start ${o}`:"open"},{key:"n",label:"start"}]},void 0,!1,void 0,this);return pe(Be,{palette:t,items:[{text:"running",tone:"success"}],hints:[{key:"space",label:"select"},{key:"n",label:"start"},{key:"x",label:"stop"}]},void 0,!1,void 0,this)}function AP(e,t,r){if(t)return e.success;if(r)return e.primary;return e.muted}function vt(e){return pe("box",{width:e.width,flexShrink:0,overflow:"hidden",children:pe("text",{fg:e.fg,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Mu=T(()=>{Pe();ot();ve();ze()});import{useEffect as Ou,useRef as yx}from"react";import{jsxDEV as K,Fragment as $P}from"@opentui/react/jsx-dev-runtime";function vx(e){let{palette:t,logs:r,names:n,logSources:o,service:i,paused:s,errorOnly:a,showSystemLogs:c,search:l,searchFocused:d,followTick:g,width:f,onSearch:h,onService:y,onToggleErrors:b,onToggleSystemLogs:w,onClearLogs:R,onSelect:S,wrapMode:N="focus",selected:J=-1,follow:v=!0,newer:A=0,viewStart:m=0,viewTotal:_,onLeaveLatest:F,onOpenExports:Z,onJumpLatest:he,view:ke,fullscreen:Je=!1,facets:Ue}=e,ae=re(),Oe=Uh(f,ae.pad,Je),Ke=c?r:r.filter((_t)=>!Oi(_t.source)),de=yo(r,{service:i,services:e.services,errorOnly:a,search:l,regex:e.regex,source:e.source,systemLogs:c}),we=ke??de,Ce=_??de.length,W=Math.min(Ce,m+we.length),Ie=Ce===0?"empty":`${m+1}\u2013${W} of ${Ce}`,lt=e.services??[],$e=lt.length>0?lt.join(","):i===""?"all services":i;return K("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[Je?null:K($P,{children:[K(Be,{palette:t,items:[{text:s?"PAUSED":"LIVE",tone:s?"warning":"success"},{text:`shown ${Ce}`,tone:"info"},{text:Ue?`total ${Ue.total}`:`total ${r.length}`},...ke&&Ce>ke.length?[{text:`${m+1}\u2013${m+ke.length} / ${Ce}`,tone:"info"}]:[],{text:$e,tone:i===""?"idle":"primary"},{text:Ai(N),tone:N==="clip"?"idle":"accent"},...v?[]:[{text:A>0?`pinned \xB7 +${A} new`:"pinned",tone:"warning"}],{text:a?"ERROR+":"all levels",tone:a?"error":"idle",onMouseDown:b},{text:c?"system: on":"system: off",tone:c?"accent":"idle",onMouseDown:w},...e.source?[{text:`src ${e.source}`,tone:"info"}]:[],...e.regex?[{text:"regex",tone:"accent"}]:[],...l===""?[]:[{text:`search ${l}`,tone:"accent"}],{text:"clear",tone:"muted",onMouseDown:R},{text:"open folder",tone:"primary",onMouseDown:Z}]},void 0,!1,void 0,this),K(Fu,{palette:t,logs:Ke,names:o??n,service:i,errorOnly:a,width:f,onService:y,onToggleErrors:b,facets:Ue},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d?K("box",{height:1,paddingLeft:1,backgroundColor:t.highlight,overflow:"hidden",children:K("input",{focused:!0,value:l,placeholder:"search messages or service names",onInput:h,backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ke&&Ce>we.length?K(Iu,{palette:t,start:m,count:we.length,total:Ce},void 0,!1,void 0,this):null,K("box",{flexGrow:1,border:!Je,borderStyle:"rounded",borderColor:t.border,title:Je?void 0:`logs ${$e} \xB7 ${Ie}`,titleColor:t.primary,padding:Je?0:ae.pad,overflow:"hidden",children:we.length===0?K(De,{palette:t,title:r.length===0?"No log events":"No events in this filter",body:r.length===0?"Start services to stream logs.":"Pick All, another service, or clear search / ERROR+.",hint:"\u2190 \u2192 cycle filters 1-9 pick a source e errors i internal ctrl+l clear"},void 0,!1,void 0,this):K(Nu,{palette:t,logs:we,width:Oe,followTick:g,focused:!1,wrapMode:N,selected:J,follow:v,showTimestamps:e.showTimestamps!==!1,showMeta:e.showMeta!==!1,onPick:S,onLeaveLatest:F,viewStart:m},g,!1,void 0,this)},void 0,!1,void 0,this),K(je,{palette:t,backgroundColor:t.element,edge:"top",children:K(Ee,{palette:t,hints:po([{key:"\u2190\u2192",label:"filter"},{key:"1-9",label:"source"},{key:"e",label:"errors"},{key:"i",label:c?"internal off":"internal on"},{key:"ctrl+l",label:"clear"},{key:"f",label:"search"},{key:"j/k",label:"move"},{key:"enter",label:"details"},{key:"g",label:A>0?`latest +${A}`:"latest"},{key:"w",label:"wrap"},{key:"p",label:"pause"},{key:"z",label:Je?"exit full":"full screen"},{key:"t",label:e.showTimestamps===!1?"time off":"time"},{key:"m",label:e.showMeta===!1?"meta off":"meta"},{key:"pgup/pgdn",label:"history"},{key:"/exports",label:"open folder"}],Math.max(20,f-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!v?K($u,{palette:t,width:f,newer:A,onJump:he},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function Iu(e){let t=Math.min(e.total,e.start+e.count),r=Math.max(0,e.start),n=Math.max(0,e.total-t);return K(Be,{palette:e.palette,items:[{text:`view ${e.start+1}\u2013${t} of ${e.total}`,tone:"primary"},{text:r>0?`\u2191 ${r} older`:"start of history",tone:r>0?"info":"idle"},{text:n>0?`\u2193 ${n} newer`:"at latest",tone:n>0?"warning":"success"}],hints:[{key:"pgup/pgdn",label:"move history window"},{key:"g",label:"latest"}]},void 0,!1,void 0,this)}function $u(e){let t=e.newer>0?`g jump to latest \xB7 ${e.newer} new`:"g jump to latest",r=Math.min(e.width,t.length+4);return K("box",{position:"absolute",left:Math.max(0,Math.floor((e.width-r)/2)),bottom:e.bottom??2,width:r,height:3,border:!0,borderStyle:"rounded",borderColor:e.palette.warning,backgroundColor:e.palette.panel,alignItems:"center",justifyContent:"center",onMouseDown:e.onJump,children:K("text",{wrapMode:"none",children:[K("span",{fg:e.palette.primary,children:"g"},void 0,!1,void 0,this),K("span",{fg:e.palette.text,children:t.slice(1)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Fu(e){let{palette:t,logs:r,names:n,service:o,errorOnly:i,width:s,onService:a,onToggleErrors:c,facets:l}=e,d=l?Ay(n,l):Ty(n,r),g=s<80,f=d.map((w,R)=>{let S=R+1,N=w.name===""?"all":w.name;return{id:N,label:g?`${S} ${N}`:`${S} ${N} \xB7 ${w.count}`,color:He(w.name,t)}}),h=Math.max(0,d.findIndex((w)=>w.name===o)),y=i?"ERROR+":g?"lvls":"all levels",b=Math.max(Lr(f[h]?.label??"1 all"),s-Lr(y));return K(je,{palette:t,backgroundColor:t.element,children:K("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[K("box",{flexGrow:1,overflow:"hidden",children:K(Xa,{palette:t,items:f,active:h,width:b,onPick:(w)=>{let R=d[w];if(R)a(R.name)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),K(ue,{palette:t,label:y,tone:i?"error":"muted",onMouseDown:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Nu(e){let{palette:t,logs:r,limit:n,width:o=80,followTick:i=0,focused:s=!1,wrapMode:a="clip",selected:c=-1,follow:l=!0,showTimestamps:d=!0,showMeta:g=!0,onPick:f,onLeaveLatest:h,viewStart:y=0}=e,b=yx(null),w=yx(""),R=n===void 0?r:r.slice(-n),S=[...new Set(r.map((v)=>v.service))],N=Xh(o,S),J=Yh({width:o,serviceWidth:N,showTimestamps:d,showMeta:g});return Ou(()=>{let v=b.current;if(!v)return;if(v.stickyScroll=l,l)v.stickyStart="bottom",v.scrollTo({x:v.scrollLeft,y:Math.max(0,v.scrollHeight)})},[l,i]),Ou(()=>{let v=`${y}:${c}:${a}`;if(w.current===v)return;if(w.current=v,l&&(c<0||c>=R.length-1))return;let A=b.current;if(!A||c<0)return;let m=`log-row-${c}`,_=requestAnimationFrame(()=>{A.stickyScroll=!1,A.scrollChildIntoView(m)});return()=>cancelAnimationFrame(_)},[l,c,R.length,y,a]),Ou(()=>{if(!l||!h)return;let v=!1,A=setTimeout(()=>{v=!0},LP),m=setInterval(()=>{let _=b.current;if(!v||!_)return;let F=_.viewport.height;if(F>0&&_.scrollTop+F<_.scrollHeight-MP)h()},DP);return()=>{clearTimeout(A),clearInterval(m)}},[l,i,h]),K("box",{flexGrow:1,height:"100%",overflow:"hidden",children:K("scrollbox",{ref:b,focused:s,stickyScroll:l,stickyStart:"bottom",scrollX:!1,style:{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:t.panel},viewportOptions:{backgroundColor:t.panel},contentOptions:{backgroundColor:t.panel},scrollbarOptions:{trackOptions:{foregroundColor:t.primary,backgroundColor:t.element}}},children:K("box",{flexDirection:"column",overflow:"hidden",children:R.map((v,A)=>K(OP,{id:`log-row-${A}`,palette:t,event:v,serviceWidth:N,msgWidth:J,expanded:qh(a,A===c),active:A===c,showTimestamps:d,showMeta:g,onPick:f?()=>f(A):void 0},`${v.timestamp}-${v.service}-${A}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function OP(e){let{id:t,palette:r,event:n,serviceWidth:o,msgWidth:i,expanded:s,active:a,showTimestamps:c=!0,showMeta:l=!0,onPick:d}=e,g=Kh(ja(n.message,i),i,s);return K("box",{id:t,flexShrink:0,flexDirection:"column",overflow:"hidden",backgroundColor:a?r.highlight:void 0,onMouseDown:d,children:g.visible.map((f,h)=>K("box",{height:1,flexDirection:"row",overflow:"hidden",children:[c?K("box",{width:Na,flexShrink:0,overflow:"hidden",children:K("text",{fg:r.muted,children:h===0?n.timestamp.slice(11,19):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,K("box",{width:o,flexShrink:0,overflow:"hidden",children:K("text",{fg:h===0?He(n.service,r):r.muted,wrapMode:"none",children:h===0?Y(n.service,o):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),K("box",{width:Ti,flexShrink:0,overflow:"hidden",children:K("text",{children:" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),K("box",{width:Ha,flexShrink:0,overflow:"hidden",children:K("text",{fg:h===0?Re(r,n.level):r.muted,children:h===0?String(n.level):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),l?K("box",{width:$a,flexShrink:0,overflow:"hidden",children:K("text",{fg:r.muted,children:h===0&&n.source?Y(n.source,$a):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,K("box",{width:Ti,flexShrink:0,overflow:"hidden",children:K("text",{fg:r.muted,children:h===0?" ":"\u2502"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K("box",{flexGrow:1,overflow:"hidden",children:K(IP,{palette:r,level:n.level,text:f,mark:h===0?g.mark:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${n.timestamp}-${h}`,!0,void 0,this))},void 0,!1,void 0,this)}function IP(e){let{palette:t,level:r,text:n,mark:o}=e;return K("text",{wrapMode:"none",children:[Jh(n).map((i,s)=>K("span",{fg:xh(t,r,i.kind),children:i.text},`${i.kind}-${s}`,!1,void 0,this)),o===""?null:K("span",{fg:t.muted,children:o},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var LP=400,DP=200,MP=2;var Hu=T(()=>{kt();ot();Pe();ve();ze()});import{jsxDEV as le}from"@opentui/react/jsx-dev-runtime";function bx(e){let{palette:t,cfg:r,snap:n,logs:o,names:i,selected:s,selectedLog:a=-1,checked:c,profile:l,google:d,width:g,paused:f,followTick:h,logService:y,logSources:b,errorOnly:w,showSystemLogs:R,onOpen:S,onSelectIndex:N,onToggle:J,onFilterService:v,onToggleErrors:A,onToggleSystemLogs:m,onClearLogs:_,onShowErrors:F,wrapMode:Z="clip",view:he,follow:ke=!0,onLeaveLatest:Je,onPickLog:Ue,viewStart:ae=0,viewTotal:Oe,newer:Ke=0,onJumpLatest:de,facets:we}=e,Ce=re();if(!r||i.length===0)return le(De,{palette:t,title:"No services configured",body:"Add services to .devctl/config.yaml or finish setup.",hint:"open the setup screen with /setup"},void 0,!1,void 0,this);let W=g<uo,Ie=ho(n),lt=Ua(n,i),$e=i.filter((Pn)=>n?.services[Pn]?.state==="FAILED").length,_t=n?.session_id?fs(n.session_id):void 0,dt=_t?mo(Date.now()-_t.getTime()):void 0,zt=Ry(o),ut=l||Wa(r),Xt=Yy(r,ut),pt=Ba(g,i,W),_n=Math.max(24,W?g-4:g-pt-4),fc=R?o:o.filter((Pn)=>!Oi(Pn.source)),C=yo(o,{service:y,errorOnly:w,systemLogs:R}),Qt=he??C,jr=Oe??C.length,Rn=Math.min(jr,ae+Qt.length),gc=jr===0?"empty":`${ae+1}\u2013${Rn} of ${jr}`,mc=y===""?"all services":y;return le("box",{flexGrow:1,flexDirection:W?"column":"row",overflow:"hidden",children:[le("box",{flexGrow:W?1:0,flexShrink:0,minWidth:W?void 0:pt,width:W?void 0:pt,border:!0,borderStyle:"rounded",borderColor:Ie?t.border:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[le(Be,{palette:t,items:[{text:vu(lt.running,i.length),tone:lt.running>0?"success":"idle"},...$e>0?[{text:`${$e} failed`,tone:"error"}]:[],...c.length>0?[{text:`${c.length} selected`,tone:"primary"}]:[],...dt!==void 0?[{text:`up ${dt}`,tone:"idle"}]:[],...zt>0?[{text:`${zt} errors`,tone:"error",onMouseDown:F}]:[]]},void 0,!1,void 0,this),le(ic,{palette:t,checked:c,idle:Ie,profileName:ut,members:Xt},void 0,!1,void 0,this),le("box",{flexGrow:1,paddingLeft:Ce.pad,paddingRight:Ce.pad,overflow:"hidden",children:le(oc,{palette:t,names:i,snap:n,selected:s,checked:c,width:Fa(pt,Ce.pad),onOpen:S,onSelectIndex:N,onToggle:J},void 0,!1,void 0,this)},void 0,!1,void 0,this),le(jP,{palette:t,names:i,snap:n,width:pt,onOpen:S},void 0,!1,void 0,this),le(BP,{palette:t,cfg:r,snap:n,google:d,width:pt},void 0,!1,void 0,this)]},void 0,!0,void 0,this),le("box",{position:"relative",flexGrow:2,minWidth:W?void 0:32,minHeight:W?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:`logs \xB7 ${gc}`,titleColor:t.primary,overflow:"hidden",flexDirection:"column",children:[le(Be,{palette:t,items:[{text:f?"PAUSED":"LIVE",tone:f?"warning":"success"},{text:`shown ${C.length}`,tone:"info"},{text:we?`total ${we.total}`:`total ${o.length}`},{text:mc,tone:y===""?"idle":"primary"},{text:w?"ERROR+":"all levels",tone:w?"error":"idle",onMouseDown:A},{text:R?"system: on":"system: off",tone:R?"accent":"idle",onMouseDown:m},{text:"clear",tone:"muted",onMouseDown:_}]},void 0,!1,void 0,this),le(Fu,{palette:t,logs:fc,names:b??i,service:y,errorOnly:w,width:_n,onService:v,onToggleErrors:A,facets:we},void 0,!1,void 0,this),jr>Qt.length?le(Iu,{palette:t,start:ae,count:Qt.length,total:jr},void 0,!1,void 0,this):null,C.length===0?le(De,{palette:t,title:Ie?"Waiting for logs":o.length===0?"No events yet":"No events in this filter",body:Ie?"Start services to stream output here. Later starts keep earlier logs.":o.length===0?"New lines appear as services write output.":"Click All or another service chip, or turn off ERROR+.",hint:"[ ] cycle service g jump to latest"},void 0,!1,void 0,this):le(Nu,{palette:t,logs:Qt,width:_n,followTick:h,focused:!1,wrapMode:Z,selected:a,follow:ke,onLeaveLatest:Je,onPick:Ue,viewStart:ae},h,!1,void 0,this),le(je,{palette:t,backgroundColor:t.element,edge:"top",children:le(Ee,{palette:t,hints:po([{key:"e",label:"errors"},{key:"i",label:R?"internal off":"internal on"},{key:"ctrl+l",label:"clear"},{key:"g",label:"latest"},{key:"z",label:"full logs"},{key:"\u2190\u2192",label:"filter"}],Math.max(20,_n-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!ke?le($u,{palette:t,width:_n,newer:Ke,bottom:1,onJump:de},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function NP(e){if(!e)return!1;return e.state===ln||e.health===Ae||e.state===pi||e.restarts>0||e.last_error!==""}function xx(e){if(e.state===ln)return 0;if(e.health===Ae)return 1;if(e.state===pi)return 2;return 3}function HP(e){if(e.last_error!=="")return e.last_error;if(e.restarts>0)return`restarted ${e.restarts}x, no error recorded`;return e.health===Ae?"failing health check":e.state.toLowerCase()}function jP(e){let{palette:t,names:r,snap:n,width:o,onOpen:i}=e,s=r.map((d)=>({name:d,rt:n?.services[d]})).filter((d)=>NP(d.rt)).sort((d,g)=>xx(d.rt)-xx(g.rt));if(s.length===0)return null;let a=s.slice(0,FP),c=s.length-a.length,l=Math.max(8,o-ju-4);return le("box",{border:!0,borderStyle:"rounded",borderColor:t.error,title:`issues (${s.length})`,titleColor:t.error,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[a.map(({name:d,rt:g})=>{let f=Ot(g);return le("box",{height:1,flexDirection:"row",overflow:"hidden",onMouseDown:()=>i(d),children:[le("box",{width:2,flexShrink:0,children:le("text",{fg:Re(t,f),children:Tt(f)},void 0,!1,void 0,this)},void 0,!1,void 0,this),le("box",{width:ju,flexShrink:0,overflow:"hidden",children:le("text",{fg:He(d,t),wrapMode:"none",children:Y(d,ju)},void 0,!1,void 0,this)},void 0,!1,void 0,this),le("box",{width:l,flexShrink:0,overflow:"hidden",children:le("text",{fg:t.muted,wrapMode:"none",children:ce(HP(g),l)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)}),c>0?le("text",{fg:t.muted,wrapMode:"none",children:`+${c} more \u2014 open a service to see details`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function BP(e){let{palette:t,cfg:r,snap:n,google:o,width:i}=e,s=o?.userEmail,a=vo(r,n?.identity,o).project,c=n?.logs.total??0,l=zy(s,a,c,i);return le(je,{palette:t,backgroundColor:t.element,edge:"top",children:le("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:l.map((d,g)=>le(ue,{palette:t,label:d.label,tone:d.tone},`${d.label}-${g}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var FP=4,ju=14;var wx=T(()=>{Pe();ot();ve();kt();ze();dn();Ye();Mu();Hu()});import{useEffect as WP,useState as GP}from"react";import{jsxDEV as V}from"@opentui/react/jsx-dev-runtime";function kx(e){let{palette:t,report:r,loading:n,progress:o,error:i,selected:s,onPick:a,onReload:c}=e,l=xo(s,Bu);if(n)return V(UP,{palette:t,progress:o},void 0,!1,void 0,this);if(i)return V(ov,{palette:t,title:"Doctor failed",body:i},void 0,!1,void 0,this);if(!r)return V(De,{palette:t,title:"Doctor",body:"Diagnostics have not run yet.",hint:"opening this screen runs doctor"},void 0,!1,void 0,this);let d=r.checks.filter((w)=>w.severity==="ok").length,g=r.checks.filter((w)=>w.severity==="warn").length,f=r.checks.filter((w)=>w.severity==="error").length,h=r.checks.length,y=Mi(h>0?d/h:0),b=f>0?t.error:g>0?t.warning:t.success;return V(et,{palette:t,title:`doctor ${r.issues} issue(s)`,children:[V("box",{height:4,flexDirection:"column",flexShrink:0,alignItems:"center",justifyContent:"center",overflow:"hidden",border:!0,borderStyle:"rounded",borderColor:t.primary,backgroundColor:t.element,onMouseDown:c,children:[V("text",{wrapMode:"none",children:[V("span",{fg:t.inverse,bg:t.primary,children:" r "},void 0,!1,void 0,this),V("span",{fg:t.primary,children:" RUN DOCTOR AGAIN"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V("text",{fg:t.muted,wrapMode:"none",children:"results stay cached until you refresh"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V("box",{height:1,flexShrink:0},void 0,!1,void 0,this),V("box",{height:1,flexShrink:0,overflow:"hidden",children:V("text",{wrapMode:"none",children:[V("span",{fg:b,children:`[${y}]`},void 0,!1,void 0,this),V("span",{fg:t.success,children:` ${d} ok`},void 0,!1,void 0,this),g>0?V("span",{fg:t.warning,children:` \xB7 ${g} warn`},void 0,!1,void 0,this):null,f>0?V("span",{fg:t.error,children:` \xB7 ${f} error`},void 0,!1,void 0,this):null,g===0&&f===0?V("span",{fg:t.muted,children:" \xB7 all clear"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V("box",{height:1,flexShrink:0},void 0,!1,void 0,this),V("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:V("box",{flexDirection:"column",overflow:"hidden",gap:1,children:r.checks.map((w,R)=>V(KP,{palette:t,check:w,index:R,active:R===s,onPick:a},`${w.name}-${R}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function UP({palette:e,progress:t}){let[r,n]=GP(0);return WP(()=>{let o=setInterval(()=>n((i)=>(i+1)%Sx.length),120);return()=>clearInterval(o)},[]),V("box",{flexGrow:1,alignItems:"center",justifyContent:"center",overflow:"hidden",children:V("box",{width:"80%",maxWidth:52,height:10,flexShrink:1,border:!0,borderStyle:"rounded",borderColor:e.borderActive,backgroundColor:e.panel,flexDirection:"column",alignItems:"center",justifyContent:"center",overflow:"hidden",children:[V("text",{wrapMode:"none",children:[V("span",{fg:e.primary,children:`${Sx[r]} `},void 0,!1,void 0,this),V("span",{fg:e.text,children:"devctl doctor"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V("box",{height:1,flexShrink:0},void 0,!1,void 0,this),V("text",{fg:e.text,wrapMode:"none",children:`Checking ${t.active}`},void 0,!1,void 0,this),V("box",{height:1,flexShrink:0},void 0,!1,void 0,this),t.checks.slice(-4).map((o,i)=>V("text",{wrapMode:"none",children:[V("span",{fg:Re(e,o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK"),children:`${Tt(o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK")} `},void 0,!1,void 0,this),V("span",{fg:e.muted,children:o.name},void 0,!1,void 0,this)]},`${o.name}-${i}`,!0,void 0,this)),t.checks.length===0?V("text",{fg:e.muted,children:"Waiting for the first result\u2026"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function KP(e){let{palette:t,check:r,index:n,active:o,onPick:i}=e,s=r.severity==="error"?"ERROR":r.severity==="warn"?"WARN":"OK";if(r.severity==="ok")return V("box",{id:`${Bu}-${n}`,flexDirection:"row",flexShrink:0,paddingLeft:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(n),children:V("text",{wrapMode:"none",children:[V("span",{fg:t.primary,children:o?"\u203A ":" "},void 0,!1,void 0,this),V("span",{fg:Re(t,s),children:Tt(s)},void 0,!1,void 0,this),V("span",{fg:o?t.primary:t.text,children:` ${r.name}`},void 0,!1,void 0,this),V("span",{fg:t.muted,children:r.message?` \xB7 ${r.message}`:""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this);let c=r.severity==="error"?t.error:t.warning;return V("box",{id:`${Bu}-${n}`,border:!0,borderStyle:"rounded",borderColor:o?t.borderActive:c,title:r.name,titleColor:c,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(n),children:[V("text",{wrapMode:"word",children:[V("span",{fg:Re(t,s),children:`${Tt(s)} `},void 0,!1,void 0,this),V("span",{fg:t.text,children:r.message},void 0,!1,void 0,this)]},void 0,!0,void 0,this),r.hint?V("text",{fg:t.info,wrapMode:"word",children:`\u2192 ${r.hint}`},void 0,!1,void 0,this):null,o&&r.action?.kind==="free-port"?V("text",{fg:t.primary,wrapMode:"none",children:`enter stop ${r.action.holder.command} (pid ${r.action.holder.pid})`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var Bu="doctor-row",Sx;var Cx=T(()=>{kt();Pe();ve();ze();Sx=["\u25D0","\u25D3","\u25D1","\u25D2"]});import{jsxDEV as Se}from"@opentui/react/jsx-dev-runtime";function Rx(e){let{palette:t,cfg:r,snap:n,profile:o,selected:i,onPick:s}=e,a=re(),c=xo(i,_x),l=Object.keys(r?.profiles??{}).sort();if(l.length===0)return Se(De,{palette:t,title:"No profiles",body:"Add profiles.<name>.services in config.yaml."},void 0,!1,void 0,this);return Se(et,{palette:t,title:"profiles",children:[Se("box",{height:1,flexShrink:0,overflow:"hidden",children:Se("text",{fg:t.muted,wrapMode:"none",children:[`${l.length} profile${l.length===1?"":"s"} \xB7 current: `,Se("span",{fg:t.success,children:o||"(none)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Se("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Se("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:Se("box",{flexDirection:"column",overflow:"hidden",gap:a.gap||1,children:l.map((d,g)=>{let f=d===o,h=g===i,y=r?.profiles[d]?.services??[],b=Object.keys(r?.profiles[d]?.environment??{}).length,w=h?t.borderActive:f?t.success:t.border,R=h?t.primary:f?t.success:t.muted;return Se("box",{id:`${_x}-${g}`,border:!0,borderStyle:"rounded",borderColor:w,title:d,titleColor:R,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:h?t.highlight:void 0,onMouseDown:()=>s(g),children:[Se("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:Se("text",{wrapMode:"none",children:[f?Se("span",{fg:t.success,children:"\u25CF current profile"},void 0,!1,void 0,this):Se("span",{fg:t.muted,children:"\u25CB not active"},void 0,!1,void 0,this),Se("span",{fg:t.muted,children:` \xB7 ${y.length} service${y.length===1?"":"s"}`},void 0,!1,void 0,this),b>0?Se("span",{fg:t.muted,children:` \xB7 ${b} env var${b===1?"":"s"}`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Se("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:y.length===0?Se("text",{fg:t.muted,wrapMode:"none",children:"(no services)"},void 0,!1,void 0,this):Se("text",{wrapMode:"none",children:y.map((S,N)=>{let J=Ot(n?.services[S]);return Se("span",{children:[Se("span",{fg:Re(t,J),children:Tt(J)},void 0,!1,void 0,this),Se("span",{fg:He(S,t),children:` ${S}`},void 0,!1,void 0,this),N<y.length-1?Se("span",{fg:t.muted,children:" "},void 0,!1,void 0,this):null]},S,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),Se(je,{palette:t,backgroundColor:t.element,edge:"top",children:Se(Ee,{palette:t,hints:[{key:"space",label:"set current"},{key:"enter",label:"set and start"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var _x="profile-row";var Px=T(()=>{kt();ot();Pe();ve();ze()});import{jsxDEV as j,Fragment as Lx}from"@opentui/react/jsx-dev-runtime";function qP(e){let t=e.toLowerCase();if(t==="iap")return"info";if(t==="service"||t==="service_account")return"primary";return"idle"}function VP(e,t,r){if(r||t>=500)return e.error;if(t===0||t>=400)return e.warning;return e.success}function JP(e,t){if(t.startsWith("sa:"))return{label:"SA",color:e.primary};if(t!=="")return{label:"USR",color:e.info};return{label:"\u2014",color:e.muted}}function QP(e){let{palette:t,req:r,cols:n}=e,o=VP(t,r.status,r.error),i=r.status>0?String(r.status):"ERR",s=JP(t,r.identity),a=r.route||Dx,c=r.error?`${r.path} \u2014 ${ce(r.error,XP)}`:r.path;return j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[j("box",{width:Wu,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:r.timestamp.slice(11,19)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showMethod?j("box",{width:sc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.text,wrapMode:"none",children:Y(r.method,sc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:ac,flexShrink:0,overflow:"hidden",children:j("text",{fg:o,wrapMode:"none",children:Y(i,ac)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showDur?j("box",{width:cc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,wrapMode:"none",children:Y(`${r.durationMs}ms`,cc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:lc,flexShrink:0,overflow:"hidden",children:j("text",{fg:s.color,wrapMode:"none",children:Y(s.label,lc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{width:n.routeCol,flexShrink:0,overflow:"hidden",children:j("text",{fg:r.route?t.info:t.muted,wrapMode:"none",children:Y(a,n.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,overflow:"hidden",children:j("text",{fg:r.error?t.error:t.text,wrapMode:"none",children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ZP(e){let{palette:t,cols:r}=e;return j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[j("box",{width:Wu,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("TIME",Wu)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showMethod?j("box",{width:sc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("METHOD",sc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:ac,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("ST",ac)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showDur?j("box",{width:cc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("DUR",cc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:lc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("WHO",lc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{width:r.routeCol,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("ROUTE",r.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,overflow:"hidden",children:j("text",{fg:t.muted,children:"PATH"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function eE(e){let{palette:t,name:r,auth:n,identity:o,upstream:i,match:s,onMouseDown:a}=e;return j("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",onMouseDown:a,children:[j("text",{fg:t.text,wrapMode:"none",children:r},void 0,!1,void 0,this),j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[j(ue,{palette:t,label:n||"no auth",tone:qP(n)},void 0,!1,void 0,this),o?j(ue,{palette:t,label:o,tone:"idle"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),s?j("text",{fg:t.muted,wrapMode:"none",children:`match: ${s}`},void 0,!1,void 0,this):null,j("text",{fg:t.muted,wrapMode:"none",children:`\u2192 ${i}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Mx(e){let{palette:t,cfg:r,snap:n,width:o,onSelectRoute:i}=e,s=n?.proxy.routes??[],a=new Map((r?.proxy.routes??[]).map((v)=>[v.name,v])),c=new Map((r?.proxy.routes??[]).map((v)=>[v.name,v.match])),l=n?.proxy.recentRequests??[],d=n?.proxy.requestTotal??0,g=n?.proxy.requestErrors??0,f=o<uo,h=Math.max(Ex,Math.min(tE,Math.floor(o*0.36))),y=f?o-Tx:o-h-Tx,b=Math.max(20,y-2),w=b>=Ax,R=b>=rE,S=b>=Ax?nE:oE,N=l.reduce((v,A)=>Math.min(S,Math.max(v,(A.route||Dx).length+zP)),YP),J={showMethod:w,showDur:R,routeCol:N};return j(et,{palette:t,title:"proxy",children:[j(Be,{palette:t,items:[{text:n?.proxy.running?"RUNNING":"STOPPED",tone:n?.proxy.running?"success":"idle"},...n?.proxy.address?[{text:n.proxy.address,tone:"info"}]:[],{text:`${s.length} routes`,tone:s.length>0?"primary":"idle"},...d>0?[{text:`${d} requests`,tone:"idle"},...g>0?[{text:`${g} errors`,tone:"warning"}]:[]]:[]]},void 0,!1,void 0,this),j("box",{flexGrow:1,flexDirection:f?"column":"row",overflow:"hidden",children:[j("box",{flexGrow:f?1:0,flexBasis:f?0:void 0,flexShrink:0,minWidth:f?void 0:Ex,width:f?void 0:h,minHeight:f?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"routes",titleColor:t.primary,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",children:s.length===0?j(De,{palette:t,title:"No proxy routes",body:"Add routes under proxy.routes or .devctl/proxy/routes.yaml."},void 0,!1,void 0,this):j(Lx,{children:[i?j("text",{fg:t.muted,wrapMode:"word",children:"click a route for full details"},void 0,!1,void 0,this):null,j("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:j("box",{flexDirection:"column",overflow:"hidden",gap:1,children:s.map((v)=>{let A=c.get(v.name),m=A&&(A.host||A.path)?`${A.host||"*"}${A.path?A.path:""}`:void 0,_=a.get(v.name);return j(eE,{palette:t,name:v.name,auth:v.auth,identity:v.identity,upstream:v.upstream,match:m,onMouseDown:i?()=>i({name:v.name,authType:_?.auth.type||v.auth,identityType:_?.auth.identity.type??"",serviceAccount:_?.auth.identity.service_account||_?.auth.service_account||"",audience:_?.auth.audience??"",matchHost:_?.match.host??"",matchPath:_?.match.path??"",upstream:v.upstream}):void 0},v.name,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,flexBasis:0,minWidth:f?void 0:30,minHeight:f?10:void 0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,title:"requests",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:l.length===0?j("box",{paddingLeft:1,paddingRight:1,children:j("text",{fg:t.muted,wrapMode:"word",children:n?.proxy.running?"No requests seen yet. Send one through the proxy to see it show up here \u2014 no need to restart or press r.":"Start the proxy, then send it a request to see live traffic here."},void 0,!1,void 0,this)},void 0,!1,void 0,this):j(Lx,{children:[j(ZP,{palette:t,cols:J},void 0,!1,void 0,this),j("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:j("box",{flexDirection:"column",overflow:"hidden",children:l.map((v)=>j(QP,{palette:t,req:v,cols:J},v.requestId,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(je,{palette:t,backgroundColor:t.element,edge:"top",children:j(Ee,{palette:t,hints:[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Wu=9,sc=8,ac=4,cc=8,lc=4,YP=8,zP=2,XP=64,Dx="(none)",Ex=26,tE=42,Tx=2,Ax=46,rE=54,nE=20,oE=12;var Ox=T(()=>{kt();Pe();ve()});import{jsxDEV as te}from"@opentui/react/jsx-dev-runtime";function Fx(e){let{palette:t,name:r}=e;return te("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:r,titleColor:He(r,t),flexDirection:"column",overflow:"hidden",children:te(Gu,{...e,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Gu(e){let{palette:t,cfg:r,snap:n,name:o,reveal:i,width:s,compact:a=!0,envScrollRef:c}=e,l=re(),d=r?.services[o];if(!d)return te(De,{palette:t,title:"Unknown service",body:`No service named ${o}.`,hint:"j/k move"},void 0,!1,void 0,this);let g=n?.services[o],f=Ot(g),h=g?.health??"UNKNOWN",y=Sn(g)||Ni(d,g),b=qy(d,i,r?.secrets.extra_markers??[],r?.secrets.extra_patterns??[]),w=s>=sE,R=[{label:"health",value:Ja(d)},{label:"workdir",value:d.working_dir||"."},{label:"restart",value:za(d)},{label:"caps",value:d.capabilities.join(", ")||"\u2014"}],S=[{label:"identity",value:Ya(d,g)},{label:"depends",value:d.dependencies.join(", ")||"\u2014"},{label:"ports",value:Ni(d,g)},{label:"tries",value:String(g?.restarts??0),tone:g?.restarts?"warning":"muted"}],N=Math.max(Cn+8,s-2),J=w?Math.floor(N/2):N;return te("box",{padding:l.pad,flexGrow:1,flexDirection:"column",overflow:"hidden",children:[te(Be,{palette:t,items:[{text:f,tone:$x(f)},{text:h,tone:$x(h)},{text:g?.pid?`pid ${g.pid}`:"pid \u2014",tone:g?.pid?"info":"idle"},{text:y==="\u2014"?"port \u2014":`port ${y}`,tone:y==="\u2014"?"idle":"info"}]},void 0,!1,void 0,this),d.description?te("box",{height:1,overflow:"hidden",children:te("text",{fg:t.muted,wrapMode:"none",children:ce(d.description,Math.max(8,s-4))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,g?.last_error?te("box",{height:1,overflow:"hidden",children:te("text",{fg:t.error,wrapMode:"none",children:ce(g.last_error,iE)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,te(Uu,{palette:t,item:{label:"command",value:Va(d)},valueWidth:Math.max(8,N-Cn)},void 0,!1,void 0,this),te(aE,{palette:t,left:R,right:S,wide:w,colWidth:J},void 0,!1,void 0,this),te(cE,{palette:t,entries:b,reveal:i,width:s,focused:!a,scrollRef:c},void 0,!1,void 0,this),a?null:te(Ee,{palette:t,hints:[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"o",label:"config"},{key:"l",label:"logs"},{key:"/reveal",label:"secrets"},{key:"esc",label:"back"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function aE(e){let{palette:t,left:r,right:n,wide:o,colWidth:i}=e,s=Math.max(4,i-Cn);if(!o)return te("box",{width:i,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[...r,...n].map((a)=>te(Uu,{palette:t,item:a,valueWidth:s},a.label,!1,void 0,this))},void 0,!1,void 0,this);return te("box",{height:r.length,flexShrink:0,flexDirection:"row",overflow:"hidden",children:[te(Ix,{palette:t,items:r,width:i},void 0,!1,void 0,this),te(Ix,{palette:t,items:n,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ix(e){let t=Math.max(4,e.width-Cn);return te("box",{width:e.width,flexShrink:0,flexDirection:"column",overflow:"hidden",children:e.items.map((r)=>te(Uu,{palette:e.palette,item:r,valueWidth:t},r.label,!1,void 0,this))},void 0,!1,void 0,this)}function Uu(e){let{palette:t,item:r,valueWidth:n}=e,o=r.tone==="warning"?t.warning:r.tone==="muted"?t.muted:t.text;return te("box",{height:1,width:Cn+n,flexDirection:"row",overflow:"hidden",children:[te("box",{width:Cn,flexShrink:0,overflow:"hidden",children:te("text",{fg:t.muted,wrapMode:"none",children:Y(r.label,Cn)},void 0,!1,void 0,this)},void 0,!1,void 0,this),te("box",{width:n,flexShrink:0,overflow:"hidden",children:te("text",{fg:o,wrapMode:"none",children:Y(r.value,n)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function cE(e){let{palette:t,entries:r,reveal:n,width:o,focused:i,scrollRef:s}=e,a=Vy(o),c=Math.max(8,o-a-4);return te("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[te(Be,{palette:t,items:[{text:`env ${r.length}`,tone:r.length>0?"info":"idle"},{text:n?"secrets shown":"redacted",tone:n?"warning":"muted"}],hints:i?[{key:"j/k",label:"scroll"}]:[{key:"/reveal",label:"secrets"}]},void 0,!1,void 0,this),r.length===0?te("text",{fg:t.muted,children:"no service env overrides"},void 0,!1,void 0,this):te("box",{flexGrow:1,height:"100%",overflow:"hidden",children:te("scrollbox",{ref:s,focused:i,stickyScroll:!1,scrollX:!1,style:{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:t.panel},viewportOptions:{backgroundColor:t.panel},contentOptions:{backgroundColor:t.panel},scrollbarOptions:{trackOptions:{foregroundColor:t.primary,backgroundColor:t.element}}},children:te("box",{flexDirection:"column",overflow:"hidden",children:r.map((l)=>te("box",{height:1,flexDirection:"row",overflow:"hidden",children:[te("box",{width:a,flexShrink:0,overflow:"hidden",children:te("text",{fg:l.required?t.warning:t.muted,wrapMode:"none",children:Y(l.required?`${l.key}*`:l.key,a)},void 0,!1,void 0,this)},void 0,!1,void 0,this),te("box",{width:c,flexShrink:0,overflow:"hidden",children:te("text",{fg:l.value===""?t.muted:t.text,wrapMode:"none",children:Y(l.value===""&&l.required?"(required)":l.value,c)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},l.key,!0,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $x(e){switch(e.toUpperCase()){case"HEALTHY":case"RUNNING":return"success";case"UNHEALTHY":case"WARNING":case"WARN":case"STARTING":case"RESTARTING":return"warning";case"FAILED":case"ERROR":return"error";default:return"muted"}}var iE=72,sE=56,Cn=9;var Ku=T(()=>{Pe();kt();ot();ve();ze()});import{jsxDEV as Nr}from"@opentui/react/jsx-dev-runtime";function Nx(e){let{palette:t,cfg:r,names:n,snap:o,selected:i,checked:s,width:a,reveal:c,onOpen:l,onSelectIndex:d,onToggle:g}=e;if(n.length===0)return Nr(De,{palette:t,title:"No services",body:"This configuration does not define any services."},void 0,!1,void 0,this);let f=a<uo,h=n[i]??"",y=Ba(a,n,f),b=4,w=f?Math.max(qu,a-b):Math.max(qu,a-y-b);return Nr("box",{flexGrow:1,flexDirection:f?"column":"row",overflow:"hidden",children:[Nr("box",{flexGrow:f?1:0,flexShrink:0,minWidth:f?void 0:Ta,width:f?void 0:y,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[Nr(ic,{palette:t,checked:s,idle:ho(o),profileName:"",members:""},void 0,!1,void 0,this),Nr("box",{flexGrow:1,overflow:"hidden",children:Nr(oc,{palette:t,names:n,snap:o,selected:i,checked:s,width:Fa(y),onOpen:l,onSelectIndex:d,onToggle:g},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Nr("box",{flexGrow:2,minWidth:f?void 0:qu,minHeight:f?lE:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:h||"detail",titleColor:h?He(h,t):t.primary,overflow:"hidden",flexDirection:"column",children:Nr(Gu,{palette:t,cfg:r,snap:o,name:h,reveal:c,width:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var qu=36,lE=12;var Hx=T(()=>{kt();Pe();ze();Ku();Mu()});import{jsxDEV as fe}from"@opentui/react/jsx-dev-runtime";function uE(e){switch(e){case"cycle":return"\u2194";case"toggle":return"\u23FB";case"page":return"\u25B8";case"action":return"!";default:return"\xB7"}}function Gx(e){let{palette:t,items:r,selected:n,locked:o,width:i,onPick:s,onActivate:a}=e,c=re(),l=eu(r,n),d=lo(r,l);return fe("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"settings",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[fe("box",{height:2,paddingLeft:c.pad,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[fe("text",{fg:t.primary,wrapMode:"none",children:"Preferences"},void 0,!1,void 0,this),fe("text",{fg:t.muted,wrapMode:"none",children:o?"DEVCTL_TUI_CONFIG is set \u2014 changes stay in this session.":"Changes save to your user tui.json unless noted."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),fe("box",{flexGrow:1,paddingLeft:c.pad,paddingRight:c.pad,overflow:"hidden",flexShrink:1,children:fe(pE,{palette:t,items:r,active:l,scale:c,width:i,onPick:s,onActivate:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe(gE,{palette:t,item:d,scale:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function pE(e){let{palette:t,items:r,active:n,scale:o,width:i,onPick:s,onActivate:a}=e,c=xo(n,Wx),l=Math.max(8,i-jx-Bx-10),d=0,g=Ph(r);return fe("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:fe("box",{flexDirection:"column",overflow:"hidden",children:g.map((f,h)=>{let y=d;d+=f.items.length;let b=n>=y&&n<y+f.items.length;return fe("box",{border:!0,borderStyle:"rounded",borderColor:b?t.borderActive:t.border,title:`${f.group} (${f.items.length})`,titleColor:b?t.primary:t.muted,flexDirection:"column",flexShrink:0,marginBottom:h<g.length-1?Math.max(1,o.gap):0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[f.group==="MCP"?fe("box",{height:1,overflow:"hidden",children:fe("text",{fg:t.muted,wrapMode:"none",children:"dedicated page \u2014 also /mcp or /agent"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,f.items.map((w,R)=>{let S=y+R;return fe(fE,{index:S,palette:t,item:w,active:S===n,rowH:o.rowH,valueWidth:l,onPick:()=>s(S),onActivate:()=>a(w)},w.id,!1,void 0,this)})]},f.group,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function fE(e){let{palette:t,index:r,item:n,active:o,rowH:i,valueWidth:s,onPick:a,onActivate:c}=e;return fe("box",{id:`${Wx}-${r}`,height:i,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:o?t.highlight:void 0,onMouseDown:()=>{if(o){c();return}a()},children:[fe("box",{width:2,flexShrink:0,overflow:"hidden",children:fe("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{width:Bx,flexShrink:0,overflow:"hidden",children:fe("text",{fg:o?t.primary:t.muted,children:uE(n.kind)},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{width:jx,flexShrink:0,overflow:"hidden",children:fe("text",{fg:o?t.primary:t.text,wrapMode:"none",children:n.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{flexGrow:1,overflow:"hidden",children:fe("text",{fg:mE(t,n,o),wrapMode:"none",children:ce(n.value,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function gE(e){let{palette:t,item:r,scale:n}=e,o=r?.id==="font",i=r?.kind==="page"?`${r.name} \u2192 dedicated page`:r?.name??"";return fe("box",{height:dE,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"selected",titleColor:t.muted,backgroundColor:t.element,paddingLeft:n.pad,paddingRight:n.pad,flexDirection:"column",overflow:"hidden",children:[fe("box",{height:1,overflow:"hidden",children:fe("text",{fg:t.primary,wrapMode:"none",children:o?`${_h(n.steps)} ${n.label}`:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{height:1,overflow:"hidden",children:fe("text",{fg:t.text,wrapMode:"word",children:r?.detail??""},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{height:1,overflow:"hidden",children:fe("text",{fg:t.muted,wrapMode:"none",children:r?r.kind==="info"?"read-only":r.hint:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function mE(e,t,r){if(t.id==="mouse")return t.value==="on"?e.success:e.text;if(t.kind==="page")return e.info;if(t.kind==="info")return e.text;return r?e.primary:e.text}var jx=14,Bx=2,dE=5,Wx="settings-row";var Ux=T(()=>{ot();Pe();ve();pr()});import{useEffect as hE,useState as yE}from"react";import{jsxDEV as U}from"@opentui/react/jsx-dev-runtime";function So(e){let{palette:t,title:r,tone:n="muted",children:o}=e,i=n==="success"?t.success:n==="warning"?t.warning:n==="error"?t.error:t.border;return U("box",{border:!0,borderStyle:"rounded",borderColor:i,title:r,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Vu(e,t){if(t.color)return t.color;switch(t.tone){case"success":return e.success;case"warning":return e.warning;case"error":return e.error;case"primary":return e.primary;case"muted":return e.muted;default:return e.text}}function ji(e){let{palette:t,cells:r,header:n,gap:o=0,stripe:i}=e;return U("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:i?t.element:void 0,children:r.map((s,a)=>U("box",{flexDirection:"row",flexShrink:0,overflow:"hidden",children:[a>0&&o>0?U("box",{width:o,flexShrink:0},void 0,!1,void 0,this):null,U("box",{width:s.width,flexShrink:0,overflow:"hidden",children:U("text",{fg:n?t.primary:Vu(t,s),wrapMode:"none",children:Y(s.text,s.width)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${s.text}-${a}`,!0,void 0,this))},void 0,!1,void 0,this)}function Kx(e){let{palette:t,width:r}=e;return U("box",{height:1,flexShrink:0,overflow:"hidden",children:U("text",{fg:t.border,wrapMode:"none",children:Y("\u2500".repeat(Math.max(1,r)),r)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Hi(e){let{palette:t,facts:r,width:n}=e,o=yu(r,n),i=[{text:"what",width:o.what},{text:"reading",width:o.reading}];if(o.meter>0)i.push({text:"used",width:o.meter});return i.push({text:"meaning",width:o.meaning}),U("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[U(ji,{palette:t,header:!0,gap:go,cells:i},void 0,!1,void 0,this),U(Kx,{palette:t,width:n},void 0,!1,void 0,this),r.map((s,a)=>{let c=s.meaning===""?[""]:ja(s.meaning,Math.max(1,o.meaning)),l=s.meter?dy(s.meter):o.meter>0?"":void 0,d=[{text:s.what,width:o.what,tone:"text"},{text:s.reading,width:o.reading,tone:s.tone??"text"}];if(o.meter>0)d.push({text:l??"",width:o.meter,tone:s.meter?s.tone??"text":"muted"});return d.push({text:c[0]??"",width:o.meaning,tone:"muted"}),U("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[U(ji,{palette:t,gap:go,stripe:a%2===1,cells:d},void 0,!1,void 0,this),c.slice(1).map((g,f)=>{let h=[{text:"",width:o.what},{text:"",width:o.reading}];if(o.meter>0)h.push({text:"",width:o.meter});return h.push({text:g,width:o.meaning,tone:"muted"}),U(ji,{palette:t,gap:go,stripe:a%2===1,cells:h},`${s.what}-more-${f}`,!1,void 0,this)})]},`${s.what}-${s.reading}-${a}`,!0,void 0,this)})]},void 0,!0,void 0,this)}function qx(e){let{palette:t,cfg:r,snap:n,width:o,onRefresh:i}=e,s=re(),[,a]=yE(0);if(hE(()=>{let Ke=setInterval(()=>{a((de)=>{let we=de+1;if(i&&we%xE===0)i();return we})},vE);return()=>clearInterval(Ke)},[i]),!r)return U(De,{palette:t,title:"No configuration loaded",body:"Add services to .devctl/config.yaml or finish setup."},void 0,!1,void 0,this);let c=Object.keys(r.services).sort(),l=c.some((Ke)=>uy(r.services[Ke])),d=ny(c,n),g=vy(d,l),f=l&&d.live>0?d.healthy/d.live:d.total>0?d.live/d.total:0,h=Mi(f,bE),y=d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",b=ay(o,s.pad),w=n?.session_id?fs(n.session_id):void 0,R=w?mo(Date.now()-w.getTime()):"just started",S=n?.logs.total??0,N=n?.logs.errors??0,J=sy(n?.logs.counts??{}),v=n?.proxy.routes??[],A=n?.credentials,m=(A?.entries??[]).filter((Ke)=>Ke.valid).length,_=n?.system,F=_?_.memAvailableKB??_.memFreeKB:0,Z=_?fy(_.loadAvg1,_.cpuCount):void 0,he=_?gy(F,_.memTotalKB):void 0,ke=[];if(_&&Z&&he)ke.push(Z,he,{what:"Computer",reading:py(_.platform),meaning:`on for ${mo(_.hostUptimeSec*wE)}`,tone:"text"});let Je=d.failed>0||Z?.tone==="error"||he?.tone==="error"?"error":y==="warning"||Z?.tone==="warning"||he?.tone==="warning"?"warning":"success",Ue=[{what:"This session",reading:R,meaning:"how long this run has been going",tone:"text"},{what:"Profile",reading:n?.profile||"none",meaning:"which group of services is selected",tone:n?.profile?"text":"muted"},{what:"This window",reading:n?.detached?"closed":"watching",meaning:n?.detached?"services keep running without this screen":"you are watching the services from here",tone:n?.detached?"warning":"text"},{what:"Project folder",reading:"",meaning:r.repoRoot,tone:"muted"}],ae=[{what:"Lines kept",reading:String(S),meaning:"log lines still in memory",tone:"text"},{what:"Error lines",reading:String(N),meaning:N>0?"open Logs and press e to see only errors":"no ERROR or FATAL lines",tone:N>0?"error":"muted"},...J.map(([Ke,de])=>({what:Ke,reading:String(de),meaning:"lines from this service",tone:"text"}))],Oe=[{what:"Web proxy",reading:n?.proxy.running?"on":"off",meaning:n?.proxy.running?`${v.length} apps${n.proxy.address?` at ${n.proxy.address}`:""}`:"not forwarding local URLs",tone:n?.proxy.running?"success":"muted"},{what:"Agent tools",reading:n?.mcp?.running?"on":"off",meaning:n?.mcp?.address?`Cursor talks to devctl at ${n.mcp.address}`:"turn on from Settings \u2192 MCP",tone:n?.mcp?.running?"success":"muted"},{what:"Google account",reading:n?.identity.user?"signed in":"not signed in",meaning:[n?.identity.user,n?.identity.project].filter(Boolean).join(" \xB7 ")||"no Google user for this session",tone:n?.identity.user?"success":"muted"},{what:"Saved tokens",reading:A?`${m} of ${A.entries.length} good`:"none",meaning:A?yy(A.backend):"nothing stored yet",tone:A&&m<A.entries.length?"warning":A?"success":"muted"}];return U(et,{palette:t,title:"stats",scroll:!0,children:[U(So,{palette:t,title:`Your services ${d.live} of ${d.total} started`,tone:Je,children:[U(Hi,{palette:t,facts:g,width:b},void 0,!1,void 0,this),U("box",{height:1,flexShrink:0},void 0,!1,void 0,this),U("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:U("text",{wrapMode:"none",children:[U("span",{fg:t.muted,children:Y(l?"Ready":"Started",yu(g,b).what)},void 0,!1,void 0,this),U("span",{children:" ".repeat(go)},void 0,!1,void 0,this),U("span",{fg:Vu(t,{text:"",width:1,tone:y}),children:`[${h}]`},void 0,!1,void 0,this),U("span",{fg:Vu(t,{text:"",width:1,tone:y}),children:l?` ${d.healthy} of ${d.live||d.total} passing checks`:` ${d.live} of ${d.total} up`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_?U(So,{palette:t,title:"This computer",tone:Z?.tone==="error"||he?.tone==="error"?"error":Z?.tone==="warning"||he?.tone==="warning"?"warning":"success",children:U(Hi,{palette:t,facts:ke,width:b},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,U(So,{palette:t,title:"This session",children:U(Hi,{palette:t,facts:Ue,width:b},void 0,!1,void 0,this)},void 0,!1,void 0,this),U(So,{palette:t,title:"Each service",tone:d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",children:d.total===0?U("text",{fg:t.muted,children:"No services in this project yet."},void 0,!1,void 0,this):U("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[U(SE,{palette:t,names:c,snap:n,width:b},void 0,!1,void 0,this),U("box",{height:1,flexShrink:0},void 0,!1,void 0,this),U("text",{fg:t.muted,wrapMode:"none",children:Y("CPU is % of one core. RAM is what that process is holding now.",b)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),U(So,{palette:t,title:"Log lines",tone:N>0?"warning":"muted",children:U(Hi,{palette:t,facts:ae,width:b},void 0,!1,void 0,this)},void 0,!1,void 0,this),U(So,{palette:t,title:"Other parts",children:U(Hi,{palette:t,facts:Oe,width:b},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function SE(e){let{palette:t,names:r,snap:n,width:o}=e,i=cy(o),s=[{text:"service",width:i.name},{text:"status",width:Jt}];if(i.health)s.push({text:"check",width:fr});if(i.cpu)s.push({text:"cpu",width:Ma});if(i.mem)s.push({text:"ram",width:Oa});if(i.up)s.push({text:"up",width:Da});if(i.rst)s.push({text:"restarts",width:Ka});if(i.pid)s.push({text:"pid",width:Mr});return U("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[U(ji,{palette:t,header:!0,gap:yt,cells:s},void 0,!1,void 0,this),U(Kx,{palette:t,width:o},void 0,!1,void 0,this),r.map((a,c)=>U(RE,{palette:t,name:a,rt:n?.services[a],cols:i,stripe:c%2===1},a,!1,void 0,this))]},void 0,!0,void 0,this)}function _E(e){if(e===void 0)return"muted";if(e>CE)return"error";if(e>kE)return"warning";return"text"}function RE(e){let{palette:t,name:r,rt:n,cols:o,stripe:i}=e,s=my(n),a=hy(n),c=n?.restarts??0,l=[{text:r,width:o.name,color:He(r,t)},{text:s,width:Jt,color:Re(t,n?.state??"STOPPED")}];if(o.health)l.push({text:a,width:fr,color:Re(t,n?.health??"UNKNOWN")});if(o.cpu)l.push({text:n?.cpuPercent!==void 0?xy(n.cpuPercent):"\u2014",width:Ma,tone:_E(n?.cpuPercent)});if(o.mem)l.push({text:n?.memoryKB!==void 0?Aa(n.memoryKB):"\u2014",width:Oa,tone:"text"});if(o.up)l.push({text:iy(n),width:Da,tone:"text"});if(o.rst)l.push({text:String(c),width:Ka,tone:c>0?"warning":"muted"});if(o.pid)l.push({text:n?.pid?String(n.pid):"\u2014",width:Mr,tone:"muted"});return U("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",children:[U(ji,{palette:t,gap:yt,stripe:i,cells:l},void 0,!1,void 0,this),n?.last_error?U("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:U("text",{fg:t.error,wrapMode:"none",children:Y(` ${n.last_error}`,Math.max(24,o.name+yt+Jt+fr))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var vE=1000,xE=5,bE=16,wE=1000,kE=80,CE=100;var Vx=T(()=>{kt();Pe();ot();ve();ze();Ye()});import{jsxDEV as me}from"@opentui/react/jsx-dev-runtime";function Jx(e){let{palette:t,cfg:r,google:n,bootError:o,bootErrorMissing:i=!1,step:s=0}=e,a=re();if(o&&!r)return i?me(De,{palette:t,title:"No configuration found",body:"Would you like to run setup?",hint:"[Enter] Setup [Esc] Exit"},void 0,!1,void 0,this):me(De,{palette:t,title:"Configuration error",body:o,hint:"Fix .devctl/config.yaml, then restart devctl [Esc] Exit"},void 0,!1,void 0,this);let c=r?Ut(r):["configuration not loaded"],l=PE(r,n,c),d=l.filter((S)=>S.ok).length,g=l.length,f=g>0?Math.round(d/g*100):0,h=20,y=Math.round(f/100*h),b="\u2588".repeat(y)+"\u2591".repeat(Math.max(0,h-y)),w=f===100?t.success:f===0?t.muted:t.primary,R=l[s];return me(et,{palette:t,title:"setup",scroll:!0,children:[me("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:me("text",{fg:t.primary,children:"Developer onboarding"},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:me("text",{wrapMode:"none",children:[me("span",{fg:w,children:`[${b}]`},void 0,!1,void 0,this),me("span",{fg:t.text,children:` ${d}/${g} ready`},void 0,!1,void 0,this),me("span",{fg:t.muted,children:` (${f}%)`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),me("box",{height:1,flexShrink:0},void 0,!1,void 0,this),l.map((S,N)=>{let J=N===s;return me("box",{height:a.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:J?t.highlight:void 0,paddingLeft:1,children:[me("box",{width:2,flexShrink:0,children:me("text",{fg:Re(t,S.ok?"OK":"WARN"),children:Tt(S.ok?"OK":"WARN")},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:3,flexShrink:0,children:me("text",{fg:J?t.primary:t.muted,children:String(N+1).padStart(2," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:20,flexShrink:0,overflow:"hidden",children:me("text",{fg:J?t.primary:t.text,children:S.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{flexGrow:1,overflow:"hidden",children:me("text",{fg:J?t.text:t.muted,wrapMode:"none",children:S.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},S.name,!0,void 0,this)}),me("box",{height:1,flexShrink:0},void 0,!1,void 0,this),R?me("box",{border:!0,borderStyle:"rounded",borderColor:R.ok?t.success:t.warning,title:R.name,titleColor:R.ok?t.success:t.warning,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:me("text",{fg:R.ok?t.text:t.warning,wrapMode:"word",children:R.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,me("box",{height:1,flexShrink:0},void 0,!1,void 0,this),me("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:me(ue,{palette:t,label:"never hard-coded",tone:"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("text",{fg:t.muted,wrapMode:"word",children:"Service accounts and IAP audiences stay in configuration. Run `devctl setup` for the interactive CLI wizard."},void 0,!1,void 0,this),me(Ee,{palette:t,hints:[{key:"j/k",label:"steps"},{key:"enter",label:r?"start":"begin setup"},{key:"esc",label:"exit"},{key:"o",label:"profiles"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function PE(e,t,r=[]){let n=Object.values(e?.services??{}).flatMap((s)=>s.ports.filter((a)=>!a.auto)),o=(e?.proxy.routes??[]).some((s)=>s.auth.type.toLowerCase()==="iap"),i=vo(e,void 0,t).project;return[{name:mr[0],ok:Boolean(e?.repoRoot),detail:e?.repoRoot||"unknown"},{name:mr[1],ok:Boolean(e?.project.name),detail:e?.project.name||"set project.name"},{name:mr[2],ok:Boolean(i),detail:i||"optional for local-only"},{name:mr[3],ok:t?.adcAvailable===!0,detail:t?.adcAvailable?"ADC available":"needed only for cloud identity / IAP"},{name:mr[4],ok:!0,detail:"read from configuration; never hard-coded"},{name:mr[5],ok:!o||(e?.proxy.routes??[]).every((s)=>s.auth.type.toLowerCase()!=="iap"||s.auth.audience!==""),detail:o?"IAP routes present":"no IAP routes"},{name:mr[6],ok:n.length===0||Boolean(e),detail:`${n.length} fixed ports from configuration`},{name:mr[7],ok:Object.keys(e?.profiles??{}).length>0,detail:`${Object.keys(e?.profiles??{}).length} profile(s)`},{name:mr[8],ok:r.length===0,detail:r.length===0?"configuration is valid":r[0]??"invalid"}]}var mr;var Yx=T(()=>{St();kt();ot();ve();Pe();ze();mr=["Repository","Environment","Google project","Authentication","Service accounts","IAP","Ports","Profiles","Validation"]});import{jsxDEV as B}from"@opentui/react/jsx-dev-runtime";function Xu(){return Od.flatMap((e)=>ua.filter((t)=>t.category===e))}function uc(){return dc+Xu().length}function Qx(){return uc()+Xx}function pc(e){if(e<dc||e>=uc())return;return Xu()[e-dc]}function Qu(e){let t=e-uc();return t>=0&&t<Xx?t:void 0}function Zx(e){let{palette:t,snap:r,port:n,portDraft:o="",selected:i,onPick:s,onToggle:a,onCopy:c,onToggleTool:l}=e,d=re(),g=r?.mcp?.running===!0,f=r?.mcp?.port??n,h=r?.mcp?.address??ao(f),y=r?.mcp?.token??"",b=Si(h,y),w=r?.mcp?.disabled_tools??[],R=Xu(),S=R.filter((v)=>!Ar(v.name,w)).length,N=b[Qu(i)??-1],J=N??b[0];return B(et,{palette:t,title:"mcp settings",children:[B(Be,{palette:t,items:[{text:g?"RUNNING":"STOPPED",tone:g?"success":"idle"},{text:`127.0.0.1:${f}`,tone:"info"}]},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Le(t),children:B("box",{flexDirection:"column",overflow:"hidden",children:[B(Ju,{palette:t,text:"Server"},void 0,!1,void 0,this),B(zx,{palette:t,active:i===Yu,rowH:d.rowH,label:"Listen",value:g?"[ ON ]":"[ OFF ]",valueTone:g?"success":"muted",hint:g?"space or enter stop":"space or enter start",onPick:()=>s(Yu),onActivate:a},void 0,!1,void 0,this),B(zx,{palette:t,active:i===zu,rowH:d.rowH,label:"Port",value:`\u2039 ${o===""?n:o} \u203A`,valueTone:"info",hint:o===""?"\u2190 \u2192 change type digits enter apply":"typing\u2026 enter apply \u232B erase",onPick:()=>s(zu)},void 0,!1,void 0,this),B("box",{height:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:g?"Listening on loopback. Agents use the URL and token in the JSON below.":"Server is stopped. Highlight Listen and press space to start it."},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(Ju,{palette:t,text:"Tools",extra:S===0?"all enabled":`${S} disabled`},void 0,!1,void 0,this),B("box",{height:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:"Disabled tools are hidden from agents and refused if called anyway."},void 0,!1,void 0,this)},void 0,!1,void 0,this),Od.map((v)=>{let A=R.filter((m)=>m.category===v);if(A.length===0)return null;return B("box",{flexDirection:"column",overflow:"hidden",children:[B("box",{height:1,marginTop:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:EE[v]??v},void 0,!1,void 0,this)},void 0,!1,void 0,this),A.map((m)=>{let _=dc+R.indexOf(m);return B(DE,{palette:t,tool:m,enabled:Ar(m.name,w),active:i===_,rowH:d.rowH,onPick:()=>s(_),onToggle:()=>l(m)},m.name,!1,void 0,this)})]},v,!0,void 0,this)}),B(Ju,{palette:t,text:"Copy agent config",extra:"highlight a row, then enter or click Copy"},void 0,!1,void 0,this),b.map((v,A)=>{let m=uc()+A;return B(LE,{palette:t,snippet:v,active:i===m,rowH:d.rowH,onPick:()=>s(m),onCopy:()=>c(v)},v.kind,!1,void 0,this)}),B(ME,{palette:t,snippet:J,selected:Boolean(N),brand:J?Ca(J.kind,t):t.muted},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(je,{palette:t,backgroundColor:t.element,edge:"top",children:B(Ee,{palette:t,hints:AE(i,g)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function AE(e,t){if(e===Yu)return[{key:"space",label:t?"stop server":"start server"},{key:"j/k",label:"move"}];if(e===zu)return[{key:"\u2190\u2192",label:"change port"},{key:"0-9",label:"type port"},{key:"enter",label:"apply port"},{key:"j/k",label:"move"}];if(pc(e))return[{key:"space",label:"enable / disable"},{key:"enter",label:"enable / disable"},{key:"j/k",label:"move"}];return[{key:"enter",label:"copy JSON"},{key:"space",label:"copy JSON"},{key:"j/k",label:"move"}]}function Ju(e){let t=e.extra?` \xB7 ${e.extra}`:"";return B("box",{height:1,marginTop:1,overflow:"hidden",children:B("text",{wrapMode:"none",children:[B("span",{fg:e.palette.primary,children:e.text},void 0,!1,void 0,this),B("span",{fg:e.palette.muted,children:t},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function zx(e){let{palette:t,active:r,rowH:n,label:o,value:i,valueTone:s,hint:a,onPick:c,onActivate:l}=e,d=s==="success"?t.success:s==="info"?t.info:t.muted;return B("box",{height:n,flexDirection:"row",overflow:"hidden",backgroundColor:r?t.highlight:t.panel,onMouseDown:()=>{if(r&&l){l();return}c()},children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:t.primary,children:r?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:Zu,flexShrink:0,overflow:"hidden",children:B("text",{fg:r?t.primary:t.text,wrapMode:"none",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:TE,flexShrink:0,overflow:"hidden",children:B("text",{fg:d,wrapMode:"none",children:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:r?t.text:t.muted,wrapMode:"none",children:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function LE(e){let{palette:t,snippet:r,active:n,rowH:o,onPick:i,onCopy:s}=e,a=Ca(r.kind,t),c=vh(r.kind,t),l=r.language==="toml"?"Copy TOML":"Copy JSON";return B("box",{height:o,flexDirection:"row",overflow:"hidden",backgroundColor:n?t.highlight:t.panel,onMouseDown:i,children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:a,children:n?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:Zu,flexShrink:0,overflow:"hidden",children:B("text",{fg:a,wrapMode:"none",children:r.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:r.path},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(ue,{palette:t,label:l,bg:a,fg:c,onMouseDown:()=>{i(),s()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function DE(e){let{palette:t,tool:r,enabled:n,active:o,rowH:i,onPick:s,onToggle:a}=e;return B("box",{height:i,flexDirection:"row",overflow:"hidden",backgroundColor:o?t.highlight:t.panel,onMouseDown:()=>{if(o){a();return}s()},children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:5,flexShrink:0,overflow:"hidden",children:B("text",{fg:n?t.success:t.muted,wrapMode:"none",children:n?" ON ":" OFF "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:Zu+4,flexShrink:0,overflow:"hidden",children:B("text",{fg:o?t.primary:n?t.text:t.muted,wrapMode:"none",children:r.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:7,flexShrink:0,overflow:"hidden",children:B("text",{fg:r.mutates?t.warning:t.muted,wrapMode:"none",children:r.mutates?"write":"read"},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:o?t.text:t.muted,wrapMode:"none",children:o?`space or enter ${n?"disable":"enable"} ${r.name}`:r.summary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ME(e){let{palette:t,snippet:r,selected:n,brand:o}=e;if(!r)return null;let i=r.hint?` \xB7 ${r.hint}`:"";return B("box",{marginTop:1,flexDirection:"column",overflow:"hidden",children:[B("text",{fg:o,wrapMode:"none",children:n?`${r.title} \xB7 paste into ${r.path}${i}`:`Preview ${r.title} \xB7 j/k to a copy row, then enter`},void 0,!1,void 0,this),B("text",{fg:t.text,children:r.text},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Yu=0,zu=1,dc=2,Xx=4,EE,Zu=14,TE=14;var eb=T(()=>{ot();ve();ze();yi();EE={inspect:"Inspect",logs:"Logs",diagnostics:"Diagnostics",control:"Control",setup:"Setup"}});import{readFileSync as OE,writeFileSync as IE}from"fs";import{useCallback as z,useEffect as Ct,useMemo as hr,useRef as tt,useState as O}from"react";import{RGBA as $E}from"@opentui/core";import{useKeyboard as FE,useTerminalDimensions as NE}from"@opentui/react";import{jsxDEV as oe,Fragment as WE}from"@opentui/react/jsx-dev-runtime";function tb({controller:e,tui:t,onQuit:r,bootError:n,bootErrorMissing:o=!1,terminalBackground:i}){let{width:s,height:a}=NE(),[c,l]=O(t.theme||e?.cfg.ui.theme||"devctl"),d=tt(c),[g,f]=O(t.mouse),h=tt(t.mouse),[y,b]=O(t.leader_timeout),w=tt(t.leader_timeout),[R,S]=O(()=>Ri(t.font_size)),N=tt(R),J=Sh(),v=hr(()=>{let p=yh(c);if(wa(c)!=="terminal"||!Yd(i))return p;let u=i??p.background;return{...p,background:u,panel:u,element:u,inverse:u}},[i,c]),A=wa(c)==="terminal"&&Yd(i)?$E.defaultBackground(i??void 0):v.background,[m,_]=O(e?"dashboard":"setup"),[F,Z]=O("none"),[he,ke]=O(""),[Je,Ue]=O(0),[ae,Oe]=O(0),[Ke,de]=O(0),[we,Ce]=O([]),[W,Ie]=O(),lt=hr(()=>Rh({themeName:c,fontSize:R,mouse:g,leaderMs:y,locked:J,configPath:J?t.path||tu():tu(),mcpRunning:W?.mcp?.running===!0}),[R,y,g,J,W?.mcp?.running,c,t.path]),[$e,_t]=O([]),[dt,zt]=O(!1),[ut,Xt]=O(!1),[pt,_n]=O(!0),[fc,C]=O(n??""),[Qt,jr]=O(),[Rn,gc]=O(),[mc,Pn]=O(!1),[pb,sp]=O(""),[hc,yc]=O(0),[fb,ap]=O({active:"Preparing diagnostics",checks:[]}),cp=tt(void 0),ko=tt(0),[gb,mb]=O({}),[lp,hb]=O(),[Xe,vc]=O(Wa(e?.cfg)),[En,yb]=O(""),[Co,vb]=O(!1),[yr,xb]=O(""),[Bi,xc]=O(!1),[dp,bb]=O(0),[Tn,up]=O(""),[Wi,wb]=O(""),[Wt,vr]=O(""),Br=jE,[pp,Sb]=O(t.log_timestamps!==!1),[fp,kb]=O(t.log_metadata!==!1),[gp,Cb]=O(()=>[...wy]),[Gi]=O(""),[Wr]=O(""),[xr,_b]=O(!1),[Ui,mp]=O(),[Rb,Pb]=O(),[_o,hp]=O("focus"),[xt,br]=O(!1),[Eb,Ro]=O(bn-1),[Po,Ki]=O(!1),[Zt,qi]=O(-1),[yp,Tb]=O(),[vp,xp]=O(""),[bp,bc]=O(!1),[wp,Sp]=O(!1),kp=tt([]),Eo=tt(null),To=tt(null),Ao=tt(null),Lo=tt(null),wc=tt(null),Sc=tt(null),Cp=tt(null),[kc,Ab]=O(""),[Lb,Vi]=O(""),Cc=tt(""),_c=tt(!1),[_p,Do]=O(0),[Ji,Rc]=O(""),[Yi,Pc]=O(),[Db,Ec]=O([]),[Rp,er]=O(!1),[Pp,Tc]=O("start"),[Gr,wr]=O("quit"),[Sr,Mb]=O(()=>t.mcp_port??io(e?.cfg.repoRoot??process.cwd())),Mo=tt(void 0),Ac=tt(0),[D,Ob]=O(e?.cfg),[Oo,Ep]=O(void 0),Tp=t.keybinds.copy??lr(),it=hr(()=>Object.keys(D?.services??{}).sort(),[D]),Io=hr(()=>Ii(it,$e,gp),[it,$e,gp]),$o=hr(()=>gh(he),[he]),An=hr(()=>Wy(he),[he]);Ct(()=>{Cb((p)=>{let u=new Set(p),k=!1;for(let E of $e)if(E.service!==""&&!it.includes(E.service)&&!u.has(E.service))u.add(E.service),k=!0;return k?[...u].sort():p})},[$e,it]),Ct(()=>{Oe(0)},[he]),Ct(()=>{if(F==="palette")Ue(0)},[F,he]);let rt=hr(()=>yo($e,{service:Wt,services:Br,errorOnly:ut,search:yr,regex:xr,source:Wr,since:Tn,until:Wi,systemLogs:pt}),[ut,xr,yr,Wt,Br,Tn,Wr,Wi,$e,pt]),Fe=hr(()=>Vh(rt,xt,_p),[rt,xt,_p]),kr=Fe.items,tr=ty(m,{doctor:Rn?.checks.length??0,settings:lt.length,profiles:Object.keys(D?.profiles??{}).length,services:it.length,logs:kr.length,mcp:Qx()}),Ap=m==="logs"?Eb:Ke,Q=tr<=0?Math.max(0,Ap):Math.max(0,Math.min(Ap,tr-1));Ct(()=>{qi(-1),br(!1),Ro(Math.max(0,Math.min(bn,rt.length)-1))},[ut,yr,Wt,pt]),Ct(()=>{if(m!=="logs")Ki(!1)},[m]),Ct(()=>{if(m!=="logs"||xt)return;Ro(Math.max(0,Math.min(bn,rt.length)-1))},[rt.length,xt,m]),Ct(()=>{if(m==="settings")return;l(d.current),S(N.current),b(w.current),f(h.current)},[m]);let Lc=z(()=>{if(!xt)Do(mu(rt.length)),br(!0)},[rt.length,xt]),Fo=z((p)=>{let u=hu(p,tr,Fe.start,Fe.newer);if(u.startDelta!==0){Do(Math.max(0,Fe.start+u.startDelta)),br(!0),Ro(u.selected);return}let k=Math.max(tr-1,0),E=tr>0&&(u.selected<k||Fe.newer>0);if(E&&!xt)Do(mu(rt.length)),br(!0);else if(!E)br(!1);Ro(u.selected)},[rt.length,tr,xt,Fe.newer,Fe.start]),zi=z((p)=>{let u=kr.length,k=hu(p,u,Fe.start,Fe.newer);if(k.startDelta!==0)Do(Math.max(0,Fe.start+k.startDelta)),br(!0);qi(k.selected)},[kr.length,Fe.newer,Fe.start]),Dc=z(()=>{if(br(!1),qi(-1),m==="logs")Ro(Math.max(0,Math.min(bn,rt.length)-1));bb((p)=>p+1),C(Fe.newer>0?`Jumped to latest (+${Fe.newer} new)`:"Jumped to latest logs")},[rt.length,Fe.newer,m]),Qe=z(()=>{if(Z("none"),ke(""),xc(!1),Mo.current)clearTimeout(Mo.current)},[]),Mc=z((p)=>{Ce((u)=>u.includes(p)?u.filter((k)=>k!==p):[...u,p])},[]),qe=z((p,u)=>{if(J){C(`${u} session only`);return}let k=sh(p);C(`${u} saved ${k}`)},[J]),Ln=z((p)=>{l(p),d.current=p,qe({theme:p},`theme ${p}`)},[qe]),No=z(()=>{let p=!g;f(p),h.current=p,qe({mouse:p},`mouse ${p?"on":"off"} restart TUI to apply clicks`)},[g,qe]),Xi=z((p)=>{b(p),w.current=p,qe({leader_timeout:p},`leader ${p}ms`)},[qe]),Ur=z((p)=>{let u=Ri(p);S(u),N.current=u,qe({font_size:u},`display ${_a(u)}`)},[qe]),Lp=z(()=>{let p=Zd();l(p.theme),d.current=p.theme,f(p.mouse),h.current=p.mouse,b(p.leader_timeout),w.current=p.leader_timeout,S(p.font_size),N.current=p.font_size,qe(p,"restored default preferences")},[qe]),Oc=z((p)=>{if(p.id==="theme"){Ue(Math.max(0,ht.indexOf(c))),Z("themes");return}if(p.id==="mouse"){No();return}if(p.id==="leader"){Xi(y);return}if(p.id==="font"){Ur(R);return}if(p.id==="reset"){wr("reset-prefs"),Z("confirm");return}if(p.id==="mcp"){_("mcp"),de(0);return}C(p.detail)},[Ur,Xi,R,y,c,No]),Dp=z((p)=>{let u=lo(lt,Q);if(!u)return;if(u.id==="theme"){Ln(kh(c,p));return}if(u.id==="leader"){Xi(Ch(y,p));return}if(u.id==="font"){Ur(Ra(R,p));return}if(u.id==="mouse")No()},[Ur,Xi,R,y,Q,Ln,lt,c,No]),Ib=z(()=>{l(d.current)},[]),ge=z(async()=>{if(!e)return;try{let p=await e.status();if(Ie(p),p.profile&&Xe==="")vc(p.profile);return p}catch(p){C(H(p));return}},[e,Xe]),Qi=z(async()=>{if(!e){C("Supervisor is not running");return}C("Probing configured identities\u2026");try{let p=await e.refreshAuth();Ie((ee)=>ee?{...ee,identity:p}:ee);let u=Object.values(p.service_account_status),k=u.filter((ee)=>ee==="available").length,E=u.filter((ee)=>ee==="unavailable").length;C(u.length===0?"Identity refreshed \u2014 no service accounts configured":`Identity refreshed \u2014 ${k} available${E>0?`, ${E} unavailable`:""}`)}catch(p){C(H(p))}},[e]),Zi=z((p)=>{let u=mn(p);Mb(u);let k=D?.repoRoot??process.cwd();if(nh(k,u)){qe({mcp_port:null},`MCP port ${u} (default)`);return}qe({mcp_port:u},`MCP port ${u}`)},[D,qe]),Dn=z(()=>{if(Ji==="")return Sr;let p=rh(Ji,Sr);return Rc(""),Zi(p),p},[Sr,Ji,Zi]),Mp=z(async(p)=>{if(!e||W?.mcp?.running!==!0)return;await e.mcpStop(),await e.mcpStart({port:p}),await ge()},[e,ge,W?.mcp?.running]),Ic=z(async(p)=>{if(!e){C("Supervisor is not running");return}let u=W?.mcp?.disabled_tools??[],k=Ar(p.name,u),E=k?[...u,p.name]:u.filter((ee)=>ee!==p.name);try{let ee=await e.mcpSetTools(E);qe({mcp_disabled_tools:ee},`${p.label} ${k?"disabled":"enabled"}`),await ge()}catch(ee){C(H(ee))}},[e,qe,ge,W]),es=z(async()=>{if(!e){C("Supervisor is not running");return}try{if(W?.mcp?.running)await e.mcpStop(),qe({mcp_enabled:!1},"MCP off"),C("MCP stopped");else await e.mcpStart({port:Sr}),qe({mcp_enabled:!0},"MCP on"),C("MCP started");await ge()}catch(p){C(H(p))}},[e,Sr,qe,ge,W?.mcp?.running]),$c=z((p)=>{Su(p.text).then(()=>{C(`Copied ${p.title} snippet`)}).catch((u)=>{C(H(u))})},[]),ts=z((p)=>{let u=Qu(p);if(u===void 0)return!1;let k=W?.mcp?.address??ao(W?.mcp?.port??Sr),E=Si(k,W?.mcp?.token??"")[u];if(!E)return!1;return $c(E),!0},[$c,Sr,W?.mcp?.address,W?.mcp?.port,W?.mcp?.token]),Mn=hr(()=>({services:Wt!==""?[Wt]:Br,level:ut?"ERROR":Gi,search:yr,regex:xr,source:Wr,since:Tn,until:Wi}),[ut,Gi,xr,yr,Wt,Br,Tn,Wr,Wi]),rs=z(async()=>{if(!e)return;try{Tb(await e.logsStats(Mn))}catch(p){C(H(p))}},[e,Mn]),Op=z(async()=>{if(!e||dt)return;try{let p=await e.logsPage(Mn);_t((u)=>ky(u,p.events)),xp(p.prevCursor),bc(p.hasPrev),await rs()}catch(p){C(H(p))}},[e,Mn,dt,rs]),Ho=z(()=>{_t([]),up(new Date().toISOString()),br(!1),C("Cleared on-screen log buffer")},[]),jo=z(()=>{_n((p)=>!p)},[]);Ct(()=>{ge().then(()=>Op())},[ge,Op]),Ct(()=>{kp.current=$e},[$e]),Ct(()=>{if(!e||wp||!_y(xt,Fe.start,bp))return;Sp(!0),e.logsPage({...Mn,cursor:vp,direction:"backward"}).then((p)=>{if(p.sessionChanged){C("Daemon session changed \u2014 older log history is no longer available"),bc(!1);return}let u=kp.current,k=Cy(u,p.events);if(_t(k),k.length>u.length)Do((E)=>E+(k.length-u.length));xp(p.prevCursor),bc(p.hasPrev)}).catch((p)=>C(H(p))).finally(()=>Sp(!1))},[e,Mn,wp,bp,xt,vp,Fe.start]),Ct(()=>{if(!e||dt||m!=="logs")return;let p=setInterval(()=>{rs()},BE);return()=>clearInterval(p)},[e,dt,rs,m]),Ct(()=>{if(!e)return;let p,u=!1,k=[],E=D&&D.logs.max_memory_events>0?D.logs.max_memory_events:50000,ee=()=>{if(p=void 0,k.length>0){let x=k.splice(0,k.length);_t((ie)=>Sy(ie,x,Tn,E))}if(u)u=!1,ge()},Cr=e.onEvent((x)=>{if(x.type===js&&x.payload&&typeof x.payload==="object"&&"event"in x.payload){let ie=x.payload.event;if(!dt)k.push(ie);if(!p)p=setTimeout(ee,30);return}if(x.type===ai){Ep(Xy(x));return}if(x.type===Bs)Ep(void 0),e.configSnapshot().then(Ob).catch((ie)=>C(H(ie)));if(u=!0,!p)p=setTimeout(ee,30)});return()=>{if(Cr(),p)clearTimeout(p)}},[e,Tn,dt,ge]),Ct(()=>{Ht(D?.google.project_id??"").then(jr).catch((p)=>{C(H(p))})},[D?.google.project_id,W?.identity.project]),Ct(()=>{if(m!=="doctor"||!D)return;let p=cp.current,u=W?.session_id??"";if(p?.cfg===D&&p.tick===hc&&p.sessionID===u&&p.reloadError===Oo)return;cp.current={cfg:D,tick:hc,sessionID:u,reloadError:Oo};let k=++ko.current;Pn(!0),sp(""),ap({active:"Preparing diagnostics",checks:[]});let E;if(D.configPath!==""){E="";try{Xo(D.repoRoot,D.configPath)}catch(ee){E=H(ee)}}Tr(D,void 0,(ee)=>{if(k===ko.current)ap(ee)},{services:W?.services,proxyRunning:W?.proxy.running,repositoryConfigError:E}).then((ee)=>{if(k!==ko.current)return;gc(ee)}).catch((ee)=>{if(k!==ko.current)return;sp(H(ee))}).finally(()=>{if(k===ko.current)Pn(!1)})},[m,D,hc,W?.session_id,Oo]);let ns=z((p)=>{yb(p),_("detail")},[]),rr=z(async(p,u)=>{if(!e||!D){C("no configuration loaded");return}try{let k=Js(D,{services:p,profile:u}),E=fi(D,k.services,k.profile);Tc("start"),Ec(E.waves.flat().filter((x)=>Di(W?.services[x]))),Pc(E),Z("plan"),er(!0);let ee=k.services.filter((x)=>!Di(W?.services[x])),Cr=await e.start({services:ee.length>0?ee:k.services,profile:k.profile});await ge(),er(!1),C(Dy(Cr))}catch(k){er(!1),await ge(),C(H(k))}},[D,e,ge,W]),os=z(async(p)=>{if(!e||!D){C("no configuration loaded");return}let u=p.length>0?p:Object.entries(W?.services??{}).filter(([,k])=>k.state!=="STOPPED"&&k.state!=="UNKNOWN").map(([k])=>k);if(u.length===0){C("nothing to stop");return}try{let k=gi(D,u);Tc("stop"),Ec([]),Pc(k),Z("plan"),er(!0),await e.stop(p),await ge(),er(!1),C(My(k))}catch(k){er(!1),await ge(),C(H(k))}},[D,e,ge,W]),Bo=z(async(p,u)=>{if(!e||!D){C("no configuration loaded");return}try{let k=ey(D,p,u),E=fi(D,k.services,k.profile);Tc("restart"),Ec([]),Pc(E),Z("plan"),er(!0),await e.restart(p),await ge(),er(!1),C($i(E)===""?"Restarted selected services":`Restarted ${$i(E)}`)}catch(k){er(!1),await ge(),C(H(k))}},[D,e,ge]),is=z(async(p="")=>{let u=F==="log-details"&&Ui?Py(Ui):Ey(rt),k=p===""?"":` \xB7 ${p}`;if(u.trim()===""){C(`No logs to copy${k}`);return}try{await Su(u);let E=u.split(`
|
|
618
|
-
`).length,ee=F==="log-details"?"Copied log event":`Copied ${
|
|
619
|
-
`)),C("Config buffer not saved");return}if(IE(D.configPath,p),Vi(""),Z("none"),!e){C(`Wrote ${D.configPath}`);return}e.reload().then((k)=>{if(C(k.restart_required.length===0?"Configuration saved and reloaded":`Saved; restart required: ${k.restart_required.join(", ")}`),k.restart_required.length>0)wr("reload"),Z("confirm");ge()})},[D,kc,e,ge]),nr=z(async(p,u)=>{if(_c.current)return;if(_c.current=!0,p.name!=="start"&&p.name!=="stop"&&p.name!=="restart")Z("none");ke("");let k=by(u,we);try{switch(p.name){case"exit":wr("quit"),Z("confirm");return;case"help":Z("help");return;case"version":C(Pt());return;case"themes":if(u[0]){Ln(u[0]);return}Ue(Math.max(0,ht.indexOf(c))),ke(""),Z("themes");return;case"settings":_("settings"),de(0);return;case"dashboard":case"services":_(p.name);return;case"logs":if(u[0])vr(u[0]);_("logs");return;case"fullscreen":_("logs"),Ki((E)=>m==="logs"?!E:!0);return;case"auth":if(u[0]?.toLowerCase()==="refresh"){_("auth"),await Qi();return}_("auth");return;case"credentials":case"proxy":case"mcp":case"config":case"profiles":case"setup":_(p.name);return;case"reload":if(!e)return;e.reload().then((E)=>{if(C(E.restart_required.length===0?"Configuration reloaded":`Reload requires restart: ${E.restart_required.join(", ")}`),E.restart_required.length>0)wr("reload"),Z("confirm");ge()});return;case"doctor":_("doctor");return;case"stats":_("stats");return;case"start":await rr(k,Xe);return;case"stop":await os(k);return;case"restart":await Bo(k,Xe);return;case"refresh":if(m==="auth"){await Qi();return}await ge(),C("Refreshed status and logs");return;case"pause":zt((E)=>!E),_("logs");return;case"filter":Xt((E)=>!E),_("logs");return;case"system":jo(),_("logs");return;case"clear":Ho();return;case"reveal":{let E=!Co;vb(E),C(E?"Secrets visible this session":"Secrets hidden");return}case"wrap":{let E=gu(_o);hp(E),C(`Log ${Ai(E)}`);return}case"copy":await is();return;case"export":{let E=to(u[0]);if(e)await e.logs({export:E,services:Br,level:ut?"ERROR":Gi,search:yr,regex:xr,source:Wr});else ra(E,rt);Cc.current=E,C(`Exported ${E}`);return}case"exports":{let E=Cc.current||Vr();na(E),C(`Opened ${Vr()}`);return}case"regex":_b((E)=>!E),C(xr?"Substring search":"Regex search");return;case"since":up(u[0]||new Date(Date.now()-3600000).toISOString()),C(`Logs since ${u[0]||"1h"}`);return;case"until":wb(u[0]||new Date().toISOString()),C(`Logs until ${u[0]||"now"}`);return;case"history":{let{listSessions:E,loadSessionEvents:ee}=await Promise.resolve().then(() => (fn(),mm)),Cr=E(),x=u[0]||Cr[0];if(!x){C("No persisted log sessions");return}_t(ee(x)),C(`Loaded session ${x}`);return}case"buffer":Fc();return;case"edit":{if(!D)return;let E=process.env.DEVCTL_EDITOR||process.env.EDITOR,ee=E?[E,D.configPath]:process.platform==="darwin"?["open",D.configPath]:["xdg-open",D.configPath];Bun.spawn({cmd:ee,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),C(`Opened ${D.configPath} in ${ee[0]}. Run /reload after saving.`);return}default:C(`/${p.name}`)}}catch(E){C(H(E))}finally{setTimeout(()=>{_c.current=!1},HE)}},[Bo,rr,os,we,D,Ho,e,is,ut,rt,Gi,xr,yr,Br,Wr,_o,Fc,Ln,Xe,ge,Qi,Co,m,c,jo]),Fb=z(()=>{let p=Cc.current||Vr();na(p),C(`Opened ${Vr()}`)},[]),Nc=z(()=>{let p=wn($o,ae);if(!p){C(he.trim()===""?"pick a command from the list":`unknown command /${he}`),Qe();return}let k=ki(he)?.name===p.name?mh(he):[];nr(p,k)},[Qe,$o,he,nr,ae]),Ip=z((p)=>{Ln(p),Qe()},[Qe,Ln]),Nb=z((p)=>{let u=ki(p);if(u)nr(u,[])},[nr]),$p=z(()=>{if(F==="palette"){let p=wn(An,Je);if(p)nr(p,[]);return}Nc()},[F,Je,An,nr,Nc]),Hb=z(()=>{if(D?.shutdown.stop_services_on_exit===void 0){wr("quit"),Z("confirm");return}r(D.shutdown.stop_services_on_exit===!1)},[D,r]),jb=z(()=>{if(Gr==="quit"){r(!1);return}if(Gr==="reload"){Qe();let p=W?.restart_required??[];if(p.length>0)Bo(p,Xe);return}if(Gr==="reset-prefs"){Qe(),Lp();return}if(Gr==="free-port"){let p=lp;if(Qe(),!p)return;Is(p).then(()=>{C(`Stopped ${p.command} (pid ${p.pid}) on port ${p.port}`),yc((u)=>u+1)}).catch((u)=>{C(H(u))});return}Qe(),rr([],Xe)},[Lp,Bo,rr,Qe,Gr,r,lp,Xe,W]),Bb=z(()=>{if(m==="logs"){let u=kr[Q];if(u)mp(u),Z("log-details");return}if(m==="profiles"){let k=Object.keys(D?.profiles??{}).sort()[Q];if(k)vc(k),wr("start-profile"),Z("confirm");return}if(m==="doctor"){let u=Rn?.checks[Q];if(u?.action?.kind==="free-port"){let k=u.action.holder;hb(k),mb({port:k.port,pid:k.pid,process:k.command}),wr("free-port"),Z("confirm")}return}if(m==="mcp"){if(Q===0){es();return}if(Q===1){Dn();return}let u=pc(Q);if(u){Ic(u);return}ts(Q);return}if(m==="settings"){let u=lo(lt,Q);if(u)Oc(u);return}if(m==="dashboard"&&ho(W)){rr([],Xe);return}let p=it[Q];if(p&&(m==="dashboard"||m==="services"))ns(p)},[Oc,Dn,rr,D,ts,Rn,Q,kr,it,ns,Xe,m,lt,W,es]);FE((p)=>{let u=(p.name??"").toLowerCase(),k=hv(p,t),E=mv(p,t);if(k&&!E){if(m==="mcp"&&ts(Q))return;is();return}if(E){let x=Date.now();if(yv(x,Ac.current)){Ac.current=0,Hb();return}Ac.current=x;let ie="Ctrl+C again to quit";if(k)is(ie);else C(`Press ${ie}`);return}if(p.ctrl&&(u==="="||u==="+"||u==="plus")){Ur(Ra(R,1));return}if(p.ctrl&&(u==="-"||u==="_"||u==="minus")){Ur(Ra(R,-1));return}if(p.ctrl&&u==="0"){Ur(Zd().font_size);return}if(F==="confirm"){if(u==="escape"){Qe();return}if(Gr==="quit"&&u==="d"){r(!0);return}if(u==="return")jb();return}if(F==="log-details"){if(u==="escape"){Qe();return}if(u==="down"||u==="j"){We(Lo.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(Lo.current,-t.scroll_speed);return}if(ec(p)){We(Lo.current,Li(a));return}if(tc(p)){We(Lo.current,-Li(a));return}return}if(F==="route-details"){if(u==="escape"||u==="return"){Qe();return}if(u==="down"||u==="j"){We(wc.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(wc.current,-t.scroll_speed);return}return}if(F==="plan"){if(u==="escape"||u==="return"&&!Rp){Qe();return}if(u==="down"||u==="j"){We(Sc.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(Sc.current,-t.scroll_speed);return}return}if(F==="help"){if(u==="escape"){Qe();return}if(u==="down"||u==="j"){We(To.current,1);return}if(u==="up"||u==="k"){We(To.current,-1);return}if(u==="pagedown"||ec(p)){We(To.current,Au);return}if(u==="pageup"||tc(p)){We(To.current,-Au);return}return}if(F==="themes"){if(u==="escape"){Ib(),Qe();return}if(u==="down"||u==="j"){Ue((x)=>{let ie=Math.min(x+1,ht.length-1),or=ht[ie];if(or)l(or);return ie});return}if(u==="up"||u==="k"){Ue((x)=>{let ie=Math.max(0,x-1),or=ht[ie];if(or)l(or);return ie});return}if(u==="return"){let x=ht[Je%ht.length];if(x)Ip(x)}return}if(F==="leader"){if(Mo.current)clearTimeout(Mo.current);Z("none");let x=hh(u),ie=x?ki(x):void 0;if(ie)nr(ie,[]);return}if(F==="config-edit"){if(u==="escape"){Vi(""),Qe();return}if(p.ctrl&&u==="s"){$b();return}return}if(av(F)){if(u==="escape"){Qe();return}if(F==="slash"&&u==="down"){Oe((x)=>Math.min(Math.max($o.length-1,0),x+1));return}if(F==="slash"&&u==="up"){Oe((x)=>Math.max(0,x-1));return}if(F==="slash"&&u==="tab"){if(p.shift){Oe((ie)=>Math.max(0,ie-1));return}let x=wn($o,ae);if(x)ke(`${x.name} `);return}if(F==="slash"&&u==="return"){Nc();return}if(F==="palette"&&u==="down"){Ue((x)=>Math.min(x+1,Math.max(An.length-1,0)));return}if(F==="palette"&&u==="up"){Ue((x)=>Math.max(0,x-1));return}if(F==="palette"&&u==="return"){let x=wn(An,Je);if(x)nr(x,[])}return}if(Bi){if(u==="escape")xc(!1);return}if(cv(p,t)){Z("leader"),Mo.current=setTimeout(()=>Z("none"),y);return}if(lv(p,t)){ke(""),Ue(0),Z("palette");return}if(dv(p,t)){ke(""),Oe(0),Z("slash");return}if(uv(p,t)){Z("help");return}if(pv(p,t)||m==="logs"&&u==="f"&&!p.ctrl&&!p.meta){_("logs"),xc(!0);return}if(u==="escape"){if(Po){Ki(!1);return}if(m==="detail"){_("services");return}if(m==="setup")if(e)_("dashboard");else r(!0);return}if(u==="z"&&(m==="logs"||m==="dashboard")&&!p.ctrl&&!p.meta){_("logs"),Ki((x)=>m==="logs"?!x:!0);return}let ee=(m==="logs"||m==="dashboard")&&!Bi;if(ee&&(u==="left"||u==="["||m==="logs"&&u==="h")){vr(xu(Io,Wt,-1));return}if(ee&&(u==="right"||u==="]"||m==="logs"&&u==="l")){vr(xu(Io,Wt,1));return}if(m==="logs"&&!Bi&&u.length===1&&u>="1"&&u<="9"){let x=Ly(Io,$e,Number(u));if(x!==void 0)vr(x);return}if(u==="tab"){_(p.shift?jy(m):Hy(m));return}let Cr=ry(u);if(Cr){_(Cr);return}if((m==="dashboard"||m==="setup")&&u==="o"){_("profiles");return}if((m==="dashboard"||m==="services")&&(u==="*"||p.shift&&u==="8")){Ce([...it]),C(`Selected ${it.length} services`);return}if((m==="dashboard"||m==="services")&&(u==="-"||u==="_"||u==="minus")){Ce([]),C("Selection cleared");return}if((m==="dashboard"||m==="services")&&u==="n"){rr(qa(we,it[Q]??""),Xe);return}if((m==="dashboard"||m==="services")&&u==="x"){os(qa(we,it[Q]??""));return}if((m==="dashboard"||m==="services"||m==="detail")&&fv(p)){Bo(qa(we,it[Q]??En),Xe);return}if((m==="dashboard"||m==="services")&&u==="r"){ge(),C("Refreshed");return}if(m==="auth"&&u==="r"){Qi();return}if(m==="logs"&&u==="t"){let x=!pp;Sb(x),qe({log_timestamps:x},x?"timestamps on":"timestamps off");return}if(m==="logs"&&u==="m"){let x=!fp;kb(x),qe({log_metadata:x},x?"metadata on":"metadata off");return}if(u==="down"||u==="j"){if(m==="mcp"&&Q===1)Dn();if(m==="config"){We(Eo.current,t.scroll_speed);return}if(m==="detail"){We(Ao.current,t.scroll_speed);return}if(m==="logs"){Fo(Q+1);return}if(m==="dashboard"&&Zt>=0){zi(Zt+1);return}de((x)=>Math.min(Math.max(tr-1,0),x+1));return}if(u==="up"||u==="k"){if(m==="mcp"&&Q===1)Dn();if(m==="config"){We(Eo.current,-t.scroll_speed);return}if(m==="detail"){We(Ao.current,-t.scroll_speed);return}if(m==="logs"){Fo(Q-1);return}if(m==="dashboard"&&Zt>=0){zi(Zt-1);return}de((x)=>Math.max(0,Math.min(x,Math.max(tr-1,0))-1));return}if(ec(p)){let x=Li(a);if(m==="config"){We(Eo.current,x);return}if(m==="detail"){We(Ao.current,x);return}if(m==="logs"){Fo(Q+x);return}if(m==="dashboard"&&(xt||Zt>=0)){zi(Math.max(0,Zt)+x);return}de((ie)=>Math.min(Math.max(tr-1,0),ie+x));return}if(tc(p)){let x=Li(a);if(m==="config"){We(Eo.current,-x);return}if(m==="detail"){We(Ao.current,-x);return}if(m==="logs"){Fo(Q-x);return}if(m==="dashboard"&&(xt||Zt>=0)){zi(Math.max(0,Zt)-x);return}de((ie)=>Math.max(0,ie-x));return}if(m==="proxy"&&u==="n"){e?.proxyStart().then(async()=>{C("Proxy started"),await ge()});return}if(m==="proxy"&&u==="x"){e?.proxyStop().then(async()=>{C("Proxy stopped"),await ge()});return}if(m==="detail"&&En!==""){if(u==="n"){rr([En],Xe);return}if(u==="x"){os([En]);return}if(u==="o"){_("config");return}if(u==="l"){vr(En),_("logs");return}}if(m==="mcp"&&Q===1&&(u==="left"||u==="h")){let x=mn(Dn()-1);Zi(x),Mp(x);return}if(m==="mcp"&&Q===1&&(u==="right"||u==="l")){let x=mn(Dn()+1);Zi(x),Mp(x);return}if(m==="mcp"&&Q===1&&(u==="backspace"||u==="delete")){Rc((x)=>th(x));return}if(m==="mcp"&&Q===1&&u.length===1&&u>="0"&&u<="9"){Rc((x)=>eh(x,u));return}if(m==="settings"&&(u==="left"||u==="h")){Dp(-1);return}if(m==="settings"&&(u==="right"||u==="l")){Dp(1);return}if(u==="space"){if(m==="profiles"){let or=Object.keys(D?.profiles??{}).sort()[Q];if(or)vc(or),C(`Profile ${or}`);return}if(m==="mcp"){if(Q===0){es();return}let ie=pc(Q);if(ie){Ic(ie);return}ts(Q);return}if(m==="logs")return;if(m==="settings"){if(lo(lt,Q)?.id==="mouse")No();return}let x=it[Q];if(x)Mc(x);return}if(u==="return"){if(m==="setup"&&!e){if(!o){C(n||"Existing configuration is invalid \u2014 fix it and restart devctl.");return}Promise.resolve().then(() => (ud(),Zg)).then(({createStarterConfig:x})=>{try{let ie=x(process.cwd());C(`Wrote ${ie}. Restart devctl or run the CLI wizard.`)}catch(ie){C(H(ie))}});return}if(m==="setup"&&e){rr([],Xe);return}Bb();return}if(u==="q"){if(D?.shutdown.stop_services_on_exit===!1){r(!0);return}if(D?.shutdown.stop_services_on_exit===!0){r(!1);return}wr("quit"),Z("confirm");return}if(Or(p,t,"services","s")&&F==="none"&&m!=="logs"){_("services");return}if(Or(p,t,"logs","l")&&F==="none"&&m!=="detail"&&m!=="logs"&&m!=="settings"){_("logs");return}if(Or(p,t,"auth","a")&&F==="none"){_("auth");return}if(Or(p,t,"proxy","p")&&F==="none"&&m!=="logs"){_("proxy");return}if(Or(p,t,"doctor","d")&&F==="none"&&m!=="doctor"){_("doctor");return}if(Or(p,t,"config","c")&&F==="none"){_("config");return}if(Or(p,t,"setup","u")&&F==="none"){_("setup");return}if(m==="config"&&u==="e"){nr(ki("/edit")??{name:"edit",aliases:[],desc:"",leader:"",group:"ui"},[]);return}if(m==="config"&&u==="v"){Fc();return}if(m==="doctor"&&u==="r"){yc((x)=>x+1),C("Re-running doctor");return}if(m==="logs"&&u==="p"){zt((x)=>!x);return}if((m==="logs"||m==="dashboard")&&u==="g"){Dc();return}if((m==="logs"||m==="dashboard")&&u==="w"){let x=gu(_o);hp(x),C(`Log ${Ai(x)}`);return}if((m==="logs"||m==="dashboard")&&u==="e"){Xt((x)=>!x);return}if((m==="logs"||m==="dashboard")&&u==="i"){jo(),C(pt?"Hiding internal auth/mcp/devctl/proxy logs":"Showing internal logs");return}if((m==="logs"||m==="dashboard")&&gv(p))Ho()});let Fp=Jy(Gr,Xe,gb),Wb=new Set(Yi?.waves.flat()??[]),Gb=Yi===void 0||Pp==="stop"?"":Object.entries(W?.services??{}).find(([p,u])=>Wb.has(p)&&u.state==="FAILED")?.[0]??"";return oe(ru.Provider,{value:Pi(R),children:oe("box",{flexDirection:"column",width:s,height:a,backgroundColor:A,overflow:"hidden",children:[Po?null:oe(WE,{children:[oe(ev,{palette:v,cfg:D,snap:W,google:Qt,profile:Xe,reveal:Co,width:s},void 0,!1,void 0,this),oe(tv,{palette:v,screen:m,width:s,onSelect:_},void 0,!1,void 0,this),Oo?oe("box",{height:1,paddingLeft:1,backgroundColor:v.panel,overflow:"hidden",children:oe("text",{fg:v.error,wrapMode:"none",children:`\u26A0 configuration reload failed: ${Oo}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),oe("box",{flexGrow:1,overflow:"hidden",children:[m==="dashboard"?oe(bx,{palette:v,cfg:D,snap:W,logs:$e,names:it,selected:Q,checked:we,profile:Xe,google:Qt,width:s,paused:dt,followTick:dp,logService:Wt,errorOnly:ut,showSystemLogs:pt,onOpen:ns,onSelectIndex:de,selectedLog:Zt,onToggle:Mc,logSources:Io,onFilterService:vr,onToggleErrors:()=>Xt((p)=>!p),onToggleSystemLogs:jo,onClearLogs:Ho,onShowErrors:()=>{vr(""),Xt(!0)},wrapMode:_o,view:kr,follow:!xt,onLeaveLatest:Lc,onPickLog:(p)=>{let u=kr[p];if(!u)return;qi(p),mp(u),Lc()},viewStart:Fe.start,viewTotal:rt.length,newer:Fe.newer,onJumpLatest:Dc,facets:yp},void 0,!1,void 0,this):null,m==="services"?oe(Nx,{palette:v,cfg:D,names:it,snap:W,selected:Q,checked:we,width:s,reveal:Co,onOpen:ns,onSelectIndex:de,onToggle:Mc},void 0,!1,void 0,this):null,m==="detail"?oe(Fx,{palette:v,cfg:D,snap:W,name:En,reveal:Co,width:s,envScrollRef:Ao},void 0,!1,void 0,this):null,m==="logs"?oe(vx,{palette:v,logs:$e,names:it,logSources:Io,service:Wt,paused:dt,errorOnly:ut,showSystemLogs:pt,search:yr,searchFocused:Bi,followTick:dp,width:s,onSearch:xb,onService:vr,onToggleErrors:()=>Xt((p)=>!p),onToggleSystemLogs:jo,onClearLogs:Ho,source:Wr,regex:xr,services:Br,showTimestamps:pp,showMeta:fp,view:kr,wrapMode:_o,selected:Q,follow:!xt,newer:Fe.newer,viewStart:Fe.start,viewTotal:rt.length,onSelect:Fo,fullscreen:Po,onLeaveLatest:Lc,onOpenExports:Fb,onJumpLatest:Dc,facets:yp},void 0,!1,void 0,this):null,m==="auth"?oe(Yv,{palette:v,cfg:D,google:Qt,identity:W?.identity},void 0,!1,void 0,this):null,m==="credentials"?oe(Xv,{palette:v,credentials:W?.credentials},void 0,!1,void 0,this):null,m==="proxy"?oe(Mx,{palette:v,cfg:D,snap:W,width:s,onSelectRoute:(p)=>{Pb(p),Z("route-details")}},void 0,!1,void 0,this):null,m==="mcp"?oe(Zx,{palette:v,snap:W,port:Sr,portDraft:Ji,selected:Q,onPick:de,onToggle:()=>{es()},onCopy:$c,onToggleTool:(p)=>{Ic(p)}},void 0,!1,void 0,this):null,m==="doctor"?oe(kx,{palette:v,report:Rn,loading:mc,progress:fb,error:pb,selected:Q,onPick:de,onReload:()=>{yc((p)=>p+1),C("Re-running doctor")}},void 0,!1,void 0,this):null,m==="stats"?oe(qx,{palette:v,cfg:D,snap:W,width:s,onRefresh:ge},void 0,!1,void 0,this):null,m==="config"?oe(mx,{palette:v,cfg:D,width:s,scrollRef:Eo},void 0,!1,void 0,this):null,m==="profiles"?oe(Rx,{palette:v,cfg:D,snap:W,profile:Xe,selected:Q,onPick:de},void 0,!1,void 0,this):null,m==="setup"?oe(Jx,{palette:v,cfg:D,google:Qt,bootError:n,bootErrorMissing:o,step:Q},void 0,!1,void 0,this):null,m==="settings"?oe(Gx,{palette:v,items:lt,selected:Q,locked:J,width:s,onPick:de,onActivate:Oc},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),F==="slash"?oe(Wv,{palette:v,items:$o,query:he,selected:ae,onQuery:ke,onSubmit:$p},void 0,!1,void 0,this):null,F==="palette"?oe(Ov,{palette:v,items:An,selected:Math.min(Je,Math.max(An.length-1,0)),termW:s,termH:a,onIndex:Ue,onPick:Nb},void 0,!1,void 0,this):null,F==="themes"?oe(Vv,{palette:v,themeName:c,selected:Je%ht.length,termW:s,termH:a,onIndex:Ue,onPreview:l,onPick:Ip},void 0,!1,void 0,this):null,F==="help"?oe(Ev,{palette:v,termW:s,termH:a,copyKey:Tp,scrollRef:To},void 0,!1,void 0,this):null,F==="leader"?oe(Lv,{palette:v,termW:s,termH:a},void 0,!1,void 0,this):null,F==="confirm"?oe(wv,{palette:v,title:Fp.title,body:Fp.body,termW:s,termH:a},void 0,!1,void 0,this):null,F==="log-details"?oe(kv,{palette:v,event:Ui,termW:s,termH:a,scrollRef:Lo},void 0,!1,void 0,this):null,F==="route-details"?oe(Hv,{palette:v,route:Rb,termW:s,termH:a,scrollRef:wc},void 0,!1,void 0,this):null,F==="config-edit"&&D?oe(xv,{palette:v,path:D.configPath,initialValue:kc,error:Lb,termW:s,termH:a,textareaRef:Cp},void 0,!1,void 0,this):null,F==="plan"&&Yi?oe(Fv,{palette:v,plan:Yi,snap:W,busy:Rp,failed:Gb,kind:Pp,termW:s,termH:a,scrollRef:Sc,initiallyRunning:Db,onDismiss:Qe},void 0,!1,void 0,this):null,F==="slash"||F==="plan"||F==="config-edit"||Po||Qh(a)&&F==="none"?null:oe(rv,{palette:v,overlay:F,query:he,onQuery:ke,onSubmit:$p},void 0,!1,void 0,this),Po?null:oe(nv,{palette:v,screen:m,overlay:F,status:fc,paused:dt,errorOnly:ut,width:s,copyKey:Tp},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var HE=50,jE,BE=2000;var rb=T(()=>{St();ui();ii();nn();_e();fn();Ye();dn();ga();kt();sv();Pe();vv();ve();bv();Sv();Cv();Tv();Dv();Iv();Nv();jv();Gv();Jv();zv();Qv();hx();wx();Cx();Hu();Px();Ox();Ku();Hx();Ux();Vx();Yx();eb();yi();ot();pr();ze();Vt();jE=[]});var nb={};ss(nb,{renderApp:()=>tp,runTui:()=>ep,runTuiWithController:()=>KE,tuiConfigFor:()=>qE});import{createCliRenderer as GE}from"@opentui/core";import{createRoot as UE}from"@opentui/react";import{jsxDEV as VE}from"@opentui/react/jsx-dev-runtime";async function KE(e){let t=qt(e.cfg.repoRoot,e.cfg.ui.keymap);await tp(e,t)}async function ep(e){let t,r,n=!1;try{t=await pg("",e)}catch(i){r=H(i),n=ds(i,Kr)}let o=qt(t?.cfg.repoRoot??process.cwd(),t?.cfg.ui.keymap);await tp(t,o,r,n)}async function tp(e,t=qt(e?.cfg.repoRoot??process.cwd(),e?.cfg.ui.keymap),r,n=!1){as();let o=Bp(),i=await GE({exitOnCtrlC:!1,useMouse:t.mouse,enableMouseMovement:t.mouse,useKittyKeyboard:{}}),s=UE(i),a=null;try{a=(await i.getPalette({timeout:120,size:16})).defaultBackground}catch{}await new Promise((c)=>{let l=(d)=>{let g=()=>{s.unmount(),o(),i.destroy(),c(),process.exit(0)};if(!e){g();return}e.close({detach:d,shutdownSupervisor:!0}).finally(g)};s.render(VE(tb,{controller:e,tui:t,onQuit:l,bootError:r,bootErrorMissing:n,terminalBackground:a},void 0,!1,void 0,this))})}function qE(e){return qt(e.repoRoot,e.ui.keymap)}var rp=T(()=>{Dl();_e();rb();Hc();Vt()});On();Hc();St();Dl();Ye();ui();_e();nn();St();ci();dn();ud();import{Command as zE}from"commander";import{setTimeout as ip}from"timers/promises";import{stringify as XE}from"yaml";import{existsSync as cb,readFileSync as QE}from"fs";St();Tl();_e();nn();import{createServer as V0}from"net";import{existsSync as Nd,unlinkSync as J0,watch as Y0}from"fs";import{cpus as z0,loadavg as X0,platform as Q0,uptime as Z0}from"os";import{isAbsolute as ah,join as Hd}from"path";Ye();dn();import{connect as Zk}from"net";var eC=2000,tC=2000,rC=200,nC=300;function em(e){if(e.interval_seconds<=0)return tC;return e.interval_seconds*1000}async function tm(e,t,r,n,o,i=[]){let s=e.timeout_seconds>0?e.timeout_seconds*1000:eC,a=e.type.toLowerCase(),c=i.find((l)=>l.name.toLowerCase()===a);if(c)try{let l=await c.check(e,{pid:t,ports:r,workDir:n,env:o});return{status:l.status,message:l.message}}catch(l){return{status:Ae,message:l instanceof Error?l.message:String(l)}}if(a==="http")return oC(e.url,s);if(a==="tcp")return sC(iC(e.address,r),s);if(a==="command")return aC(e.command.args,e.command.shell,n,o,s);if(a==="process"||a===""){if(t>0&&Rt(t))return{status:Et,message:"process running"};return{status:Ae,message:"process not running"}}return{status:Ae,message:`unknown health type ${e.type}`}}async function oC(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),t);try{let o=await fetch(e,{signal:r.signal});if(o.status>=rC&&o.status<nC)return{status:Et,message:String(o.status)};return{status:Ae,message:String(o.status)}}catch(o){return{status:Ae,message:o instanceof Error?o.message:String(o)}}finally{clearTimeout(n)}}function iC(e,t){if(e!=="")return e;if(t.http!==void 0)return`127.0.0.1:${t.http}`;let r=Object.values(t)[0];return r!==void 0?`127.0.0.1:${r}`:""}function sC(e,t){return new Promise((r)=>{if(e===""){r({status:Ae,message:"no tcp address"});return}let n=Zk(e,()=>{n.end(),r({status:Et,message:"connected"})});n.setTimeout(t),n.on("error",(o)=>{r({status:Ae,message:o.message})}),n.on("timeout",()=>{n.destroy(),r({status:Ae,message:"timeout"})})})}async function aC(e,t,r,n,o){if(e.length===0)return{status:Ae,message:"empty health command"};let i=t?process.platform==="win32"?["cmd.exe","/c",e.join(" ")]:["/bin/sh","-c",e.join(" ")]:e,s;try{s=Bun.spawn({cmd:i,cwd:r===""?void 0:r,env:n,stdout:"ignore",stderr:"ignore"})}catch(l){return{status:Ae,message:l instanceof Error?l.message:String(l)}}let a=setTimeout(()=>s.kill("SIGKILL"),o),c=await s.exited;if(clearTimeout(a),c===0)return{status:Et,message:"ok"};return{status:Ae,message:`exit ${c}`}}function rm(e){if(e===Ae)return"WARN";if(e===Et)return"INFO";return"DEBUG"}import{readFileSync as cC}from"fs";import{freemem as lC,totalmem as dC}from"os";import{spawnSync as uC}from"child_process";var pd=1024,pC=2000,fC=/page size of (\d+) bytes/i,eo;function gC(e){let t=e.match(/^MemAvailable:\s+(\d+)/m);if(!t)return;let r=Number(t[1]);return Number.isFinite(r)&&r>=0?r:void 0}function mC(e){let t=e.match(fC),r=t?Number(t[1]):0;if(!Number.isFinite(r)||r<=0)return;let n=zs(e,"free")+zs(e,"inactive")+zs(e,"speculative")+zs(e,"purgeable");return Math.round(n*r/pd)}function zs(e,t){let r=e.match(new RegExp(`Pages ${t}:\\s+(\\d+)`,"i")),n=r?Number(r[1]):0;return Number.isFinite(n)&&n>0?n:0}function hC(){if(process.platform==="linux")try{return gC(cC("/proc/meminfo","utf8"))}catch{return}if(process.platform==="darwin"){let e=Date.now();if(eo&&e-eo.at<pC)return eo.leftoverKB;let t=uC("vm_stat",{encoding:"utf8"});if(t.status!==0||!t.stdout)return eo?.leftoverKB;let r=mC(t.stdout);if(r===void 0)return eo?.leftoverKB;return eo={at:e,leftoverKB:r},r}return}function nm(){let e=Math.max(0,Math.round(dC()/pd)),t=Math.max(0,Math.round(lC()/pd)),r=Math.max(0,Math.min(e,hC()??t));return{totalKB:e,unusedKB:t,leftoverKB:r}}rn();fn();ii();fn();import{pathToFileURL as JC}from"url";St();_e();rn();import{createServer as vm}from"http";import{randomBytes as HC}from"crypto";import{Readable as jC}from"stream";var Rd="x-devctl-request-id",BC="x-devctl-internal-token",hm=100,ym=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]),WC=new Set(["gzip","deflate","br"]);class Pd{cfg;tokens;logs;bus;detector;middleware;server;running=!1;addr="";recentRequests=[];constructor(e,t,r,n,o,i=[]){this.cfg=e,this.tokens=t,this.logs=r,this.bus=n,this.detector=o,this.middleware=i}address(){return this.addr||Yr(this.cfg.listen)}isRunning(){return this.running}stats(){let e=this.recentRequests.reduce((t,r)=>t+(r.status>=400||r.error?1:0),0);return{total:this.recentRequests.length,errors:e,recent:[...this.recentRequests].reverse()}}recordRequest(e){if(this.recentRequests.push(e),this.recentRequests.length>hm)this.recentRequests.splice(0,this.recentRequests.length-hm)}start(){if(this.cfg.listen.host==="0.0.0.0")return Promise.reject(M(_r,"refusing to bind proxy to 0.0.0.0 without explicit unsafe configuration"));let e=this.cfg.listen.host||"127.0.0.1";if(this.cfg.listen.port===0)return Promise.reject(M(_r,"proxy.listen.port is required when the proxy is enabled"));let t=this.cfg.listen.port;return new Promise((r,n)=>{this.server=vm((o,i)=>{this.serve(o,i)}),this.server.on("error",(o)=>n(ye(_r,`unable to listen on ${e}:${t}`,o))),this.server.listen(t,e,()=>{this.running=!0,this.addr=`${e}:${t}`,this.bus?.publish(Ne(Dg,"",{address:this.addr})),r()})})}stop(){let e=this.server;if(!e)return Promise.resolve();return new Promise((t)=>{e.close(()=>{this.running=!1,this.bus?.publish(Ne(Mg,"",{})),t()})})}async serve(e,t){let r=Date.now(),n=e.headers[Rd]?.toString()||HC(8).toString("hex");t.setHeader(Rd,n);let o=e.method??"GET",i=e.url??"/",s=this.detector?this.detector.redactText(i):i,a=qC(this.cfg.routes,e);if(!a){ro(t,404,"no matching proxy route"),this.recordRequest({timestamp:new Date().toISOString(),requestId:n,method:o,path:s,route:"",identity:"",status:404,durationMs:Date.now()-r});return}let c=Wn(a.auth),l=ri(c),d=0,g;try{let f={};for(let[A,m]of Object.entries(e.headers)){if(ym.has(A.toLowerCase()))continue;if(typeof m==="string")f[A]=m;else if(Array.isArray(m))f[A]=m.join(",")}let h=e.socket.remoteAddress??"",y=f.host??"",b=f["x-forwarded-for"];if(f["x-forwarded-for"]=b?`${b}, ${h}`:h,f["x-forwarded-host"]=y,f["x-forwarded-proto"]="http",delete f.host,f["accept-encoding"]="gzip, deflate, br",f[Rd]=n,this.middleware.length===0)await Ed(a,f,this.tokens);for(let A of this.middleware)await A.apply({route:a,headers:f,tokens:this.tokens});let w=UC(a.upstream.url,i),R=o!=="GET"&&o!=="HEAD"?e:void 0,S=await fetch(w,{method:o,headers:f,body:R,redirect:"manual",duplex:R?"half":void 0});t.statusCode=S.status,d=S.status;let N=(S.headers.get("content-encoding")??"").split(",").map((A)=>A.trim().toLowerCase()).filter((A)=>A!==""),J=N.length>0&&N.every((A)=>WC.has(A));S.headers.forEach((A,m)=>{let _=m.toLowerCase();if(ym.has(_))return;if(J&&(_==="content-encoding"||_==="content-length"))return;t.setHeader(m,this.detector?this.detector.redactText(A):A)}),await GC(S,t);let v=Date.now()-r;this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:S.status>=400?"WARN":"INFO",message:`${o} ${i} route=${a.name} identity=${l} status=${S.status} duration=${v}ms`,pid:0,request_id:n,identity:l}),this.bus?.publish(Ne(Og,a.name,{status:S.status,request_id:n,duration:v,identity:l}))}catch(f){let h=f instanceof Error?f.message:"proxy error";g=h,d=502,this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:"ERROR",message:`${o} ${i} route=${a.name} identity=${l} error=${h}`,pid:0,request_id:n,identity:l}),ro(t,502,"proxy error")}finally{this.recordRequest({timestamp:new Date().toISOString(),requestId:n,method:o,path:s,route:a.name,identity:l,status:d,durationMs:Date.now()-r,error:g})}}}async function Ed(e,t,r){let n=e.auth.type.toLowerCase();if(n===""||n==="none")return;if(!r)throw M(_r,"token manager unavailable");let o=Wn(e.auth),i=await r.get(ri(o),e.auth.audience,[]);t.authorization=`Bearer ${i.accessToken}`}async function GC(e,t){if(!e.body){t.end();return}let r=jC.fromWeb(e.body);await new Promise((n,o)=>{r.on("error",o),t.on("error",o),t.on("finish",n),r.pipe(t)})}function UC(e,t){let r=new URL(e),n=new URL(t||"/",r),o=new URL(r.href);if(o.pathname=KC(n.pathname),o.search=n.search,o.hash="",o.origin!==r.origin)throw M(_r,"refusing to proxy to a different origin");return o}function KC(e){return(e.startsWith("/")?e:`/${e}`).replace(/^\/+/,"/")}function ro(e,t,r){e.statusCode=t,e.setHeader("content-type","text/plain; charset=utf-8"),e.setHeader("x-content-type-options","nosniff"),e.end(r)}function qC(e,t){let r=(t.headers.host??"").split(":")[0]??"",n=t.url??"/";return e.find((o)=>{let i=o.match.host===""||o.match.host===r,s=o.match.path===""||n.startsWith(o.match.path);return i&&s})}class Td{host;port;secret;tokens;server;constructor(e,t,r,n){this.host=e;this.port=t;this.secret=r;this.tokens=n}listenPort(){let e=this.server?.address();if(typeof e==="object"&&e)return e.port;return this.port}start(){let e=this.host||"127.0.0.1";if(e==="0.0.0.0")return Promise.reject(M(_r,"refusing to bind token endpoint to 0.0.0.0"));return new Promise((t,r)=>{this.server=vm((n,o)=>{this.serve(n,o)}),this.server.on("error",(n)=>r(ye(_r,"token endpoint listen failed",n))),this.server.listen(this.port,e,()=>t())})}stop(){let e=this.server;if(!e)return Promise.resolve();return new Promise((t)=>e.close(()=>t()))}async serve(e,t){if(!VC(e.socket.remoteAddress)){ro(t,403,"forbidden");return}if((e.headers[BC]??"")!==this.secret){ro(t,401,"unauthorized");return}if(e.url?.startsWith("/token")!==!0){ro(t,404,"not found");return}let r=new URL(e.url,"http://127.0.0.1"),n=r.searchParams.get("identity")??"user",o=r.searchParams.get("audience")??"";try{let i=await this.tokens.get(n,o,[]);t.setHeader("content-type","application/json"),t.end(JSON.stringify({access_token:i.accessToken,token_type:i.tokenType,expires_at:i.expiresAt.toISOString(),identity:i.identity}))}catch{ro(t,500,"token error")}}}function VC(e){if(!e)return!0;return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}ci();rn();class xm{tokenProviders=[];identityProviders=[];environmentSources=[];healthChecks=[];logParsers=[];proxyMiddleware=[];registerBuiltins(){this.tokenProviders.push(...an()),this.identityProviders.push(Ol(),Il()),this.logParsers.push(Sd()),this.proxyMiddleware.push(YC())}register(e){no(this.tokenProviders,e.tokenProviders),no(this.identityProviders,e.identityProviders),no(this.environmentSources,e.environmentSources),no(this.healthChecks,e.healthChecks),no(this.logParsers,e.logParsers),no(this.proxyMiddleware,e.proxyMiddleware)}}async function bm(e){let t=new xm;t.registerBuiltins();for(let r of e){if(r.trim()==="")continue;let o=await import(r.startsWith("file:")?r:JC(r).href);t.register(o)}return t}function YC(){return{name:"identity_inject",apply:async(e)=>{await Ed(e.route,e.headers,e.tokens)}}}function no(e,t){if(!t)return;e.push(...t)}_e();var{spawn:o0}=globalThis.Bun;Ye();var{spawn:zC}=globalThis.Bun;async function wm(e,t){if(e<=0)return;try{process.kill(-e,t);return}catch{try{process.kill(e,t)}catch{return}}}async function Sm(e){if(!Rt(e))return;let t=await hi(["ps","-p",String(e),"-o","command="]),r=Date.now(),n=XC(await hi(["ps","-p",String(e),"-o","etime="])),o=await QC(e);return{pid:e,command:t.trim(),cwd:o,startTime:n===void 0?void 0:new Date(r-n).toISOString()}}function XC(e){let t=e.trim();if(t==="")return;let r=t.indexOf("-"),n=r>=0?t.slice(0,r):"0",i=(r>=0?t.slice(r+1):t).split(":");if(i.length!==2&&i.length!==3)return;let s=Number(n),a=i.length===3?Number(i[0]):0,c=Number(i.length===3?i[1]:i[0]),l=Number(i.at(-1));if(!Number.isInteger(s)||s<0||!Number.isInteger(a)||a<0||a>23||!Number.isInteger(c)||c<0||c>59||!Number.isInteger(l)||l<0||l>59)return;return(((s*24+a)*60+c)*60+l)*1000}async function QC(e){let r=(await hi(["lsof","-a","-p",String(e),"-d","cwd","-Fn"])).split(`
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
614
|
+
`),o=[];for(let i of n)if(i.length<=r)o.push(i);else o.push(...sP(i,r));return o.length>0?o:[""]}function Jh(e,t,r){let n=e.length>0?[...e]:[""];if(r||n.length<=1)return{visible:n,mark:"",folded:!1,hidden:0};let o=n.length-1,i=` ${rP}${o}`,s=Math.max(1,t-i.length);return{visible:[le(n[0]??"",s)],mark:i,folded:!0,hidden:o}}function Yh(e,t){return e==="all"||e==="focus"&&t}function hu(e){if(e==="clip")return"focus";if(e==="focus")return"all";return"clip"}function zh(e,t,r,n=wn){if(e.length===0)return{start:0,items:[],newer:0};if(!t){let a=Math.max(0,e.length-n);return{start:a,items:e.slice(a),newer:0}}let o=e.length-1,i=Math.max(0,Math.min(r,o)),s=e.slice(i,i+n);return{start:i,items:s,newer:Math.max(0,e.length-i-s.length)}}function yu(e,t=wn){return Math.max(0,e-t)}function vu(e,t,r,n){let o=Math.max(t-1,0);if(e<0&&r>0)return{selected:0,startDelta:Math.max(-r,e)};if(e>o&&n>0)return{selected:o,startDelta:Math.min(n,e-o)};return{selected:Math.min(o,Math.max(0,e)),startDelta:0}}function Li(e){if(e==="all")return"wrap all";if(e==="focus")return"wrap selected";return"clip"}function sP(e,t){let r=[],n=e;while(n.length>t){let o=n.slice(0,t),i=aP(o);if(i>0)r.push(n.slice(0,i).trimEnd()),n=n.slice(i).trimStart();else r.push(n.slice(0,t)),n=n.slice(t)}if(n.length>0)r.push(n);return r}function aP(e){let t=e.lastIndexOf(" "),r=e.lastIndexOf("\t"),n=e.lastIndexOf(","),o=Math.max(t,r,n);if(o<Math.floor(e.length*nP))return-1;return e[o]===","?o+1:o}function Xh(e){let t=[],r=new RegExp(oP.source,"gi"),n=0,o=r.exec(e);while(o){let i=o[0]??"";if(o.index>n)t.push({text:e.slice(n,o.index),kind:"text"});t.push({text:i,kind:iP(i)}),n=o.index+i.length,o=r.exec(e)}if(n<e.length)t.push({text:e.slice(n),kind:"text"});if(t.length===0)return[{text:e,kind:"text"}];return t}function Qh(e){let t=e.showTimestamps?ja:0,r=e.showMeta?Na:0;return Math.max(Uh,e.width-t-e.serviceWidth-Ba-r-Kh-Ai*qh)}function Di(e){return Math.max(K_,e-q_*2)}function Zh(e){let t=e.width<G_,r=e.proxyOn?`\u25CF ${le(e.proxyAddress,t?10:18)}`:t?"":"\u25CB off";return[{label:t?`${e.running}/${e.total}`:bu(e.running,e.total),tone:e.running>0?"success":"idle"},{label:r,tone:e.proxyOn?"info":"idle",hide:t&&!e.proxyOn},{label:"MCP",tone:"info",hide:!e.mcpOn},{label:e.adc?t?"ADC":"ADC ok":t?"!ADC":"ADC missing",tone:e.adc?"success":"error"},{label:t?"sec":"secrets shown",tone:"warning",hide:!e.reveal}]}function ey(e,t){let r=t.reduce((s,a)=>Math.max(s,a.length),0),n=ja+Ba+Kh+Uh+Ai*qh,o=Math.max(Dh,e-n),i=Math.max(Dh,r);return Math.min(Fh,o,i)}function Ga(e,t,r){if(r)return e;let n=t.reduce((a,c)=>Math.max(a,c.length),0),o=Math.min(Fh,Math.max(pu,n+F_)),i=$h+Jt+yt+o+Nh+N_,s=Math.max(La,Math.floor(e*W_));return Math.min(s,Math.max(La,i))}function Y(e,t){if(t<=0)return"";if(e.length>=t)return le(e,t);return e.padEnd(t)}function fo(e,t){let r=[],n=0;for(let o of e){let i=o.key.length+o.label.length+3;if(n+i>t)break;r.push(o),n+=i}return r}function ty(e){return e<V_}function go(e,t,r,n,o="center",i=!0){let s=Math.min(r,Math.max(1,e-4)),a=Math.min(Hh(e,i),Math.max(0,t-1)),c=Math.min(n,Math.max(1,t-a)),l=Math.max(0,Math.min(Math.floor((e-s)/2),Math.max(0,e-s))),d=o==="bottom"?t-2-c:Math.floor((t-c)/2),g=Math.max(0,Math.min(d,t-c));return{left:l,top:g,width:s,height:c}}function ry(e){if(e==="")return"idle";if(lP.test(e))return"error";if(e.includes("session only"))return"warning";if(cP.test(e))return"success";return"info"}function ny(e,t,r){let n=r!==""&&e.profiles[r]?r:"";if(t.length>0)return{services:t,profile:n};if(n!=="")return{services:[...e.profiles[r]?.services??[]],profile:n};return{services:Object.keys(e.services),profile:""}}function oy(e,t){if(e==="doctor")return t.doctor;if(e==="settings")return t.settings;if(e==="profiles")return t.profiles;if(e==="dashboard"||e==="services")return t.services;if(e==="logs")return t.logs??0;if(e==="mcp")return t.mcp??0;if(e==="setup")return U_;return 0}function iy(e){if(e==="0")return Dr[9]?.id;if(e.length===1&&e>="1"&&e<="9")return Dr[Number(e)-1]?.id;return}function Ua(e){if(!e)return"";return Object.keys(e.profiles).sort()[0]??""}function Ka(e){return dP.has(e)}function Mi(e){if(!e)return!1;return Ka(e.state)}function qa(e,t){let r=t??Object.keys(e?.services??{});return{running:r.filter((o)=>Mi(e?.services[o])).length,total:r.length}}function sy(e,t){let r=0,n=0,o=0,i=0,s=0,a=0;for(let c of e){let l=t?.services[c];if(l?.health==="HEALTHY")o+=1;let d=l?.state??"STOPPED";if(d==="FAILED")i+=1;else if(d==="STOPPING")s+=1;else if(d==="STARTING"||d==="RESTARTING")n+=1;else if(Ka(d))r+=1;else a+=1}return{total:e.length,live:r+n,running:r,starting:n,healthy:o,failed:i,stopping:s,stopped:a}}function ay(e,t){if(!Number.isFinite(e)||!Number.isFinite(t)||t<=0)return 0;return e/t}function hP(e,t,r){if(!Number.isFinite(e))return"success";if(e>r)return"error";if(e>t)return"warning";return"success"}function yP(e,t){return hP(ay(e,t),uP,pP)}function vP(e,t){let r=t>0?e/t:1;if(r<gP)return"error";if(r<fP)return"warning";return"success"}function su(e){if(!Number.isFinite(e)||e<0)return"\u2014";return e.toFixed(2)}function xP(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${Math.round(e*100)}%`}function cy(e,t=Date.now()){if(!e?.startTime)return"\u2014";let r=new Date(e.startTime).getTime();if(!Number.isFinite(r))return"\u2014";return ho(t-r)}function ly(e,t=mP){return Object.entries(e).sort((r,n)=>n[1]-r[1]||r[0].localeCompare(n[0])).slice(0,t)}function dy(e,t=1){return Math.max(24,e-PP-t*2-RP-EP-TP)}function uy(e){let t=e>=bP,r=e>=wP,n=e>=SP,o=e>=kP,i=e>=CP,s=e>=_P,a=Jt+yt;if(t)a+=fr+yt;if(r)a+=Ia+yt;if(n)a+=$a+yt;if(o)a+=Oa+yt;if(i)a+=Va+yt;if(s)a+=Mr;return{name:Math.max(pu,e-a),health:t,cpu:r,mem:n,up:o,rst:i,pid:s}}function py(e){let t=Number.isFinite(e)&&e>0?e:0;return{ratio:Math.min(1,t),label:xP(t)}}function fy(e,t=DP){return`[${Oi(e.ratio,t)}] ${e.label.padStart(4)}`}function xu(e,t){let r=e.reduce((l,d)=>Math.max(l,d.what.length),4),n=e.reduce((l,d)=>Math.max(l,d.reading.length),7),o=e.some((l)=>l.meter)?MP:0,i=mo*(o>0?3:2),s=Math.min(AP,Math.max(au,r)),a=Math.min(LP,Math.max(cu,n)),c=t-s-a-o-i;if(c<Aa&&a>cu)a=Math.max(cu,a-(Aa-c)),c=t-s-a-o-i;if(c<Aa&&s>au)s=Math.max(au,s-(Aa-c)),c=t-s-a-o-i;return{what:s,reading:a,meaning:Math.max(0,c),meter:o}}function gy(e){return OP.has((e?.health.type??"").toLowerCase())}function my(e){if(e==="darwin")return"macOS";if(e==="win32")return"Windows";if(e==="linux")return"Linux";return e||"this computer"}function hy(e,t){let r=Math.max(1,t),n=yP(e,r),o=n==="error"?"overloaded":n==="warning"?"busy":"not busy",i=n==="error"?`${r} cores are queued up \u2014 last minute ${su(e)}`:n==="warning"?`${r} cores nearly full \u2014 last minute ${su(e)}`:`${r} cores. Last minute ${su(e)} (under ${r} is fine)`;return{what:"CPU work",reading:o,meaning:i,tone:n,meter:py(ay(e,r))}}function yy(e,t){let r=vP(e,t),n=`${Da(e)} of ${Da(t)}`,o=r==="error"?"Almost no RAM left for new work":r==="warning"?"RAM is getting tight":"RAM the computer can still give out",i=t>0?Math.max(0,(t-e)/t):0;return{what:"RAM leftover",reading:n,meaning:o,tone:r,meter:py(i)}}function vy(e){let t=e?.state??"STOPPED";if(t==="FAILED")return"crashed";if(t==="STOPPING")return"stopping";if(t==="STARTING"||t==="RESTARTING")return"starting";if(Ka(t))return"up";return"off"}function xy(e){if(!e||!Ka(e.state))return"\u2014";if(e.health==="HEALTHY")return"ready";if(e.health==="UNHEALTHY")return"failing";if(e.state==="STARTING"||e.state==="RESTARTING")return"waiting";return"checking"}function by(e){if(e==="keychain")return"password store";if(e==="file")return"local file";return e||"unknown store"}function wy(e,t){let r=[{what:"Started",reading:String(e.live),meaning:e.live===0?"nothing is running yet":"process is up",tone:e.live>0?"success":"muted"}];if(t)r.push({what:"Ready",reading:String(e.healthy),meaning:e.live===0?"start services first":"passed their health check",tone:e.live>0&&e.healthy<e.live?"warning":e.healthy>0?"success":"muted"});if(e.starting>0)r.push({what:"Still starting",reading:String(e.starting),meaning:"not ready for traffic yet",tone:"warning"});if(e.stopping>0)r.push({what:"Stopping",reading:String(e.stopping),meaning:"shutting down",tone:"warning"});return r.push({what:"Crashed",reading:String(e.failed),meaning:e.failed>0?"open the service for the error":"none",tone:e.failed>0?"error":"muted"}),r.push({what:"Not started",reading:String(e.stopped),meaning:e.stopped>0?"off until you start them":"all are up",tone:"muted"}),r}function Oi(e,t=20){let r=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0,n=Math.round(r*t);return"\u2588".repeat(n)+"\u2591".repeat(Math.max(0,t-n))}function ho(e){if(!Number.isFinite(e)||e<lu)return"< 1s";let t=Math.floor(e/Oh),r=Math.floor(e%Oh/uu),n=Math.floor(e%uu/du),o=Math.floor(e%du/lu);if(t>0)return`${t}d ${r}h`;if(r>0)return`${r}h ${n}m`;if(n>0)return`${n}m ${String(o).padStart(2,"0")}s`;return`${o}s`}function Da(e){if(!Number.isFinite(e)||e<0)return"\u2014";let t=e/IP;if(t>=Ih)return`${(t/Ih).toFixed(1)}G`;if(t>=1)return`${Math.round(t)}M`;return`${Math.round(e)}K`}function Sy(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${e.toFixed(1)}%`}function yo(e){if(!e)return!0;let t=Object.values(e.services);if(t.length===0)return!0;return!t.some((r)=>Mi(r))}function ky(e,t){if(e.length>0)return e;return[...t]}function Ja(e,t){if(e.length>0)return[...e];return t===""?[]:[t]}function Ii(e){return $P.has(e)}function _y(e,t,r,n){let o=r===""?t:t.filter((a)=>a.timestamp>=r);if(o.length===0)return e;let i=Math.max(1,n);if(o.length>=i)return o.slice(-i);let s=Math.max(0,e.length+o.length-i);return e.slice(s).concat(o)}function Py(e,t){let r=t.length>0?t[t.length-1].seq:-1,n=e.filter((o)=>o.seq>r);return[...t,...n]}function Ry(e,t){if(t.length===0)return e;let r=new Set(e.map((o)=>o.seq)),n=t.filter((o)=>!r.has(o.seq));return n.length===0?e:[...n,...e]}function Ey(e,t,r){return e&&t<=0&&r}function Ty(e){return e.filter((t)=>t.level==="ERROR"||t.level==="FATAL").length}function FP(e){return`${e.timestamp} ${e.service} ${e.level} ${e.message}`}function Ay(e){return[e.message,`time ${e.timestamp}`,`service ${e.service}`,`source ${e.source}${e.stream?` / ${e.stream}`:""}`,`level ${e.level}`,`pid ${e.pid||"\u2014"}`,`request ${e.request_id||"\u2014"}`,`identity ${e.identity||"\u2014"}`].join(`
|
|
615
|
+
`)}function Ly(e){return e.map((t)=>FP(t)).join(`
|
|
616
|
+
`)}function vo(e,t){let r=t.services?.filter((l)=>l!=="")??[],n=t.service??"",o=(t.search??"").trim(),i=t.source??"",s=t.since??"",a=t.until??"",c;if(o!=="")if(t.regex===!0){let l=ta(o);if(l)c=(d)=>l.test(d);else c=(d)=>d.toLowerCase().includes(o.toLowerCase())}else{let l=o.toLowerCase();c=(d)=>d.toLowerCase().includes(l)}return e.filter((l)=>{if(r.length>0&&!r.includes(l.service))return!1;if(n!==""&&l.service!==n)return!1;if(i!==""&&l.source!==i)return!1;if(t.systemLogs===!1&&Ii(l.source))return!1;if(s!==""&&l.timestamp<s)return!1;if(a!==""&&l.timestamp>a)return!1;if(t.errorOnly===!0&&l.level!=="ERROR"&&l.level!=="FATAL")return!1;if(!c)return!0;return c(l.message)||c(l.service)})}function NP(e,t){let r={};for(let i of e)r[i.service]=(r[i.service]??0)+1;let n=t.map((i)=>({name:i,count:r[i]??0})),o=Object.keys(r).filter((i)=>!t.includes(i)).sort().map((i)=>({name:i,count:r[i]??0}));return[...n,...o]}function Dy(e,t,r=[]){let n=$i(e,t,r);return[{name:"",count:t.length},...NP(t,n)]}function HP(e,t){let r=e.map((o)=>({name:o,count:t[o]??0})),n=Object.keys(t).filter((o)=>!e.includes(o)).sort().map((o)=>({name:o,count:t[o]??0}));return[...r,...n]}function My(e,t,r=[]){let n=Object.keys(t.byService).map((i)=>({service:i})),o=$i(e,n,r);return[{name:"",count:t.total},...HP(o,t.byService)]}function bu(e,t){if(e<=0)return"none started";return`${e}/${t} running`}function $i(e,t,r=[]){let n=[...e],o=(i)=>{if(i!==""&&!n.includes(i))n.push(i)};for(let i of r)o(i);for(let i of t)o(i.service);return n}function Oy(e,t,r){let n=["",...$i(e,t)];if(r<1||r>n.length)return;return n[r-1]}function wu(e,t,r){let n=["",...e],o=n.indexOf(t),s=((o<0?0:o)+r+n.length)%n.length;return n[s]??""}function Fi(e){return e.waves.flat().join(" \u2192 ")}function Iy(e){let t=Fi(e);if(t==="")return"Started selected services";return`Started ${t}`}function $y(e){let t=Fi(e);if(t==="")return"Stopped running services";return`Stopped ${t}`}function Fy(e,t,r,n="start"){let o=r?.services[e],i=Ot(o);if(o?.last_error&&n!=="stop")return o.last_error;if(n==="stop"){if(i==="STOPPED")return"stopped";if(i==="STOPPING")return"stopping now";if(i==="FAILED")return"already failed";return"queued"}if(i==="HEALTHY")return"ready";if(i==="STARTING")return"starting now";if(i==="RUNNING")return"up, waiting for health";if(i==="UNHEALTHY")return"unhealthy \u2014 retrying health check";if(i==="STOPPING")return"stopping first";if(i==="FAILED")return"failed \u2014 later waves will not start";let a=(t.steps.find((c)=>c.name===e)?.dependencies??[]).filter((c)=>Ot(r?.services[c])!=="HEALTHY");if(a.length>0)return`waits for ${a.join(", ")}`;return"queued"}function Ni(e,t,r="start"){if(e.length===0)return"completed";let n=e.map((i)=>t?.services[i]);if(n.some((i)=>i?.state==="FAILED"))return"failed";if(r==="stop"){if(n.every((i)=>!i||i.state==="STOPPED"||i.state==="UNKNOWN"))return"completed";if(n.some((i)=>i?.state==="STOPPING"))return"active";return"queued"}let o=(i)=>Boolean(i&&(i.state==="HEALTHY"||i.health==="HEALTHY"||i.state==="RUNNING"&&i.health!=="UNHEALTHY"));if(n.every(o))return"completed";if(n.some((i)=>i?.state==="UNHEALTHY"||i?.health==="UNHEALTHY"))return"unhealthy";if(n.some((i)=>i?.state==="STARTING"||i?.state==="RUNNING"||i?.state==="RESTARTING"))return"active";return"queued"}function Ny(e,t,r="start"){let o=e.waves.flat().length,i=0,s=0,a=0,c=0;for(let x=0;x<e.waves.length;x++){let v=e.waves[x]??[],b=Ni(v,t,r);if(b==="active"||b==="unhealthy"||b==="failed")c=x;else if(b==="completed"&&c===x&&x<e.waves.length-1)c=x+1;for(let P of v){let S=t?.services[P];if(r==="stop"?!S||S.state==="STOPPED"||S.state==="UNKNOWN":Boolean(S&&(S.state==="HEALTHY"||S.health==="HEALTHY"||S.state==="RUNNING"&&S.health!=="UNHEALTHY")))i++;else if(S?.state==="FAILED")s++;else if(S?.state==="STARTING"||S?.state==="RUNNING"||S?.state==="UNHEALTHY"||S?.health==="UNHEALTHY"||S?.state==="STOPPING"||S?.state==="RESTARTING")a++}}let l=o>0?Math.round(i/o*100):100,d=16,g=Math.round(l/100*d),f="\u2588".repeat(g)+"\u2591".repeat(Math.max(0,d-g)),h=i===o&&o>0;return{total:o,ready:i,active:a,failed:s,percent:l,progressBar:f,currentWaveIndex:c,totalWaves:e.waves.length,isComplete:h}}function Hy(e,t,r){let n=r==="completed"?"\u2713 Completed":r==="failed"?"\u2717 Failed":r==="unhealthy"?"\u26A0 Unhealthy":r==="active"?"\u23F3 In Progress":"\u25CB Queued";return`${e==="stop"?t===0?"Wave 1 (Stop First)":`Wave ${t+1}`:t===0?"Wave 1 (Start First)":`Wave ${t+1}`} \xB7 ${n}`}function jy(e,t,r,n){let o=n?` \xB7 Profile ${n}`:"";if(r)return`${e==="stop"?"Shutdown":"Startup"} Failed (${r})`;if(t)return`${e==="stop"?"Stopping Services":e==="restart"?"Restarting Pipeline":"Starting Pipeline"}${o}`;return`${e==="stop"?"Shutdown Complete":"Startup Complete"}${o}`}function By(e,t){if(e)return{primary:"Working\u2026 esc hide this panel (keeps running in background)",secondary:"Services are transitioning. You can dismiss anytime without stopping them."};if(t)return{primary:"enter or esc back to dashboard",secondary:"Execution stopped. Check logs or open Doctor to resolve errors."};return{primary:"enter or esc back to dashboard",secondary:"All waves finished. Click here or press enter to continue."}}function Wy(e){let t=bn.indexOf(e);if(t<0)return"dashboard";return bn[(t+1)%bn.length]??"dashboard"}function Gy(e){let t=bn.indexOf(e);if(t<0)return"dashboard";return bn[(t-1+bn.length)%bn.length]??"dashboard"}function Uy(e){return["services","nav","logs","ui","app"].flatMap((r)=>{let n=e.filter((o)=>o.group===r);if(n.length===0)return[];return[{group:r,items:n}]})}function Ky(e){let t=e.trim().toLowerCase().replace(/^\//,""),r=lo().filter((n)=>t===""||n.name.includes(t)||n.desc.toLowerCase().includes(t)||n.aliases.some((o)=>o.startsWith(t)));return Uy(r).flatMap((n)=>n.items)}function qy(e){return Uy(e).flatMap((t)=>t.items.map((r)=>({name:`/${r.name}`,description:`${t.group} \xB7 ${r.desc}`,value:r.name})))}function Vy(e,t,r=lr()){if(t==="slash")return[{key:"\u2191\u2193",label:"suggest"},{key:"tab",label:"complete"},{key:"enter",label:"run"},{key:"esc",label:"cancel"}];if(t==="palette"||t==="themes")return[{key:"\u2191\u2193",label:"move"},{key:"enter",label:t==="themes"?"save":"select"},{key:"esc",label:t==="themes"?"revert":"close"}];if(t==="help")return[{key:"j/k",label:"scroll"},{key:"esc",label:"close"}];if(t==="log-details")return[{key:"j/k",label:"scroll"},{key:r,label:"copy"},{key:"esc",label:"close"}];if(t==="confirm")return[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}];if(t==="plan")return[{key:"esc",label:"back to dashboard"},{key:"enter",label:"done"}];if(t==="leader")return Su();if(t==="config-edit")return[{key:"ctrl+s",label:"save"},{key:"esc",label:"discard"}];return jP(e,r)}function Su(){return[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"s",label:"services"},{key:"l",label:"logs"},{key:"t",label:"themes"},{key:"q",label:"quit"}]}function jP(e,t){let r=[{key:"/",label:"command"},{key:"ctrl+p",label:"palette"},{key:"?",label:"help"}];switch(e){case"dashboard":return[{key:"space",label:"select"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"enter",label:"start or open"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"},{key:"\u2190\u2192",label:"log filter"},{key:"g",label:"latest"},{key:"z",label:"full logs"},{key:"i",label:"internal logs"},{key:"ctrl+l",label:"clear logs"},{key:t,label:"copy logs"},{key:"j/k",label:"move"},...r];case"services":return[{key:"enter",label:"detail"},{key:"space",label:"select"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"},...r];case"detail":return[{key:"j/k",label:"scroll env"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"o",label:"config"},{key:"l",label:"logs"},{key:"esc",label:"back"},...r];case"logs":return[{key:"\u2190\u2192",label:"filter"},{key:"1-9",label:"source"},{key:"e",label:"errors"},{key:"i",label:"internal logs"},{key:"ctrl+l",label:"clear logs"},{key:"g",label:"latest"},{key:"f",label:"search"},{key:"t",label:"time"},{key:"m",label:"meta"},{key:"w",label:"wrap"},{key:"j/k",label:"move"},{key:t,label:"copy"},{key:"p",label:"pause"},{key:"z",label:"full screen"},{key:"/exports",label:"open folder"},...r];case"profiles":return[{key:"space",label:"set current"},{key:"enter",label:"set and start"},{key:"j/k",label:"move"},...r];case"proxy":return[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"},...r];case"mcp":return[{key:"j/k",label:"move"},{key:"space",label:"start or copy"},{key:"\u2190\u2192",label:"change port"},{key:"enter",label:"start or copy"},...r];case"config":return[{key:"v",label:"buffer"},{key:"e",label:"editor"},{key:"/reload",label:"reload"},{key:"j/k",label:"scroll"},...r];case"setup":return[{key:"j/k",label:"steps"},{key:"enter",label:"continue"},{key:"esc",label:"back or exit"},...r];case"doctor":return[{key:"r",label:"run doctor again"},{key:"j/k",label:"move"},{key:"enter",label:"fix port"},...r];case"auth":return[{key:"r",label:"probe identities"},{key:"/auth refresh",label:"probe"},...r];case"settings":return[{key:"j/k",label:"move"},{key:"\u2190\u2192",label:"save"},{key:"enter",label:"apply or open page"},{key:"space",label:"toggle"},...r];default:return[{key:"tab",label:"screens"},...r]}}function Jy(e,t,r){if(r<=t||e<t)return 0;return Math.min(e-t+1,r-t)}function Sn(e,t){if(e.length===0)return;let r=Math.min(Math.max(t,0),e.length-1);return e[r]}function Ya(e){return e.command.args.join(" ")||"\u2014"}function Hi(e,t){let r=kn(t);if(r!=="")return r;if(e.ports.length===0)return"\u2014";return e.ports.map((n)=>`${n.name}:${n.auto?"auto":n.value}`).join(" ")}function za(e){let t=e.health.type||"none",r=e.health.url||e.health.address;return r===""?t:`${t} ${r}`}function Xa(e,t){if(t?.identity)return t.identity;let r=e.identity.type||"none",n=e.identity.service_account;return n===""?r:`${r} ${n}`}function Qa(e){let t=e.restart.policy||"none";if(e.restart.max_retries>0)return`${t} \xD7${e.restart.max_retries}`;return t}function Yy(e,t,r,n){let o={...e.environment.defaults,...e.environment.vars},i=qP(o,t,r,n);return[...new Set([...Object.keys(i),...e.environment.required])].sort().map((a)=>({key:a,value:i[a]??"",required:e.environment.required.includes(a)}))}function zy(e){let t=Math.max(KP,e-UP);return Math.min(WP,Math.max(BP,Math.floor(t*GP)))}function kn(e){if(!e)return"";if(e.ports.http!==void 0)return String(e.ports.http);let t=Object.values(e.ports)[0];return t!==void 0?String(t):""}function Ot(e){if(!e)return"STOPPED";return eo(e)}function Xy(e,t,r){if(e==="quit")return{title:"Quit",body:"Stop managed services and leave the TUI? Press d to detach and leave them running."};if(e==="reload")return{title:"Reload applied",body:t===""?"Configuration changed. Restart marked services?":`Restart required: ${t}`};if(e==="reset-prefs")return{title:"Reset preferences",body:"Restore theme, display size, mouse, and leader timeout to defaults? This overwrites your saved tui.json values."};if(e==="free-port"){let n=r?.port??0,o=r?.process||"process",i=r?.pid??0;return{title:`Free port ${n}`,body:`Stop ${o} (pid ${i}) so port ${n} can be used? This sends SIGTERM, then SIGKILL if it stays up.`}}return{title:"Start profile",body:t===""?"Start the configured services?":`Start profile ${t}?`}}function qP(e,t,r,n){if(t)return e;return new mn(r,n).redactMap(e)}function Qy(e,t){if(!e)return"";return(e.profiles[t]?.services??[]).join(", ")}function xo(e,t,r){let n=e?.google?.project_id??"";if(n!=="")return{project:n,source:"configuration"};let o=t?.project||r?.projectID||"",i=t?.project_source||r?.projectSource||"";return{project:o,source:i}}function Zy(e,t,r,n){let o=Math.max(8,n-2),i=`logs ${r}`,s=Lr(i),a=e||"(no user)",c=t||"";if(o<=s+6){let f=Math.max(2,o-s-2);return[{label:le(a,f),tone:"idle"},{label:le(i,s-2),tone:"muted"}]}let l=o-s;if(c&&l>=36){let f=le(c,14),h=Lr(f),x=l-h-2,v=x>=a.length+9?`identity ${a}`:a;return[{label:le(v,x),tone:"idle"},{label:f,tone:"muted"},{label:i,tone:"muted"}]}if(c&&l>=28&&c.length<=10){let f=le(c,10),h=Lr(f),x=l-h-2;return[{label:le(a,x),tone:"idle"},{label:f,tone:"muted"},{label:i,tone:"muted"}]}let d=l>=a.length+9?`identity ${a}`:a;return[{label:le(d,l-2),tone:"idle"},{label:i,tone:"muted"}]}function ev(e){let t=e.payload?.error;return typeof t==="string"&&t!==""?t:"configuration reload failed"}var po=100,$h=8,Jt=12,fr=10,Ma=8,Mr=8,Oa=9,Ia=7,$a=8,pu=12,Fh=40,yt=2,F_=2,Nh=2,N_=2,La=34,H_=48,j_=60,B_=72,W_=0.48,Fa=90,G_=60,U_=9,Na=8,K_=8,q_=6,V_=20,Lh=1,J_=1,Y_=1,z_=1,X_=1,WM,Q_=2,Ta=2,Z_=80,eP=56,ja=9,Ba=7,Dh=10,Uh=16,Kh=2,Ai=1,wn=200,tP=2,Mh=1,rP="\u25B8",qh=2,nP=0.4,oP,cP,lP,Dr,bn,dP,uP=0.85,pP=1.5,fP=0.2,gP=0.1,mP=5,bP=52,wP=64,SP=72,kP=82,CP=90,_P=100,PP=2,RP=2,EP=2,TP=1,Va=8,au=8,AP=22,cu=6,LP=28,Aa=12,mo=2,DP=10,MP=18,OP,lu=1000,du,uu,Oh,IP=1024,Ih=1024,$P,Cy,BP=10,WP=28,GP=0.42,UP=2,KP=20;var Re=A(()=>{gn();ua();un();Vt();WM=Hh(Fa-1);oP=/("[^"]*"|'[^']*'|\b(?:ERROR|FATAL|WARN(?:ING)?|FAIL(?:ED)?)\b|\b\d{3,5}\b)/gi;cP=/^(started|stopped|restarted|refreshed|cleared|copied|exported|jumped|proxy started|proxy stopped|secrets|re-running|theme |mouse |leader |display |restored)/i,lP=/\b(fail|error|unknown|not found|no configuration|blocked|already in use|is using port)\b/i;Dr=[{id:"dashboard",label:"dashboard"},{id:"services",label:"services"},{id:"logs",label:"logs"},{id:"auth",label:"identity"},{id:"credentials",label:"credentials"},{id:"proxy",label:"proxy"},{id:"doctor",label:"doctor"},{id:"config",label:"config"},{id:"profiles",label:"profiles"},{id:"setup",label:"setup"},{id:"stats",label:"stats"},{id:"settings",label:"settings"}];bn=Dr.map((e)=>e.id);dP=new Set(["RUNNING","STARTING","RESTARTING","HEALTHY","UNHEALTHY"]);OP=new Set(["http","tcp","command"]);du=60*lu,uu=60*du,Oh=24*uu;$P=new Set(["auth","devctl","proxy"]),Cy=["devctl","mcp","auth"]});import{useEffect as VP,useRef as JP}from"react";import{jsxDEV as ne,Fragment as zP}from"@opentui/react/jsx-dev-runtime";function YP(e,t){switch(t){case"primary":return{bg:e.primary,fg:xn(e.primary,e.inverse)};case"accent":return{bg:e.accent,fg:_a(e)?Ca:xn(e.accent,e.inverse)};case"success":return{bg:e.success,fg:xn(e.success,e.inverse)};case"warning":return{bg:e.warning,fg:_a(e)?Ca:xn(e.warning,e.inverse)};case"error":return{bg:e.error,fg:xn(e.error,e.inverse)};case"info":return{bg:e.info,fg:xn(e.info,e.inverse)};case"muted":return{bg:e.element,fg:e.text};default:return{bg:e.element,fg:e.text}}}function tv(e){let{palette:t,dir:r}=e;return ne("box",{width:2,height:1,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,children:r==="left"?"\u2039":"\u203A"},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function je(e){let{palette:t,children:r,backgroundColor:n,edge:o="bottom"}=e,i=re(),s=e.ruled??!ur(i),a=n??t.element,c=ne("box",{flexShrink:0,flexDirection:"column",backgroundColor:a,overflow:"hidden",children:r},void 0,!1,void 0,this);if(!s)return c;return ne("box",{flexShrink:0,flexDirection:"column",overflow:"hidden",border:[...o==="both"?["top","bottom"]:[o]],borderStyle:"single",borderColor:t.border,children:c},void 0,!1,void 0,this)}function Za(e){let{palette:t,items:r,active:n,width:o,onPick:i}=e,s=r.map((d)=>Lr(d.label)),a=Bh(s,n,Math.max(1,o)),c=a.start>0,l=a.end>=0&&a.end<r.length-1;return ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[c?ne(tv,{palette:t,dir:"left"},void 0,!1,void 0,this):null,r.map((d,g)=>{if(g<a.start||g>a.end)return null;let f=g===n;return ne(pe,{palette:t,label:d.label,tone:f?"primary":"muted",fg:f?void 0:d.color,onMouseDown:()=>i(g)},d.id,!1,void 0,this)}),l?ne(tv,{palette:t,dir:"right"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function pe(e){let{palette:t,label:r,tone:n="idle",fg:o,bg:i,onMouseDown:s}=e,a=YP(t,n);return ne("box",{height:1,paddingLeft:1,paddingRight:1,backgroundColor:i??a.bg,overflow:"hidden",flexShrink:0,onMouseDown:s,children:ne("text",{fg:o??a.fg,children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ee(e){let{palette:t,hints:r}=e;return ne("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:r.map((n)=>ne("box",{height:1,paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ne("text",{wrapMode:"none",children:[ne("span",{fg:t.primary,children:n.key},void 0,!1,void 0,this),ne("span",{fg:t.muted,children:` ${n.label}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},`${n.key}-${n.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function Be(e){let{palette:t,items:r,hints:n,ruled:o=!0}=e,i=ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[r.map((s,a)=>ne(pe,{palette:t,label:s.text,tone:s.tone,onMouseDown:s.onMouseDown},`${s.text}-${a}`,!1,void 0,this)),n&&n.length>0?ne(zP,{children:[ne("box",{flexGrow:1,backgroundColor:t.element},void 0,!1,void 0,this),ne(Ee,{palette:t,hints:n},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this);if(!o)return i;return ne(je,{palette:t,backgroundColor:t.element,children:i},void 0,!1,void 0,this)}function Ze(e){let{palette:t,title:r,termW:n,termH:o,preferW:i,preferH:s,anchor:a="center",borderColor:c,bottomTitle:l,gap:d,children:g}=e,f=ur(re()),h=go(n,o,i,s,a,!f);return ne("box",{position:"absolute",left:h.left,top:h.top,width:h.width,height:h.height,border:!0,borderStyle:ku,borderColor:c??t.borderActive,backgroundColor:t.panel,padding:f?0:1,title:r,titleColor:t.primary,bottomTitle:l,gap:f?0:d,flexDirection:"column",overflow:"hidden",children:g},void 0,!1,void 0,this)}function De(e){return{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:e.panel},viewportOptions:{backgroundColor:e.panel},contentOptions:{backgroundColor:e.panel},scrollbarOptions:{trackOptions:{foregroundColor:e.primary,backgroundColor:e.element}}}}function We(e,t){if(!e)return;e.scrollBy({x:0,y:t})}function bo(e,t){let r=JP(null);return VP(()=>{let n=r.current;if(!n||e<0)return;let o=requestAnimationFrame(()=>{n.scrollChildIntoView(`${t}-${e}`)});return()=>cancelAnimationFrame(o)},[t,e]),r}function et(e){let t=re(),r=Ti(t),n=e.scroll?ne("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:De(e.palette),children:ne("box",{flexDirection:"column",overflow:"hidden",children:e.children},void 0,!1,void 0,this)},void 0,!1,void 0,this):e.children;return ne("box",{flexGrow:1,border:!0,borderStyle:ku,borderColor:e.borderColor??e.palette.border,title:e.title,titleColor:e.palette.primary,paddingLeft:t.pad,paddingRight:t.pad,paddingTop:r?0:t.pad,paddingBottom:r?0:t.pad,backgroundColor:e.palette.panel,flexDirection:"column",overflow:"hidden",children:n},void 0,!1,void 0,this)}function Cn(e){let{palette:t,label:r,value:n,tone:o="text"}=e,i=re(),s=o==="success"?t.success:o==="warning"?t.warning:o==="error"?t.error:o==="muted"?t.muted:t.text;return ne("box",{height:i.rowH,flexDirection:"row",overflow:"hidden",children:[ne("box",{width:14,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{flexGrow:1,overflow:"hidden",children:ne("text",{fg:s,wrapMode:"none",children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ec(e){let{palette:t,title:r,body:n,hint:o}=e;return ne("box",{height:o?5:4,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:ku,borderColor:t.borderActive,titleColor:t.primary,children:[ne("text",{fg:t.primary,children:r},void 0,!1,void 0,this),ne("text",{fg:t.text,wrapMode:"word",children:n},void 0,!1,void 0,this),o?ne("text",{fg:t.muted,wrapMode:"word",children:o},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var ku="rounded";var ve=A(()=>{ot();pr();ze();Re()});import{jsxDEV as se,Fragment as rv}from"@opentui/react/jsx-dev-runtime";function nv(e){let{palette:t,cfg:r,snap:n,google:o,profile:i,reveal:s,width:a}=e,c=qa(n,r?Object.keys(r.services):void 0),l=n?.proxy.running===!0,d=o?.adcAvailable===!0,g=a<Fa,f=le(r?.project.name||"local",g?18:22),h=le(i||n?.profile||"no profile",16),x=se(rv,{children:Zh({width:a,running:c.running,total:c.total,proxyOn:l,proxyAddress:n?.proxy.address??"",mcpOn:n?.mcp?.running===!0,adc:d,reveal:s}).filter((b)=>!b.hide&&b.label!=="").map((b)=>se(pe,{palette:t,label:b.label,tone:b.tone},b.label,!1,void 0,this))},void 0,!1,void 0,this),v=Ti(re());return se(je,{palette:t,backgroundColor:t.panel,ruled:!v,children:se("box",{height:g?2:1,flexDirection:"column",backgroundColor:t.panel,overflow:"hidden",children:[se("box",{height:1,flexDirection:"row",overflow:"hidden",children:[se(pe,{palette:t,label:Rt(),tone:"primary"},void 0,!1,void 0,this),se(pe,{palette:t,label:f,tone:"idle"},void 0,!1,void 0,this),se(pe,{palette:t,label:h,tone:"accent"},void 0,!1,void 0,this),g?null:se(rv,{children:[se("box",{flexGrow:1,backgroundColor:t.panel},void 0,!1,void 0,this),x]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g?se("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.panel,children:x},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function ov(e){let{palette:t,screen:r,width:n,onSelect:o}=e,i=Dr.map((a)=>({id:a.id,label:jh(a.label,n)})),s=Wh(r);return se(je,{palette:t,backgroundColor:t.element,children:se(Za,{palette:t,items:i,active:s,width:n,onPick:(a)=>{let c=Dr[a];if(c)o(c.id)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function iv(e){let{palette:t,overlay:r,query:n,onQuery:o,onSubmit:i}=e;if(r==="slash"||r==="palette"){let c=r==="slash"?"/":"> ";return se(je,{palette:t,backgroundColor:t.highlight,edge:"top",children:se("box",{height:1,backgroundColor:t.highlight,paddingLeft:1,flexDirection:"row",overflow:"hidden",children:[se("box",{width:2,flexShrink:0,children:se("text",{fg:t.primary,children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),se("box",{flexGrow:1,overflow:"hidden",children:se("input",{focused:!0,value:n,placeholder:r==="slash"?"start auth":"filter commands",onInput:o,onSubmit:()=>i(n),backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}let a=r==="leader"?[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"s",label:"services"},{key:"l",label:"logs"},{key:"t",label:"themes"},{key:"q",label:"quit"}]:[{key:"/",label:"command"},{key:"ctrl+p",label:"palette"},{key:"ctrl+x",label:"leader"},{key:"?",label:"help"}];return se(je,{palette:t,backgroundColor:t.element,edge:"top",children:se("box",{height:1,backgroundColor:t.element,overflow:"hidden",children:se(Ee,{palette:t,hints:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function sv(e){let{palette:t,screen:r,overlay:n,status:o,paused:i,errorOnly:s,width:a,copyKey:c}=e,l=Ti(re()),d=Math.max(18,Math.floor(a*0.42)),g=fo(Vy(r,n,c),d),f=ry(o);return se(je,{palette:t,backgroundColor:t.panel,edge:"top",ruled:!l,children:se("box",{height:1,backgroundColor:t.panel,overflow:"hidden",children:se(Be,{ruled:!1,palette:t,items:[{text:r,tone:"primary"},{text:i?"PAUSED":"LIVE",tone:i?"warning":"success"},...s?[{text:"ERROR+",tone:"error"}]:[],...o===""?[]:[{text:le(o,Math.max(16,a-d-28)),tone:f}]],hints:g},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Me(e){return se("box",{flexGrow:1,padding:1,overflow:"hidden",children:se(ec,{palette:e.palette,title:e.title,body:e.body,hint:e.hint},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function tc(e){return se("box",{flexGrow:1,padding:1,overflow:"hidden",children:se("text",{fg:e.palette.text,children:e.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function av(e){return se("box",{flexGrow:1,padding:1,flexDirection:"column",overflow:"hidden",children:[se("text",{fg:e.palette.error,children:e.title},void 0,!1,void 0,this),se("text",{fg:e.palette.text,wrapMode:"word",children:e.body},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var kt=A(()=>{ot();Re();ve();pr();ze()});function XP(){if(process.platform==="darwin")return[["pbcopy"]];if(process.platform==="win32")return[["clip"]];return[["wl-copy"],["xclip","-selection","clipboard"],["xsel","--clipboard","--input"]]}function QP(){return XP().filter((e)=>{let t=e[0];return typeof t==="string"&&Bun.which(t)!==null})}function ZP(e){return`\x1B]52;c;${Buffer.from(e,"utf8").toString("base64")}\x07`}function cv(){if(process.platform==="linux")return"install wl-clipboard (Wayland) or xclip (X11)";return"no clipboard helper found"}async function Cu(e){let t=QP(),r;for(let n of t)try{await tR(n,e);return}catch(o){r=o instanceof Error?o:Error(String(o))}if(process.platform!=="win32")try{await eR(e);return}catch(n){r=n instanceof Error?n:Error(String(n))}throw we(nt,"clipboard unavailable",r?`${cv()} (${r.message})`:cv())}async function eR(e){let t=ZP(e);try{await Bun.write("/dev/tty",t)}catch{if(!process.stderr.write(t))throw Error("terminal clipboard write failed")}}async function tR(e,t){let r=Bun.spawn(e,{stdin:"pipe",stdout:"ignore",stderr:"ignore"});r.stdin.write(t),await r.stdin.end();let n=await r.exited;if(n!==0)throw Error(`${e[0]} exited ${n}`)}var lv=A(()=>{_e()});function dv(e){return e==="slash"||e==="palette"||e==="config-edit"}function uv(e,t){return dr(e,t.keybinds.leader??"ctrl+x")}function pv(e,t){return dr(e,t.keybinds.command_list??"ctrl+p")}function fv(e,t){return dr(e,t.keybinds.command??"/")||e.name==="/"}function gv(e,t){return dr(e,t.keybinds.help??"?")||e.sequence==="?"}function mv(e,t){return dr(e,t.keybinds.search??"f")}function hv(e){let t=e.name??"";return t==="R"||e.shift===!0&&t.toLowerCase()==="r"}function yv(e){return e.ctrl===!0&&(e.name??"").toLowerCase()==="l"}function vv(e,t){if(t&&dr(e,t.keybinds.interrupt??"ctrl+c"))return!0;return e.ctrl===!0&&(e.name??"").toLowerCase()==="c"}function xv(e,t){return dr(e,t.keybinds.copy??lr())}function bv(e,t,r=rR){return t>0&&e-t<=r}function Or(e,t,r,n){return dr(e,t.keybinds[r]??n)}function rc(e){let t=(e.name??"").toLowerCase();return t==="pagedown"||e.ctrl===!0&&t==="d"&&!e.meta}function nc(e){let t=(e.name??"").toLowerCase();return t==="pageup"||e.ctrl===!0&&t==="u"&&!e.meta}var rR=2000;var wv=A(()=>{Vt()});import{jsxDEV as Ir}from"@opentui/react/jsx-dev-runtime";function Sv(e){let{palette:t,path:r,initialValue:n,error:o,termW:i,termH:s,textareaRef:a}=e;return Ir(Ze,{palette:t,title:"config buffer",bottomTitle:"ctrl+s save \xB7 esc discard \xB7 e still opens $EDITOR",termW:i,termH:s,preferW:88,preferH:28,gap:1,children:[Ir("box",{height:1,overflow:"hidden",children:Ir("text",{fg:t.muted,wrapMode:"none",children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this),Ir("textarea",{ref:a,focused:!0,initialValue:n,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this),o!==""?Ir("box",{height:2,overflow:"hidden",children:Ir("text",{fg:t.error,wrapMode:"word",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this):Ir("box",{height:1,overflow:"hidden",children:Ir("text",{fg:t.muted,children:"validate, then write. invalid YAML is not saved."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var kv=A(()=>{ve()});import{jsxDEV as _u}from"@opentui/react/jsx-dev-runtime";function Cv(e){let{palette:t,title:r,body:n,termW:o,termH:i}=e;return _u(Ze,{palette:t,title:r,bottomTitle:"enter confirm \xB7 esc stay",termW:o,termH:i,preferW:52,preferH:8,borderColor:t.warning,gap:1,children:[_u("text",{fg:t.text,wrapMode:"word",children:n},void 0,!1,void 0,this),_u(Ee,{palette:t,hints:[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var _v=A(()=>{ve()});import{jsxDEV as Bt}from"@opentui/react/jsx-dev-runtime";function Pv(e){let{palette:t,event:r,termW:n,termH:o,scrollRef:i}=e;if(!r)return null;let s=r.message.length>120||r.message.includes(`
|
|
617
|
+
`);return Bt(Ze,{palette:t,title:"log details",bottomTitle:"j/k scroll \xB7 esc close",termW:n,termH:o,preferW:s?84:72,preferH:s?22:14,gap:1,children:Bt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:Bt("box",{flexDirection:"column",overflow:"hidden",children:[Bt("text",{fg:t.text,wrapMode:"word",children:r.message},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`time ${r.timestamp}`},void 0,!1,void 0,this),Bt("text",{fg:He(r.service,t),children:`service ${r.service}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`source ${r.source}${r.stream?` / ${r.stream}`:""}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`level ${r.level}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`pid ${r.pid||"\u2014"}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`request ${r.request_id||"\u2014"}`},void 0,!1,void 0,this),Bt("text",{fg:t.muted,children:`identity ${r.identity||"\u2014"}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Rv=A(()=>{ve();ze()});import{jsxDEV as xe,Fragment as Tv}from"@opentui/react/jsx-dev-runtime";function dR(e){return[{key:"\u2190\u2192",label:"filter services"},{key:"1-9",label:"jump to source"},{key:"e",label:"ERROR+ only"},{key:"g",label:"jump to latest"},{key:"p",label:"pause stream"},{key:"z",label:"full-screen logs"},{key:"f",label:"search"},{key:"t",label:"timestamps"},{key:"m",label:"metadata"},{key:"w",label:"clip / wrap selected / wrap all"},{key:"j/k",label:"move and unfold"},{key:e,label:"copy visible logs"},{key:"/export",label:"write ~/.devctl/exports"},{key:"/exports",label:"open export folder"},{key:"ctrl+c \xD72",label:"quit"}]}function Fr(e){return e+iR}function Av(e){let t=Fr(Ru.length),r=Fr(Eu.length),n=Fr(e.logCount),o=Fr(Tu.length),i=Fr(Au.length),s=Lu+e.pad*2;if(e.stacked)return s+t+r+n+o+i+Pu+(cR-1)*e.gap;let a=Math.max(t,r),c=Math.max(o,i);return s+a+n+c+Pu+(lR-1)*e.gap}function uR(e){return Av(e)-Lu-e.pad*2}function pR(e){return e-Lu*2<oR}function Lv(e){let{palette:t,termW:r,termH:n,copyKey:o=lr(),scrollRef:i}=e,s=ur(re()),a=pR(r),c=s?0:1,l=s?0:1,d=dR(o),g={stacked:a,logCount:d.length,pad:c,gap:l},f=Av(g),h=uR(g);return xe(Ze,{palette:t,title:"help",bottomTitle:`${Rt()} \xB7 j/k scroll \xB7 esc close`,termW:r,termH:n,preferW:nR,preferH:f,gap:0,children:xe("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:xe("box",{height:h,flexDirection:"column",flexShrink:0,overflow:"hidden",gap:l,children:[a?xe(Tv,{children:[xe($r,{palette:t,title:"navigation",bindings:Ru},void 0,!1,void 0,this),xe($r,{palette:t,title:"services",bindings:Eu},void 0,!1,void 0,this),xe($r,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),xe($r,{palette:t,title:"commands",bindings:Tu},void 0,!1,void 0,this),xe($r,{palette:t,title:"display",bindings:Au},void 0,!1,void 0,this)]},void 0,!0,void 0,this):xe(Tv,{children:[xe(Ev,{palette:t,left:{title:"navigation",bindings:Ru},right:{title:"services",bindings:Eu}},void 0,!1,void 0,this),xe($r,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),xe(Ev,{palette:t,left:{title:"commands",bindings:Tu},right:{title:"display",bindings:Au}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),xe("box",{height:Pu,flexShrink:0,overflow:"hidden",paddingLeft:1,children:xe("text",{fg:t.muted,wrapMode:"none",children:"~/.devctl/tui.json \xB7 DEVCTL_TUI_CONFIG"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ev(e){let{palette:t,left:r,right:n}=e,o=Math.max(Fr(r.bindings.length),Fr(n.bindings.length));return xe("box",{height:o,flexDirection:"row",flexShrink:0,overflow:"hidden",gap:aR,children:[xe($r,{palette:t,title:r.title,bindings:r.bindings,height:o,stretch:!0},void 0,!1,void 0,this),xe($r,{palette:t,title:n.title,bindings:n.bindings,height:o,stretch:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $r(e){let{palette:t,title:r,bindings:n,stretch:o=!1}=e,i=e.height??Fr(n.length);return xe("box",{height:i,flexGrow:o?1:0,flexBasis:o?0:void 0,flexShrink:0,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:"rounded",borderColor:t.border,title:r,titleColor:t.accent,children:n.map((s)=>xe("box",{height:1,flexShrink:0,overflow:"hidden",paddingLeft:1,paddingRight:1,children:xe(fR,{palette:t,binding:s},void 0,!1,void 0,this)},`${s.key}-${s.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function fR(e){let{palette:t,binding:r}=e;return xe("box",{height:1,flexDirection:"row",overflow:"hidden",children:[xe("box",{width:sR,flexShrink:0,overflow:"hidden",children:xe("text",{fg:t.primary,wrapMode:"none",children:r.key},void 0,!1,void 0,this)},void 0,!1,void 0,this),xe("box",{flexGrow:1,overflow:"hidden",children:xe("text",{fg:t.text,wrapMode:"none",children:r.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var nR=78,oR=56,iR=2,Lu=2,Pu=1,Du=8,sR=16,aR=2,cR=6,lR=4,Ru,Eu,Tu,Au;var Dv=A(()=>{ot();ve();pr();Vt();Ru=[{key:"tab",label:"next screen"},{key:"1-9,0",label:"jump to screen"},{key:"s/l/a/p/d/c/u",label:"letter jump (config, setup)"},{key:"j/k",label:"move selection"},{key:"esc",label:"back / close"}],Eu=[{key:"enter",label:"start profile or open"},{key:"space",label:"multi-select"},{key:"n",label:"start"},{key:"x",label:"stop"},{key:"r",label:"refresh"},{key:"R",label:"restart"}];Tu=[{key:"/",label:"slash command"},{key:"ctrl+p",label:"command palette"},{key:"ctrl+x",label:"leader chord"},{key:"/settings",label:"preferences \xB7 MCP page"},{key:"/themes",label:"preview themes"},{key:"/mcp",label:"agent MCP server"}],Au=[{key:"ctrl+=",label:"larger"},{key:"ctrl+-",label:"smaller"},{key:"?",label:"this overlay"}]});import{jsxDEV as Mv}from"@opentui/react/jsx-dev-runtime";function Ov(e){let{palette:t,termW:r,termH:n}=e,o=Su();return Mv(Ze,{palette:t,title:"leader",termW:r,termH:n,preferW:68,preferH:5,anchor:"bottom",children:Mv(Ee,{palette:t,hints:o},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Iv=A(()=>{Re();ve()});import{jsxDEV as $v}from"@opentui/react/jsx-dev-runtime";function Fv(e){let{palette:t,items:r,selected:n,termW:o,termH:i,onIndex:s,onPick:a}=e,c=qy(r),l=go(o,i,64,18,"center",!ur(re()));return $v(Ze,{palette:t,title:"commands",bottomTitle:"enter select \xB7 esc close",termW:o,termH:i,preferW:64,preferH:18,children:$v("select",{height:Math.max(4,l.height-3),options:c,selectedIndex:n,showDescription:!0,showSelectionIndicator:!0,wrapSelection:!0,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,selectedBackgroundColor:t.highlight,selectedTextColor:t.primary,descriptionColor:t.muted,selectedDescriptionColor:t.accent,onChange:(d)=>s(d),onSelect:(d,g)=>{let f=g?.value;if(typeof f==="string"&&f!=="")a(f)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Nv=A(()=>{ot();Re();ve();pr()});import{jsxDEV as I}from"@opentui/react/jsx-dev-runtime";function Mu(e,t){switch(e){case"completed":return{icon:"\u2713",label:"Completed",tone:"success",color:t.success};case"failed":return{icon:"\u2717",label:"Failed",tone:"error",color:t.error};case"unhealthy":return{icon:"\u26A0",label:"Unhealthy",tone:"warning",color:t.warning};case"active":return{icon:"\u25CF",label:"In progress",tone:"primary",color:t.primary};default:return{icon:"\u25CB",label:"Queued",tone:"muted",color:t.muted}}}function gR(e,t,r,n){if(t!=="")return{icon:"\u2717",label:"Failed",tone:"error",color:n.error};if(!e)return{icon:"\u2713",label:"Finished",tone:"success",color:n.success};if(r==="unhealthy")return{icon:"\u26A0",label:"Waiting on health",tone:"warning",color:n.warning};return{icon:"\u25CF",label:"Running",tone:"primary",color:n.primary}}function Hv(e){return I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:I("text",{wrapMode:"none",children:[I("span",{fg:e.palette.primary,children:e.label.toUpperCase()},void 0,!1,void 0,this),e.detail?I("span",{fg:e.palette.muted,children:` ${e.detail}`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function jv(e){let{palette:t,plan:r,snap:n,busy:o,failed:i,kind:s,termW:a=80,termH:c=24,scrollRef:l,initiallyRunning:d=[],onDismiss:g}=e,f=new Set(d),h=r.waves.map((ce,Ie)=>({wave:ce.filter((Ke)=>!f.has(Ke)),waveIdx:Ie})).filter(({wave:ce})=>ce.length>0),x=Ny(r,n,s),v=r.waves[x.currentWaveIndex]??[],b=Ni(v,n,s),P=Mu(b,t),S=gR(o,i,b,t),N=jy(s,o,i,r.profile),U=By(o,i),y=i?t.inverse:t.text,k=i?t.error:t.element,m=Math.min(92,Math.max(40,a-8)),_=m>=82?22:m>=66?17:13,F=12,Q=9,ae=m>=56,be=m>=72,Je=m<72||r.waves.length>3,Ue=r.profile?`PROFILE ${r.profile}`:s.toUpperCase();return I(Ze,{palette:t,title:N,bottomTitle:"enter close \xB7 esc hide (operation continues)",termW:a,termH:c,preferW:98,preferH:28,borderColor:S.color,gap:0,children:[I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[I(pe,{palette:t,label:`${S.icon} ${S.label.toUpperCase()}`,tone:S.tone},void 0,!1,void 0,this),I("box",{paddingLeft:1,flexGrow:1,overflow:"hidden",children:I("text",{fg:t.text,wrapMode:"none",children:Ue},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(pe,{palette:t,label:`${x.ready}/${x.total} READY`,tone:x.isComplete?"success":"info"},void 0,!1,void 0,this),I(pe,{palette:t,label:`WAVE ${Math.min(x.currentWaveIndex+1,Math.max(1,x.totalWaves))}/${Math.max(1,x.totalWaves)}`,tone:P.tone},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{height:2,flexDirection:"column",overflow:"hidden",flexShrink:0,paddingLeft:1,paddingRight:1,children:[I("box",{height:1,flexDirection:"row",overflow:"hidden",children:[I("text",{wrapMode:"none",children:[I("span",{fg:t.muted,children:"PROGRESS "},void 0,!1,void 0,this),I("span",{fg:S.color,children:`[${x.progressBar}]`},void 0,!1,void 0,this),I("span",{fg:t.text,children:` ${x.percent}%`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{flexGrow:1},void 0,!1,void 0,this),I("text",{wrapMode:"none",children:I("span",{fg:P.color,children:`${P.icon} ${P.label}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I("box",{height:1,overflow:"hidden",children:I("text",{fg:t.muted,wrapMode:"none",children:o?s==="stop"?"Dependents stop first; each wave waits for the previous wave.":"Each wave waits until its services are healthy before the next wave starts.":U.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I(Hv,{palette:t,label:"Pipeline",detail:`${r.waves.length} execution wave${r.waves.length===1?"":"s"}`},void 0,!1,void 0,this),I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:r.waves.map((ce,Ie)=>{let Ke=Ni(ce,n,s),ue=Mu(Ke,t),Se=Je?`W${Ie+1} ${ue.icon} ${ce.length}`:`W${Ie+1} ${ue.icon} ${ue.label} \xB7 ${ce.length}`;return I("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:[I(pe,{palette:t,label:Se,tone:ue.tone},void 0,!1,void 0,this),Ie<r.waves.length-1?I("box",{width:3,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:" \u2500\u25BA"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},`step-${Ie}`,!0,void 0,this)})},void 0,!1,void 0,this),(r.blockers??[]).length>0?I("box",{minHeight:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:I("text",{fg:t.error,wrapMode:"word",children:`BLOCKED ${r.blockers?.map((ce)=>`${ce.name}: ${ce.message}`).join(" \xB7 ")}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,d.length>0?I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,paddingLeft:1,children:I("text",{wrapMode:"none",children:[I("span",{fg:t.success,children:"\u2713 ALREADY READY"},void 0,!1,void 0,this),I("span",{fg:t.muted,children:` ${d.join(", ")}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this):null,I(Hv,{palette:t,label:"Wave details",detail:"live process and health state"},void 0,!1,void 0,this),I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:[I("box",{width:2,flexShrink:0},void 0,!1,void 0,this),I("box",{width:_,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("SERVICE",_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:12,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("STATE",12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ae?I("box",{width:9,flexShrink:0,overflow:"hidden",children:I("text",{fg:t.muted,children:Y("PORT",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,be?I("box",{flexGrow:1,overflow:"hidden",children:I("text",{fg:t.muted,children:"DETAIL"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),I("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:I("box",{flexDirection:"column",overflow:"hidden",gap:1,children:h.map(({wave:ce,waveIdx:Ie})=>{let Ke=Ni(ce,n,s),ue=Mu(Ke,t),Se=`${Hy(s,Ie,Ke)} \xB7 ${ce.length} service${ce.length===1?"":"s"}`;return I("box",{border:!0,borderStyle:"rounded",borderColor:ue.color,title:Se,titleColor:ue.color,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ce.map((Ce)=>{let W=n?.services[Ce],$e=Ot(W),lt=Fy(Ce,r,n,s),Fe=Ce===i||$e==="FAILED",_t=$e==="UNHEALTHY",dt=$e==="HEALTHY"||s==="stop"&&$e==="STOPPED",zt=kn(W),ut=Fe?"\u2717":dt?"\u2713":_t?"\u26A0":$e==="STARTING"||$e==="RUNNING"||$e==="STOPPING"||$e==="RESTARTING"?"\u25CF":"\u25CB",Xt=Fe?t.error:Pe(t,$e),pt=Fe?t.error:_t?t.warning:dt?t.success:t.muted;return I("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[I("box",{width:2,flexShrink:0,overflow:"hidden",children:I("text",{fg:Xt,children:ut},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:_,flexShrink:0,overflow:"hidden",children:I("text",{fg:He(Ce,t),wrapMode:"none",children:Y(Ce,_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{width:12,flexShrink:0,overflow:"hidden",children:I("text",{fg:Pe(t,$e),wrapMode:"none",children:Y($e,12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ae?I("box",{width:9,flexShrink:0,overflow:"hidden",children:I("text",{fg:zt?t.info:t.muted,wrapMode:"none",children:Y(zt?`:${zt}`:"\u2014",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,be?I("box",{flexGrow:1,overflow:"hidden",children:I("text",{fg:pt,wrapMode:"none",children:lt},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},Ce,!0,void 0,this)})},`wave-card-${Ie}`,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),I("box",{height:3,flexShrink:0,flexDirection:"column",backgroundColor:k,border:["top"],borderStyle:"single",borderColor:S.color,paddingLeft:1,paddingRight:1,overflow:"hidden",onMouseDown:g,children:[I("text",{fg:y,wrapMode:"none",children:U.primary},void 0,!1,void 0,this),I("text",{fg:i?t.inverse:t.muted,wrapMode:"none",children:U.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Bv=A(()=>{Re();ve();ze()});import{jsxDEV as Yt}from"@opentui/react/jsx-dev-runtime";function Wv(e){let{palette:t,route:r,termW:n,termH:o,scrollRef:i}=e;if(!r)return null;return Yt(Ze,{palette:t,title:r.name,bottomTitle:"j/k scroll \xB7 esc close",termW:n,termH:o,preferW:78,preferH:16,gap:1,children:Yt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:Yt("box",{flexDirection:"column",overflow:"hidden",children:[Yt("text",{fg:t.muted,children:`auth ${r.authType||"none"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`identity ${r.identityType||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`account ${r.serviceAccount||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`audience ${r.audience||"\u2014"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`match host ${r.matchHost||"*"}`},void 0,!1,void 0,this),Yt("text",{fg:t.muted,children:`match path ${r.matchPath||"*"}`},void 0,!1,void 0,this),Yt("text",{fg:t.text,wrapMode:"word",children:`upstream ${r.upstream}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Gv=A(()=>{ve()});import{jsxDEV as At}from"@opentui/react/jsx-dev-runtime";function Kv(e){let{palette:t,items:r,query:n,selected:o,onQuery:i,onSubmit:s}=e,a=Jy(o,Uv,r.length),c=r.slice(a,a+Uv),l=Math.max(c.length,1),d=Sn(r,o);return At("box",{height:l+3,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,titleColor:t.primary,backgroundColor:t.panel,title:"commands",flexDirection:"column",overflow:"hidden",children:[c.length===0?At("box",{height:1,paddingLeft:1,overflow:"hidden",children:At("text",{fg:t.muted,children:"no matching command"},void 0,!1,void 0,this)},void 0,!1,void 0,this):c.map((g)=>{let f=g.name===d?.name;return At("box",{height:1,flexDirection:"row",overflow:"hidden",paddingLeft:1,paddingRight:1,backgroundColor:f?t.highlight:t.panel,children:[At("box",{width:14,flexShrink:0,overflow:"hidden",children:At("text",{fg:f?t.primary:t.text,wrapMode:"none",children:`${f?"\u203A":" "} /${g.name}`},void 0,!1,void 0,this)},void 0,!1,void 0,this),At("box",{flexGrow:1,overflow:"hidden",children:At("text",{fg:f?t.accent:t.muted,wrapMode:"none",children:g.desc},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},g.name,!0,void 0,this)}),At("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.highlight,paddingLeft:1,children:[At("box",{width:2,flexShrink:0,children:At("text",{fg:t.primary,children:"/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),At("box",{flexGrow:1,overflow:"hidden",children:At("input",{focused:!0,value:n,placeholder:"start auth",onInput:i,onSubmit:()=>s(),backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Uv=8;var qv=A(()=>{Re()});import{jsxDEV as Yv}from"@opentui/react/jsx-dev-runtime";function zv(e){let{palette:t,themeName:r,selected:n,termW:o,termH:i,onIndex:s,onPreview:a,onPick:c}=e,l=ht.map((g)=>({name:g===r?`${g} (active)`:g,description:g===r?`${zd[g]} \xB7 current`:zd[g],value:g})),d=go(o,i,Vv,Jv,"center",!ur(re()));return Yv(Ze,{palette:t,title:"/themes",bottomTitle:"enter save \xB7 esc revert",termW:o,termH:i,preferW:Vv,preferH:Jv,children:Yv("select",{height:Math.max(4,d.height-3),options:l,selectedIndex:n,showDescription:!0,showSelectionIndicator:!0,wrapSelection:!0,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,selectedBackgroundColor:t.highlight,selectedTextColor:t.primary,descriptionColor:t.muted,selectedDescriptionColor:t.accent,onChange:(g)=>{s(g);let f=ht[g];if(f)a(f)},onSelect:(g,f)=>{let h=f?.value;if(typeof h==="string"&&h!=="")c(h)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Vv=52,Jv=22;var Xv=A(()=>{ot();Re();ve();pr();ze()});import{jsxDEV as Ge}from"@opentui/react/jsx-dev-runtime";function oc(e){let{palette:t,title:r,tone:n="muted",children:o}=e,i=n==="success"?t.success:n==="warning"?t.warning:n==="error"?t.error:t.border;return Ge("box",{border:!0,borderStyle:"rounded",borderColor:i,title:r,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Qv(e){let{palette:t,cfg:r,google:n,identity:o}=e;if(!n&&!o)return Ge(tc,{palette:t,label:"Checking Application Default Credentials\u2026"},void 0,!1,void 0,this);let i=mR(r,o),s=o?.user||n?.userEmail||"",{project:a,source:c}=xo(r,o,n),l=o?.adc??n?.adcAvailable===!0,d=o?.iap??(r?.proxy.routes??[]).some((v)=>v.auth.type.toLowerCase()==="iap"),g=i.filter((v)=>v.inactive!==!0),f=g.some((v)=>v.ok===!0),h=g.some((v)=>v.ok===!1),x=f?"AVAILABLE":h?"UNAVAILABLE":g.length>0?"NOT PROBED":i.length>0?"not required":"not configured";return Ge(et,{palette:t,title:"identity",scroll:!0,children:[Ge(oc,{palette:t,title:"Google identity",tone:l?"success":"warning",children:[Ge(Cn,{palette:t,label:"user",value:s||"(unknown)"},void 0,!1,void 0,this),Ge(Cn,{palette:t,label:"project",value:a||"(unset)"},void 0,!1,void 0,this),Ge(Cn,{palette:t,label:"source",value:c||"\u2014"},void 0,!1,void 0,this),Ge(Cn,{palette:t,label:"ADC",value:l?"\u2713 available":"\u2717 missing",tone:l?"success":"error"},void 0,!1,void 0,this),Ge(Cn,{palette:t,label:"gcloud",value:n?.gcloudInstalled?"\u2713 installed":"\u2717 not installed",tone:n?.gcloudInstalled?"success":"error"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(oc,{palette:t,title:`Service accounts (${i.length})`,tone:g.length===0?"muted":f?"success":"warning",children:[i.length===0?Ge("text",{fg:t.muted,wrapMode:"word",children:"none configured \u2014 identities come from config, never hard-coded"},void 0,!1,void 0,this):i.map((v)=>Ge("text",{fg:v.inactive?t.muted:v.ok===!0?t.success:v.ok===!1?t.error:t.text,wrapMode:"none",children:`${v.inactive?"\u2013":v.ok===!0?"\u2713":v.ok===!1?"\u2717":"\u25CB"} ${v.email}${v.inactive?" \u2014 inactive (route auth is none)":""}`},v.email,!1,void 0,this)),Ge("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Ge(Cn,{palette:t,label:"impersonation",value:x,tone:f?"success":g.length>0?"warning":"muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(oc,{palette:t,title:"IAP",tone:d?"success":"muted",children:[Ge("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:Ge(pe,{palette:t,label:d?"routes present":"no IAP routes",tone:d?"success":"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),d?Ge("text",{fg:t.muted,wrapMode:"word",children:"each route needs its own audience"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),!l?Ge(oc,{palette:t,title:"ADC unavailable",tone:"warning",children:[Ge("text",{fg:t.text,wrapMode:"word",children:"Local services still start. Cloud identity, impersonation, and IAP need ADC."},void 0,!1,void 0,this),Ge("text",{fg:t.muted,wrapMode:"word",children:"run `gcloud auth application-default login` or /auth"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)}function mR(e,t){let r=new Map((e?Il(e):[]).map((i)=>[i.email,i.active])),n=t?.service_account_status??{};return[...new Set([...r.keys(),...Object.keys(n)])].sort((i,s)=>i.localeCompare(s)).map((i)=>{let s=n[i]??"unknown",a=r.get(i)===!1;return{email:i,inactive:a,ok:a||s==="unknown"?void 0:s==="available"}})}var Zv=A(()=>{kt();Re();ve();nn()});import{jsxDEV as ct}from"@opentui/react/jsx-dev-runtime";function ex(e){let{palette:t,credentials:r}=e;if(!r)return ct(tc,{palette:t,label:"Reading credential store\u2026"},void 0,!1,void 0,this);let n=r.entries.filter((i)=>i.valid).length,o=r.entries.length-n;return ct(et,{palette:t,title:"credentials",scroll:!0,children:[ct("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[ct(pe,{palette:t,label:`backend: ${r.backend}`,tone:"info"},void 0,!1,void 0,this),r.entries.length>0?ct(pe,{palette:t,label:`${n} valid`,tone:"success"},void 0,!1,void 0,this):null,o>0?ct(pe,{palette:t,label:`${o} expired`,tone:"warning"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ct("text",{fg:t.muted,wrapMode:"word",children:"Tokens stay in the OS keychain or ~/.devctl/credentials (0600). They are never shown here."},void 0,!1,void 0,this),ct("box",{height:1,flexShrink:0},void 0,!1,void 0,this),r.entries.length===0?ct("text",{fg:t.muted,children:"no cached credentials"},void 0,!1,void 0,this):ct("box",{flexDirection:"column",overflow:"hidden",gap:1,children:r.entries.map((i)=>ct("box",{border:!0,borderStyle:"rounded",borderColor:i.valid?t.success:t.warning,title:i.identity,titleColor:i.valid?t.success:t.warning,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[ct("text",{wrapMode:"none",children:[ct("span",{fg:i.valid?t.success:t.warning,children:i.valid?"\u2713 valid":"\u2717 expired"},void 0,!1,void 0,this),ct("span",{fg:t.muted,children:` \xB7 expires ${i.expires_at}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ct("text",{fg:t.muted,wrapMode:"none",children:`audience: ${i.audience||"(none)"}`},void 0,!1,void 0,this)]},`${i.identity}|${i.audience}`,!0,void 0,this))},void 0,!1,void 0,this),ct(ec,{palette:t,title:"Actions",body:"Use /refresh to mint again or auth refresh on the CLI. Invalidate clears the store without printing tokens.",hint:"/refresh /auth"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var tx=A(()=>{kt();ve()});function rx(e){let t=Object.keys(e.services).length,r=Object.keys(e.profiles).length,n=e.proxy.routes.length,o=[{text:e.project.name||"unnamed",tone:"primary"},{text:`schema ${e.version}`,tone:"muted"},{text:`${t} service${t===1?"":"s"}`,tone:t>0?"info":"idle"},{text:`${r} profile${r===1?"":"s"}`,tone:r>0?"info":"idle"},{text:e.proxy.enabled?"proxy on":"proxy off",tone:e.proxy.enabled?"success":"idle"}];if(n>0)o.push({text:`${n} route${n===1?"":"s"}`,tone:"info"});return o}function nx(e,t){return[{label:"path",value:e.configPath||"\u2014"},{label:"repo",value:e.repoRoot||"\u2014"},{label:"devctl",value:t},{label:"schema",value:String(e.version)}]}function ox(e){return[{label:"project",value:e.google.project_id||"(unset)",tone:e.google.project_id?"text":"muted"},{label:"region",value:e.google.region||"(unset)",tone:e.google.region?"text":"muted"}]}function ix(e){let t=hR(e);return[{label:"exit",value:t,tone:t==="ask on quit"?"warning":"text"},{label:"grace",value:`${e.shutdown.grace_seconds}s`},{label:"refresh",value:`${ys(e.auth)}s`},{label:"env",value:e.environment.sources.join(", ")||"\u2014",tone:e.environment.sources.length>0?"text":"muted"},{label:"theme",value:e.ui.theme||"system"}]}function sx(e){let t=e.logs.persistence;return[{label:"memory",value:`${e.logs.max_memory_events} events`},{label:"persist",value:t.enabled?t.directory:"off",tone:t.enabled?"text":"muted"},{label:"keep",value:t.enabled?`${t.retention_days}d \xB7 ${t.max_session_logs||"\u221E"} sessions`:"\u2014"}]}function ax(e){return[{label:"listen",value:Yr(e.proxy.listen),tone:e.proxy.enabled?"text":"muted"},{label:"token",value:xR(e),tone:e.proxy.token_endpoint.enabled?"text":"muted"}]}function cx(e){return Object.keys(e.services).sort().map((t)=>{let r=e.services[t]??Hn();return{name:t,extends:r.extends||"\u2014",command:Ya(r),ports:Hi(r),identity:Xa(r),health:za(r),depends:r.dependencies.join(", ")||"\u2014",restart:Qa(r)}})}function lx(e){return e.proxy.routes.map((t)=>({name:t.name||t.match.host||"(unnamed)",match:bR(t),upstream:t.upstream.url||"\u2014",auth:t.auth.type||"none",identity:wR(t)}))}function dx(e){return Object.keys(e.profiles).sort().map((t)=>{let r=e.profiles[t],n=Object.keys(r?.environment??{}).sort();return{name:t,services:r?.services.join(", ")||"\u2014",env:n.length>0?n.join(", "):"\u2014"}})}function ux(e){return Object.keys(e.templates).sort().map((t)=>({name:t,summary:SR(e.templates[t])}))}function px(e){let t=e.doctor.tools.map((i)=>i.name||i.command).filter((i)=>i!==""),r=e.plugins.map((i)=>i.path).filter((i)=>i!==""),n=Object.keys(e.ui.keymap),o=[...e.secrets.extra_markers,...e.secrets.extra_patterns];return[{label:"doctor",value:t.join(", ")||"\u2014",tone:t.length>0?"text":"muted"},{label:"plugins",value:r.join(", ")||"\u2014",tone:r.length>0?"text":"muted"},{label:"keymap",value:n.length>0?`${n.length} override${n.length===1?"":"s"}`:"defaults",tone:n.length>0?"text":"muted"},{label:"secrets",value:o.length>0?o.join(", "):"defaults",tone:o.length>0?"text":"muted"}]}function hR(e){if(e.shutdown.stop_services_on_exit===void 0)return"ask on quit";return e.shutdown.stop_services_on_exit?"stop services":"detach"}function fx(e){let t=e.reduce((r,n)=>Math.max(r,n.name.length),0);return Math.min(vR,Math.max(yR,t))}function xR(e){let t=e.proxy.token_endpoint;if(!t.enabled)return"off";let r=t.host===""?"127.0.0.1":t.host;if(t.port===0)return r;return`${r}:${t.port}`}function bR(e){let t=e.match.host||"*",r=e.match.path;if(r==="")return t;return`${t}${r.startsWith("/")?r:`/${r}`}`}function wR(e){if(e.auth.identity.service_account!=="")return e.auth.identity.service_account;if(e.auth.service_account!=="")return e.auth.service_account;return e.auth.identity.type||"user"}function SR(e){if(!e)return"empty";let t=[];if(e.health.type!=="")t.push(`health ${e.health.type}`);if(e.restart.policy!=="")t.push(`restart ${e.restart.policy}`);if(e.logs.stdout||e.logs.stderr)t.push("logs");return t.join(" \xB7 ")||"empty"}var yR=8,vR=20,gx=80,wo=10;var mx=A(()=>{St();Re()});import{jsxDEV as E}from"@opentui/react/jsx-dev-runtime";function vx(e){let{palette:t,cfg:r,width:n}=e,o=re();if(!r)return E(Me,{palette:t,title:"No configuration",body:"Create .devctl/config.yaml or run setup."},void 0,!1,void 0,this);let i=Math.max(wo+8,n-6-o.pad*2),s=i>=gx,a=s?Math.floor((i-hx)/2):i,c=cx(r),l=lx(r),d=dx(r),g=ux(r);return E(et,{palette:t,title:`config ${r.project.name||"unnamed"}`,children:[E(Be,{palette:t,items:rx(r)},void 0,!1,void 0,this),E("box",{flexGrow:1,overflow:"hidden",children:E("scrollbox",{ref:e.scrollRef,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:E("box",{flexDirection:"column",overflow:"hidden",gap:yx,children:[E(Ou,{wide:s,left:E(gr,{palette:t,title:"project",children:E(So,{palette:t,facts:nx(r,at),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:E(gr,{palette:t,title:"google",children:E(So,{palette:t,facts:ox(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E(Ou,{wide:s,left:E(gr,{palette:t,title:"runtime",children:E(So,{palette:t,facts:ix(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:E(gr,{palette:t,title:"logs",children:E(So,{palette:t,facts:sx(r),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E(gr,{palette:t,title:`proxy ${r.proxy.enabled?"enabled":"disabled"}`,children:[E(So,{palette:t,facts:ax(r),width:i},void 0,!1,void 0,this),E(CR,{palette:t,routes:l,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this),E(gr,{palette:t,title:`services ${c.length}`,children:E(kR,{palette:t,rows:c,width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),E(Ou,{wide:s,left:E(gr,{palette:t,title:`profiles ${d.length}`,children:E(_R,{palette:t,rows:d,width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:E(gr,{palette:t,title:`templates ${g.length}`,children:E(PR,{palette:t,rows:g,empty:"no templates",width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E(gr,{palette:t,title:"extras",children:E(So,{palette:t,facts:px(r),width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E(je,{palette:t,backgroundColor:t.element,edge:"top",children:E(Ee,{palette:t,hints:[{key:"v",label:"validate/save buffer"},{key:"e",label:"open in $EDITOR"},{key:"/reload",label:"re-read .devctl after editing"},{key:"j/k",label:"scroll"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ou(e){let{wide:t,left:r,right:n}=e;if(!t)return E("box",{flexDirection:"column",overflow:"hidden",gap:yx,flexShrink:0,children:[r,n]},void 0,!0,void 0,this);return E("box",{flexDirection:"row",overflow:"hidden",gap:hx,flexShrink:0,children:[E("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:r},void 0,!1,void 0,this),E("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:n},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function gr(e){let{palette:t,title:r,children:n}=e;return E("box",{border:!0,borderStyle:"rounded",borderColor:t.border,title:r,titleColor:t.accent,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",flexShrink:0,children:n},void 0,!1,void 0,this)}function So(e){let{palette:t,facts:r,width:n}=e,o=Math.max(4,n-wo-4);return E("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((i)=>E("box",{height:1,flexDirection:"row",overflow:"hidden",children:[E("box",{width:wo,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.muted,wrapMode:"none",children:Y(i.label,wo)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E("box",{width:o,flexShrink:0,overflow:"hidden",children:E("text",{fg:TR(t,i.tone),wrapMode:"none",children:Y(i.value,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},i.label,!0,void 0,this))},void 0,!1,void 0,this)}function kR(e){let{palette:t,rows:r,width:n}=e;if(r.length===0)return E(ic,{palette:t,text:"no services"},void 0,!1,void 0,this);let o=fx(r),i=Math.max(8,n-o-6);return E("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>E("box",{height:1,flexDirection:"row",overflow:"hidden",children:[E("box",{width:o,flexShrink:0,overflow:"hidden",children:E("text",{fg:He(s.name,t),wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E("box",{width:i,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.text,wrapMode:"none",children:le(RR(s),i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},s.name,!0,void 0,this))},void 0,!1,void 0,this)}function CR(e){let{palette:t,routes:r,width:n}=e;if(r.length===0)return E(ic,{palette:t,text:"no routes"},void 0,!1,void 0,this);let o=Math.min(wo+4,Math.max(8,...r.map((s)=>s.name.length))),i=Math.max(8,n-o-6);return E("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>E("box",{height:1,flexDirection:"row",overflow:"hidden",children:[E("box",{width:o,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.primary,wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E("box",{width:i,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.text,wrapMode:"none",children:le(ER(s),i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${s.name}-${s.match}`,!0,void 0,this))},void 0,!1,void 0,this)}function _R(e){let{palette:t,rows:r,width:n}=e;if(r.length===0)return E(ic,{palette:t,text:"no profiles"},void 0,!1,void 0,this);let o=Math.min(12,Math.max(8,...r.map((s)=>s.name.length))),i=Math.max(8,n-o-6);return E("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((s)=>E("box",{height:1,flexDirection:"row",overflow:"hidden",children:[E("box",{width:o,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.primary,wrapMode:"none",children:Y(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E("box",{width:i,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.text,wrapMode:"none",children:le(s.env==="\u2014"?s.services:`${s.services} env ${s.env}`,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},s.name,!0,void 0,this))},void 0,!1,void 0,this)}function PR(e){let{palette:t,rows:r,empty:n,width:o}=e;if(r.length===0)return E(ic,{palette:t,text:n},void 0,!1,void 0,this);let i=Math.min(14,Math.max(8,...r.map((a)=>a.name.length))),s=Math.max(8,o-i-6);return E("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:r.map((a)=>E("box",{height:1,flexDirection:"row",overflow:"hidden",children:[E("box",{width:i,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.text,wrapMode:"none",children:Y(a.name,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E("box",{width:s,flexShrink:0,overflow:"hidden",children:E("text",{fg:t.muted,wrapMode:"none",children:le(a.summary,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},a.name,!0,void 0,this))},void 0,!1,void 0,this)}function ic(e){return E("box",{height:1,overflow:"hidden",children:E("text",{fg:e.palette.muted,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function RR(e){let t=e.extends==="\u2014"?"":` ${e.extends}`;return` ${e.ports} ${e.identity} ${e.health} ${e.restart} \u2190 ${e.depends}${t}`}function ER(e){return` ${e.auth} ${e.identity} ${e.match} \u2192 ${e.upstream}`}function TR(e,t){if(t==="success")return e.success;if(t==="warning")return e.warning;if(t==="error")return e.error;if(t==="muted")return e.muted;return e.text}var hx=1,yx=1;var xx=A(()=>{kt();mx();ot();Re();ve();ze()});import{useRef as AR}from"react";import{jsxDEV as fe}from"@opentui/react/jsx-dev-runtime";function sc(e){let{palette:t,names:r,snap:n,selected:o,checked:i,width:s,onOpen:a,onSelectIndex:c,onToggle:l}=e,d=re(),g=AR(!1),f=new Set(i),h=mu(s),x=gu(s),v=fu(s),b=Gh(s);return fe("box",{flexDirection:"column",flexGrow:1,overflow:"hidden",children:[fe("box",{height:1,flexDirection:"row",overflow:"hidden",children:[fe(vt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),fe(vt,{width:4,fg:t.accent,text:"sel"},void 0,!1,void 0,this),fe(vt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),fe(vt,{width:b,fg:t.muted,text:"name"},void 0,!1,void 0,this),fe(vt,{width:yt,fg:t.muted,text:""},void 0,!1,void 0,this),fe(vt,{width:Jt,fg:t.muted,text:"state"},void 0,!1,void 0,this),v?fe(vt,{width:fr,fg:t.muted,text:"health"},void 0,!1,void 0,this):null,x?fe(vt,{width:Ma,fg:t.muted,text:"port"},void 0,!1,void 0,this):null,h?fe(vt,{width:Mr,fg:t.muted,text:"pid"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),r.map((P,S)=>{let N=n?.services[P],U=Ot(N),y=N?.health??"UNKNOWN",k=f.has(P),m=S===o,_=k?"[x]":"[ ]",F=m?"\u203A":" ";return fe("box",{height:d.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:m?t.highlight:k?t.element:void 0,onMouseDown:()=>{if(g.current)return;if(m){a(P);return}c(S)},children:[fe("box",{width:2,flexShrink:0,children:fe("text",{fg:t.primary,children:F},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{width:4,flexShrink:0,onMouseDown:()=>{g.current=!0,l?.(P),setTimeout(()=>{g.current=!1},0)},children:fe("text",{fg:LR(t,k,m),children:_},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe("box",{width:2,flexShrink:0,children:fe("text",{fg:Pe(t,U),children:Tt(U)},void 0,!1,void 0,this)},void 0,!1,void 0,this),fe(vt,{width:b,fg:m?t.primary:He(P,t),text:Y(P,b)},void 0,!1,void 0,this),fe(vt,{width:yt,fg:t.muted,text:""},void 0,!1,void 0,this),fe(vt,{width:Jt,fg:Pe(t,U),text:U},void 0,!1,void 0,this),v?fe(vt,{width:fr,fg:Pe(t,y),text:y},void 0,!1,void 0,this):null,x?fe(vt,{width:Ma,fg:t.text,text:kn(N)},void 0,!1,void 0,this):null,h?fe(vt,{width:Mr,fg:t.text,text:N?.pid?String(N.pid):""},void 0,!1,void 0,this):null]},P,!0,void 0,this)})]},void 0,!0,void 0,this)}function ac(e){let{palette:t,checked:r,idle:n,profileName:o}=e,i=r.length;if(i>0)return fe(Be,{palette:t,items:[{text:`${i} selected`,tone:"primary"}],hints:[{key:"space",label:"unmark"},{key:"*",label:"all"},{key:"-",label:"none"},{key:"n",label:"start these"},{key:"x",label:"stop these"}]},void 0,!1,void 0,this);if(n)return fe(Be,{palette:t,items:[{text:"none started",tone:"idle"}],hints:[{key:"space",label:"select"},{key:"enter",label:o?`start ${o}`:"open"},{key:"n",label:"start"}]},void 0,!1,void 0,this);return fe(Be,{palette:t,items:[{text:"running",tone:"success"}],hints:[{key:"space",label:"select"},{key:"n",label:"start"},{key:"x",label:"stop"}]},void 0,!1,void 0,this)}function LR(e,t,r){if(t)return e.success;if(r)return e.primary;return e.muted}function vt(e){return fe("box",{width:e.width,flexShrink:0,overflow:"hidden",children:fe("text",{fg:e.fg,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Iu=A(()=>{Re();ot();ve();ze()});import{useEffect as $u,useRef as bx}from"react";import{jsxDEV as q,Fragment as FR}from"@opentui/react/jsx-dev-runtime";function wx(e){let{palette:t,logs:r,names:n,logSources:o,service:i,paused:s,errorOnly:a,showSystemLogs:c,search:l,searchFocused:d,followTick:g,width:f,onSearch:h,onService:x,onToggleErrors:v,onToggleSystemLogs:b,onClearLogs:P,onSelect:S,wrapMode:N="focus",selected:U=-1,follow:y=!0,newer:k=0,viewStart:m=0,viewTotal:_,onLeaveLatest:F,onOpenExports:Q,onJumpLatest:ae,view:be,fullscreen:Je=!1,facets:Ue}=e,ce=re(),Ie=Vh(f,ce.pad,Je),Ke=c?r:r.filter((_t)=>!Ii(_t.source)),ue=vo(r,{service:i,services:e.services,errorOnly:a,search:l,regex:e.regex,source:e.source,systemLogs:c}),Se=be??ue,Ce=_??ue.length,W=Math.min(Ce,m+Se.length),$e=Ce===0?"empty":`${m+1}\u2013${W} of ${Ce}`,lt=e.services??[],Fe=lt.length>0?lt.join(","):i===""?"all services":i;return q("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[Je?null:q(FR,{children:[q(Be,{palette:t,items:[{text:s?"PAUSED":"LIVE",tone:s?"warning":"success"},{text:`shown ${Ce}`,tone:"info"},{text:Ue?`total ${Ue.total}`:`total ${r.length}`},...be&&Ce>be.length?[{text:`${m+1}\u2013${m+be.length} / ${Ce}`,tone:"info"}]:[],{text:Fe,tone:i===""?"idle":"primary"},{text:Li(N),tone:N==="clip"?"idle":"accent"},...y?[]:[{text:k>0?`pinned \xB7 +${k} new`:"pinned",tone:"warning"}],{text:a?"ERROR+":"all levels",tone:a?"error":"idle",onMouseDown:v},{text:c?"system: on":"system: off",tone:c?"accent":"idle",onMouseDown:b},...e.source?[{text:`src ${e.source}`,tone:"info"}]:[],...e.regex?[{text:"regex",tone:"accent"}]:[],...l===""?[]:[{text:`search ${l}`,tone:"accent"}],{text:"clear",tone:"muted",onMouseDown:P},{text:"open folder",tone:"primary",onMouseDown:Q}]},void 0,!1,void 0,this),q(Hu,{palette:t,logs:Ke,names:o??n,service:i,errorOnly:a,width:f,onService:x,onToggleErrors:v,facets:Ue},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d?q("box",{height:1,paddingLeft:1,backgroundColor:t.highlight,overflow:"hidden",children:q("input",{focused:!0,value:l,placeholder:"search messages or service names",onInput:h,backgroundColor:t.highlight,focusedBackgroundColor:t.highlight,textColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,be&&Ce>Se.length?q(Fu,{palette:t,start:m,count:Se.length,total:Ce},void 0,!1,void 0,this):null,q("box",{flexGrow:1,border:!Je,borderStyle:"rounded",borderColor:t.border,title:Je?void 0:`logs ${Fe} \xB7 ${$e}`,titleColor:t.primary,padding:Je?0:ce.pad,overflow:"hidden",children:Se.length===0?q(Me,{palette:t,title:r.length===0?"No log events":"No events in this filter",body:r.length===0?"Start services to stream logs.":"Pick All, another service, or clear search / ERROR+.",hint:"\u2190 \u2192 cycle filters 1-9 pick a source e errors i internal ctrl+l clear"},void 0,!1,void 0,this):q(ju,{palette:t,logs:Se,width:Ie,followTick:g,focused:!1,wrapMode:N,selected:U,follow:y,showTimestamps:e.showTimestamps!==!1,showMeta:e.showMeta!==!1,onPick:S,onLeaveLatest:F,viewStart:m},g,!1,void 0,this)},void 0,!1,void 0,this),q(je,{palette:t,backgroundColor:t.element,edge:"top",children:q(Ee,{palette:t,hints:fo([{key:"\u2190\u2192",label:"filter"},{key:"1-9",label:"source"},{key:"e",label:"errors"},{key:"i",label:c?"internal off":"internal on"},{key:"ctrl+l",label:"clear"},{key:"f",label:"search"},{key:"j/k",label:"move"},{key:"enter",label:"details"},{key:"g",label:k>0?`latest +${k}`:"latest"},{key:"w",label:"wrap"},{key:"p",label:"pause"},{key:"z",label:Je?"exit full":"full screen"},{key:"t",label:e.showTimestamps===!1?"time off":"time"},{key:"m",label:e.showMeta===!1?"meta off":"meta"},{key:"pgup/pgdn",label:"history"},{key:"/exports",label:"open folder"}],Math.max(20,f-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!y?q(Nu,{palette:t,width:f,newer:k,onJump:ae},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function Fu(e){let t=Math.min(e.total,e.start+e.count),r=Math.max(0,e.start),n=Math.max(0,e.total-t);return q(Be,{palette:e.palette,items:[{text:`view ${e.start+1}\u2013${t} of ${e.total}`,tone:"primary"},{text:r>0?`\u2191 ${r} older`:"start of history",tone:r>0?"info":"idle"},{text:n>0?`\u2193 ${n} newer`:"at latest",tone:n>0?"warning":"success"}],hints:[{key:"pgup/pgdn",label:"move history window"},{key:"g",label:"latest"}]},void 0,!1,void 0,this)}function Nu(e){let t=e.newer>0?`g jump to latest \xB7 ${e.newer} new`:"g jump to latest",r=Math.min(e.width,t.length+4);return q("box",{position:"absolute",left:Math.max(0,Math.floor((e.width-r)/2)),bottom:e.bottom??2,width:r,height:3,border:!0,borderStyle:"rounded",borderColor:e.palette.warning,backgroundColor:e.palette.panel,alignItems:"center",justifyContent:"center",onMouseDown:e.onJump,children:q("text",{wrapMode:"none",children:[q("span",{fg:e.palette.primary,children:"g"},void 0,!1,void 0,this),q("span",{fg:e.palette.text,children:t.slice(1)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Hu(e){let{palette:t,logs:r,names:n,service:o,errorOnly:i,width:s,onService:a,onToggleErrors:c,facets:l}=e,d=l?My(n,l):Dy(n,r),g=s<80,f=d.map((b,P)=>{let S=P+1,N=b.name===""?"all":b.name;return{id:N,label:g?`${S} ${N}`:`${S} ${N} \xB7 ${b.count}`,color:He(b.name,t)}}),h=Math.max(0,d.findIndex((b)=>b.name===o)),x=i?"ERROR+":g?"lvls":"all levels",v=Math.max(Lr(f[h]?.label??"1 all"),s-Lr(x));return q(je,{palette:t,backgroundColor:t.element,children:q("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[q("box",{flexGrow:1,overflow:"hidden",children:q(Za,{palette:t,items:f,active:h,width:v,onPick:(b)=>{let P=d[b];if(P)a(P.name)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),q(pe,{palette:t,label:x,tone:i?"error":"muted",onMouseDown:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function ju(e){let{palette:t,logs:r,limit:n,width:o=80,followTick:i=0,focused:s=!1,wrapMode:a="clip",selected:c=-1,follow:l=!0,showTimestamps:d=!0,showMeta:g=!0,onPick:f,onLeaveLatest:h,viewStart:x=0}=e,v=bx(null),b=bx(""),P=n===void 0?r:r.slice(-n),S=[...new Set(r.map((y)=>y.service))],N=ey(o,S),U=Qh({width:o,serviceWidth:N,showTimestamps:d,showMeta:g});return $u(()=>{let y=v.current;if(!y)return;if(y.stickyScroll=l,l)y.stickyStart="bottom",y.scrollTo({x:y.scrollLeft,y:Math.max(0,y.scrollHeight)})},[l,i]),$u(()=>{let y=`${x}:${c}:${a}`;if(b.current===y)return;if(b.current=y,l&&(c<0||c>=P.length-1))return;let k=v.current;if(!k||c<0)return;let m=`log-row-${c}`,_=requestAnimationFrame(()=>{k.stickyScroll=!1,k.scrollChildIntoView(m)});return()=>cancelAnimationFrame(_)},[l,c,P.length,x,a]),$u(()=>{if(!l||!h)return;let y=!1,k=setTimeout(()=>{y=!0},DR),m=setInterval(()=>{let _=v.current;if(!y||!_)return;let F=_.viewport.height;if(F>0&&_.scrollTop+F<_.scrollHeight-OR)h()},MR);return()=>{clearTimeout(k),clearInterval(m)}},[l,i,h]),q("box",{flexGrow:1,height:"100%",overflow:"hidden",children:q("scrollbox",{ref:v,focused:s,stickyScroll:l,stickyStart:"bottom",scrollX:!1,style:{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:t.panel},viewportOptions:{backgroundColor:t.panel},contentOptions:{backgroundColor:t.panel},scrollbarOptions:{trackOptions:{foregroundColor:t.primary,backgroundColor:t.element}}},children:q("box",{flexDirection:"column",overflow:"hidden",children:P.map((y,k)=>q(IR,{id:`log-row-${k}`,palette:t,event:y,serviceWidth:N,msgWidth:U,expanded:Yh(a,k===c),active:k===c,showTimestamps:d,showMeta:g,onPick:f?()=>f(k):void 0},`${y.timestamp}-${y.service}-${k}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function IR(e){let{id:t,palette:r,event:n,serviceWidth:o,msgWidth:i,expanded:s,active:a,showTimestamps:c=!0,showMeta:l=!0,onPick:d}=e,g=Jh(Wa(n.message,i),i,s);return q("box",{id:t,flexShrink:0,flexDirection:"column",overflow:"hidden",backgroundColor:a?r.highlight:void 0,onMouseDown:d,children:g.visible.map((f,h)=>q("box",{height:1,flexDirection:"row",overflow:"hidden",children:[c?q("box",{width:ja,flexShrink:0,overflow:"hidden",children:q("text",{fg:r.muted,children:h===0?n.timestamp.slice(11,19):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,q("box",{width:o,flexShrink:0,overflow:"hidden",children:q("text",{fg:h===0?He(n.service,r):r.muted,wrapMode:"none",children:h===0?Y(n.service,o):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),q("box",{width:Ai,flexShrink:0,overflow:"hidden",children:q("text",{children:" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),q("box",{width:Ba,flexShrink:0,overflow:"hidden",children:q("text",{fg:h===0?Pe(r,n.level):r.muted,children:h===0?String(n.level):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),l?q("box",{width:Na,flexShrink:0,overflow:"hidden",children:q("text",{fg:r.muted,children:h===0&&n.source?Y(n.source,Na):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,q("box",{width:Ai,flexShrink:0,overflow:"hidden",children:q("text",{fg:r.muted,children:h===0?" ":"\u2502"},void 0,!1,void 0,this)},void 0,!1,void 0,this),q("box",{flexGrow:1,overflow:"hidden",children:q($R,{palette:r,level:n.level,text:f,mark:h===0?g.mark:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${n.timestamp}-${h}`,!0,void 0,this))},void 0,!1,void 0,this)}function $R(e){let{palette:t,level:r,text:n,mark:o}=e;return q("text",{wrapMode:"none",children:[Xh(n).map((i,s)=>q("span",{fg:Sh(t,r,i.kind),children:i.text},`${i.kind}-${s}`,!1,void 0,this)),o===""?null:q("span",{fg:t.muted,children:o},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var DR=400,MR=200,OR=2;var Bu=A(()=>{kt();ot();Re();ve();ze()});import{jsxDEV as de}from"@opentui/react/jsx-dev-runtime";function kx(e){let{palette:t,cfg:r,snap:n,logs:o,names:i,selected:s,selectedLog:a=-1,checked:c,profile:l,google:d,width:g,paused:f,followTick:h,logService:x,logSources:v,errorOnly:b,showSystemLogs:P,onOpen:S,onSelectIndex:N,onToggle:U,onFilterService:y,onToggleErrors:k,onToggleSystemLogs:m,onClearLogs:_,onShowErrors:F,wrapMode:Q="clip",view:ae,follow:be=!0,onLeaveLatest:Je,onPickLog:Ue,viewStart:ce=0,viewTotal:Ie,newer:Ke=0,onJumpLatest:ue,facets:Se}=e,Ce=re();if(!r||i.length===0)return de(Me,{palette:t,title:"No services configured",body:"Add services to .devctl/config.yaml or finish setup.",hint:"open the setup screen with /setup"},void 0,!1,void 0,this);let W=g<po,$e=yo(n),lt=qa(n,i),Fe=i.filter((En)=>n?.services[En]?.state==="FAILED").length,_t=n?.session_id?gs(n.session_id):void 0,dt=_t?ho(Date.now()-_t.getTime()):void 0,zt=Ty(o),ut=l||Ua(r),Xt=Qy(r,ut),pt=Ga(g,i,W),Pn=Math.max(24,W?g-4:g-pt-4),mc=P?o:o.filter((En)=>!Ii(En.source)),R=vo(o,{service:x,errorOnly:b,systemLogs:P}),Qt=ae??R,jr=Ie??R.length,Rn=Math.min(jr,ce+Qt.length),hc=jr===0?"empty":`${ce+1}\u2013${Rn} of ${jr}`,yc=x===""?"all services":x;return de("box",{flexGrow:1,flexDirection:W?"column":"row",overflow:"hidden",children:[de("box",{flexGrow:W?1:0,flexShrink:0,minWidth:W?void 0:pt,width:W?void 0:pt,border:!0,borderStyle:"rounded",borderColor:$e?t.border:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[de(Be,{palette:t,items:[{text:bu(lt.running,i.length),tone:lt.running>0?"success":"idle"},...Fe>0?[{text:`${Fe} failed`,tone:"error"}]:[],...c.length>0?[{text:`${c.length} selected`,tone:"primary"}]:[],...dt!==void 0?[{text:`up ${dt}`,tone:"idle"}]:[],...zt>0?[{text:`${zt} errors`,tone:"error",onMouseDown:F}]:[]]},void 0,!1,void 0,this),de(ac,{palette:t,checked:c,idle:$e,profileName:ut,members:Xt},void 0,!1,void 0,this),de("box",{flexGrow:1,paddingLeft:Ce.pad,paddingRight:Ce.pad,overflow:"hidden",children:de(sc,{palette:t,names:i,snap:n,selected:s,checked:c,width:Ha(pt,Ce.pad),onOpen:S,onSelectIndex:N,onToggle:U},void 0,!1,void 0,this)},void 0,!1,void 0,this),de(BR,{palette:t,names:i,snap:n,width:pt,onOpen:S},void 0,!1,void 0,this),de(WR,{palette:t,cfg:r,snap:n,google:d,width:pt},void 0,!1,void 0,this)]},void 0,!0,void 0,this),de("box",{position:"relative",flexGrow:2,minWidth:W?void 0:32,minHeight:W?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:`logs \xB7 ${hc}`,titleColor:t.primary,overflow:"hidden",flexDirection:"column",children:[de(Be,{palette:t,items:[{text:f?"PAUSED":"LIVE",tone:f?"warning":"success"},{text:`shown ${R.length}`,tone:"info"},{text:Se?`total ${Se.total}`:`total ${o.length}`},{text:yc,tone:x===""?"idle":"primary"},{text:b?"ERROR+":"all levels",tone:b?"error":"idle",onMouseDown:k},{text:P?"system: on":"system: off",tone:P?"accent":"idle",onMouseDown:m},{text:"clear",tone:"muted",onMouseDown:_}]},void 0,!1,void 0,this),de(Hu,{palette:t,logs:mc,names:v??i,service:x,errorOnly:b,width:Pn,onService:y,onToggleErrors:k,facets:Se},void 0,!1,void 0,this),jr>Qt.length?de(Fu,{palette:t,start:ce,count:Qt.length,total:jr},void 0,!1,void 0,this):null,R.length===0?de(Me,{palette:t,title:$e?"Waiting for logs":o.length===0?"No events yet":"No events in this filter",body:$e?"Start services to stream output here. Later starts keep earlier logs.":o.length===0?"New lines appear as services write output.":"Click All or another service chip, or turn off ERROR+.",hint:"[ ] cycle service g jump to latest"},void 0,!1,void 0,this):de(ju,{palette:t,logs:Qt,width:Pn,followTick:h,focused:!1,wrapMode:Q,selected:a,follow:be,onLeaveLatest:Je,onPick:Ue,viewStart:ce},h,!1,void 0,this),de(je,{palette:t,backgroundColor:t.element,edge:"top",children:de(Ee,{palette:t,hints:fo([{key:"e",label:"errors"},{key:"i",label:P?"internal off":"internal on"},{key:"ctrl+l",label:"clear"},{key:"g",label:"latest"},{key:"z",label:"full logs"},{key:"\u2190\u2192",label:"filter"}],Math.max(20,Pn-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!be?de(Nu,{palette:t,width:Pn,newer:Ke,bottom:1,onJump:ue},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function HR(e){if(!e)return!1;return e.state===dn||e.health===Le||e.state===pi||e.restarts>0||e.last_error!==""}function Sx(e){if(e.state===dn)return 0;if(e.health===Le)return 1;if(e.state===pi)return 2;return 3}function jR(e){if(e.last_error!=="")return e.last_error;if(e.restarts>0)return`restarted ${e.restarts}x, no error recorded`;return e.health===Le?"failing health check":e.state.toLowerCase()}function BR(e){let{palette:t,names:r,snap:n,width:o,onOpen:i}=e,s=r.map((d)=>({name:d,rt:n?.services[d]})).filter((d)=>HR(d.rt)).sort((d,g)=>Sx(d.rt)-Sx(g.rt));if(s.length===0)return null;let a=s.slice(0,NR),c=s.length-a.length,l=Math.max(8,o-Wu-4);return de("box",{border:!0,borderStyle:"rounded",borderColor:t.error,title:`issues (${s.length})`,titleColor:t.error,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[a.map(({name:d,rt:g})=>{let f=Ot(g);return de("box",{height:1,flexDirection:"row",overflow:"hidden",onMouseDown:()=>i(d),children:[de("box",{width:2,flexShrink:0,children:de("text",{fg:Pe(t,f),children:Tt(f)},void 0,!1,void 0,this)},void 0,!1,void 0,this),de("box",{width:Wu,flexShrink:0,overflow:"hidden",children:de("text",{fg:He(d,t),wrapMode:"none",children:Y(d,Wu)},void 0,!1,void 0,this)},void 0,!1,void 0,this),de("box",{width:l,flexShrink:0,overflow:"hidden",children:de("text",{fg:t.muted,wrapMode:"none",children:le(jR(g),l)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)}),c>0?de("text",{fg:t.muted,wrapMode:"none",children:`+${c} more \u2014 open a service to see details`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function WR(e){let{palette:t,cfg:r,snap:n,google:o,width:i}=e,s=o?.userEmail,a=xo(r,n?.identity,o).project,c=n?.logs.total??0,l=Zy(s,a,c,i);return de(je,{palette:t,backgroundColor:t.element,edge:"top",children:de("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:l.map((d,g)=>de(pe,{palette:t,label:d.label,tone:d.tone},`${d.label}-${g}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var NR=4,Wu=14;var Cx=A(()=>{Re();ot();ve();kt();ze();un();Ye();Iu();Bu()});import{useEffect as GR,useState as UR}from"react";import{jsxDEV as J}from"@opentui/react/jsx-dev-runtime";function Px(e){let{palette:t,report:r,loading:n,progress:o,error:i,selected:s,onPick:a,onReload:c}=e,l=bo(s,Gu);if(n)return J(KR,{palette:t,progress:o},void 0,!1,void 0,this);if(i)return J(av,{palette:t,title:"Doctor failed",body:i},void 0,!1,void 0,this);if(!r)return J(Me,{palette:t,title:"Doctor",body:"Diagnostics have not run yet.",hint:"opening this screen runs doctor"},void 0,!1,void 0,this);let d=r.checks.filter((b)=>b.severity==="ok").length,g=r.checks.filter((b)=>b.severity==="warn").length,f=r.checks.filter((b)=>b.severity==="error").length,h=r.checks.length,x=Oi(h>0?d/h:0),v=f>0?t.error:g>0?t.warning:t.success;return J(et,{palette:t,title:`doctor ${r.issues} issue(s)`,children:[J("box",{height:4,flexDirection:"column",flexShrink:0,alignItems:"center",justifyContent:"center",overflow:"hidden",border:!0,borderStyle:"rounded",borderColor:t.primary,backgroundColor:t.element,onMouseDown:c,children:[J("text",{wrapMode:"none",children:[J("span",{fg:t.inverse,bg:t.primary,children:" r "},void 0,!1,void 0,this),J("span",{fg:t.primary,children:" RUN DOCTOR AGAIN"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J("text",{fg:t.muted,wrapMode:"none",children:"results stay cached until you refresh"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0,overflow:"hidden",children:J("text",{wrapMode:"none",children:[J("span",{fg:v,children:`[${x}]`},void 0,!1,void 0,this),J("span",{fg:t.success,children:` ${d} ok`},void 0,!1,void 0,this),g>0?J("span",{fg:t.warning,children:` \xB7 ${g} warn`},void 0,!1,void 0,this):null,f>0?J("span",{fg:t.error,children:` \xB7 ${f} error`},void 0,!1,void 0,this):null,g===0&&f===0?J("span",{fg:t.muted,children:" \xB7 all clear"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:J("box",{flexDirection:"column",overflow:"hidden",gap:1,children:r.checks.map((b,P)=>J(qR,{palette:t,check:b,index:P,active:P===s,onPick:a},`${b.name}-${P}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function KR({palette:e,progress:t}){let[r,n]=UR(0);return GR(()=>{let o=setInterval(()=>n((i)=>(i+1)%_x.length),120);return()=>clearInterval(o)},[]),J("box",{flexGrow:1,alignItems:"center",justifyContent:"center",overflow:"hidden",children:J("box",{width:"80%",maxWidth:52,height:10,flexShrink:1,border:!0,borderStyle:"rounded",borderColor:e.borderActive,backgroundColor:e.panel,flexDirection:"column",alignItems:"center",justifyContent:"center",overflow:"hidden",children:[J("text",{wrapMode:"none",children:[J("span",{fg:e.primary,children:`${_x[r]} `},void 0,!1,void 0,this),J("span",{fg:e.text,children:"devctl doctor"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("text",{fg:e.text,wrapMode:"none",children:`Checking ${t.active}`},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),t.checks.slice(-4).map((o,i)=>J("text",{wrapMode:"none",children:[J("span",{fg:Pe(e,o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK"),children:`${Tt(o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK")} `},void 0,!1,void 0,this),J("span",{fg:e.muted,children:o.name},void 0,!1,void 0,this)]},`${o.name}-${i}`,!0,void 0,this)),t.checks.length===0?J("text",{fg:e.muted,children:"Waiting for the first result\u2026"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function qR(e){let{palette:t,check:r,index:n,active:o,onPick:i}=e,s=r.severity==="error"?"ERROR":r.severity==="warn"?"WARN":"OK";if(r.severity==="ok")return J("box",{id:`${Gu}-${n}`,flexDirection:"row",flexShrink:0,paddingLeft:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(n),children:J("text",{wrapMode:"none",children:[J("span",{fg:t.primary,children:o?"\u203A ":" "},void 0,!1,void 0,this),J("span",{fg:Pe(t,s),children:Tt(s)},void 0,!1,void 0,this),J("span",{fg:o?t.primary:t.text,children:` ${r.name}`},void 0,!1,void 0,this),J("span",{fg:t.muted,children:r.message?` \xB7 ${r.message}`:""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this);let c=r.severity==="error"?t.error:t.warning;return J("box",{id:`${Gu}-${n}`,border:!0,borderStyle:"rounded",borderColor:o?t.borderActive:c,title:r.name,titleColor:c,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(n),children:[J("text",{wrapMode:"word",children:[J("span",{fg:Pe(t,s),children:`${Tt(s)} `},void 0,!1,void 0,this),J("span",{fg:t.text,children:r.message},void 0,!1,void 0,this)]},void 0,!0,void 0,this),r.hint?J("text",{fg:t.info,wrapMode:"word",children:`\u2192 ${r.hint}`},void 0,!1,void 0,this):null,o&&r.action?.kind==="free-port"?J("text",{fg:t.primary,wrapMode:"none",children:`enter stop ${r.action.holder.command} (pid ${r.action.holder.pid})`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var Gu="doctor-row",_x;var Rx=A(()=>{kt();Re();ve();ze();_x=["\u25D0","\u25D3","\u25D1","\u25D2"]});import{jsxDEV as ke}from"@opentui/react/jsx-dev-runtime";function Tx(e){let{palette:t,cfg:r,snap:n,profile:o,selected:i,onPick:s}=e,a=re(),c=bo(i,Ex),l=Object.keys(r?.profiles??{}).sort();if(l.length===0)return ke(Me,{palette:t,title:"No profiles",body:"Add profiles.<name>.services in config.yaml."},void 0,!1,void 0,this);return ke(et,{palette:t,title:"profiles",children:[ke("box",{height:1,flexShrink:0,overflow:"hidden",children:ke("text",{fg:t.muted,wrapMode:"none",children:[`${l.length} profile${l.length===1?"":"s"} \xB7 current: `,ke("span",{fg:t.success,children:o||"(none)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),ke("box",{height:1,flexShrink:0},void 0,!1,void 0,this),ke("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:ke("box",{flexDirection:"column",overflow:"hidden",gap:a.gap||1,children:l.map((d,g)=>{let f=d===o,h=g===i,x=r?.profiles[d]?.services??[],v=Object.keys(r?.profiles[d]?.environment??{}).length,b=h?t.borderActive:f?t.success:t.border,P=h?t.primary:f?t.success:t.muted;return ke("box",{id:`${Ex}-${g}`,border:!0,borderStyle:"rounded",borderColor:b,title:d,titleColor:P,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:h?t.highlight:void 0,onMouseDown:()=>s(g),children:[ke("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:ke("text",{wrapMode:"none",children:[f?ke("span",{fg:t.success,children:"\u25CF current profile"},void 0,!1,void 0,this):ke("span",{fg:t.muted,children:"\u25CB not active"},void 0,!1,void 0,this),ke("span",{fg:t.muted,children:` \xB7 ${x.length} service${x.length===1?"":"s"}`},void 0,!1,void 0,this),v>0?ke("span",{fg:t.muted,children:` \xB7 ${v} env var${v===1?"":"s"}`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)},void 0,!1,void 0,this),ke("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:x.length===0?ke("text",{fg:t.muted,wrapMode:"none",children:"(no services)"},void 0,!1,void 0,this):ke("text",{wrapMode:"none",children:x.map((S,N)=>{let U=Ot(n?.services[S]);return ke("span",{children:[ke("span",{fg:Pe(t,U),children:Tt(U)},void 0,!1,void 0,this),ke("span",{fg:He(S,t),children:` ${S}`},void 0,!1,void 0,this),N<x.length-1?ke("span",{fg:t.muted,children:" "},void 0,!1,void 0,this):null]},S,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),ke(je,{palette:t,backgroundColor:t.element,edge:"top",children:ke(Ee,{palette:t,hints:[{key:"space",label:"set current"},{key:"enter",label:"set and start"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Ex="profile-row";var Ax=A(()=>{kt();ot();Re();ve();ze()});import{jsxDEV as j,Fragment as Ox}from"@opentui/react/jsx-dev-runtime";function VR(e){let t=e.toLowerCase();if(t==="iap")return"info";if(t==="service"||t==="service_account")return"primary";return"idle"}function JR(e,t,r){if(r||t>=500)return e.error;if(t===0||t>=400)return e.warning;return e.success}function YR(e,t){if(t.startsWith("sa:"))return{label:"SA",color:e.primary};if(t!=="")return{label:"USR",color:e.info};return{label:"\u2014",color:e.muted}}function ZR(e){let{palette:t,req:r,cols:n}=e,o=JR(t,r.status,r.error),i=r.status>0?String(r.status):"ERR",s=YR(t,r.identity),a=r.route||Ix,c=r.error?`${r.path} \u2014 ${le(r.error,QR)}`:r.path;return j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[j("box",{width:Uu,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:r.timestamp.slice(11,19)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showMethod?j("box",{width:cc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.text,wrapMode:"none",children:Y(r.method,cc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:lc,flexShrink:0,overflow:"hidden",children:j("text",{fg:o,wrapMode:"none",children:Y(i,lc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showDur?j("box",{width:dc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,wrapMode:"none",children:Y(`${r.durationMs}ms`,dc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:uc,flexShrink:0,overflow:"hidden",children:j("text",{fg:s.color,wrapMode:"none",children:Y(s.label,uc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{width:n.routeCol,flexShrink:0,overflow:"hidden",children:j("text",{fg:r.route?t.info:t.muted,wrapMode:"none",children:Y(a,n.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,overflow:"hidden",children:j("text",{fg:r.error?t.error:t.text,wrapMode:"none",children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function eE(e){let{palette:t,cols:r}=e;return j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[j("box",{width:Uu,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("TIME",Uu)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showMethod?j("box",{width:cc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("METHOD",cc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:lc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("ST",lc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showDur?j("box",{width:dc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("DUR",dc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,j("box",{width:uc,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("WHO",uc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{width:r.routeCol,flexShrink:0,overflow:"hidden",children:j("text",{fg:t.muted,children:Y("ROUTE",r.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,overflow:"hidden",children:j("text",{fg:t.muted,children:"PATH"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function tE(e){let{palette:t,name:r,auth:n,identity:o,upstream:i,match:s,onMouseDown:a}=e;return j("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",onMouseDown:a,children:[j("text",{fg:t.text,wrapMode:"none",children:r},void 0,!1,void 0,this),j("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[j(pe,{palette:t,label:n||"no auth",tone:VR(n)},void 0,!1,void 0,this),o?j(pe,{palette:t,label:o,tone:"idle"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),s?j("text",{fg:t.muted,wrapMode:"none",children:`match: ${s}`},void 0,!1,void 0,this):null,j("text",{fg:t.muted,wrapMode:"none",children:`\u2192 ${i}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $x(e){let{palette:t,cfg:r,snap:n,width:o,onSelectRoute:i}=e,s=n?.proxy.routes??[],a=new Map((r?.proxy.routes??[]).map((y)=>[y.name,y])),c=new Map((r?.proxy.routes??[]).map((y)=>[y.name,y.match])),l=n?.proxy.recentRequests??[],d=n?.proxy.requestTotal??0,g=n?.proxy.requestErrors??0,f=o<po,h=Math.max(Lx,Math.min(rE,Math.floor(o*0.36))),x=f?o-Dx:o-h-Dx,v=Math.max(20,x-2),b=v>=Mx,P=v>=nE,S=v>=Mx?oE:iE,N=l.reduce((y,k)=>Math.min(S,Math.max(y,(k.route||Ix).length+XR)),zR),U={showMethod:b,showDur:P,routeCol:N};return j(et,{palette:t,title:"proxy",children:[j(Be,{palette:t,items:[{text:n?.proxy.running?"RUNNING":"STOPPED",tone:n?.proxy.running?"success":"idle"},...n?.proxy.address?[{text:n.proxy.address,tone:"info"}]:[],{text:`${s.length} routes`,tone:s.length>0?"primary":"idle"},...d>0?[{text:`${d} requests`,tone:"idle"},...g>0?[{text:`${g} errors`,tone:"warning"}]:[]]:[]]},void 0,!1,void 0,this),j("box",{flexGrow:1,flexDirection:f?"column":"row",overflow:"hidden",children:[j("box",{flexGrow:f?1:0,flexBasis:f?0:void 0,flexShrink:0,minWidth:f?void 0:Lx,width:f?void 0:h,minHeight:f?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"routes",titleColor:t.primary,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",children:s.length===0?j(Me,{palette:t,title:"No proxy routes",body:"Add routes under proxy.routes or .devctl/proxy/routes.yaml."},void 0,!1,void 0,this):j(Ox,{children:[i?j("text",{fg:t.muted,wrapMode:"word",children:"click a route for full details"},void 0,!1,void 0,this):null,j("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:j("box",{flexDirection:"column",overflow:"hidden",gap:1,children:s.map((y)=>{let k=c.get(y.name),m=k&&(k.host||k.path)?`${k.host||"*"}${k.path?k.path:""}`:void 0,_=a.get(y.name);return j(tE,{palette:t,name:y.name,auth:y.auth,identity:y.identity,upstream:y.upstream,match:m,onMouseDown:i?()=>i({name:y.name,authType:_?.auth.type||y.auth,identityType:_?.auth.identity.type??"",serviceAccount:_?.auth.identity.service_account||_?.auth.service_account||"",audience:_?.auth.audience??"",matchHost:_?.match.host??"",matchPath:_?.match.path??"",upstream:y.upstream}):void 0},y.name,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j("box",{flexGrow:1,flexBasis:0,minWidth:f?void 0:30,minHeight:f?10:void 0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,title:"requests",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:l.length===0?j("box",{paddingLeft:1,paddingRight:1,children:j("text",{fg:t.muted,wrapMode:"word",children:n?.proxy.running?"No requests seen yet. Send one through the proxy to see it show up here \u2014 no need to restart or press r.":"Start the proxy, then send it a request to see live traffic here."},void 0,!1,void 0,this)},void 0,!1,void 0,this):j(Ox,{children:[j(eE,{palette:t,cols:U},void 0,!1,void 0,this),j("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:j("box",{flexDirection:"column",overflow:"hidden",children:l.map((y)=>j(ZR,{palette:t,req:y,cols:U},y.requestId,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(je,{palette:t,backgroundColor:t.element,edge:"top",children:j(Ee,{palette:t,hints:[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"}]},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Uu=9,cc=8,lc=4,dc=8,uc=4,zR=8,XR=2,QR=64,Ix="(none)",Lx=26,rE=42,Dx=2,Mx=46,nE=54,oE=20,iE=12;var Fx=A(()=>{kt();Re();ve()});import{jsxDEV as te}from"@opentui/react/jsx-dev-runtime";function jx(e){let{palette:t,name:r}=e;return te("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:r,titleColor:He(r,t),flexDirection:"column",overflow:"hidden",children:te(Ku,{...e,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ku(e){let{palette:t,cfg:r,snap:n,name:o,reveal:i,width:s,compact:a=!0,envScrollRef:c}=e,l=re(),d=r?.services[o];if(!d)return te(Me,{palette:t,title:"Unknown service",body:`No service named ${o}.`,hint:"j/k move"},void 0,!1,void 0,this);let g=n?.services[o],f=Ot(g),h=g?.health??"UNKNOWN",x=kn(g)||Hi(d,g),v=Yy(d,i,r?.secrets.extra_markers??[],r?.secrets.extra_patterns??[]),b=s>=aE,P=[{label:"health",value:za(d)},{label:"workdir",value:d.working_dir||"."},{label:"restart",value:Qa(d)},{label:"caps",value:d.capabilities.join(", ")||"\u2014"}],S=[{label:"identity",value:Xa(d,g)},{label:"depends",value:d.dependencies.join(", ")||"\u2014"},{label:"ports",value:Hi(d,g)},{label:"tries",value:String(g?.restarts??0),tone:g?.restarts?"warning":"muted"}],N=Math.max(_n+8,s-2),U=b?Math.floor(N/2):N;return te("box",{padding:l.pad,flexGrow:1,flexDirection:"column",overflow:"hidden",children:[te(Be,{palette:t,items:[{text:f,tone:Hx(f)},{text:h,tone:Hx(h)},{text:g?.pid?`pid ${g.pid}`:"pid \u2014",tone:g?.pid?"info":"idle"},{text:x==="\u2014"?"port \u2014":`port ${x}`,tone:x==="\u2014"?"idle":"info"}]},void 0,!1,void 0,this),d.description?te("box",{height:1,overflow:"hidden",children:te("text",{fg:t.muted,wrapMode:"none",children:le(d.description,Math.max(8,s-4))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,g?.last_error?te("box",{height:1,overflow:"hidden",children:te("text",{fg:t.error,wrapMode:"none",children:le(g.last_error,sE)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,te(qu,{palette:t,item:{label:"command",value:Ya(d)},valueWidth:Math.max(8,N-_n)},void 0,!1,void 0,this),te(cE,{palette:t,left:P,right:S,wide:b,colWidth:U},void 0,!1,void 0,this),te(lE,{palette:t,entries:v,reveal:i,width:s,focused:!a,scrollRef:c},void 0,!1,void 0,this),a?null:te(Ee,{palette:t,hints:[{key:"n",label:"start"},{key:"x",label:"stop"},{key:"R",label:"restart"},{key:"o",label:"config"},{key:"l",label:"logs"},{key:"/reveal",label:"secrets"},{key:"esc",label:"back"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function cE(e){let{palette:t,left:r,right:n,wide:o,colWidth:i}=e,s=Math.max(4,i-_n);if(!o)return te("box",{width:i,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[...r,...n].map((a)=>te(qu,{palette:t,item:a,valueWidth:s},a.label,!1,void 0,this))},void 0,!1,void 0,this);return te("box",{height:r.length,flexShrink:0,flexDirection:"row",overflow:"hidden",children:[te(Nx,{palette:t,items:r,width:i},void 0,!1,void 0,this),te(Nx,{palette:t,items:n,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Nx(e){let t=Math.max(4,e.width-_n);return te("box",{width:e.width,flexShrink:0,flexDirection:"column",overflow:"hidden",children:e.items.map((r)=>te(qu,{palette:e.palette,item:r,valueWidth:t},r.label,!1,void 0,this))},void 0,!1,void 0,this)}function qu(e){let{palette:t,item:r,valueWidth:n}=e,o=r.tone==="warning"?t.warning:r.tone==="muted"?t.muted:t.text;return te("box",{height:1,width:_n+n,flexDirection:"row",overflow:"hidden",children:[te("box",{width:_n,flexShrink:0,overflow:"hidden",children:te("text",{fg:t.muted,wrapMode:"none",children:Y(r.label,_n)},void 0,!1,void 0,this)},void 0,!1,void 0,this),te("box",{width:n,flexShrink:0,overflow:"hidden",children:te("text",{fg:o,wrapMode:"none",children:Y(r.value,n)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function lE(e){let{palette:t,entries:r,reveal:n,width:o,focused:i,scrollRef:s}=e,a=zy(o),c=Math.max(8,o-a-4);return te("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[te(Be,{palette:t,items:[{text:`env ${r.length}`,tone:r.length>0?"info":"idle"},{text:n?"secrets shown":"redacted",tone:n?"warning":"muted"}],hints:i?[{key:"j/k",label:"scroll"}]:[{key:"/reveal",label:"secrets"}]},void 0,!1,void 0,this),r.length===0?te("text",{fg:t.muted,children:"no service env overrides"},void 0,!1,void 0,this):te("box",{flexGrow:1,height:"100%",overflow:"hidden",children:te("scrollbox",{ref:s,focused:i,stickyScroll:!1,scrollX:!1,style:{rootOptions:{flexGrow:1,height:"100%",overflow:"hidden",backgroundColor:t.panel},viewportOptions:{backgroundColor:t.panel},contentOptions:{backgroundColor:t.panel},scrollbarOptions:{trackOptions:{foregroundColor:t.primary,backgroundColor:t.element}}},children:te("box",{flexDirection:"column",overflow:"hidden",children:r.map((l)=>te("box",{height:1,flexDirection:"row",overflow:"hidden",children:[te("box",{width:a,flexShrink:0,overflow:"hidden",children:te("text",{fg:l.required?t.warning:t.muted,wrapMode:"none",children:Y(l.required?`${l.key}*`:l.key,a)},void 0,!1,void 0,this)},void 0,!1,void 0,this),te("box",{width:c,flexShrink:0,overflow:"hidden",children:te("text",{fg:l.value===""?t.muted:t.text,wrapMode:"none",children:Y(l.value===""&&l.required?"(required)":l.value,c)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},l.key,!0,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Hx(e){switch(e.toUpperCase()){case"HEALTHY":case"RUNNING":return"success";case"UNHEALTHY":case"WARNING":case"WARN":case"STARTING":case"RESTARTING":return"warning";case"FAILED":case"ERROR":return"error";default:return"muted"}}var sE=72,aE=56,_n=9;var Vu=A(()=>{Re();kt();ot();ve();ze()});import{jsxDEV as Nr}from"@opentui/react/jsx-dev-runtime";function Bx(e){let{palette:t,cfg:r,names:n,snap:o,selected:i,checked:s,width:a,reveal:c,onOpen:l,onSelectIndex:d,onToggle:g}=e;if(n.length===0)return Nr(Me,{palette:t,title:"No services",body:"This configuration does not define any services."},void 0,!1,void 0,this);let f=a<po,h=n[i]??"",x=Ga(a,n,f),v=4,b=f?Math.max(Ju,a-v):Math.max(Ju,a-x-v);return Nr("box",{flexGrow:1,flexDirection:f?"column":"row",overflow:"hidden",children:[Nr("box",{flexGrow:f?1:0,flexShrink:0,minWidth:f?void 0:La,width:f?void 0:x,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[Nr(ac,{palette:t,checked:s,idle:yo(o),profileName:"",members:""},void 0,!1,void 0,this),Nr("box",{flexGrow:1,overflow:"hidden",children:Nr(sc,{palette:t,names:n,snap:o,selected:i,checked:s,width:Ha(x),onOpen:l,onSelectIndex:d,onToggle:g},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Nr("box",{flexGrow:2,minWidth:f?void 0:Ju,minHeight:f?dE:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:h||"detail",titleColor:h?He(h,t):t.primary,overflow:"hidden",flexDirection:"column",children:Nr(Ku,{palette:t,cfg:r,snap:o,name:h,reveal:c,width:b},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Ju=36,dE=12;var Wx=A(()=>{kt();Re();ze();Vu();Iu()});import{jsxDEV as ge}from"@opentui/react/jsx-dev-runtime";function pE(e){switch(e){case"cycle":return"\u2194";case"toggle":return"\u23FB";case"page":return"\u25B8";case"action":return"!";default:return"\xB7"}}function qx(e){let{palette:t,items:r,selected:n,locked:o,width:i,onPick:s,onActivate:a}=e,c=re(),l=ru(r,n),d=uo(r,l);return ge("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"settings",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[ge("box",{height:2,paddingLeft:c.pad,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[ge("text",{fg:t.primary,wrapMode:"none",children:"Preferences"},void 0,!1,void 0,this),ge("text",{fg:t.muted,wrapMode:"none",children:o?"DEVCTL_TUI_CONFIG is set \u2014 changes stay in this session.":"Changes save to your user tui.json unless noted."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ge("box",{flexGrow:1,paddingLeft:c.pad,paddingRight:c.pad,overflow:"hidden",flexShrink:1,children:ge(fE,{palette:t,items:r,active:l,scale:c,width:i,onPick:s,onActivate:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge(mE,{palette:t,item:d,scale:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function fE(e){let{palette:t,items:r,active:n,scale:o,width:i,onPick:s,onActivate:a}=e,c=bo(n,Kx),l=Math.max(8,i-Gx-Ux-10),d=0,g=Ah(r);return ge("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:ge("box",{flexDirection:"column",overflow:"hidden",children:g.map((f,h)=>{let x=d;d+=f.items.length;let v=n>=x&&n<x+f.items.length;return ge("box",{border:!0,borderStyle:"rounded",borderColor:v?t.borderActive:t.border,title:`${f.group} (${f.items.length})`,titleColor:v?t.primary:t.muted,flexDirection:"column",flexShrink:0,marginBottom:h<g.length-1?Math.max(1,o.gap):0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[f.group==="MCP"?ge("box",{height:1,overflow:"hidden",children:ge("text",{fg:t.muted,wrapMode:"none",children:"dedicated page \u2014 also /mcp or /agent"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,f.items.map((b,P)=>{let S=x+P;return ge(gE,{index:S,palette:t,item:b,active:S===n,rowH:o.rowH,valueWidth:l,onPick:()=>s(S),onActivate:()=>a(b)},b.id,!1,void 0,this)})]},f.group,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function gE(e){let{palette:t,index:r,item:n,active:o,rowH:i,valueWidth:s,onPick:a,onActivate:c}=e;return ge("box",{id:`${Kx}-${r}`,height:i,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:o?t.highlight:void 0,onMouseDown:()=>{if(o){c();return}a()},children:[ge("box",{width:2,flexShrink:0,overflow:"hidden",children:ge("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge("box",{width:Ux,flexShrink:0,overflow:"hidden",children:ge("text",{fg:o?t.primary:t.muted,children:pE(n.kind)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge("box",{width:Gx,flexShrink:0,overflow:"hidden",children:ge("text",{fg:o?t.primary:t.text,wrapMode:"none",children:n.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge("box",{flexGrow:1,overflow:"hidden",children:ge("text",{fg:hE(t,n,o),wrapMode:"none",children:le(n.value,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function mE(e){let{palette:t,item:r,scale:n}=e,o=r?.id==="font",i=r?.kind==="page"?`${r.name} \u2192 dedicated page`:r?.name??"";return ge("box",{height:uE,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"selected",titleColor:t.muted,backgroundColor:t.element,paddingLeft:n.pad,paddingRight:n.pad,flexDirection:"column",overflow:"hidden",children:[ge("box",{height:1,overflow:"hidden",children:ge("text",{fg:t.primary,wrapMode:"none",children:o?`${Eh(n.steps)} ${n.label}`:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge("box",{height:1,overflow:"hidden",children:ge("text",{fg:t.text,wrapMode:"word",children:r?.detail??""},void 0,!1,void 0,this)},void 0,!1,void 0,this),ge("box",{height:1,overflow:"hidden",children:ge("text",{fg:t.muted,wrapMode:"none",children:r?r.kind==="info"?"read-only":r.hint:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function hE(e,t,r){if(t.id==="mouse")return t.value==="on"?e.success:e.text;if(t.kind==="page")return e.info;if(t.kind==="info")return e.text;return r?e.primary:e.text}var Gx=14,Ux=2,uE=5,Kx="settings-row";var Vx=A(()=>{ot();Re();ve();pr()});import{useEffect as yE,useState as vE}from"react";import{jsxDEV as K}from"@opentui/react/jsx-dev-runtime";function ko(e){let{palette:t,title:r,tone:n="muted",children:o}=e,i=n==="success"?t.success:n==="warning"?t.warning:n==="error"?t.error:t.border;return K("box",{border:!0,borderStyle:"rounded",borderColor:i,title:r,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Yu(e,t){if(t.color)return t.color;switch(t.tone){case"success":return e.success;case"warning":return e.warning;case"error":return e.error;case"primary":return e.primary;case"muted":return e.muted;default:return e.text}}function Bi(e){let{palette:t,cells:r,header:n,gap:o=0,stripe:i}=e;return K("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:i?t.element:void 0,children:r.map((s,a)=>K("box",{flexDirection:"row",flexShrink:0,overflow:"hidden",children:[a>0&&o>0?K("box",{width:o,flexShrink:0},void 0,!1,void 0,this):null,K("box",{width:s.width,flexShrink:0,overflow:"hidden",children:K("text",{fg:n?t.primary:Yu(t,s),wrapMode:"none",children:Y(s.text,s.width)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${s.text}-${a}`,!0,void 0,this))},void 0,!1,void 0,this)}function Jx(e){let{palette:t,width:r}=e;return K("box",{height:1,flexShrink:0,overflow:"hidden",children:K("text",{fg:t.border,wrapMode:"none",children:Y("\u2500".repeat(Math.max(1,r)),r)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ji(e){let{palette:t,facts:r,width:n}=e,o=xu(r,n),i=[{text:"what",width:o.what},{text:"reading",width:o.reading}];if(o.meter>0)i.push({text:"used",width:o.meter});return i.push({text:"meaning",width:o.meaning}),K("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[K(Bi,{palette:t,header:!0,gap:mo,cells:i},void 0,!1,void 0,this),K(Jx,{palette:t,width:n},void 0,!1,void 0,this),r.map((s,a)=>{let c=s.meaning===""?[""]:Wa(s.meaning,Math.max(1,o.meaning)),l=s.meter?fy(s.meter):o.meter>0?"":void 0,d=[{text:s.what,width:o.what,tone:"text"},{text:s.reading,width:o.reading,tone:s.tone??"text"}];if(o.meter>0)d.push({text:l??"",width:o.meter,tone:s.meter?s.tone??"text":"muted"});return d.push({text:c[0]??"",width:o.meaning,tone:"muted"}),K("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[K(Bi,{palette:t,gap:mo,stripe:a%2===1,cells:d},void 0,!1,void 0,this),c.slice(1).map((g,f)=>{let h=[{text:"",width:o.what},{text:"",width:o.reading}];if(o.meter>0)h.push({text:"",width:o.meter});return h.push({text:g,width:o.meaning,tone:"muted"}),K(Bi,{palette:t,gap:mo,stripe:a%2===1,cells:h},`${s.what}-more-${f}`,!1,void 0,this)})]},`${s.what}-${s.reading}-${a}`,!0,void 0,this)})]},void 0,!0,void 0,this)}function Yx(e){let{palette:t,cfg:r,snap:n,width:o,onRefresh:i}=e,s=re(),[,a]=vE(0);if(yE(()=>{let Ke=setInterval(()=>{a((ue)=>{let Se=ue+1;if(i&&Se%bE===0)i();return Se})},xE);return()=>clearInterval(Ke)},[i]),!r)return K(Me,{palette:t,title:"No configuration loaded",body:"Add services to .devctl/config.yaml or finish setup."},void 0,!1,void 0,this);let c=Object.keys(r.services).sort(),l=c.some((Ke)=>gy(r.services[Ke])),d=sy(c,n),g=wy(d,l),f=l&&d.live>0?d.healthy/d.live:d.total>0?d.live/d.total:0,h=Oi(f,wE),x=d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",v=dy(o,s.pad),b=n?.session_id?gs(n.session_id):void 0,P=b?ho(Date.now()-b.getTime()):"just started",S=n?.logs.total??0,N=n?.logs.errors??0,U=ly(n?.logs.counts??{}),y=n?.proxy.routes??[],k=n?.credentials,m=(k?.entries??[]).filter((Ke)=>Ke.valid).length,_=n?.system,F=_?_.memAvailableKB??_.memFreeKB:0,Q=_?hy(_.loadAvg1,_.cpuCount):void 0,ae=_?yy(F,_.memTotalKB):void 0,be=[];if(_&&Q&&ae)be.push(Q,ae,{what:"Computer",reading:my(_.platform),meaning:`on for ${ho(_.hostUptimeSec*SE)}`,tone:"text"});let Je=d.failed>0||Q?.tone==="error"||ae?.tone==="error"?"error":x==="warning"||Q?.tone==="warning"||ae?.tone==="warning"?"warning":"success",Ue=[{what:"This session",reading:P,meaning:"how long this run has been going",tone:"text"},{what:"Profile",reading:n?.profile||"none",meaning:"which group of services is selected",tone:n?.profile?"text":"muted"},{what:"This window",reading:n?.detached?"closed":"watching",meaning:n?.detached?"services keep running without this screen":"you are watching the services from here",tone:n?.detached?"warning":"text"},{what:"Project folder",reading:"",meaning:r.repoRoot,tone:"muted"}],ce=[{what:"Lines kept",reading:String(S),meaning:"log lines still in memory",tone:"text"},{what:"Error lines",reading:String(N),meaning:N>0?"open Logs and press e to see only errors":"no ERROR or FATAL lines",tone:N>0?"error":"muted"},...U.map(([Ke,ue])=>({what:Ke,reading:String(ue),meaning:"lines from this service",tone:"text"}))],Ie=[{what:"Web proxy",reading:n?.proxy.running?"on":"off",meaning:n?.proxy.running?`${y.length} apps${n.proxy.address?` at ${n.proxy.address}`:""}`:"not forwarding local URLs",tone:n?.proxy.running?"success":"muted"},{what:"Agent tools",reading:n?.mcp?.running?"on":"off",meaning:n?.mcp?.address?`Cursor talks to devctl at ${n.mcp.address}`:"turn on from Settings \u2192 MCP",tone:n?.mcp?.running?"success":"muted"},{what:"Google account",reading:n?.identity.user?"signed in":"not signed in",meaning:[n?.identity.user,n?.identity.project].filter(Boolean).join(" \xB7 ")||"no Google user for this session",tone:n?.identity.user?"success":"muted"},{what:"Saved tokens",reading:k?`${m} of ${k.entries.length} good`:"none",meaning:k?by(k.backend):"nothing stored yet",tone:k&&m<k.entries.length?"warning":k?"success":"muted"}];return K(et,{palette:t,title:"stats",scroll:!0,children:[K(ko,{palette:t,title:`Your services ${d.live} of ${d.total} started`,tone:Je,children:[K(ji,{palette:t,facts:g,width:v},void 0,!1,void 0,this),K("box",{height:1,flexShrink:0},void 0,!1,void 0,this),K("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:K("text",{wrapMode:"none",children:[K("span",{fg:t.muted,children:Y(l?"Ready":"Started",xu(g,v).what)},void 0,!1,void 0,this),K("span",{children:" ".repeat(mo)},void 0,!1,void 0,this),K("span",{fg:Yu(t,{text:"",width:1,tone:x}),children:`[${h}]`},void 0,!1,void 0,this),K("span",{fg:Yu(t,{text:"",width:1,tone:x}),children:l?` ${d.healthy} of ${d.live||d.total} passing checks`:` ${d.live} of ${d.total} up`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_?K(ko,{palette:t,title:"This computer",tone:Q?.tone==="error"||ae?.tone==="error"?"error":Q?.tone==="warning"||ae?.tone==="warning"?"warning":"success",children:K(ji,{palette:t,facts:be,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,K(ko,{palette:t,title:"This session",children:K(ji,{palette:t,facts:Ue,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),K(ko,{palette:t,title:"Each service",tone:d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",children:d.total===0?K("text",{fg:t.muted,children:"No services in this project yet."},void 0,!1,void 0,this):K("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[K(kE,{palette:t,names:c,snap:n,width:v},void 0,!1,void 0,this),K("box",{height:1,flexShrink:0},void 0,!1,void 0,this),K("text",{fg:t.muted,wrapMode:"none",children:Y("CPU is % of one core. RAM is what that process is holding now.",v)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),K(ko,{palette:t,title:"Log lines",tone:N>0?"warning":"muted",children:K(ji,{palette:t,facts:ce,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),K(ko,{palette:t,title:"Other parts",children:K(ji,{palette:t,facts:Ie,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function kE(e){let{palette:t,names:r,snap:n,width:o}=e,i=uy(o),s=[{text:"service",width:i.name},{text:"status",width:Jt}];if(i.health)s.push({text:"check",width:fr});if(i.cpu)s.push({text:"cpu",width:Ia});if(i.mem)s.push({text:"ram",width:$a});if(i.up)s.push({text:"up",width:Oa});if(i.rst)s.push({text:"restarts",width:Va});if(i.pid)s.push({text:"pid",width:Mr});return K("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[K(Bi,{palette:t,header:!0,gap:yt,cells:s},void 0,!1,void 0,this),K(Jx,{palette:t,width:o},void 0,!1,void 0,this),r.map((a,c)=>K(RE,{palette:t,name:a,rt:n?.services[a],cols:i,stripe:c%2===1},a,!1,void 0,this))]},void 0,!0,void 0,this)}function PE(e){if(e===void 0)return"muted";if(e>_E)return"error";if(e>CE)return"warning";return"text"}function RE(e){let{palette:t,name:r,rt:n,cols:o,stripe:i}=e,s=vy(n),a=xy(n),c=n?.restarts??0,l=[{text:r,width:o.name,color:He(r,t)},{text:s,width:Jt,color:Pe(t,n?.state??"STOPPED")}];if(o.health)l.push({text:a,width:fr,color:Pe(t,n?.health??"UNKNOWN")});if(o.cpu)l.push({text:n?.cpuPercent!==void 0?Sy(n.cpuPercent):"\u2014",width:Ia,tone:PE(n?.cpuPercent)});if(o.mem)l.push({text:n?.memoryKB!==void 0?Da(n.memoryKB):"\u2014",width:$a,tone:"text"});if(o.up)l.push({text:cy(n),width:Oa,tone:"text"});if(o.rst)l.push({text:String(c),width:Va,tone:c>0?"warning":"muted"});if(o.pid)l.push({text:n?.pid?String(n.pid):"\u2014",width:Mr,tone:"muted"});return K("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",children:[K(Bi,{palette:t,gap:yt,stripe:i,cells:l},void 0,!1,void 0,this),n?.last_error?K("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:K("text",{fg:t.error,wrapMode:"none",children:Y(` ${n.last_error}`,Math.max(24,o.name+yt+Jt+fr))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var xE=1000,bE=5,wE=16,SE=1000,CE=80,_E=100;var zx=A(()=>{kt();Re();ot();ve();ze();Ye()});import{jsxDEV as he}from"@opentui/react/jsx-dev-runtime";function Xx(e){let{palette:t,cfg:r,google:n,bootError:o,bootErrorMissing:i=!1,step:s=0}=e,a=re();if(o&&!r)return i?he(Me,{palette:t,title:"No configuration found",body:"Would you like to run setup?",hint:"[Enter] Setup [Esc] Exit"},void 0,!1,void 0,this):he(Me,{palette:t,title:"Configuration error",body:o,hint:"Fix .devctl/config.yaml, then restart devctl [Esc] Exit"},void 0,!1,void 0,this);let c=r?Ut(r):["configuration not loaded"],l=EE(r,n,c),d=l.filter((S)=>S.ok).length,g=l.length,f=g>0?Math.round(d/g*100):0,h=20,x=Math.round(f/100*h),v="\u2588".repeat(x)+"\u2591".repeat(Math.max(0,h-x)),b=f===100?t.success:f===0?t.muted:t.primary,P=l[s];return he(et,{palette:t,title:"setup",scroll:!0,children:[he("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:he("text",{fg:t.primary,children:"Developer onboarding"},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:he("text",{wrapMode:"none",children:[he("span",{fg:b,children:`[${v}]`},void 0,!1,void 0,this),he("span",{fg:t.text,children:` ${d}/${g} ready`},void 0,!1,void 0,this),he("span",{fg:t.muted,children:` (${f}%)`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,flexShrink:0},void 0,!1,void 0,this),l.map((S,N)=>{let U=N===s;return he("box",{height:a.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:U?t.highlight:void 0,paddingLeft:1,children:[he("box",{width:2,flexShrink:0,children:he("text",{fg:Pe(t,S.ok?"OK":"WARN"),children:Tt(S.ok?"OK":"WARN")},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:3,flexShrink:0,children:he("text",{fg:U?t.primary:t.muted,children:String(N+1).padStart(2," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:20,flexShrink:0,overflow:"hidden",children:he("text",{fg:U?t.primary:t.text,children:S.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{flexGrow:1,overflow:"hidden",children:he("text",{fg:U?t.text:t.muted,wrapMode:"none",children:S.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},S.name,!0,void 0,this)}),he("box",{height:1,flexShrink:0},void 0,!1,void 0,this),P?he("box",{border:!0,borderStyle:"rounded",borderColor:P.ok?t.success:t.warning,title:P.name,titleColor:P.ok?t.success:t.warning,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:he("text",{fg:P.ok?t.text:t.warning,wrapMode:"word",children:P.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,he("box",{height:1,flexShrink:0},void 0,!1,void 0,this),he("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:he(pe,{palette:t,label:"never hard-coded",tone:"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("text",{fg:t.muted,wrapMode:"word",children:"Service accounts and IAP audiences stay in configuration. Run `devctl setup` for the interactive CLI wizard."},void 0,!1,void 0,this),he(Ee,{palette:t,hints:[{key:"j/k",label:"steps"},{key:"enter",label:r?"start":"begin setup"},{key:"esc",label:"exit"},{key:"o",label:"profiles"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function EE(e,t,r=[]){let n=Object.values(e?.services??{}).flatMap((s)=>s.ports.filter((a)=>!a.auto)),o=(e?.proxy.routes??[]).some((s)=>s.auth.type.toLowerCase()==="iap"),i=xo(e,void 0,t).project;return[{name:mr[0],ok:Boolean(e?.repoRoot),detail:e?.repoRoot||"unknown"},{name:mr[1],ok:Boolean(e?.project.name),detail:e?.project.name||"set project.name"},{name:mr[2],ok:Boolean(i),detail:i||"optional for local-only"},{name:mr[3],ok:t?.adcAvailable===!0,detail:t?.adcAvailable?"ADC available":"needed only for cloud identity / IAP"},{name:mr[4],ok:!0,detail:"read from configuration; never hard-coded"},{name:mr[5],ok:!o||(e?.proxy.routes??[]).every((s)=>s.auth.type.toLowerCase()!=="iap"||s.auth.audience!==""),detail:o?"IAP routes present":"no IAP routes"},{name:mr[6],ok:n.length===0||Boolean(e),detail:`${n.length} fixed ports from configuration`},{name:mr[7],ok:Object.keys(e?.profiles??{}).length>0,detail:`${Object.keys(e?.profiles??{}).length} profile(s)`},{name:mr[8],ok:r.length===0,detail:r.length===0?"configuration is valid":r[0]??"invalid"}]}var mr;var Qx=A(()=>{St();kt();ot();ve();Re();ze();mr=["Repository","Environment","Google project","Authentication","Service accounts","IAP","Ports","Profiles","Validation"]});import{jsxDEV as B}from"@opentui/react/jsx-dev-runtime";function Zu(){return $d.flatMap((e)=>fa.filter((t)=>t.category===e))}function fc(){return pc+Zu().length}function tb(){return fc()+eb}function gc(e){if(e<pc||e>=fc())return;return Zu()[e-pc]}function ep(e){let t=e-fc();return t>=0&&t<eb?t:void 0}function rb(e){let{palette:t,snap:r,port:n,portDraft:o="",selected:i,onPick:s,onToggle:a,onCopy:c,onToggleTool:l}=e,d=re(),g=r?.mcp?.running===!0,f=r?.mcp?.port??n,h=r?.mcp?.address??co(f),x=r?.mcp?.token??"",v=ki(h,x),b=r?.mcp?.disabled_tools??[],P=Zu(),S=P.filter((y)=>!Ar(y.name,b)).length,N=v[ep(i)??-1],U=N??v[0];return B(et,{palette:t,title:"mcp settings",children:[B(Be,{palette:t,items:[{text:g?"RUNNING":"STOPPED",tone:g?"success":"idle"},{text:`127.0.0.1:${f}`,tone:"info"}]},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:De(t),children:B("box",{flexDirection:"column",overflow:"hidden",children:[B(zu,{palette:t,text:"Server"},void 0,!1,void 0,this),B(Zx,{palette:t,active:i===Xu,rowH:d.rowH,label:"Listen",value:g?"[ ON ]":"[ OFF ]",valueTone:g?"success":"muted",hint:g?"space or enter stop":"space or enter start",onPick:()=>s(Xu),onActivate:a},void 0,!1,void 0,this),B(Zx,{palette:t,active:i===Qu,rowH:d.rowH,label:"Port",value:`\u2039 ${o===""?n:o} \u203A`,valueTone:"info",hint:o===""?"\u2190 \u2192 change type digits enter apply":"typing\u2026 enter apply \u232B erase",onPick:()=>s(Qu)},void 0,!1,void 0,this),B("box",{height:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:g?"Listening on loopback. Agents use the URL and token in the JSON below.":"Server is stopped. Highlight Listen and press space to start it."},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(zu,{palette:t,text:"Tools",extra:S===0?"all enabled":`${S} disabled`},void 0,!1,void 0,this),B("box",{height:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:"Disabled tools are hidden from agents and refused if called anyway."},void 0,!1,void 0,this)},void 0,!1,void 0,this),$d.map((y)=>{let k=P.filter((m)=>m.category===y);if(k.length===0)return null;return B("box",{flexDirection:"column",overflow:"hidden",children:[B("box",{height:1,marginTop:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:TE[y]??y},void 0,!1,void 0,this)},void 0,!1,void 0,this),k.map((m)=>{let _=pc+P.indexOf(m);return B(ME,{palette:t,tool:m,enabled:Ar(m.name,b),active:i===_,rowH:d.rowH,onPick:()=>s(_),onToggle:()=>l(m)},m.name,!1,void 0,this)})]},y,!0,void 0,this)}),B(zu,{palette:t,text:"Copy agent config",extra:"highlight a row, then enter or click Copy"},void 0,!1,void 0,this),v.map((y,k)=>{let m=fc()+k;return B(DE,{palette:t,snippet:y,active:i===m,rowH:d.rowH,onPick:()=>s(m),onCopy:()=>c(y)},y.kind,!1,void 0,this)}),B(OE,{palette:t,snippet:U,selected:Boolean(N),brand:U?Pa(U.kind,t):t.muted},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(je,{palette:t,backgroundColor:t.element,edge:"top",children:B(Ee,{palette:t,hints:LE(i,g)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function LE(e,t){if(e===Xu)return[{key:"space",label:t?"stop server":"start server"},{key:"j/k",label:"move"}];if(e===Qu)return[{key:"\u2190\u2192",label:"change port"},{key:"0-9",label:"type port"},{key:"enter",label:"apply port"},{key:"j/k",label:"move"}];if(gc(e))return[{key:"space",label:"enable / disable"},{key:"enter",label:"enable / disable"},{key:"j/k",label:"move"}];return[{key:"enter",label:"copy JSON"},{key:"space",label:"copy JSON"},{key:"j/k",label:"move"}]}function zu(e){let t=e.extra?` \xB7 ${e.extra}`:"";return B("box",{height:1,marginTop:1,overflow:"hidden",children:B("text",{wrapMode:"none",children:[B("span",{fg:e.palette.primary,children:e.text},void 0,!1,void 0,this),B("span",{fg:e.palette.muted,children:t},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Zx(e){let{palette:t,active:r,rowH:n,label:o,value:i,valueTone:s,hint:a,onPick:c,onActivate:l}=e,d=s==="success"?t.success:s==="info"?t.info:t.muted;return B("box",{height:n,flexDirection:"row",overflow:"hidden",backgroundColor:r?t.highlight:t.panel,onMouseDown:()=>{if(r&&l){l();return}c()},children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:t.primary,children:r?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:tp,flexShrink:0,overflow:"hidden",children:B("text",{fg:r?t.primary:t.text,wrapMode:"none",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:AE,flexShrink:0,overflow:"hidden",children:B("text",{fg:d,wrapMode:"none",children:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:r?t.text:t.muted,wrapMode:"none",children:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function DE(e){let{palette:t,snippet:r,active:n,rowH:o,onPick:i,onCopy:s}=e,a=Pa(r.kind,t),c=wh(r.kind,t),l=r.language==="toml"?"Copy TOML":"Copy JSON";return B("box",{height:o,flexDirection:"row",overflow:"hidden",backgroundColor:n?t.highlight:t.panel,onMouseDown:i,children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:a,children:n?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:tp,flexShrink:0,overflow:"hidden",children:B("text",{fg:a,wrapMode:"none",children:r.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:t.muted,wrapMode:"none",children:r.path},void 0,!1,void 0,this)},void 0,!1,void 0,this),B(pe,{palette:t,label:l,bg:a,fg:c,onMouseDown:()=>{i(),s()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ME(e){let{palette:t,tool:r,enabled:n,active:o,rowH:i,onPick:s,onToggle:a}=e;return B("box",{height:i,flexDirection:"row",overflow:"hidden",backgroundColor:o?t.highlight:t.panel,onMouseDown:()=>{if(o){a();return}s()},children:[B("box",{width:2,flexShrink:0,overflow:"hidden",children:B("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:5,flexShrink:0,overflow:"hidden",children:B("text",{fg:n?t.success:t.muted,wrapMode:"none",children:n?" ON ":" OFF "},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:tp+4,flexShrink:0,overflow:"hidden",children:B("text",{fg:o?t.primary:n?t.text:t.muted,wrapMode:"none",children:r.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{width:7,flexShrink:0,overflow:"hidden",children:B("text",{fg:r.mutates?t.warning:t.muted,wrapMode:"none",children:r.mutates?"write":"read"},void 0,!1,void 0,this)},void 0,!1,void 0,this),B("box",{flexGrow:1,overflow:"hidden",children:B("text",{fg:o?t.text:t.muted,wrapMode:"none",children:o?`space or enter ${n?"disable":"enable"} ${r.name}`:r.summary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function OE(e){let{palette:t,snippet:r,selected:n,brand:o}=e;if(!r)return null;let i=r.hint?` \xB7 ${r.hint}`:"";return B("box",{marginTop:1,flexDirection:"column",overflow:"hidden",children:[B("text",{fg:o,wrapMode:"none",children:n?`${r.title} \xB7 paste into ${r.path}${i}`:`Preview ${r.title} \xB7 j/k to a copy row, then enter`},void 0,!1,void 0,this),B("text",{fg:t.text,children:r.text},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Xu=0,Qu=1,pc=2,eb=4,TE,tp=14,AE=14;var nb=A(()=>{ot();ve();ze();vi();TE={inspect:"Inspect",logs:"Logs",diagnostics:"Diagnostics",control:"Control",setup:"Setup"}});import{readFileSync as IE,writeFileSync as $E}from"fs";import{useCallback as z,useEffect as Ct,useMemo as hr,useRef as tt,useState as O}from"react";import{RGBA as FE}from"@opentui/core";import{useKeyboard as NE,useTerminalDimensions as HE}from"@opentui/react";import{jsxDEV as oe,Fragment as GE}from"@opentui/react/jsx-dev-runtime";function ob({controller:e,tui:t,onQuit:r,bootError:n,bootErrorMissing:o=!1,terminalBackground:i}){let{width:s,height:a}=HE(),[c,l]=O(t.theme||e?.cfg.ui.theme||"devctl"),d=tt(c),[g,f]=O(t.mouse),h=tt(t.mouse),[x,v]=O(t.leader_timeout),b=tt(t.leader_timeout),[P,S]=O(()=>Ri(t.font_size)),N=tt(P),U=_h(),y=hr(()=>{let p=bh(c);if(ka(c)!=="terminal"||!Xd(i))return p;let u=i??p.background;return{...p,background:u,panel:u,element:u,inverse:u}},[i,c]),k=ka(c)==="terminal"&&Xd(i)?FE.defaultBackground(i??void 0):y.background,[m,_]=O(e?"dashboard":"setup"),[F,Q]=O("none"),[ae,be]=O(""),[Je,Ue]=O(0),[ce,Ie]=O(0),[Ke,ue]=O(0),[Se,Ce]=O([]),[W,$e]=O(),lt=hr(()=>Th({themeName:c,fontSize:P,mouse:g,leaderMs:x,locked:U,configPath:U?t.path||nu():nu(),mcpRunning:W?.mcp?.running===!0}),[P,x,g,U,W?.mcp?.running,c,t.path]),[Fe,_t]=O([]),[dt,zt]=O(!1),[ut,Xt]=O(!1),[pt,Pn]=O(!0),[mc,R]=O(n??""),[Qt,jr]=O(),[Rn,hc]=O(),[yc,En]=O(!1),[mb,cp]=O(""),[vc,xc]=O(0),[hb,lp]=O({active:"Preparing diagnostics",checks:[]}),dp=tt(void 0),Co=tt(0),[yb,vb]=O({}),[up,xb]=O(),[Xe,bc]=O(Ua(e?.cfg)),[Tn,bb]=O(""),[_o,wb]=O(!1),[yr,Sb]=O(""),[Wi,wc]=O(!1),[pp,kb]=O(0),[An,fp]=O(""),[Gi,Cb]=O(""),[Wt,vr]=O(""),Br=BE,[gp,_b]=O(t.log_timestamps!==!1),[mp,Pb]=O(t.log_metadata!==!1),[hp,Rb]=O(()=>[...Cy]),[Ui]=O(""),[Wr]=O(""),[xr,Eb]=O(!1),[Ki,yp]=O(),[Tb,Ab]=O(),[Po,vp]=O("focus"),[xt,br]=O(!1),[Lb,Ro]=O(wn-1),[Eo,qi]=O(!1),[Zt,Vi]=O(-1),[xp,Db]=O(),[bp,wp]=O(""),[Sp,Sc]=O(!1),[kp,Cp]=O(!1),_p=tt([]),To=tt(null),Ao=tt(null),Lo=tt(null),Do=tt(null),kc=tt(null),Cc=tt(null),Pp=tt(null),[_c,Mb]=O(""),[Ob,Ji]=O(""),Pc=tt(""),Rc=tt(!1),[Rp,Mo]=O(0),[Yi,Ec]=O(""),[zi,Tc]=O(),[Ib,Ac]=O([]),[Ep,er]=O(!1),[Tp,Lc]=O("start"),[Gr,wr]=O("quit"),[Sr,$b]=O(()=>t.mcp_port??so(e?.cfg.repoRoot??process.cwd())),Oo=tt(void 0),Dc=tt(0),[D,Fb]=O(e?.cfg),[Io,Ap]=O(void 0),Lp=t.keybinds.copy??lr(),it=hr(()=>Object.keys(D?.services??{}).sort(),[D]),$o=hr(()=>$i(it,Fe,hp),[it,Fe,hp]),Fo=hr(()=>yh(ae),[ae]),Ln=hr(()=>Ky(ae),[ae]);Ct(()=>{Rb((p)=>{let u=new Set(p),C=!1;for(let T of Fe)if(T.service!==""&&!it.includes(T.service)&&!u.has(T.service))u.add(T.service),C=!0;return C?[...u].sort():p})},[Fe,it]),Ct(()=>{Ie(0)},[ae]),Ct(()=>{if(F==="palette")Ue(0)},[F,ae]);let rt=hr(()=>vo(Fe,{service:Wt,services:Br,errorOnly:ut,search:yr,regex:xr,source:Wr,since:An,until:Gi,systemLogs:pt}),[ut,xr,yr,Wt,Br,An,Wr,Gi,Fe,pt]),Ne=hr(()=>zh(rt,xt,Rp),[rt,xt,Rp]),kr=Ne.items,tr=oy(m,{doctor:Rn?.checks.length??0,settings:lt.length,profiles:Object.keys(D?.profiles??{}).length,services:it.length,logs:kr.length,mcp:tb()}),Dp=m==="logs"?Lb:Ke,Z=tr<=0?Math.max(0,Dp):Math.max(0,Math.min(Dp,tr-1));Ct(()=>{Vi(-1),br(!1),Ro(Math.max(0,Math.min(wn,rt.length)-1))},[ut,yr,Wt,pt]),Ct(()=>{if(m!=="logs")qi(!1)},[m]),Ct(()=>{if(m!=="logs"||xt)return;Ro(Math.max(0,Math.min(wn,rt.length)-1))},[rt.length,xt,m]),Ct(()=>{if(m==="settings")return;l(d.current),S(N.current),v(b.current),f(h.current)},[m]);let Mc=z(()=>{if(!xt)Mo(yu(rt.length)),br(!0)},[rt.length,xt]),No=z((p)=>{let u=vu(p,tr,Ne.start,Ne.newer);if(u.startDelta!==0){Mo(Math.max(0,Ne.start+u.startDelta)),br(!0),Ro(u.selected);return}let C=Math.max(tr-1,0),T=tr>0&&(u.selected<C||Ne.newer>0);if(T&&!xt)Mo(yu(rt.length)),br(!0);else if(!T)br(!1);Ro(u.selected)},[rt.length,tr,xt,Ne.newer,Ne.start]),Xi=z((p)=>{let u=kr.length,C=vu(p,u,Ne.start,Ne.newer);if(C.startDelta!==0)Mo(Math.max(0,Ne.start+C.startDelta)),br(!0);Vi(C.selected)},[kr.length,Ne.newer,Ne.start]),Oc=z(()=>{if(br(!1),Vi(-1),m==="logs")Ro(Math.max(0,Math.min(wn,rt.length)-1));kb((p)=>p+1),R(Ne.newer>0?`Jumped to latest (+${Ne.newer} new)`:"Jumped to latest logs")},[rt.length,Ne.newer,m]),Qe=z(()=>{if(Q("none"),be(""),wc(!1),Oo.current)clearTimeout(Oo.current)},[]),Ic=z((p)=>{Ce((u)=>u.includes(p)?u.filter((C)=>C!==p):[...u,p])},[]),qe=z((p,u)=>{if(U){R(`${u} session only`);return}let C=lh(p);R(`${u} saved ${C}`)},[U]),Dn=z((p)=>{l(p),d.current=p,qe({theme:p},`theme ${p}`)},[qe]),Ho=z(()=>{let p=!g;f(p),h.current=p,qe({mouse:p},`mouse ${p?"on":"off"} restart TUI to apply clicks`)},[g,qe]),Qi=z((p)=>{v(p),b.current=p,qe({leader_timeout:p},`leader ${p}ms`)},[qe]),Ur=z((p)=>{let u=Ri(p);S(u),N.current=u,qe({font_size:u},`display ${Ra(u)}`)},[qe]),Mp=z(()=>{let p=tu();l(p.theme),d.current=p.theme,f(p.mouse),h.current=p.mouse,v(p.leader_timeout),b.current=p.leader_timeout,S(p.font_size),N.current=p.font_size,qe(p,"restored default preferences")},[qe]),$c=z((p)=>{if(p.id==="theme"){Ue(Math.max(0,ht.indexOf(c))),Q("themes");return}if(p.id==="mouse"){Ho();return}if(p.id==="leader"){Qi(x);return}if(p.id==="font"){Ur(P);return}if(p.id==="reset"){wr("reset-prefs"),Q("confirm");return}if(p.id==="mcp"){_("mcp"),ue(0);return}R(p.detail)},[Ur,Qi,P,x,c,Ho]),Op=z((p)=>{let u=uo(lt,Z);if(!u)return;if(u.id==="theme"){Dn(Ph(c,p));return}if(u.id==="leader"){Qi(Rh(x,p));return}if(u.id==="font"){Ur(Ea(P,p));return}if(u.id==="mouse")Ho()},[Ur,Qi,P,x,Z,Dn,lt,c,Ho]),Nb=z(()=>{l(d.current)},[]),me=z(async()=>{if(!e)return;try{let p=await e.status();if($e(p),p.profile&&Xe==="")bc(p.profile);return p}catch(p){R(H(p));return}},[e,Xe]),Zi=z(async()=>{if(!e){R("Supervisor is not running");return}R("Probing configured identities\u2026");try{let p=await e.refreshAuth();$e((ee)=>ee?{...ee,identity:p}:ee);let u=Object.values(p.service_account_status),C=u.filter((ee)=>ee==="available").length,T=u.filter((ee)=>ee==="unavailable").length;R(u.length===0?"Identity refreshed \u2014 no service accounts configured":`Identity refreshed \u2014 ${C} available${T>0?`, ${T} unavailable`:""}`)}catch(p){R(H(p))}},[e]),es=z((p)=>{let u=hn(p);$b(u);let C=D?.repoRoot??process.cwd();if(sh(C,u)){qe({mcp_port:null},`MCP port ${u} (default)`);return}qe({mcp_port:u},`MCP port ${u}`)},[D,qe]),Mn=z(()=>{if(Yi==="")return Sr;let p=ih(Yi,Sr);return Ec(""),es(p),p},[Sr,Yi,es]),Ip=z(async(p)=>{if(!e||W?.mcp?.running!==!0)return;await e.mcpStop(),await e.mcpStart({port:p}),await me()},[e,me,W?.mcp?.running]),Fc=z(async(p)=>{if(!e){R("Supervisor is not running");return}let u=W?.mcp?.disabled_tools??[],C=Ar(p.name,u),T=C?[...u,p.name]:u.filter((ee)=>ee!==p.name);try{let ee=await e.mcpSetTools(T);qe({mcp_disabled_tools:ee},`${p.label} ${C?"disabled":"enabled"}`),await me()}catch(ee){R(H(ee))}},[e,qe,me,W]),ts=z(async()=>{if(!e){R("Supervisor is not running");return}try{if(W?.mcp?.running)await e.mcpStop(),qe({mcp_enabled:!1},"MCP off"),R("MCP stopped");else await e.mcpStart({port:Sr}),qe({mcp_enabled:!0},"MCP on"),R("MCP started");await me()}catch(p){R(H(p))}},[e,Sr,qe,me,W?.mcp?.running]),Nc=z((p)=>{Cu(p.text).then(()=>{R(`Copied ${p.title} snippet`)}).catch((u)=>{R(H(u))})},[]),rs=z((p)=>{let u=ep(p);if(u===void 0)return!1;let C=W?.mcp?.address??co(W?.mcp?.port??Sr),T=ki(C,W?.mcp?.token??"")[u];if(!T)return!1;return Nc(T),!0},[Nc,Sr,W?.mcp?.address,W?.mcp?.port,W?.mcp?.token]),On=hr(()=>({services:Wt!==""?[Wt]:Br,level:ut?"ERROR":Ui,search:yr,regex:xr,source:Wr,since:An,until:Gi}),[ut,Ui,xr,yr,Wt,Br,An,Wr,Gi]),ns=z(async()=>{if(!e)return;try{Db(await e.logsStats(On))}catch(p){R(H(p))}},[e,On]),$p=z(async()=>{if(!e||dt)return;try{let p=await e.logsPage(On);_t((u)=>Py(u,p.events)),wp(p.prevCursor),Sc(p.hasPrev),await ns()}catch(p){R(H(p))}},[e,On,dt,ns]),jo=z(()=>{_t([]),fp(new Date().toISOString()),br(!1),R("Cleared on-screen log buffer")},[]),Bo=z(()=>{Pn((p)=>!p)},[]);Ct(()=>{me().then(()=>$p())},[me,$p]),Ct(()=>{_p.current=Fe},[Fe]),Ct(()=>{if(!e||kp||!Ey(xt,Ne.start,Sp))return;Cp(!0),e.logsPage({...On,cursor:bp,direction:"backward"}).then((p)=>{if(p.sessionChanged){R("Daemon session changed \u2014 older log history is no longer available"),Sc(!1);return}let u=_p.current,C=Ry(u,p.events);if(_t(C),C.length>u.length)Mo((T)=>T+(C.length-u.length));wp(p.prevCursor),Sc(p.hasPrev)}).catch((p)=>R(H(p))).finally(()=>Cp(!1))},[e,On,kp,Sp,xt,bp,Ne.start]),Ct(()=>{if(!e||dt||m!=="logs")return;let p=setInterval(()=>{ns()},WE);return()=>clearInterval(p)},[e,dt,ns,m]),Ct(()=>{if(!e)return;let p,u=!1,C=[],T=D&&D.logs.max_memory_events>0?D.logs.max_memory_events:50000,ee=()=>{if(p=void 0,C.length>0){let w=C.splice(0,C.length);_t((ie)=>_y(ie,w,An,T))}if(u)u=!1,me()},Cr=e.onEvent((w)=>{if(w.type===Bs&&w.payload&&typeof w.payload==="object"&&"event"in w.payload){let ie=w.payload.event;if(!dt)C.push(ie);if(!p)p=setTimeout(ee,30);return}if(w.type===ai){Ap(ev(w));return}if(w.type===Ws)Ap(void 0),e.configSnapshot().then(Fb).catch((ie)=>R(H(ie)));if(u=!0,!p)p=setTimeout(ee,30)});return()=>{if(Cr(),p)clearTimeout(p)}},[e,An,dt,me]),Ct(()=>{Ht(D?.google.project_id??"").then(jr).catch((p)=>{R(H(p))})},[D?.google.project_id,W?.identity.project]),Ct(()=>{if(m!=="doctor"||!D)return;let p=dp.current,u=W?.session_id??"";if(p?.cfg===D&&p.tick===vc&&p.sessionID===u&&p.reloadError===Io)return;dp.current={cfg:D,tick:vc,sessionID:u,reloadError:Io};let C=++Co.current;En(!0),cp(""),lp({active:"Preparing diagnostics",checks:[]});let T;if(D.configPath!==""){T="";try{Qo(D.repoRoot,D.configPath)}catch(ee){T=H(ee)}}Tr(D,void 0,(ee)=>{if(C===Co.current)lp(ee)},{services:W?.services,proxyRunning:W?.proxy.running,repositoryConfigError:T}).then((ee)=>{if(C!==Co.current)return;hc(ee)}).catch((ee)=>{if(C!==Co.current)return;cp(H(ee))}).finally(()=>{if(C===Co.current)En(!1)})},[m,D,vc,W?.session_id,Io]);let os=z((p)=>{bb(p),_("detail")},[]),rr=z(async(p,u)=>{if(!e||!D){R("no configuration loaded");return}try{let C=Ys(D,{services:p,profile:u}),T=fi(D,C.services,C.profile);Lc("start"),Ac(T.waves.flat().filter((w)=>Mi(W?.services[w]))),Tc(T),Q("plan"),er(!0);let ee=C.services.filter((w)=>!Mi(W?.services[w])),Cr=await e.start({services:ee.length>0?ee:C.services,profile:C.profile});await me(),er(!1),R(Iy(Cr))}catch(C){er(!1),await me(),R(H(C))}},[D,e,me,W]),is=z(async(p)=>{if(!e||!D){R("no configuration loaded");return}let u=p.length>0?p:Object.entries(W?.services??{}).filter(([,C])=>C.state!=="STOPPED"&&C.state!=="UNKNOWN").map(([C])=>C);if(u.length===0){R("nothing to stop");return}try{let C=gi(D,u);Lc("stop"),Ac([]),Tc(C),Q("plan"),er(!0),await e.stop(p),await me(),er(!1),R($y(C))}catch(C){er(!1),await me(),R(H(C))}},[D,e,me,W]),Wo=z(async(p,u)=>{if(!e||!D){R("no configuration loaded");return}try{let C=ny(D,p,u),T=fi(D,C.services,C.profile);Lc("restart"),Ac([]),Tc(T),Q("plan"),er(!0),await e.restart(p),await me(),er(!1),R(Fi(T)===""?"Restarted selected services":`Restarted ${Fi(T)}`)}catch(C){er(!1),await me(),R(H(C))}},[D,e,me]),ss=z(async(p="")=>{let u=F==="log-details"&&Ki?Ay(Ki):Ly(rt),C=p===""?"":` \xB7 ${p}`;if(u.trim()===""){R(`No logs to copy${C}`);return}try{await Cu(u);let T=u.split(`
|
|
618
|
+
`).length,ee=F==="log-details"?"Copied log event":`Copied ${T} log lines`;R(`${ee}${C}`)}catch(T){R(H(T))}},[rt,Ki,F]),Hc=z(()=>{if(!D)return;try{Mb(IE(D.configPath,"utf8")),Ji(""),Q("config-edit")}catch(p){R(H(p))}},[D]),Hb=z(()=>{if(!D)return;let p=Pp.current?.plainText??_c,u=Bn(D.repoRoot,D.configPath,p);if(u.length>0){Ji(u.join(`
|
|
619
|
+
`)),R("Config buffer not saved");return}if($E(D.configPath,p),Ji(""),Q("none"),!e){R(`Wrote ${D.configPath}`);return}e.reload().then((C)=>{if(R(C.restart_required.length===0?"Configuration saved and reloaded":`Saved; restart required: ${C.restart_required.join(", ")}`),C.restart_required.length>0)wr("reload"),Q("confirm");me()})},[D,_c,e,me]),nr=z(async(p,u)=>{if(Rc.current)return;if(Rc.current=!0,p.name!=="start"&&p.name!=="stop"&&p.name!=="restart")Q("none");be("");let C=ky(u,Se);try{switch(p.name){case"exit":wr("quit"),Q("confirm");return;case"help":Q("help");return;case"version":R(Rt());return;case"themes":if(u[0]){Dn(u[0]);return}Ue(Math.max(0,ht.indexOf(c))),be(""),Q("themes");return;case"settings":_("settings"),ue(0);return;case"dashboard":case"services":_(p.name);return;case"logs":if(u[0])vr(u[0]);_("logs");return;case"fullscreen":_("logs"),qi((T)=>m==="logs"?!T:!0);return;case"auth":if(u[0]?.toLowerCase()==="refresh"){_("auth"),await Zi();return}_("auth");return;case"credentials":case"proxy":case"mcp":case"config":case"profiles":case"setup":_(p.name);return;case"reload":if(!e)return;e.reload().then((T)=>{if(R(T.restart_required.length===0?"Configuration reloaded":`Reload requires restart: ${T.restart_required.join(", ")}`),T.restart_required.length>0)wr("reload"),Q("confirm");me()});return;case"doctor":_("doctor");return;case"stats":_("stats");return;case"start":await rr(C,Xe);return;case"stop":await is(C);return;case"restart":await Wo(C,Xe);return;case"refresh":if(m==="auth"){await Zi();return}await me(),R("Refreshed status and logs");return;case"pause":zt((T)=>!T),_("logs");return;case"filter":Xt((T)=>!T),_("logs");return;case"system":Bo(),_("logs");return;case"clear":jo();return;case"reveal":{let T=!_o;wb(T),R(T?"Secrets visible this session":"Secrets hidden");return}case"wrap":{let T=hu(Po);vp(T),R(`Log ${Li(T)}`);return}case"copy":await ss();return;case"export":{let T=ro(u[0]);if(e)await e.logs({export:T,services:Br,level:ut?"ERROR":Ui,search:yr,regex:xr,source:Wr});else na(T,rt);Pc.current=T,R(`Exported ${T}`);return}case"exports":{let T=Pc.current||Vr();oa(T),R(`Opened ${Vr()}`);return}case"regex":Eb((T)=>!T),R(xr?"Substring search":"Regex search");return;case"since":fp(u[0]||new Date(Date.now()-3600000).toISOString()),R(`Logs since ${u[0]||"1h"}`);return;case"until":Cb(u[0]||new Date().toISOString()),R(`Logs until ${u[0]||"now"}`);return;case"history":{let{listSessions:T,loadSessionEvents:ee}=await Promise.resolve().then(() => (gn(),hm)),Cr=T(),w=u[0]||Cr[0];if(!w){R("No persisted log sessions");return}_t(ee(w)),R(`Loaded session ${w}`);return}case"buffer":Hc();return;case"edit":{if(!D)return;let T=process.env.DEVCTL_EDITOR||process.env.EDITOR,ee=T?[T,D.configPath]:process.platform==="darwin"?["open",D.configPath]:["xdg-open",D.configPath];Bun.spawn({cmd:ee,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),R(`Opened ${D.configPath} in ${ee[0]}. Run /reload after saving.`);return}default:R(`/${p.name}`)}}catch(T){R(H(T))}finally{setTimeout(()=>{Rc.current=!1},jE)}},[Wo,rr,is,Se,D,jo,e,ss,ut,rt,Ui,xr,yr,Br,Wr,Po,Hc,Dn,Xe,me,Zi,_o,m,c,Bo]),jb=z(()=>{let p=Pc.current||Vr();oa(p),R(`Opened ${Vr()}`)},[]),jc=z(()=>{let p=Sn(Fo,ce);if(!p){R(ae.trim()===""?"pick a command from the list":`unknown command /${ae}`),Qe();return}let C=Ci(ae)?.name===p.name?vh(ae):[];nr(p,C)},[Qe,Fo,ae,nr,ce]),Fp=z((p)=>{Dn(p),Qe()},[Qe,Dn]),Bb=z((p)=>{let u=Ci(p);if(u)nr(u,[])},[nr]),Np=z(()=>{if(F==="palette"){let p=Sn(Ln,Je);if(p)nr(p,[]);return}jc()},[F,Je,Ln,nr,jc]),Wb=z(()=>{if(D?.shutdown.stop_services_on_exit===void 0){wr("quit"),Q("confirm");return}r(D.shutdown.stop_services_on_exit===!1)},[D,r]),Gb=z(()=>{if(Gr==="quit"){r(!1);return}if(Gr==="reload"){Qe();let p=W?.restart_required??[];if(p.length>0)Wo(p,Xe);return}if(Gr==="reset-prefs"){Qe(),Mp();return}if(Gr==="free-port"){let p=up;if(Qe(),!p)return;$s(p).then(()=>{R(`Stopped ${p.command} (pid ${p.pid}) on port ${p.port}`),xc((u)=>u+1)}).catch((u)=>{R(H(u))});return}Qe(),rr([],Xe)},[Mp,Wo,rr,Qe,Gr,r,up,Xe,W]),Ub=z(()=>{if(m==="logs"){let u=kr[Z];if(u)yp(u),Q("log-details");return}if(m==="profiles"){let C=Object.keys(D?.profiles??{}).sort()[Z];if(C)bc(C),wr("start-profile"),Q("confirm");return}if(m==="doctor"){let u=Rn?.checks[Z];if(u?.action?.kind==="free-port"){let C=u.action.holder;xb(C),vb({port:C.port,pid:C.pid,process:C.command}),wr("free-port"),Q("confirm")}return}if(m==="mcp"){if(Z===0){ts();return}if(Z===1){Mn();return}let u=gc(Z);if(u){Fc(u);return}rs(Z);return}if(m==="settings"){let u=uo(lt,Z);if(u)$c(u);return}if(m==="dashboard"&&yo(W)){rr([],Xe);return}let p=it[Z];if(p&&(m==="dashboard"||m==="services"))os(p)},[$c,Mn,rr,D,rs,Rn,Z,kr,it,os,Xe,m,lt,W,ts]);NE((p)=>{let u=(p.name??"").toLowerCase(),C=xv(p,t),T=vv(p,t);if(C&&!T){if(m==="mcp"&&rs(Z))return;ss();return}if(T){let w=Date.now();if(bv(w,Dc.current)){Dc.current=0,Wb();return}Dc.current=w;let ie="Ctrl+C again to quit";if(C)ss(ie);else R(`Press ${ie}`);return}if(p.ctrl&&(u==="="||u==="+"||u==="plus")){Ur(Ea(P,1));return}if(p.ctrl&&(u==="-"||u==="_"||u==="minus")){Ur(Ea(P,-1));return}if(p.ctrl&&u==="0"){Ur(tu().font_size);return}if(F==="confirm"){if(u==="escape"){Qe();return}if(Gr==="quit"&&u==="d"){r(!0);return}if(u==="return")Gb();return}if(F==="log-details"){if(u==="escape"){Qe();return}if(u==="down"||u==="j"){We(Do.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(Do.current,-t.scroll_speed);return}if(rc(p)){We(Do.current,Di(a));return}if(nc(p)){We(Do.current,-Di(a));return}return}if(F==="route-details"){if(u==="escape"||u==="return"){Qe();return}if(u==="down"||u==="j"){We(kc.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(kc.current,-t.scroll_speed);return}return}if(F==="plan"){if(u==="escape"||u==="return"&&!Ep){Qe();return}if(u==="down"||u==="j"){We(Cc.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(Cc.current,-t.scroll_speed);return}return}if(F==="help"){if(u==="escape"){Qe();return}if(u==="down"||u==="j"){We(Ao.current,1);return}if(u==="up"||u==="k"){We(Ao.current,-1);return}if(u==="pagedown"||rc(p)){We(Ao.current,Du);return}if(u==="pageup"||nc(p)){We(Ao.current,-Du);return}return}if(F==="themes"){if(u==="escape"){Nb(),Qe();return}if(u==="down"||u==="j"){Ue((w)=>{let ie=Math.min(w+1,ht.length-1),or=ht[ie];if(or)l(or);return ie});return}if(u==="up"||u==="k"){Ue((w)=>{let ie=Math.max(0,w-1),or=ht[ie];if(or)l(or);return ie});return}if(u==="return"){let w=ht[Je%ht.length];if(w)Fp(w)}return}if(F==="leader"){if(Oo.current)clearTimeout(Oo.current);Q("none");let w=xh(u),ie=w?Ci(w):void 0;if(ie)nr(ie,[]);return}if(F==="config-edit"){if(u==="escape"){Ji(""),Qe();return}if(p.ctrl&&u==="s"){Hb();return}return}if(dv(F)){if(u==="escape"){Qe();return}if(F==="slash"&&u==="down"){Ie((w)=>Math.min(Math.max(Fo.length-1,0),w+1));return}if(F==="slash"&&u==="up"){Ie((w)=>Math.max(0,w-1));return}if(F==="slash"&&u==="tab"){if(p.shift){Ie((ie)=>Math.max(0,ie-1));return}let w=Sn(Fo,ce);if(w)be(`${w.name} `);return}if(F==="slash"&&u==="return"){jc();return}if(F==="palette"&&u==="down"){Ue((w)=>Math.min(w+1,Math.max(Ln.length-1,0)));return}if(F==="palette"&&u==="up"){Ue((w)=>Math.max(0,w-1));return}if(F==="palette"&&u==="return"){let w=Sn(Ln,Je);if(w)nr(w,[])}return}if(Wi){if(u==="escape")wc(!1);return}if(uv(p,t)){Q("leader"),Oo.current=setTimeout(()=>Q("none"),x);return}if(pv(p,t)){be(""),Ue(0),Q("palette");return}if(fv(p,t)){be(""),Ie(0),Q("slash");return}if(gv(p,t)){Q("help");return}if(mv(p,t)||m==="logs"&&u==="f"&&!p.ctrl&&!p.meta){_("logs"),wc(!0);return}if(u==="escape"){if(Eo){qi(!1);return}if(m==="detail"){_("services");return}if(m==="setup")if(e)_("dashboard");else r(!0);return}if(u==="z"&&(m==="logs"||m==="dashboard")&&!p.ctrl&&!p.meta){_("logs"),qi((w)=>m==="logs"?!w:!0);return}let ee=(m==="logs"||m==="dashboard")&&!Wi;if(ee&&(u==="left"||u==="["||m==="logs"&&u==="h")){vr(wu($o,Wt,-1));return}if(ee&&(u==="right"||u==="]"||m==="logs"&&u==="l")){vr(wu($o,Wt,1));return}if(m==="logs"&&!Wi&&u.length===1&&u>="1"&&u<="9"){let w=Oy($o,Fe,Number(u));if(w!==void 0)vr(w);return}if(u==="tab"){_(p.shift?Gy(m):Wy(m));return}let Cr=iy(u);if(Cr){_(Cr);return}if((m==="dashboard"||m==="setup")&&u==="o"){_("profiles");return}if((m==="dashboard"||m==="services")&&(u==="*"||p.shift&&u==="8")){Ce([...it]),R(`Selected ${it.length} services`);return}if((m==="dashboard"||m==="services")&&(u==="-"||u==="_"||u==="minus")){Ce([]),R("Selection cleared");return}if((m==="dashboard"||m==="services")&&u==="n"){rr(Ja(Se,it[Z]??""),Xe);return}if((m==="dashboard"||m==="services")&&u==="x"){is(Ja(Se,it[Z]??""));return}if((m==="dashboard"||m==="services"||m==="detail")&&hv(p)){Wo(Ja(Se,it[Z]??Tn),Xe);return}if((m==="dashboard"||m==="services")&&u==="r"){me(),R("Refreshed");return}if(m==="auth"&&u==="r"){Zi();return}if(m==="logs"&&u==="t"){let w=!gp;_b(w),qe({log_timestamps:w},w?"timestamps on":"timestamps off");return}if(m==="logs"&&u==="m"){let w=!mp;Pb(w),qe({log_metadata:w},w?"metadata on":"metadata off");return}if(u==="down"||u==="j"){if(m==="mcp"&&Z===1)Mn();if(m==="config"){We(To.current,t.scroll_speed);return}if(m==="detail"){We(Lo.current,t.scroll_speed);return}if(m==="logs"){No(Z+1);return}if(m==="dashboard"&&Zt>=0){Xi(Zt+1);return}ue((w)=>Math.min(Math.max(tr-1,0),w+1));return}if(u==="up"||u==="k"){if(m==="mcp"&&Z===1)Mn();if(m==="config"){We(To.current,-t.scroll_speed);return}if(m==="detail"){We(Lo.current,-t.scroll_speed);return}if(m==="logs"){No(Z-1);return}if(m==="dashboard"&&Zt>=0){Xi(Zt-1);return}ue((w)=>Math.max(0,Math.min(w,Math.max(tr-1,0))-1));return}if(rc(p)){let w=Di(a);if(m==="config"){We(To.current,w);return}if(m==="detail"){We(Lo.current,w);return}if(m==="logs"){No(Z+w);return}if(m==="dashboard"&&(xt||Zt>=0)){Xi(Math.max(0,Zt)+w);return}ue((ie)=>Math.min(Math.max(tr-1,0),ie+w));return}if(nc(p)){let w=Di(a);if(m==="config"){We(To.current,-w);return}if(m==="detail"){We(Lo.current,-w);return}if(m==="logs"){No(Z-w);return}if(m==="dashboard"&&(xt||Zt>=0)){Xi(Math.max(0,Zt)-w);return}ue((ie)=>Math.max(0,ie-w));return}if(m==="proxy"&&u==="n"){e?.proxyStart().then(async()=>{R("Proxy started"),await me()});return}if(m==="proxy"&&u==="x"){e?.proxyStop().then(async()=>{R("Proxy stopped"),await me()});return}if(m==="detail"&&Tn!==""){if(u==="n"){rr([Tn],Xe);return}if(u==="x"){is([Tn]);return}if(u==="o"){_("config");return}if(u==="l"){vr(Tn),_("logs");return}}if(m==="mcp"&&Z===1&&(u==="left"||u==="h")){let w=hn(Mn()-1);es(w),Ip(w);return}if(m==="mcp"&&Z===1&&(u==="right"||u==="l")){let w=hn(Mn()+1);es(w),Ip(w);return}if(m==="mcp"&&Z===1&&(u==="backspace"||u==="delete")){Ec((w)=>oh(w));return}if(m==="mcp"&&Z===1&&u.length===1&&u>="0"&&u<="9"){Ec((w)=>nh(w,u));return}if(m==="settings"&&(u==="left"||u==="h")){Op(-1);return}if(m==="settings"&&(u==="right"||u==="l")){Op(1);return}if(u==="space"){if(m==="profiles"){let or=Object.keys(D?.profiles??{}).sort()[Z];if(or)bc(or),R(`Profile ${or}`);return}if(m==="mcp"){if(Z===0){ts();return}let ie=gc(Z);if(ie){Fc(ie);return}rs(Z);return}if(m==="logs")return;if(m==="settings"){if(uo(lt,Z)?.id==="mouse")Ho();return}let w=it[Z];if(w)Ic(w);return}if(u==="return"){if(m==="setup"&&!e){if(!o){R(n||"Existing configuration is invalid \u2014 fix it and restart devctl.");return}Promise.resolve().then(() => (gd(),em)).then(({createStarterConfig:w})=>{try{let ie=w(process.cwd());R(`Wrote ${ie}. Restart devctl or run the CLI wizard.`)}catch(ie){R(H(ie))}});return}if(m==="setup"&&e){rr([],Xe);return}Ub();return}if(u==="q"){if(D?.shutdown.stop_services_on_exit===!1){r(!0);return}if(D?.shutdown.stop_services_on_exit===!0){r(!1);return}wr("quit"),Q("confirm");return}if(Or(p,t,"services","s")&&F==="none"&&m!=="logs"){_("services");return}if(Or(p,t,"logs","l")&&F==="none"&&m!=="detail"&&m!=="logs"&&m!=="settings"){_("logs");return}if(Or(p,t,"auth","a")&&F==="none"){_("auth");return}if(Or(p,t,"proxy","p")&&F==="none"&&m!=="logs"){_("proxy");return}if(Or(p,t,"doctor","d")&&F==="none"&&m!=="doctor"){_("doctor");return}if(Or(p,t,"config","c")&&F==="none"){_("config");return}if(Or(p,t,"setup","u")&&F==="none"){_("setup");return}if(m==="config"&&u==="e"){nr(Ci("/edit")??{name:"edit",aliases:[],desc:"",leader:"",group:"ui"},[]);return}if(m==="config"&&u==="v"){Hc();return}if(m==="doctor"&&u==="r"){xc((w)=>w+1),R("Re-running doctor");return}if(m==="logs"&&u==="p"){zt((w)=>!w);return}if((m==="logs"||m==="dashboard")&&u==="g"){Oc();return}if((m==="logs"||m==="dashboard")&&u==="w"){let w=hu(Po);vp(w),R(`Log ${Li(w)}`);return}if((m==="logs"||m==="dashboard")&&u==="e"){Xt((w)=>!w);return}if((m==="logs"||m==="dashboard")&&u==="i"){Bo(),R(pt?"Hiding internal auth/mcp/devctl/proxy logs":"Showing internal logs");return}if((m==="logs"||m==="dashboard")&&yv(p))jo()});let Hp=Xy(Gr,Xe,yb),Kb=new Set(zi?.waves.flat()??[]),qb=zi===void 0||Tp==="stop"?"":Object.entries(W?.services??{}).find(([p,u])=>Kb.has(p)&&u.state==="FAILED")?.[0]??"";return oe(ou.Provider,{value:Ei(P),children:oe("box",{flexDirection:"column",width:s,height:a,backgroundColor:k,overflow:"hidden",children:[Eo?null:oe(GE,{children:[oe(nv,{palette:y,cfg:D,snap:W,google:Qt,profile:Xe,reveal:_o,width:s},void 0,!1,void 0,this),oe(ov,{palette:y,screen:m,width:s,onSelect:_},void 0,!1,void 0,this),Io?oe("box",{height:1,paddingLeft:1,backgroundColor:y.panel,overflow:"hidden",children:oe("text",{fg:y.error,wrapMode:"none",children:`\u26A0 configuration reload failed: ${Io}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),oe("box",{flexGrow:1,overflow:"hidden",children:[m==="dashboard"?oe(kx,{palette:y,cfg:D,snap:W,logs:Fe,names:it,selected:Z,checked:Se,profile:Xe,google:Qt,width:s,paused:dt,followTick:pp,logService:Wt,errorOnly:ut,showSystemLogs:pt,onOpen:os,onSelectIndex:ue,selectedLog:Zt,onToggle:Ic,logSources:$o,onFilterService:vr,onToggleErrors:()=>Xt((p)=>!p),onToggleSystemLogs:Bo,onClearLogs:jo,onShowErrors:()=>{vr(""),Xt(!0)},wrapMode:Po,view:kr,follow:!xt,onLeaveLatest:Mc,onPickLog:(p)=>{let u=kr[p];if(!u)return;Vi(p),yp(u),Mc()},viewStart:Ne.start,viewTotal:rt.length,newer:Ne.newer,onJumpLatest:Oc,facets:xp},void 0,!1,void 0,this):null,m==="services"?oe(Bx,{palette:y,cfg:D,names:it,snap:W,selected:Z,checked:Se,width:s,reveal:_o,onOpen:os,onSelectIndex:ue,onToggle:Ic},void 0,!1,void 0,this):null,m==="detail"?oe(jx,{palette:y,cfg:D,snap:W,name:Tn,reveal:_o,width:s,envScrollRef:Lo},void 0,!1,void 0,this):null,m==="logs"?oe(wx,{palette:y,logs:Fe,names:it,logSources:$o,service:Wt,paused:dt,errorOnly:ut,showSystemLogs:pt,search:yr,searchFocused:Wi,followTick:pp,width:s,onSearch:Sb,onService:vr,onToggleErrors:()=>Xt((p)=>!p),onToggleSystemLogs:Bo,onClearLogs:jo,source:Wr,regex:xr,services:Br,showTimestamps:gp,showMeta:mp,view:kr,wrapMode:Po,selected:Z,follow:!xt,newer:Ne.newer,viewStart:Ne.start,viewTotal:rt.length,onSelect:No,fullscreen:Eo,onLeaveLatest:Mc,onOpenExports:jb,onJumpLatest:Oc,facets:xp},void 0,!1,void 0,this):null,m==="auth"?oe(Qv,{palette:y,cfg:D,google:Qt,identity:W?.identity},void 0,!1,void 0,this):null,m==="credentials"?oe(ex,{palette:y,credentials:W?.credentials},void 0,!1,void 0,this):null,m==="proxy"?oe($x,{palette:y,cfg:D,snap:W,width:s,onSelectRoute:(p)=>{Ab(p),Q("route-details")}},void 0,!1,void 0,this):null,m==="mcp"?oe(rb,{palette:y,snap:W,port:Sr,portDraft:Yi,selected:Z,onPick:ue,onToggle:()=>{ts()},onCopy:Nc,onToggleTool:(p)=>{Fc(p)}},void 0,!1,void 0,this):null,m==="doctor"?oe(Px,{palette:y,report:Rn,loading:yc,progress:hb,error:mb,selected:Z,onPick:ue,onReload:()=>{xc((p)=>p+1),R("Re-running doctor")}},void 0,!1,void 0,this):null,m==="stats"?oe(Yx,{palette:y,cfg:D,snap:W,width:s,onRefresh:me},void 0,!1,void 0,this):null,m==="config"?oe(vx,{palette:y,cfg:D,width:s,scrollRef:To},void 0,!1,void 0,this):null,m==="profiles"?oe(Tx,{palette:y,cfg:D,snap:W,profile:Xe,selected:Z,onPick:ue},void 0,!1,void 0,this):null,m==="setup"?oe(Xx,{palette:y,cfg:D,google:Qt,bootError:n,bootErrorMissing:o,step:Z},void 0,!1,void 0,this):null,m==="settings"?oe(qx,{palette:y,items:lt,selected:Z,locked:U,width:s,onPick:ue,onActivate:$c},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),F==="slash"?oe(Kv,{palette:y,items:Fo,query:ae,selected:ce,onQuery:be,onSubmit:Np},void 0,!1,void 0,this):null,F==="palette"?oe(Fv,{palette:y,items:Ln,selected:Math.min(Je,Math.max(Ln.length-1,0)),termW:s,termH:a,onIndex:Ue,onPick:Bb},void 0,!1,void 0,this):null,F==="themes"?oe(zv,{palette:y,themeName:c,selected:Je%ht.length,termW:s,termH:a,onIndex:Ue,onPreview:l,onPick:Fp},void 0,!1,void 0,this):null,F==="help"?oe(Lv,{palette:y,termW:s,termH:a,copyKey:Lp,scrollRef:Ao},void 0,!1,void 0,this):null,F==="leader"?oe(Ov,{palette:y,termW:s,termH:a},void 0,!1,void 0,this):null,F==="confirm"?oe(Cv,{palette:y,title:Hp.title,body:Hp.body,termW:s,termH:a},void 0,!1,void 0,this):null,F==="log-details"?oe(Pv,{palette:y,event:Ki,termW:s,termH:a,scrollRef:Do},void 0,!1,void 0,this):null,F==="route-details"?oe(Wv,{palette:y,route:Tb,termW:s,termH:a,scrollRef:kc},void 0,!1,void 0,this):null,F==="config-edit"&&D?oe(Sv,{palette:y,path:D.configPath,initialValue:_c,error:Ob,termW:s,termH:a,textareaRef:Pp},void 0,!1,void 0,this):null,F==="plan"&&zi?oe(jv,{palette:y,plan:zi,snap:W,busy:Ep,failed:qb,kind:Tp,termW:s,termH:a,scrollRef:Cc,initiallyRunning:Ib,onDismiss:Qe},void 0,!1,void 0,this):null,F==="slash"||F==="plan"||F==="config-edit"||Eo||ty(a)&&F==="none"?null:oe(iv,{palette:y,overlay:F,query:ae,onQuery:be,onSubmit:Np},void 0,!1,void 0,this),Eo?null:oe(sv,{palette:y,screen:m,overlay:F,status:mc,paused:dt,errorOnly:ut,width:s,copyKey:Lp},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var jE=50,BE,WE=2000;var ib=A(()=>{St();ui();ii();on();_e();gn();Ye();un();ha();kt();lv();Re();wv();ve();kv();_v();Rv();Dv();Iv();Nv();Bv();Gv();qv();Xv();Zv();tx();xx();Cx();Rx();Bu();Ax();Fx();Vu();Wx();Vx();zx();Qx();nb();vi();ot();pr();ze();Vt();BE=[]});var sb={};as(sb,{renderApp:()=>np,runTui:()=>rp,runTuiWithController:()=>qE,tuiConfigFor:()=>VE});import{createCliRenderer as UE}from"@opentui/core";import{createRoot as KE}from"@opentui/react";import{jsxDEV as JE}from"@opentui/react/jsx-dev-runtime";async function qE(e){let t=qt(e.cfg.repoRoot,e.cfg.ui.keymap);await np(e,t)}async function rp(e){let t,r,n=!1;try{t=await gg("",e)}catch(i){r=H(i),n=us(i,Kr)}let o=qt(t?.cfg.repoRoot??process.cwd(),t?.cfg.ui.keymap);await np(t,o,r,n)}async function np(e,t=qt(e?.cfg.repoRoot??process.cwd(),e?.cfg.ui.keymap),r,n=!1){cs();let o=Gp(),i=await UE({exitOnCtrlC:!1,useMouse:t.mouse,enableMouseMovement:t.mouse,useKittyKeyboard:{}}),s=KE(i),a=null;try{a=(await i.getPalette({timeout:120,size:16})).defaultBackground}catch{}await new Promise((c)=>{let l=(d)=>{let g=()=>{s.unmount(),o(),i.destroy(),c(),process.exit(0)};if(!e){g();return}e.close({detach:d,shutdownSupervisor:!0}).finally(g)};s.render(JE(ob,{controller:e,tui:t,onQuit:l,bootError:r,bootErrorMissing:n,terminalBackground:a},void 0,!1,void 0,this))})}function VE(e){return qt(e.repoRoot,e.ui.keymap)}var op=A(()=>{Ol();_e();ib();Bc();Vt()});In();Bc();St();Ol();Ye();ui();_e();on();St();ci();un();gd();import{Command as XE}from"commander";import{setTimeout as ap}from"timers/promises";import{stringify as QE}from"yaml";import{existsSync as ub,readFileSync as ZE}from"fs";St();Ll();_e();on();import{createServer as J0}from"net";import{existsSync as jd,unlinkSync as Y0,watch as z0}from"fs";import{cpus as X0,loadavg as Q0,platform as Z0,uptime as e_}from"os";import{isAbsolute as dh,join as Bd}from"path";Ye();un();import{connect as rC}from"net";var nC=2000,oC=2000,iC=200,sC=300;function tm(e){if(e.interval_seconds<=0)return oC;return e.interval_seconds*1000}async function rm(e,t,r,n,o,i=[]){let s=e.timeout_seconds>0?e.timeout_seconds*1000:nC,a=e.type.toLowerCase(),c=i.find((l)=>l.name.toLowerCase()===a);if(c)try{let l=await c.check(e,{pid:t,ports:r,workDir:n,env:o});return{status:l.status,message:l.message}}catch(l){return{status:Le,message:l instanceof Error?l.message:String(l)}}if(a==="http")return aC(e.url,s);if(a==="tcp")return lC(cC(e.address,r),s);if(a==="command")return dC(e.command.args,e.command.shell,n,o,s);if(a==="process"||a===""){if(t>0&&Pt(t))return{status:Et,message:"process running"};return{status:Le,message:"process not running"}}return{status:Le,message:`unknown health type ${e.type}`}}async function aC(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),t);try{let o=await fetch(e,{signal:r.signal});if(o.status>=iC&&o.status<sC)return{status:Et,message:String(o.status)};return{status:Le,message:String(o.status)}}catch(o){return{status:Le,message:o instanceof Error?o.message:String(o)}}finally{clearTimeout(n)}}function cC(e,t){if(e!=="")return e;if(t.http!==void 0)return`127.0.0.1:${t.http}`;let r=Object.values(t)[0];return r!==void 0?`127.0.0.1:${r}`:""}function lC(e,t){return new Promise((r)=>{if(e===""){r({status:Le,message:"no tcp address"});return}let n=rC(e,()=>{n.end(),r({status:Et,message:"connected"})});n.setTimeout(t),n.on("error",(o)=>{r({status:Le,message:o.message})}),n.on("timeout",()=>{n.destroy(),r({status:Le,message:"timeout"})})})}async function dC(e,t,r,n,o){if(e.length===0)return{status:Le,message:"empty health command"};let i=t?process.platform==="win32"?["cmd.exe","/c",e.join(" ")]:["/bin/sh","-c",e.join(" ")]:e,s;try{s=Bun.spawn({cmd:i,cwd:r===""?void 0:r,env:n,stdout:"ignore",stderr:"ignore"})}catch(l){return{status:Le,message:l instanceof Error?l.message:String(l)}}let a=setTimeout(()=>s.kill("SIGKILL"),o),c=await s.exited;if(clearTimeout(a),c===0)return{status:Et,message:"ok"};return{status:Le,message:`exit ${c}`}}function nm(e){if(e===Le)return"WARN";if(e===Et)return"INFO";return"DEBUG"}import{readFileSync as uC}from"fs";import{freemem as pC,totalmem as fC}from"os";import{spawnSync as gC}from"child_process";var md=1024,mC=2000,hC=/page size of (\d+) bytes/i,to;function yC(e){let t=e.match(/^MemAvailable:\s+(\d+)/m);if(!t)return;let r=Number(t[1]);return Number.isFinite(r)&&r>=0?r:void 0}function vC(e){let t=e.match(hC),r=t?Number(t[1]):0;if(!Number.isFinite(r)||r<=0)return;let n=Xs(e,"free")+Xs(e,"inactive")+Xs(e,"speculative")+Xs(e,"purgeable");return Math.round(n*r/md)}function Xs(e,t){let r=e.match(new RegExp(`Pages ${t}:\\s+(\\d+)`,"i")),n=r?Number(r[1]):0;return Number.isFinite(n)&&n>0?n:0}function xC(){if(process.platform==="linux")try{return yC(uC("/proc/meminfo","utf8"))}catch{return}if(process.platform==="darwin"){let e=Date.now();if(to&&e-to.at<mC)return to.leftoverKB;let t=gC("vm_stat",{encoding:"utf8"});if(t.status!==0||!t.stdout)return to?.leftoverKB;let r=vC(t.stdout);if(r===void 0)return to?.leftoverKB;return to={at:e,leftoverKB:r},r}return}function om(){let e=Math.max(0,Math.round(fC()/md)),t=Math.max(0,Math.round(pC()/md)),r=Math.max(0,Math.min(e,xC()??t));return{totalKB:e,unusedKB:t,leftoverKB:r}}nn();gn();ii();gn();import{pathToFileURL as YC}from"url";St();_e();nn();import{createServer as wm,request as WC}from"http";import{randomBytes as ym}from"crypto";import{Readable as GC}from"stream";var hi="x-devctl-request-id",UC="x-devctl-internal-token",vm=100,Td=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]),KC=new Set(["gzip","deflate","br"]);class Ad{cfg;tokens;logs;bus;detector;middleware;server;running=!1;addr="";upgradedSockets=new Set;recentRequests=[];constructor(e,t,r,n,o,i=[]){this.cfg=e,this.tokens=t,this.logs=r,this.bus=n,this.detector=o,this.middleware=i}address(){return this.addr||Yr(this.cfg.listen)}isRunning(){return this.running}stats(){let e=this.recentRequests.reduce((t,r)=>t+(r.status>=400||r.error?1:0),0);return{total:this.recentRequests.length,errors:e,recent:[...this.recentRequests].reverse()}}recordRequest(e){if(this.recentRequests.push(e),this.recentRequests.length>vm)this.recentRequests.splice(0,this.recentRequests.length-vm)}start(){if(this.cfg.listen.host==="0.0.0.0")return Promise.reject(M(_r,"refusing to bind proxy to 0.0.0.0 without explicit unsafe configuration"));let e=this.cfg.listen.host||"127.0.0.1";if(this.cfg.listen.port===0)return Promise.reject(M(_r,"proxy.listen.port is required when the proxy is enabled"));let t=this.cfg.listen.port;return new Promise((r,n)=>{this.server=wm((o,i)=>{this.serve(o,i)}),this.server.on("upgrade",(o,i,s)=>{this.serveUpgrade(o,i,s)}),this.server.on("error",(o)=>n(ye(_r,`unable to listen on ${e}:${t}`,o))),this.server.listen(t,e,()=>{this.running=!0,this.addr=`${e}:${t}`,this.bus?.publish(Ae(Og,"",{address:this.addr})),r()})})}stop(){let e=this.server;if(!e)return Promise.resolve();for(let t of this.upgradedSockets)t.destroy();return this.upgradedSockets.clear(),new Promise((t)=>{e.close(()=>{this.running=!1,this.bus?.publish(Ae(Ig,"",{})),t()})})}async serveUpgrade(e,t,r){let n=Date.now(),o=e.headers[hi]?.toString()||ym(8).toString("hex"),i=e.method??"GET",s=e.url??"/",a=this.detector?this.detector.redactText(s):s,c=bm(this.cfg.routes,e);if(!c){t.end(`HTTP/1.1 404 Not Found\r
|
|
620
|
+
Connection: close\r
|
|
621
|
+
Content-Length: 0\r
|
|
622
|
+
\r
|
|
623
|
+
`),this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:"",identity:"",status:404,durationMs:Date.now()-n});return}let l=rn(c.auth),d=Gn(l),g,f=!1,h=(v,b)=>{if(f)return;f=!0;let P=Date.now()-n;this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:c.name,identity:d,status:v,durationMs:P,error:b}),this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:v>=400||b?"ERROR":"INFO",message:`${i} ${s} route=${c.name} identity=${d} status=${v} duration=${P}ms upgrade=true${b?` error=${b}`:""}`,pid:0,request_id:o,identity:d}),this.bus?.publish(Ae(ed,c.name,{status:v,request_id:o,duration:P,identity:d}))},x=()=>{t.destroy(),g?.destroy()};try{let v={};for(let[y,k]of Object.entries(e.headers)){let m=y.toLowerCase();if(Td.has(m)&&m!=="connection"&&m!=="upgrade")continue;if(typeof k==="string")v[y]=k;else if(Array.isArray(k))v[y]=k.join(",")}let b=e.socket.remoteAddress??"",P=v.host??"",S=v["x-forwarded-for"];if(v["x-forwarded-for"]=S?`${S}, ${b}`:b,v["x-forwarded-host"]=P,v["x-forwarded-proto"]="http",delete v.host,v[hi]=o,this.middleware.length===0)await ia(c,v,this.tokens);for(let y of this.middleware)await y.apply({route:c,headers:v,tokens:this.tokens,req:e,method:i,path:s,upgrade:!0});let N=xm(c.upstream.url,s),U=WC(N,{method:i,headers:v});U.on("upgrade",(y,k,m)=>{g=k,this.upgradedSockets.add(t),this.upgradedSockets.add(k);let _=()=>{this.upgradedSockets.delete(t),this.upgradedSockets.delete(k)};t.once("close",()=>{_(),k.destroy()}),k.once("close",()=>{_(),t.destroy()}),t.once("error",x),k.once("error",x);let F=`HTTP/${y.httpVersion} ${y.statusCode??101} ${y.statusMessage??"Switching Protocols"}\r
|
|
624
|
+
`,Q=y.rawHeaders.map((ae,be)=>`${be%2===0?ae+":":" "+ae+`\r
|
|
625
|
+
`}`).join("");if(t.write(`${F}${Q}\r
|
|
626
|
+
`),r.length>0)k.write(r);if(m.length>0)t.write(m);t.pipe(k).pipe(t),h(y.statusCode??101)}),U.on("response",(y)=>{y.resume();let k=y.statusCode??502;t.end(`HTTP/1.1 ${k} ${y.statusMessage??"Bad Gateway"}\r
|
|
627
|
+
Connection: close\r
|
|
628
|
+
Content-Length: 0\r
|
|
629
|
+
\r
|
|
630
|
+
`),h(k,"upstream refused protocol upgrade")}),U.on("error",(y)=>{h(502,y.message),t.end(`HTTP/1.1 502 Bad Gateway\r
|
|
631
|
+
Connection: close\r
|
|
632
|
+
Content-Length: 0\r
|
|
633
|
+
\r
|
|
634
|
+
`)}),t.once("error",()=>U.destroy()),U.end()}catch(v){let b=v instanceof Error?v.message:"proxy upgrade error";h(502,b),t.end(`HTTP/1.1 502 Bad Gateway\r
|
|
635
|
+
Connection: close\r
|
|
636
|
+
Content-Length: 0\r
|
|
637
|
+
\r
|
|
638
|
+
`)}}async serve(e,t){let r=Date.now(),n=e.headers[hi]?.toString()||ym(8).toString("hex");t.setHeader(hi,n);let o=e.method??"GET",i=e.url??"/",s=this.detector?this.detector.redactText(i):i,a=bm(this.cfg.routes,e);if(!a){no(t,404,"no matching proxy route"),this.recordRequest({timestamp:new Date().toISOString(),requestId:n,method:o,path:s,route:"",identity:"",status:404,durationMs:Date.now()-r});return}let c=rn(a.auth),l=Gn(c),d=0,g;try{let f={};for(let[k,m]of Object.entries(e.headers)){if(Td.has(k.toLowerCase()))continue;if(typeof m==="string")f[k]=m;else if(Array.isArray(m))f[k]=m.join(",")}let h=e.socket.remoteAddress??"",x=f.host??"",v=f["x-forwarded-for"];if(f["x-forwarded-for"]=v?`${v}, ${h}`:h,f["x-forwarded-host"]=x,f["x-forwarded-proto"]="http",delete f.host,f["accept-encoding"]="gzip, deflate, br",f[hi]=n,this.middleware.length===0)await ia(a,f,this.tokens);for(let k of this.middleware)await k.apply({route:a,headers:f,tokens:this.tokens});let b=xm(a.upstream.url,i),P=o!=="GET"&&o!=="HEAD"?e:void 0,S=await fetch(b,{method:o,headers:f,body:P,redirect:"manual",duplex:P?"half":void 0});t.statusCode=S.status,d=S.status;let N=(S.headers.get("content-encoding")??"").split(",").map((k)=>k.trim().toLowerCase()).filter((k)=>k!==""),U=N.length>0&&N.every((k)=>KC.has(k));S.headers.forEach((k,m)=>{let _=m.toLowerCase();if(Td.has(_))return;if(U&&(_==="content-encoding"||_==="content-length"))return;t.setHeader(m,this.detector?this.detector.redactText(k):k)}),await qC(S,t);let y=Date.now()-r;this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:S.status>=400?"WARN":"INFO",message:`${o} ${i} route=${a.name} identity=${l} status=${S.status} duration=${y}ms`,pid:0,request_id:n,identity:l}),this.bus?.publish(Ae(ed,a.name,{status:S.status,request_id:n,duration:y,identity:l}))}catch(f){let h=f instanceof Error?f.message:"proxy error";g=h,d=502,this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:"ERROR",message:`${o} ${i} route=${a.name} identity=${l} error=${h}`,pid:0,request_id:n,identity:l}),no(t,502,"proxy error")}finally{this.recordRequest({timestamp:new Date().toISOString(),requestId:n,method:o,path:s,route:a.name,identity:l,status:d,durationMs:Date.now()-r,error:g})}}}async function ia(e,t,r){let n=e.auth.type.toLowerCase();if(n===""||n==="none")return;if(!r)throw M(_r,"token manager unavailable");let o=rn(e.auth),i=await r.get(Gn(o),e.auth.audience,[]);t.authorization=`Bearer ${i.accessToken}`}async function qC(e,t){if(!e.body){t.end();return}let r=GC.fromWeb(e.body);await new Promise((n,o)=>{r.on("error",o),t.on("error",o),t.on("finish",n),r.pipe(t)})}function xm(e,t){let r=new URL(e),n=new URL(t||"/",r),o=new URL(r.href);if(o.pathname=VC(n.pathname),o.search=n.search,o.hash="",o.origin!==r.origin)throw M(_r,"refusing to proxy to a different origin");return o}function VC(e){return(e.startsWith("/")?e:`/${e}`).replace(/^\/+/,"/")}function no(e,t,r){e.statusCode=t,e.setHeader("content-type","text/plain; charset=utf-8"),e.setHeader("x-content-type-options","nosniff"),e.end(r)}function bm(e,t){let r=(t.headers.host??"").split(":")[0]??"",n=t.url??"/";return e.find((o)=>{let i=o.match.host===""||o.match.host===r,s=o.match.path===""||n.startsWith(o.match.path);return i&&s})}class Ld{host;port;secret;tokens;server;constructor(e,t,r,n){this.host=e;this.port=t;this.secret=r;this.tokens=n}listenPort(){let e=this.server?.address();if(typeof e==="object"&&e)return e.port;return this.port}start(){let e=this.host||"127.0.0.1";if(e==="0.0.0.0")return Promise.reject(M(_r,"refusing to bind token endpoint to 0.0.0.0"));return new Promise((t,r)=>{this.server=wm((n,o)=>{this.serve(n,o)}),this.server.on("error",(n)=>r(ye(_r,"token endpoint listen failed",n))),this.server.listen(this.port,e,()=>t())})}stop(){let e=this.server;if(!e)return Promise.resolve();return new Promise((t)=>e.close(()=>t()))}async serve(e,t){if(!JC(e.socket.remoteAddress)){no(t,403,"forbidden");return}if((e.headers[UC]??"")!==this.secret){no(t,401,"unauthorized");return}if(e.url?.startsWith("/token")!==!0){no(t,404,"not found");return}let r=new URL(e.url,"http://127.0.0.1"),n=r.searchParams.get("identity")??"user",o=r.searchParams.get("audience")??"";try{let i=await this.tokens.get(n,o,[]);t.setHeader("content-type","application/json"),t.end(JSON.stringify({access_token:i.accessToken,token_type:i.tokenType,expires_at:i.expiresAt.toISOString(),identity:i.identity}))}catch{no(t,500,"token error")}}}function JC(e){if(!e)return!0;return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}ci();nn();class Sm{tokenProviders=[];identityProviders=[];environmentSources=[];healthChecks=[];logParsers=[];proxyMiddleware=[];registerBuiltins(){this.tokenProviders.push(...cn()),this.identityProviders.push($l(),Fl()),this.logParsers.push(_d()),this.proxyMiddleware.push(zC())}register(e){oo(this.tokenProviders,e.tokenProviders),oo(this.identityProviders,e.identityProviders),oo(this.environmentSources,e.environmentSources),oo(this.healthChecks,e.healthChecks),oo(this.logParsers,e.logParsers),oo(this.proxyMiddleware,e.proxyMiddleware)}}async function km(e){let t=new Sm;t.registerBuiltins();for(let r of e){if(r.trim()==="")continue;let o=await import(r.startsWith("file:")?r:YC(r).href);t.register(o)}return t}function zC(){return{name:"identity_inject",apply:async(e)=>{await ia(e.route,e.headers,e.tokens)}}}function oo(e,t){if(!t)return;e.push(...t)}_e();var{spawn:i0}=globalThis.Bun;Ye();var{spawn:XC}=globalThis.Bun;async function Cm(e,t){if(e<=0)return;try{process.kill(-e,t);return}catch{try{process.kill(e,t)}catch{return}}}async function _m(e){if(!Pt(e))return;let t=await yi(["ps","-p",String(e),"-o","command="]),r=Date.now(),n=QC(await yi(["ps","-p",String(e),"-o","etime="])),o=await ZC(e);return{pid:e,command:t.trim(),cwd:o,startTime:n===void 0?void 0:new Date(r-n).toISOString()}}function QC(e){let t=e.trim();if(t==="")return;let r=t.indexOf("-"),n=r>=0?t.slice(0,r):"0",i=(r>=0?t.slice(r+1):t).split(":");if(i.length!==2&&i.length!==3)return;let s=Number(n),a=i.length===3?Number(i[0]):0,c=Number(i.length===3?i[1]:i[0]),l=Number(i.at(-1));if(!Number.isInteger(s)||s<0||!Number.isInteger(a)||a<0||a>23||!Number.isInteger(c)||c<0||c>59||!Number.isInteger(l)||l<0||l>59)return;return(((s*24+a)*60+c)*60+l)*1000}async function ZC(e){let r=(await yi(["lsof","-a","-p",String(e),"-d","cwd","-Fn"])).split(`
|
|
639
|
+
`).find((i)=>i.startsWith("n"));if(r&&r.length>1)return r.slice(1).trim();let n=await yi(["pwdx",String(e)]),o=n.indexOf(":");if(o>=0)return n.slice(o+1).trim();return""}async function yi(e){try{let t=XC({cmd:e,stdout:"pipe",stderr:"ignore"}),r=t.stdout?await new Response(t.stdout).text():"";return await t.exited,r}catch{return""}}async function Pm(e){let t=new Map;if(e.length===0)return t;let r=await yi(["ps","-o","pid=,pcpu=,rss=","-p",e.join(",")]);for(let n of r.split(`
|
|
640
|
+
`)){let o=n.trim();if(o==="")continue;let[i,s,a]=o.split(/\s+/),c=Number(i),l=Number(s),d=Number(a);if(Number.isFinite(c)&&Number.isFinite(l)&&Number.isFinite(d))t.set(c,{pid:c,cpuPercent:l,memoryKB:d})}return t}function Rm(e,t){if(e.length===0||t==="")return!1;let r=e.join(" ");if(t.includes(r))return!0;let o=(e[0]??"").split(/[/\\]/).pop()??"";if(o!==""&&t.includes(o))return!0;let i=e[e.length-1]??"";return i!==""&&t.includes(i)}Ye();var{spawn:Em}=globalThis.Bun;var e0=1024;async function Tm(e,t){if(e<=0)return;try{await Em({cmd:["taskkill","/PID",String(e),"/T","/F"],stdout:"ignore",stderr:"ignore"}).exited}catch{return}}async function Am(e){let t=t0(Xc(e),e);if(t)return t;if(!Pt(e))return;let r=await Dd(["powershell","-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${e}" | Select-Object CommandLine,ExecutablePath,CreationDate | ConvertTo-Json -Compress`]),n=n0(r);if(n&&n.command!=="")return{pid:e,command:n.command,cwd:n.cwd,startTime:n.startTime};let o=await Dd(["powershell","-NoProfile","-Command",`Get-Process -Id ${e} -ErrorAction SilentlyContinue | Select-Object Path,StartTime | ConvertTo-Json -Compress`]),i=r0(o);if(!i&&!n)return;return{pid:e,command:n?.command||i?.command||"",cwd:n?.cwd||i?.cwd||"",startTime:n?.startTime||i?.startTime}}function t0(e,t){let r=String(t);for(let n of e.split(/\r?\n/)){if(!n.includes(r))continue;let i=n.split(",").map((s)=>s.replace(/^"|"$/g,"").trim())[0]??"";if(i===""||i.toLowerCase().includes("info:"))continue;return{pid:t,command:i,cwd:""}}return}function r0(e){let t=e.trim();if(t==="")return;try{let r=JSON.parse(t),n=(r.Path||"").trim();if(n==="")return;return{command:n,cwd:aa(n),startTime:r.StartTime}}catch{let r=sa(t,"Path");if(r==="")return;return{command:r,cwd:aa(r)}}}function n0(e){let t=e.trim();if(t==="")return;try{let r=JSON.parse(t),n=(r.CommandLine||r.ExecutablePath||"").trim(),o=(r.ExecutablePath||"").trim(),i=aa(o);return{command:n,cwd:i,startTime:r.CreationDate||void 0}}catch{return{command:sa(t,"CommandLine")||sa(t,"ExecutablePath"),cwd:aa(sa(t,"ExecutablePath"))}}}async function Lm(e){let t=new Map;if(e.length===0)return t;let r=e.filter((o)=>o>0).join(",");if(r==="")return t;let n=await Dd(["powershell","-NoProfile","-Command",`${r}.Split(',') | ForEach-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue } | Select-Object Id,CPU,WorkingSet64 | ConvertTo-Json -Compress`]);return o0(n)}function o0(e){let t=new Map,r=e.trim();if(r==="")return t;try{let n=JSON.parse(r),o=Array.isArray(n)?n:[n];for(let i of o){if(!i||typeof i!=="object")continue;let s=i,a=Number(s.Id),c=Number(s.CPU??0),l=Number(s.WorkingSet64??0)/e0;if(Number.isFinite(a)&&a>0&&Number.isFinite(c)&&Number.isFinite(l))t.set(a,{pid:a,cpuPercent:c,memoryKB:l})}}catch{return t}return t}function aa(e){if(e==="")return"";let t=e.replace(/\//g,"\\"),r=t.lastIndexOf("\\");return r>0?t.slice(0,r):""}function sa(e,t){let r=`${t}=`,n=e.split(/\r?\n/).find((o)=>o.startsWith(r));return n?n.slice(r.length).trim():""}async function Dd(e){try{let t=Em({cmd:e,stdout:"pipe",stderr:"ignore"}),r=t.stdout?await new Response(t.stdout).text():"";return await t.exited,r}catch{return""}}Ye();var s0=1e4,a0=2000,c0=500;class Md{running=new Map;async start(e){let t=this.running.get(e.name);if(t&&ca(t))return t;if(this.running.delete(e.name),e.args.length===0)throw M(bt,"empty command");let r=e.shell?d0(e.args):e.args,n;try{n=i0({cmd:r,cwd:e.workDir===""?void 0:e.workDir,env:e.env,stdout:e.captureStdout===!1?"ignore":"pipe",stderr:e.captureStderr===!1?"ignore":"pipe",stdin:"ignore",detached:process.platform!=="win32"})}catch(i){throw ye(bt,`failed to start ${e.name}`,i)}let o={name:e.name,pid:n.pid??0,startTime:new Date,workDir:e.workDir,args:[...e.args],proc:n,done:Promise.resolve({code:0})};return Im(n.stdout,"stdout",e.onLine),Im(n.stderr,"stderr",e.onLine),o.done=n.exited.then((i)=>{let s=typeof i==="number"?i:0,a=s===0?void 0:Error(`exited with code ${s}`);if(this.running.get(e.name)===o)this.running.delete(e.name);if(e.onExit)e.onExit(s,a);return{code:s,err:a}}),this.running.set(e.name,o),o}adopt(e){let t=this.running.get(e.name);if(t&&ca(t))return t;if(!Pt(e.pid))throw M(bt,`cannot adopt ${e.name}: pid ${e.pid} is not running`);let r={name:e.name,pid:e.pid,startTime:e.startTime,workDir:e.workDir,args:[...e.args],done:Promise.resolve({code:0})};return r.done=u0(e.pid).then((n)=>{if(this.running.get(e.name)===r)this.running.delete(e.name);if(e.onExit)e.onExit(n,n===0?void 0:Error(`exited with code ${n}`));return{code:n}}),this.running.set(e.name,r),r}async stop(e,t){let r=this.running.get(e);if(!r)return;let n=t>0?t:s0;if(await Dm(r.pid,"SIGTERM"),!await $m(r.done,n)){if(await Dm(r.pid,"SIGKILL"),!await $m(r.done,a0))throw M(bt,`process ${e} did not exit after SIGKILL`)}this.running.delete(e)}get(e){return this.running.get(e)}all(){return[...this.running.values()]}}function ca(e){if(e.proc)return e.proc.exitCode===null&&!e.proc.killed;return Pt(e.pid)}async function Dm(e,t){if(process.platform==="win32"){await Tm(e,t);return}await Cm(e,t)}async function la(e){if(process.platform==="win32")return Am(e);return _m(e)}async function Fm(e){if(process.platform==="win32")return Lm(e);return Pm(e)}var l0=2000;function da(e,t){if(e.workDir!==""&&t.cwd!==""&&Om(e.workDir)!==Om(t.cwd))return!1;if(!Rm(e.args,t.command))return!1;let r=Mm(e.startTime),n=Mm(t.startTime);if(r!==void 0&&n!==void 0)return Math.abs(r-n)<=l0;return!0}function Mm(e){if(e===void 0)return;if(e instanceof Date)return Number.isNaN(e.getTime())?void 0:e.getTime();let t=Date.parse(e);return Number.isNaN(t)?void 0:t}function d0(e){if(process.platform==="win32")return["cmd.exe","/c",e.join(" ")];return["/bin/sh","-c",e.join(" ")]}function Om(e){return e.replace(/\\/g,"/").replace(/\/+$/,"")}async function u0(e){while(Pt(e))await p0(c0);return 0}async function Im(e,t,r){if(!e||typeof e==="number"||!r)return;let n=e.getReader(),o=new TextDecoder,i="";for(;;){let{value:s,done:a}=await n.read();if(a){if(i!=="")r(t,i);return}i+=o.decode(s,{stream:!0});let c=i.split(`
|
|
641
|
+
`);i=c.pop()??"";for(let l of c)r(t,l.replace(/\r$/,""))}}async function $m(e,t){return Promise.race([e.then(()=>!0),new Promise((r)=>{setTimeout(()=>r(!1),t)})])}function p0(e){return new Promise((t)=>{setTimeout(t,e)})}_e();vi();import{createServer as S0}from"http";var k0="2025-03-26",eh="2.0",zm=-32700,Xm=-32600,C0=-32601,Qm=-32602,_0=-32603,P0=new Set(["127.0.0.1","localhost","::1"]);function R0(e){return P0.has(e)}class Fd{server;running=!1;addr="";boundPort=0;opts;constructor(e){this.opts=e}disabled(){return this.opts.disabledTools?.()??[]}address(){return this.addr}listenPort(){return this.boundPort}isRunning(){return this.running}emit(e,t){this.opts.onEvent?.(e,t)}start(){if(!R0(this.opts.host))return Promise.reject(M(nt,`refusing to bind MCP to ${this.opts.host}`));return new Promise((e,t)=>{this.server=S0((r,n)=>{this.serve(r,n)}),this.server.on("error",(r)=>t(ye(nt,`unable to listen on ${this.opts.host}:${this.opts.port}`,r))),this.server.listen(this.opts.port,this.opts.host,()=>{let r=this.server?.address();this.boundPort=typeof r==="object"&&r?r.port:this.opts.port,this.addr=`${this.opts.host}:${this.boundPort}`,this.running=!0,this.emit("INFO",`listening on ${this.addr}`),e()})})}stop(){let e=this.server,t=this.running;if(!e)return this.running=!1,Promise.resolve();return new Promise((r)=>{e.close(()=>{if(this.running=!1,this.addr="",this.boundPort=0,this.server=void 0,t)this.emit("INFO","stopped");r()})})}async serve(e,t){if(e.method==="OPTIONS"){t.writeHead(204,wi()),t.end();return}if(!this.authorized(e)){this.emit("WARN",`rejected unauthorized request from ${Zm(e)}`),io(t,401,{error:"unauthorized"});return}if(T0(e)!=="/mcp"){io(t,404,{error:"not found"});return}if(e.method==="GET"||e.method==="DELETE"){t.writeHead(405,{Allow:"POST, OPTIONS",...wi()}),t.end();return}if(e.method!=="POST"){t.writeHead(405,{Allow:"POST, OPTIONS",...wi()}),t.end();return}let n;try{n=await A0(e)}catch(a){io(t,400,xi(null,zm,a instanceof Error?a.message:"invalid body"));return}let o;try{o=JSON.parse(n)}catch{io(t,400,xi(null,zm,"parse error"));return}let i=Zm(e);if(Array.isArray(o)){let a=[];for(let c of o){let l=await this.dispatch(c,i);if(l!==void 0)a.push(l)}io(t,200,a);return}let s=await this.dispatch(o,i);if(s===void 0){t.writeHead(202,wi()),t.end();return}io(t,200,s)}authorized(e){if(this.opts.token==="")return!0;return(e.headers.authorization??"")===`Bearer ${this.opts.token}`}async dispatch(e,t){if(!ma(e))return xi(null,Xm,"invalid request");let r=e,n=r.id??null,o=r.id===void 0;if(r.method===void 0||r.method==="")return o?void 0:xi(n,Xm,"missing method");try{let i=await this.handleMethod(r.method,ma(r.params)?r.params:{},t);if(o)return;return{jsonrpc:eh,id:n,result:i}}catch(i){if(o)return;let s=i instanceof bi?i.code:_0,a=i instanceof Error?i.message:"internal error";return this.emit("WARN",`rpc error method=${r.method} addr=${t}: ${a}`),xi(n,s,a)}}async handleMethod(e,t,r){switch(e){case"initialize":{let n=E0(t);return this.emit("INFO",`client connected addr=${r}${n?` (${n})`:""}`),{protocolVersion:k0,capabilities:{tools:{},resources:{}},serverInfo:{name:"devctl",version:at}}}case"notifications/initialized":case"ping":return{};case"tools/list":return{tools:Bm(this.disabled()).map((n)=>({name:n.name,description:n.description,inputSchema:n.inputSchema}))};case"tools/call":return this.callTool(t);case"resources/list":return{resources:Id.map((n)=>({uri:n,name:n.replace("devctl://",""),mimeType:"application/json"}))};case"resources/read":return this.readResource(t);default:throw new bi(C0,`method not found: ${e}`)}}async callTool(e){let t=typeof e.name==="string"?e.name:"";if(t==="")throw new bi(Qm,"tool name is required");if(ga(t)&&!Ar(t,this.disabled())){let o=`tool ${t} is disabled in devctl's MCP settings`;return this.emit("WARN",`tool call rejected name=${t}: disabled`),{content:[{type:"text",text:o}],isError:!0}}let r=ma(e.arguments)?e.arguments:{},n=Date.now();try{let o=await Vm(this.opts.hostApi,t,r);return this.emit("INFO",`tool call name=${t} duration=${Date.now()-n}ms`),{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(o){let i=o instanceof Error?o.message:"tool failed";return this.emit("WARN",`tool call failed name=${t} duration=${Date.now()-n}ms: ${i}`),{content:[{type:"text",text:i}],isError:!0}}}async readResource(e){let t=typeof e.uri==="string"?e.uri:"";if(!Jm(t))throw new bi(Qm,`unknown resource ${t}`);let r=await Ym(this.opts.hostApi,t);return this.emit("INFO",`resource read uri=${t}`),{contents:[{uri:t,mimeType:"application/json",text:JSON.stringify(r,null,2)}]}}}function E0(e){let t=e.clientInfo;if(!ma(t))return"";let r=typeof t.name==="string"?t.name:"",n=typeof t.version==="string"?t.version:"";if(r==="")return"";return n===""?r:`${r} ${n}`}function Zm(e){return e.socket.remoteAddress??"unknown"}class bi extends Error{code;constructor(e,t){super(t);this.code=e}}function wi(){return{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Authorization, Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id","Access-Control-Allow-Methods":"POST, OPTIONS"}}function io(e,t,r){let n=JSON.stringify(r);e.writeHead(t,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),...wi()}),e.end(n)}function xi(e,t,r){return{jsonrpc:eh,id:e,error:{code:t,message:r}}}function T0(e){let t=e.url??"/",r=t.indexOf("?");return r>=0?t.slice(0,r):t}function A0(e){return new Promise((t,r)=>{let n=[];e.on("data",(o)=>{n.push(o)}),e.on("end",()=>{t(Buffer.concat(n).toString("utf8"))}),e.on("error",r)})}function ma(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}vi();ha();Vt();ui();ua();un();Ye();ci();var t_=4000,r_=100,uh=30000,ph=3,n_=2,o_=2000,i_=200,s_=3,a_=10,c_=3000;class Wd{cfg;sessionID;internalTok;bus;logs;procs;tokens;detector;proxy;proxySuppressed=!1;mcp;mcpToken;tokenEP;profile="";clientEnv=new Map;serviceProfile=new Map;serviceProfileEnv=new Map;generation=new Map;runtimes=new Map;ports=new Map;healthTimers=new Map;restarts=new Map;lock;server;shuttingDown=!1;detached=!1;identityCache=fh();serviceAccountStatus=new Map;detectGoogleFn;inspectProcessFn;processAliveFn;acquireLockFn;socketExistsFn;unlinkSocketFn;registry;restartRequired=[];processMeta=new Map;credentialEntries=[];boundTokenURL="";configWatcher;watchTimer;unhealthyStreak=new Map;healthyStreak=new Map;restartTimers=new Map;setupMode;mcpDisabledTools=[];profileEnv={};resourceTimer;constructor(e,t){this.cfg=e,this.sessionID=Yc(),this.internalTok=Qc(),this.mcpToken=ef(e.repoRoot),this.bus=new td(2048),this.detectGoogleFn=t?.detectGoogle??Ht,this.inspectProcessFn=t?.inspectProcess??la,this.processAliveFn=t?.processAlive??Pt,this.acquireLockFn=t?.acquireLock??Zp,this.socketExistsFn=t?.socketExists??jd,this.unlinkSocketFn=t?.unlinkSocket??Y0,this.detector=new mn(e.secrets.extra_markers,e.secrets.extra_patterns),this.logs=new ra(e.logs.max_memory_events,this.bus,this.detector,e.logs.persistence.enabled,e.logs.persistence.directory,this.sessionID,e.logs.persistence.retention_days,e.logs.persistence.max_session_logs),this.procs=new Md,this.tokens=t?.tokens??new Xn(e.auth.refresh_threshold_seconds*1000,cn(),this.bus),this.bus.subscribe((r)=>{let n=r.payload??{},o=r.type===zn?`token refreshed identity=${String(n.identity??"")}`:r.type===an?`token refresh failed identity=${String(n.identity??"")} audience=${String(n.audience??"")}: ${String(n.error??"")}`:`authentication changed user=${String(n.user??"")}`;if(this.logs.append({timestamp:new Date().toISOString(),service:"auth",source:"auth",level:r.type===an?"WARN":"INFO",message:o,pid:0}),r.type===zn||r.type===an)this.syncCredentialEntries()},[zn,an,Zl]),this.setupMode=!jd(e.configPath),this.identityCache=fh(e);for(let r of Object.keys(e.services))this.runtimes.set(r,Vs(r))}async run(){let e=fs(this.cfg.repoRoot);this.lock=this.acquireLockFn(this.cfg.repoRoot,e),this.removeStaleSocket(e),this.registry=await km(this.cfg.plugins.map((r)=>r.path)),this.applyRegistry(),this.checkPluginHealthTypes(),this.checkPluginIdentityTypes(),await this.recoverSession(),this.watchConfig(),this.persistState(),this.log("devctl","INFO",`supervisor started session=${this.sessionID}`),this.refreshIdentity(),this.resourceTimer=setInterval(()=>void this.pollResourceUsage(),c_);let t=qt(this.cfg.repoRoot);if(this.setMcpDisabledTools(t.mcp_disabled_tools??[]),t.mcp_enabled)await this.startMcp(t.mcp_port).catch((r)=>this.log("devctl","ERROR",H(r)));this.removeStaleSocket(e),await new Promise((r,n)=>{this.server=J0((o)=>{this.handleConn(o)}),this.server.on("error",n),this.server.listen(e,()=>r())})}removeStaleSocket(e){if(process.platform==="win32")return;if(this.socketExistsFn(e))try{this.unlinkSocketFn(e)}catch{this.log("devctl","WARN","unable to remove stale socket")}}handleConn(e){let t="",r=2000,n=[],o=!1,i=()=>{while(n.length>0){let c=n[0],l=e.write(`${JSON.stringify(c)}
|
|
623
642
|
`);if(n.shift(),!l){o=!0,e.once("drain",()=>{o=!1,i()});return}}},s=(c)=>{if(c.id===void 0&&c.event!==void 0&&n.length>=r){let d=n.findIndex((g)=>g.id===void 0&&g.event!==void 0);if(d>=0)n.splice(d,1)}if(n.push(c),!o)i()},a=this.bus.subscribe((c)=>s({event:c}));e.on("error",(c)=>{this.log("devctl","WARN",`client connection error: ${H(c)}`)}),e.on("data",(c)=>{t+=c.toString("utf8");let l=t.split(`
|
|
624
|
-
`);t=l.pop()??"";for(let d of l){if(d.trim()==="")continue;this.dispatchLine(d,s)}}),e.on("close",()=>a())}async dispatchLine(e,t){let r;try{r=JSON.parse(e)}catch{t({error:"invalid json"});return}try{let n=await this.dispatch(r.method??"",r.params);t({id:r.id,result:n})}catch(n){let o=Kp(n);t({id:r.id,error:o.error,kind:o.kind,hint:o.hint,service:o.service})}}async dispatch(e,t){let r=ph(t)?t:{};switch(e){case"ping":return{session:this.sessionID,version:at,protocol:ei};case"start":return this.start({services:so(r.services),profile:typeof r.profile==="string"?r.profile:"",detach:r.detach===!0,client_env:uh(r.client_env)});case"stop":return await this.stop(so(r.services)),null;case"restart":return await this.restart(so(r.services),{cascade:r.cascade===!0,clientEnv:uh(r.client_env)}),null;case"auth_refresh":return await this.refreshIdentity({probeServiceAccounts:!0}),this.snapshot().identity;case"status":return this.snapshot();case"logs":return this.queryLogs({services:so(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:"",export:typeof r.export==="string"?r.export:""});case"logs_page":return this.queryLogsPage({services:so(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:"",cursor:typeof r.cursor==="string"?r.cursor:void 0,direction:r.direction==="forward"?"forward":"backward",limit:typeof r.limit==="number"?r.limit:void 0});case"logs_stats":return this.queryLogsFacets({services:so(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:""});case"proxy_start":return this.proxySuppressed=!1,await this.startProxy(),null;case"proxy_stop":return this.proxySuppressed=!0,await this.stopProxy(),null;case"mcp_start":{let o=typeof r.port==="number"?r.port:void 0;return await this.startMcp(o??qt(this.cfg.repoRoot).mcp_port),null}case"mcp_stop":return await this.stopMcp(),null;case"mcp_set_tools":{let o=Array.isArray(r.disabled)?r.disabled.filter((i)=>typeof i==="string"):[];return this.setMcpDisabledTools(o),{disabled_tools:[...this.mcpDisabledTools]}}case"reload":return this.reload();case"config_snapshot":return this.cfg;case"auth_invalidate":return this.tokens.invalidate(),null;case"shutdown":let n=typeof r.stop_services==="boolean"?r.stop_services:ys(this.cfg.shutdown);return setTimeout(()=>{this.shutdown(n)},50),null;default:throw M(nt,`unknown method ${e}`)}}isDetached(){return this.detached}async start(e){if(e.detach===!0)this.detached=!0;let t=Js(this.cfg,{services:e.services,profile:e.profile,activeProfile:this.profile});if(t.profile)this.profile=t.profile;if(this.profileEnv=t.env,e.client_env)for(let s of t.services)this.clientEnv.set(s,e.client_env);for(let s of t.services)this.serviceProfile.set(s,t.profile),this.serviceProfileEnv.set(s,t.env);if(e.auto!==!0)for(let s of t.services)this.resetRestartCount(s);let r=fi(this.cfg,t.services,t.profile),n=await this.detectGoogleFn(this.cfg.google.project_id);r.blockers=fg(this.cfg,r.waves.flat(),n.adcAvailable);let o=new Set(r.blockers.map((s)=>s.name));for(let s of r.blockers)await this.fail(s.name,M(bt,s.message));if(this.cfg.proxy.enabled&&!this.proxySuppressed)await this.startProxy().catch((s)=>this.log("devctl","ERROR",H(s)));let i=[];for(let s of r.waves.flat()){if(o.has(s)||await this.claimIfAlreadyUp(s))continue;i.push(s)}if(i.length>0)try{let s=await kg(this.cfg,i,Object.fromEntries(this.ports));for(let[a,c]of Object.entries(s)){this.ports.set(a,c);let l=Object.entries(c).map(([d,g])=>`${d}=${g}`).join(", ");this.log(a,"INFO",`assigned ports: ${l||"none"}`)}}catch(s){if(s instanceof Te&&s.service!=="")await this.fail(s.service,s);else this.log("devctl","ERROR",H(s));throw s}for(let s of r.waves){let a=s.filter((c)=>i.includes(c));if(a.length>0){let c=await Promise.allSettled(a.map((d)=>this.startOne(d,t.profile,t.env))),l=!1;for(let d of c)if(d.status==="rejected")l=!0,this.log("devctl","ERROR",H(d.reason));if(l)throw M(bt,"one or more services failed to start")}try{await this.awaitWaveHealth(s)}catch(c){throw this.log("devctl","ERROR",H(c)),c}}return this.persistState(),r}serviceIsActive(e){let t=this.procs.get(e);if(t&&sa(t))return!0;let r=this.runtimes.get(e);if(!r)return!1;if(r.health===Et||r.state===cn)return!0;return r.state===rd||r.state===Kt}serviceWorkDir(e){if(e.working_dir!==""&&!ah(e.working_dir))return Hd(this.cfg.repoRoot,e.working_dir);return e.working_dir}async claimIfAlreadyUp(e){let t=this.cfg.services[e];if(this.serviceIsActive(e)){if(t&&!this.ports.has(e)){let s=await Os(t);if(s)this.ports.set(e,s)}return!0}if(!t)return!1;let r=await Os(t);if(!r)return!1;let n=Object.values(r)[0],i=(n===void 0?void 0:await Vn(n))?.pid??0;if(i>0&&i!==process.pid){let s=Uo(this.cfg.repoRoot)?.processes.find((l)=>l.name===e&&l.pid===i);if(!s)return this.log(e,"WARN",`port ${n} is held by pid ${i} with no persisted record for ${e}; not adopting`),!1;let a=await aa(i);if(a!==void 0&&a.command!==""&&ca({args:[...t.command.args],workDir:this.serviceWorkDir(t),startTime:new Date(s.startTime)},a)){this.ports.set(e,r);let l=this.attachProcess(e,i,[...t.command.args],this.serviceWorkDir(t),new Date(s.startTime))??this.bumpGeneration(e);this.setState(e,Kt,jt,i,""),this.log(e,"INFO",`already listening on ${Object.values(r).join(", ")}; not starting again`);let d=this.serviceWorkDir(t),g=await this.resolveAdoptedHealthEnv(e,t,r);return this.startHealth(e,t,i,r,d,g,l),!0}this.log(e,"WARN",`port ${n} is in use by an unrelated process (pid ${i}); not adopting`)}return!1}async startOne(e,t,r){if(this.serviceIsActive(e))return;let n=this.cfg.services[e];if(!n)throw M(nt,`unknown service ${e}`);this.setState(e,rd,jt,0,"");let o=this.bumpGeneration(e),i=As(n.identity);if(Ls(i))try{if(i=await gg(n.identity,()=>vg(this.cfg.google.project_id),this.registry?.identityProviders),i.kind==="service_account")await this.tokens.get(ri(i),"",[]),this.serviceAccountStatus.set(i.serviceAccount,"available")}catch(f){if(i.kind==="service_account")this.serviceAccountStatus.set(i.serviceAccount,"unavailable");if(u_(n)||i.kind==="service_account")throw await this.fail(e,f),f;this.log(e,"WARN","cloud identity unavailable; starting service locally")}let s=this.ports.get(e)??{},a="";if(this.proxy?.isRunning())a=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)a=`http://${Yr(this.cfg.proxy.listen)}`;let c=El(e,"127.0.0.1",s,a,this.cfg.project.name);if(c.DEVCTL_INTERNAL_TOKEN=this.internalTok,this.cfg.proxy.token_endpoint.enabled)c.DEVCTL_TOKEN_URL=this.boundTokenURL||`http://127.0.0.1:${this.tokenEP?.listenPort()||this.cfg.proxy.token_endpoint.port}/token`;let l=await Pl(this.cfg.repoRoot,{service:e,profile:t,serviceCfg:n,profileEnv:r,assignedPorts:s,runtime:c,cfg:this.cfg,fetchSecret:Rl(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources,clientEnv:this.clientEnv.get(e)}),d=n.working_dir;if(d!==""&&!ah(d))d=Hd(this.cfg.repoRoot,d);let g=await this.procs.start({name:e,args:[...n.command.args],shell:n.shell||n.command.shell,workDir:d,env:Zo(l),graceMs:vs(this.cfg.shutdown)*1000,captureStdout:of(n),captureStderr:sf(n),onLine:(f,h)=>{this.logs.append({timestamp:new Date().toISOString(),service:e,source:f,stream:f,level:"",message:h,pid:g.pid})},onExit:(f,h)=>{this.onExit(e,o,f,h)}});if(this.processMeta.set(e,{command:[...n.command.args],cwd:d,startTime:g.startTime}),this.setState(e,Kt,jt,g.pid,""),this.bus.publish(Ne(Eg,e,{pid:g.pid})),this.startHealth(e,n,g.pid,s,d,Zo(l),o),this.persistState(),n.startup.wait_for_healthy){let f=n.startup.timeout_seconds>0?n.startup.timeout_seconds*1000:ch;try{await this.waitHealthy(e,f)}catch(h){throw await this.fail(e,h),h}}}async resolveAdoptedHealthEnv(e,t,r){let n="";if(this.proxy?.isRunning())n=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)n=`http://${Yr(this.cfg.proxy.listen)}`;let o=El(e,"127.0.0.1",r,n,this.cfg.project.name);if(o.DEVCTL_INTERNAL_TOKEN=this.internalTok,this.cfg.proxy.token_endpoint.enabled)o.DEVCTL_TOKEN_URL=this.boundTokenURL||`http://127.0.0.1:${this.tokenEP?.listenPort()||this.cfg.proxy.token_endpoint.port}/token`;try{let i=await Pl(this.cfg.repoRoot,{service:e,profile:this.serviceProfile.get(e)??this.profile,serviceCfg:t,profileEnv:this.serviceProfileEnv.get(e)??this.profileEnv,assignedPorts:r,runtime:o,cfg:this.cfg,fetchSecret:Rl(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources});return Zo(i)}catch(i){return this.log(e,"WARN",`could not fully reconstruct environment for adopted service's health check (${H(i)}); using a baseline environment`),Zo(o)}}async awaitWaveHealth(e){for(let t of e){let r=this.cfg.services[t];if(!r||r.health.type==="")continue;let n=r.startup.timeout_seconds>0?r.startup.timeout_seconds*1000:ch;try{await this.waitHealthy(t,n)}catch(o){throw await this.fail(t,o),o}}}async waitHealthy(e,t){let r=Date.now()+t;while(Date.now()<r){let n=this.runtimes.get(e);if(n?.health===Et)return;if(n?.state===ln)throw M(Bc,`service ${e} failed while waiting for healthy`);await p_(t_)}throw M(Bc,`service ${e} did not become healthy in time`)}onExit(e,t,r,n){if(!this.isCurrentGeneration(e,t))return;let o=this.runtimes.get(e);if(o?.state===ln)return;if(o&&(o.state===nd||o.state===Qn)){this.setState(e,Qn,jt,0,""),this.bus.publish(Ne(zl,e,{code:r}));return}let i=this.cfg.services[e],s=i?i.restart.policy||(i.restart.enabled?"on_failure":"never"):"never",a=n?.message??`exited with code ${r}`,c=s==="always"||s==="on_failure"&&r!==0,l=this.restarts.get(e)??0,d=i&&i.restart.max_retries>0?i.restart.max_retries:lh;if(c&&i&&l<d){this.setState(e,pi,jt,0,a),this.bumpRestartCount(e,l+1),this.persistState(),this.armRestart(e,i,t,l,()=>{let g=this.serviceProfile.get(e)??this.profile,f=this.serviceProfileEnv.get(e)??this.profileEnv;this.startOne(e,g,f).catch((h)=>this.log(e,"ERROR",H(h)))});return}this.fail(e,M("process_start",a))}startHealth(e,t,r,n,o,i,s){let a=this.healthTimers.get(e);if(a)clearInterval(a);if(t.health.type===""){this.setHealth(e,Et,"no health check");return}let c=em(t.health)||n_,l=()=>{tm(t.health,r,n,o,i,this.registry?.healthChecks).catch((d)=>({status:Ae,message:H(d)})).then((d)=>{if(!this.isCurrentGeneration(e,s))return;this.setHealth(e,d.status,d.message),this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:rm(d.status),message:`health ${d.status} ${d.message}`,pid:r}),this.maybeRestartUnhealthy(e,t,d.status,s)})};l(),this.healthTimers.set(e,setInterval(l,c))}async stop(e){let t=e;if(t.length===0)t=[...this.runtimes.entries()].filter(([,i])=>i.state!==Qn).map(([i])=>i);if(t.length===0)return;let r=t.filter((i)=>!this.cfg.services[i]&&this.runtimes.has(i)),n=t.filter((i)=>!this.cfg.services[i]&&!this.runtimes.has(i));if(n.length>0)throw M(cs,`unknown service "${n[0]}"`);let o=t.filter((i)=>this.cfg.services[i]!==void 0);if(o.length>0)await this.runStopPlan(gi(this.cfg,o),{resetRestartCounts:!0});if(r.length>0){await this.runStopPlan({profile:this.profile,steps:[],waves:r.map((i)=>[i])},{resetRestartCounts:!0});for(let i of r)this.forgetService(i)}}forgetService(e){let t=this.healthTimers.get(e);if(t)clearInterval(t),this.healthTimers.delete(e);this.clearRestartTimer(e),this.runtimes.delete(e),this.ports.delete(e),this.processMeta.delete(e),this.clientEnv.delete(e),this.serviceProfile.delete(e),this.serviceProfileEnv.delete(e),this.restarts.delete(e),this.generation.delete(e),this.unhealthyStreak.delete(e),this.healthyStreak.delete(e)}reconcileServices(e,t){for(let r of Object.keys(t))if(!e[r]&&!this.runtimes.has(r))this.runtimes.set(r,qs(r));for(let r of Object.keys(e)){if(t[r])continue;if(this.serviceIsActive(r)){let n=this.runtimes.get(r);if(n)n.orphaned=!0;this.log(r,"WARN","removed from configuration while still running; now orphaned \u2014 stop it explicitly to clean it up");continue}this.forgetService(r)}}async restart(e,t){let r=t?.cascade===!0,n=r?id(this.cfg,e):e,o=r?gi(this.cfg,e):zg(this.cfg,e),i=t?.auto!==!0;await this.runStopPlan(o,{resetRestartCounts:i});let s=n.map((a)=>this.serviceProfile.get(a)).find((a)=>a!==void 0)??this.profile;await this.start({services:n,profile:s,client_env:t?.clientEnv,auto:t?.auto})}async runStopPlan(e,t){for(let n of e.waves.flat())if(this.clearRestartTimer(n),this.bumpGeneration(n),t?.resetRestartCounts)this.resetRestartCount(n);let r=vs(this.cfg.shutdown)*1000;for(let n of e.waves)await Promise.all(n.map(async(o)=>{this.setState(o,nd,jt,0,"");let i=this.healthTimers.get(o);if(i)clearInterval(i),this.healthTimers.delete(o);await this.procs.stop(o,r),await this.releasePorts(o),this.setState(o,Qn,jt,0,""),this.bus.publish(Ne(zl,o,{}))}));this.persistState()}async startProxy(){if(this.proxy?.isRunning())return;if(this.proxy=new Pd(this.cfg.proxy,this.tokens,this.logs,this.bus,this.detector,this.registry?.proxyMiddleware??[]),await this.proxy.start(),this.cfg.proxy.token_endpoint.enabled)this.tokenEP=new Td(this.cfg.proxy.token_endpoint.host||"127.0.0.1",this.cfg.proxy.token_endpoint.port,this.internalTok,this.tokens),await this.tokenEP.start(),this.boundTokenURL=`http://127.0.0.1:${this.tokenEP.listenPort()}/token`;this.persistState()}async stopProxy(){await this.proxy?.stop(),await this.tokenEP?.stop(),this.persistState()}async startMcp(e){if(this.mcp?.isRunning())return;let t=await oh(this.cfg.repoRoot,e);this.mcp=new Id({host:"127.0.0.1",port:t,token:this.mcpToken,hostApi:this.asMcpHost(),onEvent:(r,n)=>this.log("mcp",r,`mcp ${n}`),disabledTools:()=>this.mcpDisabledTools}),await this.mcp.start(),this.persistState()}setMcpDisabledTools(e){let t=e.filter((n)=>pa(n)),r=this.mcpDisabledTools.join(",");if(this.mcpDisabledTools=[...new Set(t)].sort(),this.mcpDisabledTools.join(",")===r)return;this.log("devctl","INFO",this.mcpDisabledTools.length===0?"all MCP tools enabled":`MCP tools disabled: ${this.mcpDisabledTools.join(", ")}`)}async stopMcp(){await this.mcp?.stop(),this.mcp=void 0,this.persistState()}asMcpHost(){return{status:()=>this.snapshot(),logsPage:(e)=>this.queryLogsPage(e),config:()=>this.cfg,start:(e)=>this.start(e),stop:(e)=>this.stop(e),restart:(e,t)=>this.restart(e,{cascade:t}),reload:()=>this.reload(),doctor:async()=>{for(let e of Er(this.cfg))await this.probeServiceAccount(e);return Tr(this.cfg)}}}async reload(){let e;try{e=gt(this.cfg.repoRoot,this.cfg.configPath)}catch(i){throw this.bus.publish(Ne(ai,"",{error:H(i)})),this.log("devctl","ERROR",`configuration reload failed: ${H(i)}`),i}try{this.checkPluginHealthTypes(e),this.checkPluginIdentityTypes(e)}catch(i){throw this.bus.publish(Ne(ai,"",{error:H(i)})),this.log("devctl","ERROR",`configuration reload failed: ${H(i)}`),i}if(this.setupMode){if(this.setupMode=!1,this.log("devctl","INFO",`configuration created at ${this.cfg.configPath}; leaving setup mode`),!this.configWatcher)this.watchConfig()}let t=c_(this.cfg,e),r=JSON.stringify(this.cfg.proxy)!==JSON.stringify(e.proxy),n=JSON.stringify(this.cfg.secrets)!==JSON.stringify(e.secrets),o=this.cfg.services;if(Object.assign(this.cfg,e),this.reconcileServices(o,e.services),this.restartRequired=t.restart_required,n)this.detector.update(e.secrets.extra_markers,e.secrets.extra_patterns);if(r){let i=this.proxy?.isRunning()??!1;if(await this.stopProxy(),i&&this.cfg.proxy.enabled)await this.startProxy();this.log("devctl","INFO","proxy configuration changed; proxy restarted")}if(this.bus.publish(Ne(Bs,"",{restart_required:t.restart_required,changes:t.changes,supervisor_restart_required:t.supervisor_restart_required})),this.log("devctl","INFO",t.restart_required.length===0?"configuration reloaded":`configuration reloaded; restart required: ${t.restart_required.join(", ")}`),t.supervisor_restart_required)this.log("devctl","WARN",Vs(t.supervisor_restart_required));return this.persistState(),this.refreshIdentity(),t}async shutdown(e){if(this.shuttingDown)return;if(this.shuttingDown=!0,this.persistState(),e)await this.stop([]);if(this.clearAllRestartTimers(),await this.stopProxy(),await this.stopMcp(),this.configWatcher?.close(),this.watchTimer)clearTimeout(this.watchTimer);if(this.resourceTimer)clearInterval(this.resourceTimer);this.server?.close(),this.lock?.release(),await this.logs.close()}snapshot(){let e={};for(let[n,o]of this.runtimes)e[n]={...o,ports:this.ports.get(n)??o.ports,profile:this.serviceProfile.get(n)??o.profile,env_source:this.clientEnv.has(n)?"client":"daemon"};let t=this.proxy?.stats(),r={requestTotal:t?.total??0,requestErrors:t?.errors??0,recentRequests:t?.recent??[]};return{session_id:this.sessionID,repo_root:this.cfg.repoRoot,profile:this.profile,services:e,proxy:{running:this.proxy?.isRunning()??!1,address:this.proxy?.address(),routes:this.cfg.proxy.routes.map((n)=>({name:n.name,identity:n.auth.identity.service_account||n.auth.identity.type||n.auth.type,upstream:n.upstream.url,auth:n.auth.type})),...r},mcp:{running:this.mcp?.isRunning()??!1,address:this.mcp?.isRunning()?`http://${this.mcp.address()}/mcp`:void 0,port:this.mcp?.isRunning()?this.mcp.listenPort():void 0,token:this.mcpToken,disabled_tools:[...this.mcpDisabledTools]},identity:{...this.identityCache,...this.serviceAccountSnapshot()},credentials:{backend:this.tokens.storeBackend(),entries:[...this.credentialEntries]},detached:this.detached,setup_mode:this.setupMode?!0:void 0,logs:this.logs.snapshot(),restart_required:[...this.restartRequired],system:l_()}}async syncCredentialEntries(){this.credentialEntries=(await this.tokens.listStatus()).map((e)=>({identity:e.identity,audience:e.audience,expires_at:e.expires_at,valid:e.valid}))}async refreshIdentity(e){try{let t=await this.detectGoogleFn(this.cfg.google.project_id);if(e?.probeServiceAccounts)for(let o of Er(this.cfg))await this.probeServiceAccount(o);let{service_accounts:r,service_account_status:n}=this.serviceAccountSnapshot();this.identityCache={user:t.userEmail,project:t.projectID||this.cfg.google.project_id,project_source:t.projectSource||(this.cfg.google.project_id?"configuration":""),adc:t.adcAvailable,service_accounts:r,service_account_status:n,iap:this.cfg.proxy.routes.some((o)=>o.auth.type.toLowerCase()==="iap")},await this.syncCredentialEntries(),this.bus.publish(Ne(Xl,"",{user:this.identityCache.user,adc:this.identityCache.adc})),this.log("auth","INFO",`authentication changed user=${this.identityCache.user||"(unknown)"} adc=${this.identityCache.adc}`),this.persistState()}catch(t){this.log("devctl","WARN",`identity refresh failed: ${H(t)}`)}}serviceAccountSnapshot(){let e={},t={};for(let r of Er(this.cfg)){let n=this.serviceAccountStatus.get(r)??"unknown";if(t[r]=n,n!=="unknown")e[r]=n==="available"}return{service_accounts:e,service_account_status:t}}async probeServiceAccount(e){let t;try{await d_(this.tokens.refresh(`sa:${e}`,"",[]),e_),t="available"}catch{t="unavailable"}return this.serviceAccountStatus.set(e,t),t}queryLogs(e){let t=this.logs.query({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until});if(e.export)this.logs.exportTo(e.export,{services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until});return{events:t}}queryLogsPage(e){return this.logs.queryPage({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until},{cursor:e.cursor,direction:e.direction,limit:e.limit})}queryLogsFacets(e){return this.logs.queryFacets({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until})}subscribe(e){return this.bus.subscribe(e)}formatStatus(){let e=this.snapshot(),t=[`PROFILE: ${e.profile||"(none)"}`,"","SERVICE\tSTATUS\tHEALTH\tPID"];for(let[r,n]of Object.entries(e.services))t.push(`${r} ${Zn(n)} ${n.health} ${n.pid}`);return t.push("",`PROXY ${e.proxy.running?"RUNNING":"STOPPED"} ${e.proxy.address??""}`),t.push(`MCP ${e.mcp?.running?"RUNNING":"STOPPED"} ${e.mcp?.address??""}`),t.join(`
|
|
643
|
+
`);t=l.pop()??"";for(let d of l){if(d.trim()==="")continue;this.dispatchLine(d,s)}}),e.on("close",()=>a())}async dispatchLine(e,t){let r;try{r=JSON.parse(e)}catch{t({error:"invalid json"});return}try{let n=await this.dispatch(r.method??"",r.params);t({id:r.id,result:n})}catch(n){let o=Vp(n);t({id:r.id,error:o.error,kind:o.kind,hint:o.hint,service:o.service})}}async dispatch(e,t){let r=mh(t)?t:{};switch(e){case"ping":return{session:this.sessionID,version:at,protocol:ti};case"start":return this.start({services:ao(r.services),profile:typeof r.profile==="string"?r.profile:"",detach:r.detach===!0,client_env:gh(r.client_env)});case"stop":return await this.stop(ao(r.services)),null;case"restart":return await this.restart(ao(r.services),{cascade:r.cascade===!0,clientEnv:gh(r.client_env)}),null;case"auth_refresh":return await this.refreshIdentity({probeServiceAccounts:!0}),this.snapshot().identity;case"status":return this.snapshot();case"logs":return this.queryLogs({services:ao(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:"",export:typeof r.export==="string"?r.export:""});case"logs_page":return this.queryLogsPage({services:ao(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:"",cursor:typeof r.cursor==="string"?r.cursor:void 0,direction:r.direction==="forward"?"forward":"backward",limit:typeof r.limit==="number"?r.limit:void 0});case"logs_stats":return this.queryLogsFacets({services:ao(r.services),level:typeof r.level==="string"?r.level:"",search:typeof r.search==="string"?r.search:"",regex:r.regex===!0,source:typeof r.source==="string"?r.source:"",since:typeof r.since==="string"?r.since:"",until:typeof r.until==="string"?r.until:""});case"proxy_start":return this.proxySuppressed=!1,await this.startProxy(),null;case"proxy_stop":return this.proxySuppressed=!0,await this.stopProxy(),null;case"mcp_start":{let o=typeof r.port==="number"?r.port:void 0;return await this.startMcp(o??qt(this.cfg.repoRoot).mcp_port),null}case"mcp_stop":return await this.stopMcp(),null;case"mcp_set_tools":{let o=Array.isArray(r.disabled)?r.disabled.filter((i)=>typeof i==="string"):[];return this.setMcpDisabledTools(o),{disabled_tools:[...this.mcpDisabledTools]}}case"reload":return this.reload();case"config_snapshot":return this.cfg;case"auth_invalidate":return this.tokens.invalidate(),null;case"shutdown":let n=typeof r.stop_services==="boolean"?r.stop_services:vs(this.cfg.shutdown);return setTimeout(()=>{this.shutdown(n)},50),null;default:throw M(nt,`unknown method ${e}`)}}isDetached(){return this.detached}async start(e){if(e.detach===!0)this.detached=!0;let t=Ys(this.cfg,{services:e.services,profile:e.profile,activeProfile:this.profile});if(t.profile)this.profile=t.profile;if(this.profileEnv=t.env,e.client_env)for(let s of t.services)this.clientEnv.set(s,e.client_env);for(let s of t.services)this.serviceProfile.set(s,t.profile),this.serviceProfileEnv.set(s,t.env);if(e.auto!==!0)for(let s of t.services)this.resetRestartCount(s);let r=fi(this.cfg,t.services,t.profile),n=await this.detectGoogleFn(this.cfg.google.project_id);r.blockers=mg(this.cfg,r.waves.flat(),n.adcAvailable);let o=new Set(r.blockers.map((s)=>s.name));for(let s of r.blockers)await this.fail(s.name,M(bt,s.message));if(this.cfg.proxy.enabled&&!this.proxySuppressed)await this.startProxy().catch((s)=>this.log("devctl","ERROR",H(s)));let i=[];for(let s of r.waves.flat()){if(o.has(s)||await this.claimIfAlreadyUp(s))continue;i.push(s)}if(i.length>0)try{let s=await _g(this.cfg,i,Object.fromEntries(this.ports));for(let[a,c]of Object.entries(s)){this.ports.set(a,c);let l=Object.entries(c).map(([d,g])=>`${d}=${g}`).join(", ");this.log(a,"INFO",`assigned ports: ${l||"none"}`)}}catch(s){if(s instanceof Te&&s.service!=="")await this.fail(s.service,s);else this.log("devctl","ERROR",H(s));throw s}for(let s of r.waves){let a=s.filter((c)=>i.includes(c));if(a.length>0){let c=await Promise.allSettled(a.map((d)=>this.startOne(d,t.profile,t.env))),l=!1;for(let d of c)if(d.status==="rejected")l=!0,this.log("devctl","ERROR",H(d.reason));if(l)throw M(bt,"one or more services failed to start")}try{await this.awaitWaveHealth(s)}catch(c){throw this.log("devctl","ERROR",H(c)),c}}return this.persistState(),r}serviceIsActive(e){let t=this.procs.get(e);if(t&&ca(t))return!0;let r=this.runtimes.get(e);if(!r)return!1;if(r.health===Et||r.state===ln)return!0;return r.state===id||r.state===Kt}serviceWorkDir(e){if(e.working_dir!==""&&!dh(e.working_dir))return Bd(this.cfg.repoRoot,e.working_dir);return e.working_dir}async claimIfAlreadyUp(e){let t=this.cfg.services[e];if(this.serviceIsActive(e)){if(t&&!this.ports.has(e)){let s=await Is(t);if(s)this.ports.set(e,s)}return!0}if(!t)return!1;let r=await Is(t);if(!r)return!1;let n=Object.values(r)[0],i=(n===void 0?void 0:await Jn(n))?.pid??0;if(i>0&&i!==process.pid){let s=Ko(this.cfg.repoRoot)?.processes.find((l)=>l.name===e&&l.pid===i);if(!s)return this.log(e,"WARN",`port ${n} is held by pid ${i} with no persisted record for ${e}; not adopting`),!1;let a=await la(i);if(a!==void 0&&a.command!==""&&da({args:[...t.command.args],workDir:this.serviceWorkDir(t),startTime:new Date(s.startTime)},a)){this.ports.set(e,r);let l=this.attachProcess(e,i,[...t.command.args],this.serviceWorkDir(t),new Date(s.startTime))??this.bumpGeneration(e);this.setState(e,Kt,jt,i,""),this.log(e,"INFO",`already listening on ${Object.values(r).join(", ")}; not starting again`);let d=this.serviceWorkDir(t),g=await this.resolveAdoptedHealthEnv(e,t,r);return this.startHealth(e,t,i,r,d,g,l),!0}this.log(e,"WARN",`port ${n} is in use by an unrelated process (pid ${i}); not adopting`)}return!1}async startOne(e,t,r){if(this.serviceIsActive(e))return;let n=this.cfg.services[e];if(!n)throw M(nt,`unknown service ${e}`);this.setState(e,id,jt,0,"");let o=this.bumpGeneration(e),i=Ls(n.identity);if(Ds(i))try{if(i=await hg(n.identity,()=>bg(this.cfg.google.project_id),this.registry?.identityProviders),i.kind==="service_account")await this.tokens.get(Gn(i),"",[]),this.serviceAccountStatus.set(i.serviceAccount,"available")}catch(f){if(i.kind==="service_account")this.serviceAccountStatus.set(i.serviceAccount,"unavailable");if(p_(n)||i.kind==="service_account")throw await this.fail(e,f),f;this.log(e,"WARN","cloud identity unavailable; starting service locally")}let s=this.ports.get(e)??{},a="";if(this.proxy?.isRunning())a=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)a=`http://${Yr(this.cfg.proxy.listen)}`;let c=Al(e,"127.0.0.1",s,a,this.cfg.project.name);if(c.DEVCTL_INTERNAL_TOKEN=this.internalTok,this.cfg.proxy.token_endpoint.enabled)c.DEVCTL_TOKEN_URL=this.boundTokenURL||`http://127.0.0.1:${this.tokenEP?.listenPort()||this.cfg.proxy.token_endpoint.port}/token`;let l=await Tl(this.cfg.repoRoot,{service:e,profile:t,serviceCfg:n,profileEnv:r,assignedPorts:s,runtime:c,cfg:this.cfg,fetchSecret:El(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources,clientEnv:this.clientEnv.get(e)}),d=n.working_dir;if(d!==""&&!dh(d))d=Bd(this.cfg.repoRoot,d);let g=await this.procs.start({name:e,args:[...n.command.args],shell:n.shell||n.command.shell,workDir:d,env:ei(l),graceMs:xs(this.cfg.shutdown)*1000,captureStdout:af(n),captureStderr:cf(n),onLine:(f,h)=>{this.logs.append({timestamp:new Date().toISOString(),service:e,source:f,stream:f,level:"",message:h,pid:g.pid})},onExit:(f,h)=>{this.onExit(e,o,f,h)}});if(this.processMeta.set(e,{command:[...n.command.args],cwd:d,startTime:g.startTime}),this.setState(e,Kt,jt,g.pid,""),this.bus.publish(Ae(Ag,e,{pid:g.pid})),this.startHealth(e,n,g.pid,s,d,ei(l),o),this.persistState(),n.startup.wait_for_healthy){let f=n.startup.timeout_seconds>0?n.startup.timeout_seconds*1000:uh;try{await this.waitHealthy(e,f)}catch(h){throw await this.fail(e,h),h}}}async resolveAdoptedHealthEnv(e,t,r){let n="";if(this.proxy?.isRunning())n=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)n=`http://${Yr(this.cfg.proxy.listen)}`;let o=Al(e,"127.0.0.1",r,n,this.cfg.project.name);if(o.DEVCTL_INTERNAL_TOKEN=this.internalTok,this.cfg.proxy.token_endpoint.enabled)o.DEVCTL_TOKEN_URL=this.boundTokenURL||`http://127.0.0.1:${this.tokenEP?.listenPort()||this.cfg.proxy.token_endpoint.port}/token`;try{let i=await Tl(this.cfg.repoRoot,{service:e,profile:this.serviceProfile.get(e)??this.profile,serviceCfg:t,profileEnv:this.serviceProfileEnv.get(e)??this.profileEnv,assignedPorts:r,runtime:o,cfg:this.cfg,fetchSecret:El(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources});return ei(i)}catch(i){return this.log(e,"WARN",`could not fully reconstruct environment for adopted service's health check (${H(i)}); using a baseline environment`),ei(o)}}async awaitWaveHealth(e){for(let t of e){let r=this.cfg.services[t];if(!r||r.health.type==="")continue;let n=r.startup.timeout_seconds>0?r.startup.timeout_seconds*1000:uh;try{await this.waitHealthy(t,n)}catch(o){throw await this.fail(t,o),o}}}async waitHealthy(e,t){let r=Date.now()+t;while(Date.now()<r){let n=this.runtimes.get(e);if(n?.health===Et)return;if(n?.state===dn)throw M(Gc,`service ${e} failed while waiting for healthy`);await f_(r_)}throw M(Gc,`service ${e} did not become healthy in time`)}onExit(e,t,r,n){if(!this.isCurrentGeneration(e,t))return;let o=this.runtimes.get(e);if(o?.state===dn)return;if(o&&(o.state===sd||o.state===Zn)){this.setState(e,Zn,jt,0,""),this.bus.publish(Ae(Ql,e,{code:r}));return}let i=this.cfg.services[e],s=i?i.restart.policy||(i.restart.enabled?"on_failure":"never"):"never",a=n?.message??`exited with code ${r}`,c=s==="always"||s==="on_failure"&&r!==0,l=this.restarts.get(e)??0,d=i&&i.restart.max_retries>0?i.restart.max_retries:ph;if(c&&i&&l<d){this.setState(e,pi,jt,0,a),this.bumpRestartCount(e,l+1),this.persistState(),this.armRestart(e,i,t,l,()=>{let g=this.serviceProfile.get(e)??this.profile,f=this.serviceProfileEnv.get(e)??this.profileEnv;this.startOne(e,g,f).catch((h)=>this.log(e,"ERROR",H(h)))});return}this.fail(e,M("process_start",a))}startHealth(e,t,r,n,o,i,s){let a=this.healthTimers.get(e);if(a)clearInterval(a);if(t.health.type===""){this.setHealth(e,Et,"no health check");return}let c=tm(t.health)||o_,l=()=>{rm(t.health,r,n,o,i,this.registry?.healthChecks).catch((d)=>({status:Le,message:H(d)})).then((d)=>{if(!this.isCurrentGeneration(e,s))return;this.setHealth(e,d.status,d.message),this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:nm(d.status),message:`health ${d.status} ${d.message}`,pid:r}),this.maybeRestartUnhealthy(e,t,d.status,s)})};l(),this.healthTimers.set(e,setInterval(l,c))}async stop(e){let t=e;if(t.length===0)t=[...this.runtimes.entries()].filter(([,i])=>i.state!==Zn).map(([i])=>i);if(t.length===0)return;let r=t.filter((i)=>!this.cfg.services[i]&&this.runtimes.has(i)),n=t.filter((i)=>!this.cfg.services[i]&&!this.runtimes.has(i));if(n.length>0)throw M(ls,`unknown service "${n[0]}"`);let o=t.filter((i)=>this.cfg.services[i]!==void 0);if(o.length>0)await this.runStopPlan(gi(this.cfg,o),{resetRestartCounts:!0});if(r.length>0){await this.runStopPlan({profile:this.profile,steps:[],waves:r.map((i)=>[i])},{resetRestartCounts:!0});for(let i of r)this.forgetService(i)}}forgetService(e){let t=this.healthTimers.get(e);if(t)clearInterval(t),this.healthTimers.delete(e);this.clearRestartTimer(e),this.runtimes.delete(e),this.ports.delete(e),this.processMeta.delete(e),this.clientEnv.delete(e),this.serviceProfile.delete(e),this.serviceProfileEnv.delete(e),this.restarts.delete(e),this.generation.delete(e),this.unhealthyStreak.delete(e),this.healthyStreak.delete(e)}reconcileServices(e,t){for(let r of Object.keys(t))if(!e[r]&&!this.runtimes.has(r))this.runtimes.set(r,Vs(r));for(let r of Object.keys(e)){if(t[r])continue;if(this.serviceIsActive(r)){let n=this.runtimes.get(r);if(n)n.orphaned=!0;this.log(r,"WARN","removed from configuration while still running; now orphaned \u2014 stop it explicitly to clean it up");continue}this.forgetService(r)}}async restart(e,t){let r=t?.cascade===!0,n=r?cd(this.cfg,e):e,o=r?gi(this.cfg,e):Xg(this.cfg,e),i=t?.auto!==!0;await this.runStopPlan(o,{resetRestartCounts:i});let s=n.map((a)=>this.serviceProfile.get(a)).find((a)=>a!==void 0)??this.profile;await this.start({services:n,profile:s,client_env:t?.clientEnv,auto:t?.auto})}async runStopPlan(e,t){for(let n of e.waves.flat())if(this.clearRestartTimer(n),this.bumpGeneration(n),t?.resetRestartCounts)this.resetRestartCount(n);let r=xs(this.cfg.shutdown)*1000;for(let n of e.waves)await Promise.all(n.map(async(o)=>{this.setState(o,sd,jt,0,"");let i=this.healthTimers.get(o);if(i)clearInterval(i),this.healthTimers.delete(o);await this.procs.stop(o,r),await this.releasePorts(o),this.setState(o,Zn,jt,0,""),this.bus.publish(Ae(Ql,o,{}))}));this.persistState()}async startProxy(){if(this.proxy?.isRunning())return;if(this.proxy=new Ad(this.cfg.proxy,this.tokens,this.logs,this.bus,this.detector,this.registry?.proxyMiddleware??[]),await this.proxy.start(),this.cfg.proxy.token_endpoint.enabled)this.tokenEP=new Ld(this.cfg.proxy.token_endpoint.host||"127.0.0.1",this.cfg.proxy.token_endpoint.port,this.internalTok,this.tokens),await this.tokenEP.start(),this.boundTokenURL=`http://127.0.0.1:${this.tokenEP.listenPort()}/token`;this.persistState()}async stopProxy(){await this.proxy?.stop(),await this.tokenEP?.stop(),this.persistState()}async startMcp(e){if(this.mcp?.isRunning())return;let t=await ah(this.cfg.repoRoot,e);this.mcp=new Fd({host:"127.0.0.1",port:t,token:this.mcpToken,hostApi:this.asMcpHost(),onEvent:(r,n)=>this.log("mcp",r,`mcp ${n}`),disabledTools:()=>this.mcpDisabledTools}),await this.mcp.start(),this.persistState()}setMcpDisabledTools(e){let t=e.filter((n)=>ga(n)),r=this.mcpDisabledTools.join(",");if(this.mcpDisabledTools=[...new Set(t)].sort(),this.mcpDisabledTools.join(",")===r)return;this.log("devctl","INFO",this.mcpDisabledTools.length===0?"all MCP tools enabled":`MCP tools disabled: ${this.mcpDisabledTools.join(", ")}`)}async stopMcp(){await this.mcp?.stop(),this.mcp=void 0,this.persistState()}asMcpHost(){return{status:()=>this.snapshot(),logsPage:(e)=>this.queryLogsPage(e),config:()=>this.cfg,start:(e)=>this.start(e),stop:(e)=>this.stop(e),restart:(e,t)=>this.restart(e,{cascade:t}),reload:()=>this.reload(),doctor:async()=>{for(let e of Er(this.cfg))await this.probeServiceAccount(e);return Tr(this.cfg)}}}async reload(){let e;try{e=gt(this.cfg.repoRoot,this.cfg.configPath)}catch(i){throw this.bus.publish(Ae(ai,"",{error:H(i)})),this.log("devctl","ERROR",`configuration reload failed: ${H(i)}`),i}try{this.checkPluginHealthTypes(e),this.checkPluginIdentityTypes(e)}catch(i){throw this.bus.publish(Ae(ai,"",{error:H(i)})),this.log("devctl","ERROR",`configuration reload failed: ${H(i)}`),i}if(this.setupMode){if(this.setupMode=!1,this.log("devctl","INFO",`configuration created at ${this.cfg.configPath}; leaving setup mode`),!this.configWatcher)this.watchConfig()}let t=l_(this.cfg,e),r=JSON.stringify(this.cfg.proxy)!==JSON.stringify(e.proxy),n=JSON.stringify(this.cfg.secrets)!==JSON.stringify(e.secrets),o=this.cfg.services;if(Object.assign(this.cfg,e),this.reconcileServices(o,e.services),this.restartRequired=t.restart_required,n)this.detector.update(e.secrets.extra_markers,e.secrets.extra_patterns);if(r){let i=this.proxy?.isRunning()??!1;if(await this.stopProxy(),i&&this.cfg.proxy.enabled)await this.startProxy();this.log("devctl","INFO","proxy configuration changed; proxy restarted")}if(this.bus.publish(Ae(Ws,"",{restart_required:t.restart_required,changes:t.changes,supervisor_restart_required:t.supervisor_restart_required})),this.log("devctl","INFO",t.restart_required.length===0?"configuration reloaded":`configuration reloaded; restart required: ${t.restart_required.join(", ")}`),t.supervisor_restart_required)this.log("devctl","WARN",Js(t.supervisor_restart_required));return this.persistState(),this.refreshIdentity(),t}async shutdown(e){if(this.shuttingDown)return;if(this.shuttingDown=!0,this.persistState(),e)await this.stop([]);if(this.clearAllRestartTimers(),await this.stopProxy(),await this.stopMcp(),this.configWatcher?.close(),this.watchTimer)clearTimeout(this.watchTimer);if(this.resourceTimer)clearInterval(this.resourceTimer);this.server?.close(),this.lock?.release(),await this.logs.close()}snapshot(){let e={};for(let[n,o]of this.runtimes)e[n]={...o,ports:this.ports.get(n)??o.ports,profile:this.serviceProfile.get(n)??o.profile,env_source:this.clientEnv.has(n)?"client":"daemon"};let t=this.proxy?.stats(),r={requestTotal:t?.total??0,requestErrors:t?.errors??0,recentRequests:t?.recent??[]};return{session_id:this.sessionID,repo_root:this.cfg.repoRoot,profile:this.profile,services:e,proxy:{running:this.proxy?.isRunning()??!1,address:this.proxy?.address(),routes:this.cfg.proxy.routes.map((n)=>({name:n.name,identity:n.auth.identity.service_account||n.auth.identity.type||n.auth.type,upstream:n.upstream.url,auth:n.auth.type})),...r},mcp:{running:this.mcp?.isRunning()??!1,address:this.mcp?.isRunning()?`http://${this.mcp.address()}/mcp`:void 0,port:this.mcp?.isRunning()?this.mcp.listenPort():void 0,token:this.mcpToken,disabled_tools:[...this.mcpDisabledTools]},identity:{...this.identityCache,...this.serviceAccountSnapshot()},credentials:{backend:this.tokens.storeBackend(),entries:[...this.credentialEntries]},detached:this.detached,setup_mode:this.setupMode?!0:void 0,logs:this.logs.snapshot(),restart_required:[...this.restartRequired],system:d_()}}async syncCredentialEntries(){this.credentialEntries=(await this.tokens.listStatus()).map((e)=>({identity:e.identity,audience:e.audience,expires_at:e.expires_at,valid:e.valid}))}async refreshIdentity(e){try{let t=await this.detectGoogleFn(this.cfg.google.project_id);if(e?.probeServiceAccounts)for(let o of Er(this.cfg))await this.probeServiceAccount(o);let{service_accounts:r,service_account_status:n}=this.serviceAccountSnapshot();this.identityCache={user:t.userEmail,project:t.projectID||this.cfg.google.project_id,project_source:t.projectSource||(this.cfg.google.project_id?"configuration":""),adc:t.adcAvailable,service_accounts:r,service_account_status:n,iap:this.cfg.proxy.routes.some((o)=>o.auth.type.toLowerCase()==="iap")},await this.syncCredentialEntries(),this.bus.publish(Ae(Zl,"",{user:this.identityCache.user,adc:this.identityCache.adc})),this.log("auth","INFO",`authentication changed user=${this.identityCache.user||"(unknown)"} adc=${this.identityCache.adc}`),this.persistState()}catch(t){this.log("devctl","WARN",`identity refresh failed: ${H(t)}`)}}serviceAccountSnapshot(){let e={},t={};for(let r of Er(this.cfg)){let n=this.serviceAccountStatus.get(r)??"unknown";if(t[r]=n,n!=="unknown")e[r]=n==="available"}return{service_accounts:e,service_account_status:t}}async probeServiceAccount(e){let t;try{await u_(this.tokens.refresh(`sa:${e}`,"",[]),t_),t="available"}catch{t="unavailable"}return this.serviceAccountStatus.set(e,t),t}queryLogs(e){let t=this.logs.query({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until});if(e.export)this.logs.exportTo(e.export,{services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until});return{events:t}}queryLogsPage(e){return this.logs.queryPage({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until},{cursor:e.cursor,direction:e.direction,limit:e.limit})}queryLogsFacets(e){return this.logs.queryFacets({services:e.services,level:e.level,search:e.search,regex:e.regex,source:e.source,since:e.since,until:e.until})}subscribe(e){return this.bus.subscribe(e)}formatStatus(){let e=this.snapshot(),t=[`PROFILE: ${e.profile||"(none)"}`,"","SERVICE\tSTATUS\tHEALTH\tPID"];for(let[r,n]of Object.entries(e.services))t.push(`${r} ${eo(n)} ${n.health} ${n.pid}`);return t.push("",`PROXY ${e.proxy.running?"RUNNING":"STOPPED"} ${e.proxy.address??""}`),t.push(`MCP ${e.mcp?.running?"RUNNING":"STOPPED"} ${e.mcp?.address??""}`),t.join(`
|
|
625
644
|
`)+`
|
|
626
|
-
`}setState(e,t,r,n,o){let i=this.runtimes.get(e)??
|
|
645
|
+
`}setState(e,t,r,n,o){let i=this.runtimes.get(e)??Vs(e);i.state=t,i.health=r,i.pid=n,i.last_error=o;let s=t===Kt||t===ln||t===Qn;if(i.startTime=s?this.processMeta.get(e)?.startTime.toISOString():void 0,!s)i.cpuPercent=void 0,i.memoryKB=void 0;this.runtimes.set(e,i),this.bus.publish(Ae(Dg,e,{state:t,health:r,pid:n}))}bumpRestartCount(e,t){this.restarts.set(e,t);let r=this.runtimes.get(e);if(r)r.restarts=t}resetRestartCount(e){this.healthyStreak.set(e,0),this.bumpRestartCount(e,0)}bumpGeneration(e){let t=(this.generation.get(e)??0)+1;return this.generation.set(e,t),this.healthyStreak.set(e,0),t}isCurrentGeneration(e,t){return this.generation.get(e)===t}scheduleRestart(e,t,r){this.clearRestartTimer(e);let n=setTimeout(()=>{this.restartTimers.delete(e),r()},t);this.restartTimers.set(e,n)}armRestart(e,t,r,n,o){let i=t.restart.backoff_seconds>0?t.restart.backoff_seconds:n_;this.scheduleRestart(e,i*2**n*1000,()=>{if(this.isCurrentGeneration(e,r))o()})}clearRestartTimer(e){let t=this.restartTimers.get(e);if(t)clearTimeout(t),this.restartTimers.delete(e)}clearAllRestartTimers(){for(let e of this.restartTimers.values())clearTimeout(e);this.restartTimers.clear()}async pollResourceUsage(){let e=[];for(let r of this.runtimes.values())if(r.pid>0&&(r.state===Kt||r.state===ln||r.state===Qn))e.push(r.pid);if(e.length===0)return;let t=await Fm(e);for(let r of this.runtimes.values()){let n=r.pid>0?t.get(r.pid):void 0;if(n)r.cpuPercent=n.cpuPercent,r.memoryKB=n.memoryKB}}setHealth(e,t,r){let n=this.runtimes.get(e);if(!n)return;if(n.health=t,n.state===Kt||n.state===ln||n.state===Qn)n.state=t===Et?ln:t===Le?Qn:n.state;this.bus.publish(Ae(Mg,e,{health:t,message:r}))}maybeRestartUnhealthy(e,t,r,n){if(r!==Le){if(this.unhealthyStreak.set(e,0),r===Et)this.maybeForgiveRestarts(e);return}this.healthyStreak.set(e,0);let o=t.restart.policy||(t.restart.enabled?"on_failure":"never");if(o!=="on_failure"&&o!=="always")return;let i=(this.unhealthyStreak.get(e)??0)+1;if(this.unhealthyStreak.set(e,i),i<s_)return;this.unhealthyStreak.set(e,0);let s=this.restarts.get(e)??0,a=t.restart.max_retries>0?t.restart.max_retries:ph;if(s>=a){this.log(e,"WARN",`unhealthy after ${i} consecutive checks but the restart limit (${a}) has already been reached; not restarting`);return}this.bumpRestartCount(e,s+1),this.log(e,"WARN",`restarting after ${i} consecutive unhealthy checks (attempt ${s+1}/${a})`),this.armRestart(e,t,n,s,()=>{this.restart([e],{auto:!0}).catch((c)=>this.log(e,"ERROR",H(c)))})}maybeForgiveRestarts(e){let t=(this.healthyStreak.get(e)??0)+1;if(this.healthyStreak.set(e,t),t>=a_&&(this.restarts.get(e)??0)>0)this.log(e,"INFO",`restart count reset after ${t} consecutive healthy checks`),this.bumpRestartCount(e,0)}applyRegistry(){if(!this.registry)return;if(this.registry.tokenProviders.length>0)this.tokens.replaceProviders(this.registry.tokenProviders);this.logs.setParsers(this.registry.logParsers)}checkPluginHealthTypes(e=this.cfg){let t=wl(e);if(t.length===0)return;let r=new Set((this.registry?.healthChecks??[]).map((o)=>o.name.toLowerCase())),n=t.filter((o)=>!r.has(o.type.toLowerCase()));if(n.length>0)throw M(X,`unknown health check type(s): ${n.map((o)=>`${o.service}.health.type=${o.type}`).join(", ")}`)}checkPluginIdentityTypes(e=this.cfg){let t=Sl(e);if(t.length===0)return;let r=(this.registry?.identityProviders??[]).filter((o)=>o.name!=="user"&&o.name!=="service_account"),n=t.filter(({service:o})=>{let i=e.services[o];return!i||!r.some((s)=>s.accepts(i.identity))});if(n.length>0)throw M(X,`unknown identity type(s): ${n.map((o)=>`${o.service}.identity.type=${o.type}`).join(", ")}`)}watchConfig(){let e=Bd(this.cfg.repoRoot,".devctl");if(!jd(e))return;try{this.configWatcher=z0(e,{recursive:!0},()=>{if(this.watchTimer)clearTimeout(this.watchTimer);this.watchTimer=setTimeout(()=>{this.reload().catch((t)=>this.log("devctl","WARN",H(t)))},i_)})}catch{this.log("devctl","WARN","unable to watch .devctl for configuration changes")}}async releasePorts(e){let t=this.ports.get(e);if(!t)return;let r=this.cfg.services[e],n=this.processMeta.get(e);for(let o of Object.values(t)){let i=await Jn(o);if(!i||i.pid===process.pid)continue;if(r){let s=await la(i.pid);if(!(s!==void 0&&s.command!==""&&da({args:n?.command??[...r.command.args],workDir:n?.cwd??this.serviceWorkDir(r),startTime:n?.startTime},s))){this.log(e,"WARN",`port ${o} is held by pid ${i.pid}, which does not match ${e}; leaving it running`);continue}}try{await $s(i),this.log(e,"INFO",`released port ${o} (pid ${i.pid})`)}catch(s){this.log(e,"WARN",H(s))}}this.ports.delete(e)}async fail(e,t){let r=this.healthTimers.get(e);if(r)clearInterval(r),this.healthTimers.delete(e);this.clearRestartTimer(e),this.bumpGeneration(e),this.setState(e,dn,jt,0,H(t));try{await this.procs.stop(e,xs(this.cfg.shutdown)*1000)}catch(n){this.log(e,"WARN",H(n))}this.bus.publish(Ae(Lg,e,{error:H(t)})),this.log(e,"ERROR",H(t)),this.persistState()}log(e,t,r){this.logs.append({timestamp:new Date().toISOString(),service:e,source:"devctl",level:t,message:r,pid:0})}persistState(){let e=[];for(let t of this.procs.all()){let r=this.processMeta.get(t.name);e.push({name:t.name,pid:t.pid,command:r?.command??t.args,cwd:r?.cwd??t.workDir,startTime:(r?.startTime??t.startTime).toISOString(),ports:this.ports.get(t.name)??{}})}Qp(this.cfg.repoRoot,{session_id:this.sessionID,repo_root:this.cfg.repoRoot,profile:this.profile,processes:e})}attachProcess(e,t,r,n,o){if(this.procs.get(e)&&this.processAliveFn(this.procs.get(e)?.pid??0))return;if(!this.processAliveFn(t)||t===process.pid)return;let i=this.bumpGeneration(e);try{this.procs.adopt({name:e,pid:t,args:r,workDir:n,startTime:o,onExit:(s,a)=>{this.onExit(e,i,s,a)}})}catch(s){let a=s instanceof Error?s.message:String(s);this.log(e,"WARN",`adopt pid ${t} failed (${a}); tracking leftover in snapshot only`)}return this.processMeta.set(e,{command:r,cwd:n,startTime:o}),this.persistState(),i}async recoverSession(){let e=Ko(this.cfg.repoRoot);if(!e||e.processes.length===0)return;let t=[];for(let r of e.processes){if(!this.cfg.services[r.name]||r.pid<=0||r.pid===process.pid||!this.processAliveFn(r.pid))continue;let n=await this.inspectProcessFn(r.pid);if(!(n!==void 0&&n.command!==""&&da({args:r.command,workDir:r.cwd,startTime:r.startTime?new Date(r.startTime):void 0},n))){if(Object.values(r.ports).length>0&&await Is({ports:Object.entries(r.ports).map(([c,l])=>({name:c,value:l,auto:!1}))})!==void 0)this.log(r.name,"WARN",`pid ${r.pid} does not match stored command; leftover listener not adopted`);else this.log(r.name,"WARN",`pid ${r.pid} is a different process; not adopting`);continue}let i=this.attachProcess(r.name,r.pid,r.command,r.cwd,new Date(r.startTime||Date.now()))??this.bumpGeneration(r.name);if(Object.keys(r.ports).length>0)this.ports.set(r.name,r.ports);this.setState(r.name,Kt,jt,r.pid,"");let s=this.cfg.services[r.name];if(s){let a=r.cwd||this.serviceWorkDir(s),c=await this.resolveAdoptedHealthEnv(r.name,s,r.ports);this.startHealth(r.name,s,r.pid,r.ports,a,c,i)}this.log(r.name,"INFO","adopted leftover process; stdout/stderr from before adopt are not captured"),t.push(r.name)}if(t.length>0)this.profile=e.profile||this.profile,this.bus.publish(Ae($g,"",{services:t,session_id:e.session_id})),this.log("devctl","INFO",`recovered session processes: ${t.join(", ")}`)}}function l_(e,t){let r={},n=new Set,o=new Set([...Object.keys(e.services),...Object.keys(t.services)]);for(let s of o){let a=e.services[s],c=t.services[s],l=[];if(!a||!c)l.push("presence"),n.add(s);else{if(a.command.args.join("\x00")!==c.command.args.join("\x00")||a.command.shell!==c.command.shell||a.shell!==c.shell)l.push("command"),n.add(s);if(a.working_dir!==c.working_dir)l.push("working_dir"),n.add(s);if(JSON.stringify(a.environment)!==JSON.stringify(c.environment))l.push("environment"),n.add(s);if(JSON.stringify(a.ports)!==JSON.stringify(c.ports))l.push("ports"),n.add(s);if(JSON.stringify(a.identity)!==JSON.stringify(c.identity))l.push("identity"),n.add(s);if(JSON.stringify(a.health)!==JSON.stringify(c.health))l.push("health"),n.add(s);if(JSON.stringify(a.restart)!==JSON.stringify(c.restart))l.push("restart"),n.add(s);if(JSON.stringify(a.startup)!==JSON.stringify(c.startup))l.push("startup"),n.add(s);if(JSON.stringify(a.logs)!==JSON.stringify(c.logs))l.push("logs"),n.add(s)}if(l.length>0)r[s]=l}let i=[];if(JSON.stringify(e.logs)!==JSON.stringify(t.logs))i.push("logs");if(JSON.stringify(e.auth)!==JSON.stringify(t.auth))i.push("auth");if(JSON.stringify(e.plugins)!==JSON.stringify(t.plugins))i.push("plugins");return{restart_required:[...n].sort(),changes:r,supervisor_restart_required:i.length>0?i:void 0}}function fh(e){return{user:"",project:e?.google.project_id??"",project_source:e?.google.project_id?"configuration":"",adc:!1,service_accounts:{},service_account_status:Object.fromEntries(e?Er(e).map((t)=>[t,"unknown"]):[]),iap:e?.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap")??!1}}function d_(){let e=Q0(),t=om();return{platform:Z0(),cpuCount:X0().length,loadAvg1:e[0]??0,loadAvg5:e[1]??0,loadAvg15:e[2]??0,memTotalKB:t.totalKB,memFreeKB:t.unusedKB,memAvailableKB:t.leftoverKB,hostUptimeSec:e_()}}function u_(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("identity probe timed out")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}function p_(e){return e.capabilities.some((t)=>["google_api","iap","service_identity"].includes(t))}function mh(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ao(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}function gh(e){if(!mh(e))return;let t={};for(let[r,n]of Object.entries(e))if(typeof n==="string")t[r]=n;return t}function f_(e){return new Promise((t)=>setTimeout(t,e))}gn();ha();Vt();op();var ab=["zsh","bash","fish"];function cb(e){if(e==="zsh")return`#compdef devctl
|
|
627
646
|
_devctl() {
|
|
628
647
|
local -a opts
|
|
629
648
|
local line="\${words[*]}"
|
|
@@ -643,73 +662,73 @@ complete -F _devctl devctl
|
|
|
643
662
|
devctl __complete (commandline -cp)
|
|
644
663
|
end
|
|
645
664
|
complete -c devctl -f -a "(__devctl_complete)"
|
|
646
|
-
`;throw Error(`unsupported shell "${e}"; use ${
|
|
647
|
-
`)}),e.action(async()=>{let t=e.opts();await
|
|
648
|
-
`);return}if(L(
|
|
649
|
-
`)}finally{await n.close()}})}function
|
|
650
|
-
`)}finally{await n.close()}})}function
|
|
651
|
-
`)}finally{await n.close()}})}async function
|
|
665
|
+
`;throw Error(`unsupported shell "${e}"; use ${ab.join(", ")}`)}function ip(e,t){let r=e.trim().split(/\s+/).filter((l)=>l!==""),n=e.endsWith(" ")?"":r[r.length-1]??"",o=e.endsWith(" ")?r:r.slice(0,-1),i=o[1]??"",s=Object.keys(t.services).sort(),a=Object.keys(t.profiles).sort(),c=["start","stop","restart","status","logs","doctor","setup","auth","proxy","mcp","config","reload","attach","completion","update","version"];if(i===""||o.length<2)return Hr(c,n);if(i==="start"||i==="stop"||i==="restart"||i==="logs"){if(n==="--profile"||o[o.length-1]==="--profile")return Hr(a,n==="--profile"?"":n);return Hr([...s,"--profile","--detach","--json","--since","--until"],n)}if(i==="completion")return Hr([...ab].sort(),n);if(i==="auth")return Hr(["status","login","logout","refresh"],n);if(i==="config")return Hr(["validate","show"],n);if(i==="proxy")return Hr(["status","start","stop"],n);return Hr(c,n)}function Hr(e,t){if(t==="")return e;return e.filter((r)=>r.startsWith(t))}var YE="https://api.github.com/repos/amr-m-abdelgawad/devctl/releases/latest",sp="npm install --global @amr-m-abdelgawad/devctl@latest # alternatives: Homebrew or the unsigned GitHub Release binaries \u2014 see docs/installation.md";async function db(e=fetch){try{let t=await e(YE,{headers:{Accept:"application/vnd.github+json"}});if(!t.ok)return{current:at,latest:"",newer:!1,hint:sp};let n=((await t.json()).tag_name??"").replace(/^v/,"");return{current:at,latest:n,newer:n!==""&&zE(n,at)>0,hint:sp}}catch{return{current:at,latest:"",newer:!1,hint:sp}}}function zE(e,t){let r=lb(e),n=lb(t);for(let o=0;o<3;o+=1){let i=(r[o]??0)-(n[o]??0);if(i!==0)return i>0?1:-1}return 0}function lb(e){return e.replace(/^v/,"").split(".").slice(0,3).map((t)=>{let r=Number.parseInt(t.replace(/[^0-9].*$/,""),10);return Number.isFinite(r)?r:0})}function eT(){let e=new XE;return e.name("devctl").description("Local development orchestrator").version(Rt(),"-V, --version","print version").option("--config <path>","path to config file or .devctl directory").enablePositionalOptions(),e.command("version").description("print version").action(()=>{L(`${Rt()}
|
|
666
|
+
`)}),e.action(async()=>{let t=e.opts();await rp(t.config??"")}),tT(e),rT(e),nT(e),iT(e),sT(e),dT(e),uT(e),pT(e),fT(e),gT(e),hT(e),yT(e),vT(e),mT(e),wT(e),xT(e),bT(e),ST(e),e}function Oe(e){return e.optsWithGlobals().config??""}function tT(e){e.command("start").argument("[services...]","services to start").option("--profile <name>","profile to start").option("--detach","deprecated, no longer changes behavior: the daemon already outlives this command; use `devctl down` to stop it").option("--json","machine-readable output").action(async(t,r)=>{if(r.detach)process.stderr.write("warning: --detach is deprecated and no longer changes behavior \u2014 the daemon already keeps running after `start` exits; use `devctl down` to stop it\n");let n=await Mt("",Oe(e),!0);try{let o=await n.start({services:t,profile:r.profile,detach:r.detach===!0});if(r.json){L(JSON.stringify(o,null,2)+`
|
|
667
|
+
`);return}if(L(ld(o)),r.detach)L(`detached; services continue running
|
|
668
|
+
`)}finally{await n.close()}})}function rT(e){e.command("stop").argument("[services...]","services to stop").option("--json","machine-readable output").action(async(t,r)=>{let n=await Mt("",Oe(e),!0);try{if(await n.stop(t),r.json)L(JSON.stringify({stopped:t},null,2)+`
|
|
669
|
+
`)}finally{await n.close()}})}function nT(e){e.command("restart").argument("[services...]").option("--cascade","also restart transitive dependents (default: only the named services)").option("--json","machine-readable output").action(async(t,r)=>{let n=await Mt("",Oe(e),!0);try{if(await n.restart(t,r.cascade===!0),r.json)L(JSON.stringify({restarted:t,cascade:r.cascade===!0},null,2)+`
|
|
670
|
+
`)}finally{await n.close()}})}async function pb(e,t){let{repoRoot:r,client:n}=await Ml("",t.repo??"",Oe(e));try{if(!n){let i=Ko(r);if(t.json){L(JSON.stringify({running:!1,persisted:i},null,2)+`
|
|
652
671
|
`);return}if(L(`supervisor is not running
|
|
653
672
|
`),i&&i.processes.length>0){L(`last session ${i.session_id} profile ${i.profile||"(none)"}
|
|
654
673
|
`);for(let s of i.processes)L(`${s.name} stopped UNKNOWN ${s.pid}
|
|
655
|
-
`)}return}
|
|
674
|
+
`)}return}Dl(n,"status");let o=await n.call("status",null);if(t.json){L(JSON.stringify(o,null,2)+`
|
|
656
675
|
`);return}L(`PROFILE: ${o.profile||"(none)"}
|
|
657
676
|
|
|
658
677
|
SERVICE STATUS HEALTH PID
|
|
659
|
-
`);for(let[i,s]of Object.entries(o.services))L(`${i} ${
|
|
678
|
+
`);for(let[i,s]of Object.entries(o.services))L(`${i} ${eo(s)} ${s.health} ${s.pid}
|
|
660
679
|
`);L(`
|
|
661
680
|
PROXY ${o.proxy.running?"RUNNING":"STOPPED"} ${o.proxy.address??""}
|
|
662
681
|
`),L(`MCP ${o.mcp?.running?"RUNNING":"STOPPED"} ${o.mcp?.address??""}
|
|
663
682
|
`),L(`IDENTITY ${o.identity.user||"(unknown)"}
|
|
664
683
|
`),L(`CLOUD ${o.identity.project||"(unset)"}
|
|
665
|
-
`)}finally{n?.close()}}var
|
|
666
|
-
`),await
|
|
667
|
-
`);try{await
|
|
668
|
-
`);return}let o=await
|
|
684
|
+
`)}finally{n?.close()}}var oT=2000;function iT(e){e.command("status").option("--repo <path>","target a repository directly, even without a loadable configuration").option("--json","machine-readable output").option("--watch","keep refreshing until interrupted").action(async(t)=>{if(!t.watch){await pb(e,t);return}let r=new AbortController,n=()=>r.abort();process.on("SIGINT",n),process.on("SIGTERM",n);try{while(!r.signal.aborted){L(`--- ${new Date().toISOString()} ---
|
|
685
|
+
`),await pb(e,t),L(`
|
|
686
|
+
`);try{await ap(oT,void 0,{signal:r.signal})}catch{break}}}finally{process.off("SIGINT",n),process.off("SIGTERM",n)}})}function sT(e){e.command("down").description("stop the daemon (and, by default, its services)").option("--repo <path>","target a repository directly, even without a loadable configuration").option("--keep-services","stop only the daemon; its services keep running, detached").action(async(t)=>{let{repoRoot:r,client:n}=await Ml("",t.repo??"",Oe(e));if(!n){L(`no supervisor is running for ${r}
|
|
687
|
+
`);return}let o=await cT(n);try{let i=t.keepServices!==!0;await n.call("shutdown",{stop_services:i},o)}finally{n.close()}await aT(r,o),L(t.keepServices!==!0?`stopped services and the supervisor for ${r}
|
|
669
688
|
`:`stopped the supervisor for ${r}; its services keep running
|
|
670
|
-
`)})}async function
|
|
671
|
-
`}async function
|
|
672
|
-
`:
|
|
689
|
+
`)})}async function aT(e,t){let r=Date.now()+t;while(Date.now()<r){let n=await en(e);if(!n)return;n.close()}}async function cT(e){try{let r=await e.call("config_snapshot",null),n=typeof r.shutdown?.grace_seconds==="number"?r.shutdown.grace_seconds:0;return Math.max(5000,n*1000+2000)}catch{return 30000}}function fb(e){return`${e.timestamp.slice(11,19)} ${e.service.padEnd(10)} ${String(e.level).padEnd(6)} ${e.message}
|
|
690
|
+
`}async function lT(e,t,r,n=1000){let o=await e(void 0);o.events.forEach(t);let i=o.nextCursor;while(!r.aborted){try{await ap(n,void 0,{signal:r})}catch{return}o=await e(i),o.events.forEach(t),i=o.nextCursor}}function dT(e){let t=e.command("logs").argument("[services...]").enablePositionalOptions();t.option("--level <level>","minimum level").option("--search <text>","substring or regex search").option("--regex","treat search as regular expression").option("--source <source>","filter by source").option("--since <timestamp>","only events at or after this ISO timestamp").option("--until <timestamp>","only events at or before this ISO timestamp").option("--output <path>","export path").option("--json","machine-readable output").option("-f, --follow","keep printing new matching events until interrupted").action(async(r,n)=>{let o=await Mt("",Oe(e),!0);try{let i=n.output?ro(n.output):void 0;if(n.follow&&!i){let a=new AbortController,c=()=>a.abort();process.on("SIGINT",c),process.on("SIGTERM",c);try{await lT((l)=>o.logsPage({services:r,level:n.level,search:n.search,regex:n.regex,source:n.source,since:n.since,until:n.until,cursor:l,direction:"forward"}),(l)=>L(n.json?JSON.stringify(l)+`
|
|
691
|
+
`:fb(l)),a.signal)}finally{process.off("SIGINT",c),process.off("SIGTERM",c)}return}let s=await o.logs({services:r,level:n.level,search:n.search,regex:n.regex,source:n.source,since:n.since,until:n.until,export:i});if(i){L(`exported ${i}
|
|
673
692
|
`);return}if(n.json){L(JSON.stringify(s,null,2)+`
|
|
674
|
-
`);return}for(let a of s)L(
|
|
675
|
-
`)}finally{await o.close()}})}function
|
|
676
|
-
`);else i();if(!t.follow)return;let s=new AbortController,a=()=>s.abort();process.on("SIGINT",a),process.on("SIGTERM",a);try{while(!s.signal.aborted){try{await
|
|
677
|
-
`);else L(
|
|
693
|
+
`);return}for(let a of s)L(fb(a))}finally{await o.close()}}),t.command("export").argument("[services...]").requiredOption("--output <path>","export path").option("--level <level>","minimum level").option("--search <text>","substring or regex search").option("--regex","treat search as regular expression").option("--source <source>","filter by source").action(async(r,n)=>{let o=await Mt("",Oe(e),!0);try{let i=ro(n.output);await o.logs({services:r,level:n.level,search:n.search,regex:n.regex,source:n.source,export:i}),L(`exported ${i}
|
|
694
|
+
`)}finally{await o.close()}})}function uT(e){e.command("daemon").command("logs").option("-f, --follow","keep printing new lines until interrupted").action(async(t)=>{let{repoRoot:r}=Rr("",Oe(e)),n=Uo(r),o=0,i=()=>{if(!ub(n))return;let c=ZE(n,"utf8");if(c.length>o)L(c.slice(o)),o=c.length};if(!ub(n))L(`no daemon bootstrap log yet for this repository
|
|
695
|
+
`);else i();if(!t.follow)return;let s=new AbortController,a=()=>s.abort();process.on("SIGINT",a),process.on("SIGTERM",a);try{while(!s.signal.aborted){try{await ap(500,void 0,{signal:s.signal})}catch{break}i()}}finally{process.off("SIGINT",a),process.off("SIGTERM",a)}})}function pT(e){e.command("doctor").option("--json","machine-readable output").action(async(t)=>{let r=gt("",Oe(e)),n=await Tr(r);if(t.json)L(JSON.stringify(n,null,2)+`
|
|
696
|
+
`);else L(qs(n));if(n.issues>0)process.exitCode=2})}function fT(e){e.command("setup").option("--force","overwrite an existing configuration").action(async(t)=>{await fd("",Oe(e),t.force===!0)})}function gT(e){let t=e.command("auth").description("Google authentication");t.command("status").option("--json","machine-readable output").action(async(r)=>{let n="";try{n=gt("",Oe(e)).google.project_id}catch{n=""}let o=await Ht(n);if(r.json){L(JSON.stringify(o,null,2)+`
|
|
678
697
|
`);return}if(L(`User: ${o.userEmail||"(unknown)"}
|
|
679
698
|
`),L(`Project: ${o.projectID||"(unset)"}
|
|
680
699
|
`),o.projectID!=="")L(`Source: ${o.projectSource}
|
|
681
700
|
`);L(`ADC: ${o.adcAvailable}
|
|
682
701
|
`),L(`gcloud: ${o.gcloudInstalled}
|
|
683
|
-
`)}),t.command("login").action(async()=>{await
|
|
702
|
+
`)}),t.command("login").action(async()=>{await Os()}),t.command("logout").action(async()=>{await wg()}),t.command("refresh").option("--json","machine-readable output").action(async(r)=>{let n=await Mt("",Oe(e),!1);try{let i=await new Xn(ys(n.cfg.auth)*1000,cn()).refresh("user","",[]),s=n.client?await n.refreshAuth():void 0;if(r.json){L(JSON.stringify({identity:i.identity,expires_at:i.expiresAt.toISOString(),service_account_status:s?.service_account_status??{}},null,2)+`
|
|
684
703
|
`);return}if(L(`refreshed credentials expire ${i.expiresAt.toISOString()}
|
|
685
704
|
`),s)for(let[a,c]of Object.entries(s.service_account_status).sort(([l],[d])=>l.localeCompare(d)))L(`service account ${a}: ${c}
|
|
686
|
-
`)}finally{await n.close()}})}function
|
|
705
|
+
`)}finally{await n.close()}})}function mT(e){e.command("reload").description("reload configuration").action(async()=>{let t=await Mt("",Oe(e),!0);try{let r=await t.reload();if(r.restart_required.length===0)L(`configuration reloaded
|
|
687
706
|
`);else L(`configuration reloaded; restart required: ${r.restart_required.join(", ")}
|
|
688
|
-
`);if(r.supervisor_restart_required&&r.supervisor_restart_required.length>0)L(`note: ${
|
|
689
|
-
`)}finally{await t.close()}})}function
|
|
707
|
+
`);if(r.supervisor_restart_required&&r.supervisor_restart_required.length>0)L(`note: ${Js(r.supervisor_restart_required)}
|
|
708
|
+
`)}finally{await t.close()}})}function hT(e){let t=e.command("proxy");t.command("status").option("--json").action(async(r)=>{let n=await Mt("",Oe(e),!1);try{if(!n.client){L(`PROXY STOPPED
|
|
690
709
|
`);return}let o=await n.status();if(r.json){L(JSON.stringify(o.proxy,null,2)+`
|
|
691
710
|
`);return}L(`PROXY ${o.proxy.running?"RUNNING":"STOPPED"} ${o.proxy.address??""}
|
|
692
711
|
`);for(let i of o.proxy.routes??[])L(` ${i.name.padEnd(16)} identity=${i.identity} ${i.upstream}
|
|
693
|
-
`)}finally{await n.close()}}),t.command("start").action(async()=>{let r=await Mt("",
|
|
712
|
+
`)}finally{await n.close()}}),t.command("start").action(async()=>{let r=await Mt("",Oe(e),!0);try{await r.proxyStart()}finally{await r.close()}}),t.command("stop").action(async()=>{let r=await Mt("",Oe(e),!0);try{await r.proxyStop()}finally{await r.close()}})}function yT(e){e.command("mcp").description("Local MCP server for coding agents").option("--on","start the MCP listener").option("--off","stop the MCP listener").option("--port <port>","listen port").option("--json","machine-readable output").action(async(t)=>{let r=t.port===void 0?void 0:Number(t.port);if(t.port!==void 0&&(!Number.isInteger(r)||(r??0)<=0))throw Error(`invalid --port ${t.port}`);let n=await Mt("",Oe(e),t.on===!0,{allowMissingConfig:!0});try{if(t.off===!0&&n.client)await n.mcpStop();else if(t.on===!0)await n.mcpStart({port:r});let o=n.client?await n.status():void 0,i=qt(n.cfg.repoRoot,n.cfg.ui.keymap),s=o?.mcp?.port??r??i.mcp_port??so(n.cfg.repoRoot),a=o?.mcp?.address??co(s),c=o?.mcp?.token??"";if(t.json){L(JSON.stringify({running:o?.mcp?.running===!0,setup_mode:o?.setup_mode===!0,url:a,port:s,snippets:{claude:JSON.parse(Ud(a,c)),cursor:JSON.parse(Kd(a,c)),kilo:JSON.parse(qd(a,c)),codex:Vd(a,c)}},null,2)+`
|
|
694
713
|
`);return}if(L(`MCP ${o?.mcp?.running?"RUNNING":"STOPPED"} ${a}
|
|
695
714
|
|
|
696
715
|
`),o?.setup_mode===!0)L(`This repository has no .devctl yet, so the daemon is in setup mode.
|
|
697
716
|
`),L(`Connect an agent with the config below and ask it to set devctl up for this repository.
|
|
698
717
|
`),L(`It can call get_setup_guide and validate_config; nothing will run until a configuration exists.
|
|
699
718
|
|
|
700
|
-
`);L(
|
|
719
|
+
`);L(hh(a,c))}finally{await n.close()}})}function vT(e){let t=e.command("config");t.command("validate").option("--json").action((r)=>{try{let n=gt("",Oe(e)),o=Ut(n);if(r.json){L(JSON.stringify({valid:o.length===0,issues:o},null,2)+`
|
|
701
720
|
`);return}if(o.length>0)throw Error(o.join(`
|
|
702
721
|
`));L(`configuration is valid
|
|
703
722
|
`)}catch(n){if(r.json){L(JSON.stringify({valid:!1,error:H(n)},null,2)+`
|
|
704
|
-
`);return}throw n}}),t.command("show").option("--json").action((r)=>{let n=gt("",
|
|
705
|
-
`);return}L(
|
|
723
|
+
`);return}throw n}}),t.command("show").option("--json").action((r)=>{let n=gt("",Oe(e));if(r.json){L(JSON.stringify(n,null,2)+`
|
|
724
|
+
`);return}L(QE(n))})}function xT(e){e.command("completion").argument("[shell]","zsh, bash, or fish").description("print a shell completion script").action((t)=>{L(cb(t||"zsh"))}),e.command("__complete",{hidden:!0}).argument("[line...]").description("internal completion helper").action((t)=>{let r=t.join(" "),n=r===""?"devctl ":r;try{let o=gt("",Oe(e));L(ip(n,o).join(`
|
|
706
725
|
`)+`
|
|
707
|
-
`)}catch{L(
|
|
726
|
+
`)}catch{L(ip(n,Jr()).join(`
|
|
708
727
|
`)+`
|
|
709
|
-
`)}})}function
|
|
728
|
+
`)}})}function bT(e){e.command("update").description("check GitHub Releases for a newer version").option("--json","machine-readable output").action(async(t)=>{let r=await db();if(t.json){L(JSON.stringify(r,null,2)+`
|
|
710
729
|
`);return}if(L(`current ${r.current}
|
|
711
730
|
`),L(`latest ${r.latest||"(unavailable)"}
|
|
712
731
|
`),r.newer)L(`install ${r.hint}
|
|
713
732
|
`);else if(r.latest!=="")L(`up to date
|
|
714
|
-
`)})}function
|
|
715
|
-
`),process.exit(
|
|
733
|
+
`)})}function wT(e){e.command("attach").action(async()=>{let t=await fg("",Oe(e)),{runTuiWithController:r}=await Promise.resolve().then(() => (op(),sb));await r(t)})}function ST(e){e.command("_supervisor").option("--repo <path>","repository root").action(async(t)=>{let r=Xo(t.repo??"",Oe(e)),n=new Wd(r),o=!1,i=()=>{if(o)return;o=!0,n.shutdown(vs(r.shutdown)).finally(()=>process.exit(0))};process.on("SIGINT",i),process.on("SIGTERM",i),await n.run()})}async function gb(){process.stdout.on("error",(e)=>{if(e.code==="EPIPE")process.exit(0)});try{await eT().parseAsync(process.argv)}catch(e){process.stderr.write(H(e)+`
|
|
734
|
+
`),process.exit(qp(e))}}function L(e){try{process.stdout.write(e)}catch(t){if(t.code==="EPIPE")process.exit(0);throw t}}cs();await gb();
|