@amr-m-abdelgawad/devctl 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/devctl.js +115 -115
  2. 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 Zw=Object.defineProperty;var eS=(e)=>e;function tS(e,t){this[e]=eS.bind(null,t)}var Ls=(e,t)=>{for(var n in t)Zw(e,n,{get:t[n],enumerable:!0,configurable:!0,set:tS.bind(t,n)})};var D=(e,t)=>()=>(e&&(t=e(e=0)),t);var nS=import.meta.require;var eo=D(()=>{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 Ef(e,t=""){if(t===Rf)return!0;return e.includes(Rf)||e.startsWith(rS)}function Ds(){if(Pf)return;Pf=!0;let e=process.emitWarning.bind(process);process.emitWarning=(t,...n)=>{let r=iS(n[0]),o=oS(t);if(Ef(o,r))return;e(t,...n)}}function Tf(){let e=process.stderr.write.bind(process.stderr);return process.stderr.write=(t,n,r)=>{let o=sS(t);if(Ef(o)){let i=typeof n==="function"?n:typeof r==="function"?r:void 0;if(typeof i==="function")i();return!0}if(typeof n==="function")return e(t,n);return e(t,n,r)},()=>{process.stderr.write=e}}function oS(e){if(typeof e==="string")return e;if(e instanceof Error)return e.message;return String(e)}function iS(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&"type"in e&&typeof e.type==="string")return e.type;return""}function sS(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return new TextDecoder().decode(e);return""}var Rf="MetadataLookupWarning",rS="received unexpected error =",Pf=!1;var vl=D(()=>{eo()});function L(e,t){return new Oe(e,t)}function fe(e,t,n){let r=n instanceof Error?n:Error(String(n));return new Oe(e,t,{cause:r})}function ke(e,t,n,r=""){return new Oe(e,t,{hint:n,service:r})}function Ms(e,t){return e instanceof Oe&&e.kind===t}function Df(e){if(e instanceof Oe)return e.exitCode();return 1}function Of(e){if(e instanceof Oe)return{error:F(e),kind:e.kind,hint:e.hint,service:e.service};return{error:F(e)}}function Mf(e){if(typeof e==="string")return L("general",e);if(e.kind)return new Oe(e.kind,e.error.replace(`${e.kind}: `,""),{hint:e.hint,service:e.service});return L("general",e.error)}function F(e){if(e instanceof Oe){if(e.hint!=="")return`${Af(e)} \u2014 ${e.hint}`;return Af(e)}if(e instanceof Error)return e.message;return String(e)}function Af(e){let t=`${e.kind}: `;if(e.message.startsWith(t)){let n=e.message.slice(t.length),r=e.causeError?`: ${e.causeError.message}`:"";if(r!==""&&n.endsWith(r))return n.slice(0,n.length-r.length);return n}return e.message}var ee="configuration",ar="configuration_missing",pi="service_not_found",Lf="dependency",Ke="process_start",to="authentication",cr="authorization",hn="token",Os="impersonation",yl="iap",$n="proxy",xl="health_check",Je="general",Oe;var Pe=D(()=>{Oe=class Oe extends Error{kind;hint;service;causeError;constructor(e,t,n){super(n?.cause?`${e}: ${t}: ${n.cause.message}`:`${e}: ${t}`);this.name="DevctlError",this.kind=e,this.hint=n?.hint??"",this.service=n?.service??"",this.causeError=n?.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 aS}from"child_process";import{createHash as cS,randomBytes as Sl}from"crypto";import{copyFileSync as lS,existsSync as In,mkdirSync as dS,readdirSync as uS,readFileSync as kl,renameSync as Cl,statSync as pS,unlinkSync as bl,writeFileSync as fS}from"fs";import{homedir as gS}from"os";import{basename as mS,dirname as wl,join as dt,resolve as hS}from"path";function Ft(){let e=process.env.DEVCTL_HOME;if(e&&e!=="")return e;return dt(gS(),".devctl")}function Yt(e){dS(e,{recursive:!0,mode:vS})}function vn(e){let t=hS(e),n=process.platform==="win32"?t.toLowerCase():t;return cS("sha256").update(n).digest("hex").slice(0,xS)}function no(e){let t=dt(Ft(),"state",vn(e)),n=dt(Ft(),"sessions",vn(e));if(!In(t)&&In(n)){Yt(wl(t));try{Cl(n,t)}catch{Yt(t);for(let r of["state.json","devctl.lock","devctl.sock"]){let o=dt(n,r);if(In(o))lS(o,dt(t,r))}}}return Yt(t),t}function $s(){let e=dt(Ft(),"logs");return Yt(e),e}function lr(){let e=dt(Ft(),"exports");return Yt(e),e}function Wt(){let e=dt(Ft(),"credentials");return Yt(e),e}function Is(e,t=process.platform){if(t==="win32")return`\\\\.\\pipe\\devctl-${vn(e)}`;return dt(no(e),"devctl.sock")}function bS(e){return dt(no(e),"devctl.lock")}function $f(e){return dt(no(e),"state.json")}function dr(e){return dt(no(e),"bootstrap.log")}function Ff(e){let t=dr(e);if(!In(t))return;let n=no(e),r=dt(n,`${If}${_l()}.log`);try{Cl(t,r)}catch{return}SS(n)}function SS(e){let t;try{t=uS(e).filter((r)=>r.startsWith(If)&&r.endsWith(".log"))}catch{return}let n=t.map((r)=>{let o=dt(e,r);try{return{path:o,mtime:pS(o).mtimeMs}}catch{return}}).filter((r)=>r!==void 0).sort((r,o)=>o.mtime-r.mtime);for(let r=wS;r<n.length;r++)try{bl(n[r].path)}catch{}}function Gt(e,t){Yt(wl(e));let n=dt(wl(e),`.${mS(e)}.tmp-${process.pid}-${Sl(4).toString("hex")}`);fS(n,t,{mode:yS}),Cl(n,e)}function _l(e=new Date){return`${e.toISOString().slice(0,19).replace(/:/g,"-")+"Z"}-${Sl(3).toString("hex")}`}function Fs(e){let t=e.indexOf("Z-"),n=t>=0?e.slice(0,t+1):e,r=n.indexOf("T");if(r<0||!n.endsWith("Z"))return;let o=n.slice(0,r),i=n.slice(r+1,-1).replace(/-/g,":"),s=new Date(`${o}T${i}Z`);return Number.isNaN(s.getTime())?void 0:s}function ur(e){return Rl($f(e))}function Rl(e){if(!In(e))return;try{let t=JSON.parse(kl(e,"utf8"));if(Array.isArray(t.processes)&&typeof t.repo_root==="string")return t;return}catch{return}}function Nf(e,t){Gt($f(e),`${JSON.stringify(t,null,2)}
4
- `)}function Hf(e,t){let n=bS(e);if(In(n)){let r=kS(n);if(r&&Pt(r.pid))throw Error(`supervisor already running (pid ${r.pid})`);try{bl(n)}catch{}}return Gt(n,JSON.stringify({pid:process.pid,socket:t})),{release:()=>{try{bl(n)}catch{}}}}function kS(e){if(!In(e))return;try{let t=JSON.parse(kl(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 CS(e);try{return process.kill(e,0),!0}catch{return!1}}function Pl(e){try{let t=aS("cmd.exe",["/d","/c",`tasklist /FO CSV /NH /FI "PID eq ${e}"`],{encoding:"buffer",windowsHide:!0,timeout:5000});return _S(t.stdout)}catch{return""}}function CS(e){try{return process.kill(e,0),!0}catch{}let t=Pl(e).toLowerCase();if(t===""||t.includes("no tasks")||t.includes("no matching"))return!1;return t.includes(String(e))}function _S(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 El(){return Sl(24).toString("hex")}function RS(e){return dt(no(e),"mcp-token")}function jf(e){let t=RS(e);if(In(t)){let r=kl(t,"utf8").trim();if(r!=="")return r}let n=El();return Gt(t,n),n}var vS=448,yS=384,xS=16,wS=5,If="bootstrap-";var ze=()=>{};function ro(){return{args:[],shell:!1}}function Al(){return{vars:{},required:[],defaults:{}}}function Ll(){return{type:"",url:"",address:"",command:ro(),interval_seconds:0,timeout_seconds:0,start_period_seconds:0,unhealthy_threshold:3,healthy_reset_threshold:10}}function wt(e){return typeof e==="string"?e:e.service}function Fn(e){return typeof e==="string"?"service_started":e.condition||"service_started"}function Hs(e){return Fn(e)==="service_healthy"?`${wt(e)} (healthy)`:wt(e)}function Dl(){return{type:"",mode:"",service_account:"",config:{}}}function Nn(){return{extends:"",description:"",command:ro(),shell:!1,working_dir:"",dependencies:[],ports:[],environment:Al(),health:Ll(),identity:Dl(),logs:{stdout:!1,stderr:!1},restart:{policy:"",max_retries:0,backoff_seconds:0},startup:{wait_for_healthy:!1,timeout_seconds:0},capabilities:[],proxy:[],container:void 0,hooks:{pre_start:ro(),post_start:ro()}}}function pr(){return{version:1,project:{name:""},google:{project_id:"",region:""},profiles:{},templates:{},services:{},tasks:{},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:{}},provenance:{},repoRoot:"",configPath:""}}function io(e){return e.args.length===0||e.args.length===1&&(e.args[0]??"").trim()===""}function fi(e){if(e.type!=="")return e.type;return e.mode}function yn(e){let t=fi(e).toLowerCase();return t==="service"||t==="service_account"}function Uf(e){let t=fi(e).toLowerCase();return t==="user"||t===""}function Kf(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 fr(e){let t=e.host===""?"127.0.0.1":e.host;if(e.port===0)return t;return`${t}:${e.port}`}function js(e){if(e.refresh_threshold_seconds<=0)return 300;return e.refresh_threshold_seconds}function Bs(e){if(e.stop_services_on_exit===void 0)return!0;return e.stop_services_on_exit}function gi(e){if(e.grace_seconds<=0)return 10;return e.grace_seconds}function qf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stdout}function Vf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stderr}function Ol(e,t){return e.find((n)=>n.name===t)}function Jf(e){return e[0]}var oo=1,Bf="never",Wf="on_failure",Gf="always",Ns=8080,Tl="127.0.0.1";function I(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function $l(e){return I(e)?new Set(Object.keys(e)):new Set}function K(e){if(typeof e==="string")return e;if(typeof e==="number"||typeof e==="boolean")return String(e);return""}function xe(e){if(typeof e==="number")return e;if(typeof e==="string"){let t=Number(e);return Number.isNaN(t)?0:t}return 0}function it(e){return e===!0}function Tt(e){if(!Array.isArray(e))return[];return e.map((t)=>K(t))}function Il(e){if(!Array.isArray(e))return[];return e.map((t)=>I(t)?{service:K(t.service),condition:K(t.condition)||"service_started"}:K(t))}function Hn(e){if(!I(e))return{};let t={};for(let[n,r]of Object.entries(e))t[n]=K(r);return t}function Ut(e){if(typeof e==="string")return{args:e.split(/\s+/).filter((t)=>t!==""),shell:!1};if(Array.isArray(e))return{args:e.map((t)=>K(t)),shell:!1};return ro()}function Fl(e){if(e===void 0||e===null)return[];if(typeof e==="string"||typeof e==="number")return[Ml(e,"http")];if(Array.isArray(e))return e.map((t,n)=>Ml(t,`port_${n}`));if(I(e))return Object.entries(e).map(([t,n])=>Ml(n,t));return[]}function Ml(e,t){if(typeof e==="string"&&e.toLowerCase()==="auto")return{name:t,value:0,auto:!0};return{name:t,value:xe(e),auto:!1}}function zf(e){if(!I(e))return Al();let t={},n=[],r={};for(let[o,i]of Object.entries(e))if(o==="required")n=Tt(i);else if(o==="defaults")r=Hn(i);else t[o]=K(i);return{vars:t,required:n,defaults:r}}function PS(e){if(!I(e))return Dl();return{type:K(e.type),mode:K(e.mode),service_account:K(e.service_account),config:I(e.config)?{...e.config}:{}}}function ES(e){if(!I(e))return Ll();return{type:K(e.type),url:K(e.url),address:K(e.address),command:Ut(e.command),interval_seconds:xe(e.interval_seconds),timeout_seconds:xe(e.timeout_seconds),start_period_seconds:xe(e.start_period_seconds),unhealthy_threshold:e.unhealthy_threshold===void 0?3:xe(e.unhealthy_threshold),healthy_reset_threshold:e.healthy_reset_threshold===void 0?10:xe(e.healthy_reset_threshold)}}function TS(e){if(!I(e))return{policy:"",max_retries:0,backoff_seconds:0};return{enabled:e.enabled===void 0?void 0:it(e.enabled),policy:K(e.policy),max_retries:xe(e.max_retries),backoff_seconds:xe(e.backoff_seconds)}}function AS(e){if(!I(e))return{wait_for_healthy:!1,timeout_seconds:0};return{wait_for_healthy:it(e.wait_for_healthy),timeout_seconds:xe(e.timeout_seconds)}}function mi(e){if(!I(e))return Nn();let t=I(e.logs)?e.logs:{};return{extends:K(e.extends),description:K(e.description),command:Ut(e.command),shell:it(e.shell),working_dir:K(e.working_dir),dependencies:Il(e.dependencies),ports:Fl(e.ports),environment:zf(e.environment),health:ES(e.health),identity:PS(e.identity),logs:{stdout:it(t.stdout),stderr:it(t.stderr)},restart:TS(e.restart),startup:AS(e.startup),capabilities:Tt(e.capabilities),proxy:Hl(e.proxy),container:Nl(e.container),hooks:LS(e.hooks)}}function LS(e){let t=I(e)?e:{};return{pre_start:Ut(t.pre_start),post_start:Ut(t.post_start)}}function Yf(e){let t=I(e)?e:{};return{command:Ut(t.command),shell:it(t.shell),working_dir:K(t.working_dir),dependencies:Tt(t.dependencies),environment:zf(t.environment)}}function Nl(e){if(!I(e))return;let t={};if(I(e.ports))for(let[n,r]of Object.entries(e.ports))t[n]=xe(r);return{image:K(e.image),runtime:K(e.runtime),ports:t,env:Hn(e.env),volumes:Tt(e.volumes)}}function Hl(e){if(e===void 0||e===null)return[];if(Array.isArray(e))return e.map((t)=>gr(t));if(I(e))return[gr(e)];return[]}function Ws(e){if(!I(e))return{services:[],environment:{}};return{services:Tt(e.services),environment:Hn(e.environment)}}function DS(e){if(typeof e==="string")return{type:e,service_account:""};if(!I(e))return{type:"",service_account:""};return{type:K(e.type),service_account:K(e.service_account)}}function OS(e){if(!I(e))return{type:"",identity:{type:"",service_account:""},audience:"",service_account:""};return{type:K(e.type),identity:DS(e.identity),audience:K(e.audience),service_account:K(e.service_account)}}function gr(e){if(!I(e))return{name:"",match:{host:"",path:""},upstream:{url:""},auth:{type:"",identity:{type:"",service_account:""},audience:"",service_account:""}};let t=I(e.match)?e.match:{},n=I(e.upstream)?e.upstream:{};return{name:K(e.name),match:{host:K(t.host),path:K(t.path)},upstream:{url:K(n.url)},auth:OS(e.auth)}}var jl=()=>{};import{existsSync as MS,statSync as Qf}from"fs";import{basename as Xf,dirname as Gs,isAbsolute as $S,join as Us,resolve as Zf}from"path";function jn(e,t){if(t!=="")return IS(t);let n=e===""?process.cwd():e;n=$S(n)?n:Zf(n);for(;;){let r=Us(n,St,Kt);if(hi(r))return{repoRoot:n,configPath:r};let o=Us(n,"devctl.yaml");if(hi(o))return{repoRoot:n,configPath:o};let i=Gs(n);if(i===n)break;n=i}throw ke(ar,"no devctl configuration found","run `devctl setup` or create a .devctl/config.yaml in the repository root")}function IS(e){let t=Zf(e),n;try{n=Qf(t)}catch(o){throw fe(ar,"config path not found",o)}if(n.isDirectory()){if(Xf(t)===St)return{repoRoot:Gs(t),configPath:Us(t,Kt)};return{repoRoot:t,configPath:Us(t,Kt)}}let r=Gs(t);if(Xf(r)===St)r=Gs(r);return{repoRoot:r,configPath:t}}function hi(e){return MS(e)&&!Qf(e).isDirectory()}var St=".devctl",Kt="config.yaml";var vi=D(()=>{Pe()});function Vs(){return{services:{},templates:{},provenance:{}}}function Bn(e,t,n,r,o=""){if(I(t)&&Object.keys(t).length>0){for(let[i,s]of Object.entries(t))Bn(e,s,n,r,o===""?i:`${o}.${i}`);return}if(o==="")return;(e[o]??=[]).push({source:n,layer:r})}function Ks(e,t,n){let r=$l(n);if(I(n))for(let i of FS){let s=n[i];if(I(s))for(let a of Object.keys(s))r.add(`${i}.${a}`)}let o=e[t];e[t]=o?new Set([...o,...r]):r}function eg(e,t,n=Vs(),r={source:"unknown",layer:"unknown"}){if(Bn(n.provenance,t,r.source,r.layer),t.version!==void 0)e.version=xe(t.version);if(I(t.project)&&t.project.name!==void 0)e.project.name=K(t.project.name);if(I(t.google)){if(t.google.project_id!==void 0)e.google.project_id=K(t.google.project_id);if(t.google.region!==void 0)e.google.region=K(t.google.region)}if(I(t.profiles))for(let[o,i]of Object.entries(t.profiles)){let s=e.profiles[o];e.profiles[o]=s?HS(s,i):Ws(i)}if(I(t.templates))for(let[o,i]of Object.entries(t.templates)){let s=e.templates[o];e.templates[o]=s?qs(s,i):mi(i),Ks(n.templates,o,i)}if(I(t.services))for(let[o,i]of Object.entries(t.services)){let s=e.services[o];e.services[o]=s?qs(s,i):mi(i),Ks(n.services,o,i)}if(I(t.tasks))for(let[o,i]of Object.entries(t.tasks))e.tasks[o]=e.tasks[o]?jS(e.tasks[o],i):Yf(i);if(I(t.proxy))NS(e.proxy,t.proxy);if(I(t.logs)){if(t.logs.max_memory_events!==void 0)e.logs.max_memory_events=xe(t.logs.max_memory_events);if(I(t.logs.persistence)){let o=t.logs.persistence;if(o.enabled!==void 0)e.logs.persistence.enabled=it(o.enabled);if(o.directory!==void 0)e.logs.persistence.directory=K(o.directory);if(o.retention_days!==void 0)e.logs.persistence.retention_days=xe(o.retention_days);if(o.max_session_logs!==void 0)e.logs.persistence.max_session_logs=xe(o.max_session_logs)}}if(I(t.auth)&&t.auth.refresh_threshold_seconds!==void 0)e.auth.refresh_threshold_seconds=xe(t.auth.refresh_threshold_seconds);if(I(t.shutdown)){if(t.shutdown.stop_services_on_exit!==void 0)e.shutdown.stop_services_on_exit=it(t.shutdown.stop_services_on_exit);if(t.shutdown.grace_seconds!==void 0)e.shutdown.grace_seconds=xe(t.shutdown.grace_seconds)}if(I(t.ui)){if(t.ui.theme!==void 0)e.ui.theme=K(t.ui.theme);if(t.ui.keymap!==void 0)e.ui.keymap=Hn(t.ui.keymap)}if(I(t.secrets)){if(t.secrets.extra_markers!==void 0)e.secrets.extra_markers=Tt(t.secrets.extra_markers);if(t.secrets.extra_patterns!==void 0)e.secrets.extra_patterns=Tt(t.secrets.extra_patterns)}if(I(t.doctor)&&Array.isArray(t.doctor.tools))e.doctor.tools=t.doctor.tools.filter(I).map((o)=>({name:K(o.name),command:K(o.command)}));if(Array.isArray(t.plugins))e.plugins=t.plugins.filter(I).map((o)=>({path:K(o.path)})).filter((o)=>o.path!=="");if(I(t.environment)){if(Array.isArray(t.environment.sources))e.environment.sources=Tt(t.environment.sources);if(I(t.environment.secrets))e.environment.secrets={...e.environment.secrets,...Hn(t.environment.secrets)}}}function NS(e,t){if(t.enabled!==void 0)e.enabled=it(t.enabled);if(I(t.listen)){if(t.listen.host!==void 0)e.listen.host=K(t.listen.host);if(t.listen.port!==void 0)e.listen.port=xe(t.listen.port)}if(I(t.token_endpoint)){let n=t.token_endpoint;if(n.enabled!==void 0)e.token_endpoint.enabled=it(n.enabled);if(n.host!==void 0)e.token_endpoint.host=K(n.host);if(n.port!==void 0)e.token_endpoint.port=xe(n.port)}if(Array.isArray(t.routes))e.routes=t.routes.map((n)=>gr(n))}function HS(e,t){if(!I(t))return e;return{services:t.services!==void 0?Tt(t.services):e.services,environment:t.environment!==void 0?{...e.environment,...Hn(t.environment)}:e.environment}}function jS(e,t){if(!I(t))return e;return{command:t.command!==void 0?Ut(t.command):e.command,shell:t.shell!==void 0?it(t.shell):e.shell,working_dir:t.working_dir!==void 0?K(t.working_dir):e.working_dir,dependencies:t.dependencies!==void 0?Tt(t.dependencies):e.dependencies,environment:tg(e.environment,t.environment)}}function qs(e,t){if(!I(t))return e;let n=$l(t),r={...e,environment:tg(e.environment,t.environment),health:WS(e.health,t.health),identity:GS(e.identity,t.identity),logs:US(e.logs,t.logs),restart:KS(e.restart,t.restart),startup:qS(e.startup,t.startup),container:VS(e.container,t.container),hooks:BS(e.hooks,t.hooks)};if(n.has("extends"))r.extends=K(t.extends);if(n.has("description"))r.description=K(t.description);if(n.has("command"))r.command=Ut(t.command);if(n.has("shell"))r.shell=it(t.shell);if(n.has("working_dir"))r.working_dir=K(t.working_dir);if(n.has("dependencies"))r.dependencies=Il(t.dependencies);if(n.has("ports"))r.ports=Fl(t.ports);if(n.has("capabilities"))r.capabilities=Tt(t.capabilities);if(n.has("proxy"))r.proxy=Hl(t.proxy);return r}function BS(e,t){if(!I(t))return e;return{pre_start:t.pre_start!==void 0?Ut(t.pre_start):e.pre_start,post_start:t.post_start!==void 0?Ut(t.post_start):e.post_start}}function tg(e,t){if(!I(t))return e;let n={...e.vars},r={...e.defaults},o=e.required;for(let[i,s]of Object.entries(t))if(i==="required")o=Tt(s);else if(i==="defaults")Object.assign(r,Hn(s));else n[i]=K(s);return{vars:n,required:o,defaults:r}}function WS(e,t){if(!I(t))return e;return{type:t.type!==void 0?K(t.type):e.type,url:t.url!==void 0?K(t.url):e.url,address:t.address!==void 0?K(t.address):e.address,command:t.command!==void 0?Ut(t.command):e.command,interval_seconds:t.interval_seconds!==void 0?xe(t.interval_seconds):e.interval_seconds,timeout_seconds:t.timeout_seconds!==void 0?xe(t.timeout_seconds):e.timeout_seconds,start_period_seconds:t.start_period_seconds!==void 0?xe(t.start_period_seconds):e.start_period_seconds,unhealthy_threshold:t.unhealthy_threshold!==void 0?xe(t.unhealthy_threshold):e.unhealthy_threshold,healthy_reset_threshold:t.healthy_reset_threshold!==void 0?xe(t.healthy_reset_threshold):e.healthy_reset_threshold}}function GS(e,t){if(!I(t))return e;return{type:t.type!==void 0?K(t.type):e.type,mode:t.mode!==void 0?K(t.mode):e.mode,service_account:t.service_account!==void 0?K(t.service_account):e.service_account,config:t.config!==void 0&&I(t.config)?{...e.config??{},...t.config}:e.config}}function US(e,t){if(!I(t))return e;return{stdout:t.stdout!==void 0?it(t.stdout):e.stdout,stderr:t.stderr!==void 0?it(t.stderr):e.stderr}}function KS(e,t){if(!I(t))return e;return{enabled:t.enabled!==void 0?it(t.enabled):e.enabled,policy:t.policy!==void 0?K(t.policy):e.policy,max_retries:t.max_retries!==void 0?xe(t.max_retries):e.max_retries,backoff_seconds:t.backoff_seconds!==void 0?xe(t.backoff_seconds):e.backoff_seconds}}function qS(e,t){if(!I(t))return e;return{wait_for_healthy:t.wait_for_healthy!==void 0?it(t.wait_for_healthy):e.wait_for_healthy,timeout_seconds:t.timeout_seconds!==void 0?xe(t.timeout_seconds):e.timeout_seconds}}function VS(e,t){if(!I(t))return e;let n=Nl(t);if(!n)return e;return{image:t.image!==void 0?n.image:e?.image??"",runtime:t.runtime!==void 0?n.runtime:e?.runtime??"",ports:t.ports!==void 0?{...e?.ports??{},...n.ports}:e?.ports??{},env:t.env!==void 0?{...e?.env??{},...n.env}:e?.env??{},volumes:t.volumes!==void 0?n.volumes:e?.volumes??[]}}function ng(e,t){let n=Object.keys(e.services).sort();for(let r of n){let o=e.services[r]?.proxy??[];if(o.length===0)continue;o.forEach((i,s)=>{let c={name:o.length===1?r:`${r}-${s+1}`,match:i.match,upstream:i.upstream,auth:i.auth},l=e.proxy.routes.length;if(e.proxy.routes.push(c),t)Bn(t,c,`synthesized from services.${r}.proxy`,"synthesized",`proxy.routes.${l}`)})}}function rg(e,t=Vs()){if(Object.keys(e.templates).length===0)return;let n={};for(let[r,o]of Object.entries(e.services))n[r]=og(e,o,t.services[r]??new Set,t,{});e.services=n}function og(e,t,n,r,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=r.templates[t.extends]??new Set,c=og(e,i,a,r,s),l=JS(c,t,n);return l.extends=t.extends,l}function JS(e,t,n){let r={...e};if(n.has("extends"))r.extends=t.extends;if(n.has("description"))r.description=t.description;if(n.has("command"))r.command=t.command;if(n.has("shell"))r.shell=t.shell;if(n.has("working_dir"))r.working_dir=t.working_dir;if(n.has("dependencies"))r.dependencies=t.dependencies;if(n.has("ports"))r.ports=t.ports;if(n.has("capabilities"))r.capabilities=t.capabilities;if(n.has("proxy"))r.proxy=t.proxy;if(n.has("container")){let o=t.container,i=e.container;r.container=o&&i?{image:n.has("container.image")?o.image:i.image,runtime:n.has("container.runtime")?o.runtime:i.runtime,ports:n.has("container.ports")?o.ports:i.ports,env:n.has("container.env")?o.env:i.env,volumes:n.has("container.volumes")?o.volumes:i.volumes}:o??i}return r.hooks={pre_start:n.has("hooks.pre_start")?t.hooks.pre_start:e.hooks.pre_start,post_start:n.has("hooks.post_start")?t.hooks.post_start:e.hooks.post_start},r.health={type:n.has("health.type")?t.health.type:e.health.type,url:n.has("health.url")?t.health.url:e.health.url,address:n.has("health.address")?t.health.address:e.health.address,command:n.has("health.command")?t.health.command:e.health.command,interval_seconds:n.has("health.interval_seconds")?t.health.interval_seconds:e.health.interval_seconds,timeout_seconds:n.has("health.timeout_seconds")?t.health.timeout_seconds:e.health.timeout_seconds,start_period_seconds:n.has("health.start_period_seconds")?t.health.start_period_seconds:e.health.start_period_seconds,unhealthy_threshold:n.has("health.unhealthy_threshold")?t.health.unhealthy_threshold:e.health.unhealthy_threshold,healthy_reset_threshold:n.has("health.healthy_reset_threshold")?t.health.healthy_reset_threshold:e.health.healthy_reset_threshold},r.identity={type:n.has("identity.type")?t.identity.type:e.identity.type,mode:n.has("identity.mode")?t.identity.mode:e.identity.mode,service_account:n.has("identity.service_account")?t.identity.service_account:e.identity.service_account,config:n.has("identity.config")?t.identity.config:e.identity.config},r.logs={stdout:n.has("logs.stdout")?t.logs.stdout:e.logs.stdout,stderr:n.has("logs.stderr")?t.logs.stderr:e.logs.stderr},r.restart={enabled:n.has("restart.enabled")?t.restart.enabled:e.restart.enabled,policy:n.has("restart.policy")?t.restart.policy:e.restart.policy,max_retries:n.has("restart.max_retries")?t.restart.max_retries:e.restart.max_retries,backoff_seconds:n.has("restart.backoff_seconds")?t.restart.backoff_seconds:e.restart.backoff_seconds},r.startup={wait_for_healthy:n.has("startup.wait_for_healthy")?t.startup.wait_for_healthy:e.startup.wait_for_healthy,timeout_seconds:n.has("startup.timeout_seconds")?t.startup.timeout_seconds:e.startup.timeout_seconds},r.environment={vars:{...e.environment.vars,...t.environment.vars},defaults:{...e.environment.defaults,...t.environment.defaults},required:n.has("environment.required")?t.environment.required:e.environment.required},r}var FS;var ig=D(()=>{jl();FS=["environment","restart","startup","health","logs","identity","container","hooks"]});function Bl(e){if(e.version===0)throw L(ee,"version is required");if(e.version===oo)return e;throw L(ee,`unsupported config version ${e.version} (expected ${oo}); no migration is available`)}var Wl=D(()=>{Pe()});var sg,ag,cg,lg,dg,ug,pg,fg,gg,Gl,Ul,Kl,ql,mg,hg,vg,yg,xg,bg,wg,Sg,Vl,kg,Cg,_g,Rg,Pg,Eg,Tg,Ag,Lg,Dg,Og,Mg;var Jl=D(()=>{sg=["version","project","google","profiles","templates","services","tasks","proxy","logs","auth","shutdown","ui","secrets","doctor","plugins","environment"],ag=["extends","description","command","shell","working_dir","dependencies","ports","environment","health","identity","logs","restart","startup","capabilities","proxy","container","hooks"],cg=["type","url","address","command","interval_seconds","timeout_seconds","start_period_seconds","unhealthy_threshold","healthy_reset_threshold"],lg=["service","condition"],dg=["type","mode","service_account","config"],ug=["enabled","policy","max_retries","backoff_seconds"],pg=["wait_for_healthy","timeout_seconds"],fg=["enabled","listen","token_endpoint","routes"],gg=["host","port"],Gl=["name","match","upstream","auth"],Ul=["host","path"],Kl=["url"],ql=["type","identity","audience","service_account"],mg=["max_memory_events","persistence"],hg=["enabled","directory","retention_days","max_session_logs"],vg=["refresh_threshold_seconds"],yg=["stop_services_on_exit","grace_seconds"],xg=["theme","keymap"],bg=["name"],wg=["project_id","region"],Sg=["services","environment"],Vl=["required","defaults"],kg=["stdout","stderr"],Cg=["extra_markers","extra_patterns"],_g=["tools"],Rg=["name","command"],Pg=["enabled","host","port"],Eg=["path"],Tg=["sources","secrets"],Ag=["image","runtime","ports","env","volumes"],Lg=["pre_start","post_start"],Dg=["command","shell","working_dir","dependencies","environment"],Og=["google","google_api","iap","network","service_identity","local_http"],Mg=["|","||","&&",";",">",">>","<","&"]});function Wn(e,t){if(Array.isArray(e))return e.flatMap((o,i)=>Wn(o,$g(t,String(i))));if(!nk(e))return[];let n=XS(t),r=[];for(let o of Object.keys(e)){let i=$g(t,o);if(n.length>0&&!n.includes(o)&&!YS(t))r.push(i);r.push(...Wn(e[o],i))}return r}function YS(e){if(e==="services"||e==="profiles"||e==="templates"||e==="tasks")return!0;if(e.endsWith(".environment")||e.endsWith(".defaults")||e.endsWith(".keymap"))return!0;if(e.endsWith(".container.ports")||e.endsWith(".container.env"))return!0;if(e.endsWith(".identity.config")||e.includes(".identity.config."))return!0;return e.includes(".environment.")&&!e.endsWith(".environment")}function XS(e){switch(e){case"":return sg;case"project":return bg;case"google":return wg;case"proxy":return fg;case"proxy.listen":return gg;case"proxy.token_endpoint":return Pg;case"logs":return mg;case"logs.persistence":return hg;case"auth":return vg;case"shutdown":return yg;case"ui":return xg;case"secrets":return Cg;case"doctor":return _g;case"environment":return Tg;default:return QS(e)}}function QS(e){if(e==="services"||e==="profiles"||e==="templates"||e==="tasks")return[];if(e.startsWith("services.")||e.startsWith("templates.")){if(e.includes(".dependencies."))return lg;return ZS(e)}if(e.startsWith("profiles.")){if(e.split(".").length===2)return Sg}if(e.startsWith("tasks.")){let t=e.split(".");if(t.length===2)return Dg;if(t[2]==="environment")return Vl}if(e.includes("routes"))return tk(e);if(e.startsWith("doctor.tools")&&e.split(".").length>=3)return Rg;if(e==="plugins")return[];if(e.startsWith("plugins.")&&e.split(".").length===2)return Eg;return[]}function ZS(e){let t=e.split(".");if(t.length===2)return ag;if(t.length>=3)switch(t[2]){case"health":return cg;case"identity":return dg;case"restart":return ug;case"startup":return pg;case"logs":return kg;case"environment":return Vl;case"proxy":return ek(t);case"container":return Ag;case"hooks":return Lg;default:return[]}return[]}function ek(e){let t=e.slice(3),n=t[0]!==void 0&&/^\d+$/.test(t[0])?1:0,r=t[n]??"";if(r==="match")return Ul;if(r==="upstream")return Kl;if(r==="auth")return ql;return Gl}function tk(e){if(e==="proxy.routes")return[];if(e.endsWith(".match"))return Ul;if(e.endsWith(".upstream"))return Kl;if(e.endsWith(".auth"))return ql;if(e.includes("proxy.routes")&&e.split(".").length===zS+1)return Gl;return[]}function $g(e,t){if(e==="")return t;return`${e}.${t}`}function nk(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function so(e){return`unknown fields: ${e.join(", ")}`}var zS=2;var Ig=D(()=>{Jl()});function Fg(e,t,n){let r=e,o="";for(;;){let i=r.indexOf("${");if(i<0)return o+r;o+=r.slice(0,i);let s=r.slice(i).indexOf("}");if(s<0)throw Error(`unclosed environment reference in "${e}"`);let a=r.slice(i+2,i+s);o+=rk(a,t,n),r=r.slice(i+s+1)}}function rk(e,t,n){let r=e.split(".");if(r.length<3||r[0]!=="services")throw Error(`unsupported reference \${${e}}`);let o=r[1]??"",i=t.services[o];if(!i)throw Error(`reference \${${e}}: unknown service`);let s=n[o];if(r[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=Jf(i.ports);if(a&&!a.auto)return String(a.value)}if(r[2]==="ports"){let a=r[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 zl(e,t,n){let r={};for(let[o,i]of Object.entries(e))r[o]=Fg(i,t,n);return r}function Ng(e){let t=[],n=e;for(;;){let r=n.indexOf("${");if(r<0)return t;let o=n.slice(r).indexOf("}");if(o<0)return t;t.push(n.slice(r+2,r+o)),n=n.slice(r+o+1)}}function Hg(e,t){let n=e.split(".");if(n.length<2)return!1;if(n[0]!=="services"||n.length<3)return!1;let r=t.services[n[1]??""];if(!r)return!1;if(n[2]==="port"||n[2]==="ports"){if(n.length===3)return r.ports.length>0;if(n.length>=4){let o=n[3]??"";if(!Number.isNaN(Number.parseInt(o,10)))return!0;return Ol(r.ports,o)!==void 0}}return!0}var Yl=()=>{};import{existsSync as ok}from"fs";import{isAbsolute as ik,resolve as sk}from"path";import{fileURLToPath as ak}from"url";function Xl(e){let t=[];for(let[n,r]of Object.entries(e.services)){let o=r.health.type;if(o!==""&&!Wg.includes(o.toLowerCase()))t.push({service:n,type:o})}return t}function Xt(e){let t=[];if(e.version===0)t.push("version is required");else if(e.version!==oo)t.push(`unsupported config version ${e.version} (expected ${oo}); no migration is available`);if(Object.keys(e.services).length===0)t.push("at least one service must be defined");t.push(...dk(e)),t.push(...lk(e)),t.push(...gk(e)),t.push(...mk(e)),t.push(...hk(e));for(let[n,r]of e.plugins.entries())if(r.path==="")t.push(`plugins.${n}.path is required`);else try{let o=r.path.startsWith("file:")?ak(r.path):ik(r.path)?r.path:sk(e.repoRoot,r.path);if(!ok(o))t.push(`plugins.${n}.path does not exist: ${r.path}`)}catch{t.push(`plugins.${n}.path is invalid: ${r.path}`)}if(e.logs.max_memory_events<0)t.push("logs.max_memory_events must be >= 0");return t}function lk(e){let t=[];for(let[n,r]of Object.entries(e.tasks)){let o=`tasks.${n}`;if(io(r.command))t.push(`${o}.command is required`);t.push(...Js(o,r.command,r.shell));for(let i of r.dependencies)if(!e.services[i])t.push(`${o}.dependencies: unknown service "${i}"`);t.push(...Gg(`${o}.environment`,r.environment,e))}return t}function dk(e){let t=[],n={};for(let[r,o]of Object.entries(e.services)){let i=`services.${r}`;if(io(o.command)&&!o.container)t.push(`${i}.command is required`);t.push(...Js(i,o.command,o.shell)),t.push(...Js(`${i}.hooks.pre_start`,o.hooks.pre_start,o.shell)),t.push(...Js(`${i}.hooks.post_start`,o.hooks.post_start,o.shell)),t.push(...yk(i,o.capabilities));for(let c of o.dependencies){let l=wt(c);if(!e.services[l])t.push(`${i}.dependencies: unknown service "${l}"`);if(l===r)t.push(`${i}.dependencies: service cannot depend on itself`);if(!["service_started","service_healthy"].includes(Fn(c)))t.push(`${i}.dependencies: condition must be service_started or service_healthy`);if(Fn(c)==="service_healthy"&&e.services[l]?.health.type==="")t.push(`${i}.dependencies: service_healthy requires ${l} to define a health check`)}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<Ys||c.value>zs)t.push(`${i}.ports.${c.name}: invalid port ${c.value}`);else if(n[c.value])t.push(`duplicate port ${c.value} used by ${n[c.value]} and ${r}`);else n[c.value]=r;let s=fk(`${i}.identity`,o.identity,e.plugins.length>0);if(s!=="")t.push(s);if(t.push(...uk(i,o,e.plugins.length>0)),o.health.start_period_seconds<0)t.push(`${i}.health.start_period_seconds must be >= 0`);if(o.health.unhealthy_threshold<1)t.push(`${i}.health.unhealthy_threshold must be >= 1`);if(o.health.healthy_reset_threshold<1)t.push(`${i}.health.healthy_reset_threshold must be >= 1`);let a=Kf(o.restart);if(a!==Bf&&a!==Wf&&a!==Gf)t.push(`${i}.restart.policy must be never, on_failure, or always`);if(t.push(...Gg(`${i}.environment`,o.environment,e)),o.container){if(o.container.image==="")t.push(`${i}.container.image is required`);if(o.container.runtime!==""&&o.container.runtime!=="docker"&&o.container.runtime!=="podman")t.push(`${i}.container.runtime must be docker or podman`);for(let[c,l]of Object.entries(o.container.ports)){if(!o.ports.some((d)=>d.name===c))t.push(`${i}.container.ports.${c}: no matching service port`);if(l<Ys||l>zs)t.push(`${i}.container.ports.${c}: invalid container port ${l}`)}}}return t}function uk(e,t,n){let r=[];if(t.health.type==="")return r;let o=t.health.type.toLowerCase();if(!Wg.includes(o)&&!n)r.push(`${e}.health.type must be http, tcp, process, or command`);if(o==="http"&&t.health.url==="")r.push(`${e}.health.url is required for http health checks`);if(o==="tcp"&&t.health.address===""&&t.ports.length===0)r.push(`${e}.health.address is required for tcp health checks without ports`);if(o==="command"&&io({args:t.health.command.args,shell:!1}))r.push(`${e}.health.command is required for command health checks`);return r}function fk(e,t,n){let r=fi(t).toLowerCase();if(r===""||r==="user")return"";if(r==="service"||r==="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(n)return"";return`${e}.type must be user or service_account`}function Ql(e){let t=[];for(let[n,r]of Object.entries(e.services)){let o=fi(r.identity).toLowerCase();if(!pk.includes(o))t.push({service:n,type:o})}return t}function gk(e){let t={},n=[],r=[],o=(i)=>{let s=t[i]??ck;if(s===Bg)return;if(s===jg){n.push(`dependency cycle: ${[...r,i].join(" \u2192 ")}`);return}t[i]=jg,r.push(i);let a=e.services[i];if(a)for(let c of a.dependencies){let l=wt(c);if(e.services[l])o(l)}r.pop(),t[i]=Bg};for(let i of Object.keys(e.services))o(i);return n}function Gg(e,t,n){let r=[],o=(i,s)=>{for(let a of Ng(s))if(!Hg(a,n))r.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 r}function mk(e){let t=[];for(let[n,r]of Object.entries(e.profiles))for(let o of r.services)if(!e.services[o])t.push(`profiles.${n} references unknown service "${o}"`);return t}function hk(e){let t=[];if(e.proxy.listen.host!==""&&!xk(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<Ys||e.proxy.listen.port>zs))t.push("proxy.listen.port is invalid");let n={};return e.proxy.routes.forEach((r,o)=>{let i=`proxy.routes[${o}]`;if(r.name==="")t.push(`${i}.name is required`);else if(n[r.name])t.push(`${i}: duplicate route name ${r.name}`);if(n[r.name]=!0,r.upstream.url==="")t.push(`${i}.upstream.url is required`);if(r.auth.type.toLowerCase()==="iap"){if(r.auth.audience.trim()==="")t.push(`${i}.auth.audience is required when auth.type is iap`);if(r.auth.identity.type.trim()==="")t.push(`${i}.auth.identity.type is required when auth.type is iap`)}let s=r.auth.identity.type.toLowerCase();if(s==="service"||s==="service_account"||yn({type:s,mode:"",service_account:""})){if((r.auth.identity.service_account||r.auth.service_account)==="")t.push(`${i}.auth.identity.service_account is required`)}}),t.push(...vk(e)),t}function vk(e){let t=[],n=e.proxy.token_endpoint;if(!n.enabled)return t;let r=n.host||Tl;if(r==="0.0.0.0")t.push("proxy.token_endpoint.host must be a loopback address");else if(r!==""&&r!==Tl&&r!=="localhost"&&!r.startsWith("127."))t.push("proxy.token_endpoint.host must be a loopback address");if(n.port!==0&&(n.port<Ys||n.port>zs))t.push("proxy.token_endpoint.port is invalid");return t}function Js(e,t,n){if(t.shell||n)return[];for(let r of t.args)if(Mg.includes(r)||r.includes("|")||r.includes(";")||r.includes("&&"))return[`${e}.command contains shell metacharacters; set shell: true to run via a shell`];return[]}function yk(e,t){let n=[];for(let r of t)if(!Og.includes(r))n.push(`${e}.capabilities: unknown capability "${r}"`);return n}function xk(e){if(e==="localhost")return!0;return bk(e)}function bk(e){if(/^(\d{1,3}\.){3}\d{1,3}$/.test(e))return e.split(".").every((n)=>{let r=Number(n);return r>=0&&r<=255});return e.includes(":")}var zs=65535,Ys=1,Wg,ck=0,jg=1,Bg=2,pk;var Xs=D(()=>{Jl();Yl();Wg=["http","tcp","process","command"];pk=["","user","service","service_account"]});import{readdirSync as wk,readFileSync as Sk}from"fs";import{basename as Kg,dirname as kk,extname as Ck,join as mr,resolve as _k}from"path";import{parse as Rk}from"yaml";function ao(e,t,n){try{return xi(e,t,{candidateText:n}),[]}catch(r){if(r instanceof Oe){let o=`${r.kind}: `;return[r.message.startsWith(o)?r.message.slice(o.length):r.message]}return[r instanceof Error?r.message:String(r)]}}function ut(e,t){let{repoRoot:n,configPath:r}=jn(e,t);return xi(n,r)}function yi(e,t){try{return ut(e,t)}catch(n){if(!Ms(n,ar))throw n;let r=e===""?process.cwd():_k(e),o=pr();return o.repoRoot=r,o.configPath=mr(r,St,Kt),o}}function xi(e,t,n){let r=pr(),o=Vs();qg(t,r,o,n?.candidateText,"main"),r.repoRoot=e,r.configPath=t;let i=kk(t);if(Kg(i)===St)Ek(i,r,o);r=Pk(r,e,t,o),r=Bl(r);try{rg(r,o)}catch(a){throw fe(ee,"template merge failed",a)}ng(r,o.provenance),r.provenance=o.provenance;let s=Xt(r);if(s.length>0)throw L(ee,s.join(`
5
- `));return r}function Pk(e,t,n,r){let o=mr(Ft(),"config.local.yaml"),i=mr(t,St,"config.local.yaml");for(let s of[o,i]){if(s===n||!hi(s))continue;qg(s,e,r,void 0,s===o?"home_local":"repo_local")}return e}function qg(e,t,n,r,o="main"){let i=r!==void 0?Vg(r,e):Zl(e),s=Wn(i,"");if(s.length>0)throw L(ee,so(s));eg(t,i,n,{source:e,layer:o})}function Ek(e,t,n){Ug(mr(e,"services"),(o,i,s)=>{let a=Wn(i,`services.${o}`);if(a.length>0)throw L(ee,so(a));let c=t.services[o];t.services[o]=c?qs(c,i):mi(i),Ks(n.services,o,i),Bn(n.provenance,i,s,"modular_service",`services.${o}`)}),Ug(mr(e,"profiles"),(o,i,s)=>{let a=Wn(i,`profiles.${o}`);if(a.length>0)throw L(ee,so(a));t.profiles[o]=Ws(i),Bn(n.provenance,i,s,"modular_profile",`profiles.${o}`)});let r=mr(e,"proxy","routes.yaml");if(hi(r))Tk(r,t,n)}function Tk(e,t,n){let r=Zl(e);if(I(r.proxy))Bn(n.provenance,r.proxy,e,"modular_proxy","proxy");if(Array.isArray(r.routes))Bn(n.provenance,r.routes,e,"modular_proxy","proxy.routes");if(I(r.proxy)){let o=Wn({proxy:r.proxy},"");if(o.length>0)throw L(ee,so(o))}if(Array.isArray(r.routes))r.routes.forEach((o,i)=>{let s=Wn(o,`proxy.routes.${i}`);if(s.length>0)throw L(ee,so(s))});if(I(r.proxy)){if(Array.isArray(r.proxy.routes))t.proxy.routes.push(...r.proxy.routes.map((o)=>gr(o)));if(I(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((o)=>gr(o)))}function Ug(e,t){let n;try{n=wk(e)}catch(r){if(Ak(r))return;throw r}for(let r of n.sort()){let o=Ck(r);if(o!==".yaml"&&o!==".yml")continue;let i=mr(e,r),s=Zl(i);t(Kg(r,o),s,i)}}function Zl(e){let t;try{t=Sk(e,"utf8")}catch(n){throw fe(ee,"unable to read config",n)}return Vg(t,e)}function Vg(e,t){let n;try{n=Rk(e)}catch(r){throw fe(ee,`invalid YAML in ${t}`,r)}if(n===null||n===void 0)return{};if(!I(n))throw L(ee,`unable to decode config: ${t} is not a mapping`);return n}function Ak(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Jg=D(()=>{Pe();ze();jl();vi();ig();Wl();Ig();Xs();vi();Xs()});function hr(e){return Object.entries(e.provenance).sort(([t],[n])=>t.localeCompare(n)).flatMap(([t,n])=>{let r=n[n.length-1];if(!r)return[];return[{path:t,value:Lk(e,t),...r,shadowed:n.slice(0,-1)}]})}function Lk(e,t){let n=e;for(let r of t.split(".")){if(typeof n!=="object"||n===null)return;n=n[r]}return n}var st=D(()=>{Jg();vi();Xs();Wl();Yl()});import{readdirSync as Dk}from"fs";import{join as zg,resolve as ed,sep as td}from"path";function Ok(e){let t=zg(Ft(),"state"),n;try{n=Dk(t)}catch{return}let r=Yg(ed(e)),o;for(let i of n){let s=Rl(zg(t,i,"state.json"));if(!s)continue;let a=Yg(ed(s.repo_root));if(!Mk(a,r))continue;if(!o||a.length>o.length)o=a}return o}function Qs(e,t,n=""){if(t!=="")return{repoRoot:ed(t),source:"explicit"};let r=e===""?process.cwd():e;try{let{repoRoot:i}=jn(r,n);return{repoRoot:i,source:"config"}}catch{if(n!=="")return}let o=Ok(r);return o?{repoRoot:o,source:"state-scan"}:void 0}function Yg(e){let t=e.length>1&&e.endsWith(td)?e.slice(0,-1):e;return process.platform==="win32"?t.toLowerCase():t}function Mk(e,t){return t===e||t.startsWith(e.endsWith(td)?e:`${e}${td}`)}var Xg=D(()=>{vi();ze()});import{existsSync as Zg,readFileSync as em}from"fs";import{isAbsolute as $k,join as nd}from"path";import{parse as Ik}from"dotenv";function Hk(){return{name:"dotenv",load:(e)=>{let t=Qg(e.repoRoot,e.profile);if(e.workDir!=="")Object.assign(t,Qg(e.workDir,e.profile));return t}}}function Zs(e){return async(t)=>{let n=t.includes("/versions/")?t:`${t}/versions/latest`,r=await e(),o=await fetch(`https://secretmanager.googleapis.com/v1/${n}:access`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)throw L(ee,`secret manager request failed for ${t}: HTTP ${o.status}`);let i=await o.json();if(!i.payload?.data)throw L(ee,`secret manager response for ${t} had no payload`);return Buffer.from(i.payload.data,"base64").toString("utf8")}}function jk(e){let t=e?.environment.sources??[];if(t.length===0)return[...wi];let n=new Set([...Nk,...t]),r=new Set(wi),o=t.filter((s)=>!r.has(s)),i=[];for(let s of wi){if(s==="defaults")i.push(...o);if(n.has(s))i.push(s)}return i}async function ea(e,t){let n={},r=t.serviceCfg.working_dir;if(r!==""&&!$k(r))r=nd(e,r);let o={repoRoot:e,profile:t.profile,service:t.service,serviceCfg:t.serviceCfg,workDir:r,cfg:t.cfg},i=Bk(t),s={process:t.includeProcess===!1?{}:t.clientEnv??co(),profile:bi(t.profileEnv,t.cfg,i),dotenv:bi(await Hk().load(o),t.cfg,i),generated:{},keychain:t.sourceValues?.keychain??Wk(o),secret_manager:t.sourceValues?.secret_manager??await Gk(o,t.fetchSecret),defaults:bi(t.serviceCfg.environment.defaults,t.cfg,i),vars:bi(t.serviceCfg.environment.vars,t.cfg,i),runtime:t.runtime};for(let a of jk(t.cfg)){if(s[a]!==void 0){Object.assign(n,s[a]);continue}let c=t.pluginSources?.find((l)=>l.name===a);if(c)Object.assign(n,bi(await c.load(o),t.cfg,i))}for(let a of t.serviceCfg.environment.required)if((n[a]??"").trim()==="")throw L(ee,`service ${t.service} missing required environment variable ${a}`);return n}function Bk(e){let t={};if(e.cfg)for(let[n,r]of Object.entries(e.cfg.services)){let o={};for(let i of r.ports)if(!i.auto)o[i.name]=i.value;t[n]=o}if(e.assignedPorts)t[e.service]=e.assignedPorts;return t}function bi(e,t,n){if(!t||Object.keys(e).length===0)return e;return zl(e,t,n)}function Wk(e){let t=e.cfg?.environment.sources??[];if(t.length>0&&!t.includes("keychain"))return{};let n={},r=new Set([...Object.keys(e.serviceCfg.environment.defaults),...Object.keys(e.serviceCfg.environment.vars),...e.serviceCfg.environment.required]);for(let o of r){let i=nd(Wt(),"env",o);if(!Zg(i))continue;try{n[o]=em(i,"utf8").replace(/\n$/,"")}catch(s){throw fe(ee,`unable to read keychain env ${o}`,s)}}return n}async function Gk(e,t){if(!(e.cfg?.environment.sources??[]).includes("secret_manager"))return{};let r=e.cfg?.environment.secrets??{},o={};for(let[i,s]of Object.entries(r)){if(!Fk.test(s))throw L(ee,`environment.secrets.${i} is not a Secret Manager resource`);if(!t)throw L(ee,"environment source secret_manager is not configured \u2014 set credentials or remove it from environment.sources");o[i]=await t(s)}return o}function Qg(e,t){let n={},r=[".env",".env.development",".env.local"];if(t!=="")r.push(`.env.${t}`);for(let o of r){let i=nd(e,o);if(!Zg(i))continue;try{let s=Ik(em(i));Object.assign(n,s)}catch(s){throw fe(ee,`unable to read ${i}`,s)}}return n}function co(){let e={};for(let[t,n]of Object.entries(process.env))if(n!==void 0)e[t]=n;return e}function ta(e,t,n,r,o){let i={DEVCTL_SERVICE_NAME:e,DEVCTL_ENVIRONMENT:o,SERVICE_HOST:t};if(r!=="")i.DEVCTL_PROXY_URL=r;if(n.http!==void 0)i.SERVICE_PORT=String(n.http);else{let s=Object.values(n)[0];if(s!==void 0)i.SERVICE_PORT=String(s)}for(let[s,a]of Object.entries(n))i[`${s.toUpperCase()}_PORT`]=String(a);return i}function Si(e){return{...e}}var wi,Fk,Nk;var rd=D(()=>{st();Pe();ze();wi=["process","profile","dotenv","generated","keychain","secret_manager","defaults","vars","runtime"],Fk=/^projects\/[^/]+\/secrets\/[^/]+(?:\/versions\/[^/]+)?$/,Nk=["process","defaults","vars","runtime"]});function At(){return"devctl 0.2.2"}var pt="0.2.2",ki=1;import{createConnection as Uk}from"net";var{spawn:Kk}=globalThis.Bun;function Yk(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 ${ki}`}function Xk(e){if(e.compatible&&e.daemonVersion!==void 0&&e.daemonVersion!==pt)return`attached daemon is devctl ${e.daemonVersion}; this client is ${pt} (run \`devctl down\` then start again to update it)`;return}function od(e,t){if(!e.compat.compatible&&!zk.has(t))throw ke(Je,Yk(e.compat),"run `devctl down` to stop it, then start again")}class rm{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 n=this.buf.split(`
6
- `);this.buf=n.pop()??"";for(let r of n){if(r.trim()==="")continue;this.onLine(r)}}),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 r of this.listeners)r(t.event);return}let n=t.id?this.pending.get(t.id):void 0;if(!n)return;if(this.pending.delete(t.id??""),clearTimeout(n.timer),t.error){n.reject(Mf({error:t.error,kind:t.kind,hint:t.hint,service:t.service}));return}n.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,n=Jk){this.nextID+=1;let r=String(this.nextID);return new Promise((o,i)=>{let s=setTimeout(()=>{this.pending.delete(r),i(Error(`${e} timed out after ${n}ms`))},n);this.pending.set(r,{resolve:o,reject:i,timer:s}),this.socket.write(JSON.stringify({id:r,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 om(e,t){let n=Is(e),r=Date.now()+t;return new Promise((o,i)=>{let s=()=>{let a=Uk(n);a.once("connect",()=>{let c=new rm(a);Qk(c).finally(()=>o(c))}),a.once("error",(c)=>{if(a.destroy(),Date.now()>=r){i(ke(Je,"supervisor is not running","run `devctl start` or `devctl attach` after starting services"));return}setTimeout(s,qk)})};s()})}async function Qk(e){let t;try{t=await e.call("ping",null,nm)}catch{return}let n=Zk(t)?t:{};if(typeof n.session==="string")e.session=n.session;let r=typeof n.protocol==="number"?n.protocol:void 0,o=typeof n.version==="string"?n.version:void 0;if(r===void 0){e.compat={compatible:!1,legacy:!0,daemonVersion:o};return}e.compat={compatible:r===ki,legacy:!1,daemonVersion:o,daemonProtocol:r}}function Zk(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}async function vr(e){try{return await om(e,Vk)}catch{return}}function eC(e,t,n,r){return n?[e,...r]:[e,t,...r]}async function im(e,t){let n=await vr(e);if(n)return n;Ff(e);let r=dr(e),o=eC(process.execPath,process.argv[1]??"",Bun.isStandaloneExecutable===!0,["--config",t,"_supervisor","--repo",e]);Kk({cmd:o,env:process.env,stdout:"ignore",stderr:Bun.file(r),stdin:"ignore",detached:!0}).unref();try{return await om(e,nm)}catch{throw ke(Je,"supervisor failed to start",`see ${r} for details`)}}class na{cfg;client;previousPersisted;constructor(e){this.cfg=e}async start(e){return await this.call("start",{...e,client_env:co()})}async stop(e){await this.call("stop",{services:e})}async restart(e,t){await this.call("restart",{services:e,cascade:t===!0,client_env:co()})}async runTask(e){return await this.call("run_task",{name:e,client_env:co()},tm)}async execService(e,t,n=!1){return await this.call("exec",{service:e,command:t,print_env:n,client_env:co()},tm)}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,n){if(!this.client)throw fe(Je,"supervisor is not running",Error("no client"));return od(this.client,e),this.client.call(e,t,n)}}function Ci(e){let t=e&&Xk(e.compat);if(t)process.stderr.write(`warning: ${t}
8
- `)}async function id(e,t,n=""){let r=Qs(e,t,n);if(!r)throw ke(Je,"no devctl configuration found","run `devctl setup`, create a .devctl/config.yaml in the repository root, or pass --repo");let o=await vr(r.repoRoot);return Ci(o),{repoRoot:r.repoRoot,client:o}}async function kt(e,t,n,r){let o=r?.allowMissingConfig===!0?yi(e,t):ut(e,t),i=new na(o);if(!n)return i.client=await vr(o.repoRoot),Ci(i.client),i;return i.client=await im(o.repoRoot,o.configPath),Ci(i.client),i}async function sm(e){let t=new na(pr());return t.client=e,Ci(t.client),t.cfg=await t.configSnapshot(),t}async function am(e,t){let n=Qs(e,"",t),r=n?await vr(n.repoRoot):void 0;if(!r)throw ke(Je,"supervisor is not running","run `devctl start` before `devctl attach`");return sm(r)}async function cm(e,t){let n=Qs(e,"",t),r=n?await vr(n.repoRoot):void 0;if(r)return sm(r);let o=ut(e,t),i=new na(o),s=ur(o.repoRoot);if(i.client=await im(o.repoRoot,o.configPath),Ci(i.client),i.cfg=await i.configSnapshot(),s&&s.processes.length>0)i.previousPersisted=s;return i}var qk=50,nm=8000,Vk=200,Jk=30000,tm=86400000,zk;var sd=D(()=>{st();Xg();rd();Pe();ze();zk=new Set(["logs","logs_page","logs_stats"])});function oa(e){if(yn(e))return Nt({kind:yr,serviceAccount:e.service_account});if(Uf(e)&&(e.type!==""||e.mode!==""))return Nt({kind:ra});let t=(e.type||e.mode).toLowerCase();if(t!=="")return Nt({kind:t,providerConfig:e.config??{}});return Nt({kind:lo})}function xr(e){if(e.type.toLowerCase()==="none")return Nt({kind:lo});let t=e.identity.type.toLowerCase(),n=e.identity.service_account||e.service_account;if(t==="service"||t==="service_account"||e.type==="service_account")return Nt({kind:yr,serviceAccount:n});if(e.type.toLowerCase()==="iap"&&t==="")return Nt({kind:lo});if(e.type===""&&t==="")return Nt({kind:lo});return Nt({kind:ra})}function lm(e){return e.kind===ra||e.kind===yr}function uo(e){if(e.tokenKey!=="")return e.tokenKey;if(e.kind===yr)return`sa:${e.serviceAccount}`;if(e.email!=="")return`user:${e.email}`;return"user"}function Nt(e={}){return{kind:lo,email:"",serviceAccount:"",project:"",projectSource:"",adcAvailable:!1,providerConfig:{},tokenKey:"",...e}}function ad(e){let t=new Map,n=(r,o)=>{if(r!=="")t.set(r,(t.get(r)??!1)||o)};for(let r of Object.values(e.services))if(yn(r.identity)&&r.identity.service_account!=="")n(r.identity.service_account,!0);for(let r of e.proxy.routes){let o=r.auth.type.toLowerCase(),i=r.auth.identity.type.toLowerCase(),s=r.auth.identity.service_account||r.auth.service_account;if(i==="service"||i==="service_account"||o==="service_account")n(s,o!=="none")}return[...t.entries()].map(([r,o])=>({email:r,active:o})).sort((r,o)=>r.email.localeCompare(o.email))}function Gn(e){return ad(e).filter((t)=>t.active).map((t)=>t.email)}function dm(e,t,n){let r=[];for(let o of t){let i=e.services[o];if(!i)continue;let s=oa(i.identity);if(yn(i.identity)&&i.identity.service_account===""){r.push({name:o,message:"service account identity is not configured"});continue}if((lm(s)||i.capabilities.some((c)=>c==="google_api"||c==="iap"||c==="service_identity"))&&!n)r.push({name:o,message:"ADC unavailable"})}return r}function _i(e){if(Gn(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(lm(oa(t.identity)))return!0;return t.capabilities.some((n)=>n==="google_api"||n==="iap"||n==="service_identity")})}function cd(){return{name:"user",accepts:(e)=>!yn(e),resolve:async(e,t)=>{if(e.type===""&&e.mode==="")return Nt({kind:lo});return{...await t(),kind:ra}}}}function ld(){return{name:"service_account",accepts:(e)=>yn(e),resolve:async(e,t)=>{if(e.service_account==="")throw L(Os,"service account identity is not configured");return{...await t(),kind:yr,serviceAccount:e.service_account}}}}async function um(e,t,n){if(n)for(let r=n.length-1;r>=0;r-=1){let o=n[r];if(o?.accepts(e))return o.resolve(e,t)}if(yn(e))return ld().resolve(e,t);return cd().resolve(e,t)}var ra="user",yr="service_account",lo="none";var br=D(()=>{st();Pe()});import{existsSync as ia,readFileSync as tC}from"fs";import{homedir as fm}from"os";import{join as dd}from"path";var{spawn:ud}=globalThis.Bun;function fo(){let e=globalThis;if(e.window&&typeof e.window.fetch!=="function")e.window.fetch=fetch}function pd(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS||dd(fm(),".config","gcloud","application_default_credentials.json");if(!ia(e))return"";try{let t=JSON.parse(tC(e,"utf8"));return typeof t.quota_project_id==="string"?t.quota_project_id:""}catch{return""}}async function Lt(e){let t={gcloudInstalled:await fd("gcloud"),adcAvailable:!1,userEmail:"",projectID:"",projectSource:""};if(e!=="")t.projectID=e,t.projectSource="configuration";else{let n=cC("GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_PROJECT");if(n!=="")t.projectID=n,t.projectSource="environment variable";else if(t.gcloudInstalled){let r=await pm("core/project");if(r!=="")t.projectID=r,t.projectSource="gcloud configuration"}}if(Ri())try{await vm(oC(t),rC)}catch(n){t.adcAvailable=!1,t.error=mo(n)}if(t.userEmail===""&&t.gcloudInstalled)t.userEmail=await pm("core/account");return t}async function oC(e){fo();let{GoogleAuth:t}=await import("google-auth-library"),n=new t({scopes:[nC]});await n.getClient(),e.adcAvailable=!0;let r=await n.getProjectId().catch(()=>"");if(e.projectID===""&&r)e.projectID=r,e.projectSource="application default credentials";let o=await iC(n);if(o!=="")e.userEmail=o}async function iC(e){try{let t=await e.getCredentials();if(t.client_email)return t.client_email}catch{}try{let t=await e.getClient(),n=typeof t.credentials?.id_token==="string"?t.credentials.id_token:"";if(n!==""){let r=sC(n);if(r!=="")return r}}catch{return""}return""}function sC(e){let t=e.split(".");if(t.length<2||!t[1])return"";try{let n=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));return typeof n.email==="string"?n.email:""}catch{return""}}async function mm(e){let t=await Lt(e);return Nt({kind:"user",email:t.userEmail,project:t.projectID,projectSource:t.projectSource,adcAvailable:t.adcAvailable})}async function go(){if(await ud({cmd:["gcloud","auth","application-default","login"],stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited!==0)throw ke(to,"application-default login failed","run `gcloud auth application-default login`")}async function sa(){if(await ud({cmd:["gcloud","auth","application-default","revoke","--quiet"],stdout:"ignore",stderr:"pipe"}).exited!==0)throw ke(to,"failed to revoke application-default credentials","run `gcloud auth application-default revoke`")}function mo(e){let t=aC(e).toLowerCase();if(po(t,["unauth","invalid_grant","token has been expired","expired"]))return ke(to,"credential expired or invalid","run `devctl auth login` or `gcloud auth application-default login`");if(po(t,["api has not been used","has not been enabled","access not configured","service_disabled"]))return ke(cr,"required Google API is not enabled","enable the API in the target service account project; devctl will not enable APIs automatically");if(po(t,["permission","forbidden","iam"])){if(po(t,["serviceaccounttoken","iamcredentials","token creator","getaccesstoken"]))return ke(Os,"cannot impersonate service account","ask an administrator to grant roles/iam.serviceAccountTokenCreator on the target service account");return ke(cr,"authorization failure","verify IAM permissions for the current user on this project")}if(t.includes("audience"))return ke(yl,"IAP audience is incorrect","set auth.audience on the proxy route to the IAP OAuth client ID");if(t.includes("iap"))return fe(yl,"IAP authentication failure",e);if(t.includes("project"))return ke(ee,"wrong or missing Google project","set google.project_id in .devctl/config.yaml");if(po(t,["timeout","network","connection refused","no such host"]))return fe(Je,"network problem reaching Google Cloud",e);if(po(t,["adc","default credentials","could not find"]))return ke(to,"application default credentials unavailable","run `gcloud auth application-default login`");return fe(to,"Google authentication failed",e)}function aC(e){let t=[],n=new Set,r=(o,i)=>{if(o===null||o===void 0||i>8||n.has(o))return;if(typeof o==="string"){t.push(o);return}if(typeof o!=="object")return;n.add(o);let s=o;for(let a of["message","reason","status","code","error_description","permission","service"])r(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)=>r(l,i+1));else r(c,i+1)}};return r(e,0),t.length>0?t.join(" "):String(e)}function po(e,t){return t.some((n)=>e.includes(n))}function cC(...e){for(let t of e){let n=process.env[t];if(n)return n}return""}async function fd(e){try{return(await hm(process.platform==="win32"?["where",e]:["which",e],gm)).code===0}catch{return!1}}function Ri(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS;if(e&&ia(e))return!0;if(ia(dd(fm(),".config","gcloud","application_default_credentials.json")))return!0;let t=process.env.APPDATA;return Boolean(t&&ia(dd(t,"gcloud","application_default_credentials.json")))}async function pm(e){try{let t=await hm(["gcloud","config","get-value",e],gm);if(t.code!==0)return"";let n=t.stdout.trim();if(n===""||n==="(unset)")return"";return n}catch{return""}}async function hm(e,t){let n=ud({cmd:e,stdout:"pipe",stderr:"ignore",env:{...process.env,CLOUDSDK_CORE_DISABLE_PROMPTS:"1",CLOUDSDK_CORE_DISABLE_USAGE_REPORTING:"true"}}),r=n.stdout?new Response(n.stdout).text():Promise.resolve("");try{let[o,i]=await vm(Promise.all([r,n.exited]),t);return{code:i??1,stdout:o}}catch{return n.kill(),{code:1,stdout:""}}}function vm(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("timeout")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}var nC="https://www.googleapis.com/auth/cloud-platform",gm=1500,rC=2000;var wr=D(()=>{eo();Pe();br()});var{spawn:gd}=globalThis.Bun;import{createServer as ym}from"net";async function xm(e,t,n={}){let r={};for(let[i,s]of Object.entries(n))for(let a of Object.values(s))r[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=n[i]?.[c.name],d=l&&l>=md?l:c.value;if(l===void 0&&c.auto)d=await dC();if(d<md||d>lC)throw new Oe(ee,`invalid port ${d} on service ${i}`,{service:i});if(r[d]&&r[d]!==i)throw new Oe(ee,`duplicate port ${d} used by ${r[d]} and ${i}`,{service:i});if(l!==d&&!c.auto&&!await ho(d))throw await uC(i,c.name,d);r[d]=i,a[c.name]=d}o[i]=a}return o}function dC(){return new Promise((e,t)=>{let n=ym();n.listen(0,"127.0.0.1",()=>{let r=n.address();n.close(()=>{if(r&&typeof r==="object")e(r.port);else t(fe(ee,"unable to allocate dynamic port",Error("no address")))})}),n.on("error",(r)=>t(fe(ee,"unable to allocate dynamic port",r)))})}async function aa(e){let t=e.ports.filter((r)=>!r.auto&&r.value>=md);if(t.length===0)return;let n={};for(let r of t){if(await ho(r.value))return;n[r.name]=r.value}return n}function ho(e){return new Promise((t)=>{let n=ym();n.listen(e,"127.0.0.1",()=>{n.close(()=>t(!0))}),n.on("error",()=>t(!1))})}async function uC(e,t,n){let r=await vo(n);return pC(e,t,n,r)}function pC(e,t,n,r){let o=t===""?`${e} port`:`${e} ports.${t}`;if(r&&r.pid===process.pid)return ke(Ke,`${e} blocked: this TUI already holds port ${n}`,`Stop the proxy from the Proxy screen, or change ${o} in .devctl.`,e);if(r)return ke(Ke,`${e} blocked: ${r.command} (pid ${r.pid}) is using port ${n}`,`Open Doctor and press enter to free port ${n}, or change ${o} in .devctl.`,e);return ke(Ke,`${e} blocked: port ${n} is already in use`,`Something is listening on ${n}. Open Doctor to free it, or change ${o} in .devctl.`,e)}function fC(e,t){let n=e.split(`
9
- `).filter((r)=>r.trim()!==""&&!r.startsWith("COMMAND"));for(let r of n){let o=r.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 vo(e){if(process.platform==="win32")return mC(e);let t=gd({cmd:["lsof","-nP",`-iTCP:${e}`,"-sTCP:LISTEN"],stdout:"pipe",stderr:"ignore"}),n=await new Response(t.stdout).text();await t.exited;let r=fC(n,e);if(r)return r;let o=gd({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 gC(e,t){for(let n of e.split(`
10
- `)){if(!n.includes("LISTENING")&&!n.includes("LISTEN"))continue;if(!n.includes(`:${t}`)&&!n.includes(` ${t} `))continue;let r=n.trim().match(/(\d+)\s*$/),o=r?Number(r[1]):0;if(Number.isInteger(o)&&o>0)return{port:t,pid:o,command:"process"}}return}async function mC(e){let t=gd({cmd:["netstat","-ano"],stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,gC(n,e)}async function ca(e){if(e.pid===process.pid)throw ke(Ke,`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 fe(Ke,`could not stop pid ${e.pid} on port ${e.port}`,t)}await vC(hC);try{process.kill(e.pid,0),process.kill(e.pid,"SIGKILL")}catch{return}}function vC(e){return new Promise((t)=>{setTimeout(t,e)})}var lC=65535,md=1,hC=400;var Pi=D(()=>{Pe()});var{spawn:xd}=globalThis.Bun;import{existsSync as da,readdirSync as yC,readFileSync as bm,unlinkSync as xC}from"fs";import{join as Ei}from"path";function yd(e){return Ei(Wt(),`${pa(e)}${vd}`)}function ua(e){if(e==="file"||process.env.DEVCTL_HOME&&e!=="keychain")return new la;if(e==="keychain"||process.platform==="darwin"||process.platform==="win32"||process.platform==="linux")return new wm(new la);return new la}class la{backend="file";async get(e){let t=kC(e);if(!t||t.accessToken==="")return;return t}async set(e,t){Gt(yd(e),`${JSON.stringify({...SC(t),key:e})}
11
- `)}async delete(e){let t=yd(e);if(da(t))xC(t)}async list(){let e=Wt();if(!da(e))return[];let t=[];for(let n of yC(e)){if(!n.endsWith(vd))continue;let r=n.slice(0,-vd.length),o=Sm(Ei(Wt(),n));if(!o)continue;t.push(km(o.key??r,o.record))}return t.sort((n,r)=>n.identity.localeCompare(r.identity))}}class wm{backend="keychain";fallback;constructor(e){this.fallback=e}async get(e){let t=await CC(e);if(t)return t;return this.fallback.get(e)}async set(e,t){if(!await _C(e,t))await this.fallback.set(e,t);bC(e)}async delete(e){await RC(e),await this.fallback.delete(e),wC(e)}async list(){let e=new Set(wd()),t=await this.fallback.list(),n=new Map;for(let r of t)n.set(r.key,r);for(let r of e){let o=await this.get(r);if(o)n.set(r,km(r,o))}return[...n.values()].sort((r,o)=>r.identity.localeCompare(o.identity))}}function bC(e){let t=wd();if(!t.includes(e))Gt(Ei(Wt(),bd),`${JSON.stringify([...t,e])}
12
- `)}function wC(e){let t=wd(),n=t.filter((r)=>r!==e);if(n.length!==t.length)Gt(Ei(Wt(),bd),`${JSON.stringify(n)}
13
- `)}function wd(){let e=Ei(Wt(),bd);if(!da(e))return[];try{let t=JSON.parse(bm(e,"utf8"));return Array.isArray(t)?t.filter((n)=>typeof n==="string"):[]}catch{return[]}}function SC(e){return{...e,accessToken:""}}function kC(e){return Sm(yd(e))?.record}function Sm(e){if(!da(e))return;try{let t=JSON.parse(bm(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((n)=>typeof n==="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 km(e,t){let n=Date.parse(t.expiresAt);return{key:e,identity:t.identity,audience:t.audience,scopes:t.scopes,expires_at:t.expiresAt,valid:Number.isFinite(n)&&n-Date.now()>0}}function pa(e){return e.replace(/[^A-Za-z0-9._-]+/g,"_").slice(0,80)||"token"}async function CC(e){let t=await PC(e);if(!t)return;try{return JSON.parse(t)}catch{return}}async function _C(e,t){let n=JSON.stringify(t);if(process.platform==="darwin")return await yo(["security","delete-generic-password","-s",Sr,"-a",e]),await yo(["security","add-generic-password","-s",Sr,"-a",e,"-w",n,"-U"])===0;if(process.platform==="linux")return await EC(["secret-tool","store","--label",`devctl ${e}`,"service",Sr,"account",e],n)===0;if(process.platform==="win32"){let o=`Add-Type -AssemblyName System.Security; $bytes = [Convert]::FromBase64String('${Buffer.from(n,"utf8").toString("base64")}'); $enc = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser'); [IO.File]::WriteAllBytes($env:LOCALAPPDATA + '\\devctl-cred-${pa(e)}.bin', $enc)`;return await yo(["powershell","-NoProfile","-Command",o])===0}return!1}async function RC(e){if(process.platform==="darwin"){await yo(["security","delete-generic-password","-s",Sr,"-a",e]);return}if(process.platform==="linux"){await yo(["secret-tool","clear","service",Sr,"account",e]);return}if(process.platform==="win32")await yo(["powershell","-NoProfile","-Command",`Remove-Item -ErrorAction SilentlyContinue ($env:LOCALAPPDATA + '\\devctl-cred-${pa(e)}.bin')`])}async function PC(e){if(process.platform==="darwin"){let t=await hd(["security","find-generic-password","-s",Sr,"-a",e,"-w"]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="linux"){let t=await hd(["secret-tool","lookup","service",Sr,"account",e]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="win32"){let t=`$p = $env:LOCALAPPDATA + '\\devctl-cred-${pa(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)`,n=await hd(["powershell","-NoProfile","-Command",t]);return n.code===0&&n.stdout!==""?n.stdout:void 0}return}async function yo(e){try{return await xd({cmd:e,stdout:"ignore",stderr:"ignore",timeout:Sd}).exited}catch{return 1}}async function EC(e,t){try{return await xd({cmd:e,stdin:new TextEncoder().encode(t),stdout:"ignore",stderr:"ignore",timeout:Sd}).exited}catch{return 1}}async function hd(e){try{let t=xd({cmd:e,stdout:"pipe",stderr:"ignore",timeout:Sd}),n=t.stdout?await new Response(t.stdout).text():"";return{code:await t.exited,stdout:n.trim()}}catch{return{code:1,stdout:""}}}var bd="keychain-index.json",Sr="devctl.credentials",vd=".cred.json",Sd=3000;var kd=D(()=>{ze()});function Me(e,t,n){return{type:e,timestamp:new Date().toISOString(),service:t,payload:n}}class Pd{subs=new Map;nextID=0;buffer=[];maxBuf;constructor(e){this.maxBuf=e>0?e:1024}subscribe(e,t=[]){this.nextID+=1;let n=this.nextID;return this.subs.set(n,{types:new Set(t),handler:e}),()=>{this.subs.delete(n)}}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 n of this.subs.values())if(n.types.size===0||n.types.has(t.type))n.handler(t)}recent(){return[...this.buffer]}}var Cm="ServiceStarted",Cd="ServiceStopped",_m="ServiceFailed",Rm="ServiceStateChanged",Pm="ServiceHealthChanged",fa="LogReceived",xo="TokenRefreshed",kr="TokenRefreshFailed",_d="AuthenticationChanged",Em="ProxyStarted",Tm="ProxyStopped",Rd="ProxyRequest",ga="ConfigurationChanged",Ti="ConfigurationReloadFailed",Am="SessionRecovered";async function Lm(e,t={}){let n=t.attempts??TC,r=t.backoffMs??AC,o=t.retry??LC,i=Error("retry exhausted");for(let s=0;s<n;s+=1)try{return await e()}catch(a){if(i=a,!o(a)||s===n-1)throw a;await DC(r*(s+1))}throw i}function LC(e){if(e instanceof Oe)return e.kind!==ee&&e.kind!==cr;return!0}function DC(e){return new Promise((t)=>{setTimeout(t,e)})}var TC=3,AC=200;var Dm=D(()=>{Pe()});var Im={};Ls(Im,{TokenManager:()=>bo,expiresSoonToken:()=>Mm,googleTokenProviders:()=>Cr,isValidToken:()=>Om,staticTokenProvider:()=>GC,tokenCacheKey:()=>Ed,tokenMetaPath:()=>$m});import{createHash as OC}from"crypto";import{join as MC}from"path";import{GoogleAuth as ha,Impersonated as $C}from"google-auth-library";function Ed(e,t,n){return`${e}|${t}|${n.join(",")}`}function Om(e,t=Td){if(e.accessToken==="")return!1;return e.expiresAt.getTime()-Date.now()>=t}function Mm(e,t=Td){if(e.accessToken==="")return!0;let n=e.expiresAt.getTime()-Date.now();return n>0&&n<t}class bo{cache=new Map;inflight=new Map;providers;thresholdMs;bus;store;constructor(e,t,n,r){this.thresholdMs=e>0?e:Td,this.providers=[...t],this.bus=n,this.store=r??ua(process.env.DEVCTL_CREDENTIAL_BACKEND==="file"?"file":void 0)}replaceProviders(e){this.providers.splice(0,this.providers.length,...e)}isValid(e){return Om(e,this.thresholdMs)}expiresSoon(e){return Mm(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,n){let r=Ed(e,t,n),o=this.cache.get(r)??await this.loadStored(r);if(o&&this.isValid(o))return this.cache.set(r,o),o;return this.refresh(e,t,n)}async refresh(e,t,n){let r=Ed(e,t,n),o=this.inflight.get(r);if(o)return o;let i=this.refreshOnce(r,e,t,n);this.inflight.set(r,i);try{return await i}finally{this.inflight.delete(r)}}async refreshOnce(e,t,n,r){let o=this.providers.filter((s)=>!s.accepts||s.accepts(t,n,r));if(o.length===0)throw L(hn,`no token provider accepts identity ${t}`);let i=L(hn,"no token provider available");for(let s of o)try{let a=await Lm(()=>s.fetch(t,n,r),{attempts:FC,backoffMs:NC,retry:ZC});return this.cache.set(e,a),jC(e,a),await this.store.set(e,BC(a)),this.bus?.publish(Me(xo,"",{identity:a.identity,audience:a.audience})),a}catch(a){i=a instanceof Error?a:Error(String(a))}throw this.bus?.publish(Me(kr,"",{identity:t,audience:n,error:F(i)})),i}async loadStored(e){let t=await this.store.get(e);if(!t||t.accessToken==="")return;return WC(t)}async clearStore(){let e=await this.store.list();await Promise.all(e.map((t)=>this.store.delete(t.key)))}}function $m(e){let t=OC("sha256").update(e).digest("hex").slice(0,16);return MC(Wt(),`${t}.json`)}function jC(e,t){let n={identity:t.identity,audience:t.audience,expires_at:t.expiresAt.toISOString(),scopes:t.scopes};Gt($m(e),`${JSON.stringify(n)}
14
- `)}function BC(e){return{identity:e.identity,audience:e.audience,scopes:e.scopes,accessToken:e.accessToken,tokenType:e.tokenType,expiresAt:e.expiresAt.toISOString()}}function WC(e){return{accessToken:e.accessToken,tokenType:e.tokenType||"Bearer",expiresAt:new Date(e.expiresAt),audience:e.audience,identity:e.identity,scopes:e.scopes}}function Cr(){return[qC(),KC(),UC()]}function GC(e){return{name:"static",accepts:(t,n)=>(e.identity===""||t===e.identity)&&(e.audience===""||n===e.audience),fetch:async(t,n,r)=>({...e,identity:t,audience:n,scopes:r})}}function UC(){return{name:"user",accepts:(e,t)=>!e.startsWith("sa:")&&t==="",fetch:async(e,t,n)=>{if(e.startsWith("sa:"))throw L(hn,"user provider cannot mint service-account tokens");return YC(e,t,n)}}}function KC(){return{name:"service_account",accepts:(e,t)=>e.startsWith("sa:")&&t==="",fetch:async(e,t,n)=>{if(!e.startsWith("sa:"))throw L(hn,"service-account provider cannot mint user tokens");return VC(e,t,n)}}}function qC(){return{name:"iap",accepts:(e,t)=>t!=="",fetch:async(e,t,n)=>{if(t==="")throw L(hn,"IAP audience is required");if(e.startsWith("sa:"))return JC(e,t,n);return zC(e,t,n)}}}async function VC(e,t,n){let r=e.slice(3);try{fo();let i=await new ha({scopes:n.length>0?n:[ma]}).getClient(),s=new $C({sourceClient:i,targetPrincipal:r,targetScopes:n.length>0?n:[ma],lifetime:3600}),a=await s.getAccessToken(),c=typeof a==="string"?a:a?.token;if(!c)throw L(hn,"empty impersonated token");return{accessToken:c,tokenType:"Bearer",expiresAt:va(c,s),audience:t,identity:e,scopes:n}}catch(o){throw mo(o)}}async function JC(e,t,n){let r=e.slice(3);try{fo();let i=await new ha({scopes:[ma]}).getClient(),s=`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(r)}:generateIdToken`,c=(await i.request({url:s,method:"POST",data:{audience:t,includeEmail:!0}})).data.token;if(!c)throw L(hn,"empty impersonated IAP id token");return{accessToken:c,tokenType:"Bearer",expiresAt:va(c),audience:t,identity:e,scopes:n}}catch(o){throw mo(o)}}async function zC(e,t,n){try{fo();let i=await(await new ha({scopes:n.length>0?n:[HC]}).getIdTokenClient(t)).idTokenProvider.fetchIdToken(t);return{accessToken:i,tokenType:"Bearer",expiresAt:va(i),audience:t,identity:e,scopes:n}}catch(r){throw mo(r)}}async function YC(e,t,n){try{fo();let o=await new ha({scopes:n.length>0?n:[ma]}).getClient(),i=await o.getAccessToken();if(!i.token)throw L(hn,"empty access token");return{accessToken:i.token,tokenType:"Bearer",expiresAt:XC(o,i.token),audience:t,identity:e,scopes:n}}catch(r){throw mo(r)}}function va(e,t){if(t?.credentials?.expiry_date)return new Date(t.credentials.expiry_date);return QC(e)??new Date(Date.now()+IC)}function XC(e,t){return va(t,e)}function QC(e){let t=e.split(".");if(t.length<2||!t[1])return;try{let n=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));if(typeof n.exp==="number")return new Date(n.exp*1000)}catch{return}return}function ZC(e){if(e instanceof Oe)return e.kind!==ee&&e.kind!==cr;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 Td=300000,IC=3000000,FC=3,NC=200,ma="https://www.googleapis.com/auth/cloud-platform",HC="https://www.googleapis.com/auth/userinfo.email";var Ai=D(()=>{eo();kd();Pe();wr();Dm();ze()});async function Un(e,t=Fm,n,r){let o={checks:[],issues:0},i="Preparing diagnostics",s=()=>n?.({active:i,checks:[...o.checks]}),a=(m)=>{i=m,s()},c=(m)=>{if(o.checks.push(m),m.severity==="error")o.issues+=1;s()},l=[...new Set(Object.values(e.services).flatMap((m)=>m.container?[m.container.runtime||"docker"]:[]))];for(let m of l){a(`${m} container runtime`);let x=await t.hasCommand(m),v=x&&await(t.containerRuntimeAvailable??Fm.containerRuntimeAvailable)(m);c(v?{name:`${m} container runtime`,severity:"ok",message:`${m} daemon reachable`}:{name:`${m} container runtime`,severity:"error",message:x?`${m} daemon is not reachable`:`${m} not found`,hint:`install and start ${m}`})}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:_i(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 d=await t.detectGoogle(e.google.project_id);if(d.adcAvailable)c({name:"Google authentication available",severity:"ok",message:"Application Default Credentials found"});else c({name:"Google authentication available",severity:_i(e)?"error":"warn",message:"ADC unavailable",hint:"run `gcloud auth application-default login`"});if(d.projectID!=="")c({name:"Project configured",severity:"ok",message:`${d.projectID} (source: ${d.projectSource})`});else c({name:"Project configured",severity:_i(e)?"error":"warn",message:"no Google project configured",hint:"set google.project_id in .devctl/config.yaml"});if(_i(e)||Object.values(e.services).some((m)=>m.capabilities.includes("google")||m.identity.type!=="")){a("Live Google access");let m=!0,x=(v)=>{if(m)c(v)};try{await Di((async()=>{await n_(e,x,t,d.userEmail),await t_(e,x,t)})(),t.liveDeadlineMs??e_)}catch(v){x({name:"Live Google probes",severity:"warn",message:F(v),hint:"network or timeout \u2014 retry when online"})}finally{m=!1}}for(let m of e.doctor.tools){let x=m.command||m.name;if(a(`${m.name} installed`),await t.hasCommand(x))c({name:`${m.name} installed`,severity:"ok",message:`${x} found`});else c({name:`${m.name} installed`,severity:"error",message:`${x} not found`,hint:`install ${m.name} and ensure it is on PATH`})}if(a("Repository configuration"),r?.repositoryConfigError!==void 0)if(r.repositoryConfigError==="")c({name:"Repository configuration",severity:"ok",message:"valid"});else c({name:"Repository configuration",severity:"error",message:r.repositoryConfigError});else try{let m=Xt(e);if(m.length>0)c({name:"Repository configuration",severity:"error",message:m.join("; ")});else c({name:"Repository configuration",severity:"ok",message:"valid"})}catch(m){c({name:"Repository configuration",severity:"error",message:F(m)})}let g={};for(let[m,x]of Object.entries(e.services))for(let v of x.ports){if(v.auto)continue;let S=`Port ${v.value}`;if(a(S),g[v.value])c({name:S,severity:"error",message:`configured on both ${g[v.value]} and ${m}`});else{g[v.value]=m;let P=r?.services?.[m],k=Boolean(x.container&&P&&["STARTING","RUNNING","HEALTHY","UNHEALTHY"].includes(P.state??""));if(Boolean(P&&(P.pid>0||k)&&Object.values(P.ports).includes(v.value)))c({name:S,severity:"ok",message:`in use by running service ${m}`});else if(await t.portAvailable(v.value))c({name:S,severity:"ok",message:"available"});else c(await Hm(S,v.value,`services.${m}.ports`))}}if(e.proxy.listen.port>0){let m=`Port ${e.proxy.listen.port}`;if(a(m),r?.proxyRunning)c({name:m,severity:"ok",message:"in use by the running proxy"});else if(await t.portAvailable(e.proxy.listen.port))c({name:m,severity:"ok",message:"proxy listen port available"});else c(await Hm(m,e.proxy.listen.port,"proxy.listen.port"))}return i="Diagnostics complete",s(),o}async function t_(e,t,n){let r=e.google.project_id,o=n.hasLocalAdc??Ri;if(r===""||!o())return;let i=n.probeServiceUsage??Wm,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(r,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:F(c.reason),hint:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`})})}async function jm(){if(!Ad)Ad=Promise.resolve().then(() => (Ai(),Im)).then(({TokenManager:e,googleTokenProviders:t})=>new e(60000,t(),void 0,ua("file")));return Ad}async function Bm(e,t){await(await jm()).get(e,t,[])}async function Wm(e,t){let n=await jm(),r=await Di(n.get("user","",[]),Li),o=`https://serviceusage.googleapis.com/v1/projects/${e}/services/${t}`,i=await fetch(o,{headers:{Authorization:`Bearer ${r.accessToken}`},signal:AbortSignal.timeout(Li)});if(!i.ok)return!1;return(await i.json().catch(()=>{return}))?.state==="ENABLED"}async function n_(e,t,n,r){let o=Gn(e),i=e.proxy.routes.filter((f)=>f.auth.type.toLowerCase()==="iap"),s=i.filter((f)=>f.auth.audience.trim()!=="");for(let f of i)if(f.auth.audience.trim()==="")t({name:`IAP audience ${f.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(!(n.hasLocalAdc??Ri)())return;let c=n.mintToken??Bm,l=o.map(async(f)=>{try{await Di(c(`sa:${f}`,""),Li),t({name:`Impersonate ${f}`,severity:"ok",message:"token minted"})}catch(g){let m=(n.adcQuotaProject??pd)(),x=r||"the ADC principal",v=m===""?"unknown":m,S=Nm(`Impersonate ${f}`,g,`grant roles/iam.serviceAccountTokenCreator to ${x} on ${f}; ADC quota project: ${v}`);if(m!==""&&S.message.toLowerCase().includes("api is not enabled"))S.message=`IAM Credentials API is disabled in ADC quota project ${m}`,S.hint=`enable iamcredentials.googleapis.com in ${m}, or set the ADC quota project to ${e.google.project_id}`;else if(S.message.toLowerCase()==="google authentication failed")S.message=`access-token mint failed: ${x} \u2192 ${f}`,S.hint=`verify roles/iam.serviceAccountTokenCreator for ${x} on this service account; ADC quota project: ${v}`;t(S)}}),d=s.map(async(f)=>{let g=xr(f.auth).kind===yr?`sa:${xr(f.auth).serviceAccount}`:"user";try{await Di(c(g,f.auth.audience),Li),t({name:`IAP ${f.name}`,severity:"ok",message:"id token minted"})}catch(m){t(Nm(`IAP ${f.name}`,m,"check IAP OAuth client ID and ADC"))}});await Promise.all([...l,...d])}function Nm(e,t,n){let r=F(t),o=r.toLowerCase();if(o.includes("timeout")||o.includes("network")||o.includes("econnrefused")||o.includes("enotfound"))return{name:e,severity:"warn",message:r,hint:"network or timeout \u2014 retry when online"};if(t instanceof Oe&&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:r,hint:n}}function Di(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("timeout")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}async function Hm(e,t,n){let r=await vo(t);if(!r)return{name:e,severity:"error",message:"already in use",hint:`stop the process using port ${t} or change ${n}`};if(r.pid===process.pid)return{name:e,severity:"error",message:`in use by this TUI (${r.command} pid ${r.pid})`,hint:"stop the proxy from the proxy screen (x), then rerun doctor"};return{name:e,severity:"error",message:`in use by ${r.command} (pid ${r.pid})`,hint:"enter stop that process after a confirmation",action:{kind:"free-port",holder:r}}}function ya(e){let t=[`${At()} doctor`,""];for(let n of e.checks){let r=n.severity==="error"?"\u2717":n.severity==="warn"?"!":"\u2713";if(t.push(`${r} ${n.name}`),n.severity!=="ok"){if(t.push(` ${n.message}`),n.hint)t.push(` \u2192 ${n.hint}`)}}return t.push("",`${e.issues} issue(s) found.`),t.join(`
3
+ var rS=Object.defineProperty;var oS=(e)=>e;function iS(e,t){this[e]=oS.bind(null,t)}var Ms=(e,t)=>{for(var n in t)rS(e,n,{get:t[n],enumerable:!0,configurable:!0,set:iS.bind(t,n)})};var D=(e,t)=>()=>(e&&(t=e(e=0)),t);var sS=import.meta.require;var eo=D(()=>{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 Df(e,t=""){if(t===Af)return!0;return e.includes(Af)||e.startsWith(aS)}function $s(){if(Lf)return;Lf=!0;let e=process.emitWarning.bind(process);process.emitWarning=(t,...n)=>{let r=lS(n[0]),o=cS(t);if(Df(o,r))return;e(t,...n)}}function Of(){let e=process.stderr.write.bind(process.stderr);return process.stderr.write=(t,n,r)=>{let o=dS(t);if(Df(o)){let i=typeof n==="function"?n:typeof r==="function"?r:void 0;if(typeof i==="function")i();return!0}if(typeof n==="function")return e(t,n);return e(t,n,r)},()=>{process.stderr.write=e}}function cS(e){if(typeof e==="string")return e;if(e instanceof Error)return e.message;return String(e)}function lS(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&"type"in e&&typeof e.type==="string")return e.type;return""}function dS(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return new TextDecoder().decode(e);return""}var Af="MetadataLookupWarning",aS="received unexpected error =",Lf=!1;var Cl=D(()=>{eo()});function L(e,t){return new Me(e,t)}function fe(e,t,n){let r=n instanceof Error?n:Error(String(n));return new Me(e,t,{cause:r})}function ke(e,t,n,r=""){return new Me(e,t,{hint:n,service:r})}function Fs(e,t){return e instanceof Me&&e.kind===t}function If(e){if(e instanceof Me)return e.exitCode();return 1}function Ff(e){if(e instanceof Me)return{error:O(e),kind:e.kind,hint:e.hint,service:e.service};return{error:O(e)}}function Nf(e){if(typeof e==="string")return L("general",e);if(e.kind)return new Me(e.kind,e.error.replace(`${e.kind}: `,""),{hint:e.hint,service:e.service});return L("general",e.error)}function O(e){if(e instanceof Me){if(e.hint!=="")return`${Mf(e)} \u2014 ${e.hint}`;return Mf(e)}if(e instanceof Error)return e.message;return String(e)}function Mf(e){let t=`${e.kind}: `;if(e.message.startsWith(t)){let n=e.message.slice(t.length),r=e.causeError?`: ${e.causeError.message}`:"";if(r!==""&&n.endsWith(r))return n.slice(0,n.length-r.length);return n}return e.message}var Z="configuration",cr="configuration_missing",fi="service_not_found",$f="dependency",Ne="process_start",to="authentication",lr="authorization",hn="token",Is="impersonation",_l="iap",$n="proxy",El="health_check",Je="general",Me;var Re=D(()=>{Me=class Me extends Error{kind;hint;service;causeError;constructor(e,t,n){super(n?.cause?`${e}: ${t}: ${n.cause.message}`:`${e}: ${t}`);this.name="DevctlError",this.kind=e,this.hint=n?.hint??"",this.service=n?.service??"",this.causeError=n?.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 uS}from"child_process";import{createHash as pS,randomBytes as Tl}from"crypto";import{copyFileSync as fS,existsSync as In,mkdirSync as gS,readdirSync as mS,readFileSync as Al,renameSync as Ll,statSync as hS,unlinkSync as Rl,writeFileSync as vS}from"fs";import{homedir as yS}from"os";import{basename as xS,dirname as Pl,join as dt,resolve as bS}from"path";function Nt(){let e=process.env.DEVCTL_HOME;if(e&&e!=="")return e;return dt(yS(),".devctl")}function Yt(e){gS(e,{recursive:!0,mode:wS})}function vn(e){let t=bS(e),n=process.platform==="win32"?t.toLowerCase():t;return pS("sha256").update(n).digest("hex").slice(0,kS)}function no(e){let t=dt(Nt(),"state",vn(e)),n=dt(Nt(),"sessions",vn(e));if(!In(t)&&In(n)){Yt(Pl(t));try{Ll(n,t)}catch{Yt(t);for(let r of["state.json","devctl.lock","devctl.sock"]){let o=dt(n,r);if(In(o))fS(o,dt(t,r))}}}return Yt(t),t}function Ns(){let e=dt(Nt(),"logs");return Yt(e),e}function dr(){let e=dt(Nt(),"exports");return Yt(e),e}function Gt(){let e=dt(Nt(),"credentials");return Yt(e),e}function Hs(e,t=process.platform){if(t==="win32")return`\\\\.\\pipe\\devctl-${vn(e)}`;return dt(no(e),"devctl.sock")}function CS(e){return dt(no(e),"devctl.lock")}function Hf(e){return dt(no(e),"state.json")}function ur(e){return dt(no(e),"bootstrap.log")}function Bf(e){let t=ur(e);if(!In(t))return;let n=no(e),r=dt(n,`${jf}${Dl()}.log`);try{Ll(t,r)}catch{return}ES(n)}function ES(e){let t;try{t=mS(e).filter((r)=>r.startsWith(jf)&&r.endsWith(".log"))}catch{return}let n=t.map((r)=>{let o=dt(e,r);try{return{path:o,mtime:hS(o).mtimeMs}}catch{return}}).filter((r)=>r!==void 0).sort((r,o)=>o.mtime-r.mtime);for(let r=_S;r<n.length;r++)try{Rl(n[r].path)}catch{}}function Ut(e,t){Yt(Pl(e));let n=dt(Pl(e),`.${xS(e)}.tmp-${process.pid}-${Tl(4).toString("hex")}`);vS(n,t,{mode:SS}),Ll(n,e)}function Dl(e=new Date){return`${e.toISOString().slice(0,19).replace(/:/g,"-")+"Z"}-${Tl(3).toString("hex")}`}function js(e){let t=e.indexOf("Z-"),n=t>=0?e.slice(0,t+1):e,r=n.indexOf("T");if(r<0||!n.endsWith("Z"))return;let o=n.slice(0,r),i=n.slice(r+1,-1).replace(/-/g,":"),s=new Date(`${o}T${i}Z`);return Number.isNaN(s.getTime())?void 0:s}function pr(e){return Ol(Hf(e))}function Ol(e){if(!In(e))return;try{let t=JSON.parse(Al(e,"utf8"));if(Array.isArray(t.processes)&&typeof t.repo_root==="string")return t;return}catch{return}}function Wf(e,t){Ut(Hf(e),`${JSON.stringify(t,null,2)}
4
+ `)}function Gf(e,t){let n=CS(e);if(In(n)){let r=RS(n);if(r&&Tt(r.pid))throw Error(`supervisor already running (pid ${r.pid})`);try{Rl(n)}catch{}}return Ut(n,JSON.stringify({pid:process.pid,socket:t})),{release:()=>{try{Rl(n)}catch{}}}}function RS(e){if(!In(e))return;try{let t=JSON.parse(Al(e,"utf8"));if(typeof t.pid==="number"&&typeof t.socket==="string")return{pid:t.pid,socket:t.socket}}catch{return}return}function Tt(e){if(e<=0)return!1;if(process.platform==="win32")return PS(e);try{return process.kill(e,0),!0}catch{return!1}}function Ml(e){try{let t=uS("cmd.exe",["/d","/c",`tasklist /FO CSV /NH /FI "PID eq ${e}"`],{encoding:"buffer",windowsHide:!0,timeout:5000});return TS(t.stdout)}catch{return""}}function PS(e){try{return process.kill(e,0),!0}catch{}let t=Ml(e).toLowerCase();if(t===""||t.includes("no tasks")||t.includes("no matching"))return!1;return t.includes(String(e))}function TS(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 $l(){return Tl(24).toString("hex")}function AS(e){return dt(no(e),"mcp-token")}function Uf(e){let t=AS(e);if(In(t)){let r=Al(t,"utf8").trim();if(r!=="")return r}let n=$l();return Ut(t,n),n}var wS=448,SS=384,kS=16,_S=5,jf="bootstrap-";var ze=()=>{};function ro(){return{args:[],shell:!1}}function Fl(){return{vars:{},required:[],defaults:{}}}function Nl(){return{type:"",url:"",address:"",command:ro(),interval_seconds:0,timeout_seconds:0,start_period_seconds:0,unhealthy_threshold:3,healthy_reset_threshold:10}}function wt(e){return typeof e==="string"?e:e.service}function Fn(e){return typeof e==="string"?"service_started":e.condition||"service_started"}function Ws(e){return Fn(e)==="service_healthy"?`${wt(e)} (healthy)`:wt(e)}function Hl(){return{type:"",mode:"",service_account:"",config:{}}}function Nn(){return{extends:"",description:"",command:ro(),shell:!1,working_dir:"",dependencies:[],ports:[],environment:Fl(),health:Nl(),identity:Hl(),logs:{stdout:!1,stderr:!1},restart:{policy:"",max_retries:0,backoff_seconds:0},startup:{wait_for_healthy:!1,timeout_seconds:0},capabilities:[],proxy:[],container:void 0,hooks:{pre_start:ro(),post_start:ro()}}}function fr(){return{version:1,project:{name:""},google:{project_id:"",region:""},profiles:{},templates:{},services:{},tasks:{},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:{}},provenance:{},repoRoot:"",configPath:""}}function io(e){return e.args.length===0||e.args.length===1&&(e.args[0]??"").trim()===""}function gi(e){if(e.type!=="")return e.type;return e.mode}function yn(e){let t=gi(e).toLowerCase();return t==="service"||t==="service_account"}function Jf(e){let t=gi(e).toLowerCase();return t==="user"||t===""}function zf(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 gr(e){let t=e.host===""?"127.0.0.1":e.host;if(e.port===0)return t;return`${t}:${e.port}`}function Gs(e){if(e.refresh_threshold_seconds<=0)return 300;return e.refresh_threshold_seconds}function Us(e){if(e.stop_services_on_exit===void 0)return!0;return e.stop_services_on_exit}function so(e){if(e.grace_seconds<=0)return 10;return e.grace_seconds}function Yf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stdout}function Xf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stderr}function jl(e,t){return e.find((n)=>n.name===t)}function Qf(e){return e[0]}var oo=1,Kf="never",qf="on_failure",Vf="always",Bs=8080,Il="127.0.0.1";function F(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Wl(e){return F(e)?new Set(Object.keys(e)):new Set}function K(e){if(typeof e==="string")return e;if(typeof e==="number"||typeof e==="boolean")return String(e);return""}function xe(e){if(typeof e==="number")return e;if(typeof e==="string"){let t=Number(e);return Number.isNaN(t)?0:t}return 0}function it(e){return e===!0}function Lt(e){if(!Array.isArray(e))return[];return e.map((t)=>K(t))}function Gl(e){if(!Array.isArray(e))return[];return e.map((t)=>F(t)?{service:K(t.service),condition:K(t.condition)||"service_started"}:K(t))}function Hn(e){if(!F(e))return{};let t={};for(let[n,r]of Object.entries(e))t[n]=K(r);return t}function Kt(e){if(typeof e==="string")return{args:e.split(/\s+/).filter((t)=>t!==""),shell:!1};if(Array.isArray(e))return{args:e.map((t)=>K(t)),shell:!1};return ro()}function Ul(e){if(e===void 0||e===null)return[];if(typeof e==="string"||typeof e==="number")return[Bl(e,"http")];if(Array.isArray(e))return e.map((t,n)=>Bl(t,`port_${n}`));if(F(e))return Object.entries(e).map(([t,n])=>Bl(n,t));return[]}function Bl(e,t){if(typeof e==="string"&&e.toLowerCase()==="auto")return{name:t,value:0,auto:!0};return{name:t,value:xe(e),auto:!1}}function Zf(e){if(!F(e))return Fl();let t={},n=[],r={};for(let[o,i]of Object.entries(e))if(o==="required")n=Lt(i);else if(o==="defaults")r=Hn(i);else t[o]=K(i);return{vars:t,required:n,defaults:r}}function LS(e){if(!F(e))return Hl();return{type:K(e.type),mode:K(e.mode),service_account:K(e.service_account),config:F(e.config)?{...e.config}:{}}}function DS(e){if(!F(e))return Nl();return{type:K(e.type),url:K(e.url),address:K(e.address),command:Kt(e.command),interval_seconds:xe(e.interval_seconds),timeout_seconds:xe(e.timeout_seconds),start_period_seconds:xe(e.start_period_seconds),unhealthy_threshold:e.unhealthy_threshold===void 0?3:xe(e.unhealthy_threshold),healthy_reset_threshold:e.healthy_reset_threshold===void 0?10:xe(e.healthy_reset_threshold)}}function OS(e){if(!F(e))return{policy:"",max_retries:0,backoff_seconds:0};return{enabled:e.enabled===void 0?void 0:it(e.enabled),policy:K(e.policy),max_retries:xe(e.max_retries),backoff_seconds:xe(e.backoff_seconds)}}function MS(e){if(!F(e))return{wait_for_healthy:!1,timeout_seconds:0};return{wait_for_healthy:it(e.wait_for_healthy),timeout_seconds:xe(e.timeout_seconds)}}function mi(e){if(!F(e))return Nn();let t=F(e.logs)?e.logs:{};return{extends:K(e.extends),description:K(e.description),command:Kt(e.command),shell:it(e.shell),working_dir:K(e.working_dir),dependencies:Gl(e.dependencies),ports:Ul(e.ports),environment:Zf(e.environment),health:DS(e.health),identity:LS(e.identity),logs:{stdout:it(t.stdout),stderr:it(t.stderr)},restart:OS(e.restart),startup:MS(e.startup),capabilities:Lt(e.capabilities),proxy:ql(e.proxy),container:Kl(e.container),hooks:$S(e.hooks)}}function $S(e){let t=F(e)?e:{};return{pre_start:Kt(t.pre_start),post_start:Kt(t.post_start)}}function eg(e){let t=F(e)?e:{};return{command:Kt(t.command),shell:it(t.shell),working_dir:K(t.working_dir),dependencies:Lt(t.dependencies),environment:Zf(t.environment)}}function Kl(e){if(!F(e))return;let t={};if(F(e.ports))for(let[n,r]of Object.entries(e.ports))t[n]=xe(r);return{image:K(e.image),runtime:K(e.runtime),ports:t,env:Hn(e.env),volumes:Lt(e.volumes)}}function ql(e){if(e===void 0||e===null)return[];if(Array.isArray(e))return e.map((t)=>mr(t));if(F(e))return[mr(e)];return[]}function Ks(e){if(!F(e))return{services:[],environment:{}};return{services:Lt(e.services),environment:Hn(e.environment)}}function IS(e){if(typeof e==="string")return{type:e,service_account:""};if(!F(e))return{type:"",service_account:""};return{type:K(e.type),service_account:K(e.service_account)}}function FS(e){if(!F(e))return{type:"",identity:{type:"",service_account:""},audience:"",service_account:""};return{type:K(e.type),identity:IS(e.identity),audience:K(e.audience),service_account:K(e.service_account)}}function mr(e){if(!F(e))return{name:"",match:{host:"",path:""},upstream:{url:""},auth:{type:"",identity:{type:"",service_account:""},audience:"",service_account:""}};let t=F(e.match)?e.match:{},n=F(e.upstream)?e.upstream:{};return{name:K(e.name),match:{host:K(t.host),path:K(t.path)},upstream:{url:K(n.url)},auth:FS(e.auth)}}var Vl=()=>{};import{existsSync as NS,statSync as ng}from"fs";import{basename as tg,dirname as qs,isAbsolute as HS,join as Vs,resolve as rg}from"path";function jn(e,t){if(t!=="")return jS(t);let n=e===""?process.cwd():e;n=HS(n)?n:rg(n);for(;;){let r=Vs(n,St,qt);if(hi(r))return{repoRoot:n,configPath:r};let o=Vs(n,"devctl.yaml");if(hi(o))return{repoRoot:n,configPath:o};let i=qs(n);if(i===n)break;n=i}throw ke(cr,"no devctl configuration found","run `devctl setup` or create a .devctl/config.yaml in the repository root")}function jS(e){let t=rg(e),n;try{n=ng(t)}catch(o){throw fe(cr,"config path not found",o)}if(n.isDirectory()){if(tg(t)===St)return{repoRoot:qs(t),configPath:Vs(t,qt)};return{repoRoot:t,configPath:Vs(t,qt)}}let r=qs(t);if(tg(r)===St)r=qs(r);return{repoRoot:r,configPath:t}}function hi(e){return NS(e)&&!ng(e).isDirectory()}var St=".devctl",qt="config.yaml";var vi=D(()=>{Re()});function Ys(){return{services:{},templates:{},provenance:{}}}function Bn(e,t,n,r,o=""){if(F(t)&&Object.keys(t).length>0){for(let[i,s]of Object.entries(t))Bn(e,s,n,r,o===""?i:`${o}.${i}`);return}if(o==="")return;(e[o]??=[]).push({source:n,layer:r})}function Js(e,t,n){let r=Wl(n);if(F(n))for(let i of BS){let s=n[i];if(F(s))for(let a of Object.keys(s))r.add(`${i}.${a}`)}let o=e[t];e[t]=o?new Set([...o,...r]):r}function og(e,t,n=Ys(),r={source:"unknown",layer:"unknown"}){if(Bn(n.provenance,t,r.source,r.layer),t.version!==void 0)e.version=xe(t.version);if(F(t.project)&&t.project.name!==void 0)e.project.name=K(t.project.name);if(F(t.google)){if(t.google.project_id!==void 0)e.google.project_id=K(t.google.project_id);if(t.google.region!==void 0)e.google.region=K(t.google.region)}if(F(t.profiles))for(let[o,i]of Object.entries(t.profiles)){let s=e.profiles[o];e.profiles[o]=s?GS(s,i):Ks(i)}if(F(t.templates))for(let[o,i]of Object.entries(t.templates)){let s=e.templates[o];e.templates[o]=s?zs(s,i):mi(i),Js(n.templates,o,i)}if(F(t.services))for(let[o,i]of Object.entries(t.services)){let s=e.services[o];e.services[o]=s?zs(s,i):mi(i),Js(n.services,o,i)}if(F(t.tasks))for(let[o,i]of Object.entries(t.tasks))e.tasks[o]=e.tasks[o]?US(e.tasks[o],i):eg(i);if(F(t.proxy))WS(e.proxy,t.proxy);if(F(t.logs)){if(t.logs.max_memory_events!==void 0)e.logs.max_memory_events=xe(t.logs.max_memory_events);if(F(t.logs.persistence)){let o=t.logs.persistence;if(o.enabled!==void 0)e.logs.persistence.enabled=it(o.enabled);if(o.directory!==void 0)e.logs.persistence.directory=K(o.directory);if(o.retention_days!==void 0)e.logs.persistence.retention_days=xe(o.retention_days);if(o.max_session_logs!==void 0)e.logs.persistence.max_session_logs=xe(o.max_session_logs)}}if(F(t.auth)&&t.auth.refresh_threshold_seconds!==void 0)e.auth.refresh_threshold_seconds=xe(t.auth.refresh_threshold_seconds);if(F(t.shutdown)){if(t.shutdown.stop_services_on_exit!==void 0)e.shutdown.stop_services_on_exit=it(t.shutdown.stop_services_on_exit);if(t.shutdown.grace_seconds!==void 0)e.shutdown.grace_seconds=xe(t.shutdown.grace_seconds)}if(F(t.ui)){if(t.ui.theme!==void 0)e.ui.theme=K(t.ui.theme);if(t.ui.keymap!==void 0)e.ui.keymap=Hn(t.ui.keymap)}if(F(t.secrets)){if(t.secrets.extra_markers!==void 0)e.secrets.extra_markers=Lt(t.secrets.extra_markers);if(t.secrets.extra_patterns!==void 0)e.secrets.extra_patterns=Lt(t.secrets.extra_patterns)}if(F(t.doctor)&&Array.isArray(t.doctor.tools))e.doctor.tools=t.doctor.tools.filter(F).map((o)=>({name:K(o.name),command:K(o.command)}));if(Array.isArray(t.plugins))e.plugins=t.plugins.filter(F).map((o)=>({path:K(o.path)})).filter((o)=>o.path!=="");if(F(t.environment)){if(Array.isArray(t.environment.sources))e.environment.sources=Lt(t.environment.sources);if(F(t.environment.secrets))e.environment.secrets={...e.environment.secrets,...Hn(t.environment.secrets)}}}function WS(e,t){if(t.enabled!==void 0)e.enabled=it(t.enabled);if(F(t.listen)){if(t.listen.host!==void 0)e.listen.host=K(t.listen.host);if(t.listen.port!==void 0)e.listen.port=xe(t.listen.port)}if(F(t.token_endpoint)){let n=t.token_endpoint;if(n.enabled!==void 0)e.token_endpoint.enabled=it(n.enabled);if(n.host!==void 0)e.token_endpoint.host=K(n.host);if(n.port!==void 0)e.token_endpoint.port=xe(n.port)}if(Array.isArray(t.routes))e.routes=t.routes.map((n)=>mr(n))}function GS(e,t){if(!F(t))return e;return{services:t.services!==void 0?Lt(t.services):e.services,environment:t.environment!==void 0?{...e.environment,...Hn(t.environment)}:e.environment}}function US(e,t){if(!F(t))return e;return{command:t.command!==void 0?Kt(t.command):e.command,shell:t.shell!==void 0?it(t.shell):e.shell,working_dir:t.working_dir!==void 0?K(t.working_dir):e.working_dir,dependencies:t.dependencies!==void 0?Lt(t.dependencies):e.dependencies,environment:ig(e.environment,t.environment)}}function zs(e,t){if(!F(t))return e;let n=Wl(t),r={...e,environment:ig(e.environment,t.environment),health:qS(e.health,t.health),identity:VS(e.identity,t.identity),logs:JS(e.logs,t.logs),restart:zS(e.restart,t.restart),startup:YS(e.startup,t.startup),container:XS(e.container,t.container),hooks:KS(e.hooks,t.hooks)};if(n.has("extends"))r.extends=K(t.extends);if(n.has("description"))r.description=K(t.description);if(n.has("command"))r.command=Kt(t.command);if(n.has("shell"))r.shell=it(t.shell);if(n.has("working_dir"))r.working_dir=K(t.working_dir);if(n.has("dependencies"))r.dependencies=Gl(t.dependencies);if(n.has("ports"))r.ports=Ul(t.ports);if(n.has("capabilities"))r.capabilities=Lt(t.capabilities);if(n.has("proxy"))r.proxy=ql(t.proxy);return r}function KS(e,t){if(!F(t))return e;return{pre_start:t.pre_start!==void 0?Kt(t.pre_start):e.pre_start,post_start:t.post_start!==void 0?Kt(t.post_start):e.post_start}}function ig(e,t){if(!F(t))return e;let n={...e.vars},r={...e.defaults},o=e.required;for(let[i,s]of Object.entries(t))if(i==="required")o=Lt(s);else if(i==="defaults")Object.assign(r,Hn(s));else n[i]=K(s);return{vars:n,required:o,defaults:r}}function qS(e,t){if(!F(t))return e;return{type:t.type!==void 0?K(t.type):e.type,url:t.url!==void 0?K(t.url):e.url,address:t.address!==void 0?K(t.address):e.address,command:t.command!==void 0?Kt(t.command):e.command,interval_seconds:t.interval_seconds!==void 0?xe(t.interval_seconds):e.interval_seconds,timeout_seconds:t.timeout_seconds!==void 0?xe(t.timeout_seconds):e.timeout_seconds,start_period_seconds:t.start_period_seconds!==void 0?xe(t.start_period_seconds):e.start_period_seconds,unhealthy_threshold:t.unhealthy_threshold!==void 0?xe(t.unhealthy_threshold):e.unhealthy_threshold,healthy_reset_threshold:t.healthy_reset_threshold!==void 0?xe(t.healthy_reset_threshold):e.healthy_reset_threshold}}function VS(e,t){if(!F(t))return e;return{type:t.type!==void 0?K(t.type):e.type,mode:t.mode!==void 0?K(t.mode):e.mode,service_account:t.service_account!==void 0?K(t.service_account):e.service_account,config:t.config!==void 0&&F(t.config)?{...e.config??{},...t.config}:e.config}}function JS(e,t){if(!F(t))return e;return{stdout:t.stdout!==void 0?it(t.stdout):e.stdout,stderr:t.stderr!==void 0?it(t.stderr):e.stderr}}function zS(e,t){if(!F(t))return e;return{enabled:t.enabled!==void 0?it(t.enabled):e.enabled,policy:t.policy!==void 0?K(t.policy):e.policy,max_retries:t.max_retries!==void 0?xe(t.max_retries):e.max_retries,backoff_seconds:t.backoff_seconds!==void 0?xe(t.backoff_seconds):e.backoff_seconds}}function YS(e,t){if(!F(t))return e;return{wait_for_healthy:t.wait_for_healthy!==void 0?it(t.wait_for_healthy):e.wait_for_healthy,timeout_seconds:t.timeout_seconds!==void 0?xe(t.timeout_seconds):e.timeout_seconds}}function XS(e,t){if(!F(t))return e;let n=Kl(t);if(!n)return e;return{image:t.image!==void 0?n.image:e?.image??"",runtime:t.runtime!==void 0?n.runtime:e?.runtime??"",ports:t.ports!==void 0?{...e?.ports??{},...n.ports}:e?.ports??{},env:t.env!==void 0?{...e?.env??{},...n.env}:e?.env??{},volumes:t.volumes!==void 0?n.volumes:e?.volumes??[]}}function sg(e,t){let n=Object.keys(e.services).sort();for(let r of n){let o=e.services[r]?.proxy??[];if(o.length===0)continue;o.forEach((i,s)=>{let c={name:o.length===1?r:`${r}-${s+1}`,match:i.match,upstream:i.upstream,auth:i.auth},l=e.proxy.routes.length;if(e.proxy.routes.push(c),t)Bn(t,c,`synthesized from services.${r}.proxy`,"synthesized",`proxy.routes.${l}`)})}}function ag(e,t=Ys()){if(Object.keys(e.templates).length===0)return;let n={};for(let[r,o]of Object.entries(e.services))n[r]=cg(e,o,t.services[r]??new Set,t,{});e.services=n}function cg(e,t,n,r,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=r.templates[t.extends]??new Set,c=cg(e,i,a,r,s),l=QS(c,t,n);return l.extends=t.extends,l}function QS(e,t,n){let r={...e};if(n.has("extends"))r.extends=t.extends;if(n.has("description"))r.description=t.description;if(n.has("command"))r.command=t.command;if(n.has("shell"))r.shell=t.shell;if(n.has("working_dir"))r.working_dir=t.working_dir;if(n.has("dependencies"))r.dependencies=t.dependencies;if(n.has("ports"))r.ports=t.ports;if(n.has("capabilities"))r.capabilities=t.capabilities;if(n.has("proxy"))r.proxy=t.proxy;if(n.has("container")){let o=t.container,i=e.container;r.container=o&&i?{image:n.has("container.image")?o.image:i.image,runtime:n.has("container.runtime")?o.runtime:i.runtime,ports:n.has("container.ports")?o.ports:i.ports,env:n.has("container.env")?o.env:i.env,volumes:n.has("container.volumes")?o.volumes:i.volumes}:o??i}return r.hooks={pre_start:n.has("hooks.pre_start")?t.hooks.pre_start:e.hooks.pre_start,post_start:n.has("hooks.post_start")?t.hooks.post_start:e.hooks.post_start},r.health={type:n.has("health.type")?t.health.type:e.health.type,url:n.has("health.url")?t.health.url:e.health.url,address:n.has("health.address")?t.health.address:e.health.address,command:n.has("health.command")?t.health.command:e.health.command,interval_seconds:n.has("health.interval_seconds")?t.health.interval_seconds:e.health.interval_seconds,timeout_seconds:n.has("health.timeout_seconds")?t.health.timeout_seconds:e.health.timeout_seconds,start_period_seconds:n.has("health.start_period_seconds")?t.health.start_period_seconds:e.health.start_period_seconds,unhealthy_threshold:n.has("health.unhealthy_threshold")?t.health.unhealthy_threshold:e.health.unhealthy_threshold,healthy_reset_threshold:n.has("health.healthy_reset_threshold")?t.health.healthy_reset_threshold:e.health.healthy_reset_threshold},r.identity={type:n.has("identity.type")?t.identity.type:e.identity.type,mode:n.has("identity.mode")?t.identity.mode:e.identity.mode,service_account:n.has("identity.service_account")?t.identity.service_account:e.identity.service_account,config:n.has("identity.config")?t.identity.config:e.identity.config},r.logs={stdout:n.has("logs.stdout")?t.logs.stdout:e.logs.stdout,stderr:n.has("logs.stderr")?t.logs.stderr:e.logs.stderr},r.restart={enabled:n.has("restart.enabled")?t.restart.enabled:e.restart.enabled,policy:n.has("restart.policy")?t.restart.policy:e.restart.policy,max_retries:n.has("restart.max_retries")?t.restart.max_retries:e.restart.max_retries,backoff_seconds:n.has("restart.backoff_seconds")?t.restart.backoff_seconds:e.restart.backoff_seconds},r.startup={wait_for_healthy:n.has("startup.wait_for_healthy")?t.startup.wait_for_healthy:e.startup.wait_for_healthy,timeout_seconds:n.has("startup.timeout_seconds")?t.startup.timeout_seconds:e.startup.timeout_seconds},r.environment={vars:{...e.environment.vars,...t.environment.vars},defaults:{...e.environment.defaults,...t.environment.defaults},required:n.has("environment.required")?t.environment.required:e.environment.required},r}var BS;var lg=D(()=>{Vl();BS=["environment","restart","startup","health","logs","identity","container","hooks"]});function Jl(e){if(e.version===0)throw L(Z,"version is required");if(e.version===oo)return e;throw L(Z,`unsupported config version ${e.version} (expected ${oo}); no migration is available`)}var zl=D(()=>{Re()});var dg,ug,pg,fg,gg,mg,hg,vg,yg,Yl,Xl,Ql,Zl,xg,bg,wg,Sg,kg,Cg,_g,Eg,ed,Rg,Pg,Tg,Ag,Lg,Dg,Og,Mg,$g,Ig,Fg,Ng;var td=D(()=>{dg=["version","project","google","profiles","templates","services","tasks","proxy","logs","auth","shutdown","ui","secrets","doctor","plugins","environment"],ug=["extends","description","command","shell","working_dir","dependencies","ports","environment","health","identity","logs","restart","startup","capabilities","proxy","container","hooks"],pg=["type","url","address","command","interval_seconds","timeout_seconds","start_period_seconds","unhealthy_threshold","healthy_reset_threshold"],fg=["service","condition"],gg=["type","mode","service_account","config"],mg=["enabled","policy","max_retries","backoff_seconds"],hg=["wait_for_healthy","timeout_seconds"],vg=["enabled","listen","token_endpoint","routes"],yg=["host","port"],Yl=["name","match","upstream","auth"],Xl=["host","path"],Ql=["url"],Zl=["type","identity","audience","service_account"],xg=["max_memory_events","persistence"],bg=["enabled","directory","retention_days","max_session_logs"],wg=["refresh_threshold_seconds"],Sg=["stop_services_on_exit","grace_seconds"],kg=["theme","keymap"],Cg=["name"],_g=["project_id","region"],Eg=["services","environment"],ed=["required","defaults"],Rg=["stdout","stderr"],Pg=["extra_markers","extra_patterns"],Tg=["tools"],Ag=["name","command"],Lg=["enabled","host","port"],Dg=["path"],Og=["sources","secrets"],Mg=["image","runtime","ports","env","volumes"],$g=["pre_start","post_start"],Ig=["command","shell","working_dir","dependencies","environment"],Fg=["google","google_api","iap","network","service_identity","local_http"],Ng=["|","||","&&",";",">",">>","<","&"]});function Wn(e,t){if(Array.isArray(e))return e.flatMap((o,i)=>Wn(o,Hg(t,String(i))));if(!sk(e))return[];let n=tk(t),r=[];for(let o of Object.keys(e)){let i=Hg(t,o);if(n.length>0&&!n.includes(o)&&!ek(t))r.push(i);r.push(...Wn(e[o],i))}return r}function ek(e){if(e==="services"||e==="profiles"||e==="templates"||e==="tasks")return!0;if(e.endsWith(".environment")||e.endsWith(".defaults")||e.endsWith(".keymap"))return!0;if(e.endsWith(".container.ports")||e.endsWith(".container.env"))return!0;if(e.endsWith(".identity.config")||e.includes(".identity.config."))return!0;return e.includes(".environment.")&&!e.endsWith(".environment")}function tk(e){switch(e){case"":return dg;case"project":return Cg;case"google":return _g;case"proxy":return vg;case"proxy.listen":return yg;case"proxy.token_endpoint":return Lg;case"logs":return xg;case"logs.persistence":return bg;case"auth":return wg;case"shutdown":return Sg;case"ui":return kg;case"secrets":return Pg;case"doctor":return Tg;case"environment":return Og;default:return nk(e)}}function nk(e){if(e==="services"||e==="profiles"||e==="templates"||e==="tasks")return[];if(e.startsWith("services.")||e.startsWith("templates.")){if(e.includes(".dependencies."))return fg;return rk(e)}if(e.startsWith("profiles.")){if(e.split(".").length===2)return Eg}if(e.startsWith("tasks.")){let t=e.split(".");if(t.length===2)return Ig;if(t[2]==="environment")return ed}if(e.includes("routes"))return ik(e);if(e.startsWith("doctor.tools")&&e.split(".").length>=3)return Ag;if(e==="plugins")return[];if(e.startsWith("plugins.")&&e.split(".").length===2)return Dg;return[]}function rk(e){let t=e.split(".");if(t.length===2)return ug;if(t.length>=3)switch(t[2]){case"health":return pg;case"identity":return gg;case"restart":return mg;case"startup":return hg;case"logs":return Rg;case"environment":return ed;case"proxy":return ok(t);case"container":return Mg;case"hooks":return $g;default:return[]}return[]}function ok(e){let t=e.slice(3),n=t[0]!==void 0&&/^\d+$/.test(t[0])?1:0,r=t[n]??"";if(r==="match")return Xl;if(r==="upstream")return Ql;if(r==="auth")return Zl;return Yl}function ik(e){if(e==="proxy.routes")return[];if(e.endsWith(".match"))return Xl;if(e.endsWith(".upstream"))return Ql;if(e.endsWith(".auth"))return Zl;if(e.includes("proxy.routes")&&e.split(".").length===ZS+1)return Yl;return[]}function Hg(e,t){if(e==="")return t;return`${e}.${t}`}function sk(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ao(e){return`unknown fields: ${e.join(", ")}`}var ZS=2;var jg=D(()=>{td()});function Bg(e,t,n){let r=e,o="";for(;;){let i=r.indexOf("${");if(i<0)return o+r;o+=r.slice(0,i);let s=r.slice(i).indexOf("}");if(s<0)throw Error(`unclosed environment reference in "${e}"`);let a=r.slice(i+2,i+s);o+=ak(a,t,n),r=r.slice(i+s+1)}}function ak(e,t,n){let r=e.split(".");if(r.length<3||r[0]!=="services")throw Error(`unsupported reference \${${e}}`);let o=r[1]??"",i=t.services[o];if(!i)throw Error(`reference \${${e}}: unknown service`);let s=n[o];if(r[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=Qf(i.ports);if(a&&!a.auto)return String(a.value)}if(r[2]==="ports"){let a=r[3];if(!a)throw Error(`reference \${${e}}: missing port name`);if(s&&s[a]!==void 0)return String(s[a]);let c=jl(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 nd(e,t,n){let r={};for(let[o,i]of Object.entries(e))r[o]=Bg(i,t,n);return r}function Wg(e){let t=[],n=e;for(;;){let r=n.indexOf("${");if(r<0)return t;let o=n.slice(r).indexOf("}");if(o<0)return t;t.push(n.slice(r+2,r+o)),n=n.slice(r+o+1)}}function Gg(e,t){let n=e.split(".");if(n.length<2)return!1;if(n[0]!=="services"||n.length<3)return!1;let r=t.services[n[1]??""];if(!r)return!1;if(n[2]==="port"||n[2]==="ports"){if(n.length===3)return r.ports.length>0;if(n.length>=4){let o=n[3]??"";if(!Number.isNaN(Number.parseInt(o,10)))return!0;return jl(r.ports,o)!==void 0}}return!0}var rd=()=>{};import{existsSync as ck}from"fs";import{isAbsolute as lk,resolve as dk}from"path";import{fileURLToPath as uk}from"url";function od(e){let t=[];for(let[n,r]of Object.entries(e.services)){let o=r.health.type;if(o!==""&&!qg.includes(o.toLowerCase()))t.push({service:n,type:o})}return t}function Xt(e){let t=[];if(e.version===0)t.push("version is required");else if(e.version!==oo)t.push(`unsupported config version ${e.version} (expected ${oo}); no migration is available`);if(Object.keys(e.services).length===0)t.push("at least one service must be defined");t.push(...gk(e)),t.push(...fk(e)),t.push(...yk(e)),t.push(...xk(e)),t.push(...bk(e));for(let[n,r]of e.plugins.entries())if(r.path==="")t.push(`plugins.${n}.path is required`);else try{let o=r.path.startsWith("file:")?uk(r.path):lk(r.path)?r.path:dk(e.repoRoot,r.path);if(!ck(o))t.push(`plugins.${n}.path does not exist: ${r.path}`)}catch{t.push(`plugins.${n}.path is invalid: ${r.path}`)}if(e.logs.max_memory_events<0)t.push("logs.max_memory_events must be >= 0");return t}function fk(e){let t=[];for(let[n,r]of Object.entries(e.tasks)){let o=`tasks.${n}`;if(io(r.command))t.push(`${o}.command is required`);t.push(...Xs(o,r.command,r.shell));for(let i of r.dependencies)if(!e.services[i])t.push(`${o}.dependencies: unknown service "${i}"`);t.push(...Vg(`${o}.environment`,r.environment,e))}return t}function gk(e){let t=[],n={};for(let[r,o]of Object.entries(e.services)){let i=`services.${r}`;if(io(o.command)&&!o.container)t.push(`${i}.command is required`);t.push(...Xs(i,o.command,o.shell)),t.push(...Xs(`${i}.hooks.pre_start`,o.hooks.pre_start,o.shell)),t.push(...Xs(`${i}.hooks.post_start`,o.hooks.post_start,o.shell)),t.push(...Sk(i,o.capabilities));for(let c of o.dependencies){let l=wt(c);if(!e.services[l])t.push(`${i}.dependencies: unknown service "${l}"`);if(l===r)t.push(`${i}.dependencies: service cannot depend on itself`);if(!["service_started","service_healthy"].includes(Fn(c)))t.push(`${i}.dependencies: condition must be service_started or service_healthy`);if(Fn(c)==="service_healthy"&&e.services[l]?.health.type==="")t.push(`${i}.dependencies: service_healthy requires ${l} to define a health check`)}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<Zs||c.value>Qs)t.push(`${i}.ports.${c.name}: invalid port ${c.value}`);else if(n[c.value])t.push(`duplicate port ${c.value} used by ${n[c.value]} and ${r}`);else n[c.value]=r;let s=vk(`${i}.identity`,o.identity,e.plugins.length>0);if(s!=="")t.push(s);if(t.push(...mk(i,o,e.plugins.length>0)),o.health.start_period_seconds<0)t.push(`${i}.health.start_period_seconds must be >= 0`);if(o.health.unhealthy_threshold<1)t.push(`${i}.health.unhealthy_threshold must be >= 1`);if(o.health.healthy_reset_threshold<1)t.push(`${i}.health.healthy_reset_threshold must be >= 1`);let a=zf(o.restart);if(a!==Kf&&a!==qf&&a!==Vf)t.push(`${i}.restart.policy must be never, on_failure, or always`);if(t.push(...Vg(`${i}.environment`,o.environment,e)),o.container){if(o.container.image==="")t.push(`${i}.container.image is required`);if(o.container.runtime!==""&&o.container.runtime!=="docker"&&o.container.runtime!=="podman")t.push(`${i}.container.runtime must be docker or podman`);for(let[c,l]of Object.entries(o.container.ports)){if(!o.ports.some((d)=>d.name===c))t.push(`${i}.container.ports.${c}: no matching service port`);if(l<Zs||l>Qs)t.push(`${i}.container.ports.${c}: invalid container port ${l}`)}}}return t}function mk(e,t,n){let r=[];if(t.health.type==="")return r;let o=t.health.type.toLowerCase();if(!qg.includes(o)&&!n)r.push(`${e}.health.type must be http, tcp, process, or command`);if(o==="http"&&t.health.url==="")r.push(`${e}.health.url is required for http health checks`);if(o==="tcp"&&t.health.address===""&&t.ports.length===0)r.push(`${e}.health.address is required for tcp health checks without ports`);if(o==="command"&&io({args:t.health.command.args,shell:!1}))r.push(`${e}.health.command is required for command health checks`);return r}function vk(e,t,n){let r=gi(t).toLowerCase();if(r===""||r==="user")return"";if(r==="service"||r==="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(n)return"";return`${e}.type must be user or service_account`}function id(e){let t=[];for(let[n,r]of Object.entries(e.services)){let o=gi(r.identity).toLowerCase();if(!hk.includes(o))t.push({service:n,type:o})}return t}function yk(e){let t={},n=[],r=[],o=(i)=>{let s=t[i]??pk;if(s===Kg)return;if(s===Ug){n.push(`dependency cycle: ${[...r,i].join(" \u2192 ")}`);return}t[i]=Ug,r.push(i);let a=e.services[i];if(a)for(let c of a.dependencies){let l=wt(c);if(e.services[l])o(l)}r.pop(),t[i]=Kg};for(let i of Object.keys(e.services))o(i);return n}function Vg(e,t,n){let r=[],o=(i,s)=>{for(let a of Wg(s))if(!Gg(a,n))r.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 r}function xk(e){let t=[];for(let[n,r]of Object.entries(e.profiles))for(let o of r.services)if(!e.services[o])t.push(`profiles.${n} references unknown service "${o}"`);return t}function bk(e){let t=[];if(e.proxy.listen.host!==""&&!kk(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<Zs||e.proxy.listen.port>Qs))t.push("proxy.listen.port is invalid");let n={};return e.proxy.routes.forEach((r,o)=>{let i=`proxy.routes[${o}]`;if(r.name==="")t.push(`${i}.name is required`);else if(n[r.name])t.push(`${i}: duplicate route name ${r.name}`);if(n[r.name]=!0,r.upstream.url==="")t.push(`${i}.upstream.url is required`);if(r.auth.type.toLowerCase()==="iap"){if(r.auth.audience.trim()==="")t.push(`${i}.auth.audience is required when auth.type is iap`);if(r.auth.identity.type.trim()==="")t.push(`${i}.auth.identity.type is required when auth.type is iap`)}let s=r.auth.identity.type.toLowerCase();if(s==="service"||s==="service_account"||yn({type:s,mode:"",service_account:""})){if((r.auth.identity.service_account||r.auth.service_account)==="")t.push(`${i}.auth.identity.service_account is required`)}}),t.push(...wk(e)),t}function wk(e){let t=[],n=e.proxy.token_endpoint;if(!n.enabled)return t;let r=n.host||Il;if(r==="0.0.0.0")t.push("proxy.token_endpoint.host must be a loopback address");else if(r!==""&&r!==Il&&r!=="localhost"&&!r.startsWith("127."))t.push("proxy.token_endpoint.host must be a loopback address");if(n.port!==0&&(n.port<Zs||n.port>Qs))t.push("proxy.token_endpoint.port is invalid");return t}function Xs(e,t,n){if(t.shell||n)return[];for(let r of t.args)if(Ng.includes(r)||r.includes("|")||r.includes(";")||r.includes("&&"))return[`${e}.command contains shell metacharacters; set shell: true to run via a shell`];return[]}function Sk(e,t){let n=[];for(let r of t)if(!Fg.includes(r))n.push(`${e}.capabilities: unknown capability "${r}"`);return n}function kk(e){if(e==="localhost")return!0;return Ck(e)}function Ck(e){if(/^(\d{1,3}\.){3}\d{1,3}$/.test(e))return e.split(".").every((n)=>{let r=Number(n);return r>=0&&r<=255});return e.includes(":")}var Qs=65535,Zs=1,qg,pk=0,Ug=1,Kg=2,hk;var ea=D(()=>{td();rd();qg=["http","tcp","process","command"];hk=["","user","service","service_account"]});import{readdirSync as _k,readFileSync as Ek}from"fs";import{basename as zg,dirname as Rk,extname as Pk,join as hr,resolve as Tk}from"path";import{parse as Ak}from"yaml";function co(e,t,n){try{return xi(e,t,{candidateText:n}),[]}catch(r){if(r instanceof Me){let o=`${r.kind}: `;return[r.message.startsWith(o)?r.message.slice(o.length):r.message]}return[r instanceof Error?r.message:String(r)]}}function ut(e,t){let{repoRoot:n,configPath:r}=jn(e,t);return xi(n,r)}function yi(e,t){try{return ut(e,t)}catch(n){if(!Fs(n,cr))throw n;let r=e===""?process.cwd():Tk(e),o=fr();return o.repoRoot=r,o.configPath=hr(r,St,qt),o}}function xi(e,t,n){let r=fr(),o=Ys();Yg(t,r,o,n?.candidateText,"main"),r.repoRoot=e,r.configPath=t;let i=Rk(t);if(zg(i)===St)Dk(i,r,o);r=Lk(r,e,t,o),r=Jl(r);try{ag(r,o)}catch(a){throw fe(Z,"template merge failed",a)}sg(r,o.provenance),r.provenance=o.provenance;let s=Xt(r);if(s.length>0)throw L(Z,s.join(`
5
+ `));return r}function Lk(e,t,n,r){let o=hr(Nt(),"config.local.yaml"),i=hr(t,St,"config.local.yaml");for(let s of[o,i]){if(s===n||!hi(s))continue;Yg(s,e,r,void 0,s===o?"home_local":"repo_local")}return e}function Yg(e,t,n,r,o="main"){let i=r!==void 0?Xg(r,e):sd(e),s=Wn(i,"");if(s.length>0)throw L(Z,ao(s));og(t,i,n,{source:e,layer:o})}function Dk(e,t,n){Jg(hr(e,"services"),(o,i,s)=>{let a=Wn(i,`services.${o}`);if(a.length>0)throw L(Z,ao(a));let c=t.services[o];t.services[o]=c?zs(c,i):mi(i),Js(n.services,o,i),Bn(n.provenance,i,s,"modular_service",`services.${o}`)}),Jg(hr(e,"profiles"),(o,i,s)=>{let a=Wn(i,`profiles.${o}`);if(a.length>0)throw L(Z,ao(a));t.profiles[o]=Ks(i),Bn(n.provenance,i,s,"modular_profile",`profiles.${o}`)});let r=hr(e,"proxy","routes.yaml");if(hi(r))Ok(r,t,n)}function Ok(e,t,n){let r=sd(e);if(F(r.proxy))Bn(n.provenance,r.proxy,e,"modular_proxy","proxy");if(Array.isArray(r.routes))Bn(n.provenance,r.routes,e,"modular_proxy","proxy.routes");if(F(r.proxy)){let o=Wn({proxy:r.proxy},"");if(o.length>0)throw L(Z,ao(o))}if(Array.isArray(r.routes))r.routes.forEach((o,i)=>{let s=Wn(o,`proxy.routes.${i}`);if(s.length>0)throw L(Z,ao(s))});if(F(r.proxy)){if(Array.isArray(r.proxy.routes))t.proxy.routes.push(...r.proxy.routes.map((o)=>mr(o)));if(F(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((o)=>mr(o)))}function Jg(e,t){let n;try{n=_k(e)}catch(r){if(Mk(r))return;throw r}for(let r of n.sort()){let o=Pk(r);if(o!==".yaml"&&o!==".yml")continue;let i=hr(e,r),s=sd(i);t(zg(r,o),s,i)}}function sd(e){let t;try{t=Ek(e,"utf8")}catch(n){throw fe(Z,"unable to read config",n)}return Xg(t,e)}function Xg(e,t){let n;try{n=Ak(e)}catch(r){throw fe(Z,`invalid YAML in ${t}`,r)}if(n===null||n===void 0)return{};if(!F(n))throw L(Z,`unable to decode config: ${t} is not a mapping`);return n}function Mk(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Qg=D(()=>{Re();ze();Vl();vi();lg();zl();jg();ea();vi();ea()});function vr(e){return Object.entries(e.provenance).sort(([t],[n])=>t.localeCompare(n)).flatMap(([t,n])=>{let r=n[n.length-1];if(!r)return[];return[{path:t,value:$k(e,t),...r,shadowed:n.slice(0,-1)}]})}function $k(e,t){let n=e;for(let r of t.split(".")){if(typeof n!=="object"||n===null)return;n=n[r]}return n}var st=D(()=>{Qg();vi();ea();zl();rd()});import{readdirSync as Ik}from"fs";import{join as Zg,resolve as ad,sep as cd}from"path";function Fk(e){let t=Zg(Nt(),"state"),n;try{n=Ik(t)}catch{return}let r=em(ad(e)),o;for(let i of n){let s=Ol(Zg(t,i,"state.json"));if(!s)continue;let a=em(ad(s.repo_root));if(!Nk(a,r))continue;if(!o||a.length>o.length)o=a}return o}function ta(e,t,n=""){if(t!=="")return{repoRoot:ad(t),source:"explicit"};let r=e===""?process.cwd():e;try{let{repoRoot:i}=jn(r,n);return{repoRoot:i,source:"config"}}catch{if(n!=="")return}let o=Fk(r);return o?{repoRoot:o,source:"state-scan"}:void 0}function em(e){let t=e.length>1&&e.endsWith(cd)?e.slice(0,-1):e;return process.platform==="win32"?t.toLowerCase():t}function Nk(e,t){return t===e||t.startsWith(e.endsWith(cd)?e:`${e}${cd}`)}var tm=D(()=>{vi();ze()});import{existsSync as rm,readFileSync as om}from"fs";import{isAbsolute as Hk,join as ld}from"path";import{parse as jk}from"dotenv";function Gk(){return{name:"dotenv",load:(e)=>{let t=nm(e.repoRoot,e.profile);if(e.workDir!=="")Object.assign(t,nm(e.workDir,e.profile));return t}}}function na(e){return async(t)=>{let n=t.includes("/versions/")?t:`${t}/versions/latest`,r=await e(),o=await fetch(`https://secretmanager.googleapis.com/v1/${n}:access`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)throw L(Z,`secret manager request failed for ${t}: HTTP ${o.status}`);let i=await o.json();if(!i.payload?.data)throw L(Z,`secret manager response for ${t} had no payload`);return Buffer.from(i.payload.data,"base64").toString("utf8")}}function Uk(e){let t=e?.environment.sources??[];if(t.length===0)return[...wi];let n=new Set([...Wk,...t]),r=new Set(wi),o=t.filter((s)=>!r.has(s)),i=[];for(let s of wi){if(s==="defaults")i.push(...o);if(n.has(s))i.push(s)}return i}async function ra(e,t){let n={},r=t.serviceCfg.working_dir;if(r!==""&&!Hk(r))r=ld(e,r);let o={repoRoot:e,profile:t.profile,service:t.service,serviceCfg:t.serviceCfg,workDir:r,cfg:t.cfg},i=Kk(t),s={process:t.includeProcess===!1?{}:t.clientEnv??lo(),profile:bi(t.profileEnv,t.cfg,i),dotenv:bi(await Gk().load(o),t.cfg,i),generated:{},keychain:t.sourceValues?.keychain??qk(o),secret_manager:t.sourceValues?.secret_manager??await Vk(o,t.fetchSecret),defaults:bi(t.serviceCfg.environment.defaults,t.cfg,i),vars:bi(t.serviceCfg.environment.vars,t.cfg,i),runtime:t.runtime};for(let a of Uk(t.cfg)){if(s[a]!==void 0){Object.assign(n,s[a]);continue}let c=t.pluginSources?.find((l)=>l.name===a);if(c)Object.assign(n,bi(await c.load(o),t.cfg,i))}for(let a of t.serviceCfg.environment.required)if((n[a]??"").trim()==="")throw L(Z,`service ${t.service} missing required environment variable ${a}`);return n}function Kk(e){let t={};if(e.cfg)for(let[n,r]of Object.entries(e.cfg.services)){let o={};for(let i of r.ports)if(!i.auto)o[i.name]=i.value;t[n]=o}if(e.assignedPorts)t[e.service]=e.assignedPorts;return t}function bi(e,t,n){if(!t||Object.keys(e).length===0)return e;return nd(e,t,n)}function qk(e){let t=e.cfg?.environment.sources??[];if(t.length>0&&!t.includes("keychain"))return{};let n={},r=new Set([...Object.keys(e.serviceCfg.environment.defaults),...Object.keys(e.serviceCfg.environment.vars),...e.serviceCfg.environment.required]);for(let o of r){let i=ld(Gt(),"env",o);if(!rm(i))continue;try{n[o]=om(i,"utf8").replace(/\n$/,"")}catch(s){throw fe(Z,`unable to read keychain env ${o}`,s)}}return n}async function Vk(e,t){if(!(e.cfg?.environment.sources??[]).includes("secret_manager"))return{};let r=e.cfg?.environment.secrets??{},o={};for(let[i,s]of Object.entries(r)){if(!Bk.test(s))throw L(Z,`environment.secrets.${i} is not a Secret Manager resource`);if(!t)throw L(Z,"environment source secret_manager is not configured \u2014 set credentials or remove it from environment.sources");o[i]=await t(s)}return o}function nm(e,t){let n={},r=[".env",".env.development",".env.local"];if(t!=="")r.push(`.env.${t}`);for(let o of r){let i=ld(e,o);if(!rm(i))continue;try{let s=jk(om(i));Object.assign(n,s)}catch(s){throw fe(Z,`unable to read ${i}`,s)}}return n}function lo(){let e={};for(let[t,n]of Object.entries(process.env))if(n!==void 0)e[t]=n;return e}function oa(e,t,n,r,o){let i={DEVCTL_SERVICE_NAME:e,DEVCTL_ENVIRONMENT:o,SERVICE_HOST:t};if(r!=="")i.DEVCTL_PROXY_URL=r;if(n.http!==void 0)i.SERVICE_PORT=String(n.http);else{let s=Object.values(n)[0];if(s!==void 0)i.SERVICE_PORT=String(s)}for(let[s,a]of Object.entries(n))i[`${s.toUpperCase()}_PORT`]=String(a);return i}function Si(e){return{...e}}var wi,Bk,Wk;var dd=D(()=>{st();Re();ze();wi=["process","profile","dotenv","generated","keychain","secret_manager","defaults","vars","runtime"],Bk=/^projects\/[^/]+\/secrets\/[^/]+(?:\/versions\/[^/]+)?$/,Wk=["process","defaults","vars","runtime"]});function Dt(){return"devctl 0.2.3"}var pt="0.2.3",ki=1;import{createConnection as Jk}from"net";var{spawn:zk}=globalThis.Bun;function eC(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 ${ki}`}function tC(e){if(e.compatible&&e.daemonVersion!==void 0&&e.daemonVersion!==pt)return`attached daemon is devctl ${e.daemonVersion}; this client is ${pt} (run \`devctl down\` then start again to update it)`;return}function ud(e,t){if(!e.compat.compatible&&!Zk.has(t))throw ke(Je,eC(e.compat),"run `devctl down` to stop it, then start again")}class am{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 n=this.buf.split(`
6
+ `);this.buf=n.pop()??"";for(let r of n){if(r.trim()==="")continue;this.onLine(r)}}),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 r of this.listeners)r(t.event);return}let n=t.id?this.pending.get(t.id):void 0;if(!n)return;if(this.pending.delete(t.id??""),clearTimeout(n.timer),t.error){n.reject(Nf({error:t.error,kind:t.kind,hint:t.hint,service:t.service}));return}n.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,n=Qk){this.nextID+=1;let r=String(this.nextID);return new Promise((o,i)=>{let s=setTimeout(()=>{this.pending.delete(r),i(Error(`${e} timed out after ${n}ms`))},n);this.pending.set(r,{resolve:o,reject:i,timer:s}),this.socket.write(JSON.stringify({id:r,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 cm(e,t){let n=Hs(e),r=Date.now()+t;return new Promise((o,i)=>{let s=()=>{let a=Jk(n);a.once("connect",()=>{let c=new am(a);nC(c).finally(()=>o(c))}),a.once("error",(c)=>{if(a.destroy(),Date.now()>=r){i(ke(Je,"supervisor is not running","run `devctl start` or `devctl attach` after starting services"));return}setTimeout(s,Yk)})};s()})}async function nC(e){let t;try{t=await e.call("ping",null,sm)}catch{return}let n=rC(t)?t:{};if(typeof n.session==="string")e.session=n.session;let r=typeof n.protocol==="number"?n.protocol:void 0,o=typeof n.version==="string"?n.version:void 0;if(r===void 0){e.compat={compatible:!1,legacy:!0,daemonVersion:o};return}e.compat={compatible:r===ki,legacy:!1,daemonVersion:o,daemonProtocol:r}}function rC(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}async function yr(e){try{return await cm(e,Xk)}catch{return}}function oC(e,t,n,r){return n?[e,...r]:[e,t,...r]}async function lm(e,t){let n=await yr(e);if(n)return n;Bf(e);let r=ur(e),o=oC(process.execPath,process.argv[1]??"",Bun.isStandaloneExecutable===!0,["--config",t,"_supervisor","--repo",e]);zk({cmd:o,env:process.env,stdout:"ignore",stderr:Bun.file(r),stdin:"ignore",detached:!0}).unref();try{return await cm(e,sm)}catch{throw ke(Je,"supervisor failed to start",`see ${r} for details`)}}class ia{cfg;client;previousPersisted;constructor(e){this.cfg=e}async start(e){return await this.call("start",{...e,client_env:lo()})}async stop(e){await this.call("stop",{services:e})}async restart(e,t){await this.call("restart",{services:e,cascade:t===!0,client_env:lo()})}async runTask(e){return await this.call("run_task",{name:e,client_env:lo()},im)}async execService(e,t,n=!1){return await this.call("exec",{service:e,command:t,print_env:n,client_env:lo()},im)}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,n){if(!this.client)throw fe(Je,"supervisor is not running",Error("no client"));return ud(this.client,e),this.client.call(e,t,n)}}function Ci(e){let t=e&&tC(e.compat);if(t)process.stderr.write(`warning: ${t}
8
+ `)}async function pd(e,t,n=""){let r=ta(e,t,n);if(!r)throw ke(Je,"no devctl configuration found","run `devctl setup`, create a .devctl/config.yaml in the repository root, or pass --repo");let o=await yr(r.repoRoot);return Ci(o),{repoRoot:r.repoRoot,client:o}}async function kt(e,t,n,r){let o=r?.allowMissingConfig===!0?yi(e,t):ut(e,t),i=new ia(o);if(!n)return i.client=await yr(o.repoRoot),Ci(i.client),i;return i.client=await lm(o.repoRoot,o.configPath),Ci(i.client),i}async function dm(e){let t=new ia(fr());return t.client=e,Ci(t.client),t.cfg=await t.configSnapshot(),t}async function um(e,t){let n=ta(e,"",t),r=n?await yr(n.repoRoot):void 0;if(!r)throw ke(Je,"supervisor is not running","run `devctl start` before `devctl attach`");return dm(r)}async function pm(e,t){let n=ta(e,"",t),r=n?await yr(n.repoRoot):void 0;if(r)return dm(r);let o=ut(e,t),i=new ia(o),s=pr(o.repoRoot);if(i.client=await lm(o.repoRoot,o.configPath),Ci(i.client),i.cfg=await i.configSnapshot(),s&&s.processes.length>0)i.previousPersisted=s;return i}var Yk=50,sm=8000,Xk=200,Qk=30000,im=86400000,Zk;var fd=D(()=>{st();tm();dd();Re();ze();Zk=new Set(["logs","logs_page","logs_stats"])});function aa(e){if(yn(e))return Ht({kind:xr,serviceAccount:e.service_account});if(Jf(e)&&(e.type!==""||e.mode!==""))return Ht({kind:sa});let t=(e.type||e.mode).toLowerCase();if(t!=="")return Ht({kind:t,providerConfig:e.config??{}});return Ht({kind:uo})}function br(e){if(e.type.toLowerCase()==="none")return Ht({kind:uo});let t=e.identity.type.toLowerCase(),n=e.identity.service_account||e.service_account;if(t==="service"||t==="service_account"||e.type==="service_account")return Ht({kind:xr,serviceAccount:n});if(e.type.toLowerCase()==="iap"&&t==="")return Ht({kind:uo});if(e.type===""&&t==="")return Ht({kind:uo});return Ht({kind:sa})}function fm(e){return e.kind===sa||e.kind===xr}function po(e){if(e.tokenKey!=="")return e.tokenKey;if(e.kind===xr)return`sa:${e.serviceAccount}`;if(e.email!=="")return`user:${e.email}`;return"user"}function Ht(e={}){return{kind:uo,email:"",serviceAccount:"",project:"",projectSource:"",adcAvailable:!1,providerConfig:{},tokenKey:"",...e}}function gd(e){let t=new Map,n=(r,o)=>{if(r!=="")t.set(r,(t.get(r)??!1)||o)};for(let r of Object.values(e.services))if(yn(r.identity)&&r.identity.service_account!=="")n(r.identity.service_account,!0);for(let r of e.proxy.routes){let o=r.auth.type.toLowerCase(),i=r.auth.identity.type.toLowerCase(),s=r.auth.identity.service_account||r.auth.service_account;if(i==="service"||i==="service_account"||o==="service_account")n(s,o!=="none")}return[...t.entries()].map(([r,o])=>({email:r,active:o})).sort((r,o)=>r.email.localeCompare(o.email))}function Gn(e){return gd(e).filter((t)=>t.active).map((t)=>t.email)}function gm(e,t,n){let r=[];for(let o of t){let i=e.services[o];if(!i)continue;let s=aa(i.identity);if(yn(i.identity)&&i.identity.service_account===""){r.push({name:o,message:"service account identity is not configured"});continue}if((fm(s)||i.capabilities.some((c)=>c==="google_api"||c==="iap"||c==="service_identity"))&&!n)r.push({name:o,message:"ADC unavailable"})}return r}function _i(e){if(Gn(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(fm(aa(t.identity)))return!0;return t.capabilities.some((n)=>n==="google_api"||n==="iap"||n==="service_identity")})}function md(){return{name:"user",accepts:(e)=>!yn(e),resolve:async(e,t)=>{if(e.type===""&&e.mode==="")return Ht({kind:uo});return{...await t(),kind:sa}}}}function hd(){return{name:"service_account",accepts:(e)=>yn(e),resolve:async(e,t)=>{if(e.service_account==="")throw L(Is,"service account identity is not configured");return{...await t(),kind:xr,serviceAccount:e.service_account}}}}async function mm(e,t,n){if(n)for(let r=n.length-1;r>=0;r-=1){let o=n[r];if(o?.accepts(e))return o.resolve(e,t)}if(yn(e))return hd().resolve(e,t);return md().resolve(e,t)}var sa="user",xr="service_account",uo="none";var wr=D(()=>{st();Re()});import{existsSync as ca,readFileSync as iC}from"fs";import{homedir as vm}from"os";import{join as vd}from"path";var{spawn:yd}=globalThis.Bun;function go(){let e=globalThis;if(e.window&&typeof e.window.fetch!=="function")e.window.fetch=fetch}function xd(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS||vd(vm(),".config","gcloud","application_default_credentials.json");if(!ca(e))return"";try{let t=JSON.parse(iC(e,"utf8"));return typeof t.quota_project_id==="string"?t.quota_project_id:""}catch{return""}}async function Ot(e){let t={gcloudInstalled:await bd("gcloud"),adcAvailable:!1,userEmail:"",projectID:"",projectSource:""};if(e!=="")t.projectID=e,t.projectSource="configuration";else{let n=pC("GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_PROJECT");if(n!=="")t.projectID=n,t.projectSource="environment variable";else if(t.gcloudInstalled){let r=await hm("core/project");if(r!=="")t.projectID=r,t.projectSource="gcloud configuration"}}if(Ei())try{await wm(cC(t),aC)}catch(n){t.adcAvailable=!1,t.error=ho(n)}if(t.userEmail===""&&t.gcloudInstalled)t.userEmail=await hm("core/account");return t}async function cC(e){go();let{GoogleAuth:t}=await import("google-auth-library"),n=new t({scopes:[sC]});await n.getClient(),e.adcAvailable=!0;let r=await n.getProjectId().catch(()=>"");if(e.projectID===""&&r)e.projectID=r,e.projectSource="application default credentials";let o=await lC(n);if(o!=="")e.userEmail=o}async function lC(e){try{let t=await e.getCredentials();if(t.client_email)return t.client_email}catch{}try{let t=await e.getClient(),n=typeof t.credentials?.id_token==="string"?t.credentials.id_token:"";if(n!==""){let r=dC(n);if(r!=="")return r}}catch{return""}return""}function dC(e){let t=e.split(".");if(t.length<2||!t[1])return"";try{let n=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));return typeof n.email==="string"?n.email:""}catch{return""}}async function xm(e){let t=await Ot(e);return Ht({kind:"user",email:t.userEmail,project:t.projectID,projectSource:t.projectSource,adcAvailable:t.adcAvailable})}async function mo(){if(await yd({cmd:["gcloud","auth","application-default","login"],stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited!==0)throw ke(to,"application-default login failed","run `gcloud auth application-default login`")}async function la(){if(await yd({cmd:["gcloud","auth","application-default","revoke","--quiet"],stdout:"ignore",stderr:"pipe"}).exited!==0)throw ke(to,"failed to revoke application-default credentials","run `gcloud auth application-default revoke`")}function ho(e){let t=uC(e).toLowerCase();if(fo(t,["unauth","invalid_grant","token has been expired","expired"]))return ke(to,"credential expired or invalid","run `devctl auth login` or `gcloud auth application-default login`");if(fo(t,["api has not been used","has not been enabled","access not configured","service_disabled"]))return ke(lr,"required Google API is not enabled","enable the API in the target service account project; devctl will not enable APIs automatically");if(fo(t,["permission","forbidden","iam"])){if(fo(t,["serviceaccounttoken","iamcredentials","token creator","getaccesstoken"]))return ke(Is,"cannot impersonate service account","ask an administrator to grant roles/iam.serviceAccountTokenCreator on the target service account");return ke(lr,"authorization failure","verify IAM permissions for the current user on this project")}if(t.includes("audience"))return ke(_l,"IAP audience is incorrect","set auth.audience on the proxy route to the IAP OAuth client ID");if(t.includes("iap"))return fe(_l,"IAP authentication failure",e);if(t.includes("project"))return ke(Z,"wrong or missing Google project","set google.project_id in .devctl/config.yaml");if(fo(t,["timeout","network","connection refused","no such host"]))return fe(Je,"network problem reaching Google Cloud",e);if(fo(t,["adc","default credentials","could not find"]))return ke(to,"application default credentials unavailable","run `gcloud auth application-default login`");return fe(to,"Google authentication failed",e)}function uC(e){let t=[],n=new Set,r=(o,i)=>{if(o===null||o===void 0||i>8||n.has(o))return;if(typeof o==="string"){t.push(o);return}if(typeof o!=="object")return;n.add(o);let s=o;for(let a of["message","reason","status","code","error_description","permission","service"])r(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)=>r(l,i+1));else r(c,i+1)}};return r(e,0),t.length>0?t.join(" "):String(e)}function fo(e,t){return t.some((n)=>e.includes(n))}function pC(...e){for(let t of e){let n=process.env[t];if(n)return n}return""}async function bd(e){try{return(await bm(process.platform==="win32"?["where",e]:["which",e],ym)).code===0}catch{return!1}}function Ei(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS;if(e&&ca(e))return!0;if(ca(vd(vm(),".config","gcloud","application_default_credentials.json")))return!0;let t=process.env.APPDATA;return Boolean(t&&ca(vd(t,"gcloud","application_default_credentials.json")))}async function hm(e){try{let t=await bm(["gcloud","config","get-value",e],ym);if(t.code!==0)return"";let n=t.stdout.trim();if(n===""||n==="(unset)")return"";return n}catch{return""}}async function bm(e,t){let n=yd({cmd:e,stdout:"pipe",stderr:"ignore",env:{...process.env,CLOUDSDK_CORE_DISABLE_PROMPTS:"1",CLOUDSDK_CORE_DISABLE_USAGE_REPORTING:"true"}}),r=n.stdout?new Response(n.stdout).text():Promise.resolve("");try{let[o,i]=await wm(Promise.all([r,n.exited]),t);return{code:i??1,stdout:o}}catch{return n.kill(),{code:1,stdout:""}}}function wm(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("timeout")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}var sC="https://www.googleapis.com/auth/cloud-platform",ym=1500,aC=2000;var Sr=D(()=>{eo();Re();wr()});var{spawn:Sd}=globalThis.Bun;import{createServer as Sm}from"net";async function km(e,t,n={}){let r={};for(let[i,s]of Object.entries(n))for(let a of Object.values(s))r[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=n[i]?.[c.name],d=l&&l>=wd?l:c.value;if(l===void 0&&c.auto)d=await gC();if(d<wd||d>fC)throw new Me(Z,`invalid port ${d} on service ${i}`,{service:i});if(r[d]&&r[d]!==i)throw new Me(Z,`duplicate port ${d} used by ${r[d]} and ${i}`,{service:i});if(l!==d&&!c.auto&&!await vo(d))throw await mC(i,c.name,d);r[d]=i,a[c.name]=d}o[i]=a}return o}function gC(){return new Promise((e,t)=>{let n=Sm();n.listen(0,"127.0.0.1",()=>{let r=n.address();n.close(()=>{if(r&&typeof r==="object")e(r.port);else t(fe(Z,"unable to allocate dynamic port",Error("no address")))})}),n.on("error",(r)=>t(fe(Z,"unable to allocate dynamic port",r)))})}async function da(e){let t=e.ports.filter((r)=>!r.auto&&r.value>=wd);if(t.length===0)return;let n={};for(let r of t){if(await vo(r.value))return;n[r.name]=r.value}return n}function vo(e){return new Promise((t)=>{let n=Sm();n.listen(e,"127.0.0.1",()=>{n.close(()=>t(!0))}),n.on("error",()=>t(!1))})}async function mC(e,t,n){let r=await yo(n);return hC(e,t,n,r)}function hC(e,t,n,r){let o=t===""?`${e} port`:`${e} ports.${t}`;if(r&&r.pid===process.pid)return ke(Ne,`${e} blocked: this TUI already holds port ${n}`,`Stop the proxy from the Proxy screen, or change ${o} in .devctl.`,e);if(r)return ke(Ne,`${e} blocked: ${r.command} (pid ${r.pid}) is using port ${n}`,`Open Doctor and press enter to free port ${n}, or change ${o} in .devctl.`,e);return ke(Ne,`${e} blocked: port ${n} is already in use`,`Something is listening on ${n}. Open Doctor to free it, or change ${o} in .devctl.`,e)}function vC(e,t){let n=e.split(`
9
+ `).filter((r)=>r.trim()!==""&&!r.startsWith("COMMAND"));for(let r of n){let o=r.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 yo(e){if(process.platform==="win32")return wC(e);let t=await yC(e);if(t)return t;return xC(e)}async function yC(e){try{let t=Sd({cmd:["lsof","-nP",`-iTCP:${e}`,"-sTCP:LISTEN"],stdout:"pipe",stderr:"ignore"}),n=await new Response(t.stdout).text();return await t.exited,vC(n,e)}catch{return}}async function xC(e){let t;try{let o=Sd({cmd:["fuser","-n","tcp",String(e)],stdout:"pipe",stderr:"pipe"});t=`${await new Response(o.stdout).text()} ${await new Response(o.stderr).text()}`,await o.exited}catch{return}let n=t.match(/(\d+)/),r=n?Number(n[1]):0;if(!Number.isInteger(r)||r<=0)return;return{port:e,pid:r,command:"process"}}function bC(e,t){for(let n of e.split(`
10
+ `)){if(!n.includes("LISTENING")&&!n.includes("LISTEN"))continue;if(!n.includes(`:${t}`)&&!n.includes(` ${t} `))continue;let r=n.trim().match(/(\d+)\s*$/),o=r?Number(r[1]):0;if(Number.isInteger(o)&&o>0)return{port:t,pid:o,command:"process"}}return}async function wC(e){let t=Sd({cmd:["netstat","-ano"],stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,bC(n,e)}async function ua(e){if(e.pid===process.pid)throw ke(Ne,`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 fe(Ne,`could not stop pid ${e.pid} on port ${e.port}`,t)}await kC(SC);try{process.kill(e.pid,0),process.kill(e.pid,"SIGKILL")}catch{return}}function kC(e){return new Promise((t)=>{setTimeout(t,e)})}var fC=65535,wd=1,SC=400;var Ri=D(()=>{Re()});var{spawn:Ed}=globalThis.Bun;import{existsSync as fa,readdirSync as CC,readFileSync as Cm,unlinkSync as _C}from"fs";import{join as Pi}from"path";function _d(e){return Pi(Gt(),`${ma(e)}${Cd}`)}function ga(e){if(e==="file"||process.env.DEVCTL_HOME&&e!=="keychain")return new pa;if(e==="keychain"||process.platform==="darwin"||process.platform==="win32"||process.platform==="linux")return new _m(new pa);return new pa}class pa{backend="file";async get(e){let t=TC(e);if(!t||t.accessToken==="")return;return t}async set(e,t){Ut(_d(e),`${JSON.stringify({...PC(t),key:e})}
11
+ `)}async delete(e){let t=_d(e);if(fa(t))_C(t)}async list(){let e=Gt();if(!fa(e))return[];let t=[];for(let n of CC(e)){if(!n.endsWith(Cd))continue;let r=n.slice(0,-Cd.length),o=Em(Pi(Gt(),n));if(!o)continue;t.push(Rm(o.key??r,o.record))}return t.sort((n,r)=>n.identity.localeCompare(r.identity))}}class _m{backend="keychain";fallback;constructor(e){this.fallback=e}async get(e){let t=await AC(e);if(t)return t;return this.fallback.get(e)}async set(e,t){if(!await LC(e,t))await this.fallback.set(e,t);EC(e)}async delete(e){await DC(e),await this.fallback.delete(e),RC(e)}async list(){let e=new Set(Pd()),t=await this.fallback.list(),n=new Map;for(let r of t)n.set(r.key,r);for(let r of e){let o=await this.get(r);if(o)n.set(r,Rm(r,o))}return[...n.values()].sort((r,o)=>r.identity.localeCompare(o.identity))}}function EC(e){let t=Pd();if(!t.includes(e))Ut(Pi(Gt(),Rd),`${JSON.stringify([...t,e])}
12
+ `)}function RC(e){let t=Pd(),n=t.filter((r)=>r!==e);if(n.length!==t.length)Ut(Pi(Gt(),Rd),`${JSON.stringify(n)}
13
+ `)}function Pd(){let e=Pi(Gt(),Rd);if(!fa(e))return[];try{let t=JSON.parse(Cm(e,"utf8"));return Array.isArray(t)?t.filter((n)=>typeof n==="string"):[]}catch{return[]}}function PC(e){return{...e,accessToken:""}}function TC(e){return Em(_d(e))?.record}function Em(e){if(!fa(e))return;try{let t=JSON.parse(Cm(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((n)=>typeof n==="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 Rm(e,t){let n=Date.parse(t.expiresAt);return{key:e,identity:t.identity,audience:t.audience,scopes:t.scopes,expires_at:t.expiresAt,valid:Number.isFinite(n)&&n-Date.now()>0}}function ma(e){return e.replace(/[^A-Za-z0-9._-]+/g,"_").slice(0,80)||"token"}async function AC(e){let t=await OC(e);if(!t)return;try{return JSON.parse(t)}catch{return}}async function LC(e,t){let n=JSON.stringify(t);if(process.platform==="darwin")return await xo(["security","delete-generic-password","-s",kr,"-a",e]),await xo(["security","add-generic-password","-s",kr,"-a",e,"-w",n,"-U"])===0;if(process.platform==="linux")return await MC(["secret-tool","store","--label",`devctl ${e}`,"service",kr,"account",e],n)===0;if(process.platform==="win32"){let o=`Add-Type -AssemblyName System.Security; $bytes = [Convert]::FromBase64String('${Buffer.from(n,"utf8").toString("base64")}'); $enc = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, 'CurrentUser'); [IO.File]::WriteAllBytes($env:LOCALAPPDATA + '\\devctl-cred-${ma(e)}.bin', $enc)`;return await xo(["powershell","-NoProfile","-Command",o])===0}return!1}async function DC(e){if(process.platform==="darwin"){await xo(["security","delete-generic-password","-s",kr,"-a",e]);return}if(process.platform==="linux"){await xo(["secret-tool","clear","service",kr,"account",e]);return}if(process.platform==="win32")await xo(["powershell","-NoProfile","-Command",`Remove-Item -ErrorAction SilentlyContinue ($env:LOCALAPPDATA + '\\devctl-cred-${ma(e)}.bin')`])}async function OC(e){if(process.platform==="darwin"){let t=await kd(["security","find-generic-password","-s",kr,"-a",e,"-w"]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="linux"){let t=await kd(["secret-tool","lookup","service",kr,"account",e]);return t.code===0&&t.stdout!==""?t.stdout:void 0}if(process.platform==="win32"){let t=`$p = $env:LOCALAPPDATA + '\\devctl-cred-${ma(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)`,n=await kd(["powershell","-NoProfile","-Command",t]);return n.code===0&&n.stdout!==""?n.stdout:void 0}return}async function xo(e){try{return await Ed({cmd:e,stdout:"ignore",stderr:"ignore",timeout:Td}).exited}catch{return 1}}async function MC(e,t){try{return await Ed({cmd:e,stdin:new TextEncoder().encode(t),stdout:"ignore",stderr:"ignore",timeout:Td}).exited}catch{return 1}}async function kd(e){try{let t=Ed({cmd:e,stdout:"pipe",stderr:"ignore",timeout:Td}),n=t.stdout?await new Response(t.stdout).text():"";return{code:await t.exited,stdout:n.trim()}}catch{return{code:1,stdout:""}}}var Rd="keychain-index.json",kr="devctl.credentials",Cd=".cred.json",Td=3000;var Ad=D(()=>{ze()});function Le(e,t,n){return{type:e,timestamp:new Date().toISOString(),service:t,payload:n}}class $d{subs=new Map;nextID=0;buffer=[];maxBuf;constructor(e){this.maxBuf=e>0?e:1024}subscribe(e,t=[]){this.nextID+=1;let n=this.nextID;return this.subs.set(n,{types:new Set(t),handler:e}),()=>{this.subs.delete(n)}}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 n of this.subs.values())if(n.types.size===0||n.types.has(t.type))n.handler(t)}recent(){return[...this.buffer]}}var Pm="ServiceStarted",Ld="ServiceStopped",Dd="ServiceFailed",Tm="ServiceStateChanged",Am="ServiceHealthChanged",ha="LogReceived",bo="TokenRefreshed",Cr="TokenRefreshFailed",Od="AuthenticationChanged",Lm="ProxyStarted",Dm="ProxyStopped",Md="ProxyRequest",va="ConfigurationChanged",Ti="ConfigurationReloadFailed",Om="SessionRecovered";async function Mm(e,t={}){let n=t.attempts??$C,r=t.backoffMs??IC,o=t.retry??FC,i=Error("retry exhausted");for(let s=0;s<n;s+=1)try{return await e()}catch(a){if(i=a,!o(a)||s===n-1)throw a;await NC(r*(s+1))}throw i}function FC(e){if(e instanceof Me)return e.kind!==Z&&e.kind!==lr;return!0}function NC(e){return new Promise((t)=>{setTimeout(t,e)})}var $C=3,IC=200;var $m=D(()=>{Re()});var Hm={};Ms(Hm,{TokenManager:()=>wo,expiresSoonToken:()=>Fm,googleTokenProviders:()=>_r,isValidToken:()=>Im,staticTokenProvider:()=>zC,tokenCacheKey:()=>Id,tokenMetaPath:()=>Nm});import{createHash as HC}from"crypto";import{join as jC}from"path";import{GoogleAuth as xa,Impersonated as BC}from"google-auth-library";function Id(e,t,n){return`${e}|${t}|${n.join(",")}`}function Im(e,t=Fd){if(e.accessToken==="")return!1;return e.expiresAt.getTime()-Date.now()>=t}function Fm(e,t=Fd){if(e.accessToken==="")return!0;let n=e.expiresAt.getTime()-Date.now();return n>0&&n<t}class wo{cache=new Map;inflight=new Map;providers;thresholdMs;bus;store;constructor(e,t,n,r){this.thresholdMs=e>0?e:Fd,this.providers=[...t],this.bus=n,this.store=r??ga(process.env.DEVCTL_CREDENTIAL_BACKEND==="file"?"file":void 0)}replaceProviders(e){this.providers.splice(0,this.providers.length,...e)}isValid(e){return Im(e,this.thresholdMs)}expiresSoon(e){return Fm(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,n){let r=Id(e,t,n),o=this.cache.get(r)??await this.loadStored(r);if(o&&this.isValid(o))return this.cache.set(r,o),o;return this.refresh(e,t,n)}async refresh(e,t,n){let r=Id(e,t,n),o=this.inflight.get(r);if(o)return o;let i=this.refreshOnce(r,e,t,n);this.inflight.set(r,i);try{return await i}finally{this.inflight.delete(r)}}async refreshOnce(e,t,n,r){let o=this.providers.filter((s)=>!s.accepts||s.accepts(t,n,r));if(o.length===0)throw L(hn,`no token provider accepts identity ${t}`);let i=L(hn,"no token provider available");for(let s of o)try{let a=await Mm(()=>s.fetch(t,n,r),{attempts:GC,backoffMs:UC,retry:i_});return this.cache.set(e,a),qC(e,a),await this.store.set(e,VC(a)),this.bus?.publish(Le(bo,"",{identity:a.identity,audience:a.audience})),a}catch(a){i=a instanceof Error?a:Error(String(a))}throw this.bus?.publish(Le(Cr,"",{identity:t,audience:n,error:O(i)})),i}async loadStored(e){let t=await this.store.get(e);if(!t||t.accessToken==="")return;return JC(t)}async clearStore(){let e=await this.store.list();await Promise.all(e.map((t)=>this.store.delete(t.key)))}}function Nm(e){let t=HC("sha256").update(e).digest("hex").slice(0,16);return jC(Gt(),`${t}.json`)}function qC(e,t){let n={identity:t.identity,audience:t.audience,expires_at:t.expiresAt.toISOString(),scopes:t.scopes};Ut(Nm(e),`${JSON.stringify(n)}
14
+ `)}function VC(e){return{identity:e.identity,audience:e.audience,scopes:e.scopes,accessToken:e.accessToken,tokenType:e.tokenType,expiresAt:e.expiresAt.toISOString()}}function JC(e){return{accessToken:e.accessToken,tokenType:e.tokenType||"Bearer",expiresAt:new Date(e.expiresAt),audience:e.audience,identity:e.identity,scopes:e.scopes}}function _r(){return[QC(),XC(),YC()]}function zC(e){return{name:"static",accepts:(t,n)=>(e.identity===""||t===e.identity)&&(e.audience===""||n===e.audience),fetch:async(t,n,r)=>({...e,identity:t,audience:n,scopes:r})}}function YC(){return{name:"user",accepts:(e,t)=>!e.startsWith("sa:")&&t==="",fetch:async(e,t,n)=>{if(e.startsWith("sa:"))throw L(hn,"user provider cannot mint service-account tokens");return n_(e,t,n)}}}function XC(){return{name:"service_account",accepts:(e,t)=>e.startsWith("sa:")&&t==="",fetch:async(e,t,n)=>{if(!e.startsWith("sa:"))throw L(hn,"service-account provider cannot mint user tokens");return ZC(e,t,n)}}}function QC(){return{name:"iap",accepts:(e,t)=>t!=="",fetch:async(e,t,n)=>{if(t==="")throw L(hn,"IAP audience is required");if(e.startsWith("sa:"))return e_(e,t,n);return t_(e,t,n)}}}async function ZC(e,t,n){let r=e.slice(3);try{go();let i=await new xa({scopes:n.length>0?n:[ya]}).getClient(),s=new BC({sourceClient:i,targetPrincipal:r,targetScopes:n.length>0?n:[ya],lifetime:3600}),a=await s.getAccessToken(),c=typeof a==="string"?a:a?.token;if(!c)throw L(hn,"empty impersonated token");return{accessToken:c,tokenType:"Bearer",expiresAt:ba(c,s),audience:t,identity:e,scopes:n}}catch(o){throw ho(o)}}async function e_(e,t,n){let r=e.slice(3);try{go();let i=await new xa({scopes:[ya]}).getClient(),s=`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(r)}:generateIdToken`,c=(await i.request({url:s,method:"POST",data:{audience:t,includeEmail:!0}})).data.token;if(!c)throw L(hn,"empty impersonated IAP id token");return{accessToken:c,tokenType:"Bearer",expiresAt:ba(c),audience:t,identity:e,scopes:n}}catch(o){throw ho(o)}}async function t_(e,t,n){try{go();let i=await(await new xa({scopes:n.length>0?n:[KC]}).getIdTokenClient(t)).idTokenProvider.fetchIdToken(t);return{accessToken:i,tokenType:"Bearer",expiresAt:ba(i),audience:t,identity:e,scopes:n}}catch(r){throw ho(r)}}async function n_(e,t,n){try{go();let o=await new xa({scopes:n.length>0?n:[ya]}).getClient(),i=await o.getAccessToken();if(!i.token)throw L(hn,"empty access token");return{accessToken:i.token,tokenType:"Bearer",expiresAt:r_(o,i.token),audience:t,identity:e,scopes:n}}catch(r){throw ho(r)}}function ba(e,t){if(t?.credentials?.expiry_date)return new Date(t.credentials.expiry_date);return o_(e)??new Date(Date.now()+WC)}function r_(e,t){return ba(t,e)}function o_(e){let t=e.split(".");if(t.length<2||!t[1])return;try{let n=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));if(typeof n.exp==="number")return new Date(n.exp*1000)}catch{return}return}function i_(e){if(e instanceof Me)return e.kind!==Z&&e.kind!==lr;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 Fd=300000,WC=3000000,GC=3,UC=200,ya="https://www.googleapis.com/auth/cloud-platform",KC="https://www.googleapis.com/auth/userinfo.email";var Ai=D(()=>{eo();Ad();Re();Sr();$m();ze()});async function Un(e,t=jm,n,r){let o={checks:[],issues:0},i="Preparing diagnostics",s=()=>n?.({active:i,checks:[...o.checks]}),a=(m)=>{i=m,s()},c=(m)=>{if(o.checks.push(m),m.severity==="error")o.issues+=1;s()},l=[...new Set(Object.values(e.services).flatMap((m)=>m.container?[m.container.runtime||"docker"]:[]))];for(let m of l){a(`${m} container runtime`);let x=await t.hasCommand(m),v=x&&await(t.containerRuntimeAvailable??jm.containerRuntimeAvailable)(m);c(v?{name:`${m} container runtime`,severity:"ok",message:`${m} daemon reachable`}:{name:`${m} container runtime`,severity:"error",message:x?`${m} daemon is not reachable`:`${m} not found`,hint:`install and start ${m}`})}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:_i(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 d=await t.detectGoogle(e.google.project_id);if(d.adcAvailable)c({name:"Google authentication available",severity:"ok",message:"Application Default Credentials found"});else c({name:"Google authentication available",severity:_i(e)?"error":"warn",message:"ADC unavailable",hint:"run `gcloud auth application-default login`"});if(d.projectID!=="")c({name:"Project configured",severity:"ok",message:`${d.projectID} (source: ${d.projectSource})`});else c({name:"Project configured",severity:_i(e)?"error":"warn",message:"no Google project configured",hint:"set google.project_id in .devctl/config.yaml"});if(_i(e)||Object.values(e.services).some((m)=>m.capabilities.includes("google")||m.identity.type!=="")){a("Live Google access");let m=!0,x=(v)=>{if(m)c(v)};try{await Di((async()=>{await c_(e,x,t,d.userEmail),await a_(e,x,t)})(),t.liveDeadlineMs??s_)}catch(v){x({name:"Live Google probes",severity:"warn",message:O(v),hint:"network or timeout \u2014 retry when online"})}finally{m=!1}}for(let m of e.doctor.tools){let x=m.command||m.name;if(a(`${m.name} installed`),await t.hasCommand(x))c({name:`${m.name} installed`,severity:"ok",message:`${x} found`});else c({name:`${m.name} installed`,severity:"error",message:`${x} not found`,hint:`install ${m.name} and ensure it is on PATH`})}if(a("Repository configuration"),r?.repositoryConfigError!==void 0)if(r.repositoryConfigError==="")c({name:"Repository configuration",severity:"ok",message:"valid"});else c({name:"Repository configuration",severity:"error",message:r.repositoryConfigError});else try{let m=Xt(e);if(m.length>0)c({name:"Repository configuration",severity:"error",message:m.join("; ")});else c({name:"Repository configuration",severity:"ok",message:"valid"})}catch(m){c({name:"Repository configuration",severity:"error",message:O(m)})}let g={};for(let[m,x]of Object.entries(e.services))for(let v of x.ports){if(v.auto)continue;let w=`Port ${v.value}`;if(a(w),g[v.value])c({name:w,severity:"error",message:`configured on both ${g[v.value]} and ${m}`});else{g[v.value]=m;let E=r?.services?.[m],k=Boolean(x.container&&E&&["STARTING","RUNNING","HEALTHY","UNHEALTHY"].includes(E.state??""));if(Boolean(E&&(E.pid>0||k)&&Object.values(E.ports).includes(v.value)))c({name:w,severity:"ok",message:`in use by running service ${m}`});else if(await t.portAvailable(v.value))c({name:w,severity:"ok",message:"available"});else c(await Wm(w,v.value,`services.${m}.ports`))}}if(e.proxy.listen.port>0){let m=`Port ${e.proxy.listen.port}`;if(a(m),r?.proxyRunning)c({name:m,severity:"ok",message:"in use by the running proxy"});else if(await t.portAvailable(e.proxy.listen.port))c({name:m,severity:"ok",message:"proxy listen port available"});else c(await Wm(m,e.proxy.listen.port,"proxy.listen.port"))}return i="Diagnostics complete",s(),o}async function a_(e,t,n){let r=e.google.project_id,o=n.hasLocalAdc??Ei;if(r===""||!o())return;let i=n.probeServiceUsage??Km,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(r,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:O(c.reason),hint:`enable ${d.service} in the Google Cloud console \u2014 doctor never auto-enables APIs`})})}async function Gm(){if(!Nd)Nd=Promise.resolve().then(() => (Ai(),Hm)).then(({TokenManager:e,googleTokenProviders:t})=>new e(60000,t(),void 0,ga("file")));return Nd}async function Um(e,t){await(await Gm()).get(e,t,[])}async function Km(e,t){let n=await Gm(),r=await Di(n.get("user","",[]),Li),o=`https://serviceusage.googleapis.com/v1/projects/${e}/services/${t}`,i=await fetch(o,{headers:{Authorization:`Bearer ${r.accessToken}`},signal:AbortSignal.timeout(Li)});if(!i.ok)return!1;return(await i.json().catch(()=>{return}))?.state==="ENABLED"}async function c_(e,t,n,r){let o=Gn(e),i=e.proxy.routes.filter((f)=>f.auth.type.toLowerCase()==="iap"),s=i.filter((f)=>f.auth.audience.trim()!=="");for(let f of i)if(f.auth.audience.trim()==="")t({name:`IAP audience ${f.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(!(n.hasLocalAdc??Ei)())return;let c=n.mintToken??Um,l=o.map(async(f)=>{try{await Di(c(`sa:${f}`,""),Li),t({name:`Impersonate ${f}`,severity:"ok",message:"token minted"})}catch(g){let m=(n.adcQuotaProject??xd)(),x=r||"the ADC principal",v=m===""?"unknown":m,w=Bm(`Impersonate ${f}`,g,`grant roles/iam.serviceAccountTokenCreator to ${x} on ${f}; ADC quota project: ${v}`);if(m!==""&&w.message.toLowerCase().includes("api is not enabled"))w.message=`IAM Credentials API is disabled in ADC quota project ${m}`,w.hint=`enable iamcredentials.googleapis.com in ${m}, 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: ${x} \u2192 ${f}`,w.hint=`verify roles/iam.serviceAccountTokenCreator for ${x} on this service account; ADC quota project: ${v}`;t(w)}}),d=s.map(async(f)=>{let g=br(f.auth).kind===xr?`sa:${br(f.auth).serviceAccount}`:"user";try{await Di(c(g,f.auth.audience),Li),t({name:`IAP ${f.name}`,severity:"ok",message:"id token minted"})}catch(m){t(Bm(`IAP ${f.name}`,m,"check IAP OAuth client ID and ADC"))}});await Promise.all([...l,...d])}function Bm(e,t,n){let r=O(t),o=r.toLowerCase();if(o.includes("timeout")||o.includes("network")||o.includes("econnrefused")||o.includes("enotfound"))return{name:e,severity:"warn",message:r,hint:"network or timeout \u2014 retry when online"};if(t instanceof Me&&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:r,hint:n}}function Di(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("timeout")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}async function Wm(e,t,n){let r=await yo(t);if(!r)return{name:e,severity:"error",message:"already in use",hint:`stop the process using port ${t} or change ${n}`};if(r.pid===process.pid)return{name:e,severity:"error",message:`in use by this TUI (${r.command} pid ${r.pid})`,hint:"stop the proxy from the proxy screen (x), then rerun doctor"};return{name:e,severity:"error",message:`in use by ${r.command} (pid ${r.pid})`,hint:"enter stop that process after a confirmation",action:{kind:"free-port",holder:r}}}function wa(e){let t=[`${Dt()} doctor`,""];for(let n of e.checks){let r=n.severity==="error"?"\u2717":n.severity==="warn"?"!":"\u2713";if(t.push(`${r} ${n.name}`),n.severity!=="ok"){if(t.push(` ${n.message}`),n.hint)t.push(` \u2192 ${n.hint}`)}}return t.push("",`${e.issues} issue(s) found.`),t.join(`
15
15
  `)+`
16
- `}var Li=4000,e_=8000,Fm,Ad;var Oi=D(()=>{eo();st();Pe();wr();br();Pi();kd();Fm={detectGoogle:Lt,hasCommand:fd,portAvailable:ho,hasLocalAdc:Ri,adcQuotaProject:pd,mintToken:Bm,probeServiceUsage:Wm,containerRuntimeAvailable:async(e)=>{try{return await Bun.spawn({cmd:[e,"info"],stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited===0}catch{return!1}}}});function ko(e){if(e.state===Ht&&e.health===Ct)return _r;if(e.state===Ht&&e.health===Ce)return wo;return e.state}function xa(e){return{name:e,state:So,health:Dt,pid:0,ports:{},restarts:0,last_error:"",identity:"",startTime:void 0,cpuPercent:void 0,memoryKB:void 0,profile:"",env_source:"daemon",orphaned:!1}}function Um(e,t){let n={},r={};for(let a of Object.keys(t))n[a]=0;for(let a of Object.keys(t)){let c=e.services[a]?.dependencies??[];for(let l of c){let d=wt(l);if(!t[d])continue;r[d]=[...r[d]??[],a],n[a]=(n[a]??0)+1}}let o=[],i=Object.keys(t).length,s={};while(i>0){let a=Object.entries(n).filter(([c,l])=>l===0&&!s[c]).map(([c])=>c).sort();if(a.length===0)throw L(Lf,"dependency cycle detected while planning startup");o.push(a);for(let c of a){s[c]=!0,i-=1;for(let l of r[c]??[])n[l]=(n[l]??0)-1}}return o}function Od(e,t){if(!e.services[t])throw L(pi,`unknown service "${t}"`)}function $i(e,t,n){let r={},o=(a)=>{if(r[a])return;Od(e,a),r[a]=!0;for(let c of e.services[a]?.dependencies??[])o(wt(c))};for(let a of t)o(a);let i=Um(e,r),s=[];return i.forEach((a,c)=>{for(let l of a)s.push({name:l,wave:c+1,dependencies:[...e.services[l]?.dependencies??[]]})}),{profile:n,steps:s,waves:i,blockers:[]}}function Md(e,t){let n={};for(let[i,s]of Object.entries(e.services))for(let a of s.dependencies){let c=wt(a);n[c]=[...n[c]??[],i]}let r={},o=(i)=>{if(r[i])return;Od(e,i),r[i]=!0;for(let s of n[i]??[])o(s)};for(let i of t)o(i);return Object.keys(r)}function Km(e,t){let n=[...Um(e,t)].reverse().map((o)=>[...o].sort()),r=[];return n.forEach((o,i)=>{for(let s of o)r.push({name:s,wave:i+1,dependencies:[...e.services[s]?.dependencies??[]]})}),{steps:r,waves:n,profile:"",blockers:[]}}function Ii(e,t){let n=Object.fromEntries(Md(e,t).map((r)=>[r,!0]));return Km(e,n)}function qm(e,t){let n={};for(let r of t)Od(e,r),n[r]=!0;return Km(e,n)}function $d(e){let t="";if(e.profile!=="")t+=`Profile: ${e.profile}
16
+ `}var Li=4000,s_=8000,jm,Nd;var Oi=D(()=>{eo();st();Re();Sr();wr();Ri();Ad();jm={detectGoogle:Ot,hasCommand:bd,portAvailable:vo,hasLocalAdc:Ei,adcQuotaProject:xd,mintToken:Um,probeServiceUsage:Km,containerRuntimeAvailable:async(e)=>{try{return await Bun.spawn({cmd:[e,"info"],stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited===0}catch{return!1}}}});function Co(e){if(e.state===jt&&e.health===_t)return Er;if(e.state===jt&&e.health===Ce)return So;return e.state}function Sa(e){return{name:e,state:ko,health:Ct,pid:0,ports:{},restarts:0,last_error:"",identity:"",startTime:void 0,cpuPercent:void 0,memoryKB:void 0,profile:"",env_source:"daemon",orphaned:!1}}function Vm(e,t){let n={},r={};for(let a of Object.keys(t))n[a]=0;for(let a of Object.keys(t)){let c=e.services[a]?.dependencies??[];for(let l of c){let d=wt(l);if(!t[d])continue;r[d]=[...r[d]??[],a],n[a]=(n[a]??0)+1}}let o=[],i=Object.keys(t).length,s={};while(i>0){let a=Object.entries(n).filter(([c,l])=>l===0&&!s[c]).map(([c])=>c).sort();if(a.length===0)throw L($f,"dependency cycle detected while planning startup");o.push(a);for(let c of a){s[c]=!0,i-=1;for(let l of r[c]??[])n[l]=(n[l]??0)-1}}return o}function Bd(e,t){if(!e.services[t])throw L(fi,`unknown service "${t}"`)}function $i(e,t,n){let r={},o=(a)=>{if(r[a])return;Bd(e,a),r[a]=!0;for(let c of e.services[a]?.dependencies??[])o(wt(c))};for(let a of t)o(a);let i=Vm(e,r),s=[];return i.forEach((a,c)=>{for(let l of a)s.push({name:l,wave:c+1,dependencies:[...e.services[l]?.dependencies??[]]})}),{profile:n,steps:s,waves:i,blockers:[]}}function Wd(e,t){let n={};for(let[i,s]of Object.entries(e.services))for(let a of s.dependencies){let c=wt(a);n[c]=[...n[c]??[],i]}let r={},o=(i)=>{if(r[i])return;Bd(e,i),r[i]=!0;for(let s of n[i]??[])o(s)};for(let i of t)o(i);return Object.keys(r)}function Jm(e,t){let n=[...Vm(e,t)].reverse().map((o)=>[...o].sort()),r=[];return n.forEach((o,i)=>{for(let s of o)r.push({name:s,wave:i+1,dependencies:[...e.services[s]?.dependencies??[]]})}),{steps:r,waves:n,profile:"",blockers:[]}}function Ii(e,t){let n=Object.fromEntries(Wd(e,t).map((r)=>[r,!0]));return Jm(e,n)}function zm(e,t){let n={};for(let r of t)Bd(e,r),n[r]=!0;return Jm(e,n)}function Gd(e){let t="";if(e.profile!=="")t+=`Profile: ${e.profile}
17
17
 
18
18
  `;t+=`Plan:
19
19
 
@@ -21,7 +21,7 @@ var Zw=Object.defineProperty;var eS=(e)=>e;function tS(e,t){this[e]=eS.bind(null
21
21
  `,n+=1;if((e.blockers??[]).length>0){t+=`
22
22
  Blocked:
23
23
  `;for(let r of e.blockers??[])t+=`- ${r.name}: ${r.message}
24
- `}return t}function ba(e){return`${e.join(", ")} changed and only take effect after a full \`devctl down && devctl start\`, not a reload`}function r_(e,t,n){let r={};if(t!==""){let o=e.profiles[t];if(!o)throw L("configuration",`unknown profile "${t}"`);Object.assign(r,o.environment)}if(n.length>0)return{services:Gm(e,n),env:r};if(t==="")return{services:Object.keys(e.services),env:r};return{services:Gm(e,e.profiles[t]?.services??[]),env:r}}function o_(e){return Object.keys(e.profiles).sort()[0]??""}function wa(e,t){let n=t.services??[],r=t.profile??"";if(n.length===0&&r===""){if(r=t.activeProfile||o_(e),r==="")throw L(ee,"no profile or services given; pass service names or add a profile")}let o=r_(e,r,n);return{services:o.services,env:o.env,profile:r}}function Gm(e,t){let n={},r=[];for(let o of t){if(n[o])continue;if(!e.services[o])throw L("service_not_found",`unknown service "${o}"`);n[o]=!0,r.push(o)}return r}var Ld="STARTING",Ht="RUNNING",_r="HEALTHY",wo="UNHEALTHY",Dd="STOPPING",So="STOPPED",Rr="FAILED",Mi="RESTARTING",Dt="UNKNOWN",Ct="HEALTHY",Ce="UNHEALTHY";var Pr=D(()=>{st();Pe()});var zm={};Ls(zm,{createStarterConfig:()=>u_,resolveSetupTarget:()=>Vm,runSetup:()=>Hd});import{existsSync as Nd,mkdirSync as Id,statSync as i_,writeFileSync as s_}from"fs";import{createInterface as a_}from"readline/promises";import{stdin as c_,stdout as l_}from"process";import{basename as Sa,dirname as Fd,join as xn,resolve as d_}from"path";function Vm(e,t){let n=e===""?process.cwd():e;if(t==="")return{repo:n,cfgPath:xn(n,St,Kt)};let r=d_(t);if(!(Nd(r)?i_(r).isDirectory():!/\.ya?ml$/i.test(r))){let i=Fd(r);return{repo:Sa(i)===St?Fd(i):i,cfgPath:r}}if(Sa(r)===St)return{repo:Fd(r),cfgPath:xn(r,Kt)};return{repo:r,cfgPath:xn(r,St,Kt)}}function u_(e,t=Sa(e),n="",r="",o=!1){let i=xn(e,St,Kt);if(!o&&Nd(i))throw L(ee,`configuration already exists at ${i}; not overwriting`);return Jm(e,t,n,r),i}async function Hd(e,t="",n=!1){let{repo:r,cfgPath:o}=Vm(e,t);if(!n&&Nd(o)){ht(`Found existing configuration at ${o}; nothing written.`),ht("Pass --force to overwrite it, or edit it directly.");return}let i=a_({input:c_,output:l_}),s=async(k,j)=>{let V=j!==""?` [${j}]`:"",C=(await i.question(`${k}${V}: `)).trim();return C===""?j:C},a=t===""?9:8,c=0,l=()=>(c+=1,c);if(ht(`devctl setup \u2014 ${a} steps`),ht(""),t==="")await s(`${l()}. Repository root`,r);let d=await s(`${l()}. Environment / project name`,Sa(r)),f=await Lt(""),g=await s(`${l()}. Google Cloud project`,f.projectID);if(ht(`${l()}. Authentication`),!f.adcAvailable){if(ht(" ADC is not available. Run: gcloud auth application-default login"),(await s(" Run login now? (y/N)","n")).toLowerCase()==="y")try{await go()}catch(j){ht(` login failed: ${j instanceof Error?j.message:String(j)}`)}}else if(ht(" \u2713 Application Default Credentials available"),f.userEmail!=="")ht(` user: ${f.userEmail}`);let m=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(Ns)),S=Number(v)||Ns,P=await s(`${l()}. Default profile name (optional)`,"");i.close(),Jm(r,d,g,P,{sa:m,audience:x,proxyPort:S}),ht(""),ht(`Wrote starter configuration to ${o}`),ht(`${l()}. Validation`);try{let k=ut(r,""),j=await Un(k);ht(ya(j))}catch(k){ht(` configuration is not valid yet: ${k instanceof Error?k.message:String(k)}`),ht(" edit .devctl/config.yaml and run `devctl config validate`")}}function Jm(e,t,n,r,o={sa:"",audience:"",proxyPort:Ns}){let i=xn(e,".devctl");Id(xn(i,"services"),{recursive:!0}),Id(xn(i,"profiles"),{recursive:!0}),Id(xn(i,"proxy"),{recursive:!0}),s_(xn(i,"config.yaml"),`# yaml-language-server: $schema=https://raw.githubusercontent.com/amr-m-abdelgawad/devctl/main/schema/devctl.config.schema.json
24
+ `}return t}function ka(e){return`${e.join(", ")} changed and only take effect after a full \`devctl down && devctl start\`, not a reload`}function l_(e,t,n){let r={};if(t!==""){let o=e.profiles[t];if(!o)throw L("configuration",`unknown profile "${t}"`);Object.assign(r,o.environment)}if(n.length>0)return{services:qm(e,n),env:r};if(t==="")return{services:Object.keys(e.services),env:r};return{services:qm(e,e.profiles[t]?.services??[]),env:r}}function d_(e){return Object.keys(e.profiles).sort()[0]??""}function Ca(e,t){let n=t.services??[],r=t.profile??"";if(n.length===0&&r===""){if(r=t.activeProfile||d_(e),r==="")throw L(Z,"no profile or services given; pass service names or add a profile")}let o=l_(e,r,n);return{services:o.services,env:o.env,profile:r}}function qm(e,t){let n={},r=[];for(let o of t){if(n[o])continue;if(!e.services[o])throw L("service_not_found",`unknown service "${o}"`);n[o]=!0,r.push(o)}return r}var Hd="STARTING",jt="RUNNING",Er="HEALTHY",So="UNHEALTHY",jd="STOPPING",ko="STOPPED",Kn="FAILED",Mi="RESTARTING",Ct="UNKNOWN",_t="HEALTHY",Ce="UNHEALTHY";var Rr=D(()=>{st();Re()});var Qm={};Ms(Qm,{createStarterConfig:()=>v_,resolveSetupTarget:()=>Ym,runSetup:()=>Vd});import{existsSync as qd,mkdirSync as Ud,statSync as u_,writeFileSync as p_}from"fs";import{createInterface as f_}from"readline/promises";import{stdin as g_,stdout as m_}from"process";import{basename as _a,dirname as Kd,join as xn,resolve as h_}from"path";function Ym(e,t){let n=e===""?process.cwd():e;if(t==="")return{repo:n,cfgPath:xn(n,St,qt)};let r=h_(t);if(!(qd(r)?u_(r).isDirectory():!/\.ya?ml$/i.test(r))){let i=Kd(r);return{repo:_a(i)===St?Kd(i):i,cfgPath:r}}if(_a(r)===St)return{repo:Kd(r),cfgPath:xn(r,qt)};return{repo:r,cfgPath:xn(r,St,qt)}}function v_(e,t=_a(e),n="",r="",o=!1){let i=xn(e,St,qt);if(!o&&qd(i))throw L(Z,`configuration already exists at ${i}; not overwriting`);return Xm(e,t,n,r),i}async function Vd(e,t="",n=!1){let{repo:r,cfgPath:o}=Ym(e,t);if(!n&&qd(o)){ht(`Found existing configuration at ${o}; nothing written.`),ht("Pass --force to overwrite it, or edit it directly.");return}let i=f_({input:g_,output:m_}),s=async(k,j)=>{let V=j!==""?` [${j}]`:"",C=(await i.question(`${k}${V}: `)).trim();return C===""?j:C},a=t===""?9:8,c=0,l=()=>(c+=1,c);if(ht(`devctl setup \u2014 ${a} steps`),ht(""),t==="")await s(`${l()}. Repository root`,r);let d=await s(`${l()}. Environment / project name`,_a(r)),f=await Ot(""),g=await s(`${l()}. Google Cloud project`,f.projectID);if(ht(`${l()}. Authentication`),!f.adcAvailable){if(ht(" ADC is not available. Run: gcloud auth application-default login"),(await s(" Run login now? (y/N)","n")).toLowerCase()==="y")try{await mo()}catch(j){ht(` login failed: ${j instanceof Error?j.message:String(j)}`)}}else if(ht(" \u2713 Application Default Credentials available"),f.userEmail!=="")ht(` user: ${f.userEmail}`);let m=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(Bs)),w=Number(v)||Bs,E=await s(`${l()}. Default profile name (optional)`,"");i.close(),Xm(r,d,g,E,{sa:m,audience:x,proxyPort:w}),ht(""),ht(`Wrote starter configuration to ${o}`),ht(`${l()}. Validation`);try{let k=ut(r,""),j=await Un(k);ht(wa(j))}catch(k){ht(` configuration is not valid yet: ${k instanceof Error?k.message:String(k)}`),ht(" edit .devctl/config.yaml and run `devctl config validate`")}}function Xm(e,t,n,r,o={sa:"",audience:"",proxyPort:Bs}){let i=xn(e,".devctl");Ud(xn(i,"services"),{recursive:!0}),Ud(xn(i,"profiles"),{recursive:!0}),Ud(xn(i,"proxy"),{recursive:!0}),p_(xn(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 ht(e){process.stdout.write(`${e}
72
- `)}var jd=D(()=>{st();Oi();Pe();wr()});var uh={};Ls(uh,{DEFAULT_LOG_PAGE_SIZE:()=>ih,LevelDebug:()=>Vd,LevelError:()=>_a,LevelFatal:()=>Ra,LevelInfo:()=>Jd,LevelTrace:()=>qd,LevelUnknown:()=>Yd,LevelWarn:()=>zd,LogManager:()=>Ea,MAX_LOG_PAGE_SIZE:()=>sh,clampLogPageSize:()=>ah,compileLogSearch:()=>Pa,defaultExportPath:()=>ch,defaultLogParser:()=>Xd,listSessions:()=>Y_,loadSessionEvents:()=>X_,matchLog:()=>Er,openInFileManager:()=>Aa,parseLevel:()=>Qd,parseRequestID:()=>Zd,pruneSessions:()=>dh,resolveExportPath:()=>_o,safeServiceFile:()=>lh,writeLogExport:()=>Ta});import{spawn as Wd}from"child_process";import{createWriteStream as A_,existsSync as Fi,mkdirSync as L_,readdirSync as Kd,readFileSync as D_,rmSync as O_,statSync as Ud,writeFileSync as M_}from"fs";import{homedir as $_}from"os";import{dirname as nh,isAbsolute as I_,join as Tr,resolve as F_}from"path";function Xd(){return{name:"default",parse:(e)=>({level:Qd(e),request_id:Zd(e)||void 0})}}function Qd(e){return H_.find((n)=>n.re.test(e))?.level??Yd}function Zd(e){return N_.exec(e)?.[1]??""}function Er(e,t){if(e.services&&e.services.length>0&&!e.services.includes(t.service))return!1;if(e.level&&(eh[t.level]??2)<(eh[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 n=Pa(e.search);if(n)return n.test(t.message)}return t.message.toLowerCase().includes(e.search.toLowerCase())}function Pa(e){let t=G_(e);if(t===void 0)return;return new RegExp(t)}function G_(e){if(e.length===0||e.length>j_)return;let t={raw:e,i:0,out:[],quantifiers:0,depth:0,lastAtom:"none",groupQuant:[]};if(!rh(t)||t.i!==e.length||t.depth!==0)return;return t.out.join("")}function rh(e){while(e.i<e.raw.length){if(e.raw[e.i]===")")return!0;if(!U_(e))return!1}return!0}function U_(e){let t=e.raw[e.i]??"";if(t==="|")return Ca(e,"|","none");if(t==="^")return Ca(e,"^","none");if(t==="$")return Ca(e,"$","none");if(t===".")return Ca(e,".","atom");if(t==="(")return K_(e);if(t==="[")return V_(e);if(t==="*"||t==="+"||t==="?"||t==="{")return q_(e);if(t==="\\")return oh(e);return e.out.push(RegExp.escape(t)),e.i+=1,e.lastAtom="atom",!0}function Ca(e,t,n){return e.out.push(t),e.i+=1,e.lastAtom=n,!0}function K_(e){if(e.i+=1,e.depth+=1,e.depth>W_)return!1;if(e.groupQuant.push(!1),e.out.push("(?:"),!rh(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 q_(e){let t=e.raw[e.i]??"";if(t==="{"||e.lastAtom==="none"||e.lastAtom==="quant"||e.lastAtom==="quantified-group")return!1;if(e.quantifiers>=B_)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 n=e.groupQuant.length-1;if(n>=0)e.groupQuant[n]=!0;if(e.raw[e.i]==="?")e.out.push("?"),e.i+=1;return e.lastAtom="quant",!0}function V_(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(!oh(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 oh(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 th(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64url")}function z_(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 Gd(e,t){let n={...e};return n[t]=void 0,n}function ah(e){if(!Number.isInteger(e)||(e??0)<=0)return ih;return Math.min(e,sh)}class Ea{events=[];eventStart=0;nextSeq=1;max;bus;detector;persistDir;persist;sessionID;streams=new Map;lastWrite=new Map;parsers=[];constructor(e,t,n,r,o,i,s=0,a=0){this.max=e>0?e:J_,this.bus=t,this.detector=n,this.sessionID=i;let c=o===""||o.startsWith("~/")?$s():o;if(this.persist=r&&i!=="",this.persistDir=this.persist?Tr(c,`${eu}${i}`):"",this.persist)L_(this.persistDir,{recursive:!0,mode:448}),dh(c,s,a)}sessionDir(){return this.persistDir}setParsers(e){this.parsers=e}append(e){let t=this.parseLine(e.message),n={...e,timestamp:e.timestamp||new Date().toISOString(),level:e.level||t.level||Qd(e.message),request_id:e.request_id||t.request_id||Zd(e.message),message:this.detector?this.detector.redactText(e.message):e.message,seq:this.nextSeq++};if(this.events.length<this.max)this.events.push(n);else this.events[this.eventStart]=n,this.eventStart=(this.eventStart+1)%this.max;if(this.bus?.publish(Me(fa,n.service,{event:n,level:n.level})),this.persist){let r=`${n.timestamp} ${n.service} ${n.level} ${n.message}
73
- `,o=lh(n.service),i=this.streamFor(o);this.lastWrite.set(o,new Promise((s)=>{i.write(r,()=>s())}))}}async flush(){await Promise.all([...this.lastWrite.values()])}parseLine(e){let t={};for(let n of this.parsers)try{let r=n.parse(e);if(r)t={...t,...r}}catch{}return t}streamFor(e){let t=this.streams.get(e);if(t===void 0)t=A_(Tr(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((n)=>{if(Er(e,n))t.push(n)}),t}queryPage(e,t={}){let n=ah(t.limit),r=t.cursor?z_(t.cursor):void 0,o=r!==void 0&&r.session!==this.sessionID,i=o?void 0:r,s=i?t.direction??"backward":"backward",a=[];this.forEachEvent((m)=>{if(Er(e,m))a.push(m)});let c;if(!i)c=a.slice(Math.max(0,a.length-n));else if(s==="forward")c=a.filter((m)=>m.seq>i.seq).slice(0,n);else{let m=a.filter((x)=>x.seq<i.seq);c=m.slice(Math.max(0,m.length-n))}let l=c[0]?.seq,d=c[c.length-1]?.seq,f=l!==void 0&&a.some((m)=>m.seq<l),g=d!==void 0&&a.some((m)=>m.seq>d);return{events:c,prevCursor:th({session:this.sessionID,seq:l??i?.seq??0}),nextCursor:th({session:this.sessionID,seq:d??i?.seq??this.nextSeq-1}),hasNext:g,hasPrev:f,sessionChanged:o}}queryFacets(e){let t=Gd(e,"services"),n=Gd(e,"level"),r=Gd(e,"source"),o=0,i={},s={},a={};return this.forEachEvent((c)=>{if(Er(e,c))o+=1;if(Er(t,c))i[c.service]=(i[c.service]??0)+1;if(Er(n,c))s[c.level]=(s[c.level]??0)+1;if(Er(r,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((n)=>{if(e[n.service]=(e[n.service]??0)+1,n.level===_a||n.level===Ra)t+=1}),{total:this.events.length,errors:t,counts:e}}forEachEvent(e){let t=this.events.length;for(let n=0;n<t;n+=1){let r=this.events[(this.eventStart+n)%t];if(r)e(r)}}exportTo(e,t){Ta(e,this.query(t))}}function ch(e=new Date){let t=e.toISOString().replace(/[:.]/g,"-");return Tr(lr(),`devctl-logs-${t}.log`)}function _o(e=""){if(e==="")return ch();let t=e.startsWith("~/")?Tr($_(),e.slice(2)):e;return I_(t)?t:F_(process.cwd(),t)}function Ta(e,t){Yt(nh(e));let n=t.map((r)=>`${r.timestamp} ${r.service} ${r.level} ${r.message}`);M_(e,`${n.join(`
72
+ `)}var Jd=D(()=>{st();Oi();Re();Sr()});var mh={};Ms(mh,{DEFAULT_LOG_PAGE_SIZE:()=>lh,LevelDebug:()=>Ta,LevelError:()=>Ni,LevelFatal:()=>Hi,LevelInfo:()=>Aa,LevelTrace:()=>Pa,LevelUnknown:()=>ji,LevelWarn:()=>La,LogManager:()=>Oa,MAX_LOG_PAGE_SIZE:()=>dh,clampLogPageSize:()=>uh,compileLogSearch:()=>Da,defaultExportPath:()=>ph,defaultLogParser:()=>eu,listSessions:()=>a0,loadSessionEvents:()=>c0,matchLog:()=>Pr,openInFileManager:()=>$a,parseJSONLogLine:()=>tu,parseLevel:()=>nu,parseRequestID:()=>ru,pruneSessions:()=>gh,resolveExportPath:()=>Eo,safeServiceFile:()=>fh,writeLogExport:()=>Ma});import{spawn as Yd}from"child_process";import{createWriteStream as I_,existsSync as Fi,mkdirSync as F_,readdirSync as Zd,readFileSync as N_,rmSync as H_,statSync as Qd,writeFileSync as j_}from"fs";import{homedir as B_}from"os";import{dirname as sh,isAbsolute as W_,join as Tr,resolve as G_}from"path";function eu(){return{name:"default",parse:(e)=>{let t=tu(e);if(t)return t;return{level:nu(e),request_id:ru(e)||void 0}}}}function oh(e,t){for(let n of t){let r=e[n];if(typeof r==="string"&&r.trim()!=="")return r}return}function J_(e){for(let t of K_){let n=e[t];if(typeof n==="number"){let r=V_[n];if(r)return r;continue}if(typeof n==="string"&&n.trim()!=="")return n.toUpperCase()}return}function tu(e){let t=e.trim();if(!t.startsWith("{")||!t.endsWith("}"))return;let n;try{n=JSON.parse(t)}catch{return}if(typeof n!=="object"||n===null||Array.isArray(n))return;let r=n,o=oh(r,U_),i=J_(r),s=oh(r,q_);if(o===void 0&&i===void 0&&s===void 0)return;return{message:o??t,level:i,request_id:s,raw:t}}function nu(e){return Y_.find((n)=>n.re.test(e))?.level??ji}function ru(e){return z_.exec(e)?.[1]??""}function Pr(e,t){if(e.services&&e.services.length>0&&!e.services.includes(t.service))return!1;if(e.level&&(rh[t.level]??2)<(rh[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=Da(e.search);if(r)return r.test(t.message)||t.raw!==void 0&&r.test(t.raw)}let n=e.search.toLowerCase();return t.message.toLowerCase().includes(n)||t.raw!==void 0&&t.raw.toLowerCase().includes(n)}function Da(e){let t=e0(e);if(t===void 0)return;return new RegExp(t)}function e0(e){if(e.length===0||e.length>X_)return;let t={raw:e,i:0,out:[],quantifiers:0,depth:0,lastAtom:"none",groupQuant:[]};if(!ah(t)||t.i!==e.length||t.depth!==0)return;return t.out.join("")}function ah(e){while(e.i<e.raw.length){if(e.raw[e.i]===")")return!0;if(!t0(e))return!1}return!0}function t0(e){let t=e.raw[e.i]??"";if(t==="|")return Ra(e,"|","none");if(t==="^")return Ra(e,"^","none");if(t==="$")return Ra(e,"$","none");if(t===".")return Ra(e,".","atom");if(t==="(")return n0(e);if(t==="[")return o0(e);if(t==="*"||t==="+"||t==="?"||t==="{")return r0(e);if(t==="\\")return ch(e);return e.out.push(RegExp.escape(t)),e.i+=1,e.lastAtom="atom",!0}function Ra(e,t,n){return e.out.push(t),e.i+=1,e.lastAtom=n,!0}function n0(e){if(e.i+=1,e.depth+=1,e.depth>Z_)return!1;if(e.groupQuant.push(!1),e.out.push("(?:"),!ah(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 r0(e){let t=e.raw[e.i]??"";if(t==="{"||e.lastAtom==="none"||e.lastAtom==="quant"||e.lastAtom==="quantified-group")return!1;if(e.quantifiers>=Q_)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 n=e.groupQuant.length-1;if(n>=0)e.groupQuant[n]=!0;if(e.raw[e.i]==="?")e.out.push("?"),e.i+=1;return e.lastAtom="quant",!0}function o0(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(!ch(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 ch(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 ih(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64url")}function s0(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 Xd(e,t){let n={...e};return n[t]=void 0,n}function uh(e){if(!Number.isInteger(e)||(e??0)<=0)return lh;return Math.min(e,dh)}class Oa{events=[];eventStart=0;nextSeq=1;max;bus;detector;persistDir;persist;sessionID;streams=new Map;lastWrite=new Map;parsers=[];constructor(e,t,n,r,o,i,s=0,a=0){this.max=e>0?e:i0,this.bus=t,this.detector=n,this.sessionID=i;let c=o===""||o.startsWith("~/")?Ns():o;if(this.persist=r&&i!=="",this.persistDir=this.persist?Tr(c,`${ou}${i}`):"",this.persist)F_(this.persistDir,{recursive:!0,mode:448}),gh(c,s,a)}sessionDir(){return this.persistDir}setParsers(e){this.parsers=e}append(e){let t=this.parseLine(e.message),n=(s)=>this.detector?this.detector.redactText(s):s,r=t.raw!==void 0,o=n(e.message),i={...e,timestamp:e.timestamp||new Date().toISOString(),level:e.level||t.level||nu(e.message),request_id:e.request_id||t.request_id||ru(e.message),message:r&&t.message!==void 0?n(t.message):o,raw:r?o:void 0,seq:this.nextSeq++};if(this.events.length<this.max)this.events.push(i);else this.events[this.eventStart]=i,this.eventStart=(this.eventStart+1)%this.max;if(this.bus?.publish(Le(ha,i.service,{event:i,level:i.level})),this.persist){let s=`${i.timestamp} ${i.service} ${i.level} ${i.raw??i.message}
73
+ `,a=fh(i.service),c=this.streamFor(a);this.lastWrite.set(a,new Promise((l)=>{c.write(s,()=>l())}))}}async flush(){await Promise.all([...this.lastWrite.values()])}parseLine(e){let t={};for(let n of this.parsers)try{let r=n.parse(e);if(r)t={...t,...r}}catch{}return t}streamFor(e){let t=this.streams.get(e);if(t===void 0)t=I_(Tr(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((n)=>{if(Pr(e,n))t.push(n)}),t}queryPage(e,t={}){let n=uh(t.limit),r=t.cursor?s0(t.cursor):void 0,o=r!==void 0&&r.session!==this.sessionID,i=o?void 0:r,s=i?t.direction??"backward":"backward",a=[];this.forEachEvent((m)=>{if(Pr(e,m))a.push(m)});let c;if(!i)c=a.slice(Math.max(0,a.length-n));else if(s==="forward")c=a.filter((m)=>m.seq>i.seq).slice(0,n);else{let m=a.filter((x)=>x.seq<i.seq);c=m.slice(Math.max(0,m.length-n))}let l=c[0]?.seq,d=c[c.length-1]?.seq,f=l!==void 0&&a.some((m)=>m.seq<l),g=d!==void 0&&a.some((m)=>m.seq>d);return{events:c,prevCursor:ih({session:this.sessionID,seq:l??i?.seq??0}),nextCursor:ih({session:this.sessionID,seq:d??i?.seq??this.nextSeq-1}),hasNext:g,hasPrev:f,sessionChanged:o}}queryFacets(e){let t=Xd(e,"services"),n=Xd(e,"level"),r=Xd(e,"source"),o=0,i={},s={},a={};return this.forEachEvent((c)=>{if(Pr(e,c))o+=1;if(Pr(t,c))i[c.service]=(i[c.service]??0)+1;if(Pr(n,c))s[c.level]=(s[c.level]??0)+1;if(Pr(r,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((n)=>{if(e[n.service]=(e[n.service]??0)+1,n.level===Ni||n.level===Hi)t+=1}),{total:this.events.length,errors:t,counts:e}}forEachEvent(e){let t=this.events.length;for(let n=0;n<t;n+=1){let r=this.events[(this.eventStart+n)%t];if(r)e(r)}}exportTo(e,t){Ma(e,this.query(t))}}function ph(e=new Date){let t=e.toISOString().replace(/[:.]/g,"-");return Tr(dr(),`devctl-logs-${t}.log`)}function Eo(e=""){if(e==="")return ph();let t=e.startsWith("~/")?Tr(B_(),e.slice(2)):e;return W_(t)?t:G_(process.cwd(),t)}function Ma(e,t){Yt(sh(e));let n=t.map((r)=>`${r.timestamp} ${r.service} ${r.level} ${r.raw??r.message}`);j_(e,`${n.join(`
74
74
  `)}
75
- `,{mode:384})}function Aa(e){let t=Fi(e)&&Ud(e).isDirectory()?e:nh(e);if(Yt(t),process.platform==="darwin"){let n=Fi(e)&&Ud(e).isFile()?["-R",e]:[t];Wd("open",n,{detached:!0,stdio:"ignore"}).unref();return}if(process.platform==="win32"){Wd("explorer",[t],{detached:!0,stdio:"ignore"}).unref();return}Wd("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref()}function Y_(e=$s()){if(!Fi(e))return[];return Kd(e).filter((t)=>t.startsWith(eu)).sort().reverse()}function X_(e,t=$s()){let n=Tr(t,e);if(!Fi(n))return[];let r=[];for(let i of Kd(n)){if(!i.endsWith(".log"))continue;let s=D_(Tr(n,i),"utf8");for(let a of s.split(`
76
- `)){if(a.trim()==="")continue;let c=a.split(" ");r.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=r.sort((i,s)=>i.timestamp.localeCompare(s.timestamp));return o.forEach((i,s)=>{i.seq=s+1}),o}function lh(e){let t=e.replace(/[^A-Za-z0-9._-]+/g,"_");return t===""?"service":t}function dh(e,t,n){if(!Fi(e))return;let r=Kd(e).filter((i)=>i.startsWith(eu)).map((i)=>{let s=Tr(e,i),a=Ud(s);return{path:s,mtime:a.mtimeMs}}).sort((i,s)=>s.mtime-i.mtime),o=t>0?Date.now()-t*86400000:0;r.forEach((i,s)=>{let a=o>0&&i.mtime<o,c=n>0&&s>=n;if(a||c)O_(i.path,{recursive:!0,force:!0})})}var qd="TRACE",Vd="DEBUG",Jd="INFO",zd="WARN",_a="ERROR",Ra="FATAL",Yd="UNKNOWN",eh,N_,H_,j_=200,B_=8,W_=2,J_=50000,eu="session-",ih=500,sh=5000;var Ar=D(()=>{ze();eh={[qd]:0,[Vd]:1,[Jd]:2,[zd]:3,[_a]:4,[Ra]:5,[Yd]:2};N_=/(?:x-devctl-request-id|request[_-]?id)[=: ]+([A-Za-z0-9-]+)/i,H_=[{re:/\b(fatal|critical)\b/i,level:Ra},{re:/\b(error|err)\b/i,level:_a},{re:/\b(warn|warning)\b/i,level:zd},{re:/\b(debug|dbg)\b/i,level:Vd},{re:/\b(trace)\b/i,level:qd},{re:/\b(info|information)\b/i,level:Jd}]});class qt{nameMarkers;patterns;constructor(e,t){this.nameMarkers=[...jh,...e],this.patterns=t.flatMap((n)=>{try{return[new RegExp(n)]}catch{return[]}})}update(e,t){this.nameMarkers=[...jh,...e],this.patterns=t.flatMap((n)=>{try{return[new RegExp(n)]}catch{return[]}})}isSecretName(e){let t=e.toUpperCase();return this.nameMarkers.some((n)=>t.includes(n.toUpperCase()))}redactValue(e,t){if(t==="")return t;if(this.isSecretName(e))return"********";if(this.patterns.some((n)=>n.test(t)))return"********";return t}redactMap(e){let t={};for(let[n,r]of Object.entries(e))t[n]=this.redactValue(n,r);return t}redactText(e){if(e==="")return e;let t=e;for(let n of this.patterns)t=t.replace(n,"********");return P0(t)}}function P0(e){let t=e.toLowerCase(),n="authorization: bearer ",r=t.indexOf("authorization: bearer ");if(r>=0)return Bh(e,r+22);let o=t.indexOf("bearer ");if(o<0)return e;return Bh(e,o+7)}function Bh(e,t){let n=t;while(n<e.length&&!E0(e[n]??""))n+=1;return e.slice(0,t)+"********"+e.slice(n)}function E0(e){return e===" "||e==="\t"||e===`
77
- `||e==="\r"}var jh;var To=D(()=>{jh=["PASSWORD","SECRET","TOKEN","PRIVATE_KEY","CLIENT_SECRET","API_KEY","CREDENTIAL","ACCESS_KEY","AUTH_KEY"]});var Fa;var Wh=D(()=>{Fa={procedure:`---
75
+ `,{mode:384})}function $a(e){let t=Fi(e)&&Qd(e).isDirectory()?e:sh(e);if(Yt(t),process.platform==="darwin"){let n=Fi(e)&&Qd(e).isFile()?["-R",e]:[t];Yd("open",n,{detached:!0,stdio:"ignore"}).unref();return}if(process.platform==="win32"){Yd("explorer",[t],{detached:!0,stdio:"ignore"}).unref();return}Yd("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref()}function a0(e=Ns()){if(!Fi(e))return[];return Zd(e).filter((t)=>t.startsWith(ou)).sort().reverse()}function c0(e,t=Ns()){let n=Tr(t,e);if(!Fi(n))return[];let r=[];for(let i of Zd(n)){if(!i.endsWith(".log"))continue;let s=N_(Tr(n,i),"utf8");for(let a of s.split(`
76
+ `)){if(a.trim()==="")continue;let c=a.split(" "),l=c.slice(3).join(" "),d=tu(l);r.push({timestamp:c[0]??"",service:c[1]??i.replace(/\.log$/,""),source:"history",level:c[2]??"INFO",message:d?.message??l,raw:d?l:void 0,pid:0,seq:0})}}let o=r.sort((i,s)=>i.timestamp.localeCompare(s.timestamp));return o.forEach((i,s)=>{i.seq=s+1}),o}function fh(e){let t=e.replace(/[^A-Za-z0-9._-]+/g,"_");return t===""?"service":t}function gh(e,t,n){if(!Fi(e))return;let r=Zd(e).filter((i)=>i.startsWith(ou)).map((i)=>{let s=Tr(e,i),a=Qd(s);return{path:s,mtime:a.mtimeMs}}).sort((i,s)=>s.mtime-i.mtime),o=t>0?Date.now()-t*86400000:0;r.forEach((i,s)=>{let a=o>0&&i.mtime<o,c=n>0&&s>=n;if(a||c)H_(i.path,{recursive:!0,force:!0})})}var Pa="TRACE",Ta="DEBUG",Aa="INFO",La="WARN",Ni="ERROR",Hi="FATAL",ji="UNKNOWN",rh,U_,K_,q_,V_,z_,Y_,X_=200,Q_=8,Z_=2,i0=50000,ou="session-",lh=500,dh=5000;var Ar=D(()=>{ze();rh={[Pa]:0,[Ta]:1,[Aa]:2,[La]:3,[Ni]:4,[Hi]:5,[ji]:2};U_=["message","msg","text","log","event"],K_=["level","severity","levelname","loglevel","lvl"],q_=["request_id","requestId","trace_id","traceId","correlation_id","correlationId"],V_={10:Pa,20:Ta,30:Aa,40:La,50:Ni,60:Hi};z_=/(?:x-devctl-request-id|request[_-]?id)[=: ]+([A-Za-z0-9-]+)/i,Y_=[{re:/\b(fatal|critical)\b/i,level:Hi},{re:/\b(error|err)\b/i,level:Ni},{re:/\b(warn|warning)\b/i,level:La},{re:/\b(debug|dbg)\b/i,level:Ta},{re:/\b(trace)\b/i,level:Pa},{re:/\b(info|information)\b/i,level:Aa}]});class Vt{nameMarkers;patterns;constructor(e,t){this.nameMarkers=[...Uh,...e],this.patterns=t.flatMap((n)=>{try{return[new RegExp(n)]}catch{return[]}})}update(e,t){this.nameMarkers=[...Uh,...e],this.patterns=t.flatMap((n)=>{try{return[new RegExp(n)]}catch{return[]}})}isSecretName(e){let t=e.toUpperCase();return this.nameMarkers.some((n)=>t.includes(n.toUpperCase()))}redactValue(e,t){if(t==="")return t;if(this.isSecretName(e))return"********";if(this.patterns.some((n)=>n.test(t)))return"********";return t}redactMap(e){let t={};for(let[n,r]of Object.entries(e))t[n]=this.redactValue(n,r);return t}redactText(e){if(e==="")return e;let t=e;for(let n of this.patterns)t=t.replace(n,"********");return N0(t)}}function N0(e){let t=e.toLowerCase(),n="authorization: bearer ",r=t.indexOf("authorization: bearer ");if(r>=0)return Kh(e,r+22);let o=t.indexOf("bearer ");if(o<0)return e;return Kh(e,o+7)}function Kh(e,t){let n=t;while(n<e.length&&!H0(e[n]??""))n+=1;return e.slice(0,t)+"********"+e.slice(n)}function H0(e){return e===" "||e==="\t"||e===`
77
+ `||e==="\r"}var Uh;var Ao=D(()=>{Uh=["PASSWORD","SECRET","TOKEN","PRIVATE_KEY","CLIENT_SECRET","API_KEY","CREDENTIAL","ACCESS_KEY","AUTH_KEY"]});var Wa;var qh=D(()=>{Wa={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
  ---
@@ -607,32 +607,32 @@ Rules for turning that into YAML:
607
607
  a full one. Remember that a bare \`devctl start\` falls back to the first
608
608
  configured profile, and the TUI's default is the first profile
609
609
  alphabetically \u2014 so name them with that in mind.
610
- `}});import{existsSync as T0,readFileSync as A0}from"fs";function Kn(e,t){return!(t??[]).includes(e)}function Gh(e){return Ha.filter((t)=>Kn(t.name,e))}function ja(e){return Ha.some((t)=>t.name===e)}function Ba(e){return new qt(e.secrets.extra_markers,e.secrets.extra_patterns)}function Uh(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 D0(e,t){let n=e.config(),r=n.services[t];if(!r)throw Error(`unknown service ${t}`);let i=e.status().services[t],s=Ba(n);return{name:t,state:i?.state,health:i?.health,pid:i?.pid,last_error:i?.last_error,command:r.command.args,cwd:r.working_dir,ports:i?.ports??Object.fromEntries(r.ports.map((a)=>[a.name,a.value])),environment:s.redactMap({...r.environment.defaults,...r.environment.vars}),container:r.container?{...r.container,env:s.redactMap(r.container.env)}:void 0}}function Kh(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 qh(e,t){let n=typeof t.service==="string"?t.service:"",r=typeof t.since==="string"?t.since:"",o=typeof t.cursor==="string"?t.cursor:void 0,i=await e.logsPage({services:n===""?[]:[n],level:typeof t.level==="string"?t.level:"",search:typeof t.search==="string"?t.search:"",source:typeof t.source==="string"?t.source:"",since:r,until:typeof t.until==="string"?t.until:"",cursor:o,direction:o?"forward":void 0,limit:L0}),s=Ba(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??r,next_cursor:i.nextCursor,session_changed:i.sessionChanged}}function O0(e){return Object.entries(e.profiles).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>({name:t,services:n.services}))}function Vh(e){let t=Object.entries(e.services).map(([n,r])=>({name:n,description:r.description,command:r.command.args,cwd:r.working_dir,ports:r.ports.map((o)=>({name:o.name,value:o.auto?0:o.value,auto:o.auto})),dependencies:r.dependencies,container:r.container?{image:r.container.image,runtime:r.container.runtime||"docker",ports:r.container.ports,volumes:r.container.volumes}:void 0}));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((n)=>({name:n.name,match:n.match,upstream:n.upstream.url,auth:n.auth.type}))}}}function M0(e){let t=Ba(e);return{entries:hr(e).map((n)=>{let r=typeof n.value==="string"?n.value:JSON.stringify(n.value);return{...n,value:t.redactMap({[n.path]:r})[n.path]}})}}function Na(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}async function Jh(e,t,n){switch(t){case"list_services":return Uh(e.status());case"get_service":if(typeof n.name!=="string"||n.name==="")throw Error("name is required");return D0(e,n.name);case"get_status":return Kh(e.status());case"get_logs":return qh(e,n);case"list_profiles":return O0(e.config());case"get_config":return Vh(e.config());case"get_config_sources":return M0(e.config());case"run_doctor":return e.doctor();case"start_services":return e.start({services:Na(n.services),profile:typeof n.profile==="string"?n.profile:""});case"stop_services":return await e.stop(Na(n.services)),{ok:!0};case"restart_services":return await e.restart(Na(n.services),n.cascade===!0),{ok:!0};case"reload_config":return e.reload();case"exec_service":{if(typeof n.service!=="string"||n.service==="")throw Error("service is required");if(!e.exec)throw Error("exec is unavailable");let r=await e.exec(n.service,Na(n.command),n.print_env===!0),o=Ba(e.config());return{...r,stdout:o.redactText(r.stdout),stderr:o.redactText(r.stderr),environment:r.environment?o.redactMap(r.environment):void 0}}case"get_setup_guide":return $0(n);case"validate_config":return I0(e,n);default:throw Error(`unknown tool ${t}`)}}function $0(e){let t=typeof e.section==="string"?e.section:"procedure",n=t in Fa?t:"procedure";return{section:n,text:Fa[n],sections:Object.keys(Fa)}}function I0(e,t){let n=e.config();if(typeof t.text==="string"){let o=ao(n.repoRoot,n.configPath,t.text);return{valid:o.length===0,issues:o,source:"candidate",config_path:n.configPath}}if(!T0(n.configPath))return{valid:!1,issues:[`no configuration at ${n.configPath}`],source:"disk",config_path:n.configPath,setup_mode:!0};let r=ao(n.repoRoot,n.configPath,A0(n.configPath,"utf8"));return{valid:r.length===0,issues:r,source:"disk",config_path:n.configPath}}function zh(e){return au.includes(e)}async function Yh(e,t){switch(t){case"devctl://status":return Kh(e.status());case"devctl://services":return Uh(e.status());case"devctl://logs":return qh(e,{});case"devctl://config":return Vh(e.config());case"devctl://doctor":return e.doctor();default:throw Error(`unknown resource ${t}`)}}var L0=200,au,cu,Ha;var ji=D(()=>{st();To();Wh();au=["devctl://status","devctl://services","devctl://logs","devctl://config","devctl://doctor"],cu=["inspect","logs","diagnostics","control","setup"],Ha=[{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:"get_config_sources",label:"Config sources",summary:"Winning and shadowed config sources",category:"inspect",description:"List effective configuration values with their winning source/layer and any shadowed sources. Secret-like values are redacted.",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:"exec_service",label:"Execute in service",summary:"Run a command in a resolved service context",category:"control",mutates:!0,description:"Run an arbitrary command with a service's fully resolved environment and working directory, whether or not it is running. Output and print_env values are redacted.",inputSchema:{type:"object",properties:{service:{type:"string"},command:{type:"array",items:{type:"string"}},print_env:{type:"boolean",description:"Return the resolved environment without executing a command"}},required:["service"],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 Or(e){if(!Number.isInteger(e))return du;return Math.min(rv,Math.max(J0,e))}function ov(e,t){if(t.length!==1||t<"0"||t>"9")return e;if(e.length>=z0)return t;return`${e}${t}`}function iv(e){return e.slice(0,-1)}function sv(e,t){if(e==="")return Or(t);let n=Number(e);if(!Number.isInteger(n))return Or(t);return Or(n)}function Lo(e){let t=Number.parseInt(vn(e).slice(0,q0),16),n=Number.isFinite(t)?t%nv:0;return du+n}function av(e,t){return t===Lo(e)}async function cv(e,t){let n=Number.isInteger(t)&&(t??0)>0?t:Lo(e);for(let r=0;r<V0;r+=1){let o=n+r;if(o>rv)break;if(await ho(o))return o}throw L(ee,`no free MCP port starting at ${n}`)}var du=18700,nv=600,kM,q0=8,V0=600,rv=65535,J0=1024,z0=5;var Ga=D(()=>{Pe();Pi();ze();kM=du+nv-1});import{existsSync as Va,readFileSync as Ua}from"fs";import{dirname as Y0,isAbsolute as lv,join as qa,resolve as X0}from"path";function bn(){return process.platform==="darwin"?"cmd+c":"ctrl+shift+c"}function rR(){return{theme:"devctl",leader_timeout:Ja,font_size:$r,keybinds:{...nR},scroll_speed:Q0,scroll_acceleration:{enabled:!1},diff_style:"auto",cursor:{style:"block",blinking:!0},mouse:!0,attention:{enabled:!1,notifications:!0,sound:!0,volume:Z0,sound_pack:"default",sounds:{}},log_timestamps:!0,log_metadata:!0,mcp_enabled:!1}}function za(){return qa(Ft(),"tui.json")}function Ui(e=""){for(let t of[eR,tR]){let n=process.env[t];if(!n||n==="")continue;let r=lv(n)?n:X0(e||process.cwd(),n);if(Va(r))return r}return}function oR(e,t){if(!t||Object.keys(t).length===0)return e;return{...e,keybinds:{...e.keybinds,...t}}}function Qt(e,t){let n=oR(rR(),t),r=Ui(e);if(r)return uu(n,Ka(Ua(r,"utf8")),r);let o=iR(e),i=o?uu(n,Ka(Ua(o,"utf8")),o):n,s=za();if(!Va(s)||o===s)return i;return uu(i,Ka(Ua(s,"utf8")),s)}function dv(e){let t=za(),n={};if(Va(t)){let o=Ka(Ua(t,"utf8"));if(Mr(o))n=o}let r={...n};if(e.theme!==void 0)r.theme=e.theme;if(e.mouse!==void 0)r.mouse=e.mouse;if(e.leader_timeout!==void 0)r.leader_timeout=e.leader_timeout;if(e.font_size!==void 0)r.font_size=e.font_size;if(e.log_timestamps!==void 0)r.log_timestamps=e.log_timestamps;if(e.log_metadata!==void 0)r.log_metadata=e.log_metadata;if(e.mcp_enabled!==void 0)r.mcp_enabled=e.mcp_enabled;if(e.mcp_port===null)delete r.mcp_port;else if(e.mcp_port!==void 0)r.mcp_port=e.mcp_port;if(e.mcp_disabled_tools!==void 0)r.mcp_disabled_tools=e.mcp_disabled_tools;return Gt(t,`${JSON.stringify(r,null,2)}
611
- `),t}function iR(e){let t=Ui(e);if(t)return t;let n=[e||process.cwd(),qa(e||process.cwd(),".devctl"),Ft()],r=["tui.json","tui.jsonc"];for(let o of n)for(let i of r){let s=qa(o,i);if(Va(s))return s}return}function uu(e,t,n){let r=Mr(t)?t:{},o={...e.keybinds};if(Mr(r.keybinds)){for(let[c,l]of Object.entries(r.keybinds))if(typeof l==="string")o[c]=l}let i={...e.cursor};if(Mr(r.cursor)){if(aR(r.cursor.style))i.style=r.cursor.style;if(typeof r.cursor.blinking==="boolean")i.blinking=r.cursor.blinking}let s={...e.scroll_acceleration};if(Mr(r.scroll_acceleration)&&typeof r.scroll_acceleration.enabled==="boolean")s.enabled=r.scroll_acceleration.enabled;let a={...e.attention,sounds:{...e.attention.sounds}};if(Mr(r.attention)){if(typeof r.attention.enabled==="boolean")a.enabled=r.attention.enabled;if(typeof r.attention.notifications==="boolean")a.notifications=r.attention.notifications;if(typeof r.attention.sound==="boolean")a.sound=r.attention.sound;if(typeof r.attention.volume==="number")a.volume=r.attention.volume;if(typeof r.attention.sound_pack==="string")a.sound_pack=r.attention.sound_pack;if(Mr(r.attention.sounds)){for(let[c,l]of Object.entries(r.attention.sounds))if(typeof l==="string")a.sounds[c]=sR(l,n)}}return{theme:typeof r.theme==="string"?r.theme:e.theme,leader_timeout:typeof r.leader_timeout==="number"?r.leader_timeout:e.leader_timeout,font_size:typeof r.font_size==="number"&&Number.isFinite(r.font_size)?Math.round(r.font_size):e.font_size,keybinds:o,scroll_speed:typeof r.scroll_speed==="number"?r.scroll_speed:e.scroll_speed,scroll_acceleration:s,diff_style:r.diff_style==="stacked"?"stacked":"auto",cursor:i,mouse:typeof r.mouse==="boolean"?r.mouse:e.mouse,attention:a,log_timestamps:typeof r.log_timestamps==="boolean"?r.log_timestamps:e.log_timestamps,log_metadata:typeof r.log_metadata==="boolean"?r.log_metadata:e.log_metadata,mcp_enabled:typeof r.mcp_enabled==="boolean"?r.mcp_enabled:e.mcp_enabled,mcp_port:typeof r.mcp_port==="number"&&Number.isInteger(r.mcp_port)?r.mcp_port:e.mcp_port,mcp_disabled_tools:Array.isArray(r.mcp_disabled_tools)?r.mcp_disabled_tools.filter((c)=>typeof c==="string"):e.mcp_disabled_tools,path:n}}function sR(e,t){if(e.startsWith("file://")||lv(e))return e;return qa(Y0(t),e)}function aR(e){return e==="block"||e==="underline"||e==="line"||e==="default"}function Mr(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Ka(e){let t=e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"");return JSON.parse(t)}function cR(e){if(e===""||e==="none")return[];return e.split(",").flatMap((t)=>{let n=t.trim();if(n===""||n==="none"||/\s/.test(n))return[];let r=n.toLowerCase().split("+"),o=r[r.length-1]??"";return[{name:o==="return"?"return":o,ctrl:r.includes("ctrl")||r.includes("control"),shift:r.includes("shift"),meta:r.includes("meta")||r.includes("cmd")||r.includes("super"),alt:r.includes("alt")||r.includes("option")}]})}function wn(e,t){return cR(t).some((r)=>(e.name??"").toLowerCase()===r.name&&Boolean(e.ctrl)===r.ctrl&&Boolean(e.shift)===r.shift&&Boolean(e.meta||e.super)===r.meta&&Boolean(e.option??e.alt)===r.alt)}var Ja=2000,$r=14,Q0=3,Z0=0.4,eR="DEVCTL_TUI_CONFIG",tR="OPENCODE_TUI_CONFIG",nR;var Zt=D(()=>{ze();nR={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:bn()}});function Do(e){return`http://127.0.0.1:${e}/mcp`}function mu(e){if(e==="")return{};return{Authorization:`Bearer ${e}`}}function hu(e,t){return JSON.stringify({mcpServers:{devctl:{type:"http",url:e,headers:mu(t)}}},null,2)}function vu(e,t){return JSON.stringify({mcpServers:{devctl:{url:e,headers:mu(t)}}},null,2)}function yu(e,t){return JSON.stringify({mcp:{devctl:{type:"remote",url:e,headers:mu(t),enabled:!0}}},null,2)}function xu(e,t){let n=t===""?"":`
610
+ `}});import{existsSync as j0,readFileSync as B0}from"fs";function qn(e,t){return!(t??[]).includes(e)}function Vh(e){return Ua.filter((t)=>qn(t.name,e))}function Ka(e){return Ua.some((t)=>t.name===e)}function qa(e){return new Vt(e.secrets.extra_markers,e.secrets.extra_patterns)}function Jh(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 G0(e,t){let n=e.config(),r=n.services[t];if(!r)throw Error(`unknown service ${t}`);let i=e.status().services[t],s=qa(n);return{name:t,state:i?.state,health:i?.health,pid:i?.pid,last_error:i?.last_error,command:r.command.args,cwd:r.working_dir,ports:i?.ports??Object.fromEntries(r.ports.map((a)=>[a.name,a.value])),environment:s.redactMap({...r.environment.defaults,...r.environment.vars}),container:r.container?{...r.container,env:s.redactMap(r.container.env)}:void 0}}function zh(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 Yh(e,t){let n=typeof t.service==="string"?t.service:"",r=typeof t.since==="string"?t.since:"",o=typeof t.cursor==="string"?t.cursor:void 0,i=await e.logsPage({services:n===""?[]:[n],level:typeof t.level==="string"?t.level:"",search:typeof t.search==="string"?t.search:"",source:typeof t.source==="string"?t.source:"",since:r,until:typeof t.until==="string"?t.until:"",cursor:o,direction:o?"forward":void 0,limit:W0}),s=qa(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??r,next_cursor:i.nextCursor,session_changed:i.sessionChanged}}function U0(e){return Object.entries(e.profiles).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>({name:t,services:n.services}))}function Xh(e){let t=Object.entries(e.services).map(([n,r])=>({name:n,description:r.description,command:r.command.args,cwd:r.working_dir,ports:r.ports.map((o)=>({name:o.name,value:o.auto?0:o.value,auto:o.auto})),dependencies:r.dependencies,container:r.container?{image:r.container.image,runtime:r.container.runtime||"docker",ports:r.container.ports,volumes:r.container.volumes}:void 0}));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((n)=>({name:n.name,match:n.match,upstream:n.upstream.url,auth:n.auth.type}))}}}function K0(e){let t=qa(e);return{entries:vr(e).map((n)=>{let r=typeof n.value==="string"?n.value:JSON.stringify(n.value);return{...n,value:t.redactMap({[n.path]:r})[n.path]}})}}function Ga(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}async function Qh(e,t,n){switch(t){case"list_services":return Jh(e.status());case"get_service":if(typeof n.name!=="string"||n.name==="")throw Error("name is required");return G0(e,n.name);case"get_status":return zh(e.status());case"get_logs":return Yh(e,n);case"list_profiles":return U0(e.config());case"get_config":return Xh(e.config());case"get_config_sources":return K0(e.config());case"run_doctor":return e.doctor();case"start_services":return e.start({services:Ga(n.services),profile:typeof n.profile==="string"?n.profile:""});case"stop_services":return await e.stop(Ga(n.services)),{ok:!0};case"restart_services":return await e.restart(Ga(n.services),n.cascade===!0),{ok:!0};case"reload_config":return e.reload();case"exec_service":{if(typeof n.service!=="string"||n.service==="")throw Error("service is required");if(!e.exec)throw Error("exec is unavailable");let r=await e.exec(n.service,Ga(n.command),n.print_env===!0),o=qa(e.config());return{...r,stdout:o.redactText(r.stdout),stderr:o.redactText(r.stderr),environment:r.environment?o.redactMap(r.environment):void 0}}case"get_setup_guide":return q0(n);case"validate_config":return V0(e,n);default:throw Error(`unknown tool ${t}`)}}function q0(e){let t=typeof e.section==="string"?e.section:"procedure",n=t in Wa?t:"procedure";return{section:n,text:Wa[n],sections:Object.keys(Wa)}}function V0(e,t){let n=e.config();if(typeof t.text==="string"){let o=co(n.repoRoot,n.configPath,t.text);return{valid:o.length===0,issues:o,source:"candidate",config_path:n.configPath}}if(!j0(n.configPath))return{valid:!1,issues:[`no configuration at ${n.configPath}`],source:"disk",config_path:n.configPath,setup_mode:!0};let r=co(n.repoRoot,n.configPath,B0(n.configPath,"utf8"));return{valid:r.length===0,issues:r,source:"disk",config_path:n.configPath}}function Zh(e){return uu.includes(e)}async function ev(e,t){switch(t){case"devctl://status":return zh(e.status());case"devctl://services":return Jh(e.status());case"devctl://logs":return Yh(e,{});case"devctl://config":return Xh(e.config());case"devctl://doctor":return e.doctor();default:throw Error(`unknown resource ${t}`)}}var W0=200,uu,pu,Ua;var Gi=D(()=>{st();Ao();qh();uu=["devctl://status","devctl://services","devctl://logs","devctl://config","devctl://doctor"],pu=["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:"get_config_sources",label:"Config sources",summary:"Winning and shadowed config sources",category:"inspect",description:"List effective configuration values with their winning source/layer and any shadowed sources. Secret-like values are redacted.",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:"exec_service",label:"Execute in service",summary:"Run a command in a resolved service context",category:"control",mutates:!0,description:"Run an arbitrary command with a service's fully resolved environment and working directory, whether or not it is running. Output and print_env values are redacted.",inputSchema:{type:"object",properties:{service:{type:"string"},command:{type:"array",items:{type:"string"}},print_env:{type:"boolean",description:"Return the resolved environment without executing a command"}},required:["service"],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 Or(e){if(!Number.isInteger(e))return gu;return Math.min(av,Math.max(iE,e))}function cv(e,t){if(t.length!==1||t<"0"||t>"9")return e;if(e.length>=sE)return t;return`${e}${t}`}function lv(e){return e.slice(0,-1)}function dv(e,t){if(e==="")return Or(t);let n=Number(e);if(!Number.isInteger(n))return Or(t);return Or(n)}function Do(e){let t=Number.parseInt(vn(e).slice(0,rE),16),n=Number.isFinite(t)?t%sv:0;return gu+n}function uv(e,t){return t===Do(e)}async function pv(e,t){let n=Number.isInteger(t)&&(t??0)>0?t:Do(e);for(let r=0;r<oE;r+=1){let o=n+r;if(o>av)break;if(await vo(o))return o}throw L(Z,`no free MCP port starting at ${n}`)}var gu=18700,sv=600,AM,rE=8,oE=600,av=65535,iE=1024,sE=5;var Ja=D(()=>{Re();Ri();ze();AM=gu+sv-1});import{existsSync as Qa,readFileSync as za}from"fs";import{dirname as aE,isAbsolute as fv,join as Xa,resolve as cE}from"path";function bn(){return process.platform==="darwin"?"cmd+c":"ctrl+shift+c"}function gE(){return{theme:"devctl",leader_timeout:Za,font_size:$r,keybinds:{...fE},scroll_speed:lE,scroll_acceleration:{enabled:!1},diff_style:"auto",cursor:{style:"block",blinking:!0},mouse:!0,attention:{enabled:!1,notifications:!0,sound:!0,volume:dE,sound_pack:"default",sounds:{}},log_timestamps:!0,log_metadata:!0,mcp_enabled:!1}}function ec(){return Xa(Nt(),"tui.json")}function Vi(e=""){for(let t of[uE,pE]){let n=process.env[t];if(!n||n==="")continue;let r=fv(n)?n:cE(e||process.cwd(),n);if(Qa(r))return r}return}function mE(e,t){if(!t||Object.keys(t).length===0)return e;return{...e,keybinds:{...e.keybinds,...t}}}function Qt(e,t){let n=mE(gE(),t),r=Vi(e);if(r)return mu(n,Ya(za(r,"utf8")),r);let o=hE(e),i=o?mu(n,Ya(za(o,"utf8")),o):n,s=ec();if(!Qa(s)||o===s)return i;return mu(i,Ya(za(s,"utf8")),s)}function gv(e){let t=ec(),n={};if(Qa(t)){let o=Ya(za(t,"utf8"));if(Mr(o))n=o}let r={...n};if(e.theme!==void 0)r.theme=e.theme;if(e.mouse!==void 0)r.mouse=e.mouse;if(e.leader_timeout!==void 0)r.leader_timeout=e.leader_timeout;if(e.font_size!==void 0)r.font_size=e.font_size;if(e.log_timestamps!==void 0)r.log_timestamps=e.log_timestamps;if(e.log_metadata!==void 0)r.log_metadata=e.log_metadata;if(e.mcp_enabled!==void 0)r.mcp_enabled=e.mcp_enabled;if(e.mcp_port===null)delete r.mcp_port;else if(e.mcp_port!==void 0)r.mcp_port=e.mcp_port;if(e.mcp_disabled_tools!==void 0)r.mcp_disabled_tools=e.mcp_disabled_tools;return Ut(t,`${JSON.stringify(r,null,2)}
611
+ `),t}function hE(e){let t=Vi(e);if(t)return t;let n=[e||process.cwd(),Xa(e||process.cwd(),".devctl"),Nt()],r=["tui.json","tui.jsonc"];for(let o of n)for(let i of r){let s=Xa(o,i);if(Qa(s))return s}return}function mu(e,t,n){let r=Mr(t)?t:{},o={...e.keybinds};if(Mr(r.keybinds)){for(let[c,l]of Object.entries(r.keybinds))if(typeof l==="string")o[c]=l}let i={...e.cursor};if(Mr(r.cursor)){if(yE(r.cursor.style))i.style=r.cursor.style;if(typeof r.cursor.blinking==="boolean")i.blinking=r.cursor.blinking}let s={...e.scroll_acceleration};if(Mr(r.scroll_acceleration)&&typeof r.scroll_acceleration.enabled==="boolean")s.enabled=r.scroll_acceleration.enabled;let a={...e.attention,sounds:{...e.attention.sounds}};if(Mr(r.attention)){if(typeof r.attention.enabled==="boolean")a.enabled=r.attention.enabled;if(typeof r.attention.notifications==="boolean")a.notifications=r.attention.notifications;if(typeof r.attention.sound==="boolean")a.sound=r.attention.sound;if(typeof r.attention.volume==="number")a.volume=r.attention.volume;if(typeof r.attention.sound_pack==="string")a.sound_pack=r.attention.sound_pack;if(Mr(r.attention.sounds)){for(let[c,l]of Object.entries(r.attention.sounds))if(typeof l==="string")a.sounds[c]=vE(l,n)}}return{theme:typeof r.theme==="string"?r.theme:e.theme,leader_timeout:typeof r.leader_timeout==="number"?r.leader_timeout:e.leader_timeout,font_size:typeof r.font_size==="number"&&Number.isFinite(r.font_size)?Math.round(r.font_size):e.font_size,keybinds:o,scroll_speed:typeof r.scroll_speed==="number"?r.scroll_speed:e.scroll_speed,scroll_acceleration:s,diff_style:r.diff_style==="stacked"?"stacked":"auto",cursor:i,mouse:typeof r.mouse==="boolean"?r.mouse:e.mouse,attention:a,log_timestamps:typeof r.log_timestamps==="boolean"?r.log_timestamps:e.log_timestamps,log_metadata:typeof r.log_metadata==="boolean"?r.log_metadata:e.log_metadata,mcp_enabled:typeof r.mcp_enabled==="boolean"?r.mcp_enabled:e.mcp_enabled,mcp_port:typeof r.mcp_port==="number"&&Number.isInteger(r.mcp_port)?r.mcp_port:e.mcp_port,mcp_disabled_tools:Array.isArray(r.mcp_disabled_tools)?r.mcp_disabled_tools.filter((c)=>typeof c==="string"):e.mcp_disabled_tools,path:n}}function vE(e,t){if(e.startsWith("file://")||fv(e))return e;return Xa(aE(t),e)}function yE(e){return e==="block"||e==="underline"||e==="line"||e==="default"}function Mr(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Ya(e){let t=e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,"");return JSON.parse(t)}function xE(e){if(e===""||e==="none")return[];return e.split(",").flatMap((t)=>{let n=t.trim();if(n===""||n==="none"||/\s/.test(n))return[];let r=n.toLowerCase().split("+"),o=r[r.length-1]??"";return[{name:o==="return"?"return":o,ctrl:r.includes("ctrl")||r.includes("control"),shift:r.includes("shift"),meta:r.includes("meta")||r.includes("cmd")||r.includes("super"),alt:r.includes("alt")||r.includes("option")}]})}function wn(e,t){return xE(t).some((r)=>(e.name??"").toLowerCase()===r.name&&Boolean(e.ctrl)===r.ctrl&&Boolean(e.shift)===r.shift&&Boolean(e.meta||e.super)===r.meta&&Boolean(e.option??e.alt)===r.alt)}var Za=2000,$r=14,lE=3,dE=0.4,uE="DEVCTL_TUI_CONFIG",pE="OPENCODE_TUI_CONFIG",fE;var Zt=D(()=>{ze();fE={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:bn()}});function Oo(e){return`http://127.0.0.1:${e}/mcp`}function xu(e){if(e==="")return{};return{Authorization:`Bearer ${e}`}}function bu(e,t){return JSON.stringify({mcpServers:{devctl:{type:"http",url:e,headers:xu(t)}}},null,2)}function wu(e,t){return JSON.stringify({mcpServers:{devctl:{url:e,headers:xu(t)}}},null,2)}function Su(e,t){return JSON.stringify({mcp:{devctl:{type:"remote",url:e,headers:xu(t),enabled:!0}}},null,2)}function ku(e,t){let n=t===""?"":`
612
612
  http_headers = { Authorization = "Bearer ${t}" }`;return`[mcp_servers.devctl]
613
613
  url = "${e}"${n}
614
- `}function TR(e){return`codex mcp add --url ${e}`}function Ki(e,t){return[{kind:"claude",title:"Claude",path:".mcp.json",language:"json",text:hu(e,t),hint:"claude mcp add-json"},{kind:"cursor",title:"Cursor",path:".cursor/mcp.json",language:"json",text:vu(e,t)},{kind:"kilo",title:"Kilo Code",path:"kilo.jsonc",language:"json",text:yu(e,t)},{kind:"codex",title:"Codex",path:"~/.codex/config.toml",language:"toml",text:xu(e,t),hint:TR(e)}]}function mv(e,t){let n=[`URL ${e}`,""];for(let r of Ki(e,t))n.push(`# ${r.title} ${r.path}${r.hint?` (${r.hint})`:""}`),n.push(r.text.trimEnd()),n.push("");return n.join(`
615
- `)}function Oo(){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:"run",aliases:["task"],desc:"Run a one-off task: /run <task>",leader:"",group:"services"},{name:"exec",aliases:[],desc:"Run a command in a service context: /exec <service> -- <command\u2026>",leader:"",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; /auth login, logout, or refresh",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:"diff",aliases:["provenance"],desc:"Show winning config sources and what they shadowed",leader:"",group:"ui"},{name:"daemon",aliases:["bootstrap"],desc:"Show supervisor bootstrap logs (same file as devctl daemon logs)",leader:"",group:"app"},{name:"update",aliases:[],desc:"Check GitHub Releases for a newer version",leader:"",group:"app"},{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 hv(e){let t=e.trim().toLowerCase().replace(/^\//,"");return Oo().filter((n)=>t===""||AR(n,t))}function AR(e,t){if(e.name.startsWith(t)||e.name.includes(t)||e.desc.toLowerCase().includes(t))return!0;return e.aliases.some((n)=>n.startsWith(t)||n===t)}function qi(e){let t=e.trim().toLowerCase().replace(/^\//,"").split(" ")[0]??"";return Oo().find((n)=>n.name===t||n.aliases.includes(t))}function vv(e){return e.trim().replace(/^\//,"").split(/\s+/).slice(1).filter((n)=>n!=="")}function yv(e){return Oo().find((n)=>n.leader===e)?.name??""}function xv(e){let t=e.includes("--print-env"),n=e.includes("--reveal"),r=e.filter((o)=>o!=="--print-env"&&o!=="--reveal"&&o!=="--");return{service:r[0]??"",printEnv:t,reveal:n,command:r.slice(1)}}function wu(e){if(e.newer)return`update available ${e.current} \u2192 ${e.latest} ${e.hint}`;if(e.latest!=="")return`${e.current} up to date`;return`${e.current} (latest unavailable)`}async function Vi(e=fetch){try{let t=await e(LR,{headers:{Accept:"application/vnd.github+json"}});if(!t.ok)return{current:pt,latest:"",newer:!1,hint:bu};let r=((await t.json()).tag_name??"").replace(/^v/,"");return{current:pt,latest:r,newer:r!==""&&DR(r,pt)>0,hint:bu}}catch{return{current:pt,latest:"",newer:!1,hint:bu}}}function DR(e,t){let n=bv(e),r=bv(t);for(let o=0;o<3;o+=1){let i=(n[o]??0)-(r[o]??0);if(i!==0)return i>0?1:-1}return 0}function bv(e){return e.replace(/^v/,"").split(".").slice(0,3).map((t)=>{let n=Number.parseInt(t.replace(/[^0-9].*$/,""),10);return Number.isFinite(n)?n:0})}var LR="https://api.github.com/repos/amr-m-abdelgawad/devctl/releases/latest",bu="npm install --global @amr-m-abdelgawad/devctl@latest # alternatives: Homebrew or the unsigned GitHub Release binaries \u2014 see docs/installation.md";var Su=()=>{};function Tv(e,t=!0){let n=e<sc?wv+1:wv,r=t?VR:0;return n+r+UR+r+KR+r+qR+r}function qn(e){return e.length+JR}function Av(e,t){if(t<YR)return ce(e,3);if(t<zR)return ce(e,4);return e}function Lv(e,t,n){let r=e.length;if(r===0||n<=0)return{start:0,end:-1};let o=t>=0&&t<r?t:0,i=ku(e,o,n);if(i.start===0&&i.end===r-1)return i;let s=o>0?Qa:0,a=o<r-1?Qa:0,c=s+a,l=ku(e,o,Math.max(e[o]??0,n-c)),d=(s>0&&l.start===0?Qa:0)+(a>0&&l.end===r-1?Qa:0);if(d===0)return l;return ku(e,o,Math.max(e[o]??0,n-c+d))}function ku(e,t,n){let r=e.length,o=t,i=t,s=e[t]??0;if(s>=n)return{start:t,end:t};while(o>0||i<r-1){let a=o>0?e[o-1]??0:Number.POSITIVE_INFINITY,c=i<r-1?e[i+1]??0:Number.POSITIVE_INFINITY,l=o>0&&s+a<=n,d=i<r-1&&s+c<=n;if(!l&&!d)break;let f=t-(o-1),g=i+1-t;if(l&&(!d||f<=g))o-=1,s+=a;else if(d)i+=1,s+=c;else break}return{start:o,end:i}}function Dv(e){if(e==="detail")return Vn.findIndex((t)=>t.id==="services");return Vn.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 Lu(e){return e>=$R}function Du(e){return e>=IR}function Ou(e){return e>=FR}function cc(e,t=0){return Math.max(1,e-Ev-t*2)}function Ov(e){let t=Rv+en+vt;if(Lu(e))t+=Sn;if(Du(e))t+=nc;if(Ou(e))t+=Jn;return Math.max(Au,e-t)}function Fv(e,t,n){let r=n?kv:XR+kv+Math.max(0,t)*2;return Math.max(1,e-r)}function tP(e){if(e.startsWith('"')||e.startsWith("'"))return"string";if(/^\d+$/.test(e))return"number";return"keyword"}function $o(e){return e.replace(nP,"")}function uc(e,t){let n=Math.max(1,t),r=$o(e).replace(/\r\n/g,`
614
+ `}function jE(e){return`codex mcp add --url ${e}`}function Ji(e,t){return[{kind:"claude",title:"Claude",path:".mcp.json",language:"json",text:bu(e,t),hint:"claude mcp add-json"},{kind:"cursor",title:"Cursor",path:".cursor/mcp.json",language:"json",text:wu(e,t)},{kind:"kilo",title:"Kilo Code",path:"kilo.jsonc",language:"json",text:Su(e,t)},{kind:"codex",title:"Codex",path:"~/.codex/config.toml",language:"toml",text:ku(e,t),hint:jE(e)}]}function xv(e,t){let n=[`URL ${e}`,""];for(let r of Ji(e,t))n.push(`# ${r.title} ${r.path}${r.hint?` (${r.hint})`:""}`),n.push(r.text.trimEnd()),n.push("");return n.join(`
615
+ `)}function Mo(){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:"run",aliases:["task"],desc:"Run a one-off task: /run <task>",leader:"",group:"services"},{name:"exec",aliases:[],desc:"Run a command in a service context: /exec <service> -- <command\u2026>",leader:"",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; /auth login, logout, or refresh",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:"diff",aliases:["provenance"],desc:"Show winning config sources and what they shadowed",leader:"",group:"ui"},{name:"daemon",aliases:["bootstrap"],desc:"Show supervisor bootstrap logs (same file as devctl daemon logs)",leader:"",group:"app"},{name:"update",aliases:[],desc:"Check GitHub Releases for a newer version",leader:"",group:"app"},{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 bv(e){let t=e.trim().toLowerCase().replace(/^\//,"");return Mo().filter((n)=>t===""||BE(n,t))}function BE(e,t){if(e.name.startsWith(t)||e.name.includes(t)||e.desc.toLowerCase().includes(t))return!0;return e.aliases.some((n)=>n.startsWith(t)||n===t)}function zi(e){let t=e.trim().toLowerCase().replace(/^\//,"").split(" ")[0]??"";return Mo().find((n)=>n.name===t||n.aliases.includes(t))}function wv(e){return e.trim().replace(/^\//,"").split(/\s+/).slice(1).filter((n)=>n!=="")}function Sv(e){return Mo().find((n)=>n.leader===e)?.name??""}function kv(e){let t=e.includes("--print-env"),n=e.includes("--reveal"),r=e.filter((o)=>o!=="--print-env"&&o!=="--reveal"&&o!=="--");return{service:r[0]??"",printEnv:t,reveal:n,command:r.slice(1)}}function _u(e){if(e.newer)return`update available ${e.current} \u2192 ${e.latest} ${e.hint}`;if(e.latest!=="")return`${e.current} up to date`;return`${e.current} (latest unavailable)`}async function Yi(e=fetch){try{let t=await e(WE,{headers:{Accept:"application/vnd.github+json"}});if(!t.ok)return{current:pt,latest:"",newer:!1,hint:Cu};let r=((await t.json()).tag_name??"").replace(/^v/,"");return{current:pt,latest:r,newer:r!==""&&GE(r,pt)>0,hint:Cu}}catch{return{current:pt,latest:"",newer:!1,hint:Cu}}}function GE(e,t){let n=Cv(e),r=Cv(t);for(let o=0;o<3;o+=1){let i=(n[o]??0)-(r[o]??0);if(i!==0)return i>0?1:-1}return 0}function Cv(e){return e.replace(/^v/,"").split(".").slice(0,3).map((t)=>{let n=Number.parseInt(t.replace(/[^0-9].*$/,""),10);return Number.isFinite(n)?n:0})}var WE="https://api.github.com/repos/amr-m-abdelgawad/devctl/releases/latest",Cu="npm install --global @amr-m-abdelgawad/devctl@latest # alternatives: Homebrew or the unsigned GitHub Release binaries \u2014 see docs/installation.md";var Eu=()=>{};function Ov(e,t=!0){let n=e<uc?_v+1:_v,r=t?oR:0;return n+r+tR+r+nR+r+rR+r}function Vn(e){return e.length+iR}function Mv(e,t){if(t<aR)return ce(e,3);if(t<sR)return ce(e,4);return e}function $v(e,t,n){let r=e.length;if(r===0||n<=0)return{start:0,end:-1};let o=t>=0&&t<r?t:0,i=Ru(e,o,n);if(i.start===0&&i.end===r-1)return i;let s=o>0?rc:0,a=o<r-1?rc:0,c=s+a,l=Ru(e,o,Math.max(e[o]??0,n-c)),d=(s>0&&l.start===0?rc:0)+(a>0&&l.end===r-1?rc:0);if(d===0)return l;return Ru(e,o,Math.max(e[o]??0,n-c+d))}function Ru(e,t,n){let r=e.length,o=t,i=t,s=e[t]??0;if(s>=n)return{start:t,end:t};while(o>0||i<r-1){let a=o>0?e[o-1]??0:Number.POSITIVE_INFINITY,c=i<r-1?e[i+1]??0:Number.POSITIVE_INFINITY,l=o>0&&s+a<=n,d=i<r-1&&s+c<=n;if(!l&&!d)break;let f=t-(o-1),g=i+1-t;if(l&&(!d||f<=g))o-=1,s+=a;else if(d)i+=1,s+=c;else break}return{start:o,end:i}}function Iv(e){if(e==="detail")return Jn.findIndex((t)=>t.id==="services");return Jn.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 $u(e){return e>=qE}function Iu(e){return e>=VE}function Fu(e){return e>=JE}function fc(e,t=0){return Math.max(1,e-Dv-t*2)}function Fv(e){let t=Av+en+vt;if($u(e))t+=Sn;if(Iu(e))t+=ac;if(Fu(e))t+=zn;return Math.max(Mu,e-t)}function hc(e){return e===ji?"\u2014":e}function Bv(e,t,n){let r=n?Rv:cR+Rv+Math.max(0,t)*2;return Math.max(1,e-r)}function pR(e){if(e.startsWith('"')||e.startsWith("'"))return"string";if(/^\d+$/.test(e))return"number";return"keyword"}function Io(e){return e.replace(fR,"")}function Wv(e){try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}function vc(e,t){let n=Math.max(1,t),r=Io(e).replace(/\r\n/g,`
616
616
  `).replace(/\r/g,`
617
617
  `).split(`
618
- `),o=[];for(let i of r)if(i.length<=n)o.push(i);else o.push(...rP(i,n));return o.length>0?o:[""]}function Nv(e,t,n){let r=e.length>0?[...e]:[""];if(n||r.length<=1)return{visible:r,mark:"",folded:!1,hidden:0};let o=r.length-1,i=` ${QR}${o}`,s=Math.max(1,t-i.length);return{visible:[ce(r[0]??"",s)],mark:i,folded:!0,hidden:o}}function Hv(e,t){return e==="all"||e==="focus"&&t}function Mu(e){if(e==="clip")return"focus";if(e==="focus")return"all";return"clip"}function jv(e,t,n,r=Nr){if(e.length===0)return{start:0,items:[],newer:0};if(!t){let a=Math.max(0,e.length-r);return{start:a,items:e.slice(a),newer:0}}let o=e.length-1,i=Math.max(0,Math.min(n,o)),s=e.slice(i,i+r);return{start:i,items:s,newer:Math.max(0,e.length-i-s.length)}}function $u(e,t=Nr){return Math.max(0,e-t)}function Iu(e,t,n,r){let o=Math.max(t-1,0);if(e<0&&n>0)return{selected:0,startDelta:Math.max(-n,e)};if(e>o&&r>0)return{selected:o,startDelta:Math.min(r,e-o)};return{selected:Math.min(o,Math.max(0,e)),startDelta:0}}function zi(e){if(e==="all")return"wrap all";if(e==="focus")return"wrap selected";return"clip"}function rP(e,t){let n=[],r=e;while(r.length>t){let o=r.slice(0,t),i=oP(o);if(i>0)n.push(r.slice(0,i).trimEnd()),r=r.slice(i).trimStart();else n.push(r.slice(0,t)),r=r.slice(t)}if(r.length>0)n.push(r);return n}function oP(e){let t=e.lastIndexOf(" "),n=e.lastIndexOf("\t"),r=e.lastIndexOf(","),o=Math.max(t,n,r);if(o<Math.floor(e.length*ZR))return-1;return e[o]===","?o+1:o}function Bv(e){let t=$o(e),n=[],r=new RegExp(eP.source,"gi"),o=0,i=r.exec(t);while(i){let s=i[0]??"";if(i.index>o)n.push({text:t.slice(o,i.index),kind:"text"});n.push({text:s,kind:tP(s)}),o=i.index+s.length,i=r.exec(t)}if(o<t.length)n.push({text:t.slice(o),kind:"text"});if(n.length===0)return[{text:t,kind:"text"}];return n}function Wv(e){let t=e.showTimestamps?lc:0,n=e.showMeta?ac:0;return Math.max(Mv,e.width-t-e.serviceWidth-dc-n-$v-Ji*Iv)}function Yi(e){return Math.max(BR,e-WR*2)}function Gv(e){let t=e.width<HR,n=e.proxyOn?`\u25CF ${ce(e.proxyAddress,t?10:18)}`:t?"":"\u25CB off";return[{label:t?`${e.running}/${e.total}`:Nu(e.running,e.total),tone:e.running>0?"success":"idle"},{label:n,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 Uv(e,t){let n=t.reduce((s,a)=>Math.max(s,a.length),0),r=lc+dc+$v+Mv+Ji*Iv,o=Math.max(Sv,e-r),i=Math.max(Sv,n);return Math.min(Pv,o,i)}function pc(e,t,n){if(n)return e;let r=t.reduce((a,c)=>Math.max(a,c.length),0),o=Math.min(Pv,Math.max(Au,r+OR)),i=Rv+en+vt+o+Ev+MR,s=Math.max(ec,Math.floor(e*NR));return Math.min(s,Math.max(ec,i))}function X(e,t){if(t<=0)return"";if(e.length>=t)return ce(e,t);return e.padEnd(t)}function Io(e,t){let n=[],r=0;for(let o of e){let i=o.key.length+o.label.length+3;if(r+i>t)break;n.push(o),r+=i}return n}function Kv(e){return e<GR}function Fo(e,t,n,r,o="center",i=!0){let s=Math.min(n,Math.max(1,e-4)),a=Math.min(Tv(e,i),Math.max(0,t-1)),c=Math.min(r,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),f=Math.max(0,Math.min(d,t-c));return{left:l,top:f,width:s,height:c}}function qv(e){if(e==="")return"idle";if(sP.test(e))return"error";if(e.includes("session only"))return"warning";if(iP.test(e))return"success";return"info"}function Vv(e,t,n){let r=n!==""&&e.profiles[n]?n:"";if(t.length>0)return{services:t,profile:r};if(r!=="")return{services:[...e.profiles[n]?.services??[]],profile:r};return{services:Object.keys(e.services),profile:""}}function Jv(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 jR;return 0}function zv(e){if(e==="0")return Vn[9]?.id;if(e.length===1&&e>="1"&&e<="9")return Vn[Number(e)-1]?.id;return}function fc(e){if(!e)return"";return Object.keys(e.profiles).sort()[0]??""}function gc(e){return aP.has(e)}function Xi(e){if(!e)return!1;return gc(e.state)}function mc(e,t){let n=t??Object.keys(e?.services??{});return{running:n.filter((o)=>Xi(e?.services[o])).length,total:n.length}}function Yv(e,t){let n=0,r=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")r+=1;else if(gc(d))n+=1;else a+=1}return{total:e.length,live:n+r,running:n,starting:r,healthy:o,failed:i,stopping:s,stopped:a}}function Xv(e,t){if(!Number.isFinite(e)||!Number.isFinite(t)||t<=0)return 0;return e/t}function fP(e,t,n){if(!Number.isFinite(e))return"success";if(e>n)return"error";if(e>t)return"warning";return"success"}function gP(e,t){return fP(Xv(e,t),cP,lP)}function mP(e,t){let n=t>0?e/t:1;if(n<uP)return"error";if(n<dP)return"warning";return"success"}function Cu(e){if(!Number.isFinite(e)||e<0)return"\u2014";return e.toFixed(2)}function hP(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${Math.round(e*100)}%`}function Qv(e,t=Date.now()){if(!e?.startTime)return"\u2014";let n=new Date(e.startTime).getTime();if(!Number.isFinite(n))return"\u2014";return Ho(t-n)}function Zv(e,t=pP){return Object.entries(e).sort((n,r)=>r[1]-n[1]||n[0].localeCompare(r[0])).slice(0,t)}function ey(e,t=1){return Math.max(24,e-kP-t*2-CP-_P-RP)}function ty(e){let t=e>=vP,n=e>=yP,r=e>=xP,o=e>=bP,i=e>=wP,s=e>=SP,a=en+vt;if(t)a+=Sn+vt;if(n)a+=oc+vt;if(r)a+=ic+vt;if(o)a+=rc+vt;if(i)a+=hc+vt;if(s)a+=Jn;return{name:Math.max(Au,e-a),health:t,cpu:n,mem:r,up:o,rst:i,pid:s}}function ny(e){let t=Number.isFinite(e)&&e>0?e:0;return{ratio:Math.min(1,t),label:hP(t)}}function ry(e,t=TP){return`[${Qi(e.ratio,t)}] ${e.label.padStart(4)}`}function Fu(e,t){let n=e.reduce((l,d)=>Math.max(l,d.what.length),4),r=e.reduce((l,d)=>Math.max(l,d.reading.length),7),o=e.some((l)=>l.meter)?AP:0,i=No*(o>0?3:2),s=Math.min(PP,Math.max(_u,n)),a=Math.min(EP,Math.max(Ru,r)),c=t-s-a-o-i;if(c<Za&&a>Ru)a=Math.max(Ru,a-(Za-c)),c=t-s-a-o-i;if(c<Za&&s>_u)s=Math.max(_u,s-(Za-c)),c=t-s-a-o-i;return{what:s,reading:a,meaning:Math.max(0,c),meter:o}}function oy(e){return LP.has((e?.health.type??"").toLowerCase())}function iy(e){if(e==="darwin")return"macOS";if(e==="win32")return"Windows";if(e==="linux")return"Linux";return e||"this computer"}function sy(e,t){let n=Math.max(1,t),r=gP(e,n),o=r==="error"?"overloaded":r==="warning"?"busy":"not busy",i=r==="error"?`${n} cores are queued up \u2014 last minute ${Cu(e)}`:r==="warning"?`${n} cores nearly full \u2014 last minute ${Cu(e)}`:`${n} cores. Last minute ${Cu(e)} (under ${n} is fine)`;return{what:"CPU work",reading:o,meaning:i,tone:r,meter:ny(Xv(e,n))}}function ay(e,t){let n=mP(e,t),r=`${tc(e)} of ${tc(t)}`,o=n==="error"?"Almost no RAM left for new work":n==="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:r,meaning:o,tone:n,meter:ny(i)}}function cy(e){let t=e?.state??"STOPPED";if(t==="FAILED")return"crashed";if(t==="STOPPING")return"stopping";if(t==="STARTING"||t==="RESTARTING")return"starting";if(gc(t))return"up";return"off"}function ly(e){if(!e||!gc(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 dy(e){if(e==="keychain")return"password store";if(e==="file")return"local file";return e||"unknown store"}function uy(e,t){let n=[{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)n.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)n.push({what:"Still starting",reading:String(e.starting),meaning:"not ready for traffic yet",tone:"warning"});if(e.stopping>0)n.push({what:"Stopping",reading:String(e.stopping),meaning:"shutting down",tone:"warning"});return n.push({what:"Crashed",reading:String(e.failed),meaning:e.failed>0?"open the service for the error":"none",tone:e.failed>0?"error":"muted"}),n.push({what:"Not started",reading:String(e.stopped),meaning:e.stopped>0?"off until you start them":"all are up",tone:"muted"}),n}function Qi(e,t=20){let n=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0,r=Math.round(n*t);return"\u2588".repeat(r)+"\u2591".repeat(Math.max(0,t-r))}function Ho(e){if(!Number.isFinite(e)||e<Pu)return"< 1s";let t=Math.floor(e/Cv),n=Math.floor(e%Cv/Tu),r=Math.floor(e%Tu/Eu),o=Math.floor(e%Eu/Pu);if(t>0)return`${t}d ${n}h`;if(n>0)return`${n}h ${r}m`;if(r>0)return`${r}m ${String(o).padStart(2,"0")}s`;return`${o}s`}function tc(e){if(!Number.isFinite(e)||e<0)return"\u2014";let t=e/DP;if(t>=_v)return`${(t/_v).toFixed(1)}G`;if(t>=1)return`${Math.round(t)}M`;return`${Math.round(e)}K`}function py(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${e.toFixed(1)}%`}function jo(e){if(!e)return!0;let t=Object.values(e.services);if(t.length===0)return!0;return!t.some((n)=>Xi(n))}function fy(e,t){if(e.length>0)return e;return[...t]}function vc(e,t){if(e.length>0)return[...e];return t===""?[]:[t]}function Zi(e){return OP.has(e)}function my(e,t,n,r){let o=n===""?t:t.filter((a)=>a.timestamp>=n);if(o.length===0)return e;let i=Math.max(1,r);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 hy(e,t){let n=t.length>0?t[t.length-1].seq:-1,r=e.filter((o)=>o.seq>n);return[...t,...r]}function vy(e,t){if(t.length===0)return e;let n=new Set(e.map((o)=>o.seq)),r=t.filter((o)=>!n.has(o.seq));return r.length===0?e:[...r,...e]}function yy(e,t,n){return e&&t<=0&&n}function xy(e){return e.filter((t)=>t.level==="ERROR"||t.level==="FATAL").length}function MP(e){return`${e.timestamp} ${e.service} ${e.level} ${$o(e.message)}`}function by(e){return[$o(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(`
619
- `)}function wy(e){return e.map((t)=>MP(t)).join(`
620
- `)}function Bo(e,t){let n=t.services?.filter((l)=>l!=="")??[],r=t.service??"",o=(t.search??"").trim(),i=t.source??"",s=t.since??"",a=t.until??"",c;if(o!=="")if(t.regex===!0){let l=Pa(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(n.length>0&&!n.includes(l.service))return!1;if(r!==""&&l.service!==r)return!1;if(i!==""&&l.source!==i)return!1;if(t.systemLogs===!1&&Zi(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 $P(e,t){let n={};for(let i of e)n[i.service]=(n[i.service]??0)+1;let r=t.map((i)=>({name:i,count:n[i]??0})),o=Object.keys(n).filter((i)=>!t.includes(i)).sort().map((i)=>({name:i,count:n[i]??0}));return[...r,...o]}function Sy(e,t,n=[]){let r=es(e,t,n);return[{name:"",count:t.length},...$P(t,r)]}function IP(e,t){let n=e.map((o)=>({name:o,count:t[o]??0})),r=Object.keys(t).filter((o)=>!e.includes(o)).sort().map((o)=>({name:o,count:t[o]??0}));return[...n,...r]}function ky(e,t,n=[]){let r=Object.keys(t.byService).map((i)=>({service:i})),o=es(e,r,n);return[{name:"",count:t.total},...IP(o,t.byService)]}function Nu(e,t){if(e<=0)return"none started";return`${e}/${t} running`}function es(e,t,n=[]){let r=[...e],o=(i)=>{if(i!==""&&!r.includes(i))r.push(i)};for(let i of n)o(i);for(let i of t)o(i.service);return r}function Cy(e,t,n){let r=["",...es(e,t)];if(n<1||n>r.length)return;return r[n-1]}function Hu(e,t,n){let r=["",...e],o=r.indexOf(t),s=((o<0?0:o)+n+r.length)%r.length;return r[s]??""}function ts(e){return e.waves.flat().join(" \u2192 ")}function _y(e){let t=ts(e);if(t==="")return"Started selected services";return`Started ${t}`}function Ry(e){let t=ts(e);if(t==="")return"Stopped running services";return`Stopped ${t}`}function Py(e,t,n,r="start"){let o=n?.services[e],i=jt(o);if(o?.last_error&&r!=="stop")return o.last_error;if(r==="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)=>{let l=jt(n?.services[wt(c)]);return Fn(c)==="service_healthy"?l!=="HEALTHY":l==="STOPPED"||l==="FAILED"}).map(wt);if(a.length>0)return`waits for ${a.join(", ")}`;return"queued"}function ns(e,t,n="start"){if(e.length===0)return"completed";let r=e.map((i)=>t?.services[i]);if(r.some((i)=>i?.state==="FAILED"))return"failed";if(n==="stop"){if(r.every((i)=>!i||i.state==="STOPPED"||i.state==="UNKNOWN"))return"completed";if(r.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(r.every(o))return"completed";if(r.some((i)=>i?.state==="UNHEALTHY"||i?.health==="UNHEALTHY"))return"unhealthy";if(r.some((i)=>i?.state==="STARTING"||i?.state==="RUNNING"||i?.state==="RESTARTING"))return"active";return"queued"}function Ey(e,t,n="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]??[],S=ns(v,t,n);if(S==="active"||S==="unhealthy"||S==="failed")c=x;else if(S==="completed"&&c===x&&x<e.waves.length-1)c=x+1;for(let P of v){let k=t?.services[P];if(n==="stop"?!k||k.state==="STOPPED"||k.state==="UNKNOWN":Boolean(k&&(k.state==="HEALTHY"||k.health==="HEALTHY"||k.state==="RUNNING"&&k.health!=="UNHEALTHY")))i++;else if(k?.state==="FAILED")s++;else if(k?.state==="STARTING"||k?.state==="RUNNING"||k?.state==="UNHEALTHY"||k?.health==="UNHEALTHY"||k?.state==="STOPPING"||k?.state==="RESTARTING")a++}}let l=o>0?Math.round(i/o*100):100,d=16,f=Math.round(l/100*d),g="\u2588".repeat(f)+"\u2591".repeat(Math.max(0,d-f)),m=i===o&&o>0;return{total:o,ready:i,active:a,failed:s,percent:l,progressBar:g,currentWaveIndex:c,totalWaves:e.waves.length,isComplete:m}}function Ty(e,t,n){let r=n==="completed"?"\u2713 Completed":n==="failed"?"\u2717 Failed":n==="unhealthy"?"\u26A0 Unhealthy":n==="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 ${r}`}function Ay(e,t,n,r){let o=r?` \xB7 Profile ${r}`:"";if(n)return`${e==="stop"?"Shutdown":"Startup"} Failed (${n})`;if(t)return`${e==="stop"?"Stopping Services":e==="restart"?"Restarting Pipeline":"Starting Pipeline"}${o}`;return`${e==="stop"?"Shutdown Complete":"Startup Complete"}${o}`}function Ly(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 Dy(e){let t=Fr.indexOf(e);if(t<0)return"dashboard";return Fr[(t+1)%Fr.length]??"dashboard"}function Oy(e){let t=Fr.indexOf(e);if(t<0)return"dashboard";return Fr[(t-1+Fr.length)%Fr.length]??"dashboard"}function My(e){return["services","nav","logs","ui","app"].flatMap((n)=>{let r=e.filter((o)=>o.group===n);if(r.length===0)return[];return[{group:n,items:r}]})}function $y(e){let t=e.trim().toLowerCase().replace(/^\//,""),n=Oo().filter((r)=>t===""||r.name.includes(t)||r.desc.toLowerCase().includes(t)||r.aliases.some((o)=>o.startsWith(t)));return My(n).flatMap((r)=>r.items)}function Iy(e){return My(e).flatMap((t)=>t.items.map((n)=>({name:`/${n.name}`,description:`${t.group} \xB7 ${n.desc}`,value:n.name})))}function Fy(e,t,n=bn()){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"||t==="scroll-text")return[{key:"j/k",label:"scroll"},{key:n,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 ju();if(t==="config-edit")return[{key:"ctrl+s",label:"save"},{key:"esc",label:"discard"}];return FP(e,n)}function ju(){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 FP(e,t){let n=[{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"},...n];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"},...n];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"},...n];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"},...n];case"profiles":return[{key:"space",label:"set current"},{key:"enter",label:"set and start"},{key:"j/k",label:"move"},...n];case"proxy":return[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"},...n];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"},...n];case"config":return[{key:"v",label:"buffer"},{key:"e",label:"editor"},{key:"/diff",label:"sources"},{key:"/reload",label:"reload"},{key:"j/k",label:"scroll"},...n];case"setup":return[{key:"j/k",label:"steps"},{key:"enter",label:"continue"},{key:"esc",label:"back or exit"},...n];case"doctor":return[{key:"r",label:"run doctor again"},{key:"j/k",label:"move"},{key:"enter",label:"fix port"},...n];case"auth":return[{key:"r",label:"probe identities"},{key:"/auth login",label:"ADC login"},{key:"/auth logout",label:"revoke ADC"},{key:"/auth refresh",label:"probe"},...n];case"settings":return[{key:"j/k",label:"move"},{key:"\u2190\u2192",label:"save"},{key:"enter",label:"apply or open page"},{key:"space",label:"toggle"},...n];default:return[{key:"tab",label:"screens"},...n]}}function Ny(e,t,n){if(n<=t||e<t)return 0;return Math.min(e-t+1,n-t)}function Hr(e,t){if(e.length===0)return;let n=Math.min(Math.max(t,0),e.length-1);return e[n]}function yc(e){return e.command.args.join(" ")||"\u2014"}function rs(e,t){let n=jr(t);if(n!=="")return n;if(e.ports.length===0)return"\u2014";return e.ports.map((r)=>`${r.name}:${r.auto?"auto":r.value}`).join(" ")}function xc(e){let t=e.health.type||"none",n=e.health.url||e.health.address;return n===""?t:`${t} ${n}`}function bc(e,t){if(t?.identity)return t.identity;let n=e.identity.type||"none",r=e.identity.service_account;return r===""?n:`${n} ${r}`}function wc(e){let t=e.restart.policy||"none";if(e.restart.max_retries>0)return`${t} \xD7${e.restart.max_retries}`;return t}function Hy(e,t,n,r,o){let i=o??{...e.environment.defaults,...e.environment.vars},s=GP(i,t,n,r);return[...new Set([...Object.keys(s),...e.environment.required])].sort().map((c)=>({key:c,value:s[c]??"",required:e.environment.required.includes(c)}))}function jy(e,t){if(!e||e.processes.length===0)return;if(t!==void 0&&t!==""&&e.session_id===t)return;return e}function By(e){let t=Math.max(WP,e-BP);return Math.min(HP,Math.max(NP,Math.floor(t*jP)))}function jr(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 jt(e){if(!e)return"STOPPED";return ko(e)}function Wy(e,t,n){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 r=n?.port??0,o=n?.process||"process",i=n?.pid??0;return{title:`Free port ${r}`,body:`Stop ${o} (pid ${i}) so port ${r} 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 GP(e,t,n,r){if(t)return e;return new qt(n,r).redactMap(e)}function Gy(e,t){if(!e)return"";return(e.profiles[t]?.services??[]).join(", ")}function Wo(e,t,n){let r=e?.google?.project_id??"";if(r!=="")return{project:r,source:"configuration"};let o=t?.project||n?.projectID||"",i=t?.project_source||n?.projectSource||"";return{project:o,source:i}}function Uy(e,t,n,r){let o=Math.max(8,r-2),i=`logs ${n}`,s=qn(i),a=e||"(no user)",c=t||"";if(o<=s+6){let g=Math.max(2,o-s-2);return[{label:ce(a,g),tone:"idle"},{label:ce(i,s-2),tone:"muted"}]}let l=o-s;if(c&&l>=36){let g=ce(c,14),m=qn(g),x=l-m-2,v=x>=a.length+9?`identity ${a}`:a;return[{label:ce(v,x),tone:"idle"},{label:g,tone:"muted"},{label:i,tone:"muted"}]}if(c&&l>=28&&c.length<=10){let g=ce(c,10),m=qn(g),x=l-m-2;return[{label:ce(a,x),tone:"idle"},{label:g,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 Ky(e){let t=e.payload?.error;return typeof t==="string"&&t!==""?t:"configuration reload failed"}var Mo=100,Rv=8,en=12,Sn=10,nc=8,Jn=8,rc=9,oc=7,ic=8,Au=12,Pv=40,vt=2,OR=2,Ev=2,MR=2,ec=34,$R=48,IR=60,FR=72,NR=0.48,sc=90,HR=60,jR=9,ac=8,BR=8,WR=6,GR=20,wv=1,UR=1,KR=1,qR=1,VR=1,g$,JR=2,Qa=2,zR=80,YR=56,lc=9,dc=7,Sv=10,Mv=16,$v=2,Ji=1,Nr=200,XR=2,kv=1,QR="\u25B8",Iv=2,ZR=0.4,eP,nP,iP,sP,Vn,Fr,aP,cP=0.85,lP=1.5,dP=0.2,uP=0.1,pP=5,vP=52,yP=64,xP=72,bP=82,wP=90,SP=100,kP=2,CP=2,_P=2,RP=1,hc=8,_u=8,PP=22,Ru=6,EP=28,Za=12,No=2,TP=10,AP=18,LP,Pu=1000,Eu,Tu,Cv,DP=1024,_v=1024,OP,gy,NP=10,HP=28,jP=0.42,BP=2,WP=20;var Ee=D(()=>{st();Ar();To();Pr();Zt();g$=Tv(sc-1);eP=/("[^"]*"|'[^']*'|\b(?:ERROR|FATAL|WARN(?:ING)?|FAIL(?:ED)?)\b|\b\d{3,5}\b)/gi;nP=/\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;iP=/^(started|stopped|restarted|refreshed|cleared|copied|exported|jumped|proxy started|proxy stopped|secrets|re-running|theme |mouse |leader |display |restored)/i,sP=/\b(fail|error|unknown|not found|no configuration|blocked|already in use|is using port)\b/i;Vn=[{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"}];Fr=Vn.map((e)=>e.id);aP=new Set(["RUNNING","STARTING","RESTARTING","HEALTHY","UNHEALTHY"]);LP=new Set(["http","tcp","command"]);Eu=60*Pu,Tu=60*Eu,Cv=24*Tu;OP=new Set(["auth","devctl","proxy"]),gy=["devctl","mcp","auth"]});function qy(e){let t=Object.keys(e.services).length,n=Object.keys(e.profiles).length,r=e.proxy.routes.length,o=Object.keys(e.tasks).length,i=[{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:`${n} profile${n===1?"":"s"}`,tone:n>0?"info":"idle"},{text:e.proxy.enabled?"proxy on":"proxy off",tone:e.proxy.enabled?"success":"idle"}];if(r>0)i.push({text:`${r} route${r===1?"":"s"}`,tone:"info"});if(o>0)i.push({text:`${o} task${o===1?"":"s"}`,tone:"info"});return i}function Vy(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 Jy(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 zy(e){let t=UP(e);return[{label:"exit",value:t,tone:t==="ask on quit"?"warning":"text"},{label:"grace",value:`${e.shutdown.grace_seconds}s`},{label:"refresh",value:`${js(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 Yy(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 Xy(e){return[{label:"listen",value:fr(e.proxy.listen),tone:e.proxy.enabled?"text":"muted"},{label:"token",value:VP(e),tone:e.proxy.token_endpoint.enabled?"text":"muted"}]}function Qy(e){return Object.keys(e.services).sort().map((t)=>{let n=e.services[t]??Nn();return{name:t,extends:n.extends||"\u2014",command:yc(n),ports:rs(n),identity:bc(n),health:xc(n),depends:n.dependencies.map(Hs).join(", ")||"\u2014",restart:wc(n)}})}function Zy(e){return e.proxy.routes.map((t)=>({name:t.name||t.match.host||"(unnamed)",match:JP(t),upstream:t.upstream.url||"\u2014",auth:t.auth.type||"none",identity:zP(t)}))}function ex(e){return Object.keys(e.profiles).sort().map((t)=>{let n=e.profiles[t],r=Object.keys(n?.environment??{}).sort();return{name:t,services:n?.services.join(", ")||"\u2014",env:r.length>0?r.join(", "):"\u2014"}})}function tx(e){return Object.keys(e.templates).sort().map((t)=>({name:t,summary:YP(e.templates[t])}))}function nx(e){return Object.keys(e.tasks).sort().map((t)=>{let n=e.tasks[t],r=n?.command.args.join(" ")||"\u2014",o=n?.dependencies.join(", ");return{name:t,summary:o?`${r} depends ${o}`:r}})}function rx(e,t){let n=hr(e);if(n.length===0)return"No provenance recorded for this configuration.";let r=new qt(e.secrets.extra_markers,e.secrets.extra_patterns);return n.map((o)=>{let i=typeof o.value==="string"?o.value:JSON.stringify(o.value),s=t?i:r.redactMap({[o.path]:i})[o.path],a=o.shadowed.length===0?"":`
618
+ `),o=[];for(let i of r)if(i.length<=n)o.push(i);else o.push(...gR(i,n));return o.length>0?o:[""]}function Gv(e,t,n){let r=e.length>0?[...e]:[""];if(n||r.length<=1)return{visible:r,mark:"",folded:!1,hidden:0};let o=r.length-1,i=` ${lR}${o}`,s=Math.max(1,t-i.length);return{visible:[ce(r[0]??"",s)],mark:i,folded:!0,hidden:o}}function Uv(e,t){return e==="all"||e==="focus"&&t}function Nu(e){if(e==="clip")return"focus";if(e==="focus")return"all";return"clip"}function Kv(e,t,n,r=Nr){if(e.length===0)return{start:0,items:[],newer:0};if(!t){let a=Math.max(0,e.length-r);return{start:a,items:e.slice(a),newer:0}}let o=e.length-1,i=Math.max(0,Math.min(n,o)),s=e.slice(i,i+r);return{start:i,items:s,newer:Math.max(0,e.length-i-s.length)}}function Hu(e,t=Nr){return Math.max(0,e-t)}function ju(e,t,n,r){let o=Math.max(t-1,0);if(e<0&&n>0)return{selected:0,startDelta:Math.max(-n,e)};if(e>o&&r>0)return{selected:o,startDelta:Math.min(r,e-o)};return{selected:Math.min(o,Math.max(0,e)),startDelta:0}}function Qi(e){if(e==="all")return"wrap all";if(e==="focus")return"wrap selected";return"clip"}function gR(e,t){let n=[],r=e;while(r.length>t){let o=r.slice(0,t),i=mR(o);if(i>0)n.push(r.slice(0,i).trimEnd()),r=r.slice(i).trimStart();else n.push(r.slice(0,t)),r=r.slice(t)}if(r.length>0)n.push(r);return n}function mR(e){let t=e.lastIndexOf(" "),n=e.lastIndexOf("\t"),r=e.lastIndexOf(","),o=Math.max(t,n,r);if(o<Math.floor(e.length*dR))return-1;return e[o]===","?o+1:o}function qv(e){let t=Io(e),n=[],r=new RegExp(uR.source,"gi"),o=0,i=r.exec(t);while(i){let s=i[0]??"";if(i.index>o)n.push({text:t.slice(o,i.index),kind:"text"});n.push({text:s,kind:pR(s)}),o=i.index+s.length,i=r.exec(t)}if(o<t.length)n.push({text:t.slice(o),kind:"text"});if(n.length===0)return[{text:t,kind:"text"}];return n}function Vv(e){let t=e.showTimestamps?gc:0,n=e.showMeta?pc:0;return Math.max(Nv,e.width-t-e.serviceWidth-mc-n-Hv-Xi*jv)}function Zi(e){return Math.max(QE,e-ZE*2)}function Jv(e){let t=e.width<YE,n=e.proxyOn?`\u25CF ${ce(e.proxyAddress,t?10:18)}`:t?"":"\u25CB off";return[{label:t?`${e.running}/${e.total}`:Wu(e.running,e.total),tone:e.running>0?"success":"idle"},{label:n,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 zv(e,t){let n=t.reduce((s,a)=>Math.max(s,a.length),0),r=gc+mc+Hv+Nv+Xi*jv,o=Math.max(Ev,e-r),i=Math.max(Ev,n);return Math.min(Lv,o,i)}function yc(e,t,n){if(n)return e;let r=t.reduce((a,c)=>Math.max(a,c.length),0),o=Math.min(Lv,Math.max(Mu,r+UE)),i=Av+en+vt+o+Dv+KE,s=Math.max(ic,Math.floor(e*zE));return Math.min(s,Math.max(ic,i))}function ee(e,t){if(t<=0)return"";if(e.length>=t)return ce(e,t);return e.padEnd(t)}function Fo(e,t){let n=[],r=0;for(let o of e){let i=o.key.length+o.label.length+3;if(r+i>t)break;n.push(o),r+=i}return n}function Yv(e){return e<eR}function No(e,t,n,r,o="center",i=!0){let s=Math.min(n,Math.max(1,e-4)),a=Math.min(Ov(e,i),Math.max(0,t-1)),c=Math.min(r,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),f=Math.max(0,Math.min(d,t-c));return{left:l,top:f,width:s,height:c}}function Xv(e){if(e==="")return"idle";if(vR.test(e))return"error";if(e.includes("session only"))return"warning";if(hR.test(e))return"success";return"info"}function Qv(e,t,n){let r=n!==""&&e.profiles[n]?n:"";if(t.length>0)return{services:t,profile:r};if(r!=="")return{services:[...e.profiles[n]?.services??[]],profile:r};return{services:Object.keys(e.services),profile:""}}function Zv(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 XE;return 0}function ey(e){if(e==="0")return Jn[9]?.id;if(e.length===1&&e>="1"&&e<="9")return Jn[Number(e)-1]?.id;return}function xc(e){if(!e)return"";return Object.keys(e.profiles).sort()[0]??""}function bc(e){return yR.has(e)}function es(e){if(!e)return!1;return bc(e.state)}function wc(e,t){let n=t??Object.keys(e?.services??{});return{running:n.filter((o)=>es(e?.services[o])).length,total:n.length}}function ty(e,t){let n=0,r=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")r+=1;else if(bc(d))n+=1;else a+=1}return{total:e.length,live:n+r,running:n,starting:r,healthy:o,failed:i,stopping:s,stopped:a}}function ny(e,t){if(!Number.isFinite(e)||!Number.isFinite(t)||t<=0)return 0;return e/t}function CR(e,t,n){if(!Number.isFinite(e))return"success";if(e>n)return"error";if(e>t)return"warning";return"success"}function _R(e,t){return CR(ny(e,t),xR,bR)}function ER(e,t){let n=t>0?e/t:1;if(n<SR)return"error";if(n<wR)return"warning";return"success"}function Pu(e){if(!Number.isFinite(e)||e<0)return"\u2014";return e.toFixed(2)}function RR(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${Math.round(e*100)}%`}function ry(e,t=Date.now()){if(!e?.startTime)return"\u2014";let n=new Date(e.startTime).getTime();if(!Number.isFinite(n))return"\u2014";return jo(t-n)}function oy(e,t=kR){return Object.entries(e).sort((n,r)=>r[1]-n[1]||n[0].localeCompare(r[0])).slice(0,t)}function iy(e,t=1){return Math.max(24,e-MR-t*2-$R-IR-FR)}function sy(e){let t=e>=PR,n=e>=TR,r=e>=AR,o=e>=LR,i=e>=DR,s=e>=OR,a=en+vt;if(t)a+=Sn+vt;if(n)a+=lc+vt;if(r)a+=dc+vt;if(o)a+=cc+vt;if(i)a+=Sc+vt;if(s)a+=zn;return{name:Math.max(Mu,e-a),health:t,cpu:n,mem:r,up:o,rst:i,pid:s}}function ay(e){let t=Number.isFinite(e)&&e>0?e:0;return{ratio:Math.min(1,t),label:RR(t)}}function cy(e,t=jR){return`[${ts(e.ratio,t)}] ${e.label.padStart(4)}`}function Bu(e,t){let n=e.reduce((l,d)=>Math.max(l,d.what.length),4),r=e.reduce((l,d)=>Math.max(l,d.reading.length),7),o=e.some((l)=>l.meter)?BR:0,i=Ho*(o>0?3:2),s=Math.min(NR,Math.max(Tu,n)),a=Math.min(HR,Math.max(Au,r)),c=t-s-a-o-i;if(c<oc&&a>Au)a=Math.max(Au,a-(oc-c)),c=t-s-a-o-i;if(c<oc&&s>Tu)s=Math.max(Tu,s-(oc-c)),c=t-s-a-o-i;return{what:s,reading:a,meaning:Math.max(0,c),meter:o}}function ly(e){return WR.has((e?.health.type??"").toLowerCase())}function dy(e){if(e==="darwin")return"macOS";if(e==="win32")return"Windows";if(e==="linux")return"Linux";return e||"this computer"}function uy(e,t){let n=Math.max(1,t),r=_R(e,n),o=r==="error"?"overloaded":r==="warning"?"busy":"not busy",i=r==="error"?`${n} cores are queued up \u2014 last minute ${Pu(e)}`:r==="warning"?`${n} cores nearly full \u2014 last minute ${Pu(e)}`:`${n} cores. Last minute ${Pu(e)} (under ${n} is fine)`;return{what:"CPU work",reading:o,meaning:i,tone:r,meter:ay(ny(e,n))}}function py(e,t){let n=ER(e,t),r=`${sc(e)} of ${sc(t)}`,o=n==="error"?"Almost no RAM left for new work":n==="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:r,meaning:o,tone:n,meter:ay(i)}}function fy(e){let t=e?.state??"STOPPED";if(t==="FAILED")return"crashed";if(t==="STOPPING")return"stopping";if(t==="STARTING"||t==="RESTARTING")return"starting";if(bc(t))return"up";return"off"}function gy(e){if(!e||!bc(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 my(e){if(e==="keychain")return"password store";if(e==="file")return"local file";return e||"unknown store"}function hy(e,t){let n=[{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)n.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)n.push({what:"Still starting",reading:String(e.starting),meaning:"not ready for traffic yet",tone:"warning"});if(e.stopping>0)n.push({what:"Stopping",reading:String(e.stopping),meaning:"shutting down",tone:"warning"});return n.push({what:"Crashed",reading:String(e.failed),meaning:e.failed>0?"open the service for the error":"none",tone:e.failed>0?"error":"muted"}),n.push({what:"Not started",reading:String(e.stopped),meaning:e.stopped>0?"off until you start them":"all are up",tone:"muted"}),n}function ts(e,t=20){let n=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0,r=Math.round(n*t);return"\u2588".repeat(r)+"\u2591".repeat(Math.max(0,t-r))}function jo(e){if(!Number.isFinite(e)||e<Lu)return"< 1s";let t=Math.floor(e/Pv),n=Math.floor(e%Pv/Ou),r=Math.floor(e%Ou/Du),o=Math.floor(e%Du/Lu);if(t>0)return`${t}d ${n}h`;if(n>0)return`${n}h ${r}m`;if(r>0)return`${r}m ${String(o).padStart(2,"0")}s`;return`${o}s`}function sc(e){if(!Number.isFinite(e)||e<0)return"\u2014";let t=e/GR;if(t>=Tv)return`${(t/Tv).toFixed(1)}G`;if(t>=1)return`${Math.round(t)}M`;return`${Math.round(e)}K`}function vy(e){if(!Number.isFinite(e)||e<0)return"\u2014";return`${e.toFixed(1)}%`}function Bo(e){if(!e)return!0;let t=Object.values(e.services);if(t.length===0)return!0;return!t.some((n)=>es(n))}function yy(e,t){if(e.length>0)return e;return[...t]}function kc(e,t){if(e.length>0)return[...e];return t===""?[]:[t]}function ns(e){return UR.has(e)}function by(e,t,n,r){let o=n===""?t:t.filter((a)=>a.timestamp>=n);if(o.length===0)return e;let i=Math.max(1,r);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 wy(e,t){let n=t.length>0?t[t.length-1].seq:-1,r=e.filter((o)=>o.seq>n);return[...t,...r]}function Sy(e,t){if(t.length===0)return e;let n=new Set(e.map((o)=>o.seq)),r=t.filter((o)=>!n.has(o.seq));return r.length===0?e:[...r,...e]}function ky(e,t,n){return e&&t<=0&&n}function Cy(e){return e.filter((t)=>t.level==="ERROR"||t.level==="FATAL").length}function KR(e){return`${e.timestamp} ${e.service} ${e.level} ${Io(e.message)}`}function _y(e){return[Io(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(`
619
+ `)}function Ey(e){return e.map((t)=>KR(t)).join(`
620
+ `)}function Wo(e,t){let n=t.services?.filter((l)=>l!=="")??[],r=t.service??"",o=(t.search??"").trim(),i=t.source??"",s=t.since??"",a=t.until??"",c;if(o!=="")if(t.regex===!0){let l=Da(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(n.length>0&&!n.includes(l.service))return!1;if(r!==""&&l.service!==r)return!1;if(i!==""&&l.source!==i)return!1;if(t.systemLogs===!1&&ns(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 qR(e,t){let n={};for(let i of e)n[i.service]=(n[i.service]??0)+1;let r=t.map((i)=>({name:i,count:n[i]??0})),o=Object.keys(n).filter((i)=>!t.includes(i)).sort().map((i)=>({name:i,count:n[i]??0}));return[...r,...o]}function Ry(e,t,n=[]){let r=rs(e,t,n);return[{name:"",count:t.length},...qR(t,r)]}function VR(e,t){let n=e.map((o)=>({name:o,count:t[o]??0})),r=Object.keys(t).filter((o)=>!e.includes(o)).sort().map((o)=>({name:o,count:t[o]??0}));return[...n,...r]}function Py(e,t,n=[]){let r=Object.keys(t.byService).map((i)=>({service:i})),o=rs(e,r,n);return[{name:"",count:t.total},...VR(o,t.byService)]}function Wu(e,t){if(e<=0)return"none started";return`${e}/${t} running`}function rs(e,t,n=[]){let r=[...e],o=(i)=>{if(i!==""&&!r.includes(i))r.push(i)};for(let i of n)o(i);for(let i of t)o(i.service);return r}function Ty(e,t,n){let r=["",...rs(e,t)];if(n<1||n>r.length)return;return r[n-1]}function Gu(e,t,n){let r=["",...e],o=r.indexOf(t),s=((o<0?0:o)+n+r.length)%r.length;return r[s]??""}function os(e){return e.waves.flat().join(" \u2192 ")}function Ay(e){let t=os(e);if(t==="")return"Started selected services";return`Started ${t}`}function Ly(e){let t=os(e);if(t==="")return"Stopped running services";return`Stopped ${t}`}function Dy(e,t,n,r="start"){let o=n?.services[e],i=Bt(o);if(o?.last_error&&r!=="stop")return o.last_error;if(r==="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)=>{let l=Bt(n?.services[wt(c)]);return Fn(c)==="service_healthy"?l!=="HEALTHY":l==="STOPPED"||l==="FAILED"}).map(wt);if(a.length>0)return`waits for ${a.join(", ")}`;return"queued"}function is(e,t,n="start"){if(e.length===0)return"completed";let r=e.map((i)=>t?.services[i]);if(r.some((i)=>i?.state==="FAILED"))return"failed";if(n==="stop"){if(r.every((i)=>!i||i.state==="STOPPED"||i.state==="UNKNOWN"))return"completed";if(r.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(r.every(o))return"completed";if(r.some((i)=>i?.state==="UNHEALTHY"||i?.health==="UNHEALTHY"))return"unhealthy";if(r.some((i)=>i?.state==="STARTING"||i?.state==="RUNNING"||i?.state==="RESTARTING"))return"active";return"queued"}function Oy(e,t,n="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]??[],w=is(v,t,n);if(w==="active"||w==="unhealthy"||w==="failed")c=x;else if(w==="completed"&&c===x&&x<e.waves.length-1)c=x+1;for(let E of v){let k=t?.services[E];if(n==="stop"?!k||k.state==="STOPPED"||k.state==="UNKNOWN":Boolean(k&&(k.state==="HEALTHY"||k.health==="HEALTHY"||k.state==="RUNNING"&&k.health!=="UNHEALTHY")))i++;else if(k?.state==="FAILED")s++;else if(k?.state==="STARTING"||k?.state==="RUNNING"||k?.state==="UNHEALTHY"||k?.health==="UNHEALTHY"||k?.state==="STOPPING"||k?.state==="RESTARTING")a++}}let l=o>0?Math.round(i/o*100):100,d=16,f=Math.round(l/100*d),g="\u2588".repeat(f)+"\u2591".repeat(Math.max(0,d-f)),m=i===o&&o>0;return{total:o,ready:i,active:a,failed:s,percent:l,progressBar:g,currentWaveIndex:c,totalWaves:e.waves.length,isComplete:m}}function My(e,t,n){let r=n==="completed"?"\u2713 Completed":n==="failed"?"\u2717 Failed":n==="unhealthy"?"\u26A0 Unhealthy":n==="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 ${r}`}function $y(e,t,n,r){let o=r?` \xB7 Profile ${r}`:"";if(n)return`${e==="stop"?"Shutdown":"Startup"} Failed (${n})`;if(t)return`${e==="stop"?"Stopping Services":e==="restart"?"Restarting Pipeline":"Starting Pipeline"}${o}`;return`${e==="stop"?"Shutdown Complete":"Startup Complete"}${o}`}function Iy(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 Fy(e){let t=Fr.indexOf(e);if(t<0)return"dashboard";return Fr[(t+1)%Fr.length]??"dashboard"}function Ny(e){let t=Fr.indexOf(e);if(t<0)return"dashboard";return Fr[(t-1+Fr.length)%Fr.length]??"dashboard"}function Hy(e){return["services","nav","logs","ui","app"].flatMap((n)=>{let r=e.filter((o)=>o.group===n);if(r.length===0)return[];return[{group:n,items:r}]})}function jy(e){let t=e.trim().toLowerCase().replace(/^\//,""),n=Mo().filter((r)=>t===""||r.name.includes(t)||r.desc.toLowerCase().includes(t)||r.aliases.some((o)=>o.startsWith(t)));return Hy(n).flatMap((r)=>r.items)}function By(e){return Hy(e).flatMap((t)=>t.items.map((n)=>({name:`/${n.name}`,description:`${t.group} \xB7 ${n.desc}`,value:n.name})))}function Wy(e,t,n=bn()){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"||t==="scroll-text")return[{key:"j/k",label:"scroll"},{key:n,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 Uu();if(t==="config-edit")return[{key:"ctrl+s",label:"save"},{key:"esc",label:"discard"}];return JR(e,n)}function Uu(){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 JR(e,t){let n=[{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"},...n];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"},...n];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"},...n];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"},...n];case"profiles":return[{key:"space",label:"set current"},{key:"enter",label:"set and start"},{key:"j/k",label:"move"},...n];case"proxy":return[{key:"n",label:"start proxy"},{key:"x",label:"stop proxy"},...n];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"},...n];case"config":return[{key:"v",label:"buffer"},{key:"e",label:"editor"},{key:"/diff",label:"sources"},{key:"/reload",label:"reload"},{key:"j/k",label:"scroll"},...n];case"setup":return[{key:"j/k",label:"steps"},{key:"enter",label:"continue"},{key:"esc",label:"back or exit"},...n];case"doctor":return[{key:"r",label:"run doctor again"},{key:"j/k",label:"move"},{key:"enter",label:"fix port"},...n];case"auth":return[{key:"r",label:"probe identities"},{key:"/auth login",label:"ADC login"},{key:"/auth logout",label:"revoke ADC"},{key:"/auth refresh",label:"probe"},...n];case"settings":return[{key:"j/k",label:"move"},{key:"\u2190\u2192",label:"save"},{key:"enter",label:"apply or open page"},{key:"space",label:"toggle"},...n];default:return[{key:"tab",label:"screens"},...n]}}function Gy(e,t,n){if(n<=t||e<t)return 0;return Math.min(e-t+1,n-t)}function Hr(e,t){if(e.length===0)return;let n=Math.min(Math.max(t,0),e.length-1);return e[n]}function Cc(e){return e.command.args.join(" ")||"\u2014"}function ss(e,t){let n=jr(t);if(n!=="")return n;if(e.ports.length===0)return"\u2014";return e.ports.map((r)=>`${r.name}:${r.auto?"auto":r.value}`).join(" ")}function _c(e){let t=e.health.type||"none",n=e.health.url||e.health.address;return n===""?t:`${t} ${n}`}function Ec(e,t){if(t?.identity)return t.identity;let n=e.identity.type||"none",r=e.identity.service_account;return r===""?n:`${n} ${r}`}function Rc(e){let t=e.restart.policy||"none";if(e.restart.max_retries>0)return`${t} \xD7${e.restart.max_retries}`;return t}function Uy(e,t,n,r,o){let i={...e.environment.defaults,...e.environment.vars},a=zR(o??i,t,n,r);return[...new Set([...Object.keys(a),...e.environment.required])].map((l)=>({key:l,value:a[l]??"",required:e.environment.required.includes(l),fromConfig:Object.prototype.hasOwnProperty.call(i,l)})).sort((l,d)=>l.fromConfig===d.fromConfig?l.key.localeCompare(d.key):l.fromConfig?-1:1)}function Ky(e,t){if(!e||e.processes.length===0)return;if(t!==void 0&&t!==""&&e.session_id===t)return;return e}function jr(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 Bt(e){if(!e)return"STOPPED";return Co(e)}function qy(e,t,n){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 r=n?.port??0,o=n?.process||"process",i=n?.pid??0;return{title:`Free port ${r}`,body:`Stop ${o} (pid ${i}) so port ${r} 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 zR(e,t,n,r){if(t)return e;return new Vt(n,r).redactMap(e)}function Vy(e,t){if(!e)return"";return(e.profiles[t]?.services??[]).join(", ")}function Go(e,t,n){let r=e?.google?.project_id??"";if(r!=="")return{project:r,source:"configuration"};let o=t?.project||n?.projectID||"",i=t?.project_source||n?.projectSource||"";return{project:o,source:i}}function Jy(e,t,n,r){let o=Math.max(8,r-2),i=`logs ${n}`,s=Vn(i),a=e||"(no user)",c=t||"";if(o<=s+6){let g=Math.max(2,o-s-2);return[{label:ce(a,g),tone:"idle"},{label:ce(i,s-2),tone:"muted"}]}let l=o-s;if(c&&l>=36){let g=ce(c,14),m=Vn(g),x=l-m-2,v=x>=a.length+9?`identity ${a}`:a;return[{label:ce(v,x),tone:"idle"},{label:g,tone:"muted"},{label:i,tone:"muted"}]}if(c&&l>=28&&c.length<=10){let g=ce(c,10),m=Vn(g),x=l-m-2;return[{label:ce(a,x),tone:"idle"},{label:g,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 zy(e){let t=e.payload?.error;return typeof t==="string"&&t!==""?t:"configuration reload failed"}var $o=100,Av=8,en=12,Sn=10,ac=8,zn=8,cc=9,lc=7,dc=8,Mu=12,Lv=40,vt=2,UE=2,Dv=2,KE=2,ic=34,qE=48,VE=60,JE=72,zE=0.48,uc=90,YE=60,XE=9,pc=8,QE=8,ZE=6,eR=20,_v=1,tR=1,nR=1,rR=1,oR=1,w$,iR=2,rc=2,sR=80,aR=56,gc=9,mc=7,Ev=10,Nv=16,Hv=2,Xi=1,Nr=200,cR=2,Rv=1,lR="\u25B8",jv=2,dR=0.4,uR,fR,hR,vR,Jn,Fr,yR,xR=0.85,bR=1.5,wR=0.2,SR=0.1,kR=5,PR=52,TR=64,AR=72,LR=82,DR=90,OR=100,MR=2,$R=2,IR=2,FR=1,Sc=8,Tu=8,NR=22,Au=6,HR=28,oc=12,Ho=2,jR=10,BR=18,WR,Lu=1000,Du,Ou,Pv,GR=1024,Tv=1024,UR,xy;var Pe=D(()=>{st();Ar();Ao();Rr();Zt();w$=Ov(uc-1);uR=/("[^"]*"|'[^']*'|\b(?:ERROR|FATAL|WARN(?:ING)?|FAIL(?:ED)?)\b|\b\d{3,5}\b)/gi;fR=/\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;hR=/^(started|stopped|restarted|refreshed|cleared|copied|exported|jumped|proxy started|proxy stopped|secrets|re-running|theme |mouse |leader |display |restored)/i,vR=/\b(fail|error|unknown|not found|no configuration|blocked|already in use|is using port)\b/i;Jn=[{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"}];Fr=Jn.map((e)=>e.id);yR=new Set(["RUNNING","STARTING","RESTARTING","HEALTHY","UNHEALTHY"]);WR=new Set(["http","tcp","command"]);Du=60*Lu,Ou=60*Du,Pv=24*Ou;UR=new Set(["auth","devctl","proxy"]),xy=["devctl","mcp","auth"]});function Yy(e){let t=Object.keys(e.services).length,n=Object.keys(e.profiles).length,r=e.proxy.routes.length,o=Object.keys(e.tasks).length,i=[{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:`${n} profile${n===1?"":"s"}`,tone:n>0?"info":"idle"},{text:e.proxy.enabled?"proxy on":"proxy off",tone:e.proxy.enabled?"success":"idle"}];if(r>0)i.push({text:`${r} route${r===1?"":"s"}`,tone:"info"});if(o>0)i.push({text:`${o} task${o===1?"":"s"}`,tone:"info"});return i}function Xy(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 Qy(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 Zy(e){let t=YR(e);return[{label:"exit",value:t,tone:t==="ask on quit"?"warning":"text"},{label:"grace",value:`${e.shutdown.grace_seconds}s`},{label:"refresh",value:`${Gs(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 ex(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 tx(e){return[{label:"listen",value:gr(e.proxy.listen),tone:e.proxy.enabled?"text":"muted"},{label:"token",value:ZR(e),tone:e.proxy.token_endpoint.enabled?"text":"muted"}]}function nx(e){return Object.keys(e.services).sort().map((t)=>{let n=e.services[t]??Nn();return{name:t,extends:n.extends||"\u2014",command:Cc(n),ports:ss(n),identity:Ec(n),health:_c(n),depends:n.dependencies.map(Ws).join(", ")||"\u2014",restart:Rc(n)}})}function rx(e){return e.proxy.routes.map((t)=>({name:t.name||t.match.host||"(unnamed)",match:eP(t),upstream:t.upstream.url||"\u2014",auth:t.auth.type||"none",identity:tP(t)}))}function ox(e){return Object.keys(e.profiles).sort().map((t)=>{let n=e.profiles[t],r=Object.keys(n?.environment??{}).sort();return{name:t,services:n?.services.join(", ")||"\u2014",env:r.length>0?r.join(", "):"\u2014"}})}function ix(e){return Object.keys(e.templates).sort().map((t)=>({name:t,summary:nP(e.templates[t])}))}function sx(e){return Object.keys(e.tasks).sort().map((t)=>{let n=e.tasks[t],r=n?.command.args.join(" ")||"\u2014",o=n?.dependencies.join(", ");return{name:t,summary:o?`${r} depends ${o}`:r}})}function ax(e,t){let n=vr(e);if(n.length===0)return"No provenance recorded for this configuration.";let r=new Vt(e.secrets.extra_markers,e.secrets.extra_patterns);return n.map((o)=>{let i=typeof o.value==="string"?o.value:JSON.stringify(o.value),s=t?i:r.redactMap({[o.path]:i})[o.path],a=o.shadowed.length===0?"":`
621
621
  shadowed ${o.shadowed.map((c)=>`${c.layer} \xB7 ${c.source}`).join("; ")}`;return`${o.path}
622
622
  ${o.layer} \xB7 ${o.source}
623
623
  ${s??""}${a}`}).join(`
624
624
 
625
- `)}function ox(e){let t=e.doctor.tools.map((i)=>i.name||i.command).filter((i)=>i!==""),n=e.plugins.map((i)=>i.path).filter((i)=>i!==""),r=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:n.join(", ")||"\u2014",tone:n.length>0?"text":"muted"},{label:"keymap",value:r.length>0?`${r.length} override${r.length===1?"":"s"}`:"defaults",tone:r.length>0?"text":"muted"},{label:"secrets",value:o.length>0?o.join(", "):"defaults",tone:o.length>0?"text":"muted"}]}function UP(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 ix(e){let t=e.reduce((n,r)=>Math.max(n,r.name.length),0);return Math.min(qP,Math.max(KP,t))}function VP(e){let t=e.proxy.token_endpoint;if(!t.enabled)return"off";let n=t.host===""?"127.0.0.1":t.host;if(t.port===0)return n;return`${n}:${t.port}`}function JP(e){let t=e.match.host||"*",n=e.match.path;if(n==="")return t;return`${t}${n.startsWith("/")?n:`/${n}`}`}function zP(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 YP(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 KP=8,qP=20,sx=80,Go=10;var Bu=D(()=>{st();To();Ee()});function Sc(e){let t=e.toLowerCase().trim(),n=XP[t];if(n)return n;return yt.includes(t)?t:"devctl"}function QP(){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"}),n=t.stdout.toString();if(t.exitCode===0&&n.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 ax(e){let t=Sc(e);if(t==="system"){if(QP())return{...Wu["solarized-light"],name:"system"};return Wu.system}return Wu[t]}function Ot(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 Br(e,t){return is(e)>=os?kc:t}function is(e){let t=e.startsWith("#")?e.slice(1):e,n=Number.parseInt(t,aE);if(Number.isNaN(n))return 0;let r=n>>cE&Gu,o=n>>lE&Gu,i=n&Gu;return(r*rE+o*oE+i*iE)/sE}function dE(e){let t=tE;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,nE);return t>>>0}function Cc(e){return is(e.background)>=os}function Ku(e){if(!e||!/^#[0-9a-f]{6}$/i.test(e))return!1;return is(e)<os}function _c(e,t){let n=uE[e];return Cc(t)?n.light:n.dark}function cx(e,t){return is(_c(e,t))>=os?pE:fE}function Ne(e,t){if(e===""||e==="all")return t.muted;let n=is(t.background)>=os?eE:ZP;return n[dE(e)%n.length]??t.info}function gE(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 lx(e,t,n){if(n==="string")return e.accent;if(n==="number")return e.info;if(n==="keyword")return e.error;return gE(e,t)}function Le(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 yt,Uu,Wu,XP,ZP,eE,tE=2166136261,nE=16777619,rE=299,oE=587,iE=114,sE=1000,os=160,aE=16,Gu=255,cE=16,lE=8,kc="#1A1A1A",uE,pE="#1A1A1A",fE="#F5F5F5";var Ye=D(()=>{yt=["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"],Uu={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)"},Wu={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"}},XP={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"};ZP=["#7AA2F7","#9ECE6A","#E0AF68","#BB9AF7","#2AC3DE","#FF9E64","#F7768E","#73DACA","#C0CAF5","#FF79C6","#7DCFFF","#C3E88D"],eE=["#2E5AAC","#3D7A1F","#9A6B12","#6B3FA0","#0E7A86","#B85C1A","#B4234A","#1A7A6D","#4A5080","#9A3480","#1565C0","#4A7C19"];uE={claude:{dark:"#E08A6A",light:"#B54328"},cursor:{dark:"#B8D4FF",light:"#1E4EBF"},kilo:{dark:"#F0C94A",light:"#8A6400"},codex:{dark:"#4ADE80",light:"#0B7A4B"}}});function px(){return Ui()!==void 0}function dx(e){let t=e/1000;if(Number.isInteger(t))return`${t}s`;return`${e}ms`}function Ju(e,t,n){let r=e.indexOf(t),i=((r<0?0:r)+n+e.length)%e.length;return e[i]??e[0]}function fx(e,t){let n=[...yt],r=n.includes(e)?e:Vu;return Ju(n,r,t)}function gx(e,t){let n=[...mE],r=n.reduce((o,i)=>Math.abs(i-e)<Math.abs(o-e)?i:o,n[0]);return Ju(n,r,t)}function ss(e){let t=[...qu];return t.reduce((n,r)=>Math.abs(r-e)<Math.abs(n-e)?r:n,t[0])}function Pc(e,t){return Ju([...qu],ss(e),t)}function as(e){let t=ss(e),n=ux[t]??ux[$r];return{px:t,...n}}function kn(e){return e.label==="compact"}function cs(e){return e.steps<=2}function mx(e){return qu.map((n,r)=>r<e?"\u2588":"\u2591").join(" ")}function Rc(e){return as(e).label}function hx(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:Rc(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:dx(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:pt,hint:"read-only",detail:At()},{id:"reset",group:"About",kind:"action",name:"Reset",value:"defaults",hint:"enter confirm reset",detail:`Restore theme ${Vu}, display ${Rc($r)}, mouse on, leader ${dx(Ja)}. Enter asks first. ${t}`}]}function zu(){return{theme:Vu,mouse:!0,leader_timeout:Ja,font_size:$r}}function vx(e){return["Appearance","Input","MCP","About"].flatMap((n)=>{let r=e.filter((o)=>o.group===n);if(r.length===0)return[];return[{group:n,items:r}]})}function Yu(e,t){if(e.length===0)return 0;return Math.min(Math.max(t,0),e.length-1)}function Uo(e,t){return e[Yu(e,t)]}function Xu(){return Ui()??za()}var mE,qu,Vu="devctl",ux;var Cn=D(()=>{Ye();Zt();mE=[1000,2000,3000],qu=[12,14,16,18,20,22];ux={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 hE,useContext as vE}from"react";function se(){return vE(Qu)}var Qu;var at=D(()=>{Cn();Zt();Qu=hE(as($r))});import{useEffect as yE,useRef as xE}from"react";import{jsxDEV as ae,Fragment as wE}from"@opentui/react/jsx-dev-runtime";function bE(e,t){switch(t){case"primary":return{bg:e.primary,fg:Br(e.primary,e.inverse)};case"accent":return{bg:e.accent,fg:Cc(e)?kc:Br(e.accent,e.inverse)};case"success":return{bg:e.success,fg:Br(e.success,e.inverse)};case"warning":return{bg:e.warning,fg:Cc(e)?kc:Br(e.warning,e.inverse)};case"error":return{bg:e.error,fg:Br(e.error,e.inverse)};case"info":return{bg:e.info,fg:Br(e.info,e.inverse)};case"muted":return{bg:e.element,fg:e.text};default:return{bg:e.element,fg:e.text}}}function yx(e){let{palette:t,dir:n}=e;return ae("box",{width:2,height:1,flexShrink:0,overflow:"hidden",children:ae("text",{fg:t.muted,children:n==="left"?"\u2039":"\u203A"},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function He(e){let{palette:t,children:n,backgroundColor:r,edge:o="bottom"}=e,i=se(),s=e.ruled??!kn(i),a=r??t.element,c=ae("box",{flexShrink:0,flexDirection:"column",backgroundColor:a,overflow:"hidden",children:n},void 0,!1,void 0,this);if(!s)return c;return ae("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 Ec(e){let{palette:t,items:n,active:r,width:o,onPick:i}=e,s=n.map((d)=>qn(d.label)),a=Lv(s,r,Math.max(1,o)),c=a.start>0,l=a.end>=0&&a.end<n.length-1;return ae("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[c?ae(yx,{palette:t,dir:"left"},void 0,!1,void 0,this):null,n.map((d,f)=>{if(f<a.start||f>a.end)return null;let g=f===r;return ae(ge,{palette:t,label:d.label,tone:g?"primary":"muted",fg:g?void 0:d.color,onMouseDown:()=>i(f)},d.id,!1,void 0,this)}),l?ae(yx,{palette:t,dir:"right"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function ge(e){let{palette:t,label:n,tone:r="idle",fg:o,bg:i,onMouseDown:s}=e,a=bE(t,r);return ae("box",{height:1,paddingLeft:1,paddingRight:1,backgroundColor:i??a.bg,overflow:"hidden",flexShrink:0,onMouseDown:s,children:ae("text",{fg:o??a.fg,children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function De(e){let{palette:t,hints:n}=e;return ae("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:n.map((r)=>ae("box",{height:1,paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ae("text",{wrapMode:"none",children:[ae("span",{fg:t.primary,children:r.key},void 0,!1,void 0,this),ae("span",{fg:t.muted,children:` ${r.label}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},`${r.key}-${r.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function je(e){let{palette:t,items:n,hints:r,ruled:o=!0}=e,i=ae("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[n.map((s,a)=>ae(ge,{palette:t,label:s.text,tone:s.tone,onMouseDown:s.onMouseDown},`${s.text}-${a}`,!1,void 0,this)),r&&r.length>0?ae(wE,{children:[ae("box",{flexGrow:1,backgroundColor:t.element},void 0,!1,void 0,this),ae(De,{palette:t,hints:r},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this);if(!o)return i;return ae(He,{palette:t,backgroundColor:t.element,children:i},void 0,!1,void 0,this)}function qe(e){let{palette:t,title:n,termW:r,termH:o,preferW:i,preferH:s,anchor:a="center",borderColor:c,bottomTitle:l,gap:d,children:f}=e,g=kn(se()),m=Fo(r,o,i,s,a,!g);return ae("box",{position:"absolute",left:m.left,top:m.top,width:m.width,height:m.height,border:!0,borderStyle:Zu,borderColor:c??t.borderActive,backgroundColor:t.panel,padding:g?0:1,title:n,titleColor:t.primary,bottomTitle:l,gap:g?0:d,flexDirection:"column",overflow:"hidden",children:f},void 0,!1,void 0,this)}function Te(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 Be(e,t){if(!e)return;e.scrollBy({x:0,y:t})}function Ko(e,t){let n=xE(null);return yE(()=>{let r=n.current;if(!r||e<0)return;let o=requestAnimationFrame(()=>{r.scrollChildIntoView(`${t}-${e}`)});return()=>cancelAnimationFrame(o)},[t,e]),n}function tt(e){let t=se(),n=cs(t),r=e.scroll?ae("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(e.palette),children:ae("box",{flexDirection:"column",overflow:"hidden",children:e.children},void 0,!1,void 0,this)},void 0,!1,void 0,this):e.children;return ae("box",{flexGrow:1,border:!0,borderStyle:Zu,borderColor:e.borderColor??e.palette.border,title:e.title,titleColor:e.palette.primary,paddingLeft:t.pad,paddingRight:t.pad,paddingTop:n?0:t.pad,paddingBottom:n?0:t.pad,backgroundColor:e.palette.panel,flexDirection:"column",overflow:"hidden",children:r},void 0,!1,void 0,this)}function Wr(e){let{palette:t,label:n,value:r,tone:o="text"}=e,i=se(),s=o==="success"?t.success:o==="warning"?t.warning:o==="error"?t.error:o==="muted"?t.muted:t.text;return ae("box",{height:i.rowH,flexDirection:"row",overflow:"hidden",children:[ae("box",{width:14,flexShrink:0,overflow:"hidden",children:ae("text",{fg:t.muted,children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this),ae("box",{flexGrow:1,overflow:"hidden",children:ae("text",{fg:s,wrapMode:"none",children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Tc(e){let{palette:t,title:n,body:r,hint:o}=e;return ae("box",{height:o?5:4,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:Zu,borderColor:t.borderActive,titleColor:t.primary,children:[ae("text",{fg:t.primary,children:n},void 0,!1,void 0,this),ae("text",{fg:t.text,wrapMode:"word",children:r},void 0,!1,void 0,this),o?ae("text",{fg:t.muted,wrapMode:"word",children:o},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var Zu="rounded";var be=D(()=>{at();Cn();Ye();Ee()});import{jsxDEV as de,Fragment as xx}from"@opentui/react/jsx-dev-runtime";function bx(e){let{palette:t,cfg:n,snap:r,google:o,profile:i,reveal:s,width:a}=e,c=mc(r,n?Object.keys(n.services):void 0),l=r?.proxy.running===!0,d=o?.adcAvailable===!0,f=a<sc,g=ce(n?.project.name||"local",f?18:22),m=ce(i||r?.profile||"no profile",16),x=de(xx,{children:Gv({width:a,running:c.running,total:c.total,proxyOn:l,proxyAddress:r?.proxy.address??"",mcpOn:r?.mcp?.running===!0,adc:d,reveal:s}).filter((S)=>!S.hide&&S.label!=="").map((S)=>de(ge,{palette:t,label:S.label,tone:S.tone},S.label,!1,void 0,this))},void 0,!1,void 0,this),v=cs(se());return de(He,{palette:t,backgroundColor:t.panel,ruled:!v,children:de("box",{height:f?2:1,flexDirection:"column",backgroundColor:t.panel,overflow:"hidden",children:[de("box",{height:1,flexDirection:"row",overflow:"hidden",children:[de(ge,{palette:t,label:At(),tone:"primary"},void 0,!1,void 0,this),de(ge,{palette:t,label:g,tone:"idle"},void 0,!1,void 0,this),de(ge,{palette:t,label:m,tone:"accent"},void 0,!1,void 0,this),f?null:de(xx,{children:[de("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),f?de("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 wx(e){let{palette:t,screen:n,width:r,onSelect:o}=e,i=Vn.map((a)=>({id:a.id,label:Av(a.label,r)})),s=Dv(n);return de(He,{palette:t,backgroundColor:t.element,children:de(Ec,{palette:t,items:i,active:s,width:r,onPick:(a)=>{let c=Vn[a];if(c)o(c.id)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Sx(e){let{palette:t,overlay:n,query:r,onQuery:o,onSubmit:i}=e;if(n==="slash"||n==="palette"){let c=n==="slash"?"/":"> ";return de(He,{palette:t,backgroundColor:t.highlight,edge:"top",children:de("box",{height:1,backgroundColor:t.highlight,paddingLeft:1,flexDirection:"row",overflow:"hidden",children:[de("box",{width:2,flexShrink:0,children:de("text",{fg:t.primary,children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),de("box",{flexGrow:1,overflow:"hidden",children:de("input",{focused:!0,value:r,placeholder:n==="slash"?"start auth":"filter commands",onInput:o,onSubmit:()=>i(r),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=n==="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 de(He,{palette:t,backgroundColor:t.element,edge:"top",children:de("box",{height:1,backgroundColor:t.element,overflow:"hidden",children:de(De,{palette:t,hints:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function kx(e){let{palette:t,screen:n,overlay:r,status:o,paused:i,errorOnly:s,width:a,copyKey:c}=e,l=cs(se()),d=Math.max(18,Math.floor(a*0.42)),f=Io(Fy(n,r,c),d),g=qv(o);return de(He,{palette:t,backgroundColor:t.panel,edge:"top",ruled:!l,children:de("box",{height:1,backgroundColor:t.panel,overflow:"hidden",children:de(je,{ruled:!1,palette:t,items:[{text:n,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:g}]],hints:f},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function $e(e){return de("box",{flexGrow:1,padding:1,overflow:"hidden",children:de(Tc,{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 Ac(e){return de("box",{flexGrow:1,padding:1,overflow:"hidden",children:de("text",{fg:e.palette.text,children:e.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Cx(e){return de("box",{flexGrow:1,padding:1,flexDirection:"column",overflow:"hidden",children:[de("text",{fg:e.palette.error,children:e.title},void 0,!1,void 0,this),de("text",{fg:e.palette.text,wrapMode:"word",children:e.body},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var _t=D(()=>{at();Ee();be();Cn();Ye()});function SE(){if(process.platform==="darwin")return[["pbcopy"]];if(process.platform==="win32")return[["clip"]];return[["wl-copy"],["xclip","-selection","clipboard"],["xsel","--clipboard","--input"]]}function kE(){return SE().filter((e)=>{let t=e[0];return typeof t==="string"&&Bun.which(t)!==null})}function CE(e){return`\x1B]52;c;${Buffer.from(e,"utf8").toString("base64")}\x07`}function _x(){if(process.platform==="linux")return"install wl-clipboard (Wayland) or xclip (X11)";return"no clipboard helper found"}async function ep(e){let t=kE(),n;for(let r of t)try{await RE(r,e);return}catch(o){n=o instanceof Error?o:Error(String(o))}if(process.platform!=="win32")try{await _E(e);return}catch(r){n=r instanceof Error?r:Error(String(r))}throw ke(Je,"clipboard unavailable",n?`${_x()} (${n.message})`:_x())}async function _E(e){let t=CE(e);try{await Bun.write("/dev/tty",t)}catch{if(!process.stderr.write(t))throw Error("terminal clipboard write failed")}}async function RE(e,t){let n=Bun.spawn(e,{stdin:"pipe",stdout:"ignore",stderr:"ignore"});n.stdin.write(t),await n.stdin.end();let r=await n.exited;if(r!==0)throw Error(`${e[0]} exited ${r}`)}var Rx=D(()=>{Pe()});function Px(e){return e==="slash"||e==="palette"||e==="config-edit"}function Ex(e,t){return wn(e,t.keybinds.leader??"ctrl+x")}function Tx(e,t){return wn(e,t.keybinds.command_list??"ctrl+p")}function Ax(e,t){return wn(e,t.keybinds.command??"/")||e.name==="/"}function Lx(e,t){return wn(e,t.keybinds.help??"?")||e.sequence==="?"}function Dx(e,t){return wn(e,t.keybinds.search??"f")}function Ox(e){let t=e.name??"";return t==="R"||e.shift===!0&&t.toLowerCase()==="r"}function Mx(e){return e.ctrl===!0&&(e.name??"").toLowerCase()==="l"}function $x(e,t){if(t&&wn(e,t.keybinds.interrupt??"ctrl+c"))return!0;return e.ctrl===!0&&(e.name??"").toLowerCase()==="c"}function Ix(e,t){return wn(e,t.keybinds.copy??bn())}function Fx(e,t,n=PE){return t>0&&e-t<=n}function zn(e,t,n,r){return wn(e,t.keybinds[n]??r)}function Lc(e){let t=(e.name??"").toLowerCase();return t==="pagedown"||e.ctrl===!0&&t==="d"&&!e.meta}function Dc(e){let t=(e.name??"").toLowerCase();return t==="pageup"||e.ctrl===!0&&t==="u"&&!e.meta}var PE=2000;var Nx=D(()=>{Zt()});import{jsxDEV as Yn}from"@opentui/react/jsx-dev-runtime";function Hx(e){let{palette:t,path:n,initialValue:r,error:o,termW:i,termH:s,textareaRef:a}=e;return Yn(qe,{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:[Yn("box",{height:1,overflow:"hidden",children:Yn("text",{fg:t.muted,wrapMode:"none",children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this),Yn("textarea",{ref:a,focused:!0,initialValue:r,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this),o!==""?Yn("box",{height:2,overflow:"hidden",children:Yn("text",{fg:t.error,wrapMode:"word",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this):Yn("box",{height:1,overflow:"hidden",children:Yn("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 jx=D(()=>{be()});import{jsxDEV as tp}from"@opentui/react/jsx-dev-runtime";function Bx(e){let{palette:t,title:n,body:r,termW:o,termH:i}=e;return tp(qe,{palette:t,title:n,bottomTitle:"enter confirm \xB7 esc stay",termW:o,termH:i,preferW:52,preferH:8,borderColor:t.warning,gap:1,children:[tp("text",{fg:t.text,wrapMode:"word",children:r},void 0,!1,void 0,this),tp(De,{palette:t,hints:[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Wx=D(()=>{be()});import{jsxDEV as Vt}from"@opentui/react/jsx-dev-runtime";function Gx(e){let{palette:t,event:n,termW:r,termH:o,scrollRef:i}=e;if(!n)return null;let s=n.message.length>120||n.message.includes(`
626
- `);return Vt(qe,{palette:t,title:"log details",bottomTitle:"j/k scroll \xB7 esc close",termW:r,termH:o,preferW:s?84:72,preferH:s?22:14,gap:1,children:Vt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Vt("box",{flexDirection:"column",overflow:"hidden",children:[Vt("text",{fg:t.text,wrapMode:"word",children:$o(n.message)},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`time ${n.timestamp}`},void 0,!1,void 0,this),Vt("text",{fg:Ne(n.service,t),children:`service ${n.service}`},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`source ${n.source}${n.stream?` / ${n.stream}`:""}`},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`level ${n.level}`},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`pid ${n.pid||"\u2014"}`},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`request ${n.request_id||"\u2014"}`},void 0,!1,void 0,this),Vt("text",{fg:t.muted,children:`identity ${n.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 Ux=D(()=>{be();Ee();Ye()});import{jsxDEV as we,Fragment as qx}from"@opentui/react/jsx-dev-runtime";function $E(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 Qn(e){return e+AE}function Vx(e){let t=Qn(rp.length),n=Qn(op.length),r=Qn(e.logCount),o=Qn(ip.length),i=Qn(sp.length),s=ap+e.pad*2;if(e.stacked)return s+t+n+r+o+i+np+(OE-1)*e.gap;let a=Math.max(t,n),c=Math.max(o,i);return s+a+r+c+np+(ME-1)*e.gap}function IE(e){return Vx(e)-ap-e.pad*2}function FE(e){return e-ap*2<TE}function Jx(e){let{palette:t,termW:n,termH:r,copyKey:o=bn(),scrollRef:i}=e,s=kn(se()),a=FE(n),c=s?0:1,l=s?0:1,d=$E(o),f={stacked:a,logCount:d.length,pad:c,gap:l},g=Vx(f),m=IE(f);return we(qe,{palette:t,title:"help",bottomTitle:`${At()} \xB7 j/k scroll \xB7 esc close`,termW:n,termH:r,preferW:EE,preferH:g,gap:0,children:we("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:we("box",{height:m,flexDirection:"column",flexShrink:0,overflow:"hidden",gap:l,children:[a?we(qx,{children:[we(Xn,{palette:t,title:"navigation",bindings:rp},void 0,!1,void 0,this),we(Xn,{palette:t,title:"services",bindings:op},void 0,!1,void 0,this),we(Xn,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),we(Xn,{palette:t,title:"commands",bindings:ip},void 0,!1,void 0,this),we(Xn,{palette:t,title:"display",bindings:sp},void 0,!1,void 0,this)]},void 0,!0,void 0,this):we(qx,{children:[we(Kx,{palette:t,left:{title:"navigation",bindings:rp},right:{title:"services",bindings:op}},void 0,!1,void 0,this),we(Xn,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),we(Kx,{palette:t,left:{title:"commands",bindings:ip},right:{title:"display",bindings:sp}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),we("box",{height:np,flexShrink:0,overflow:"hidden",paddingLeft:1,children:we("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 Kx(e){let{palette:t,left:n,right:r}=e,o=Math.max(Qn(n.bindings.length),Qn(r.bindings.length));return we("box",{height:o,flexDirection:"row",flexShrink:0,overflow:"hidden",gap:DE,children:[we(Xn,{palette:t,title:n.title,bindings:n.bindings,height:o,stretch:!0},void 0,!1,void 0,this),we(Xn,{palette:t,title:r.title,bindings:r.bindings,height:o,stretch:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Xn(e){let{palette:t,title:n,bindings:r,stretch:o=!1}=e,i=e.height??Qn(r.length);return we("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:n,titleColor:t.accent,children:r.map((s)=>we("box",{height:1,flexShrink:0,overflow:"hidden",paddingLeft:1,paddingRight:1,children:we(NE,{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 NE(e){let{palette:t,binding:n}=e;return we("box",{height:1,flexDirection:"row",overflow:"hidden",children:[we("box",{width:LE,flexShrink:0,overflow:"hidden",children:we("text",{fg:t.primary,wrapMode:"none",children:n.key},void 0,!1,void 0,this)},void 0,!1,void 0,this),we("box",{flexGrow:1,overflow:"hidden",children:we("text",{fg:t.text,wrapMode:"none",children:n.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var EE=78,TE=56,AE=2,ap=2,np=1,cp=8,LE=16,DE=2,OE=6,ME=4,rp,op,ip,sp;var zx=D(()=>{at();be();Cn();Zt();rp=[{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"}],op=[{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"}];ip=[{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:"/diff",label:"config sources"},{key:"/mcp",label:"agent MCP server"}],sp=[{key:"ctrl+=",label:"larger"},{key:"ctrl+-",label:"smaller"},{key:"?",label:"this overlay"}]});import{jsxDEV as Yx}from"@opentui/react/jsx-dev-runtime";function Xx(e){let{palette:t,termW:n,termH:r}=e,o=ju();return Yx(qe,{palette:t,title:"leader",termW:n,termH:r,preferW:68,preferH:5,anchor:"bottom",children:Yx(De,{palette:t,hints:o},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Qx=D(()=>{Ee();be()});import{jsxDEV as Zx}from"@opentui/react/jsx-dev-runtime";function eb(e){let{palette:t,items:n,selected:r,termW:o,termH:i,onIndex:s,onPick:a}=e,c=Iy(n),l=Fo(o,i,64,18,"center",!kn(se()));return Zx(qe,{palette:t,title:"commands",bottomTitle:"enter select \xB7 esc close",termW:o,termH:i,preferW:64,preferH:18,children:Zx("select",{height:Math.max(4,l.height-3),options:c,selectedIndex:r,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,f)=>{let g=f?.value;if(typeof g==="string"&&g!=="")a(g)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var tb=D(()=>{at();Ee();be();Cn()});import{jsxDEV as H}from"@opentui/react/jsx-dev-runtime";function lp(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 HE(e,t,n,r){if(t!=="")return{icon:"\u2717",label:"Failed",tone:"error",color:r.error};if(!e)return{icon:"\u2713",label:"Finished",tone:"success",color:r.success};if(n==="unhealthy")return{icon:"\u26A0",label:"Waiting on health",tone:"warning",color:r.warning};return{icon:"\u25CF",label:"Running",tone:"primary",color:r.primary}}function nb(e){return H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:H("text",{wrapMode:"none",children:[H("span",{fg:e.palette.primary,children:e.label.toUpperCase()},void 0,!1,void 0,this),e.detail?H("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 rb(e){let{palette:t,plan:n,snap:r,busy:o,failed:i,kind:s,termW:a=80,termH:c=24,scrollRef:l,initiallyRunning:d=[],onDismiss:f}=e,g=new Set(d),m=n.waves.map((oe,Ge)=>({wave:oe.filter((Re)=>!g.has(Re)),waveIdx:Ge})).filter(({wave:oe})=>oe.length>0),x=Ey(n,r,s),v=n.waves[x.currentWaveIndex]??[],S=ns(v,r,s),P=lp(S,t),k=HE(o,i,S,t),j=Ay(s,o,i,n.profile),V=Ly(o,i),C=i?t.inverse:t.text,y=i?t.error:t.element,B=Math.min(92,Math.max(40,a-8)),h=B>=82?22:B>=66?17:13,q=12,M=9,Y=B>=56,ue=B>=72,Ie=B<72||n.waves.length>3,ct=n.profile?`PROFILE ${n.profile}`:s.toUpperCase();return H(qe,{palette:t,title:j,bottomTitle:"enter close \xB7 esc hide (operation continues)",termW:a,termH:c,preferW:98,preferH:28,borderColor:k.color,gap:0,children:[H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[H(ge,{palette:t,label:`${k.icon} ${k.label.toUpperCase()}`,tone:k.tone},void 0,!1,void 0,this),H("box",{paddingLeft:1,flexGrow:1,overflow:"hidden",children:H("text",{fg:t.text,wrapMode:"none",children:ct},void 0,!1,void 0,this)},void 0,!1,void 0,this),H(ge,{palette:t,label:`${x.ready}/${x.total} READY`,tone:x.isComplete?"success":"info"},void 0,!1,void 0,this),H(ge,{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),H("box",{height:2,flexDirection:"column",overflow:"hidden",flexShrink:0,paddingLeft:1,paddingRight:1,children:[H("box",{height:1,flexDirection:"row",overflow:"hidden",children:[H("text",{wrapMode:"none",children:[H("span",{fg:t.muted,children:"PROGRESS "},void 0,!1,void 0,this),H("span",{fg:k.color,children:`[${x.progressBar}]`},void 0,!1,void 0,this),H("span",{fg:t.text,children:` ${x.percent}%`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("box",{flexGrow:1},void 0,!1,void 0,this),H("text",{wrapMode:"none",children:H("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),H("box",{height:1,overflow:"hidden",children:H("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.":V.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H(nb,{palette:t,label:"Pipeline",detail:`${n.waves.length} execution wave${n.waves.length===1?"":"s"}`},void 0,!1,void 0,this),H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:n.waves.map((oe,Ge)=>{let Re=ns(oe,r,s),Qe=lp(Re,t),pe=Ie?`W${Ge+1} ${Qe.icon} ${oe.length}`:`W${Ge+1} ${Qe.icon} ${Qe.label} \xB7 ${oe.length}`;return H("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:[H(ge,{palette:t,label:pe,tone:Qe.tone},void 0,!1,void 0,this),Ge<n.waves.length-1?H("box",{width:3,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:" \u2500\u25BA"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},`step-${Ge}`,!0,void 0,this)})},void 0,!1,void 0,this),(n.blockers??[]).length>0?H("box",{minHeight:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:H("text",{fg:t.error,wrapMode:"word",children:`BLOCKED ${n.blockers?.map((oe)=>`${oe.name}: ${oe.message}`).join(" \xB7 ")}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,d.length>0?H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,paddingLeft:1,children:H("text",{wrapMode:"none",children:[H("span",{fg:t.success,children:"\u2713 ALREADY READY"},void 0,!1,void 0,this),H("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,H(nb,{palette:t,label:"Wave details",detail:"live process and health state"},void 0,!1,void 0,this),H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:[H("box",{width:2,flexShrink:0},void 0,!1,void 0,this),H("box",{width:h,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:X("SERVICE",h)},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:12,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:X("STATE",12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y?H("box",{width:9,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:X("PORT",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ue?H("box",{flexGrow:1,overflow:"hidden",children:H("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),H("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:H("box",{flexDirection:"column",overflow:"hidden",gap:1,children:m.map(({wave:oe,waveIdx:Ge})=>{let Re=ns(oe,r,s),Qe=lp(Re,t),pe=`${Ty(s,Ge,Re)} \xB7 ${oe.length} service${oe.length===1?"":"s"}`;return H("box",{border:!0,borderStyle:"rounded",borderColor:Qe.color,title:pe,titleColor:Qe.color,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:oe.map((Se)=>{let $t=r?.services[Se],N=jt($t),Rt=Py(Se,n,r,s),nt=Se===i||N==="FAILED",Ve=N==="UNHEALTHY",Bt=N==="HEALTHY"||s==="stop"&&N==="STOPPED",lt=jr($t),er=nt?"\u2717":Bt?"\u2713":Ve?"\u26A0":N==="STARTING"||N==="RUNNING"||N==="STOPPING"||N==="RESTARTING"?"\u25CF":"\u25CB",mt=nt?t.error:Le(t,N),on=nt?t.error:Ve?t.warning:Bt?t.success:t.muted;return H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[H("box",{width:2,flexShrink:0,overflow:"hidden",children:H("text",{fg:mt,children:er},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:h,flexShrink:0,overflow:"hidden",children:H("text",{fg:Ne(Se,t),wrapMode:"none",children:X(Se,h)},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:12,flexShrink:0,overflow:"hidden",children:H("text",{fg:Le(t,N),wrapMode:"none",children:X(N,12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y?H("box",{width:9,flexShrink:0,overflow:"hidden",children:H("text",{fg:lt?t.info:t.muted,wrapMode:"none",children:X(lt?`:${lt}`:"\u2014",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ue?H("box",{flexGrow:1,overflow:"hidden",children:H("text",{fg:on,wrapMode:"none",children:Rt},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},Se,!0,void 0,this)})},`wave-card-${Ge}`,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{height:3,flexShrink:0,flexDirection:"column",backgroundColor:y,border:["top"],borderStyle:"single",borderColor:k.color,paddingLeft:1,paddingRight:1,overflow:"hidden",onMouseDown:f,children:[H("text",{fg:C,wrapMode:"none",children:V.primary},void 0,!1,void 0,this),H("text",{fg:i?t.inverse:t.muted,wrapMode:"none",children:V.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var ob=D(()=>{Ee();be();Ye()});import{jsxDEV as tn}from"@opentui/react/jsx-dev-runtime";function ib(e){let{palette:t,route:n,termW:r,termH:o,scrollRef:i}=e;if(!n)return null;return tn(qe,{palette:t,title:n.name,bottomTitle:"j/k scroll \xB7 esc close",termW:r,termH:o,preferW:78,preferH:16,gap:1,children:tn("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:tn("box",{flexDirection:"column",overflow:"hidden",children:[tn("text",{fg:t.muted,children:`auth ${n.authType||"none"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`identity ${n.identityType||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`account ${n.serviceAccount||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`audience ${n.audience||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`match host ${n.matchHost||"*"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`match path ${n.matchPath||"*"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`upstream ${n.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 sb=D(()=>{be()});import{jsxDEV as Oc}from"@opentui/react/jsx-dev-runtime";function ab(e){let{palette:t,title:n,body:r,termW:o,termH:i,scrollRef:s}=e,a=r.length>400||r.split(`
627
- `).length>16;return Oc(qe,{palette:t,title:n,bottomTitle:"j/k scroll \xB7 esc close",termW:o,termH:i,preferW:a?88:76,preferH:a?24:16,gap:1,children:Oc("scrollbox",{ref:s,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Oc("box",{flexDirection:"column",overflow:"hidden",children:Oc("text",{fg:r===""?t.muted:t.text,wrapMode:"word",children:r===""?"(empty)":r},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var cb=D(()=>{be()});import{jsxDEV as Mt}from"@opentui/react/jsx-dev-runtime";function db(e){let{palette:t,items:n,query:r,selected:o,onQuery:i,onSubmit:s}=e,a=Ny(o,lb,n.length),c=n.slice(a,a+lb),l=Math.max(c.length,1),d=Hr(n,o);return Mt("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?Mt("box",{height:1,paddingLeft:1,overflow:"hidden",children:Mt("text",{fg:t.muted,children:"no matching command"},void 0,!1,void 0,this)},void 0,!1,void 0,this):c.map((f)=>{let g=f.name===d?.name;return Mt("box",{height:1,flexDirection:"row",overflow:"hidden",paddingLeft:1,paddingRight:1,backgroundColor:g?t.highlight:t.panel,children:[Mt("box",{width:14,flexShrink:0,overflow:"hidden",children:Mt("text",{fg:g?t.primary:t.text,wrapMode:"none",children:`${g?"\u203A":" "} /${f.name}`},void 0,!1,void 0,this)},void 0,!1,void 0,this),Mt("box",{flexGrow:1,overflow:"hidden",children:Mt("text",{fg:g?t.accent:t.muted,wrapMode:"none",children:f.desc},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},f.name,!0,void 0,this)}),Mt("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.highlight,paddingLeft:1,children:[Mt("box",{width:2,flexShrink:0,children:Mt("text",{fg:t.primary,children:"/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),Mt("box",{flexGrow:1,overflow:"hidden",children:Mt("input",{focused:!0,value:r,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 lb=8;var ub=D(()=>{Ee()});import{jsxDEV as gb}from"@opentui/react/jsx-dev-runtime";function mb(e){let{palette:t,themeName:n,selected:r,termW:o,termH:i,onIndex:s,onPreview:a,onPick:c}=e,l=yt.map((f)=>({name:f===n?`${f} (active)`:f,description:f===n?`${Uu[f]} \xB7 current`:Uu[f],value:f})),d=Fo(o,i,pb,fb,"center",!kn(se()));return gb(qe,{palette:t,title:"/themes",bottomTitle:"enter save \xB7 esc revert",termW:o,termH:i,preferW:pb,preferH:fb,children:gb("select",{height:Math.max(4,d.height-3),options:l,selectedIndex:r,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:(f)=>{s(f);let g=yt[f];if(g)a(g)},onSelect:(f,g)=>{let m=g?.value;if(typeof m==="string"&&m!=="")c(m)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var pb=52,fb=22;var hb=D(()=>{at();Ee();be();Cn();Ye()});import{jsxDEV as We}from"@opentui/react/jsx-dev-runtime";function Mc(e){let{palette:t,title:n,tone:r="muted",children:o}=e,i=r==="success"?t.success:r==="warning"?t.warning:r==="error"?t.error:t.border;return We("box",{border:!0,borderStyle:"rounded",borderColor:i,title:n,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function vb(e){let{palette:t,cfg:n,google:r,identity:o}=e;if(!r&&!o)return We(Ac,{palette:t,label:"Checking Application Default Credentials\u2026"},void 0,!1,void 0,this);let i=jE(n,o),s=o?.user||r?.userEmail||"",{project:a,source:c}=Wo(n,o,r),l=o?.adc??r?.adcAvailable===!0,d=o?.iap??(n?.proxy.routes??[]).some((v)=>v.auth.type.toLowerCase()==="iap"),f=i.filter((v)=>v.inactive!==!0),g=f.some((v)=>v.ok===!0),m=f.some((v)=>v.ok===!1),x=g?"AVAILABLE":m?"UNAVAILABLE":f.length>0?"NOT PROBED":i.length>0?"not required":"not configured";return We(tt,{palette:t,title:"identity",scroll:!0,children:[We(Mc,{palette:t,title:"Google identity",tone:l?"success":"warning",children:[We(Wr,{palette:t,label:"user",value:s||"(unknown)"},void 0,!1,void 0,this),We(Wr,{palette:t,label:"project",value:a||"(unset)"},void 0,!1,void 0,this),We(Wr,{palette:t,label:"source",value:c||"\u2014"},void 0,!1,void 0,this),We(Wr,{palette:t,label:"ADC",value:l?"\u2713 available":"\u2717 missing",tone:l?"success":"error"},void 0,!1,void 0,this),We(Wr,{palette:t,label:"gcloud",value:r?.gcloudInstalled?"\u2713 installed":"\u2717 not installed",tone:r?.gcloudInstalled?"success":"error"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),We(Mc,{palette:t,title:`Service accounts (${i.length})`,tone:f.length===0?"muted":g?"success":"warning",children:[i.length===0?We("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)=>We("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)),We("box",{height:1,flexShrink:0},void 0,!1,void 0,this),We(Wr,{palette:t,label:"impersonation",value:x,tone:g?"success":f.length>0?"warning":"muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),We(Mc,{palette:t,title:"IAP",tone:d?"success":"muted",children:[We("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:We(ge,{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?We("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?We(Mc,{palette:t,title:"ADC unavailable",tone:"warning",children:[We("text",{fg:t.text,wrapMode:"word",children:"Local services still start. Cloud identity, impersonation, and IAP need ADC."},void 0,!1,void 0,this),We("text",{fg:t.muted,wrapMode:"word",children:"/auth login suspends this screen and runs gcloud ADC login, then restores the TUI"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)}function jE(e,t){let n=new Map((e?ad(e):[]).map((i)=>[i.email,i.active])),r=t?.service_account_status??{};return[...new Set([...n.keys(),...Object.keys(r)])].sort((i,s)=>i.localeCompare(s)).map((i)=>{let s=r[i]??"unknown",a=n.get(i)===!1;return{email:i,inactive:a,ok:a||s==="unknown"?void 0:s==="available"}})}var yb=D(()=>{_t();Ee();be();br()});import{jsxDEV as ft}from"@opentui/react/jsx-dev-runtime";function xb(e){let{palette:t,credentials:n}=e;if(!n)return ft(Ac,{palette:t,label:"Reading credential store\u2026"},void 0,!1,void 0,this);let r=n.entries.filter((i)=>i.valid).length,o=n.entries.length-r;return ft(tt,{palette:t,title:"credentials",scroll:!0,children:[ft("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[ft(ge,{palette:t,label:`backend: ${n.backend}`,tone:"info"},void 0,!1,void 0,this),n.entries.length>0?ft(ge,{palette:t,label:`${r} valid`,tone:"success"},void 0,!1,void 0,this):null,o>0?ft(ge,{palette:t,label:`${o} expired`,tone:"warning"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ft("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),ft("box",{height:1,flexShrink:0},void 0,!1,void 0,this),n.entries.length===0?ft("text",{fg:t.muted,children:"no cached credentials"},void 0,!1,void 0,this):ft("box",{flexDirection:"column",overflow:"hidden",gap:1,children:n.entries.map((i)=>ft("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:[ft("text",{wrapMode:"none",children:[ft("span",{fg:i.valid?t.success:t.warning,children:i.valid?"\u2713 valid":"\u2717 expired"},void 0,!1,void 0,this),ft("span",{fg:t.muted,children:` \xB7 expires ${i.expires_at}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ft("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),ft(Tc,{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 bb=D(()=>{_t();be()});import{jsxDEV as A}from"@opentui/react/jsx-dev-runtime";function Cb(e){let{palette:t,cfg:n,width:r}=e,o=se();if(!n)return A($e,{palette:t,title:"No configuration",body:"Create .devctl/config.yaml or run setup."},void 0,!1,void 0,this);let i=Math.max(Go+8,r-6-o.pad*2),s=i>=sx,a=s?Math.floor((i-Sb)/2):i,c=Qy(n),l=Zy(n),d=ex(n),f=tx(n),g=nx(n);return A(tt,{palette:t,title:`config ${n.project.name||"unnamed"}`,children:[A(je,{palette:t,items:qy(n)},void 0,!1,void 0,this),A("box",{flexGrow:1,overflow:"hidden",children:A("scrollbox",{ref:e.scrollRef,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:A("box",{flexDirection:"column",overflow:"hidden",gap:kb,children:[A(dp,{wide:s,left:A(nn,{palette:t,title:"project",children:A(qo,{palette:t,facts:Vy(n,pt),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:"google",children:A(qo,{palette:t,facts:Jy(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(dp,{wide:s,left:A(nn,{palette:t,title:"runtime",children:A(qo,{palette:t,facts:zy(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:"logs",children:A(qo,{palette:t,facts:Yy(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:`proxy ${n.proxy.enabled?"enabled":"disabled"}`,children:[A(qo,{palette:t,facts:Xy(n),width:i},void 0,!1,void 0,this),A(WE,{palette:t,routes:l,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A(nn,{palette:t,title:`services ${c.length}`,children:A(BE,{palette:t,rows:c,width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:`tasks ${g.length}`,children:A(wb,{palette:t,rows:g,empty:"no tasks",width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(dp,{wide:s,left:A(nn,{palette:t,title:`profiles ${d.length}`,children:A(GE,{palette:t,rows:d,width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:`templates ${f.length}`,children:A(wb,{palette:t,rows:f,empty:"no templates",width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:"extras",children:A(qo,{palette:t,facts:ox(n),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),A(He,{palette:t,backgroundColor:t.element,edge:"top",children:A(De,{palette:t,hints:[{key:"v",label:"validate/save buffer"},{key:"e",label:"open in $EDITOR"},{key:"/diff",label:"config sources"},{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 dp(e){let{wide:t,left:n,right:r}=e;if(!t)return A("box",{flexDirection:"column",overflow:"hidden",gap:kb,flexShrink:0,children:[n,r]},void 0,!0,void 0,this);return A("box",{flexDirection:"row",overflow:"hidden",gap:Sb,flexShrink:0,children:[A("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:n},void 0,!1,void 0,this),A("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:r},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function nn(e){let{palette:t,title:n,children:r}=e;return A("box",{border:!0,borderStyle:"rounded",borderColor:t.border,title:n,titleColor:t.accent,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",flexShrink:0,children:r},void 0,!1,void 0,this)}function qo(e){let{palette:t,facts:n,width:r}=e,o=Math.max(4,r-Go-4);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((i)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:Go,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.muted,wrapMode:"none",children:X(i.label,Go)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:qE(t,i.tone),wrapMode:"none",children:X(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 BE(e){let{palette:t,rows:n,width:r}=e;if(n.length===0)return A($c,{palette:t,text:"no services"},void 0,!1,void 0,this);let o=ix(n),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:Ne(s.name,t),wrapMode:"none",children:X(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:ce(UE(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 WE(e){let{palette:t,routes:n,width:r}=e;if(n.length===0)return A($c,{palette:t,text:"no routes"},void 0,!1,void 0,this);let o=Math.min(Go+4,Math.max(8,...n.map((s)=>s.name.length))),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.primary,wrapMode:"none",children:X(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:ce(KE(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 GE(e){let{palette:t,rows:n,width:r}=e;if(n.length===0)return A($c,{palette:t,text:"no profiles"},void 0,!1,void 0,this);let o=Math.min(12,Math.max(8,...n.map((s)=>s.name.length))),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.primary,wrapMode:"none",children:X(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("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 wb(e){let{palette:t,rows:n,empty:r,width:o}=e;if(n.length===0)return A($c,{palette:t,text:r},void 0,!1,void 0,this);let i=Math.min(14,Math.max(8,...n.map((a)=>a.name.length))),s=Math.max(8,o-i-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((a)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:X(a.name,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:s,flexShrink:0,overflow:"hidden",children:A("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 $c(e){return A("box",{height:1,overflow:"hidden",children:A("text",{fg:e.palette.muted,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function UE(e){let t=e.extends==="\u2014"?"":` ${e.extends}`;return` ${e.ports} ${e.identity} ${e.health} ${e.restart} \u2190 ${e.depends}${t}`}function KE(e){return` ${e.auth} ${e.identity} ${e.match} \u2192 ${e.upstream}`}function qE(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 Sb=1,kb=1;var _b=D(()=>{_t();Bu();at();Ee();be();Ye()});import{useRef as VE}from"react";import{jsxDEV as me}from"@opentui/react/jsx-dev-runtime";function Ic(e){let{palette:t,names:n,snap:r,selected:o,checked:i,width:s,onOpen:a,onSelectIndex:c,onToggle:l}=e,d=se(),f=VE(!1),g=new Set(i),m=Ou(s),x=Du(s),v=Lu(s),S=Ov(s);return me("box",{flexDirection:"column",flexGrow:1,overflow:"hidden",children:[me("box",{height:1,flexDirection:"row",overflow:"hidden",children:[me(xt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:4,fg:t.accent,text:"sel"},void 0,!1,void 0,this),me(xt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:S,fg:t.muted,text:"name"},void 0,!1,void 0,this),me(xt,{width:vt,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:en,fg:t.muted,text:"state"},void 0,!1,void 0,this),v?me(xt,{width:Sn,fg:t.muted,text:"health"},void 0,!1,void 0,this):null,x?me(xt,{width:nc,fg:t.muted,text:"port"},void 0,!1,void 0,this):null,m?me(xt,{width:Jn,fg:t.muted,text:"pid"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),n.map((P,k)=>{let j=r?.services[P],V=jt(j),C=j?.health??"UNKNOWN",y=g.has(P),B=k===o,h=y?"[x]":"[ ]",q=B?"\u203A":" ";return me("box",{height:d.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:B?t.highlight:y?t.element:void 0,onMouseDown:()=>{if(f.current)return;if(B){a(P);return}c(k)},children:[me("box",{width:2,flexShrink:0,children:me("text",{fg:t.primary,children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:4,flexShrink:0,onMouseDown:()=>{f.current=!0,l?.(P),setTimeout(()=>{f.current=!1},0)},children:me("text",{fg:JE(t,y,B),children:h},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:2,flexShrink:0,children:me("text",{fg:Le(t,V),children:Ot(V)},void 0,!1,void 0,this)},void 0,!1,void 0,this),me(xt,{width:S,fg:B?t.primary:Ne(P,t),text:X(P,S)},void 0,!1,void 0,this),me(xt,{width:vt,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:en,fg:Le(t,V),text:V},void 0,!1,void 0,this),v?me(xt,{width:Sn,fg:Le(t,C),text:C},void 0,!1,void 0,this):null,x?me(xt,{width:nc,fg:t.text,text:jr(j)},void 0,!1,void 0,this):null,m?me(xt,{width:Jn,fg:t.text,text:j?.pid?String(j.pid):""},void 0,!1,void 0,this):null]},P,!0,void 0,this)})]},void 0,!0,void 0,this)}function Fc(e){let{palette:t,checked:n,idle:r,profileName:o}=e,i=n.length;if(i>0)return me(je,{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(r)return me(je,{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 me(je,{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 JE(e,t,n){if(t)return e.success;if(n)return e.primary;return e.muted}function xt(e){return me("box",{width:e.width,flexShrink:0,overflow:"hidden",children:me("text",{fg:e.fg,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var up=D(()=>{Ee();at();be();Ye()});import{useEffect as pp,useRef as Rb}from"react";import{jsxDEV as z,Fragment as eT}from"@opentui/react/jsx-dev-runtime";function Pb(e){let{palette:t,logs:n,names:r,logSources:o,service:i,paused:s,errorOnly:a,showSystemLogs:c,search:l,searchFocused:d,followTick:f,width:g,onSearch:m,onService:x,onToggleErrors:v,onToggleSystemLogs:S,onClearLogs:P,onSelect:k,wrapMode:j="focus",selected:V=-1,follow:C=!0,newer:y=0,viewStart:B=0,viewTotal:h,onLeaveLatest:q,onOpenExports:M,onJumpLatest:Y,view:ue,fullscreen:Ie=!1,facets:ct}=e,oe=se(),Ge=Fv(g,oe.pad,Ie),Re=c?n:n.filter((Ve)=>!Zi(Ve.source)),Qe=Bo(n,{service:i,services:e.services,errorOnly:a,search:l,regex:e.regex,source:e.source,systemLogs:c}),pe=ue??Qe,Se=h??Qe.length,$t=Math.min(Se,B+pe.length),N=Se===0?"empty":`${B+1}\u2013${$t} of ${Se}`,Rt=e.services??[],nt=Rt.length>0?Rt.join(","):i===""?"all services":i;return z("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[Ie?null:z(eT,{children:[z(je,{palette:t,items:[{text:s?"PAUSED":"LIVE",tone:s?"warning":"success"},{text:`shown ${Se}`,tone:"info"},{text:ct?`total ${ct.total}`:`total ${n.length}`},...ue&&Se>ue.length?[{text:`${B+1}\u2013${B+ue.length} / ${Se}`,tone:"info"}]:[],{text:nt,tone:i===""?"idle":"primary"},{text:zi(j),tone:j==="clip"?"idle":"accent"},...C?[]:[{text:y>0?`pinned \xB7 +${y} 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:S},...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:M}]},void 0,!1,void 0,this),z(mp,{palette:t,logs:Re,names:o??r,service:i,errorOnly:a,width:g,onService:x,onToggleErrors:v,facets:ct},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d?z("box",{height:1,paddingLeft:1,backgroundColor:t.highlight,overflow:"hidden",children:z("input",{focused:!0,value:l,placeholder:"search messages or service names",onInput:m,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,ue&&Se>pe.length?z(fp,{palette:t,start:B,count:pe.length,total:Se},void 0,!1,void 0,this):null,z("box",{flexGrow:1,border:!Ie,borderStyle:"rounded",borderColor:t.border,title:Ie?void 0:`logs ${nt} \xB7 ${N}`,titleColor:t.primary,padding:Ie?0:oe.pad,overflow:"hidden",children:pe.length===0?z($e,{palette:t,title:n.length===0?"No log events":"No events in this filter",body:n.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):z(hp,{palette:t,logs:pe,width:Ge,followTick:f,focused:!1,wrapMode:j,selected:V,follow:C,showTimestamps:e.showTimestamps!==!1,showMeta:e.showMeta!==!1,onPick:k,onLeaveLatest:q,viewStart:B},f,!1,void 0,this)},void 0,!1,void 0,this),z(He,{palette:t,backgroundColor:t.element,edge:"top",children:z(De,{palette:t,hints:Io([{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:y>0?`latest +${y}`:"latest"},{key:"w",label:"wrap"},{key:"p",label:"pause"},{key:"z",label:Ie?"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,g-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!C?z(gp,{palette:t,width:g,newer:y,onJump:Y},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function fp(e){let t=Math.min(e.total,e.start+e.count),n=Math.max(0,e.start),r=Math.max(0,e.total-t);return z(je,{palette:e.palette,items:[{text:`view ${e.start+1}\u2013${t} of ${e.total}`,tone:"primary"},{text:n>0?`\u2191 ${n} older`:"start of history",tone:n>0?"info":"idle"},{text:r>0?`\u2193 ${r} newer`:"at latest",tone:r>0?"warning":"success"}],hints:[{key:"pgup/pgdn",label:"move history window"},{key:"g",label:"latest"}]},void 0,!1,void 0,this)}function gp(e){let t=e.newer>0?`g jump to latest \xB7 ${e.newer} new`:"g jump to latest",n=Math.min(e.width,t.length+4);return z("box",{position:"absolute",left:Math.max(0,Math.floor((e.width-n)/2)),bottom:e.bottom??2,width:n,height:3,border:!0,borderStyle:"rounded",borderColor:e.palette.warning,backgroundColor:e.palette.panel,alignItems:"center",justifyContent:"center",onMouseDown:e.onJump,children:z("text",{wrapMode:"none",children:[z("span",{fg:e.palette.primary,children:"g"},void 0,!1,void 0,this),z("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 mp(e){let{palette:t,logs:n,names:r,service:o,errorOnly:i,width:s,onService:a,onToggleErrors:c,facets:l}=e,d=l?ky(r,l):Sy(r,n),f=s<80,g=d.map((S,P)=>{let k=P+1,j=S.name===""?"all":S.name;return{id:j,label:f?`${k} ${j}`:`${k} ${j} \xB7 ${S.count}`,color:Ne(S.name,t)}}),m=Math.max(0,d.findIndex((S)=>S.name===o)),x=i?"ERROR+":f?"lvls":"all levels",v=Math.max(qn(g[m]?.label??"1 all"),s-qn(x));return z(He,{palette:t,backgroundColor:t.element,children:z("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[z("box",{flexGrow:1,overflow:"hidden",children:z(Ec,{palette:t,items:g,active:m,width:v,onPick:(S)=>{let P=d[S];if(P)a(P.name)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),z(ge,{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 hp(e){let{palette:t,logs:n,limit:r,width:o=80,followTick:i=0,focused:s=!1,wrapMode:a="clip",selected:c=-1,follow:l=!0,showTimestamps:d=!0,showMeta:f=!0,onPick:g,onLeaveLatest:m,viewStart:x=0}=e,v=Rb(null),S=Rb(""),P=r===void 0?n:n.slice(-r),k=[...new Set(n.map((C)=>C.service))],j=Uv(o,k),V=Wv({width:o,serviceWidth:j,showTimestamps:d,showMeta:f});return pp(()=>{let C=v.current;if(!C)return;if(C.stickyScroll=l,l)C.stickyStart="bottom",C.scrollTo({x:C.scrollLeft,y:Math.max(0,C.scrollHeight)})},[l,i]),pp(()=>{let C=`${x}:${c}:${a}`;if(S.current===C)return;if(S.current=C,l&&(c<0||c>=P.length-1))return;let y=v.current;if(!y||c<0)return;let B=`log-row-${c}`,h=requestAnimationFrame(()=>{y.stickyScroll=!1,y.scrollChildIntoView(B)});return()=>cancelAnimationFrame(h)},[l,c,P.length,x,a]),pp(()=>{if(!l||!m)return;let C=!1,y=setTimeout(()=>{C=!0},zE),B=setInterval(()=>{let h=v.current;if(!C||!h)return;let q=h.viewport.height;if(q>0&&h.scrollTop+q<h.scrollHeight-XE)m()},YE);return()=>{clearTimeout(y),clearInterval(B)}},[l,i,m]),z("box",{flexGrow:1,height:"100%",overflow:"hidden",children:z("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:z("box",{flexDirection:"column",overflow:"hidden",children:P.map((C,y)=>z(QE,{id:`log-row-${y}`,palette:t,event:C,serviceWidth:j,msgWidth:V,expanded:Hv(a,y===c),active:y===c,showTimestamps:d,showMeta:f,onPick:g?()=>g(y):void 0},`${C.timestamp}-${C.service}-${y}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function QE(e){let{id:t,palette:n,event:r,serviceWidth:o,msgWidth:i,expanded:s,active:a,showTimestamps:c=!0,showMeta:l=!0,onPick:d}=e,f=Nv(uc(r.message,i),i,s);return z("box",{id:t,flexShrink:0,flexDirection:"column",overflow:"hidden",backgroundColor:a?n.highlight:void 0,onMouseDown:d,children:f.visible.map((g,m)=>z("box",{height:1,flexDirection:"row",overflow:"hidden",children:[c?z("box",{width:lc,flexShrink:0,overflow:"hidden",children:z("text",{fg:n.muted,children:m===0?r.timestamp.slice(11,19):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,z("box",{width:o,flexShrink:0,overflow:"hidden",children:z("text",{fg:m===0?Ne(r.service,n):n.muted,wrapMode:"none",children:m===0?X(r.service,o):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),z("box",{width:Ji,flexShrink:0,overflow:"hidden",children:z("text",{children:" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),z("box",{width:dc,flexShrink:0,overflow:"hidden",children:z("text",{fg:m===0?Le(n,r.level):n.muted,children:m===0?String(r.level):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),l?z("box",{width:ac,flexShrink:0,overflow:"hidden",children:z("text",{fg:n.muted,children:m===0&&r.source?X(r.source,ac):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,z("box",{width:Ji,flexShrink:0,overflow:"hidden",children:z("text",{fg:n.muted,children:m===0?" ":"\u2502"},void 0,!1,void 0,this)},void 0,!1,void 0,this),z("box",{flexGrow:1,overflow:"hidden",children:z(ZE,{palette:n,level:r.level,text:g,mark:m===0?f.mark:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${r.timestamp}-${m}`,!0,void 0,this))},void 0,!1,void 0,this)}function ZE(e){let{palette:t,level:n,text:r,mark:o}=e;return z("text",{wrapMode:"none",children:[Bv(r).map((i,s)=>z("span",{fg:lx(t,n,i.kind),children:i.text},`${i.kind}-${s}`,!1,void 0,this)),o===""?null:z("span",{fg:t.muted,children:o},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var zE=400,YE=200,XE=2;var vp=D(()=>{_t();at();Ee();be();Ye()});import{jsxDEV as ne}from"@opentui/react/jsx-dev-runtime";function Tb(e){let{palette:t,cfg:n,snap:r,logs:o,names:i,selected:s,selectedLog:a=-1,checked:c,profile:l,google:d,width:f,paused:g,followTick:m,logService:x,logSources:v,errorOnly:S,showSystemLogs:P,onOpen:k,onSelectIndex:j,onToggle:V,onFilterService:C,onToggleErrors:y,onToggleSystemLogs:B,onClearLogs:h,onShowErrors:q,wrapMode:M="clip",view:Y,follow:ue=!0,onLeaveLatest:Ie,onPickLog:ct,viewStart:oe=0,viewTotal:Ge,newer:Re=0,onJumpLatest:Qe,facets:pe,leftover:Se}=e,$t=se();if(!n||i.length===0)return ne($e,{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 N=f<Mo,Rt=jo(r),nt=mc(r,i),Ve=i.filter((Jo)=>r?.services[Jo]?.state==="FAILED").length,Bt=r?.session_id?Fs(r.session_id):void 0,lt=Bt?Ho(Date.now()-Bt.getTime()):void 0,er=xy(o),mt=l||fc(n),on=Gy(n,mt),sn=Rt?jy(Se,r?.session_id):void 0,an=pc(f,i,N),Ur=Math.max(24,N?f-4:f-an-4),_=P?o:o.filter((Jo)=>!Zi(Jo.source)),cn=Bo(o,{service:x,errorOnly:S,systemLogs:P}),Pn=Y??cn,Jt=Ge??cn.length,Kc=Math.min(Jt,oe+Pn.length),qc=Jt===0?"empty":`${oe+1}\u2013${Kc} of ${Jt}`,us=x===""?"all services":x;return ne("box",{flexGrow:1,flexDirection:N?"column":"row",overflow:"hidden",children:[ne("box",{flexGrow:N?1:0,flexShrink:0,minWidth:N?void 0:an,width:N?void 0:an,border:!0,borderStyle:"rounded",borderColor:Rt?t.border:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[ne(je,{palette:t,items:[{text:Nu(nt.running,i.length),tone:nt.running>0?"success":"idle"},...Ve>0?[{text:`${Ve} failed`,tone:"error"}]:[],...c.length>0?[{text:`${c.length} selected`,tone:"primary"}]:[],...lt!==void 0?[{text:`up ${lt}`,tone:"idle"}]:[],...er>0?[{text:`${er} errors`,tone:"error",onMouseDown:q}]:[]]},void 0,!1,void 0,this),ne(Fc,{palette:t,checked:c,idle:Rt,profileName:mt,members:on},void 0,!1,void 0,this),ne("box",{flexGrow:1,paddingLeft:$t.pad,paddingRight:$t.pad,overflow:"hidden",children:ne(Ic,{palette:t,names:i,snap:r,selected:s,checked:c,width:cc(an,$t.pad),onOpen:k,onSelectIndex:j,onToggle:V},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne(oT,{palette:t,names:i,snap:r,width:an,onOpen:k},void 0,!1,void 0,this),sn?ne(sT,{palette:t,leftover:sn,width:an},void 0,!1,void 0,this):null,ne(aT,{palette:t,cfg:n,snap:r,google:d,width:an},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ne("box",{position:"relative",flexGrow:2,minWidth:N?void 0:32,minHeight:N?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:`logs \xB7 ${qc}`,titleColor:t.primary,overflow:"hidden",flexDirection:"column",children:[ne(je,{palette:t,items:[{text:g?"PAUSED":"LIVE",tone:g?"warning":"success"},{text:`shown ${cn.length}`,tone:"info"},{text:pe?`total ${pe.total}`:`total ${o.length}`},{text:us,tone:x===""?"idle":"primary"},{text:S?"ERROR+":"all levels",tone:S?"error":"idle",onMouseDown:y},{text:P?"system: on":"system: off",tone:P?"accent":"idle",onMouseDown:B},{text:"clear",tone:"muted",onMouseDown:h}]},void 0,!1,void 0,this),ne(mp,{palette:t,logs:_,names:v??i,service:x,errorOnly:S,width:Ur,onService:C,onToggleErrors:y,facets:pe},void 0,!1,void 0,this),Jt>Pn.length?ne(fp,{palette:t,start:oe,count:Pn.length,total:Jt},void 0,!1,void 0,this):null,cn.length===0?ne($e,{palette:t,title:Rt?"Waiting for logs":o.length===0?"No events yet":"No events in this filter",body:Rt?"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):ne(hp,{palette:t,logs:Pn,width:Ur,followTick:m,focused:!1,wrapMode:M,selected:a,follow:ue,onLeaveLatest:Ie,onPick:ct,viewStart:oe},m,!1,void 0,this),ne(He,{palette:t,backgroundColor:t.element,edge:"top",children:ne(De,{palette:t,hints:Io([{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,Ur-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!ue?ne(gp,{palette:t,width:Ur,newer:Re,bottom:1,onJump:Qe},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function nT(e){if(!e)return!1;return e.state===Rr||e.health===Ce||e.state===Mi||e.restarts>0||e.last_error!==""}function Eb(e){if(e.state===Rr)return 0;if(e.health===Ce)return 1;if(e.state===Mi)return 2;return 3}function rT(e){if(e.last_error!=="")return e.last_error;if(e.restarts>0)return`restarted ${e.restarts}x, no error recorded`;return e.health===Ce?"failing health check":e.state.toLowerCase()}function oT(e){let{palette:t,names:n,snap:r,width:o,onOpen:i}=e,s=n.map((d)=>({name:d,rt:r?.services[d]})).filter((d)=>nT(d.rt)).sort((d,f)=>Eb(d.rt)-Eb(f.rt));if(s.length===0)return null;let a=s.slice(0,tT),c=s.length-a.length,l=Math.max(8,o-yp-4);return ne("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:f})=>{let g=jt(f);return ne("box",{height:1,flexDirection:"row",overflow:"hidden",onMouseDown:()=>i(d),children:[ne("box",{width:2,flexShrink:0,children:ne("text",{fg:Le(t,g),children:Ot(g)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:yp,flexShrink:0,overflow:"hidden",children:ne("text",{fg:Ne(d,t),wrapMode:"none",children:X(d,yp)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:l,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,wrapMode:"none",children:ce(rT(f),l)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)}),c>0?ne("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 sT(e){let{palette:t,leftover:n,width:r}=e,o=n.processes.slice(0,iT),i=n.processes.length-o.length,s=Math.max(8,r-xp-4);return ne("box",{border:!0,borderStyle:"rounded",borderColor:t.warning,title:"last session",titleColor:t.warning,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[ne("text",{fg:t.muted,wrapMode:"none",children:ce(`${n.session_id} ${n.profile||"(none)"}`,Math.max(8,r-4))},void 0,!1,void 0,this),o.map((a)=>ne("box",{height:1,flexDirection:"row",overflow:"hidden",children:[ne("box",{width:xp,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.text,wrapMode:"none",children:X(a.name,xp)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:s,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,wrapMode:"none",children:ce(`pid ${a.pid} leftover`,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${a.name}-${a.pid}`,!0,void 0,this)),i>0?ne("text",{fg:t.muted,wrapMode:"none",children:`+${i} more leftover pids`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function aT(e){let{palette:t,cfg:n,snap:r,google:o,width:i}=e,s=o?.userEmail,a=Wo(n,r?.identity,o).project,c=r?.logs.total??0,l=Uy(s,a,c,i);return ne(He,{palette:t,backgroundColor:t.element,edge:"top",children:ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:l.map((d,f)=>ne(ge,{palette:t,label:d.label,tone:d.tone},`${d.label}-${f}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var tT=4,yp=14,iT=4,xp=14;var Ab=D(()=>{Ee();at();be();_t();Ye();Pr();ze();up();vp()});import{useEffect as cT,useState as lT}from"react";import{jsxDEV as Q}from"@opentui/react/jsx-dev-runtime";function Db(e){let{palette:t,report:n,loading:r,progress:o,error:i,selected:s,onPick:a,onReload:c}=e,l=Ko(s,bp);if(r)return Q(dT,{palette:t,progress:o},void 0,!1,void 0,this);if(i)return Q(Cx,{palette:t,title:"Doctor failed",body:i},void 0,!1,void 0,this);if(!n)return Q($e,{palette:t,title:"Doctor",body:"Diagnostics have not run yet.",hint:"opening this screen runs doctor"},void 0,!1,void 0,this);let d=n.checks.filter((S)=>S.severity==="ok").length,f=n.checks.filter((S)=>S.severity==="warn").length,g=n.checks.filter((S)=>S.severity==="error").length,m=n.checks.length,x=Qi(m>0?d/m:0),v=g>0?t.error:f>0?t.warning:t.success;return Q(tt,{palette:t,title:`doctor ${n.issues} issue(s)`,children:[Q("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:[Q("text",{wrapMode:"none",children:[Q("span",{fg:t.inverse,bg:t.primary,children:" r "},void 0,!1,void 0,this),Q("span",{fg:t.primary,children:" RUN DOCTOR AGAIN"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q("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),Q("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Q("box",{height:1,flexShrink:0,overflow:"hidden",children:Q("text",{wrapMode:"none",children:[Q("span",{fg:v,children:`[${x}]`},void 0,!1,void 0,this),Q("span",{fg:t.success,children:` ${d} ok`},void 0,!1,void 0,this),f>0?Q("span",{fg:t.warning,children:` \xB7 ${f} warn`},void 0,!1,void 0,this):null,g>0?Q("span",{fg:t.error,children:` \xB7 ${g} error`},void 0,!1,void 0,this):null,f===0&&g===0?Q("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),Q("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Q("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Q("box",{flexDirection:"column",overflow:"hidden",gap:1,children:n.checks.map((S,P)=>Q(uT,{palette:t,check:S,index:P,active:P===s,onPick:a},`${S.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 dT({palette:e,progress:t}){let[n,r]=lT(0);return cT(()=>{let o=setInterval(()=>r((i)=>(i+1)%Lb.length),120);return()=>clearInterval(o)},[]),Q("box",{flexGrow:1,alignItems:"center",justifyContent:"center",overflow:"hidden",children:Q("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:[Q("text",{wrapMode:"none",children:[Q("span",{fg:e.primary,children:`${Lb[n]} `},void 0,!1,void 0,this),Q("span",{fg:e.text,children:"devctl doctor"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Q("text",{fg:e.text,wrapMode:"none",children:`Checking ${t.active}`},void 0,!1,void 0,this),Q("box",{height:1,flexShrink:0},void 0,!1,void 0,this),t.checks.slice(-4).map((o,i)=>Q("text",{wrapMode:"none",children:[Q("span",{fg:Le(e,o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK"),children:`${Ot(o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK")} `},void 0,!1,void 0,this),Q("span",{fg:e.muted,children:o.name},void 0,!1,void 0,this)]},`${o.name}-${i}`,!0,void 0,this)),t.checks.length===0?Q("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 uT(e){let{palette:t,check:n,index:r,active:o,onPick:i}=e,s=n.severity==="error"?"ERROR":n.severity==="warn"?"WARN":"OK";if(n.severity==="ok")return Q("box",{id:`${bp}-${r}`,flexDirection:"row",flexShrink:0,paddingLeft:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(r),children:Q("text",{wrapMode:"none",children:[Q("span",{fg:t.primary,children:o?"\u203A ":" "},void 0,!1,void 0,this),Q("span",{fg:Le(t,s),children:Ot(s)},void 0,!1,void 0,this),Q("span",{fg:o?t.primary:t.text,children:` ${n.name}`},void 0,!1,void 0,this),Q("span",{fg:t.muted,children:n.message?` \xB7 ${n.message}`:""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this);let c=n.severity==="error"?t.error:t.warning;return Q("box",{id:`${bp}-${r}`,border:!0,borderStyle:"rounded",borderColor:o?t.borderActive:c,title:n.name,titleColor:c,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(r),children:[Q("text",{wrapMode:"word",children:[Q("span",{fg:Le(t,s),children:`${Ot(s)} `},void 0,!1,void 0,this),Q("span",{fg:t.text,children:n.message},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n.hint?Q("text",{fg:t.info,wrapMode:"word",children:`\u2192 ${n.hint}`},void 0,!1,void 0,this):null,o&&n.action?.kind==="free-port"?Q("text",{fg:t.primary,wrapMode:"none",children:`enter stop ${n.action.holder.command} (pid ${n.action.holder.pid})`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var bp="doctor-row",Lb;var Ob=D(()=>{_t();Ee();be();Ye();Lb=["\u25D0","\u25D3","\u25D1","\u25D2"]});import{jsxDEV as Ae}from"@opentui/react/jsx-dev-runtime";function $b(e){let{palette:t,cfg:n,snap:r,profile:o,selected:i,onPick:s}=e,a=se(),c=Ko(i,Mb),l=Object.keys(n?.profiles??{}).sort();if(l.length===0)return Ae($e,{palette:t,title:"No profiles",body:"Add profiles.<name>.services in config.yaml."},void 0,!1,void 0,this);return Ae(tt,{palette:t,title:"profiles",children:[Ae("box",{height:1,flexShrink:0,overflow:"hidden",children:Ae("text",{fg:t.muted,wrapMode:"none",children:[`${l.length} profile${l.length===1?"":"s"} \xB7 current: `,Ae("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),Ae("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Ae("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Ae("box",{flexDirection:"column",overflow:"hidden",gap:a.gap||1,children:l.map((d,f)=>{let g=d===o,m=f===i,x=n?.profiles[d]?.services??[],v=Object.keys(n?.profiles[d]?.environment??{}).length,S=m?t.borderActive:g?t.success:t.border,P=m?t.primary:g?t.success:t.muted;return Ae("box",{id:`${Mb}-${f}`,border:!0,borderStyle:"rounded",borderColor:S,title:d,titleColor:P,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:m?t.highlight:void 0,onMouseDown:()=>s(f),children:[Ae("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:Ae("text",{wrapMode:"none",children:[g?Ae("span",{fg:t.success,children:"\u25CF current profile"},void 0,!1,void 0,this):Ae("span",{fg:t.muted,children:"\u25CB not active"},void 0,!1,void 0,this),Ae("span",{fg:t.muted,children:` \xB7 ${x.length} service${x.length===1?"":"s"}`},void 0,!1,void 0,this),v>0?Ae("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),Ae("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:x.length===0?Ae("text",{fg:t.muted,wrapMode:"none",children:"(no services)"},void 0,!1,void 0,this):Ae("text",{wrapMode:"none",children:x.map((k,j)=>{let V=jt(r?.services[k]);return Ae("span",{children:[Ae("span",{fg:Le(t,V),children:Ot(V)},void 0,!1,void 0,this),Ae("span",{fg:Ne(k,t),children:` ${k}`},void 0,!1,void 0,this),j<x.length-1?Ae("span",{fg:t.muted,children:" "},void 0,!1,void 0,this):null]},k,!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),Ae(He,{palette:t,backgroundColor:t.element,edge:"top",children:Ae(De,{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 Mb="profile-row";var Ib=D(()=>{_t();at();Ee();be();Ye()});import{jsxDEV as G,Fragment as jb}from"@opentui/react/jsx-dev-runtime";function pT(e){let t=e.toLowerCase();if(t==="iap")return"info";if(t==="service"||t==="service_account")return"primary";return"idle"}function fT(e,t,n){if(n||t>=500)return e.error;if(t===0||t>=400)return e.warning;return e.success}function gT(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 yT(e){let{palette:t,req:n,cols:r}=e,o=fT(t,n.status,n.error),i=n.status>0?String(n.status):"ERR",s=gT(t,n.identity),a=n.route||Bb,c=n.error?`${n.path} \u2014 ${ce(n.error,vT)}`:n.path;return G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[G("box",{width:wp,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:n.timestamp.slice(11,19)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showMethod?G("box",{width:Nc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.text,wrapMode:"none",children:X(n.method,Nc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Hc,flexShrink:0,overflow:"hidden",children:G("text",{fg:o,wrapMode:"none",children:X(i,Hc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showDur?G("box",{width:jc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,wrapMode:"none",children:X(`${n.durationMs}ms`,jc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Bc,flexShrink:0,overflow:"hidden",children:G("text",{fg:s.color,wrapMode:"none",children:X(s.label,Bc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{width:r.routeCol,flexShrink:0,overflow:"hidden",children:G("text",{fg:n.route?t.info:t.muted,wrapMode:"none",children:X(a,r.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{flexGrow:1,overflow:"hidden",children:G("text",{fg:n.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 xT(e){let{palette:t,cols:n}=e;return G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[G("box",{width:wp,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("TIME",wp)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showMethod?G("box",{width:Nc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("METHOD",Nc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Hc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("ST",Hc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showDur?G("box",{width:jc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("DUR",jc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Bc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("WHO",Bc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{width:n.routeCol,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:X("ROUTE",n.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{flexGrow:1,overflow:"hidden",children:G("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 bT(e){let{palette:t,name:n,auth:r,identity:o,upstream:i,match:s,onMouseDown:a}=e;return G("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",onMouseDown:a,children:[G("text",{fg:t.text,wrapMode:"none",children:n},void 0,!1,void 0,this),G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[G(ge,{palette:t,label:r||"no auth",tone:pT(r)},void 0,!1,void 0,this),o?G(ge,{palette:t,label:o,tone:"idle"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),s?G("text",{fg:t.muted,wrapMode:"word",children:`match: ${s}`},void 0,!1,void 0,this):null,G("text",{fg:t.muted,wrapMode:"word",children:`\u2192 ${i}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Wb(e){let{palette:t,cfg:n,snap:r,width:o,onSelectRoute:i}=e,s=r?.proxy.routes??[],a=new Map((n?.proxy.routes??[]).map((C)=>[C.name,C])),c=new Map((n?.proxy.routes??[]).map((C)=>[C.name,C.match])),l=r?.proxy.recentRequests??[],d=r?.proxy.requestTotal??0,f=r?.proxy.requestErrors??0,g=o<Mo,m=Math.max(Fb,Math.min(wT,Math.floor(o*0.36))),x=g?o-Nb:o-m-Nb,v=Math.max(20,x-2),S=v>=Hb,P=v>=ST,k=v>=Hb?kT:CT,j=l.reduce((C,y)=>Math.min(k,Math.max(C,(y.route||Bb).length+hT)),mT),V={showMethod:S,showDur:P,routeCol:j};return G(tt,{palette:t,title:"proxy",children:[G(je,{palette:t,items:[{text:r?.proxy.running?"RUNNING":"STOPPED",tone:r?.proxy.running?"success":"idle"},...r?.proxy.address?[{text:r.proxy.address,tone:"info"}]:[],{text:`${s.length} routes`,tone:s.length>0?"primary":"idle"},...d>0?[{text:`${d} requests`,tone:"idle"},...f>0?[{text:`${f} errors`,tone:"warning"}]:[]]:[]]},void 0,!1,void 0,this),G("box",{flexGrow:1,flexDirection:g?"column":"row",overflow:"hidden",children:[G("box",{flexGrow:g?1:0,flexBasis:g?0:void 0,flexShrink:0,minWidth:g?void 0:Fb,width:g?void 0:m,minHeight:g?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?G($e,{palette:t,title:"No proxy routes",body:"Add routes under proxy.routes or .devctl/proxy/routes.yaml."},void 0,!1,void 0,this):G(jb,{children:[i?G("text",{fg:t.muted,wrapMode:"word",children:"click a route for full details"},void 0,!1,void 0,this):null,G("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:G("box",{flexDirection:"column",overflow:"hidden",gap:1,children:s.map((C)=>{let y=c.get(C.name),B=y&&(y.host||y.path)?`${y.host||"*"}${y.path?y.path:""}`:void 0,h=a.get(C.name);return G(bT,{palette:t,name:C.name,auth:C.auth,identity:C.identity,upstream:C.upstream,match:B,onMouseDown:i?()=>i({name:C.name,authType:h?.auth.type||C.auth,identityType:h?.auth.identity.type??"",serviceAccount:h?.auth.identity.service_account||h?.auth.service_account||"",audience:h?.auth.audience??"",matchHost:h?.match.host??"",matchPath:h?.match.path??"",upstream:C.upstream}):void 0},C.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),G("box",{flexGrow:1,flexBasis:0,minWidth:g?void 0:30,minHeight:g?10:void 0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,title:"requests",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:l.length===0?G("box",{paddingLeft:1,paddingRight:1,children:G("text",{fg:t.muted,wrapMode:"word",children:r?.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):G(jb,{children:[G(xT,{palette:t,cols:V},void 0,!1,void 0,this),G("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:G("box",{flexDirection:"column",overflow:"hidden",children:l.map((C)=>G(yT,{palette:t,req:C,cols:V},C.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),G(He,{palette:t,backgroundColor:t.element,edge:"top",children:G(De,{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 wp=9,Nc=8,Hc=4,jc=8,Bc=4,mT=8,hT=2,vT=64,Bb="(none)",Fb=26,wT=56,Nb=2,Hb=46,ST=54,kT=20,CT=12;var Gb=D(()=>{_t();Ee();be()});import{jsxDEV as re}from"@opentui/react/jsx-dev-runtime";function qb(e){let{palette:t,name:n}=e;return re("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:n,titleColor:Ne(n,t),flexDirection:"column",overflow:"hidden",children:re(Sp,{...e,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Sp(e){let{palette:t,cfg:n,snap:r,name:o,reveal:i,width:s,compact:a=!0,envScrollRef:c}=e,l=se(),d=n?.services[o];if(!d)return re($e,{palette:t,title:"Unknown service",body:`No service named ${o}.`,hint:"j/k move"},void 0,!1,void 0,this);let f=r?.services[o],g=jt(f),m=f?.health??"UNKNOWN",x=jr(f)||rs(d,f),v=Hy(d,i,n?.secrets.extra_markers??[],n?.secrets.extra_patterns??[],e.resolvedEnv),S=e.envStatus==="error"?"error":e.envStatus==="resolved"?"success":e.envStatus==="loading"?"info":"muted",P=e.envStatus==="resolved"?"resolved":e.envStatus==="loading"?"resolving":e.envStatus==="error"?"config fallback":"config",k=s>=RT,j=[{label:"health",value:xc(d)},{label:"workdir",value:d.working_dir||"."},{label:"restart",value:wc(d)},{label:"caps",value:d.capabilities.join(", ")||"\u2014"},{label:"runtime",value:d.container?`${d.container.runtime||"docker"} \xB7 ${d.container.image}`:"host"}],V=[{label:"identity",value:bc(d,f)},{label:"depends",value:d.dependencies.map(Hs).join(", ")||"\u2014"},{label:"ports",value:rs(d,f)},{label:"tries",value:String(f?.restarts??0),tone:f?.restarts?"warning":"muted"}],C=Math.max(Gr+8,s-2),y=k?Math.floor(C/2):C;return re("box",{padding:l.pad,flexGrow:1,flexDirection:"column",overflow:"hidden",children:[re(je,{palette:t,items:[{text:g,tone:Kb(g)},{text:m,tone:Kb(m)},{text:f?.pid?`pid ${f.pid}`:"pid \u2014",tone:f?.pid?"info":"idle"},{text:x==="\u2014"?"port \u2014":`port ${x}`,tone:x==="\u2014"?"idle":"info"}]},void 0,!1,void 0,this),d.description?re("box",{height:1,overflow:"hidden",children:re("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,f?.last_error?re("box",{height:1,overflow:"hidden",children:re("text",{fg:t.error,wrapMode:"none",children:ce(f.last_error,_T)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,re(kp,{palette:t,item:{label:"command",value:yc(d)},valueWidth:Math.max(8,C-Gr)},void 0,!1,void 0,this),re(PT,{palette:t,left:j,right:V,wide:k,colWidth:y},void 0,!1,void 0,this),re(ET,{palette:t,entries:v,reveal:i,width:s,focused:!a,scrollRef:c,source:P,sourceTone:S,error:e.envError},void 0,!1,void 0,this),a?null:re(De,{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 PT(e){let{palette:t,left:n,right:r,wide:o,colWidth:i}=e,s=Math.max(4,i-Gr);if(!o)return re("box",{width:i,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[...n,...r].map((a)=>re(kp,{palette:t,item:a,valueWidth:s},a.label,!1,void 0,this))},void 0,!1,void 0,this);return re("box",{height:n.length,flexShrink:0,flexDirection:"row",overflow:"hidden",children:[re(Ub,{palette:t,items:n,width:i},void 0,!1,void 0,this),re(Ub,{palette:t,items:r,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ub(e){let t=Math.max(4,e.width-Gr);return re("box",{width:e.width,flexShrink:0,flexDirection:"column",overflow:"hidden",children:e.items.map((n)=>re(kp,{palette:e.palette,item:n,valueWidth:t},n.label,!1,void 0,this))},void 0,!1,void 0,this)}function kp(e){let{palette:t,item:n,valueWidth:r}=e,o=n.tone==="warning"?t.warning:n.tone==="muted"?t.muted:t.text;return re("box",{height:1,width:Gr+r,flexDirection:"row",overflow:"hidden",children:[re("box",{width:Gr,flexShrink:0,overflow:"hidden",children:re("text",{fg:t.muted,wrapMode:"none",children:X(n.label,Gr)},void 0,!1,void 0,this)},void 0,!1,void 0,this),re("box",{width:r,flexShrink:0,overflow:"hidden",children:re("text",{fg:o,wrapMode:"none",children:X(n.value,r)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ET(e){let{palette:t,entries:n,reveal:r,width:o,focused:i,scrollRef:s,source:a,sourceTone:c,error:l}=e,d=By(o),f=Math.max(8,o-d-4);return re("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[re(je,{palette:t,items:[{text:`env ${n.length}`,tone:n.length>0?"info":"idle"},{text:a,tone:c},{text:r?"secrets shown":"redacted",tone:r?"warning":"muted"}],hints:i?[{key:"j/k",label:"scroll"}]:[{key:"/reveal",label:"secrets"}]},void 0,!1,void 0,this),l?re("box",{height:1,overflow:"hidden",children:re("text",{fg:t.warning,wrapMode:"none",children:ce(l,Math.max(8,o-4))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,n.length===0?re("text",{fg:t.muted,children:"no service env overrides"},void 0,!1,void 0,this):re("box",{flexGrow:1,height:"100%",overflow:"hidden",children:re("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:re("box",{flexDirection:"column",overflow:"hidden",children:n.map((g)=>re("box",{height:1,flexDirection:"row",overflow:"hidden",children:[re("box",{width:d,flexShrink:0,overflow:"hidden",children:re("text",{fg:g.required?t.warning:t.muted,wrapMode:"none",children:X(g.required?`${g.key}*`:g.key,d)},void 0,!1,void 0,this)},void 0,!1,void 0,this),re("box",{width:f,flexShrink:0,overflow:"hidden",children:re("text",{fg:g.value===""?t.muted:t.text,wrapMode:"none",children:X(g.value===""&&g.required?"(required)":g.value,f)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},g.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 Kb(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 _T=72,RT=56,Gr=9;var Cp=D(()=>{Ee();_t();at();be();Ye();st()});import{jsxDEV as Zn}from"@opentui/react/jsx-dev-runtime";function Vb(e){let{palette:t,cfg:n,names:r,snap:o,selected:i,checked:s,width:a,reveal:c,onOpen:l,onSelectIndex:d,onToggle:f,resolvedEnv:g,envStatus:m,envError:x}=e;if(r.length===0)return Zn($e,{palette:t,title:"No services",body:"This configuration does not define any services."},void 0,!1,void 0,this);let v=a<Mo,S=r[i]??"",P=pc(a,r,v),k=4,j=v?Math.max(_p,a-k):Math.max(_p,a-P-k);return Zn("box",{flexGrow:1,flexDirection:v?"column":"row",overflow:"hidden",children:[Zn("box",{flexGrow:v?1:0,flexShrink:0,minWidth:v?void 0:ec,width:v?void 0:P,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[Zn(Fc,{palette:t,checked:s,idle:jo(o),profileName:"",members:""},void 0,!1,void 0,this),Zn("box",{flexGrow:1,overflow:"hidden",children:Zn(Ic,{palette:t,names:r,snap:o,selected:i,checked:s,width:cc(P),onOpen:l,onSelectIndex:d,onToggle:f},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zn("box",{flexGrow:2,minWidth:v?void 0:_p,minHeight:v?TT:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:S||"detail",titleColor:S?Ne(S,t):t.primary,overflow:"hidden",flexDirection:"column",children:Zn(Sp,{palette:t,cfg:n,snap:o,name:S,reveal:c,width:j,resolvedEnv:g,envStatus:m,envError:x},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var _p=36,TT=12;var Jb=D(()=>{_t();Ee();Ye();Cp();up()});import{jsxDEV as he}from"@opentui/react/jsx-dev-runtime";function LT(e){switch(e){case"cycle":return"\u2194";case"toggle":return"\u23FB";case"page":return"\u25B8";case"action":return"!";default:return"\xB7"}}function Qb(e){let{palette:t,items:n,selected:r,locked:o,width:i,onPick:s,onActivate:a}=e,c=se(),l=Yu(n,r),d=Uo(n,l);return he("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"settings",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[he("box",{height:2,paddingLeft:c.pad,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[he("text",{fg:t.primary,wrapMode:"none",children:"Preferences"},void 0,!1,void 0,this),he("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),he("box",{flexGrow:1,paddingLeft:c.pad,paddingRight:c.pad,overflow:"hidden",flexShrink:1,children:he(DT,{palette:t,items:n,active:l,scale:c,width:i,onPick:s,onActivate:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),he(MT,{palette:t,item:d,scale:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function DT(e){let{palette:t,items:n,active:r,scale:o,width:i,onPick:s,onActivate:a}=e,c=Ko(r,Xb),l=Math.max(8,i-zb-Yb-10),d=0,f=vx(n);return he("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:he("box",{flexDirection:"column",overflow:"hidden",children:f.map((g,m)=>{let x=d;d+=g.items.length;let v=r>=x&&r<x+g.items.length;return he("box",{border:!0,borderStyle:"rounded",borderColor:v?t.borderActive:t.border,title:`${g.group} (${g.items.length})`,titleColor:v?t.primary:t.muted,flexDirection:"column",flexShrink:0,marginBottom:m<f.length-1?Math.max(1,o.gap):0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[g.group==="MCP"?he("box",{height:1,overflow:"hidden",children:he("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,g.items.map((S,P)=>{let k=x+P;return he(OT,{index:k,palette:t,item:S,active:k===r,rowH:o.rowH,valueWidth:l,onPick:()=>s(k),onActivate:()=>a(S)},S.id,!1,void 0,this)})]},g.group,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function OT(e){let{palette:t,index:n,item:r,active:o,rowH:i,valueWidth:s,onPick:a,onActivate:c}=e;return he("box",{id:`${Xb}-${n}`,height:i,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:o?t.highlight:void 0,onMouseDown:()=>{if(o){c();return}a()},children:[he("box",{width:2,flexShrink:0,overflow:"hidden",children:he("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:Yb,flexShrink:0,overflow:"hidden",children:he("text",{fg:o?t.primary:t.muted,children:LT(r.kind)},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:zb,flexShrink:0,overflow:"hidden",children:he("text",{fg:o?t.primary:t.text,wrapMode:"none",children:r.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{flexGrow:1,overflow:"hidden",children:he("text",{fg:$T(t,r,o),wrapMode:"none",children:ce(r.value,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function MT(e){let{palette:t,item:n,scale:r}=e,o=n?.id==="font",i=n?.kind==="page"?`${n.name} \u2192 dedicated page`:n?.name??"";return he("box",{height:AT,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"selected",titleColor:t.muted,backgroundColor:t.element,paddingLeft:r.pad,paddingRight:r.pad,flexDirection:"column",overflow:"hidden",children:[he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.primary,wrapMode:"none",children:o?`${mx(r.steps)} ${r.label}`:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.text,wrapMode:"word",children:n?.detail??""},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.muted,wrapMode:"none",children:n?n.kind==="info"?"read-only":n.hint:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $T(e,t,n){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 n?e.primary:e.text}var zb=14,Yb=2,AT=5,Xb="settings-row";var Zb=D(()=>{at();Ee();be();Cn()});import{useEffect as IT,useState as FT}from"react";import{jsxDEV as J}from"@opentui/react/jsx-dev-runtime";function Vo(e){let{palette:t,title:n,tone:r="muted",children:o}=e,i=r==="success"?t.success:r==="warning"?t.warning:r==="error"?t.error:t.border;return J("box",{border:!0,borderStyle:"rounded",borderColor:i,title:n,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Rp(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 ds(e){let{palette:t,cells:n,header:r,gap:o=0,stripe:i}=e;return J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:i?t.element:void 0,children:n.map((s,a)=>J("box",{flexDirection:"row",flexShrink:0,overflow:"hidden",children:[a>0&&o>0?J("box",{width:o,flexShrink:0},void 0,!1,void 0,this):null,J("box",{width:s.width,flexShrink:0,overflow:"hidden",children:J("text",{fg:r?t.primary:Rp(t,s),wrapMode:"none",children:X(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 ew(e){let{palette:t,width:n}=e;return J("box",{height:1,flexShrink:0,overflow:"hidden",children:J("text",{fg:t.border,wrapMode:"none",children:X("\u2500".repeat(Math.max(1,n)),n)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ls(e){let{palette:t,facts:n,width:r}=e,o=Fu(n,r),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}),J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(ds,{palette:t,header:!0,gap:No,cells:i},void 0,!1,void 0,this),J(ew,{palette:t,width:r},void 0,!1,void 0,this),n.map((s,a)=>{let c=s.meaning===""?[""]:uc(s.meaning,Math.max(1,o.meaning)),l=s.meter?ry(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"}),J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(ds,{palette:t,gap:No,stripe:a%2===1,cells:d},void 0,!1,void 0,this),c.slice(1).map((f,g)=>{let m=[{text:"",width:o.what},{text:"",width:o.reading}];if(o.meter>0)m.push({text:"",width:o.meter});return m.push({text:f,width:o.meaning,tone:"muted"}),J(ds,{palette:t,gap:No,stripe:a%2===1,cells:m},`${s.what}-more-${g}`,!1,void 0,this)})]},`${s.what}-${s.reading}-${a}`,!0,void 0,this)})]},void 0,!0,void 0,this)}function tw(e){let{palette:t,cfg:n,snap:r,width:o,onRefresh:i}=e,s=se(),[,a]=FT(0);if(IT(()=>{let Re=setInterval(()=>{a((Qe)=>{let pe=Qe+1;if(i&&pe%HT===0)i();return pe})},NT);return()=>clearInterval(Re)},[i]),!n)return J($e,{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(n.services).sort(),l=c.some((Re)=>oy(n.services[Re])),d=Yv(c,r),f=uy(d,l),g=l&&d.live>0?d.healthy/d.live:d.total>0?d.live/d.total:0,m=Qi(g,jT),x=d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",v=ey(o,s.pad),S=r?.session_id?Fs(r.session_id):void 0,P=S?Ho(Date.now()-S.getTime()):"just started",k=r?.logs.total??0,j=r?.logs.errors??0,V=Zv(r?.logs.counts??{}),C=r?.proxy.routes??[],y=r?.credentials,B=(y?.entries??[]).filter((Re)=>Re.valid).length,h=r?.system,q=h?h.memAvailableKB??h.memFreeKB:0,M=h?sy(h.loadAvg1,h.cpuCount):void 0,Y=h?ay(q,h.memTotalKB):void 0,ue=[];if(h&&M&&Y)ue.push(M,Y,{what:"Computer",reading:iy(h.platform),meaning:`on for ${Ho(h.hostUptimeSec*BT)}`,tone:"text"});let Ie=d.failed>0||M?.tone==="error"||Y?.tone==="error"?"error":x==="warning"||M?.tone==="warning"||Y?.tone==="warning"?"warning":"success",ct=[{what:"This session",reading:P,meaning:"how long this run has been going",tone:"text"},{what:"Profile",reading:r?.profile||"none",meaning:"which group of services is selected",tone:r?.profile?"text":"muted"},{what:"This window",reading:r?.detached?"closed":"watching",meaning:r?.detached?"services keep running without this screen":"you are watching the services from here",tone:r?.detached?"warning":"text"},{what:"Project folder",reading:"",meaning:n.repoRoot,tone:"muted"}],oe=[{what:"Lines kept",reading:String(k),meaning:"log lines still in memory",tone:"text"},{what:"Error lines",reading:String(j),meaning:j>0?"open Logs and press e to see only errors":"no ERROR or FATAL lines",tone:j>0?"error":"muted"},...V.map(([Re,Qe])=>({what:Re,reading:String(Qe),meaning:"lines from this service",tone:"text"}))],Ge=[{what:"Web proxy",reading:r?.proxy.running?"on":"off",meaning:r?.proxy.running?`${C.length} apps${r.proxy.address?` at ${r.proxy.address}`:""}`:"not forwarding local URLs",tone:r?.proxy.running?"success":"muted"},{what:"Agent tools",reading:r?.mcp?.running?"on":"off",meaning:r?.mcp?.address?`Cursor talks to devctl at ${r.mcp.address}`:"turn on from Settings \u2192 MCP",tone:r?.mcp?.running?"success":"muted"},{what:"Google account",reading:r?.identity.user?"signed in":"not signed in",meaning:[r?.identity.user,r?.identity.project].filter(Boolean).join(" \xB7 ")||"no Google user for this session",tone:r?.identity.user?"success":"muted"},{what:"Saved tokens",reading:y?`${B} of ${y.entries.length} good`:"none",meaning:y?dy(y.backend):"nothing stored yet",tone:y&&B<y.entries.length?"warning":y?"success":"muted"}];return J(tt,{palette:t,title:"stats",scroll:!0,children:[J(Vo,{palette:t,title:`Your services ${d.live} of ${d.total} started`,tone:Ie,children:[J(ls,{palette:t,facts:f,width:v},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:J("text",{wrapMode:"none",children:[J("span",{fg:t.muted,children:X(l?"Ready":"Started",Fu(f,v).what)},void 0,!1,void 0,this),J("span",{children:" ".repeat(No)},void 0,!1,void 0,this),J("span",{fg:Rp(t,{text:"",width:1,tone:x}),children:`[${m}]`},void 0,!1,void 0,this),J("span",{fg:Rp(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),h?J(Vo,{palette:t,title:"This computer",tone:M?.tone==="error"||Y?.tone==="error"?"error":M?.tone==="warning"||Y?.tone==="warning"?"warning":"success",children:J(ls,{palette:t,facts:ue,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,J(Vo,{palette:t,title:"This session",children:J(ls,{palette:t,facts:ct,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),J(Vo,{palette:t,title:"Each service",tone:d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",children:d.total===0?J("text",{fg:t.muted,children:"No services in this project yet."},void 0,!1,void 0,this):J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(WT,{palette:t,names:c,snap:r,width:v},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("text",{fg:t.muted,wrapMode:"none",children:X("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),J(Vo,{palette:t,title:"Log lines",tone:j>0?"warning":"muted",children:J(ls,{palette:t,facts:oe,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),J(Vo,{palette:t,title:"Other parts",children:J(ls,{palette:t,facts:Ge,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function WT(e){let{palette:t,names:n,snap:r,width:o}=e,i=ty(o),s=[{text:"service",width:i.name},{text:"status",width:en}];if(i.health)s.push({text:"check",width:Sn});if(i.cpu)s.push({text:"cpu",width:oc});if(i.mem)s.push({text:"ram",width:ic});if(i.up)s.push({text:"up",width:rc});if(i.rst)s.push({text:"restarts",width:hc});if(i.pid)s.push({text:"pid",width:Jn});return J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(ds,{palette:t,header:!0,gap:vt,cells:s},void 0,!1,void 0,this),J(ew,{palette:t,width:o},void 0,!1,void 0,this),n.map((a,c)=>J(qT,{palette:t,name:a,rt:r?.services[a],cols:i,stripe:c%2===1},a,!1,void 0,this))]},void 0,!0,void 0,this)}function KT(e){if(e===void 0)return"muted";if(e>UT)return"error";if(e>GT)return"warning";return"text"}function qT(e){let{palette:t,name:n,rt:r,cols:o,stripe:i}=e,s=cy(r),a=ly(r),c=r?.restarts??0,l=[{text:n,width:o.name,color:Ne(n,t)},{text:s,width:en,color:Le(t,r?.state??"STOPPED")}];if(o.health)l.push({text:a,width:Sn,color:Le(t,r?.health??"UNKNOWN")});if(o.cpu)l.push({text:r?.cpuPercent!==void 0?py(r.cpuPercent):"\u2014",width:oc,tone:KT(r?.cpuPercent)});if(o.mem)l.push({text:r?.memoryKB!==void 0?tc(r.memoryKB):"\u2014",width:ic,tone:"text"});if(o.up)l.push({text:Qv(r),width:rc,tone:"text"});if(o.rst)l.push({text:String(c),width:hc,tone:c>0?"warning":"muted"});if(o.pid)l.push({text:r?.pid?String(r.pid):"\u2014",width:Jn,tone:"muted"});return J("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",children:[J(ds,{palette:t,gap:vt,stripe:i,cells:l},void 0,!1,void 0,this),r?.last_error?J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:J("text",{fg:t.error,wrapMode:"none",children:X(` ${r.last_error}`,Math.max(24,o.name+vt+en+Sn))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var NT=1000,HT=5,jT=16,BT=1000,GT=80,UT=100;var nw=D(()=>{_t();Ee();at();be();Ye();ze()});import{jsxDEV as ye}from"@opentui/react/jsx-dev-runtime";function rw(e){let{palette:t,cfg:n,google:r,bootError:o,bootErrorMissing:i=!1,step:s=0}=e,a=se();if(o&&!n)return i?ye($e,{palette:t,title:"No configuration found",body:"Would you like to run setup?",hint:"[Enter] Setup [Esc] Exit"},void 0,!1,void 0,this):ye($e,{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=n?Xt(n):["configuration not loaded"],l=VT(n,r,c),d=l.filter((k)=>k.ok).length,f=l.length,g=f>0?Math.round(d/f*100):0,m=20,x=Math.round(g/100*m),v="\u2588".repeat(x)+"\u2591".repeat(Math.max(0,m-x)),S=g===100?t.success:g===0?t.muted:t.primary,P=l[s];return ye(tt,{palette:t,title:"setup",scroll:!0,children:[ye("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye("text",{fg:t.primary,children:"Developer onboarding"},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye("text",{wrapMode:"none",children:[ye("span",{fg:S,children:`[${v}]`},void 0,!1,void 0,this),ye("span",{fg:t.text,children:` ${d}/${f} ready`},void 0,!1,void 0,this),ye("span",{fg:t.muted,children:` (${g}%)`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),l.map((k,j)=>{let V=j===s;return ye("box",{height:a.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:V?t.highlight:void 0,paddingLeft:1,children:[ye("box",{width:2,flexShrink:0,children:ye("text",{fg:Le(t,k.ok?"OK":"WARN"),children:Ot(k.ok?"OK":"WARN")},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{width:3,flexShrink:0,children:ye("text",{fg:V?t.primary:t.muted,children:String(j+1).padStart(2," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{width:20,flexShrink:0,overflow:"hidden",children:ye("text",{fg:V?t.primary:t.text,children:k.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{flexGrow:1,overflow:"hidden",children:ye("text",{fg:V?t.text:t.muted,wrapMode:"none",children:k.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},k.name,!0,void 0,this)}),ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),P?ye("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:ye("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,ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),ye("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye(ge,{palette:t,label:"never hard-coded",tone:"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("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),ye(De,{palette:t,hints:[{key:"j/k",label:"steps"},{key:"enter",label:n?"start":"begin setup"},{key:"esc",label:"exit"},{key:"o",label:"profiles"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function VT(e,t,n=[]){let r=Object.values(e?.services??{}).flatMap((s)=>s.ports.filter((a)=>!a.auto)),o=(e?.proxy.routes??[]).some((s)=>s.auth.type.toLowerCase()==="iap"),i=Wo(e,void 0,t).project;return[{name:_n[0],ok:Boolean(e?.repoRoot),detail:e?.repoRoot||"unknown"},{name:_n[1],ok:Boolean(e?.project.name),detail:e?.project.name||"set project.name"},{name:_n[2],ok:Boolean(i),detail:i||"optional for local-only"},{name:_n[3],ok:t?.adcAvailable===!0,detail:t?.adcAvailable?"ADC available":"needed only for cloud identity / IAP"},{name:_n[4],ok:!0,detail:"read from configuration; never hard-coded"},{name:_n[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:_n[6],ok:r.length===0||Boolean(e),detail:`${r.length} fixed ports from configuration`},{name:_n[7],ok:Object.keys(e?.profiles??{}).length>0,detail:`${Object.keys(e?.profiles??{}).length} profile(s)`},{name:_n[8],ok:n.length===0,detail:n.length===0?"configuration is valid":n[0]??"invalid"}]}var _n;var ow=D(()=>{st();_t();at();be();Ee();Ye();_n=["Repository","Environment","Google project","Authentication","Service accounts","IAP","Ports","Profiles","Validation"]});import{jsxDEV as U}from"@opentui/react/jsx-dev-runtime";function Ap(){return cu.flatMap((e)=>Ha.filter((t)=>t.category===e))}function Gc(){return Wc+Ap().length}function aw(){return Gc()+sw}function Uc(e){if(e<Wc||e>=Gc())return;return Ap()[e-Wc]}function Lp(e){let t=e-Gc();return t>=0&&t<sw?t:void 0}function cw(e){let{palette:t,snap:n,port:r,portDraft:o="",selected:i,onPick:s,onToggle:a,onCopy:c,onToggleTool:l}=e,d=se(),f=n?.mcp?.running===!0,g=n?.mcp?.port??r,m=n?.mcp?.address??Do(g),x=n?.mcp?.token??"",v=Ki(m,x),S=n?.mcp?.disabled_tools??[],P=Ap(),k=P.filter((C)=>!Kn(C.name,S)).length,j=v[Lp(i)??-1],V=j??v[0];return U(tt,{palette:t,title:"mcp settings",children:[U(je,{palette:t,items:[{text:f?"RUNNING":"STOPPED",tone:f?"success":"idle"},{text:`127.0.0.1:${g}`,tone:"info"}]},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:U("box",{flexDirection:"column",overflow:"hidden",children:[U(Pp,{palette:t,text:"Server"},void 0,!1,void 0,this),U(iw,{palette:t,active:i===Ep,rowH:d.rowH,label:"Listen",value:f?"[ ON ]":"[ OFF ]",valueTone:f?"success":"muted",hint:f?"space or enter stop":"space or enter start",onPick:()=>s(Ep),onActivate:a},void 0,!1,void 0,this),U(iw,{palette:t,active:i===Tp,rowH:d.rowH,label:"Port",value:`\u2039 ${o===""?r:o} \u203A`,valueTone:"info",hint:o===""?"\u2190 \u2192 change type digits enter apply":"typing\u2026 enter apply \u232B erase",onPick:()=>s(Tp)},void 0,!1,void 0,this),U("box",{height:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:f?"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),U(Pp,{palette:t,text:"Tools",extra:k===0?"all enabled":`${k} disabled`},void 0,!1,void 0,this),U("box",{height:1,overflow:"hidden",children:U("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),cu.map((C)=>{let y=P.filter((B)=>B.category===C);if(y.length===0)return null;return U("box",{flexDirection:"column",overflow:"hidden",children:[U("box",{height:1,marginTop:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:JT[C]??C},void 0,!1,void 0,this)},void 0,!1,void 0,this),y.map((B)=>{let h=Wc+P.indexOf(B);return U(QT,{palette:t,tool:B,enabled:Kn(B.name,S),active:i===h,rowH:d.rowH,onPick:()=>s(h),onToggle:()=>l(B)},B.name,!1,void 0,this)})]},C,!0,void 0,this)}),U(Pp,{palette:t,text:"Copy agent config",extra:"highlight a row, then enter or click Copy"},void 0,!1,void 0,this),v.map((C,y)=>{let B=Gc()+y;return U(XT,{palette:t,snippet:C,active:i===B,rowH:d.rowH,onPick:()=>s(B),onCopy:()=>c(C)},C.kind,!1,void 0,this)}),U(ZT,{palette:t,snippet:V,selected:Boolean(j),brand:V?_c(V.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),U(He,{palette:t,backgroundColor:t.element,edge:"top",children:U(De,{palette:t,hints:YT(i,f)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function YT(e,t){if(e===Ep)return[{key:"space",label:t?"stop server":"start server"},{key:"j/k",label:"move"}];if(e===Tp)return[{key:"\u2190\u2192",label:"change port"},{key:"0-9",label:"type port"},{key:"enter",label:"apply port"},{key:"j/k",label:"move"}];if(Uc(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 Pp(e){let t=e.extra?` \xB7 ${e.extra}`:"";return U("box",{height:1,marginTop:1,overflow:"hidden",children:U("text",{wrapMode:"none",children:[U("span",{fg:e.palette.primary,children:e.text},void 0,!1,void 0,this),U("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 iw(e){let{palette:t,active:n,rowH:r,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 U("box",{height:r,flexDirection:"row",overflow:"hidden",backgroundColor:n?t.highlight:t.panel,onMouseDown:()=>{if(n&&l){l();return}c()},children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:t.primary,children:n?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Dp,flexShrink:0,overflow:"hidden",children:U("text",{fg:n?t.primary:t.text,wrapMode:"none",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:zT,flexShrink:0,overflow:"hidden",children:U("text",{fg:d,wrapMode:"none",children:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:n?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 XT(e){let{palette:t,snippet:n,active:r,rowH:o,onPick:i,onCopy:s}=e,a=_c(n.kind,t),c=cx(n.kind,t),l=n.language==="toml"?"Copy TOML":"Copy JSON";return U("box",{height:o,flexDirection:"row",overflow:"hidden",backgroundColor:r?t.highlight:t.panel,onMouseDown:i,children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:a,children:r?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Dp,flexShrink:0,overflow:"hidden",children:U("text",{fg:a,wrapMode:"none",children:n.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:n.path},void 0,!1,void 0,this)},void 0,!1,void 0,this),U(ge,{palette:t,label:l,bg:a,fg:c,onMouseDown:()=>{i(),s()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function QT(e){let{palette:t,tool:n,enabled:r,active:o,rowH:i,onPick:s,onToggle:a}=e;return U("box",{height:i,flexDirection:"row",overflow:"hidden",backgroundColor:o?t.highlight:t.panel,onMouseDown:()=>{if(o){a();return}s()},children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:5,flexShrink:0,overflow:"hidden",children:U("text",{fg:r?t.success:t.muted,wrapMode:"none",children:r?" ON ":" OFF "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Dp+4,flexShrink:0,overflow:"hidden",children:U("text",{fg:o?t.primary:r?t.text:t.muted,wrapMode:"none",children:n.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:7,flexShrink:0,overflow:"hidden",children:U("text",{fg:n.mutates?t.warning:t.muted,wrapMode:"none",children:n.mutates?"write":"read"},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:o?t.text:t.muted,wrapMode:"none",children:o?`space or enter ${r?"disable":"enable"} ${n.name}`:n.summary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ZT(e){let{palette:t,snippet:n,selected:r,brand:o}=e;if(!n)return null;let i=n.hint?` \xB7 ${n.hint}`:"";return U("box",{marginTop:1,flexDirection:"column",overflow:"hidden",children:[U("text",{fg:o,wrapMode:"none",children:r?`${n.title} \xB7 paste into ${n.path}${i}`:`Preview ${n.title} \xB7 j/k to a copy row, then enter`},void 0,!1,void 0,this),U("text",{fg:t.text,children:n.text},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Ep=0,Tp=1,Wc=2,sw=4,JT,Dp=14,zT=14;var lw=D(()=>{at();be();Ye();ji();JT={inspect:"Inspect",logs:"Logs",diagnostics:"Diagnostics",control:"Control",setup:"Setup"}});async function dw(e,t){e.suspend();try{return await t()}finally{e.resume(),e.intermediateRender()}}import{existsSync as eA,readFileSync as uw,writeFileSync as tA}from"fs";import{useCallback as Z,useEffect as gt,useMemo as Rn,useRef as Xe,useState as O}from"react";import{RGBA as nA}from"@opentui/core";import{useKeyboard as rA,useRenderer as oA,useTerminalDimensions as iA}from"@opentui/react";import{jsxDEV as ie,Fragment as lA}from"@opentui/react/jsx-dev-runtime";function pw({controller:e,tui:t,onQuit:n,bootError:r,bootErrorMissing:o=!1,terminalBackground:i}){let s=oA(),{width:a,height:c}=iA(),[l,d]=O(t.theme||e?.cfg.ui.theme||"devctl"),f=Xe(l),[g,m]=O(t.mouse),x=Xe(t.mouse),[v,S]=O(t.leader_timeout),P=Xe(t.leader_timeout),[k,j]=O(()=>ss(t.font_size)),V=Xe(k),C=px(),y=Rn(()=>{let p=ax(l);if(Sc(l)!=="terminal"||!Ku(i))return p;let u=i??p.background;return{...p,background:u,panel:u,element:u,inverse:u}},[i,l]),B=Sc(l)==="terminal"&&Ku(i)?nA.defaultBackground(i??void 0):y.background,[h,q]=O(e?"dashboard":"setup"),[M,Y]=O("none"),[ue,Ie]=O(""),[ct,oe]=O(0),[Ge,Re]=O(0),[Qe,pe]=O(0),[Se,$t]=O([]),[N,Rt]=O(),nt=Rn(()=>hx({themeName:l,fontSize:k,mouse:g,leaderMs:v,locked:C,configPath:C?t.path||Xu():Xu(),mcpRunning:N?.mcp?.running===!0}),[k,v,g,C,N?.mcp?.running,l,t.path]),[Ve,Bt]=O([]),[lt,er]=O(!1),[mt,on]=O(!1),[sn,an]=O(!0),[Ur,_]=O(r??""),[cn,Pn]=O(),[Jt,Kc]=O(),[qc,us]=O(!1),[Jo,Np]=O(""),[Vc,Jc]=O(0),[ww,Hp]=O({active:"Preparing diagnostics",checks:[]}),jp=Xe(void 0),zo=Xe(0),[Sw,kw]=O({}),[Bp,Cw]=O(),[Ze,zc]=O(fc(e?.cfg)),[tr,_w]=O(""),[Kr,Wp]=O(!1),[En,Rw]=O(""),[ps,Yc]=O(!1),[Gp,Pw]=O(0),[qr,Up]=O(""),[fs,Ew]=O(""),[zt,It]=O(""),nr=aA,[Kp,Tw]=O(t.log_timestamps!==!1),[qp,Aw]=O(t.log_metadata!==!1),[Vp,Lw]=O(()=>[...gy]),[gs]=O(""),[rr]=O(""),[Tn,Dw]=O(!1),[ms,Jp]=O(),[Ow,Mw]=O(),[Vr,zp]=O(),[hs,Xc]=O(),[$w,Yp]=O(!1),[Xp,Jr]=O(""),[Yo,Qp]=O("focus"),[bt,An]=O(!1),[Iw,Xo]=O(Nr-1),[Qo,vs]=O(!1),[ln,ys]=O(-1),[Zp,Fw]=O(),[ef,tf]=O(""),[nf,Qc]=O(!1),[rf,of]=O(!1),sf=Xe([]),Zo=Xe(null),ei=Xe(null),ti=Xe(null),af=Xe(null),Zc=Xe(null),cf=Xe(null),el=Xe(null),lf=Xe(null),[tl,Nw]=O(""),[Hw,xs]=O(""),nl=Xe(""),rl=Xe(!1),[df,ni]=O(0),[bs,ol]=O(""),[ws,il]=O(),[jw,sl]=O([]),[uf,dn]=O(!1),[pf,al]=O("start"),[or,Ln]=O("quit"),[Dn,Bw]=O(()=>t.mcp_port??Lo(e?.cfg.repoRoot??process.cwd())),ri=Xe(void 0),cl=Xe(0),[T,Ww]=O(e?.cfg),Gw=e?.previousPersisted,[oi,ff]=O(void 0),gf=t.keybinds.copy??bn(),rt=Rn(()=>Object.keys(T?.services??{}).sort(),[T]),ii=Rn(()=>es(rt,Ve,Vp),[rt,Ve,Vp]),si=Rn(()=>hv(ue),[ue]),zr=Rn(()=>$y(ue),[ue]);gt(()=>{Lw((p)=>{let u=new Set(p),R=!1;for(let b of Ve)if(b.service!==""&&!rt.includes(b.service)&&!u.has(b.service))u.add(b.service),R=!0;return R?[...u].sort():p})},[Ve,rt]),gt(()=>{Re(0)},[ue]),gt(()=>{if(M==="palette")oe(0)},[M,ue]);let ot=Rn(()=>Bo(Ve,{service:zt,services:nr,errorOnly:mt,search:En,regex:Tn,source:rr,since:qr,until:fs,systemLogs:sn}),[mt,Tn,En,zt,nr,qr,rr,fs,Ve,sn]),Fe=Rn(()=>jv(ot,bt,df),[ot,bt,df]),On=Fe.items,un=Jv(h,{doctor:Jt?.checks.length??0,settings:nt.length,profiles:Object.keys(T?.profiles??{}).length,services:rt.length,logs:On.length,mcp:aw()}),mf=h==="logs"?Iw:Qe,te=un<=0?Math.max(0,mf):Math.max(0,Math.min(mf,un-1)),pn=h==="detail"?tr:h==="services"?rt[te]??"":"",Ss=hs?.name===pn,hf=Ss?hs?.env:void 0,vf=pn===""?"config":$w&&!Ss?"loading":Ss?"resolved":Xp!==""?"error":"config",yf=Ss||pn===""?"":Xp;gt(()=>{ys(-1),An(!1),Xo(Math.max(0,Math.min(Nr,ot.length)-1))},[mt,En,zt,sn]),gt(()=>{if(h!=="logs")vs(!1)},[h]),gt(()=>{if(h!=="logs"||bt)return;Xo(Math.max(0,Math.min(Nr,ot.length)-1))},[ot.length,bt,h]),gt(()=>{if(h==="settings")return;d(f.current),j(V.current),S(P.current),m(x.current)},[h]);let ll=Z(()=>{if(!bt)ni($u(ot.length)),An(!0)},[ot.length,bt]),ai=Z((p)=>{let u=Iu(p,un,Fe.start,Fe.newer);if(u.startDelta!==0){ni(Math.max(0,Fe.start+u.startDelta)),An(!0),Xo(u.selected);return}let R=Math.max(un-1,0),b=un>0&&(u.selected<R||Fe.newer>0);if(b&&!bt)ni($u(ot.length)),An(!0);else if(!b)An(!1);Xo(u.selected)},[ot.length,un,bt,Fe.newer,Fe.start]),ks=Z((p)=>{let u=On.length,R=Iu(p,u,Fe.start,Fe.newer);if(R.startDelta!==0)ni(Math.max(0,Fe.start+R.startDelta)),An(!0);ys(R.selected)},[On.length,Fe.newer,Fe.start]),dl=Z(()=>{if(An(!1),ys(-1),h==="logs")Xo(Math.max(0,Math.min(Nr,ot.length)-1));Pw((p)=>p+1),_(Fe.newer>0?`Jumped to latest (+${Fe.newer} new)`:"Jumped to latest logs")},[ot.length,Fe.newer,h]),et=Z(()=>{if(Y("none"),Ie(""),Yc(!1),ri.current)clearTimeout(ri.current)},[]),ul=Z((p)=>{$t((u)=>u.includes(p)?u.filter((R)=>R!==p):[...u,p])},[]),Ue=Z((p,u)=>{if(C){_(`${u} session only`);return}let R=dv(p);_(`${u} saved ${R}`)},[C]),Yr=Z((p)=>{d(p),f.current=p,Ue({theme:p},`theme ${p}`)},[Ue]),ci=Z(()=>{let p=!g;m(p),x.current=p,Ue({mouse:p},`mouse ${p?"on":"off"} restart TUI to apply clicks`)},[g,Ue]),Cs=Z((p)=>{S(p),P.current=p,Ue({leader_timeout:p},`leader ${p}ms`)},[Ue]),ir=Z((p)=>{let u=ss(p);j(u),V.current=u,Ue({font_size:u},`display ${Rc(u)}`)},[Ue]),xf=Z(()=>{let p=zu();d(p.theme),f.current=p.theme,m(p.mouse),x.current=p.mouse,S(p.leader_timeout),P.current=p.leader_timeout,j(p.font_size),V.current=p.font_size,Ue(p,"restored default preferences")},[Ue]),pl=Z((p)=>{if(p.id==="theme"){oe(Math.max(0,yt.indexOf(l))),Y("themes");return}if(p.id==="mouse"){ci();return}if(p.id==="leader"){Cs(v);return}if(p.id==="font"){ir(k);return}if(p.id==="reset"){Ln("reset-prefs"),Y("confirm");return}if(p.id==="mcp"){q("mcp"),pe(0);return}_(p.detail)},[ir,Cs,k,v,l,ci]),bf=Z((p)=>{let u=Uo(nt,te);if(!u)return;if(u.id==="theme"){Yr(fx(l,p));return}if(u.id==="leader"){Cs(gx(v,p));return}if(u.id==="font"){ir(Pc(k,p));return}if(u.id==="mouse")ci()},[ir,Cs,k,v,te,Yr,nt,l,ci]),Uw=Z(()=>{d(f.current)},[]),ve=Z(async()=>{if(!e)return;try{let p=await e.status();if(Rt(p),p.profile&&Ze==="")zc(p.profile);return p}catch(p){_(F(p));return}},[e,Ze]),Xr=Z(async()=>{if(!e){_("Supervisor is not running");return}_("Probing configured identities\u2026");try{let p=await e.refreshAuth();Rt((W)=>W?{...W,identity:p}:W);let u=Object.values(p.service_account_status),R=u.filter((W)=>W==="available").length,b=u.filter((W)=>W==="unavailable").length;_(u.length===0?"Identity refreshed \u2014 no service accounts configured":`Identity refreshed \u2014 ${R} available${b>0?`, ${b} unavailable`:""}`)}catch(p){_(F(p))}},[e]),_s=Z((p)=>{let u=Or(p);Bw(u);let R=T?.repoRoot??process.cwd();if(av(R,u)){Ue({mcp_port:null},`MCP port ${u} (default)`);return}Ue({mcp_port:u},`MCP port ${u}`)},[T,Ue]),Qr=Z(()=>{if(bs==="")return Dn;let p=sv(bs,Dn);return ol(""),_s(p),p},[Dn,bs,_s]),wf=Z(async(p)=>{if(!e||N?.mcp?.running!==!0)return;await e.mcpStop(),await e.mcpStart({port:p}),await ve()},[e,ve,N?.mcp?.running]),fl=Z(async(p)=>{if(!e){_("Supervisor is not running");return}let u=N?.mcp?.disabled_tools??[],R=Kn(p.name,u),b=R?[...u,p.name]:u.filter((W)=>W!==p.name);try{let W=await e.mcpSetTools(b);Ue({mcp_disabled_tools:W},`${p.label} ${R?"disabled":"enabled"}`),await ve()}catch(W){_(F(W))}},[e,Ue,ve,N]),Rs=Z(async()=>{if(!e){_("Supervisor is not running");return}try{if(N?.mcp?.running)await e.mcpStop(),Ue({mcp_enabled:!1},"MCP off"),_("MCP stopped");else await e.mcpStart({port:Dn}),Ue({mcp_enabled:!0},"MCP on"),_("MCP started");await ve()}catch(p){_(F(p))}},[e,Dn,Ue,ve,N?.mcp?.running]),gl=Z((p)=>{ep(p.text).then(()=>{_(`Copied ${p.title} snippet`)}).catch((u)=>{_(F(u))})},[]),Ps=Z((p)=>{let u=Lp(p);if(u===void 0)return!1;let R=N?.mcp?.address??Do(N?.mcp?.port??Dn),b=Ki(R,N?.mcp?.token??"")[u];if(!b)return!1;return gl(b),!0},[gl,Dn,N?.mcp?.address,N?.mcp?.port,N?.mcp?.token]),Zr=Rn(()=>({services:zt!==""?[zt]:nr,level:mt?"ERROR":gs,search:En,regex:Tn,source:rr,since:qr,until:fs}),[mt,gs,Tn,En,zt,nr,qr,rr,fs]),Es=Z(async()=>{if(!e)return;try{Fw(await e.logsStats(Zr))}catch(p){_(F(p))}},[e,Zr]),Sf=Z(async()=>{if(!e||lt)return;try{let p=await e.logsPage(Zr);Bt((u)=>hy(u,p.events)),tf(p.prevCursor),Qc(p.hasPrev),await Es()}catch(p){_(F(p))}},[e,Zr,lt,Es]),li=Z(()=>{Bt([]),Up(new Date().toISOString()),An(!1),_("Cleared on-screen log buffer")},[]),di=Z(()=>{an((p)=>!p)},[]);gt(()=>{ve().then(()=>Sf())},[ve,Sf]),gt(()=>{sf.current=Ve},[Ve]),gt(()=>{if(!e||rf||!yy(bt,Fe.start,nf))return;of(!0),e.logsPage({...Zr,cursor:ef,direction:"backward"}).then((p)=>{if(p.sessionChanged){_("Daemon session changed \u2014 older log history is no longer available"),Qc(!1);return}let u=sf.current,R=vy(u,p.events);if(Bt(R),R.length>u.length)ni((b)=>b+(R.length-u.length));tf(p.prevCursor),Qc(p.hasPrev)}).catch((p)=>_(F(p))).finally(()=>of(!1))},[e,Zr,rf,nf,bt,ef,Fe.start]),gt(()=>{if(!e||lt||h!=="logs")return;let p=setInterval(()=>{Es()},cA);return()=>clearInterval(p)},[e,lt,Es,h]),gt(()=>{if(!e)return;let p,u=!1,R=[],b=T&&T.logs.max_memory_events>0?T.logs.max_memory_events:50000,W=()=>{if(p=void 0,R.length>0){let w=R.splice(0,R.length);Bt((le)=>my(le,w,qr,b))}if(u)u=!1,ve()},Mn=e.onEvent((w)=>{if(w.type===fa&&w.payload&&typeof w.payload==="object"&&"event"in w.payload){let le=w.payload.event;if(!lt)R.push(le);if(!p)p=setTimeout(W,30);return}if(w.type===Ti){ff(Ky(w));return}if(w.type===ga)ff(void 0),e.configSnapshot().then(Ww).catch((le)=>_(F(le)));if(u=!0,!p)p=setTimeout(W,30)});return()=>{if(Mn(),p)clearTimeout(p)}},[e,qr,lt,ve]),gt(()=>{Lt(T?.google.project_id??"").then(Pn).catch((p)=>{_(F(p))})},[T?.google.project_id,N?.identity.project]),gt(()=>{if(h!=="doctor"||!T)return;let p=jp.current,u=N?.session_id??"";if(p?.cfg===T&&p.tick===Vc&&p.sessionID===u&&p.reloadError===oi)return;jp.current={cfg:T,tick:Vc,sessionID:u,reloadError:oi};let R=++zo.current;us(!0),Np(""),Hp({active:"Preparing diagnostics",checks:[]});let b;if(T.configPath!==""){b="";try{xi(T.repoRoot,T.configPath)}catch(W){b=F(W)}}Un(T,void 0,(W)=>{if(R===zo.current)Hp(W)},{services:N?.services,proxyRunning:N?.proxy.running,repositoryConfigError:b}).then((W)=>{if(R!==zo.current)return;Kc(W)}).catch((W)=>{if(R!==zo.current)return;Np(F(W))}).finally(()=>{if(R===zo.current)us(!1)})},[h,T,Vc,N?.session_id,oi]);let sr=Z((p)=>{_w(p),q("detail")},[]);gt(()=>{Xc(void 0),Jr("")},[T]),gt(()=>{if(!e||pn===""||!T?.services[pn])return;if(hs?.name===pn)return;let p=!1;return Yp(!0),Jr(""),e.execService(pn,[],!0).then((u)=>{if(p)return;Xc({name:pn,env:u.environment??{}}),Jr("")}).catch((u)=>{if(p)return;Jr(F(u))}).finally(()=>{Yp(!1)}),()=>{p=!0}},[T,e,pn,hs?.name]);let fn=Z(async(p,u)=>{if(!e||!T){_("no configuration loaded");return}try{let R=wa(T,{services:p,profile:u}),b=$i(T,R.services,R.profile);al("start"),sl(b.waves.flat().filter((w)=>Xi(N?.services[w]))),il(b),Y("plan"),dn(!0);let W=R.services.filter((w)=>!Xi(N?.services[w])),Mn=await e.start({services:W.length>0?W:R.services,profile:R.profile});await ve(),dn(!1),_(_y(Mn))}catch(R){dn(!1),await ve(),_(F(R))}},[T,e,ve,N]),Ts=Z(async(p)=>{if(!e||!T){_("no configuration loaded");return}let u=p.length>0?p:Object.entries(N?.services??{}).filter(([,R])=>R.state!=="STOPPED"&&R.state!=="UNKNOWN").map(([R])=>R);if(u.length===0){_("nothing to stop");return}try{let R=Ii(T,u);al("stop"),sl([]),il(R),Y("plan"),dn(!0),await e.stop(p),await ve(),dn(!1),_(Ry(R))}catch(R){dn(!1),await ve(),_(F(R))}},[T,e,ve,N]),ui=Z(async(p,u)=>{if(!e||!T){_("no configuration loaded");return}try{let R=Vv(T,p,u),b=$i(T,R.services,R.profile);al("restart"),sl([]),il(b),Y("plan"),dn(!0),await e.restart(p),await ve(),dn(!1),_(ts(b)===""?"Restarted selected services":`Restarted ${ts(b)}`)}catch(R){dn(!1),await ve(),_(F(R))}},[T,e,ve]),As=Z(async(p="")=>{let u=M==="log-details"&&ms?by(ms):M==="scroll-text"&&Vr?Vr.body:wy(ot),R=p===""?"":` \xB7 ${p}`;if(u.trim()===""){_(`No logs to copy${R}`);return}try{await ep(u);let b=u.split(`
628
- `).length,W=M==="log-details"?"Copied log event":M==="scroll-text"?"Copied overlay text":`Copied ${b} log lines`;_(`${W}${R}`)}catch(b){_(F(b))}},[ot,ms,M,Vr]),ml=Z(()=>{if(!T)return;try{Nw(uw(T.configPath,"utf8")),xs(""),Y("config-edit")}catch(p){_(F(p))}},[T]),Kw=Z(()=>{if(!T)return;let p=lf.current?.plainText??tl,u=ao(T.repoRoot,T.configPath,p);if(u.length>0){xs(u.join(`
629
- `)),_("Config buffer not saved");return}if(tA(T.configPath,p),xs(""),Y("none"),!e){_(`Wrote ${T.configPath}`);return}e.reload().then((R)=>{if(_(R.restart_required.length===0?"Configuration saved and reloaded":`Saved; restart required: ${R.restart_required.join(", ")}`),R.restart_required.length>0)Ln("reload"),Y("confirm");ve()})},[T,tl,e,ve]),gn=Z(async(p,u)=>{if(rl.current)return;if(rl.current=!0,p.name!=="start"&&p.name!=="stop"&&p.name!=="restart")Y("none");Ie("");let R=fy(u,Se);try{switch(p.name){case"exit":Ln("quit"),Y("confirm");return;case"help":Y("help");return;case"version":_(At()),Vi().then((b)=>_(wu(b))).catch((b)=>_(F(b)));return;case"update":_("checking for update\u2026"),Vi().then((b)=>_(wu(b))).catch((b)=>_(F(b)));return;case"themes":if(u[0]){Yr(u[0]);return}oe(Math.max(0,yt.indexOf(l))),Ie(""),Y("themes");return;case"settings":q("settings"),pe(0);return;case"dashboard":case"services":q(p.name);return;case"logs":if(u[0])It(u[0]);q("logs");return;case"fullscreen":q("logs"),vs((b)=>h==="logs"?!b:!0);return;case"auth":{let b=(u[0]??"").toLowerCase();if(b==="refresh"){q("auth"),await Xr();return}if(b==="login"){q("auth"),_("starting gcloud ADC login\u2026");try{await dw(s,()=>go()),Pn(await Lt(T?.google.project_id??"")),await Xr(),_("ADC login complete")}catch(W){_(F(W))}return}if(b==="logout"){q("auth"),_("revoking ADC\u2026");try{await sa(),Pn(await Lt(T?.google.project_id??"")),await Xr(),_("ADC revoked")}catch(W){_(F(W))}return}q("auth");return}case"credentials":case"proxy":case"mcp":case"config":case"profiles":case"setup":q(p.name);return;case"diff":if(!T){_("no configuration loaded");return}zp({title:"config sources",body:rx(T,Kr)}),Y("scroll-text");return;case"daemon":{let b=T?.repoRoot;if(!b){_("no repository");return}let W=dr(b);if(!eA(W)){_("no daemon bootstrap log yet for this repository");return}zp({title:"daemon bootstrap",body:uw(W,"utf8")}),Y("scroll-text");return}case"reload":if(!e)return;e.reload().then((b)=>{if(_(b.restart_required.length===0?"Configuration reloaded":`Reload requires restart: ${b.restart_required.join(", ")}`),b.restart_required.length>0)Ln("reload"),Y("confirm");ve()});return;case"doctor":q("doctor");return;case"stats":q("stats");return;case"start":await fn(R,Ze);return;case"stop":await Ts(R);return;case"restart":await ui(R,Ze);return;case"run":{let b=u[0]??"";if(!e||!b){_(b?"no daemon attached":"usage: /run <task>");return}try{let W=await e.runTask(b);It(`task:${b}`),q("logs"),_(`task ${b} exited ${W.code}`)}catch(W){throw It(`task:${b}`),q("logs"),W}return}case"exec":{let b=xv(u);if(!e||!b.service){_(b.service?"no daemon attached":"usage: /exec <service> -- <command\u2026>");return}if(b.printEnv){if(!T?.services[b.service]){_(`unknown service ${b.service}`);return}if(b.reveal)Wp(!0);_(`Resolving environment for ${b.service}\u2026`);try{let W=await e.execService(b.service,[],!0);Xc({name:b.service,env:W.environment??{}}),Jr(""),sr(b.service),_(`Resolved environment for ${b.service}`)}catch(W){Jr(F(W)),sr(b.service),_(F(W))}return}if(b.command.length===0){_("usage: /exec <service> -- <command\u2026>");return}try{let W=await e.execService(b.service,b.command);It(`${b.service}:exec`),q("logs"),_(`${b.service}:exec exited ${W.code}`)}catch(W){throw It(`${b.service}:exec`),q("logs"),W}return}case"refresh":if(h==="auth"){await Xr();return}await ve(),_("Refreshed status and logs");return;case"pause":er((b)=>!b),q("logs");return;case"filter":on((b)=>!b),q("logs");return;case"system":di(),q("logs");return;case"clear":li();return;case"reveal":{let b=!Kr;Wp(b),_(b?"Secrets visible this session":"Secrets hidden");return}case"wrap":{let b=Mu(Yo);Qp(b),_(`Log ${zi(b)}`);return}case"copy":await As();return;case"export":{let b=_o(u[0]);if(e)await e.logs({export:b,services:nr,level:mt?"ERROR":gs,search:En,regex:Tn,source:rr});else Ta(b,ot);nl.current=b,_(`Exported ${b}`);return}case"exports":{let b=nl.current||lr();Aa(b),_(`Opened ${lr()}`);return}case"regex":Dw((b)=>!b),_(Tn?"Substring search":"Regex search");return;case"since":Up(u[0]||new Date(Date.now()-3600000).toISOString()),_(`Logs since ${u[0]||"1h"}`);return;case"until":Ew(u[0]||new Date().toISOString()),_(`Logs until ${u[0]||"now"}`);return;case"history":{let{listSessions:b,loadSessionEvents:W}=await Promise.resolve().then(() => (Ar(),uh)),Mn=b(),w=u[0]||Mn[0];if(!w){_("No persisted log sessions");return}Bt(W(w)),_(`Loaded session ${w}`);return}case"buffer":ml();return;case"edit":{if(!T)return;let b=process.env.DEVCTL_EDITOR||process.env.EDITOR,W=b?[b,T.configPath]:process.platform==="darwin"?["open",T.configPath]:["xdg-open",T.configPath];Bun.spawn({cmd:W,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),_(`Opened ${T.configPath} in ${W[0]}. Run /reload after saving.`);return}default:_(`/${p.name}`)}}catch(b){_(F(b))}finally{setTimeout(()=>{rl.current=!1},sA)}},[ui,fn,Ts,Se,T,li,e,As,mt,ot,gs,Tn,En,nr,rr,Yo,ml,sr,Yr,Ze,ve,Xr,s,Kr,h,l,di]),qw=Z(()=>{let p=nl.current||lr();Aa(p),_(`Opened ${lr()}`)},[]),hl=Z(()=>{let p=Hr(si,Ge);if(!p){_(ue.trim()===""?"pick a command from the list":`unknown command /${ue}`),et();return}let R=qi(ue)?.name===p.name?vv(ue):[];gn(p,R)},[et,si,ue,gn,Ge]),kf=Z((p)=>{Yr(p),et()},[et,Yr]),Vw=Z((p)=>{let u=qi(p);if(u)gn(u,[])},[gn]),Cf=Z(()=>{if(M==="palette"){let p=Hr(zr,ct);if(p)gn(p,[]);return}hl()},[M,ct,zr,gn,hl]),Jw=Z(()=>{if(T?.shutdown.stop_services_on_exit===void 0){Ln("quit"),Y("confirm");return}n(T.shutdown.stop_services_on_exit===!1)},[T,n]),zw=Z(()=>{if(or==="quit"){n(!1);return}if(or==="reload"){et();let p=N?.restart_required??[];if(p.length>0)ui(p,Ze);return}if(or==="reset-prefs"){et(),xf();return}if(or==="free-port"){let p=Bp;if(et(),!p)return;ca(p).then(()=>{_(`Stopped ${p.command} (pid ${p.pid}) on port ${p.port}`),Jc((u)=>u+1)}).catch((u)=>{_(F(u))});return}et(),fn([],Ze)},[xf,ui,fn,et,or,n,Bp,Ze,N]),Yw=Z(()=>{if(h==="logs"){let u=On[te];if(u)Jp(u),Y("log-details");return}if(h==="profiles"){let R=Object.keys(T?.profiles??{}).sort()[te];if(R)zc(R),Ln("start-profile"),Y("confirm");return}if(h==="doctor"){let u=Jt?.checks[te];if(u?.action?.kind==="free-port"){let R=u.action.holder;Cw(R),kw({port:R.port,pid:R.pid,process:R.command}),Ln("free-port"),Y("confirm")}return}if(h==="mcp"){if(te===0){Rs();return}if(te===1){Qr();return}let u=Uc(te);if(u){fl(u);return}Ps(te);return}if(h==="settings"){let u=Uo(nt,te);if(u)pl(u);return}if(h==="dashboard"&&jo(N)){fn([],Ze);return}let p=rt[te];if(p&&(h==="dashboard"||h==="services"))sr(p)},[pl,Qr,fn,T,Ps,Jt,te,On,rt,sr,Ze,h,nt,N,Rs]);rA((p)=>{let u=(p.name??"").toLowerCase(),R=Ix(p,t),b=$x(p,t);if(R&&!b){if(h==="mcp"&&Ps(te))return;As();return}if(b){let w=Date.now();if(Fx(w,cl.current)){cl.current=0,Jw();return}cl.current=w;let le="Ctrl+C again to quit";if(R)As(le);else _(`Press ${le}`);return}if(p.ctrl&&(u==="="||u==="+"||u==="plus")){ir(Pc(k,1));return}if(p.ctrl&&(u==="-"||u==="_"||u==="minus")){ir(Pc(k,-1));return}if(p.ctrl&&u==="0"){ir(zu().font_size);return}if(M==="confirm"){if(u==="escape"){et();return}if(or==="quit"&&u==="d"){n(!0);return}if(u==="return")zw();return}if(M==="log-details"||M==="scroll-text"){if(u==="escape"){et();return}let w=M==="log-details"?af.current:cf.current;if(u==="down"||u==="j"){Be(w,t.scroll_speed);return}if(u==="up"||u==="k"){Be(w,-t.scroll_speed);return}if(Lc(p)){Be(w,Yi(c));return}if(Dc(p)){Be(w,-Yi(c));return}return}if(M==="route-details"){if(u==="escape"||u==="return"){et();return}if(u==="down"||u==="j"){Be(Zc.current,t.scroll_speed);return}if(u==="up"||u==="k"){Be(Zc.current,-t.scroll_speed);return}return}if(M==="plan"){if(u==="escape"||u==="return"&&!uf){et();return}if(u==="down"||u==="j"){Be(el.current,t.scroll_speed);return}if(u==="up"||u==="k"){Be(el.current,-t.scroll_speed);return}return}if(M==="help"){if(u==="escape"){et();return}if(u==="down"||u==="j"){Be(ei.current,1);return}if(u==="up"||u==="k"){Be(ei.current,-1);return}if(u==="pagedown"||Lc(p)){Be(ei.current,cp);return}if(u==="pageup"||Dc(p)){Be(ei.current,-cp);return}return}if(M==="themes"){if(u==="escape"){Uw(),et();return}if(u==="down"||u==="j"){oe((w)=>{let le=Math.min(w+1,yt.length-1),mn=yt[le];if(mn)d(mn);return le});return}if(u==="up"||u==="k"){oe((w)=>{let le=Math.max(0,w-1),mn=yt[le];if(mn)d(mn);return le});return}if(u==="return"){let w=yt[ct%yt.length];if(w)kf(w)}return}if(M==="leader"){if(ri.current)clearTimeout(ri.current);Y("none");let w=yv(u),le=w?qi(w):void 0;if(le)gn(le,[]);return}if(M==="config-edit"){if(u==="escape"){xs(""),et();return}if(p.ctrl&&u==="s"){Kw();return}return}if(Px(M)){if(u==="escape"){et();return}if(M==="slash"&&u==="down"){Re((w)=>Math.min(Math.max(si.length-1,0),w+1));return}if(M==="slash"&&u==="up"){Re((w)=>Math.max(0,w-1));return}if(M==="slash"&&u==="tab"){if(p.shift){Re((le)=>Math.max(0,le-1));return}let w=Hr(si,Ge);if(w)Ie(`${w.name} `);return}if(M==="slash"&&u==="return"){hl();return}if(M==="palette"&&u==="down"){oe((w)=>Math.min(w+1,Math.max(zr.length-1,0)));return}if(M==="palette"&&u==="up"){oe((w)=>Math.max(0,w-1));return}if(M==="palette"&&u==="return"){let w=Hr(zr,ct);if(w)gn(w,[])}return}if(ps){if(u==="escape")Yc(!1);return}if(Ex(p,t)){Y("leader"),ri.current=setTimeout(()=>Y("none"),v);return}if(Tx(p,t)){Ie(""),oe(0),Y("palette");return}if(Ax(p,t)){Ie(""),Re(0),Y("slash");return}if(Lx(p,t)){Y("help");return}if(Dx(p,t)||h==="logs"&&u==="f"&&!p.ctrl&&!p.meta){q("logs"),Yc(!0);return}if(u==="escape"){if(Qo){vs(!1);return}if(h==="detail"){q("services");return}if(h==="setup")if(e)q("dashboard");else n(!0);return}if(u==="z"&&(h==="logs"||h==="dashboard")&&!p.ctrl&&!p.meta){q("logs"),vs((w)=>h==="logs"?!w:!0);return}let W=(h==="logs"||h==="dashboard")&&!ps;if(W&&(u==="left"||u==="["||h==="logs"&&u==="h")){It(Hu(ii,zt,-1));return}if(W&&(u==="right"||u==="]"||h==="logs"&&u==="l")){It(Hu(ii,zt,1));return}if(h==="logs"&&!ps&&u.length===1&&u>="1"&&u<="9"){let w=Cy(ii,Ve,Number(u));if(w!==void 0)It(w);return}if(u==="tab"){q(p.shift?Oy(h):Dy(h));return}let Mn=zv(u);if(Mn){q(Mn);return}if((h==="dashboard"||h==="setup")&&u==="o"){q("profiles");return}if((h==="dashboard"||h==="services")&&(u==="*"||p.shift&&u==="8")){$t([...rt]),_(`Selected ${rt.length} services`);return}if((h==="dashboard"||h==="services")&&(u==="-"||u==="_"||u==="minus")){$t([]),_("Selection cleared");return}if((h==="dashboard"||h==="services")&&u==="n"){fn(vc(Se,rt[te]??""),Ze);return}if((h==="dashboard"||h==="services")&&u==="x"){Ts(vc(Se,rt[te]??""));return}if((h==="dashboard"||h==="services"||h==="detail")&&Ox(p)){ui(vc(Se,rt[te]??tr),Ze);return}if((h==="dashboard"||h==="services")&&u==="r"){ve(),_("Refreshed");return}if(h==="auth"&&u==="r"){Xr();return}if(h==="logs"&&u==="t"){let w=!Kp;Tw(w),Ue({log_timestamps:w},w?"timestamps on":"timestamps off");return}if(h==="logs"&&u==="m"){let w=!qp;Aw(w),Ue({log_metadata:w},w?"metadata on":"metadata off");return}if(u==="down"||u==="j"){if(h==="mcp"&&te===1)Qr();if(h==="config"){Be(Zo.current,t.scroll_speed);return}if(h==="detail"){Be(ti.current,t.scroll_speed);return}if(h==="logs"){ai(te+1);return}if(h==="dashboard"&&ln>=0){ks(ln+1);return}pe((w)=>Math.min(Math.max(un-1,0),w+1));return}if(u==="up"||u==="k"){if(h==="mcp"&&te===1)Qr();if(h==="config"){Be(Zo.current,-t.scroll_speed);return}if(h==="detail"){Be(ti.current,-t.scroll_speed);return}if(h==="logs"){ai(te-1);return}if(h==="dashboard"&&ln>=0){ks(ln-1);return}pe((w)=>Math.max(0,Math.min(w,Math.max(un-1,0))-1));return}if(Lc(p)){let w=Yi(c);if(h==="config"){Be(Zo.current,w);return}if(h==="detail"){Be(ti.current,w);return}if(h==="logs"){ai(te+w);return}if(h==="dashboard"&&(bt||ln>=0)){ks(Math.max(0,ln)+w);return}pe((le)=>Math.min(Math.max(un-1,0),le+w));return}if(Dc(p)){let w=Yi(c);if(h==="config"){Be(Zo.current,-w);return}if(h==="detail"){Be(ti.current,-w);return}if(h==="logs"){ai(te-w);return}if(h==="dashboard"&&(bt||ln>=0)){ks(Math.max(0,ln)-w);return}pe((le)=>Math.max(0,le-w));return}if(h==="proxy"&&u==="n"){e?.proxyStart().then(async()=>{_("Proxy started"),await ve()});return}if(h==="proxy"&&u==="x"){e?.proxyStop().then(async()=>{_("Proxy stopped"),await ve()});return}if(h==="detail"&&tr!==""){if(u==="n"){fn([tr],Ze);return}if(u==="x"){Ts([tr]);return}if(u==="o"){q("config");return}if(u==="l"){It(tr),q("logs");return}}if(h==="mcp"&&te===1&&(u==="left"||u==="h")){let w=Or(Qr()-1);_s(w),wf(w);return}if(h==="mcp"&&te===1&&(u==="right"||u==="l")){let w=Or(Qr()+1);_s(w),wf(w);return}if(h==="mcp"&&te===1&&(u==="backspace"||u==="delete")){ol((w)=>iv(w));return}if(h==="mcp"&&te===1&&u.length===1&&u>="0"&&u<="9"){ol((w)=>ov(w,u));return}if(h==="settings"&&(u==="left"||u==="h")){bf(-1);return}if(h==="settings"&&(u==="right"||u==="l")){bf(1);return}if(u==="space"){if(h==="profiles"){let mn=Object.keys(T?.profiles??{}).sort()[te];if(mn)zc(mn),_(`Profile ${mn}`);return}if(h==="mcp"){if(te===0){Rs();return}let le=Uc(te);if(le){fl(le);return}Ps(te);return}if(h==="logs")return;if(h==="settings"){if(Uo(nt,te)?.id==="mouse")ci();return}let w=rt[te];if(w)ul(w);return}if(u==="return"){if(h==="setup"&&!e){if(!o){_(r||"Existing configuration is invalid \u2014 fix it and restart devctl.");return}Promise.resolve().then(() => (jd(),zm)).then(({createStarterConfig:w})=>{try{let le=w(process.cwd());_(`Wrote ${le}. Restart devctl or run the CLI wizard.`)}catch(le){_(F(le))}});return}if(h==="setup"&&e){fn([],Ze);return}Yw();return}if(u==="q"){if(T?.shutdown.stop_services_on_exit===!1){n(!0);return}if(T?.shutdown.stop_services_on_exit===!0){n(!1);return}Ln("quit"),Y("confirm");return}if(zn(p,t,"services","s")&&M==="none"&&h!=="logs"){q("services");return}if(zn(p,t,"logs","l")&&M==="none"&&h!=="detail"&&h!=="logs"&&h!=="settings"){q("logs");return}if(zn(p,t,"auth","a")&&M==="none"){q("auth");return}if(zn(p,t,"proxy","p")&&M==="none"&&h!=="logs"){q("proxy");return}if(zn(p,t,"doctor","d")&&M==="none"&&h!=="doctor"){q("doctor");return}if(zn(p,t,"config","c")&&M==="none"){q("config");return}if(zn(p,t,"setup","u")&&M==="none"){q("setup");return}if(h==="config"&&u==="e"){gn(qi("/edit")??{name:"edit",aliases:[],desc:"",leader:"",group:"ui"},[]);return}if(h==="config"&&u==="v"){ml();return}if(h==="doctor"&&u==="r"){Jc((w)=>w+1),_("Re-running doctor");return}if(h==="logs"&&u==="p"){er((w)=>!w);return}if((h==="logs"||h==="dashboard")&&u==="g"){dl();return}if((h==="logs"||h==="dashboard")&&u==="w"){let w=Mu(Yo);Qp(w),_(`Log ${zi(w)}`);return}if((h==="logs"||h==="dashboard")&&u==="e"){on((w)=>!w);return}if((h==="logs"||h==="dashboard")&&u==="i"){di(),_(sn?"Hiding internal auth/mcp/devctl/proxy logs":"Showing internal logs");return}if((h==="logs"||h==="dashboard")&&Mx(p))li()});let _f=Wy(or,Ze,Sw),Xw=new Set(ws?.waves.flat()??[]),Qw=ws===void 0||pf==="stop"?"":Object.entries(N?.services??{}).find(([p,u])=>Xw.has(p)&&u.state==="FAILED")?.[0]??"";return ie(Qu.Provider,{value:as(k),children:ie("box",{flexDirection:"column",width:a,height:c,backgroundColor:B,overflow:"hidden",children:[Qo?null:ie(lA,{children:[ie(bx,{palette:y,cfg:T,snap:N,google:cn,profile:Ze,reveal:Kr,width:a},void 0,!1,void 0,this),ie(wx,{palette:y,screen:h,width:a,onSelect:q},void 0,!1,void 0,this),oi?ie("box",{height:1,paddingLeft:1,backgroundColor:y.panel,overflow:"hidden",children:ie("text",{fg:y.error,wrapMode:"none",children:`\u26A0 configuration reload failed: ${oi}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ie("box",{flexGrow:1,overflow:"hidden",children:[h==="dashboard"?ie(Tb,{palette:y,cfg:T,snap:N,logs:Ve,names:rt,selected:te,checked:Se,profile:Ze,google:cn,width:a,paused:lt,followTick:Gp,logService:zt,errorOnly:mt,showSystemLogs:sn,onOpen:sr,onSelectIndex:pe,selectedLog:ln,onToggle:ul,logSources:ii,onFilterService:It,onToggleErrors:()=>on((p)=>!p),onToggleSystemLogs:di,onClearLogs:li,onShowErrors:()=>{It(""),on(!0)},wrapMode:Yo,view:On,follow:!bt,onLeaveLatest:ll,onPickLog:(p)=>{let u=On[p];if(!u)return;ys(p),Jp(u),ll()},viewStart:Fe.start,viewTotal:ot.length,newer:Fe.newer,onJumpLatest:dl,facets:Zp,leftover:Gw},void 0,!1,void 0,this):null,h==="services"?ie(Vb,{palette:y,cfg:T,names:rt,snap:N,selected:te,checked:Se,width:a,reveal:Kr,onOpen:sr,onSelectIndex:pe,onToggle:ul,resolvedEnv:hf,envStatus:vf,envError:yf},void 0,!1,void 0,this):null,h==="detail"?ie(qb,{palette:y,cfg:T,snap:N,name:tr,reveal:Kr,width:a,envScrollRef:ti,resolvedEnv:hf,envStatus:vf,envError:yf},void 0,!1,void 0,this):null,h==="logs"?ie(Pb,{palette:y,logs:Ve,names:rt,logSources:ii,service:zt,paused:lt,errorOnly:mt,showSystemLogs:sn,search:En,searchFocused:ps,followTick:Gp,width:a,onSearch:Rw,onService:It,onToggleErrors:()=>on((p)=>!p),onToggleSystemLogs:di,onClearLogs:li,source:rr,regex:Tn,services:nr,showTimestamps:Kp,showMeta:qp,view:On,wrapMode:Yo,selected:te,follow:!bt,newer:Fe.newer,viewStart:Fe.start,viewTotal:ot.length,onSelect:ai,fullscreen:Qo,onLeaveLatest:ll,onOpenExports:qw,onJumpLatest:dl,facets:Zp},void 0,!1,void 0,this):null,h==="auth"?ie(vb,{palette:y,cfg:T,google:cn,identity:N?.identity},void 0,!1,void 0,this):null,h==="credentials"?ie(xb,{palette:y,credentials:N?.credentials},void 0,!1,void 0,this):null,h==="proxy"?ie(Wb,{palette:y,cfg:T,snap:N,width:a,onSelectRoute:(p)=>{Mw(p),Y("route-details")}},void 0,!1,void 0,this):null,h==="mcp"?ie(cw,{palette:y,snap:N,port:Dn,portDraft:bs,selected:te,onPick:pe,onToggle:()=>{Rs()},onCopy:gl,onToggleTool:(p)=>{fl(p)}},void 0,!1,void 0,this):null,h==="doctor"?ie(Db,{palette:y,report:Jt,loading:qc,progress:ww,error:Jo,selected:te,onPick:pe,onReload:()=>{Jc((p)=>p+1),_("Re-running doctor")}},void 0,!1,void 0,this):null,h==="stats"?ie(tw,{palette:y,cfg:T,snap:N,width:a,onRefresh:ve},void 0,!1,void 0,this):null,h==="config"?ie(Cb,{palette:y,cfg:T,width:a,scrollRef:Zo},void 0,!1,void 0,this):null,h==="profiles"?ie($b,{palette:y,cfg:T,snap:N,profile:Ze,selected:te,onPick:pe},void 0,!1,void 0,this):null,h==="setup"?ie(rw,{palette:y,cfg:T,google:cn,bootError:r,bootErrorMissing:o,step:te},void 0,!1,void 0,this):null,h==="settings"?ie(Qb,{palette:y,items:nt,selected:te,locked:C,width:a,onPick:pe,onActivate:pl},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),M==="slash"?ie(db,{palette:y,items:si,query:ue,selected:Ge,onQuery:Ie,onSubmit:Cf},void 0,!1,void 0,this):null,M==="palette"?ie(eb,{palette:y,items:zr,selected:Math.min(ct,Math.max(zr.length-1,0)),termW:a,termH:c,onIndex:oe,onPick:Vw},void 0,!1,void 0,this):null,M==="themes"?ie(mb,{palette:y,themeName:l,selected:ct%yt.length,termW:a,termH:c,onIndex:oe,onPreview:d,onPick:kf},void 0,!1,void 0,this):null,M==="help"?ie(Jx,{palette:y,termW:a,termH:c,copyKey:gf,scrollRef:ei},void 0,!1,void 0,this):null,M==="leader"?ie(Xx,{palette:y,termW:a,termH:c},void 0,!1,void 0,this):null,M==="confirm"?ie(Bx,{palette:y,title:_f.title,body:_f.body,termW:a,termH:c},void 0,!1,void 0,this):null,M==="log-details"?ie(Gx,{palette:y,event:ms,termW:a,termH:c,scrollRef:af},void 0,!1,void 0,this):null,M==="route-details"?ie(ib,{palette:y,route:Ow,termW:a,termH:c,scrollRef:Zc},void 0,!1,void 0,this):null,M==="scroll-text"&&Vr?ie(ab,{palette:y,title:Vr.title,body:Vr.body,termW:a,termH:c,scrollRef:cf},void 0,!1,void 0,this):null,M==="config-edit"&&T?ie(Hx,{palette:y,path:T.configPath,initialValue:tl,error:Hw,termW:a,termH:c,textareaRef:lf},void 0,!1,void 0,this):null,M==="plan"&&ws?ie(rb,{palette:y,plan:ws,snap:N,busy:uf,failed:Qw,kind:pf,termW:a,termH:c,scrollRef:el,initiallyRunning:jw,onDismiss:et},void 0,!1,void 0,this):null,M==="slash"||M==="plan"||M==="config-edit"||Qo||Kv(c)&&M==="none"?null:ie(Sx,{palette:y,overlay:M,query:ue,onQuery:Ie,onSubmit:Cf},void 0,!1,void 0,this),Qo?null:ie(kx,{palette:y,screen:h,overlay:M,status:Ur,paused:lt,errorOnly:mt,width:a,copyKey:gf},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var sA=50,aA,cA=2000;var fw=D(()=>{st();Oi();Pi();wr();Pe();Ar();ze();Pr();Ga();Su();Bu();_t();Rx();Ee();Nx();be();jx();Wx();Ux();zx();Qx();tb();ob();sb();cb();ub();hb();yb();bb();_b();Ab();Ob();vp();Ib();Gb();Cp();Jb();Zb();nw();ow();lw();ji();at();Cn();Ye();Zt();aA=[]});var gw={};Ls(gw,{renderApp:()=>Mp,runTui:()=>Op,runTuiWithController:()=>pA,tuiConfigFor:()=>fA});import{createCliRenderer as dA}from"@opentui/core";import{createRoot as uA}from"@opentui/react";import{jsxDEV as gA}from"@opentui/react/jsx-dev-runtime";async function pA(e){let t=Qt(e.cfg.repoRoot,e.cfg.ui.keymap);await Mp(e,t)}async function Op(e){let t,n,r=!1;try{t=await cm("",e)}catch(i){n=F(i),r=Ms(i,ar)}let o=Qt(t?.cfg.repoRoot??process.cwd(),t?.cfg.ui.keymap);await Mp(t,o,n,r)}async function Mp(e,t=Qt(e?.cfg.repoRoot??process.cwd(),e?.cfg.ui.keymap),n,r=!1){Ds();let o=Tf(),i=await dA({exitOnCtrlC:!1,useMouse:t.mouse,enableMouseMovement:t.mouse,useKittyKeyboard:{}}),s=uA(i),a=null;try{a=(await i.getPalette({timeout:120,size:16})).defaultBackground}catch{}await new Promise((c)=>{let l=(d)=>{let f=()=>{s.unmount(),o(),i.destroy(),c(),process.exit(0)};if(!e){f();return}e.close({detach:d,shutdownSupervisor:!0}).finally(f)};s.render(gA(pw,{controller:e,tui:t,onQuit:l,bootError:n,bootErrorMissing:r,terminalBackground:a},void 0,!1,void 0,this))})}function fA(e){return Qt(e.repoRoot,e.ui.keymap)}var $p=D(()=>{sd();Pe();fw();vl();Zt()});eo();vl();st();sd();ze();Oi();Pe();wr();st();Ai();Pr();jd();import{Command as mA}from"commander";import{setTimeout as Fp}from"timers/promises";import{stringify as hA}from"yaml";import{existsSync as vw,readFileSync as vA}from"fs";st();rd();Pe();wr();import{createServer as lR}from"net";import{existsSync as pu,unlinkSync as dR,watch as uR}from"fs";import{cpus as pR,loadavg as fR,platform as gR,uptime as mR}from"os";import{isAbsolute as fu,join as Ya}from"path";ze();Pr();import{connect as p_}from"net";var f_=2000,g_=2000,m_=200,h_=300;function Ym(e){if(e.interval_seconds<=0)return g_;return e.interval_seconds*1000}async function Xm(e,t,n,r,o,i=[]){let s=e.timeout_seconds>0?e.timeout_seconds*1000:f_,a=e.type.toLowerCase(),c=i.find((l)=>l.name.toLowerCase()===a);if(c)try{let l=await c.check(e,{pid:t,ports:n,workDir:r,env:o});return{status:l.status,message:l.message}}catch(l){return{status:Ce,message:l instanceof Error?l.message:String(l)}}if(a==="http")return v_(e.url,s);if(a==="tcp")return x_(y_(e.address,n),s);if(a==="command")return b_(e.command.args,e.command.shell,r,o,s);if(a==="process"||a===""){if(t>0&&Pt(t))return{status:Ct,message:"process running"};return{status:Ce,message:"process not running"}}return{status:Ce,message:`unknown health type ${e.type}`}}async function v_(e,t){let n=new AbortController,r=setTimeout(()=>n.abort(),t);try{let o=await fetch(e,{signal:n.signal});if(o.status>=m_&&o.status<h_)return{status:Ct,message:String(o.status)};return{status:Ce,message:String(o.status)}}catch(o){return{status:Ce,message:o instanceof Error?o.message:String(o)}}finally{clearTimeout(r)}}function y_(e,t){if(e!=="")return e;if(t.http!==void 0)return`127.0.0.1:${t.http}`;let n=Object.values(t)[0];return n!==void 0?`127.0.0.1:${n}`:""}function x_(e,t){return new Promise((n)=>{if(e===""){n({status:Ce,message:"no tcp address"});return}let r=e.lastIndexOf(":"),o=Number.parseInt(e.slice(r+1),10),i=e.slice(0,r).replace(/^\[|\]$/g,"");if(r<1||!Number.isFinite(o)){n({status:Ce,message:`invalid tcp address ${e}`});return}let s=p_({host:i,port:o},()=>{s.end(),n({status:Ct,message:"connected"})});s.setTimeout(t),s.on("error",(a)=>{n({status:Ce,message:a.message})}),s.on("timeout",()=>{s.destroy(),n({status:Ce,message:"timeout"})})})}async function b_(e,t,n,r,o){if(e.length===0)return{status:Ce,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:n===""?void 0:n,env:r,stdout:"ignore",stderr:"ignore"})}catch(l){return{status:Ce,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:Ct,message:"ok"};return{status:Ce,message:`exit ${c}`}}function Qm(e){if(e===Ce)return"WARN";if(e===Ct)return"INFO";return"DEBUG"}import{readFileSync as w_}from"fs";import{freemem as S_,totalmem as k_}from"os";import{spawnSync as C_}from"child_process";var Bd=1024,__=2000,R_=/page size of (\d+) bytes/i,Co;function P_(e){let t=e.match(/^MemAvailable:\s+(\d+)/m);if(!t)return;let n=Number(t[1]);return Number.isFinite(n)&&n>=0?n:void 0}function E_(e){let t=e.match(R_),n=t?Number(t[1]):0;if(!Number.isFinite(n)||n<=0)return;let r=ka(e,"free")+ka(e,"inactive")+ka(e,"speculative")+ka(e,"purgeable");return Math.round(r*n/Bd)}function ka(e,t){let n=e.match(new RegExp(`Pages ${t}:\\s+(\\d+)`,"i")),r=n?Number(n[1]):0;return Number.isFinite(r)&&r>0?r:0}function T_(){if(process.platform==="linux")try{return P_(w_("/proc/meminfo","utf8"))}catch{return}if(process.platform==="darwin"){let e=Date.now();if(Co&&e-Co.at<__)return Co.leftoverKB;let t=C_("vm_stat",{encoding:"utf8"});if(t.status!==0||!t.stdout)return Co?.leftoverKB;let n=E_(t.stdout);if(n===void 0)return Co?.leftoverKB;return Co={at:e,leftoverKB:n},n}return}function Zm(){let e=Math.max(0,Math.round(k_()/Bd)),t=Math.max(0,Math.round(S_()/Bd)),n=Math.max(0,Math.min(e,T_()??t));return{totalKB:e,unusedKB:t,leftoverKB:n}}br();Ar();Pi();Ar();import{pathToFileURL as i0}from"url";import{isAbsolute as s0,resolve as a0}from"path";st();Pe();br();import{createServer as hh,request as Q_}from"http";import{randomBytes as ph}from"crypto";import{Readable as Z_}from"stream";var Ni="x-devctl-request-id",e0="x-devctl-internal-token",fh=100,tu=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]),t0=new Set(["gzip","deflate","br"]);class nu{cfg;tokens;logs;bus;detector;middleware;server;running=!1;addr="";upgradedSockets=new Set;recentRequests=[];constructor(e,t,n,r,o,i=[]){this.cfg=e,this.tokens=t,this.logs=n,this.bus=r,this.detector=o,this.middleware=i}address(){return this.addr||fr(this.cfg.listen)}isRunning(){return this.running}stats(){let e=this.recentRequests.reduce((t,n)=>t+(n.status>=400||n.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>fh)this.recentRequests.splice(0,this.recentRequests.length-fh)}start(){if(this.cfg.listen.host==="0.0.0.0")return Promise.reject(L($n,"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(L($n,"proxy.listen.port is required when the proxy is enabled"));let t=this.cfg.listen.port;return new Promise((n,r)=>{this.server=hh((o,i)=>{this.serve(o,i)}),this.server.on("upgrade",(o,i,s)=>{this.serveUpgrade(o,i,s)}),this.server.on("error",(o)=>r(fe($n,`unable to listen on ${e}:${t}`,o))),this.server.listen(t,e,()=>{this.running=!0,this.addr=`${e}:${t}`,this.bus?.publish(Me(Em,"",{address:this.addr})),n()})})}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(Me(Tm,"",{})),t()})})}async serveUpgrade(e,t,n){let r=Date.now(),o=e.headers[Ni]?.toString()||ph(8).toString("hex"),i=e.method??"GET",s=e.url??"/",a=this.detector?this.detector.redactText(s):s,c=mh(this.cfg.routes,e);if(!c){t.end(`HTTP/1.1 404 Not Found\r
625
+ `)}function cx(e){let t=e.doctor.tools.map((i)=>i.name||i.command).filter((i)=>i!==""),n=e.plugins.map((i)=>i.path).filter((i)=>i!==""),r=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:n.join(", ")||"\u2014",tone:n.length>0?"text":"muted"},{label:"keymap",value:r.length>0?`${r.length} override${r.length===1?"":"s"}`:"defaults",tone:r.length>0?"text":"muted"},{label:"secrets",value:o.length>0?o.join(", "):"defaults",tone:o.length>0?"text":"muted"}]}function YR(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 lx(e){let t=e.reduce((n,r)=>Math.max(n,r.name.length),0);return Math.min(QR,Math.max(XR,t))}function ZR(e){let t=e.proxy.token_endpoint;if(!t.enabled)return"off";let n=t.host===""?"127.0.0.1":t.host;if(t.port===0)return n;return`${n}:${t.port}`}function eP(e){let t=e.match.host||"*",n=e.match.path;if(n==="")return t;return`${t}${n.startsWith("/")?n:`/${n}`}`}function tP(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 nP(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 XR=8,QR=20,dx=80,Uo=10;var Ku=D(()=>{st();Ao();Pe()});function Pc(e){let t=e.toLowerCase().trim(),n=rP[t];if(n)return n;return yt.includes(t)?t:"devctl"}function oP(){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"}),n=t.stdout.toString();if(t.exitCode===0&&n.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 ux(e){let t=Pc(e);if(t==="system"){if(oP())return{...qu["solarized-light"],name:"system"};return qu.system}return qu[t]}function Mt(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 Br(e,t){return cs(e)>=as?Tc:t}function cs(e){let t=e.startsWith("#")?e.slice(1):e,n=Number.parseInt(t,fP);if(Number.isNaN(n))return 0;let r=n>>gP&Vu,o=n>>mP&Vu,i=n&Vu;return(r*lP+o*dP+i*uP)/pP}function hP(e){let t=aP;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,cP);return t>>>0}function Ac(e){return cs(e.background)>=as}function zu(e){if(!e||!/^#[0-9a-f]{6}$/i.test(e))return!1;return cs(e)<as}function Lc(e,t){let n=vP[e];return Ac(t)?n.light:n.dark}function px(e,t){return cs(Lc(e,t))>=as?yP:xP}function He(e,t){if(e===""||e==="all")return t.muted;let n=cs(t.background)>=as?sP:iP;return n[hP(e)%n.length]??t.info}function bP(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 fx(e,t,n){if(n==="string")return e.accent;if(n==="number")return e.info;if(n==="keyword")return e.error;return bP(e,t)}function De(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 yt,Ju,qu,rP,iP,sP,aP=2166136261,cP=16777619,lP=299,dP=587,uP=114,pP=1000,as=160,fP=16,Vu=255,gP=16,mP=8,Tc="#1A1A1A",vP,yP="#1A1A1A",xP="#F5F5F5";var Ye=D(()=>{yt=["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"],Ju={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)"},qu={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"}},rP={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"};iP=["#7AA2F7","#9ECE6A","#E0AF68","#BB9AF7","#2AC3DE","#FF9E64","#F7768E","#73DACA","#C0CAF5","#FF79C6","#7DCFFF","#C3E88D"],sP=["#2E5AAC","#3D7A1F","#9A6B12","#6B3FA0","#0E7A86","#B85C1A","#B4234A","#1A7A6D","#4A5080","#9A3480","#1565C0","#4A7C19"];vP={claude:{dark:"#E08A6A",light:"#B54328"},cursor:{dark:"#B8D4FF",light:"#1E4EBF"},kilo:{dark:"#F0C94A",light:"#8A6400"},codex:{dark:"#4ADE80",light:"#0B7A4B"}}});function hx(){return Vi()!==void 0}function gx(e){let t=e/1000;if(Number.isInteger(t))return`${t}s`;return`${e}ms`}function Qu(e,t,n){let r=e.indexOf(t),i=((r<0?0:r)+n+e.length)%e.length;return e[i]??e[0]}function vx(e,t){let n=[...yt],r=n.includes(e)?e:Xu;return Qu(n,r,t)}function yx(e,t){let n=[...wP],r=n.reduce((o,i)=>Math.abs(i-e)<Math.abs(o-e)?i:o,n[0]);return Qu(n,r,t)}function ls(e){let t=[...Yu];return t.reduce((n,r)=>Math.abs(r-e)<Math.abs(n-e)?r:n,t[0])}function Oc(e,t){return Qu([...Yu],ls(e),t)}function ds(e){let t=ls(e),n=mx[t]??mx[$r];return{px:t,...n}}function kn(e){return e.label==="compact"}function us(e){return e.steps<=2}function xx(e){return Yu.map((n,r)=>r<e?"\u2588":"\u2591").join(" ")}function Dc(e){return ds(e).label}function bx(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:Dc(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:gx(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:pt,hint:"read-only",detail:Dt()},{id:"reset",group:"About",kind:"action",name:"Reset",value:"defaults",hint:"enter confirm reset",detail:`Restore theme ${Xu}, display ${Dc($r)}, mouse on, leader ${gx(Za)}. Enter asks first. ${t}`}]}function Zu(){return{theme:Xu,mouse:!0,leader_timeout:Za,font_size:$r}}function wx(e){return["Appearance","Input","MCP","About"].flatMap((n)=>{let r=e.filter((o)=>o.group===n);if(r.length===0)return[];return[{group:n,items:r}]})}function ep(e,t){if(e.length===0)return 0;return Math.min(Math.max(t,0),e.length-1)}function Ko(e,t){return e[ep(e,t)]}function tp(){return Vi()??ec()}var wP,Yu,Xu="devctl",mx;var Cn=D(()=>{Ye();Zt();wP=[1000,2000,3000],Yu=[12,14,16,18,20,22];mx={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 SP,useContext as kP}from"react";function se(){return kP(np)}var np;var at=D(()=>{Cn();Zt();np=SP(ds($r))});import{useEffect as CP,useRef as _P}from"react";import{jsxDEV as ae,Fragment as RP}from"@opentui/react/jsx-dev-runtime";function EP(e,t){switch(t){case"primary":return{bg:e.primary,fg:Br(e.primary,e.inverse)};case"accent":return{bg:e.accent,fg:Ac(e)?Tc:Br(e.accent,e.inverse)};case"success":return{bg:e.success,fg:Br(e.success,e.inverse)};case"warning":return{bg:e.warning,fg:Ac(e)?Tc:Br(e.warning,e.inverse)};case"error":return{bg:e.error,fg:Br(e.error,e.inverse)};case"info":return{bg:e.info,fg:Br(e.info,e.inverse)};case"muted":return{bg:e.element,fg:e.text};default:return{bg:e.element,fg:e.text}}}function Sx(e){let{palette:t,dir:n}=e;return ae("box",{width:2,height:1,flexShrink:0,overflow:"hidden",children:ae("text",{fg:t.muted,children:n==="left"?"\u2039":"\u203A"},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function je(e){let{palette:t,children:n,backgroundColor:r,edge:o="bottom"}=e,i=se(),s=e.ruled??!kn(i),a=r??t.element,c=ae("box",{flexShrink:0,flexDirection:"column",backgroundColor:a,overflow:"hidden",children:n},void 0,!1,void 0,this);if(!s)return c;return ae("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 Mc(e){let{palette:t,items:n,active:r,width:o,onPick:i}=e,s=n.map((d)=>Vn(d.label)),a=$v(s,r,Math.max(1,o)),c=a.start>0,l=a.end>=0&&a.end<n.length-1;return ae("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[c?ae(Sx,{palette:t,dir:"left"},void 0,!1,void 0,this):null,n.map((d,f)=>{if(f<a.start||f>a.end)return null;let g=f===r;return ae(ge,{palette:t,label:d.label,tone:g?"primary":"muted",fg:g?void 0:d.color,onMouseDown:()=>i(f)},d.id,!1,void 0,this)}),l?ae(Sx,{palette:t,dir:"right"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function ge(e){let{palette:t,label:n,tone:r="idle",fg:o,bg:i,onMouseDown:s}=e,a=EP(t,r);return ae("box",{height:1,paddingLeft:1,paddingRight:1,backgroundColor:i??a.bg,overflow:"hidden",flexShrink:0,onMouseDown:s,children:ae("text",{fg:o??a.fg,children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Oe(e){let{palette:t,hints:n}=e;return ae("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:n.map((r)=>ae("box",{height:1,paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ae("text",{wrapMode:"none",children:[ae("span",{fg:t.primary,children:r.key},void 0,!1,void 0,this),ae("span",{fg:t.muted,children:` ${r.label}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},`${r.key}-${r.label}`,!1,void 0,this))},void 0,!1,void 0,this)}function Be(e){let{palette:t,items:n,hints:r,ruled:o=!0}=e,i=ae("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[n.map((s,a)=>ae(ge,{palette:t,label:s.text,tone:s.tone,onMouseDown:s.onMouseDown},`${s.text}-${a}`,!1,void 0,this)),r&&r.length>0?ae(RP,{children:[ae("box",{flexGrow:1,backgroundColor:t.element},void 0,!1,void 0,this),ae(Oe,{palette:t,hints:r},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this);if(!o)return i;return ae(je,{palette:t,backgroundColor:t.element,children:i},void 0,!1,void 0,this)}function qe(e){let{palette:t,title:n,termW:r,termH:o,preferW:i,preferH:s,anchor:a="center",borderColor:c,bottomTitle:l,gap:d,children:f}=e,g=kn(se()),m=No(r,o,i,s,a,!g);return ae("box",{position:"absolute",left:m.left,top:m.top,width:m.width,height:m.height,border:!0,borderStyle:rp,borderColor:c??t.borderActive,backgroundColor:t.panel,padding:g?0:1,title:n,titleColor:t.primary,bottomTitle:l,gap:g?0:d,flexDirection:"column",overflow:"hidden",children:f},void 0,!1,void 0,this)}function Te(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 qo(e,t){let n=_P(null);return CP(()=>{let r=n.current;if(!r||e<0)return;let o=requestAnimationFrame(()=>{r.scrollChildIntoView(`${t}-${e}`)});return()=>cancelAnimationFrame(o)},[t,e]),n}function tt(e){let t=se(),n=us(t),r=e.scroll?ae("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(e.palette),children:ae("box",{flexDirection:"column",overflow:"hidden",children:e.children},void 0,!1,void 0,this)},void 0,!1,void 0,this):e.children;return ae("box",{flexGrow:1,border:!0,borderStyle:rp,borderColor:e.borderColor??e.palette.border,title:e.title,titleColor:e.palette.primary,paddingLeft:t.pad,paddingRight:t.pad,paddingTop:n?0:t.pad,paddingBottom:n?0:t.pad,backgroundColor:e.palette.panel,flexDirection:"column",overflow:"hidden",children:r},void 0,!1,void 0,this)}function Wr(e){let{palette:t,label:n,value:r,tone:o="text"}=e,i=se(),s=o==="success"?t.success:o==="warning"?t.warning:o==="error"?t.error:o==="muted"?t.muted:t.text;return ae("box",{height:i.rowH,flexDirection:"row",overflow:"hidden",children:[ae("box",{width:14,flexShrink:0,overflow:"hidden",children:ae("text",{fg:t.muted,children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this),ae("box",{flexGrow:1,overflow:"hidden",children:ae("text",{fg:s,wrapMode:"none",children:r},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $c(e){let{palette:t,title:n,body:r,hint:o}=e;return ae("box",{paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",border:!0,borderStyle:rp,borderColor:t.borderActive,titleColor:t.primary,children:[ae("text",{fg:t.primary,children:n},void 0,!1,void 0,this),ae("text",{fg:t.text,wrapMode:"word",children:r},void 0,!1,void 0,this),o?ae("text",{fg:t.muted,wrapMode:"word",children:o},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var rp="rounded";var be=D(()=>{at();Cn();Ye();Pe()});import{jsxDEV as de,Fragment as kx}from"@opentui/react/jsx-dev-runtime";function Cx(e){let{palette:t,cfg:n,snap:r,google:o,profile:i,reveal:s,width:a}=e,c=wc(r,n?Object.keys(n.services):void 0),l=r?.proxy.running===!0,d=o?.adcAvailable===!0,f=a<uc,g=ce(n?.project.name||"local",f?18:22),m=ce(i||r?.profile||"no profile",16),x=de(kx,{children:Jv({width:a,running:c.running,total:c.total,proxyOn:l,proxyAddress:r?.proxy.address??"",mcpOn:r?.mcp?.running===!0,adc:d,reveal:s}).filter((w)=>!w.hide&&w.label!=="").map((w)=>de(ge,{palette:t,label:w.label,tone:w.tone},w.label,!1,void 0,this))},void 0,!1,void 0,this),v=us(se());return de(je,{palette:t,backgroundColor:t.panel,ruled:!v,children:de("box",{height:f?2:1,flexDirection:"column",backgroundColor:t.panel,overflow:"hidden",children:[de("box",{height:1,flexDirection:"row",overflow:"hidden",children:[de(ge,{palette:t,label:Dt(),tone:"primary"},void 0,!1,void 0,this),de(ge,{palette:t,label:g,tone:"idle"},void 0,!1,void 0,this),de(ge,{palette:t,label:m,tone:"accent"},void 0,!1,void 0,this),f?null:de(kx,{children:[de("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),f?de("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 _x(e){let{palette:t,screen:n,width:r,onSelect:o}=e,i=Jn.map((a)=>({id:a.id,label:Mv(a.label,r)})),s=Iv(n);return de(je,{palette:t,backgroundColor:t.element,children:de(Mc,{palette:t,items:i,active:s,width:r,onPick:(a)=>{let c=Jn[a];if(c)o(c.id)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ex(e){let{palette:t,overlay:n,query:r,onQuery:o,onSubmit:i}=e;if(n==="slash"||n==="palette"){let c=n==="slash"?"/":"> ";return de(je,{palette:t,backgroundColor:t.highlight,edge:"top",children:de("box",{height:1,backgroundColor:t.highlight,paddingLeft:1,flexDirection:"row",overflow:"hidden",children:[de("box",{width:2,flexShrink:0,children:de("text",{fg:t.primary,children:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),de("box",{flexGrow:1,overflow:"hidden",children:de("input",{focused:!0,value:r,placeholder:n==="slash"?"start auth":"filter commands",onInput:o,onSubmit:()=>i(r),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=n==="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 de(je,{palette:t,backgroundColor:t.element,edge:"top",children:de("box",{height:1,backgroundColor:t.element,overflow:"hidden",children:de(Oe,{palette:t,hints:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Rx(e){let{palette:t,screen:n,overlay:r,status:o,paused:i,errorOnly:s,width:a,copyKey:c}=e,l=us(se()),d=Math.max(18,Math.floor(a*0.42)),f=Fo(Wy(n,r,c),d),g=Xv(o);return de(je,{palette:t,backgroundColor:t.panel,edge:"top",ruled:!l,children:de("box",{height:1,backgroundColor:t.panel,overflow:"hidden",children:de(Be,{ruled:!1,palette:t,items:[{text:n,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:g}]],hints:f},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function $e(e){return de("box",{flexGrow:1,padding:1,overflow:"hidden",children:de($c,{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 Ic(e){return de("box",{flexGrow:1,padding:1,overflow:"hidden",children:de("text",{fg:e.palette.text,children:e.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Px(e){return de("box",{flexGrow:1,padding:1,flexDirection:"column",overflow:"hidden",children:[de("text",{fg:e.palette.error,children:e.title},void 0,!1,void 0,this),de("text",{fg:e.palette.text,wrapMode:"word",children:e.body},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Et=D(()=>{at();Pe();be();Cn();Ye()});function PP(){if(process.platform==="darwin")return[["pbcopy"]];if(process.platform==="win32")return[["clip"]];return[["wl-copy"],["xclip","-selection","clipboard"],["xsel","--clipboard","--input"]]}function TP(){return PP().filter((e)=>{let t=e[0];return typeof t==="string"&&Bun.which(t)!==null})}function AP(e){return`\x1B]52;c;${Buffer.from(e,"utf8").toString("base64")}\x07`}function Tx(){if(process.platform==="linux")return"install wl-clipboard (Wayland) or xclip (X11)";return"no clipboard helper found"}async function op(e){let t=TP(),n;for(let r of t)try{await DP(r,e);return}catch(o){n=o instanceof Error?o:Error(String(o))}if(process.platform!=="win32")try{await LP(e);return}catch(r){n=r instanceof Error?r:Error(String(r))}throw ke(Je,"clipboard unavailable",n?`${Tx()} (${n.message})`:Tx())}async function LP(e){let t=AP(e);try{await Bun.write("/dev/tty",t)}catch{if(!process.stderr.write(t))throw Error("terminal clipboard write failed")}}async function DP(e,t){let n=Bun.spawn(e,{stdin:"pipe",stdout:"ignore",stderr:"ignore"});n.stdin.write(t),await n.stdin.end();let r=await n.exited;if(r!==0)throw Error(`${e[0]} exited ${r}`)}var Ax=D(()=>{Re()});function Lx(e){return e==="slash"||e==="palette"||e==="config-edit"}function Dx(e,t){return wn(e,t.keybinds.leader??"ctrl+x")}function Ox(e,t){return wn(e,t.keybinds.command_list??"ctrl+p")}function Mx(e,t){return wn(e,t.keybinds.command??"/")||e.name==="/"}function $x(e,t){return wn(e,t.keybinds.help??"?")||e.sequence==="?"}function Ix(e,t){return wn(e,t.keybinds.search??"f")}function Fx(e){let t=e.name??"";return t==="R"||e.shift===!0&&t.toLowerCase()==="r"}function Nx(e){return e.ctrl===!0&&(e.name??"").toLowerCase()==="l"}function Hx(e,t){if(t&&wn(e,t.keybinds.interrupt??"ctrl+c"))return!0;return e.ctrl===!0&&(e.name??"").toLowerCase()==="c"}function jx(e,t){return wn(e,t.keybinds.copy??bn())}function Bx(e,t,n=OP){return t>0&&e-t<=n}function Yn(e,t,n,r){return wn(e,t.keybinds[n]??r)}function Fc(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 OP=2000;var Wx=D(()=>{Zt()});import{jsxDEV as Xn}from"@opentui/react/jsx-dev-runtime";function Gx(e){let{palette:t,path:n,initialValue:r,error:o,termW:i,termH:s,textareaRef:a}=e;return Xn(qe,{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:[Xn("box",{height:1,overflow:"hidden",children:Xn("text",{fg:t.muted,wrapMode:"none",children:n},void 0,!1,void 0,this)},void 0,!1,void 0,this),Xn("textarea",{ref:a,focused:!0,initialValue:r,backgroundColor:t.panel,focusedBackgroundColor:t.panel,textColor:t.text,focusedTextColor:t.text,cursorColor:t.primary},void 0,!1,void 0,this),o!==""?Xn("box",{height:2,overflow:"hidden",children:Xn("text",{fg:t.error,wrapMode:"word",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this):Xn("box",{height:1,overflow:"hidden",children:Xn("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 Ux=D(()=>{be()});import{jsxDEV as ip}from"@opentui/react/jsx-dev-runtime";function Kx(e){let{palette:t,title:n,body:r,termW:o,termH:i}=e;return ip(qe,{palette:t,title:n,bottomTitle:"enter confirm \xB7 esc stay",termW:o,termH:i,preferW:52,preferH:8,borderColor:t.warning,gap:1,children:[ip("text",{fg:t.text,wrapMode:"word",children:r},void 0,!1,void 0,this),ip(Oe,{palette:t,hints:[{key:"enter",label:"confirm"},{key:"esc",label:"stay"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var qx=D(()=>{be()});import{jsxDEV as Rt,Fragment as MP}from"@opentui/react/jsx-dev-runtime";function Vx(e){let{palette:t,event:n,termW:r,termH:o,scrollRef:i}=e;if(!n)return null;let s=n.raw?Wv(n.raw):void 0,a=n.message.length>120||n.message.includes(`
626
+ `)||s!==void 0;return Rt(qe,{palette:t,title:"log details",bottomTitle:"j/k scroll \xB7 esc close",termW:r,termH:o,preferW:a?84:72,preferH:a?22:14,gap:1,children:Rt("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Rt("box",{flexDirection:"column",overflow:"hidden",children:[Rt("text",{fg:t.text,wrapMode:"word",children:Io(n.message)},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`time ${n.timestamp}`},void 0,!1,void 0,this),Rt("text",{fg:He(n.service,t),children:`service ${n.service}`},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`source ${n.source}${n.stream?` / ${n.stream}`:""}`},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`level ${hc(n.level)}`},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`pid ${n.pid||"\u2014"}`},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`request ${n.request_id||"\u2014"}`},void 0,!1,void 0,this),Rt("text",{fg:t.muted,children:`identity ${n.identity||"\u2014"}`},void 0,!1,void 0,this),s===void 0?null:Rt(MP,{children:[Rt("text",{fg:t.muted,children:"raw json"},void 0,!1,void 0,this),Rt("text",{fg:t.text,wrapMode:"word",children:s},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var Jx=D(()=>{be();Pe();Ye()});import{jsxDEV as we,Fragment as Yx}from"@opentui/react/jsx-dev-runtime";function WP(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 Zn(e){return e+FP}function Xx(e){let t=Zn(ap.length),n=Zn(cp.length),r=Zn(e.logCount),o=Zn(lp.length),i=Zn(dp.length),s=up+e.pad*2;if(e.stacked)return s+t+n+r+o+i+sp+(jP-1)*e.gap;let a=Math.max(t,n),c=Math.max(o,i);return s+a+r+c+sp+(BP-1)*e.gap}function GP(e){return Xx(e)-up-e.pad*2}function UP(e){return e-up*2<IP}function Qx(e){let{palette:t,termW:n,termH:r,copyKey:o=bn(),scrollRef:i}=e,s=kn(se()),a=UP(n),c=s?0:1,l=s?0:1,d=WP(o),f={stacked:a,logCount:d.length,pad:c,gap:l},g=Xx(f),m=GP(f);return we(qe,{palette:t,title:"help",bottomTitle:`${Dt()} \xB7 j/k scroll \xB7 esc close`,termW:n,termH:r,preferW:$P,preferH:g,gap:0,children:we("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:we("box",{height:m,flexDirection:"column",flexShrink:0,overflow:"hidden",gap:l,children:[a?we(Yx,{children:[we(Qn,{palette:t,title:"navigation",bindings:ap},void 0,!1,void 0,this),we(Qn,{palette:t,title:"services",bindings:cp},void 0,!1,void 0,this),we(Qn,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),we(Qn,{palette:t,title:"commands",bindings:lp},void 0,!1,void 0,this),we(Qn,{palette:t,title:"display",bindings:dp},void 0,!1,void 0,this)]},void 0,!0,void 0,this):we(Yx,{children:[we(zx,{palette:t,left:{title:"navigation",bindings:ap},right:{title:"services",bindings:cp}},void 0,!1,void 0,this),we(Qn,{palette:t,title:"logs",bindings:d},void 0,!1,void 0,this),we(zx,{palette:t,left:{title:"commands",bindings:lp},right:{title:"display",bindings:dp}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),we("box",{height:sp,flexShrink:0,overflow:"hidden",paddingLeft:1,children:we("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 zx(e){let{palette:t,left:n,right:r}=e,o=Math.max(Zn(n.bindings.length),Zn(r.bindings.length));return we("box",{height:o,flexDirection:"row",flexShrink:0,overflow:"hidden",gap:HP,children:[we(Qn,{palette:t,title:n.title,bindings:n.bindings,height:o,stretch:!0},void 0,!1,void 0,this),we(Qn,{palette:t,title:r.title,bindings:r.bindings,height:o,stretch:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Qn(e){let{palette:t,title:n,bindings:r,stretch:o=!1}=e,i=e.height??Zn(r.length);return we("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:n,titleColor:t.accent,children:r.map((s)=>we("box",{height:1,flexShrink:0,overflow:"hidden",paddingLeft:1,paddingRight:1,children:we(KP,{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 KP(e){let{palette:t,binding:n}=e;return we("box",{height:1,flexDirection:"row",overflow:"hidden",children:[we("box",{width:NP,flexShrink:0,overflow:"hidden",children:we("text",{fg:t.primary,wrapMode:"none",children:n.key},void 0,!1,void 0,this)},void 0,!1,void 0,this),we("box",{flexGrow:1,overflow:"hidden",children:we("text",{fg:t.text,wrapMode:"none",children:n.label},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var $P=78,IP=56,FP=2,up=2,sp=1,pp=8,NP=16,HP=2,jP=6,BP=4,ap,cp,lp,dp;var Zx=D(()=>{at();be();Cn();Zt();ap=[{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"}],cp=[{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"}];lp=[{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:"/diff",label:"config sources"},{key:"/mcp",label:"agent MCP server"}],dp=[{key:"ctrl+=",label:"larger"},{key:"ctrl+-",label:"smaller"},{key:"?",label:"this overlay"}]});import{jsxDEV as eb}from"@opentui/react/jsx-dev-runtime";function tb(e){let{palette:t,termW:n,termH:r}=e,o=Uu();return eb(qe,{palette:t,title:"leader",termW:n,termH:r,preferW:68,preferH:5,anchor:"bottom",children:eb(Oe,{palette:t,hints:o},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var nb=D(()=>{Pe();be()});import{jsxDEV as rb}from"@opentui/react/jsx-dev-runtime";function ob(e){let{palette:t,items:n,selected:r,termW:o,termH:i,onIndex:s,onPick:a}=e,c=By(n),l=No(o,i,64,18,"center",!kn(se()));return rb(qe,{palette:t,title:"commands",bottomTitle:"enter select \xB7 esc close",termW:o,termH:i,preferW:64,preferH:18,children:rb("select",{height:Math.max(4,l.height-3),options:c,selectedIndex:r,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,f)=>{let g=f?.value;if(typeof g==="string"&&g!=="")a(g)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var ib=D(()=>{at();Pe();be();Cn()});import{jsxDEV as H}from"@opentui/react/jsx-dev-runtime";function fp(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 qP(e,t,n,r){if(t!=="")return{icon:"\u2717",label:"Failed",tone:"error",color:r.error};if(!e)return{icon:"\u2713",label:"Finished",tone:"success",color:r.success};if(n==="unhealthy")return{icon:"\u26A0",label:"Waiting on health",tone:"warning",color:r.warning};return{icon:"\u25CF",label:"Running",tone:"primary",color:r.primary}}function sb(e){return H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:H("text",{wrapMode:"none",children:[H("span",{fg:e.palette.primary,children:e.label.toUpperCase()},void 0,!1,void 0,this),e.detail?H("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 ab(e){let{palette:t,plan:n,snap:r,busy:o,failed:i,kind:s,termW:a=80,termH:c=24,scrollRef:l,initiallyRunning:d=[],onDismiss:f}=e,g=new Set(d),m=n.waves.map((oe,Ue)=>({wave:oe.filter((Ee)=>!g.has(Ee)),waveIdx:Ue})).filter(({wave:oe})=>oe.length>0),x=Oy(n,r,s),v=n.waves[x.currentWaveIndex]??[],w=is(v,r,s),E=fp(w,t),k=qP(o,i,w,t),j=$y(s,o,i,n.profile),V=Iy(o,i),C=i?t.inverse:t.text,y=i?t.error:t.element,B=Math.min(92,Math.max(40,a-8)),h=B>=82?22:B>=66?17:13,q=12,I=9,z=B>=56,ue=B>=72,Ie=B<72||n.waves.length>3,ct=n.profile?`PROFILE ${n.profile}`:s.toUpperCase();return H(qe,{palette:t,title:j,bottomTitle:"enter close \xB7 esc hide (operation continues)",termW:a,termH:c,preferW:98,preferH:28,borderColor:k.color,gap:0,children:[H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[H(ge,{palette:t,label:`${k.icon} ${k.label.toUpperCase()}`,tone:k.tone},void 0,!1,void 0,this),H("box",{paddingLeft:1,flexGrow:1,overflow:"hidden",children:H("text",{fg:t.text,wrapMode:"none",children:ct},void 0,!1,void 0,this)},void 0,!1,void 0,this),H(ge,{palette:t,label:`${x.ready}/${x.total} READY`,tone:x.isComplete?"success":"info"},void 0,!1,void 0,this),H(ge,{palette:t,label:`WAVE ${Math.min(x.currentWaveIndex+1,Math.max(1,x.totalWaves))}/${Math.max(1,x.totalWaves)}`,tone:E.tone},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("box",{height:2,flexDirection:"column",overflow:"hidden",flexShrink:0,paddingLeft:1,paddingRight:1,children:[H("box",{height:1,flexDirection:"row",overflow:"hidden",children:[H("text",{wrapMode:"none",children:[H("span",{fg:t.muted,children:"PROGRESS "},void 0,!1,void 0,this),H("span",{fg:k.color,children:`[${x.progressBar}]`},void 0,!1,void 0,this),H("span",{fg:t.text,children:` ${x.percent}%`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("box",{flexGrow:1},void 0,!1,void 0,this),H("text",{wrapMode:"none",children:H("span",{fg:E.color,children:`${E.icon} ${E.label}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("box",{height:1,overflow:"hidden",children:H("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.":V.primary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H(sb,{palette:t,label:"Pipeline",detail:`${n.waves.length} execution wave${n.waves.length===1?"":"s"}`},void 0,!1,void 0,this),H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:n.waves.map((oe,Ue)=>{let Ee=is(oe,r,s),Qe=fp(Ee,t),pe=Ie?`W${Ue+1} ${Qe.icon} ${oe.length}`:`W${Ue+1} ${Qe.icon} ${Qe.label} \xB7 ${oe.length}`;return H("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:[H(ge,{palette:t,label:pe,tone:Qe.tone},void 0,!1,void 0,this),Ue<n.waves.length-1?H("box",{width:3,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:" \u2500\u25BA"},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},`step-${Ue}`,!0,void 0,this)})},void 0,!1,void 0,this),(n.blockers??[]).length>0?H("box",{minHeight:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:H("text",{fg:t.error,wrapMode:"word",children:`BLOCKED ${n.blockers?.map((oe)=>`${oe.name}: ${oe.message}`).join(" \xB7 ")}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,d.length>0?H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,paddingLeft:1,children:H("text",{wrapMode:"none",children:[H("span",{fg:t.success,children:"\u2713 ALREADY READY"},void 0,!1,void 0,this),H("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,H(sb,{palette:t,label:"Wave details",detail:"live process and health state"},void 0,!1,void 0,this),H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,paddingLeft:1,children:[H("box",{width:2,flexShrink:0},void 0,!1,void 0,this),H("box",{width:h,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:ee("SERVICE",h)},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:12,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:ee("STATE",12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),z?H("box",{width:9,flexShrink:0,overflow:"hidden",children:H("text",{fg:t.muted,children:ee("PORT",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ue?H("box",{flexGrow:1,overflow:"hidden",children:H("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),H("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:H("box",{flexDirection:"column",overflow:"hidden",gap:1,children:m.map(({wave:oe,waveIdx:Ue})=>{let Ee=is(oe,r,s),Qe=fp(Ee,t),pe=`${My(s,Ue,Ee)} \xB7 ${oe.length} service${oe.length===1?"":"s"}`;return H("box",{border:!0,borderStyle:"rounded",borderColor:Qe.color,title:pe,titleColor:Qe.color,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:oe.map((Se)=>{let It=r?.services[Se],N=Bt(It),Pt=Dy(Se,n,r,s),nt=Se===i||N==="FAILED",Ve=N==="UNHEALTHY",Wt=N==="HEALTHY"||s==="stop"&&N==="STOPPED",lt=jr(It),tr=nt?"\u2717":Wt?"\u2713":Ve?"\u26A0":N==="STARTING"||N==="RUNNING"||N==="STOPPING"||N==="RESTARTING"?"\u25CF":"\u25CB",mt=nt?t.error:De(t,N),on=nt?t.error:Ve?t.warning:Wt?t.success:t.muted;return H("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[H("box",{width:2,flexShrink:0,overflow:"hidden",children:H("text",{fg:mt,children:tr},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:h,flexShrink:0,overflow:"hidden",children:H("text",{fg:He(Se,t),wrapMode:"none",children:ee(Se,h)},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{width:12,flexShrink:0,overflow:"hidden",children:H("text",{fg:De(t,N),wrapMode:"none",children:ee(N,12)},void 0,!1,void 0,this)},void 0,!1,void 0,this),z?H("box",{width:9,flexShrink:0,overflow:"hidden",children:H("text",{fg:lt?t.info:t.muted,wrapMode:"none",children:ee(lt?`:${lt}`:"\u2014",9)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ue?H("box",{flexGrow:1,overflow:"hidden",children:H("text",{fg:on,wrapMode:"none",children:Pt},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},Se,!0,void 0,this)})},`wave-card-${Ue}`,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("box",{height:3,flexShrink:0,flexDirection:"column",backgroundColor:y,border:["top"],borderStyle:"single",borderColor:k.color,paddingLeft:1,paddingRight:1,overflow:"hidden",onMouseDown:f,children:[H("text",{fg:C,wrapMode:"none",children:V.primary},void 0,!1,void 0,this),H("text",{fg:i?t.inverse:t.muted,wrapMode:"none",children:V.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var cb=D(()=>{Pe();be();Ye()});import{jsxDEV as tn}from"@opentui/react/jsx-dev-runtime";function lb(e){let{palette:t,route:n,termW:r,termH:o,scrollRef:i}=e;if(!n)return null;return tn(qe,{palette:t,title:n.name,bottomTitle:"j/k scroll \xB7 esc close",termW:r,termH:o,preferW:78,preferH:16,gap:1,children:tn("scrollbox",{ref:i,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:tn("box",{flexDirection:"column",overflow:"hidden",children:[tn("text",{fg:t.muted,children:`auth ${n.authType||"none"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`identity ${n.identityType||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`account ${n.serviceAccount||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`audience ${n.audience||"\u2014"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`match host ${n.matchHost||"*"}`},void 0,!1,void 0,this),tn("text",{fg:t.muted,children:`match path ${n.matchPath||"*"}`},void 0,!1,void 0,this),tn("text",{fg:t.text,wrapMode:"word",children:`upstream ${n.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 db=D(()=>{be()});import{jsxDEV as Hc}from"@opentui/react/jsx-dev-runtime";function ub(e){let{palette:t,title:n,body:r,termW:o,termH:i,scrollRef:s}=e,a=r.length>400||r.split(`
627
+ `).length>16;return Hc(qe,{palette:t,title:n,bottomTitle:"j/k scroll \xB7 esc close",termW:o,termH:i,preferW:a?88:76,preferH:a?24:16,gap:1,children:Hc("scrollbox",{ref:s,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Hc("box",{flexDirection:"column",overflow:"hidden",children:Hc("text",{fg:r===""?t.muted:t.text,wrapMode:"word",children:r===""?"(empty)":r},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var pb=D(()=>{be()});import{jsxDEV as $t}from"@opentui/react/jsx-dev-runtime";function gb(e){let{palette:t,items:n,query:r,selected:o,onQuery:i,onSubmit:s}=e,a=Gy(o,fb,n.length),c=n.slice(a,a+fb),l=Math.max(c.length,1),d=Hr(n,o);return $t("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?$t("box",{height:1,paddingLeft:1,overflow:"hidden",children:$t("text",{fg:t.muted,children:"no matching command"},void 0,!1,void 0,this)},void 0,!1,void 0,this):c.map((f)=>{let g=f.name===d?.name;return $t("box",{height:1,flexDirection:"row",overflow:"hidden",paddingLeft:1,paddingRight:1,backgroundColor:g?t.highlight:t.panel,children:[$t("box",{width:14,flexShrink:0,overflow:"hidden",children:$t("text",{fg:g?t.primary:t.text,wrapMode:"none",children:`${g?"\u203A":" "} /${f.name}`},void 0,!1,void 0,this)},void 0,!1,void 0,this),$t("box",{flexGrow:1,overflow:"hidden",children:$t("text",{fg:g?t.accent:t.muted,wrapMode:"none",children:f.desc},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},f.name,!0,void 0,this)}),$t("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.highlight,paddingLeft:1,children:[$t("box",{width:2,flexShrink:0,children:$t("text",{fg:t.primary,children:"/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),$t("box",{flexGrow:1,overflow:"hidden",children:$t("input",{focused:!0,value:r,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 fb=8;var mb=D(()=>{Pe()});import{jsxDEV as yb}from"@opentui/react/jsx-dev-runtime";function xb(e){let{palette:t,themeName:n,selected:r,termW:o,termH:i,onIndex:s,onPreview:a,onPick:c}=e,l=yt.map((f)=>({name:f===n?`${f} (active)`:f,description:f===n?`${Ju[f]} \xB7 current`:Ju[f],value:f})),d=No(o,i,hb,vb,"center",!kn(se()));return yb(qe,{palette:t,title:"/themes",bottomTitle:"enter save \xB7 esc revert",termW:o,termH:i,preferW:hb,preferH:vb,children:yb("select",{height:Math.max(4,d.height-3),options:l,selectedIndex:r,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:(f)=>{s(f);let g=yt[f];if(g)a(g)},onSelect:(f,g)=>{let m=g?.value;if(typeof m==="string"&&m!=="")c(m)}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var hb=52,vb=22;var bb=D(()=>{at();Pe();be();Cn();Ye()});import{jsxDEV as Ge}from"@opentui/react/jsx-dev-runtime";function jc(e){let{palette:t,title:n,tone:r="muted",children:o}=e,i=r==="success"?t.success:r==="warning"?t.warning:r==="error"?t.error:t.border;return Ge("box",{border:!0,borderStyle:"rounded",borderColor:i,title:n,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function wb(e){let{palette:t,cfg:n,google:r,identity:o}=e;if(!r&&!o)return Ge(Ic,{palette:t,label:"Checking Application Default Credentials\u2026"},void 0,!1,void 0,this);let i=VP(n,o),s=o?.user||r?.userEmail||"",{project:a,source:c}=Go(n,o,r),l=o?.adc??r?.adcAvailable===!0,d=o?.iap??(n?.proxy.routes??[]).some((v)=>v.auth.type.toLowerCase()==="iap"),f=i.filter((v)=>v.inactive!==!0),g=f.some((v)=>v.ok===!0),m=f.some((v)=>v.ok===!1),x=g?"AVAILABLE":m?"UNAVAILABLE":f.length>0?"NOT PROBED":i.length>0?"not required":"not configured";return Ge(tt,{palette:t,title:"identity",scroll:!0,children:[Ge(jc,{palette:t,title:"Google identity",tone:l?"success":"warning",children:[Ge(Wr,{palette:t,label:"user",value:s||"(unknown)"},void 0,!1,void 0,this),Ge(Wr,{palette:t,label:"project",value:a||"(unset)"},void 0,!1,void 0,this),Ge(Wr,{palette:t,label:"source",value:c||"\u2014"},void 0,!1,void 0,this),Ge(Wr,{palette:t,label:"ADC",value:l?"\u2713 available":"\u2717 missing",tone:l?"success":"error"},void 0,!1,void 0,this),Ge(Wr,{palette:t,label:"gcloud",value:r?.gcloudInstalled?"\u2713 installed":"\u2717 not installed",tone:r?.gcloudInstalled?"success":"error"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(jc,{palette:t,title:`Service accounts (${i.length})`,tone:f.length===0?"muted":g?"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(Wr,{palette:t,label:"impersonation",value:x,tone:g?"success":f.length>0?"warning":"muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ge(jc,{palette:t,title:"IAP",tone:d?"success":"muted",children:[Ge("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:Ge(ge,{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(jc,{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:"/auth login suspends this screen and runs gcloud ADC login, then restores the TUI"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):null]},void 0,!0,void 0,this)}function VP(e,t){let n=new Map((e?gd(e):[]).map((i)=>[i.email,i.active])),r=t?.service_account_status??{};return[...new Set([...n.keys(),...Object.keys(r)])].sort((i,s)=>i.localeCompare(s)).map((i)=>{let s=r[i]??"unknown",a=n.get(i)===!1;return{email:i,inactive:a,ok:a||s==="unknown"?void 0:s==="available"}})}var Sb=D(()=>{Et();Pe();be();wr()});import{jsxDEV as ft}from"@opentui/react/jsx-dev-runtime";function kb(e){let{palette:t,credentials:n}=e;if(!n)return ft(Ic,{palette:t,label:"Reading credential store\u2026"},void 0,!1,void 0,this);let r=n.entries.filter((i)=>i.valid).length,o=n.entries.length-r;return ft(tt,{palette:t,title:"credentials",scroll:!0,children:[ft("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[ft(ge,{palette:t,label:`backend: ${n.backend}`,tone:"info"},void 0,!1,void 0,this),n.entries.length>0?ft(ge,{palette:t,label:`${r} valid`,tone:"success"},void 0,!1,void 0,this):null,o>0?ft(ge,{palette:t,label:`${o} expired`,tone:"warning"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ft("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),ft("box",{height:1,flexShrink:0},void 0,!1,void 0,this),n.entries.length===0?ft("text",{fg:t.muted,children:"no cached credentials"},void 0,!1,void 0,this):ft("box",{flexDirection:"column",overflow:"hidden",gap:1,children:n.entries.map((i)=>ft("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:[ft("text",{wrapMode:"none",children:[ft("span",{fg:i.valid?t.success:t.warning,children:i.valid?"\u2713 valid":"\u2717 expired"},void 0,!1,void 0,this),ft("span",{fg:t.muted,children:` \xB7 expires ${i.expires_at}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ft("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),ft($c,{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 Cb=D(()=>{Et();be()});import{jsxDEV as A}from"@opentui/react/jsx-dev-runtime";function Pb(e){let{palette:t,cfg:n,width:r}=e,o=se();if(!n)return A($e,{palette:t,title:"No configuration",body:"Create .devctl/config.yaml or run setup."},void 0,!1,void 0,this);let i=Math.max(Uo+8,r-6-o.pad*2),s=i>=dx,a=s?Math.floor((i-Eb)/2):i,c=nx(n),l=rx(n),d=ox(n),f=ix(n),g=sx(n);return A(tt,{palette:t,title:`config ${n.project.name||"unnamed"}`,children:[A(Be,{palette:t,items:Yy(n)},void 0,!1,void 0,this),A("box",{flexGrow:1,overflow:"hidden",children:A("scrollbox",{ref:e.scrollRef,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:A("box",{flexDirection:"column",overflow:"hidden",gap:Rb,children:[A(gp,{wide:s,left:A(nn,{palette:t,title:"project",children:A(Vo,{palette:t,facts:Xy(n,pt),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:"google",children:A(Vo,{palette:t,facts:Qy(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(gp,{wide:s,left:A(nn,{palette:t,title:"runtime",children:A(Vo,{palette:t,facts:Zy(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:"logs",children:A(Vo,{palette:t,facts:ex(n),width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:`proxy ${n.proxy.enabled?"enabled":"disabled"}`,children:[A(Vo,{palette:t,facts:tx(n),width:i},void 0,!1,void 0,this),A(zP,{palette:t,routes:l,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A(nn,{palette:t,title:`services ${c.length}`,children:A(JP,{palette:t,rows:c,width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:`tasks ${g.length}`,children:A(_b,{palette:t,rows:g,empty:"no tasks",width:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(gp,{wide:s,left:A(nn,{palette:t,title:`profiles ${d.length}`,children:A(YP,{palette:t,rows:d,width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),right:A(nn,{palette:t,title:`templates ${f.length}`,children:A(_b,{palette:t,rows:f,empty:"no templates",width:a},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A(nn,{palette:t,title:"extras",children:A(Vo,{palette:t,facts:cx(n),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),A(je,{palette:t,backgroundColor:t.element,edge:"top",children:A(Oe,{palette:t,hints:[{key:"v",label:"validate/save buffer"},{key:"e",label:"open in $EDITOR"},{key:"/diff",label:"config sources"},{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 gp(e){let{wide:t,left:n,right:r}=e;if(!t)return A("box",{flexDirection:"column",overflow:"hidden",gap:Rb,flexShrink:0,children:[n,r]},void 0,!0,void 0,this);return A("box",{flexDirection:"row",overflow:"hidden",gap:Eb,flexShrink:0,children:[A("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:n},void 0,!1,void 0,this),A("box",{flexGrow:1,flexBasis:0,overflow:"hidden",children:r},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function nn(e){let{palette:t,title:n,children:r}=e;return A("box",{border:!0,borderStyle:"rounded",borderColor:t.border,title:n,titleColor:t.accent,paddingLeft:1,paddingRight:1,flexDirection:"column",overflow:"hidden",flexShrink:0,children:r},void 0,!1,void 0,this)}function Vo(e){let{palette:t,facts:n,width:r}=e,o=Math.max(4,r-Uo-4);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((i)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:Uo,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.muted,wrapMode:"none",children:ee(i.label,Uo)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:ZP(t,i.tone),wrapMode:"none",children:ee(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 JP(e){let{palette:t,rows:n,width:r}=e;if(n.length===0)return A(Bc,{palette:t,text:"no services"},void 0,!1,void 0,this);let o=lx(n),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:He(s.name,t),wrapMode:"none",children:ee(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:ce(XP(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 zP(e){let{palette:t,routes:n,width:r}=e;if(n.length===0)return A(Bc,{palette:t,text:"no routes"},void 0,!1,void 0,this);let o=Math.min(Uo+4,Math.max(8,...n.map((s)=>s.name.length))),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.primary,wrapMode:"none",children:ee(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:ce(QP(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 YP(e){let{palette:t,rows:n,width:r}=e;if(n.length===0)return A(Bc,{palette:t,text:"no profiles"},void 0,!1,void 0,this);let o=Math.min(12,Math.max(8,...n.map((s)=>s.name.length))),i=Math.max(8,r-o-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((s)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:o,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.primary,wrapMode:"none",children:ee(s.name,o)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("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 _b(e){let{palette:t,rows:n,empty:r,width:o}=e;if(n.length===0)return A(Bc,{palette:t,text:r},void 0,!1,void 0,this);let i=Math.min(14,Math.max(8,...n.map((a)=>a.name.length))),s=Math.max(8,o-i-6);return A("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:n.map((a)=>A("box",{height:1,flexDirection:"row",overflow:"hidden",children:[A("box",{width:i,flexShrink:0,overflow:"hidden",children:A("text",{fg:t.text,wrapMode:"none",children:ee(a.name,i)},void 0,!1,void 0,this)},void 0,!1,void 0,this),A("box",{width:s,flexShrink:0,overflow:"hidden",children:A("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 Bc(e){return A("box",{height:1,overflow:"hidden",children:A("text",{fg:e.palette.muted,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function XP(e){let t=e.extends==="\u2014"?"":` ${e.extends}`;return` ${e.ports} ${e.identity} ${e.health} ${e.restart} \u2190 ${e.depends}${t}`}function QP(e){return` ${e.auth} ${e.identity} ${e.match} \u2192 ${e.upstream}`}function ZP(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 Eb=1,Rb=1;var Tb=D(()=>{Et();Ku();at();Pe();be();Ye()});import{useRef as eT}from"react";import{jsxDEV as me}from"@opentui/react/jsx-dev-runtime";function Wc(e){let{palette:t,names:n,snap:r,selected:o,checked:i,width:s,onOpen:a,onSelectIndex:c,onToggle:l}=e,d=se(),f=eT(!1),g=new Set(i),m=Fu(s),x=Iu(s),v=$u(s),w=Fv(s);return me("box",{flexDirection:"column",flexGrow:1,overflow:"hidden",children:[me("box",{height:1,flexDirection:"row",overflow:"hidden",children:[me(xt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:4,fg:t.accent,text:"sel"},void 0,!1,void 0,this),me(xt,{width:2,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:w,fg:t.muted,text:"name"},void 0,!1,void 0,this),me(xt,{width:vt,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:en,fg:t.muted,text:"state"},void 0,!1,void 0,this),v?me(xt,{width:Sn,fg:t.muted,text:"health"},void 0,!1,void 0,this):null,x?me(xt,{width:ac,fg:t.muted,text:"port"},void 0,!1,void 0,this):null,m?me(xt,{width:zn,fg:t.muted,text:"pid"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),n.map((E,k)=>{let j=r?.services[E],V=Bt(j),C=j?.health??"UNKNOWN",y=g.has(E),B=k===o,h=y?"[x]":"[ ]",q=B?"\u203A":" ";return me("box",{height:d.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:B?t.highlight:y?t.element:void 0,onMouseDown:()=>{if(f.current)return;if(B){a(E);return}c(k)},children:[me("box",{width:2,flexShrink:0,children:me("text",{fg:t.primary,children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:4,flexShrink:0,onMouseDown:()=>{f.current=!0,l?.(E),setTimeout(()=>{f.current=!1},0)},children:me("text",{fg:tT(t,y,B),children:h},void 0,!1,void 0,this)},void 0,!1,void 0,this),me("box",{width:2,flexShrink:0,children:me("text",{fg:De(t,V),children:Mt(V)},void 0,!1,void 0,this)},void 0,!1,void 0,this),me(xt,{width:w,fg:B?t.primary:He(E,t),text:ee(E,w)},void 0,!1,void 0,this),me(xt,{width:vt,fg:t.muted,text:""},void 0,!1,void 0,this),me(xt,{width:en,fg:De(t,V),text:V},void 0,!1,void 0,this),v?me(xt,{width:Sn,fg:De(t,C),text:C},void 0,!1,void 0,this):null,x?me(xt,{width:ac,fg:t.text,text:jr(j)},void 0,!1,void 0,this):null,m?me(xt,{width:zn,fg:t.text,text:j?.pid?String(j.pid):""},void 0,!1,void 0,this):null]},E,!0,void 0,this)})]},void 0,!0,void 0,this)}function Gc(e){let{palette:t,checked:n,idle:r,profileName:o}=e,i=n.length;if(i>0)return me(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(r)return me(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 me(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 tT(e,t,n){if(t)return e.success;if(n)return e.primary;return e.muted}function xt(e){return me("box",{width:e.width,flexShrink:0,overflow:"hidden",children:me("text",{fg:e.fg,wrapMode:"none",children:e.text},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var mp=D(()=>{Pe();at();be();Ye()});import{useEffect as hp,useRef as Ab}from"react";import{jsxDEV as Y,Fragment as aT}from"@opentui/react/jsx-dev-runtime";function Lb(e){let{palette:t,logs:n,names:r,logSources:o,service:i,paused:s,errorOnly:a,showSystemLogs:c,search:l,searchFocused:d,followTick:f,width:g,onSearch:m,onService:x,onToggleErrors:v,onToggleSystemLogs:w,onClearLogs:E,onSelect:k,wrapMode:j="focus",selected:V=-1,follow:C=!0,newer:y=0,viewStart:B=0,viewTotal:h,onLeaveLatest:q,onOpenExports:I,onJumpLatest:z,view:ue,fullscreen:Ie=!1,facets:ct}=e,oe=se(),Ue=Bv(g,oe.pad,Ie),Ee=c?n:n.filter((Ve)=>!ns(Ve.source)),Qe=Wo(n,{service:i,services:e.services,errorOnly:a,search:l,regex:e.regex,source:e.source,systemLogs:c}),pe=ue??Qe,Se=h??Qe.length,It=Math.min(Se,B+pe.length),N=Se===0?"empty":`${B+1}\u2013${It} of ${Se}`,Pt=e.services??[],nt=Pt.length>0?Pt.join(","):i===""?"all services":i;return Y("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[Ie?null:Y(aT,{children:[Y(Be,{palette:t,items:[{text:s?"PAUSED":"LIVE",tone:s?"warning":"success"},{text:`shown ${Se}`,tone:"info"},{text:ct?`total ${ct.total}`:`total ${n.length}`},...ue&&Se>ue.length?[{text:`${B+1}\u2013${B+ue.length} / ${Se}`,tone:"info"}]:[],{text:nt,tone:i===""?"idle":"primary"},{text:Qi(j),tone:j==="clip"?"idle":"accent"},...C?[]:[{text:y>0?`pinned \xB7 +${y} 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: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:E},{text:"open folder",tone:"primary",onMouseDown:I}]},void 0,!1,void 0,this),Y(xp,{palette:t,logs:Ee,names:o??r,service:i,errorOnly:a,width:g,onService:x,onToggleErrors:v,facets:ct},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d?Y("box",{height:1,paddingLeft:1,backgroundColor:t.highlight,overflow:"hidden",children:Y("input",{focused:!0,value:l,placeholder:"search messages or service names",onInput:m,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,ue&&Se>pe.length?Y(vp,{palette:t,start:B,count:pe.length,total:Se},void 0,!1,void 0,this):null,Y("box",{flexGrow:1,border:!Ie,borderStyle:"rounded",borderColor:t.border,title:Ie?void 0:`logs ${nt} \xB7 ${N}`,titleColor:t.primary,padding:Ie?0:oe.pad,overflow:"hidden",children:pe.length===0?Y($e,{palette:t,title:n.length===0?"No log events":"No events in this filter",body:n.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):Y(bp,{palette:t,logs:pe,width:Ue,followTick:f,focused:!1,wrapMode:j,selected:V,follow:C,showTimestamps:e.showTimestamps!==!1,showMeta:e.showMeta!==!1,onPick:k,onLeaveLatest:q,viewStart:B},f,!1,void 0,this)},void 0,!1,void 0,this),Y(je,{palette:t,backgroundColor:t.element,edge:"top",children:Y(Oe,{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:y>0?`latest +${y}`:"latest"},{key:"w",label:"wrap"},{key:"p",label:"pause"},{key:"z",label:Ie?"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,g-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!C?Y(yp,{palette:t,width:g,newer:y,onJump:z},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function vp(e){let t=Math.min(e.total,e.start+e.count),n=Math.max(0,e.start),r=Math.max(0,e.total-t);return Y(Be,{palette:e.palette,items:[{text:`view ${e.start+1}\u2013${t} of ${e.total}`,tone:"primary"},{text:n>0?`\u2191 ${n} older`:"start of history",tone:n>0?"info":"idle"},{text:r>0?`\u2193 ${r} newer`:"at latest",tone:r>0?"warning":"success"}],hints:[{key:"pgup/pgdn",label:"move history window"},{key:"g",label:"latest"}]},void 0,!1,void 0,this)}function yp(e){let t=e.newer>0?`g jump to latest \xB7 ${e.newer} new`:"g jump to latest",n=Math.min(e.width,t.length+4);return Y("box",{position:"absolute",left:Math.max(0,Math.floor((e.width-n)/2)),bottom:e.bottom??2,width:n,height:3,border:!0,borderStyle:"rounded",borderColor:e.palette.warning,backgroundColor:e.palette.panel,alignItems:"center",justifyContent:"center",onMouseDown:e.onJump,children:Y("text",{wrapMode:"none",children:[Y("span",{fg:e.palette.primary,children:"g"},void 0,!1,void 0,this),Y("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 xp(e){let{palette:t,logs:n,names:r,service:o,errorOnly:i,width:s,onService:a,onToggleErrors:c,facets:l}=e,d=l?Py(r,l):Ry(r,n),f=s<80,g=d.map((w,E)=>{let k=E+1,j=w.name===""?"all":w.name;return{id:j,label:f?`${k} ${j}`:`${k} ${j} \xB7 ${w.count}`,color:He(w.name,t)}}),m=Math.max(0,d.findIndex((w)=>w.name===o)),x=i?"ERROR+":f?"lvls":"all levels",v=Math.max(Vn(g[m]?.label??"1 all"),s-Vn(x));return Y(je,{palette:t,backgroundColor:t.element,children:Y("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:[Y("box",{flexGrow:1,overflow:"hidden",children:Y(Mc,{palette:t,items:g,active:m,width:v,onPick:(w)=>{let E=d[w];if(E)a(E.name)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y(ge,{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 bp(e){let{palette:t,logs:n,limit:r,width:o=80,followTick:i=0,focused:s=!1,wrapMode:a="clip",selected:c=-1,follow:l=!0,showTimestamps:d=!0,showMeta:f=!0,onPick:g,onLeaveLatest:m,viewStart:x=0}=e,v=Ab(null),w=Ab(""),E=r===void 0?n:n.slice(-r),k=[...new Set(n.map((C)=>C.service))],j=zv(o,k),V=Vv({width:o,serviceWidth:j,showTimestamps:d,showMeta:f});return hp(()=>{let C=v.current;if(!C)return;if(C.stickyScroll=l,l)C.stickyStart="bottom",C.scrollTo({x:C.scrollLeft,y:Math.max(0,C.scrollHeight)})},[l,i]),hp(()=>{let C=`${x}:${c}:${a}`;if(w.current===C)return;if(w.current=C,l&&(c<0||c>=E.length-1))return;let y=v.current;if(!y||c<0)return;let B=`log-row-${c}`,h=requestAnimationFrame(()=>{y.stickyScroll=!1,y.scrollChildIntoView(B)});return()=>cancelAnimationFrame(h)},[l,c,E.length,x,a]),hp(()=>{if(!l||!m)return;let C=!1,y=setTimeout(()=>{C=!0},nT),B=setInterval(()=>{let h=v.current;if(!C||!h)return;let q=h.viewport.height;if(q>0&&h.scrollTop+q<h.scrollHeight-oT)m()},rT);return()=>{clearTimeout(y),clearInterval(B)}},[l,i,m]),Y("box",{flexGrow:1,height:"100%",overflow:"hidden",children:Y("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:Y("box",{flexDirection:"column",overflow:"hidden",children:E.map((C,y)=>Y(iT,{id:`log-row-${y}`,palette:t,event:C,serviceWidth:j,msgWidth:V,expanded:Uv(a,y===c),active:y===c,showTimestamps:d,showMeta:f,onPick:g?()=>g(y):void 0},`${C.timestamp}-${C.service}-${y}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function iT(e){let{id:t,palette:n,event:r,serviceWidth:o,msgWidth:i,expanded:s,active:a,showTimestamps:c=!0,showMeta:l=!0,onPick:d}=e,f=Gv(vc(r.message,i),i,s);return Y("box",{id:t,flexShrink:0,flexDirection:"column",overflow:"hidden",backgroundColor:a?n.highlight:void 0,onMouseDown:d,children:f.visible.map((g,m)=>Y("box",{height:1,flexDirection:"row",overflow:"hidden",children:[c?Y("box",{width:gc,flexShrink:0,overflow:"hidden",children:Y("text",{fg:n.muted,children:m===0?r.timestamp.slice(11,19):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,Y("box",{width:o,flexShrink:0,overflow:"hidden",children:Y("text",{fg:m===0?He(r.service,n):n.muted,wrapMode:"none",children:m===0?ee(r.service,o):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y("box",{width:Xi,flexShrink:0,overflow:"hidden",children:Y("text",{children:" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y("box",{width:mc,flexShrink:0,overflow:"hidden",children:Y("text",{fg:m===0?De(n,r.level):n.muted,children:m===0?hc(String(r.level)):""},void 0,!1,void 0,this)},void 0,!1,void 0,this),l?Y("box",{width:pc,flexShrink:0,overflow:"hidden",children:Y("text",{fg:n.muted,children:m===0&&r.source?ee(r.source,pc):""},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,Y("box",{width:Xi,flexShrink:0,overflow:"hidden",children:Y("text",{fg:n.muted,children:m===0?" ":"\u2502"},void 0,!1,void 0,this)},void 0,!1,void 0,this),Y("box",{flexGrow:1,overflow:"hidden",children:Y(sT,{palette:n,level:r.level,text:g,mark:m===0?f.mark:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${r.timestamp}-${m}`,!0,void 0,this))},void 0,!1,void 0,this)}function sT(e){let{palette:t,level:n,text:r,mark:o}=e;return Y("text",{wrapMode:"none",children:[qv(r).map((i,s)=>Y("span",{fg:fx(t,n,i.kind),children:i.text},`${i.kind}-${s}`,!1,void 0,this)),o===""?null:Y("span",{fg:t.muted,children:o},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var nT=400,rT=200,oT=2;var wp=D(()=>{Et();at();Pe();be();Ye()});import{jsxDEV as ne}from"@opentui/react/jsx-dev-runtime";function Ob(e){let{palette:t,cfg:n,snap:r,logs:o,names:i,selected:s,selectedLog:a=-1,checked:c,profile:l,google:d,width:f,paused:g,followTick:m,logService:x,logSources:v,errorOnly:w,showSystemLogs:E,onOpen:k,onSelectIndex:j,onToggle:V,onFilterService:C,onToggleErrors:y,onToggleSystemLogs:B,onClearLogs:h,onShowErrors:q,wrapMode:I="clip",view:z,follow:ue=!0,onLeaveLatest:Ie,onPickLog:ct,viewStart:oe=0,viewTotal:Ue,newer:Ee=0,onJumpLatest:Qe,facets:pe,leftover:Se}=e,It=se();if(!n||i.length===0)return ne($e,{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 N=f<$o,Pt=Bo(r),nt=wc(r,i),Ve=i.filter((zo)=>r?.services[zo]?.state==="FAILED").length,Wt=r?.session_id?js(r.session_id):void 0,lt=Wt?jo(Date.now()-Wt.getTime()):void 0,tr=Cy(o),mt=l||xc(n),on=Vy(n,mt),sn=Pt?Ky(Se,r?.session_id):void 0,an=yc(f,i,N),Ur=Math.max(24,N?f-4:f-an-4),_=E?o:o.filter((zo)=>!ns(zo.source)),cn=Wo(o,{service:x,errorOnly:w,systemLogs:E}),Rn=z??cn,Jt=Ue??cn.length,Xc=Math.min(Jt,oe+Rn.length),Qc=Jt===0?"empty":`${oe+1}\u2013${Xc} of ${Jt}`,gs=x===""?"all services":x;return ne("box",{flexGrow:1,flexDirection:N?"column":"row",overflow:"hidden",children:[ne("box",{flexGrow:N?1:0,flexShrink:0,minWidth:N?void 0:an,width:N?void 0:an,border:!0,borderStyle:"rounded",borderColor:Pt?t.border:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[ne(Be,{palette:t,items:[{text:Wu(nt.running,i.length),tone:nt.running>0?"success":"idle"},...Ve>0?[{text:`${Ve} failed`,tone:"error"}]:[],...c.length>0?[{text:`${c.length} selected`,tone:"primary"}]:[],...lt!==void 0?[{text:`up ${lt}`,tone:"idle"}]:[],...tr>0?[{text:`${tr} errors`,tone:"error",onMouseDown:q}]:[]]},void 0,!1,void 0,this),ne(Gc,{palette:t,checked:c,idle:Pt,profileName:mt,members:on},void 0,!1,void 0,this),ne("box",{flexGrow:1,paddingLeft:It.pad,paddingRight:It.pad,overflow:"hidden",children:ne(Wc,{palette:t,names:i,snap:r,selected:s,checked:c,width:fc(an,It.pad),onOpen:k,onSelectIndex:j,onToggle:V},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne(uT,{palette:t,names:i,snap:r,width:an,onOpen:k},void 0,!1,void 0,this),sn?ne(fT,{palette:t,leftover:sn,width:an},void 0,!1,void 0,this):null,ne(gT,{palette:t,cfg:n,snap:r,google:d,width:an},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ne("box",{position:"relative",flexGrow:2,minWidth:N?void 0:32,minHeight:N?8:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:`logs \xB7 ${Qc}`,titleColor:t.primary,overflow:"hidden",flexDirection:"column",children:[ne(Be,{palette:t,items:[{text:g?"PAUSED":"LIVE",tone:g?"warning":"success"},{text:`shown ${cn.length}`,tone:"info"},{text:pe?`total ${pe.total}`:`total ${o.length}`},{text:gs,tone:x===""?"idle":"primary"},{text:w?"ERROR+":"all levels",tone:w?"error":"idle",onMouseDown:y},{text:E?"system: on":"system: off",tone:E?"accent":"idle",onMouseDown:B},{text:"clear",tone:"muted",onMouseDown:h}]},void 0,!1,void 0,this),ne(xp,{palette:t,logs:_,names:v??i,service:x,errorOnly:w,width:Ur,onService:C,onToggleErrors:y,facets:pe},void 0,!1,void 0,this),Jt>Rn.length?ne(vp,{palette:t,start:oe,count:Rn.length,total:Jt},void 0,!1,void 0,this):null,cn.length===0?ne($e,{palette:t,title:Pt?"Waiting for logs":o.length===0?"No events yet":"No events in this filter",body:Pt?"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):ne(bp,{palette:t,logs:Rn,width:Ur,followTick:m,focused:!1,wrapMode:I,selected:a,follow:ue,onLeaveLatest:Ie,onPick:ct,viewStart:oe},m,!1,void 0,this),ne(je,{palette:t,backgroundColor:t.element,edge:"top",children:ne(Oe,{palette:t,hints:Fo([{key:"e",label:"errors"},{key:"i",label:E?"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,Ur-2))},void 0,!1,void 0,this)},void 0,!1,void 0,this),!ue?ne(yp,{palette:t,width:Ur,newer:Ee,bottom:1,onJump:Qe},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function lT(e){if(!e)return!1;return e.state===Kn||e.health===Ce||e.state===Mi||e.restarts>0||e.last_error!==""}function Db(e){if(e.state===Kn)return 0;if(e.health===Ce)return 1;if(e.state===Mi)return 2;return 3}function dT(e){if(e.last_error!=="")return e.last_error;if(e.restarts>0)return`restarted ${e.restarts}x, no error recorded`;return e.health===Ce?"failing health check":e.state.toLowerCase()}function uT(e){let{palette:t,names:n,snap:r,width:o,onOpen:i}=e,s=n.map((d)=>({name:d,rt:r?.services[d]})).filter((d)=>lT(d.rt)).sort((d,f)=>Db(d.rt)-Db(f.rt));if(s.length===0)return null;let a=s.slice(0,cT),c=s.length-a.length,l=Math.max(8,o-Sp-4);return ne("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:f})=>{let g=Bt(f);return ne("box",{height:1,flexDirection:"row",overflow:"hidden",onMouseDown:()=>i(d),children:[ne("box",{width:2,flexShrink:0,children:ne("text",{fg:De(t,g),children:Mt(g)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:Sp,flexShrink:0,overflow:"hidden",children:ne("text",{fg:He(d,t),wrapMode:"none",children:ee(d,Sp)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:l,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,wrapMode:"none",children:ce(dT(f),l)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},d,!0,void 0,this)}),c>0?ne("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 fT(e){let{palette:t,leftover:n,width:r}=e,o=n.processes.slice(0,pT),i=n.processes.length-o.length,s=Math.max(8,r-kp-4);return ne("box",{border:!0,borderStyle:"rounded",borderColor:t.warning,title:"last session",titleColor:t.warning,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[ne("text",{fg:t.muted,wrapMode:"none",children:ce(`${n.session_id} ${n.profile||"(none)"}`,Math.max(8,r-4))},void 0,!1,void 0,this),o.map((a)=>ne("box",{height:1,flexDirection:"row",overflow:"hidden",children:[ne("box",{width:kp,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.text,wrapMode:"none",children:ee(a.name,kp)},void 0,!1,void 0,this)},void 0,!1,void 0,this),ne("box",{width:s,flexShrink:0,overflow:"hidden",children:ne("text",{fg:t.muted,wrapMode:"none",children:ce(`pid ${a.pid} leftover`,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`${a.name}-${a.pid}`,!0,void 0,this)),i>0?ne("text",{fg:t.muted,wrapMode:"none",children:`+${i} more leftover pids`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}function gT(e){let{palette:t,cfg:n,snap:r,google:o,width:i}=e,s=o?.userEmail,a=Go(n,r?.identity,o).project,c=r?.logs.total??0,l=Jy(s,a,c,i);return ne(je,{palette:t,backgroundColor:t.element,edge:"top",children:ne("box",{height:1,flexDirection:"row",overflow:"hidden",backgroundColor:t.element,children:l.map((d,f)=>ne(ge,{palette:t,label:d.label,tone:d.tone},`${d.label}-${f}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)}var cT=4,Sp=14,pT=4,kp=14;var Mb=D(()=>{Pe();at();be();Et();Ye();Rr();ze();mp();wp()});import{useEffect as mT,useState as hT}from"react";import{jsxDEV as X}from"@opentui/react/jsx-dev-runtime";function Ib(e){let{palette:t,report:n,loading:r,progress:o,error:i,selected:s,onPick:a,onReload:c}=e,l=qo(s,Cp);if(r)return X(vT,{palette:t,progress:o},void 0,!1,void 0,this);if(i)return X(Px,{palette:t,title:"Doctor failed",body:i},void 0,!1,void 0,this);if(!n)return X($e,{palette:t,title:"Doctor",body:"Diagnostics have not run yet.",hint:"opening this screen runs doctor"},void 0,!1,void 0,this);let d=n.checks.filter((w)=>w.severity==="ok").length,f=n.checks.filter((w)=>w.severity==="warn").length,g=n.checks.filter((w)=>w.severity==="error").length,m=n.checks.length,x=ts(m>0?d/m:0),v=g>0?t.error:f>0?t.warning:t.success;return X(tt,{palette:t,title:`doctor ${n.issues} issue(s)`,children:[X("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:[X("text",{wrapMode:"none",children:[X("span",{fg:t.inverse,bg:t.primary,children:" r "},void 0,!1,void 0,this),X("span",{fg:t.primary,children:" RUN DOCTOR AGAIN"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X("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),X("box",{height:1,flexShrink:0},void 0,!1,void 0,this),X("box",{height:1,flexShrink:0,overflow:"hidden",children:X("text",{wrapMode:"none",children:[X("span",{fg:v,children:`[${x}]`},void 0,!1,void 0,this),X("span",{fg:t.success,children:` ${d} ok`},void 0,!1,void 0,this),f>0?X("span",{fg:t.warning,children:` \xB7 ${f} warn`},void 0,!1,void 0,this):null,g>0?X("span",{fg:t.error,children:` \xB7 ${g} error`},void 0,!1,void 0,this):null,f===0&&g===0?X("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),X("box",{height:1,flexShrink:0},void 0,!1,void 0,this),X("scrollbox",{ref:l,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:X("box",{flexDirection:"column",overflow:"hidden",gap:1,children:n.checks.map((w,E)=>X(yT,{palette:t,check:w,index:E,active:E===s,onPick:a},`${w.name}-${E}`,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function vT({palette:e,progress:t}){let[n,r]=hT(0);return mT(()=>{let o=setInterval(()=>r((i)=>(i+1)%$b.length),120);return()=>clearInterval(o)},[]),X("box",{flexGrow:1,alignItems:"center",justifyContent:"center",overflow:"hidden",children:X("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:[X("text",{wrapMode:"none",children:[X("span",{fg:e.primary,children:`${$b[n]} `},void 0,!1,void 0,this),X("span",{fg:e.text,children:"devctl doctor"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X("box",{height:1,flexShrink:0},void 0,!1,void 0,this),X("text",{fg:e.text,wrapMode:"none",children:`Checking ${t.active}`},void 0,!1,void 0,this),X("box",{height:1,flexShrink:0},void 0,!1,void 0,this),t.checks.slice(-4).map((o,i)=>X("text",{wrapMode:"none",children:[X("span",{fg:De(e,o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK"),children:`${Mt(o.severity==="error"?"ERROR":o.severity==="warn"?"WARN":"OK")} `},void 0,!1,void 0,this),X("span",{fg:e.muted,children:o.name},void 0,!1,void 0,this)]},`${o.name}-${i}`,!0,void 0,this)),t.checks.length===0?X("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 yT(e){let{palette:t,check:n,index:r,active:o,onPick:i}=e,s=n.severity==="error"?"ERROR":n.severity==="warn"?"WARN":"OK";if(n.severity==="ok")return X("box",{id:`${Cp}-${r}`,flexDirection:"row",flexShrink:0,paddingLeft:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(r),children:X("text",{wrapMode:"none",children:[X("span",{fg:t.primary,children:o?"\u203A ":" "},void 0,!1,void 0,this),X("span",{fg:De(t,s),children:Mt(s)},void 0,!1,void 0,this),X("span",{fg:o?t.primary:t.text,children:` ${n.name}`},void 0,!1,void 0,this),X("span",{fg:t.muted,children:n.message?` \xB7 ${n.message}`:""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this);let c=n.severity==="error"?t.error:t.warning;return X("box",{id:`${Cp}-${r}`,border:!0,borderStyle:"rounded",borderColor:o?t.borderActive:c,title:n.name,titleColor:c,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:o?t.highlight:void 0,onMouseDown:()=>i(r),children:[X("text",{wrapMode:"word",children:[X("span",{fg:De(t,s),children:`${Mt(s)} `},void 0,!1,void 0,this),X("span",{fg:t.text,children:n.message},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n.hint?X("text",{fg:t.info,wrapMode:"word",children:`\u2192 ${n.hint}`},void 0,!1,void 0,this):null,o&&n.action?.kind==="free-port"?X("text",{fg:t.primary,wrapMode:"none",children:`enter stop ${n.action.holder.command} (pid ${n.action.holder.pid})`},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var Cp="doctor-row",$b;var Fb=D(()=>{Et();Pe();be();Ye();$b=["\u25D0","\u25D3","\u25D1","\u25D2"]});import{jsxDEV as Ae}from"@opentui/react/jsx-dev-runtime";function Hb(e){let{palette:t,cfg:n,snap:r,profile:o,selected:i,onPick:s}=e,a=se(),c=qo(i,Nb),l=Object.keys(n?.profiles??{}).sort();if(l.length===0)return Ae($e,{palette:t,title:"No profiles",body:"Add profiles.<name>.services in config.yaml."},void 0,!1,void 0,this);return Ae(tt,{palette:t,title:"profiles",children:[Ae("box",{height:1,flexShrink:0,overflow:"hidden",children:Ae("text",{fg:t.muted,wrapMode:"none",children:[`${l.length} profile${l.length===1?"":"s"} \xB7 current: `,Ae("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),Ae("box",{height:1,flexShrink:0},void 0,!1,void 0,this),Ae("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:Ae("box",{flexDirection:"column",overflow:"hidden",gap:a.gap||1,children:l.map((d,f)=>{let g=d===o,m=f===i,x=n?.profiles[d]?.services??[],v=Object.keys(n?.profiles[d]?.environment??{}).length,w=m?t.borderActive:g?t.success:t.border,E=m?t.primary:g?t.success:t.muted;return Ae("box",{id:`${Nb}-${f}`,border:!0,borderStyle:"rounded",borderColor:w,title:d,titleColor:E,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,overflow:"hidden",backgroundColor:m?t.highlight:void 0,onMouseDown:()=>s(f),children:[Ae("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:Ae("text",{wrapMode:"none",children:[g?Ae("span",{fg:t.success,children:"\u25CF current profile"},void 0,!1,void 0,this):Ae("span",{fg:t.muted,children:"\u25CB not active"},void 0,!1,void 0,this),Ae("span",{fg:t.muted,children:` \xB7 ${x.length} service${x.length===1?"":"s"}`},void 0,!1,void 0,this),v>0?Ae("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),Ae("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:x.length===0?Ae("text",{fg:t.muted,wrapMode:"none",children:"(no services)"},void 0,!1,void 0,this):Ae("text",{wrapMode:"word",children:x.map((k,j)=>{let V=Bt(r?.services[k]);return Ae("span",{children:[Ae("span",{fg:De(t,V),children:Mt(V)},void 0,!1,void 0,this),Ae("span",{fg:He(k,t),children:` ${k}`},void 0,!1,void 0,this),j<x.length-1?Ae("span",{fg:t.muted,children:" "},void 0,!1,void 0,this):null]},k,!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),Ae(je,{palette:t,backgroundColor:t.element,edge:"top",children:Ae(Oe,{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 Nb="profile-row";var jb=D(()=>{Et();at();Pe();be();Ye()});import{jsxDEV as G,Fragment as Ub}from"@opentui/react/jsx-dev-runtime";function xT(e){let t=e.toLowerCase();if(t==="iap")return"info";if(t==="service"||t==="service_account")return"primary";return"idle"}function bT(e,t,n){if(n||t>=500)return e.error;if(t===0||t>=400)return e.warning;return e.success}function wT(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 _T(e){let{palette:t,req:n,cols:r}=e,o=bT(t,n.status,n.error),i=n.status>0?String(n.status):"ERR",s=wT(t,n.identity),a=n.route||Kb,c=n.error?`${n.path} \u2014 ${ce(n.error,CT)}`:n.path;return G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[G("box",{width:_p,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:n.timestamp.slice(11,19)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showMethod?G("box",{width:Uc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.text,wrapMode:"none",children:ee(n.method,Uc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Kc,flexShrink:0,overflow:"hidden",children:G("text",{fg:o,wrapMode:"none",children:ee(i,Kc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),r.showDur?G("box",{width:qc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,wrapMode:"none",children:ee(`${n.durationMs}ms`,qc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Vc,flexShrink:0,overflow:"hidden",children:G("text",{fg:s.color,wrapMode:"none",children:ee(s.label,Vc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{width:r.routeCol,flexShrink:0,overflow:"hidden",children:G("text",{fg:n.route?t.info:t.muted,wrapMode:"none",children:ee(a,r.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{flexGrow:1,overflow:"hidden",children:G("text",{fg:n.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 ET(e){let{palette:t,cols:n}=e;return G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:t.element,children:[G("box",{width:_p,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("TIME",_p)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showMethod?G("box",{width:Uc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("METHOD",Uc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Kc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("ST",Kc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n.showDur?G("box",{width:qc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("DUR",qc)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,G("box",{width:Vc,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("WHO",Vc)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{width:n.routeCol,flexShrink:0,overflow:"hidden",children:G("text",{fg:t.muted,children:ee("ROUTE",n.routeCol)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("box",{flexGrow:1,overflow:"hidden",children:G("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 RT(e){let{palette:t,name:n,auth:r,identity:o,upstream:i,match:s,onMouseDown:a}=e;return G("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",onMouseDown:a,children:[G("text",{fg:t.text,wrapMode:"none",children:n},void 0,!1,void 0,this),G("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:[G(ge,{palette:t,label:r||"no auth",tone:xT(r)},void 0,!1,void 0,this),o?G(ge,{palette:t,label:o,tone:"idle"},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),s?G("text",{fg:t.muted,wrapMode:"word",children:`match: ${s}`},void 0,!1,void 0,this):null,G("text",{fg:t.muted,wrapMode:"word",children:`\u2192 ${i}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function qb(e){let{palette:t,cfg:n,snap:r,width:o,onSelectRoute:i}=e,s=r?.proxy.routes??[],a=new Map((n?.proxy.routes??[]).map((C)=>[C.name,C])),c=new Map((n?.proxy.routes??[]).map((C)=>[C.name,C.match])),l=r?.proxy.recentRequests??[],d=r?.proxy.requestTotal??0,f=r?.proxy.requestErrors??0,g=o<$o,m=Math.max(Bb,Math.min(PT,Math.floor(o*0.36))),x=g?o-Wb:o-m-Wb,v=Math.max(20,x-2),w=v>=Gb,E=v>=TT,k=v>=Gb?AT:LT,j=l.reduce((C,y)=>Math.min(k,Math.max(C,(y.route||Kb).length+kT)),ST),V={showMethod:w,showDur:E,routeCol:j};return G(tt,{palette:t,title:"proxy",children:[G(Be,{palette:t,items:[{text:r?.proxy.running?"RUNNING":"STOPPED",tone:r?.proxy.running?"success":"idle"},...r?.proxy.address?[{text:r.proxy.address,tone:"info"}]:[],{text:`${s.length} routes`,tone:s.length>0?"primary":"idle"},...d>0?[{text:`${d} requests`,tone:"idle"},...f>0?[{text:`${f} errors`,tone:"warning"}]:[]]:[]]},void 0,!1,void 0,this),G("box",{flexGrow:1,flexDirection:g?"column":"row",overflow:"hidden",children:[G("box",{flexGrow:g?1:0,flexBasis:g?0:void 0,flexShrink:0,minWidth:g?void 0:Bb,width:g?void 0:m,minHeight:g?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?G($e,{palette:t,title:"No proxy routes",body:"Add routes under proxy.routes or .devctl/proxy/routes.yaml."},void 0,!1,void 0,this):G(Ub,{children:[i?G("text",{fg:t.muted,wrapMode:"word",children:"click a route for full details"},void 0,!1,void 0,this):null,G("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:G("box",{flexDirection:"column",overflow:"hidden",gap:1,children:s.map((C)=>{let y=c.get(C.name),B=y&&(y.host||y.path)?`${y.host||"*"}${y.path?y.path:""}`:void 0,h=a.get(C.name);return G(RT,{palette:t,name:C.name,auth:C.auth,identity:C.identity,upstream:C.upstream,match:B,onMouseDown:i?()=>i({name:C.name,authType:h?.auth.type||C.auth,identityType:h?.auth.identity.type??"",serviceAccount:h?.auth.identity.service_account||h?.auth.service_account||"",audience:h?.auth.audience??"",matchHost:h?.match.host??"",matchPath:h?.match.path??"",upstream:C.upstream}):void 0},C.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),G("box",{flexGrow:1,flexBasis:0,minWidth:g?void 0:30,minHeight:g?10:void 0,border:!0,borderStyle:"rounded",borderColor:t.borderActive,title:"requests",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:l.length===0?G("box",{paddingLeft:1,paddingRight:1,children:G("text",{fg:t.muted,wrapMode:"word",children:r?.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):G(Ub,{children:[G(ET,{palette:t,cols:V},void 0,!1,void 0,this),G("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:G("box",{flexDirection:"column",overflow:"hidden",children:l.map((C)=>G(_T,{palette:t,req:C,cols:V},C.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),G(je,{palette:t,backgroundColor:t.element,edge:"top",children:G(Oe,{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 _p=9,Uc=8,Kc=4,qc=8,Vc=4,ST=8,kT=2,CT=64,Kb="(none)",Bb=26,PT=56,Wb=2,Gb=46,TT=54,AT=20,LT=12;var Vb=D(()=>{Et();Pe();be()});import{jsxDEV as re}from"@opentui/react/jsx-dev-runtime";function Yb(e){let{palette:t,name:n}=e;return re("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:n,titleColor:He(n,t),flexDirection:"column",overflow:"hidden",children:re(Ep,{...e,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function Ep(e){let{palette:t,cfg:n,snap:r,name:o,reveal:i,width:s,compact:a=!0,envScrollRef:c}=e,l=se(),d=n?.services[o];if(!d)return re($e,{palette:t,title:"Unknown service",body:`No service named ${o}.`,hint:"j/k move"},void 0,!1,void 0,this);let f=r?.services[o],g=Bt(f),m=f?.health??"UNKNOWN",x=jr(f)||ss(d,f),v=Uy(d,i,n?.secrets.extra_markers??[],n?.secrets.extra_patterns??[],e.resolvedEnv),w=e.envStatus==="error"?"error":e.envStatus==="resolved"?"success":e.envStatus==="loading"?"info":"muted",E=e.envStatus==="resolved"?"resolved":e.envStatus==="loading"?"resolving":e.envStatus==="error"?"config fallback":"config",k=s>=OT,j=[{label:"health",value:_c(d)},{label:"workdir",value:d.working_dir||"."},{label:"restart",value:Rc(d)},{label:"caps",value:d.capabilities.join(", ")||"\u2014"},{label:"runtime",value:d.container?`${d.container.runtime||"docker"} \xB7 ${d.container.image}`:"host"}],V=[{label:"identity",value:Ec(d,f)},{label:"depends",value:d.dependencies.map(Ws).join(", ")||"\u2014"},{label:"ports",value:ss(d,f)},{label:"tries",value:String(f?.restarts??0),tone:f?.restarts?"warning":"muted"}],C=Math.max(Gr+8,s-2),y=k?Math.floor(C/2):C;return re("box",{padding:l.pad,flexGrow:1,flexDirection:"column",overflow:"hidden",children:[re(Be,{palette:t,items:[{text:g,tone:zb(g)},{text:m,tone:zb(m)},{text:f?.pid?`pid ${f.pid}`:"pid \u2014",tone:f?.pid?"info":"idle"},{text:x==="\u2014"?"port \u2014":`port ${x}`,tone:x==="\u2014"?"idle":"info"}]},void 0,!1,void 0,this),d.description?re("box",{height:1,overflow:"hidden",children:re("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,f?.last_error?re("box",{height:1,overflow:"hidden",children:re("text",{fg:t.error,wrapMode:"none",children:ce(f.last_error,DT)},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,re(Rp,{palette:t,item:{label:"command",value:Cc(d)},valueWidth:Math.max(8,C-Gr)},void 0,!1,void 0,this),re(MT,{palette:t,left:j,right:V,wide:k,colWidth:y},void 0,!1,void 0,this),re($T,{palette:t,entries:v,reveal:i,width:s,focused:!a,scrollRef:c,source:E,sourceTone:w,error:e.envError,onSelect:e.onSelectEnv},void 0,!1,void 0,this),a?null:re(Oe,{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 MT(e){let{palette:t,left:n,right:r,wide:o,colWidth:i}=e,s=Math.max(4,i-Gr);if(!o)return re("box",{width:i,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[...n,...r].map((a)=>re(Rp,{palette:t,item:a,valueWidth:s},a.label,!1,void 0,this))},void 0,!1,void 0,this);return re("box",{height:n.length,flexShrink:0,flexDirection:"row",overflow:"hidden",children:[re(Jb,{palette:t,items:n,width:i},void 0,!1,void 0,this),re(Jb,{palette:t,items:r,width:i},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Jb(e){let t=Math.max(4,e.width-Gr);return re("box",{width:e.width,flexShrink:0,flexDirection:"column",overflow:"hidden",children:e.items.map((n)=>re(Rp,{palette:e.palette,item:n,valueWidth:t},n.label,!1,void 0,this))},void 0,!1,void 0,this)}function Rp(e){let{palette:t,item:n,valueWidth:r}=e,o=n.tone==="warning"?t.warning:n.tone==="muted"?t.muted:t.text;return re("box",{height:1,width:Gr+r,flexDirection:"row",overflow:"hidden",children:[re("box",{width:Gr,flexShrink:0,overflow:"hidden",children:re("text",{fg:t.muted,wrapMode:"none",children:ee(n.label,Gr)},void 0,!1,void 0,this)},void 0,!1,void 0,this),re("box",{width:r,flexShrink:0,overflow:"hidden",children:re("text",{fg:o,wrapMode:"none",children:ee(n.value,r)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $T(e){let{palette:t,entries:n,reveal:r,width:o,focused:i,scrollRef:s,source:a,sourceTone:c,error:l,onSelect:d}=e;return re("box",{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[re(Be,{palette:t,items:[{text:`env ${n.length}`,tone:n.length>0?"info":"idle"},{text:a,tone:c},{text:r?"secrets shown":"redacted",tone:r?"warning":"muted"}],hints:i?[{key:"j/k",label:"scroll"}]:[{key:"/reveal",label:"secrets"}]},void 0,!1,void 0,this),l?re("box",{height:1,overflow:"hidden",children:re("text",{fg:t.warning,wrapMode:"none",children:ce(l,Math.max(8,o-4))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,n.length===0?re("text",{fg:t.muted,children:"no service env overrides"},void 0,!1,void 0,this):re("box",{flexGrow:1,height:"100%",overflow:"hidden",children:[d?re("text",{fg:t.muted,wrapMode:"word",children:"click a variable for its full value"},void 0,!1,void 0,this):null,re("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:re("box",{flexDirection:"column",overflow:"hidden",children:n.map((f)=>{let g=f.required?t.warning:f.fromConfig?t.accent:t.muted,m=f.value===""&&f.required?"(required)":f.value;return re("box",{flexDirection:"row",overflow:"hidden",onMouseDown:d?()=>d(f):void 0,children:re("text",{wrapMode:"word",children:[re("span",{fg:g,children:f.required?`${f.key}*`:f.key},void 0,!1,void 0,this),re("span",{fg:f.value===""?t.muted:t.text,children:` ${m}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},f.key,!1,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function zb(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 DT=72,OT=56,Gr=9;var Pp=D(()=>{Pe();Et();at();be();Ye();st()});import{jsxDEV as er}from"@opentui/react/jsx-dev-runtime";function Xb(e){let{palette:t,cfg:n,names:r,snap:o,selected:i,checked:s,width:a,reveal:c,onOpen:l,onSelectIndex:d,onToggle:f,resolvedEnv:g,envStatus:m,envError:x,onSelectEnv:v}=e;if(r.length===0)return er($e,{palette:t,title:"No services",body:"This configuration does not define any services."},void 0,!1,void 0,this);let w=a<$o,E=r[i]??"",k=yc(a,r,w),j=4,V=w?Math.max(Tp,a-j):Math.max(Tp,a-k-j);return er("box",{flexGrow:1,flexDirection:w?"column":"row",overflow:"hidden",children:[er("box",{flexGrow:w?1:0,flexShrink:0,minWidth:w?void 0:ic,width:w?void 0:k,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"services",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[er(Gc,{palette:t,checked:s,idle:Bo(o),profileName:"",members:""},void 0,!1,void 0,this),er("box",{flexGrow:1,overflow:"hidden",children:er(Wc,{palette:t,names:r,snap:o,selected:i,checked:s,width:fc(k),onOpen:l,onSelectIndex:d,onToggle:f},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),er("box",{flexGrow:2,minWidth:w?void 0:Tp,minHeight:w?IT:void 0,border:!0,borderStyle:"rounded",borderColor:t.border,backgroundColor:t.panel,title:E||"detail",titleColor:E?He(E,t):t.primary,overflow:"hidden",flexDirection:"column",children:er(Ep,{palette:t,cfg:n,snap:o,name:E,reveal:c,width:V,resolvedEnv:g,envStatus:m,envError:x,onSelectEnv:v},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Tp=36,IT=12;var Qb=D(()=>{Et();Pe();Ye();Pp();mp()});import{jsxDEV as he}from"@opentui/react/jsx-dev-runtime";function NT(e){switch(e){case"cycle":return"\u2194";case"toggle":return"\u23FB";case"page":return"\u25B8";case"action":return"!";default:return"\xB7"}}function nw(e){let{palette:t,items:n,selected:r,locked:o,width:i,onPick:s,onActivate:a}=e,c=se(),l=ep(n,r),d=Ko(n,l);return he("box",{flexGrow:1,border:!0,borderStyle:"rounded",borderColor:t.borderActive,backgroundColor:t.panel,title:"settings",titleColor:t.primary,flexDirection:"column",overflow:"hidden",children:[he("box",{height:2,paddingLeft:c.pad,flexShrink:0,flexDirection:"column",overflow:"hidden",children:[he("text",{fg:t.primary,wrapMode:"none",children:"Preferences"},void 0,!1,void 0,this),he("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),he("box",{flexGrow:1,paddingLeft:c.pad,paddingRight:c.pad,overflow:"hidden",flexShrink:1,children:he(HT,{palette:t,items:n,active:l,scale:c,width:i,onPick:s,onActivate:a},void 0,!1,void 0,this)},void 0,!1,void 0,this),he(BT,{palette:t,item:d,scale:c},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function HT(e){let{palette:t,items:n,active:r,scale:o,width:i,onPick:s,onActivate:a}=e,c=qo(r,tw),l=Math.max(8,i-Zb-ew-10),d=0,f=wx(n);return he("scrollbox",{ref:c,focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:he("box",{flexDirection:"column",overflow:"hidden",children:f.map((g,m)=>{let x=d;d+=g.items.length;let v=r>=x&&r<x+g.items.length;return he("box",{border:!0,borderStyle:"rounded",borderColor:v?t.borderActive:t.border,title:`${g.group} (${g.items.length})`,titleColor:v?t.primary:t.muted,flexDirection:"column",flexShrink:0,marginBottom:m<f.length-1?Math.max(1,o.gap):0,paddingLeft:1,paddingRight:1,overflow:"hidden",children:[g.group==="MCP"?he("box",{height:1,overflow:"hidden",children:he("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,g.items.map((w,E)=>{let k=x+E;return he(jT,{index:k,palette:t,item:w,active:k===r,rowH:o.rowH,valueWidth:l,onPick:()=>s(k),onActivate:()=>a(w)},w.id,!1,void 0,this)})]},g.group,!0,void 0,this)})},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function jT(e){let{palette:t,index:n,item:r,active:o,rowH:i,valueWidth:s,onPick:a,onActivate:c}=e;return he("box",{id:`${tw}-${n}`,height:i,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:o?t.highlight:void 0,onMouseDown:()=>{if(o){c();return}a()},children:[he("box",{width:2,flexShrink:0,overflow:"hidden",children:he("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:ew,flexShrink:0,overflow:"hidden",children:he("text",{fg:o?t.primary:t.muted,children:NT(r.kind)},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{width:Zb,flexShrink:0,overflow:"hidden",children:he("text",{fg:o?t.primary:t.text,wrapMode:"none",children:r.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{flexGrow:1,overflow:"hidden",children:he("text",{fg:WT(t,r,o),wrapMode:"none",children:ce(r.value,s)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function BT(e){let{palette:t,item:n,scale:r}=e,o=n?.id==="font",i=n?.kind==="page"?`${n.name} \u2192 dedicated page`:n?.name??"";return he("box",{height:FT,flexShrink:0,border:!0,borderStyle:"rounded",borderColor:t.border,title:"selected",titleColor:t.muted,backgroundColor:t.element,paddingLeft:r.pad,paddingRight:r.pad,flexDirection:"column",overflow:"hidden",children:[he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.primary,wrapMode:"none",children:o?`${xx(r.steps)} ${r.label}`:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.text,wrapMode:"word",children:n?.detail??""},void 0,!1,void 0,this)},void 0,!1,void 0,this),he("box",{height:1,overflow:"hidden",children:he("text",{fg:t.muted,wrapMode:"none",children:n?n.kind==="info"?"read-only":n.hint:""},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function WT(e,t,n){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 n?e.primary:e.text}var Zb=14,ew=2,FT=5,tw="settings-row";var rw=D(()=>{at();Pe();be();Cn()});import{useEffect as GT,useState as UT}from"react";import{jsxDEV as J}from"@opentui/react/jsx-dev-runtime";function Jo(e){let{palette:t,title:n,tone:r="muted",children:o}=e,i=r==="success"?t.success:r==="warning"?t.warning:r==="error"?t.error:t.border;return J("box",{border:!0,borderStyle:"rounded",borderColor:i,title:n,titleColor:i,flexDirection:"column",flexShrink:0,paddingLeft:1,paddingRight:1,marginBottom:1,overflow:"hidden",children:o},void 0,!1,void 0,this)}function Ap(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 fs(e){let{palette:t,cells:n,header:r,gap:o=0,stripe:i}=e;return J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,backgroundColor:i?t.element:void 0,children:n.map((s,a)=>J("box",{flexDirection:"row",flexShrink:0,overflow:"hidden",children:[a>0&&o>0?J("box",{width:o,flexShrink:0},void 0,!1,void 0,this):null,J("box",{width:s.width,flexShrink:0,overflow:"hidden",children:J("text",{fg:r?t.primary:Ap(t,s),wrapMode:"none",children:ee(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 ow(e){let{palette:t,width:n}=e;return J("box",{height:1,flexShrink:0,overflow:"hidden",children:J("text",{fg:t.border,wrapMode:"none",children:ee("\u2500".repeat(Math.max(1,n)),n)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ps(e){let{palette:t,facts:n,width:r}=e,o=Bu(n,r),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}),J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(fs,{palette:t,header:!0,gap:Ho,cells:i},void 0,!1,void 0,this),J(ow,{palette:t,width:r},void 0,!1,void 0,this),n.map((s,a)=>{let c=s.meaning===""?[""]:vc(s.meaning,Math.max(1,o.meaning)),l=s.meter?cy(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"}),J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(fs,{palette:t,gap:Ho,stripe:a%2===1,cells:d},void 0,!1,void 0,this),c.slice(1).map((f,g)=>{let m=[{text:"",width:o.what},{text:"",width:o.reading}];if(o.meter>0)m.push({text:"",width:o.meter});return m.push({text:f,width:o.meaning,tone:"muted"}),J(fs,{palette:t,gap:Ho,stripe:a%2===1,cells:m},`${s.what}-more-${g}`,!1,void 0,this)})]},`${s.what}-${s.reading}-${a}`,!0,void 0,this)})]},void 0,!0,void 0,this)}function iw(e){let{palette:t,cfg:n,snap:r,width:o,onRefresh:i}=e,s=se(),[,a]=UT(0);if(GT(()=>{let Ee=setInterval(()=>{a((Qe)=>{let pe=Qe+1;if(i&&pe%qT===0)i();return pe})},KT);return()=>clearInterval(Ee)},[i]),!n)return J($e,{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(n.services).sort(),l=c.some((Ee)=>ly(n.services[Ee])),d=ty(c,r),f=hy(d,l),g=l&&d.live>0?d.healthy/d.live:d.total>0?d.live/d.total:0,m=ts(g,VT),x=d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",v=iy(o,s.pad),w=r?.session_id?js(r.session_id):void 0,E=w?jo(Date.now()-w.getTime()):"just started",k=r?.logs.total??0,j=r?.logs.errors??0,V=oy(r?.logs.counts??{}),C=r?.proxy.routes??[],y=r?.credentials,B=(y?.entries??[]).filter((Ee)=>Ee.valid).length,h=r?.system,q=h?h.memAvailableKB??h.memFreeKB:0,I=h?uy(h.loadAvg1,h.cpuCount):void 0,z=h?py(q,h.memTotalKB):void 0,ue=[];if(h&&I&&z)ue.push(I,z,{what:"Computer",reading:dy(h.platform),meaning:`on for ${jo(h.hostUptimeSec*JT)}`,tone:"text"});let Ie=d.failed>0||I?.tone==="error"||z?.tone==="error"?"error":x==="warning"||I?.tone==="warning"||z?.tone==="warning"?"warning":"success",ct=[{what:"This session",reading:E,meaning:"how long this run has been going",tone:"text"},{what:"Profile",reading:r?.profile||"none",meaning:"which group of services is selected",tone:r?.profile?"text":"muted"},{what:"This window",reading:r?.detached?"closed":"watching",meaning:r?.detached?"services keep running without this screen":"you are watching the services from here",tone:r?.detached?"warning":"text"},{what:"Project folder",reading:"",meaning:n.repoRoot,tone:"muted"}],oe=[{what:"Lines kept",reading:String(k),meaning:"log lines still in memory",tone:"text"},{what:"Error lines",reading:String(j),meaning:j>0?"open Logs and press e to see only errors":"no ERROR or FATAL lines",tone:j>0?"error":"muted"},...V.map(([Ee,Qe])=>({what:Ee,reading:String(Qe),meaning:"lines from this service",tone:"text"}))],Ue=[{what:"Web proxy",reading:r?.proxy.running?"on":"off",meaning:r?.proxy.running?`${C.length} apps${r.proxy.address?` at ${r.proxy.address}`:""}`:"not forwarding local URLs",tone:r?.proxy.running?"success":"muted"},{what:"Agent tools",reading:r?.mcp?.running?"on":"off",meaning:r?.mcp?.address?`Cursor talks to devctl at ${r.mcp.address}`:"turn on from Settings \u2192 MCP",tone:r?.mcp?.running?"success":"muted"},{what:"Google account",reading:r?.identity.user?"signed in":"not signed in",meaning:[r?.identity.user,r?.identity.project].filter(Boolean).join(" \xB7 ")||"no Google user for this session",tone:r?.identity.user?"success":"muted"},{what:"Saved tokens",reading:y?`${B} of ${y.entries.length} good`:"none",meaning:y?my(y.backend):"nothing stored yet",tone:y&&B<y.entries.length?"warning":y?"success":"muted"}];return J(tt,{palette:t,title:"stats",scroll:!0,children:[J(Jo,{palette:t,title:`Your services ${d.live} of ${d.total} started`,tone:Ie,children:[J(ps,{palette:t,facts:f,width:v},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:J("text",{wrapMode:"none",children:[J("span",{fg:t.muted,children:ee(l?"Ready":"Started",Bu(f,v).what)},void 0,!1,void 0,this),J("span",{children:" ".repeat(Ho)},void 0,!1,void 0,this),J("span",{fg:Ap(t,{text:"",width:1,tone:x}),children:`[${m}]`},void 0,!1,void 0,this),J("span",{fg:Ap(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),h?J(Jo,{palette:t,title:"This computer",tone:I?.tone==="error"||z?.tone==="error"?"error":I?.tone==="warning"||z?.tone==="warning"?"warning":"success",children:J(ps,{palette:t,facts:ue,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,J(Jo,{palette:t,title:"This session",children:J(ps,{palette:t,facts:ct,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),J(Jo,{palette:t,title:"Each service",tone:d.failed>0?"error":l&&d.live>0&&d.healthy<d.live?"warning":"success",children:d.total===0?J("text",{fg:t.muted,children:"No services in this project yet."},void 0,!1,void 0,this):J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(zT,{palette:t,names:c,snap:r,width:v},void 0,!1,void 0,this),J("box",{height:1,flexShrink:0},void 0,!1,void 0,this),J("text",{fg:t.muted,wrapMode:"none",children:ee("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),J(Jo,{palette:t,title:"Log lines",tone:j>0?"warning":"muted",children:J(ps,{palette:t,facts:oe,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),J(Jo,{palette:t,title:"Other parts",children:J(ps,{palette:t,facts:Ue,width:v},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function zT(e){let{palette:t,names:n,snap:r,width:o}=e,i=sy(o),s=[{text:"service",width:i.name},{text:"status",width:en}];if(i.health)s.push({text:"check",width:Sn});if(i.cpu)s.push({text:"cpu",width:lc});if(i.mem)s.push({text:"ram",width:dc});if(i.up)s.push({text:"up",width:cc});if(i.rst)s.push({text:"restarts",width:Sc});if(i.pid)s.push({text:"pid",width:zn});return J("box",{flexDirection:"column",overflow:"hidden",flexShrink:0,children:[J(fs,{palette:t,header:!0,gap:vt,cells:s},void 0,!1,void 0,this),J(ow,{palette:t,width:o},void 0,!1,void 0,this),n.map((a,c)=>J(ZT,{palette:t,name:a,rt:r?.services[a],cols:i,stripe:c%2===1},a,!1,void 0,this))]},void 0,!0,void 0,this)}function QT(e){if(e===void 0)return"muted";if(e>XT)return"error";if(e>YT)return"warning";return"text"}function ZT(e){let{palette:t,name:n,rt:r,cols:o,stripe:i}=e,s=fy(r),a=gy(r),c=r?.restarts??0,l=[{text:n,width:o.name,color:He(n,t)},{text:s,width:en,color:De(t,r?.state??"STOPPED")}];if(o.health)l.push({text:a,width:Sn,color:De(t,r?.health??"UNKNOWN")});if(o.cpu)l.push({text:r?.cpuPercent!==void 0?vy(r.cpuPercent):"\u2014",width:lc,tone:QT(r?.cpuPercent)});if(o.mem)l.push({text:r?.memoryKB!==void 0?sc(r.memoryKB):"\u2014",width:dc,tone:"text"});if(o.up)l.push({text:ry(r),width:cc,tone:"text"});if(o.rst)l.push({text:String(c),width:Sc,tone:c>0?"warning":"muted"});if(o.pid)l.push({text:r?.pid?String(r.pid):"\u2014",width:zn,tone:"muted"});return J("box",{flexDirection:"column",flexShrink:0,overflow:"hidden",children:[J(fs,{palette:t,gap:vt,stripe:i,cells:l},void 0,!1,void 0,this),r?.last_error?J("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:J("text",{fg:t.error,wrapMode:"none",children:ee(` ${r.last_error}`,Math.max(24,o.name+vt+en+Sn))},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)}var KT=1000,qT=5,VT=16,JT=1000,YT=80,XT=100;var sw=D(()=>{Et();Pe();at();be();Ye();ze()});import{jsxDEV as ye}from"@opentui/react/jsx-dev-runtime";function aw(e){let{palette:t,cfg:n,google:r,bootError:o,bootErrorMissing:i=!1,step:s=0}=e,a=se();if(o&&!n)return i?ye($e,{palette:t,title:"No configuration found",body:"Would you like to run setup?",hint:"[Enter] Setup [Esc] Exit"},void 0,!1,void 0,this):ye($e,{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=n?Xt(n):["configuration not loaded"],l=eA(n,r,c),d=l.filter((k)=>k.ok).length,f=l.length,g=f>0?Math.round(d/f*100):0,m=20,x=Math.round(g/100*m),v="\u2588".repeat(x)+"\u2591".repeat(Math.max(0,m-x)),w=g===100?t.success:g===0?t.muted:t.primary,E=l[s];return ye(tt,{palette:t,title:"setup",scroll:!0,children:[ye("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye("text",{fg:t.primary,children:"Developer onboarding"},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{height:1,flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye("text",{wrapMode:"none",children:[ye("span",{fg:w,children:`[${v}]`},void 0,!1,void 0,this),ye("span",{fg:t.text,children:` ${d}/${f} ready`},void 0,!1,void 0,this),ye("span",{fg:t.muted,children:` (${g}%)`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),l.map((k,j)=>{let V=j===s;return ye("box",{height:a.rowH,flexDirection:"row",overflow:"hidden",backgroundColor:V?t.highlight:void 0,paddingLeft:1,children:[ye("box",{width:2,flexShrink:0,children:ye("text",{fg:De(t,k.ok?"OK":"WARN"),children:Mt(k.ok?"OK":"WARN")},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{width:3,flexShrink:0,children:ye("text",{fg:V?t.primary:t.muted,children:String(j+1).padStart(2," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{width:20,flexShrink:0,overflow:"hidden",children:ye("text",{fg:V?t.primary:t.text,children:k.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("box",{flexGrow:1,overflow:"hidden",children:ye("text",{fg:V?t.text:t.muted,wrapMode:"none",children:k.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},k.name,!0,void 0,this)}),ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),E?ye("box",{border:!0,borderStyle:"rounded",borderColor:E.ok?t.success:t.warning,title:E.name,titleColor:E.ok?t.success:t.warning,flexDirection:"column",paddingLeft:1,paddingRight:1,flexShrink:0,overflow:"hidden",children:ye("text",{fg:E.ok?t.text:t.warning,wrapMode:"word",children:E.detail},void 0,!1,void 0,this)},void 0,!1,void 0,this):null,ye("box",{height:1,flexShrink:0},void 0,!1,void 0,this),ye("box",{flexDirection:"row",overflow:"hidden",flexShrink:0,children:ye(ge,{palette:t,label:"never hard-coded",tone:"idle"},void 0,!1,void 0,this)},void 0,!1,void 0,this),ye("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),ye(Oe,{palette:t,hints:[{key:"j/k",label:"steps"},{key:"enter",label:n?"start":"begin setup"},{key:"esc",label:"exit"},{key:"o",label:"profiles"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function eA(e,t,n=[]){let r=Object.values(e?.services??{}).flatMap((s)=>s.ports.filter((a)=>!a.auto)),o=(e?.proxy.routes??[]).some((s)=>s.auth.type.toLowerCase()==="iap"),i=Go(e,void 0,t).project;return[{name:_n[0],ok:Boolean(e?.repoRoot),detail:e?.repoRoot||"unknown"},{name:_n[1],ok:Boolean(e?.project.name),detail:e?.project.name||"set project.name"},{name:_n[2],ok:Boolean(i),detail:i||"optional for local-only"},{name:_n[3],ok:t?.adcAvailable===!0,detail:t?.adcAvailable?"ADC available":"needed only for cloud identity / IAP"},{name:_n[4],ok:!0,detail:"read from configuration; never hard-coded"},{name:_n[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:_n[6],ok:r.length===0||Boolean(e),detail:`${r.length} fixed ports from configuration`},{name:_n[7],ok:Object.keys(e?.profiles??{}).length>0,detail:`${Object.keys(e?.profiles??{}).length} profile(s)`},{name:_n[8],ok:n.length===0,detail:n.length===0?"configuration is valid":n[0]??"invalid"}]}var _n;var cw=D(()=>{st();Et();at();be();Pe();Ye();_n=["Repository","Environment","Google project","Authentication","Service accounts","IAP","Ports","Profiles","Validation"]});import{jsxDEV as U}from"@opentui/react/jsx-dev-runtime";function Mp(){return pu.flatMap((e)=>Ua.filter((t)=>t.category===e))}function zc(){return Jc+Mp().length}function uw(){return zc()+dw}function Yc(e){if(e<Jc||e>=zc())return;return Mp()[e-Jc]}function $p(e){let t=e-zc();return t>=0&&t<dw?t:void 0}function pw(e){let{palette:t,snap:n,port:r,portDraft:o="",selected:i,onPick:s,onToggle:a,onCopy:c,onToggleTool:l}=e,d=se(),f=n?.mcp?.running===!0,g=n?.mcp?.port??r,m=n?.mcp?.address??Oo(g),x=n?.mcp?.token??"",v=Ji(m,x),w=n?.mcp?.disabled_tools??[],E=Mp(),k=E.filter((C)=>!qn(C.name,w)).length,j=v[$p(i)??-1],V=j??v[0];return U(tt,{palette:t,title:"mcp settings",children:[U(Be,{palette:t,items:[{text:f?"RUNNING":"STOPPED",tone:f?"success":"idle"},{text:`127.0.0.1:${g}`,tone:"info"}]},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("scrollbox",{focused:!1,stickyScroll:!1,scrollX:!1,style:Te(t),children:U("box",{flexDirection:"column",overflow:"hidden",children:[U(Lp,{palette:t,text:"Server"},void 0,!1,void 0,this),U(lw,{palette:t,active:i===Dp,rowH:d.rowH,label:"Listen",value:f?"[ ON ]":"[ OFF ]",valueTone:f?"success":"muted",hint:f?"space or enter stop":"space or enter start",onPick:()=>s(Dp),onActivate:a},void 0,!1,void 0,this),U(lw,{palette:t,active:i===Op,rowH:d.rowH,label:"Port",value:`\u2039 ${o===""?r:o} \u203A`,valueTone:"info",hint:o===""?"\u2190 \u2192 change type digits enter apply":"typing\u2026 enter apply \u232B erase",onPick:()=>s(Op)},void 0,!1,void 0,this),U("box",{height:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:f?"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),U(Lp,{palette:t,text:"Tools",extra:k===0?"all enabled":`${k} disabled`},void 0,!1,void 0,this),U("box",{height:1,overflow:"hidden",children:U("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),pu.map((C)=>{let y=E.filter((B)=>B.category===C);if(y.length===0)return null;return U("box",{flexDirection:"column",overflow:"hidden",children:[U("box",{height:1,marginTop:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:tA[C]??C},void 0,!1,void 0,this)},void 0,!1,void 0,this),y.map((B)=>{let h=Jc+E.indexOf(B);return U(iA,{palette:t,tool:B,enabled:qn(B.name,w),active:i===h,rowH:d.rowH,onPick:()=>s(h),onToggle:()=>l(B)},B.name,!1,void 0,this)})]},C,!0,void 0,this)}),U(Lp,{palette:t,text:"Copy agent config",extra:"highlight a row, then enter or click Copy"},void 0,!1,void 0,this),v.map((C,y)=>{let B=zc()+y;return U(oA,{palette:t,snippet:C,active:i===B,rowH:d.rowH,onPick:()=>s(B),onCopy:()=>c(C)},C.kind,!1,void 0,this)}),U(sA,{palette:t,snippet:V,selected:Boolean(j),brand:V?Lc(V.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),U(je,{palette:t,backgroundColor:t.element,edge:"top",children:U(Oe,{palette:t,hints:rA(i,f)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function rA(e,t){if(e===Dp)return[{key:"space",label:t?"stop server":"start server"},{key:"j/k",label:"move"}];if(e===Op)return[{key:"\u2190\u2192",label:"change port"},{key:"0-9",label:"type port"},{key:"enter",label:"apply port"},{key:"j/k",label:"move"}];if(Yc(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 Lp(e){let t=e.extra?` \xB7 ${e.extra}`:"";return U("box",{height:1,marginTop:1,overflow:"hidden",children:U("text",{wrapMode:"none",children:[U("span",{fg:e.palette.primary,children:e.text},void 0,!1,void 0,this),U("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 lw(e){let{palette:t,active:n,rowH:r,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 U("box",{height:r,flexDirection:"row",overflow:"hidden",backgroundColor:n?t.highlight:t.panel,onMouseDown:()=>{if(n&&l){l();return}c()},children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:t.primary,children:n?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Ip,flexShrink:0,overflow:"hidden",children:U("text",{fg:n?t.primary:t.text,wrapMode:"none",children:o},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:nA,flexShrink:0,overflow:"hidden",children:U("text",{fg:d,wrapMode:"none",children:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:n?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 oA(e){let{palette:t,snippet:n,active:r,rowH:o,onPick:i,onCopy:s}=e,a=Lc(n.kind,t),c=px(n.kind,t),l=n.language==="toml"?"Copy TOML":"Copy JSON";return U("box",{height:o,flexDirection:"row",overflow:"hidden",backgroundColor:r?t.highlight:t.panel,onMouseDown:i,children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:a,children:r?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Ip,flexShrink:0,overflow:"hidden",children:U("text",{fg:a,wrapMode:"none",children:n.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:t.muted,wrapMode:"none",children:n.path},void 0,!1,void 0,this)},void 0,!1,void 0,this),U(ge,{palette:t,label:l,bg:a,fg:c,onMouseDown:()=>{i(),s()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function iA(e){let{palette:t,tool:n,enabled:r,active:o,rowH:i,onPick:s,onToggle:a}=e;return U("box",{height:i,flexDirection:"row",overflow:"hidden",backgroundColor:o?t.highlight:t.panel,onMouseDown:()=>{if(o){a();return}s()},children:[U("box",{width:2,flexShrink:0,overflow:"hidden",children:U("text",{fg:t.primary,children:o?"\u203A":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:5,flexShrink:0,overflow:"hidden",children:U("text",{fg:r?t.success:t.muted,wrapMode:"none",children:r?" ON ":" OFF "},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:Ip+4,flexShrink:0,overflow:"hidden",children:U("text",{fg:o?t.primary:r?t.text:t.muted,wrapMode:"none",children:n.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{width:7,flexShrink:0,overflow:"hidden",children:U("text",{fg:n.mutates?t.warning:t.muted,wrapMode:"none",children:n.mutates?"write":"read"},void 0,!1,void 0,this)},void 0,!1,void 0,this),U("box",{flexGrow:1,overflow:"hidden",children:U("text",{fg:o?t.text:t.muted,wrapMode:"none",children:o?`space or enter ${r?"disable":"enable"} ${n.name}`:n.summary},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function sA(e){let{palette:t,snippet:n,selected:r,brand:o}=e;if(!n)return null;let i=n.hint?` \xB7 ${n.hint}`:"";return U("box",{marginTop:1,flexDirection:"column",overflow:"hidden",children:[U("text",{fg:o,wrapMode:"none",children:r?`${n.title} \xB7 paste into ${n.path}${i}`:`Preview ${n.title} \xB7 j/k to a copy row, then enter`},void 0,!1,void 0,this),U("text",{fg:t.text,children:n.text},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Dp=0,Op=1,Jc=2,dw=4,tA,Ip=14,nA=14;var fw=D(()=>{at();be();Ye();Gi();tA={inspect:"Inspect",logs:"Logs",diagnostics:"Diagnostics",control:"Control",setup:"Setup"}});async function gw(e,t){e.suspend();try{return await t()}finally{e.resume(),e.intermediateRender()}}import{existsSync as aA,readFileSync as mw,writeFileSync as cA}from"fs";import{useCallback as Q,useEffect as gt,useMemo as En,useRef as Xe,useState as M}from"react";import{RGBA as lA}from"@opentui/core";import{useKeyboard as dA,useRenderer as uA,useTerminalDimensions as pA}from"@opentui/react";import{jsxDEV as ie,Fragment as hA}from"@opentui/react/jsx-dev-runtime";function hw({controller:e,tui:t,onQuit:n,bootError:r,bootErrorMissing:o=!1,terminalBackground:i}){let s=uA(),{width:a,height:c}=pA(),[l,d]=M(t.theme||e?.cfg.ui.theme||"devctl"),f=Xe(l),[g,m]=M(t.mouse),x=Xe(t.mouse),[v,w]=M(t.leader_timeout),E=Xe(t.leader_timeout),[k,j]=M(()=>ls(t.font_size)),V=Xe(k),C=hx(),y=En(()=>{let p=ux(l);if(Pc(l)!=="terminal"||!zu(i))return p;let u=i??p.background;return{...p,background:u,panel:u,element:u,inverse:u}},[i,l]),B=Pc(l)==="terminal"&&zu(i)?lA.defaultBackground(i??void 0):y.background,[h,q]=M(e?"dashboard":"setup"),[I,z]=M("none"),[ue,Ie]=M(""),[ct,oe]=M(0),[Ue,Ee]=M(0),[Qe,pe]=M(0),[Se,It]=M([]),[N,Pt]=M(),nt=En(()=>bx({themeName:l,fontSize:k,mouse:g,leaderMs:v,locked:C,configPath:C?t.path||tp():tp(),mcpRunning:N?.mcp?.running===!0}),[k,v,g,C,N?.mcp?.running,l,t.path]),[Ve,Wt]=M([]),[lt,tr]=M(!1),[mt,on]=M(!1),[sn,an]=M(!0),[Ur,_]=M(r??""),[cn,Rn]=M(),[Jt,Xc]=M(),[Qc,gs]=M(!1),[zo,Wp]=M(""),[Zc,el]=M(0),[_w,Gp]=M({active:"Preparing diagnostics",checks:[]}),Up=Xe(void 0),Yo=Xe(0),[Ew,Rw]=M({}),[Kp,Pw]=M(),[Ze,tl]=M(xc(e?.cfg)),[nr,Tw]=M(""),[Kr,qp]=M(!1),[Pn,Aw]=M(""),[ms,nl]=M(!1),[Vp,Lw]=M(0),[qr,Jp]=M(""),[hs,Dw]=M(""),[zt,Ft]=M(""),rr=gA,[zp,Ow]=M(t.log_timestamps!==!1),[Yp,Mw]=M(t.log_metadata!==!1),[Xp,$w]=M(()=>[...xy]),[vs]=M(""),[or]=M(""),[Tn,Iw]=M(!1),[ys,Qp]=M(),[Fw,Nw]=M(),[Vr,rl]=M(),[xs,ol]=M(),[Hw,Zp]=M(!1),[ef,Jr]=M(""),[Xo,tf]=M("focus"),[bt,An]=M(!1),[jw,Qo]=M(Nr-1),[Zo,bs]=M(!1),[ln,ws]=M(-1),[nf,Bw]=M(),[rf,of]=M(""),[sf,il]=M(!1),[af,cf]=M(!1),lf=Xe([]),ei=Xe(null),ti=Xe(null),ni=Xe(null),df=Xe(null),sl=Xe(null),uf=Xe(null),al=Xe(null),pf=Xe(null),[cl,Ww]=M(""),[Gw,Ss]=M(""),ll=Xe(""),dl=Xe(!1),[ff,ri]=M(0),[ks,ul]=M(""),[Cs,pl]=M(),[Uw,fl]=M([]),[gf,dn]=M(!1),[mf,gl]=M("start"),[ir,Ln]=M("quit"),[Dn,Kw]=M(()=>t.mcp_port??Do(e?.cfg.repoRoot??process.cwd())),oi=Xe(void 0),ml=Xe(0),[T,qw]=M(e?.cfg),Vw=e?.previousPersisted,[ii,hf]=M(void 0),vf=t.keybinds.copy??bn(),rt=En(()=>Object.keys(T?.services??{}).sort(),[T]),si=En(()=>rs(rt,Ve,Xp),[rt,Ve,Xp]),ai=En(()=>bv(ue),[ue]),zr=En(()=>jy(ue),[ue]);gt(()=>{$w((p)=>{let u=new Set(p),R=!1;for(let b of Ve)if(b.service!==""&&!rt.includes(b.service)&&!u.has(b.service))u.add(b.service),R=!0;return R?[...u].sort():p})},[Ve,rt]),gt(()=>{Ee(0)},[ue]),gt(()=>{if(I==="palette")oe(0)},[I,ue]);let ot=En(()=>Wo(Ve,{service:zt,services:rr,errorOnly:mt,search:Pn,regex:Tn,source:or,since:qr,until:hs,systemLogs:sn}),[mt,Tn,Pn,zt,rr,qr,or,hs,Ve,sn]),Fe=En(()=>Kv(ot,bt,ff),[ot,bt,ff]),On=Fe.items,un=Zv(h,{doctor:Jt?.checks.length??0,settings:nt.length,profiles:Object.keys(T?.profiles??{}).length,services:rt.length,logs:On.length,mcp:uw()}),yf=h==="logs"?jw:Qe,te=un<=0?Math.max(0,yf):Math.max(0,Math.min(yf,un-1)),pn=h==="detail"?nr:h==="services"?rt[te]??"":"",_s=xs?.name===pn,xf=_s?xs?.env:void 0,bf=pn===""?"config":Hw&&!_s?"loading":_s?"resolved":ef!==""?"error":"config",wf=_s||pn===""?"":ef;gt(()=>{ws(-1),An(!1),Qo(Math.max(0,Math.min(Nr,ot.length)-1))},[mt,Pn,zt,sn]),gt(()=>{if(h!=="logs")bs(!1)},[h]),gt(()=>{if(h!=="logs"||bt)return;Qo(Math.max(0,Math.min(Nr,ot.length)-1))},[ot.length,bt,h]),gt(()=>{if(h==="settings")return;d(f.current),j(V.current),w(E.current),m(x.current)},[h]);let hl=Q(()=>{if(!bt)ri(Hu(ot.length)),An(!0)},[ot.length,bt]),ci=Q((p)=>{let u=ju(p,un,Fe.start,Fe.newer);if(u.startDelta!==0){ri(Math.max(0,Fe.start+u.startDelta)),An(!0),Qo(u.selected);return}let R=Math.max(un-1,0),b=un>0&&(u.selected<R||Fe.newer>0);if(b&&!bt)ri(Hu(ot.length)),An(!0);else if(!b)An(!1);Qo(u.selected)},[ot.length,un,bt,Fe.newer,Fe.start]),Es=Q((p)=>{let u=On.length,R=ju(p,u,Fe.start,Fe.newer);if(R.startDelta!==0)ri(Math.max(0,Fe.start+R.startDelta)),An(!0);ws(R.selected)},[On.length,Fe.newer,Fe.start]),vl=Q(()=>{if(An(!1),ws(-1),h==="logs")Qo(Math.max(0,Math.min(Nr,ot.length)-1));Lw((p)=>p+1),_(Fe.newer>0?`Jumped to latest (+${Fe.newer} new)`:"Jumped to latest logs")},[ot.length,Fe.newer,h]),et=Q(()=>{if(z("none"),Ie(""),nl(!1),oi.current)clearTimeout(oi.current)},[]),yl=Q((p)=>{It((u)=>u.includes(p)?u.filter((R)=>R!==p):[...u,p])},[]),Ke=Q((p,u)=>{if(C){_(`${u} session only`);return}let R=gv(p);_(`${u} saved ${R}`)},[C]),Yr=Q((p)=>{d(p),f.current=p,Ke({theme:p},`theme ${p}`)},[Ke]),li=Q(()=>{let p=!g;m(p),x.current=p,Ke({mouse:p},`mouse ${p?"on":"off"} restart TUI to apply clicks`)},[g,Ke]),Rs=Q((p)=>{w(p),E.current=p,Ke({leader_timeout:p},`leader ${p}ms`)},[Ke]),sr=Q((p)=>{let u=ls(p);j(u),V.current=u,Ke({font_size:u},`display ${Dc(u)}`)},[Ke]),Sf=Q(()=>{let p=Zu();d(p.theme),f.current=p.theme,m(p.mouse),x.current=p.mouse,w(p.leader_timeout),E.current=p.leader_timeout,j(p.font_size),V.current=p.font_size,Ke(p,"restored default preferences")},[Ke]),xl=Q((p)=>{if(p.id==="theme"){oe(Math.max(0,yt.indexOf(l))),z("themes");return}if(p.id==="mouse"){li();return}if(p.id==="leader"){Rs(v);return}if(p.id==="font"){sr(k);return}if(p.id==="reset"){Ln("reset-prefs"),z("confirm");return}if(p.id==="mcp"){q("mcp"),pe(0);return}_(p.detail)},[sr,Rs,k,v,l,li]),kf=Q((p)=>{let u=Ko(nt,te);if(!u)return;if(u.id==="theme"){Yr(vx(l,p));return}if(u.id==="leader"){Rs(yx(v,p));return}if(u.id==="font"){sr(Oc(k,p));return}if(u.id==="mouse")li()},[sr,Rs,k,v,te,Yr,nt,l,li]),Jw=Q(()=>{d(f.current)},[]),ve=Q(async()=>{if(!e)return;try{let p=await e.status();if(Pt(p),p.profile&&Ze==="")tl(p.profile);return p}catch(p){_(O(p));return}},[e,Ze]),Xr=Q(async()=>{if(!e){_("Supervisor is not running");return}_("Probing configured identities\u2026");try{let p=await e.refreshAuth();Pt((W)=>W?{...W,identity:p}:W);let u=Object.values(p.service_account_status),R=u.filter((W)=>W==="available").length,b=u.filter((W)=>W==="unavailable").length;_(u.length===0?"Identity refreshed \u2014 no service accounts configured":`Identity refreshed \u2014 ${R} available${b>0?`, ${b} unavailable`:""}`)}catch(p){_(O(p))}},[e]),Ps=Q((p)=>{let u=Or(p);Kw(u);let R=T?.repoRoot??process.cwd();if(uv(R,u)){Ke({mcp_port:null},`MCP port ${u} (default)`);return}Ke({mcp_port:u},`MCP port ${u}`)},[T,Ke]),Qr=Q(()=>{if(ks==="")return Dn;let p=dv(ks,Dn);return ul(""),Ps(p),p},[Dn,ks,Ps]),Cf=Q(async(p)=>{if(!e||N?.mcp?.running!==!0)return;await e.mcpStop(),await e.mcpStart({port:p}),await ve()},[e,ve,N?.mcp?.running]),bl=Q(async(p)=>{if(!e){_("Supervisor is not running");return}let u=N?.mcp?.disabled_tools??[],R=qn(p.name,u),b=R?[...u,p.name]:u.filter((W)=>W!==p.name);try{let W=await e.mcpSetTools(b);Ke({mcp_disabled_tools:W},`${p.label} ${R?"disabled":"enabled"}`),await ve()}catch(W){_(O(W))}},[e,Ke,ve,N]),Ts=Q(async()=>{if(!e){_("Supervisor is not running");return}try{if(N?.mcp?.running)await e.mcpStop(),Ke({mcp_enabled:!1},"MCP off"),_("MCP stopped");else await e.mcpStart({port:Dn}),Ke({mcp_enabled:!0},"MCP on"),_("MCP started");await ve()}catch(p){_(O(p))}},[e,Dn,Ke,ve,N?.mcp?.running]),wl=Q((p)=>{op(p.text).then(()=>{_(`Copied ${p.title} snippet`)}).catch((u)=>{_(O(u))})},[]),As=Q((p)=>{let u=$p(p);if(u===void 0)return!1;let R=N?.mcp?.address??Oo(N?.mcp?.port??Dn),b=Ji(R,N?.mcp?.token??"")[u];if(!b)return!1;return wl(b),!0},[wl,Dn,N?.mcp?.address,N?.mcp?.port,N?.mcp?.token]),Zr=En(()=>({services:zt!==""?[zt]:rr,level:mt?"ERROR":vs,search:Pn,regex:Tn,source:or,since:qr,until:hs}),[mt,vs,Tn,Pn,zt,rr,qr,or,hs]),Ls=Q(async()=>{if(!e)return;try{Bw(await e.logsStats(Zr))}catch(p){_(O(p))}},[e,Zr]),_f=Q(async()=>{if(!e||lt)return;try{let p=await e.logsPage(Zr);Wt((u)=>wy(u,p.events)),of(p.prevCursor),il(p.hasPrev),await Ls()}catch(p){_(O(p))}},[e,Zr,lt,Ls]),di=Q(()=>{Wt([]),Jp(new Date().toISOString()),An(!1),_("Cleared on-screen log buffer")},[]),ui=Q(()=>{an((p)=>!p)},[]);gt(()=>{ve().then(()=>_f())},[ve,_f]),gt(()=>{lf.current=Ve},[Ve]),gt(()=>{if(!e||af||!ky(bt,Fe.start,sf))return;cf(!0),e.logsPage({...Zr,cursor:rf,direction:"backward"}).then((p)=>{if(p.sessionChanged){_("Daemon session changed \u2014 older log history is no longer available"),il(!1);return}let u=lf.current,R=Sy(u,p.events);if(Wt(R),R.length>u.length)ri((b)=>b+(R.length-u.length));of(p.prevCursor),il(p.hasPrev)}).catch((p)=>_(O(p))).finally(()=>cf(!1))},[e,Zr,af,sf,bt,rf,Fe.start]),gt(()=>{if(!e||lt||h!=="logs")return;let p=setInterval(()=>{Ls()},mA);return()=>clearInterval(p)},[e,lt,Ls,h]),gt(()=>{if(!e)return;let p,u=!1,R=[],b=T&&T.logs.max_memory_events>0?T.logs.max_memory_events:50000,W=()=>{if(p=void 0,R.length>0){let S=R.splice(0,R.length);Wt((le)=>by(le,S,qr,b))}if(u)u=!1,ve()},Mn=e.onEvent((S)=>{if(S.type===ha&&S.payload&&typeof S.payload==="object"&&"event"in S.payload){let le=S.payload.event;if(!lt)R.push(le);if(!p)p=setTimeout(W,30);return}if(S.type===Ti){hf(zy(S));return}if(S.type===va)hf(void 0),e.configSnapshot().then(qw).catch((le)=>_(O(le)));if(u=!0,!p)p=setTimeout(W,30)});return()=>{if(Mn(),p)clearTimeout(p)}},[e,qr,lt,ve]),gt(()=>{Ot(T?.google.project_id??"").then(Rn).catch((p)=>{_(O(p))})},[T?.google.project_id,N?.identity.project]),gt(()=>{if(h!=="doctor"||!T)return;let p=Up.current,u=N?.session_id??"";if(p?.cfg===T&&p.tick===Zc&&p.sessionID===u&&p.reloadError===ii)return;Up.current={cfg:T,tick:Zc,sessionID:u,reloadError:ii};let R=++Yo.current;gs(!0),Wp(""),Gp({active:"Preparing diagnostics",checks:[]});let b;if(T.configPath!==""){b="";try{xi(T.repoRoot,T.configPath)}catch(W){b=O(W)}}Un(T,void 0,(W)=>{if(R===Yo.current)Gp(W)},{services:N?.services,proxyRunning:N?.proxy.running,repositoryConfigError:b}).then((W)=>{if(R!==Yo.current)return;Xc(W)}).catch((W)=>{if(R!==Yo.current)return;Wp(O(W))}).finally(()=>{if(R===Yo.current)gs(!1)})},[h,T,Zc,N?.session_id,ii]);let ar=Q((p)=>{Tw(p),q("detail")},[]),Ef=Q((p)=>{let u=p.value!==""?p.value:p.required?"(required, not set)":"(empty)";rl({title:p.key,body:u}),z("scroll-text")},[]);gt(()=>{ol(void 0),Jr("")},[T]),gt(()=>{if(!e||pn===""||!T?.services[pn])return;if(xs?.name===pn)return;let p=!1;return Zp(!0),Jr(""),e.execService(pn,[],!0).then((u)=>{if(p)return;ol({name:pn,env:u.environment??{}}),Jr("")}).catch((u)=>{if(p)return;Jr(O(u))}).finally(()=>{Zp(!1)}),()=>{p=!0}},[T,e,pn,xs?.name]);let fn=Q(async(p,u)=>{if(!e||!T){_("no configuration loaded");return}try{let R=Ca(T,{services:p,profile:u}),b=$i(T,R.services,R.profile);gl("start"),fl(b.waves.flat().filter((S)=>es(N?.services[S]))),pl(b),z("plan"),dn(!0);let W=R.services.filter((S)=>!es(N?.services[S])),Mn=await e.start({services:W.length>0?W:R.services,profile:R.profile});await ve(),dn(!1),_(Ay(Mn))}catch(R){dn(!1),await ve(),_(O(R))}},[T,e,ve,N]),Ds=Q(async(p)=>{if(!e||!T){_("no configuration loaded");return}let u=p.length>0?p:Object.entries(N?.services??{}).filter(([,R])=>R.state!=="STOPPED"&&R.state!=="UNKNOWN").map(([R])=>R);if(u.length===0){_("nothing to stop");return}try{let R=Ii(T,u);gl("stop"),fl([]),pl(R),z("plan"),dn(!0),await e.stop(p),await ve(),dn(!1),_(Ly(R))}catch(R){dn(!1),await ve(),_(O(R))}},[T,e,ve,N]),pi=Q(async(p,u)=>{if(!e||!T){_("no configuration loaded");return}try{let R=Qv(T,p,u),b=$i(T,R.services,R.profile);gl("restart"),fl([]),pl(b),z("plan"),dn(!0),await e.restart(p),await ve(),dn(!1),_(os(b)===""?"Restarted selected services":`Restarted ${os(b)}`)}catch(R){dn(!1),await ve(),_(O(R))}},[T,e,ve]),Os=Q(async(p="")=>{let u=I==="log-details"&&ys?_y(ys):I==="scroll-text"&&Vr?Vr.body:Ey(ot),R=p===""?"":` \xB7 ${p}`;if(u.trim()===""){_(`No logs to copy${R}`);return}try{await op(u);let b=u.split(`
628
+ `).length,W=I==="log-details"?"Copied log event":I==="scroll-text"?"Copied overlay text":`Copied ${b} log lines`;_(`${W}${R}`)}catch(b){_(O(b))}},[ot,ys,I,Vr]),Sl=Q(()=>{if(!T)return;try{Ww(mw(T.configPath,"utf8")),Ss(""),z("config-edit")}catch(p){_(O(p))}},[T]),zw=Q(()=>{if(!T)return;let p=pf.current?.plainText??cl,u=co(T.repoRoot,T.configPath,p);if(u.length>0){Ss(u.join(`
629
+ `)),_("Config buffer not saved");return}if(cA(T.configPath,p),Ss(""),z("none"),!e){_(`Wrote ${T.configPath}`);return}e.reload().then((R)=>{if(_(R.restart_required.length===0?"Configuration saved and reloaded":`Saved; restart required: ${R.restart_required.join(", ")}`),R.restart_required.length>0)Ln("reload"),z("confirm");ve()})},[T,cl,e,ve]),gn=Q(async(p,u)=>{if(dl.current)return;if(dl.current=!0,p.name!=="start"&&p.name!=="stop"&&p.name!=="restart")z("none");Ie("");let R=yy(u,Se);try{switch(p.name){case"exit":Ln("quit"),z("confirm");return;case"help":z("help");return;case"version":_(Dt()),Yi().then((b)=>_(_u(b))).catch((b)=>_(O(b)));return;case"update":_("checking for update\u2026"),Yi().then((b)=>_(_u(b))).catch((b)=>_(O(b)));return;case"themes":if(u[0]){Yr(u[0]);return}oe(Math.max(0,yt.indexOf(l))),Ie(""),z("themes");return;case"settings":q("settings"),pe(0);return;case"dashboard":case"services":q(p.name);return;case"logs":if(u[0])Ft(u[0]);q("logs");return;case"fullscreen":q("logs"),bs((b)=>h==="logs"?!b:!0);return;case"auth":{let b=(u[0]??"").toLowerCase();if(b==="refresh"){q("auth"),await Xr();return}if(b==="login"){q("auth"),_("starting gcloud ADC login\u2026");try{await gw(s,()=>mo()),Rn(await Ot(T?.google.project_id??"")),await Xr(),_("ADC login complete")}catch(W){_(O(W))}return}if(b==="logout"){q("auth"),_("revoking ADC\u2026");try{await la(),Rn(await Ot(T?.google.project_id??"")),await Xr(),_("ADC revoked")}catch(W){_(O(W))}return}q("auth");return}case"credentials":case"proxy":case"mcp":case"config":case"profiles":case"setup":q(p.name);return;case"diff":if(!T){_("no configuration loaded");return}rl({title:"config sources",body:ax(T,Kr)}),z("scroll-text");return;case"daemon":{let b=T?.repoRoot;if(!b){_("no repository");return}let W=ur(b);if(!aA(W)){_("no daemon bootstrap log yet for this repository");return}rl({title:"daemon bootstrap",body:mw(W,"utf8")}),z("scroll-text");return}case"reload":if(!e)return;e.reload().then((b)=>{if(_(b.restart_required.length===0?"Configuration reloaded":`Reload requires restart: ${b.restart_required.join(", ")}`),b.restart_required.length>0)Ln("reload"),z("confirm");ve()});return;case"doctor":q("doctor");return;case"stats":q("stats");return;case"start":await fn(R,Ze);return;case"stop":await Ds(R);return;case"restart":await pi(R,Ze);return;case"run":{let b=u[0]??"";if(!e||!b){_(b?"no daemon attached":"usage: /run <task>");return}try{let W=await e.runTask(b);Ft(`task:${b}`),q("logs"),_(`task ${b} exited ${W.code}`)}catch(W){throw Ft(`task:${b}`),q("logs"),W}return}case"exec":{let b=kv(u);if(!e||!b.service){_(b.service?"no daemon attached":"usage: /exec <service> -- <command\u2026>");return}if(b.printEnv){if(!T?.services[b.service]){_(`unknown service ${b.service}`);return}if(b.reveal)qp(!0);_(`Resolving environment for ${b.service}\u2026`);try{let W=await e.execService(b.service,[],!0);ol({name:b.service,env:W.environment??{}}),Jr(""),ar(b.service),_(`Resolved environment for ${b.service}`)}catch(W){Jr(O(W)),ar(b.service),_(O(W))}return}if(b.command.length===0){_("usage: /exec <service> -- <command\u2026>");return}try{let W=await e.execService(b.service,b.command);Ft(`${b.service}:exec`),q("logs"),_(`${b.service}:exec exited ${W.code}`)}catch(W){throw Ft(`${b.service}:exec`),q("logs"),W}return}case"refresh":if(h==="auth"){await Xr();return}await ve(),_("Refreshed status and logs");return;case"pause":tr((b)=>!b),q("logs");return;case"filter":on((b)=>!b),q("logs");return;case"system":ui(),q("logs");return;case"clear":di();return;case"reveal":{let b=!Kr;qp(b),_(b?"Secrets visible this session":"Secrets hidden");return}case"wrap":{let b=Nu(Xo);tf(b),_(`Log ${Qi(b)}`);return}case"copy":await Os();return;case"export":{let b=Eo(u[0]);if(e)await e.logs({export:b,services:rr,level:mt?"ERROR":vs,search:Pn,regex:Tn,source:or});else Ma(b,ot);ll.current=b,_(`Exported ${b}`);return}case"exports":{let b=ll.current||dr();$a(b),_(`Opened ${dr()}`);return}case"regex":Iw((b)=>!b),_(Tn?"Substring search":"Regex search");return;case"since":Jp(u[0]||new Date(Date.now()-3600000).toISOString()),_(`Logs since ${u[0]||"1h"}`);return;case"until":Dw(u[0]||new Date().toISOString()),_(`Logs until ${u[0]||"now"}`);return;case"history":{let{listSessions:b,loadSessionEvents:W}=await Promise.resolve().then(() => (Ar(),mh)),Mn=b(),S=u[0]||Mn[0];if(!S){_("No persisted log sessions");return}Wt(W(S)),_(`Loaded session ${S}`);return}case"buffer":Sl();return;case"edit":{if(!T)return;let b=process.env.DEVCTL_EDITOR||process.env.EDITOR,W=b?[b,T.configPath]:process.platform==="darwin"?["open",T.configPath]:["xdg-open",T.configPath];Bun.spawn({cmd:W,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),_(`Opened ${T.configPath} in ${W[0]}. Run /reload after saving.`);return}default:_(`/${p.name}`)}}catch(b){_(O(b))}finally{setTimeout(()=>{dl.current=!1},fA)}},[pi,fn,Ds,Se,T,di,e,Os,mt,ot,vs,Tn,Pn,rr,or,Xo,Sl,ar,Yr,Ze,ve,Xr,s,Kr,h,l,ui]),Yw=Q(()=>{let p=ll.current||dr();$a(p),_(`Opened ${dr()}`)},[]),kl=Q(()=>{let p=Hr(ai,Ue);if(!p){_(ue.trim()===""?"pick a command from the list":`unknown command /${ue}`),et();return}let R=zi(ue)?.name===p.name?wv(ue):[];gn(p,R)},[et,ai,ue,gn,Ue]),Rf=Q((p)=>{Yr(p),et()},[et,Yr]),Xw=Q((p)=>{let u=zi(p);if(u)gn(u,[])},[gn]),Pf=Q(()=>{if(I==="palette"){let p=Hr(zr,ct);if(p)gn(p,[]);return}kl()},[I,ct,zr,gn,kl]),Qw=Q(()=>{if(T?.shutdown.stop_services_on_exit===void 0){Ln("quit"),z("confirm");return}n(T.shutdown.stop_services_on_exit===!1)},[T,n]),Zw=Q(()=>{if(ir==="quit"){n(!1);return}if(ir==="reload"){et();let p=N?.restart_required??[];if(p.length>0)pi(p,Ze);return}if(ir==="reset-prefs"){et(),Sf();return}if(ir==="free-port"){let p=Kp;if(et(),!p)return;ua(p).then(()=>{_(`Stopped ${p.command} (pid ${p.pid}) on port ${p.port}`),el((u)=>u+1)}).catch((u)=>{_(O(u))});return}et(),fn([],Ze)},[Sf,pi,fn,et,ir,n,Kp,Ze,N]),eS=Q(()=>{if(h==="logs"){let u=On[te];if(u)Qp(u),z("log-details");return}if(h==="profiles"){let R=Object.keys(T?.profiles??{}).sort()[te];if(R)tl(R),Ln("start-profile"),z("confirm");return}if(h==="doctor"){let u=Jt?.checks[te];if(u?.action?.kind==="free-port"){let R=u.action.holder;Pw(R),Rw({port:R.port,pid:R.pid,process:R.command}),Ln("free-port"),z("confirm")}return}if(h==="mcp"){if(te===0){Ts();return}if(te===1){Qr();return}let u=Yc(te);if(u){bl(u);return}As(te);return}if(h==="settings"){let u=Ko(nt,te);if(u)xl(u);return}if(h==="dashboard"&&Bo(N)){fn([],Ze);return}let p=rt[te];if(p&&(h==="dashboard"||h==="services"))ar(p)},[xl,Qr,fn,T,As,Jt,te,On,rt,ar,Ze,h,nt,N,Ts]);dA((p)=>{let u=(p.name??"").toLowerCase(),R=jx(p,t),b=Hx(p,t);if(R&&!b){if(h==="mcp"&&As(te))return;Os();return}if(b){let S=Date.now();if(Bx(S,ml.current)){ml.current=0,Qw();return}ml.current=S;let le="Ctrl+C again to quit";if(R)Os(le);else _(`Press ${le}`);return}if(p.ctrl&&(u==="="||u==="+"||u==="plus")){sr(Oc(k,1));return}if(p.ctrl&&(u==="-"||u==="_"||u==="minus")){sr(Oc(k,-1));return}if(p.ctrl&&u==="0"){sr(Zu().font_size);return}if(I==="confirm"){if(u==="escape"){et();return}if(ir==="quit"&&u==="d"){n(!0);return}if(u==="return")Zw();return}if(I==="log-details"||I==="scroll-text"){if(u==="escape"){et();return}let S=I==="log-details"?df.current:uf.current;if(u==="down"||u==="j"){We(S,t.scroll_speed);return}if(u==="up"||u==="k"){We(S,-t.scroll_speed);return}if(Fc(p)){We(S,Zi(c));return}if(Nc(p)){We(S,-Zi(c));return}return}if(I==="route-details"){if(u==="escape"||u==="return"){et();return}if(u==="down"||u==="j"){We(sl.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(sl.current,-t.scroll_speed);return}return}if(I==="plan"){if(u==="escape"||u==="return"&&!gf){et();return}if(u==="down"||u==="j"){We(al.current,t.scroll_speed);return}if(u==="up"||u==="k"){We(al.current,-t.scroll_speed);return}return}if(I==="help"){if(u==="escape"){et();return}if(u==="down"||u==="j"){We(ti.current,1);return}if(u==="up"||u==="k"){We(ti.current,-1);return}if(u==="pagedown"||Fc(p)){We(ti.current,pp);return}if(u==="pageup"||Nc(p)){We(ti.current,-pp);return}return}if(I==="themes"){if(u==="escape"){Jw(),et();return}if(u==="down"||u==="j"){oe((S)=>{let le=Math.min(S+1,yt.length-1),mn=yt[le];if(mn)d(mn);return le});return}if(u==="up"||u==="k"){oe((S)=>{let le=Math.max(0,S-1),mn=yt[le];if(mn)d(mn);return le});return}if(u==="return"){let S=yt[ct%yt.length];if(S)Rf(S)}return}if(I==="leader"){if(oi.current)clearTimeout(oi.current);z("none");let S=Sv(u),le=S?zi(S):void 0;if(le)gn(le,[]);return}if(I==="config-edit"){if(u==="escape"){Ss(""),et();return}if(p.ctrl&&u==="s"){zw();return}return}if(Lx(I)){if(u==="escape"){et();return}if(I==="slash"&&u==="down"){Ee((S)=>Math.min(Math.max(ai.length-1,0),S+1));return}if(I==="slash"&&u==="up"){Ee((S)=>Math.max(0,S-1));return}if(I==="slash"&&u==="tab"){if(p.shift){Ee((le)=>Math.max(0,le-1));return}let S=Hr(ai,Ue);if(S)Ie(`${S.name} `);return}if(I==="slash"&&u==="return"){kl();return}if(I==="palette"&&u==="down"){oe((S)=>Math.min(S+1,Math.max(zr.length-1,0)));return}if(I==="palette"&&u==="up"){oe((S)=>Math.max(0,S-1));return}if(I==="palette"&&u==="return"){let S=Hr(zr,ct);if(S)gn(S,[])}return}if(ms){if(u==="escape")nl(!1);return}if(Dx(p,t)){z("leader"),oi.current=setTimeout(()=>z("none"),v);return}if(Ox(p,t)){Ie(""),oe(0),z("palette");return}if(Mx(p,t)){Ie(""),Ee(0),z("slash");return}if($x(p,t)){z("help");return}if(Ix(p,t)||h==="logs"&&u==="f"&&!p.ctrl&&!p.meta){q("logs"),nl(!0);return}if(u==="escape"){if(Zo){bs(!1);return}if(h==="detail"){q("services");return}if(h==="setup")if(e)q("dashboard");else n(!0);return}if(u==="z"&&(h==="logs"||h==="dashboard")&&!p.ctrl&&!p.meta){q("logs"),bs((S)=>h==="logs"?!S:!0);return}let W=(h==="logs"||h==="dashboard")&&!ms;if(W&&(u==="left"||u==="["||h==="logs"&&u==="h")){Ft(Gu(si,zt,-1));return}if(W&&(u==="right"||u==="]"||h==="logs"&&u==="l")){Ft(Gu(si,zt,1));return}if(h==="logs"&&!ms&&u.length===1&&u>="1"&&u<="9"){let S=Ty(si,Ve,Number(u));if(S!==void 0)Ft(S);return}if(u==="tab"){q(p.shift?Ny(h):Fy(h));return}let Mn=ey(u);if(Mn){q(Mn);return}if((h==="dashboard"||h==="setup")&&u==="o"){q("profiles");return}if((h==="dashboard"||h==="services")&&(u==="*"||p.shift&&u==="8")){It([...rt]),_(`Selected ${rt.length} services`);return}if((h==="dashboard"||h==="services")&&(u==="-"||u==="_"||u==="minus")){It([]),_("Selection cleared");return}if((h==="dashboard"||h==="services")&&u==="n"){fn(kc(Se,rt[te]??""),Ze);return}if((h==="dashboard"||h==="services")&&u==="x"){Ds(kc(Se,rt[te]??""));return}if((h==="dashboard"||h==="services"||h==="detail")&&Fx(p)){pi(kc(Se,rt[te]??nr),Ze);return}if((h==="dashboard"||h==="services")&&u==="r"){ve(),_("Refreshed");return}if(h==="auth"&&u==="r"){Xr();return}if(h==="logs"&&u==="t"){let S=!zp;Ow(S),Ke({log_timestamps:S},S?"timestamps on":"timestamps off");return}if(h==="logs"&&u==="m"){let S=!Yp;Mw(S),Ke({log_metadata:S},S?"metadata on":"metadata off");return}if(u==="down"||u==="j"){if(h==="mcp"&&te===1)Qr();if(h==="config"){We(ei.current,t.scroll_speed);return}if(h==="detail"){We(ni.current,t.scroll_speed);return}if(h==="logs"){ci(te+1);return}if(h==="dashboard"&&ln>=0){Es(ln+1);return}pe((S)=>Math.min(Math.max(un-1,0),S+1));return}if(u==="up"||u==="k"){if(h==="mcp"&&te===1)Qr();if(h==="config"){We(ei.current,-t.scroll_speed);return}if(h==="detail"){We(ni.current,-t.scroll_speed);return}if(h==="logs"){ci(te-1);return}if(h==="dashboard"&&ln>=0){Es(ln-1);return}pe((S)=>Math.max(0,Math.min(S,Math.max(un-1,0))-1));return}if(Fc(p)){let S=Zi(c);if(h==="config"){We(ei.current,S);return}if(h==="detail"){We(ni.current,S);return}if(h==="logs"){ci(te+S);return}if(h==="dashboard"&&(bt||ln>=0)){Es(Math.max(0,ln)+S);return}pe((le)=>Math.min(Math.max(un-1,0),le+S));return}if(Nc(p)){let S=Zi(c);if(h==="config"){We(ei.current,-S);return}if(h==="detail"){We(ni.current,-S);return}if(h==="logs"){ci(te-S);return}if(h==="dashboard"&&(bt||ln>=0)){Es(Math.max(0,ln)-S);return}pe((le)=>Math.max(0,le-S));return}if(h==="proxy"&&u==="n"){e?.proxyStart().then(async()=>{_("Proxy started"),await ve()});return}if(h==="proxy"&&u==="x"){e?.proxyStop().then(async()=>{_("Proxy stopped"),await ve()});return}if(h==="detail"&&nr!==""){if(u==="n"){fn([nr],Ze);return}if(u==="x"){Ds([nr]);return}if(u==="o"){q("config");return}if(u==="l"){Ft(nr),q("logs");return}}if(h==="mcp"&&te===1&&(u==="left"||u==="h")){let S=Or(Qr()-1);Ps(S),Cf(S);return}if(h==="mcp"&&te===1&&(u==="right"||u==="l")){let S=Or(Qr()+1);Ps(S),Cf(S);return}if(h==="mcp"&&te===1&&(u==="backspace"||u==="delete")){ul((S)=>lv(S));return}if(h==="mcp"&&te===1&&u.length===1&&u>="0"&&u<="9"){ul((S)=>cv(S,u));return}if(h==="settings"&&(u==="left"||u==="h")){kf(-1);return}if(h==="settings"&&(u==="right"||u==="l")){kf(1);return}if(u==="space"){if(h==="profiles"){let mn=Object.keys(T?.profiles??{}).sort()[te];if(mn)tl(mn),_(`Profile ${mn}`);return}if(h==="mcp"){if(te===0){Ts();return}let le=Yc(te);if(le){bl(le);return}As(te);return}if(h==="logs")return;if(h==="settings"){if(Ko(nt,te)?.id==="mouse")li();return}let S=rt[te];if(S)yl(S);return}if(u==="return"){if(h==="setup"&&!e){if(!o){_(r||"Existing configuration is invalid \u2014 fix it and restart devctl.");return}Promise.resolve().then(() => (Jd(),Qm)).then(({createStarterConfig:S})=>{try{let le=S(process.cwd());_(`Wrote ${le}. Restart devctl or run the CLI wizard.`)}catch(le){_(O(le))}});return}if(h==="setup"&&e){fn([],Ze);return}eS();return}if(u==="q"){if(T?.shutdown.stop_services_on_exit===!1){n(!0);return}if(T?.shutdown.stop_services_on_exit===!0){n(!1);return}Ln("quit"),z("confirm");return}if(Yn(p,t,"services","s")&&I==="none"&&h!=="logs"){q("services");return}if(Yn(p,t,"logs","l")&&I==="none"&&h!=="detail"&&h!=="logs"&&h!=="settings"){q("logs");return}if(Yn(p,t,"auth","a")&&I==="none"){q("auth");return}if(Yn(p,t,"proxy","p")&&I==="none"&&h!=="logs"){q("proxy");return}if(Yn(p,t,"doctor","d")&&I==="none"&&h!=="doctor"){q("doctor");return}if(Yn(p,t,"config","c")&&I==="none"){q("config");return}if(Yn(p,t,"setup","u")&&I==="none"){q("setup");return}if(h==="config"&&u==="e"){gn(zi("/edit")??{name:"edit",aliases:[],desc:"",leader:"",group:"ui"},[]);return}if(h==="config"&&u==="v"){Sl();return}if(h==="doctor"&&u==="r"){el((S)=>S+1),_("Re-running doctor");return}if(h==="logs"&&u==="p"){tr((S)=>!S);return}if((h==="logs"||h==="dashboard")&&u==="g"){vl();return}if((h==="logs"||h==="dashboard")&&u==="w"){let S=Nu(Xo);tf(S),_(`Log ${Qi(S)}`);return}if((h==="logs"||h==="dashboard")&&u==="e"){on((S)=>!S);return}if((h==="logs"||h==="dashboard")&&u==="i"){ui(),_(sn?"Hiding internal auth/mcp/devctl/proxy logs":"Showing internal logs");return}if((h==="logs"||h==="dashboard")&&Nx(p))di()});let Tf=qy(ir,Ze,Ew),tS=new Set(Cs?.waves.flat()??[]),nS=Cs===void 0||mf==="stop"?"":Object.entries(N?.services??{}).find(([p,u])=>tS.has(p)&&u.state==="FAILED")?.[0]??"";return ie(np.Provider,{value:ds(k),children:ie("box",{flexDirection:"column",width:a,height:c,backgroundColor:B,overflow:"hidden",children:[Zo?null:ie(hA,{children:[ie(Cx,{palette:y,cfg:T,snap:N,google:cn,profile:Ze,reveal:Kr,width:a},void 0,!1,void 0,this),ie(_x,{palette:y,screen:h,width:a,onSelect:q},void 0,!1,void 0,this),ii?ie("box",{height:1,paddingLeft:1,backgroundColor:y.panel,overflow:"hidden",children:ie("text",{fg:y.error,wrapMode:"none",children:`\u26A0 configuration reload failed: ${ii}`},void 0,!1,void 0,this)},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),ie("box",{flexGrow:1,overflow:"hidden",children:[h==="dashboard"?ie(Ob,{palette:y,cfg:T,snap:N,logs:Ve,names:rt,selected:te,checked:Se,profile:Ze,google:cn,width:a,paused:lt,followTick:Vp,logService:zt,errorOnly:mt,showSystemLogs:sn,onOpen:ar,onSelectIndex:pe,selectedLog:ln,onToggle:yl,logSources:si,onFilterService:Ft,onToggleErrors:()=>on((p)=>!p),onToggleSystemLogs:ui,onClearLogs:di,onShowErrors:()=>{Ft(""),on(!0)},wrapMode:Xo,view:On,follow:!bt,onLeaveLatest:hl,onPickLog:(p)=>{let u=On[p];if(!u)return;ws(p),Qp(u),hl()},viewStart:Fe.start,viewTotal:ot.length,newer:Fe.newer,onJumpLatest:vl,facets:nf,leftover:Vw},void 0,!1,void 0,this):null,h==="services"?ie(Xb,{palette:y,cfg:T,names:rt,snap:N,selected:te,checked:Se,width:a,reveal:Kr,onOpen:ar,onSelectIndex:pe,onToggle:yl,resolvedEnv:xf,envStatus:bf,envError:wf,onSelectEnv:Ef},void 0,!1,void 0,this):null,h==="detail"?ie(Yb,{palette:y,cfg:T,snap:N,name:nr,reveal:Kr,width:a,envScrollRef:ni,resolvedEnv:xf,envStatus:bf,envError:wf,onSelectEnv:Ef},void 0,!1,void 0,this):null,h==="logs"?ie(Lb,{palette:y,logs:Ve,names:rt,logSources:si,service:zt,paused:lt,errorOnly:mt,showSystemLogs:sn,search:Pn,searchFocused:ms,followTick:Vp,width:a,onSearch:Aw,onService:Ft,onToggleErrors:()=>on((p)=>!p),onToggleSystemLogs:ui,onClearLogs:di,source:or,regex:Tn,services:rr,showTimestamps:zp,showMeta:Yp,view:On,wrapMode:Xo,selected:te,follow:!bt,newer:Fe.newer,viewStart:Fe.start,viewTotal:ot.length,onSelect:ci,fullscreen:Zo,onLeaveLatest:hl,onOpenExports:Yw,onJumpLatest:vl,facets:nf},void 0,!1,void 0,this):null,h==="auth"?ie(wb,{palette:y,cfg:T,google:cn,identity:N?.identity},void 0,!1,void 0,this):null,h==="credentials"?ie(kb,{palette:y,credentials:N?.credentials},void 0,!1,void 0,this):null,h==="proxy"?ie(qb,{palette:y,cfg:T,snap:N,width:a,onSelectRoute:(p)=>{Nw(p),z("route-details")}},void 0,!1,void 0,this):null,h==="mcp"?ie(pw,{palette:y,snap:N,port:Dn,portDraft:ks,selected:te,onPick:pe,onToggle:()=>{Ts()},onCopy:wl,onToggleTool:(p)=>{bl(p)}},void 0,!1,void 0,this):null,h==="doctor"?ie(Ib,{palette:y,report:Jt,loading:Qc,progress:_w,error:zo,selected:te,onPick:pe,onReload:()=>{el((p)=>p+1),_("Re-running doctor")}},void 0,!1,void 0,this):null,h==="stats"?ie(iw,{palette:y,cfg:T,snap:N,width:a,onRefresh:ve},void 0,!1,void 0,this):null,h==="config"?ie(Pb,{palette:y,cfg:T,width:a,scrollRef:ei},void 0,!1,void 0,this):null,h==="profiles"?ie(Hb,{palette:y,cfg:T,snap:N,profile:Ze,selected:te,onPick:pe},void 0,!1,void 0,this):null,h==="setup"?ie(aw,{palette:y,cfg:T,google:cn,bootError:r,bootErrorMissing:o,step:te},void 0,!1,void 0,this):null,h==="settings"?ie(nw,{palette:y,items:nt,selected:te,locked:C,width:a,onPick:pe,onActivate:xl},void 0,!1,void 0,this):null]},void 0,!0,void 0,this),I==="slash"?ie(gb,{palette:y,items:ai,query:ue,selected:Ue,onQuery:Ie,onSubmit:Pf},void 0,!1,void 0,this):null,I==="palette"?ie(ob,{palette:y,items:zr,selected:Math.min(ct,Math.max(zr.length-1,0)),termW:a,termH:c,onIndex:oe,onPick:Xw},void 0,!1,void 0,this):null,I==="themes"?ie(xb,{palette:y,themeName:l,selected:ct%yt.length,termW:a,termH:c,onIndex:oe,onPreview:d,onPick:Rf},void 0,!1,void 0,this):null,I==="help"?ie(Qx,{palette:y,termW:a,termH:c,copyKey:vf,scrollRef:ti},void 0,!1,void 0,this):null,I==="leader"?ie(tb,{palette:y,termW:a,termH:c},void 0,!1,void 0,this):null,I==="confirm"?ie(Kx,{palette:y,title:Tf.title,body:Tf.body,termW:a,termH:c},void 0,!1,void 0,this):null,I==="log-details"?ie(Vx,{palette:y,event:ys,termW:a,termH:c,scrollRef:df},void 0,!1,void 0,this):null,I==="route-details"?ie(lb,{palette:y,route:Fw,termW:a,termH:c,scrollRef:sl},void 0,!1,void 0,this):null,I==="scroll-text"&&Vr?ie(ub,{palette:y,title:Vr.title,body:Vr.body,termW:a,termH:c,scrollRef:uf},void 0,!1,void 0,this):null,I==="config-edit"&&T?ie(Gx,{palette:y,path:T.configPath,initialValue:cl,error:Gw,termW:a,termH:c,textareaRef:pf},void 0,!1,void 0,this):null,I==="plan"&&Cs?ie(ab,{palette:y,plan:Cs,snap:N,busy:gf,failed:nS,kind:mf,termW:a,termH:c,scrollRef:al,initiallyRunning:Uw,onDismiss:et},void 0,!1,void 0,this):null,I==="slash"||I==="plan"||I==="config-edit"||Zo||Yv(c)&&I==="none"?null:ie(Ex,{palette:y,overlay:I,query:ue,onQuery:Ie,onSubmit:Pf},void 0,!1,void 0,this),Zo?null:ie(Rx,{palette:y,screen:h,overlay:I,status:Ur,paused:lt,errorOnly:mt,width:a,copyKey:vf},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var fA=50,gA,mA=2000;var vw=D(()=>{st();Oi();Ri();Sr();Re();Ar();ze();Rr();Ja();Eu();Ku();Et();Ax();Pe();Wx();be();Ux();qx();Jx();Zx();nb();ib();cb();db();pb();mb();bb();Sb();Cb();Tb();Mb();Fb();wp();jb();Vb();Pp();Qb();rw();sw();cw();fw();Gi();at();Cn();Ye();Zt();gA=[]});var yw={};Ms(yw,{renderApp:()=>Np,runTui:()=>Fp,runTuiWithController:()=>xA,tuiConfigFor:()=>bA});import{createCliRenderer as vA}from"@opentui/core";import{createRoot as yA}from"@opentui/react";import{jsxDEV as wA}from"@opentui/react/jsx-dev-runtime";async function xA(e){let t=Qt(e.cfg.repoRoot,e.cfg.ui.keymap);await Np(e,t)}async function Fp(e){let t,n,r=!1;try{t=await pm("",e)}catch(i){n=O(i),r=Fs(i,cr)}let o=Qt(t?.cfg.repoRoot??process.cwd(),t?.cfg.ui.keymap);await Np(t,o,n,r)}async function Np(e,t=Qt(e?.cfg.repoRoot??process.cwd(),e?.cfg.ui.keymap),n,r=!1){$s();let o=Of(),i=await vA({exitOnCtrlC:!1,useMouse:t.mouse,enableMouseMovement:t.mouse,useKittyKeyboard:{}}),s=yA(i),a=null;try{a=(await i.getPalette({timeout:120,size:16})).defaultBackground}catch{}await new Promise((c)=>{let l=(d)=>{let f=()=>{s.unmount(),o(),i.destroy(),c(),process.exit(0)};if(!e){f();return}e.close({detach:d,shutdownSupervisor:!0}).finally(f)};s.render(wA(hw,{controller:e,tui:t,onQuit:l,bootError:n,bootErrorMissing:r,terminalBackground:a},void 0,!1,void 0,this))})}function bA(e){return Qt(e.repoRoot,e.ui.keymap)}var Hp=D(()=>{fd();Re();vw();Cl();Zt()});eo();Cl();st();fd();ze();Oi();Re();Sr();st();Ai();Rr();Jd();import{Command as SA}from"commander";import{setTimeout as Bp}from"timers/promises";import{stringify as kA}from"yaml";import{existsSync as ww,readFileSync as CA}from"fs";st();dd();Re();Sr();import{createServer as bE}from"net";import{existsSync as hu,unlinkSync as wE,watch as SE}from"fs";import{cpus as kE,loadavg as CE,platform as _E,uptime as EE}from"os";import{isAbsolute as vu,join as tc}from"path";ze();Rr();import{connect as y_}from"net";var x_=2000,b_=2000,w_=200,S_=300;function Zm(e){if(e.interval_seconds<=0)return b_;return e.interval_seconds*1000}async function eh(e,t,n,r,o,i=[]){let s=e.timeout_seconds>0?e.timeout_seconds*1000:x_,a=e.type.toLowerCase(),c=i.find((l)=>l.name.toLowerCase()===a);if(c)try{let l=await c.check(e,{pid:t,ports:n,workDir:r,env:o});return{status:l.status,message:l.message}}catch(l){return{status:Ce,message:l instanceof Error?l.message:String(l)}}if(a==="http")return k_(e.url,s);if(a==="tcp")return __(C_(e.address,n),s);if(a==="command")return E_(e.command.args,e.command.shell,r,o,s);if(a==="process"||a===""){if(t>0&&Tt(t))return{status:_t,message:"process running"};return{status:Ce,message:"process not running"}}return{status:Ce,message:`unknown health type ${e.type}`}}async function k_(e,t){let n=new AbortController,r=setTimeout(()=>n.abort(),t);try{let o=await fetch(e,{signal:n.signal});if(o.status>=w_&&o.status<S_)return{status:_t,message:String(o.status)};return{status:Ce,message:String(o.status)}}catch(o){return{status:Ce,message:o instanceof Error?o.message:String(o)}}finally{clearTimeout(r)}}function C_(e,t){if(e!=="")return e;if(t.http!==void 0)return`127.0.0.1:${t.http}`;let n=Object.values(t)[0];return n!==void 0?`127.0.0.1:${n}`:""}function __(e,t){return new Promise((n)=>{if(e===""){n({status:Ce,message:"no tcp address"});return}let r=e.lastIndexOf(":"),o=Number.parseInt(e.slice(r+1),10),i=e.slice(0,r).replace(/^\[|\]$/g,"");if(r<1||!Number.isFinite(o)){n({status:Ce,message:`invalid tcp address ${e}`});return}let s=y_({host:i,port:o},()=>{s.end(),n({status:_t,message:"connected"})});s.setTimeout(t),s.on("error",(a)=>{n({status:Ce,message:a.message})}),s.on("timeout",()=>{s.destroy(),n({status:Ce,message:"timeout"})})})}async function E_(e,t,n,r,o){if(e.length===0)return{status:Ce,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:n===""?void 0:n,env:r,stdout:"ignore",stderr:"ignore"})}catch(l){return{status:Ce,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:_t,message:"ok"};return{status:Ce,message:`exit ${c}`}}function th(e){if(e===Ce)return"WARN";if(e===_t)return"INFO";return"DEBUG"}import{readFileSync as R_}from"fs";import{freemem as P_,totalmem as T_}from"os";import{spawnSync as A_}from"child_process";var zd=1024,L_=2000,D_=/page size of (\d+) bytes/i,_o;function O_(e){let t=e.match(/^MemAvailable:\s+(\d+)/m);if(!t)return;let n=Number(t[1]);return Number.isFinite(n)&&n>=0?n:void 0}function M_(e){let t=e.match(D_),n=t?Number(t[1]):0;if(!Number.isFinite(n)||n<=0)return;let r=Ea(e,"free")+Ea(e,"inactive")+Ea(e,"speculative")+Ea(e,"purgeable");return Math.round(r*n/zd)}function Ea(e,t){let n=e.match(new RegExp(`Pages ${t}:\\s+(\\d+)`,"i")),r=n?Number(n[1]):0;return Number.isFinite(r)&&r>0?r:0}function $_(){if(process.platform==="linux")try{return O_(R_("/proc/meminfo","utf8"))}catch{return}if(process.platform==="darwin"){let e=Date.now();if(_o&&e-_o.at<L_)return _o.leftoverKB;let t=A_("vm_stat",{encoding:"utf8"});if(t.status!==0||!t.stdout)return _o?.leftoverKB;let n=M_(t.stdout);if(n===void 0)return _o?.leftoverKB;return _o={at:e,leftoverKB:n},n}return}function nh(){let e=Math.max(0,Math.round(T_()/zd)),t=Math.max(0,Math.round(P_()/zd)),n=Math.max(0,Math.min(e,$_()??t));return{totalKB:e,unusedKB:t,leftoverKB:n}}wr();Ar();Ri();Ar();import{pathToFileURL as h0}from"url";import{isAbsolute as v0,resolve as y0}from"path";st();Re();wr();import{createServer as bh,request as l0}from"http";import{randomBytes as hh}from"crypto";import{Readable as d0}from"stream";var Bi="x-devctl-request-id",u0="x-devctl-internal-token",vh=100,iu=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]),p0=new Set(["gzip","deflate","br"]);class su{cfg;tokens;logs;bus;detector;middleware;server;running=!1;addr="";upgradedSockets=new Set;recentRequests=[];constructor(e,t,n,r,o,i=[]){this.cfg=e,this.tokens=t,this.logs=n,this.bus=r,this.detector=o,this.middleware=i}address(){return this.addr||gr(this.cfg.listen)}isRunning(){return this.running}stats(){let e=this.recentRequests.reduce((t,n)=>t+(n.status>=400||n.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>vh)this.recentRequests.splice(0,this.recentRequests.length-vh)}start(){if(this.cfg.listen.host==="0.0.0.0")return Promise.reject(L($n,"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(L($n,"proxy.listen.port is required when the proxy is enabled"));let t=this.cfg.listen.port;return new Promise((n,r)=>{this.server=bh((o,i)=>{this.serve(o,i)}),this.server.on("upgrade",(o,i,s)=>{this.serveUpgrade(o,i,s)}),this.server.on("error",(o)=>r(fe($n,`unable to listen on ${e}:${t}`,o))),this.server.listen(t,e,()=>{this.running=!0,this.addr=`${e}:${t}`,this.bus?.publish(Le(Lm,"",{address:this.addr})),n()})})}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(Le(Dm,"",{})),t()})})}async serveUpgrade(e,t,n){let r=Date.now(),o=e.headers[Bi]?.toString()||hh(8).toString("hex"),i=e.method??"GET",s=e.url??"/",a=this.detector?this.detector.redactText(s):s,c=xh(this.cfg.routes,e);if(!c){t.end(`HTTP/1.1 404 Not Found\r
630
630
  Connection: close\r
631
631
  Content-Length: 0\r
632
632
  \r
633
- `),this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:"",identity:"",status:404,durationMs:Date.now()-r});return}let l=xr(c.auth),d=uo(l),f,g=!1,m=(v,S)=>{if(g)return;g=!0;let P=Date.now()-r;this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:c.name,identity:d,status:v,durationMs:P,error:S}),this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:v>=400||S?"ERROR":"INFO",message:`${i} ${s} route=${c.name} identity=${d} status=${v} duration=${P}ms upgrade=true${S?` error=${S}`:""}`,pid:0,request_id:o,identity:d}),this.bus?.publish(Me(Rd,c.name,{status:v,request_id:o,duration:P,identity:d}))},x=()=>{t.destroy(),f?.destroy()};try{let v={};for(let[C,y]of Object.entries(e.headers)){let B=C.toLowerCase();if(tu.has(B)&&B!=="connection"&&B!=="upgrade")continue;if(typeof y==="string")v[C]=y;else if(Array.isArray(y))v[C]=y.join(",")}let S=e.socket.remoteAddress??"",P=v.host??"",k=v["x-forwarded-for"];if(v["x-forwarded-for"]=k?`${k}, ${S}`:S,v["x-forwarded-host"]=P,v["x-forwarded-proto"]="http",delete v.host,v[Ni]=o,this.middleware.length===0)await La(c,v,this.tokens);for(let C of this.middleware)await C.apply({route:c,headers:v,tokens:this.tokens,req:e,method:i,path:s,upgrade:!0});let j=gh(c.upstream.url,s),V=Q_(j,{method:i,headers:v});V.on("upgrade",(C,y,B)=>{f=y,this.upgradedSockets.add(t),this.upgradedSockets.add(y);let h=()=>{this.upgradedSockets.delete(t),this.upgradedSockets.delete(y)};t.once("close",()=>{h(),y.destroy()}),y.once("close",()=>{h(),t.destroy()}),t.once("error",x),y.once("error",x);let q=`HTTP/${C.httpVersion} ${C.statusCode??101} ${C.statusMessage??"Switching Protocols"}\r
634
- `,M=C.rawHeaders.map((Y,ue)=>`${ue%2===0?Y+":":" "+Y+`\r
635
- `}`).join("");if(t.write(`${q}${M}\r
633
+ `),this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:"",identity:"",status:404,durationMs:Date.now()-r});return}let l=br(c.auth),d=po(l),f,g=!1,m=(v,w)=>{if(g)return;g=!0;let E=Date.now()-r;this.recordRequest({timestamp:new Date().toISOString(),requestId:o,method:i,path:a,route:c.name,identity:d,status:v,durationMs:E,error:w}),this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:v>=400||w?"ERROR":"INFO",message:`${i} ${s} route=${c.name} identity=${d} status=${v} duration=${E}ms upgrade=true${w?` error=${w}`:""}`,pid:0,request_id:o,identity:d}),this.bus?.publish(Le(Md,c.name,{status:v,request_id:o,duration:E,identity:d}))},x=()=>{t.destroy(),f?.destroy()};try{let v={};for(let[C,y]of Object.entries(e.headers)){let B=C.toLowerCase();if(iu.has(B)&&B!=="connection"&&B!=="upgrade")continue;if(typeof y==="string")v[C]=y;else if(Array.isArray(y))v[C]=y.join(",")}let w=e.socket.remoteAddress??"",E=v.host??"",k=v["x-forwarded-for"];if(v["x-forwarded-for"]=k?`${k}, ${w}`:w,v["x-forwarded-host"]=E,v["x-forwarded-proto"]="http",delete v.host,v[Bi]=o,this.middleware.length===0)await Ia(c,v,this.tokens);for(let C of this.middleware)await C.apply({route:c,headers:v,tokens:this.tokens,req:e,method:i,path:s,upgrade:!0});let j=yh(c.upstream.url,s),V=l0(j,{method:i,headers:v});V.on("upgrade",(C,y,B)=>{f=y,this.upgradedSockets.add(t),this.upgradedSockets.add(y);let h=()=>{this.upgradedSockets.delete(t),this.upgradedSockets.delete(y)};t.once("close",()=>{h(),y.destroy()}),y.once("close",()=>{h(),t.destroy()}),t.once("error",x),y.once("error",x);let q=`HTTP/${C.httpVersion} ${C.statusCode??101} ${C.statusMessage??"Switching Protocols"}\r
634
+ `,I=C.rawHeaders.map((z,ue)=>`${ue%2===0?z+":":" "+z+`\r
635
+ `}`).join("");if(t.write(`${q}${I}\r
636
636
  `),n.length>0)y.write(n);if(B.length>0)t.write(B);t.pipe(y).pipe(t),m(C.statusCode??101)}),V.on("response",(C)=>{C.resume();let y=C.statusCode??502;t.end(`HTTP/1.1 ${y} ${C.statusMessage??"Bad Gateway"}\r
637
637
  Connection: close\r
638
638
  Content-Length: 0\r
@@ -641,21 +641,21 @@ Content-Length: 0\r
641
641
  Connection: close\r
642
642
  Content-Length: 0\r
643
643
  \r
644
- `)}),t.once("error",()=>V.destroy()),V.end()}catch(v){let S=v instanceof Error?v.message:"proxy upgrade error";m(502,S),t.end(`HTTP/1.1 502 Bad Gateway\r
644
+ `)}),t.once("error",()=>V.destroy()),V.end()}catch(v){let w=v instanceof Error?v.message:"proxy upgrade error";m(502,w),t.end(`HTTP/1.1 502 Bad Gateway\r
645
645
  Connection: close\r
646
646
  Content-Length: 0\r
647
647
  \r
648
- `)}}async serve(e,t){let n=Date.now(),r=e.headers[Ni]?.toString()||ph(8).toString("hex");t.setHeader(Ni,r);let o=e.method??"GET",i=e.url??"/",s=this.detector?this.detector.redactText(i):i,a=mh(this.cfg.routes,e);if(!a){Ro(t,404,"no matching proxy route"),this.recordRequest({timestamp:new Date().toISOString(),requestId:r,method:o,path:s,route:"",identity:"",status:404,durationMs:Date.now()-n});return}let c=xr(a.auth),l=uo(c),d=0,f;try{let g={};for(let[y,B]of Object.entries(e.headers)){if(tu.has(y.toLowerCase()))continue;if(typeof B==="string")g[y]=B;else if(Array.isArray(B))g[y]=B.join(",")}let m=e.socket.remoteAddress??"",x=g.host??"",v=g["x-forwarded-for"];if(g["x-forwarded-for"]=v?`${v}, ${m}`:m,g["x-forwarded-host"]=x,g["x-forwarded-proto"]="http",delete g.host,g["accept-encoding"]="gzip, deflate, br",g[Ni]=r,this.middleware.length===0)await La(a,g,this.tokens);for(let y of this.middleware)await y.apply({route:a,headers:g,tokens:this.tokens});let S=gh(a.upstream.url,i),P=o!=="GET"&&o!=="HEAD"?e:void 0,k=await fetch(S,{method:o,headers:g,body:P,redirect:"manual",duplex:P?"half":void 0});t.statusCode=k.status,d=k.status;let j=(k.headers.get("content-encoding")??"").split(",").map((y)=>y.trim().toLowerCase()).filter((y)=>y!==""),V=j.length>0&&j.every((y)=>t0.has(y));k.headers.forEach((y,B)=>{let h=B.toLowerCase();if(tu.has(h))return;if(V&&(h==="content-encoding"||h==="content-length"))return;t.setHeader(B,this.detector?this.detector.redactText(y):y)}),await n0(k,t);let C=Date.now()-n;this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:k.status>=400?"WARN":"INFO",message:`${o} ${i} route=${a.name} identity=${l} status=${k.status} duration=${C}ms`,pid:0,request_id:r,identity:l}),this.bus?.publish(Me(Rd,a.name,{status:k.status,request_id:r,duration:C,identity:l}))}catch(g){let m=g instanceof Error?g.message:"proxy error";f=m,d=502,this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:"ERROR",message:`${o} ${i} route=${a.name} identity=${l} error=${m}`,pid:0,request_id:r,identity:l}),Ro(t,502,"proxy error")}finally{this.recordRequest({timestamp:new Date().toISOString(),requestId:r,method:o,path:s,route:a.name,identity:l,status:d,durationMs:Date.now()-n,error:f})}}}async function La(e,t,n){let r=e.auth.type.toLowerCase();if(r===""||r==="none")return;if(!n)throw L($n,"token manager unavailable");let o=xr(e.auth),i=await n.get(uo(o),e.auth.audience,[]);t.authorization=`Bearer ${i.accessToken}`}async function n0(e,t){if(!e.body){t.end();return}let n=Z_.fromWeb(e.body);await new Promise((r,o)=>{n.on("error",o),t.on("error",o),t.on("finish",r),n.pipe(t)})}function gh(e,t){let n=new URL(e),r=new URL(t||"/",n),o=new URL(n.href);if(o.pathname=r0(r.pathname),o.search=r.search,o.hash="",o.origin!==n.origin)throw L($n,"refusing to proxy to a different origin");return o}function r0(e){return(e.startsWith("/")?e:`/${e}`).replace(/^\/+/,"/")}function Ro(e,t,n){e.statusCode=t,e.setHeader("content-type","text/plain; charset=utf-8"),e.setHeader("x-content-type-options","nosniff"),e.end(n)}function mh(e,t){let n=(t.headers.host??"").split(":")[0]??"",r=t.url??"/";return e.find((o)=>{let i=o.match.host===""||o.match.host===n,s=o.match.path===""||r.startsWith(o.match.path);return i&&s})}class ru{host;port;secret;tokens;server;constructor(e,t,n,r){this.host=e;this.port=t;this.secret=n;this.tokens=r}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(L($n,"refusing to bind token endpoint to 0.0.0.0"));return new Promise((t,n)=>{this.server=hh((r,o)=>{this.serve(r,o)}),this.server.on("error",(r)=>n(fe($n,"token endpoint listen failed",r))),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(!o0(e.socket.remoteAddress)){Ro(t,403,"forbidden");return}if((e.headers[e0]??"")!==this.secret){Ro(t,401,"unauthorized");return}if(e.url?.startsWith("/token")!==!0){Ro(t,404,"not found");return}let n=new URL(e.url,"http://127.0.0.1"),r=n.searchParams.get("identity")??"user",o=n.searchParams.get("audience")??"";try{let i=await this.tokens.get(r,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 o0(e){if(!e)return!0;return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}Ai();br();var vh=1;class yh{tokenProviders=[];identityProviders=[];pluginIdentityProviders=[];environmentSources=[];healthChecks=[];logParsers=[];proxyMiddleware=[];loadErrors=[];registerBuiltins(){this.tokenProviders.push(...Cr()),this.identityProviders.push(cd(),ld()),this.logParsers.push(Xd()),this.proxyMiddleware.push(l0())}register(e){c0(e),Lr(this.tokenProviders,e.tokenProviders),Lr(this.identityProviders,e.identityProviders),Lr(this.pluginIdentityProviders,e.identityProviders),Lr(this.environmentSources,e.environmentSources),Lr(this.healthChecks,e.healthChecks),Lr(this.logParsers,e.logParsers),Lr(this.proxyMiddleware,e.proxyMiddleware)}}async function xh(e,t=process.cwd()){let n=new yh;n.registerBuiltins();for(let r of e){if(r.trim()==="")continue;try{let o=r.startsWith("file:")?r:s0(r)?r:a0(t,r),s=await import(o.startsWith("file:")?o:i0(o).href);if(s.sdkVersion!==vh)throw Error(`plugin SDK version ${String(s.sdkVersion??"missing")} is incompatible; expected ${vh}`);n.register(s)}catch(o){n.loadErrors.push({path:r,message:o instanceof Error?o.message:String(o)})}}return n}function c0(e){if(!e||typeof e!=="object")throw Error("plugin module must export an object");Po("tokenProviders",e.tokenProviders,["fetch"]),Po("identityProviders",e.identityProviders,["accepts","resolve"]),Po("environmentSources",e.environmentSources,["load"]),Po("healthChecks",e.healthChecks,["check"]),Po("logParsers",e.logParsers,["parse"]),Po("proxyMiddleware",e.proxyMiddleware,["apply"])}function Po(e,t,n){if(t===void 0)return;if(!Array.isArray(t))throw Error(`${e} must be an array`);for(let[r,o]of t.entries()){if(!o||typeof o!=="object"||typeof o.name!=="string"||o.name==="")throw Error(`${e}[${r}] must have a name`);for(let i of n)if(typeof o[i]!=="function")throw Error(`${e}[${r}].${i} must be a function`)}}function l0(){return{name:"identity_inject",apply:async(e)=>{await La(e.route,e.headers,e.tokens)}}}function Lr(e,t){if(!t)return;e.push(...t)}Pe();var{spawn:Oh}=globalThis.Bun;ze();var{spawn:d0}=globalThis.Bun;async function bh(e,t){if(e<=0)return;try{process.kill(-e,t);return}catch{try{process.kill(e,t)}catch{return}}}async function wh(e){if(!Pt(e))return;let t=await Hi(["ps","-p",String(e),"-o","command="]),n=Date.now(),r=u0(await Hi(["ps","-p",String(e),"-o","etime="])),o=await p0(e);return{pid:e,command:t.trim(),cwd:o,startTime:r===void 0?void 0:new Date(n-r).toISOString()}}function u0(e){let t=e.trim();if(t==="")return;let n=t.indexOf("-"),r=n>=0?t.slice(0,n):"0",i=(n>=0?t.slice(n+1):t).split(":");if(i.length!==2&&i.length!==3)return;let s=Number(r),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 p0(e){let n=(await Hi(["lsof","-a","-p",String(e),"-d","cwd","-Fn"])).split(`
649
- `).find((i)=>i.startsWith("n"));if(n&&n.length>1)return n.slice(1).trim();let r=await Hi(["pwdx",String(e)]),o=r.indexOf(":");if(o>=0)return r.slice(o+1).trim();return""}async function Hi(e){try{let t=d0({cmd:e,stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,n}catch{return""}}async function Sh(e){let t=new Map;if(e.length===0)return t;let n=await Hi(["ps","-o","pid=,pcpu=,rss=","-p",e.join(",")]);for(let r of n.split(`
650
- `)){let o=r.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 kh(e,t){if(e.length===0||t==="")return!1;let n=e.join(" ");if(t.includes(n))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)}ze();var{spawn:Ch}=globalThis.Bun;var f0=1024;async function _h(e,t){if(e<=0)return;try{await Ch({cmd:["taskkill","/PID",String(e),"/T","/F"],stdout:"ignore",stderr:"ignore"}).exited}catch{return}}async function Rh(e){let t=g0(Pl(e),e);if(t)return t;if(!Pt(e))return;let n=await ou(["powershell","-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${e}" | Select-Object CommandLine,ExecutablePath,CreationDate | ConvertTo-Json -Compress`]),r=h0(n);if(r&&r.command!=="")return{pid:e,command:r.command,cwd:r.cwd,startTime:r.startTime};let o=await ou(["powershell","-NoProfile","-Command",`Get-Process -Id ${e} -ErrorAction SilentlyContinue | Select-Object Path,StartTime | ConvertTo-Json -Compress`]),i=m0(o);if(!i&&!r)return;return{pid:e,command:r?.command||i?.command||"",cwd:r?.cwd||i?.cwd||"",startTime:r?.startTime||i?.startTime}}function g0(e,t){let n=String(t);for(let r of e.split(/\r?\n/)){if(!r.includes(n))continue;let i=r.split(",").map((s)=>s.replace(/^"|"$/g,"").trim())[0]??"";if(i===""||i.toLowerCase().includes("info:"))continue;return{pid:t,command:i,cwd:""}}return}function m0(e){let t=e.trim();if(t==="")return;try{let n=JSON.parse(t),r=(n.Path||"").trim();if(r==="")return;return{command:r,cwd:Oa(r),startTime:n.StartTime}}catch{let n=Da(t,"Path");if(n==="")return;return{command:n,cwd:Oa(n)}}}function h0(e){let t=e.trim();if(t==="")return;try{let n=JSON.parse(t),r=(n.CommandLine||n.ExecutablePath||"").trim(),o=(n.ExecutablePath||"").trim(),i=Oa(o);return{command:r,cwd:i,startTime:n.CreationDate||void 0}}catch{return{command:Da(t,"CommandLine")||Da(t,"ExecutablePath"),cwd:Oa(Da(t,"ExecutablePath"))}}}async function Ph(e){let t=new Map;if(e.length===0)return t;let n=e.filter((o)=>o>0).join(",");if(n==="")return t;let r=await ou(["powershell","-NoProfile","-Command",`${n}.Split(',') | ForEach-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue } | Select-Object Id,CPU,WorkingSet64 | ConvertTo-Json -Compress`]);return v0(r)}function v0(e){let t=new Map,n=e.trim();if(n==="")return t;try{let r=JSON.parse(n),o=Array.isArray(r)?r:[r];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)/f0;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 Oa(e){if(e==="")return"";let t=e.replace(/\//g,"\\"),n=t.lastIndexOf("\\");return n>0?t.slice(0,n):""}function Da(e,t){let n=`${t}=`,r=e.split(/\r?\n/).find((o)=>o.startsWith(n));return r?r.slice(n.length).trim():""}async function ou(e){try{let t=Ch({cmd:e,stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,n}catch{return""}}ze();Pe();var{spawn:iu}=globalThis.Bun;async function Th(e){await b0(e.runtime,e.containerName);let t=y0(e),n=await Eo(e.runtime,t,e.env);if(n.code!==0||n.stdout.trim()==="")throw L(Ke,`failed to start ${e.containerName}: ${n.stderr.trim()||"container runtime returned no id"}`);let r=n.stdout.trim().split(/\s+/)[0]??"";return Dh(e.runtime,e.containerName,r,e.onLine,e.onExit)}function y0(e){let t=["run","--detach","--name",e.containerName,"--label","devctl.managed=true"];for(let[n,r]of Object.entries(e.ports)){let o=e.targetPorts[n]??r;t.push("--publish",`127.0.0.1:${r}:${o}`)}for(let n of Object.keys(e.env).sort())t.push("--env",n);for(let n of e.volumes)t.push("--volume",n);return t.push(e.image,...e.command),t}var x0=new Set(["PATH","HOME","HOSTNAME","PWD","OLDPWD","SHLVL","_","TMPDIR"]);function Ah(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!x0.has(t)))}async function Lh(e,t,n,r){let o=await Eo(e,["inspect","--format","{{.Id}} {{.State.Running}}",t],process.env);if(o.code!==0)return;let[i,s]=o.stdout.trim().split(/\s+/);if(!i||s!=="true")return;return Dh(e,t,i,n,r)}function Dh(e,t,n,r,o){let i=!0,s=iu({cmd:[e,"logs","--follow",n],stdout:"pipe",stderr:"pipe",stdin:"ignore"});Eh(s.stdout,"stdout",r),Eh(s.stderr,"stderr",r);let a=iu({cmd:[e,"wait",n],stdout:"pipe",stderr:"pipe",stdin:"ignore"}),c=Promise.all([new Response(a.stdout).text(),a.exited]).then(async([l,d])=>{i=!1,s.kill();let f=Number.parseInt(l.trim(),10),g=Number.isFinite(f)?f:d??1,m=g===0?void 0:Error(`container exited with code ${g}`);return await Eo(e,["rm","--force",n],process.env),o?.(g,m),{code:g,err:m}});return{id:n,runtime:e,containerName:t,done:c,running:()=>i,stop:async(l)=>{let d=Math.max(1,Math.ceil(l/1000));await Eo(e,["stop","--time",String(d),n],process.env),await c}}}async function b0(e,t){let n=await Eo(e,["inspect","--format","{{.State.Running}}",t],process.env);if(n.code===0&&n.stdout.trim()==="false")await Eo(e,["rm","--force",t],process.env)}async function Eo(e,t,n){try{let r=iu({cmd:[e,...t],env:{...process.env,...n},stdout:"pipe",stderr:"pipe",stdin:"ignore"}),[o,i,s]=await Promise.all([new Response(r.stdout).text(),new Response(r.stderr).text(),r.exited]);return{code:s??1,stdout:o,stderr:i}}catch(r){throw fe(Ke,`unable to run ${e}`,r)}}async function Eh(e,t,n){if(!e||typeof e==="number"||!n)return;let r=e.getReader(),o=new TextDecoder,i="";for(;;){let s=await r.read();if(s.done)break;i+=o.decode(s.value,{stream:!0});let a=i.split(`
651
- `);i=a.pop()??"";for(let c of a)n(t,c.replace(/\r$/,""))}if(i!=="")n(t,i)}var w0=1e4,S0=2000,k0=500;class su{running=new Map;async start(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;if(this.running.delete(e.name),e.args.length===0)throw L(Ke,"empty command");let n=e.shell?Ih(e.args):e.args,r;try{r=Oh({cmd:n,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 fe(Ke,`failed to start ${e.name}`,i)}let o={name:e.name,pid:r.pid??0,startTime:new Date,workDir:e.workDir,args:[...e.args],proc:r,done:Promise.resolve({code:0})};return Ma(r.stdout,"stdout",e.onLine),Ma(r.stderr,"stderr",e.onLine),o.done=r.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}async runOnce(e){if(e.args.length===0)throw L(Ke,"empty command");let t;try{t=Oh({cmd:e.shell?Ih(e.args):e.args,cwd:e.workDir||void 0,env:e.env,stdout:"pipe",stderr:"pipe",stdin:"ignore"})}catch(a){throw fe(Ke,`failed to run ${e.name}`,a)}let n="",r="",o=(a,c)=>{if(a==="stdout")n+=`${c}
648
+ `)}}async serve(e,t){let n=Date.now(),r=e.headers[Bi]?.toString()||hh(8).toString("hex");t.setHeader(Bi,r);let o=e.method??"GET",i=e.url??"/",s=this.detector?this.detector.redactText(i):i,a=xh(this.cfg.routes,e);if(!a){Ro(t,404,"no matching proxy route"),this.recordRequest({timestamp:new Date().toISOString(),requestId:r,method:o,path:s,route:"",identity:"",status:404,durationMs:Date.now()-n});return}let c=br(a.auth),l=po(c),d=0,f;try{let g={};for(let[y,B]of Object.entries(e.headers)){if(iu.has(y.toLowerCase()))continue;if(typeof B==="string")g[y]=B;else if(Array.isArray(B))g[y]=B.join(",")}let m=e.socket.remoteAddress??"",x=g.host??"",v=g["x-forwarded-for"];if(g["x-forwarded-for"]=v?`${v}, ${m}`:m,g["x-forwarded-host"]=x,g["x-forwarded-proto"]="http",delete g.host,g["accept-encoding"]="gzip, deflate, br",g[Bi]=r,this.middleware.length===0)await Ia(a,g,this.tokens);for(let y of this.middleware)await y.apply({route:a,headers:g,tokens:this.tokens});let w=yh(a.upstream.url,i),E=o!=="GET"&&o!=="HEAD"?e:void 0,k=await fetch(w,{method:o,headers:g,body:E,redirect:"manual",duplex:E?"half":void 0});t.statusCode=k.status,d=k.status;let j=(k.headers.get("content-encoding")??"").split(",").map((y)=>y.trim().toLowerCase()).filter((y)=>y!==""),V=j.length>0&&j.every((y)=>p0.has(y));k.headers.forEach((y,B)=>{let h=B.toLowerCase();if(iu.has(h))return;if(V&&(h==="content-encoding"||h==="content-length"))return;t.setHeader(B,this.detector?this.detector.redactText(y):y)}),await f0(k,t);let C=Date.now()-n;this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:k.status>=400?"WARN":"INFO",message:`${o} ${i} route=${a.name} identity=${l} status=${k.status} duration=${C}ms`,pid:0,request_id:r,identity:l}),this.bus?.publish(Le(Md,a.name,{status:k.status,request_id:r,duration:C,identity:l}))}catch(g){let m=g instanceof Error?g.message:"proxy error";f=m,d=502,this.logs?.append({timestamp:new Date().toISOString(),service:"proxy",source:"proxy",level:"ERROR",message:`${o} ${i} route=${a.name} identity=${l} error=${m}`,pid:0,request_id:r,identity:l}),Ro(t,502,"proxy error")}finally{this.recordRequest({timestamp:new Date().toISOString(),requestId:r,method:o,path:s,route:a.name,identity:l,status:d,durationMs:Date.now()-n,error:f})}}}async function Ia(e,t,n){let r=e.auth.type.toLowerCase();if(r===""||r==="none")return;if(!n)throw L($n,"token manager unavailable");let o=br(e.auth),i=await n.get(po(o),e.auth.audience,[]);t.authorization=`Bearer ${i.accessToken}`}async function f0(e,t){if(!e.body){t.end();return}let n=d0.fromWeb(e.body);await new Promise((r,o)=>{n.on("error",o),t.on("error",o),t.on("finish",r),n.pipe(t)})}function yh(e,t){let n=new URL(e),r=new URL(t||"/",n),o=new URL(n.href);if(o.pathname=g0(r.pathname),o.search=r.search,o.hash="",o.origin!==n.origin)throw L($n,"refusing to proxy to a different origin");return o}function g0(e){return(e.startsWith("/")?e:`/${e}`).replace(/^\/+/,"/")}function Ro(e,t,n){e.statusCode=t,e.setHeader("content-type","text/plain; charset=utf-8"),e.setHeader("x-content-type-options","nosniff"),e.end(n)}function xh(e,t){let n=(t.headers.host??"").split(":")[0]??"",r=t.url??"/";return e.find((o)=>{let i=o.match.host===""||o.match.host===n,s=o.match.path===""||r.startsWith(o.match.path);return i&&s})}class au{host;port;secret;tokens;server;constructor(e,t,n,r){this.host=e;this.port=t;this.secret=n;this.tokens=r}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(L($n,"refusing to bind token endpoint to 0.0.0.0"));return new Promise((t,n)=>{this.server=bh((r,o)=>{this.serve(r,o)}),this.server.on("error",(r)=>n(fe($n,"token endpoint listen failed",r))),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(!m0(e.socket.remoteAddress)){Ro(t,403,"forbidden");return}if((e.headers[u0]??"")!==this.secret){Ro(t,401,"unauthorized");return}if(e.url?.startsWith("/token")!==!0){Ro(t,404,"not found");return}let n=new URL(e.url,"http://127.0.0.1"),r=n.searchParams.get("identity")??"user",o=n.searchParams.get("audience")??"";try{let i=await this.tokens.get(r,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 m0(e){if(!e)return!0;return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}Ai();wr();var wh=1;class Sh{tokenProviders=[];identityProviders=[];pluginIdentityProviders=[];environmentSources=[];healthChecks=[];logParsers=[];proxyMiddleware=[];loadErrors=[];registerBuiltins(){this.tokenProviders.push(..._r()),this.identityProviders.push(md(),hd()),this.logParsers.push(eu()),this.proxyMiddleware.push(b0())}register(e){x0(e),Lr(this.tokenProviders,e.tokenProviders),Lr(this.identityProviders,e.identityProviders),Lr(this.pluginIdentityProviders,e.identityProviders),Lr(this.environmentSources,e.environmentSources),Lr(this.healthChecks,e.healthChecks),Lr(this.logParsers,e.logParsers),Lr(this.proxyMiddleware,e.proxyMiddleware)}}async function kh(e,t=process.cwd()){let n=new Sh;n.registerBuiltins();for(let r of e){if(r.trim()==="")continue;try{let o=r.startsWith("file:")?r:v0(r)?r:y0(t,r),s=await import(o.startsWith("file:")?o:h0(o).href);if(s.sdkVersion!==wh)throw Error(`plugin SDK version ${String(s.sdkVersion??"missing")} is incompatible; expected ${wh}`);n.register(s)}catch(o){n.loadErrors.push({path:r,message:o instanceof Error?o.message:String(o)})}}return n}function x0(e){if(!e||typeof e!=="object")throw Error("plugin module must export an object");Po("tokenProviders",e.tokenProviders,["fetch"]),Po("identityProviders",e.identityProviders,["accepts","resolve"]),Po("environmentSources",e.environmentSources,["load"]),Po("healthChecks",e.healthChecks,["check"]),Po("logParsers",e.logParsers,["parse"]),Po("proxyMiddleware",e.proxyMiddleware,["apply"])}function Po(e,t,n){if(t===void 0)return;if(!Array.isArray(t))throw Error(`${e} must be an array`);for(let[r,o]of t.entries()){if(!o||typeof o!=="object"||typeof o.name!=="string"||o.name==="")throw Error(`${e}[${r}] must have a name`);for(let i of n)if(typeof o[i]!=="function")throw Error(`${e}[${r}].${i} must be a function`)}}function b0(){return{name:"identity_inject",apply:async(e)=>{await Ia(e.route,e.headers,e.tokens)}}}function Lr(e,t){if(!t)return;e.push(...t)}Re();var{spawn:Fh}=globalThis.Bun;ze();var{spawn:w0}=globalThis.Bun;async function Ch(e,t){if(e<=0)return;try{process.kill(-e,t);return}catch{try{process.kill(e,t)}catch{return}}}async function _h(e){if(!Tt(e))return;let t=await Wi(["ps","-p",String(e),"-o","command="]),n=Date.now(),r=S0(await Wi(["ps","-p",String(e),"-o","etime="])),o=await k0(e);return{pid:e,command:t.trim(),cwd:o,startTime:r===void 0?void 0:new Date(n-r).toISOString()}}function S0(e){let t=e.trim();if(t==="")return;let n=t.indexOf("-"),r=n>=0?t.slice(0,n):"0",i=(n>=0?t.slice(n+1):t).split(":");if(i.length!==2&&i.length!==3)return;let s=Number(r),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 k0(e){let n=(await Wi(["lsof","-a","-p",String(e),"-d","cwd","-Fn"])).split(`
649
+ `).find((i)=>i.startsWith("n"));if(n&&n.length>1)return n.slice(1).trim();let r=await Wi(["pwdx",String(e)]),o=r.indexOf(":");if(o>=0)return r.slice(o+1).trim();return""}async function Wi(e){try{let t=w0({cmd:e,stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,n}catch{return""}}async function Eh(e){let t=new Map;if(e.length===0)return t;let n=await Wi(["ps","-o","pid=,pcpu=,rss=","-p",e.join(",")]);for(let r of n.split(`
650
+ `)){let o=r.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 Rh(e,t){if(e.length===0||t==="")return!1;let n=e.join(" ");if(t.includes(n))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)}ze();var{spawn:Ph}=globalThis.Bun;var C0=1024;async function Th(e,t){if(e<=0)return;try{await Ph({cmd:["taskkill","/PID",String(e),"/T","/F"],stdout:"ignore",stderr:"ignore"}).exited}catch{return}}async function Ah(e){let t=_0(Ml(e),e);if(t)return t;if(!Tt(e))return;let n=await cu(["powershell","-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${e}" | Select-Object CommandLine,ExecutablePath,CreationDate | ConvertTo-Json -Compress`]),r=R0(n);if(r&&r.command!=="")return{pid:e,command:r.command,cwd:r.cwd,startTime:r.startTime};let o=await cu(["powershell","-NoProfile","-Command",`Get-Process -Id ${e} -ErrorAction SilentlyContinue | Select-Object Path,StartTime | ConvertTo-Json -Compress`]),i=E0(o);if(!i&&!r)return;return{pid:e,command:r?.command||i?.command||"",cwd:r?.cwd||i?.cwd||"",startTime:r?.startTime||i?.startTime}}function _0(e,t){let n=String(t);for(let r of e.split(/\r?\n/)){if(!r.includes(n))continue;let i=r.split(",").map((s)=>s.replace(/^"|"$/g,"").trim())[0]??"";if(i===""||i.toLowerCase().includes("info:"))continue;return{pid:t,command:i,cwd:""}}return}function E0(e){let t=e.trim();if(t==="")return;try{let n=JSON.parse(t),r=(n.Path||"").trim();if(r==="")return;return{command:r,cwd:Na(r),startTime:n.StartTime}}catch{let n=Fa(t,"Path");if(n==="")return;return{command:n,cwd:Na(n)}}}function R0(e){let t=e.trim();if(t==="")return;try{let n=JSON.parse(t),r=(n.CommandLine||n.ExecutablePath||"").trim(),o=(n.ExecutablePath||"").trim(),i=Na(o);return{command:r,cwd:i,startTime:n.CreationDate||void 0}}catch{return{command:Fa(t,"CommandLine")||Fa(t,"ExecutablePath"),cwd:Na(Fa(t,"ExecutablePath"))}}}async function Lh(e){let t=new Map;if(e.length===0)return t;let n=e.filter((o)=>o>0).join(",");if(n==="")return t;let r=await cu(["powershell","-NoProfile","-Command",`${n}.Split(',') | ForEach-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue } | Select-Object Id,CPU,WorkingSet64 | ConvertTo-Json -Compress`]);return P0(r)}function P0(e){let t=new Map,n=e.trim();if(n==="")return t;try{let r=JSON.parse(n),o=Array.isArray(r)?r:[r];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)/C0;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 Na(e){if(e==="")return"";let t=e.replace(/\//g,"\\"),n=t.lastIndexOf("\\");return n>0?t.slice(0,n):""}function Fa(e,t){let n=`${t}=`,r=e.split(/\r?\n/).find((o)=>o.startsWith(n));return r?r.slice(n.length).trim():""}async function cu(e){try{let t=Ph({cmd:e,stdout:"pipe",stderr:"ignore"}),n=t.stdout?await new Response(t.stdout).text():"";return await t.exited,n}catch{return""}}ze();Re();var{spawn:lu}=globalThis.Bun;async function Oh(e){await L0(e.runtime,e.containerName);let t=T0(e),n=await To(e.runtime,t,e.env);if(n.code!==0||n.stdout.trim()==="")throw L(Ne,`failed to start ${e.containerName}: ${n.stderr.trim()||"container runtime returned no id"}`);let r=n.stdout.trim().split(/\s+/)[0]??"";return Ih(e.runtime,e.containerName,r,e.onLine,e.onExit)}function T0(e){let t=["run","--detach","--name",e.containerName,"--label","devctl.managed=true"];for(let[n,r]of Object.entries(e.ports)){let o=e.targetPorts[n]??r;t.push("--publish",`127.0.0.1:${r}:${o}`)}for(let n of Object.keys(e.env).sort())t.push("--env",n);for(let n of e.volumes)t.push("--volume",n);return t.push(e.image,...e.command),t}var A0=new Set(["PATH","HOME","HOSTNAME","PWD","OLDPWD","SHLVL","_","TMPDIR"]);function Mh(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!A0.has(t)))}async function $h(e,t,n,r){let o=await To(e,["inspect","--format","{{.Id}} {{.State.Running}}",t],process.env);if(o.code!==0)return;let[i,s]=o.stdout.trim().split(/\s+/);if(!i||s!=="true")return;return Ih(e,t,i,n,r)}function Ih(e,t,n,r,o){let i=!0,s=lu({cmd:[e,"logs","--follow",n],stdout:"pipe",stderr:"pipe",stdin:"ignore"});Dh(s.stdout,"stdout",r),Dh(s.stderr,"stderr",r);let a=lu({cmd:[e,"wait",n],stdout:"pipe",stderr:"pipe",stdin:"ignore"}),c=Promise.all([new Response(a.stdout).text(),a.exited]).then(async([l,d])=>{i=!1,s.kill();let f=Number.parseInt(l.trim(),10),g=Number.isFinite(f)?f:d??1,m=g===0?void 0:Error(`container exited with code ${g}`);return await To(e,["rm","--force",n],process.env),o?.(g,m),{code:g,err:m}});return{id:n,runtime:e,containerName:t,done:c,running:()=>i,stop:async(l)=>{let d=Math.max(1,Math.ceil(l/1000));await To(e,["stop","--time",String(d),n],process.env),await c}}}async function L0(e,t){let n=await To(e,["inspect","--format","{{.State.Running}}",t],process.env);if(n.code===0&&n.stdout.trim()==="false")await To(e,["rm","--force",t],process.env)}async function To(e,t,n){try{let r=lu({cmd:[e,...t],env:{...process.env,...n},stdout:"pipe",stderr:"pipe",stdin:"ignore"}),[o,i,s]=await Promise.all([new Response(r.stdout).text(),new Response(r.stderr).text(),r.exited]);return{code:s??1,stdout:o,stderr:i}}catch(r){throw fe(Ne,`unable to run ${e}`,r)}}async function Dh(e,t,n){if(!e||typeof e==="number"||!n)return;let r=e.getReader(),o=new TextDecoder,i="";for(;;){let s=await r.read();if(s.done)break;i+=o.decode(s.value,{stream:!0});let a=i.split(`
651
+ `);i=a.pop()??"";for(let c of a)n(t,c.replace(/\r$/,""))}if(i!=="")n(t,i)}var D0=1e4,O0=2000,M0=500;class du{running=new Map;async start(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;if(this.running.delete(e.name),e.args.length===0)throw L(Ne,"empty command");let n=e.shell?jh(e.args):e.args,r;try{r=Fh({cmd:n,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 fe(Ne,`failed to start ${e.name}`,i)}let o={name:e.name,pid:r.pid??0,startTime:new Date,workDir:e.workDir,args:[...e.args],proc:r,done:Promise.resolve({code:0})};return Ha(r.stdout,"stdout",e.onLine),Ha(r.stderr,"stderr",e.onLine),o.done=r.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}async runOnce(e){if(e.args.length===0)throw L(Ne,"empty command");let t;try{t=Fh({cmd:e.shell?jh(e.args):e.args,cwd:e.workDir||void 0,env:e.env,stdout:"pipe",stderr:"pipe",stdin:"ignore"})}catch(a){throw fe(Ne,`failed to run ${e.name}`,a)}let n="",r="",o=(a,c)=>{if(a==="stdout")n+=`${c}
652
652
  `;else r+=`${c}
653
- `;e.onLine?.(a,c)},i=[Ma(t.stdout,"stdout",o),Ma(t.stderr,"stderr",o)],s=await t.exited;return await Promise.all(i),{code:typeof s==="number"?s:0,stdout:n,stderr:r}}async startContainer(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;let n=await Th(e),r={name:e.name,pid:0,startTime:new Date,workDir:e.workDir,args:[...e.command],done:n.done,container:n};return n.done.finally(()=>{if(this.running.get(e.name)===r)this.running.delete(e.name)}),this.running.set(e.name,r),r}async adoptContainer(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;let n=await Lh(e.runtime,e.containerName,e.onLine,e.onExit);if(!n)return;let r={name:e.name,pid:0,startTime:new Date,workDir:e.workDir,args:[],done:n.done,container:n};return n.done.finally(()=>{if(this.running.get(e.name)===r)this.running.delete(e.name)}),this.running.set(e.name,r),r}adopt(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;if(!Pt(e.pid))throw L(Ke,`cannot adopt ${e.name}: pid ${e.pid} is not running`);let n={name:e.name,pid:e.pid,startTime:e.startTime,workDir:e.workDir,args:[...e.args],done:Promise.resolve({code:0})};return n.done=_0(e.pid).then((r)=>{if(this.running.get(e.name)===n)this.running.delete(e.name);if(e.onExit)e.onExit(r,r===0?void 0:Error(`exited with code ${r}`));return{code:r}}),this.running.set(e.name,n),n}async stop(e,t){let n=this.running.get(e);if(!n)return;let r=t>0?t:w0;if(n.container){await n.container.stop(r),this.running.delete(e);return}if(await Mh(n.pid,"SIGTERM"),!await Nh(n.done,r)){if(await Mh(n.pid,"SIGKILL"),!await Nh(n.done,S0))throw L(Ke,`process ${e} did not exit after SIGKILL`)}this.running.delete(e)}get(e){return this.running.get(e)}all(){return[...this.running.values()]}}function Dr(e){if(e.container)return e.container.running();if(e.proc)return e.proc.exitCode===null&&!e.proc.killed;return Pt(e.pid)}async function Mh(e,t){if(process.platform==="win32"){await _h(e,t);return}await bh(e,t)}async function $a(e){if(process.platform==="win32")return Rh(e);return wh(e)}async function Hh(e){if(process.platform==="win32")return Ph(e);return Sh(e)}var C0=2000;function Ia(e,t){if(e.workDir!==""&&t.cwd!==""&&Fh(e.workDir)!==Fh(t.cwd))return!1;if(!kh(e.args,t.command))return!1;let n=$h(e.startTime),r=$h(t.startTime);if(n!==void 0&&r!==void 0)return Math.abs(n-r)<=C0;return!0}function $h(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 Ih(e){if(process.platform==="win32")return["cmd.exe","/c",e.join(" ")];return["/bin/sh","-c",e.join(" ")]}function Fh(e){return e.replace(/\\/g,"/").replace(/\/+$/,"")}async function _0(e){while(Pt(e))await R0(k0);return 0}async function Ma(e,t,n){if(!e||typeof e==="number"||!n)return;let r=e.getReader(),o=new TextDecoder,i="";for(;;){let{value:s,done:a}=await r.read();if(a){if(i!=="")n(t,i);return}i+=o.decode(s,{stream:!0});let c=i.split(`
654
- `);i=c.pop()??"";for(let l of c)n(t,l.replace(/\r$/,""))}}async function Nh(e,t){return Promise.race([e.then(()=>!0),new Promise((n)=>{setTimeout(()=>n(!1),t)})])}function R0(e){return new Promise((t)=>{setTimeout(t,e)})}Pe();ji();import{createServer as F0}from"http";var N0="2025-03-26",tv="2.0",Xh=-32700,Qh=-32600,H0=-32601,Zh=-32602,j0=-32603,B0=new Set(["127.0.0.1","localhost","::1"]);function W0(e){return B0.has(e)}class lu{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(!W0(this.opts.host))return Promise.reject(L(Je,`refusing to bind MCP to ${this.opts.host}`));return new Promise((e,t)=>{this.server=F0((n,r)=>{this.serve(n,r)}),this.server.on("error",(n)=>t(fe(Je,`unable to listen on ${this.opts.host}:${this.opts.port}`,n))),this.server.listen(this.opts.port,this.opts.host,()=>{let n=this.server?.address();this.boundPort=typeof n==="object"&&n?n.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((n)=>{e.close(()=>{if(this.running=!1,this.addr="",this.boundPort=0,this.server=void 0,t)this.emit("INFO","stopped");n()})})}async serve(e,t){if(e.method==="OPTIONS"){t.writeHead(204,Gi()),t.end();return}if(!this.authorized(e)){this.emit("WARN",`rejected unauthorized request from ${ev(e)}`),Ao(t,401,{error:"unauthorized"});return}if(U0(e)!=="/mcp"){Ao(t,404,{error:"not found"});return}if(e.method==="GET"||e.method==="DELETE"){t.writeHead(405,{Allow:"POST, OPTIONS",...Gi()}),t.end();return}if(e.method!=="POST"){t.writeHead(405,{Allow:"POST, OPTIONS",...Gi()}),t.end();return}let r;try{r=await K0(e)}catch(a){Ao(t,400,Bi(null,Xh,a instanceof Error?a.message:"invalid body"));return}let o;try{o=JSON.parse(r)}catch{Ao(t,400,Bi(null,Xh,"parse error"));return}let i=ev(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)}Ao(t,200,a);return}let s=await this.dispatch(o,i);if(s===void 0){t.writeHead(202,Gi()),t.end();return}Ao(t,200,s)}authorized(e){if(this.opts.token==="")return!0;return(e.headers.authorization??"")===`Bearer ${this.opts.token}`}async dispatch(e,t){if(!Wa(e))return Bi(null,Qh,"invalid request");let n=e,r=n.id??null,o=n.id===void 0;if(n.method===void 0||n.method==="")return o?void 0:Bi(r,Qh,"missing method");try{let i=await this.handleMethod(n.method,Wa(n.params)?n.params:{},t);if(o)return;return{jsonrpc:tv,id:r,result:i}}catch(i){if(o)return;let s=i instanceof Wi?i.code:j0,a=i instanceof Error?i.message:"internal error";return this.emit("WARN",`rpc error method=${n.method} addr=${t}: ${a}`),Bi(r,s,a)}}async handleMethod(e,t,n){switch(e){case"initialize":{let r=G0(t);return this.emit("INFO",`client connected addr=${n}${r?` (${r})`:""}`),{protocolVersion:N0,capabilities:{tools:{},resources:{}},serverInfo:{name:"devctl",version:pt}}}case"notifications/initialized":case"ping":return{};case"tools/list":return{tools:Gh(this.disabled()).map((r)=>({name:r.name,description:r.description,inputSchema:r.inputSchema}))};case"tools/call":return this.callTool(t);case"resources/list":return{resources:au.map((r)=>({uri:r,name:r.replace("devctl://",""),mimeType:"application/json"}))};case"resources/read":return this.readResource(t);default:throw new Wi(H0,`method not found: ${e}`)}}async callTool(e){let t=typeof e.name==="string"?e.name:"";if(t==="")throw new Wi(Zh,"tool name is required");if(ja(t)&&!Kn(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 n=Wa(e.arguments)?e.arguments:{},r=Date.now();try{let o=await Jh(this.opts.hostApi,t,n);return this.emit("INFO",`tool call name=${t} duration=${Date.now()-r}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()-r}ms: ${i}`),{content:[{type:"text",text:i}],isError:!0}}}async readResource(e){let t=typeof e.uri==="string"?e.uri:"";if(!zh(t))throw new Wi(Zh,`unknown resource ${t}`);let n=await Yh(this.opts.hostApi,t);return this.emit("INFO",`resource read uri=${t}`),{contents:[{uri:t,mimeType:"application/json",text:JSON.stringify(n,null,2)}]}}}function G0(e){let t=e.clientInfo;if(!Wa(t))return"";let n=typeof t.name==="string"?t.name:"",r=typeof t.version==="string"?t.version:"";if(n==="")return"";return r===""?n:`${n} ${r}`}function ev(e){return e.socket.remoteAddress??"unknown"}class Wi extends Error{code;constructor(e,t){super(t);this.code=e}}function Gi(){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 Ao(e,t,n){let r=JSON.stringify(n);e.writeHead(t,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),...Gi()}),e.end(r)}function Bi(e,t,n){return{jsonrpc:tv,id:e,error:{code:t,message:n}}}function U0(e){let t=e.url??"/",n=t.indexOf("?");return n>=0?t.slice(0,n):t}function K0(e){return new Promise((t,n)=>{let r=[];e.on("data",(o)=>{r.push(o)}),e.on("end",()=>{t(Buffer.concat(r).toString("utf8"))}),e.on("error",n)})}function Wa(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}ji();Ga();Zt();Oi();To();Pr();ze();Ai();var hR=4000,vR=100,uv=30000,pv=3,yR=2,xR=2000,bR=200,wR=3,SR=10,kR=3000;class gu{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=fv();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=_l(),this.internalTok=El(),this.mcpToken=jf(e.repoRoot),this.bus=new Pd(2048),this.detectGoogleFn=t?.detectGoogle??Lt,this.inspectProcessFn=t?.inspectProcess??$a,this.processAliveFn=t?.processAlive??Pt,this.acquireLockFn=t?.acquireLock??Hf,this.socketExistsFn=t?.socketExists??pu,this.unlinkSocketFn=t?.unlinkSocket??dR,this.detector=new qt(e.secrets.extra_markers,e.secrets.extra_patterns),this.logs=new Ea(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 su,this.tokens=t?.tokens??new bo(e.auth.refresh_threshold_seconds*1000,Cr(),this.bus),this.bus.subscribe((n)=>{let r=n.payload??{},o=n.type===xo?`token refreshed identity=${String(r.identity??"")}`:n.type===kr?`token refresh failed identity=${String(r.identity??"")} audience=${String(r.audience??"")}: ${String(r.error??"")}`:`authentication changed user=${String(r.user??"")}`;if(this.logs.append({timestamp:new Date().toISOString(),service:"auth",source:"auth",level:n.type===kr?"WARN":"INFO",message:o,pid:0}),n.type===xo||n.type===kr)this.syncCredentialEntries()},[xo,kr,_d]),this.setupMode=!pu(e.configPath),this.identityCache=fv(e);for(let n of Object.keys(e.services))this.runtimes.set(n,xa(n))}async run(){let e=Is(this.cfg.repoRoot);this.lock=this.acquireLockFn(this.cfg.repoRoot,e),this.removeStaleSocket(e),this.registry=await xh(this.cfg.plugins.map((n)=>n.path),this.cfg.repoRoot);for(let n of this.registry.loadErrors)this.log("devctl","ERROR",`plugin ${n.path} skipped: ${n.message}`);this.applyRegistry(),this.checkPluginHealthTypes(),this.checkPluginIdentityTypes(),this.checkPluginEnvironmentSources(),await this.recoverSession(),this.watchConfig(),this.persistState(),this.log("devctl","INFO",`supervisor started session=${this.sessionID}`),this.refreshIdentity(),this.resourceTimer=setInterval(()=>void this.pollResourceUsage(),kR);let t=Qt(this.cfg.repoRoot);if(this.setMcpDisabledTools(t.mcp_disabled_tools??[]),t.mcp_enabled)await this.startMcp(t.mcp_port).catch((n)=>this.log("devctl","ERROR",F(n)));this.removeStaleSocket(e),await new Promise((n,r)=>{this.server=lR((o)=>{this.handleConn(o)}),this.server.on("error",r),this.server.listen(e,()=>n())})}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="",n=2000,r=[],o=!1,i=()=>{while(r.length>0){let c=r[0],l=e.write(`${JSON.stringify(c)}
655
- `);if(r.shift(),!l){o=!0,e.once("drain",()=>{o=!1,i()});return}}},s=(c)=>{if(c.id===void 0&&c.event!==void 0&&r.length>=n){let d=r.findIndex((f)=>f.id===void 0&&f.event!==void 0);if(d>=0)r.splice(d,1)}if(r.push(c),!o)i()},a=this.bus.subscribe((c)=>s({event:c}));e.on("error",(c)=>{this.log("devctl","WARN",`client connection error: ${F(c)}`)}),e.on("data",(c)=>{t+=c.toString("utf8");let l=t.split(`
656
- `);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 n;try{n=JSON.parse(e)}catch{t({error:"invalid json"});return}try{let r=await this.dispatch(n.method??"",n.params);t({id:n.id,result:r})}catch(r){let o=Of(r);t({id:n.id,error:o.error,kind:o.kind,hint:o.hint,service:o.service})}}async dispatch(e,t){let n=gv(t)?t:{};switch(e){case"ping":return{session:this.sessionID,version:pt,protocol:ki};case"start":return this.start({services:Ir(n.services),profile:typeof n.profile==="string"?n.profile:"",detach:n.detach===!0,client_env:Xa(n.client_env)});case"stop":return await this.stop(Ir(n.services)),null;case"restart":return await this.restart(Ir(n.services),{cascade:n.cascade===!0,clientEnv:Xa(n.client_env)}),null;case"run_task":return this.runTask(typeof n.name==="string"?n.name:"",Xa(n.client_env)??{});case"exec":return this.execService(typeof n.service==="string"?n.service:"",Ir(n.command),Xa(n.client_env)??{},n.print_env===!0);case"auth_refresh":return await this.refreshIdentity({probeServiceAccounts:!0}),this.snapshot().identity;case"status":return this.snapshot();case"logs":return this.queryLogs({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.until:"",export:typeof n.export==="string"?n.export:""});case"logs_page":return this.queryLogsPage({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.until:"",cursor:typeof n.cursor==="string"?n.cursor:void 0,direction:n.direction==="forward"?"forward":"backward",limit:typeof n.limit==="number"?n.limit:void 0});case"logs_stats":return this.queryLogsFacets({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.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 n.port==="number"?n.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(n.disabled)?n.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 r=typeof n.stop_services==="boolean"?n.stop_services:Bs(this.cfg.shutdown);return setTimeout(()=>{this.shutdown(r)},50),null;default:throw L(Je,`unknown method ${e}`)}}isDetached(){return this.detached}async start(e){if(e.detach===!0)this.detached=!0;let t=wa(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 n=$i(this.cfg,t.services,t.profile),r=await this.detectGoogleFn(this.cfg.google.project_id);n.blockers=dm(this.cfg,n.waves.flat(),r.adcAvailable);let o=new Set(n.blockers.map((s)=>s.name));for(let s of n.blockers)await this.fail(s.name,L(Ke,s.message));if(this.cfg.proxy.enabled&&!this.proxySuppressed)await this.startProxy().catch((s)=>this.log("devctl","ERROR",F(s)));let i=[];for(let s of n.waves.flat()){if(o.has(s)||await this.claimIfAlreadyUp(s))continue;i.push(s)}if(i.length>0)try{let s=await xm(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,f])=>`${d}=${f}`).join(", ");this.log(a,"INFO",`assigned ports: ${l||"none"}`)}}catch(s){if(s instanceof Oe&&s.service!=="")await this.fail(s.service,s);else this.log("devctl","ERROR",F(s));throw s}for(let s of n.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,e.auto!==!0))),l=!1;for(let d of c)if(d.status==="rejected")l=!0,this.log("devctl","ERROR",F(d.reason));if(l)throw L(Ke,"one or more services failed to start")}try{await this.awaitWaveHealth(s,n.waves.flat())}catch(c){throw this.log("devctl","ERROR",F(c)),c}}return this.persistState(),n}async runTask(e,t){let n=this.cfg.tasks[e];if(!n)throw L(Je,`unknown task ${e}`);if(n.dependencies.length>0)await this.start({services:n.dependencies,client_env:t});let r={...Nn(),command:n.command,shell:n.shell,working_dir:n.working_dir,dependencies:n.dependencies,environment:n.environment},o=await ea(this.cfg.repoRoot,{service:`task:${e}`,profile:this.profile,serviceCfg:r,profileEnv:this.profileEnv,assignedPorts:{},runtime:ta(`task:${e}`,"127.0.0.1",{},"",this.cfg.project.name),cfg:this.cfg,clientEnv:t,fetchSecret:Zs(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources}),i=n.working_dir&&!fu(n.working_dir)?Ya(this.cfg.repoRoot,n.working_dir):n.working_dir,s=await this.runTransient(`task:${e}`,n.command,n.shell,i,Si(o));return{task:e,...s}}async execService(e,t,n,r=!1){let o=this.cfg.services[e];if(!o)throw L(pi,`unknown service ${e}`);let i=this.serviceProfile.get(e)??this.profile,s=this.serviceProfileEnv.get(e)??this.profileEnv,{env:a,workDir:c}=await this.resolveServiceExecution(e,o,i,s,n,!o.container);if(r)return{service:e,code:0,stdout:"",stderr:"",environment:a};if(t.length===0)throw L(Je,"exec command is required");let l=await this.runTransient(`${e}:exec`,{args:t,shell:!1},!1,c,a);return{service:e,...l}}async resolveServiceExecution(e,t,n,r,o,i=!0){let s=this.ports.get(e)??Object.fromEntries(t.ports.filter((f)=>!f.auto).map((f)=>[f.name,f.value])),a=this.proxy?.isRunning()?`http://${this.proxy.address()}`:this.cfg.proxy.enabled?`http://${fr(this.cfg.proxy.listen)}`:"",c=ta(e,"127.0.0.1",s,a,this.cfg.project.name);if(!t.container){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 ea(this.cfg.repoRoot,{service:e,profile:n,serviceCfg:t,profileEnv:r,assignedPorts:s,runtime:c,cfg:this.cfg,fetchSecret:Zs(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources,clientEnv:o,includeProcess:i}),d=t.working_dir&&!fu(t.working_dir)?Ya(this.cfg.repoRoot,t.working_dir):t.working_dir;return{env:Si(l),workDir:d}}async runTransient(e,t,n,r,o){if(io(t))return{code:0,stdout:"",stderr:""};this.log(e,"INFO",`running ${t.args.join(" ")}`);let i=await this.procs.runOnce({name:e,args:[...t.args],shell:n||t.shell,workDir:r,env:o,graceMs:gi(this.cfg.shutdown)*1000,onLine:(s,a)=>this.logs.append({timestamp:new Date().toISOString(),service:e,source:s,stream:s,level:"",message:a,pid:0})});if(i.code!==0)throw L(Ke,`${e} exited with code ${i.code}`);return i}serviceIsActive(e){let t=this.procs.get(e);if(t&&Dr(t))return!0;let n=this.runtimes.get(e);if(!n)return!1;if(n.health===Ct||n.state===_r)return!0;return n.state===Ld||n.state===Ht}serviceWorkDir(e){if(e.working_dir!==""&&!fu(e.working_dir))return Ya(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 aa(t);if(s)this.ports.set(e,s)}return!0}if(!t)return!1;if(t.container){let s=this.bumpGeneration(e),a=t.container.runtime==="podman"?"podman":"docker",c=this.serviceWorkDir(t),l=await this.procs.adoptContainer({name:e,runtime:a,containerName:`devctl-${vn(this.cfg.repoRoot)}-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,workDir:c,onLine:(g,m)=>this.logs.append({timestamp:new Date().toISOString(),service:e,source:g,stream:g,level:"",message:m,pid:0}),onExit:(g,m)=>this.onExit(e,s,g,m)});if(!l)return!1;let d=this.ports.get(e)??Object.fromEntries(t.ports.filter((g)=>!g.auto).map((g)=>[g.name,g.value]));this.ports.set(e,d),this.processMeta.set(e,{command:[...t.command.args],cwd:c,startTime:l.startTime}),this.setState(e,Ht,Dt,0,"");let f=await this.resolveAdoptedHealthEnv(e,t,d);return this.startHealth(e,t,0,d,c,f,s),this.persistState(),this.log(e,"INFO",`claimed running ${a} container ${l.container?.id??""}`),!0}let n=await aa(t);if(!n)return!1;let r=Object.values(n)[0],i=(r===void 0?void 0:await vo(r))?.pid??0;if(i>0&&i!==process.pid){let s=ur(this.cfg.repoRoot)?.processes.find((l)=>l.name===e&&l.pid===i);if(!s)return this.log(e,"WARN",`port ${r} is held by pid ${i} with no persisted record for ${e}; not adopting`),!1;let a=await $a(i);if(a!==void 0&&a.command!==""&&Ia({args:[...t.command.args],workDir:this.serviceWorkDir(t),startTime:new Date(s.startTime)},a)){this.ports.set(e,n);let l=this.attachProcess(e,i,[...t.command.args],this.serviceWorkDir(t),new Date(s.startTime))??this.bumpGeneration(e);this.setState(e,Ht,Dt,i,""),this.log(e,"INFO",`already listening on ${Object.values(n).join(", ")}; not starting again`);let d=this.serviceWorkDir(t),f=await this.resolveAdoptedHealthEnv(e,t,n);return this.startHealth(e,t,i,n,d,f,l),!0}this.log(e,"WARN",`port ${r} is in use by an unrelated process (pid ${i}); not adopting`)}return!1}async startOne(e,t,n,r=!1){if(this.serviceIsActive(e))return;let o=this.cfg.services[e];if(!o)throw L(Je,`unknown service ${e}`);this.setState(e,Ld,Dt,0,"");let i=this.bumpGeneration(e),s=oa(o.identity);if(s.kind!=="none")try{if(s=await um(o.identity,()=>mm(this.cfg.google.project_id),this.registry?.identityProviders),s.kind==="service_account")await this.tokens.get(uo(s),"",[]),this.serviceAccountStatus.set(s.serviceAccount,"available")}catch(m){if(s.kind==="service_account")this.serviceAccountStatus.set(s.serviceAccount,"unavailable");if(PR(o)||s.kind==="service_account"||s.kind!=="user"&&s.kind!=="none")throw await this.fail(e,m),m;this.log(e,"WARN","cloud identity unavailable; starting service locally")}let a=this.ports.get(e)??{},{env:c,workDir:l}=await this.resolveServiceExecution(e,o,t,n,this.clientEnv.get(e),!o.container);if(r)try{await this.runTransient(`${e}:pre_start`,o.hooks.pre_start,o.shell,l,c)}catch(m){throw await this.fail(e,m),m}let d=(m,x)=>{this.logs.append({timestamp:new Date().toISOString(),service:e,source:m,stream:m,level:"",message:x,pid:g.pid})},f=(m,x)=>this.onExit(e,i,m,x),g=o.container?await this.procs.startContainer({name:e,runtime:o.container.runtime==="podman"?"podman":"docker",containerName:`devctl-${vn(this.cfg.repoRoot)}-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,image:o.container.image,command:[...o.command.args],env:Ah({...c,...o.container.env}),ports:a,targetPorts:o.container.ports,volumes:o.container.volumes,workDir:l,onLine:d,onExit:f}):await this.procs.start({name:e,args:[...o.command.args],shell:o.shell||o.command.shell,workDir:l,env:c,graceMs:gi(this.cfg.shutdown)*1000,captureStdout:qf(o),captureStderr:Vf(o),onLine:d,onExit:f});if(this.processMeta.set(e,{command:[...o.command.args],cwd:l,startTime:g.startTime}),this.setState(e,Ht,Dt,g.pid,""),this.bus.publish(Me(Cm,e,{pid:g.pid})),r)try{await this.runTransient(`${e}:post_start`,o.hooks.post_start,o.shell,l,c)}catch(m){throw await this.fail(e,m),m}if(this.startHealth(e,o,g.pid,a,l,c,i),this.persistState(),o.startup.wait_for_healthy){let m=o.startup.timeout_seconds>0?o.startup.timeout_seconds*1000:uv;try{await this.waitHealthy(e,m)}catch(x){throw await this.fail(e,x),x}}}async resolveAdoptedHealthEnv(e,t,n){let r="";if(this.proxy?.isRunning())r=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)r=`http://${fr(this.cfg.proxy.listen)}`;let o=ta(e,"127.0.0.1",n,r,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 ea(this.cfg.repoRoot,{service:e,profile:this.serviceProfile.get(e)??this.profile,serviceCfg:t,profileEnv:this.serviceProfileEnv.get(e)??this.profileEnv,assignedPorts:n,runtime:o,cfg:this.cfg,fetchSecret:Zs(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources});return Si(i)}catch(i){return this.log(e,"WARN",`could not fully reconstruct environment for adopted service's health check (${F(i)}); using a baseline environment`),Si(o)}}async awaitWaveHealth(e,t){for(let n of e){let r=this.cfg.services[n],o=t.some((s)=>(this.cfg.services[s]?.dependencies??[]).some((a)=>wt(a)===n&&Fn(a)==="service_healthy"));if(!r||r.health.type===""||!o)continue;let i=r.startup.timeout_seconds>0?r.startup.timeout_seconds*1000:uv;try{await this.waitHealthy(n,i)}catch(s){throw await this.fail(n,s),s}}}async waitHealthy(e,t){let n=Date.now()+t;while(Date.now()<n){let r=this.runtimes.get(e);if(r?.health===Ct)return;if(r?.state===Rr)throw L(xl,`service ${e} failed while waiting for healthy`);await ER(vR)}throw L(xl,`service ${e} did not become healthy in time`)}onExit(e,t,n,r){if(!this.isCurrentGeneration(e,t))return;let o=this.runtimes.get(e);if(o?.state===Rr)return;if(o&&(o.state===Dd||o.state===So)){this.setState(e,So,Dt,0,""),this.bus.publish(Me(Cd,e,{code:n}));return}let i=this.cfg.services[e],s=i?i.restart.policy||(i.restart.enabled?"on_failure":"never"):"never",a=r?.message??`exited with code ${n}`,c=s==="always"||s==="on_failure"&&n!==0,l=this.restarts.get(e)??0,d=i&&i.restart.max_retries>0?i.restart.max_retries:pv;if(c&&i&&l<d){this.setState(e,Mi,Dt,0,a),this.bumpRestartCount(e,l+1),this.persistState(),this.armRestart(e,i,t,l,()=>{let f=this.serviceProfile.get(e)??this.profile,g=this.serviceProfileEnv.get(e)??this.profileEnv;this.startOne(e,f,g,!1).catch((m)=>this.log(e,"ERROR",F(m)))});return}this.fail(e,L("process_start",a))}startHealth(e,t,n,r,o,i,s){let a=this.healthTimers.get(e);if(a)clearInterval(a);if(t.health.type===""){this.setHealth(e,Ct,"no health check");return}let c=Ym(t.health)||xR,l=Date.parse(this.runtimes.get(e)?.startTime??"")||Date.now(),d=()=>{(t.container&&t.health.type.toLowerCase()==="process"?Promise.resolve(this.procs.get(e)&&Dr(this.procs.get(e))?{status:Ct,message:"container running"}:{status:Ce,message:"container not running"}):Xm(t.health,n,r,o,i,this.registry?.healthChecks)).catch((g)=>({status:Ce,message:F(g)})).then((g)=>{if(!this.isCurrentGeneration(e,s))return;if(g.status===Ce&&Date.now()-l<t.health.start_period_seconds*1000){this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:"INFO",message:`health check still in start period: ${g.message}`,pid:n});return}this.setHealth(e,g.status,g.message),this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:Qm(g.status),message:`health ${g.status} ${g.message}`,pid:n}),this.maybeRestartUnhealthy(e,t,g.status,s)})};d(),this.healthTimers.set(e,setInterval(d,c))}async stop(e){let t=e;if(t.length===0)t=[...this.runtimes.entries()].filter(([,i])=>i.state!==So).map(([i])=>i);if(t.length===0)return;let n=t.filter((i)=>!this.cfg.services[i]&&this.runtimes.has(i)),r=t.filter((i)=>!this.cfg.services[i]&&!this.runtimes.has(i));if(r.length>0)throw L(pi,`unknown service "${r[0]}"`);let o=t.filter((i)=>this.cfg.services[i]!==void 0);if(o.length>0)await this.runStopPlan(Ii(this.cfg,o),{resetRestartCounts:!0});if(n.length>0){await this.runStopPlan({profile:this.profile,steps:[],waves:n.map((i)=>[i])},{resetRestartCounts:!0});for(let i of n)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 n of Object.keys(t))if(!e[n]&&!this.runtimes.has(n))this.runtimes.set(n,xa(n));for(let n of Object.keys(e)){if(t[n])continue;if(this.serviceIsActive(n)){let r=this.runtimes.get(n);if(r)r.orphaned=!0;this.log(n,"WARN","removed from configuration while still running; now orphaned \u2014 stop it explicitly to clean it up");continue}this.forgetService(n)}}async restart(e,t){let n=t?.cascade===!0,r=n?Md(this.cfg,e):e,o=n?Ii(this.cfg,e):qm(this.cfg,e),i=t?.auto!==!0;await this.runStopPlan(o,{resetRestartCounts:i});let s=r.map((a)=>this.serviceProfile.get(a)).find((a)=>a!==void 0)??this.profile;await this.start({services:r,profile:s,client_env:t?.clientEnv,auto:t?.auto})}async runStopPlan(e,t){for(let r of e.waves.flat())if(this.clearRestartTimer(r),this.bumpGeneration(r),t?.resetRestartCounts)this.resetRestartCount(r);let n=gi(this.cfg.shutdown)*1000;for(let r of e.waves)await Promise.all(r.map(async(o)=>{this.setState(o,Dd,Dt,0,"");let i=this.healthTimers.get(o);if(i)clearInterval(i),this.healthTimers.delete(o);await this.procs.stop(o,n),await this.releasePorts(o),this.setState(o,So,Dt,0,""),this.bus.publish(Me(Cd,o,{}))}));this.persistState()}async startProxy(){if(this.proxy?.isRunning())return;if(this.proxy=new nu(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 ru(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 cv(this.cfg.repoRoot,e);this.mcp=new lu({host:"127.0.0.1",port:t,token:this.mcpToken,hostApi:this.asMcpHost(),onEvent:(n,r)=>this.log("mcp",n,`mcp ${r}`),disabledTools:()=>this.mcpDisabledTools}),await this.mcp.start(),this.persistState()}setMcpDisabledTools(e){let t=e.filter((r)=>ja(r)),n=this.mcpDisabledTools.join(",");if(this.mcpDisabledTools=[...new Set(t)].sort(),this.mcpDisabledTools.join(",")===n)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 Gn(this.cfg))await this.probeServiceAccount(e);return Un(this.cfg)},exec:(e,t,n)=>this.execService(e,t,void 0,n)}}async reload(){let e;try{e=ut(this.cfg.repoRoot,this.cfg.configPath)}catch(i){throw this.bus.publish(Me(Ti,"",{error:F(i)})),this.log("devctl","ERROR",`configuration reload failed: ${F(i)}`),i}try{this.checkPluginHealthTypes(e),this.checkPluginIdentityTypes(e),this.checkPluginEnvironmentSources(e)}catch(i){throw this.bus.publish(Me(Ti,"",{error:F(i)})),this.log("devctl","ERROR",`configuration reload failed: ${F(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=CR(this.cfg,e),n=JSON.stringify(this.cfg.proxy)!==JSON.stringify(e.proxy),r=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,r)this.detector.update(e.secrets.extra_markers,e.secrets.extra_patterns);if(n){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(Me(ga,"",{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",ba(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[r,o]of this.runtimes)e[r]={...o,ports:this.ports.get(r)??o.ports,profile:this.serviceProfile.get(r)??o.profile,env_source:this.clientEnv.has(r)?"client":"daemon"};let t=this.proxy?.stats(),n={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((r)=>{let o=r.match.host||"*",i=r.match.path,s=i===""?o:`${o}${i.startsWith("/")?i:`/${i}`}`;return{name:r.name,identity:r.auth.identity.service_account||r.auth.identity.type||r.auth.type,upstream:r.upstream.url,auth:r.auth.type,match:s}}),...n},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:_R()}}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 Gn(this.cfg))await this.probeServiceAccount(o);let{service_accounts:n,service_account_status:r}=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:n,service_account_status:r,iap:this.cfg.proxy.routes.some((o)=>o.auth.type.toLowerCase()==="iap")},await this.syncCredentialEntries(),this.bus.publish(Me(_d,"",{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: ${F(t)}`)}}serviceAccountSnapshot(){let e={},t={};for(let n of Gn(this.cfg)){let r=this.serviceAccountStatus.get(n)??"unknown";if(t[n]=r,r!=="unknown")e[n]=r==="available"}return{service_accounts:e,service_account_status:t}}async probeServiceAccount(e){let t;try{await RR(this.tokens.refresh(`sa:${e}`,"",[]),hR),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[n,r]of Object.entries(e.services))t.push(`${n} ${ko(r)} ${r.health} ${r.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(`
653
+ `;e.onLine?.(a,c)},i=[Ha(t.stdout,"stdout",o),Ha(t.stderr,"stderr",o)],s=await t.exited;return await Promise.all(i),{code:typeof s==="number"?s:0,stdout:n,stderr:r}}async startContainer(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;let n=await Oh(e),r={name:e.name,pid:0,startTime:new Date,workDir:e.workDir,args:[...e.command],done:n.done,container:n};return n.done.finally(()=>{if(this.running.get(e.name)===r)this.running.delete(e.name)}),this.running.set(e.name,r),r}async adoptContainer(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;let n=await $h(e.runtime,e.containerName,e.onLine,e.onExit);if(!n)return;let r={name:e.name,pid:0,startTime:new Date,workDir:e.workDir,args:[],done:n.done,container:n};return n.done.finally(()=>{if(this.running.get(e.name)===r)this.running.delete(e.name)}),this.running.set(e.name,r),r}adopt(e){let t=this.running.get(e.name);if(t&&Dr(t))return t;if(!Tt(e.pid))throw L(Ne,`cannot adopt ${e.name}: pid ${e.pid} is not running`);let n={name:e.name,pid:e.pid,startTime:e.startTime,workDir:e.workDir,args:[...e.args],done:Promise.resolve({code:0})};return n.done=I0(e.pid).then((r)=>{if(this.running.get(e.name)===n)this.running.delete(e.name);if(e.onExit)e.onExit(r,r===0?void 0:Error(`exited with code ${r}`));return{code:r}}),this.running.set(e.name,n),n}async stop(e,t){let n=this.running.get(e);if(!n)return;let r=t>0?t:D0;if(n.container){await n.container.stop(r),this.running.delete(e);return}if(await Nh(n.pid,"SIGTERM"),!await Wh(n.done,r)){if(await Nh(n.pid,"SIGKILL"),!await Wh(n.done,O0))throw L(Ne,`process ${e} did not exit after SIGKILL`)}this.running.delete(e)}get(e){return this.running.get(e)}all(){return[...this.running.values()]}}function Dr(e){if(e.container)return e.container.running();if(e.proc)return e.proc.exitCode===null&&!e.proc.killed;return Tt(e.pid)}async function Nh(e,t){if(process.platform==="win32"){await Th(e,t);return}await Ch(e,t)}async function ja(e){if(process.platform==="win32")return Ah(e);return _h(e)}async function Gh(e){if(process.platform==="win32")return Lh(e);return Eh(e)}var $0=2000;function Ba(e,t){if(e.workDir!==""&&t.cwd!==""&&Bh(e.workDir)!==Bh(t.cwd))return!1;if(!Rh(e.args,t.command))return!1;let n=Hh(e.startTime),r=Hh(t.startTime);if(n!==void 0&&r!==void 0)return Math.abs(n-r)<=$0;return!0}function Hh(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 jh(e){if(process.platform==="win32")return["cmd.exe","/c",e.join(" ")];return["/bin/sh","-c",e.join(" ")]}function Bh(e){return e.replace(/\\/g,"/").replace(/\/+$/,"")}async function I0(e){while(Tt(e))await F0(M0);return 0}async function Ha(e,t,n){if(!e||typeof e==="number"||!n)return;let r=e.getReader(),o=new TextDecoder,i="";for(;;){let{value:s,done:a}=await r.read();if(a){if(i!=="")n(t,i);return}i+=o.decode(s,{stream:!0});let c=i.split(`
654
+ `);i=c.pop()??"";for(let l of c)n(t,l.replace(/\r$/,""))}}async function Wh(e,t){return Promise.race([e.then(()=>!0),new Promise((n)=>{setTimeout(()=>n(!1),t)})])}function F0(e){return new Promise((t)=>{setTimeout(t,e)})}Re();Gi();import{createServer as J0}from"http";var z0="2025-03-26",iv="2.0",tv=-32700,nv=-32600,Y0=-32601,rv=-32602,X0=-32603,Q0=new Set(["127.0.0.1","localhost","::1"]);function Z0(e){return Q0.has(e)}class fu{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(!Z0(this.opts.host))return Promise.reject(L(Je,`refusing to bind MCP to ${this.opts.host}`));return new Promise((e,t)=>{this.server=J0((n,r)=>{this.serve(n,r)}),this.server.on("error",(n)=>t(fe(Je,`unable to listen on ${this.opts.host}:${this.opts.port}`,n))),this.server.listen(this.opts.port,this.opts.host,()=>{let n=this.server?.address();this.boundPort=typeof n==="object"&&n?n.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((n)=>{e.close(()=>{if(this.running=!1,this.addr="",this.boundPort=0,this.server=void 0,t)this.emit("INFO","stopped");n()})})}async serve(e,t){if(e.method==="OPTIONS"){t.writeHead(204,qi()),t.end();return}if(!this.authorized(e)){this.emit("WARN",`rejected unauthorized request from ${ov(e)}`),Lo(t,401,{error:"unauthorized"});return}if(tE(e)!=="/mcp"){Lo(t,404,{error:"not found"});return}if(e.method==="GET"||e.method==="DELETE"){t.writeHead(405,{Allow:"POST, OPTIONS",...qi()}),t.end();return}if(e.method!=="POST"){t.writeHead(405,{Allow:"POST, OPTIONS",...qi()}),t.end();return}let r;try{r=await nE(e)}catch(a){Lo(t,400,Ui(null,tv,a instanceof Error?a.message:"invalid body"));return}let o;try{o=JSON.parse(r)}catch{Lo(t,400,Ui(null,tv,"parse error"));return}let i=ov(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)}Lo(t,200,a);return}let s=await this.dispatch(o,i);if(s===void 0){t.writeHead(202,qi()),t.end();return}Lo(t,200,s)}authorized(e){if(this.opts.token==="")return!0;return(e.headers.authorization??"")===`Bearer ${this.opts.token}`}async dispatch(e,t){if(!Va(e))return Ui(null,nv,"invalid request");let n=e,r=n.id??null,o=n.id===void 0;if(n.method===void 0||n.method==="")return o?void 0:Ui(r,nv,"missing method");try{let i=await this.handleMethod(n.method,Va(n.params)?n.params:{},t);if(o)return;return{jsonrpc:iv,id:r,result:i}}catch(i){if(o)return;let s=i instanceof Ki?i.code:X0,a=i instanceof Error?i.message:"internal error";return this.emit("WARN",`rpc error method=${n.method} addr=${t}: ${a}`),Ui(r,s,a)}}async handleMethod(e,t,n){switch(e){case"initialize":{let r=eE(t);return this.emit("INFO",`client connected addr=${n}${r?` (${r})`:""}`),{protocolVersion:z0,capabilities:{tools:{},resources:{}},serverInfo:{name:"devctl",version:pt}}}case"notifications/initialized":case"ping":return{};case"tools/list":return{tools:Vh(this.disabled()).map((r)=>({name:r.name,description:r.description,inputSchema:r.inputSchema}))};case"tools/call":return this.callTool(t);case"resources/list":return{resources:uu.map((r)=>({uri:r,name:r.replace("devctl://",""),mimeType:"application/json"}))};case"resources/read":return this.readResource(t);default:throw new Ki(Y0,`method not found: ${e}`)}}async callTool(e){let t=typeof e.name==="string"?e.name:"";if(t==="")throw new Ki(rv,"tool name is required");if(Ka(t)&&!qn(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 n=Va(e.arguments)?e.arguments:{},r=Date.now();try{let o=await Qh(this.opts.hostApi,t,n);return this.emit("INFO",`tool call name=${t} duration=${Date.now()-r}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()-r}ms: ${i}`),{content:[{type:"text",text:i}],isError:!0}}}async readResource(e){let t=typeof e.uri==="string"?e.uri:"";if(!Zh(t))throw new Ki(rv,`unknown resource ${t}`);let n=await ev(this.opts.hostApi,t);return this.emit("INFO",`resource read uri=${t}`),{contents:[{uri:t,mimeType:"application/json",text:JSON.stringify(n,null,2)}]}}}function eE(e){let t=e.clientInfo;if(!Va(t))return"";let n=typeof t.name==="string"?t.name:"",r=typeof t.version==="string"?t.version:"";if(n==="")return"";return r===""?n:`${n} ${r}`}function ov(e){return e.socket.remoteAddress??"unknown"}class Ki extends Error{code;constructor(e,t){super(t);this.code=e}}function qi(){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 Lo(e,t,n){let r=JSON.stringify(n);e.writeHead(t,{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),...qi()}),e.end(r)}function Ui(e,t,n){return{jsonrpc:iv,id:e,error:{code:t,message:n}}}function tE(e){let t=e.url??"/",n=t.indexOf("?");return n>=0?t.slice(0,n):t}function nE(e){return new Promise((t,n)=>{let r=[];e.on("data",(o)=>{r.push(o)}),e.on("end",()=>{t(Buffer.concat(r).toString("utf8"))}),e.on("error",n)})}function Va(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}Gi();Ja();Zt();Oi();Ao();Rr();ze();Ai();var RE=4000,PE=100,mv=30000,hv=3,TE=2,AE=2000,LE=200,DE=3,OE=10,ME=3000;class yu{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=vv();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=Dl(),this.internalTok=$l(),this.mcpToken=Uf(e.repoRoot),this.bus=new $d(2048),this.detectGoogleFn=t?.detectGoogle??Ot,this.inspectProcessFn=t?.inspectProcess??ja,this.processAliveFn=t?.processAlive??Tt,this.acquireLockFn=t?.acquireLock??Gf,this.socketExistsFn=t?.socketExists??hu,this.unlinkSocketFn=t?.unlinkSocket??wE,this.detector=new Vt(e.secrets.extra_markers,e.secrets.extra_patterns),this.logs=new Oa(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=t?.procs??new du,this.tokens=t?.tokens??new wo(e.auth.refresh_threshold_seconds*1000,_r(),this.bus),this.bus.subscribe((n)=>{let r=n.payload??{},o=n.type===bo?`token refreshed identity=${String(r.identity??"")}`:n.type===Cr?`token refresh failed identity=${String(r.identity??"")} audience=${String(r.audience??"")}: ${String(r.error??"")}`:`authentication changed user=${String(r.user??"")}`;if(this.logs.append({timestamp:new Date().toISOString(),service:"auth",source:"auth",level:n.type===Cr?"WARN":"INFO",message:o,pid:0}),n.type===bo||n.type===Cr)this.syncCredentialEntries()},[bo,Cr,Od]),this.setupMode=!hu(e.configPath),this.identityCache=vv(e);for(let n of Object.keys(e.services))this.runtimes.set(n,Sa(n))}async run(){let e=Hs(this.cfg.repoRoot);this.lock=this.acquireLockFn(this.cfg.repoRoot,e),this.removeStaleSocket(e),this.registry=await kh(this.cfg.plugins.map((n)=>n.path),this.cfg.repoRoot);for(let n of this.registry.loadErrors)this.log("devctl","ERROR",`plugin ${n.path} skipped: ${n.message}`);this.applyRegistry(),this.checkPluginHealthTypes(),this.checkPluginIdentityTypes(),this.checkPluginEnvironmentSources(),await this.recoverSession(),this.watchConfig(),this.persistState(),this.log("devctl","INFO",`supervisor started session=${this.sessionID}`),this.refreshIdentity(),this.resourceTimer=setInterval(()=>void this.pollResourceUsage(),ME);let t=Qt(this.cfg.repoRoot);if(this.setMcpDisabledTools(t.mcp_disabled_tools??[]),t.mcp_enabled)await this.startMcp(t.mcp_port).catch((n)=>this.log("devctl","ERROR",O(n)));this.removeStaleSocket(e),await new Promise((n,r)=>{this.server=bE((o)=>{this.handleConn(o)}),this.server.on("error",r),this.server.listen(e,()=>n())})}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="",n=2000,r=[],o=!1,i=()=>{while(r.length>0){let c=r[0],l=e.write(`${JSON.stringify(c)}
655
+ `);if(r.shift(),!l){o=!0,e.once("drain",()=>{o=!1,i()});return}}},s=(c)=>{if(c.id===void 0&&c.event!==void 0&&r.length>=n){let d=r.findIndex((f)=>f.id===void 0&&f.event!==void 0);if(d>=0)r.splice(d,1)}if(r.push(c),!o)i()},a=this.bus.subscribe((c)=>s({event:c}));e.on("error",(c)=>{this.log("devctl","WARN",`client connection error: ${O(c)}`)}),e.on("data",(c)=>{t+=c.toString("utf8");let l=t.split(`
656
+ `);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 n;try{n=JSON.parse(e)}catch{t({error:"invalid json"});return}try{let r=await this.dispatch(n.method??"",n.params);t({id:n.id,result:r})}catch(r){let o=Ff(r);t({id:n.id,error:o.error,kind:o.kind,hint:o.hint,service:o.service})}}async dispatch(e,t){let n=yv(t)?t:{};switch(e){case"ping":return{session:this.sessionID,version:pt,protocol:ki};case"start":return this.start({services:Ir(n.services),profile:typeof n.profile==="string"?n.profile:"",detach:n.detach===!0,client_env:nc(n.client_env)});case"stop":return await this.stop(Ir(n.services)),null;case"restart":return await this.restart(Ir(n.services),{cascade:n.cascade===!0,clientEnv:nc(n.client_env)}),null;case"run_task":return this.runTask(typeof n.name==="string"?n.name:"",nc(n.client_env)??{});case"exec":return this.execService(typeof n.service==="string"?n.service:"",Ir(n.command),nc(n.client_env)??{},n.print_env===!0);case"auth_refresh":return await this.refreshIdentity({probeServiceAccounts:!0}),this.snapshot().identity;case"status":return this.snapshot();case"logs":return this.queryLogs({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.until:"",export:typeof n.export==="string"?n.export:""});case"logs_page":return this.queryLogsPage({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.until:"",cursor:typeof n.cursor==="string"?n.cursor:void 0,direction:n.direction==="forward"?"forward":"backward",limit:typeof n.limit==="number"?n.limit:void 0});case"logs_stats":return this.queryLogsFacets({services:Ir(n.services),level:typeof n.level==="string"?n.level:"",search:typeof n.search==="string"?n.search:"",regex:n.regex===!0,source:typeof n.source==="string"?n.source:"",since:typeof n.since==="string"?n.since:"",until:typeof n.until==="string"?n.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 n.port==="number"?n.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(n.disabled)?n.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 r=typeof n.stop_services==="boolean"?n.stop_services:Us(this.cfg.shutdown);return setTimeout(()=>{this.shutdown(r)},50),null;default:throw L(Je,`unknown method ${e}`)}}isDetached(){return this.detached}async start(e){if(e.detach===!0)this.detached=!0;let t=Ca(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 n=$i(this.cfg,t.services,t.profile),r=await this.detectGoogleFn(this.cfg.google.project_id);n.blockers=gm(this.cfg,n.waves.flat(),r.adcAvailable);let o=new Set(n.blockers.map((s)=>s.name));for(let s of n.blockers)await this.fail(s.name,L(Ne,s.message));if(this.cfg.proxy.enabled&&!this.proxySuppressed)await this.startProxy().catch((s)=>this.log("devctl","ERROR",O(s)));let i=[];for(let s of n.waves.flat()){if(o.has(s)||await this.claimIfAlreadyUp(s))continue;i.push(s)}if(i.length>0)try{let s=await km(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,f])=>`${d}=${f}`).join(", ");this.log(a,"INFO",`assigned ports: ${l||"none"}`)}}catch(s){if(s instanceof Me&&s.service!=="")await this.fail(s.service,s);else this.log("devctl","ERROR",O(s));throw s}for(let s of n.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,e.auto!==!0))),l=!1;for(let d of c)if(d.status==="rejected")l=!0,this.log("devctl","ERROR",O(d.reason));if(l)throw L(Ne,"one or more services failed to start")}try{await this.awaitWaveHealth(s,n.waves.flat())}catch(c){throw this.log("devctl","ERROR",O(c)),c}}return this.persistState(),n}async runTask(e,t){let n=this.cfg.tasks[e];if(!n)throw L(Je,`unknown task ${e}`);if(n.dependencies.length>0)await this.start({services:n.dependencies,client_env:t});let r={...Nn(),command:n.command,shell:n.shell,working_dir:n.working_dir,dependencies:n.dependencies,environment:n.environment},o=await ra(this.cfg.repoRoot,{service:`task:${e}`,profile:this.profile,serviceCfg:r,profileEnv:this.profileEnv,assignedPorts:{},runtime:oa(`task:${e}`,"127.0.0.1",{},"",this.cfg.project.name),cfg:this.cfg,clientEnv:t,fetchSecret:na(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources}),i=n.working_dir&&!vu(n.working_dir)?tc(this.cfg.repoRoot,n.working_dir):n.working_dir,s=await this.runTransient(`task:${e}`,n.command,n.shell,i,Si(o));return{task:e,...s}}async execService(e,t,n,r=!1){let o=this.cfg.services[e];if(!o)throw L(fi,`unknown service ${e}`);let i=this.serviceProfile.get(e)??this.profile,s=this.serviceProfileEnv.get(e)??this.profileEnv,{env:a,workDir:c}=await this.resolveServiceExecution(e,o,i,s,n,!o.container);if(r)return{service:e,code:0,stdout:"",stderr:"",environment:a};if(t.length===0)throw L(Je,"exec command is required");let l=await this.runTransient(`${e}:exec`,{args:t,shell:!1},!1,c,a);return{service:e,...l}}async resolveServiceExecution(e,t,n,r,o,i=!0){let s=this.ports.get(e)??Object.fromEntries(t.ports.filter((f)=>!f.auto).map((f)=>[f.name,f.value])),a=this.proxy?.isRunning()?`http://${this.proxy.address()}`:this.cfg.proxy.enabled?`http://${gr(this.cfg.proxy.listen)}`:"",c=oa(e,"127.0.0.1",s,a,this.cfg.project.name);if(!t.container){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 ra(this.cfg.repoRoot,{service:e,profile:n,serviceCfg:t,profileEnv:r,assignedPorts:s,runtime:c,cfg:this.cfg,fetchSecret:na(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources,clientEnv:o,includeProcess:i}),d=t.working_dir&&!vu(t.working_dir)?tc(this.cfg.repoRoot,t.working_dir):t.working_dir;return{env:Si(l),workDir:d}}async runTransient(e,t,n,r,o){if(io(t))return{code:0,stdout:"",stderr:""};this.log(e,"INFO",`running ${t.args.join(" ")}`);let i=await this.procs.runOnce({name:e,args:[...t.args],shell:n||t.shell,workDir:r,env:o,graceMs:so(this.cfg.shutdown)*1000,onLine:(s,a)=>this.logs.append({timestamp:new Date().toISOString(),service:e,source:s,stream:s,level:"",message:a,pid:0})});if(i.code!==0)throw L(Ne,`${e} exited with code ${i.code}`);return i}serviceIsActive(e){let t=this.procs.get(e);if(t&&Dr(t))return!0;let n=this.runtimes.get(e);if(!n)return!1;if(n.health===_t||n.state===Er)return!0;return n.state===Hd||n.state===jt}serviceWorkDir(e){if(e.working_dir!==""&&!vu(e.working_dir))return tc(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 da(t);if(s)this.ports.set(e,s)}return!0}if(!t)return!1;if(t.container){let s=this.bumpGeneration(e),a=t.container.runtime==="podman"?"podman":"docker",c=this.serviceWorkDir(t),l=await this.procs.adoptContainer({name:e,runtime:a,containerName:`devctl-${vn(this.cfg.repoRoot)}-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,workDir:c,onLine:(g,m)=>this.logs.append({timestamp:new Date().toISOString(),service:e,source:g,stream:g,level:"",message:m,pid:0}),onExit:(g,m)=>this.onExit(e,s,g,m)});if(!l)return!1;let d=this.ports.get(e)??Object.fromEntries(t.ports.filter((g)=>!g.auto).map((g)=>[g.name,g.value]));this.ports.set(e,d),this.processMeta.set(e,{command:[...t.command.args],cwd:c,startTime:l.startTime}),this.setState(e,jt,Ct,0,"");let f=await this.resolveAdoptedHealthEnv(e,t,d);return this.startHealth(e,t,0,d,c,f,s),this.persistState(),this.log(e,"INFO",`claimed running ${a} container ${l.container?.id??""}`),!0}let n=await da(t);if(!n)return!1;let r=Object.values(n)[0],i=(r===void 0?void 0:await yo(r))?.pid??0;if(i>0&&i!==process.pid){let s=pr(this.cfg.repoRoot)?.processes.find((l)=>l.name===e&&l.pid===i);if(!s)return this.log(e,"WARN",`port ${r} is held by pid ${i} with no persisted record for ${e}; not adopting`),!1;let a=await ja(i);if(a!==void 0&&a.command!==""&&Ba({args:[...t.command.args],workDir:this.serviceWorkDir(t),startTime:new Date(s.startTime)},a)){this.ports.set(e,n);let l=this.attachProcess(e,i,[...t.command.args],this.serviceWorkDir(t),new Date(s.startTime))??this.bumpGeneration(e);this.setState(e,jt,Ct,i,""),this.log(e,"INFO",`already listening on ${Object.values(n).join(", ")}; not starting again`);let d=this.serviceWorkDir(t),f=await this.resolveAdoptedHealthEnv(e,t,n);return this.startHealth(e,t,i,n,d,f,l),!0}this.log(e,"WARN",`port ${r} is in use by an unrelated process (pid ${i}); not adopting`)}return!1}async startOne(e,t,n,r=!1){if(this.serviceIsActive(e))return;let o=this.cfg.services[e];if(!o)throw L(Je,`unknown service ${e}`);this.setState(e,Hd,Ct,0,"");let i=this.bumpGeneration(e),s=aa(o.identity);if(s.kind!=="none")try{if(s=await mm(o.identity,()=>xm(this.cfg.google.project_id),this.registry?.identityProviders),s.kind==="service_account")await this.tokens.get(po(s),"",[]),this.serviceAccountStatus.set(s.serviceAccount,"available")}catch(m){if(s.kind==="service_account")this.serviceAccountStatus.set(s.serviceAccount,"unavailable");if(NE(o)||s.kind==="service_account"||s.kind!=="user"&&s.kind!=="none")throw await this.fail(e,m),m;this.log(e,"WARN","cloud identity unavailable; starting service locally")}let a=this.ports.get(e)??{},{env:c,workDir:l}=await this.resolveServiceExecution(e,o,t,n,this.clientEnv.get(e),!o.container);if(r)try{await this.runTransient(`${e}:pre_start`,o.hooks.pre_start,o.shell,l,c)}catch(m){throw await this.fail(e,m),m}if(!this.isCurrentGeneration(e,i))return;let d=(m,x)=>{this.logs.append({timestamp:new Date().toISOString(),service:e,source:m,stream:m,level:"",message:x,pid:g.pid})},f=(m,x)=>this.onExit(e,i,m,x),g=o.container?await this.procs.startContainer({name:e,runtime:o.container.runtime==="podman"?"podman":"docker",containerName:`devctl-${vn(this.cfg.repoRoot)}-${e.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,image:o.container.image,command:[...o.command.args],env:Mh({...c,...o.container.env}),ports:a,targetPorts:o.container.ports,volumes:o.container.volumes,workDir:l,onLine:d,onExit:f}):await this.procs.start({name:e,args:[...o.command.args],shell:o.shell||o.command.shell,workDir:l,env:c,graceMs:so(this.cfg.shutdown)*1000,captureStdout:Yf(o),captureStderr:Xf(o),onLine:d,onExit:f});if(!this.isCurrentGeneration(e,i)){if(this.procs.get(e)===g)await this.procs.stop(e,so(this.cfg.shutdown)*1000).catch(()=>{});return}if(this.processMeta.set(e,{command:[...o.command.args],cwd:l,startTime:g.startTime}),this.setState(e,jt,Ct,g.pid,""),this.bus.publish(Le(Pm,e,{pid:g.pid})),r)try{await this.runTransient(`${e}:post_start`,o.hooks.post_start,o.shell,l,c)}catch(m){throw await this.fail(e,m),m}if(this.startHealth(e,o,g.pid,a,l,c,i),this.persistState(),o.startup.wait_for_healthy){let m=o.startup.timeout_seconds>0?o.startup.timeout_seconds*1000:mv;try{await this.waitHealthy(e,m)}catch(x){throw await this.fail(e,x),x}}}async resolveAdoptedHealthEnv(e,t,n){let r="";if(this.proxy?.isRunning())r=`http://${this.proxy.address()}`;else if(this.cfg.proxy.enabled)r=`http://${gr(this.cfg.proxy.listen)}`;let o=oa(e,"127.0.0.1",n,r,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 ra(this.cfg.repoRoot,{service:e,profile:this.serviceProfile.get(e)??this.profile,serviceCfg:t,profileEnv:this.serviceProfileEnv.get(e)??this.profileEnv,assignedPorts:n,runtime:o,cfg:this.cfg,fetchSecret:na(async()=>(await this.tokens.get("user","",[])).accessToken),pluginSources:this.registry?.environmentSources});return Si(i)}catch(i){return this.log(e,"WARN",`could not fully reconstruct environment for adopted service's health check (${O(i)}); using a baseline environment`),Si(o)}}async awaitWaveHealth(e,t){for(let n of e){let r=this.cfg.services[n],o=t.some((s)=>(this.cfg.services[s]?.dependencies??[]).some((a)=>wt(a)===n&&Fn(a)==="service_healthy"));if(!r||r.health.type===""||!o)continue;let i=r.startup.timeout_seconds>0?r.startup.timeout_seconds*1000:mv;try{await this.waitHealthy(n,i)}catch(s){throw await this.fail(n,s),s}}}async waitHealthy(e,t){let n=Date.now()+t;while(Date.now()<n){let r=this.runtimes.get(e);if(r?.health===_t)return;if(r?.state===Kn)throw L(El,`service ${e} failed while waiting for healthy`);await HE(PE)}throw L(El,`service ${e} did not become healthy in time`)}onExit(e,t,n,r){if(!this.isCurrentGeneration(e,t))return;let o=this.runtimes.get(e);if(o?.state===Kn)return;if(o&&(o.state===jd||o.state===ko)){this.setState(e,ko,Ct,0,""),this.bus.publish(Le(Ld,e,{code:n}));return}let i=this.cfg.services[e],s=i?i.restart.policy||(i.restart.enabled?"on_failure":"never"):"never",a=r?.message??`exited with code ${n}`,c=s==="always"||s==="on_failure"&&n!==0,l=this.restarts.get(e)??0,d=i&&i.restart.max_retries>0?i.restart.max_retries:hv;if(c&&i&&l<d){this.setState(e,Mi,Ct,0,a),this.bumpRestartCount(e,l+1),this.persistState(),this.armRestart(e,i,t,l,()=>{let f=this.serviceProfile.get(e)??this.profile,g=this.serviceProfileEnv.get(e)??this.profileEnv;this.startOne(e,f,g,!1).catch((m)=>this.log(e,"ERROR",O(m)))});return}this.fail(e,L("process_start",a))}startHealth(e,t,n,r,o,i,s){let a=this.healthTimers.get(e);if(a)clearInterval(a);if(t.health.type===""){this.setHealth(e,_t,"no health check");return}let c=Zm(t.health)||AE,l=Date.parse(this.runtimes.get(e)?.startTime??"")||Date.now(),d=()=>{(t.container&&t.health.type.toLowerCase()==="process"?Promise.resolve(this.procs.get(e)&&Dr(this.procs.get(e))?{status:_t,message:"container running"}:{status:Ce,message:"container not running"}):eh(t.health,n,r,o,i,this.registry?.healthChecks)).catch((g)=>({status:Ce,message:O(g)})).then((g)=>{if(!this.isCurrentGeneration(e,s))return;if(g.status===Ce&&Date.now()-l<t.health.start_period_seconds*1000){this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:"INFO",message:`health check still in start period: ${g.message}`,pid:n});return}this.setHealth(e,g.status,g.message),this.logs.append({timestamp:new Date().toISOString(),service:e,source:"health",level:th(g.status),message:`health ${g.status} ${g.message}`,pid:n}),this.maybeRestartUnhealthy(e,t,g.status,s)})};d(),this.healthTimers.set(e,setInterval(d,c))}async stop(e){let t=e;if(t.length===0)t=[...this.runtimes.entries()].filter(([,i])=>i.state!==ko).map(([i])=>i);if(t.length===0)return;let n=t.filter((i)=>!this.cfg.services[i]&&this.runtimes.has(i)),r=t.filter((i)=>!this.cfg.services[i]&&!this.runtimes.has(i));if(r.length>0)throw L(fi,`unknown service "${r[0]}"`);let o=t.filter((i)=>this.cfg.services[i]!==void 0);if(o.length>0)await this.runStopPlan(Ii(this.cfg,o),{resetRestartCounts:!0});if(n.length>0){await this.runStopPlan({profile:this.profile,steps:[],waves:n.map((i)=>[i])},{resetRestartCounts:!0});for(let i of n)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 n of Object.keys(t))if(!e[n]&&!this.runtimes.has(n))this.runtimes.set(n,Sa(n));for(let n of Object.keys(e)){if(t[n])continue;if(this.serviceIsActive(n)){let r=this.runtimes.get(n);if(r)r.orphaned=!0;this.log(n,"WARN","removed from configuration while still running; now orphaned \u2014 stop it explicitly to clean it up");continue}this.forgetService(n)}}async restart(e,t){let n=t?.cascade===!0,r=n?Wd(this.cfg,e):e,o=n?Ii(this.cfg,e):zm(this.cfg,e),i=t?.auto!==!0;await this.runStopPlan(o,{resetRestartCounts:i});let s=r.map((a)=>this.serviceProfile.get(a)).find((a)=>a!==void 0)??this.profile;await this.start({services:r,profile:s,client_env:t?.clientEnv,auto:t?.auto})}async runStopPlan(e,t){for(let o of e.waves.flat())if(this.clearRestartTimer(o),this.bumpGeneration(o),t?.resetRestartCounts)this.resetRestartCount(o);let n=so(this.cfg.shutdown)*1000,r=[];for(let o of e.waves){let i=await Promise.allSettled(o.map(async(s)=>{this.setState(s,jd,Ct,0,"");let a=this.healthTimers.get(s);if(a)clearInterval(a),this.healthTimers.delete(s);try{await this.procs.stop(s,n)}catch(c){throw this.setState(s,Kn,Ct,0,O(c)),this.bus.publish(Le(Dd,s,{error:O(c)})),c}try{await this.releasePorts(s)}catch(c){this.log(s,"WARN",O(c))}this.setState(s,ko,Ct,0,""),this.bus.publish(Le(Ld,s,{}))}));for(let s=0;s<i.length;s+=1){let a=i[s];if(a?.status==="rejected"){let c=o[s]??"";r.push(c),this.log(c||"devctl","ERROR",O(a.reason))}}}if(this.persistState(),r.length>0)throw L(Ne,`failed to stop: ${r.join(", ")}`)}async startProxy(){if(this.proxy?.isRunning())return;if(this.proxy=new su(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 au(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 pv(this.cfg.repoRoot,e);this.mcp=new fu({host:"127.0.0.1",port:t,token:this.mcpToken,hostApi:this.asMcpHost(),onEvent:(n,r)=>this.log("mcp",n,`mcp ${r}`),disabledTools:()=>this.mcpDisabledTools}),await this.mcp.start(),this.persistState()}setMcpDisabledTools(e){let t=e.filter((r)=>Ka(r)),n=this.mcpDisabledTools.join(",");if(this.mcpDisabledTools=[...new Set(t)].sort(),this.mcpDisabledTools.join(",")===n)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 Gn(this.cfg))await this.probeServiceAccount(e);return Un(this.cfg)},exec:(e,t,n)=>this.execService(e,t,void 0,n)}}async reload(){let e;try{e=ut(this.cfg.repoRoot,this.cfg.configPath)}catch(i){throw this.bus.publish(Le(Ti,"",{error:O(i)})),this.log("devctl","ERROR",`configuration reload failed: ${O(i)}`),i}try{this.checkPluginHealthTypes(e),this.checkPluginIdentityTypes(e),this.checkPluginEnvironmentSources(e)}catch(i){throw this.bus.publish(Le(Ti,"",{error:O(i)})),this.log("devctl","ERROR",`configuration reload failed: ${O(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=$E(this.cfg,e),n=JSON.stringify(this.cfg.proxy)!==JSON.stringify(e.proxy),r=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,r)this.detector.update(e.secrets.extra_markers,e.secrets.extra_patterns);if(n){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(Le(va,"",{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",ka(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[r,o]of this.runtimes)e[r]={...o,ports:this.ports.get(r)??o.ports,profile:this.serviceProfile.get(r)??o.profile,env_source:this.clientEnv.has(r)?"client":"daemon"};let t=this.proxy?.stats(),n={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((r)=>{let o=r.match.host||"*",i=r.match.path,s=i===""?o:`${o}${i.startsWith("/")?i:`/${i}`}`;return{name:r.name,identity:r.auth.identity.service_account||r.auth.identity.type||r.auth.type,upstream:r.upstream.url,auth:r.auth.type,match:s}}),...n},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:IE()}}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 Gn(this.cfg))await this.probeServiceAccount(o);let{service_accounts:n,service_account_status:r}=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:n,service_account_status:r,iap:this.cfg.proxy.routes.some((o)=>o.auth.type.toLowerCase()==="iap")},await this.syncCredentialEntries(),this.bus.publish(Le(Od,"",{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: ${O(t)}`)}}serviceAccountSnapshot(){let e={},t={};for(let n of Gn(this.cfg)){let r=this.serviceAccountStatus.get(n)??"unknown";if(t[n]=r,r!=="unknown")e[n]=r==="available"}return{service_accounts:e,service_account_status:t}}async probeServiceAccount(e){let t;try{await FE(this.tokens.refresh(`sa:${e}`,"",[]),RE),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[n,r]of Object.entries(e.services))t.push(`${n} ${Co(r)} ${r.health} ${r.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(`
657
657
  `)+`
658
- `}setState(e,t,n,r,o){let i=this.runtimes.get(e)??xa(e);i.state=t,i.health=n,i.pid=r,i.last_error=o;let s=t===Ht||t===_r||t===wo;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(Me(Rm,e,{state:t,health:n,pid:r}))}bumpRestartCount(e,t){this.restarts.set(e,t);let n=this.runtimes.get(e);if(n)n.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,n){this.clearRestartTimer(e);let r=setTimeout(()=>{this.restartTimers.delete(e),n()},t);this.restartTimers.set(e,r)}armRestart(e,t,n,r,o){let i=t.restart.backoff_seconds>0?t.restart.backoff_seconds:yR;this.scheduleRestart(e,i*2**r*1000,()=>{if(this.isCurrentGeneration(e,n))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 n of this.runtimes.values())if(n.pid>0&&(n.state===Ht||n.state===_r||n.state===wo))e.push(n.pid);if(e.length===0)return;let t=await Hh(e);for(let n of this.runtimes.values()){let r=n.pid>0?t.get(n.pid):void 0;if(r)n.cpuPercent=r.cpuPercent,n.memoryKB=r.memoryKB}}setHealth(e,t,n){let r=this.runtimes.get(e);if(!r)return;if(r.health=t,r.state===Ht||r.state===_r||r.state===wo)r.state=t===Ct?_r:t===Ce?wo:r.state;this.bus.publish(Me(Pm,e,{health:t,message:n}))}maybeRestartUnhealthy(e,t,n,r){if(n!==Ce){if(this.unhealthyStreak.set(e,0),n===Ct)this.maybeForgiveRestarts(e,t);return}this.healthyStreak.set(e,0);let o=t.restart.policy||(t.restart.enabled?"on_failure":"never");if(o!=="on_failure"&&o!=="always")return;if(this.restartTimers.has(e))return;let i=(this.unhealthyStreak.get(e)??0)+1;this.unhealthyStreak.set(e,i);let s=t.health.unhealthy_threshold>0?t.health.unhealthy_threshold:wR;if(i<s)return;this.unhealthyStreak.set(e,0);let a=this.restarts.get(e)??0,c=t.restart.max_retries>0?t.restart.max_retries:pv;if(a>=c){this.log(e,"WARN",`unhealthy after ${i} consecutive checks but the restart limit (${c}) has already been reached; not restarting`);return}this.bumpRestartCount(e,a+1),this.log(e,"WARN",`restarting after ${i} consecutive unhealthy checks (attempt ${a+1}/${c})`),this.armRestart(e,t,r,a,()=>{this.restart([e],{auto:!0}).catch((l)=>this.log(e,"ERROR",F(l)))})}maybeForgiveRestarts(e,t){let n=(this.healthyStreak.get(e)??0)+1;this.healthyStreak.set(e,n);let r=t.health.healthy_reset_threshold>0?t.health.healthy_reset_threshold:SR;if(n>=r&&(this.restarts.get(e)??0)>0)this.log(e,"INFO",`restart count reset after ${n} 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=Xl(e);if(t.length===0)return;let n=new Set((this.registry?.healthChecks??[]).map((o)=>o.name.toLowerCase())),r=t.filter((o)=>!n.has(o.type.toLowerCase()));if(r.length>0)throw L(ee,`unknown health check type(s): ${r.map((o)=>`${o.service}.health.type=${o.type}`).join(", ")}`)}checkPluginIdentityTypes(e=this.cfg){let t=Ql(e);if(t.length===0)return;let n=this.registry?.pluginIdentityProviders??[],r=t.filter(({service:o})=>{let i=e.services[o];return!i||!n.some((s)=>s.accepts(i.identity))});if(r.length>0)throw L(ee,`unknown identity type(s): ${r.map((o)=>`${o.service}.identity.type=${o.type}`).join(", ")}`)}checkPluginEnvironmentSources(e=this.cfg){let t=new Set(wi),n=new Set((this.registry?.environmentSources??[]).map((o)=>o.name)),r=e.environment.sources.filter((o)=>!t.has(o)&&!n.has(o));if(r.length>0)throw L(ee,`unknown environment source(s): ${r.join(", ")}`)}watchConfig(){let e=Ya(this.cfg.repoRoot,".devctl");if(!pu(e))return;try{this.configWatcher=uR(e,{recursive:!0},()=>{if(this.watchTimer)clearTimeout(this.watchTimer);this.watchTimer=setTimeout(()=>{this.reload().catch((t)=>this.log("devctl","WARN",F(t)))},bR)})}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 n=this.cfg.services[e];if(n?.container){this.ports.delete(e);return}let r=this.processMeta.get(e);for(let o of Object.values(t)){let i=await vo(o);if(!i||i.pid===process.pid)continue;if(n){let s=await $a(i.pid);if(!(s!==void 0&&s.command!==""&&Ia({args:r?.command??[...n.command.args],workDir:r?.cwd??this.serviceWorkDir(n),startTime:r?.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 ca(i),this.log(e,"INFO",`released port ${o} (pid ${i.pid})`)}catch(s){this.log(e,"WARN",F(s))}}this.ports.delete(e)}async fail(e,t){let n=this.healthTimers.get(e);if(n)clearInterval(n),this.healthTimers.delete(e);this.clearRestartTimer(e),this.bumpGeneration(e),this.setState(e,Rr,Dt,0,F(t));try{await this.procs.stop(e,gi(this.cfg.shutdown)*1000)}catch(r){this.log(e,"WARN",F(r))}this.bus.publish(Me(_m,e,{error:F(t)})),this.log(e,"ERROR",F(t)),this.persistState()}log(e,t,n){this.logs.append({timestamp:new Date().toISOString(),service:e,source:"devctl",level:t,message:n,pid:0})}persistState(){let e=[];for(let t of this.procs.all()){let n=this.processMeta.get(t.name);e.push({name:t.name,pid:t.pid,command:n?.command??t.args,cwd:n?.cwd??t.workDir,startTime:(n?.startTime??t.startTime).toISOString(),ports:this.ports.get(t.name)??{}})}Nf(this.cfg.repoRoot,{session_id:this.sessionID,repo_root:this.cfg.repoRoot,profile:this.profile,processes:e})}attachProcess(e,t,n,r,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:n,workDir:r,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:n,cwd:r,startTime:o}),this.persistState(),i}async recoverSession(){let e=ur(this.cfg.repoRoot);if(!e)return;let t=[];for(let[n,r]of Object.entries(this.cfg.services)){if(!r.container)continue;let o=e.processes.find((d)=>d.name===n),i=this.bumpGeneration(n),s=r.container.runtime==="podman"?"podman":"docker",a=await this.procs.adoptContainer({name:n,runtime:s,containerName:`devctl-${vn(this.cfg.repoRoot)}-${n.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,workDir:this.serviceWorkDir(r),onLine:(d,f)=>this.logs.append({timestamp:new Date().toISOString(),service:n,source:d,stream:d,level:"",message:f,pid:0}),onExit:(d,f)=>this.onExit(n,i,d,f)});if(!a)continue;let c=o?.ports??Object.fromEntries(r.ports.filter((d)=>!d.auto).map((d)=>[d.name,d.value]));this.ports.set(n,c),this.processMeta.set(n,{command:[...r.command.args],cwd:this.serviceWorkDir(r),startTime:o?.startTime?new Date(o.startTime):a.startTime}),this.setState(n,Ht,Dt,0,"");let l=await this.resolveAdoptedHealthEnv(n,r,c);this.startHealth(n,r,0,c,this.serviceWorkDir(r),l,i),this.log(n,"INFO",`adopted ${s} container ${a.container?.id??""}`),t.push(n)}for(let n of e.processes){if(!this.cfg.services[n.name]||this.cfg.services[n.name]?.container||n.pid<=0||n.pid===process.pid||!this.processAliveFn(n.pid))continue;let r=await this.inspectProcessFn(n.pid);if(!(r!==void 0&&r.command!==""&&Ia({args:n.command,workDir:n.cwd,startTime:n.startTime?new Date(n.startTime):void 0},r))){if(Object.values(n.ports).length>0&&await aa({ports:Object.entries(n.ports).map(([c,l])=>({name:c,value:l,auto:!1}))})!==void 0)this.log(n.name,"WARN",`pid ${n.pid} does not match stored command; leftover listener not adopted`);else this.log(n.name,"WARN",`pid ${n.pid} is a different process; not adopting`);continue}let i=this.attachProcess(n.name,n.pid,n.command,n.cwd,new Date(n.startTime||Date.now()))??this.bumpGeneration(n.name);if(Object.keys(n.ports).length>0)this.ports.set(n.name,n.ports);this.setState(n.name,Ht,Dt,n.pid,"");let s=this.cfg.services[n.name];if(s){let a=n.cwd||this.serviceWorkDir(s),c=await this.resolveAdoptedHealthEnv(n.name,s,n.ports);this.startHealth(n.name,s,n.pid,n.ports,a,c,i)}this.log(n.name,"INFO","adopted leftover process; stdout/stderr from before adopt are not captured"),t.push(n.name)}if(t.length>0)this.profile=e.profile||this.profile,this.bus.publish(Me(Am,"",{services:t,session_id:e.session_id})),this.log("devctl","INFO",`recovered session processes: ${t.join(", ")}`)}}function CR(e,t){let n={},r=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"),r.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"),r.add(s);if(a.working_dir!==c.working_dir)l.push("working_dir"),r.add(s);if(JSON.stringify(a.environment)!==JSON.stringify(c.environment))l.push("environment"),r.add(s);if(JSON.stringify(a.ports)!==JSON.stringify(c.ports))l.push("ports"),r.add(s);if(JSON.stringify(a.identity)!==JSON.stringify(c.identity))l.push("identity"),r.add(s);if(JSON.stringify(a.health)!==JSON.stringify(c.health))l.push("health"),r.add(s);if(JSON.stringify(a.restart)!==JSON.stringify(c.restart))l.push("restart"),r.add(s);if(JSON.stringify(a.startup)!==JSON.stringify(c.startup))l.push("startup"),r.add(s);if(JSON.stringify(a.logs)!==JSON.stringify(c.logs))l.push("logs"),r.add(s);if(JSON.stringify(a.container)!==JSON.stringify(c.container))l.push("container"),r.add(s)}if(l.length>0)n[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:[...r].sort(),changes:n,supervisor_restart_required:i.length>0?i:void 0}}function fv(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?Gn(e).map((t)=>[t,"unknown"]):[]),iap:e?.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap")??!1}}function _R(){let e=fR(),t=Zm();return{platform:gR(),cpuCount:pR().length,loadAvg1:e[0]??0,loadAvg5:e[1]??0,loadAvg15:e[2]??0,memTotalKB:t.totalKB,memFreeKB:t.unusedKB,memAvailableKB:t.leftoverKB,hostUptimeSec:mR()}}function RR(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("identity probe timed out")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}function PR(e){return e.capabilities.some((t)=>["google_api","iap","service_identity"].includes(t))}function gv(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Ir(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}function Xa(e){if(!gv(e))return;let t={};for(let[n,r]of Object.entries(e))if(typeof r==="string")t[n]=r;return t}function ER(e){return new Promise((t)=>setTimeout(t,e))}Ar();Ga();Zt();$p();var mw=["zsh","bash","fish"];function hw(e){if(e==="zsh")return`#compdef devctl
658
+ `}setState(e,t,n,r,o){let i=this.runtimes.get(e)??Sa(e);i.state=t,i.health=n,i.pid=r,i.last_error=o;let s=t===jt||t===Er||t===So;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(Le(Tm,e,{state:t,health:n,pid:r}))}bumpRestartCount(e,t){this.restarts.set(e,t);let n=this.runtimes.get(e);if(n)n.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,n){this.clearRestartTimer(e);let r=setTimeout(()=>{this.restartTimers.delete(e),n()},t);this.restartTimers.set(e,r)}armRestart(e,t,n,r,o){let i=t.restart.backoff_seconds>0?t.restart.backoff_seconds:TE;this.scheduleRestart(e,i*2**r*1000,()=>{if(this.isCurrentGeneration(e,n))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 n of this.runtimes.values())if(n.pid>0&&(n.state===jt||n.state===Er||n.state===So))e.push(n.pid);if(e.length===0)return;let t=await Gh(e);for(let n of this.runtimes.values()){let r=n.pid>0?t.get(n.pid):void 0;if(r)n.cpuPercent=r.cpuPercent,n.memoryKB=r.memoryKB}}setHealth(e,t,n){let r=this.runtimes.get(e);if(!r)return;if(r.health=t,r.state===jt||r.state===Er||r.state===So)r.state=t===_t?Er:t===Ce?So:r.state;this.bus.publish(Le(Am,e,{health:t,message:n}))}maybeRestartUnhealthy(e,t,n,r){if(n!==Ce){if(this.unhealthyStreak.set(e,0),n===_t)this.maybeForgiveRestarts(e,t);return}this.healthyStreak.set(e,0);let o=t.restart.policy||(t.restart.enabled?"on_failure":"never");if(o!=="on_failure"&&o!=="always")return;if(this.restartTimers.has(e))return;let i=(this.unhealthyStreak.get(e)??0)+1;this.unhealthyStreak.set(e,i);let s=t.health.unhealthy_threshold>0?t.health.unhealthy_threshold:DE;if(i<s)return;this.unhealthyStreak.set(e,0);let a=this.restarts.get(e)??0,c=t.restart.max_retries>0?t.restart.max_retries:hv;if(a>=c){this.log(e,"WARN",`unhealthy after ${i} consecutive checks but the restart limit (${c}) has already been reached; not restarting`);return}this.bumpRestartCount(e,a+1),this.log(e,"WARN",`restarting after ${i} consecutive unhealthy checks (attempt ${a+1}/${c})`),this.armRestart(e,t,r,a,()=>{this.restart([e],{auto:!0}).catch((l)=>this.log(e,"ERROR",O(l)))})}maybeForgiveRestarts(e,t){let n=(this.healthyStreak.get(e)??0)+1;this.healthyStreak.set(e,n);let r=t.health.healthy_reset_threshold>0?t.health.healthy_reset_threshold:OE;if(n>=r&&(this.restarts.get(e)??0)>0)this.log(e,"INFO",`restart count reset after ${n} 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=od(e);if(t.length===0)return;let n=new Set((this.registry?.healthChecks??[]).map((o)=>o.name.toLowerCase())),r=t.filter((o)=>!n.has(o.type.toLowerCase()));if(r.length>0)throw L(Z,`unknown health check type(s): ${r.map((o)=>`${o.service}.health.type=${o.type}`).join(", ")}`)}checkPluginIdentityTypes(e=this.cfg){let t=id(e);if(t.length===0)return;let n=this.registry?.pluginIdentityProviders??[],r=t.filter(({service:o})=>{let i=e.services[o];return!i||!n.some((s)=>s.accepts(i.identity))});if(r.length>0)throw L(Z,`unknown identity type(s): ${r.map((o)=>`${o.service}.identity.type=${o.type}`).join(", ")}`)}checkPluginEnvironmentSources(e=this.cfg){let t=new Set(wi),n=new Set((this.registry?.environmentSources??[]).map((o)=>o.name)),r=e.environment.sources.filter((o)=>!t.has(o)&&!n.has(o));if(r.length>0)throw L(Z,`unknown environment source(s): ${r.join(", ")}`)}watchConfig(){let e=tc(this.cfg.repoRoot,".devctl");if(!hu(e))return;try{this.configWatcher=SE(e,{recursive:!0},()=>{if(this.watchTimer)clearTimeout(this.watchTimer);this.watchTimer=setTimeout(()=>{this.reload().catch((t)=>this.log("devctl","WARN",O(t)))},LE)})}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 n=this.cfg.services[e];if(n?.container){this.ports.delete(e);return}let r=this.processMeta.get(e);for(let o of Object.values(t)){let i=await yo(o);if(!i||i.pid===process.pid)continue;if(n){let s=await ja(i.pid);if(!(s!==void 0&&s.command!==""&&Ba({args:r?.command??[...n.command.args],workDir:r?.cwd??this.serviceWorkDir(n),startTime:r?.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 ua(i),this.log(e,"INFO",`released port ${o} (pid ${i.pid})`)}catch(s){this.log(e,"WARN",O(s))}}this.ports.delete(e)}async fail(e,t){let n=this.healthTimers.get(e);if(n)clearInterval(n),this.healthTimers.delete(e);this.clearRestartTimer(e),this.bumpGeneration(e),this.setState(e,Kn,Ct,0,O(t));try{await this.procs.stop(e,so(this.cfg.shutdown)*1000)}catch(r){this.log(e,"WARN",O(r))}this.bus.publish(Le(Dd,e,{error:O(t)})),this.log(e,"ERROR",O(t)),this.persistState()}log(e,t,n){this.logs.append({timestamp:new Date().toISOString(),service:e,source:"devctl",level:t,message:n,pid:0})}persistState(){let e=[];for(let t of this.procs.all()){let n=this.processMeta.get(t.name);e.push({name:t.name,pid:t.pid,command:n?.command??t.args,cwd:n?.cwd??t.workDir,startTime:(n?.startTime??t.startTime).toISOString(),ports:this.ports.get(t.name)??{}})}Wf(this.cfg.repoRoot,{session_id:this.sessionID,repo_root:this.cfg.repoRoot,profile:this.profile,processes:e})}attachProcess(e,t,n,r,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:n,workDir:r,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:n,cwd:r,startTime:o}),this.persistState(),i}async recoverSession(){let e=pr(this.cfg.repoRoot);if(!e)return;let t=[];for(let[n,r]of Object.entries(this.cfg.services)){if(!r.container)continue;let o=e.processes.find((d)=>d.name===n),i=this.bumpGeneration(n),s=r.container.runtime==="podman"?"podman":"docker",a=await this.procs.adoptContainer({name:n,runtime:s,containerName:`devctl-${vn(this.cfg.repoRoot)}-${n.replace(/[^a-zA-Z0-9_.-]/g,"-")}`,workDir:this.serviceWorkDir(r),onLine:(d,f)=>this.logs.append({timestamp:new Date().toISOString(),service:n,source:d,stream:d,level:"",message:f,pid:0}),onExit:(d,f)=>this.onExit(n,i,d,f)});if(!a)continue;let c=o?.ports??Object.fromEntries(r.ports.filter((d)=>!d.auto).map((d)=>[d.name,d.value]));this.ports.set(n,c),this.processMeta.set(n,{command:[...r.command.args],cwd:this.serviceWorkDir(r),startTime:o?.startTime?new Date(o.startTime):a.startTime}),this.setState(n,jt,Ct,0,"");let l=await this.resolveAdoptedHealthEnv(n,r,c);this.startHealth(n,r,0,c,this.serviceWorkDir(r),l,i),this.log(n,"INFO",`adopted ${s} container ${a.container?.id??""}`),t.push(n)}for(let n of e.processes){if(!this.cfg.services[n.name]||this.cfg.services[n.name]?.container||n.pid<=0||n.pid===process.pid||!this.processAliveFn(n.pid))continue;let r=await this.inspectProcessFn(n.pid);if(!(r!==void 0&&r.command!==""&&Ba({args:n.command,workDir:n.cwd,startTime:n.startTime?new Date(n.startTime):void 0},r))){if(Object.values(n.ports).length>0&&await da({ports:Object.entries(n.ports).map(([c,l])=>({name:c,value:l,auto:!1}))})!==void 0)this.log(n.name,"WARN",`pid ${n.pid} does not match stored command; leftover listener not adopted`);else this.log(n.name,"WARN",`pid ${n.pid} is a different process; not adopting`);continue}let i=this.attachProcess(n.name,n.pid,n.command,n.cwd,new Date(n.startTime||Date.now()))??this.bumpGeneration(n.name);if(Object.keys(n.ports).length>0)this.ports.set(n.name,n.ports);this.setState(n.name,jt,Ct,n.pid,"");let s=this.cfg.services[n.name];if(s){let a=n.cwd||this.serviceWorkDir(s),c=await this.resolveAdoptedHealthEnv(n.name,s,n.ports);this.startHealth(n.name,s,n.pid,n.ports,a,c,i)}this.log(n.name,"INFO","adopted leftover process; stdout/stderr from before adopt are not captured"),t.push(n.name)}if(t.length>0)this.profile=e.profile||this.profile,this.bus.publish(Le(Om,"",{services:t,session_id:e.session_id})),this.log("devctl","INFO",`recovered session processes: ${t.join(", ")}`)}}function $E(e,t){let n={},r=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"),r.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"),r.add(s);if(a.working_dir!==c.working_dir)l.push("working_dir"),r.add(s);if(JSON.stringify(a.environment)!==JSON.stringify(c.environment))l.push("environment"),r.add(s);if(JSON.stringify(a.ports)!==JSON.stringify(c.ports))l.push("ports"),r.add(s);if(JSON.stringify(a.identity)!==JSON.stringify(c.identity))l.push("identity"),r.add(s);if(JSON.stringify(a.health)!==JSON.stringify(c.health))l.push("health"),r.add(s);if(JSON.stringify(a.restart)!==JSON.stringify(c.restart))l.push("restart"),r.add(s);if(JSON.stringify(a.startup)!==JSON.stringify(c.startup))l.push("startup"),r.add(s);if(JSON.stringify(a.logs)!==JSON.stringify(c.logs))l.push("logs"),r.add(s);if(JSON.stringify(a.container)!==JSON.stringify(c.container))l.push("container"),r.add(s)}if(l.length>0)n[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:[...r].sort(),changes:n,supervisor_restart_required:i.length>0?i:void 0}}function vv(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?Gn(e).map((t)=>[t,"unknown"]):[]),iap:e?.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap")??!1}}function IE(){let e=CE(),t=nh();return{platform:_E(),cpuCount:kE().length,loadAvg1:e[0]??0,loadAvg5:e[1]??0,loadAvg15:e[2]??0,memTotalKB:t.totalKB,memFreeKB:t.unusedKB,memAvailableKB:t.leftoverKB,hostUptimeSec:EE()}}function FE(e,t){return new Promise((n,r)=>{let o=setTimeout(()=>r(Error("identity probe timed out")),t);e.then((i)=>{clearTimeout(o),n(i)},(i)=>{clearTimeout(o),r(i)})})}function NE(e){return e.capabilities.some((t)=>["google_api","iap","service_identity"].includes(t))}function yv(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Ir(e){if(!Array.isArray(e))return[];return e.filter((t)=>typeof t==="string")}function nc(e){if(!yv(e))return;let t={};for(let[n,r]of Object.entries(e))if(typeof r==="string")t[n]=r;return t}function HE(e){return new Promise((t)=>setTimeout(t,e))}Ar();Ja();Zt();Hp();var xw=["zsh","bash","fish"];function bw(e){if(e==="zsh")return`#compdef devctl
659
659
  _devctl() {
660
660
  local -a opts
661
661
  local line="\${words[*]}"
@@ -675,81 +675,81 @@ complete -F _devctl devctl
675
675
  devctl __complete (commandline -cp)
676
676
  end
677
677
  complete -c devctl -f -a "(__devctl_complete)"
678
- `;throw Error(`unsupported shell "${e}"; use ${mw.join(", ")}`)}function Ip(e,t){let n=e.trim().split(/\s+/).filter((l)=>l!==""),r=e.endsWith(" ")?"":n[n.length-1]??"",o=e.endsWith(" ")?n:n.slice(0,-1),i=o[1]??"",s=Object.keys(t.services).sort(),a=Object.keys(t.profiles).sort(),c=["start","run","exec","down","daemon","stop","restart","status","logs","doctor","setup","auth","proxy","mcp","config","reload","attach","completion","update","version"];if(i===""||o.length<2)return rn(c,r);if(i==="start"||i==="stop"||i==="restart"||i==="logs"){if(r==="--profile"||o[o.length-1]==="--profile")return rn(a,r==="--profile"?"":r);return rn([...s,"--profile","--detach","--json","--since","--until"],r)}if(i==="completion")return rn([...mw].sort(),r);if(i==="run")return rn([...Object.keys(t.tasks).sort(),"--json"],r);if(i==="exec")return rn([...s,"--print-env","--reveal","--json"],r);if(i==="auth")return rn(["status","login","logout","refresh"],r);if(i==="config")return rn(["validate","show","diff"],r);if(i==="proxy")return rn(["status","start","stop"],r);return rn(c,r)}function rn(e,t){if(t==="")return e;return e.filter((n)=>n.startsWith(t))}Su();To();function yA(){let e=new mA;return e.name("devctl").description("Local development orchestrator").version(At(),"-V, --version","print version").option("--config <path>","path to config file or .devctl directory").enablePositionalOptions(),e.command("version").description("print version").action(()=>{E(`${At()}
679
- `)}),e.action(async()=>{let t=e.opts();await Op(t.config??"")}),wA(e),SA(e),kA(e),bA(e),xA(e),_A(e),RA(e),AA(e),LA(e),DA(e),OA(e),MA(e),IA(e),FA(e),NA(e),$A(e),BA(e),HA(e),jA(e),WA(e),e}function xA(e){e.command("exec").argument("<service>","service whose execution context to use").argument("[command...]","command and arguments").option("--print-env","print the resolved environment instead of running a command").option("--reveal","show secret values with --print-env").option("--json","machine-readable output").action(async(t,n,r)=>{if(!r.printEnv&&n.length===0)throw Error("exec command is required (or use --print-env)");let o=await kt("",_e(e),!0);try{let i=await o.execService(t,n,r.printEnv===!0);if(i.environment){let s=r.reveal?i.environment:new qt(o.cfg.secrets.extra_markers,o.cfg.secrets.extra_patterns).redactMap(i.environment);if(r.json)E(JSON.stringify({...i,environment:s},null,2)+`
680
- `);else for(let a of Object.keys(s).sort())E(`${a}=${s[a]}
681
- `)}else if(r.json)E(JSON.stringify(i,null,2)+`
682
- `);else{if(i.stdout)E(i.stdout);if(i.stderr)process.stderr.write(i.stderr)}}finally{await o.close()}})}function bA(e){e.command("run").argument("<task>","task to run").option("--json","machine-readable output").action(async(t,n)=>{let r=await kt("",_e(e),!0);try{let o=await r.runTask(t);if(n.json)E(JSON.stringify(o,null,2)+`
683
- `);else{if(o.stdout)E(o.stdout);if(o.stderr)process.stderr.write(o.stderr)}}finally{await r.close()}})}function _e(e){return e.optsWithGlobals().config??""}function wA(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,n)=>{if(n.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 r=await kt("",_e(e),!0);try{let o=await r.start({services:t,profile:n.profile,detach:n.detach===!0});if(n.json){E(JSON.stringify(o,null,2)+`
684
- `);return}if(E($d(o)),n.detach)E(`detached; services continue running
685
- `)}finally{await r.close()}})}function SA(e){e.command("stop").argument("[services...]","services to stop").option("--json","machine-readable output").action(async(t,n)=>{let r=await kt("",_e(e),!0);try{if(await r.stop(t),n.json)E(JSON.stringify({stopped:t},null,2)+`
686
- `)}finally{await r.close()}})}function kA(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,n)=>{let r=await kt("",_e(e),!0);try{if(await r.restart(t,n.cascade===!0),n.json)E(JSON.stringify({restarted:t,cascade:n.cascade===!0},null,2)+`
687
- `)}finally{await r.close()}})}async function yw(e,t){let{repoRoot:n,client:r}=await id("",t.repo??"",_e(e));try{if(!r){let i=ur(n);if(t.json){E(JSON.stringify({running:!1,persisted:i},null,2)+`
688
- `);return}if(E(`supervisor is not running
689
- `),i&&i.processes.length>0){E(`last session ${i.session_id} profile ${i.profile||"(none)"}
690
- `);for(let s of i.processes)E(`${s.name} stopped UNKNOWN ${s.pid}
691
- `)}return}od(r,"status");let o=await r.call("status",null);if(t.json){E(JSON.stringify(o,null,2)+`
692
- `);return}E(`PROFILE: ${o.profile||"(none)"}
678
+ `;throw Error(`unsupported shell "${e}"; use ${xw.join(", ")}`)}function jp(e,t){let n=e.trim().split(/\s+/).filter((l)=>l!==""),r=e.endsWith(" ")?"":n[n.length-1]??"",o=e.endsWith(" ")?n:n.slice(0,-1),i=o[1]??"",s=Object.keys(t.services).sort(),a=Object.keys(t.profiles).sort(),c=["start","run","exec","down","daemon","stop","restart","status","logs","doctor","setup","auth","proxy","mcp","config","reload","attach","completion","update","version"];if(i===""||o.length<2)return rn(c,r);if(i==="start"||i==="stop"||i==="restart"||i==="logs"){if(r==="--profile"||o[o.length-1]==="--profile")return rn(a,r==="--profile"?"":r);return rn([...s,"--profile","--detach","--json","--since","--until"],r)}if(i==="completion")return rn([...xw].sort(),r);if(i==="run")return rn([...Object.keys(t.tasks).sort(),"--json"],r);if(i==="exec")return rn([...s,"--print-env","--reveal","--json"],r);if(i==="auth")return rn(["status","login","logout","refresh"],r);if(i==="config")return rn(["validate","show","diff"],r);if(i==="proxy")return rn(["status","start","stop"],r);return rn(c,r)}function rn(e,t){if(t==="")return e;return e.filter((n)=>n.startsWith(t))}Eu();Ao();function _A(){let e=new SA;return e.name("devctl").description("Local development orchestrator").version(Dt(),"-V, --version","print version").option("--config <path>","path to config file or .devctl directory").enablePositionalOptions(),e.command("version").description("print version").action(()=>{P(`${Dt()}
679
+ `)}),e.action(async()=>{let t=e.opts();await Fp(t.config??"")}),PA(e),TA(e),AA(e),RA(e),EA(e),DA(e),OA(e),FA(e),NA(e),HA(e),jA(e),BA(e),GA(e),UA(e),KA(e),WA(e),JA(e),qA(e),VA(e),zA(e),e}function EA(e){e.command("exec").argument("<service>","service whose execution context to use").argument("[command...]","command and arguments").option("--print-env","print the resolved environment instead of running a command").option("--reveal","show secret values with --print-env").option("--json","machine-readable output").action(async(t,n,r)=>{if(!r.printEnv&&n.length===0)throw Error("exec command is required (or use --print-env)");let o=await kt("",_e(e),!0);try{let i=await o.execService(t,n,r.printEnv===!0);if(i.environment){let s=r.reveal?i.environment:new Vt(o.cfg.secrets.extra_markers,o.cfg.secrets.extra_patterns).redactMap(i.environment);if(r.json)P(JSON.stringify({...i,environment:s},null,2)+`
680
+ `);else for(let a of Object.keys(s).sort())P(`${a}=${s[a]}
681
+ `)}else if(r.json)P(JSON.stringify(i,null,2)+`
682
+ `);else{if(i.stdout)P(i.stdout);if(i.stderr)process.stderr.write(i.stderr)}}finally{await o.close()}})}function RA(e){e.command("run").argument("<task>","task to run").option("--json","machine-readable output").action(async(t,n)=>{let r=await kt("",_e(e),!0);try{let o=await r.runTask(t);if(n.json)P(JSON.stringify(o,null,2)+`
683
+ `);else{if(o.stdout)P(o.stdout);if(o.stderr)process.stderr.write(o.stderr)}}finally{await r.close()}})}function _e(e){return e.optsWithGlobals().config??""}function PA(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,n)=>{if(n.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 r=await kt("",_e(e),!0);try{let o=await r.start({services:t,profile:n.profile,detach:n.detach===!0});if(n.json){P(JSON.stringify(o,null,2)+`
684
+ `);return}if(P(Gd(o)),n.detach)P(`detached; services continue running
685
+ `)}finally{await r.close()}})}function TA(e){e.command("stop").argument("[services...]","services to stop").option("--json","machine-readable output").action(async(t,n)=>{let r=await kt("",_e(e),!0);try{if(await r.stop(t),n.json)P(JSON.stringify({stopped:t},null,2)+`
686
+ `)}finally{await r.close()}})}function AA(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,n)=>{let r=await kt("",_e(e),!0);try{if(await r.restart(t,n.cascade===!0),n.json)P(JSON.stringify({restarted:t,cascade:n.cascade===!0},null,2)+`
687
+ `)}finally{await r.close()}})}async function Sw(e,t){let{repoRoot:n,client:r}=await pd("",t.repo??"",_e(e));try{if(!r){let i=pr(n);if(t.json){P(JSON.stringify({running:!1,persisted:i},null,2)+`
688
+ `);return}if(P(`supervisor is not running
689
+ `),i&&i.processes.length>0){P(`last session ${i.session_id} profile ${i.profile||"(none)"}
690
+ `);for(let s of i.processes)P(`${s.name} stopped UNKNOWN ${s.pid}
691
+ `)}return}ud(r,"status");let o=await r.call("status",null);if(t.json){P(JSON.stringify(o,null,2)+`
692
+ `);return}P(`PROFILE: ${o.profile||"(none)"}
693
693
 
694
694
  SERVICE STATUS HEALTH PID
695
- `);for(let[i,s]of Object.entries(o.services))E(`${i} ${ko(s)} ${s.health} ${s.pid}
696
- `);E(`
695
+ `);for(let[i,s]of Object.entries(o.services))P(`${i} ${Co(s)} ${s.health} ${s.pid}
696
+ `);P(`
697
697
  PROXY ${o.proxy.running?"RUNNING":"STOPPED"} ${o.proxy.address??""}
698
- `),E(`MCP ${o.mcp?.running?"RUNNING":"STOPPED"} ${o.mcp?.address??""}
699
- `),E(`IDENTITY ${o.identity.user||"(unknown)"}
700
- `),E(`CLOUD ${o.identity.project||"(unset)"}
701
- `)}finally{r?.close()}}var CA=2000;function _A(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 yw(e,t);return}let n=new AbortController,r=()=>n.abort();process.on("SIGINT",r),process.on("SIGTERM",r);try{while(!n.signal.aborted){E(`--- ${new Date().toISOString()} ---
702
- `),await yw(e,t),E(`
703
- `);try{await Fp(CA,void 0,{signal:n.signal})}catch{break}}}finally{process.off("SIGINT",r),process.off("SIGTERM",r)}})}function RA(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:n,client:r}=await id("",t.repo??"",_e(e));if(!r){E(`no supervisor is running for ${n}
704
- `);return}let o=await EA(r);try{let i=t.keepServices!==!0;await r.call("shutdown",{stop_services:i},o)}finally{r.close()}await PA(n,o),E(t.keepServices!==!0?`stopped services and the supervisor for ${n}
698
+ `),P(`MCP ${o.mcp?.running?"RUNNING":"STOPPED"} ${o.mcp?.address??""}
699
+ `),P(`IDENTITY ${o.identity.user||"(unknown)"}
700
+ `),P(`CLOUD ${o.identity.project||"(unset)"}
701
+ `)}finally{r?.close()}}var LA=2000;function DA(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 Sw(e,t);return}let n=new AbortController,r=()=>n.abort();process.on("SIGINT",r),process.on("SIGTERM",r);try{while(!n.signal.aborted){P(`--- ${new Date().toISOString()} ---
702
+ `),await Sw(e,t),P(`
703
+ `);try{await Bp(LA,void 0,{signal:n.signal})}catch{break}}}finally{process.off("SIGINT",r),process.off("SIGTERM",r)}})}function OA(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:n,client:r}=await pd("",t.repo??"",_e(e));if(!r){P(`no supervisor is running for ${n}
704
+ `);return}let o=await $A(r);try{let i=t.keepServices!==!0;await r.call("shutdown",{stop_services:i},o)}finally{r.close()}await MA(n,o),P(t.keepServices!==!0?`stopped services and the supervisor for ${n}
705
705
  `:`stopped the supervisor for ${n}; its services keep running
706
- `)})}async function PA(e,t){let n=Date.now()+t;while(Date.now()<n){let r=await vr(e);if(!r)return;r.close()}}async function EA(e){try{let n=await e.call("config_snapshot",null),r=typeof n.shutdown?.grace_seconds==="number"?n.shutdown.grace_seconds:0;return Math.max(5000,r*1000+2000)}catch{return 30000}}function xw(e){return`${e.timestamp.slice(11,19)} ${e.service.padEnd(10)} ${String(e.level).padEnd(6)} ${e.message}
707
- `}async function TA(e,t,n,r=1000){let o=await e(void 0);o.events.forEach(t);let i=o.nextCursor;while(!n.aborted){try{await Fp(r,void 0,{signal:n})}catch{return}o=await e(i),o.events.forEach(t),i=o.nextCursor}}function AA(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(n,r)=>{let o=await kt("",_e(e),!0);try{let i=r.output?_o(r.output):void 0;if(r.follow&&!i){let a=new AbortController,c=()=>a.abort();process.on("SIGINT",c),process.on("SIGTERM",c);try{await TA((l)=>o.logsPage({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,since:r.since,until:r.until,cursor:l,direction:"forward"}),(l)=>E(r.json?JSON.stringify(l)+`
708
- `:xw(l)),a.signal)}finally{process.off("SIGINT",c),process.off("SIGTERM",c)}return}let s=await o.logs({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,since:r.since,until:r.until,export:i});if(i){E(`exported ${i}
709
- `);return}if(r.json){E(JSON.stringify(s,null,2)+`
710
- `);return}for(let a of s)E(xw(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(n,r)=>{let o=await kt("",_e(e),!0);try{let i=_o(r.output);await o.logs({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,export:i}),E(`exported ${i}
711
- `)}finally{await o.close()}})}function LA(e){e.command("daemon").command("logs").option("-f, --follow","keep printing new lines until interrupted").action(async(t)=>{let{repoRoot:n}=jn("",_e(e)),r=dr(n),o=0,i=()=>{if(!vw(r))return;let c=vA(r,"utf8");if(c.length>o)E(c.slice(o)),o=c.length};if(!vw(r))E(`no daemon bootstrap log yet for this repository
712
- `);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 Fp(500,void 0,{signal:s.signal})}catch{break}i()}}finally{process.off("SIGINT",a),process.off("SIGTERM",a)}})}function DA(e){e.command("doctor").option("--json","machine-readable output").action(async(t)=>{let n=ut("",_e(e)),r=await Un(n);if(t.json)E(JSON.stringify(r,null,2)+`
713
- `);else E(ya(r));if(r.issues>0)process.exitCode=2})}function OA(e){e.command("setup").option("--force","overwrite an existing configuration").action(async(t)=>{await Hd("",_e(e),t.force===!0)})}function MA(e){let t=e.command("auth").description("Google authentication");t.command("status").option("--json","machine-readable output").action(async(n)=>{let r="";try{r=ut("",_e(e)).google.project_id}catch{r=""}let o=await Lt(r);if(n.json){E(JSON.stringify(o,null,2)+`
714
- `);return}if(E(`User: ${o.userEmail||"(unknown)"}
715
- `),E(`Project: ${o.projectID||"(unset)"}
716
- `),o.projectID!=="")E(`Source: ${o.projectSource}
717
- `);E(`ADC: ${o.adcAvailable}
718
- `),E(`gcloud: ${o.gcloudInstalled}
719
- `)}),t.command("login").action(async()=>{await go()}),t.command("logout").action(async()=>{await sa()}),t.command("refresh").option("--json","machine-readable output").action(async(n)=>{let r=await kt("",_e(e),!1);try{let i=await new bo(js(r.cfg.auth)*1000,Cr()).refresh("user","",[]),s=r.client?await r.refreshAuth():void 0;if(n.json){E(JSON.stringify({identity:i.identity,expires_at:i.expiresAt.toISOString(),service_account_status:s?.service_account_status??{}},null,2)+`
720
- `);return}if(E(`refreshed credentials expire ${i.expiresAt.toISOString()}
721
- `),s)for(let[a,c]of Object.entries(s.service_account_status).sort(([l],[d])=>l.localeCompare(d)))E(`service account ${a}: ${c}
722
- `)}finally{await r.close()}})}function $A(e){e.command("reload").description("reload configuration").action(async()=>{let t=await kt("",_e(e),!0);try{let n=await t.reload();if(n.restart_required.length===0)E(`configuration reloaded
723
- `);else E(`configuration reloaded; restart required: ${n.restart_required.join(", ")}
724
- `);if(n.supervisor_restart_required&&n.supervisor_restart_required.length>0)E(`note: ${ba(n.supervisor_restart_required)}
725
- `)}finally{await t.close()}})}function IA(e){let t=e.command("proxy");t.command("status").option("--json").action(async(n)=>{let r=await kt("",_e(e),!1);try{if(!r.client){E(`PROXY STOPPED
726
- `);return}let o=await r.status();if(n.json){E(JSON.stringify(o.proxy,null,2)+`
727
- `);return}E(`PROXY ${o.proxy.running?"RUNNING":"STOPPED"} ${o.proxy.address??""}
728
- `);for(let i of o.proxy.routes??[]){let s=i.match?` match=${i.match}`:"";E(` ${i.name.padEnd(16)} identity=${i.identity}${s} ${i.upstream}
729
- `)}}finally{await r.close()}}),t.command("start").action(async()=>{let n=await kt("",_e(e),!0);try{await n.proxyStart()}finally{await n.close()}}),t.command("stop").action(async()=>{let n=await kt("",_e(e),!0);try{await n.proxyStop()}finally{await n.close()}})}function FA(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 n=t.port===void 0?void 0:Number(t.port);if(t.port!==void 0&&(!Number.isInteger(n)||(n??0)<=0))throw Error(`invalid --port ${t.port}`);let r=await kt("",_e(e),t.on===!0,{allowMissingConfig:!0});try{if(t.off===!0&&r.client)await r.mcpStop();else if(t.on===!0)await r.mcpStart({port:n});let o=r.client?await r.status():void 0,i=Qt(r.cfg.repoRoot,r.cfg.ui.keymap),s=o?.mcp?.port??n??i.mcp_port??Lo(r.cfg.repoRoot),a=o?.mcp?.address??Do(s),c=o?.mcp?.token??"";if(t.json){E(JSON.stringify({running:o?.mcp?.running===!0,setup_mode:o?.setup_mode===!0,url:a,port:s,snippets:{claude:JSON.parse(hu(a,c)),cursor:JSON.parse(vu(a,c)),kilo:JSON.parse(yu(a,c)),codex:xu(a,c)}},null,2)+`
730
- `);return}if(E(`MCP ${o?.mcp?.running?"RUNNING":"STOPPED"} ${a}
731
-
732
- `),o?.setup_mode===!0)E(`This repository has no .devctl yet, so the daemon is in setup mode.
733
- `),E(`Connect an agent with the config below and ask it to set devctl up for this repository.
734
- `),E(`It can call get_setup_guide and validate_config; nothing will run until a configuration exists.
735
-
736
- `);E(mv(a,c))}finally{await r.close()}})}function NA(e){let t=e.command("config");t.command("validate").option("--json").action((n)=>{try{let r=ut("",_e(e)),o=Xt(r);if(n.json){E(JSON.stringify({valid:o.length===0,issues:o},null,2)+`
706
+ `)})}async function MA(e,t){let n=Date.now()+t;while(Date.now()<n){let r=await yr(e);if(!r)return;r.close()}}async function $A(e){try{let n=await e.call("config_snapshot",null),r=typeof n.shutdown?.grace_seconds==="number"?n.shutdown.grace_seconds:0;return Math.max(5000,r*1000+2000)}catch{return 30000}}function kw(e){return`${e.timestamp.slice(11,19)} ${e.service.padEnd(10)} ${String(e.level).padEnd(6)} ${e.message}
707
+ `}async function IA(e,t,n,r=1000){let o=await e(void 0);o.events.forEach(t);let i=o.nextCursor;while(!n.aborted){try{await Bp(r,void 0,{signal:n})}catch{return}o=await e(i),o.events.forEach(t),i=o.nextCursor}}function FA(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(n,r)=>{let o=await kt("",_e(e),!0);try{let i=r.output?Eo(r.output):void 0;if(r.follow&&!i){let a=new AbortController,c=()=>a.abort();process.on("SIGINT",c),process.on("SIGTERM",c);try{await IA((l)=>o.logsPage({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,since:r.since,until:r.until,cursor:l,direction:"forward"}),(l)=>P(r.json?JSON.stringify(l)+`
708
+ `:kw(l)),a.signal)}finally{process.off("SIGINT",c),process.off("SIGTERM",c)}return}let s=await o.logs({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,since:r.since,until:r.until,export:i});if(i){P(`exported ${i}
709
+ `);return}if(r.json){P(JSON.stringify(s,null,2)+`
710
+ `);return}for(let a of s)P(kw(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(n,r)=>{let o=await kt("",_e(e),!0);try{let i=Eo(r.output);await o.logs({services:n,level:r.level,search:r.search,regex:r.regex,source:r.source,export:i}),P(`exported ${i}
711
+ `)}finally{await o.close()}})}function NA(e){e.command("daemon").command("logs").option("-f, --follow","keep printing new lines until interrupted").action(async(t)=>{let{repoRoot:n}=jn("",_e(e)),r=ur(n),o=0,i=()=>{if(!ww(r))return;let c=CA(r,"utf8");if(c.length>o)P(c.slice(o)),o=c.length};if(!ww(r))P(`no daemon bootstrap log yet for this repository
712
+ `);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 Bp(500,void 0,{signal:s.signal})}catch{break}i()}}finally{process.off("SIGINT",a),process.off("SIGTERM",a)}})}function HA(e){e.command("doctor").option("--json","machine-readable output").action(async(t)=>{let n=ut("",_e(e)),r=await Un(n);if(t.json)P(JSON.stringify(r,null,2)+`
713
+ `);else P(wa(r));if(r.issues>0)process.exitCode=2})}function jA(e){e.command("setup").option("--force","overwrite an existing configuration").action(async(t)=>{await Vd("",_e(e),t.force===!0)})}function BA(e){let t=e.command("auth").description("Google authentication");t.command("status").option("--json","machine-readable output").action(async(n)=>{let r="";try{r=ut("",_e(e)).google.project_id}catch{r=""}let o=await Ot(r);if(n.json){P(JSON.stringify(o,null,2)+`
714
+ `);return}if(P(`User: ${o.userEmail||"(unknown)"}
715
+ `),P(`Project: ${o.projectID||"(unset)"}
716
+ `),o.projectID!=="")P(`Source: ${o.projectSource}
717
+ `);P(`ADC: ${o.adcAvailable}
718
+ `),P(`gcloud: ${o.gcloudInstalled}
719
+ `)}),t.command("login").action(async()=>{await mo()}),t.command("logout").action(async()=>{await la()}),t.command("refresh").option("--json","machine-readable output").action(async(n)=>{let r=await kt("",_e(e),!1);try{let i=await new wo(Gs(r.cfg.auth)*1000,_r()).refresh("user","",[]),s=r.client?await r.refreshAuth():void 0;if(n.json){P(JSON.stringify({identity:i.identity,expires_at:i.expiresAt.toISOString(),service_account_status:s?.service_account_status??{}},null,2)+`
720
+ `);return}if(P(`refreshed credentials expire ${i.expiresAt.toISOString()}
721
+ `),s)for(let[a,c]of Object.entries(s.service_account_status).sort(([l],[d])=>l.localeCompare(d)))P(`service account ${a}: ${c}
722
+ `)}finally{await r.close()}})}function WA(e){e.command("reload").description("reload configuration").action(async()=>{let t=await kt("",_e(e),!0);try{let n=await t.reload();if(n.restart_required.length===0)P(`configuration reloaded
723
+ `);else P(`configuration reloaded; restart required: ${n.restart_required.join(", ")}
724
+ `);if(n.supervisor_restart_required&&n.supervisor_restart_required.length>0)P(`note: ${ka(n.supervisor_restart_required)}
725
+ `)}finally{await t.close()}})}function GA(e){let t=e.command("proxy");t.command("status").option("--json").action(async(n)=>{let r=await kt("",_e(e),!1);try{if(!r.client){P(`PROXY STOPPED
726
+ `);return}let o=await r.status();if(n.json){P(JSON.stringify(o.proxy,null,2)+`
727
+ `);return}P(`PROXY ${o.proxy.running?"RUNNING":"STOPPED"} ${o.proxy.address??""}
728
+ `);for(let i of o.proxy.routes??[]){let s=i.match?` match=${i.match}`:"";P(` ${i.name.padEnd(16)} identity=${i.identity}${s} ${i.upstream}
729
+ `)}}finally{await r.close()}}),t.command("start").action(async()=>{let n=await kt("",_e(e),!0);try{await n.proxyStart()}finally{await n.close()}}),t.command("stop").action(async()=>{let n=await kt("",_e(e),!0);try{await n.proxyStop()}finally{await n.close()}})}function UA(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 n=t.port===void 0?void 0:Number(t.port);if(t.port!==void 0&&(!Number.isInteger(n)||(n??0)<=0))throw Error(`invalid --port ${t.port}`);let r=await kt("",_e(e),t.on===!0,{allowMissingConfig:!0});try{if(t.off===!0&&r.client)await r.mcpStop();else if(t.on===!0)await r.mcpStart({port:n});let o=r.client?await r.status():void 0,i=Qt(r.cfg.repoRoot,r.cfg.ui.keymap),s=o?.mcp?.port??n??i.mcp_port??Do(r.cfg.repoRoot),a=o?.mcp?.address??Oo(s),c=o?.mcp?.token??"";if(t.json){P(JSON.stringify({running:o?.mcp?.running===!0,setup_mode:o?.setup_mode===!0,url:a,port:s,snippets:{claude:JSON.parse(bu(a,c)),cursor:JSON.parse(wu(a,c)),kilo:JSON.parse(Su(a,c)),codex:ku(a,c)}},null,2)+`
730
+ `);return}if(P(`MCP ${o?.mcp?.running?"RUNNING":"STOPPED"} ${a}
731
+
732
+ `),o?.setup_mode===!0)P(`This repository has no .devctl yet, so the daemon is in setup mode.
733
+ `),P(`Connect an agent with the config below and ask it to set devctl up for this repository.
734
+ `),P(`It can call get_setup_guide and validate_config; nothing will run until a configuration exists.
735
+
736
+ `);P(xv(a,c))}finally{await r.close()}})}function KA(e){let t=e.command("config");t.command("validate").option("--json").action((n)=>{try{let r=ut("",_e(e)),o=Xt(r);if(n.json){P(JSON.stringify({valid:o.length===0,issues:o},null,2)+`
737
737
  `);return}if(o.length>0)throw Error(o.join(`
738
- `));E(`configuration is valid
739
- `)}catch(r){if(n.json){E(JSON.stringify({valid:!1,error:F(r)},null,2)+`
740
- `);return}throw r}}),t.command("diff").description("show where effective configuration values came from").option("--json").action((n)=>{let r=ut("",_e(e)),o=hr(r);if(n.json){E(JSON.stringify({entries:o},null,2)+`
741
- `);return}for(let i of o){E(`${i.path} = ${JSON.stringify(i.value)}
742
- `),E(` winner: ${i.layer} (${i.source})
743
- `);for(let s of i.shadowed)E(` shadowed: ${s.layer} (${s.source})
744
- `)}}),t.command("show").option("--json").action((n)=>{let r=ut("",_e(e));if(n.json){E(JSON.stringify(r,null,2)+`
745
- `);return}E(hA(r))})}function HA(e){e.command("completion").argument("[shell]","zsh, bash, or fish").description("print a shell completion script").action((t)=>{E(hw(t||"zsh"))}),e.command("__complete",{hidden:!0}).argument("[line...]").description("internal completion helper").action((t)=>{let n=t.join(" "),r=n===""?"devctl ":n;try{let o=ut("",_e(e));E(Ip(r,o).join(`
738
+ `));P(`configuration is valid
739
+ `)}catch(r){if(n.json){P(JSON.stringify({valid:!1,error:O(r)},null,2)+`
740
+ `);return}throw r}}),t.command("diff").description("show where effective configuration values came from").option("--json").action((n)=>{let r=ut("",_e(e)),o=vr(r);if(n.json){P(JSON.stringify({entries:o},null,2)+`
741
+ `);return}for(let i of o){P(`${i.path} = ${JSON.stringify(i.value)}
742
+ `),P(` winner: ${i.layer} (${i.source})
743
+ `);for(let s of i.shadowed)P(` shadowed: ${s.layer} (${s.source})
744
+ `)}}),t.command("show").option("--json").action((n)=>{let r=ut("",_e(e));if(n.json){P(JSON.stringify(r,null,2)+`
745
+ `);return}P(kA(r))})}function qA(e){e.command("completion").argument("[shell]","zsh, bash, or fish").description("print a shell completion script").action((t)=>{P(bw(t||"zsh"))}),e.command("__complete",{hidden:!0}).argument("[line...]").description("internal completion helper").action((t)=>{let n=t.join(" "),r=n===""?"devctl ":n;try{let o=ut("",_e(e));P(jp(r,o).join(`
746
746
  `)+`
747
- `)}catch{E(Ip(r,pr()).join(`
747
+ `)}catch{P(jp(r,fr()).join(`
748
748
  `)+`
749
- `)}})}function jA(e){e.command("update").description("check GitHub Releases for a newer version").option("--json","machine-readable output").action(async(t)=>{let n=await Vi();if(t.json){E(JSON.stringify(n,null,2)+`
750
- `);return}if(E(`current ${n.current}
751
- `),E(`latest ${n.latest||"(unavailable)"}
752
- `),n.newer)E(`install ${n.hint}
753
- `);else if(n.latest!=="")E(`up to date
754
- `)})}function BA(e){e.command("attach").action(async()=>{let t=await am("",_e(e)),{runTuiWithController:n}=await Promise.resolve().then(() => ($p(),gw));await n(t)})}function WA(e){e.command("_supervisor").option("--repo <path>","repository root").action(async(t)=>{let n=yi(t.repo??"",_e(e)),r=new gu(n),o=!1,i=()=>{if(o)return;o=!0,r.shutdown(Bs(n.shutdown)).finally(()=>process.exit(0))};process.on("SIGINT",i),process.on("SIGTERM",i),await r.run()})}async function bw(){process.stdout.on("error",(e)=>{if(e.code==="EPIPE")process.exit(0)});try{await yA().parseAsync(process.argv)}catch(e){process.stderr.write(F(e)+`
755
- `),process.exit(Df(e))}}function E(e){try{process.stdout.write(e)}catch(t){if(t.code==="EPIPE")process.exit(0);throw t}}Ds();await bw();
749
+ `)}})}function VA(e){e.command("update").description("check GitHub Releases for a newer version").option("--json","machine-readable output").action(async(t)=>{let n=await Yi();if(t.json){P(JSON.stringify(n,null,2)+`
750
+ `);return}if(P(`current ${n.current}
751
+ `),P(`latest ${n.latest||"(unavailable)"}
752
+ `),n.newer)P(`install ${n.hint}
753
+ `);else if(n.latest!=="")P(`up to date
754
+ `)})}function JA(e){e.command("attach").action(async()=>{let t=await um("",_e(e)),{runTuiWithController:n}=await Promise.resolve().then(() => (Hp(),yw));await n(t)})}function zA(e){e.command("_supervisor").option("--repo <path>","repository root").action(async(t)=>{let n=yi(t.repo??"",_e(e)),r=new yu(n),o=!1,i=()=>{if(o)return;o=!0,r.shutdown(Us(n.shutdown)).finally(()=>process.exit(0))};process.on("SIGINT",i),process.on("SIGTERM",i),await r.run()})}async function Cw(){process.stdout.on("error",(e)=>{if(e.code==="EPIPE")process.exit(0)});try{await _A().parseAsync(process.argv)}catch(e){process.stderr.write(O(e)+`
755
+ `),process.exit(If(e))}}function P(e){try{process.stdout.write(e)}catch(t){if(t.code==="EPIPE")process.exit(0);throw t}}$s();await Cw();