@vibecontrols/agent 2026.601.30 → 2026.602.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-yvjadjmh.js → app-jeyyhz7s.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/index-5t4t0avg.js +26 -0
- package/dist/{index-3ys16efc.js → index-c4xqp05z.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{register-core-qrawzyym.js → register-core-mbv4hrbv.js} +1 -1
- package/package.json +1 -1
- package/dist/index-c58g96mb.js +0 -26
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{n as a}from"./index-
|
|
2
|
+
import{n as a}from"./index-5t4t0avg.js";import"./index-n7qyrdr1.js";import"./index-1hnw0rhc.js";import"./index-6jzsthh9.js";import"./index-g8zv1gta.js";import"./index-qfz9fy56.js";import"./index-ssjmzqcz.js";import"./index-tp4y9jde.js";import"./index-4wgjx8bf.js";import"./index-g3ap3xpr.js";import"./index-0ckffygp.js";import"./index-rc79x8fw.js";import"./index-yrgm89r8.js";import"./index-52cp759f.js";import"./index-v9fx5wab.js";import"./index-01qzsnwd.js";import"./index-d5ysy1yn.js";import"./index-04n4qgvd.js";import"./index-xjzmb1pn.js";import"./index-g2raeeh4.js";import"./index-9bqd8veb.js";import"./index-0cn9bv8z.js";import"./index-jw1k4vbk.js";import"./index-yy1mm8zs.js";export{a as createApp};
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{H as O}from"./index-mxc61yr1.js";import{I as Q,J as w}from"./index-
|
|
3
|
+
import{H as O}from"./index-mxc61yr1.js";import{I as Q,J as w}from"./index-c4xqp05z.js";import"./index-2gsarrbn.js";import"./index-b5dhmybd.js";import"./index-e1bw1bwr.js";import"./index-g8zv1gta.js";import"./index-qfz9fy56.js";import"./index-ssjmzqcz.js";import{wa as Z,za as I}from"./index-tp4y9jde.js";import{Aa as G,Ba as H}from"./index-4wgjx8bf.js";import{Wa as J}from"./index-g3ap3xpr.js";import{Xa as U}from"./index-0ckffygp.js";import"./index-rc79x8fw.js";import{bb as K}from"./index-yrgm89r8.js";import"./index-52cp759f.js";import"./index-01qzsnwd.js";import"./index-d5ysy1yn.js";import"./index-04n4qgvd.js";import{cc as $}from"./index-2xs9cvjn.js";import"./index-5mw3eshk.js";import{mc as E}from"./index-z5a4yxzz.js";import"./index-ef95xr4z.js";import"./index-xjzmb1pn.js";import"./index-g2raeeh4.js";import{Nd as Y}from"./index-9bqd8veb.js";import{_d as W,ce as X}from"./index-0cn9bv8z.js";import"./index-jw1k4vbk.js";import"./index-yy1mm8zs.js";import{join as B}from"path";if(typeof Bun>"u")console.error(`\x1B[31mError:\x1B[0m VibeControls Agent requires the Bun runtime.
|
|
4
4
|
Install Bun: https://bun.sh
|
|
5
5
|
Then run: bun run vibe ...`),process.exit(1);var T=process.argv.slice(2),_=T.includes("--plain")||T.includes("--json")||process.env.NO_COLOR==="1"||!process.stdout.isTTY;E(!_);try{O()}catch{}var N="1.0.0";try{let q=B(import.meta.dir,"..","package.json");N=(await Bun.file(q).json()).version}catch{}var x=new $;x.name("vibe").description("VibeControls Agent CLI \u2014 Remote development environment management").version(N,"-v, --version").option("--provider <name>","Override the default provider for tunnel/session operations").option("-p, --profile <name>","Target a specific profile (one-off; doesn't change the persisted default). See `vibe profile`.").option("--json","Emit machine-readable JSON instead of human output.").option("--plain","Force plain-text output (no interactive UI).").hook("preAction",(q,z)=>{let F=q.opts().profile;if(F)process.env.VIBECONTROLS_PROFILE=F;try{K.init(),K.emit("command.executed",{command_name:z.name()})}catch{}});w(x);async function M(){let q=new J;try{await q.loadCorePlugins()}catch{}try{await q.loadAll()}catch{}let z=new Z,F={storage:{async get(){return null},async set(){},async delete(){return!1},async list(){return[]},async deleteAll(){return 0}},logger:Y().logger,serviceRegistry:z,getProvider:(L)=>z.getProvider(L),getAgentBaseUrl:()=>process.env.AGENT_URL||"http://localhost:3005",getAgentVersion:()=>N,broadcast:()=>{},workspaceQuery:async()=>({data:void 0,errors:[{message:"workspaceQuery is not available in CLI mode"}]}),isGatewayConfigured:()=>!1,getAgentRecordId:async()=>null,getWorkspaceId:async()=>null,getConfig:async()=>{return},getPluginRegistry:()=>X(),getDataDir:()=>W(),cliContributors:new G,telemetry:{emit:(L,D)=>{try{K.emit(L,D??{})}catch{}}},os:U(),iframeBridge:I()};H(F.cliContributors);try{await q.dispatchCliSetup(x,F)}catch{}x.configureHelp({formatHelp:()=>Q(x,!0)}),await x.parseAsync()}M().then(()=>{process.exit(process.exitCode??0)}).catch((q)=>{console.error(`\x1B[31mFatal:\x1B[0m ${q instanceof Error?q.message:q}`),process.exit(1)});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{o as V4,q as $4}from"./index-n7qyrdr1.js";import{u as a4,v as L5,w as O5}from"./index-1hnw0rhc.js";import{E as B4}from"./index-6jzsthh9.js";import{$ as b4,Q as T5,aa as K2,ba as j0,ca as v4,da as y4,ea as d4,fa as P4,ha as E2,ia as g2,ja as n2,ka as C2}from"./index-g8zv1gta.js";import{la as E5,qa as C5,sa as T0}from"./index-qfz9fy56.js";import{va as f2}from"./index-ssjmzqcz.js";import{wa as N5,xa as j5,ya as U5,za as x5}from"./index-tp4y9jde.js";import{Aa as F5}from"./index-4wgjx8bf.js";import{Ja as M0,Wa as M5}from"./index-g3ap3xpr.js";import{Xa as _2}from"./index-0ckffygp.js";import{ab as h2}from"./index-rc79x8fw.js";import{eb as e4,fb as Y5,gb as W5,hb as z5,ib as H5,jb as J2,kb as G5,lb as B5,mb as V5,nb as K5,pb as _5}from"./index-v9fx5wab.js";import{Ab as d0,Eb as U2,Fb as X0,Gb as $5,Hb as Z5,Ib as O0,Jb as x2,Kb as m,Lb as l,Mb as p4,Nb as l4,Ob as J5,Pb as X5,tb as g0,ub as D2,vb as p0,wb as J0,xb as l0,yb as Q5}from"./index-01qzsnwd.js";import{Tb as z,Ub as D}from"./index-04n4qgvd.js";import{md as r0,nd as s,od as m0,pd as P2,qd as S2}from"./index-g2raeeh4.js";import{Cd as d2,Hd as g,Jd as x0,Kd as b,Ld as a,Nd as G,Od as Y0,vd as U0,wd as s4,xd as r4,yd as t4,zd as G2}from"./index-9bqd8veb.js";import{Rd as a0,Sd as z0,Ud as v2,Vd as s0,Xd as T2,Yd as d,_d as k2,ae as M2,be as V2,ce as l2}from"./index-0cn9bv8z.js";import{ee as D0,he as f}from"./index-yy1mm8zs.js";var R0=typeof new Headers()?.toJSON==="function",A5=($)=>{if(R0)return Object.keys($.toJSON()).join(", ");let Z="",Q=0;return $.forEach((Y,X)=>{if(Q)Z=Z+", "+X;else Z=X;Q++}),Z},A0=($)=>{let{aot:Z=!0,origin:Q=!0,methods:Y=!0,allowedHeaders:X=!0,exposeHeaders:J=!0,credentials:W=!0,maxAge:H=5,preflight:B=!0}=$??{};if(Array.isArray(X))X=X.join(", ");if(Array.isArray(J))J=J.join(", ");let K=typeof Q==="boolean"?void 0:Array.isArray(Q)?Q:[Q],N=new D({name:"@elysiajs/cors",seed:$,aot:Z}),I=K?.some((F)=>F==="*"),C={};if(K){for(let F of K)if(typeof F==="string")C[F]=!0}let U=(F,T,x)=>{if(Array.isArray(F))return F.some((q)=>U(q,T,x));switch(typeof F){case"string":if(x in C)return!0;let q=x.indexOf("://");if(q!==-1)x=x.slice(q+3);return F===x;case"function":return F(T)===!0;case"object":if(F instanceof RegExp)return F.test(x)}return!1},V=(F,T)=>{if(Q===!0){F.headers.vary="*",F.headers["access-control-allow-origin"]=T.headers.get("Origin")||"*";return}if(I){F.headers.vary="*",F.headers["access-control-allow-origin"]="*";return}if(!K?.length)return;if(K.length){let x=T.headers.get("Origin")??"";for(let q=0;q<K.length;q++)if(U(K[q],T,x)===!0){F.headers.vary=Q?"Origin":"*",F.headers["access-control-allow-origin"]=x||"*";return}}F.headers.vary="Origin"},E=(F,T)=>{if(!T)return;if(Y===!0)return F.headers["access-control-allow-methods"]=T??"*";if(Y===!1||!Y?.length)return;if(Y==="*")return F.headers["access-control-allow-methods"]="*";if(!Array.isArray(Y))return F.headers["access-control-allow-methods"]=Y;F.headers["access-control-allow-methods"]=Y.join(", ")},R={};if(typeof J==="string")R["access-control-expose-headers"]=J;if(typeof X==="string")R["access-control-allow-headers"]=X;if(W===!0)R["access-control-allow-credentials"]="true";N.headers(R);function h({set:F,request:T,headers:x}){if(V(F,T),E(F,T.headers.get("access-control-request-method")),X===!0||J===!0){if(X===!0)F.headers["access-control-allow-headers"]=x["access-control-request-headers"];if(J===!0)F.headers["access-control-expose-headers"]=Object.keys(x).join(",")}if(H)F.headers["access-control-max-age"]=H.toString();return new Response(null,{status:204})}if(B)N.options("/",h).options("/*",h);return N.onRequest(function({set:T,request:x}){if(V(T,x),B&&x.method==="OPTIONS")return h({set:T,request:x,headers:R0?x.headers.toJSON():Object.fromEntries(x.headers.entries())});if(E(T,x.method),X===!0||J===!0){let q=A5(x.headers);if(X===!0)T.headers["access-control-allow-headers"]=q;if(J===!0)T.headers["access-control-expose-headers"]=q}})};import{createHash as k0}from"crypto";var Y2="idempotency",w5=300000,w0=1e4,R2=new Map;function k5($,Z,Q,Y){return k0("sha256").update(`${$}|${Z}|${Q}|${Y}`).digest("hex")}async function S5($,Z){let Q=await $.getPluginState(Y2,Z);if(!Q)return null;try{let Y=JSON.parse(Q);if(Y.expiresAt<Date.now())return await $.deletePluginState(Y2,Z),null;return Y}catch{return null}}async function D5($,Z,Q){await $.setPluginState(Y2,Z,JSON.stringify(Q))}async function h5($){let Z=await $.getAllPluginState(Y2),Q=Date.now(),Y=0,X=[];for(let J of Z)try{if(JSON.parse(J.value).expiresAt<Q)await $.deletePluginState(Y2,J.key),Y+=1;else X.push({key:J.key,updatedAt:J.updatedAt})}catch{await $.deletePluginState(Y2,J.key),Y+=1}if(X.length>w0){X.sort((W,H)=>(W.updatedAt??"").localeCompare(H.updatedAt??""));let J=X.slice(0,X.length-w0);for(let W of J)await $.deletePluginState(Y2,W.key),Y+=1}if(Y>0)G().logger.info("idempotency",`Swept ${Y} expired/over-cap entries`)}var e2=null,v5=600000;function P5($){if(e2)return;e2=setInterval(()=>{let Z=$.getDb();if(!Z)return;h5(Z).catch((Q)=>{G().logger.warn("idempotency","Sweep failed",{error:String(Q)})})},v5),e2.unref?.()}function S0($){return P5($),new D({name:"plugin/idempotency"}).onBeforeHandle(async({request:Z,path:Q,set:Y,store:X})=>{if(Z.method!=="POST"&&Z.method!=="PUT")return;let J=Z.headers.get("x-idempotency-key")??Z.headers.get("X-Idempotency-Key");if(!J)return;if(J.length<8||J.length>200)return Y.status=400,{error:"X-Idempotency-Key must be 8\u2013200 chars",code:"BAD_REQUEST"};let W=$.getDb();if(!W)return;let H="no-body";try{let E=await Z.clone().text();H=k0("sha256").update(E).digest("hex")}catch{}let B=k5(Z.method,Q,J,H),K=await S5(W,B);if(K){Y.status=K.status;let V=Y.headers??={};V["Content-Type"]=K.contentType,V["X-Idempotency-Replay"]="true",X.__idemReplay=K.body;try{return JSON.parse(K.body)}catch{return K.body}}let N=R2.get(B);if(N){let V=await N.catch(()=>null);if(V){Y.status=V.status;let E=Y.headers??={};E["Content-Type"]=V.contentType,E["X-Idempotency-Replay"]="true",X.__idemReplay=V.body;try{return JSON.parse(V.body)}catch{return V.body}}}let I,C,U=new Promise((V,E)=>{I=V,C=E});R2.set(B,U),X.__idemKey=B,X.__idemResolve=I,X.__idemReject=C}).onAfterHandle(async({response:Z,set:Q,store:Y})=>{let X=Y.__idemKey;if(!X)return;let J=Y.__idemResolve,W=$.getDb(),H=Q.status??200,B=typeof Z==="string"?Z:JSON.stringify(Z),N=Q.headers?.["Content-Type"]??"application/json",I={status:H,body:B,contentType:N,expiresAt:Date.now()+w5},C=H>=200&&H<300;try{if(W&&C)await D5(W,X,I)}catch(U){G().logger.warn("idempotency","Failed to persist response",{error:String(U)})}finally{try{J?.(C?I:null)}catch{}R2.delete(X)}}).onError(({store:Z})=>{let Q=Z.__idemKey;if(!Q)return;let Y=Z.__idemReject;try{Y?.(Error("idempotency: handler errored"))}catch{}R2.delete(Q)}).as("global")}import u from"os";import{readFileSync as s5}from"fs";import{join as r5}from"path";var h0={enabled:!1,async scrape(){return`# vibecontrols agent metrics disabled (OTel SDK not initialised)
|
|
3
|
+
`},recordHttpRequest(){},setPluginsLoaded(){}},$2=null,A2=null;async function w2($){if($2)return $2;if(A2)return A2;return A2=(async()=>{try{let{MeterProvider:Z}=await import("./index-hrdamx5j.js").then((m)=>D0(m.default,1)),{PrometheusExporter:Q,PrometheusSerializer:Y}=await import("./index-1zw3kea7.js").then((m)=>D0(m.default,1)),X=new Q({preventServerStart:!0}),J=new Y,H=new Z({readers:[X]}).getMeter("vibecontrols-agent"),B=H.createGauge("vibecontrols_agent_info",{description:"Static info about the agent process; value is always 1."});H.createObservableGauge("vibecontrols_agent_uptime_seconds",{description:"Process uptime in seconds."}).addCallback((V)=>{V.observe(process.uptime())});let N=H.createCounter("vibecontrols_http_requests_total",{description:"Total HTTP requests handled by the agent, labelled by method, route, status."}),I={};H.createObservableGauge("vibecontrols_plugins_loaded",{description:"Plugins loaded by the agent, broken down by status (loaded, failed, etc.)."}).addCallback((V)=>{for(let[E,R]of Object.entries(I))V.observe(R,{status:E})}),B.record(1,{version:$?.version??"unknown",profile:$?.profile??"default"});let U={enabled:!0,async scrape(){let V=await X.collect();if(!V.resourceMetrics)return"";return J.serialize(V.resourceMetrics)},recordHttpRequest(V,E,R){N.add(1,{method:V,route:E,status:String(R)})},setPluginsLoaded(V){I={...V}}};return $2=U,G().logger.info("metrics","OTel Prometheus registry initialised"),U}catch(Z){return G().logger.warn("metrics","Failed to initialise OTel metrics; /metrics will return a stub body",{error:Z instanceof Error?Z.message:String(Z)}),$2=h0,h0}})(),A2}function v0($,Z,Q){if(!$2)return;$2.recordHttpRequest($,Z,Q)}function P0($){if(!$2)return;$2.setPluginsLoaded($)}var f5=new Set(["127.0.0.1","::1"]),f0=!1;function b5(){if(f0)return;if(process.env.METRICS_ANONYMOUS_LOCALHOST==="true")f0=!0,G().logger.warn("metrics","METRICS_ANONYMOUS_LOCALHOST=true \u2014 /metrics is open to TCP loopback peers without an API key. Prefer issuing a scoped API key for your scraper.")}function y5($){let Z=$.replace(/^\[|\]$/g,"");if(Z.startsWith("::ffff:"))return Z.slice(7);return Z}function Q0($,Z){let Q=Z?.requestIP($)?.address;if(!Q)return!1;return f5.has(y5(Q))}function b0(){return b5(),new D({name:"routes/metrics"}).get("/metrics",async({request:$,server:Z,set:Q})=>{if(!(process.env.METRICS_ANONYMOUS_LOCALHOST==="true"&&Q0($,Z))){let W=m(Object.fromEntries($.headers.entries()));if(!l(W))return Q.status=401,Q.headers["content-type"]="application/json",JSON.stringify({error:"Unauthorized",message:"Invalid or missing API key"})}let J=await(await w2()).scrape();return Q.headers["content-type"]="text/plain; version=0.0.4; charset=utf-8",J})}import{randomBytes as c5,timingSafeEqual as u5}from"crypto";import{chmodSync as m5,existsSync as y0,mkdirSync as g5,readFileSync as p5,unlinkSync as l5,writeFileSync as d5}from"fs";import{dirname as n5,join as i5}from"path";var W2=null;function c0(){return i5(k2(),"pairing-token")}function o5(){return c5(32).toString("base64url")}function a5($,Z){let Q=Buffer.from($),Y=Buffer.from(Z);if(Q.length!==Y.length)return!1;try{return u5(Q,Y)}catch{return!1}}function X6(){if(W2)return W2;let $=c0();try{if(y0($)){let Q=p5($,"utf8").trim();if(Q.length>=32)return W2=Q,Q}}catch{}let Z=o5();try{g5(n5($),{recursive:!0}),d5($,Z,{encoding:"utf8"});try{m5($,384)}catch{}}catch(Q){}return W2=Z,Z}function $0($){if(!$)return!1;if(!W2)return!1;return a5($,W2)}function u0(){W2=null;try{let $=c0();if(y0($))l5($)}catch{}}function Z0($){return $["x-pairing-token"]??$["X-Pairing-Token"]??null}function t5(){let $=u.hostname(),Z=u.platform(),Q=u.arch(),Y=new Bun.CryptoHasher("sha256");return Y.update(`${$}-${Z}-${Q}`),Y.digest("hex").substring(0,16)}function e5(){for(let $ of["..","../.."])try{let Z=r5(import.meta.dir,$,"package.json"),Y=JSON.parse(s5(Z,"utf8")).version;if(Y)return Y}catch{}return"0.0.0"}async function QQ($){let Z=[],Q=$.getProvider("tunnel");if(Q)Z.push(Q);for(let Y of $.listProvidersForType("tunnel")){let X=$.getProviderByName("tunnel",Y.pluginName);if(X&&!Z.includes(X))Z.push(X)}for(let Y of Z){if(!Y.getActiveTunnelUrl)continue;let X=await Y.getActiveTunnelUrl();if(X)return X}return null}function n0({serviceRegistry:$,runFinalize:Z,getDb:Q}){let Y=e5(),X=t5();return new D({prefix:"/api/agent"}).get("/identity",()=>({hostname:u.hostname(),platform:u.platform(),architecture:u.arch(),agentVersion:Y,agentInstanceId:m0()})).get("/version",()=>({version:Y,runtime:"bun",runtimeVersion:typeof Bun<"u"?Bun.version:"unknown"})).get("/api-key",({request:J,server:W,set:H})=>{if(!Q0(J,W)){let K=m(Object.fromEntries(J.headers.entries()));if(!l(K))return H.status=401,{error:"Unauthorized",message:"Invalid or missing API key"}}return{apiKey:x2()}}).post("/iframe-token",({body:J,request:W,set:H})=>{let B=m(Object.fromEntries(W.headers.entries()));if(!l(B))return H.status=401,{error:"Unauthorized",message:"Invalid or missing API key"};try{if(Array.isArray(J.pathPrefixes)&&J.pathPrefixes.length>0)return p0({pathPrefixes:J.pathPrefixes,methods:J.methods},J.ttlSeconds??void 0);if(!J.pathPrefix)return H.status=400,{error:"BadRequest",message:"Provide either pathPrefix (string) or pathPrefixes (string[])"};return D2(J.pathPrefix,J.ttlSeconds??void 0)}catch(K){return H.status=400,{error:"BadRequest",message:K instanceof Error?K.message:String(K)}}},{body:z.Object({pathPrefix:z.Optional(z.String({minLength:1})),pathPrefixes:z.Optional(z.Array(z.String({minLength:1}),{minItems:1,maxItems:16})),methods:z.Optional(z.Array(z.String({minLength:1}),{minItems:1,maxItems:8})),ttlSeconds:z.Optional(z.Number())})}).post("/terminal-exchange",({body:J,set:W})=>{let{sid:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"sid and token required"};if(!g0(H))return W.status=400,{error:"BadRequest",message:"invalid sid"};let K=`/terminal/${H}`,N=l0(B,K);if(!N.ok)return G().logger.warn("terminal-exchange","iframe token rejected",{sid:H,reason:N.reason}),W.status=401,{error:"Unauthorized",message:"invalid iframe token",code:N.reason==="expired"?"expired":N.reason==="replayed"?"replayed":"invalid"};let I=d0(H,600),C=`vt_term_${H}`;return W.headers["set-cookie"]=`${C}=${I.token}; HttpOnly; Secure; SameSite=None; Path=/terminal/${H}; Max-Age=600`,W.status=204,null},{body:z.Object({sid:z.String({minLength:1}),token:z.String({minLength:1})})}).post("/ui-exchange",({body:J,set:W})=>{let{plugin:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"plugin and token required"};if(!U2(H))return W.status=400,{error:"BadRequest",message:"invalid plugin name"};let K=`/ui/${H}`;if(!J0(B,K))return W.status=401,{error:"Unauthorized",message:"invalid iframe token"};let N=X0(H,600),I=`vt_ui_${H}`;return W.headers["set-cookie"]=`${I}=${N.token}; HttpOnly; Secure; SameSite=None; Path=/ui/${H}/; Max-Age=600`,W.status=204,null},{body:z.Object({plugin:z.String({minLength:1}),token:z.String({minLength:1})})}).post("/ui-exchange-plugin",({body:J,set:W})=>{let{plugin:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"plugin and token required"};if(!U2(H))return W.status=400,{error:"BadRequest",message:"invalid plugin name"};if(![`/api/plugins/${H}/ui`,`/${H}`].find((U)=>J0(B,U)))return W.status=401,{error:"Unauthorized",message:"invalid iframe token"};let I=X0(H,600),C=`vt_ui_${H}`;return W.headers["set-cookie"]=`${C}=${I.token}; HttpOnly; Secure; SameSite=None; Path=/api/plugins/${H}/ui/; Max-Age=600`,W.status=204,null},{body:z.Object({plugin:z.String({minLength:1}),token:z.String({minLength:1})})}).get("/system",({request:J,set:W})=>{let H=m(Object.fromEntries(J.headers.entries()));if(!l(H))return W.status=401,{error:"Unauthorized",message:"Invalid or missing API key"};return{machineId:X,hostname:u.hostname(),platform:u.platform(),arch:u.arch(),release:u.release(),cpus:u.cpus().length,totalMemory:u.totalmem(),freeMemory:u.freemem(),uptime:u.uptime(),bunVersion:typeof Bun<"u"?Bun.version:void 0,agentVersion:Y,homeDir:u.homedir(),cwd:process.cwd(),environment:"production"}}).get("/tunnel",async({request:J,set:W})=>{let H=Object.fromEntries(J.headers.entries()),B=l(m(H)),K=$0(Z0(H));if(!B&&!K)return W.status=401,{error:"Unauthorized",message:"Provide x-agent-api-key OR x-pairing-token to read tunnel URL"};let N=await QQ($);if(!N)return{tunnelUrl:null,message:"No tunnel provider registered"};return{tunnelUrl:N}}).get("/status",()=>{let J=["tunnel","session","ai"].filter((W)=>$.hasProvider(W));return{state:G().getBootState(),status:G().getBootState(),version:Y,providers:J,timestamp:new Date().toISOString()}}).get("/gateway-auth",()=>({configured:g.isConfigured(),config:h2(g.getConfig()),state:G().getBootState()})).post("/retry-config",async({set:J})=>{let{getFinalizeRetryHandle:W}=await import("./finalize-retry-handle-registry-vv241fsq.js"),H=W();if(!H)return J.status=409,{ok:!1,error:"No finalize retry worker is active. The agent either never had cached credentials to retry with, or it already reached the ready state."};let B=await H.forceRetryNow();if(!B.ok)J.status=503;return{ok:B.ok,error:B.ok?void 0:B.error,state:G().getBootState(),worker:H.getState()}}).post("/gateway-auth",async({body:J,request:W,set:H})=>{let B=G().getBootState(),K=Object.fromEntries(W.headers.entries());if(B==="ready"){let F=m(K);if(!l(F))return H.status=401,{success:!1,state:B,error:"Unauthorized: API key required to reconfigure"}}else{let F=m(K),T=Z0(K),x=l(F),q=$0(T);if(!x&&!q)return H.status=401,{success:!1,state:B,error:"Unauthorized: provide x-agent-api-key OR x-pairing-token for bootstrap"}}let{clientId:N,clientSecret:I,workspaceId:C,globalGatewayUrl:U,workspaceGatewayUrl:V}=J;if(!N||!I||!C||!U||!V)return H.status=400,{success:!1,state:G().getBootState(),error:"clientId, clientSecret, workspaceId, globalGatewayUrl, and workspaceGatewayUrl are required"};let E,R;try{E=G2(U,"globalGatewayUrl"),R=G2(V,"workspaceGatewayUrl")}catch(F){return H.status=400,{success:!1,state:G().getBootState(),error:F instanceof Error?F.message:String(F)}}{let F=b()??G();try{await S2({clientId:N,clientSecret:I,workspaceId:C,ownerUserId:J.ownerUserId,organizationId:J.organizationId,globalGatewayUrl:E,workspaceGatewayUrl:R,agentRecordId:J.agentRecordId,scopes:J.scopes,...J.storageAdapter?{storageAdapter:J.storageAdapter}:{},...J.storageOptions?{storageOptions:J.storageOptions}:{},...J.dbPath?{dbPath:J.dbPath}:{}},{dir:F.dataDir,scope:F.name})}catch(T){return H.status=500,{success:!1,state:G().getBootState(),error:`Failed to persist gateway credentials to secrets backend: ${T instanceof Error?T.message:String(T)}`}}}let h=G().getBootState();if(h==="ready"){let F=Q();if(F){if(await F.setConfig("gateway-auth:clientId",N),await F.setConfig("gateway-auth:clientSecret",I),await F.setConfig("gateway-auth:workspaceId",C),J.organizationId)await F.setConfig("gateway-auth:organizationId",J.organizationId);if(await F.setConfig("gateway-auth:globalGatewayUrl",E),await F.setConfig("gateway-auth:workspaceGatewayUrl",R),J.agentRecordId)await F.setConfig("gateway-auth:agentRecordId",J.agentRecordId)}g.configure({globalGatewayUrl:E,workspaceGatewayUrl:R,clientId:N,clientSecret:I,workspaceId:C,organizationId:J.organizationId}),G().logger.info("preconfig","Gateway credentials re-configured (agent was already ready)");let T=!!(J.storageAdapter||J.storageOptions||J.dbPath);return{success:!0,state:h,message:T?"Gateway auth re-configured. Restart the agent (vibe restart) to apply the new storage configuration.":"Gateway auth re-configured"}}return G().logger.info("preconfig","Gateway credentials received \u2014 beginning finalize (background)"),u0(),Z({clientId:N,clientSecret:I,workspaceId:C,organizationId:J.organizationId,globalGatewayUrl:E,workspaceGatewayUrl:R},{agentRecordId:J.agentRecordId,scopes:J.scopes}).catch((F)=>{G().logger.error("preconfig","Background finalize threw",{error:F instanceof Error?F.message:String(F)})}),H.status=202,{success:!0,state:G().getBootState(),agentRecordId:J.agentRecordId,message:"Gateway credentials accepted; finalize is running in the background. Poll /health/ready for completion."}},{body:z.Object({clientId:z.Optional(z.String()),clientSecret:z.Optional(z.String()),workspaceId:z.Optional(z.String()),ownerUserId:z.Optional(z.String()),organizationId:z.Optional(z.String()),globalGatewayUrl:z.Optional(z.String()),workspaceGatewayUrl:z.Optional(z.String()),scopes:z.Optional(z.Array(z.String())),agentRecordId:z.Optional(z.String()),storageAdapter:z.Optional(z.String()),storageOptions:z.Optional(z.Record(z.String(),z.String())),dbPath:z.Optional(z.String())})})}import{existsSync as e,mkdirSync as $Q,rmSync as i0,readdirSync as t0}from"fs";import{join as b2}from"path";function o($){return b2(V2(),"agents",d($))}function ZQ(){let $=b2(V2(),"agents");if(!e($))return[];return t0($,{withFileTypes:!0}).filter((Z)=>Z.isDirectory()).map((Z)=>Z.name).filter((Z)=>/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(Z))}function e0($){return b2(V2(),"agents",d($))}function W0($){return s({dir:e0($)})}function o0($,Z){return P2(Z,{dir:e0($),scope:d($)})}function B2($){let Z=v2(),Q=z0().find((J)=>J.name===$),Y=a.get($),X={name:$,isDefault:$===Z,isRunning:Q?.status==="running",attached:Y!==void 0,bootState:Y?Y.getBootState():null,dataDir:Y?Y.dataDir:null};if(Q)X.port=Q.port,X.pid=Q.pid,X.startTime=Q.startTime;if(e(o($)))X.config=h2(W0($));return X}function Q4($={}){let Z=$.serviceManagerFactory?$.serviceManagerFactory():new f2;return new D({prefix:"/api/profiles"}).get("/",()=>{let Q=ZQ(),Y=v2(),X=new Set(Q);return X.add(Y),[...X].sort().map((J)=>B2(J))}).post("/",async({body:Q,set:Y})=>{try{let X=d(Q.name),J=o(X);if(e(J))return Y.status=409,{error:"exists",message:`Profile '${X}' already exists.`};let W;if(Q.copyFrom){let H=d(Q.copyFrom);if(!e(o(H)))return Y.status=400,{error:"copy-source-missing",message:`Profile '${H}' does not exist.`};W=W0(H),delete W["static-api-key"],delete W.agentRecordId,delete W.apiKeys}else W=r0();if(Q.gatewayUrl)W.globalGatewayUrl=Q.gatewayUrl;if(Q.workspaceGatewayUrl)W.workspaceGatewayUrl=Q.workspaceGatewayUrl;if(Q.clientId)W.clientId=Q.clientId;if(Q.clientSecret)W.clientSecret=Q.clientSecret;if(Q.workspaceId)W.workspaceId=Q.workspaceId;if(Q.organizationId)W.organizationId=Q.organizationId;$Q(J,{recursive:!0}),o0(X,W);try{Y0(X)}catch(H){G().logger.warn("profile-mgmt",`In-process attach failed for '${X}'`,{error:String(H)})}if(G().logger.info("profile-mgmt",`Created profile '${X}' at ${J}`),Q.start){let H={name:X,port:Q.port??0,daemon:!0,dbPath:M2(),profile:X};await Z.startDaemon(H)}return Y.status=201,B2(X)}catch(X){return Y.status=400,{error:"create-failed",message:X instanceof Error?X.message:String(X)}}},{body:z.Object({name:z.String(),gatewayUrl:z.Optional(z.String()),workspaceGatewayUrl:z.Optional(z.String()),clientId:z.Optional(z.String()),clientSecret:z.Optional(z.String()),workspaceId:z.Optional(z.String()),organizationId:z.Optional(z.String()),copyFrom:z.Optional(z.String()),start:z.Optional(z.Boolean()),port:z.Optional(z.Number())})}).get("/:name",({params:Q,set:Y})=>{try{let X=d(Q.name);if(!e(o(X)))return Y.status=404,{error:"not-found",message:`No profile '${X}'.`};return B2(X)}catch(X){return Y.status=400,{error:"bad-request",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})}).put("/:name",({params:Q,body:Y,set:X})=>{try{let J=d(Q.name);if(!e(o(J)))return X.status=404,{error:"not-found",message:`No profile '${J}'.`};let W=["static-api-key","apiKeys","agentRecordId"];for(let K of W)if(K in Y)return X.status=400,{error:"forbidden-field",message:`Field '${K}' is managed via dedicated commands (vibe key rotate / vibe profile create). It cannot be patched here.`};if("registry"in Y)return X.status=400,{error:"forbidden-field",message:"Field 'registry' cannot be patched via this endpoint. Use POST /api/agent/registry with operator confirmation (VIBE_ALLOW_REGISTRY_CHANGE=1) so the change is auditable."};let B={...W0(J),...Y};return o0(J,B),B2(J)}catch(J){return X.status=400,{error:"update-failed",message:J instanceof Error?J.message:String(J)}}},{params:z.Object({name:z.String()}),body:z.Record(z.String(),z.Any())}).delete("/:name",async({params:Q,body:Y,query:X,set:J})=>{try{let W=d(Q.name);if(W===v2())return J.status=409,{error:"is-default",message:`Cannot delete active default profile '${W}'. Switch to another profile first.`};let H=X?.purge==="true"||X?.purge==="1",B=e(o(W)),K=a.has(W);if(!B&&!K)return J.status=404,{error:"not-found",message:`No profile '${W}'.`};if(B&&!H&&!Y?.confirm)return J.status=400,{error:"confirm-required",message:"Pass { confirm: true } in the body or `?purge=true` in the query to delete the on-disk dataDir (destructive)."};try{await Z.stop(W)}catch{}try{await a.destroy(W)}catch(N){G().logger.warn("profile-mgmt",`In-process detach failed for '${W}'`,{error:String(N)})}if(B)if(Y?.keepConfig)for(let N of t0(o(W))){if(N==="config.json")continue;i0(b2(o(W),N),{recursive:!0,force:!0})}else i0(o(W),{recursive:!0,force:!0});return G().logger.info("profile-mgmt",`Deleted profile '${W}'`),{ok:!0,deleted:W,keptConfig:!!Y?.keepConfig,detached:K,purged:B}}catch(W){return J.status=400,{error:"delete-failed",message:W instanceof Error?W.message:String(W)}}},{params:z.Object({name:z.String()}),query:z.Optional(z.Object({purge:z.Optional(z.String())})),body:z.Optional(z.Object({confirm:z.Optional(z.Boolean()),keepConfig:z.Optional(z.Boolean())}))}).post("/:name/switch",async({params:Q,set:Y})=>{try{let X=d(Q.name);if(!e(o(X)))return Y.status=404,{error:"not-found",message:`No profile '${X}'.`};return await a0(()=>s0(X)),G().logger.info("profile-mgmt",`Default profile switched to '${X}'`),{ok:!0,defaultProfile:X}}catch(X){return Y.status=400,{error:"switch-failed",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})}).post("/:name/start",async({params:Q,body:Y,set:X})=>{try{let J=d(Q.name);if(!e(o(J)))return X.status=404,{error:"not-found",message:`No profile '${J}'.`};try{Y0(J)}catch(H){G().logger.warn("profile-mgmt",`In-process attach failed for '${J}'`,{error:String(H)})}if(!z0().some((H)=>H.name===J&&H.status==="running")){let H={name:J,port:Y?.port??0,daemon:!0,dbPath:M2(),profile:J};await Z.startDaemon(H)}return B2(J)}catch(J){return X.status=500,{error:"start-failed",message:J instanceof Error?J.message:String(J)}}},{params:z.Object({name:z.String()}),body:z.Optional(z.Object({port:z.Optional(z.Number())}))}).post("/:name/stop",async({params:Q,set:Y})=>{try{let X=d(Q.name);try{await Z.stop(X)}catch{}try{await a.destroy(X)}catch(J){G().logger.warn("profile-mgmt",`In-process detach failed for '${X}'`,{error:String(J)})}return B2(X)}catch(X){return Y.status=500,{error:"stop-failed",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})})}function JQ(){let $=process.memoryUsage(),Z=process.resourceUsage(),Q=Z.userCPUTime/1000,Y=Z.systemCPUTime/1000,X=Q+Y,J=a.list().map((W)=>{let H;try{H=$4(W.spawnOwnerKey).length}catch{H=0}return{name:W.name,status:W.getBootState(),childPidCount:H,cpuMs:X,heapBytes:$.heapUsed,dataDir:W.dataDir}});return{process:{pid:process.pid,uptimeSeconds:process.uptime(),cpuUserMs:Q,cpuSystemMs:Y,heapUsedBytes:$.heapUsed,heapTotalBytes:$.heapTotal,rssBytes:$.rss},profiles:J,notes:{perProfileCpu:"deferred",perProfileHeap:"deferred"}}}function Z4(){return new D({prefix:"/api/profile-stats"}).get("/",()=>JQ())}function y2($,Z){return Promise.race([$,new Promise((Q,Y)=>setTimeout(()=>Y(Error(`timeout after ${Z}ms`)),Z))])}function XQ($){let Z=$ instanceof Error?$.message:String($);return/ENOENT/.test(Z)||/no such file or directory/i.test(Z)}async function J4($){let Q=`__health__:probe:${typeof crypto<"u"&&typeof crypto.randomUUID==="function"?crypto.randomUUID():`${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`}`,Y=String(Date.now());if(await y2($.setConfig(Q,Y),2000),await y2($.getConfig(Q),2000)!==Y)throw Error("round-trip mismatch");try{await y2($.deleteConfig(Q),500)}catch{}}async function YQ($,Z){if(!$)return{ok:!1,message:"database not opened"};let Q=performance.now();try{return await J4($),{ok:!0,durationMs:performance.now()-Q}}catch(Y){if(Z&&XQ(Y))try{return(await import("fs")).mkdirSync(Z,{recursive:!0}),await J4($),{ok:!0,message:`recovered: dbPath ${Z} was missing \u2014 recreated`,durationMs:performance.now()-Q}}catch(X){return{ok:!1,message:`ENOENT on dbPath ${Z}: ${X instanceof Error?X.message:String(X)}`,durationMs:performance.now()-Q}}return{ok:!1,message:Y instanceof Error?Y.message:String(Y),durationMs:performance.now()-Q}}}function X4($,Z){if(!$)return{ok:!1,message:"no service registry"};let Y=G().getBootState()==="awaiting-config";if(Z==="tunnel"){let X=$.getProvider("tunnel");if(!X&&process.env.AGENT_TUNNEL==="false")return{ok:!0,message:"tunnel disabled via AGENT_TUNNEL=false"};if(X)return{ok:!0,message:`provider: ${X.name}`};return{ok:!1,message:Y?"agent is awaiting-config \u2014 POST OAuth credentials to /api/agent/gateway-auth to register tunnel provider":"no tunnel provider registered"}}if(Z==="session"){let X=$.getProvider("session");if(X)return{ok:!0,message:`provider: ${X.name}`};return{ok:!1,message:Y?"agent is awaiting-config \u2014 POST OAuth credentials to /api/agent/gateway-auth to register session provider":"no session provider registered"}}return{ok:!0}}async function WQ($){if(!$)return{};let Z={};for(let Q of $.getAllPlugins()){let Y=Q.getHealth;if(typeof Y!=="function")continue;let X=performance.now();try{let J=await y2(Promise.resolve(Y.call(Q)),2000);Z[Q.name]={ok:J?.ok!==!1,message:J?.message,durationMs:performance.now()-X}}catch(J){Z[Q.name]={ok:!1,message:J instanceof Error?J.message:String(J),durationMs:performance.now()-X}}}return Z}function Y4($){let Z=$&&"serviceRegistry"in $?$:{serviceRegistry:$};return new D({prefix:"/health"}).get("/",()=>{return{status:"ok",lifecycleState:Z.serviceRegistry?.getService("agent","lifecycle")?.getState()??"running",bootState:G().getBootState(),timestamp:new Date().toISOString(),uptime:process.uptime()}}).get("/live",()=>({status:"ok"})).get("/ready",async({set:Q})=>{let X=Z.serviceRegistry?.getService("agent","lifecycle")?.getState()??"running",J=G().getBootState(),W={};W.boot={ok:J==="ready",message:J==="ready"?void 0:`boot state ${J}`},W.lifecycle={ok:X==="running",message:X==="running"?void 0:`lifecycle ${X}`},W.db=await YQ(Z.getDb?.()??null,Z.getDbPath?.()??null),W.tunnel=X4(Z.serviceRegistry,"tunnel"),W.session=X4(Z.serviceRegistry,"session");try{let{gatewayClient:V}=await import("./gateway-client-43gzvj5s.js");if(!V.isConfigured())W.registration={ok:!0,message:"not configured"};else{let E=Z.getDb?.()??null;if(E?await E.getConfig("gateway-auth:agentRecordId"):null)W.registration={ok:!0};else{let h=G().getDegradedReasons().some((F)=>F.plugin==="agent-registration");W.registration=h?{ok:!1,message:"agent failed to register with the workspace after retries"}:{ok:!0,message:"registering"}}}}catch(V){W.registration={ok:!0,message:`registration check skipped: ${V instanceof Error?V.message:String(V)}`}}let H=await WQ(Z.getPluginManager?.()??null),B=Object.values(W).every((V)=>V.ok)&&Object.values(H).every((V)=>V.ok);if(!B)Q.status=503;let K=J==="degraded"?G().getDegradedReasons():[],N=G().name,I={};for(let V of a.list())I[V.name]={bootState:V.getBootState(),ok:V.getBootState()==="ready",degradedReasons:V.getDegradedReasons()};let C=G().getLastFinalizeError(),U={status:B?"ok":"degraded",lifecycleState:X,bootState:J,daemon:{profile:N,bootState:J,ok:J==="ready"},profiles:I,components:W,plugins:H,degradedReasons:K,lastFinalizeError:C,timestamp:new Date().toISOString()};if(!B)G().logger.warn("health","Readiness probe failed",{components:W,plugins:H,bootState:J});return U})}var c2=0,W4=0;function z4(){return new D({name:"inflight-tracker"}).onRequest(()=>{c2+=1}).onAfterResponse(()=>{c2=Math.max(0,c2-1),W4+=1})}function H4(){return new D({prefix:"/api/stats"}).get("/inflight",()=>({inflight:Math.max(0,c2-1),totalServed:W4}))}var H0=Object.freeze(["code","code-insiders","codium","cursor","idea","pycharm","webstorm","goland","phpstorm","rubymine","clion","rider","zed","subl","vim","nvim","emacs","neovide","fleet","helix"]),zQ=new Set(H0),HQ=new Set(["--new-window","-n","--reuse-window","-r","--wait","-w","--add","--goto"]);function G4($){try{return Bun.which($)??null}catch{return null}}function K4(){return new D({prefix:"/api/editor"}).get("/allowlist",()=>({commands:[...H0]})).get("/detect",async()=>{let $=H0.map((Y)=>[Y,G4(Y)]),Z=[],Q={};for(let[Y,X]of $)if(X)Z.push(Y),Q[Y]=X;return{available:Z,paths:Q}}).post("/open",async({body:$,set:Z})=>{let{command:Q,path:Y,args:X=[]}=$;if(!zQ.has(Q))return Z.status=400,{ok:!1,error:`Command '${Q}' is not in the IDE allowlist`};for(let H of X)if(typeof H!=="string"||!HQ.has(H))return Z.status=400,{ok:!1,error:`Argument '${H}' is not in the flag allowlist`};let J;try{J=(await B4(Y,{mustExist:!0})).realPath}catch(H){return Z.status=400,{ok:!1,error:`Invalid path: ${H instanceof Error?H.message:String(H)}`}}let W=G4(Q);if(!W)return Z.status=404,{ok:!1,error:`'${Q}' is not installed or not on PATH on this agent`};try{let H=V4({owner:`editor:${Q}`,cmd:[W,...X,J],env:process.env,stdout:"ignore",stderr:"ignore",stdin:"ignore",meta:{command:Q,path:J}});return G().logger.info("editor",`Launched ${Q} on ${J}`,{pid:H.pid}),G().audit.emit("agent","editor.open",{command:Q,path:J,pid:H.pid}),{ok:!0,command:Q,resolvedPath:J,pid:H.pid}}catch(H){return Z.status=500,{ok:!1,error:`Failed to spawn editor: ${H instanceof Error?H.message:String(H)}`}}},{body:z.Object({command:z.String({minLength:1,maxLength:40}),path:z.String({minLength:1,maxLength:4096}),args:z.Optional(z.Array(z.String({maxLength:32})))})})}var _4=Symbol.for("@vibecontrols/plugin-sdk:contextProviders@1");function GQ(){let $=globalThis,Z=$[_4];if(Z)return Z;let Q=new Map;return $[_4]=Q,Q}function G0(){return Array.from(GQ().values())}function N4(){return(b()??G()).dataDir}function n(){let $=s({dir:N4()});return{ownerUserId:$.ownerUserId,workspaceId:$.workspaceId}}function u2(){return s({dir:N4()}).agentRecordId}function F4($){if(!$)return null;try{return new URL($).host}catch{return null}}async function L4($,Z){let Q=$.getPluginManager(),Y=Q?Q.getPluginDetails().map((H)=>({pluginName:H.pluginName,packageName:H.packageName,version:H.version,tags:H.tags??[]})):[],X=process.memoryUsage(),J=F4($.getTunnelHost?.()??null),W;try{W=K2(n()).map((H)=>({id:H.id,label:H.label,host:F4(H.tunnelUrl),agentRecordId:H.agentRecordId??null,permissions:H.permissions,canForward:H.permissions.includes("mesh:forward"),lastReachable:H.lastReachable??null}))}catch{W=[]}return{pluginName:"agent",description:"vibecontrols-agent runtime self-report",generatedAt:new Date().toISOString(),data:{profile:Z.profile,vibeId:Z.vibeId??null,runtime:{bunVersion:typeof Bun<"u"?Bun.version:null,nodeVersion:process.versions.node??null,platform:process.platform,arch:process.arch,pid:process.pid,uptimeSeconds:Math.round(process.uptime()),memory:{rssMB:Math.round(X.rss/1048576),heapUsedMB:Math.round(X.heapUsed/1048576)}},agent:{version:$.getAgentVersion?.()??null,profileRegistered:T2(),tunnelHost:J},plugins:{count:Y.length,items:Y},mesh:{peerCount:W.length,peers:W}}}}var BQ=2000,O4=1000;async function VQ($,Z){let Q,Y=new Promise((X,J)=>{Q=setTimeout(()=>J(Error(`timeout after ${Z}ms`)),Z)});try{return await Promise.race([$,Y])}finally{if(Q)clearTimeout(Q)}}async function j4($,Z){let Q=performance.now(),Y=$.timeoutMs??BQ;try{let X=await VQ($.getContext(Z),Y);if(!X.generatedAt)X.generatedAt=new Date().toISOString();return{ok:!0,data:X,durationMs:Math.round(performance.now()-Q)}}catch(X){return{ok:!1,error:X.message??String(X),durationMs:Math.round(performance.now()-Q)}}}class B0{deps;inflight=new Map;constructor($){this.deps=$}async aggregate($){let Z=`${$.profile}::${$.vibeId??""}`,Q=this.inflight.get(Z);if(Q&&Date.now()-Q.ts<O4)return Q.promise;let Y=this.doAggregate($).finally(()=>{setTimeout(()=>{let X=this.inflight.get(Z);if(X&&X.promise===Y)this.inflight.delete(Z)},O4).unref?.()});return this.inflight.set(Z,{ts:Date.now(),promise:Y}),Y}async selfContext($){return L4(this.deps,$)}async pluginContext($,Z){let Q=G0().find((Y)=>Y.name===$);if(!Q)return null;return j4(Q,Z)}async pluginsContext($){let Z=G0(),Q=await Promise.allSettled(Z.map((X)=>j4(X,$))),Y={};return Z.forEach((X,J)=>{let W=Q[J];if(W&&W.status==="fulfilled")Y[X.name]=W.value;else if(W&&W.status==="rejected")Y[X.name]={ok:!1,error:W.reason instanceof Error?W.reason.message:String(W.reason),durationMs:0}}),Y}async doAggregate($){let[Z,Q]=await Promise.all([this.selfContext($),this.pluginsContext($)]);return{agent:Z,plugins:Q}}}function m2($){let Z=$.vibeId;if(typeof Z!=="string")return;let Q=Z.trim();return Q.length>0&&Q.length<=128?Q:void 0}function U4($){let Z=new B0($);return new D({prefix:"/api/agent/context"}).get("/",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=m2(Y);return Z.aggregate({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/agent",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=m2(Y);return Z.selfContext({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/plugins",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=m2(Y);return Z.pluginsContext({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/plugins/:name",async({params:Q,query:Y,set:X})=>{let J=Q?.profile??"default",W=Q?.name;if(!W)return X.status=400,{error:"missing plugin name"};let H=m2(Y),B=await Z.pluginContext(W,{profile:J,vibeId:H});if(!B)return X.status=404,{error:`no context provider registered under name "${W}"`};return B},{params:z.Object({name:z.String()}),query:z.Object({vibeId:z.Optional(z.String())})})}var Q2="autoupdate",KQ=86400000,x4=300000,_Q=900000,S={timer:null,running:!1,profile:"default",lastCheckAt:null,lastCheck:null,lastUpdateAt:null,lastUpdate:null,startedAt:null};function V0(){let $=(process.env.VIBE_AUTOUPDATE??"").trim().toLowerCase();return $==="0"||$==="false"||$==="off"||$==="no"}function T4(){if(V0())return!1;try{return s().autoUpdate!==!1}catch{return!0}}function K0(){let $=Number(process.env.VIBE_AUTOUPDATE_INTERVAL_MS);if(Number.isFinite($)&&$>0)return Math.max(_Q,$);return KQ}async function _0($){let Z=G().logger;if(S.running)return{check:S.lastCheck??await M4(),update:null};S.running=!0;try{let Q=await E2();if(S.lastCheck=Q,S.lastCheckAt=new Date().toISOString(),Q.error)Z.debug(Q2,`Update check failed: ${Q.error}`);else if(Q.hasUpdate)Z.info(Q2,`New agent version available: ${Q.current} \u2192 ${Q.latest}`);let Y=$?.force||T4();if(!Q.hasUpdate||!Y)return{check:Q,update:null};Z.info(Q2,`Auto-updating ${Q.current} \u2192 ${Q.latest} (idle-gated restart)\u2026`);let X=await g2({restart:!0,name:S.profile,onLog:(J)=>Z.info(Q2,J)});if(S.lastUpdate=X,S.lastUpdateAt=new Date().toISOString(),X.ok&&X.updated)Z.info(Q2,`Auto-update applied: now ${X.current} (restart: ${X.restart}).`);else if(!X.ok)Z.warn(Q2,`Auto-update failed: ${X.error}`);return{check:Q,update:X}}catch(Q){return Z.warn(Q2,`Auto-update tick threw: ${Q instanceof Error?Q.message:String(Q)}`),{check:await M4(),update:null}}finally{S.running=!1}}async function M4(){if(S.lastCheck)return S.lastCheck;let $=await E2();return S.lastCheck=$,S.lastCheckAt=new Date().toISOString(),$}function E4($){if(S.timer)clearTimeout(S.timer);S.timer=setTimeout(()=>{_0().finally(()=>{if(S.startedAt)E4(K0())})},$),S.timer.unref?.()}function NQ($){let Z=G().logger;if(S.profile=$?.profile||process.env.VIBECONTROLS_PROFILE||"default",S.startedAt=new Date().toISOString(),V0()){Z.info(Q2,"Autoupdate disabled via VIBE_AUTOUPDATE \u2014 not scheduling.");return}Z.info(Q2,`Autoupdate scheduled (first check in ${Math.round(x4/60000)}m, then every ${Math.round(K0()/3600000)}h).`),E4(x4)}function B7(){if(S.timer)clearTimeout(S.timer),S.timer=null;S.startedAt=null}function C4($){if(P2({autoUpdate:$}),$&&!S.startedAt)NQ({profile:S.profile})}function N0(){let $=!0;try{$=s().autoUpdate!==!1}catch{}return{enabled:T4(),envKillSwitch:V0(),configEnabled:$,scheduled:!!S.startedAt,intervalMs:K0(),profile:S.profile,startedAt:S.startedAt,lastCheckAt:S.lastCheckAt,lastCheck:S.lastCheck,lastUpdateAt:S.lastUpdateAt,lastUpdate:S.lastUpdate}}import{existsSync as I4}from"fs";import{join as q4}from"path";var FQ=600000,F0=1e6;function LQ(){let $=_2(),Z=$.which("bun")??`bun${$.executableSuffix}`,Q=q4(import.meta.dir,"cli.js");if(I4(Q))return{runner:Z,prefix:[Q]};let Y=q4(import.meta.dir,"..","cli.ts");if(I4(Y))return{runner:Z,prefix:[Y]};let X=$.which("vibe");if(X)return{runner:X,prefix:[]};return null}function R4($){if($.length<=F0)return $;return $.slice(0,F0)+`
|
|
4
|
+
\u2026[output truncated at ${F0} bytes]`}async function p2($,Z={}){let Q=LQ();if(!Q)return{ok:!1,exitCode:null,stdout:"",stderr:"Could not locate the vibe CLI to execute (no dist/cli.js, source, or PATH entry).",timedOut:!1,argv:$,command:"(unresolved)"};let Y=[...Q.prefix,...$],X=[Q.runner,...Y].join(" ");try{let J=Bun.spawn([Q.runner,...Y],{cwd:Z.cwd,env:{...process.env,VIBE_AUTO_ACCEPT:"1",CI:"1",NO_COLOR:"1",...Z.env},stdout:"pipe",stderr:"pipe"}),W=Z.timeoutMs??FQ,H=!1,B=setTimeout(()=>{H=!0;try{J.kill()}catch{}},W),[K,N,I]=await Promise.all([new Response(J.stdout).text(),new Response(J.stderr).text(),J.exited]);return clearTimeout(B),{ok:!H&&I===0,exitCode:I,stdout:R4(K),stderr:R4(N),timedOut:H,argv:$,command:X}}catch(J){return{ok:!1,exitCode:null,stdout:"",stderr:`Failed to spawn vibe CLI: ${J instanceof Error?J.message:String(J)}`,timedOut:!1,argv:$,command:X}}}async function A4(){let{Command:$}=await import("./esm-9fpye77x.js"),{registerCoreCommands:Z}=await import("./register-core-mbv4hrbv.js"),Q=new $;Q.name("vibe").option("--json").option("--plain").option("-y, --yes").option("-p, --profile <name>");try{Z(Q)}catch{}let Y=new Set(["nuke","kill","gc","stop","rollback","deploy"]),X=[];for(let J of Q.commands){let W=J.name();if(!W||W==="help")continue;X.push({name:W,description:J.description()||"",usage:J.usage()||"",options:J.options.map((H)=>({flags:H.flags,description:H.description||""})),group:"core",destructive:Y.has(W)})}return X.sort((J,W)=>J.name.localeCompare(W.name))}import{spawn as OQ}from"child_process";import{writeFileSync as jQ,mkdirSync as UQ}from"fs";import{tmpdir as xQ}from"os";import{join as w4}from"path";var MQ="@vibecontrols/agent";function k4($){let Z=_2(),Q=Z.which("bun")??`bun${Z.executableSuffix}`,Y=Z.which("npm")??`npm${Z.executableSuffix}`,X=l2(),J=$.delayMs??3000,W=$.pids.filter((B)=>Number.isInteger(B)&&B>0),H=`// vibecontrols agent self-uninstall reaper (auto-generated)
|
|
5
|
+
const PIDS = ${JSON.stringify(W)};
|
|
6
|
+
const NPM = ${JSON.stringify(Y)};
|
|
7
|
+
const BUN = ${JSON.stringify(Q)};
|
|
8
|
+
const REGISTRY = ${JSON.stringify(X)};
|
|
9
|
+
const PKG = ${JSON.stringify(MQ)};
|
|
10
|
+
await Bun.sleep(${J});
|
|
11
|
+
for (const pid of PIDS) {
|
|
12
|
+
try { process.kill(pid, "SIGTERM"); } catch {}
|
|
13
|
+
}
|
|
14
|
+
await Bun.sleep(2500);
|
|
15
|
+
for (const pid of PIDS) {
|
|
16
|
+
try { process.kill(pid, "SIGKILL"); } catch {}
|
|
17
|
+
}
|
|
18
|
+
try { Bun.spawnSync([NPM, "uninstall", "-g", PKG, "--registry=" + REGISTRY], { stdout: "inherit", stderr: "inherit" }); } catch {}
|
|
19
|
+
try { Bun.spawnSync([BUN, "remove", "-g", PKG], { stdout: "inherit", stderr: "inherit" }); } catch {}
|
|
20
|
+
`;try{let B=w4(xQ(),"vibecontrols-uninstall");UQ(B,{recursive:!0});let K=w4(B,`reaper-${process.pid}.ts`);return jQ(K,H,{encoding:"utf8"}),OQ(Q,[K],{detached:!0,stdio:"ignore",windowsHide:!0}).unref(),G().logger.info("self-uninstall",`Scheduled detached uninstall reaper (pids=${W.join(",")}) at ${K}`),{ok:!0,scriptPath:K}}catch(B){return{ok:!1,scriptPath:null,error:B instanceof Error?B.message:String(B)}}}var TQ=new Set(["db","plugins-registry","logs","binaries","subprocs"]);async function S4($){let Z=await A4();try{let Q=$.getPluginManager?.();if(Q){let Y=new Set(Z.map((X)=>X.name));for(let X of Q.getPluginDetails()){let J=X.cliCommand;if(J&&!Y.has(J))Y.add(J),Z.push({name:J,description:X.description||`${X.pluginName} plugin command`,usage:"",options:[],group:"plugin",destructive:!1})}}}catch{}return Z.sort((Q,Y)=>Q.name.localeCompare(Y.name))}function D4($={}){return new D({name:"agent-maintenance"}).get("/api/agent/update/check",async()=>{return await E2()}).get("/api/agent/update/status",()=>{return N0()}).post("/api/agent/update",async({body:Z})=>{return await g2({targetVersion:typeof Z?.version==="string"?Z.version:void 0,allowIncompatible:Z?.allowIncompatible===!0,restart:Z?.restart!==!1})},{body:z.Optional(z.Object({version:z.Optional(z.String()),allowIncompatible:z.Optional(z.Boolean()),restart:z.Optional(z.Boolean())}))}).post("/api/agent/update/config",({body:Z})=>{return C4(Z.enabled),{ok:!0,status:N0()}},{body:z.Object({enabled:z.Boolean()})}).post("/api/agent/update/check-now",async({body:Z})=>{return{ok:!0,...await _0({force:Z?.force===!0})}},{body:z.Optional(z.Object({force:z.Optional(z.Boolean())}))}).get("/api/agent/commands",async()=>{let Z=await S4($);return{commands:Z,count:Z.length}}).post("/api/agent/commands/run",async({body:Z,set:Q})=>{let Y=Array.isArray(Z?.argv)?Z.argv.filter((B)=>typeof B==="string"):[];if(Y.length===0)return Q.status=400,{ok:!1,error:"argv must be a non-empty string array"};let X=Y[0],J=await S4($),W=new Set(J.map((B)=>B.name));if(!W.has(X))return Q.status=400,{ok:!1,error:`Unknown or disallowed command: "${X}"`,allowed:[...W].sort()};return await p2(Y,{timeoutMs:typeof Z?.timeoutMs==="number"?Z.timeoutMs:void 0})},{body:z.Object({argv:z.Array(z.String()),timeoutMs:z.Optional(z.Number())})}).post("/api/agent/nuke",async({body:Z,set:Q})=>{let Y=["nuke"];if(Z?.all)Y.push("--all");if(Z?.removeConfig)Y.push("--remove-config");if(Z?.dryRun)Y.push("--dry-run");if(typeof Z?.removePlugins==="string"&&Z.removePlugins)Y.push("--remove-plugins",Z.removePlugins);if(typeof Z?.keep==="string"&&Z.keep){let W=Z.keep.split(",").map((H)=>H.trim()).filter((H)=>H&&!TQ.has(H));if(W.length>0)return Q.status=400,{ok:!1,error:`Invalid --keep value(s): ${W.join(", ")}`};Y.push("--keep",Z.keep)}Y.push("-y","--json");let X=await p2(Y),J=null;try{let W=X.stdout.trim().split(`
|
|
21
|
+
`).reverse().find((H)=>H.trim().startsWith("{"));if(W)J=JSON.parse(W)}catch{}return{...X,parsed:J}},{body:z.Optional(z.Object({all:z.Optional(z.Boolean()),removeConfig:z.Optional(z.Boolean()),removePlugins:z.Optional(z.String()),keep:z.Optional(z.String()),dryRun:z.Optional(z.Boolean())}))}).post("/api/agent/uninstall",async({body:Z})=>{let Q=Z?.dryRun===!0,Y=["nuke","--all","--remove-config","-y","--json"];if(Q)Y.push("--dry-run");let X=await p2(Y);if(Q)return{ok:X.ok,dryRun:!0,nuke:X,note:"Dry run \u2014 would nuke all state and uninstall @vibecontrols/agent."};let J=new Set([process.pid]);try{let H=new f2;for(let B of await H.listInstances())if(typeof B.pid==="number"&&B.pid>0)J.add(B.pid)}catch{}let W=k4({pids:[...J]});return{ok:X.ok&&W.ok,nuke:X,uninstallScheduled:W.ok,scriptPath:W.scriptPath,...W.error?{error:W.error}:{},note:"Agent state nuked; package self-uninstall scheduled \u2014 the daemon will stop and `@vibecontrols/agent` will be removed shortly."}},{body:z.Optional(z.Object({dryRun:z.Optional(z.Boolean())}))})}import{existsSync as RQ,readFileSync as AQ}from"fs";import{join as wQ}from"path";var EQ=`mutation AddAgentFromTunnel($input: AddAgentFromTunnelInput!) {
|
|
22
|
+
addVibecontrolsAgentFromTunnel(input: $input) { agent { id name } clientId success error }
|
|
23
|
+
}`,CQ=`mutation ReportAgentMeshLink($input: ReportAgentMeshLinkInput!) {
|
|
24
|
+
reportAgentMeshLink(input: $input) { id }
|
|
25
|
+
}`,h4="VIBE_BOOTSTRAP_JSON=";function IQ($){for(let Y of $.split(/\r?\n/)){let X=Y.indexOf(h4);if(X>=0)try{return JSON.parse(Y.slice(X+h4.length))}catch{}}let Z=$.indexOf("{"),Q=$.lastIndexOf("}");if(Z>=0&&Q>Z)try{return JSON.parse($.slice(Z,Q+1))}catch{return null}return null}async function f4($,Z){let Q=(N,I,C)=>Z?.({step:N,status:I,message:C}),Y=P4($.permissions??["tunnel:read","session:list","plugin:list","diagnostics:read","mesh:forward"]);if(!Y.includes("mesh:forward"))Y.push("mesh:forward");let X=(N)=>({ok:!1,peerId:"",agentRecordId:null,tunnelUrl:null,permissions:Y,error:N}),J;try{J=n2($.target,{identityFile:$.identityFile})}catch(N){return X(N instanceof Error?N.message:String(N))}let W=$.label??J.id,H=Y.join(","),B,K='export PATH="$HOME/.bun/bin:$PATH"; ';try{if(!$.connectExisting){Q("probe","running");let x=await J.probe();if(Q("probe","completed",`os=${x.os??"?"} arch=${x.arch??"?"}`),!x.bun){if($.installBun===!1)return X("Bun is required to run the agent but is not installed, and Bun auto-install was disabled.");Q("install-bun","running");let X2=await J.run(["sh","-c",`curl -fsSL https://bun.sh/install | bash && echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc`],{timeoutMs:300000});if(X2.code!==0)return Q("install-bun","failed",X2.stderr.slice(0,400)),X("Bun auto-install failed.");let N2=await J.run(["sh","-c","$HOME/.bun/bin/bun --version 2>/dev/null"],{timeoutMs:1e4});if(N2.code===0&&N2.stdout.trim())x.bun="$HOME/.bun/bin/bun",Q("install-bun","completed",N2.stdout.trim());else return X("Bun installed but the binary is not reachable.")}Q("install-agent","running");let q=$.version??"latest",c=$.registry??"https://registry.npmjs.org/";if(!/^[A-Za-z0-9._@/^~>=<-]+$/.test(q))return Q("install-agent","failed","invalid version"),X(`Invalid agent version: ${q}`);if(!/^https?:\/\/[A-Za-z0-9._~:/?#@!$&'()*+,;=%-]+$/.test(c))return Q("install-agent","failed","invalid registry"),X(`Invalid registry URL: ${c}`);let y=await J.run(["sh","-c",`${K}npm_config_registry="${c}" bun install -g @vibecontrols/agent@${q} --no-cache`],{timeoutMs:600000});if(y.code!==0)return Q("install-agent","failed",y.stderr.slice(0,400)),X(`Agent install failed (exit ${y.code}).`);if(B=(await J.run(["sh","-c",`${K}vibe --version`],{timeoutMs:15000})).stdout.trim()||void 0,Q("install-agent","completed",B),$.autostart)Q("autostart","running"),await J.run(["sh","-c",`${K}vibe autostart install`],{timeoutMs:60000}),Q("autostart","completed");if($.installPlugins?.length){Q("plugins","running");for(let X2 of $.installPlugins)await J.run(["sh","-c",`${K}vibe plugin install ${X2}`],{timeoutMs:300000});Q("plugins","completed")}Q("start","running"),await J.run(["sh","-c",`${K}vibe start`],{timeoutMs:60000}),Q("start","completed")}Q("bootstrap","running");let N=$.expiresIn?` --expires-in ${$.expiresIn}`:"",I=W.replace(/'/g,""),C=null;for(let x=0;x<15;x++){let q=`${K}vibe peer-bootstrap --json --emit-default-key --label '${I}' --scope ${H}${N} 2>/dev/null`,c=await J.run(["sh","-c",q],{timeoutMs:15000});if(c.code===0){let y=IQ(c.stdout);if(y&&typeof y.apiKey==="string"){C=y;break}}await new Promise((y)=>setTimeout(y,2000))}if(!C)return Q("bootstrap","failed","could not obtain peer-bootstrap bundle"),X("Remote peer-bootstrap did not return a credential bundle.");Q("bootstrap","completed");let U=n(),V=String(C.id),E=String(C.apiKey),R=d2(typeof C.tunnelUrl==="string"?C.tunnelUrl:null),h=typeof C.agentRecordId==="string"?C.agentRecordId:null;if($.onboardBackend!==!1&&g.isConfigured()&&R&&typeof C.fullDefaultApiKey==="string"){Q("onboard","running");try{let q=(await g.workspaceQuery(EQ,{input:{tunnelUrl:R,apiKey:C.fullDefaultApiKey,name:W}})).data?.addVibecontrolsAgentFromTunnel;if(q?.agent?.id)h=q.agent.id,Q("onboard","completed",`agent ${h}`);else Q("onboard","failed",q?.error??"no agent returned")}catch(x){Q("onboard","failed",x instanceof Error?x.message:String(x))}}else Q("onboard","skipped");Q("store-creds","running"),v4({id:V,label:W,tunnelUrl:R??"",apiKey:E,permissions:Y,addedAt:new Date().toISOString(),agentRecordId:h??void 0,workspaceId:(typeof C.workspaceId==="string"?C.workspaceId:U.workspaceId)??void 0,fingerprint:V,ownerUserId:U.ownerUserId,sshTarget:J.mode==="ssh"?$.target:void 0,sshIdentityFile:$.identityFile}),Q("store-creds","completed");let F=u2();if($.onboardBackend!==!1&&g.isConfigured()&&F&&h){Q("report-link","running");try{await g.workspaceQuery(CQ,{input:{sourceAgentRecordId:F,destinationAgentRecordId:h,label:W}}),Q("report-link","completed")}catch(x){Q("report-link","failed",x instanceof Error?x.message:String(x))}}else Q("report-link","skipped");let T=await C2(V,"/api/profiles/default/agent/identity",{operation:"post-deploy-probe"});return Q("probe-peer",T.ok?"completed":"failed",T.error??void 0),{ok:!0,peerId:V,agentRecordId:h,tunnelUrl:R,permissions:Y,remoteVersion:B}}catch(N){return X(N instanceof Error?N.message:String(N))}finally{await J.close().catch(()=>{})}}var L0='export PATH="$HOME/.bun/bin:$PATH"; ';function qQ($){let Z=$.indexOf("{"),Q=$.lastIndexOf("}");if(Z>=0&&Q>Z)try{let Y=JSON.parse($.slice(Z,Q+1));if(Y.tunnelUrl)return Y.tunnelUrl;if(Y.url&&Y.url.startsWith("https"))return Y.url}catch{}return null}async function c4($,Z){let Q=(J,W,H)=>Z?.({step:J,status:W,message:H}),Y=b4($);if(!Y)return{ok:!1,peerId:$,tunnelUrl:null,error:`No peer with id ${$}`};if(!Y.sshTarget)return{ok:!1,peerId:$,tunnelUrl:null,error:"No SSH target stored for this peer \u2014 it wasn't SSH-deployed, so it can't be woken via SSH."};let X;try{X=n2(Y.sshTarget,{identityFile:Y.sshIdentityFile})}catch(J){return{ok:!1,peerId:$,tunnelUrl:null,error:J instanceof Error?J.message:String(J)}}try{Q("ssh-restart","running",Y.sshTarget);let J=await X.run(["sh","-c",`${L0}vibe restart 2>/dev/null || ${L0}vibe start`],{timeoutMs:90000});if(J.code!==0)return Q("ssh-restart","failed",J.stderr.slice(0,300)),{ok:!1,peerId:$,tunnelUrl:null,error:`Remote restart failed (exit ${J.code})`};Q("ssh-restart","completed"),Q("await-tunnel","running");let W=null;for(let H=0;H<15;H++){let B=await X.run(["sh","-c",`${L0}vibe url --json 2>/dev/null`],{timeoutMs:15000});if(B.code===0){let K=qQ(B.stdout),N=d2(K);if(N){W=N;break}}await new Promise((K)=>setTimeout(K,2000))}if(!W)return Q("await-tunnel","failed","no fresh tunnel after restart"),{ok:!1,peerId:$,tunnelUrl:null,error:"Agent restarted but no fresh tunnel came up."};return Q("await-tunnel","completed",W),y4($,{tunnelUrl:W,lastReachable:new Date().toISOString()}),Q("update","completed"),{ok:!0,peerId:$,tunnelUrl:W}}catch(J){return{ok:!1,peerId:$,tunnelUrl:null,error:J instanceof Error?J.message:String(J)}}finally{await X.close().catch(()=>{})}}var kQ=Number(process.env.VIBECONTROLS_MESH_MAX_HOPS||"8");function u4(){return(b()??G()).name}function SQ(){return(b()??G()).dataDir}function m4(){try{let Z=wQ(SQ(),"runtime.json");if(RQ(Z)){let Q=JSON.parse(AQ(Z,"utf8"));if(Q.port&&Number.isInteger(Q.port))return Q.port}}catch{}let $=Number(process.env.PORT);return Number.isInteger($)&&$>0?$:3005}function DQ($){let Z={};return $.headers.forEach((Q,Y)=>{Z[Y]=Q}),Z}function Z2($,Z){let Q=m(DQ($));return l4(p4(Q),Z)}function hQ($){let{apiKey:Z,...Q}=$;return{...Q,apiKey:"[REDACTED]"}}function g4($){return typeof $==="string"&&$.startsWith("/api/")&&!$.includes("..")&&!$.includes("//")}var i2=new Map;function vQ(){let $=Date.now()-3600000;for(let[Z,Q]of i2)if(Q.completedAt&&Date.parse(Q.completedAt)<$)i2.delete(Z)}function n4(){return new D({name:"agent-mesh"}).get("/api/mesh/peers",({request:$,set:Z})=>{if(!Z2($,["read"]))return Z.status=403,{error:"forbidden"};return{peers:K2(n()).map(hQ)}}).delete("/api/mesh/peers/:id",({request:$,set:Z,params:Q})=>{if(!Z2($,["mutate"]))return Z.status=403,{error:"forbidden"};if(!K2(n()).some((X)=>X.id===Q.id))return Z.status=404,{error:"not found"};return{ok:d4(Q.id)}}).post("/api/mesh/peers/:id/call",async({request:$,set:Z,params:Q,body:Y})=>{if(!Z2($,["mesh:forward"]))return Z.status=403,{error:"forbidden"};let X=Y;if(!g4(X.path))return Z.status=400,{error:"invalid path"};if(!K2(n()).find((H)=>H.id===Q.id))return Z.status=404,{error:"not found"};let W=await C2(Q.id,X.path,{method:X.method??"GET",body:X.body,operation:"mesh-call"});return{ok:W.ok,status:W.status,data:W.data,rotated:W.rotated,error:W.error}},{body:z.Object({method:z.Optional(z.String()),path:z.String(),body:z.Optional(z.Any())})}).post("/api/mesh/forward",async({request:$,set:Z,body:Q})=>{if(!Z2($,["mesh:forward"]))return Z.status=403,{error:"forbidden"};let Y=Q;if(!Y.request||!g4(Y.request.path))return Z.status=400,{error:"invalid request"};let X=(Y._hopCount??0)+1;if(X>kQ)return Z.status=422,{error:"hop limit exceeded"};let J=n(),W=u2(),H=Y.hops??[];if(H.length===0){G().audit.emit("mesh","forward.terminal",{path:Y.request.path,method:Y.request.method??"GET"});let U=(Y.request.method??"GET").toUpperCase();try{let V=await fetch(`http://127.0.0.1:${m4()}${Y.request.path}`,{method:U,headers:{"x-agent-api-key":await O0(),...Y.request.body!==void 0?{"content-type":"application/json"}:{}},body:Y.request.body!==void 0?JSON.stringify(Y.request.body):void 0,signal:AbortSignal.timeout(60000)}),E=await V.text().catch(()=>""),R=null;try{R=E?JSON.parse(E):null}catch{R=null}return{ok:V.ok,status:V.status,data:R,text:E||null,error:V.ok?null:E||`status ${V.status}`}}catch(V){return Z.status=502,{ok:!1,status:0,error:V instanceof Error?V.message:String(V)}}}let B=H[0],K=Y._traversed??[];if(B===W||K.includes(B))return Z.status=422,{error:"cycle detected",at:B};let N=j0(B,J);if(!N)return Z.status=403,{error:"next hop not in authorized boundary"};if(!N.permissions.includes("mesh:forward"))return Z.status=403,{error:"peer lacks mesh:forward grant"};G().audit.emit("mesh","forward.hop",{nextId:B,remaining:H.length,hopCount:X});let I=encodeURIComponent(u4()),C=await C2(N.id,`/api/profiles/${I}/mesh/forward`,{method:"POST",operation:"mesh-forward",timeoutMs:60000,body:{hops:H.slice(1),request:Y.request,_traversed:[...K,W??"self"],_hopCount:X}});if(!C.ok)return Z.status=502,{ok:!1,status:C.status,error:C.error,failedAtHop:B};return C.data},{body:z.Object({hops:z.Optional(z.Array(z.String())),request:z.Object({method:z.Optional(z.String()),path:z.String(),body:z.Optional(z.Any())}),_traversed:z.Optional(z.Array(z.String())),_hopCount:z.Optional(z.Number())})}).post("/api/mesh/deploy",({request:$,set:Z,body:Q})=>{if(!Z2($,["admin"]))return Z.status=403,{error:"forbidden"};vQ();let Y=Q,X=n(),J=crypto.randomUUID(),W={id:J,status:"running",steps:[],ownerUserId:X.ownerUserId,workspaceId:X.workspaceId,startedAt:new Date().toISOString()};return i2.set(J,W),f4({target:Y.target,permissions:Y.permissions,installPlugins:Y.installPlugins,autostart:Y.autostart,identityFile:Y.identityFile,label:Y.label,version:Y.version,connectExisting:Y.connectExisting},(H)=>{W.steps.push(H),J2("mesh:deploy:progress",{jobId:J,step:H})}).then((H)=>{if(W.result=H,W.status=H.ok?"completed":"failed",!H.ok)W.error=H.error;W.completedAt=new Date().toISOString(),J2(H.ok?"mesh:deploy:complete":"mesh:deploy:failed",{jobId:J,result:H})}).catch((H)=>{W.status="failed",W.error=H instanceof Error?H.message:String(H),W.completedAt=new Date().toISOString(),J2("mesh:deploy:failed",{jobId:J,error:W.error})}),Z.status=202,{jobId:J,status:"running"}},{body:z.Object({target:z.String(),permissions:z.Optional(z.Array(z.String())),installPlugins:z.Optional(z.Array(z.String())),autostart:z.Optional(z.Boolean()),identityFile:z.Optional(z.String()),label:z.Optional(z.String()),version:z.Optional(z.String()),connectExisting:z.Optional(z.Boolean())})}).get("/api/mesh/deploy/jobs/:id",({request:$,set:Z,params:Q})=>{if(!Z2($,["read"]))return Z.status=403,{error:"forbidden"};let Y=i2.get(Q.id),X=n();if(!Y||X.ownerUserId&&Y.ownerUserId&&Y.ownerUserId!==X.ownerUserId)return Z.status=404,{error:"not found"};return Y}).post("/api/mesh/wake",async({request:$,set:Z,body:Q})=>{if(!Z2($,["admin"]))return Z.status=403,{error:"forbidden"};let Y=Q,X=j0(Y.targetAgentRecordId,n());if(!X)return Z.status=404,{ok:!1,error:"peer not in authorized boundary"};G().audit.emit("mesh","wake.start",{peerId:X.id,agentRecordId:Y.targetAgentRecordId});let J=await c4(X.id,(W)=>J2("mesh:wake:progress",{peerId:X.id,step:W}));if(!J.ok)Z.status=502;return J},{body:z.Object({targetAgentRecordId:z.String()})}).post("/api/mesh/session",async({request:$,set:Z,body:Q})=>{if(!Z2($,["mesh:forward","mutate"]))return Z.status=403,{error:"forbidden"};let Y=Q,X=Y.sessionId&&/^[A-Za-z0-9_-]{1,128}$/.test(Y.sessionId)?Y.sessionId:crypto.randomUUID(),J=encodeURIComponent(u4()),W=await O0(),H=`http://127.0.0.1:${m4()}`,B=Y.command||"bash";try{let K=await fetch(`${H}/api/profiles/${J}/sessions/create`,{method:"POST",headers:{"x-agent-api-key":W,"content-type":"application/json"},body:JSON.stringify({sessionId:X,sessionName:`vc-mesh-${X.slice(0,8)}`,command:B,provider:"TERMINAL",...Y.vibeId?{projectId:Y.vibeId}:{}}),signal:AbortSignal.timeout(20000)});if(!K.ok)return Z.status=502,{error:`session create returned ${K.status}: ${await K.text().catch(()=>"")}`};let N=await fetch(`${H}/api/profiles/${J}/sessions/${encodeURIComponent(X)}/terminal`,{method:"POST",headers:{"x-agent-api-key":W},signal:AbortSignal.timeout(20000)});if(!N.ok)return Z.status=502,{error:`terminal start returned ${N.status}: ${await N.text().catch(()=>"")}`};let I=D2(`/terminal/${X}`,600);return G().audit.emit("mesh","session.created",{sessionId:X,kind:Y.kind??"TERMINAL"}),{connectionId:X,sessionId:X,capabilityToken:I.token,expiresAt:I.expiresAt}}catch(K){return Z.status=502,{error:K instanceof Error?K.message:String(K)}}},{body:z.Object({sessionId:z.Optional(z.String()),kind:z.Optional(z.String()),cwd:z.Optional(z.String()),vibeId:z.Optional(z.String()),command:z.Optional(z.String())})})}var PQ=["/health","/api/agent/status","/api/agent/version","/api/agent/identity","/api/agent/api-key","/api/agent/tunnel","/api/agent/system","/api/agent/gateway-auth","/api/stats","/metrics","/api/profiles","/api/profile-stats"];function fQ($){return PQ.some((Z)=>$.startsWith(Z))}var bQ=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function yQ($){return $.split("/").map((Z)=>{if(!Z)return Z;if(/^\d+$/.test(Z))return":id";if(bQ.test(Z))return":id";if(Z.length>=24&&/^[A-Za-z0-9_-]+$/.test(Z))return":id";return Z}).join("/")}async function l8($){let{port:Z,host:Q,dbPath:Y,logLevel:X,corsOrigin:J}=$,W=Y??M2();try{(await import("fs")).mkdirSync(W,{recursive:!0})}catch(_){throw G().logger.error("app","Failed to create dbPath dir at boot",{dbPath:W,error:String(_)}),Error(`Cannot create dbPath ${W}: ${_ instanceof Error?_.message:String(_)}`,{cause:_})}if(X)G().logger.setLevel(X);(async()=>{let{logShipper:_}=await import("./log-shipper-k24m8yw5.js");_.init()})(),(async()=>{let _=await o4();await w2({version:_,profile:T2()})})();try{let{checkDependencies:_}=await import("./bootstrap.service-pjmnpxha.js"),M=_(),O=M.filter((A)=>A.required&&!A.installed),w=M.filter((A)=>!A.required&&!A.installed);if(O.length>0)G().logger.error("app",`Missing required system deps: ${O.map((A)=>A.name).join(", ")}. Run \`vibe setup\` to install.`);if(w.length>0)G().logger.warn("app",`Missing optional system deps: ${w.map((A)=>A.name).join(", ")}. Some plugins may fail their prereqs check.`)}catch(_){G().logger.warn("app","Boot-time dependency check failed",{error:String(_)})}try{G().audit.runRetention()}catch(_){G().logger.warn("app","Audit-log retention sweep failed",{error:String(_)})}let H=new N5;C5(H,{port:Z});let B="GET, POST, PUT, PATCH, DELETE, OPTIONS",K="Content-Type, x-agent-api-key, Authorization, x-requested-with",N=Array.isArray(J)?J:(J??"").split(",").map((_)=>_.trim()).filter(Boolean),I=new Set(["https://vibecontrols.com","https://app.vibecontrols.com","https://alphaapp.vibecontrols.com","https://burdenoff.com","https://app.burdenoff.com","https://alphaapp.burdenoff.com"]),C=(_)=>{try{let M=new URL(_);if(N.includes(_))return!0;if(N.includes("*"))return!1;return M.hostname==="localhost"||M.hostname==="127.0.0.1"||M.hostname==="0.0.0.0"||M.hostname.endsWith(".local.burdenoff.com")||I.has(M.origin)}catch{return!1}},U=null,V=null,E=null,R=null,h=!1,F=()=>[],T=null,x=null,q=null,c=5000,y=async(_,M)=>{let O=Date.now();try{await Promise.race([Promise.resolve(M()),new Promise((w,A)=>setTimeout(()=>A(Error(`shutdown phase ${_} exceeded ${c}ms`)),c))]),G().logger.info("app",`shutdown.phase ${_} complete`,{ms:Date.now()-O})}catch(w){G().logger.warn("app",`shutdown.phase ${_} failed`,{error:String(w),ms:Date.now()-O})}},o2=async(_)=>{if(h)return;if(h=!0,G().logger.info("app","Agent shutdown starting",{reason:_?.reason??"shutdown"}),await y("plugins",async()=>{if(V)await V.dispatchServerStop(_)}),await y("bootstrap-tunnel",()=>T0()),await y("tracked-subprocesses",async()=>{let{killAllTracked:M}=await import("./subprocess-g9sk1ep9.js");await M()}),_?.reason!=="reload")await y("db-close",async()=>{if(U)await U.close()});await y("http-listener",async()=>{try{await Promise.resolve(r.stop())}catch(M){G().logger.warn("app","Listener stop threw (already stopped or never started?)",{error:String(M)})}}),G().logger.info("app","Agent server stopped"),G().logger.close()},X2=async(_,M)=>{if(G().getBootState()==="ready")return{ok:!0};if(q)return q;return q=(async()=>{G().setBootState("initializing");try{let O={..._,globalGatewayUrl:G2(_.globalGatewayUrl,"globalGatewayUrl"),workspaceGatewayUrl:G2(_.workspaceGatewayUrl,"workspaceGatewayUrl")},w=await L5(O),A=W,v=s({dir:G().dataDir}),p=v.storageAdapter??process.env.VIBE_STORAGE_ADAPTER??void 0,i=v.storageOptions,t=(L)=>{let j=(L instanceof Error?L.message:String(L)).toLowerCase(),k=L&&typeof L==="object"&&"code"in L?String(L.code).toUpperCase():"";if(k==="EBUSY"||k==="EPERM"||k==="EACCES"||k==="EAGAIN"||k==="EMFILE"||k==="ENFILE"||k==="ETIMEDOUT"||k==="ECONNRESET"||k==="ECONNREFUSED"||j.includes("encryption key")||j.includes("fetch")&&j.includes("key")||j.includes("temporarily unavailable")||j.includes("resource busy"))return"transient";if(j.includes("auth tag")||j.includes("authentication tag")||j.includes("unable to authenticate data")||j.includes("bad decrypt")||j.includes("unsupported state")||j.includes("incorrect header check")||j.includes("invalid distance")||j.includes("incorrect data check")||j.includes("unexpected end of")||j.includes("unexpected token")||j.includes("json")&&(j.includes("parse")||j.includes("invalid"))||j.includes("truncated")||j.includes("malformed")||j.includes("corrupt"))return"corruption";return"unknown"},F2=()=>a4({dbPath:A,encryptionKey:w,adapterName:p,adapterOptions:i});try{U=await F2()}catch(L){let j=L,k=t(L),q2=[500,2000,8000];if(k==="transient"||k==="unknown"){G().logger.warn("app",`Storage open failed (${k}); will retry up to ${q2.length} times before quarantine`,{error:L instanceof Error?L.message:String(L),path:A});for(let j2 of q2){await new Promise((P)=>setTimeout(P,j2));try{U=await F2(),j=null;break}catch(P){if(j=P,k=t(P),G().logger.warn("app",`Storage open retry failed (${k}) after ${j2}ms`,{error:P instanceof Error?P.message:String(P)}),k==="corruption")break}}}if(!U&&j){if(k!=="corruption"){let P=j instanceof Error?j.message:String(j);G().logger.error("app",`Storage open failed after retries with non-corruption error (${k}); refusing to quarantine valid data`,{error:P,path:A}),G().recordDegradedReason("storage",P);try{throw j}catch(H2){throw Error(`Storage open failed (${k}); agent is degraded: ${P}`,{cause:H2})}}let j2=j instanceof Error?j.message:String(j);G().logger.error("app","QUARANTINE: Storage file is corrupt \u2014 renaming and creating fresh DB",{errorClass:"corruption",error:j2,path:A});try{let P=await import("fs");if(P.existsSync(A)){let H2=new Date().toISOString().replace(/[:.]/g,"-"),q0=`${A}.broken-${H2}`;P.renameSync(A,q0),G().logger.warn("app",`Quarantined corrupt storage to ${q0} \u2014 fresh DB will be created`,{originalError:j2})}U=await F2()}catch(P){let H2=P instanceof Error?P.message:String(P);throw G().recordDegradedReason("storage",H2),Error(`Storage open failed twice (quarantine path); agent is degraded: ${H2}`,{cause:P})}}}if(!U)throw Error("Internal error: storage open recovery exited without an open database and without throwing");if(await S2({clientId:O.clientId,clientSecret:O.clientSecret,workspaceId:O.workspaceId,organizationId:O.organizationId,globalGatewayUrl:O.globalGatewayUrl,workspaceGatewayUrl:O.workspaceGatewayUrl,agentRecordId:M?.agentRecordId,scopes:M?.scopes},{dir:G().dataDir,scope:G().name}),await U.setConfig("gateway-auth:clientId",O.clientId),await U.setConfig("gateway-auth:clientSecret",O.clientSecret),await U.setConfig("gateway-auth:globalGatewayUrl",O.globalGatewayUrl),await U.setConfig("gateway-auth:workspaceGatewayUrl",O.workspaceGatewayUrl),await U.setConfig("gateway-auth:workspaceId",O.workspaceId),O.organizationId)await U.setConfig("gateway-auth:organizationId",O.organizationId);if(M?.agentRecordId)await U.setConfig("gateway-auth:agentRecordId",M.agentRecordId);H.db=U,await H.hydrateDefaultsFromDb(),V=new M5(U),await V.loadCorePlugins();try{await V.loadAll()}catch(L){G().logger.warn("app","Failed to load some external plugins",{error:String(L)})}let L2=T5(V2())??void 0,O2=process.env.VIBE_SKIP_AUTO_INSTALL==="1"||await U.getConfig("plugins:auto-install-disabled");if(O2!=="true"&&O2!==!0)try{let L=await V.ensureDefaultPlugins((j)=>G().logger.info("app",`[auto-install] ${j}`),[],L2);if(L.length>0)G().logger.info("app",`Auto-installed ${L.length} default plugin(s): ${L.map((j)=>j.packageName).join(", ")}`)}catch(L){G().logger.warn("app","Failed to auto-install default plugins",{error:String(L)})}G().logger.info("app",`Plugins loaded: ${V.getPluginDetails().length} total (${V.getPluginDetails().filter((L)=>L.isCore).length} core)`);try{let L=V.getPluginDetails(),j={loaded:L.filter((k)=>k.loaded).length,failed:L.filter((k)=>!k.loaded).length};P0(j)}catch{}let s2={async get(L,j){return await U.getPluginState(L,j)??null},async set(L,j,k){await U.setPluginState(L,j,k)},async delete(L,j){return U.deletePluginState(L,j)},async list(L){return await U.getAllPluginState(L)},async deleteAll(L){return U.deleteAllPluginState(L)}},I2=await o4();E={storage:s2,logger:G().logger,serviceRegistry:H,getProvider:(L)=>H.getProvider(L),getAgentBaseUrl:()=>process.env.AGENT_URL||`http://localhost:${Z}`,getAgentVersion:()=>I2,validateApiKey:(L)=>l(L),setCodeServerSessionValidator:(L)=>{I5=L},broadcast:J2,workspaceQuery:async(L,j)=>g.workspaceQuery(L,j),isGatewayConfigured:()=>g.isConfigured(),getAgentRecordId:async()=>await U.getConfig("gateway-auth:agentRecordId")??null,getWorkspaceId:async()=>await U.getConfig("gateway-auth:workspaceId")??null,getConfig:async(L)=>await U.getConfig(L)??void 0,getPluginRegistry:()=>l2(),getDataDir:()=>k2(),cliContributors:new F5,audit:{emit:(L,j)=>G().audit.emit("agent",L,j??{})},telemetry:{emit:(L,j)=>{import("./telemetry-tnq47dcs.js").then(({telemetryService:k})=>k.emit(L,j??{})).catch(()=>{})}},os:_2(),iframeBridge:x5()},g.configure({globalGatewayUrl:O.globalGatewayUrl,workspaceGatewayUrl:O.workspaceGatewayUrl,clientId:O.clientId,clientSecret:O.clientSecret,workspaceId:O.workspaceId,organizationId:O.organizationId});let z2={db:U,serviceRegistry:H,pluginManager:V,broadcast:J2,hostServices:E};z2.app=r;let I0=!1,r2=()=>{let{routes:L,getPublicPaths:j,mountPlugin:k}=e4(V,z2);if(z2.mountPlugin=k,F=j,J5(),T=L,x=U5(V),V&&I0&&E)V.dispatchServerStart(T,E).catch((q2)=>G().logger.warn("app","Re-dispatch of onServerStart after plugin reload failed",{error:String(q2)}));I0=!0};z2.rebuildPluginSurfaces=r2,r2(),R=new O5(H,V,U,r,E,o2),H.registerService("agent","lifecycle",R),G().attachServices({db:U,serviceRegistry:H,pluginManager:V,lifecycle:R,hostServices:E}),K5(G(),{rebuildPluginSurfaces:r2,mountPlugin:z2.mountPlugin});try{await G().keyVault.bindApiKey(x2())}catch(L){G().logger.warn("app","Failed to bind api key into daemon keyVault",{error:String(L)})}let t2=[];try{let{failures:L}=await V.dispatchServerStart(T,E);for(let j of L)if(M0(j.plugin)||(j.packageName?M0(j.packageName):!1))t2.push(j),G().recordDegradedReason(j.plugin,j.error);else G().logger.warn("app",`Non-critical plugin ${j.plugin} failed onServerStart; continuing`,{error:j.error})}catch(L){G().logger.warn("app","Error during plugin onServerStart dispatch",{error:String(L)})}try{await V.dispatchServerReady(r,E)}catch(L){G().logger.warn("app","Error during plugin onServerReady dispatch",{error:String(L)})}if(G().clearFinalizeError(),t2.length>0)G().setBootState("degraded"),G().logger.error("app","Agent finalized but degraded \u2014 critical plugins failed",{failures:t2.map((L)=>`${L.plugin}: ${L.error}`)});else G().setBootState("ready"),G().logger.info("app","Agent finalized \u2014 state=ready"),G().audit.emit("agent","gateway-auth.configured",{workspaceId:O.workspaceId,organizationId:O.organizationId,agentRecordId:M?.agentRecordId});return(async()=>{try{if(await V.provisionDefaultPrereqs(r,E,z2.mountPlugin,L2),G().logger.info("app","Default provider prerequisites provisioned"),(H.listProvidersForType("tunnel")??[]).some((k)=>k.pluginName!=="bootstrap")){let{tryHandoverBootstrapTunnel:k}=await import("./tunnel-bootstrap-2kg79ng8.js");if(!k())T0();H.unregisterProvider("tunnel","bootstrap"),G().logger.info("app","Bootstrap tunnel handed over to the real tunnel provider")}}catch(L){G().logger.warn("app","Plugin prerequisite provisioning failed",{error:String(L)})}})(),{ok:!0}}catch(O){G().setBootState("awaiting-config");let w=O instanceof Error?O.message:String(O);if(G().recordFinalizeError(w),G().logger.error("app","Finalize failed",{error:w}),process.env.VIBE_STRICT_KEY_FETCH==="1")G().logger.error("app","VIBE_STRICT_KEY_FETCH=1 \u2192 aborting daemon (strict mode)",{error:w}),setTimeout(()=>process.exit(1),50);return{ok:!1,error:w}}finally{q=null}})(),q},N2=A0({origin:(_)=>{let M=_.headers.get("origin");return!!M&&C(M)},credentials:!0,allowedHeaders:K.split(",").map((_)=>_.trim()),methods:B.split(",").map((_)=>_.trim()),exposeHeaders:["content-type","content-length"],maxAge:86400,preflight:!0}),q5=10485760,E0=process.env.VIBECONTROLS_MAX_BODY_BYTES,a2=E0?Number.parseInt(E0,10):NaN,R5=Number.isFinite(a2)&&a2>0?a2:q5,C0={current:null},r=new D({serve:{maxRequestBodySize:R5}}).onRequest(({request:_,set:M})=>{let w=s4(_.headers)??U0();r4({requestId:w,startedAt:new Date().toISOString()});let A=M.headers??={};A["X-Request-Id"]=w}).onRequest(({request:_})=>{try{let M=new URL(_.url).pathname,w=/^\/api\/profiles\/([^/]+)(?:\/|$)/.exec(M)?.[1],A=w?a.get(w):null;x0(A??G())}catch{x0(G())}}).onRequest(({request:_,set:M})=>{let O=new URL(_.url).pathname;if(!O.startsWith("/api/"))return;if(O==="/api/profiles"||O.startsWith("/api/profiles/"))return;if(O==="/api/profile-stats"||O.startsWith("/api/profile-stats/"))return;let w=new URL(_.url);w.pathname=`/api/profiles/default${O.slice(4)}`;try{_.headers.set("x-vc-profile-rewrite","1"),_.headers.set("x-vc-profile-rewrite-target",w.pathname)}catch{}return}).derive(()=>({requestId:t4()??U0()})).use(N2).use(Y5()).use(X5(()=>F())).use(S0({getDb:()=>b()?.db??U})).onBeforeHandle(({request:_,set:M})=>{let O=G().getBootState();if(O==="ready")return;let w=new URL(_.url).pathname;if(fQ(w))return;return M.status=503,{error:"Agent not yet configured",message:"Agent is in '"+O+"' state. POST credentials to /api/agent/gateway-auth to finalize.",state:O}}).onAfterHandle(({request:_,set:M})=>{let O=new URL(_.url).pathname,w=O==="/health"||O.startsWith("/api/logs/stream")||O.startsWith("/ui/")||O==="/ws/events"||O==="/api/sessions/health-check"||O.startsWith("/terminal/"),A=typeof M.status==="number"?M.status:200,v=w?"debug":A>=400?"warn":"info";G().logger[v]("http",`${_.method} ${O} \u2192 ${A}`,{method:_.method,path:O,statusCode:A});try{v0(_.method,yQ(O),A)}catch{}}).use(Y4({serviceRegistry:H,getDb:()=>b()?.db??U,getDbPath:()=>W,getPluginManager:()=>b()?.pluginManager??V})).use(b0()).use(n0({serviceRegistry:H,runFinalize:(_,M)=>X2(_,M),getDb:()=>b()?.db??U})).use(z4()).use(H4()).use(D4({getPluginManager:()=>b()?.pluginManager??V})).use(n4()).use(K4()).use(U4({getPluginManager:()=>b()?.pluginManager??V,getTunnelHost:()=>E5()?.url??null})).use(Q4()).use(Z4()).use(G5()).use(V5()).use(B5(H)).ws("/code-server/*",uQ(Z)).all("/api/profiles/:name/*",async({params:_,request:M,set:O})=>{let w=M.method!=="GET"&&M.method!=="HEAD",A=w?await M.arrayBuffer():void 0,v=await _5(_.name,M,A);if(v&&v.status!==404)return v;let p=T2(),i=_.name;if(i!==p)return O.status=404,{error:"profile-mismatch",running:p,requested:i,hint:"This daemon serves a different profile. Call GET /api/profiles to discover the right tunnel."};let t=new URL(M.url),F2=t.pathname.replace(/^\/api\/profiles\/[^/]+/,"/api"),L2=new Headers(M.headers);L2.set("x-vc-profile-rewrite","1");let O2={method:M.method,headers:L2};if(w&&A!==void 0)O2.body=A;let s2=new Request(`${t.origin}${F2}${t.search}`,O2),I2=C0.current;if(!I2)return new Response(JSON.stringify({error:"agent-not-ready"}),{status:503,headers:{"content-type":"application/json"}});return I2.handle(s2)}).all("/api/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response(JSON.stringify({error:"Agent not yet configured",state:G().getBootState(),message:"Plugin routes are unavailable until the agent reaches state=ready. POST credentials to /api/agent/gateway-auth to finalize."}),{status:503,headers:{"content-type":"application/json"}});try{let M=new URL(_.url),O=/^\/api\/plugins\/([a-z0-9-]{1,64})\/ui(?:\/.*)?$/.exec(M.pathname);if(O&&_.method==="GET"){let w=O[1];if(U2(w)){let A=M.pathname.slice(`/api/plugins/${w}/ui`.length),v=A===""||A==="/",i=_.headers.get("sec-fetch-mode")==="navigate";if(v||i){let t=Z5(_,w);if(!t||!$5(t,w))return new Response(j5(w,"/api/profiles/default/agent/ui-exchange-plugin"),{status:200,headers:{"content-type":"text/html; charset=utf-8","Content-Security-Policy":"frame-ancestors 'self' http://localhost:* http://127.0.0.1:* https://localhost:* https://127.0.0.1:* https://*.local.burdenoff.com https://vibecontrols.com https://*.vibecontrols.com https://burdenoff.com https://app.burdenoff.com https://alphaapp.burdenoff.com"}})}}}}catch{}return T.handle(_)}).all("/ui/*",async({request:_})=>{if(G().getBootState()!=="ready"||!x)return new Response("Plugin UI not yet available",{status:503});return x.handle(_)}).all("/code-server/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response("code-server not yet available",{status:503});return T.handle(_)}).all("/plan/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response("plan provider not yet available",{status:503});return T.handle(_)});return C0.current=r,{app:r,async start(){r.listen({port:Z,hostname:Q}),G().logger.info("app",`Agent server listening on ${Q}:${Z}`);try{let _=(process.env.VIBECONTROLS_PROFILES??"").split(",").map((v)=>v.trim()).filter(Boolean),M=G().name,{getOrCreateProfile:O}=await import("./daemon-profile-vas1vf2t.js"),{attachSecondaryProfile:w}=await import("./secondary-profile-attach-db5cr3e1.js"),A=process.env.VIBE_STRICT_KEY_FETCH==="1";for(let v of _){if(v===M)continue;try{let p=O(v),i=await w(p);if(i.ok)G().logger.info("app",`Secondary profile '${v}' attached (db+services online)`);else if(A)throw Error(`attachServices for secondary profile '${v}' failed: ${i.error}`);else p.recordDegradedReason("attach",i.error??"unknown"),G().logger.warn("app",`Secondary profile '${v}' is degraded (no creds / attach failed)`,{error:i.error})}catch(p){if(A)throw G().logger.error("app",`--strict-key-fetch: secondary profile '${v}' attach failed; aborting`,{error:String(p)}),setTimeout(()=>process.exit(1),50),p;G().logger.warn("app",`Failed to attach secondary profile '${v}'`,{error:String(p)})}}}catch{}return r},stop:o2,finalize:X2,getState:()=>G().getBootState(),getLifecycle:()=>b()?.lifecycle??R,getDb:()=>b()?.db??U,getServiceRegistry:()=>b()?.serviceRegistry??H,getPluginManager:()=>b()?.pluginManager??V,getHostServices:()=>b()?.hostServices??E}}var I5=null;function cQ($,Z){if(!$)return null;let Q=$.match(new RegExp(`(?:^|;\\s*)${Z}=([^;]*)`));return Q?Q[1]:null}var i4=W5(z5);function uQ($){let X=(J)=>typeof J==="string"?Buffer.byteLength(J):J.byteLength;return{open(J){let W=J.data,H=m(W.headers??{})??m(W.request?Object.fromEntries(W.request.headers.entries()):{}),B=W.query?.vt,K=!!B&&Q5(B,"/code-server","GET"),N,I=l(H);if(!I&&!K){let E=W.headers?.cookie??W.request?.headers.get("cookie")??null,R=cQ(E,"__vibe_cs_session");if(!R||!I5?.(R)){J.close(1008,"Unauthorized");return}N=`session:${R}`}else if(I)N="api-key";else N="vt";let C=J.remoteAddress??null,U=H5(C,W.headers);if(!i4.accept(N,U,J)){G().logger.warn("code-server-ws",`code-server WS cap exceeded (key=${N}, ip=${U??"unknown"})`),J.close(1013,"too many connections");return}W._csCapKey=N,W._csRemoteIp=U;let V=G().name;fetch(`http://127.0.0.1:${$}/api/profiles/${encodeURIComponent(V)}/code-server/status`,{headers:{"x-agent-api-key":x2()}}).then((E)=>E.json()).then((E)=>{if(W._csClosed)return;let R=E;if(!R.running||!R.port){J.close(1011,"code-server not running");return}let h=W.request?.url??"/code-server/",F;try{let q=new URL(h,`http://127.0.0.1:${R.port}`);F=(q.pathname.replace(/^\/code-server\/?/,"/")||"/")+q.search}catch{F="/"}let T=new WebSocket(`ws://127.0.0.1:${R.port}${F}`),x={upstream:T,ready:!1,buffer:[],bufferBytes:0,openTimer:setTimeout(()=>{try{T.close(1011,"upstream open timeout")}catch{}try{J.close(1011,"upstream open timeout")}catch{}},1e4)};W._csBridge=x,T.addEventListener("open",()=>{clearTimeout(x.openTimer),x.ready=!0;for(let q of x.buffer)T.send(q);x.buffer.length=0,x.bufferBytes=0}),T.addEventListener("message",(q)=>{try{let c=q.data;if(c instanceof ArrayBuffer)J.send(new Uint8Array(c));else if(c instanceof Blob)c.arrayBuffer().then((y)=>{try{J.send(new Uint8Array(y))}catch{}});else J.send(c)}catch{}}),T.addEventListener("close",(q)=>{clearTimeout(x.openTimer);try{J.close(q.code||1000,q.reason||"upstream closed")}catch{}}),T.addEventListener("error",()=>{clearTimeout(x.openTimer);try{J.close(1011,"upstream error")}catch{}})}).catch(()=>{J.close(1011,"Failed to query code-server status")})},message(J,W){let H=J.data?._csBridge;if(!H)return;let B;if(typeof W==="string")B=W;else if(W instanceof ArrayBuffer)B=W;else if(W instanceof Uint8Array||Buffer.isBuffer(W)){let K=new ArrayBuffer(W.byteLength);new Uint8Array(K).set(new Uint8Array(W.buffer,W.byteOffset,W.byteLength)),B=K}else if(typeof W==="object"&&W!==null)B=JSON.stringify(W);else B=String(W);if(H.upstream&&H.ready&&H.upstream.readyState===WebSocket.OPEN)try{H.upstream.send(B)}catch{}else{let K=X(B);if(H.buffer.length>=256||H.bufferBytes+K>1048576){try{H.upstream.close(1013,"buffer limit exceeded")}catch{}try{J.close(1013,"buffer limit exceeded")}catch{}return}H.buffer.push(B),H.bufferBytes+=K}},close(J){J.data._csClosed=!0;let W=J.data?._csBridge;if(W?.openTimer)clearTimeout(W.openTimer);if(W?.upstream&&W.upstream.readyState===WebSocket.OPEN)W.upstream.close(1000,"client disconnected");let H=J.data._csCapKey,B=J.data._csRemoteIp;if(H)i4.release(H,B??null,J)}}}async function o4(){try{let{readFileSync:$}=await import("fs"),{join:Z,dirname:Q}=await import("path"),{fileURLToPath:Y}=await import("url"),X=Q(Y(import.meta.url));return JSON.parse($(Z(X,"..","package.json"),"utf8")).version||"1.0.0"}catch{return"1.0.0"}}
|
|
26
|
+
export{X6 as j,u0 as k,NQ as l,B7 as m,l8 as n};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{L as r1}from"./index-2gsarrbn.js";import{M as b2}from"./index-b5dhmybd.js";import{O as a$,P as B1}from"./index-e1bw1bwr.js";import{$ as U2,Q as r$,R as c$,S as s0,T as r0,U as e$,V as e0,W as $0,X as $1,Y as D$,Z as E$,_ as J2,ca as z0,da as I2,ea as _2,fa as K0,ga as U1,ha as I1,ia as _1,ja as L2,ka as W0}from"./index-g8zv1gta.js";import{la as J$,ma as X$,na as B$,oa as Q1,ta as w2}from"./index-qfz9fy56.js";import{va as o}from"./index-ssjmzqcz.js";import{Ca as X2}from"./index-4wgjx8bf.js";import{Ea as t1,Fa as k$,Ha as o$,Ma as t0,Oa as s1,Pa as g2,Wa as s$}from"./index-g3ap3xpr.js";import{Xa as l}from"./index-0ckffygp.js";import{Ya as d1,ab as a}from"./index-rc79x8fw.js";import{db as P2}from"./index-52cp759f.js";import{Ib as M2}from"./index-01qzsnwd.js";import{gc as t$,hc as T$,ic as f,jc as b,kc as B,lc as q0}from"./index-5mw3eshk.js";import{Bc as x$,Cc as W$,Dc as u$,nc as K,oc as N,pc as V,qc as C,rc as U,sc as j,tc as W,uc as T,vc as _,wc as J,xc as n,yc as G$}from"./index-z5a4yxzz.js";import{Ec as b0,Fc as e,Gc as v$}from"./index-ef95xr4z.js";import{Kc as M,Mc as S,Nc as y,Oc as m,Pc as L0,Qc as P$}from"./index-xjzmb1pn.js";import{Rc as Z2,Tc as A0,Uc as a1,Wc as G2,Xc as f0,Zc as y$,ad as F2,bd as f$,cd as P0,dd as T2,ed as V0,fd as R2,gd as j2,hd as E2,id as N2,kd as B0,ld as O1,nd as q$,pd as U$,td as a0}from"./index-g2raeeh4.js";import{Nd as c0,zd as O0}from"./index-9bqd8veb.js";import{$d as V$,Xd as Y0,_d as Q$,ae as N$,be as Z$}from"./index-0cn9bv8z.js";import{he as Y$}from"./index-yy1mm8zs.js";import{existsSync as o0}from"fs";import{join as p2}from"path";import{createServer as n2}from"net";function i2(Y,q="0.0.0.0"){return new Promise(($)=>{let Z=n2();Z.once("error",()=>$(!1)),Z.once("listening",()=>{Z.close(()=>$(!0))}),Z.listen({host:q,port:Y,exclusive:!0})})}async function p0(Y,q="0.0.0.0"){let $=Y;while(!await i2($,q))if($++,$>65535)throw Error(`No free port found starting from ${Y}`);return $}function Y1(Y){Y.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>","Port to listen on. Default: 3005 for the 'default' profile, deterministic 3100-3399 for any other profile (FNV-1a hash) so multiple profiles run side-by-side without EADDRINUSE.").option("-n, --name <name>","Agent instance name","default").option("-f, --foreground","Run in foreground mode (default: daemon)",!1).option("--db-path <path>","Path to the agent storage directory").option("--profile <profile>","Profile name for isolated config (env: VIBECONTROLS_PROFILE)").option("--host <host>","Host to bind to","0.0.0.0").option("--skip-plugin-install","Skip automatic installation of default plugins",!1).option("--skip-plugin <name>","Skip a specific default plugin (repeatable). Accepts the short pluginName or the full package name.",(q,$=[])=>[...$,q],[]).option("--no-install-deps","Skip auto-installing missing tools (installed by their plugins on start by default)").option("-y, --yes","Skip the first-run install consent prompt. Equivalent to VIBE_AUTO_ACCEPT=1; useful for CI / Docker / nohup contexts.",!1).option("--client-id <id>","Gateway OAuth client ID (env: VIBE_CLIENT_ID)").option("--client-secret <secret>","Gateway OAuth client secret (env: VIBE_CLIENT_SECRET)").option("--global-gateway-url <url>","Global gateway URL (env: VIBE_GLOBAL_GATEWAY_URL)").option("--workspace-gateway-url <url>","Workspace gateway URL (env: VIBE_WORKSPACE_GATEWAY_URL)").option("--workspace-id <id>","Workspace ID for auto-report (env: VIBE_WORKSPACE_ID)").option("--isolate <plugins>","Comma-separated list of plugin names to force into worker_threads isolation (Phase 4 hostile-plugin mode). Sets VIBE_ISOLATE_PLUGINS in the daemon env.").option("--profiles <names>","Comma-separated list of profiles to host in this daemon (multi-profile boot). When unset, the daemon hosts a single profile resolved via --profile / VIBECONTROLS_PROFILE / 'default'. Sets VIBECONTROLS_PROFILES in the daemon env so app boot can spin up additional ProfileContexts via the in-process registry.").option("--strict-key-fetch","Refuse to boot if any profile's encryption-key fetch fails. Default lenient: a failed profile is marked degraded and the daemon stays up. Sets VIBE_STRICT_KEY_FETCH=1 in the daemon env.",!1).option("--json","Emit JSON").option("--plain","Plain text output (no interactive TUI). Implied for non-TTY / CI.").option("--abilities <list>","Comma-separated ability keys to install non-interactively (e.g. session,ai,gitops). Storage/tunnel/backup are always included.").option("--providers <list>","Comma-separated extra provider plugins to install beyond each meta's default (e.g. session-wezterm,ai-claude). Accepts short names or @vibecontrols/... packages. Persisted; manage later with `vibe capability`.").option("--wait-ready [seconds]","Block until the agent is fully ready (or fails). Polls /health/ready and renders phase transitions live. Without a value, defaults to 60s. Exits non-zero if the agent ends up degraded or times out. Useful for scripts/CI.").option("--no-wait","Skip the phase tracker entirely after spawning the daemon. Restores the old fire-and-print behavior \u2014 for users who want the previous quick-return UX.").action(async function(q){let $={...Y.opts(),...q};try{let E=function(h){if(h==="default")return 3005;let d=2166136261;for(let g=0;g<h.length;g++)d=Math.imul(d^h.charCodeAt(g),16777619);return 3100+Math.abs(d)%300},Z=new o,X=q.profile||process.env.VIBECONTROLS_PROFILE||"default";if(process.env.VIBECONTROLS_PROFILE=X,typeof q.isolate==="string"&&q.isolate.length>0)process.env.VIBE_ISOLATE_PLUGINS=q.isolate;if(typeof q.profiles==="string"&&q.profiles.length>0){let h=q.profiles.split(",").map((d)=>d.trim()).filter(Boolean);if(h.length>0){if(process.env.VIBECONTROLS_PROFILES=h.join(","),process.env.VIBECONTROLS_PROFILE=h[0],h.length>1)j(`--profiles received ${h.length} entries; daemon boots with '${h[0]}'. Remaining (${h.slice(1).join(", ")}) will be attached via /api/profiles after listen.`)}}if(q.strictKeyFetch===!0)process.env.VIBE_STRICT_KEY_FETCH="1";a0();let H=q.dbPath||N$(),Q=Z$(),z=!o0(H)&&!o0(p2(Q,"agents.json")),L=f($),I=L!=="json"&&L!=="plain"&&t$()&&q.yes!==!0,O=r$(Q),G;if(typeof $.abilities==="string"&&$.abilities.trim()!=="")G=e0($.abilities);else if(O!==null)G=O;else if(I)G=await e$();else G=$0();let x=typeof $.providers==="string"&&$.providers.trim()!=="",F=x?s0($.providers):c$(Q);if(O===null){let h=r0({installDeps:q.installDeps===!0,skipPluginInstall:q.skipPluginInstall===!0,skipPlugins:Array.isArray(q.skipPlugin)?q.skipPlugin:[]},G);if(z&&h.plugins.length>0)J(),W(`Installing ${h.plugins.length} plugin(s) for the selected abilities.`),J();$1(Q,h,G,process.env.VIBE_AGENT_VERSION,F)}else if(x)D$(Q,{providers:F,agentVersion:process.env.VIBE_AGENT_VERSION});if((z||x)&&F.length>0&&q.skipPluginInstall!==!0){W(`Installing ${F.length} selected provider plugin(s)...`);try{let{PluginManager:h}=await import("./plugin-system-c916v9an.js"),d=new h;for(let g of F)try{await d.install(g),U(`Installed provider ${g}`)}catch(u){j(`Could not install provider ${g}: ${u instanceof Error?u.message:String(u)}`)}}catch(h){j(`Provider install skipped: ${h instanceof Error?h.message:String(h)}`)}J()}if(z){W("First run detected \u2014 running setup..."),J();let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=q.skipPluginInstall?[]:o$(process.platform,G).filter((r)=>!h.includes(r.packageName)&&!h.includes(r.pluginName)).map((r)=>r.packageName),g=t0(d),K$=a$(g).filter((r)=>!r.installed);if(K$.length>0)if(j(`Missing tools: ${K$.map((r)=>r.name).join(", ")}`),q.installDeps)W("Their plugins will install them automatically on startup.");else W("Auto-install skipped (`--no-install-deps`) \u2014 install them yourself or drop the flag.");else U("All plugin tools present.");J()}if(!q.skipPluginInstall){let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=new s$;await d.loadCorePlugins(),await d.loadAll();let g=await d.ensureDefaultPlugins((u)=>{if(u.startsWith("No "))j(u);else if(u.startsWith("Installed "))U(u);else if(u.startsWith("Failed "))j(u);else W(u)},h,G);if(g.length>0)U(`Auto-installed ${g.length} default plugin${g.length>1?"s":""}.`),J()}let R=q.profile||process.env.VIBECONTROLS_PROFILE||q.name||"default",w=q.port?parseInt(q.port,10):E(R);if(isNaN(w)||w<1||w>65535)V("Invalid port number. Must be between 1 and 65535.");let D=await p0(w);if(D!==w)j(`Port ${w} is in use. Auto-selecting port ${K.bold(String(D))} instead.`),w=D;let A=q.host,s=`http://${A==="0.0.0.0"?"localhost":A}:${w}`,p=q.clientId||process.env.VIBE_CLIENT_ID,v=q.clientSecret||process.env.VIBE_CLIENT_SECRET,P=q.globalGatewayUrl||process.env.VIBE_GLOBAL_GATEWAY_URL,c=q.workspaceGatewayUrl||process.env.VIBE_WORKSPACE_GATEWAY_URL,O$=q.workspaceId||process.env.VIBE_WORKSPACE_ID;if(p&&!v)V("--client-secret is required when --client-id is provided.");if(v&&!p)V("--client-id is required when --client-secret is provided.");if(p&&v){if(!P&&!process.env.VIBE_GLOBAL_GATEWAY_URL)V("--global-gateway-url is required when providing client credentials (none set in env).");if(process.env.VIBE_CLIENT_ID=p,process.env.VIBE_CLIENT_SECRET=v,P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;let{writeAgentConfig:h}=await import("./agent-config-85pskv43.js");if(h({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c}),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;U("Gateway credentials staged in env. Agent will authenticate and persist them on startup."),J()}else if(c||O$||P){if(j("Workspace options provided without --client-id / --client-secret \u2014 they will be staged in env but unused until credentials are configured."),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;if(P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;J()}if(q.foreground){if(!$.json)T("Starting agent in foreground"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();let{bootstrapWorkspace:h}=await import("./bootstrap-workspace-zpm20zez.js");h();let{createApp:d}=await import("./app-yvjadjmh.js"),g=await d({port:w,host:A,dbPath:H});if(await g.start(),p&&v&&O$&&P&&c){let K$=await g.finalize({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c});if(!K$.ok)j(`Finalize failed \u2014 agent remains in awaiting-config state: ${K$.error}`)}if(B($,{ok:!0,name:q.name,port:w,host:A,pid:process.pid,url:s}));else await u$(s);let u=async()=>{await g.stop(),process.exit(0)};process.on("SIGTERM",u),process.on("SIGINT",u)}else{if(!$.json)T("Starting agent in daemon mode"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();if(q.installDeps===!1)process.env.VIBE_SKIP_PREREQ_INSTALL="1";await Z.startDaemon({port:w,name:q.name,daemon:!0,dbPath:H,host:A,profile:X});let d=(await Z.getStatus(q.name))?.port??w,u=`http://${A==="0.0.0.0"?"localhost":A}:${d}`,K$=q.waitReady,r=q.wait===!1,l0=K$!==void 0;if(r&&l0)j("--wait-ready is ignored because --no-wait was also passed.");let p$=!r&&l0,n0=!r&&(p$||!$.json),i0=(()=>{let C$=typeof K$==="string"?Number.parseInt(K$,10):NaN;if(Number.isInteger(C$)&&C$>0)return C$*1000;return p$?60000:25000})();if($.json){if(n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js"),$$=await C$(u,{timeoutMs:i0,verbose:!1});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1;B($,{ok:$$.outcome==="ready"||$$.outcome==="awaiting-config",name:q.name,port:d,host:A,url:u,abilities:[...G],outcome:$$.outcome,bootState:$$.bootState,degradedReasons:$$.degradedReasons,summary:$$.summary})}else B($,{ok:!0,name:q.name,port:d,host:A,url:u});return}if(await u$(u),n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js");J();let $$=await C$(u,{timeoutMs:i0,verbose:!0});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1}}}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Failed to start agent: ${X}`)}})}function q1(Y){Y.command("stop").description("Stop a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("--all","Stop all running agent instances",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(q.all){let X=await Z.listInstances();if(!X||X.length===0){if(B($,{ok:!0,stopped:[]}))return;T("Stopping all agent instances"),J(),W(`${N.info} No running agent instances found.`);return}let H=[];if(!$.json)T("Stopping all agent instances"),J();for(let Q of X)try{if(await Z.stop(Q.name),H.push(Q.name),!$.json)U(`${N.success} Stopped ${K.bold(Q.name)}`)}catch{if(!$.json)V(`Failed to stop ${K.bold(Q.name)}`)}if(B($,{ok:!0,stopped:H,total:X.length}))return;J(),U(`${N.success} Stopped ${H.length}/${X.length} instance(s).`)}else{if(await Z.stop(q.name),B($,{ok:!0,name:q.name}))return;T(`Stopping agent: ${q.name}`),J(),U(`${N.success} Agent ${K.bold(q.name)} stopped.`)}}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to stop agent: ${C(Z)}`)}})}function Z1(Y){Y.command("restart").description("Restart a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on").option("--db-path <path>","Path to the agent storage directory").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(!$.json)T(`Restarting agent: ${q.name}`),J(),W(`${N.info} Stopping agent ${K.bold(q.name)}...`);let X=await Z.getStatus(q.name);try{if(await Z.stop(q.name),!$.json)U(`${N.success} Agent stopped.`)}catch{if(!$.json)W(`${N.info} Agent was not running.`)}let H=q.port??X?.port??3005,Q=typeof H==="number"?H:parseInt(H,10);if(isNaN(Q)||Q<1||Q>65535){if($.json){B($,{ok:!1,error:"Invalid port number"});return}V("Invalid port number. Must be between 1 and 65535.");return}let z={port:Q,name:q.name,daemon:!0,dbPath:q.dbPath??X?.config?.dbPath??N$(),host:X?.config?.host,profile:X?.config?.profile};if(!$.json)J(),W(`${N.info} Starting agent ${K.bold(q.name)}...`);await Z.startDaemon(z);let L=`http://localhost:${Q}`;if(B($,{ok:!0,name:q.name,port:Q,url:L}))return;J(),U(`${N.success} Agent ${K.bold(q.name)} restarted.`),J(),_("Port",String(Q)),_("Database",z.dbPath),J(),u$(L)}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to restart agent: ${C(Z)}`)}})}import{existsSync as o2,readFileSync as a2,unlinkSync as X1}from"fs";import{join as z1}from"path";function t2(Y){let q=z1(V$(),Y,"runtime.json");if(!o2(q))return null;try{let $=JSON.parse(a2(q,"utf8"));if(typeof $.pid!=="number")return null;return{...$,pid:$.pid,path:q}}catch{return null}}async function H1(Y){let q=t2(Y);if(!q)return null;if(!B$(q.pid)){try{X1(q.path)}catch{}return`agent pid=${q.pid} (${Y}) already gone (cleaned runtime.json).`}let $=l();if(!$.killProcessTree(q.pid,"SIGTERM"))return`failed to SIGTERM agent pid=${q.pid}.`;if(await new Promise((Z)=>setTimeout(Z,3000)),B$(q.pid))$.killProcessTree(q.pid,"SIGKILL");try{X1(q.path)}catch{}return`agent ${Y} pid=${q.pid}${q.port?` (port ${q.port})`:""} killed.`}async function s2(Y){let q=z1(V$(),Y),$=J$(q);if(!$)return null;if(!B$($.pid))return X$(q),`tunnel pid=${$.pid} already gone (cleaned state).`;let Z=l();if(!Z.killProcessTree($.pid,"SIGTERM"))return`failed to SIGTERM tunnel pid=${$.pid}.`;if(await new Promise((X)=>setTimeout(X,3000)),B$($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(q),`tunnel ${$.provider} pid=${$.pid} (${$.url??"no url"}) killed.`}function W1(Y){Y.command("kill").description("Force-kill an agent instance and its tunnel. Defaults to active profile.").option("-n, --name <name>","Agent instance name (alias of --profile, kept for back-compat)").option("--profile <name>","Kill a specific profile (overrides --name and VIBECONTROLS_PROFILE)").option("--all","Kill every agent instance and every profile's tunnel",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=q.all?"ALL agent instances + every profile's tunnel":`agent '${$.profile??$.name??"active profile"}'`;if(!await q0($,`Force-kill ${Z}? This sends SIGKILL (no graceful shutdown).`)){W("Aborted.");return}let X=[];try{let H=new o;if(q.all){if(!$.json)T("Force killing all agent instances + tunnels"),J();let I=await H.listInstances()??[],O=0,G=new Set;for(let R of I)try{if(await H.kill(R.name),!$.json)U(`${N.success} agent ${K.bold(R.name)} (pid=${R.pid||"?"}) killed.`);X.push(R.name),O++,G.add(R.name)}catch{if(!$.json)j(`${N.warning} could not kill agent ${R.name}.`)}try{let R=await import("fs"),E=V$(),w=R.existsSync(E)?R.readdirSync(E):[];for(let D of w){if(G.has(D))continue;let A=await H1(D);if(A)U(`${N.success} ${A}`),O++}}catch(R){j(`${N.warning} runtime.json sweep failed: ${R instanceof Error?C(R):String(R)}`)}let x=Q1({allProfiles:!0}),F=0;for(let R of x){if(!R.alive){X$(R.profileDir);continue}let E=l();if(E.killProcessTree(R.pid,"SIGTERM"),await new Promise((w)=>setTimeout(w,3000)),B$(R.pid))E.killProcessTree(R.pid,"SIGKILL");X$(R.profileDir),U(`${N.success} tunnel ${R.provider} pid=${R.pid} (${R.url??"no url"}, ${R.profileDir.split("/").pop()}) killed.`),F++}if(B($,{ok:!0,killed:X,tunnels:F}))return;J(),U(`${N.success} killed ${O} agent(s) and ${F} tunnel(s).`);return}let Q=q.profile||q.name||Y0();if(!$.json)T(`Force killing profile: ${Q}`),J();let z=await H.getStatus(Q);if(z){if(await H.kill(Q),X.push(Q),!$.json)U(`${N.success} agent ${K.bold(Q)} pid=${z.pid||"?"} killed.`)}else{let I=await H1(Q);if(I){if(X.push(Q),!$.json)U(`${N.success} ${I}`)}else if(!$.json)W(`${N.info} no running agent service for profile ${Q}.`)}let L=await s2(Q);if(L){if(!$.json)U(`${N.success} ${L}`)}else if(!$.json)W(`${N.info} no tunnel recorded for profile ${Q}.`);B($,{ok:!0,killed:X})}catch(H){if($.json){B($,{ok:!1,error:C(H)});return}V(`Failed to kill: ${C(H)}`)}})}function K1(Y){Y.command("list").alias("ls").description("List all VibeControls agent instances").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new o;await b({mode:f($),fetchData:()=>Z.listInstances(),plain:(X)=>{if(T("Agent Instances"),J(),!X||X.length===0){W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((L)=>({Name:L.name,Status:x$(L.status),PID:L.pid||"-",Port:L.port||"-",Host:L.config?.host||"-",Database:L.config?.dbPath||"-",Started:L.startTime?G$(L.startTime):"-"}));n(H),J();let Q=X.filter((L)=>L.status==="running").length,z=X.length-Q;W(`${N.info} ${X.length} instance(s): ${K.green(String(Q))} running, ${K.dim(String(z))} stopped`)},interactive:async(X)=>{if(!X||X.length===0){T("Agent Instances"),J(),W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((Q)=>{let z=[`${K.bold(Q.name)} ${x$(Q.status)}`,"",` PID: ${Q.pid??"-"}`,` Port: ${Q.port??"-"}`,` Host: ${Q.config?.host??"-"}`,` Database: ${Q.config?.dbPath??"-"}`,` Started: ${Q.startTime?G$(Q.startTime):"-"}`];return{id:Q.name,label:Q.name,hint:Q.status==="running"?"running":"stopped",detail:z.join(`
|
|
2
|
+
import{L as r1}from"./index-2gsarrbn.js";import{M as b2}from"./index-b5dhmybd.js";import{O as a$,P as B1}from"./index-e1bw1bwr.js";import{$ as U2,Q as r$,R as c$,S as s0,T as r0,U as e$,V as e0,W as $0,X as $1,Y as D$,Z as E$,_ as J2,ca as z0,da as I2,ea as _2,fa as K0,ga as U1,ha as I1,ia as _1,ja as L2,ka as W0}from"./index-g8zv1gta.js";import{la as J$,ma as X$,na as B$,oa as Q1,ta as w2}from"./index-qfz9fy56.js";import{va as o}from"./index-ssjmzqcz.js";import{Ca as X2}from"./index-4wgjx8bf.js";import{Ea as t1,Fa as k$,Ha as o$,Ma as t0,Oa as s1,Pa as g2,Wa as s$}from"./index-g3ap3xpr.js";import{Xa as l}from"./index-0ckffygp.js";import{Ya as d1,ab as a}from"./index-rc79x8fw.js";import{db as P2}from"./index-52cp759f.js";import{Ib as M2}from"./index-01qzsnwd.js";import{gc as t$,hc as T$,ic as f,jc as b,kc as B,lc as q0}from"./index-5mw3eshk.js";import{Bc as x$,Cc as W$,Dc as u$,nc as K,oc as N,pc as V,qc as C,rc as U,sc as j,tc as W,uc as T,vc as _,wc as J,xc as n,yc as G$}from"./index-z5a4yxzz.js";import{Ec as b0,Fc as e,Gc as v$}from"./index-ef95xr4z.js";import{Kc as M,Mc as S,Nc as y,Oc as m,Pc as L0,Qc as P$}from"./index-xjzmb1pn.js";import{Rc as Z2,Tc as A0,Uc as a1,Wc as G2,Xc as f0,Zc as y$,ad as F2,bd as f$,cd as P0,dd as T2,ed as V0,fd as R2,gd as j2,hd as E2,id as N2,kd as B0,ld as O1,nd as q$,pd as U$,td as a0}from"./index-g2raeeh4.js";import{Nd as c0,zd as O0}from"./index-9bqd8veb.js";import{$d as V$,Xd as Y0,_d as Q$,ae as N$,be as Z$}from"./index-0cn9bv8z.js";import{he as Y$}from"./index-yy1mm8zs.js";import{existsSync as o0}from"fs";import{join as p2}from"path";import{createServer as n2}from"net";function i2(Y,q="0.0.0.0"){return new Promise(($)=>{let Z=n2();Z.once("error",()=>$(!1)),Z.once("listening",()=>{Z.close(()=>$(!0))}),Z.listen({host:q,port:Y,exclusive:!0})})}async function p0(Y,q="0.0.0.0"){let $=Y;while(!await i2($,q))if($++,$>65535)throw Error(`No free port found starting from ${Y}`);return $}function Y1(Y){Y.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>","Port to listen on. Default: 3005 for the 'default' profile, deterministic 3100-3399 for any other profile (FNV-1a hash) so multiple profiles run side-by-side without EADDRINUSE.").option("-n, --name <name>","Agent instance name","default").option("-f, --foreground","Run in foreground mode (default: daemon)",!1).option("--db-path <path>","Path to the agent storage directory").option("--profile <profile>","Profile name for isolated config (env: VIBECONTROLS_PROFILE)").option("--host <host>","Host to bind to","0.0.0.0").option("--skip-plugin-install","Skip automatic installation of default plugins",!1).option("--skip-plugin <name>","Skip a specific default plugin (repeatable). Accepts the short pluginName or the full package name.",(q,$=[])=>[...$,q],[]).option("--no-install-deps","Skip auto-installing missing tools (installed by their plugins on start by default)").option("-y, --yes","Skip the first-run install consent prompt. Equivalent to VIBE_AUTO_ACCEPT=1; useful for CI / Docker / nohup contexts.",!1).option("--client-id <id>","Gateway OAuth client ID (env: VIBE_CLIENT_ID)").option("--client-secret <secret>","Gateway OAuth client secret (env: VIBE_CLIENT_SECRET)").option("--global-gateway-url <url>","Global gateway URL (env: VIBE_GLOBAL_GATEWAY_URL)").option("--workspace-gateway-url <url>","Workspace gateway URL (env: VIBE_WORKSPACE_GATEWAY_URL)").option("--workspace-id <id>","Workspace ID for auto-report (env: VIBE_WORKSPACE_ID)").option("--isolate <plugins>","Comma-separated list of plugin names to force into worker_threads isolation (Phase 4 hostile-plugin mode). Sets VIBE_ISOLATE_PLUGINS in the daemon env.").option("--profiles <names>","Comma-separated list of profiles to host in this daemon (multi-profile boot). When unset, the daemon hosts a single profile resolved via --profile / VIBECONTROLS_PROFILE / 'default'. Sets VIBECONTROLS_PROFILES in the daemon env so app boot can spin up additional ProfileContexts via the in-process registry.").option("--strict-key-fetch","Refuse to boot if any profile's encryption-key fetch fails. Default lenient: a failed profile is marked degraded and the daemon stays up. Sets VIBE_STRICT_KEY_FETCH=1 in the daemon env.",!1).option("--json","Emit JSON").option("--plain","Plain text output (no interactive TUI). Implied for non-TTY / CI.").option("--abilities <list>","Comma-separated ability keys to install non-interactively (e.g. session,ai,gitops). Storage/tunnel/backup are always included.").option("--providers <list>","Comma-separated extra provider plugins to install beyond each meta's default (e.g. session-wezterm,ai-claude). Accepts short names or @vibecontrols/... packages. Persisted; manage later with `vibe capability`.").option("--wait-ready [seconds]","Block until the agent is fully ready (or fails). Polls /health/ready and renders phase transitions live. Without a value, defaults to 60s. Exits non-zero if the agent ends up degraded or times out. Useful for scripts/CI.").option("--no-wait","Skip the phase tracker entirely after spawning the daemon. Restores the old fire-and-print behavior \u2014 for users who want the previous quick-return UX.").action(async function(q){let $={...Y.opts(),...q};try{let E=function(h){if(h==="default")return 3005;let d=2166136261;for(let g=0;g<h.length;g++)d=Math.imul(d^h.charCodeAt(g),16777619);return 3100+Math.abs(d)%300},Z=new o,X=q.profile||process.env.VIBECONTROLS_PROFILE||"default";if(process.env.VIBECONTROLS_PROFILE=X,typeof q.isolate==="string"&&q.isolate.length>0)process.env.VIBE_ISOLATE_PLUGINS=q.isolate;if(typeof q.profiles==="string"&&q.profiles.length>0){let h=q.profiles.split(",").map((d)=>d.trim()).filter(Boolean);if(h.length>0){if(process.env.VIBECONTROLS_PROFILES=h.join(","),process.env.VIBECONTROLS_PROFILE=h[0],h.length>1)j(`--profiles received ${h.length} entries; daemon boots with '${h[0]}'. Remaining (${h.slice(1).join(", ")}) will be attached via /api/profiles after listen.`)}}if(q.strictKeyFetch===!0)process.env.VIBE_STRICT_KEY_FETCH="1";a0();let H=q.dbPath||N$(),Q=Z$(),z=!o0(H)&&!o0(p2(Q,"agents.json")),L=f($),I=L!=="json"&&L!=="plain"&&t$()&&q.yes!==!0,O=r$(Q),G;if(typeof $.abilities==="string"&&$.abilities.trim()!=="")G=e0($.abilities);else if(O!==null)G=O;else if(I)G=await e$();else G=$0();let x=typeof $.providers==="string"&&$.providers.trim()!=="",F=x?s0($.providers):c$(Q);if(O===null){let h=r0({installDeps:q.installDeps===!0,skipPluginInstall:q.skipPluginInstall===!0,skipPlugins:Array.isArray(q.skipPlugin)?q.skipPlugin:[]},G);if(z&&h.plugins.length>0)J(),W(`Installing ${h.plugins.length} plugin(s) for the selected abilities.`),J();$1(Q,h,G,process.env.VIBE_AGENT_VERSION,F)}else if(x)D$(Q,{providers:F,agentVersion:process.env.VIBE_AGENT_VERSION});if((z||x)&&F.length>0&&q.skipPluginInstall!==!0){W(`Installing ${F.length} selected provider plugin(s)...`);try{let{PluginManager:h}=await import("./plugin-system-c916v9an.js"),d=new h;for(let g of F)try{await d.install(g),U(`Installed provider ${g}`)}catch(u){j(`Could not install provider ${g}: ${u instanceof Error?u.message:String(u)}`)}}catch(h){j(`Provider install skipped: ${h instanceof Error?h.message:String(h)}`)}J()}if(z){W("First run detected \u2014 running setup..."),J();let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=q.skipPluginInstall?[]:o$(process.platform,G).filter((r)=>!h.includes(r.packageName)&&!h.includes(r.pluginName)).map((r)=>r.packageName),g=t0(d),K$=a$(g).filter((r)=>!r.installed);if(K$.length>0)if(j(`Missing tools: ${K$.map((r)=>r.name).join(", ")}`),q.installDeps)W("Their plugins will install them automatically on startup.");else W("Auto-install skipped (`--no-install-deps`) \u2014 install them yourself or drop the flag.");else U("All plugin tools present.");J()}if(!q.skipPluginInstall){let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=new s$;await d.loadCorePlugins(),await d.loadAll();let g=await d.ensureDefaultPlugins((u)=>{if(u.startsWith("No "))j(u);else if(u.startsWith("Installed "))U(u);else if(u.startsWith("Failed "))j(u);else W(u)},h,G);if(g.length>0)U(`Auto-installed ${g.length} default plugin${g.length>1?"s":""}.`),J()}let R=q.profile||process.env.VIBECONTROLS_PROFILE||q.name||"default",w=q.port?parseInt(q.port,10):E(R);if(isNaN(w)||w<1||w>65535)V("Invalid port number. Must be between 1 and 65535.");let D=await p0(w);if(D!==w)j(`Port ${w} is in use. Auto-selecting port ${K.bold(String(D))} instead.`),w=D;let A=q.host,s=`http://${A==="0.0.0.0"?"localhost":A}:${w}`,p=q.clientId||process.env.VIBE_CLIENT_ID,v=q.clientSecret||process.env.VIBE_CLIENT_SECRET,P=q.globalGatewayUrl||process.env.VIBE_GLOBAL_GATEWAY_URL,c=q.workspaceGatewayUrl||process.env.VIBE_WORKSPACE_GATEWAY_URL,O$=q.workspaceId||process.env.VIBE_WORKSPACE_ID;if(p&&!v)V("--client-secret is required when --client-id is provided.");if(v&&!p)V("--client-id is required when --client-secret is provided.");if(p&&v){if(!P&&!process.env.VIBE_GLOBAL_GATEWAY_URL)V("--global-gateway-url is required when providing client credentials (none set in env).");if(process.env.VIBE_CLIENT_ID=p,process.env.VIBE_CLIENT_SECRET=v,P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;let{writeAgentConfig:h}=await import("./agent-config-85pskv43.js");if(h({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c}),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;U("Gateway credentials staged in env. Agent will authenticate and persist them on startup."),J()}else if(c||O$||P){if(j("Workspace options provided without --client-id / --client-secret \u2014 they will be staged in env but unused until credentials are configured."),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;if(P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;J()}if(q.foreground){if(!$.json)T("Starting agent in foreground"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();let{bootstrapWorkspace:h}=await import("./bootstrap-workspace-zpm20zez.js");h();let{createApp:d}=await import("./app-jeyyhz7s.js"),g=await d({port:w,host:A,dbPath:H});if(await g.start(),p&&v&&O$&&P&&c){let K$=await g.finalize({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c});if(!K$.ok)j(`Finalize failed \u2014 agent remains in awaiting-config state: ${K$.error}`)}if(B($,{ok:!0,name:q.name,port:w,host:A,pid:process.pid,url:s}));else await u$(s);let u=async()=>{await g.stop(),process.exit(0)};process.on("SIGTERM",u),process.on("SIGINT",u)}else{if(!$.json)T("Starting agent in daemon mode"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();if(q.installDeps===!1)process.env.VIBE_SKIP_PREREQ_INSTALL="1";await Z.startDaemon({port:w,name:q.name,daemon:!0,dbPath:H,host:A,profile:X});let d=(await Z.getStatus(q.name))?.port??w,u=`http://${A==="0.0.0.0"?"localhost":A}:${d}`,K$=q.waitReady,r=q.wait===!1,l0=K$!==void 0;if(r&&l0)j("--wait-ready is ignored because --no-wait was also passed.");let p$=!r&&l0,n0=!r&&(p$||!$.json),i0=(()=>{let C$=typeof K$==="string"?Number.parseInt(K$,10):NaN;if(Number.isInteger(C$)&&C$>0)return C$*1000;return p$?60000:25000})();if($.json){if(n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js"),$$=await C$(u,{timeoutMs:i0,verbose:!1});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1;B($,{ok:$$.outcome==="ready"||$$.outcome==="awaiting-config",name:q.name,port:d,host:A,url:u,abilities:[...G],outcome:$$.outcome,bootState:$$.bootState,degradedReasons:$$.degradedReasons,summary:$$.summary})}else B($,{ok:!0,name:q.name,port:d,host:A,url:u});return}if(await u$(u),n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js");J();let $$=await C$(u,{timeoutMs:i0,verbose:!0});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1}}}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Failed to start agent: ${X}`)}})}function q1(Y){Y.command("stop").description("Stop a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("--all","Stop all running agent instances",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(q.all){let X=await Z.listInstances();if(!X||X.length===0){if(B($,{ok:!0,stopped:[]}))return;T("Stopping all agent instances"),J(),W(`${N.info} No running agent instances found.`);return}let H=[];if(!$.json)T("Stopping all agent instances"),J();for(let Q of X)try{if(await Z.stop(Q.name),H.push(Q.name),!$.json)U(`${N.success} Stopped ${K.bold(Q.name)}`)}catch{if(!$.json)V(`Failed to stop ${K.bold(Q.name)}`)}if(B($,{ok:!0,stopped:H,total:X.length}))return;J(),U(`${N.success} Stopped ${H.length}/${X.length} instance(s).`)}else{if(await Z.stop(q.name),B($,{ok:!0,name:q.name}))return;T(`Stopping agent: ${q.name}`),J(),U(`${N.success} Agent ${K.bold(q.name)} stopped.`)}}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to stop agent: ${C(Z)}`)}})}function Z1(Y){Y.command("restart").description("Restart a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on").option("--db-path <path>","Path to the agent storage directory").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(!$.json)T(`Restarting agent: ${q.name}`),J(),W(`${N.info} Stopping agent ${K.bold(q.name)}...`);let X=await Z.getStatus(q.name);try{if(await Z.stop(q.name),!$.json)U(`${N.success} Agent stopped.`)}catch{if(!$.json)W(`${N.info} Agent was not running.`)}let H=q.port??X?.port??3005,Q=typeof H==="number"?H:parseInt(H,10);if(isNaN(Q)||Q<1||Q>65535){if($.json){B($,{ok:!1,error:"Invalid port number"});return}V("Invalid port number. Must be between 1 and 65535.");return}let z={port:Q,name:q.name,daemon:!0,dbPath:q.dbPath??X?.config?.dbPath??N$(),host:X?.config?.host,profile:X?.config?.profile};if(!$.json)J(),W(`${N.info} Starting agent ${K.bold(q.name)}...`);await Z.startDaemon(z);let L=`http://localhost:${Q}`;if(B($,{ok:!0,name:q.name,port:Q,url:L}))return;J(),U(`${N.success} Agent ${K.bold(q.name)} restarted.`),J(),_("Port",String(Q)),_("Database",z.dbPath),J(),u$(L)}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to restart agent: ${C(Z)}`)}})}import{existsSync as o2,readFileSync as a2,unlinkSync as X1}from"fs";import{join as z1}from"path";function t2(Y){let q=z1(V$(),Y,"runtime.json");if(!o2(q))return null;try{let $=JSON.parse(a2(q,"utf8"));if(typeof $.pid!=="number")return null;return{...$,pid:$.pid,path:q}}catch{return null}}async function H1(Y){let q=t2(Y);if(!q)return null;if(!B$(q.pid)){try{X1(q.path)}catch{}return`agent pid=${q.pid} (${Y}) already gone (cleaned runtime.json).`}let $=l();if(!$.killProcessTree(q.pid,"SIGTERM"))return`failed to SIGTERM agent pid=${q.pid}.`;if(await new Promise((Z)=>setTimeout(Z,3000)),B$(q.pid))$.killProcessTree(q.pid,"SIGKILL");try{X1(q.path)}catch{}return`agent ${Y} pid=${q.pid}${q.port?` (port ${q.port})`:""} killed.`}async function s2(Y){let q=z1(V$(),Y),$=J$(q);if(!$)return null;if(!B$($.pid))return X$(q),`tunnel pid=${$.pid} already gone (cleaned state).`;let Z=l();if(!Z.killProcessTree($.pid,"SIGTERM"))return`failed to SIGTERM tunnel pid=${$.pid}.`;if(await new Promise((X)=>setTimeout(X,3000)),B$($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(q),`tunnel ${$.provider} pid=${$.pid} (${$.url??"no url"}) killed.`}function W1(Y){Y.command("kill").description("Force-kill an agent instance and its tunnel. Defaults to active profile.").option("-n, --name <name>","Agent instance name (alias of --profile, kept for back-compat)").option("--profile <name>","Kill a specific profile (overrides --name and VIBECONTROLS_PROFILE)").option("--all","Kill every agent instance and every profile's tunnel",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=q.all?"ALL agent instances + every profile's tunnel":`agent '${$.profile??$.name??"active profile"}'`;if(!await q0($,`Force-kill ${Z}? This sends SIGKILL (no graceful shutdown).`)){W("Aborted.");return}let X=[];try{let H=new o;if(q.all){if(!$.json)T("Force killing all agent instances + tunnels"),J();let I=await H.listInstances()??[],O=0,G=new Set;for(let R of I)try{if(await H.kill(R.name),!$.json)U(`${N.success} agent ${K.bold(R.name)} (pid=${R.pid||"?"}) killed.`);X.push(R.name),O++,G.add(R.name)}catch{if(!$.json)j(`${N.warning} could not kill agent ${R.name}.`)}try{let R=await import("fs"),E=V$(),w=R.existsSync(E)?R.readdirSync(E):[];for(let D of w){if(G.has(D))continue;let A=await H1(D);if(A)U(`${N.success} ${A}`),O++}}catch(R){j(`${N.warning} runtime.json sweep failed: ${R instanceof Error?C(R):String(R)}`)}let x=Q1({allProfiles:!0}),F=0;for(let R of x){if(!R.alive){X$(R.profileDir);continue}let E=l();if(E.killProcessTree(R.pid,"SIGTERM"),await new Promise((w)=>setTimeout(w,3000)),B$(R.pid))E.killProcessTree(R.pid,"SIGKILL");X$(R.profileDir),U(`${N.success} tunnel ${R.provider} pid=${R.pid} (${R.url??"no url"}, ${R.profileDir.split("/").pop()}) killed.`),F++}if(B($,{ok:!0,killed:X,tunnels:F}))return;J(),U(`${N.success} killed ${O} agent(s) and ${F} tunnel(s).`);return}let Q=q.profile||q.name||Y0();if(!$.json)T(`Force killing profile: ${Q}`),J();let z=await H.getStatus(Q);if(z){if(await H.kill(Q),X.push(Q),!$.json)U(`${N.success} agent ${K.bold(Q)} pid=${z.pid||"?"} killed.`)}else{let I=await H1(Q);if(I){if(X.push(Q),!$.json)U(`${N.success} ${I}`)}else if(!$.json)W(`${N.info} no running agent service for profile ${Q}.`)}let L=await s2(Q);if(L){if(!$.json)U(`${N.success} ${L}`)}else if(!$.json)W(`${N.info} no tunnel recorded for profile ${Q}.`);B($,{ok:!0,killed:X})}catch(H){if($.json){B($,{ok:!1,error:C(H)});return}V(`Failed to kill: ${C(H)}`)}})}function K1(Y){Y.command("list").alias("ls").description("List all VibeControls agent instances").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new o;await b({mode:f($),fetchData:()=>Z.listInstances(),plain:(X)=>{if(T("Agent Instances"),J(),!X||X.length===0){W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((L)=>({Name:L.name,Status:x$(L.status),PID:L.pid||"-",Port:L.port||"-",Host:L.config?.host||"-",Database:L.config?.dbPath||"-",Started:L.startTime?G$(L.startTime):"-"}));n(H),J();let Q=X.filter((L)=>L.status==="running").length,z=X.length-Q;W(`${N.info} ${X.length} instance(s): ${K.green(String(Q))} running, ${K.dim(String(z))} stopped`)},interactive:async(X)=>{if(!X||X.length===0){T("Agent Instances"),J(),W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((Q)=>{let z=[`${K.bold(Q.name)} ${x$(Q.status)}`,"",` PID: ${Q.pid??"-"}`,` Port: ${Q.port??"-"}`,` Host: ${Q.config?.host??"-"}`,` Database: ${Q.config?.dbPath??"-"}`,` Started: ${Q.startTime?G$(Q.startTime):"-"}`];return{id:Q.name,label:Q.name,hint:Q.status==="running"?"running":"stopped",detail:z.join(`
|
|
3
3
|
`)}});await e({title:`vibe list \u2014 ${X.length} instance(s)`,rows:H,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(X)=>X.map((H)=>({name:H.name,status:H.status,pid:H.pid??null,port:H.port??null,host:H.config?.host??null,database:H.config?.dbPath??null,startTime:H.startTime??null}))})}catch($){V(`Failed to list instances: ${$.message}`)}})}var V1=5000;function L1(Y){Y.command("logs").description("View logs for a VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-f, --follow","Follow log output",!1).option("--tail <lines>","Number of lines to show from the end","100").option("--json","Emit JSON (one object per line, banners suppressed)").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new o,X=parseInt($.tail??"100",10);if(isNaN(X)||X<1||X>V1){V(`Invalid tail value. Must be between 1 and ${V1}.`);return}let H=$.name??"default";if(!await Z.getStatus(H)){V(`Agent instance ${K.bold(H)} not found.`);return}if(!$.json){if($.follow)T(`Following logs: ${H}`),W(`${N.info} Press Ctrl+C to stop following.`);else T(`Logs: ${H}`);J()}await Z.showLogs(H,{follow:!!$.follow,tail:X})}catch($){V(`Failed to get logs: ${C($)}`)}})}function J1(Y){Y.command("setup").description("Install system dependencies and (optionally) write gateway auth config").option("--check","Only check dependencies without installing",!1).option("--client-id <id>","OAuth app client ID (for backend authentication)").option("--client-secret <secret>","OAuth app client secret").option("--workspace-id <id>","Workspace UUID this agent belongs to").option("--global-gateway-url <url>","Global public gateway URL (default: http://localhost:4000/global/graphql)").option("--workspace-gateway-url <url>","Workspace gateway URL (default: http://localhost:4001/workspaces/graphql)").option("--storage-adapter <name>","Named storage adapter (default: skalex, or custom:<path>)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=[];try{if(!$.json)T("VibeControls Agent Setup");let X={};if(q.clientId)X.clientId=q.clientId;if(q.clientSecret)X.clientSecret=q.clientSecret;if(q.workspaceId)X.workspaceId=q.workspaceId;if(q.globalGatewayUrl)X.globalGatewayUrl=O0(q.globalGatewayUrl,"globalGatewayUrl");if(q.workspaceGatewayUrl)X.workspaceGatewayUrl=O0(q.workspaceGatewayUrl,"workspaceGatewayUrl");if(q.storageAdapter)X.storageAdapter=q.storageAdapter;if(Object.keys(X).length>0){let O=U$(X);if(Z.push(...Object.keys(X)),!$.json){U(`Agent config written to ${B0()}`),_("clientId",O.clientId?K.dim("(set)"):K.dim("(unset)")),_("clientSecret",O.clientSecret?K.dim("(set)"):K.dim("(unset)")),_("workspaceId",O.workspaceId??K.dim("(unset)"));let G=O1();if(_("globalGatewayUrl",O.globalGatewayUrl??G.globalGatewayUrl),_("workspaceGatewayUrl",O.workspaceGatewayUrl??G.workspaceGatewayUrl),O.storageAdapter)_("storageAdapter",O.storageAdapter);J()}}else{let O=q$();if((O.clientId||O.clientSecret||O.workspaceId)&&!$.json)W(`Using existing agent config at ${B0()} (pass --client-id/--client-secret/--workspace-id to update).`),J()}if(!$.json)W("Checking dependencies..."),J();let H=a$(),Q=[],z=[];for(let O of H){if(O.installed)z.push(O.name);if(!$.json){let G=O.installed?N.success:N.error,x=O.version?K.dim(` (${O.version})`):"",F=O.required?"":K.dim(" [optional]");_(`${G} ${O.name}`,`${O.installed?K.green("installed"):K.red("missing")}${x}${F}`)}if(!O.installed)Q.push(O.name)}if(!$.json)J();if(Q.length===0){if(B($,{ok:!0,installed:z,configured:Z}))return;U("All dependencies are installed.");return}if(q.check){if($.json){B($,{ok:!1,installed:z,missing:Q,configured:Z});return}j(`Missing: ${Q.join(", ")}`),W(`Run ${K.bold("vibe setup")} to install them.`),process.exit(1)}if(!$.json)W(`Installing missing dependencies: ${Q.join(", ")}...`),J();let L=await B1(Q),I=Q.filter((O)=>!L.failed.includes(O));if(L.failed.length>0){if($.json){B($,{ok:!1,installed:[...z,...I],failed:L.failed,configured:Z});return}j(`${L.failed.length} tool(s) failed: ${L.failed.join(", ")}`),W("You may need to install manually or use sudo."),process.exit(1)}else{if(B($,{ok:!0,installed:[...z,...I],configured:Z}))return;U("All dependencies installed successfully.")}}catch(X){let H=X instanceof Error?C(X):String(X);if($.json){B($,{ok:!1,error:H});return}V(`Setup failed: ${H}`)}})}function r2(Y){let q=l();return q.which(Y)??`${Y}${q.executableSuffix}`}function C1(Y){Y.command("update").description("Check for and install VibeControls agent updates").option("--check","Only check for updates without installing",!1).option("--allow-incompatible","Override engines.bun compatibility check (use with care)",!1).option("--no-restart","Skip the post-install idle-aware restart of any running agent").option("-n, --name <name>","Agent profile name to restart after update","default").option("--version-target <version>","Install a specific version instead of the latest (e.g. 2026.601.21)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{if(!$.json)T("VibeControls Agent Update"),J(),W(`${N.info} Checking for updates...`),J();let Z=await I1();if(Z.error&&!Z.latest){if(B($,{ok:!1,current:Z.current,error:Z.error}))return;V(Z.error);return}if(!$.json)_("Package",K.bold(Z.name)),_("Registry",K.bold(Z.registry)),_("Current version",K.bold(Z.current)),_("Latest version",K.bold(Z.latest??"unknown")),J();if(q.check){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!Z.hasUpdate}))return;if(!Z.hasUpdate)U(`${N.success} You are running the latest version.`);else j(`${N.warning} A new version is available: ${K.green(Z.latest??"")}`),W(`${N.info} Run ${K.bold("vibe update")} to install the update.`);return}let X=q.versionTarget;if(!X&&!Z.hasUpdate){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!0}))return;U(`${N.success} You are running the latest version.`);return}if(!$.json)W(`${N.info} Updating to ${K.bold(X??Z.latest??"latest")}...`),J();let H=await _1({targetVersion:X,allowIncompatible:!!q.allowIncompatible,restart:q.restart!==!1,name:q.name,onLog:$.json?void 0:(Q)=>W(`${N.info} ${Q}`)});if(!H.ok){if(B($,{ok:!1,current:H.current,previous:H.previous,latest:H.latest,rolledBack:H.rolledBack,error:H.error}))return;V(H.error??"Update failed.");return}if(!$.json)switch(H.restart){case"restarted":U(`${N.success} Restarted agent ${K.bold(q.name)} on the new version.`);break;case"not-running":W(`${N.info} No running agent for profile ${K.bold(q.name)}; nothing to restart.`);break;case"still-busy":j(`${N.warning} Agent still serving requests \u2014 run ${K.bold("vibe restart")} when it's quiet.`);break;case"error":j(`${N.warning} Auto-restart failed: ${H.restartError}. Run ${K.bold("vibe restart")} manually.`);break}if(B($,{ok:!0,current:H.current,previous:H.previous,latest:H.latest,updated:H.updated,restart:H.restart,...H.restartError?{restartError:H.restartError}:{}}))return;if(J(),H.updated)U(`${N.success} Updated to ${K.bold(H.current)} (smoke: ${H.smoke?.step??"ok"}).`);else U(`${N.success} You are running the latest version.`);if(q.restart===!1)W(`${N.info} --no-restart set \u2014 restart running agents manually for the update to take effect.`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Update failed: ${X}`)}}),Y.command("rollback").description("Roll the global agent install back to a specific version").argument("<version>","Target CalVer version (e.g. 2026.428.3)").action(async(q)=>{try{T("VibeControls Agent Rollback");let $=await U1();if(_("Package",K.bold($.name)),_("Current version",K.bold($.version)),_("Target version",K.bold(q)),J(),W(`${N.info} Rolling back\u2026`),Bun.spawnSync([r2("npm"),"install","-g",`${$.name}@${q}`,`--registry=${$.registry}`],{stdout:"inherit",stderr:"inherit"}).exitCode!==0){V("Rollback failed.");return}U(`${N.success} Rolled back to ${K.bold(q)}.`)}catch($){V(`Rollback failed: ${$ instanceof Error?C($):String($)}`)}})}import{existsSync as F$,mkdirSync as e2,writeFileSync as I0,unlinkSync as $6,readFileSync as J0}from"fs";import{join as L$}from"path";import{homedir as M$}from"os";var Y6=/^[A-Za-z0-9][A-Za-z0-9:_-]{0,63}$/,q6=/^--[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;function R1(Y){return Y6.test(Y)?Y:null}function j1(Y){return Y.filter((q)=>R1(q))}function Z6(Y){return Y.filter((q)=>q6.test(q))}function w$(Y){return Y.commands.flatMap((q)=>{let $=R1(q.name());if(!$)return[];return[{name:$,description:q.description()||"",options:q.options.map((Z)=>({flags:Z.flags,description:Z.description||""})),subcommands:w$(q)}]})}function X6(Y){return j1(Y.map((q)=>q.name))}function H6(Y,q){let $=Y.find((X)=>X.name===q);if(!$)return[];let Z=[];for(let X of $.options){let H=X.flags.match(/--([\w-]+)/);if(H)Z.push(`--${H[1]}`)}return Z6(Z)}function E1(Y){let q=X6(Y),Z=Y.filter((H)=>H.subcommands.length>0).map((H)=>({name:H.name,subs:j1(H.subcommands.map((Q)=>Q.name))})).map((H)=>` ${H.name})
|
|
4
4
|
COMPREPLY=($(compgen -W "${H.subs.join(" ")}" -- "\${cur}"))
|
|
5
5
|
return 0
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{j as o,k as r,l as t,m as e,n as XQ}from"./index-
|
|
3
|
+
import{j as o,k as r,l as t,m as e,n as XQ}from"./index-5t4t0avg.js";import"./index-n7qyrdr1.js";import{t as QQ}from"./index-6jq17k9s.js";import"./index-1hnw0rhc.js";import"./index-6jzsthh9.js";import"./index-g8zv1gta.js";import"./index-qfz9fy56.js";import"./index-ssjmzqcz.js";import"./index-tp4y9jde.js";import"./index-4wgjx8bf.js";import{Da as a}from"./index-g3ap3xpr.js";import"./index-0ckffygp.js";import"./index-rc79x8fw.js";import{bb as W}from"./index-yrgm89r8.js";import"./index-52cp759f.js";import"./index-v9fx5wab.js";import{Ib as s,Jb as i}from"./index-01qzsnwd.js";import"./index-d5ysy1yn.js";import"./index-04n4qgvd.js";import"./index-xjzmb1pn.js";import{Rc as p,Sc as v,nd as C,td as l,ud as n}from"./index-g2raeeh4.js";import{Nd as q}from"./index-9bqd8veb.js";import{Xd as D,_d as S,ae as g,be as M}from"./index-0cn9bv8z.js";import"./index-jw1k4vbk.js";import{he as B}from"./index-yy1mm8zs.js";import{isAbsolute as MQ}from"path";import{existsSync as V,mkdirSync as y,readFileSync as _Q,readdirSync as P,renameSync as BQ,unlinkSync as DQ,writeFileSync as f}from"fs";import{dirname as d,join as F}from"path";var GQ=".secrets-migrated-v1",IQ=["static-api-key","clientId","clientSecret"];function WQ(Q,H){return`${Q}:${H}`}function c(){return F(M(),GQ)}function TQ(){let Q=c();y(d(Q),{recursive:!0}),f(Q,`${new Date().toISOString()}
|
|
4
4
|
`,{mode:384})}function JQ(Q){if(!V(Q))return null;try{let H=_Q(Q,"utf8"),X=JSON.parse(H);if(X&&typeof X==="object"&&!Array.isArray(X))return X}catch{}return null}function VQ(Q,H){y(d(Q),{recursive:!0});let X=`${Q}.${process.pid}.tmp`;f(X,`${JSON.stringify(H,null,2)}
|
|
5
5
|
`,{mode:384}),BQ(X,Q)}function FQ(){let Q=M(),H=F(Q,"agents");if(!V(H))return[];let X=[],L;try{L=P(H)}catch{return[]}for(let Y of L){let z=F(H,Y,"config.json");if(!V(z))continue;X.push({path:z,scope:Y})}return X}function jQ(){let Q=M(),H=F(Q,"profiles");if(!V(H))return[];let X=[],L;try{L=P(H)}catch{return[]}for(let Y of L){if(!Y.endsWith(".json"))continue;X.push({path:F(H,Y),scope:Y.slice(0,-5)})}return X}async function KQ(Q,H){let X=JQ(Q);if(!X)return 0;let L=0;for(let Y of IQ){let z=X[Y];if(typeof z!=="string"||z.length===0)continue;let _=WQ(H,Y);try{await v(_,z),delete X[Y],L++,q().logger.info("secrets-migrator","migrated field",{path:Q,scope:H,key:Y})}catch(G){q().logger.warn("secrets-migrator","failed to migrate field",{path:Q,scope:H,key:Y,error:String(G)})}}if(L>0)VQ(Q,X);return L}async function m(){let Q={alreadyMigrated:!1,fieldsMoved:0,filesUpdated:0};if(V(c()))return Q.alreadyMigrated=!0,Q;let H=[...FQ(),...jQ()];for(let X of H){let L;try{L=await KQ(X.path,X.scope)}catch(Y){q().logger.warn("secrets-migrator","skipping target after error",{path:X.path,error:String(Y)});continue}if(L>0)Q.fieldsMoved+=L,Q.filesUpdated++}try{TQ()}catch(X){q().logger.warn("secrets-migrator","failed to drop migration marker",{error:String(X)})}if(Q.fieldsMoved>0)q().logger.info("secrets-migrator","migration complete",{fieldsMoved:Q.fieldsMoved,filesUpdated:Q.filesUpdated});return Q}{let Q=JSON.parse.bind(JSON);JSON.parse=(L,Y)=>{try{return Q(L,Y)}catch(z){if(typeof L==="string"&&L.endsWith("}}"))try{return Q(L.slice(0,-1),Y)}catch{}throw z}};let X=globalThis.Request?.prototype;if(X&&typeof X.json==="function"){let L=X.json;X.json=async function(){let z=await this.text();if(!z)return;try{return Q(z)}catch{if(z.endsWith("}}"))try{return Q(z.slice(0,-1))}catch{}let _=new Request("http://shim/",{method:"POST",body:z});return L.call(_)}}}}QQ();l();if(!process.env.VIBECONTROLS_DATA_DIR)process.env.VIBECONTROLS_DATA_DIR=S();if(typeof Bun>"u")console.error("ERROR: VibeControls Agent requires Bun runtime."),console.error("Install Bun: https://bun.sh"),process.exit(1);function UQ(Q){if(Q==="default")return 3005;let H=2166136261;for(let X=0;X<Q.length;X++)H=Math.imul(H^Q.charCodeAt(X),16777619);return 3100+Math.abs(H)%300}var E=(()=>{try{return D()}catch{return"default"}})(),A=Number.parseInt(process.env.PORT||String(UQ(E)),10),U=Number.isInteger(A)&&A>0?A:3005,R=process.env.HOST||"0.0.0.0",RQ=(()=>{let Q=process.env.DB_PATH;if(!Q)return;if(MQ(Q))return Q;console.warn(`[boot] Ignoring relative DB_PATH=${Q} (cwd=${process.cwd()}). Use an absolute path or unset to fall back to ${g()}.`);return})(),x=process.env.AGENT_API_KEY||void 0,CQ=process.env.LOG_LEVEL||"info",EQ=process.env.CORS_ORIGIN||void 0;async function wQ(){try{await m()}catch($){q().logger.warn("server","secrets migration encountered an error",{error:String($)})}let Q=C()["static-api-key"],H=(()=>{try{return D()}catch{return"default"}})(),X=Q??await p(`${H}:static-api-key`),L=!x&&!X;await s(),await n();let Y=process.env.VIBE_CLIENT_ID,z=process.env.VIBE_CLIENT_SECRET,_=process.env.VIBE_GLOBAL_GATEWAY_URL,G=process.env.VIBE_WORKSPACE_GATEWAY_URL,b=process.env.VIBE_WORKSPACE_ID,ZQ=!!Y&&!!z&&!!_&&!!G&&!!b;q().logger.info("server","Starting VibeControls Agent...",{runtime:"bun",bunVersion:Bun.version,port:U,host:R,env:"production"});try{let $=C(),Z=$["telemetry.enabled"]===!0||$["telemetry.enabled"]==="true";W.init({persisted:Z});let N=Date.now();W.emit("agent.started",{version:process.env.npm_package_version??"unknown",profile:E,platform:process.platform}),process.__vibe_started_at=N}catch{}let j=Math.max(1,Number.parseInt(process.env.VIBECONTROLS_AGENT_BOOT_RETRIES??"10",10)||10),$Q=($)=>{let Z=String($?.message??$).toLowerCase();return Z.includes("syntax")||Z.includes("cannot find module")||Z.includes("module not found")||Z.includes("typeerror")||Z.includes("config schema")||Z.includes("invalid config")||Z.includes("corrupt")||Z.includes("eaccess")||Z.includes("eperm")},O=null,I=0;while(!O){I++;try{O=await XQ({port:U,host:R,dbPath:RQ,apiKey:x,logLevel:CQ,corsOrigin:EQ}),await O.start();try{let $=await import("fs"),Z=`${S()}/runtime.json`;$.writeFileSync(Z,JSON.stringify({pid:process.pid,port:U,host:R,profile:E,startedAt:new Date().toISOString(),version:a()},null,2));let N=()=>{try{if($.existsSync(Z))$.unlinkSync(Z)}catch{}};process.once("SIGTERM",N),process.once("SIGINT",N),process.once("exit",N)}catch($){q().logger.warn("server","Could not write runtime.json",{error:String($)})}}catch($){let Z=$Q($);if(q().logger.error("server","Failed to start agent server",{attempt:I,maxBootAttempts:j,fatal:Z,error:String($)}),Z||I>=j)console.error(`\u274C Failed to start VibeControls Agent (attempt ${I}/${j}, fatal=${Z}):`,$),process.exit(1);let N=Math.min(30000,1000*2**Math.min(5,I-1)),J=Math.floor(Math.random()*500),K=N+J;console.warn(`\u26A0\uFE0F Agent boot attempt ${I}/${j} failed (transient), retrying in ${Math.round(K/1000)}s...`),await new Promise((k)=>setTimeout(k,K)),O=null}}let h=O.getServiceRegistry().getProvider("tunnel"),T=null;if(h?.getActiveTunnelUrl)for(let $=0;$<30;$++){if(T=await h.getActiveTunnelUrl(),T)break;await new Promise((Z)=>setTimeout(Z,1000))}if(!T){let{sanitizeEnvSuffix:$}=await import("./tunnel-bootstrap-2kg79ng8.js"),{getVibecontrolsProfile:Z}=await import("./path-utils-35re7qf9.js"),N=$(Z());T=process.env[`AGENT_TUNNEL_URL_${N}`]??process.env.AGENT_TUNNEL_URL??null}let HQ=C(),LQ=x||i()||HQ["static-api-key"]||"",w=q().getBootState(),YQ=w==="ready"?null:o();if(w==="ready")r();kQ({port:U,host:R,tunnelUrl:T,apiKey:LQ,revealApiKey:L||process.env.AGENT_PRINT_API_KEY==="1",state:w,pairingToken:YQ});try{t({profile:E})}catch($){q().logger.warn("server","Could not start autoupdate",{error:String($)})}let{existsSync:NQ,unlinkSync:qQ}=await import("fs"),{tmpdir:zQ}=await import("os"),{join:OQ}=await import("path"),u=async($)=>{q().logger.info("server",`Received ${$}, shutting down...`),e();try{let N=process.__vibe_started_at??Date.now();W.emit("agent.stopped",{uptime_s:Math.round((Date.now()-N)/1000),reason:$}),await W.flush(),W.stop()}catch{}let Z=O.getLifecycle();if($==="SIGTERM"){let N=OQ(zQ(),`.boff-vibecontrols-kill-${process.pid}`);if(NQ(N)){try{qQ(N)}catch{}if(q().logger.info("server","Kill-intent flag detected \u2014 full shutdown"),Z)await Z.kill();else await O.stop({reason:"shutdown"}),process.exit(0)}else if(q().logger.info("server","No kill flag \u2014 treating as hot-reload (soft stop)"),Z)await Z.softStop();else await O.stop({reason:"reload"})}else if(Z)await Z.kill();else await O.stop({reason:"shutdown"}),process.exit(0)};if(process.on("SIGINT",()=>u("SIGINT")),process.on("SIGTERM",()=>u("SIGTERM")),ZQ){let $=(()=>{let Z=process.env.VIBECONTROLS_FINALIZE_TIMEOUT_MS,N=Z?Number.parseInt(Z,10):NaN;return Number.isFinite(N)&&N>0?N:300000})();q().logger.info("server",`VIBE_* env vars detected \u2014 running inline finalize (timeout ${Math.round($/1000)}s)`),(async()=>{let Z={clientId:Y,clientSecret:z,workspaceId:b,globalGatewayUrl:_,workspaceGatewayUrl:G};try{let N=await Promise.race([O.finalize(Z),new Promise((J)=>setTimeout(()=>J({ok:!1,error:`inline finalize timed out after ${Math.round($/1000)}s`}),$))]);if(!N.ok){q().logger.warn("server","Inline finalize failed \u2014 agent stays awaiting-config. Background retry worker will keep trying.",{error:N.error});let{startFinalizeRetryWorker:J}=await import("./finalize-retry-worker-xp1nhv3c.js"),{setFinalizeRetryHandle:K}=await import("./finalize-retry-handle-registry-vv241fsq.js"),k=J({trigger:()=>O.finalize(Z)});K(k)}}catch(N){q().logger.error("server","Inline finalize threw",{error:String(N)})}})()}else q().logger.info("server","Agent is awaiting gateway credentials. Add it on the VibeControls platform using the tunnel URL and API key shown above.")}function kQ(Q){let X=(G)=>("\u2551 "+G).padEnd(65)+"\u2551",L="\u2560"+"\u2550".repeat(64)+"\u2563",Y="\u2554"+"\u2550".repeat(64)+"\u2557",z="\u255A"+"\u2550".repeat(64)+"\u255D",_=Q.revealApiKey?Q.apiKey:Q.apiKey?`${Q.apiKey.substring(0,8)}****${Q.apiKey.substring(Q.apiKey.length-4)}`:"(none)";if(console.log(""),console.log(Y),console.log(X("VibeControls Agent")),console.log(L),console.log(X(`State: ${Q.state}`)),console.log(X(`Agent URL: http://${Q.host}:${Q.port}`)),console.log(X(`API Key: ${_}`)),console.log(X(`Tunnel URL: ${Q.tunnelUrl??"(none)"}`)),Q.pairingToken)console.log(X(`Pairing: ${Q.pairingToken}`)),console.log(X(" (send as x-pairing-token on bootstrap)"));if(console.log(L),console.log(X(`Health: http://localhost:${Q.port}/health`)),console.log(X(`Status: http://localhost:${Q.port}/api/agent/status`)),console.log(z),!Q.revealApiKey)console.log(" (Set AGENT_PRINT_API_KEY=1 to print the API key in full.)");console.log("")}wQ();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{J as a}from"./index-
|
|
2
|
+
import{J as a}from"./index-c4xqp05z.js";import"./index-2gsarrbn.js";import"./index-b5dhmybd.js";import"./index-e1bw1bwr.js";import"./index-g8zv1gta.js";import"./index-qfz9fy56.js";import"./index-ssjmzqcz.js";import"./index-4wgjx8bf.js";import"./index-g3ap3xpr.js";import"./index-0ckffygp.js";import"./index-rc79x8fw.js";import"./index-yrgm89r8.js";import"./index-52cp759f.js";import"./index-01qzsnwd.js";import"./index-d5ysy1yn.js";import"./index-04n4qgvd.js";import"./index-5mw3eshk.js";import"./index-z5a4yxzz.js";import"./index-ef95xr4z.js";import"./index-xjzmb1pn.js";import"./index-g2raeeh4.js";import"./index-9bqd8veb.js";import"./index-0cn9bv8z.js";import"./index-jw1k4vbk.js";import"./index-yy1mm8zs.js";export{a as registerCoreCommands};
|
package/package.json
CHANGED
package/dist/index-c58g96mb.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{o as K4,q as Z4}from"./index-n7qyrdr1.js";import{u as s4,v as O5,w as j5}from"./index-1hnw0rhc.js";import{E as V4}from"./index-6jzsthh9.js";import{$ as y4,Q as E5,aa as _2,ba as U0,ca as P4,da as c4,ea as n4,fa as f4,ha as C2,ia as p2,ja as i2,ka as I2}from"./index-g8zv1gta.js";import{la as C5,qa as I5,sa as E0}from"./index-qfz9fy56.js";import{va as b2}from"./index-ssjmzqcz.js";import{wa as F5,xa as U5,ya as x5,za as M5}from"./index-tp4y9jde.js";import{Aa as L5}from"./index-4wgjx8bf.js";import{Ja as T0,Wa as T5}from"./index-g3ap3xpr.js";import{Xa as N2}from"./index-0ckffygp.js";import{ab as v2}from"./index-rc79x8fw.js";import{eb as Q5,fb as W5,gb as z5,hb as H5,ib as G5,jb as J2,kb as B5,lb as V5,mb as K5,nb as _5,pb as N5}from"./index-v9fx5wab.js";import{Ab as n0,Eb as x2,Fb as Y0,Gb as Z5,Hb as J5,Ib as j0,Jb as M2,Kb as m,Lb as l,Mb as l4,Nb as d4,Ob as X5,Pb as Y5,tb as p0,ub as h2,vb as l0,wb as X0,xb as d0,yb as $5}from"./index-01qzsnwd.js";import{Tb as z,Ub as D}from"./index-04n4qgvd.js";import{md as t0,nd as s,od as g0,pd as f2,qd as D2}from"./index-g2raeeh4.js";import{Cd as n2,Hd as g,Jd as M0,Kd as b,Ld as a,Nd as G,Od as W0,vd as x0,wd as r4,xd as t4,yd as e4,zd as B2}from"./index-9bqd8veb.js";import{Rd as s0,Sd as H0,Ud as P2,Vd as r0,Xd as E2,Yd as d,_d as S2,ae as T2,be as K2,ce as d2}from"./index-0cn9bv8z.js";import{ee as h0,he as f}from"./index-yy1mm8zs.js";var A0=typeof new Headers()?.toJSON==="function",A5=($)=>{if(A0)return Object.keys($.toJSON()).join(", ");let Z="",Q=0;return $.forEach((Y,X)=>{if(Q)Z=Z+", "+X;else Z=X;Q++}),Z},w0=($)=>{let{aot:Z=!0,origin:Q=!0,methods:Y=!0,allowedHeaders:X=!0,exposeHeaders:J=!0,credentials:W=!0,maxAge:H=5,preflight:B=!0}=$??{};if(Array.isArray(X))X=X.join(", ");if(Array.isArray(J))J=J.join(", ");let K=typeof Q==="boolean"?void 0:Array.isArray(Q)?Q:[Q],N=new D({name:"@elysiajs/cors",seed:$,aot:Z}),I=K?.some((F)=>F==="*"),C={};if(K){for(let F of K)if(typeof F==="string")C[F]=!0}let U=(F,T,x)=>{if(Array.isArray(F))return F.some((R)=>U(R,T,x));switch(typeof F){case"string":if(x in C)return!0;let R=x.indexOf("://");if(R!==-1)x=x.slice(R+3);return F===x;case"function":return F(T)===!0;case"object":if(F instanceof RegExp)return F.test(x)}return!1},V=(F,T)=>{if(Q===!0){F.headers.vary="*",F.headers["access-control-allow-origin"]=T.headers.get("Origin")||"*";return}if(I){F.headers.vary="*",F.headers["access-control-allow-origin"]="*";return}if(!K?.length)return;if(K.length){let x=T.headers.get("Origin")??"";for(let R=0;R<K.length;R++)if(U(K[R],T,x)===!0){F.headers.vary=Q?"Origin":"*",F.headers["access-control-allow-origin"]=x||"*";return}}F.headers.vary="Origin"},E=(F,T)=>{if(!T)return;if(Y===!0)return F.headers["access-control-allow-methods"]=T??"*";if(Y===!1||!Y?.length)return;if(Y==="*")return F.headers["access-control-allow-methods"]="*";if(!Array.isArray(Y))return F.headers["access-control-allow-methods"]=Y;F.headers["access-control-allow-methods"]=Y.join(", ")},q={};if(typeof J==="string")q["access-control-expose-headers"]=J;if(typeof X==="string")q["access-control-allow-headers"]=X;if(W===!0)q["access-control-allow-credentials"]="true";N.headers(q);function h({set:F,request:T,headers:x}){if(V(F,T),E(F,T.headers.get("access-control-request-method")),X===!0||J===!0){if(X===!0)F.headers["access-control-allow-headers"]=x["access-control-request-headers"];if(J===!0)F.headers["access-control-expose-headers"]=Object.keys(x).join(",")}if(H)F.headers["access-control-max-age"]=H.toString();return new Response(null,{status:204})}if(B)N.options("/",h).options("/*",h);return N.onRequest(function({set:T,request:x}){if(V(T,x),B&&x.method==="OPTIONS")return h({set:T,request:x,headers:A0?x.headers.toJSON():Object.fromEntries(x.headers.entries())});if(E(T,x.method),X===!0||J===!0){let R=A5(x.headers);if(X===!0)T.headers["access-control-allow-headers"]=R;if(J===!0)T.headers["access-control-expose-headers"]=R}})};import{createHash as S0}from"crypto";var X2="idempotency",w5=300000,k0=1e4,A2=new Map;function k5($,Z,Q,Y){return S0("sha256").update(`${$}|${Z}|${Q}|${Y}`).digest("hex")}async function S5($,Z){let Q=await $.getPluginState(X2,Z);if(!Q)return null;try{let Y=JSON.parse(Q);if(Y.expiresAt<Date.now())return await $.deletePluginState(X2,Z),null;return Y}catch{return null}}async function D5($,Z,Q){await $.setPluginState(X2,Z,JSON.stringify(Q))}async function h5($){let Z=await $.getAllPluginState(X2),Q=Date.now(),Y=0,X=[];for(let J of Z)try{if(JSON.parse(J.value).expiresAt<Q)await $.deletePluginState(X2,J.key),Y+=1;else X.push({key:J.key,updatedAt:J.updatedAt})}catch{await $.deletePluginState(X2,J.key),Y+=1}if(X.length>k0){X.sort((W,H)=>(W.updatedAt??"").localeCompare(H.updatedAt??""));let J=X.slice(0,X.length-k0);for(let W of J)await $.deletePluginState(X2,W.key),Y+=1}if(Y>0)G().logger.info("idempotency",`Swept ${Y} expired/over-cap entries`)}var Q0=null,v5=600000;function P5($){if(Q0)return;Q0=setInterval(()=>{let Z=$.getDb();if(!Z)return;h5(Z).catch((Q)=>{G().logger.warn("idempotency","Sweep failed",{error:String(Q)})})},v5),Q0.unref?.()}function D0($){return P5($),new D({name:"plugin/idempotency"}).onBeforeHandle(async({request:Z,path:Q,set:Y,store:X})=>{if(Z.method!=="POST"&&Z.method!=="PUT")return;let J=Z.headers.get("x-idempotency-key")??Z.headers.get("X-Idempotency-Key");if(!J)return;if(J.length<8||J.length>200)return Y.status=400,{error:"X-Idempotency-Key must be 8\u2013200 chars",code:"BAD_REQUEST"};let W=$.getDb();if(!W)return;let H="no-body";try{let E=await Z.clone().text();H=S0("sha256").update(E).digest("hex")}catch{}let B=k5(Z.method,Q,J,H),K=await S5(W,B);if(K){Y.status=K.status;let V=Y.headers??={};V["Content-Type"]=K.contentType,V["X-Idempotency-Replay"]="true",X.__idemReplay=K.body;try{return JSON.parse(K.body)}catch{return K.body}}let N=A2.get(B);if(N){let V=await N.catch(()=>null);if(V){Y.status=V.status;let E=Y.headers??={};E["Content-Type"]=V.contentType,E["X-Idempotency-Replay"]="true",X.__idemReplay=V.body;try{return JSON.parse(V.body)}catch{return V.body}}}let I,C,U=new Promise((V,E)=>{I=V,C=E});A2.set(B,U),X.__idemKey=B,X.__idemResolve=I,X.__idemReject=C}).onAfterHandle(async({response:Z,set:Q,store:Y})=>{let X=Y.__idemKey;if(!X)return;let J=Y.__idemResolve,W=$.getDb(),H=Q.status??200,B=typeof Z==="string"?Z:JSON.stringify(Z),N=Q.headers?.["Content-Type"]??"application/json",I={status:H,body:B,contentType:N,expiresAt:Date.now()+w5},C=H>=200&&H<300;try{if(W&&C)await D5(W,X,I)}catch(U){G().logger.warn("idempotency","Failed to persist response",{error:String(U)})}finally{try{J?.(C?I:null)}catch{}A2.delete(X)}}).onError(({store:Z})=>{let Q=Z.__idemKey;if(!Q)return;let Y=Z.__idemReject;try{Y?.(Error("idempotency: handler errored"))}catch{}A2.delete(Q)}).as("global")}import c from"os";import{readFileSync as s5}from"fs";import{join as r5}from"path";var v0={enabled:!1,async scrape(){return`# vibecontrols agent metrics disabled (OTel SDK not initialised)
|
|
3
|
-
`},recordHttpRequest(){},setPluginsLoaded(){}},$2=null,w2=null;async function k2($){if($2)return $2;if(w2)return w2;return w2=(async()=>{try{let{MeterProvider:Z}=await import("./index-hrdamx5j.js").then((m)=>h0(m.default,1)),{PrometheusExporter:Q,PrometheusSerializer:Y}=await import("./index-1zw3kea7.js").then((m)=>h0(m.default,1)),X=new Q({preventServerStart:!0}),J=new Y,H=new Z({readers:[X]}).getMeter("vibecontrols-agent"),B=H.createGauge("vibecontrols_agent_info",{description:"Static info about the agent process; value is always 1."});H.createObservableGauge("vibecontrols_agent_uptime_seconds",{description:"Process uptime in seconds."}).addCallback((V)=>{V.observe(process.uptime())});let N=H.createCounter("vibecontrols_http_requests_total",{description:"Total HTTP requests handled by the agent, labelled by method, route, status."}),I={};H.createObservableGauge("vibecontrols_plugins_loaded",{description:"Plugins loaded by the agent, broken down by status (loaded, failed, etc.)."}).addCallback((V)=>{for(let[E,q]of Object.entries(I))V.observe(q,{status:E})}),B.record(1,{version:$?.version??"unknown",profile:$?.profile??"default"});let U={enabled:!0,async scrape(){let V=await X.collect();if(!V.resourceMetrics)return"";return J.serialize(V.resourceMetrics)},recordHttpRequest(V,E,q){N.add(1,{method:V,route:E,status:String(q)})},setPluginsLoaded(V){I={...V}}};return $2=U,G().logger.info("metrics","OTel Prometheus registry initialised"),U}catch(Z){return G().logger.warn("metrics","Failed to initialise OTel metrics; /metrics will return a stub body",{error:Z instanceof Error?Z.message:String(Z)}),$2=v0,v0}})(),w2}function P0($,Z,Q){if(!$2)return;$2.recordHttpRequest($,Z,Q)}function f0($){if(!$2)return;$2.setPluginsLoaded($)}var f5=new Set(["127.0.0.1","::1"]),b0=!1;function b5(){if(b0)return;if(process.env.METRICS_ANONYMOUS_LOCALHOST==="true")b0=!0,G().logger.warn("metrics","METRICS_ANONYMOUS_LOCALHOST=true \u2014 /metrics is open to TCP loopback peers without an API key. Prefer issuing a scoped API key for your scraper.")}function y5($){let Z=$.replace(/^\[|\]$/g,"");if(Z.startsWith("::ffff:"))return Z.slice(7);return Z}function $0($,Z){let Q=Z?.requestIP($)?.address;if(!Q)return!1;return f5.has(y5(Q))}function y0(){return b5(),new D({name:"routes/metrics"}).get("/metrics",async({request:$,server:Z,set:Q})=>{if(!(process.env.METRICS_ANONYMOUS_LOCALHOST==="true"&&$0($,Z))){let W=m(Object.fromEntries($.headers.entries()));if(!l(W))return Q.status=401,Q.headers["content-type"]="application/json",JSON.stringify({error:"Unauthorized",message:"Invalid or missing API key"})}let J=await(await k2()).scrape();return Q.headers["content-type"]="text/plain; version=0.0.4; charset=utf-8",J})}import{randomBytes as c5,timingSafeEqual as u5}from"crypto";import{chmodSync as m5,existsSync as c0,mkdirSync as g5,readFileSync as p5,unlinkSync as l5,writeFileSync as d5}from"fs";import{dirname as n5,join as i5}from"path";var Y2=null;function u0(){return i5(S2(),"pairing-token")}function o5(){return c5(32).toString("base64url")}function a5($,Z){let Q=Buffer.from($),Y=Buffer.from(Z);if(Q.length!==Y.length)return!1;try{return u5(Q,Y)}catch{return!1}}function X6(){if(Y2)return Y2;let $=u0();try{if(c0($)){let Q=p5($,"utf8").trim();if(Q.length>=32)return Y2=Q,Q}}catch{}let Z=o5();try{g5(n5($),{recursive:!0}),d5($,Z,{encoding:"utf8"});try{m5($,384)}catch{}}catch(Q){}return Y2=Z,Z}function Z0($){if(!$)return!1;if(!Y2)return!1;return a5($,Y2)}function m0(){Y2=null;try{let $=u0();if(c0($))l5($)}catch{}}function J0($){return $["x-pairing-token"]??$["X-Pairing-Token"]??null}function t5(){let $=c.hostname(),Z=c.platform(),Q=c.arch(),Y=new Bun.CryptoHasher("sha256");return Y.update(`${$}-${Z}-${Q}`),Y.digest("hex").substring(0,16)}function e5(){for(let $ of["..","../.."])try{let Z=r5(import.meta.dir,$,"package.json"),Y=JSON.parse(s5(Z,"utf8")).version;if(Y)return Y}catch{}return"0.0.0"}async function QQ($){let Z=[],Q=$.getProvider("tunnel");if(Q)Z.push(Q);for(let Y of $.listProvidersForType("tunnel")){let X=$.getProviderByName("tunnel",Y.pluginName);if(X&&!Z.includes(X))Z.push(X)}for(let Y of Z){if(!Y.getActiveTunnelUrl)continue;let X=await Y.getActiveTunnelUrl();if(X)return X}return null}function i0({serviceRegistry:$,runFinalize:Z,getDb:Q}){let Y=e5(),X=t5();return new D({prefix:"/api/agent"}).get("/identity",()=>({hostname:c.hostname(),platform:c.platform(),architecture:c.arch(),agentVersion:Y,agentInstanceId:g0()})).get("/version",()=>({version:Y,runtime:"bun",runtimeVersion:typeof Bun<"u"?Bun.version:"unknown"})).get("/api-key",({request:J,server:W,set:H})=>{if(!$0(J,W)){let K=m(Object.fromEntries(J.headers.entries()));if(!l(K))return H.status=401,{error:"Unauthorized",message:"Invalid or missing API key"}}return{apiKey:M2()}}).post("/iframe-token",({body:J,request:W,set:H})=>{let B=m(Object.fromEntries(W.headers.entries()));if(!l(B))return H.status=401,{error:"Unauthorized",message:"Invalid or missing API key"};try{if(Array.isArray(J.pathPrefixes)&&J.pathPrefixes.length>0)return l0({pathPrefixes:J.pathPrefixes,methods:J.methods},J.ttlSeconds??void 0);if(!J.pathPrefix)return H.status=400,{error:"BadRequest",message:"Provide either pathPrefix (string) or pathPrefixes (string[])"};return h2(J.pathPrefix,J.ttlSeconds??void 0)}catch(K){return H.status=400,{error:"BadRequest",message:K instanceof Error?K.message:String(K)}}},{body:z.Object({pathPrefix:z.Optional(z.String({minLength:1})),pathPrefixes:z.Optional(z.Array(z.String({minLength:1}),{minItems:1,maxItems:16})),methods:z.Optional(z.Array(z.String({minLength:1}),{minItems:1,maxItems:8})),ttlSeconds:z.Optional(z.Number())})}).post("/terminal-exchange",({body:J,set:W})=>{let{sid:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"sid and token required"};if(!p0(H))return W.status=400,{error:"BadRequest",message:"invalid sid"};let K=`/terminal/${H}`,N=d0(B,K);if(!N.ok)return G().logger.warn("terminal-exchange","iframe token rejected",{sid:H,reason:N.reason}),W.status=401,{error:"Unauthorized",message:"invalid iframe token",code:N.reason==="expired"?"expired":N.reason==="replayed"?"replayed":"invalid"};let I=n0(H,600),C=`vt_term_${H}`;return W.headers["set-cookie"]=`${C}=${I.token}; HttpOnly; Secure; SameSite=None; Path=/terminal/${H}; Max-Age=600`,W.status=204,null},{body:z.Object({sid:z.String({minLength:1}),token:z.String({minLength:1})})}).post("/ui-exchange",({body:J,set:W})=>{let{plugin:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"plugin and token required"};if(!x2(H))return W.status=400,{error:"BadRequest",message:"invalid plugin name"};let K=`/ui/${H}`;if(!X0(B,K))return W.status=401,{error:"Unauthorized",message:"invalid iframe token"};let N=Y0(H,600),I=`vt_ui_${H}`;return W.headers["set-cookie"]=`${I}=${N.token}; HttpOnly; Secure; SameSite=None; Path=/ui/${H}/; Max-Age=600`,W.status=204,null},{body:z.Object({plugin:z.String({minLength:1}),token:z.String({minLength:1})})}).post("/ui-exchange-plugin",({body:J,set:W})=>{let{plugin:H,token:B}=J;if(!H||!B)return W.status=400,{error:"BadRequest",message:"plugin and token required"};if(!x2(H))return W.status=400,{error:"BadRequest",message:"invalid plugin name"};if(![`/api/plugins/${H}/ui`,`/${H}`].find((U)=>X0(B,U)))return W.status=401,{error:"Unauthorized",message:"invalid iframe token"};let I=Y0(H,600),C=`vt_ui_${H}`;return W.headers["set-cookie"]=`${C}=${I.token}; HttpOnly; Secure; SameSite=None; Path=/api/plugins/${H}/ui/; Max-Age=600`,W.status=204,null},{body:z.Object({plugin:z.String({minLength:1}),token:z.String({minLength:1})})}).get("/system",({request:J,set:W})=>{let H=m(Object.fromEntries(J.headers.entries()));if(!l(H))return W.status=401,{error:"Unauthorized",message:"Invalid or missing API key"};return{machineId:X,hostname:c.hostname(),platform:c.platform(),arch:c.arch(),release:c.release(),cpus:c.cpus().length,totalMemory:c.totalmem(),freeMemory:c.freemem(),uptime:c.uptime(),bunVersion:typeof Bun<"u"?Bun.version:void 0,agentVersion:Y,homeDir:c.homedir(),cwd:process.cwd(),environment:"production"}}).get("/tunnel",async({request:J,set:W})=>{let H=Object.fromEntries(J.headers.entries()),B=l(m(H)),K=Z0(J0(H));if(!B&&!K)return W.status=401,{error:"Unauthorized",message:"Provide x-agent-api-key OR x-pairing-token to read tunnel URL"};let N=await QQ($);if(!N)return{tunnelUrl:null,message:"No tunnel provider registered"};return{tunnelUrl:N}}).get("/status",()=>{let J=["tunnel","session","ai"].filter((W)=>$.hasProvider(W));return{state:G().getBootState(),status:G().getBootState(),version:Y,providers:J,timestamp:new Date().toISOString()}}).get("/gateway-auth",()=>({configured:g.isConfigured(),config:v2(g.getConfig()),state:G().getBootState()})).post("/retry-config",async({set:J})=>{let{getFinalizeRetryHandle:W}=await import("./finalize-retry-handle-registry-vv241fsq.js"),H=W();if(!H)return J.status=409,{ok:!1,error:"No finalize retry worker is active. The agent either never had cached credentials to retry with, or it already reached the ready state."};let B=await H.forceRetryNow();if(!B.ok)J.status=503;return{ok:B.ok,error:B.ok?void 0:B.error,state:G().getBootState(),worker:H.getState()}}).post("/gateway-auth",async({body:J,request:W,set:H})=>{let B=G().getBootState(),K=Object.fromEntries(W.headers.entries());if(B==="ready"){let F=m(K);if(!l(F))return H.status=401,{success:!1,state:B,error:"Unauthorized: API key required to reconfigure"}}else{let F=m(K),T=J0(K),x=l(F),R=Z0(T);if(!x&&!R)return H.status=401,{success:!1,state:B,error:"Unauthorized: provide x-agent-api-key OR x-pairing-token for bootstrap"}}let{clientId:N,clientSecret:I,workspaceId:C,globalGatewayUrl:U,workspaceGatewayUrl:V}=J;if(!N||!I||!C||!U||!V)return H.status=400,{success:!1,state:G().getBootState(),error:"clientId, clientSecret, workspaceId, globalGatewayUrl, and workspaceGatewayUrl are required"};let E,q;try{E=B2(U,"globalGatewayUrl"),q=B2(V,"workspaceGatewayUrl")}catch(F){return H.status=400,{success:!1,state:G().getBootState(),error:F instanceof Error?F.message:String(F)}}{let F=b()??G();try{await D2({clientId:N,clientSecret:I,workspaceId:C,ownerUserId:J.ownerUserId,organizationId:J.organizationId,globalGatewayUrl:E,workspaceGatewayUrl:q,agentRecordId:J.agentRecordId,scopes:J.scopes,...J.storageAdapter?{storageAdapter:J.storageAdapter}:{},...J.storageOptions?{storageOptions:J.storageOptions}:{},...J.dbPath?{dbPath:J.dbPath}:{}},{dir:F.dataDir,scope:F.name})}catch(T){return H.status=500,{success:!1,state:G().getBootState(),error:`Failed to persist gateway credentials to secrets backend: ${T instanceof Error?T.message:String(T)}`}}}let h=G().getBootState();if(h==="ready"){let F=Q();if(F){if(await F.setConfig("gateway-auth:clientId",N),await F.setConfig("gateway-auth:clientSecret",I),await F.setConfig("gateway-auth:workspaceId",C),J.organizationId)await F.setConfig("gateway-auth:organizationId",J.organizationId);if(await F.setConfig("gateway-auth:globalGatewayUrl",E),await F.setConfig("gateway-auth:workspaceGatewayUrl",q),J.agentRecordId)await F.setConfig("gateway-auth:agentRecordId",J.agentRecordId)}g.configure({globalGatewayUrl:E,workspaceGatewayUrl:q,clientId:N,clientSecret:I,workspaceId:C,organizationId:J.organizationId}),G().logger.info("preconfig","Gateway credentials re-configured (agent was already ready)");let T=!!(J.storageAdapter||J.storageOptions||J.dbPath);return{success:!0,state:h,message:T?"Gateway auth re-configured. Restart the agent (vibe restart) to apply the new storage configuration.":"Gateway auth re-configured"}}return G().logger.info("preconfig","Gateway credentials received \u2014 beginning finalize (background)"),m0(),Z({clientId:N,clientSecret:I,workspaceId:C,organizationId:J.organizationId,globalGatewayUrl:E,workspaceGatewayUrl:q},{agentRecordId:J.agentRecordId,scopes:J.scopes}).catch((F)=>{G().logger.error("preconfig","Background finalize threw",{error:F instanceof Error?F.message:String(F)})}),H.status=202,{success:!0,state:G().getBootState(),agentRecordId:J.agentRecordId,message:"Gateway credentials accepted; finalize is running in the background. Poll /health/ready for completion."}},{body:z.Object({clientId:z.Optional(z.String()),clientSecret:z.Optional(z.String()),workspaceId:z.Optional(z.String()),ownerUserId:z.Optional(z.String()),organizationId:z.Optional(z.String()),globalGatewayUrl:z.Optional(z.String()),workspaceGatewayUrl:z.Optional(z.String()),scopes:z.Optional(z.Array(z.String())),agentRecordId:z.Optional(z.String()),storageAdapter:z.Optional(z.String()),storageOptions:z.Optional(z.Record(z.String(),z.String())),dbPath:z.Optional(z.String())})})}import{existsSync as e,mkdirSync as $Q,rmSync as o0,readdirSync as e0}from"fs";import{join as y2}from"path";function o($){return y2(K2(),"agents",d($))}function ZQ(){let $=y2(K2(),"agents");if(!e($))return[];return e0($,{withFileTypes:!0}).filter((Z)=>Z.isDirectory()).map((Z)=>Z.name).filter((Z)=>/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(Z))}function Q4($){return y2(K2(),"agents",d($))}function z0($){return s({dir:Q4($)})}function a0($,Z){return f2(Z,{dir:Q4($),scope:d($)})}function V2($){let Z=P2(),Q=H0().find((J)=>J.name===$),Y=a.get($),X={name:$,isDefault:$===Z,isRunning:Q?.status==="running",attached:Y!==void 0,bootState:Y?Y.getBootState():null,dataDir:Y?Y.dataDir:null};if(Q)X.port=Q.port,X.pid=Q.pid,X.startTime=Q.startTime;if(e(o($)))X.config=v2(z0($));return X}function $4($={}){let Z=$.serviceManagerFactory?$.serviceManagerFactory():new b2;return new D({prefix:"/api/profiles"}).get("/",()=>{let Q=ZQ(),Y=P2(),X=new Set(Q);return X.add(Y),[...X].sort().map((J)=>V2(J))}).post("/",async({body:Q,set:Y})=>{try{let X=d(Q.name),J=o(X);if(e(J))return Y.status=409,{error:"exists",message:`Profile '${X}' already exists.`};let W;if(Q.copyFrom){let H=d(Q.copyFrom);if(!e(o(H)))return Y.status=400,{error:"copy-source-missing",message:`Profile '${H}' does not exist.`};W=z0(H),delete W["static-api-key"],delete W.agentRecordId,delete W.apiKeys}else W=t0();if(Q.gatewayUrl)W.globalGatewayUrl=Q.gatewayUrl;if(Q.workspaceGatewayUrl)W.workspaceGatewayUrl=Q.workspaceGatewayUrl;if(Q.clientId)W.clientId=Q.clientId;if(Q.clientSecret)W.clientSecret=Q.clientSecret;if(Q.workspaceId)W.workspaceId=Q.workspaceId;if(Q.organizationId)W.organizationId=Q.organizationId;$Q(J,{recursive:!0}),a0(X,W);try{W0(X)}catch(H){G().logger.warn("profile-mgmt",`In-process attach failed for '${X}'`,{error:String(H)})}if(G().logger.info("profile-mgmt",`Created profile '${X}' at ${J}`),Q.start){let H={name:X,port:Q.port??0,daemon:!0,dbPath:T2(),profile:X};await Z.startDaemon(H)}return Y.status=201,V2(X)}catch(X){return Y.status=400,{error:"create-failed",message:X instanceof Error?X.message:String(X)}}},{body:z.Object({name:z.String(),gatewayUrl:z.Optional(z.String()),workspaceGatewayUrl:z.Optional(z.String()),clientId:z.Optional(z.String()),clientSecret:z.Optional(z.String()),workspaceId:z.Optional(z.String()),organizationId:z.Optional(z.String()),copyFrom:z.Optional(z.String()),start:z.Optional(z.Boolean()),port:z.Optional(z.Number())})}).get("/:name",({params:Q,set:Y})=>{try{let X=d(Q.name);if(!e(o(X)))return Y.status=404,{error:"not-found",message:`No profile '${X}'.`};return V2(X)}catch(X){return Y.status=400,{error:"bad-request",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})}).put("/:name",({params:Q,body:Y,set:X})=>{try{let J=d(Q.name);if(!e(o(J)))return X.status=404,{error:"not-found",message:`No profile '${J}'.`};let W=["static-api-key","apiKeys","agentRecordId"];for(let K of W)if(K in Y)return X.status=400,{error:"forbidden-field",message:`Field '${K}' is managed via dedicated commands (vibe key rotate / vibe profile create). It cannot be patched here.`};if("registry"in Y)return X.status=400,{error:"forbidden-field",message:"Field 'registry' cannot be patched via this endpoint. Use POST /api/agent/registry with operator confirmation (VIBE_ALLOW_REGISTRY_CHANGE=1) so the change is auditable."};let B={...z0(J),...Y};return a0(J,B),V2(J)}catch(J){return X.status=400,{error:"update-failed",message:J instanceof Error?J.message:String(J)}}},{params:z.Object({name:z.String()}),body:z.Record(z.String(),z.Any())}).delete("/:name",async({params:Q,body:Y,query:X,set:J})=>{try{let W=d(Q.name);if(W===P2())return J.status=409,{error:"is-default",message:`Cannot delete active default profile '${W}'. Switch to another profile first.`};let H=X?.purge==="true"||X?.purge==="1",B=e(o(W)),K=a.has(W);if(!B&&!K)return J.status=404,{error:"not-found",message:`No profile '${W}'.`};if(B&&!H&&!Y?.confirm)return J.status=400,{error:"confirm-required",message:"Pass { confirm: true } in the body or `?purge=true` in the query to delete the on-disk dataDir (destructive)."};try{await Z.stop(W)}catch{}try{await a.destroy(W)}catch(N){G().logger.warn("profile-mgmt",`In-process detach failed for '${W}'`,{error:String(N)})}if(B)if(Y?.keepConfig)for(let N of e0(o(W))){if(N==="config.json")continue;o0(y2(o(W),N),{recursive:!0,force:!0})}else o0(o(W),{recursive:!0,force:!0});return G().logger.info("profile-mgmt",`Deleted profile '${W}'`),{ok:!0,deleted:W,keptConfig:!!Y?.keepConfig,detached:K,purged:B}}catch(W){return J.status=400,{error:"delete-failed",message:W instanceof Error?W.message:String(W)}}},{params:z.Object({name:z.String()}),query:z.Optional(z.Object({purge:z.Optional(z.String())})),body:z.Optional(z.Object({confirm:z.Optional(z.Boolean()),keepConfig:z.Optional(z.Boolean())}))}).post("/:name/switch",async({params:Q,set:Y})=>{try{let X=d(Q.name);if(!e(o(X)))return Y.status=404,{error:"not-found",message:`No profile '${X}'.`};return await s0(()=>r0(X)),G().logger.info("profile-mgmt",`Default profile switched to '${X}'`),{ok:!0,defaultProfile:X}}catch(X){return Y.status=400,{error:"switch-failed",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})}).post("/:name/start",async({params:Q,body:Y,set:X})=>{try{let J=d(Q.name);if(!e(o(J)))return X.status=404,{error:"not-found",message:`No profile '${J}'.`};try{W0(J)}catch(H){G().logger.warn("profile-mgmt",`In-process attach failed for '${J}'`,{error:String(H)})}if(!H0().some((H)=>H.name===J&&H.status==="running")){let H={name:J,port:Y?.port??0,daemon:!0,dbPath:T2(),profile:J};await Z.startDaemon(H)}return V2(J)}catch(J){return X.status=500,{error:"start-failed",message:J instanceof Error?J.message:String(J)}}},{params:z.Object({name:z.String()}),body:z.Optional(z.Object({port:z.Optional(z.Number())}))}).post("/:name/stop",async({params:Q,set:Y})=>{try{let X=d(Q.name);try{await Z.stop(X)}catch{}try{await a.destroy(X)}catch(J){G().logger.warn("profile-mgmt",`In-process detach failed for '${X}'`,{error:String(J)})}return V2(X)}catch(X){return Y.status=500,{error:"stop-failed",message:X instanceof Error?X.message:String(X)}}},{params:z.Object({name:z.String()})})}function JQ(){let $=process.memoryUsage(),Z=process.resourceUsage(),Q=Z.userCPUTime/1000,Y=Z.systemCPUTime/1000,X=Q+Y,J=a.list().map((W)=>{let H;try{H=Z4(W.spawnOwnerKey).length}catch{H=0}return{name:W.name,status:W.getBootState(),childPidCount:H,cpuMs:X,heapBytes:$.heapUsed,dataDir:W.dataDir}});return{process:{pid:process.pid,uptimeSeconds:process.uptime(),cpuUserMs:Q,cpuSystemMs:Y,heapUsedBytes:$.heapUsed,heapTotalBytes:$.heapTotal,rssBytes:$.rss},profiles:J,notes:{perProfileCpu:"deferred",perProfileHeap:"deferred"}}}function J4(){return new D({prefix:"/api/profile-stats"}).get("/",()=>JQ())}function c2($,Z){return Promise.race([$,new Promise((Q,Y)=>setTimeout(()=>Y(Error(`timeout after ${Z}ms`)),Z))])}function XQ($){let Z=$ instanceof Error?$.message:String($);return/ENOENT/.test(Z)||/no such file or directory/i.test(Z)}async function X4($){let Q=`__health__:probe:${typeof crypto<"u"&&typeof crypto.randomUUID==="function"?crypto.randomUUID():`${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`}`,Y=String(Date.now());if(await c2($.setConfig(Q,Y),2000),await c2($.getConfig(Q),2000)!==Y)throw Error("round-trip mismatch");try{await c2($.deleteConfig(Q),500)}catch{}}async function YQ($,Z){if(!$)return{ok:!1,message:"database not opened"};let Q=performance.now();try{return await X4($),{ok:!0,durationMs:performance.now()-Q}}catch(Y){if(Z&&XQ(Y))try{return(await import("fs")).mkdirSync(Z,{recursive:!0}),await X4($),{ok:!0,message:`recovered: dbPath ${Z} was missing \u2014 recreated`,durationMs:performance.now()-Q}}catch(X){return{ok:!1,message:`ENOENT on dbPath ${Z}: ${X instanceof Error?X.message:String(X)}`,durationMs:performance.now()-Q}}return{ok:!1,message:Y instanceof Error?Y.message:String(Y),durationMs:performance.now()-Q}}}function Y4($,Z){if(!$)return{ok:!1,message:"no service registry"};let Y=G().getBootState()==="awaiting-config";if(Z==="tunnel"){let X=$.getProvider("tunnel");if(!X&&process.env.AGENT_TUNNEL==="false")return{ok:!0,message:"tunnel disabled via AGENT_TUNNEL=false"};if(X)return{ok:!0,message:`provider: ${X.name}`};return{ok:!1,message:Y?"agent is awaiting-config \u2014 POST OAuth credentials to /api/agent/gateway-auth to register tunnel provider":"no tunnel provider registered"}}if(Z==="session"){let X=$.getProvider("session");if(X)return{ok:!0,message:`provider: ${X.name}`};return{ok:!1,message:Y?"agent is awaiting-config \u2014 POST OAuth credentials to /api/agent/gateway-auth to register session provider":"no session provider registered"}}return{ok:!0}}async function WQ($){if(!$)return{};let Z={};for(let Q of $.getAllPlugins()){let Y=Q.getHealth;if(typeof Y!=="function")continue;let X=performance.now();try{let J=await c2(Promise.resolve(Y.call(Q)),2000);Z[Q.name]={ok:J?.ok!==!1,message:J?.message,durationMs:performance.now()-X}}catch(J){Z[Q.name]={ok:!1,message:J instanceof Error?J.message:String(J),durationMs:performance.now()-X}}}return Z}function W4($){let Z=$&&"serviceRegistry"in $?$:{serviceRegistry:$};return new D({prefix:"/health"}).get("/",()=>{return{status:"ok",lifecycleState:Z.serviceRegistry?.getService("agent","lifecycle")?.getState()??"running",bootState:G().getBootState(),timestamp:new Date().toISOString(),uptime:process.uptime()}}).get("/live",()=>({status:"ok"})).get("/ready",async({set:Q})=>{let X=Z.serviceRegistry?.getService("agent","lifecycle")?.getState()??"running",J=G().getBootState(),W={};W.boot={ok:J==="ready",message:J==="ready"?void 0:`boot state ${J}`},W.lifecycle={ok:X==="running",message:X==="running"?void 0:`lifecycle ${X}`},W.db=await YQ(Z.getDb?.()??null,Z.getDbPath?.()??null),W.tunnel=Y4(Z.serviceRegistry,"tunnel"),W.session=Y4(Z.serviceRegistry,"session");try{let{gatewayClient:V}=await import("./gateway-client-43gzvj5s.js");if(!V.isConfigured())W.registration={ok:!0,message:"not configured"};else{let E=Z.getDb?.()??null;if(E?await E.getConfig("gateway-auth:agentRecordId"):null)W.registration={ok:!0};else{let h=G().getDegradedReasons().some((F)=>F.plugin==="agent-registration");W.registration=h?{ok:!1,message:"agent failed to register with the workspace after retries"}:{ok:!0,message:"registering"}}}}catch(V){W.registration={ok:!0,message:`registration check skipped: ${V instanceof Error?V.message:String(V)}`}}let H=await WQ(Z.getPluginManager?.()??null),B=Object.values(W).every((V)=>V.ok)&&Object.values(H).every((V)=>V.ok);if(!B)Q.status=503;let K=J==="degraded"?G().getDegradedReasons():[],N=G().name,I={};for(let V of a.list())I[V.name]={bootState:V.getBootState(),ok:V.getBootState()==="ready",degradedReasons:V.getDegradedReasons()};let C=G().getLastFinalizeError(),U={status:B?"ok":"degraded",lifecycleState:X,bootState:J,daemon:{profile:N,bootState:J,ok:J==="ready"},profiles:I,components:W,plugins:H,degradedReasons:K,lastFinalizeError:C,timestamp:new Date().toISOString()};if(!B)G().logger.warn("health","Readiness probe failed",{components:W,plugins:H,bootState:J});return U})}var u2=0,z4=0;function H4(){return new D({name:"inflight-tracker"}).onRequest(()=>{u2+=1}).onAfterResponse(()=>{u2=Math.max(0,u2-1),z4+=1})}function G4(){return new D({prefix:"/api/stats"}).get("/inflight",()=>({inflight:Math.max(0,u2-1),totalServed:z4}))}var G0=Object.freeze(["code","code-insiders","codium","cursor","idea","pycharm","webstorm","goland","phpstorm","rubymine","clion","rider","zed","subl","vim","nvim","emacs","neovide","fleet","helix"]),zQ=new Set(G0),HQ=new Set(["--new-window","-n","--reuse-window","-r","--wait","-w","--add","--goto"]);function B4($){try{return Bun.which($)??null}catch{return null}}function _4(){return new D({prefix:"/api/editor"}).get("/allowlist",()=>({commands:[...G0]})).get("/detect",async()=>{let $=G0.map((Y)=>[Y,B4(Y)]),Z=[],Q={};for(let[Y,X]of $)if(X)Z.push(Y),Q[Y]=X;return{available:Z,paths:Q}}).post("/open",async({body:$,set:Z})=>{let{command:Q,path:Y,args:X=[]}=$;if(!zQ.has(Q))return Z.status=400,{ok:!1,error:`Command '${Q}' is not in the IDE allowlist`};for(let H of X)if(typeof H!=="string"||!HQ.has(H))return Z.status=400,{ok:!1,error:`Argument '${H}' is not in the flag allowlist`};let J;try{J=(await V4(Y,{mustExist:!0})).realPath}catch(H){return Z.status=400,{ok:!1,error:`Invalid path: ${H instanceof Error?H.message:String(H)}`}}let W=B4(Q);if(!W)return Z.status=404,{ok:!1,error:`'${Q}' is not installed or not on PATH on this agent`};try{let H=K4({owner:`editor:${Q}`,cmd:[W,...X,J],env:process.env,stdout:"ignore",stderr:"ignore",stdin:"ignore",meta:{command:Q,path:J}});return G().logger.info("editor",`Launched ${Q} on ${J}`,{pid:H.pid}),G().audit.emit("agent","editor.open",{command:Q,path:J,pid:H.pid}),{ok:!0,command:Q,resolvedPath:J,pid:H.pid}}catch(H){return Z.status=500,{ok:!1,error:`Failed to spawn editor: ${H instanceof Error?H.message:String(H)}`}}},{body:z.Object({command:z.String({minLength:1,maxLength:40}),path:z.String({minLength:1,maxLength:4096}),args:z.Optional(z.Array(z.String({maxLength:32})))})})}var N4=Symbol.for("@vibecontrols/plugin-sdk:contextProviders@1");function GQ(){let $=globalThis,Z=$[N4];if(Z)return Z;let Q=new Map;return $[N4]=Q,Q}function B0(){return Array.from(GQ().values())}function F4(){return(b()??G()).dataDir}function n(){let $=s({dir:F4()});return{ownerUserId:$.ownerUserId,workspaceId:$.workspaceId}}function m2(){return s({dir:F4()}).agentRecordId}function L4($){if(!$)return null;try{return new URL($).host}catch{return null}}async function O4($,Z){let Q=$.getPluginManager(),Y=Q?Q.getPluginDetails().map((H)=>({pluginName:H.pluginName,packageName:H.packageName,version:H.version,tags:H.tags??[]})):[],X=process.memoryUsage(),J=L4($.getTunnelHost?.()??null),W;try{W=_2(n()).map((H)=>({id:H.id,label:H.label,host:L4(H.tunnelUrl),agentRecordId:H.agentRecordId??null,permissions:H.permissions,canForward:H.permissions.includes("mesh:forward"),lastReachable:H.lastReachable??null}))}catch{W=[]}return{pluginName:"agent",description:"vibecontrols-agent runtime self-report",generatedAt:new Date().toISOString(),data:{profile:Z.profile,vibeId:Z.vibeId??null,runtime:{bunVersion:typeof Bun<"u"?Bun.version:null,nodeVersion:process.versions.node??null,platform:process.platform,arch:process.arch,pid:process.pid,uptimeSeconds:Math.round(process.uptime()),memory:{rssMB:Math.round(X.rss/1048576),heapUsedMB:Math.round(X.heapUsed/1048576)}},agent:{version:$.getAgentVersion?.()??null,profileRegistered:E2(),tunnelHost:J},plugins:{count:Y.length,items:Y},mesh:{peerCount:W.length,peers:W}}}}var BQ=2000,j4=1000;async function VQ($,Z){let Q,Y=new Promise((X,J)=>{Q=setTimeout(()=>J(Error(`timeout after ${Z}ms`)),Z)});try{return await Promise.race([$,Y])}finally{if(Q)clearTimeout(Q)}}async function U4($,Z){let Q=performance.now(),Y=$.timeoutMs??BQ;try{let X=await VQ($.getContext(Z),Y);if(!X.generatedAt)X.generatedAt=new Date().toISOString();return{ok:!0,data:X,durationMs:Math.round(performance.now()-Q)}}catch(X){return{ok:!1,error:X.message??String(X),durationMs:Math.round(performance.now()-Q)}}}class V0{deps;inflight=new Map;constructor($){this.deps=$}async aggregate($){let Z=`${$.profile}::${$.vibeId??""}`,Q=this.inflight.get(Z);if(Q&&Date.now()-Q.ts<j4)return Q.promise;let Y=this.doAggregate($).finally(()=>{setTimeout(()=>{let X=this.inflight.get(Z);if(X&&X.promise===Y)this.inflight.delete(Z)},j4).unref?.()});return this.inflight.set(Z,{ts:Date.now(),promise:Y}),Y}async selfContext($){return O4(this.deps,$)}async pluginContext($,Z){let Q=B0().find((Y)=>Y.name===$);if(!Q)return null;return U4(Q,Z)}async pluginsContext($){let Z=B0(),Q=await Promise.allSettled(Z.map((X)=>U4(X,$))),Y={};return Z.forEach((X,J)=>{let W=Q[J];if(W&&W.status==="fulfilled")Y[X.name]=W.value;else if(W&&W.status==="rejected")Y[X.name]={ok:!1,error:W.reason instanceof Error?W.reason.message:String(W.reason),durationMs:0}}),Y}async doAggregate($){let[Z,Q]=await Promise.all([this.selfContext($),this.pluginsContext($)]);return{agent:Z,plugins:Q}}}function g2($){let Z=$.vibeId;if(typeof Z!=="string")return;let Q=Z.trim();return Q.length>0&&Q.length<=128?Q:void 0}function x4($){let Z=new V0($);return new D({prefix:"/api/agent/context"}).get("/",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=g2(Y);return Z.aggregate({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/agent",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=g2(Y);return Z.selfContext({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/plugins",async({params:Q,query:Y})=>{let X=Q?.profile??"default",J=g2(Y);return Z.pluginsContext({profile:X,vibeId:J})},{query:z.Object({vibeId:z.Optional(z.String())})}).get("/plugins/:name",async({params:Q,query:Y,set:X})=>{let J=Q?.profile??"default",W=Q?.name;if(!W)return X.status=400,{error:"missing plugin name"};let H=g2(Y),B=await Z.pluginContext(W,{profile:J,vibeId:H});if(!B)return X.status=404,{error:`no context provider registered under name "${W}"`};return B},{params:z.Object({name:z.String()}),query:z.Object({vibeId:z.Optional(z.String())})})}var Q2="autoupdate",KQ=86400000,M4=300000,_Q=900000,S={timer:null,running:!1,profile:"default",lastCheckAt:null,lastCheck:null,lastUpdateAt:null,lastUpdate:null,startedAt:null};function K0(){let $=(process.env.VIBE_AUTOUPDATE??"").trim().toLowerCase();return $==="0"||$==="false"||$==="off"||$==="no"}function E4(){if(K0())return!1;try{return s().autoUpdate!==!1}catch{return!0}}function _0(){let $=Number(process.env.VIBE_AUTOUPDATE_INTERVAL_MS);if(Number.isFinite($)&&$>0)return Math.max(_Q,$);return KQ}async function N0($){let Z=G().logger;if(S.running)return{check:S.lastCheck??await T4(),update:null};S.running=!0;try{let Q=await C2();if(S.lastCheck=Q,S.lastCheckAt=new Date().toISOString(),Q.error)Z.debug(Q2,`Update check failed: ${Q.error}`);else if(Q.hasUpdate)Z.info(Q2,`New agent version available: ${Q.current} \u2192 ${Q.latest}`);let Y=$?.force||E4();if(!Q.hasUpdate||!Y)return{check:Q,update:null};Z.info(Q2,`Auto-updating ${Q.current} \u2192 ${Q.latest} (idle-gated restart)\u2026`);let X=await p2({restart:!0,name:S.profile,onLog:(J)=>Z.info(Q2,J)});if(S.lastUpdate=X,S.lastUpdateAt=new Date().toISOString(),X.ok&&X.updated)Z.info(Q2,`Auto-update applied: now ${X.current} (restart: ${X.restart}).`);else if(!X.ok)Z.warn(Q2,`Auto-update failed: ${X.error}`);return{check:Q,update:X}}catch(Q){return Z.warn(Q2,`Auto-update tick threw: ${Q instanceof Error?Q.message:String(Q)}`),{check:await T4(),update:null}}finally{S.running=!1}}async function T4(){if(S.lastCheck)return S.lastCheck;let $=await C2();return S.lastCheck=$,S.lastCheckAt=new Date().toISOString(),$}function C4($){if(S.timer)clearTimeout(S.timer);S.timer=setTimeout(()=>{N0().finally(()=>{if(S.startedAt)C4(_0())})},$),S.timer.unref?.()}function NQ($){let Z=G().logger;if(S.profile=$?.profile||process.env.VIBECONTROLS_PROFILE||"default",S.startedAt=new Date().toISOString(),K0()){Z.info(Q2,"Autoupdate disabled via VIBE_AUTOUPDATE \u2014 not scheduling.");return}Z.info(Q2,`Autoupdate scheduled (first check in ${Math.round(M4/60000)}m, then every ${Math.round(_0()/3600000)}h).`),C4(M4)}function B7(){if(S.timer)clearTimeout(S.timer),S.timer=null;S.startedAt=null}function I4($){if(f2({autoUpdate:$}),$&&!S.startedAt)NQ({profile:S.profile})}function F0(){let $=!0;try{$=s().autoUpdate!==!1}catch{}return{enabled:E4(),envKillSwitch:K0(),configEnabled:$,scheduled:!!S.startedAt,intervalMs:_0(),profile:S.profile,startedAt:S.startedAt,lastCheckAt:S.lastCheckAt,lastCheck:S.lastCheck,lastUpdateAt:S.lastUpdateAt,lastUpdate:S.lastUpdate}}import{existsSync as q4}from"fs";import{join as R4}from"path";var FQ=600000,L0=1e6;function LQ(){let $=N2(),Z=$.which("bun")??`bun${$.executableSuffix}`,Q=R4(import.meta.dir,"cli.js");if(q4(Q))return{runner:Z,prefix:[Q]};let Y=R4(import.meta.dir,"..","cli.ts");if(q4(Y))return{runner:Z,prefix:[Y]};let X=$.which("vibe");if(X)return{runner:X,prefix:[]};return null}function A4($){if($.length<=L0)return $;return $.slice(0,L0)+`
|
|
4
|
-
\u2026[output truncated at ${L0} bytes]`}async function l2($,Z={}){let Q=LQ();if(!Q)return{ok:!1,exitCode:null,stdout:"",stderr:"Could not locate the vibe CLI to execute (no dist/cli.js, source, or PATH entry).",timedOut:!1,argv:$,command:"(unresolved)"};let Y=[...Q.prefix,...$],X=[Q.runner,...Y].join(" ");try{let J=Bun.spawn([Q.runner,...Y],{cwd:Z.cwd,env:{...process.env,VIBE_AUTO_ACCEPT:"1",CI:"1",NO_COLOR:"1",...Z.env},stdout:"pipe",stderr:"pipe"}),W=Z.timeoutMs??FQ,H=!1,B=setTimeout(()=>{H=!0;try{J.kill()}catch{}},W),[K,N,I]=await Promise.all([new Response(J.stdout).text(),new Response(J.stderr).text(),J.exited]);return clearTimeout(B),{ok:!H&&I===0,exitCode:I,stdout:A4(K),stderr:A4(N),timedOut:H,argv:$,command:X}}catch(J){return{ok:!1,exitCode:null,stdout:"",stderr:`Failed to spawn vibe CLI: ${J instanceof Error?J.message:String(J)}`,timedOut:!1,argv:$,command:X}}}async function w4(){let{Command:$}=await import("./esm-9fpye77x.js"),{registerCoreCommands:Z}=await import("./register-core-qrawzyym.js"),Q=new $;Q.name("vibe").option("--json").option("--plain").option("-y, --yes").option("-p, --profile <name>");try{Z(Q)}catch{}let Y=new Set(["nuke","kill","gc","stop","rollback","deploy"]),X=[];for(let J of Q.commands){let W=J.name();if(!W||W==="help")continue;X.push({name:W,description:J.description()||"",usage:J.usage()||"",options:J.options.map((H)=>({flags:H.flags,description:H.description||""})),group:"core",destructive:Y.has(W)})}return X.sort((J,W)=>J.name.localeCompare(W.name))}import{spawn as OQ}from"child_process";import{writeFileSync as jQ,mkdirSync as UQ}from"fs";import{tmpdir as xQ}from"os";import{join as k4}from"path";var MQ="@vibecontrols/agent";function S4($){let Z=N2(),Q=Z.which("bun")??`bun${Z.executableSuffix}`,Y=Z.which("npm")??`npm${Z.executableSuffix}`,X=d2(),J=$.delayMs??3000,W=$.pids.filter((B)=>Number.isInteger(B)&&B>0),H=`// vibecontrols agent self-uninstall reaper (auto-generated)
|
|
5
|
-
const PIDS = ${JSON.stringify(W)};
|
|
6
|
-
const NPM = ${JSON.stringify(Y)};
|
|
7
|
-
const BUN = ${JSON.stringify(Q)};
|
|
8
|
-
const REGISTRY = ${JSON.stringify(X)};
|
|
9
|
-
const PKG = ${JSON.stringify(MQ)};
|
|
10
|
-
await Bun.sleep(${J});
|
|
11
|
-
for (const pid of PIDS) {
|
|
12
|
-
try { process.kill(pid, "SIGTERM"); } catch {}
|
|
13
|
-
}
|
|
14
|
-
await Bun.sleep(2500);
|
|
15
|
-
for (const pid of PIDS) {
|
|
16
|
-
try { process.kill(pid, "SIGKILL"); } catch {}
|
|
17
|
-
}
|
|
18
|
-
try { Bun.spawnSync([NPM, "uninstall", "-g", PKG, "--registry=" + REGISTRY], { stdout: "inherit", stderr: "inherit" }); } catch {}
|
|
19
|
-
try { Bun.spawnSync([BUN, "remove", "-g", PKG], { stdout: "inherit", stderr: "inherit" }); } catch {}
|
|
20
|
-
`;try{let B=k4(xQ(),"vibecontrols-uninstall");UQ(B,{recursive:!0});let K=k4(B,`reaper-${process.pid}.ts`);return jQ(K,H,{encoding:"utf8"}),OQ(Q,[K],{detached:!0,stdio:"ignore",windowsHide:!0}).unref(),G().logger.info("self-uninstall",`Scheduled detached uninstall reaper (pids=${W.join(",")}) at ${K}`),{ok:!0,scriptPath:K}}catch(B){return{ok:!1,scriptPath:null,error:B instanceof Error?B.message:String(B)}}}var TQ=new Set(["db","plugins-registry","logs","binaries","subprocs"]);async function D4($){let Z=await w4();try{let Q=$.getPluginManager?.();if(Q){let Y=new Set(Z.map((X)=>X.name));for(let X of Q.getPluginDetails()){let J=X.cliCommand;if(J&&!Y.has(J))Y.add(J),Z.push({name:J,description:X.description||`${X.pluginName} plugin command`,usage:"",options:[],group:"plugin",destructive:!1})}}}catch{}return Z.sort((Q,Y)=>Q.name.localeCompare(Y.name))}function h4($={}){return new D({name:"agent-maintenance"}).get("/api/agent/update/check",async()=>{return await C2()}).get("/api/agent/update/status",()=>{return F0()}).post("/api/agent/update",async({body:Z})=>{return await p2({targetVersion:typeof Z?.version==="string"?Z.version:void 0,allowIncompatible:Z?.allowIncompatible===!0,restart:Z?.restart!==!1})},{body:z.Optional(z.Object({version:z.Optional(z.String()),allowIncompatible:z.Optional(z.Boolean()),restart:z.Optional(z.Boolean())}))}).post("/api/agent/update/config",({body:Z})=>{return I4(Z.enabled),{ok:!0,status:F0()}},{body:z.Object({enabled:z.Boolean()})}).post("/api/agent/update/check-now",async({body:Z})=>{return{ok:!0,...await N0({force:Z?.force===!0})}},{body:z.Optional(z.Object({force:z.Optional(z.Boolean())}))}).get("/api/agent/commands",async()=>{let Z=await D4($);return{commands:Z,count:Z.length}}).post("/api/agent/commands/run",async({body:Z,set:Q})=>{let Y=Array.isArray(Z?.argv)?Z.argv.filter((B)=>typeof B==="string"):[];if(Y.length===0)return Q.status=400,{ok:!1,error:"argv must be a non-empty string array"};let X=Y[0],J=await D4($),W=new Set(J.map((B)=>B.name));if(!W.has(X))return Q.status=400,{ok:!1,error:`Unknown or disallowed command: "${X}"`,allowed:[...W].sort()};return await l2(Y,{timeoutMs:typeof Z?.timeoutMs==="number"?Z.timeoutMs:void 0})},{body:z.Object({argv:z.Array(z.String()),timeoutMs:z.Optional(z.Number())})}).post("/api/agent/nuke",async({body:Z,set:Q})=>{let Y=["nuke"];if(Z?.all)Y.push("--all");if(Z?.removeConfig)Y.push("--remove-config");if(Z?.dryRun)Y.push("--dry-run");if(typeof Z?.removePlugins==="string"&&Z.removePlugins)Y.push("--remove-plugins",Z.removePlugins);if(typeof Z?.keep==="string"&&Z.keep){let W=Z.keep.split(",").map((H)=>H.trim()).filter((H)=>H&&!TQ.has(H));if(W.length>0)return Q.status=400,{ok:!1,error:`Invalid --keep value(s): ${W.join(", ")}`};Y.push("--keep",Z.keep)}Y.push("-y","--json");let X=await l2(Y),J=null;try{let W=X.stdout.trim().split(`
|
|
21
|
-
`).reverse().find((H)=>H.trim().startsWith("{"));if(W)J=JSON.parse(W)}catch{}return{...X,parsed:J}},{body:z.Optional(z.Object({all:z.Optional(z.Boolean()),removeConfig:z.Optional(z.Boolean()),removePlugins:z.Optional(z.String()),keep:z.Optional(z.String()),dryRun:z.Optional(z.Boolean())}))}).post("/api/agent/uninstall",async({body:Z})=>{let Q=Z?.dryRun===!0,Y=["nuke","--all","--remove-config","-y","--json"];if(Q)Y.push("--dry-run");let X=await l2(Y);if(Q)return{ok:X.ok,dryRun:!0,nuke:X,note:"Dry run \u2014 would nuke all state and uninstall @vibecontrols/agent."};let J=new Set([process.pid]);try{let H=new b2;for(let B of await H.listInstances())if(typeof B.pid==="number"&&B.pid>0)J.add(B.pid)}catch{}let W=S4({pids:[...J]});return{ok:X.ok&&W.ok,nuke:X,uninstallScheduled:W.ok,scriptPath:W.scriptPath,...W.error?{error:W.error}:{},note:"Agent state nuked; package self-uninstall scheduled \u2014 the daemon will stop and `@vibecontrols/agent` will be removed shortly."}},{body:z.Optional(z.Object({dryRun:z.Optional(z.Boolean())}))})}import{existsSync as RQ,readFileSync as AQ}from"fs";import{join as wQ}from"path";var EQ=`mutation AddAgentFromTunnel($input: AddAgentFromTunnelInput!) {
|
|
22
|
-
addVibecontrolsAgentFromTunnel(input: $input) { agent { id name } clientId success error }
|
|
23
|
-
}`,CQ=`mutation ReportAgentMeshLink($input: ReportAgentMeshLinkInput!) {
|
|
24
|
-
reportAgentMeshLink(input: $input) { id }
|
|
25
|
-
}`,v4="VIBE_BOOTSTRAP_JSON=";function IQ($){for(let Y of $.split(/\r?\n/)){let X=Y.indexOf(v4);if(X>=0)try{return JSON.parse(Y.slice(X+v4.length))}catch{}}let Z=$.indexOf("{"),Q=$.lastIndexOf("}");if(Z>=0&&Q>Z)try{return JSON.parse($.slice(Z,Q+1))}catch{return null}return null}async function b4($,Z){let Q=(N,I,C)=>Z?.({step:N,status:I,message:C}),Y=f4($.permissions??["tunnel:read","session:list","plugin:list","diagnostics:read","mesh:forward"]);if(!Y.includes("mesh:forward"))Y.push("mesh:forward");let X=(N)=>({ok:!1,peerId:"",agentRecordId:null,tunnelUrl:null,permissions:Y,error:N}),J;try{J=i2($.target,{identityFile:$.identityFile})}catch(N){return X(N instanceof Error?N.message:String(N))}let W=$.label??J.id,H=Y.join(","),B,K='export PATH="$HOME/.bun/bin:$PATH"; ';try{if(!$.connectExisting){Q("probe","running");let x=await J.probe();if(Q("probe","completed",`os=${x.os??"?"} arch=${x.arch??"?"}`),!x.npm&&!x.bun){if($.installBun===!1)return X("Neither npm nor bun present and Bun install was disabled.");Q("install-bun","running");let z2=await J.run(["sh","-c",`curl -fsSL https://bun.sh/install | bash && echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc`],{timeoutMs:300000});if(z2.code!==0)return Q("install-bun","failed",z2.stderr.slice(0,400)),X("Bun auto-install failed.");let F2=await J.run(["sh","-c","$HOME/.bun/bin/bun --version 2>/dev/null"],{timeoutMs:1e4});if(F2.code===0&&F2.stdout.trim())x.bun="$HOME/.bun/bin/bun",Q("install-bun","completed",F2.stdout.trim());else return X("Bun installed but the binary is not reachable.")}Q("install-agent","running");let R=$.version??"latest",u=$.registry??"https://registry.npmjs.org/",y=x.npm?"npm":"bun",W2=await J.run(y==="npm"?["npm","install","-g",`@vibecontrols/agent@${R}`,`--registry=${u}`]:["sh","-c",`export PATH="$HOME/.bun/bin:$PATH"; bun install -g @vibecontrols/agent@${R} --no-cache`],{timeoutMs:600000});if(W2.code!==0)return Q("install-agent","failed",W2.stderr.slice(0,400)),X(`Agent install failed (exit ${W2.code}).`);if(B=(await J.run(["sh","-c",`${K}vibe --version`],{timeoutMs:15000})).stdout.trim()||void 0,Q("install-agent","completed",B),$.autostart)Q("autostart","running"),await J.run(["sh","-c",`${K}vibe autostart install`],{timeoutMs:60000}),Q("autostart","completed");if($.installPlugins?.length){Q("plugins","running");for(let z2 of $.installPlugins)await J.run(["sh","-c",`${K}vibe plugin install ${z2}`],{timeoutMs:300000});Q("plugins","completed")}Q("start","running"),await J.run(["sh","-c",`${K}vibe start`],{timeoutMs:60000}),Q("start","completed")}Q("bootstrap","running");let N=$.expiresIn?` --expires-in ${$.expiresIn}`:"",I=W.replace(/'/g,""),C=null;for(let x=0;x<15;x++){let R=`${K}vibe peer-bootstrap --json --emit-default-key --label '${I}' --scope ${H}${N} 2>/dev/null`,u=await J.run(["sh","-c",R],{timeoutMs:15000});if(u.code===0){let y=IQ(u.stdout);if(y&&typeof y.apiKey==="string"){C=y;break}}await new Promise((y)=>setTimeout(y,2000))}if(!C)return Q("bootstrap","failed","could not obtain peer-bootstrap bundle"),X("Remote peer-bootstrap did not return a credential bundle.");Q("bootstrap","completed");let U=n(),V=String(C.id),E=String(C.apiKey),q=n2(typeof C.tunnelUrl==="string"?C.tunnelUrl:null),h=typeof C.agentRecordId==="string"?C.agentRecordId:null;if($.onboardBackend!==!1&&g.isConfigured()&&q&&typeof C.fullDefaultApiKey==="string"){Q("onboard","running");try{let R=(await g.workspaceQuery(EQ,{input:{tunnelUrl:q,apiKey:C.fullDefaultApiKey,name:W}})).data?.addVibecontrolsAgentFromTunnel;if(R?.agent?.id)h=R.agent.id,Q("onboard","completed",`agent ${h}`);else Q("onboard","failed",R?.error??"no agent returned")}catch(x){Q("onboard","failed",x instanceof Error?x.message:String(x))}}else Q("onboard","skipped");Q("store-creds","running"),P4({id:V,label:W,tunnelUrl:q??"",apiKey:E,permissions:Y,addedAt:new Date().toISOString(),agentRecordId:h??void 0,workspaceId:(typeof C.workspaceId==="string"?C.workspaceId:U.workspaceId)??void 0,fingerprint:V,ownerUserId:U.ownerUserId,sshTarget:J.mode==="ssh"?$.target:void 0,sshIdentityFile:$.identityFile}),Q("store-creds","completed");let F=m2();if($.onboardBackend!==!1&&g.isConfigured()&&F&&h){Q("report-link","running");try{await g.workspaceQuery(CQ,{input:{sourceAgentRecordId:F,destinationAgentRecordId:h,label:W}}),Q("report-link","completed")}catch(x){Q("report-link","failed",x instanceof Error?x.message:String(x))}}else Q("report-link","skipped");let T=await I2(V,"/api/profiles/default/agent/identity",{operation:"post-deploy-probe"});return Q("probe-peer",T.ok?"completed":"failed",T.error??void 0),{ok:!0,peerId:V,agentRecordId:h,tunnelUrl:q,permissions:Y,remoteVersion:B}}catch(N){return X(N instanceof Error?N.message:String(N))}finally{await J.close().catch(()=>{})}}var O0='export PATH="$HOME/.bun/bin:$PATH"; ';function qQ($){let Z=$.indexOf("{"),Q=$.lastIndexOf("}");if(Z>=0&&Q>Z)try{let Y=JSON.parse($.slice(Z,Q+1));if(Y.tunnelUrl)return Y.tunnelUrl;if(Y.url&&Y.url.startsWith("https"))return Y.url}catch{}return null}async function u4($,Z){let Q=(J,W,H)=>Z?.({step:J,status:W,message:H}),Y=y4($);if(!Y)return{ok:!1,peerId:$,tunnelUrl:null,error:`No peer with id ${$}`};if(!Y.sshTarget)return{ok:!1,peerId:$,tunnelUrl:null,error:"No SSH target stored for this peer \u2014 it wasn't SSH-deployed, so it can't be woken via SSH."};let X;try{X=i2(Y.sshTarget,{identityFile:Y.sshIdentityFile})}catch(J){return{ok:!1,peerId:$,tunnelUrl:null,error:J instanceof Error?J.message:String(J)}}try{Q("ssh-restart","running",Y.sshTarget);let J=await X.run(["sh","-c",`${O0}vibe restart 2>/dev/null || ${O0}vibe start`],{timeoutMs:90000});if(J.code!==0)return Q("ssh-restart","failed",J.stderr.slice(0,300)),{ok:!1,peerId:$,tunnelUrl:null,error:`Remote restart failed (exit ${J.code})`};Q("ssh-restart","completed"),Q("await-tunnel","running");let W=null;for(let H=0;H<15;H++){let B=await X.run(["sh","-c",`${O0}vibe url --json 2>/dev/null`],{timeoutMs:15000});if(B.code===0){let K=qQ(B.stdout),N=n2(K);if(N){W=N;break}}await new Promise((K)=>setTimeout(K,2000))}if(!W)return Q("await-tunnel","failed","no fresh tunnel after restart"),{ok:!1,peerId:$,tunnelUrl:null,error:"Agent restarted but no fresh tunnel came up."};return Q("await-tunnel","completed",W),c4($,{tunnelUrl:W,lastReachable:new Date().toISOString()}),Q("update","completed"),{ok:!0,peerId:$,tunnelUrl:W}}catch(J){return{ok:!1,peerId:$,tunnelUrl:null,error:J instanceof Error?J.message:String(J)}}finally{await X.close().catch(()=>{})}}var kQ=Number(process.env.VIBECONTROLS_MESH_MAX_HOPS||"8");function m4(){return(b()??G()).name}function SQ(){return(b()??G()).dataDir}function g4(){try{let Z=wQ(SQ(),"runtime.json");if(RQ(Z)){let Q=JSON.parse(AQ(Z,"utf8"));if(Q.port&&Number.isInteger(Q.port))return Q.port}}catch{}let $=Number(process.env.PORT);return Number.isInteger($)&&$>0?$:3005}function DQ($){let Z={};return $.headers.forEach((Q,Y)=>{Z[Y]=Q}),Z}function Z2($,Z){let Q=m(DQ($));return d4(l4(Q),Z)}function hQ($){let{apiKey:Z,...Q}=$;return{...Q,apiKey:"[REDACTED]"}}function p4($){return typeof $==="string"&&$.startsWith("/api/")&&!$.includes("..")&&!$.includes("//")}var o2=new Map;function vQ(){let $=Date.now()-3600000;for(let[Z,Q]of o2)if(Q.completedAt&&Date.parse(Q.completedAt)<$)o2.delete(Z)}function i4(){return new D({name:"agent-mesh"}).get("/api/mesh/peers",({request:$,set:Z})=>{if(!Z2($,["read"]))return Z.status=403,{error:"forbidden"};return{peers:_2(n()).map(hQ)}}).delete("/api/mesh/peers/:id",({request:$,set:Z,params:Q})=>{if(!Z2($,["mutate"]))return Z.status=403,{error:"forbidden"};if(!_2(n()).some((X)=>X.id===Q.id))return Z.status=404,{error:"not found"};return{ok:n4(Q.id)}}).post("/api/mesh/peers/:id/call",async({request:$,set:Z,params:Q,body:Y})=>{if(!Z2($,["mesh:forward"]))return Z.status=403,{error:"forbidden"};let X=Y;if(!p4(X.path))return Z.status=400,{error:"invalid path"};if(!_2(n()).find((H)=>H.id===Q.id))return Z.status=404,{error:"not found"};let W=await I2(Q.id,X.path,{method:X.method??"GET",body:X.body,operation:"mesh-call"});return{ok:W.ok,status:W.status,data:W.data,rotated:W.rotated,error:W.error}},{body:z.Object({method:z.Optional(z.String()),path:z.String(),body:z.Optional(z.Any())})}).post("/api/mesh/forward",async({request:$,set:Z,body:Q})=>{if(!Z2($,["mesh:forward"]))return Z.status=403,{error:"forbidden"};let Y=Q;if(!Y.request||!p4(Y.request.path))return Z.status=400,{error:"invalid request"};let X=(Y._hopCount??0)+1;if(X>kQ)return Z.status=422,{error:"hop limit exceeded"};let J=n(),W=m2(),H=Y.hops??[];if(H.length===0){G().audit.emit("mesh","forward.terminal",{path:Y.request.path,method:Y.request.method??"GET"});let U=(Y.request.method??"GET").toUpperCase();try{let V=await fetch(`http://127.0.0.1:${g4()}${Y.request.path}`,{method:U,headers:{"x-agent-api-key":await j0(),...Y.request.body!==void 0?{"content-type":"application/json"}:{}},body:Y.request.body!==void 0?JSON.stringify(Y.request.body):void 0,signal:AbortSignal.timeout(60000)}),E=await V.text().catch(()=>""),q=null;try{q=E?JSON.parse(E):null}catch{q=null}return{ok:V.ok,status:V.status,data:q,text:E||null,error:V.ok?null:E||`status ${V.status}`}}catch(V){return Z.status=502,{ok:!1,status:0,error:V instanceof Error?V.message:String(V)}}}let B=H[0],K=Y._traversed??[];if(B===W||K.includes(B))return Z.status=422,{error:"cycle detected",at:B};let N=U0(B,J);if(!N)return Z.status=403,{error:"next hop not in authorized boundary"};if(!N.permissions.includes("mesh:forward"))return Z.status=403,{error:"peer lacks mesh:forward grant"};G().audit.emit("mesh","forward.hop",{nextId:B,remaining:H.length,hopCount:X});let I=encodeURIComponent(m4()),C=await I2(N.id,`/api/profiles/${I}/mesh/forward`,{method:"POST",operation:"mesh-forward",timeoutMs:60000,body:{hops:H.slice(1),request:Y.request,_traversed:[...K,W??"self"],_hopCount:X}});if(!C.ok)return Z.status=502,{ok:!1,status:C.status,error:C.error,failedAtHop:B};return C.data},{body:z.Object({hops:z.Optional(z.Array(z.String())),request:z.Object({method:z.Optional(z.String()),path:z.String(),body:z.Optional(z.Any())}),_traversed:z.Optional(z.Array(z.String())),_hopCount:z.Optional(z.Number())})}).post("/api/mesh/deploy",({request:$,set:Z,body:Q})=>{if(!Z2($,["admin"]))return Z.status=403,{error:"forbidden"};vQ();let Y=Q,X=n(),J=crypto.randomUUID(),W={id:J,status:"running",steps:[],ownerUserId:X.ownerUserId,workspaceId:X.workspaceId,startedAt:new Date().toISOString()};return o2.set(J,W),b4({target:Y.target,permissions:Y.permissions,installPlugins:Y.installPlugins,autostart:Y.autostart,identityFile:Y.identityFile,label:Y.label,version:Y.version,connectExisting:Y.connectExisting},(H)=>{W.steps.push(H),J2("mesh:deploy:progress",{jobId:J,step:H})}).then((H)=>{if(W.result=H,W.status=H.ok?"completed":"failed",!H.ok)W.error=H.error;W.completedAt=new Date().toISOString(),J2(H.ok?"mesh:deploy:complete":"mesh:deploy:failed",{jobId:J,result:H})}).catch((H)=>{W.status="failed",W.error=H instanceof Error?H.message:String(H),W.completedAt=new Date().toISOString(),J2("mesh:deploy:failed",{jobId:J,error:W.error})}),Z.status=202,{jobId:J,status:"running"}},{body:z.Object({target:z.String(),permissions:z.Optional(z.Array(z.String())),installPlugins:z.Optional(z.Array(z.String())),autostart:z.Optional(z.Boolean()),identityFile:z.Optional(z.String()),label:z.Optional(z.String()),version:z.Optional(z.String()),connectExisting:z.Optional(z.Boolean())})}).get("/api/mesh/deploy/jobs/:id",({request:$,set:Z,params:Q})=>{if(!Z2($,["read"]))return Z.status=403,{error:"forbidden"};let Y=o2.get(Q.id),X=n();if(!Y||X.ownerUserId&&Y.ownerUserId&&Y.ownerUserId!==X.ownerUserId)return Z.status=404,{error:"not found"};return Y}).post("/api/mesh/wake",async({request:$,set:Z,body:Q})=>{if(!Z2($,["admin"]))return Z.status=403,{error:"forbidden"};let Y=Q,X=U0(Y.targetAgentRecordId,n());if(!X)return Z.status=404,{ok:!1,error:"peer not in authorized boundary"};G().audit.emit("mesh","wake.start",{peerId:X.id,agentRecordId:Y.targetAgentRecordId});let J=await u4(X.id,(W)=>J2("mesh:wake:progress",{peerId:X.id,step:W}));if(!J.ok)Z.status=502;return J},{body:z.Object({targetAgentRecordId:z.String()})}).post("/api/mesh/session",async({request:$,set:Z,body:Q})=>{if(!Z2($,["mesh:forward","mutate"]))return Z.status=403,{error:"forbidden"};let Y=Q,X=Y.sessionId&&/^[A-Za-z0-9_-]{1,128}$/.test(Y.sessionId)?Y.sessionId:crypto.randomUUID(),J=encodeURIComponent(m4()),W=await j0(),H=`http://127.0.0.1:${g4()}`,B=Y.command||"bash";try{let K=await fetch(`${H}/api/profiles/${J}/sessions/create`,{method:"POST",headers:{"x-agent-api-key":W,"content-type":"application/json"},body:JSON.stringify({sessionId:X,sessionName:`vc-mesh-${X.slice(0,8)}`,command:B,provider:"TERMINAL",...Y.vibeId?{projectId:Y.vibeId}:{}}),signal:AbortSignal.timeout(20000)});if(!K.ok)return Z.status=502,{error:`session create returned ${K.status}: ${await K.text().catch(()=>"")}`};let N=await fetch(`${H}/api/profiles/${J}/sessions/${encodeURIComponent(X)}/terminal`,{method:"POST",headers:{"x-agent-api-key":W},signal:AbortSignal.timeout(20000)});if(!N.ok)return Z.status=502,{error:`terminal start returned ${N.status}: ${await N.text().catch(()=>"")}`};let I=h2(`/terminal/${X}`,600);return G().audit.emit("mesh","session.created",{sessionId:X,kind:Y.kind??"TERMINAL"}),{connectionId:X,sessionId:X,capabilityToken:I.token,expiresAt:I.expiresAt}}catch(K){return Z.status=502,{error:K instanceof Error?K.message:String(K)}}},{body:z.Object({sessionId:z.Optional(z.String()),kind:z.Optional(z.String()),cwd:z.Optional(z.String()),vibeId:z.Optional(z.String()),command:z.Optional(z.String())})})}var PQ=["/health","/api/agent/status","/api/agent/version","/api/agent/identity","/api/agent/api-key","/api/agent/tunnel","/api/agent/system","/api/agent/gateway-auth","/api/stats","/metrics","/api/profiles","/api/profile-stats"];function fQ($){return PQ.some((Z)=>$.startsWith(Z))}var bQ=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function yQ($){return $.split("/").map((Z)=>{if(!Z)return Z;if(/^\d+$/.test(Z))return":id";if(bQ.test(Z))return":id";if(Z.length>=24&&/^[A-Za-z0-9_-]+$/.test(Z))return":id";return Z}).join("/")}async function l8($){let{port:Z,host:Q,dbPath:Y,logLevel:X,corsOrigin:J}=$,W=Y??T2();try{(await import("fs")).mkdirSync(W,{recursive:!0})}catch(_){throw G().logger.error("app","Failed to create dbPath dir at boot",{dbPath:W,error:String(_)}),Error(`Cannot create dbPath ${W}: ${_ instanceof Error?_.message:String(_)}`,{cause:_})}if(X)G().logger.setLevel(X);(async()=>{let{logShipper:_}=await import("./log-shipper-k24m8yw5.js");_.init()})(),(async()=>{let _=await a4();await k2({version:_,profile:E2()})})();try{let{checkDependencies:_}=await import("./bootstrap.service-pjmnpxha.js"),M=_(),O=M.filter((A)=>A.required&&!A.installed),w=M.filter((A)=>!A.required&&!A.installed);if(O.length>0)G().logger.error("app",`Missing required system deps: ${O.map((A)=>A.name).join(", ")}. Run \`vibe setup\` to install.`);if(w.length>0)G().logger.warn("app",`Missing optional system deps: ${w.map((A)=>A.name).join(", ")}. Some plugins may fail their prereqs check.`)}catch(_){G().logger.warn("app","Boot-time dependency check failed",{error:String(_)})}try{G().audit.runRetention()}catch(_){G().logger.warn("app","Audit-log retention sweep failed",{error:String(_)})}let H=new F5;I5(H,{port:Z});let B="GET, POST, PUT, PATCH, DELETE, OPTIONS",K="Content-Type, x-agent-api-key, Authorization, x-requested-with",N=Array.isArray(J)?J:(J??"").split(",").map((_)=>_.trim()).filter(Boolean),I=new Set(["https://vibecontrols.com","https://app.vibecontrols.com","https://alphaapp.vibecontrols.com","https://burdenoff.com","https://app.burdenoff.com","https://alphaapp.burdenoff.com"]),C=(_)=>{try{let M=new URL(_);if(N.includes(_))return!0;if(N.includes("*"))return!1;return M.hostname==="localhost"||M.hostname==="127.0.0.1"||M.hostname==="0.0.0.0"||M.hostname.endsWith(".local.burdenoff.com")||I.has(M.origin)}catch{return!1}},U=null,V=null,E=null,q=null,h=!1,F=()=>[],T=null,x=null,R=null,u=5000,y=async(_,M)=>{let O=Date.now();try{await Promise.race([Promise.resolve(M()),new Promise((w,A)=>setTimeout(()=>A(Error(`shutdown phase ${_} exceeded ${u}ms`)),u))]),G().logger.info("app",`shutdown.phase ${_} complete`,{ms:Date.now()-O})}catch(w){G().logger.warn("app",`shutdown.phase ${_} failed`,{error:String(w),ms:Date.now()-O})}},W2=async(_)=>{if(h)return;if(h=!0,G().logger.info("app","Agent shutdown starting",{reason:_?.reason??"shutdown"}),await y("plugins",async()=>{if(V)await V.dispatchServerStop(_)}),await y("bootstrap-tunnel",()=>E0()),await y("tracked-subprocesses",async()=>{let{killAllTracked:M}=await import("./subprocess-g9sk1ep9.js");await M()}),_?.reason!=="reload")await y("db-close",async()=>{if(U)await U.close()});await y("http-listener",async()=>{try{await Promise.resolve(r.stop())}catch(M){G().logger.warn("app","Listener stop threw (already stopped or never started?)",{error:String(M)})}}),G().logger.info("app","Agent server stopped"),G().logger.close()},a2=async(_,M)=>{if(G().getBootState()==="ready")return{ok:!0};if(R)return R;return R=(async()=>{G().setBootState("initializing");try{let O={..._,globalGatewayUrl:B2(_.globalGatewayUrl,"globalGatewayUrl"),workspaceGatewayUrl:B2(_.workspaceGatewayUrl,"workspaceGatewayUrl")},w=await O5(O),A=W,v=s({dir:G().dataDir}),p=v.storageAdapter??process.env.VIBE_STORAGE_ADAPTER??void 0,i=v.storageOptions,t=(L)=>{let j=(L instanceof Error?L.message:String(L)).toLowerCase(),k=L&&typeof L==="object"&&"code"in L?String(L.code).toUpperCase():"";if(k==="EBUSY"||k==="EPERM"||k==="EACCES"||k==="EAGAIN"||k==="EMFILE"||k==="ENFILE"||k==="ETIMEDOUT"||k==="ECONNRESET"||k==="ECONNREFUSED"||j.includes("encryption key")||j.includes("fetch")&&j.includes("key")||j.includes("temporarily unavailable")||j.includes("resource busy"))return"transient";if(j.includes("auth tag")||j.includes("authentication tag")||j.includes("unable to authenticate data")||j.includes("bad decrypt")||j.includes("unsupported state")||j.includes("incorrect header check")||j.includes("invalid distance")||j.includes("incorrect data check")||j.includes("unexpected end of")||j.includes("unexpected token")||j.includes("json")&&(j.includes("parse")||j.includes("invalid"))||j.includes("truncated")||j.includes("malformed")||j.includes("corrupt"))return"corruption";return"unknown"},L2=()=>s4({dbPath:A,encryptionKey:w,adapterName:p,adapterOptions:i});try{U=await L2()}catch(L){let j=L,k=t(L),R2=[500,2000,8000];if(k==="transient"||k==="unknown"){G().logger.warn("app",`Storage open failed (${k}); will retry up to ${R2.length} times before quarantine`,{error:L instanceof Error?L.message:String(L),path:A});for(let U2 of R2){await new Promise((P)=>setTimeout(P,U2));try{U=await L2(),j=null;break}catch(P){if(j=P,k=t(P),G().logger.warn("app",`Storage open retry failed (${k}) after ${U2}ms`,{error:P instanceof Error?P.message:String(P)}),k==="corruption")break}}}if(!U&&j){if(k!=="corruption"){let P=j instanceof Error?j.message:String(j);G().logger.error("app",`Storage open failed after retries with non-corruption error (${k}); refusing to quarantine valid data`,{error:P,path:A}),G().recordDegradedReason("storage",P);try{throw j}catch(G2){throw Error(`Storage open failed (${k}); agent is degraded: ${P}`,{cause:G2})}}let U2=j instanceof Error?j.message:String(j);G().logger.error("app","QUARANTINE: Storage file is corrupt \u2014 renaming and creating fresh DB",{errorClass:"corruption",error:U2,path:A});try{let P=await import("fs");if(P.existsSync(A)){let G2=new Date().toISOString().replace(/[:.]/g,"-"),R0=`${A}.broken-${G2}`;P.renameSync(A,R0),G().logger.warn("app",`Quarantined corrupt storage to ${R0} \u2014 fresh DB will be created`,{originalError:U2})}U=await L2()}catch(P){let G2=P instanceof Error?P.message:String(P);throw G().recordDegradedReason("storage",G2),Error(`Storage open failed twice (quarantine path); agent is degraded: ${G2}`,{cause:P})}}}if(!U)throw Error("Internal error: storage open recovery exited without an open database and without throwing");if(await D2({clientId:O.clientId,clientSecret:O.clientSecret,workspaceId:O.workspaceId,organizationId:O.organizationId,globalGatewayUrl:O.globalGatewayUrl,workspaceGatewayUrl:O.workspaceGatewayUrl,agentRecordId:M?.agentRecordId,scopes:M?.scopes},{dir:G().dataDir,scope:G().name}),await U.setConfig("gateway-auth:clientId",O.clientId),await U.setConfig("gateway-auth:clientSecret",O.clientSecret),await U.setConfig("gateway-auth:globalGatewayUrl",O.globalGatewayUrl),await U.setConfig("gateway-auth:workspaceGatewayUrl",O.workspaceGatewayUrl),await U.setConfig("gateway-auth:workspaceId",O.workspaceId),O.organizationId)await U.setConfig("gateway-auth:organizationId",O.organizationId);if(M?.agentRecordId)await U.setConfig("gateway-auth:agentRecordId",M.agentRecordId);H.db=U,await H.hydrateDefaultsFromDb(),V=new T5(U),await V.loadCorePlugins();try{await V.loadAll()}catch(L){G().logger.warn("app","Failed to load some external plugins",{error:String(L)})}let O2=E5(K2())??void 0,j2=process.env.VIBE_SKIP_AUTO_INSTALL==="1"||await U.getConfig("plugins:auto-install-disabled");if(j2!=="true"&&j2!==!0)try{let L=await V.ensureDefaultPlugins((j)=>G().logger.info("app",`[auto-install] ${j}`),[],O2);if(L.length>0)G().logger.info("app",`Auto-installed ${L.length} default plugin(s): ${L.map((j)=>j.packageName).join(", ")}`)}catch(L){G().logger.warn("app","Failed to auto-install default plugins",{error:String(L)})}G().logger.info("app",`Plugins loaded: ${V.getPluginDetails().length} total (${V.getPluginDetails().filter((L)=>L.isCore).length} core)`);try{let L=V.getPluginDetails(),j={loaded:L.filter((k)=>k.loaded).length,failed:L.filter((k)=>!k.loaded).length};f0(j)}catch{}let r2={async get(L,j){return await U.getPluginState(L,j)??null},async set(L,j,k){await U.setPluginState(L,j,k)},async delete(L,j){return U.deletePluginState(L,j)},async list(L){return await U.getAllPluginState(L)},async deleteAll(L){return U.deleteAllPluginState(L)}},q2=await a4();E={storage:r2,logger:G().logger,serviceRegistry:H,getProvider:(L)=>H.getProvider(L),getAgentBaseUrl:()=>process.env.AGENT_URL||`http://localhost:${Z}`,getAgentVersion:()=>q2,validateApiKey:(L)=>l(L),setCodeServerSessionValidator:(L)=>{q5=L},broadcast:J2,workspaceQuery:async(L,j)=>g.workspaceQuery(L,j),isGatewayConfigured:()=>g.isConfigured(),getAgentRecordId:async()=>await U.getConfig("gateway-auth:agentRecordId")??null,getWorkspaceId:async()=>await U.getConfig("gateway-auth:workspaceId")??null,getConfig:async(L)=>await U.getConfig(L)??void 0,getPluginRegistry:()=>d2(),getDataDir:()=>S2(),cliContributors:new L5,audit:{emit:(L,j)=>G().audit.emit("agent",L,j??{})},telemetry:{emit:(L,j)=>{import("./telemetry-tnq47dcs.js").then(({telemetryService:k})=>k.emit(L,j??{})).catch(()=>{})}},os:N2(),iframeBridge:M5()},g.configure({globalGatewayUrl:O.globalGatewayUrl,workspaceGatewayUrl:O.workspaceGatewayUrl,clientId:O.clientId,clientSecret:O.clientSecret,workspaceId:O.workspaceId,organizationId:O.organizationId});let H2={db:U,serviceRegistry:H,pluginManager:V,broadcast:J2,hostServices:E};H2.app=r;let q0=!1,t2=()=>{let{routes:L,getPublicPaths:j,mountPlugin:k}=Q5(V,H2);if(H2.mountPlugin=k,F=j,X5(),T=L,x=x5(V),V&&q0&&E)V.dispatchServerStart(T,E).catch((R2)=>G().logger.warn("app","Re-dispatch of onServerStart after plugin reload failed",{error:String(R2)}));q0=!0};H2.rebuildPluginSurfaces=t2,t2(),q=new j5(H,V,U,r,E,W2),H.registerService("agent","lifecycle",q),G().attachServices({db:U,serviceRegistry:H,pluginManager:V,lifecycle:q,hostServices:E}),_5(G(),{rebuildPluginSurfaces:t2,mountPlugin:H2.mountPlugin});try{await G().keyVault.bindApiKey(M2())}catch(L){G().logger.warn("app","Failed to bind api key into daemon keyVault",{error:String(L)})}let e2=[];try{let{failures:L}=await V.dispatchServerStart(T,E);for(let j of L)if(T0(j.plugin)||(j.packageName?T0(j.packageName):!1))e2.push(j),G().recordDegradedReason(j.plugin,j.error);else G().logger.warn("app",`Non-critical plugin ${j.plugin} failed onServerStart; continuing`,{error:j.error})}catch(L){G().logger.warn("app","Error during plugin onServerStart dispatch",{error:String(L)})}try{await V.dispatchServerReady(r,E)}catch(L){G().logger.warn("app","Error during plugin onServerReady dispatch",{error:String(L)})}if(G().clearFinalizeError(),e2.length>0)G().setBootState("degraded"),G().logger.error("app","Agent finalized but degraded \u2014 critical plugins failed",{failures:e2.map((L)=>`${L.plugin}: ${L.error}`)});else G().setBootState("ready"),G().logger.info("app","Agent finalized \u2014 state=ready"),G().audit.emit("agent","gateway-auth.configured",{workspaceId:O.workspaceId,organizationId:O.organizationId,agentRecordId:M?.agentRecordId});return(async()=>{try{if(await V.provisionDefaultPrereqs(r,E,H2.mountPlugin,O2),G().logger.info("app","Default provider prerequisites provisioned"),(H.listProvidersForType("tunnel")??[]).some((k)=>k.pluginName!=="bootstrap")){let{tryHandoverBootstrapTunnel:k}=await import("./tunnel-bootstrap-2kg79ng8.js");if(!k())E0();H.unregisterProvider("tunnel","bootstrap"),G().logger.info("app","Bootstrap tunnel handed over to the real tunnel provider")}}catch(L){G().logger.warn("app","Plugin prerequisite provisioning failed",{error:String(L)})}})(),{ok:!0}}catch(O){G().setBootState("awaiting-config");let w=O instanceof Error?O.message:String(O);if(G().recordFinalizeError(w),G().logger.error("app","Finalize failed",{error:w}),process.env.VIBE_STRICT_KEY_FETCH==="1")G().logger.error("app","VIBE_STRICT_KEY_FETCH=1 \u2192 aborting daemon (strict mode)",{error:w}),setTimeout(()=>process.exit(1),50);return{ok:!1,error:w}}finally{R=null}})(),R},z2=w0({origin:(_)=>{let M=_.headers.get("origin");return!!M&&C(M)},credentials:!0,allowedHeaders:K.split(",").map((_)=>_.trim()),methods:B.split(",").map((_)=>_.trim()),exposeHeaders:["content-type","content-length"],maxAge:86400,preflight:!0}),F2=10485760,C0=process.env.VIBECONTROLS_MAX_BODY_BYTES,s2=C0?Number.parseInt(C0,10):NaN,R5=Number.isFinite(s2)&&s2>0?s2:F2,I0={current:null},r=new D({serve:{maxRequestBodySize:R5}}).onRequest(({request:_,set:M})=>{let w=r4(_.headers)??x0();t4({requestId:w,startedAt:new Date().toISOString()});let A=M.headers??={};A["X-Request-Id"]=w}).onRequest(({request:_})=>{try{let M=new URL(_.url).pathname,w=/^\/api\/profiles\/([^/]+)(?:\/|$)/.exec(M)?.[1],A=w?a.get(w):null;M0(A??G())}catch{M0(G())}}).onRequest(({request:_,set:M})=>{let O=new URL(_.url).pathname;if(!O.startsWith("/api/"))return;if(O==="/api/profiles"||O.startsWith("/api/profiles/"))return;if(O==="/api/profile-stats"||O.startsWith("/api/profile-stats/"))return;let w=new URL(_.url);w.pathname=`/api/profiles/default${O.slice(4)}`;try{_.headers.set("x-vc-profile-rewrite","1"),_.headers.set("x-vc-profile-rewrite-target",w.pathname)}catch{}return}).derive(()=>({requestId:e4()??x0()})).use(z2).use(W5()).use(Y5(()=>F())).use(D0({getDb:()=>b()?.db??U})).onBeforeHandle(({request:_,set:M})=>{let O=G().getBootState();if(O==="ready")return;let w=new URL(_.url).pathname;if(fQ(w))return;return M.status=503,{error:"Agent not yet configured",message:"Agent is in '"+O+"' state. POST credentials to /api/agent/gateway-auth to finalize.",state:O}}).onAfterHandle(({request:_,set:M})=>{let O=new URL(_.url).pathname,w=O==="/health"||O.startsWith("/api/logs/stream")||O.startsWith("/ui/")||O==="/ws/events"||O==="/api/sessions/health-check"||O.startsWith("/terminal/"),A=typeof M.status==="number"?M.status:200,v=w?"debug":A>=400?"warn":"info";G().logger[v]("http",`${_.method} ${O} \u2192 ${A}`,{method:_.method,path:O,statusCode:A});try{P0(_.method,yQ(O),A)}catch{}}).use(W4({serviceRegistry:H,getDb:()=>b()?.db??U,getDbPath:()=>W,getPluginManager:()=>b()?.pluginManager??V})).use(y0()).use(i0({serviceRegistry:H,runFinalize:(_,M)=>a2(_,M),getDb:()=>b()?.db??U})).use(H4()).use(G4()).use(h4({getPluginManager:()=>b()?.pluginManager??V})).use(i4()).use(_4()).use(x4({getPluginManager:()=>b()?.pluginManager??V,getTunnelHost:()=>C5()?.url??null})).use($4()).use(J4()).use(B5()).use(K5()).use(V5(H)).ws("/code-server/*",uQ(Z)).all("/api/profiles/:name/*",async({params:_,request:M,set:O})=>{let w=M.method!=="GET"&&M.method!=="HEAD",A=w?await M.arrayBuffer():void 0,v=await N5(_.name,M,A);if(v&&v.status!==404)return v;let p=E2(),i=_.name;if(i!==p)return O.status=404,{error:"profile-mismatch",running:p,requested:i,hint:"This daemon serves a different profile. Call GET /api/profiles to discover the right tunnel."};let t=new URL(M.url),L2=t.pathname.replace(/^\/api\/profiles\/[^/]+/,"/api"),O2=new Headers(M.headers);O2.set("x-vc-profile-rewrite","1");let j2={method:M.method,headers:O2};if(w&&A!==void 0)j2.body=A;let r2=new Request(`${t.origin}${L2}${t.search}`,j2),q2=I0.current;if(!q2)return new Response(JSON.stringify({error:"agent-not-ready"}),{status:503,headers:{"content-type":"application/json"}});return q2.handle(r2)}).all("/api/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response(JSON.stringify({error:"Agent not yet configured",state:G().getBootState(),message:"Plugin routes are unavailable until the agent reaches state=ready. POST credentials to /api/agent/gateway-auth to finalize."}),{status:503,headers:{"content-type":"application/json"}});try{let M=new URL(_.url),O=/^\/api\/plugins\/([a-z0-9-]{1,64})\/ui(?:\/.*)?$/.exec(M.pathname);if(O&&_.method==="GET"){let w=O[1];if(x2(w)){let A=M.pathname.slice(`/api/plugins/${w}/ui`.length),v=A===""||A==="/",i=_.headers.get("sec-fetch-mode")==="navigate";if(v||i){let t=J5(_,w);if(!t||!Z5(t,w))return new Response(U5(w,"/api/profiles/default/agent/ui-exchange-plugin"),{status:200,headers:{"content-type":"text/html; charset=utf-8","Content-Security-Policy":"frame-ancestors 'self' http://localhost:* http://127.0.0.1:* https://localhost:* https://127.0.0.1:* https://*.local.burdenoff.com https://vibecontrols.com https://*.vibecontrols.com https://burdenoff.com https://app.burdenoff.com https://alphaapp.burdenoff.com"}})}}}}catch{}return T.handle(_)}).all("/ui/*",async({request:_})=>{if(G().getBootState()!=="ready"||!x)return new Response("Plugin UI not yet available",{status:503});return x.handle(_)}).all("/code-server/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response("code-server not yet available",{status:503});return T.handle(_)}).all("/plan/*",async({request:_})=>{if(G().getBootState()!=="ready"||!T)return new Response("plan provider not yet available",{status:503});return T.handle(_)});return I0.current=r,{app:r,async start(){r.listen({port:Z,hostname:Q}),G().logger.info("app",`Agent server listening on ${Q}:${Z}`);try{let _=(process.env.VIBECONTROLS_PROFILES??"").split(",").map((v)=>v.trim()).filter(Boolean),M=G().name,{getOrCreateProfile:O}=await import("./daemon-profile-vas1vf2t.js"),{attachSecondaryProfile:w}=await import("./secondary-profile-attach-db5cr3e1.js"),A=process.env.VIBE_STRICT_KEY_FETCH==="1";for(let v of _){if(v===M)continue;try{let p=O(v),i=await w(p);if(i.ok)G().logger.info("app",`Secondary profile '${v}' attached (db+services online)`);else if(A)throw Error(`attachServices for secondary profile '${v}' failed: ${i.error}`);else p.recordDegradedReason("attach",i.error??"unknown"),G().logger.warn("app",`Secondary profile '${v}' is degraded (no creds / attach failed)`,{error:i.error})}catch(p){if(A)throw G().logger.error("app",`--strict-key-fetch: secondary profile '${v}' attach failed; aborting`,{error:String(p)}),setTimeout(()=>process.exit(1),50),p;G().logger.warn("app",`Failed to attach secondary profile '${v}'`,{error:String(p)})}}}catch{}return r},stop:W2,finalize:a2,getState:()=>G().getBootState(),getLifecycle:()=>b()?.lifecycle??q,getDb:()=>b()?.db??U,getServiceRegistry:()=>b()?.serviceRegistry??H,getPluginManager:()=>b()?.pluginManager??V,getHostServices:()=>b()?.hostServices??E}}var q5=null;function cQ($,Z){if(!$)return null;let Q=$.match(new RegExp(`(?:^|;\\s*)${Z}=([^;]*)`));return Q?Q[1]:null}var o4=z5(H5);function uQ($){let X=(J)=>typeof J==="string"?Buffer.byteLength(J):J.byteLength;return{open(J){let W=J.data,H=m(W.headers??{})??m(W.request?Object.fromEntries(W.request.headers.entries()):{}),B=W.query?.vt,K=!!B&&$5(B,"/code-server","GET"),N,I=l(H);if(!I&&!K){let E=W.headers?.cookie??W.request?.headers.get("cookie")??null,q=cQ(E,"__vibe_cs_session");if(!q||!q5?.(q)){J.close(1008,"Unauthorized");return}N=`session:${q}`}else if(I)N="api-key";else N="vt";let C=J.remoteAddress??null,U=G5(C,W.headers);if(!o4.accept(N,U,J)){G().logger.warn("code-server-ws",`code-server WS cap exceeded (key=${N}, ip=${U??"unknown"})`),J.close(1013,"too many connections");return}W._csCapKey=N,W._csRemoteIp=U;let V=G().name;fetch(`http://127.0.0.1:${$}/api/profiles/${encodeURIComponent(V)}/code-server/status`,{headers:{"x-agent-api-key":M2()}}).then((E)=>E.json()).then((E)=>{if(W._csClosed)return;let q=E;if(!q.running||!q.port){J.close(1011,"code-server not running");return}let h=W.request?.url??"/code-server/",F;try{let R=new URL(h,`http://127.0.0.1:${q.port}`);F=(R.pathname.replace(/^\/code-server\/?/,"/")||"/")+R.search}catch{F="/"}let T=new WebSocket(`ws://127.0.0.1:${q.port}${F}`),x={upstream:T,ready:!1,buffer:[],bufferBytes:0,openTimer:setTimeout(()=>{try{T.close(1011,"upstream open timeout")}catch{}try{J.close(1011,"upstream open timeout")}catch{}},1e4)};W._csBridge=x,T.addEventListener("open",()=>{clearTimeout(x.openTimer),x.ready=!0;for(let R of x.buffer)T.send(R);x.buffer.length=0,x.bufferBytes=0}),T.addEventListener("message",(R)=>{try{let u=R.data;if(u instanceof ArrayBuffer)J.send(new Uint8Array(u));else if(u instanceof Blob)u.arrayBuffer().then((y)=>{try{J.send(new Uint8Array(y))}catch{}});else J.send(u)}catch{}}),T.addEventListener("close",(R)=>{clearTimeout(x.openTimer);try{J.close(R.code||1000,R.reason||"upstream closed")}catch{}}),T.addEventListener("error",()=>{clearTimeout(x.openTimer);try{J.close(1011,"upstream error")}catch{}})}).catch(()=>{J.close(1011,"Failed to query code-server status")})},message(J,W){let H=J.data?._csBridge;if(!H)return;let B;if(typeof W==="string")B=W;else if(W instanceof ArrayBuffer)B=W;else if(W instanceof Uint8Array||Buffer.isBuffer(W)){let K=new ArrayBuffer(W.byteLength);new Uint8Array(K).set(new Uint8Array(W.buffer,W.byteOffset,W.byteLength)),B=K}else if(typeof W==="object"&&W!==null)B=JSON.stringify(W);else B=String(W);if(H.upstream&&H.ready&&H.upstream.readyState===WebSocket.OPEN)try{H.upstream.send(B)}catch{}else{let K=X(B);if(H.buffer.length>=256||H.bufferBytes+K>1048576){try{H.upstream.close(1013,"buffer limit exceeded")}catch{}try{J.close(1013,"buffer limit exceeded")}catch{}return}H.buffer.push(B),H.bufferBytes+=K}},close(J){J.data._csClosed=!0;let W=J.data?._csBridge;if(W?.openTimer)clearTimeout(W.openTimer);if(W?.upstream&&W.upstream.readyState===WebSocket.OPEN)W.upstream.close(1000,"client disconnected");let H=J.data._csCapKey,B=J.data._csRemoteIp;if(H)o4.release(H,B??null,J)}}}async function a4(){try{let{readFileSync:$}=await import("fs"),{join:Z,dirname:Q}=await import("path"),{fileURLToPath:Y}=await import("url"),X=Q(Y(import.meta.url));return JSON.parse($(Z(X,"..","package.json"),"utf8")).version||"1.0.0"}catch{return"1.0.0"}}
|
|
26
|
-
export{X6 as j,m0 as k,NQ as l,B7 as m,l8 as n};
|