@vibecontrols/agent 2026.602.6 → 2026.608.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/{agent-config-4ppenhqp.js → agent-config-pxkfd7ec.js} +1 -1
- package/dist/{agent-ready-tracker-kgs7td6t.js → agent-ready-tracker-pyw7zrp0.js} +1 -1
- package/dist/app-wj8qwk11.js +2 -0
- package/dist/{bootstrap-workspace-qgs6d5f0.js → bootstrap-workspace-1ff98st2.js} +1 -1
- package/dist/{bridge-client-1fxza4p7.js → bridge-client-73z9c5nm.js} +1 -1
- package/dist/cli.js +1 -1
- package/dist/{daemon-profile-gwdcqx0q.js → daemon-profile-696722nr.js} +1 -1
- package/dist/{finalize-retry-worker-dvykrzed.js → finalize-retry-worker-vfdskqb5.js} +1 -1
- package/dist/{gateway-client-9kwnmk89.js → gateway-client-xdy5g715.js} +1 -1
- package/dist/{index-0924jp9m.js → index-08y76yzh.js} +1 -1
- package/dist/{index-190q0sxy.js → index-41vve5br.js} +2 -2
- package/dist/{index-hw61pg70.js → index-4hn26x1h.js} +1 -1
- package/dist/{index-h74va4wd.js → index-63ba5fb4.js} +1 -1
- package/dist/{index-vaxcmbdg.js → index-68r2ex9d.js} +1 -1
- package/dist/{index-hvjqgb97.js → index-6p3gcnxr.js} +2 -2
- package/dist/{index-wq0z4sft.js → index-84hfet2g.js} +4 -4
- package/dist/{index-1mppacnx.js → index-85ke6hng.js} +1 -1
- package/dist/{index-rqq0k5fc.js → index-bfeekmyh.js} +1 -1
- package/dist/{index-f4da1dth.js → index-bwt6c337.js} +2 -2
- package/dist/{index-9006n9tq.js → index-cv0xhb46.js} +3 -3
- package/dist/{index-5wpck4aw.js → index-czrb2yd1.js} +1 -1
- package/dist/{index-nrsqzcfc.js → index-eawbdgkb.js} +1 -1
- package/dist/{index-rvwb9g8g.js → index-ebx79cc1.js} +1 -1
- package/dist/{index-jc83tg1e.js → index-ghz61a5p.js} +3 -3
- package/dist/{index-ydc0tk17.js → index-jrtsdm8f.js} +1 -1
- package/dist/{index-ebwwtwwc.js → index-m9dpfyxb.js} +1 -1
- package/dist/{index-tgrt61qr.js → index-p9cgvp3x.js} +1 -1
- package/dist/{index-rv6h14n8.js → index-rjhcmnx0.js} +1 -1
- package/dist/{index-b6x6a4xp.js → index-t8tnkqxh.js} +1 -1
- package/dist/{index-d1xjj001.js → index-wetsgcyq.js} +1 -1
- package/dist/{index-js1xn4sq.js → index-xnr6t79p.js} +1 -1
- package/dist/{index-rw9x93zb.js → index-yas07mv9.js} +1 -1
- package/dist/{index-9hjnbg75.js → index-z2gbk1pn.js} +2 -2
- package/dist/{index-z5s398n0.js → index-z73x3sdf.js} +1 -1
- package/dist/{index-rzpaqrhx.js → index-zhyxdyk6.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/key.cmd-q8c7ywwd.js +2 -0
- package/dist/{plugin-system-kaj4069d.js → plugin-system-jegwkd9p.js} +1 -1
- package/dist/{prereqs-runner-27x3j1md.js → prereqs-runner-t5jhqr7x.js} +1 -1
- package/dist/{profile-mount-8dc9jwt5.js → profile-mount-m714p85h.js} +1 -1
- package/dist/register-core-r7fjpp4w.js +2 -0
- package/dist/secondary-profile-attach-kxg4xj2t.js +2 -0
- package/dist/{subprocess-1nna3d3x.js → subprocess-q2ky0ptw.js} +1 -1
- package/dist/telemetry-jxfgrm61.js +2 -0
- package/dist/{tunnel-bootstrap-5wgt9a1h.js → tunnel-bootstrap-zdczwezc.js} +1 -1
- package/package.json +2 -2
- package/dist/app-k4v5pf0w.js +0 -2
- package/dist/key.cmd-972133dv.js +0 -2
- package/dist/register-core-yb4p0td9.js +0 -2
- package/dist/secondary-profile-attach-mk30rj1z.js +0 -2
- package/dist/telemetry-8jfdyt51.js +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{$c as f,Wc as a,Xc as b,Yc as c,Zc as d,_c as e,ad as g,bd as h,cd as i,dd as j,ed as k,fd as l,gd as m,hd as n,id as o,jd as p,kd as q,ld as r,md as s,nd as t,od as u,pd as v,qd as w,rd as x,sd as y,td as z,ud as A,vd as B}from"./index-
|
|
2
|
+
import{$c as f,Wc as a,Xc as b,Yc as c,Zc as d,_c as e,ad as g,bd as h,cd as i,dd as j,ed as k,fd as l,gd as m,hd as n,id as o,jd as p,kd as q,ld as r,md as s,nd as t,od as u,pd as v,qd as w,rd as x,sd as y,td as z,ud as A,vd as B}from"./index-63ba5fb4.js";import"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";export{m as writeProfile,x as writeAgentConfigAwaitSecrets,w as writeAgentConfig,j as writeActiveProfileName,l as readProfile,y as readAgentConfigWithSecrets,u as readAgentConfig,i as readActiveProfileName,z as readActiveProfile,k as listProfileNames,f as getProfilesDir,h as getProfilePath,q as getProductionGatewayUrls,v as getOrCreateAgentInstanceId,t as getAgentConfigSeed,r as getAgentConfigPath,s as getAgentConfigDefaults,g as getActiveProfilePointerPath,p as ensureProfilesInitialized,n as deleteProfile,o as buildProfileSeed,e as assertValidProfileName,B as applyAgentSecretsToEnv,A as applyAgentConfigToEnv,c as NAMED_ENV_PRESETS,d as DEFAULT_PROFILE_NAME,a as CURRENT_CONFIG_SCHEMA_VERSION,b as BUILTIN_PROFILE_SEEDS};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{oc as G,vc as f,wc as y,xc as V}from"./index-
|
|
2
|
+
import{oc as G,vc as f,wc as y,xc as V}from"./index-85ke6hng.js";import"./index-c7554sg7.js";var N={pending:()=>G.gray("\u25CF"),active:()=>G.cyan("\u25B6"),ok:()=>G.green("\u2713"),warn:()=>G.yellow("\u26A0"),fail:()=>G.red("\u2717")};function L(E,A){if(A)console.log(" "+E)}async function O(E,A=2000){let W=new AbortController,j=setTimeout(()=>W.abort(),A);try{let q=await fetch(`${E}/health/ready`,{signal:W.signal});if(q.status!==200&&q.status!==503)return null;return await q.json()}catch{return null}finally{clearTimeout(j)}}function P(E){if(!E?.message)return null;let A=E.message.match(/provider:\s*(\S+)/);return A?A[1]:null}async function M(E,A={}){let W=A.timeoutMs??60000,j=A.pollIntervalMs??500,q=A.verbose!==!1;if(q)f("Waiting for agent to become ready");let C={daemon:!1,awaiting:!1,initializing:!1,db:!1,session:!1,tunnel:!1},z=Date.now(),X="",H=0,D=null;while(Date.now()-z<W){let Q=await O(E);if(!Q){await T(j);continue}if(!C.daemon)L(`${N.ok()} Daemon listening on ${E}`,q),C.daemon=!0;let F=Q.bootState??"unknown",Y=Q.components??{};if(F!==X){if(X=F,F==="awaiting-config"&&!C.awaiting)L(`${N.warn()} Workspace config: ${G.yellow("awaiting OAuth credentials \u2014 register this agent in the VibeControls UI")}`,q),C.awaiting=!0;else if(F==="initializing"&&!C.initializing)L(`${N.active()} Finalizing: fetching encryption key, opening storage, loading plugins\u2026`,q),C.initializing=!0}if(F==="awaiting-config"){if(H++,H>=2)return{outcome:"awaiting-config",bootState:F,degradedReasons:[],summary:"Agent is awaiting workspace registration. Open the VibeControls UI \u2192 Agents \u2192 Add Agent, paste the API Key and Tunnel URL printed above."}}else H=0;if(Y.db?.ok&&!C.db)L(`${N.ok()} Storage encryption key loaded, DB opened`,q),C.db=!0;if(Y.session?.ok&&!C.session){let x=Y.session.message??"";L(`${N.ok()} Plugins started \u2014 ${x}`,q),C.session=!0}let Z=P(Y.tunnel);if(Z&&Z!=="bootstrap"&&Z!==D){if(D=Z,!C.tunnel)L(`${N.ok()} Tunnel ready (provider: ${Z})`,q),C.tunnel=!0}let I=Q.status==="degraded";if(F==="ready"&&!I){if(q)V(),y("Status",G.green("ready"));return{outcome:"ready",bootState:F,degradedReasons:[],summary:"Agent ready."}}if(F==="degraded"||F==="ready"&&I){let x=Q.degradedReasons??[],_=x;if(x.length===0){let J=[];for(let[$,K]of Object.entries(Y)){if($==="boot"||$==="lifecycle")continue;if(K&&!K.ok&&K.message)J.push({plugin:$,message:K.message})}for(let[$,K]of Object.entries(Q.plugins??{}))if(K&&!K.ok&&K.message)J.push({plugin:`plugin:${$}`,message:K.message});_=J}if(q){V(),L(`${N.fail()} Agent boot ${G.red("degraded")} \u2014 investigate before retrying`,q);for(let J of _)L(` ${G.gray("\xB7")} [${J.plugin}] ${J.message}`,q);V()}return{outcome:"degraded",bootState:F,degradedReasons:_,summary:_.length?`Agent degraded: ${_.map((J)=>`[${J.plugin}] ${J.message}`).join("; ")}`:"Agent degraded with no reported reason \u2014 check vibe logs."}}await T(j)}if(q)V(),L(`${N.warn()} Timed out after ${Math.round(W/1000)}s; last bootState=${X||"unknown"}. Check ${G.bold("vibe logs")} for details.`,q),V();return{outcome:"timeout",bootState:X||"unknown",degradedReasons:[],summary:`Timed out waiting for ready. Last bootState=${X||"unknown"}.`}}function T(E){return new Promise((A)=>setTimeout(A,E))}export{M as trackAgentReady};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{n as a}from"./index-84hfet2g.js";import"./index-czrb2yd1.js";import"./index-41vve5br.js";import"./index-6jzsthh9.js";import"./index-ebx79cc1.js";import"./index-yas07mv9.js";import"./index-68r2ex9d.js";import"./index-4hn26x1h.js";import"./index-4wgjx8bf.js";import"./index-cv0xhb46.js";import"./index-0ckffygp.js";import"./index-rc79x8fw.js";import"./index-jrtsdm8f.js";import"./index-52cp759f.js";import"./index-6p3gcnxr.js";import"./index-bfeekmyh.js";import"./index-5dysvvjv.js";import"./index-pgew6sge.js";import"./index-t8tnkqxh.js";import"./index-63ba5fb4.js";import"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";export{a as createApp};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{t as a}from"./index-
|
|
2
|
+
import{t as a}from"./index-rjhcmnx0.js";import"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";export{a as bootstrapWorkspace};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Id as K,Od as D}from"./index-
|
|
2
|
+
import{Id as K,Od as D}from"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";var b="bridge-client",U=2000,G=30000,N=30000,O=6,z={ws:null,pingTimer:null,reconnectTimer:null,reconnectAttempt:0,connected:!1,stopped:!1,agentId:null,profile:"default",pendingEvents:[]};function Z(J,Q,$){D().logger[J](b,Q,$)}function C(J){try{let Q=new URL(J);Q.protocol=Q.protocol==="https:"?"wss:":"ws:",Q.pathname="/agent-bridge",Q.search="",Q.hash="";let $=process.env.VIBE_BRIDGE_URL;if($)return $;return Q.toString()}catch{return process.env.VIBE_BRIDGE_URL??""}}async function x(){if(z.stopped||z.ws)return;if(!K.isConfigured()){Z("debug","Gateway client not configured yet; deferring bridge connect");return}if(!z.agentId){Z("debug","No agentId set yet; deferring bridge connect");return}let J,Q,$;try{let Y=await K.getAccessToken();J=Y.token,Q=Y.workspaceGatewayUrl,$=Y.workspaceId}catch(Y){Z("warn","Failed to fetch access token for bridge",{error:Y instanceof Error?Y.message:String(Y)}),W();return}if(!J||!Q){W();return}let q=C(Q);if(!q){Z("warn","Cannot resolve bridge URL from workspaceGatewayUrl",{workspaceGatewayUrl:Q}),W();return}Z("info","Connecting to agent-bridge",{url:q,agentId:z.agentId});let H;try{H=new WebSocket(q,{headers:{Authorization:`Bearer ${J}`,...$?{"x-workspace-id":$}:{}}})}catch(Y){Z("warn","Bridge connect threw",{error:Y instanceof Error?Y.message:String(Y)}),W();return}z.ws=H,H.addEventListener("open",()=>{z.reconnectAttempt=0,Z("info","Bridge socket open \u2014 sending hello"),X({type:"hello",agentId:z.agentId,profile:z.profile,version:process.env.npm_package_version??"unknown"})}),H.addEventListener("message",(Y)=>{let B=typeof Y.data==="string"?Y.data:Y.data instanceof Blob?"":new TextDecoder().decode(Y.data);if(!B)return;let V;try{V=JSON.parse(B)}catch{return}if(V.type==="welcome")z.connected=!0,Z("info","Bridge welcome received \u2014 connection ready",{workspaceId:typeof V.workspaceId==="string"?V.workspaceId:void 0}),L(),P();else if(V.type==="error")Z("warn","Bridge error frame",{error:V})}),H.addEventListener("close",(Y)=>{if(Z("info","Bridge socket closed",{code:Y.code,reason:Y.reason}),M(),!z.stopped)W()}),H.addEventListener("error",(Y)=>{Z("warn","Bridge socket error",{message:Y.message})})}function X(J){if(!z.ws||z.ws.readyState!==1)return!1;try{return z.ws.send(JSON.stringify(J)),!0}catch(Q){return Z("debug","safeSend failed",{error:Q instanceof Error?Q.message:String(Q)}),!1}}function L(){F(),z.pingTimer=setInterval(()=>{X({type:"ping"})},N),z.pingTimer.unref?.()}function F(){if(z.pingTimer)clearInterval(z.pingTimer),z.pingTimer=null}function M(){z.connected=!1,F(),z.ws=null}function W(){if(z.stopped||z.reconnectTimer)return;let J=z.reconnectAttempt+1,Q=Math.min(U*2**Math.min(J-1,5),G);if(z.reconnectAttempt=J,J===O)Z("warn",`Bridge unavailable after ${J} attempts \u2014 falling back to existing HTTP polling for heartbeat/tunnel sync. Will keep retrying in the background.`);z.reconnectTimer=setTimeout(()=>{z.reconnectTimer=null,x()},Q),z.reconnectTimer.unref?.()}function P(){if(!z.connected)return;while(z.pendingEvents.length>0){let J=z.pendingEvents.shift();if(!X({type:J.type,...J.payload})){z.pendingEvents.unshift(J);return}}}var R=500;function j(J){if(z.connected&&X({type:J.type,...J.payload}))return;if(z.pendingEvents.length>=R)z.pendingEvents.shift();z.pendingEvents.push(J)}var I={start(J,Q){if(z.stopped=!1,z.agentId===J&&z.connected)return;z.agentId=J,z.profile=Q||"default",x()},stop(){if(z.stopped=!0,z.reconnectTimer)clearTimeout(z.reconnectTimer),z.reconnectTimer=null;let J=z.ws;try{J?.close(1000,"agent shutdown")}catch{}M()},publishEvent(J){j({type:"event",payload:{topic:J.topic,payload:J.payload}})},publishLog(J){j({type:"log",payload:{payload:J}})},isConnected(){return z.connected},isFallbackEngaged(){return z.reconnectAttempt>=O&&!z.connected}};export{I as bridgeClient};
|
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-ghz61a5p.js";import"./index-wetsgcyq.js";import"./index-b5dhmybd.js";import"./index-e1bw1bwr.js";import"./index-ebx79cc1.js";import"./index-yas07mv9.js";import"./index-68r2ex9d.js";import{wa as Z,za as I}from"./index-4hn26x1h.js";import{Aa as G,Ba as H}from"./index-4wgjx8bf.js";import{Wa as J}from"./index-cv0xhb46.js";import{Xa as U}from"./index-0ckffygp.js";import"./index-rc79x8fw.js";import{bb as K}from"./index-jrtsdm8f.js";import"./index-52cp759f.js";import"./index-bfeekmyh.js";import"./index-5dysvvjv.js";import"./index-pgew6sge.js";import{dc as $}from"./index-8sdrhr3q.js";import"./index-8nqp3a4d.js";import{nc as E}from"./index-85ke6hng.js";import"./index-thammzct.js";import"./index-t8tnkqxh.js";import"./index-63ba5fb4.js";import{Od as Y}from"./index-xnr6t79p.js";import{$d as W,de as X}from"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.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)});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Md as a,Nd as b,Od as c,Pd as d,Qd as e}from"./index-
|
|
2
|
+
import{Md as a,Nd as b,Od as c,Pd as d,Qd as e}from"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";export{a as profileRegistry,d as getOrCreateProfile,c as getDaemonProfile,b as ensureDaemonProfile,e as __resetDaemonProfileForTests};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Od as Y}from"./index-
|
|
2
|
+
import{Od as Y}from"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";var Z=[300000,600000,900000,1800000];function j(R){let W=R.backoffsMs??Z,w=0,z=!1,G=null,J=null,I=null,q=Y();if(q.getBootState()==="ready")return{cancel(){},async forceRetryNow(){return{ok:!0}},getState(){return{attempt:0,cancelled:!0,nextAttemptAt:null}}};function Q(){if(G!==null)clearTimeout(G),G=null,J=null}function X(){if(z)return Promise.resolve({ok:!1,error:"retry worker cancelled"});if(q.getBootState()==="ready")return z=!0,Q(),Promise.resolve({ok:!0});if(I)return I;return w+=1,R.onAttempt?.(w),q.logger.info("finalize-retry",`Background finalize retry attempt ${w}`),I=(async()=>{try{let v=await R.trigger();if(v.ok)q.logger.info("finalize-retry",`Background finalize succeeded on attempt ${w} \u2014 agent recovered`),z=!0,Q();else q.recordFinalizeError(v.error,w),q.logger.warn("finalize-retry",`Background finalize attempt ${w} failed`,{error:v.error});return v}catch(v){let H=v instanceof Error?v.message:String(v);return q.recordFinalizeError(H,w),q.logger.error("finalize-retry",`Background finalize attempt ${w} threw`,{error:H}),{ok:!1,error:H}}finally{I=null}})(),I}function V(){if(z)return;if(q.getBootState()==="ready"){z=!0;return}if(G!==null)return;let v=Math.min(w,W.length-1),H=W[v];J=Date.now()+H,G=setTimeout(async()=>{if(G=null,await X(),!z&&q.getBootState()!=="ready")V()},H)}return V(),{cancel(){z=!0,Q()},async forceRetryNow(){if(q.getBootState()==="ready")return{ok:!0};if(z)return{ok:!1,error:"retry worker cancelled"};Q();let v=await X();if(!z&&q.getBootState()!=="ready")V();return v},getState(){return{attempt:w,cancelled:z,nextAttemptAt:J?new Date(J).toISOString():null}}}}export{j as startFinalizeRetryWorker};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Gd as a,Hd as b,Id as c,Jd as d}from"./index-
|
|
2
|
+
import{Gd as a,Hd as b,Id as c,Jd as d}from"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";export{a as normalizeGatewayUrl,c as gatewayClient,d as default,b as GatewayClient};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{i as L}from"./index-cs78wq6y.js";import{C as N,D as M,E as D,F as m,G as k}from"./index-6jzsthh9.js";import{Xa as v}from"./index-0ckffygp.js";import{Ub as I,Vb as h}from"./index-pgew6sge.js";import{jc as p,kc as d,lc as w}from"./index-8nqp3a4d.js";import{Cc as f,Dc as x,qc as O,rc as q,sc as B,uc as A,vc as S,yc as i,zc as E}from"./index-
|
|
2
|
+
import{i as L}from"./index-cs78wq6y.js";import{C as N,D as M,E as D,F as m,G as k}from"./index-6jzsthh9.js";import{Xa as v}from"./index-0ckffygp.js";import{Ub as I,Vb as h}from"./index-pgew6sge.js";import{jc as p,kc as d,lc as w}from"./index-8nqp3a4d.js";import{Cc as f,Dc as x,qc as O,rc as q,sc as B,uc as A,vc as S,yc as i,zc as E}from"./index-85ke6hng.js";import{Gc as r}from"./index-thammzct.js";import{Kc as n,Lc as C,Nc as y,Oc as l,Pc as T}from"./index-t8tnkqxh.js";import"./index-63ba5fb4.js";import{Fd as b,Id as g}from"./index-xnr6t79p.js";import"./index-a4854mwz.js";import"./index-4qq083yd.js";import"./index-c7554sg7.js";import{promises as J}from"fs";import H2 from"path";import V2 from"os";function u(j,H){let Q=Number.parseInt(process.env[j]??"",10);return Number.isInteger(Q)&&Q>0?Q:H}var j2=u("VIBECONTROLS_MAX_CONCURRENT_TASKS",4),Q2=u("VIBECONTROLS_MAX_TASK_OUTPUT_BYTES",1048576),Z2=new Set(["bash","sh","zsh","python","python3","node","bun","powershell","pwsh","cmd"]);async function $2(j,H){if(!j.command)throw Error("Command is required");let Q=j.cwd?(await D(j.cwd,{mustExist:!0})).path:process.cwd(),V=Bun.spawn(v().shellArgv(j.command),{cwd:Q,env:{...process.env,...j.env},stdout:"pipe",stderr:"pipe"}),Z=!1,z;if(H&&H>0)z=setTimeout(()=>{Z=!0,V.kill()},H);let[K,$]=await Promise.all([R(V.stdout,()=>V.kill()),R(V.stderr,()=>V.kill())]),Y=await V.exited;if(z)clearTimeout(z);if(Z)throw Error(`Command timed out after ${H}ms`);return{stdout:K,stderr:$,exitCode:Y}}async function z2(j,H){if(!j.script)throw Error("Script is required");let Q=v().platform==="win32",V=j.interpreter||(Q?"powershell":"bash");if(!Z2.has(V)||V.includes("/"))throw Error(`Interpreter '${V}' is not allowed`);let Z=j.cwd?(await D(j.cwd,{mustExist:!0})).path:process.cwd(),z=V2.tmpdir(),K=V==="powershell"||V==="pwsh"?"ps1":V==="cmd"?"cmd":"sh",$=H2.join(z,`vibecontrols-script-${globalThis.crypto.randomUUID()}.${K}`);await J.writeFile($,j.script,{mode:448});try{let Y=j.env?{...process.env,...j.env}:process.env,W=V==="powershell"||V==="pwsh"?[V,"-NoProfile","-ExecutionPolicy","Bypass","-File",$]:V==="cmd"?["cmd","/c",$]:[V,$],X=Bun.spawn(W,{cwd:Z,env:Y,stdout:"pipe",stderr:"pipe"}),G=!1,_;if(H&&H>0)_=setTimeout(()=>{G=!0,X.kill()},H);let[a,e]=await Promise.all([R(X.stdout,()=>X.kill()),R(X.stderr,()=>X.kill())]),t=await X.exited;if(_)clearTimeout(_);if(G)throw Error(`Script timed out after ${H}ms`);return{stdout:a,stderr:e,exitCode:t}}finally{await J.unlink($).catch(()=>{})}}async function R(j,H){let Q=new TextDecoder,V="",Z=0,z=!1;for await(let K of j){if(Z+=K.byteLength,Z>Q2){if(!z)z=!0,H(),V+=`
|
|
3
3
|
[output truncated: task output limit exceeded]
|
|
4
4
|
`;continue}V+=Q.decode(K,{stream:!0})}return V+=Q.decode(),V}async function Y2(j){if(!j.path)throw Error("Path is required");switch(j.operation){case"read":{let H=(await D(j.path,{mustExist:!0})).path;if(N(H))throw Error("Access to sensitive files not allowed");return await m(H),{content:await J.readFile(H,"utf-8"),path:H}}case"write":{if(!j.content)throw Error("Content is required for write operation");let H=(await D(j.path,{forWrite:!0})).path;if(M(H)||N(H))throw Error("Write access to sensitive files not allowed");return await J.writeFile(H,j.content),{success:!0,path:H}}case"delete":{let H=(await D(j.path,{mustExist:!0})).path;if(M(H)||N(H))throw Error("Delete access to this path is not allowed");return await J.unlink(H),{success:!0,path:H}}case"exists":try{let H=(await D(j.path)).path;return await J.access(H),{exists:!0,path:H}}catch{return{exists:!1}}case"list":{let H=(await D(j.path,{mustExist:!0})).path;return{files:(await k(H)).map((V)=>V.name),path:H}}default:throw Error(`Unknown file operation: ${j.operation}`)}}async function K2(j,H,Q,V){try{let Z=await j.getTask(H.id);if(Z&&Z.status!=="pending")return;await j.updateTask(H.id,{status:"running"});let z=JSON.parse(H.payload),K,$;switch(H.type){case"command":{let X=await $2(z,V?.timeout);K=X,$=X.exitCode;break}case"script":{let X=await z2(z,V?.timeout);K=X,$=X.exitCode;break}case"file_operation":K=await Y2(z);break;default:throw Error(`Unknown task type: ${H.type}`)}let Y=$!==void 0&&$!==0,W=Y?"failed":"completed";if(await j.updateTask(H.id,{status:W,result:JSON.stringify(K),...$!==void 0&&{exitCode:$},...Y&&{error:`Process exited with code ${$}`}}),V?.callbackUrl)P(V.callbackUrl,{agentTaskId:H.id,status:W,result:K,exitCode:$,...Y&&{error:`Process exited with code ${$}`}})}catch(Z){let z=Z instanceof Error?Z.message:String(Z);try{await j.updateTask(H.id,{status:"failed",error:z})}catch(K){console.warn(`[task] failed to mark task ${H.id} as failed: ${K instanceof Error?K.message:String(K)}`)}if(V?.callbackUrl)P(V.callbackUrl,{agentTaskId:H.id,status:"failed",error:z})}finally{Q.active=Math.max(0,Q.active-1)}}function P(j,H){fetch(j,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(H),signal:AbortSignal.timeout(1e4)}).catch(()=>{})}function c(j){let{db:H}=j,Q={active:0};return new h().get("/",async({query:V})=>{if(V.status==="pending")return{tasks:await H.getPendingTasks()};return{tasks:await H.getAllTasks()}}).get("/:id",async({params:V,set:Z})=>{let z=await H.getTask(V.id);if(!z)return Z.status=404,{error:"Task not found"};return{task:z}}).post("/legacy",async({body:V,set:Z})=>{try{return{task:await H.createTask({id:globalThis.crypto.randomUUID(),type:"file_operation",status:"completed",payload:JSON.stringify({operation:"exists",path:process.cwd(),meta:V}),result:JSON.stringify({legacy:!0,note:"Legacy doctor-script task accepted (no-op)."})})}}catch(z){return Z.status=500,{error:"Failed to create task",details:String(z)}}},{body:I.Any()}).post("/",async({body:V,request:Z,server:z,set:K})=>{let $=V;if($&&typeof $==="object"&&!$.type&&!$.payload&&($.title||$.description||$.command))try{return{task:await H.createTask({id:globalThis.crypto.randomUUID(),type:"file_operation",status:"completed",payload:JSON.stringify({operation:"exists",path:process.cwd(),meta:$}),result:JSON.stringify({legacy:!0,note:"Legacy doctor-script task accepted (no-op)."})})}}catch(W){return K.status=500,{error:"Failed to create task",details:String(W)}}let Y=V;try{if(Y.type==="command"||Y.type==="script"){let X=await L(Z,"VIBECONTROLS_ALLOW_REMOTE_SHELL_TASK",z,{getConfig:(G)=>H.getConfig(G)});if(X)return K.status=403,{error:"Forbidden",message:X}}else if(Y.type==="file_operation"&&["write","delete"].includes(String(Y.payload?.operation??""))){let X=await L(Z,"VIBECONTROLS_ALLOW_REMOTE_FILE_TASK",z,{getConfig:(G)=>H.getConfig(G)});if(X)return K.status=403,{error:"Forbidden",message:X}}if(Q.active>=j2)return K.status=429,{error:"Too many tasks are already running"};if(Q.active+=1,Y.callbackUrl&&!b(Y.callbackUrl,(()=>{let X=g.getConfig();return[X?.globalGatewayUrl,X?.workspaceGatewayUrl]})()))return Q.active=Math.max(0,Q.active-1),K.status=400,{error:"callbackUrl is not allowed"};let W=await H.createTask({id:globalThis.crypto.randomUUID(),type:Y.type,status:"pending",payload:JSON.stringify(Y.payload),...Y.calendarTaskId&&{calendarTaskId:Y.calendarTaskId},...Y.timeout&&{timeout:Y.timeout}});return K2(H,W,Q,{timeout:Y.timeout,callbackUrl:Y.callbackUrl}),{task:W}}catch(W){return Q.active=Math.max(0,Q.active-1),K.status=500,{error:"Failed to create task",details:String(W)}}},{body:I.Any()}).post("/:id/cancel",async({params:V,set:Z})=>{let z=await H.getTask(V.id);if(!z)return Z.status=404,{error:"Task not found"};if(z.status!=="pending")return Z.status=400,{error:"Only pending tasks can be cancelled"};return await H.updateTask(V.id,{status:"failed",error:"Task cancelled by user"}),{success:!0}}).delete("/:id",async({params:V,set:Z})=>{let z=await H.getTask(V.id);if(!z)return Z.status=404,{error:"Task not found"};if(z.status==="pending")await H.updateTask(V.id,{status:"failed",error:"Task cancelled via DELETE"});return{success:!0,status:z.status}})}var U="http://localhost:3005";function F(j){return`/api/profiles/${encodeURIComponent(y(j))}/tasks`}function o(j){let H=j.command("task").description("Manage background tasks");H.command("list").description("List tasks").option("--status <status>","Filter by status").option("--profile <name>","Profile name (overrides default resolution)").option("--agent-url <url>","Agent URL",U).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(Q){let V={...j.opts(),...Q};try{let Z=C(Q),z=F(V),K=Q.status?`${z}/?status=${encodeURIComponent(Q.status)}`:`${z}/`;await d({mode:p(V),fetchData:async()=>{return(await l(Z,K)).tasks||[]},plain:($)=>{if(!$||$.length===0){A("No tasks found.");return}S("Tasks"),i($.map((Y)=>({ID:x(Y.id),Type:Y.type||"-",Status:f(Y.status),Created:Y.createdAt?E(Y.createdAt):"-"})))},interactive:async($)=>{if(!$||$.length===0){S("Tasks"),A("No tasks found.");return}let Y=$.map((W)=>({id:String(W.id),label:W.type||x(W.id),hint:W.status||"",detail:[`ID: ${W.id}`,`Type: ${W.type??"-"}`,`Status: ${f(W.status)}`,`Created: ${W.createdAt?E(W.createdAt):"-"}`].join(`
|
|
5
5
|
`)}));await r({title:`vibe task list \u2014 ${$.length} task(s)`,rows:Y})},json:($)=>$.map((Y)=>({id:Y.id,type:Y.type??null,status:Y.status??null,createdAt:Y.createdAt??null}))})}catch(Z){O(q(Z))}}),H.command("run").description("Run a new task").requiredOption("-c, --command <cmd>","Command to run").option("--cwd <dir>","Working directory").option("--profile <name>","Profile name (overrides default resolution)").option("--agent-url <url>","Agent URL",U).option("--json","Emit JSON").action(async function(Q){let V={...j.opts(),...Q};try{let Z=C(Q);if(!n(Z)&&process.env.VIBECONTROLS_ALLOW_REMOTE_SHELL_TASK!=="1"){if(V.json){w(V,{ok:!1,error:"Remote shell task refused without env override"});return}O("Refusing to create a shell task on a remote agent URL. Set VIBECONTROLS_ALLOW_REMOTE_SHELL_TASK=1 only if you trust the target.");return}let z={command:Q.command};if(Q.cwd)z.cwd=Q.cwd;let K=F(V),$=await T(Z,`${K}/`,{type:"command",payload:z}),Y=$?.task?.id||$?.id||$?.taskId;if(w(V,{ok:!0,id:Y}))return;if(!Y){O("Task created but no ID returned by the agent");return}B(`Task created: ${x(Y)}`)}catch(Z){if(V.json){w(V,{ok:!1,error:q(Z)});return}O(q(Z))}}),H.command("cancel").description("Cancel a running task").requiredOption("-i, --id <id>","Task ID").option("--profile <name>","Profile name (overrides default resolution)").option("--agent-url <url>","Agent URL",U).option("--json","Emit JSON").action(async function(Q){let V={...j.opts(),...Q};try{let Z=C(Q),z=F(V);if(await T(Z,`${z}/${Q.id}/cancel`,{}),w(V,{ok:!0,id:Q.id}))return;B(`Task ${x(Q.id)} cancelled.`)}catch(Z){if(V.json){w(V,{ok:!1,error:q(Z)});return}O(q(Z))}})}function s(j,H){o(j)}function U2(j){return{name:"task",version:"2.2.0",description:"Background task execution \u2014 commands, scripts, file operations",capabilities:{storage:"rw",subprocess:!0,audit:!0,telemetry:!0},tags:["backend","cli"],cliCommand:"task",apiPrefix:"/api/tasks",createRoutes:(H)=>c(H),onCliSetup:async(H,Q)=>{s(H,Q)}}}export{U2 as createPlugin};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{wa as qa,za as Fa}from"./index-
|
|
2
|
+
import{wa as qa,za as Fa}from"./index-4hn26x1h.js";import{Aa as Ka}from"./index-4wgjx8bf.js";import{Da as ka,Wa as Ua}from"./index-cv0xhb46.js";import{Xa as Pa}from"./index-0ckffygp.js";import{nb as ja}from"./index-6p3gcnxr.js";import{Jb as Ma}from"./index-bfeekmyh.js";import{qd as ba,sd as yt}from"./index-63ba5fb4.js";import{Ad as Gt,Cd as os,Ed as Ra,Id as v,Md as Ta,Od as g,Pd as Oa}from"./index-xnr6t79p.js";import{Zd as Xt,ce as Ia}from"./index-a4854mwz.js";import{ie as Ae}from"./index-c7554sg7.js";var Qt=[0,5000,15000,30000,60000],za=2000,Ba=5000,Xa=120000,cs=10,Ha=1048576;class Zt extends Error{resetAt;resource;constructor(e,t,i){super(e);this.name="RateLimitError",this.resource=t,this.resetAt=i}}function ei(e,t){if(!e?.length)return null;let i=e.find((r)=>r.extensions?.code==="RATE_LIMITED");if(!i)return null;let s=i.extensions?.resetAt,n=null;if(s){let r=new Date(s);if(!Number.isNaN(r.getTime()))n=r}return new Zt(`${t} rate limited${n?` until ${n.toISOString()}`:""}`,t,n)}function Va(e){if(!e.resetAt)return 60000;let t=e.resetAt.getTime()-Date.now()+za;return Math.min(Math.max(t,Ba),Xa)}async function Ja(e,t){let i=e.headers.get("content-length");if(i){let o=Number.parseInt(i,10);if(Number.isInteger(o)&&o>t)throw Error(`Gateway response is too large (${o} bytes)`)}if(!e.body)return"";let s=e.body.getReader(),n=[],r=0;try{while(!0){let{done:o,value:c}=await s.read();if(o)break;if(!c)continue;if(r+=c.byteLength,r>t)throw await s.cancel().catch(()=>{return}),Error(`Gateway response exceeds ${t} bytes`);n.push(c)}}finally{s.releaseLock()}let a=new Uint8Array(r),l=0;for(let o of n)a.set(o,l),l+=o.byteLength;return new TextDecoder().decode(a)}async function ti(e,t){let i=await Ja(e,Ha),s;try{s=i?JSON.parse(i):{}}catch(n){let r=i.slice(0,240).replace(/\s+/g," ");throw Error(`${t} returned non-JSON response (${e.status} ${e.statusText})${r?`: ${r}`:""}`,{cause:n})}if(!e.ok){let n=i.slice(0,240).replace(/\s+/g," ");throw Error(`${t} failed (${e.status} ${e.statusText})${n?`: ${n}`:""}`)}return s}function ii(e){return e.endsWith("/graphql")?e:`${e}/graphql`}function Ya(e){let t;try{t=new URL(e).hostname.toLowerCase().replace(/^\[|\]$/g,"")}catch{return!1}if(t==="localhost"||t==="127.0.0.1"||t==="::1"||t==="0.0.0.0"||t==="host.docker.internal")return!0;return t.endsWith(".localhost")||t.endsWith(".local")||t.endsWith(".local.burdenoff.com")}function si(e){if(!(process.env.VIBE_DEV_INSECURE_TLS==="1"||process.env.NODE_TLS_REJECT_UNAUTHORIZED==="0")&&!Ya(e))return{};return{tls:{rejectUnauthorized:!1}}}async function Wa(e,t,i){let s=await fetch(ii(e),{method:"POST",...si(e),headers:{"Content-Type":"application/json"},body:JSON.stringify({query:`mutation AuthenticateApp($input: AuthenticateAppInput!) {
|
|
3
3
|
authenticateApp(input: $input) { accessToken expiresIn }
|
|
4
4
|
}`,variables:{input:{clientId:t,clientSecret:i,scopes:[]}}}),signal:AbortSignal.timeout(15000)}),n=await ti(s,"authenticateApp"),r=ei(n.errors,"authenticateApp");if(r)throw r;if(n.errors?.length){let l=n.errors.map((o)=>o.extensions?.code??"UNKNOWN").join(",");throw Error(`authenticateApp errors [${l}]: ${n.errors.map((o)=>o.message).join("; ")}`)}let a=n.data?.authenticateApp?.accessToken;if(!a)throw Error("authenticateApp returned no token");return a}async function Qa(e,t,i,s){let n=await fetch(ii(e),{method:"POST",...si(e),headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({query:`mutation IssueAgentWorkspaceToken($input: IssueWorkspaceTokenInput!) {
|
|
5
5
|
issueWorkspaceToken(input: $input) {
|
|
@@ -174,5 +174,5 @@ data: /message
|
|
|
174
174
|
mutation NotifyVibecontrolsAgentPluginChange($agentId: ID!) {
|
|
175
175
|
notifyVibecontrolsAgentPluginChange(agentId: $agentId)
|
|
176
176
|
}
|
|
177
|
-
`;async function Cd(e){try{if(!v.isConfigured())return;let t=await e.getConfig("gateway-auth:agentRecordId");if(!t)return;let i=await v.workspaceQuery(Dh,{agentId:t});if(i.errors?.length)g().logger.debug(y,"Plugin-change notify returned errors",{errors:i.errors.map((s)=>s.message)})}catch(t){g().logger.debug(y,`Plugin-change notify failed: ${t instanceof Error?t.message:String(t)}`)}}var ut=null,_t=null;function wt(e,t,i){if(ut)return;let s=Number(process.env.VIBE_TUNNEL_SYNC_MS),n=Number.isFinite(s)&&s>0?s:i??60000;ut=setInterval(async()=>{if(!v.isConfigured())return;try{let r=t.getProvider("tunnel");if(!r||!r.getActiveTunnelUrl)return;let a=os(await r.getActiveTunnelUrl()),l=await e.getConfig("gateway-auth:agentRecordId");if(!l)return;if(await Vt(l),!a)return;let o=v.getConfig()?.workspaceId||"",c;if(o)c=(await v.workspaceQuery(Yt,{workspaceId:o})).data?.vibecontrolsAgents?.find((f)=>f.id===l)?.tunnelUrl??null;let h=a!==_t,u=c!==void 0&&c!==a;if(!h&&!u)return;g().logger.info(y,"Re-publishing tunnel URL",{reason:u?"backend-drift":"local-change",backend:c,local:a,lastReported:_t});let d=await v.workspaceQuery(Jt,{id:l,input:{tunnelUrl:a,tunnelStatus:"CONNECTED"}});if(!d.errors?.length)_t=a,g().logger.info(y,"Tunnel URL synced to backend",{tunnelUrl:a});else g().logger.warn(y,"Tunnel URL sync returned errors",{errors:d.errors.map((_)=>_.message)})}catch(r){g().logger.debug(y,`Tunnel sync check failed: ${r instanceof Error?r.message:String(r)}`)}},n),ut.unref?.()}function Rd(){if(ut)clearInterval(ut),ut=null}async function kd(e,t,i){if(!v.isConfigured()){g().logger.debug(y,"Gateway auth not configured \u2014 skipping auto-report");return}let s=await e.getConfig("gateway-auth:workspaceId");if(!s){g().logger.warn(y,"No workspaceId configured \u2014 skipping auto-report. "+"Configure via POST /api/agent/gateway-auth with workspaceId.");return}g().logger.info(y,"Starting auto-report to backend...");try{let n=process.env.VIBE_AGENT_NAME||Ht.hostname(),r=Ht.platform(),a=Ht.arch(),l=ka(),o=await Nh(t),c=await as(e,n);if(c){g().logger.info(y,`Updating agent record ${c} via workspace gateway`);let u=await v.workspaceQuery(Jt,{id:c,input:{tunnelUrl:o||null,tunnelStatus:o?"CONNECTED":"DISCONNECTED",agentApiKey:i}});if(u.errors?.length){if(g().logger.warn(y,"Update mutation returned errors",{errors:u.errors.map((_)=>_.message)}),await $h(s,c)){g().logger.warn(y,"Agent record still exists \u2014 treating update failure as transient; will retry on next sync (NOT registering a duplicate)",{agentRecordId:c}),await Ca(s,{hostname:n,platform:r,arch:a,tunnelUrl:o,apiKey:i}),await Vt(c),_t=o,wt(e,t),dt(e);return}g().logger.info(y,"Cached agent record no longer exists \u2014 clearing cache and registering fresh",{agentRecordId:c}),await e.setConfig("gateway-auth:agentRecordId",""),c=null}else{g().logger.info(y,"Agent record updated successfully",{agentRecordId:c,tunnelUrl:o}),await Da(c,o,s),await Ca(s,{hostname:n,platform:r,arch:a,tunnelUrl:o,apiKey:i}),await Vt(c),_t=o,wt(e,t),dt(e);return}}g().logger.info(y,`Registering installed agent via workspace gateway (hostname: ${n})`);for(let u=1;u<=Fe&&!c;u++){if(u>1){let p=await as(e,n);if(p){c=p,g().logger.info(y,"Adopted an agent record discovered after a retry (not registering a duplicate)",{agentRecordId:c});break}}let d=await v.workspaceQuery(La,{workspaceId:s,input:{name:n,hostname:n,platform:r,architecture:a,tunnelUrl:o||null,agentApiKey:i}}),_=d.errors?.length?void 0:d.data?.registerInstalledAgent?.id;if(_){await e.setConfig("gateway-auth:agentRecordId",_),c=_,g().logger.info(y,"Agent registered successfully",{agentRecordId:_,name:d.data?.registerInstalledAgent?.name,tunnelUrl:o,version:l,attempt:u});break}let f=d.errors?.length?d.errors.map((p)=>p.message):["registerInstalledAgent returned no id"];if(u<Fe){let p=Math.min(30000,rs*2**(u-1));g().logger.warn(y,`Register installed agent failed (attempt ${u}/${Fe}) \u2014 retrying in ${Math.round(p/1000)}s`,{errors:f}),await new Promise((m)=>setTimeout(m,p));continue}g().logger.error(y,"Register installed agent failed after retries \u2014 agent is running but NOT registered with the workspace",{errors:f}),g().recordDegradedReason("agent-registration",`registerInstalledAgent failed after ${Fe} attempts: ${f.join("; ")}`)}if(!c){wt(e,t),dt(e);return}let h=await v.workspaceQuery(Jt,{id:c,input:{tunnelUrl:o||null,tunnelStatus:o?"CONNECTED":"DISCONNECTED"}});if(h.errors?.length)g().logger.warn(y,"Post-registration agent update returned errors",{errors:h.errors.map((u)=>u.message)});else g().logger.info(y,"Post-registration agent sync completed",{agentRecordId:c,tunnelUrl:o});if(await Da(c,o,s),await Vt(c),_t=o,wt(e,t),dt(e),process.env.VIBE_BRIDGE_DISABLED!=="1")try{let{bridgeClient:u}=await import("./bridge-client-1fxza4p7.js"),d=process.env.VIBECONTROLS_PROFILE||"default";u.start(c,d)}catch(u){g().logger.warn(y,`bridge-client start failed: ${u instanceof Error?u.message:String(u)}`)}}catch(n){g().logger.error(y,`Auto-report failed: ${n instanceof Error?n.message:String(n)}`);try{wt(e,t),dt(e)}catch{}}}var S="lifecycle";class ls{serviceRegistry;pluginManager;db;app;hostServices;appStopFn;state="running";transition=Promise.resolve();constructor(e,t,i,s,n,r){this.serviceRegistry=e;this.pluginManager=t;this.db=i;this.app=s;this.hostServices=n;this.appStopFn=r}getState(){return this.state}enqueueTransition(e,t){let i=this.transition.then(t,t);return this.transition=i.catch((s)=>{g().logger.warn(S,`Lifecycle transition '${e}' failed`,{error:String(s)})}),i}async stop(){return this.enqueueTransition("stop",async()=>{if(this.state==="stopped"){g().logger.warn(S,"Agent is already stopped");return}g().logger.info(S,"Stopping agent..."),this.state="stopped";let e=this.serviceRegistry.getProvider("session");if(e)try{let t=await e.list();for(let i of t)if(i.status==="active")try{await e.kill(i.id),g().logger.debug(S,`Killed session ${i.id}`)}catch(s){g().logger.warn(S,`Failed to kill session ${i.id}`,{error:String(s)})}}catch(t){g().logger.warn(S,"Failed to list/stop sessions",{error:String(t)})}try{await this.pluginManager.dispatchServerStop()}catch(t){g().logger.warn(S,"Error during plugin stop dispatch",{error:String(t)})}g().logger.info(S,"Agent stopped (tunnel + HTTP still alive)");try{await Wt(this.db,"stopped")}catch(t){g().logger.warn(S,"Failed to report stopped state to backend",{error:String(t)})}})}async start(){return this.enqueueTransition("start",async()=>{if(this.state==="running"){g().logger.warn(S,"Agent is already running");return}g().logger.info(S,"Starting agent..."),this.state="running";try{await this.pluginManager.dispatchServerStart(this.app,this.hostServices),await this.pluginManager.dispatchServerReady(this.app,this.hostServices)}catch(e){g().logger.warn(S,"Error during plugin start dispatch",{error:String(e)})}g().logger.info(S,"Agent started");try{await Wt(this.db,"running")}catch(e){g().logger.warn(S,"Failed to report running state to backend",{error:String(e)})}})}async softStop(){return this.enqueueTransition("softStop",async()=>{g().logger.info(S,"Soft-stopping agent (hot-reload)...");try{await this.pluginManager.dispatchServerStop({reason:"reload"})}catch(e){g().logger.warn(S,"Error during plugin soft-stop dispatch",{error:String(e)})}try{await this.appStopFn({reason:"reload"})}catch{}g().logger.info(S,"Agent soft-stopped \u2014 exiting for reload"),process.exit(0)})}async prepareForReset(){return this.enqueueTransition("prepareForReset",async()=>{g().logger.info(S,"Preparing agent for reset..."),this.state="stopped";try{await this.pluginManager.dispatchServerStop({reason:"shutdown"})}catch(e){g().logger.warn(S,"Error during reset stop dispatch",{error:String(e)})}})}async kill(){return this.enqueueTransition("kill",async()=>{g().logger.info(S,"Killing agent...");try{await Promise.race([Wt(this.db,"killed"),new Promise((t,i)=>setTimeout(()=>i(Error("Timeout")),5000))])}catch(t){g().logger.warn(S,"Failed to report killed state to backend",{error:String(t)})}let e=this.serviceRegistry.getProvider("tunnel");if(e)try{let t=await e.list();for(let i of t)try{await e.stop(i.id)}catch{}}catch(t){g().logger.warn(S,"Failed to stop tunnels",{error:String(t)})}try{await this.appStopFn()}catch{}g().logger.info(S,"Agent killed \u2014 exiting process"),process.exit(0)})}}async function Ch(e){let t=await Rh(e);if(t)return t;return kh(e.name)}async function Rh(e){let t;try{t=await yt({dir:e.dataDir,scope:e.name})}catch{return null}if(!t.clientId||!t.clientSecret||!t.globalGatewayUrl||!t.workspaceGatewayUrl||!t.workspaceId)return null;return{clientId:t.clientId,clientSecret:t.clientSecret,globalGatewayUrl:t.globalGatewayUrl,workspaceGatewayUrl:t.workspaceGatewayUrl,workspaceId:t.workspaceId,organizationId:t.organizationId}}function kh(e){let t=e.replace(/[^A-Za-z0-9_]/g,"_").toUpperCase(),i=(o)=>process.env[`VIBE_${t}_${o}`],s=i("CLIENT_ID"),n=i("CLIENT_SECRET"),r=i("GLOBAL_GATEWAY_URL"),a=i("WORKSPACE_GATEWAY_URL"),l=i("WORKSPACE_ID");if(!s||!n||!r||!a||!l)return null;return{clientId:s,clientSecret:n,globalGatewayUrl:r,workspaceGatewayUrl:a,workspaceId:l,organizationId:i("ORGANIZATION_ID")}}async function Na(e){let t=await Ch(e);if(!t)return{ok:!1,error:`no creds for profile '${e.name}' (run gateway-auth against this profile or set VIBE_${e.name.toUpperCase()}_* env vars)`};e.setBootState("initializing");let i;try{let l=await hs(t);i=await va({dbPath:e.dataDir,encryptionKey:l})}catch(l){return e.setBootState("awaiting-config"),{ok:!1,error:l instanceof Error?l.message:String(l)}}let s=new qa(i);await s.hydrateDefaultsFromDb();let n=new Ua(i);await n.loadCorePlugins();try{await n.loadAll()}catch(l){e.logger.warn("secondary-profile-attach","failed to load some external plugins for secondary profile",{error:l instanceof Error?l.message:String(l)})}let r={storage:{async get(l,o){return await i.getPluginState(l,o)??null},async set(l,o,c){await i.setPluginState(l,o,c)},async delete(l,o){return i.deletePluginState(l,o)},async list(l){return await i.getAllPluginState(l)},async deleteAll(l){return i.deleteAllPluginState(l)}},logger:e.logger,serviceRegistry:s,getProvider:(l)=>s.getProvider(l),getAgentBaseUrl:()=>process.env.AGENT_URL||"http://localhost:0",getAgentVersion:()=>"0.0.0",broadcast:()=>{},workspaceQuery:async()=>({}),isGatewayConfigured:()=>!0,getAgentRecordId:async()=>await i.getConfig("gateway-auth:agentRecordId")??null,getWorkspaceId:async()=>await i.getConfig("gateway-auth:workspaceId")??null,getConfig:async(l)=>await i.getConfig(l)??void 0,getPluginRegistry:()=>"",getDataDir:()=>e.dataDir,cliContributors:new Ka,audit:{emit:(l,o)=>e.audit.emit("agent",l,o??{})},telemetry:{emit:()=>{}},os:Pa(),iframeBridge:Fa()},a=new ls(s,n,i,{},r,async()=>{});s.registerService("agent","lifecycle",a),e.attachServices({db:i,serviceRegistry:s,pluginManager:n,lifecycle:a,hostServices:r});try{ja(e)}catch(l){e.logger.warn("secondary-profile-attach","failed to mount per-profile plugin routes",{error:l instanceof Error?l.message:String(l)})}try{await e.keyVault.bindApiKey(Ma())}catch{}return e.setBootState("ready"),{ok:!0}}
|
|
177
|
+
`;async function Cd(e){try{if(!v.isConfigured())return;let t=await e.getConfig("gateway-auth:agentRecordId");if(!t)return;let i=await v.workspaceQuery(Dh,{agentId:t});if(i.errors?.length)g().logger.debug(y,"Plugin-change notify returned errors",{errors:i.errors.map((s)=>s.message)})}catch(t){g().logger.debug(y,`Plugin-change notify failed: ${t instanceof Error?t.message:String(t)}`)}}var ut=null,_t=null;function wt(e,t,i){if(ut)return;let s=Number(process.env.VIBE_TUNNEL_SYNC_MS),n=Number.isFinite(s)&&s>0?s:i??60000;ut=setInterval(async()=>{if(!v.isConfigured())return;try{let r=t.getProvider("tunnel");if(!r||!r.getActiveTunnelUrl)return;let a=os(await r.getActiveTunnelUrl()),l=await e.getConfig("gateway-auth:agentRecordId");if(!l)return;if(await Vt(l),!a)return;let o=v.getConfig()?.workspaceId||"",c;if(o)c=(await v.workspaceQuery(Yt,{workspaceId:o})).data?.vibecontrolsAgents?.find((f)=>f.id===l)?.tunnelUrl??null;let h=a!==_t,u=c!==void 0&&c!==a;if(!h&&!u)return;g().logger.info(y,"Re-publishing tunnel URL",{reason:u?"backend-drift":"local-change",backend:c,local:a,lastReported:_t});let d=await v.workspaceQuery(Jt,{id:l,input:{tunnelUrl:a,tunnelStatus:"CONNECTED"}});if(!d.errors?.length)_t=a,g().logger.info(y,"Tunnel URL synced to backend",{tunnelUrl:a});else g().logger.warn(y,"Tunnel URL sync returned errors",{errors:d.errors.map((_)=>_.message)})}catch(r){g().logger.debug(y,`Tunnel sync check failed: ${r instanceof Error?r.message:String(r)}`)}},n),ut.unref?.()}function Rd(){if(ut)clearInterval(ut),ut=null}async function kd(e,t,i){if(!v.isConfigured()){g().logger.debug(y,"Gateway auth not configured \u2014 skipping auto-report");return}let s=await e.getConfig("gateway-auth:workspaceId");if(!s){g().logger.warn(y,"No workspaceId configured \u2014 skipping auto-report. "+"Configure via POST /api/agent/gateway-auth with workspaceId.");return}g().logger.info(y,"Starting auto-report to backend...");try{let n=process.env.VIBE_AGENT_NAME||Ht.hostname(),r=Ht.platform(),a=Ht.arch(),l=ka(),o=await Nh(t),c=await as(e,n);if(c){g().logger.info(y,`Updating agent record ${c} via workspace gateway`);let u=await v.workspaceQuery(Jt,{id:c,input:{tunnelUrl:o||null,tunnelStatus:o?"CONNECTED":"DISCONNECTED",agentApiKey:i}});if(u.errors?.length){if(g().logger.warn(y,"Update mutation returned errors",{errors:u.errors.map((_)=>_.message)}),await $h(s,c)){g().logger.warn(y,"Agent record still exists \u2014 treating update failure as transient; will retry on next sync (NOT registering a duplicate)",{agentRecordId:c}),await Ca(s,{hostname:n,platform:r,arch:a,tunnelUrl:o,apiKey:i}),await Vt(c),_t=o,wt(e,t),dt(e);return}g().logger.info(y,"Cached agent record no longer exists \u2014 clearing cache and registering fresh",{agentRecordId:c}),await e.setConfig("gateway-auth:agentRecordId",""),c=null}else{g().logger.info(y,"Agent record updated successfully",{agentRecordId:c,tunnelUrl:o}),await Da(c,o,s),await Ca(s,{hostname:n,platform:r,arch:a,tunnelUrl:o,apiKey:i}),await Vt(c),_t=o,wt(e,t),dt(e);return}}g().logger.info(y,`Registering installed agent via workspace gateway (hostname: ${n})`);for(let u=1;u<=Fe&&!c;u++){if(u>1){let p=await as(e,n);if(p){c=p,g().logger.info(y,"Adopted an agent record discovered after a retry (not registering a duplicate)",{agentRecordId:c});break}}let d=await v.workspaceQuery(La,{workspaceId:s,input:{name:n,hostname:n,platform:r,architecture:a,tunnelUrl:o||null,agentApiKey:i}}),_=d.errors?.length?void 0:d.data?.registerInstalledAgent?.id;if(_){await e.setConfig("gateway-auth:agentRecordId",_),c=_,g().logger.info(y,"Agent registered successfully",{agentRecordId:_,name:d.data?.registerInstalledAgent?.name,tunnelUrl:o,version:l,attempt:u});break}let f=d.errors?.length?d.errors.map((p)=>p.message):["registerInstalledAgent returned no id"];if(u<Fe){let p=Math.min(30000,rs*2**(u-1));g().logger.warn(y,`Register installed agent failed (attempt ${u}/${Fe}) \u2014 retrying in ${Math.round(p/1000)}s`,{errors:f}),await new Promise((m)=>setTimeout(m,p));continue}g().logger.error(y,"Register installed agent failed after retries \u2014 agent is running but NOT registered with the workspace",{errors:f}),g().recordDegradedReason("agent-registration",`registerInstalledAgent failed after ${Fe} attempts: ${f.join("; ")}`)}if(!c){wt(e,t),dt(e);return}let h=await v.workspaceQuery(Jt,{id:c,input:{tunnelUrl:o||null,tunnelStatus:o?"CONNECTED":"DISCONNECTED"}});if(h.errors?.length)g().logger.warn(y,"Post-registration agent update returned errors",{errors:h.errors.map((u)=>u.message)});else g().logger.info(y,"Post-registration agent sync completed",{agentRecordId:c,tunnelUrl:o});if(await Da(c,o,s),await Vt(c),_t=o,wt(e,t),dt(e),process.env.VIBE_BRIDGE_DISABLED!=="1")try{let{bridgeClient:u}=await import("./bridge-client-73z9c5nm.js"),d=process.env.VIBECONTROLS_PROFILE||"default";u.start(c,d)}catch(u){g().logger.warn(y,`bridge-client start failed: ${u instanceof Error?u.message:String(u)}`)}}catch(n){g().logger.error(y,`Auto-report failed: ${n instanceof Error?n.message:String(n)}`);try{wt(e,t),dt(e)}catch{}}}var S="lifecycle";class ls{serviceRegistry;pluginManager;db;app;hostServices;appStopFn;state="running";transition=Promise.resolve();constructor(e,t,i,s,n,r){this.serviceRegistry=e;this.pluginManager=t;this.db=i;this.app=s;this.hostServices=n;this.appStopFn=r}getState(){return this.state}enqueueTransition(e,t){let i=this.transition.then(t,t);return this.transition=i.catch((s)=>{g().logger.warn(S,`Lifecycle transition '${e}' failed`,{error:String(s)})}),i}async stop(){return this.enqueueTransition("stop",async()=>{if(this.state==="stopped"){g().logger.warn(S,"Agent is already stopped");return}g().logger.info(S,"Stopping agent..."),this.state="stopped";let e=this.serviceRegistry.getProvider("session");if(e)try{let t=await e.list();for(let i of t)if(i.status==="active")try{await e.kill(i.id),g().logger.debug(S,`Killed session ${i.id}`)}catch(s){g().logger.warn(S,`Failed to kill session ${i.id}`,{error:String(s)})}}catch(t){g().logger.warn(S,"Failed to list/stop sessions",{error:String(t)})}try{await this.pluginManager.dispatchServerStop()}catch(t){g().logger.warn(S,"Error during plugin stop dispatch",{error:String(t)})}g().logger.info(S,"Agent stopped (tunnel + HTTP still alive)");try{await Wt(this.db,"stopped")}catch(t){g().logger.warn(S,"Failed to report stopped state to backend",{error:String(t)})}})}async start(){return this.enqueueTransition("start",async()=>{if(this.state==="running"){g().logger.warn(S,"Agent is already running");return}g().logger.info(S,"Starting agent..."),this.state="running";try{await this.pluginManager.dispatchServerStart(this.app,this.hostServices),await this.pluginManager.dispatchServerReady(this.app,this.hostServices)}catch(e){g().logger.warn(S,"Error during plugin start dispatch",{error:String(e)})}g().logger.info(S,"Agent started");try{await Wt(this.db,"running")}catch(e){g().logger.warn(S,"Failed to report running state to backend",{error:String(e)})}})}async softStop(){return this.enqueueTransition("softStop",async()=>{g().logger.info(S,"Soft-stopping agent (hot-reload)...");try{await this.pluginManager.dispatchServerStop({reason:"reload"})}catch(e){g().logger.warn(S,"Error during plugin soft-stop dispatch",{error:String(e)})}try{await this.appStopFn({reason:"reload"})}catch{}g().logger.info(S,"Agent soft-stopped \u2014 exiting for reload"),process.exit(0)})}async prepareForReset(){return this.enqueueTransition("prepareForReset",async()=>{g().logger.info(S,"Preparing agent for reset..."),this.state="stopped";try{await this.pluginManager.dispatchServerStop({reason:"shutdown"})}catch(e){g().logger.warn(S,"Error during reset stop dispatch",{error:String(e)})}})}async kill(){return this.enqueueTransition("kill",async()=>{g().logger.info(S,"Killing agent...");try{await Promise.race([Wt(this.db,"killed"),new Promise((t,i)=>setTimeout(()=>i(Error("Timeout")),5000))])}catch(t){g().logger.warn(S,"Failed to report killed state to backend",{error:String(t)})}let e=this.serviceRegistry.getProvider("tunnel");if(e)try{let t=await e.list();for(let i of t)try{await e.stop(i.id)}catch{}}catch(t){g().logger.warn(S,"Failed to stop tunnels",{error:String(t)})}try{await this.appStopFn()}catch{}g().logger.info(S,"Agent killed \u2014 exiting process"),process.exit(0)})}}async function Ch(e){let t=await Rh(e);if(t)return t;return kh(e.name)}async function Rh(e){let t;try{t=await yt({dir:e.dataDir,scope:e.name})}catch{return null}if(!t.clientId||!t.clientSecret||!t.globalGatewayUrl||!t.workspaceGatewayUrl||!t.workspaceId)return null;return{clientId:t.clientId,clientSecret:t.clientSecret,globalGatewayUrl:t.globalGatewayUrl,workspaceGatewayUrl:t.workspaceGatewayUrl,workspaceId:t.workspaceId,organizationId:t.organizationId}}function kh(e){let t=e.replace(/[^A-Za-z0-9_]/g,"_").toUpperCase(),i=(o)=>process.env[`VIBE_${t}_${o}`],s=i("CLIENT_ID"),n=i("CLIENT_SECRET"),r=i("GLOBAL_GATEWAY_URL"),a=i("WORKSPACE_GATEWAY_URL"),l=i("WORKSPACE_ID");if(!s||!n||!r||!a||!l)return null;return{clientId:s,clientSecret:n,globalGatewayUrl:r,workspaceGatewayUrl:a,workspaceId:l,organizationId:i("ORGANIZATION_ID")}}async function Na(e){let t=await Ch(e);if(!t)return{ok:!1,error:`no creds for profile '${e.name}' (run gateway-auth against this profile or set VIBE_${e.name.toUpperCase()}_* env vars)`};e.setBootState("initializing");let i;try{let l=await hs(t);i=await va({dbPath:e.dataDir,encryptionKey:l})}catch(l){return e.setBootState("awaiting-config"),{ok:!1,error:l instanceof Error?l.message:String(l)}}let s=new qa(i);await s.hydrateDefaultsFromDb();let n=new Ua(i);await n.loadCorePlugins();try{await n.loadAll()}catch(l){e.logger.warn("secondary-profile-attach","failed to load some external plugins for secondary profile",{error:l instanceof Error?l.message:String(l)})}let r={storage:{async get(l,o){return await i.getPluginState(l,o)??null},async set(l,o,c){await i.setPluginState(l,o,c)},async delete(l,o){return i.deletePluginState(l,o)},async list(l){return await i.getAllPluginState(l)},async deleteAll(l){return i.deleteAllPluginState(l)}},logger:e.logger,serviceRegistry:s,getProvider:(l)=>s.getProvider(l),getAgentBaseUrl:()=>process.env.AGENT_URL||"http://localhost:0",getAgentVersion:()=>"0.0.0",broadcast:()=>{},workspaceQuery:async()=>({}),isGatewayConfigured:()=>!0,getAgentRecordId:async()=>await i.getConfig("gateway-auth:agentRecordId")??null,getWorkspaceId:async()=>await i.getConfig("gateway-auth:workspaceId")??null,getConfig:async(l)=>await i.getConfig(l)??void 0,getPluginRegistry:()=>"",getDataDir:()=>e.dataDir,cliContributors:new Ka,audit:{emit:(l,o)=>e.audit.emit("agent",l,o??{})},telemetry:{emit:()=>{}},os:Pa(),iframeBridge:Fa()},a=new ls(s,n,i,{},r,async()=>{});s.registerService("agent","lifecycle",a),e.attachServices({db:i,serviceRegistry:s,pluginManager:n,lifecycle:a,hostServices:r});try{ja(e)}catch(l){e.logger.warn("secondary-profile-attach","failed to mount per-profile plugin routes",{error:l instanceof Error?l.message:String(l)})}try{await e.keyVault.bindApiKey(Ma())}catch{}return e.setBootState("ready"),{ok:!0}}
|
|
178
178
|
export{va as u,hs as v,ls as w,Na as x,Sd as y,Cd as z,Rd as A,kd as B};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Sa as k}from"./index-
|
|
2
|
+
import{Sa as k}from"./index-cv0xhb46.js";import{Eb as F,Fb as h,Gb as S,Hb as q,Jb as N,wb as f,zb as c}from"./index-bfeekmyh.js";import{Vb as P}from"./index-pgew6sge.js";import{Od as V}from"./index-xnr6t79p.js";var U=["tunnel","session","ai","plan","gitops","security"];class m{providers=new Map;providerOrder=new Map;defaults=new Map;services=new Map;db;constructor(z){this.db=z}getDb(){return this.db}setProviderDefault(z,J){this.defaults.set(z,J)}clearProviderDefault(z,J){if(!J||this.defaults.get(z)===J)this.defaults.delete(z)}async hydrateDefaultsFromDb(){if(!this.db)return;for(let z of U)try{let J=await this.db.getConfig(`provider:default:${z}`);if(J)this.defaults.set(z,J)}catch{}}registerProvider(z,J,Q){if(!this.providers.has(z))this.providers.set(z,new Map),this.providerOrder.set(z,[]);let W=this.providers.get(z),Z=this.providerOrder.get(z);if(W.has(Q))V().logger.info("service-registry",`Updating ${z} provider from plugin '${Q}'`);else V().logger.info("service-registry",`Registered ${z} provider from plugin '${Q}'`);if(W.set(Q,{provider:J,pluginName:Q,registeredAt:new Date}),!Z.includes(Q))Z.push(Q)}getProvider(z){let J=this.providers.get(z);if(!J||J.size===0)return;let Q=this.defaults.get(z);if(Q&&J.has(Q))return J.get(Q).provider;let W=this.providerOrder.get(z);if(W&&W.length>0){let Z=W[0];return J.get(Z)?.provider}return}getProviderByName(z,J){let Q=this.providers.get(z);if(!Q)return;return Q.get(J)?.provider}hasProvider(z){let J=this.providers.get(z);return!!J&&J.size>0}unregisterProvider(z,J){let Q=this.providers.get(z);if(!Q)return!1;let W=Q.delete(J);if(W){let Z=this.providerOrder.get(z);if(Z){let X=Z.indexOf(J);if(X!==-1)Z.splice(X,1)}this.clearProviderDefault(z,J),V().logger.info("service-registry",`Unregistered ${z} provider from plugin '${J}'`)}return W}unregisterPlugin(z){for(let J of U)this.unregisterProvider(J,z);this.unregisterServices(z)}listProvidersForType(z){let J=this.providers.get(z);if(!J)return[];let Q=this.defaults.get(z);if(!Q||!J.has(Q)){let W=this.providerOrder.get(z);Q=W&&W.length>0?W[0]:void 0}return Array.from(J.keys()).map((W)=>({pluginName:W,isDefault:W===Q}))}registerService(z,J,Q){let W=`${z}:${J}`;this.services.set(W,{service:Q,pluginName:z}),V().logger.debug("service-registry",`Registered service '${W}'`)}getService(z,J){let Q=`${z}:${J}`;return this.services.get(Q)?.service}unregisterServices(z){let J=[];for(let[Q,W]of this.services)if(W.pluginName===z)J.push(Q);for(let Q of J)this.services.delete(Q);if(J.length>0)V().logger.info("service-registry",`Unregistered ${J.length} services from ${z}`)}listProviders(){let z=[];for(let[J,Q]of this.providers)for(let[W,Z]of Q)z.push({type:J,name:W,pluginName:Z.pluginName});return z}listServices(){return Array.from(this.services.entries()).map(([z,J])=>({pluginName:J.pluginName,serviceName:z.split(":").slice(1).join(":")}))}clear(){this.providers.clear(),this.providerOrder.clear(),this.defaults.clear(),this.services.clear()}}import{extname as g,relative as o,resolve as u}from"path";import{realpath as E}from"fs/promises";var n=["'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"],D=!1;function w(){let z=process.env.VIBE_UI_FRAME_ANCESTORS?.trim(),J=z?z.split(/[\s,]+/).filter(Boolean):n;if(z&&!D&&(J.includes("*")||!J.includes("'self'")))D=!0,console.warn(`[ui-server] VIBE_UI_FRAME_ANCESTORS override does not include "'self'" or contains "*". This significantly weakens CSP frame-ancestors and is almost never intended. Override: ${z}`);return`frame-ancestors ${J.join(" ")}`}var l={".html":"text/html",".js":"application/javascript",".mjs":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json",".wasm":"application/wasm"};function s(z){return l[g(z).toLowerCase()]||"application/octet-stream"}var b=`<script>
|
|
3
3
|
window.__VIBE_AUTH__={apiKey:null};
|
|
4
4
|
(function(){
|
|
5
5
|
var p=new URLSearchParams(window.location.search);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Od as p}from"./index-
|
|
2
|
+
import{Od as p}from"./index-xnr6t79p.js";import{$d as wq,Rd as K,Yd as Mq,ce as j}from"./index-a4854mwz.js";import{existsSync as G,mkdirSync as u,readdirSync as mq,readFileSync as B,renameSync as P,rmSync as oq,writeFileSync as D}from"fs";import{dirname as k,join as v}from"path";import{randomUUID as pq}from"crypto";import{existsSync as b,mkdirSync as d,readFileSync as Zq,renameSync as Jq,unlinkSync as Tq,writeFileSync as F}from"fs";import{dirname as E,join as V}from"path";import{spawnSync as r}from"child_process";import{hostname as Lq,networkInterfaces as xq,platform as Xq,userInfo as Cq}from"os";import{createCipheriv as Fq,createDecipheriv as Nq,pbkdf2Sync as Aq,randomBytes as Rq}from"crypto";var n="secrets:fallback",Wq="secrets:index",t=10,uq=100,a=new Map;function Hq(q,Q){let $=`${q}:${Q}`,z=(a.get($)??0)+1;if(a.set($,z),z<=t)return!0;return(z-t)%uq===0}var C="vibecontrols-agent",Yq=".libsecret-install-attempted",jq="secrets.json";function Pq(){return globalThis.Bun?.secrets??null}class S{api;kind="bun-secrets";constructor(q){this.api=q}async get(q){return this.api.get({service:C,name:q})}async set(q,Q){await this.api.set({service:C,name:q,value:Q}),await yq(q)}async delete(q){let Q=await this.api.delete({service:C,name:q});return await lq(q),Q}async list(q){return Eq(q)}}var Gq=".secrets-encrypted-v1",kq=1e5,vq=32,Iq="sha256",L=null,e=null;function _q(){let q=xq();for(let Q of Object.values(q)){if(!Q)continue;for(let $ of Q){let z=$?.mac;if(z&&z!=="00:00:00:00:00:00")return z}}return"no-mac"}function qq(){if(e!==null)return e;let q;try{q=Cq().username||"unknown"}catch{q=process.env.USER||process.env.USERNAME||"unknown"}return`${Lq()}|${q}|${_q()}`}function Vq(){if(L)return L;let q=`vibecontrols-agent::${qq()}`;return L=Aq(q,qq(),kq,vq,Iq),L}function Qq(q){let Q=Rq(12),$=Fq("aes-256-gcm",Vq(),Q),z=Buffer.concat([$.update(q,"utf8"),$.final()]),Z=$.getAuthTag();return`${Q.toString("hex")}:${Z.toString("hex")}:${z.toString("hex")}`}function hq(q){let Q=q.split(":");if(Q.length!==3)return!1;let[$,z,Z]=Q;return/^[0-9a-f]+$/i.test($)&&$.length===24&&/^[0-9a-f]+$/i.test(z)&&z.length===32&&/^[0-9a-f]*$/i.test(Z)}function gq(q){if(!hq(q))return null;try{let[Q,$,z]=q.split(":"),Z=Nq("aes-256-gcm",Vq(),Buffer.from(Q,"hex"));return Z.setAuthTag(Buffer.from($,"hex")),Buffer.concat([Z.update(Buffer.from(z,"hex")),Z.final()]).toString("utf8")}catch{return null}}class Kq{kind="json-fallback";path;constructor(){this.path=V(j(),jq)}async get(q){let{plain:Q}=this.readWithMigration(),$=Q[q];return typeof $==="string"?$:null}async set(q,Q){await K(n,async()=>{let{encrypted:$}=this.readWithMigration();$[q]=Qq(Q),this.writeEncrypted($)})}async delete(q){return K(n,async()=>{let{encrypted:Q}=this.readWithMigration();if(!(q in Q))return!1;return delete Q[q],this.writeEncrypted(Q),!0})}async list(q){let{encrypted:Q}=this.readWithMigration(),$=Object.keys(Q);return(q?$.filter((Z)=>Z.startsWith(q)):$).sort().map((Z)=>({name:Z}))}readWithMigration(){if(!b(this.path))return{encrypted:{},plain:{}};let q;try{q=Zq(this.path,"utf8")}catch{return{encrypted:{},plain:{}}}let Q;try{Q=JSON.parse(q)}catch{return{encrypted:{},plain:{}}}if(!Q||typeof Q!=="object"||Array.isArray(Q))return{encrypted:{},plain:{}};let $={},z={},Z=!1;for(let[J,X]of Object.entries(Q)){if(typeof X!=="string")continue;let Y=gq(X);if(Y!==null){$[J]=X,z[J]=Y;continue}$[J]=Qq(X),z[J]=X,Z=!0}if(Z)try{this.writeEncrypted($),this.writeMarker()}catch{}return{encrypted:$,plain:z}}writeEncrypted(q){d(E(this.path),{recursive:!0});let Q=`${this.path}.${process.pid}.tmp`;if(F(Q,`${JSON.stringify(q,null,2)}
|
|
3
3
|
`,{mode:384}),Jq(Q,this.path),!b(this.markerPath()))this.writeMarker()}markerPath(){return V(E(this.path),Gq)}writeMarker(){try{F(this.markerPath(),`${new Date().toISOString()}
|
|
4
4
|
`,{mode:384})}catch{}}}var fq=".secrets-index.json";function m(){return V(j(),fq)}function o(){let q=m();if(!b(q))return new Set;try{let Q=Zq(q,"utf8"),$=JSON.parse(Q);if(Array.isArray($))return new Set($.filter((z)=>typeof z==="string"))}catch{}return new Set}function Uq(q){let Q=m();d(E(Q),{recursive:!0});let $=`${Q}.${process.pid}.tmp`;F($,`${JSON.stringify([...q].sort(),null,2)}
|
|
5
5
|
`,{mode:384}),Jq($,Q)}async function yq(q){await K(Wq,()=>{let Q=o();if(Q.has(q))return;Q.add(q),Uq(Q)})}async function lq(q){await K(Wq,()=>{let Q=o();if(!Q.delete(q))return;Uq(Q)})}function Eq(q){let $=[...o()];return(q?$.filter((Z)=>Z.startsWith(q)):$).sort().map((Z)=>({name:Z}))}function Sq(){if(Xq()!=="linux")return{ok:!1};if(process.env.CI==="true")return{ok:!1,warning:"CI/test environment detected; using JSON fallback"};if(process.env.VIBE_SKIP_LIBSECRET_INSTALL==="1")return{ok:!1,warning:"VIBE_SKIP_LIBSECRET_INSTALL=1 set; using JSON fallback"};let q=j(),Q=V(q,Yq);if(b(Q))return{ok:!1,warning:"previous attempt failed; not retrying"};try{d(q,{recursive:!0}),F(Q,`${new Date().toISOString()}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Da as D}from"./index-
|
|
2
|
+
import{Da as D}from"./index-cv0xhb46.js";import{Xa as V}from"./index-0ckffygp.js";import{$d as A,Sd as _,Td as w,Ud as x,Vd as N,Wd as j,Zd as X,ce as I}from"./index-a4854mwz.js";import{ie as S}from"./index-c7554sg7.js";import{existsSync as $,readdirSync as v,readFileSync as O,writeFileSync as M,mkdirSync as E,openSync as T,closeSync as b,unlinkSync as R}from"fs";import{join as Q}from"path";import{tmpdir as F}from"os";import{spawn as h}from"child_process";class P{registryPath;logsDir;productDir;constructor(){let q=I();this.productDir=q,this.registryPath=Q(q,"agents.json");let z=A();this.logsDir=Q(z,"logs"),E(q,{recursive:!0}),E(z,{recursive:!0}),E(this.logsDir,{recursive:!0})}async startDaemon(q){return X(q.name),this.withInstanceLock(q.name,async()=>{let z=await this.findProcessByName(q.name);if(z&&z.status==="running"){let U=z.version,W=D();if(U===W){console.log(`\u26A0\uFE0F Agent '${q.name}' is already running on port ${z.port}`);return}console.log(`\uD83D\uDD04 Agent '${q.name}' is running an older build (${U??"unknown"} \u2192 ${W}) \u2014 restarting to apply the update`);try{await this.stopInternal(q.name)}catch(Z){console.log(`\u26A0\uFE0F Could not cleanly stop the stale daemon (${Z instanceof Error?Z.message:String(Z)}); proceeding to start the new build`)}}let B=Q(this.logsDir,`${q.name}.log`),C=T(B,"a"),H=Q(import.meta.dir,"index.js"),G=Q(import.meta.dir,"..","index.ts"),L=$(H)?H:G,K=h(process.execPath,["run",L],{detached:!0,windowsHide:!0,stdio:["ignore",C,C],env:{...process.env,VIBECONTROLS_PROFILE:q.profile||"default",PORT:q.port.toString(),DB_PATH:q.dbPath,NODE_ENV:"production",AGENT_LOG_FILE:B}});K.on("error",()=>{}),b(C),await new Promise((U)=>setTimeout(U,2000));let J=K.pid;if(!(J!==void 0&&await this.isProcessRunning(J))){let U="";try{U=O(B,"utf8").split(/\r?\n/).filter((k)=>k.trim()).slice(-25).join(`
|
|
3
3
|
`)}catch{}let W=`See ${B}`;throw Error(U?`Failed to start agent '${q.name}'. ${W}
|
|
4
4
|
--- last log lines ---
|
|
5
5
|
${U}`:`Failed to start agent '${q.name}'. ${W}`)}K.unref(),await this.saveProcessInfo(q.name,J,q),console.log(`\uD83D\uDE80 Agent '${q.name}' started (PID: ${J}, Port: ${q.port})`)})}async stop(q){return X(q),this.withInstanceLock(q,()=>this.stopInternal(q))}async stopInternal(q){let z=await this.findProcessByName(q);if(!z||z.status!=="running"){console.log(`\u26A0\uFE0F Agent '${q}' is not running`);return}try{if(process.kill(z.pid,"SIGTERM"),await new Promise((C)=>setTimeout(C,3000)),await this.isProcessRunning(z.pid))process.kill(z.pid,"SIGKILL");await this.updateProcessStatus(q,"stopped"),console.log(`\u2705 Agent '${q}' stopped (tunnel + API key preserved)`)}catch(B){throw Error(`Failed to stop agent '${q}': ${B}`,{cause:B})}}async restart(q,z){X(q),X(z.name);let B=await this.findProcessByName(q);if(B&&B.status==="running")await this.stop(q);await this.startDaemon(z),console.log(`\uD83D\uDD04 Agent '${q}' restarted (tunnel + API key preserved)`)}async kill(q){return X(q),this.withInstanceLock(q,async()=>{let z=await this.findProcessByName(q);if(!z||z.status!=="running"){console.log(`\u26A0\uFE0F Agent '${q}' is not running`);return}let B=Q(F(),`.boff-vibecontrols-kill-${z.pid}`);try{await Bun.write(B,"kill")}catch{}try{process.kill(z.pid,"SIGTERM"),await new Promise((H)=>setTimeout(H,5000))}catch{}if(await this.isProcessRunning(z.pid))await this.killProcessTree(z.pid);await this.updateProcessStatus(q,"stopped"),console.log(`\uD83D\uDC80 Agent '${q}' killed (tunnel + state torn down)`)})}async getStatus(q){return X(q),this.findProcessByName(q)}discoverRuntimeInstances(){let q=Q(this.productDir,"agents");if(!$(q))return[];let z;try{z=v(q,{withFileTypes:!0}).filter((C)=>C.isDirectory()).map((C)=>C.name)}catch{return[]}let B=[];for(let C of z){let H=Q(q,C,"runtime.json");if(!$(H))continue;try{let G=JSON.parse(O(H,"utf8"));if(typeof G.pid!=="number"||typeof G.port!=="number")continue;let L=G.profile||C;try{X(L)}catch{continue}B.push({name:L,pid:G.pid,port:G.port,config:{name:L,port:G.port,daemon:!0,dbPath:Q(q,C,"agent-db"),host:G.host,profile:L},startTime:G.startedAt??new Date(0).toISOString(),status:"unknown",version:G.version})}catch{}}return B}async getStatusAll(){let q=this.loadRegistry(),z=new Set(q.map((G)=>G.name)),B=[...q];for(let G of this.discoverRuntimeInstances())if(!z.has(G.name))B.push(G);let C=[];for(let G of B){let L=await this.isManagedProcessRunning(G);if(!z.has(G.name)&&!L)continue;C.push({...G,status:L?"running":"stopped"})}let H=C.filter((G)=>G.status==="running"&&!z.has(G.name));if(H.length>0)try{await _(()=>{let G=this.loadRegistry(),L=new Set(G.map((J)=>J.name)),K=H.filter((J)=>!L.has(J.name));if(K.length>0)this.saveRegistry([...G,...K.map((J)=>({...J,status:"running"}))])})}catch{}return C}async listInstances(){return this.getStatusAll()}getDefaultProfile(){return N()}setDefaultProfile(q){j(X(q))}async showLogs(q,z){X(q);let B=Q(this.logsDir,`${q}.log`);if(!$(B)){console.log(`No logs found for agent '${q}'`);return}if(z.follow)try{let C=async(J)=>{let Y=await Bun.file(B).text(),W=Y.split(`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Bb as k,Cb as a,Db as y,Lb as T,Mb as x,tb as r,yb as v}from"./index-
|
|
2
|
+
import{Bb as k,Cb as a,Db as y,Lb as T,Mb as x,tb as r,yb as v}from"./index-bfeekmyh.js";import{Vb as B}from"./index-pgew6sge.js";import{Kd as e,Od as j}from"./index-xnr6t79p.js";function w(Q,J){let $=new B,Z=[],G=new Set;function Y(z){return z.endsWith("/")&&z!=="/"?z.slice(0,-1):z}function U(z,H){if(!H.startsWith("/"))return null;if(H==="/"||H.includes("..")||H.includes("*"))return null;let F=Y(z),X=Y(`${F}${H}`);if(X===F||!X.startsWith(`${F}/`))return null;return X}function V(z){if(!z.createRoutes)return!1;if(G.has(z.name))return!1;let H=z.apiPrefix||`/api/${z.name}`;try{let F=z.createRoutes(J);if(j().logger.info("plugin-router",`Plugin '${z.name}' registered routes`,{prefix:H}),$.use(new B({prefix:H}).derive(()=>({pluginContext:{chain:[z.name],parentPlugin:void 0,activePlugin:z.name}})).use(F)),z.publicPaths)for(let X of z.publicPaths){let K=U(H,X);if(!K){j().logger.warn("plugin-router",`Ignoring unsafe public path from plugin '${z.name}'`,{publicPath:X,prefix:H});continue}Z.push(K)}return G.add(z.name),!0}catch(F){return j().logger.error("plugin-router",`Failed to mount routes for plugin '${z.name}'`,{error:String(F)}),!1}}for(let z of Q.getAllPlugins())V(z);return{routes:$,getPublicPaths:()=>[...Z],mountPlugin:V}}import{EventEmitter as VJ}from"events";var u=1e4;function L(Q,J){let $=process.env[Q];if(!$)return J;let Z=Number.parseInt($,10);return Number.isFinite(Z)&&Z>0?Z:J}function ZJ(){return[{name:"health",match:(Q)=>Q.startsWith("/health"),perMinute:L("VIBECONTROLS_RATELIMIT_HEALTH",1000)},{name:"gateway-auth",match:(Q)=>Q.startsWith("/api/agent/gateway-auth"),perMinute:L("VIBECONTROLS_RATELIMIT_GATEWAY_AUTH",10)},{name:"plugin-install",match:(Q)=>Q.startsWith("/api/plugins/install"),perMinute:L("VIBECONTROLS_RATELIMIT_PLUGIN_INSTALL",5)},{name:"alias-exec",match:(Q)=>/^\/api\/aliases\/[^/]+\/execute/.test(Q),perMinute:L("VIBECONTROLS_RATELIMIT_ALIAS_EXEC",30)},{name:"api",match:(Q)=>Q.startsWith("/api/"),perMinute:L("VIBECONTROLS_RATELIMIT_API",100)}]}function $J(Q,J,$){for(let Z of Q)if(Z.match(J,$))return Z;return null}function R(Q){if(!Q)return!1;return Q==="127.0.0.1"||Q==="::1"||Q==="::ffff:127.0.0.1"||Q.startsWith("127.")}function GJ(Q=Date.now){let J=new Map,$=(Z,G)=>{J.delete(Z),J.set(Z,G)};return{take(Z,G,Y){let U=Q(),V=J.get(Z);if(!V)V={tokens:G,lastRefillMs:U,capacity:G,refillPerSec:Y};else{let H=(U-V.lastRefillMs)/1000;V.tokens=Math.min(G,V.tokens+H*Y),V.lastRefillMs=U,V.capacity=G,V.refillPerSec=Y}let z=V.tokens>=1;if(z)V.tokens-=1;if($(Z,V),J.size>u){let H=J.keys();while(J.size>u){let F=H.next();if(F.done)break;J.delete(F.value)}}return z},retryAfterSec(Z){let G=J.get(Z);if(!G)return 1;if(G.refillPerSec<=0)return 60;let Y=1-G.tokens;if(Y<=0)return 0;return Math.max(1,Math.ceil(Y/G.refillPerSec))},size(){return J.size},reset(){J.clear()}}}function SJ(Q={}){let J=Q.classes??ZJ(),$=Q.store??GJ();return new B({name:"plugin/rate-limit"}).onRequest(({request:Z,set:G,server:Y})=>{let U;try{U=Y?.requestIP(Z)?.address??null}catch{U=null}if(R(U))return;let V=new URL(Z.url),z=$J(J,V.pathname,Z.method);if(!z)return;let F=`${U??"unknown"}|${z.name}`,X=z.perMinute/60;if(!$.take(F,z.perMinute,X)){let K=$.retryAfterSec(F);G.status=429;let P=G.headers??={};return P["Retry-After"]=String(K),{error:"rate_limited",message:`Too many requests for ${z.name}; retry after ${K}s.`,retryAfterSec:K}}}).as("global")}var YJ=(()=>{let Q=process.env.VIBECONTROLS_WS_MAX_PER_IP,J=Q?Number.parseInt(Q,10):NaN;return Number.isFinite(J)&&J>0?J:5})();function C(Q=YJ){let J=new Map;return{accept($,Z){if(R($))return!0;let G=$??"unknown",Y=J.get(G);if(!Y)Y=new Set,J.set(G,Y);if(Y.size>=Q)return!1;return Y.add(Z),!0},release($,Z){if(R($))return;let G=$??"unknown",Y=J.get(G);if(!Y)return;if(Y.delete(Z),Y.size===0)J.delete(G)},size($){let Z=$??"unknown";return J.get(Z)?.size??0}}}function c(Q){let J=new Set,$=new Map,Z=new Map;return{accept(G,Y,U){if(J.size>=Q.maxGlobal)return!1;let V=$.get(G)??new Set;if(V.size>=Q.maxPerKey)return!1;let z=Y??"unknown";if(!R(Y)){let H=Z.get(z)??new Set;if(H.size>=Q.maxPerIp)return!1;H.add(U),Z.set(z,H)}return J.add(U),V.add(U),$.set(G,V),!0},release(G,Y,U){J.delete(U);let V=$.get(G);if(V){if(V.delete(U),V.size===0)$.delete(G)}if(!R(Y)){let z=Y??"unknown",H=Z.get(z);if(H){if(H.delete(U),H.size===0)Z.delete(z)}}},globalCount(){return J.size},keyCount(G){return $.get(G)?.size??0}}}function _(Q,J){let $=process.env[Q];if(!$)return J;let Z=Number.parseInt($,10);return Number.isFinite(Z)&&Z>0?Z:J}var m={maxGlobal:_("VIBE_TERMINAL_WS_MAX_GLOBAL",64),maxPerKey:_("VIBE_TERMINAL_WS_MAX_PER_SESSION",4),maxPerIp:_("VIBE_TERMINAL_WS_MAX_PER_IP",16)},LJ={maxGlobal:_("VIBE_CODE_SERVER_WS_MAX_GLOBAL",64),maxPerKey:_("VIBE_CODE_SERVER_WS_MAX_PER_SESSION",8),maxPerIp:_("VIBE_CODE_SERVER_WS_MAX_PER_IP",16)};function UJ(Q){if(!Q)return new Set;let J=new Set;for(let $ of Q.split(",")){let Z=$.trim();if(Z)J.add(Z)}return J}var D=null;function zJ(){let Q=process.env.VIBE_TRUSTED_PROXIES;if(!D||D.raw!==Q)D={raw:Q,set:UJ(Q)};return D.set}function E(Q,J){let $=zJ();if(!!Q&&(R(Q)||$.has(Q))&&J){let G=J["x-forwarded-for"];if(G){let U=G.split(",")[0]?.trim();if(U)return U}let Y=J["x-real-ip"];if(Y)return Y}return Q}var d=C(),h=new VJ;h.setMaxListeners(100);function b(Q,J){let $={type:Q,payload:J,timestamp:new Date().toISOString()};h.emit("ws:event",$)}var p=(()=>{let Q=process.env.VIBECONTROLS_MAX_WS_CLIENTS,J=Q?Number.parseInt(Q,10):NaN;return Number.isFinite(J)&&J>0?J:200})(),HJ=(()=>{let Q=process.env.VIBECONTROLS_MAX_WS_BUFFER_PER_CLIENT,J=Q?Number.parseInt(Q,10):NaN;return Number.isFinite(J)&&J>0?J:100})();function XJ(){let Q=new Set;return h.on("ws:event",(J)=>{let $=JSON.stringify(J);for(let Z of Q){if(Z.pendingSends>=HJ){if(Z.drops+=1,Z.drops===1||Z.drops%100===0)j().logger.warn("ws-events",`Dropping events for slow client (${Z.drops} dropped)`);continue}try{Z.send($)}catch{}}}),new B().ws("/ws/events",{open(J){if(Q.size>=p){j().logger.warn("ws-events",`MAX_WS_CLIENTS exceeded (${Q.size}/${p}); refusing new connection`),J.close(1013,"Server overloaded");return}let $=J.data,Z=T($.headers??{});if(!x(Z)){J.close(1008,"Unauthorized: invalid or missing API key");return}let G=J.remoteAddress??null,Y=E(G,$.headers);if(!d.accept(Y??null,J)){J.close(1008,"too many connections");return}J._remoteIp=Y??null;let U={ws:J,channels:new Set,pendingSends:0,drops:0,send:(V)=>{U.pendingSends+=1;try{J.send(V)}finally{queueMicrotask(()=>{U.pendingSends=Math.max(0,U.pendingSends-1)})}}};Q.add(U),J._client=U,j().logger.debug("ws-events","Client connected",{id:String(J.id||"unknown")}),J.send(JSON.stringify({type:"connected",timestamp:new Date().toISOString()}))},message(J,$){try{let Z=typeof $==="string"?JSON.parse($):$;switch(Z.type){case"subscribe":{let G=J._client;if(G)G.channels.add(Z.channel);j().logger.debug("ws-events",`Subscribed to ${Z.channel}`);break}case"unsubscribe":{let G=J._client;if(G)G.channels.delete(Z.channel);j().logger.debug("ws-events",`Unsubscribed from ${Z.channel}`);break}case"ping":J.send(JSON.stringify({type:"pong",timestamp:new Date().toISOString()}));break;default:j().logger.debug("ws-events",`Unknown message type: ${Z.type}`)}}catch{j().logger.warn("ws-events","Failed to parse incoming message")}},close(J){let $=J._client;if($)Q.delete($);let Z=J._remoteIp;d.release(Z??null,J),j().logger.debug("ws-events","Client disconnected")}})}var g=c(m),FJ=256,jJ=1048576,KJ=1e4;async function l(Q,J,$,Z,G,Y){let U={};for(let[z,H]of Object.entries(G))if(H&&!["host","connection"].includes(z.toLowerCase()))U[z]=H;let V={method:Z,headers:U};if(Z!=="GET"&&Z!=="HEAD"&&Y)V.body=typeof Y==="string"?Y:JSON.stringify(Y);return fetch(`http://${Q}:${J}${$}`,V)}async function I(Q,J){let $=Q.listProvidersForType("session");for(let{pluginName:Z}of $){let G=Q.getProviderByName("session",Z);if(!G)continue;let Y=await G.getTerminalInfo(J);if(!Y)continue;try{process.kill(Y.pid,0)}catch{continue}let U=Y;return{host:U.host??"127.0.0.1",port:Y.port,wsPath:U.wsPath??"/ws",subprotocols:U.subprotocols??["tty"]}}return null}var M=new Map,NJ=0,q=new Map,o=30000;function A(Q){g.release(Q.sessionId,Q.remoteIp,Q.capRef)}function BJ(Q){return typeof Q==="string"?Buffer.byteLength(Q):Q.byteLength}function n(Q){let J=new Headers(Q.headers);return J.set("Permissions-Policy","clipboard-read=(self), clipboard-write=(self)"),J.delete("X-Frame-Options"),new Response(Q.body,{status:Q.status,headers:J})}function i(Q){return`<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="utf-8">
|
|
@@ -79,5 +79,5 @@ import{Bb as k,Cb as a,Db as y,Lb as T,Mb as x,tb as r,yb as v}from"./index-rqq0
|
|
|
79
79
|
})();
|
|
80
80
|
</script>
|
|
81
81
|
</body>
|
|
82
|
-
</html>`}function MJ(Q){return new B().all("/terminal/:sessionId",async({params:J,request:$,set:Z})=>{let G=J.sessionId,Y=y($,G);if(!Y||!k(Y,G)){if($.method==="GET")return Z.status=200,Z.headers["content-type"]="text/html; charset=utf-8",i(G);return Z.status=401,{error:"Unauthorized: terminal cookie required"}}let U=await I(Q,G);if(!U)return Z.status=502,{error:"Terminal not running for this session"};let V=await l(U.host,U.port,"/",$.method,Object.fromEntries(Object.entries($.headers).map(([z,H])=>[z,H])));return Z.status=V.status,n(V)}).all("/terminal/:sessionId/*",async({params:J,request:$,set:Z})=>{let G=J.sessionId,Y=J["*"]||"",U=y($,G);if(!U||!k(U,G)){if($.method==="GET"&&(Y===""||Y==="/"))return Z.status=200,Z.headers["content-type"]="text/html; charset=utf-8",i(G);return Z.status=401,{error:"Unauthorized: terminal cookie required"}}let V=await I(Q,G);if(!V)return Z.status=502,{error:"Terminal not running for this session"};let z=await l(V.host,V.port,`/${Y}`,$.method,Object.fromEntries(Object.entries($.headers).map(([H,F])=>[H,F])));return Z.status=z.status,n(z)}).ws("/terminal/:sessionId/ws",{open(J){let $=J.data,Z=$.params?.sessionId;if(!Z){J.close(1008,"Missing sessionId");return}if(!r(Z)){J.close(1008,"Invalid sessionId");return}let G=a($.headers??{},Z),Y=!!G&&k(G,Z),U=$.query?.vt,V=!!U&&v(U,`/terminal/${Z}`,"GET");if(!Y&&!V){J.close(1008,"Unauthorized: invalid or missing terminal credentials");return}let z=J.remoteAddress??null,H=E(z,$.headers),F=`bridge-${++NJ}`;if($._bridgeId=F,!g.accept(Z,H,F)){j().logger.warn("terminal-ws",`Terminal WS cap exceeded for session ${Z} (ip=${H??"unknown"})`),J.close(1013,"too many connections");return}$._remoteIp=H;let X={upstream:null,upstreamReady:!1,buffer:[],bufferBytes:0,openTimer:null,sessionId:Z,remoteIp:H,capRef:F};M.set(F,X),j().logger.debug("terminal-ws",`Client connected for session ${Z} (${F})`),I(Q,Z).then((K)=>{if(M.get(F)!==X)return;if(!K){let O=q.get(Z)??0,N=Date.now();if(q.size>50){let f=N-o*2;for(let[JJ,QJ]of q)if(QJ<f)q.delete(JJ)}if(N-O>o)j().logger.warn("terminal-ws",`No terminal running for session ${Z}`),q.set(Z,N);A(X),M.delete(F),J.close(1011,"No terminal running");return}let P=`ws://${K.host}:${K.port}${K.wsPath}`,W=new WebSocket(P,K.subprotocols);X.upstream=W,X.openTimer=setTimeout(()=>{A(X),M.delete(F);try{W.close(1011,"upstream open timeout")}catch{}try{J.close(1011,"Upstream open timeout")}catch{}},KJ),W.addEventListener("open",()=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;X.upstreamReady=!0,j().logger.debug("terminal-ws",`Bridge established \u2192 port ${K.port}, buffered=${X.buffer.length}`,{sessionId:Z});for(let O of X.buffer)W.send(O);X.buffer.length=0,X.bufferBytes=0}),W.addEventListener("message",(O)=>{try{let N=O.data;if(N instanceof ArrayBuffer)J.send(new Uint8Array(N));else if(N instanceof Blob)N.arrayBuffer().then((f)=>{try{J.send(new Uint8Array(f))}catch{}});else J.send(N)}catch(N){j().logger.error("terminal-ws",`Failed to forward upstream\u2192client: ${N}`,{sessionId:Z})}}),W.addEventListener("close",(O)=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;j().logger.debug("terminal-ws",`Upstream closed (code=${O.code})`,{sessionId:Z}),A(X),M.delete(F);try{J.close(1000,"Upstream closed")}catch{}}),W.addEventListener("error",(O)=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;j().logger.error("terminal-ws","Upstream error",{sessionId:Z}),A(X),M.delete(F);try{J.close(1011,"Upstream error")}catch{}})}).catch((K)=>{A(X),M.delete(F),j().logger.warn("terminal-ws","Failed to resolve terminal endpoint",{sessionId:Z,error:String(K)});try{J.close(1011,"Failed to resolve terminal")}catch{}})},message(J,$){let G=J.data._bridgeId;if(!G)return;let Y=M.get(G);if(!Y)return;let U;if(typeof $==="string")U=$;else if($ instanceof ArrayBuffer)U=$;else if($ instanceof Uint8Array||Buffer.isBuffer($)){let V=new ArrayBuffer($.byteLength);new Uint8Array(V).set(new Uint8Array($.buffer,$.byteOffset,$.byteLength)),U=V}else if(typeof $==="object"&&$!==null)U=JSON.stringify($);else U=String($);if(Y.upstream&&Y.upstreamReady&&Y.upstream.readyState===WebSocket.OPEN)try{Y.upstream.send(U)}catch(V){j().logger.error("terminal-ws",`Failed to forward client\u2192upstream: ${V}`,{sessionId:Y.sessionId})}else{let V=BJ(U);if(Y.buffer.length>=FJ||Y.bufferBytes+V>jJ){A(Y),M.delete(G);try{J.close(1013,"Terminal buffer limit exceeded")}catch{}return}Y.buffer.push(U),Y.bufferBytes+=V}},close(J){let $=J.data,Z=$._bridgeId,G=$.params?.sessionId;if(j().logger.debug("terminal-ws","Client disconnected",{sessionId:G}),Z){let Y=M.get(Z);if(Y?.upstream&&Y.upstream.readyState===WebSocket.OPEN)Y.upstream.close(1000,"Client disconnected");if(Y?.openTimer)clearTimeout(Y.openTimer);if(Y)A(Y);M.delete(Z)}if(G&&Z)g.release(G,$._remoteIp??null,Z)}})}var t=C(),s={debug:0,info:1,warn:2,error:3};function OJ(Q){return Q==="debug"||Q==="info"||Q==="warn"||Q==="error"?Q:null}function WJ(){return new B().ws("/ws/logs",{open(Q){let J=Q.data,$=T(J.headers??{}),Z=J.query?.vt,G=x($),Y=!!Z&&v(Z,"/ws/logs","GET");if(!G&&!Y){Q.close(1008,"Unauthorized: invalid or missing credentials");return}let U=Q.remoteAddress??null,V=E(U,J.headers);if(!t.accept(V??null,Q)){Q.close(1008,"too many connections");return}Q._remoteIp=V??null,j().logger.info("ws-logs","Log stream client connected");let z={minLevel:"info",source:""};Q._filters=z;let H=(F)=>{let X=Q._filters;if(s[F.level]<s[X.minLevel])return;if(X.source&&!F.source.includes(X.source))return;try{Q.send(JSON.stringify(F))}catch{}};j().logger.on("log",H),Q._logHandler=H,Q.send(JSON.stringify({type:"connected",timestamp:new Date().toISOString()}))},message(Q,J){try{let $=typeof J==="string"?JSON.parse(J):J;if($.type==="filter"){let Z=Q._filters,G=OJ($.level);if(G)Z.minLevel=G;if(typeof $.source==="string")Z.source=$.source.slice(0,128);Q.send(JSON.stringify({type:"filter-updated",filters:Z}))}}catch{}},close(Q){let J=Q._logHandler;if(J)j().logger.removeListener("log",J);let $=Q._remoteIp;t.release($??null,Q),j().logger.info("ws-logs","Log stream client disconnected")}})}var S=new Map;function tJ(Q,J){if(!Q.db||!Q.serviceRegistry||!Q.pluginManager)throw Error(`mountProfileRoutes: profile '${Q.name}' has no attached services`);let $={db:Q.db,serviceRegistry:Q.serviceRegistry,pluginManager:Q.pluginManager,broadcast:b,hostServices:Q.hostServices??void 0,rebuildPluginSurfaces:J?.rebuildPluginSurfaces,mountPlugin:J?.mountPlugin},{routes:Z}=w(Q.pluginManager,$);S.set(Q.name,{ctx:Q,router:Z})}function sJ(Q){return S.delete(Q)}async function eJ(Q,J,$){let Z=S.get(Q);if(!Z)return null;e(Z.ctx);let G=new URL(J.url),U=`/api${G.pathname.replace(/^\/api\/profiles\/[^/]+/,"")}${G.search}`,V=new Headers(J.headers),z={method:J.method,headers:V};if(J.method!=="GET"&&J.method!=="HEAD")if($!==void 0)z.body=$;else z.body=J.body,z.duplex="half";let H=new Request(`${G.origin}${U}`,z);return Z.router.handle(H)}function JQ(){return[...S.keys()].sort()}function QQ(){S.clear()}function ZQ(Q,J,$){S.set(Q,{ctx:J,router:$})}
|
|
82
|
+
</html>`}function MJ(Q){return new B().all("/terminal/:sessionId",async({params:J,request:$,set:Z})=>{let G=J.sessionId,Y=y($,G);if(!Y||!k(Y,G)){if($.method==="GET")return Z.status=200,Z.headers["content-type"]="text/html; charset=utf-8",i(G);return Z.status=401,{error:"Unauthorized: terminal cookie required"}}let U=await I(Q,G);if(!U)return Z.status=502,{error:"Terminal not running for this session"};let V=await l(U.host,U.port,"/",$.method,Object.fromEntries(Object.entries($.headers).map(([z,H])=>[z,H])));return Z.status=V.status,n(V)}).all("/terminal/:sessionId/*",async({params:J,request:$,set:Z})=>{let G=J.sessionId,Y=J["*"]||"",U=y($,G);if(!U||!k(U,G)){if($.method==="GET"&&(Y===""||Y==="/"))return Z.status=200,Z.headers["content-type"]="text/html; charset=utf-8",i(G);return Z.status=401,{error:"Unauthorized: terminal cookie required"}}let V=await I(Q,G);if(!V)return Z.status=502,{error:"Terminal not running for this session"};let z=await l(V.host,V.port,`/${Y}`,$.method,Object.fromEntries(Object.entries($.headers).map(([H,F])=>[H,F])));return Z.status=z.status,n(z)}).ws("/terminal/:sessionId/ws",{open(J){let $=J.data,Z=$.params?.sessionId;if(!Z){J.close(1008,"Missing sessionId");return}if(!r(Z)){J.close(1008,"Invalid sessionId");return}let G=a($.headers??{},Z),Y=!!G&&k(G,Z),U=$.query?.vt,V=!!U&&v(U,`/terminal/${Z}`,"GET");if(!Y&&!V){J.close(1008,"Unauthorized: invalid or missing terminal credentials");return}let z=J.remoteAddress??null,H=E(z,$.headers),F=`bridge-${++NJ}`;if($._bridgeId=F,!g.accept(Z,H,F)){j().logger.warn("terminal-ws",`Terminal WS cap exceeded for session ${Z} (ip=${H??"unknown"})`),J.close(1013,"too many connections");return}$._remoteIp=H;let X={upstream:null,upstreamReady:!1,buffer:[],bufferBytes:0,openTimer:null,sessionId:Z,remoteIp:H,capRef:F};M.set(F,X),j().logger.debug("terminal-ws",`Client connected for session ${Z} (${F})`),I(Q,Z).then((K)=>{if(M.get(F)!==X)return;if(!K){let O=q.get(Z)??0,N=Date.now();if(q.size>50){let f=N-o*2;for(let[JJ,QJ]of q)if(QJ<f)q.delete(JJ)}if(N-O>o)j().logger.warn("terminal-ws",`No terminal running for session ${Z}`),q.set(Z,N);A(X),M.delete(F),J.close(1011,"No terminal running");return}let P=`ws://${K.host}:${K.port}${K.wsPath}`,W=new WebSocket(P,K.subprotocols);X.upstream=W,X.openTimer=setTimeout(()=>{A(X),M.delete(F);try{W.close(1011,"upstream open timeout")}catch{}try{J.close(1011,"Upstream open timeout")}catch{}},KJ),W.addEventListener("open",()=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;X.upstreamReady=!0,j().logger.debug("terminal-ws",`Bridge established \u2192 port ${K.port}, buffered=${X.buffer.length}`,{sessionId:Z});for(let O of X.buffer)W.send(O);X.buffer.length=0,X.bufferBytes=0}),W.addEventListener("message",(O)=>{try{let N=O.data;if(N instanceof ArrayBuffer)J.send(new Uint8Array(N));else if(N instanceof Blob)N.arrayBuffer().then((f)=>{try{J.send(new Uint8Array(f))}catch{}});else J.send(N)}catch(N){j().logger.error("terminal-ws",`Failed to forward upstream\u2192client: ${N}`,{sessionId:Z})}}),W.addEventListener("close",(O)=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;j().logger.debug("terminal-ws",`Upstream closed (code=${O.code})`,{sessionId:Z}),A(X),M.delete(F);try{J.close(1000,"Upstream closed")}catch{}}),W.addEventListener("error",(O)=>{if(X.openTimer)clearTimeout(X.openTimer),X.openTimer=null;j().logger.error("terminal-ws","Upstream error",{sessionId:Z}),A(X),M.delete(F);try{J.close(1011,"Upstream error")}catch{}})}).catch((K)=>{A(X),M.delete(F),j().logger.warn("terminal-ws","Failed to resolve terminal endpoint",{sessionId:Z,error:String(K)});try{J.close(1011,"Failed to resolve terminal")}catch{}})},message(J,$){let G=J.data._bridgeId;if(!G)return;let Y=M.get(G);if(!Y)return;let U;if(typeof $==="string")U=$;else if($ instanceof ArrayBuffer)U=$;else if($ instanceof Uint8Array||Buffer.isBuffer($)){let V=new ArrayBuffer($.byteLength);new Uint8Array(V).set(new Uint8Array($.buffer,$.byteOffset,$.byteLength)),U=V}else if(typeof $==="object"&&$!==null)U=JSON.stringify($);else U=String($);if(Y.upstream&&Y.upstreamReady&&Y.upstream.readyState===WebSocket.OPEN)try{Y.upstream.send(U)}catch(V){j().logger.error("terminal-ws",`Failed to forward client\u2192upstream: ${V}`,{sessionId:Y.sessionId})}else{let V=BJ(U);if(Y.buffer.length>=FJ||Y.bufferBytes+V>jJ){A(Y),M.delete(G);try{J.close(1013,"Terminal buffer limit exceeded")}catch{}return}Y.buffer.push(U),Y.bufferBytes+=V}},close(J){let $=J.data,Z=$._bridgeId,G=$.params?.sessionId;if(j().logger.debug("terminal-ws","Client disconnected",{sessionId:G}),Z){let Y=M.get(Z);if(Y?.upstream&&Y.upstream.readyState===WebSocket.OPEN)Y.upstream.close(1000,"Client disconnected");if(Y?.openTimer)clearTimeout(Y.openTimer);if(Y)A(Y);M.delete(Z)}if(G&&Z)g.release(G,$._remoteIp??null,Z)}})}var t=C(),s={debug:0,info:1,warn:2,error:3};function OJ(Q){return Q==="debug"||Q==="info"||Q==="warn"||Q==="error"?Q:null}function WJ(){return new B().ws("/ws/logs",{open(Q){let J=Q.data,$=T(J.headers??{}),Z=J.query?.vt,G=x($),Y=!!Z&&v(Z,"/ws/logs","GET");if(!G&&!Y){Q.close(1008,"Unauthorized: invalid or missing credentials");return}let U=Q.remoteAddress??null,V=E(U,J.headers);if(!t.accept(V??null,Q)){Q.close(1008,"too many connections");return}Q._remoteIp=V??null,j().logger.info("ws-logs","Log stream client connected");let z={minLevel:"info",source:""};Q._filters=z;let H=(F)=>{let X=Q._filters;if(s[F.level]<s[X.minLevel])return;if(X.source&&!F.source.includes(X.source))return;try{Q.send(JSON.stringify(F))}catch{}};j().logger.on("log",H),Q._logHandler=H,Q.send(JSON.stringify({type:"connected",timestamp:new Date().toISOString()}))},message(Q,J){try{let $=typeof J==="string"?JSON.parse(J):J;if($.type==="filter"){let Z=Q._filters,G=OJ($.level);if(G)Z.minLevel=G;if(typeof $.source==="string")Z.source=$.source.slice(0,128);Q.send(JSON.stringify({type:"filter-updated",filters:Z}))}}catch{}},close(Q){let J=Q._logHandler;if(J)j().logger.removeListener("log",J);let $=Q._remoteIp;t.release($??null,Q),j().logger.info("ws-logs","Log stream client disconnected")}})}var S=new Map;function tJ(Q,J){if(!Q.db||!Q.serviceRegistry||!Q.pluginManager)throw Error(`mountProfileRoutes: profile '${Q.name}' has no attached services`);let $={db:Q.db,serviceRegistry:Q.serviceRegistry,pluginManager:Q.pluginManager,broadcast:b,hostServices:Q.hostServices??void 0,rebuildPluginSurfaces:J?.rebuildPluginSurfaces,mountPlugin:J?.mountPlugin,app:J?.app},{routes:Z}=w(Q.pluginManager,$);S.set(Q.name,{ctx:Q,router:Z})}function sJ(Q){return S.delete(Q)}async function eJ(Q,J,$){let Z=S.get(Q);if(!Z)return null;e(Z.ctx);let G=new URL(J.url),U=`/api${G.pathname.replace(/^\/api\/profiles\/[^/]+/,"")}${G.search}`,V=new Headers(J.headers),z={method:J.method,headers:V};if(J.method!=="GET"&&J.method!=="HEAD")if($!==void 0)z.body=$;else z.body=J.body,z.duplex="half";let H=new Request(`${G.origin}${U}`,z);return Z.router.handle(H)}function JQ(){return[...S.keys()].sort()}function QQ(){S.clear()}function ZQ(Q,J,$){S.set(Q,{ctx:J,router:$})}
|
|
83
83
|
export{w as eb,SJ as fb,c as gb,LJ as hb,E as ib,b as jb,XJ as kb,MJ as lb,WJ as mb,tJ as nb,sJ as ob,eJ as pb,JQ as qb,QQ as rb,ZQ as sb};
|